diff --git a/.clang-format b/.clang-format index 150127471485c..8dc1f55d57581 100644 --- a/.clang-format +++ b/.clang-format @@ -32,6 +32,8 @@ ColumnLimit: 100 ConstructorInitializerIndentWidth: 8 ContinuationIndentWidth: 8 ForEachMacros: + - 'ARRAY_FOR_EACH' + - 'ARRAY_FOR_EACH_PTR' - 'FOR_EACH' - 'FOR_EACH_FIXED_ARG' - 'FOR_EACH_IDX' diff --git a/.github/workflows/bsim-tests.yaml b/.github/workflows/bsim-tests.yaml index 52d384e92fdf3..271cc1dbfe7ff 100644 --- a/.github/workflows/bsim-tests.yaml +++ b/.github/workflows/bsim-tests.yaml @@ -34,18 +34,13 @@ jobs: runs-on: group: zephyr-runner-v2-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' env: ZEPHYR_TOOLCHAIN_VARIANT: zephyr BSIM_OUT_PATH: /opt/bsim/ BSIM_COMPONENTS_PATH: /opt/bsim/components EDTT_PATH: ../tools/edtt - bsim_bt_52_test_results_file: ./bsim_bt/52_bsim_results.xml - bsim_bt_53_test_results_file: ./bsim_bt/53_bsim_results.xml - bsim_bt_53split_test_results_file: ./bsim_bt/53_bsim_split_results.xml - bsim_net_52_test_results_file: ./bsim_net/52_bsim_results.xml - bsim_uart_test_results_file: ./bsim_uart/uart_bsim_results.xml steps: - name: Apply container owner mismatch workaround run: | @@ -153,59 +148,39 @@ jobs: - name: Run Bluetooth Tests with BSIM if: steps.check-bluetooth-files.outputs.any_changed == 'true' || steps.check-common-files.outputs.any_changed == 'true' run: | - export ZEPHYR_BASE=${PWD} - # Build and run the BT tests for nrf52_bsim: - nice tests/bsim/bluetooth/compile.sh - RESULTS_FILE=${ZEPHYR_BASE}/${bsim_bt_52_test_results_file} \ - TESTS_FILE=tests/bsim/bluetooth/tests.nrf52bsim.txt tests/bsim/run_parallel.sh - # Build and run the BT controller tests also for the nrf5340bsim/nrf5340/cpunet - nice tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpunet.sh - BOARD=nrf5340bsim/nrf5340/cpunet \ - RESULTS_FILE=${ZEPHYR_BASE}/${bsim_bt_53_test_results_file} \ - TESTS_FILE=tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpunet.txt \ - tests/bsim/run_parallel.sh - # Build and run the nrf5340 split stack tests set - nice tests/bsim/bluetooth/compile.nrf5340bsim_nrf5340_cpuapp.sh - BOARD=nrf5340bsim/nrf5340/cpuapp \ - RESULTS_FILE=${ZEPHYR_BASE}/${bsim_bt_53split_test_results_file} \ - TESTS_FILE=tests/bsim/bluetooth/tests.nrf5340bsim_nrf5340_cpuapp.txt \ - tests/bsim/run_parallel.sh + tests/bsim/ci.bt.sh - name: Run Networking Tests with BSIM if: steps.check-networking-files.outputs.any_changed == 'true' || steps.check-common-files.outputs.any_changed == 'true' run: | - export ZEPHYR_BASE=${PWD} - WORK_DIR=${ZEPHYR_BASE}/bsim_net nice tests/bsim/net/compile.sh - RESULTS_FILE=${ZEPHYR_BASE}/${bsim_net_52_test_results_file} \ - SEARCH_PATH=tests/bsim/net/ tests/bsim/run_parallel.sh + tests/bsim/ci.net.sh - name: Run UART Tests with BSIM if: steps.check-uart-files.outputs.any_changed == 'true' || steps.check-common-files.outputs.any_changed == 'true' run: | - echo "UART: Single device tests" - ./scripts/twister -T tests/drivers/uart/ --force-color --inline-logs -v -M -p nrf52_bsim \ - --fixture gpio_loopback -- -uart0_loopback - echo "UART: Multi device tests" - export ZEPHYR_BASE=${PWD} - WORK_DIR=${ZEPHYR_BASE}/bsim_uart nice tests/bsim/drivers/uart/compile.sh - RESULTS_FILE=${ZEPHYR_BASE}/${bsim_uart_test_results_file} \ - SEARCH_PATH=tests/bsim/drivers/uart/ tests/bsim/run_parallel.sh - - - name: Upload Test Results + tests/bsim/ci.uart.sh + + - name: Merge Test Results + run: | + pip3 install junitparser junit2html + junitparser merge --glob "./bsim_*/*bsim_results.*.xml" "./twister-out/twister.xml" junit.xml + junit2html junit.xml junit.html + + - name: Upload Unit Test Results in HTML if: always() uses: actions/upload-artifact@v4 with: - name: bsim-test-results + name: HTML Unit Test Results + if-no-files-found: ignore path: | - ./bsim_bt/52_bsim_results.xml - ./bsim_bt/53_bsim_results.xml - ./bsim_bt/53_bsim_split_results.xml - ./bsim_net/52_bsim_results.xml - ./bsim_uart/uart_bsim_results.xml - ./twister-out/twister.xml - ./twister-out/twister.json - ${{ github.event_path }} - if-no-files-found: warn + junit.html + + - name: Publish Unit Test Results + uses: EnricoMi/publish-unit-test-result-action@v2 + with: + check_name: Bsim Test Results + files: "junit.xml" + comment_mode: off - name: Upload Event Details if: always() diff --git a/.github/workflows/clang.yaml b/.github/workflows/clang.yaml index 77a36a0c9317e..95d68acf47a49 100644 --- a/.github/workflows/clang.yaml +++ b/.github/workflows/clang.yaml @@ -12,7 +12,7 @@ jobs: runs-on: group: zephyr-runner-v2-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' strategy: fail-fast: false diff --git a/.github/workflows/codecov.yaml b/.github/workflows/codecov.yaml index 1c5ded582f0df..8bf4d2289ebd3 100644 --- a/.github/workflows/codecov.yaml +++ b/.github/workflows/codecov.yaml @@ -2,7 +2,7 @@ name: Code Coverage with codecov on: schedule: - - cron: '25 06,18 * * 1-5' + - cron: '25 06,18 * * *' concurrency: group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.head_ref || github.ref }} @@ -14,7 +14,7 @@ jobs: runs-on: group: zephyr-runner-v2-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' strategy: fail-fast: false @@ -220,10 +220,10 @@ jobs: - name: Upload coverage to Codecov if: always() - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4 with: - directory: ./coverage/reports env_vars: OS,PYTHON fail_ci_if_error: false verbose: true - files: merged.xml + token: ${{ secrets.CODECOV_TOKEN }} + files: coverage/reports/merged.xml diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index e8d53405257e9..c50625a1879ea 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -18,6 +18,9 @@ env: # so we fetch that through pip. CMAKE_VERSION: 3.20.5 DOXYGEN_VERSION: 1.9.6 + # Job count is set to 2 less than the vCPU count of 16 because the total available RAM is 32GiB + # and each sphinx-build process may use more than 2GiB of RAM. + JOB_COUNT: 14 jobs: doc-file-check: @@ -50,6 +53,8 @@ jobs: scripts/dts/ doc/requirements.txt .github/workflows/doc-build.yml + scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py + scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/shell.py doc-build-html: name: "Documentation Build (HTML)" @@ -130,7 +135,11 @@ jobs: else DOC_TARGET="html" fi - DOC_TAG=${DOC_TAG} SPHINXOPTS_EXTRA="-q -t publish" make -C doc ${DOC_TARGET} + + DOC_TAG=${DOC_TAG} \ + SPHINXOPTS="-j ${JOB_COUNT} -W --keep-going -T" \ + SPHINXOPTS_EXTRA="-q -t publish" \ + make -C doc ${DOC_TARGET} # API documentation coverage python3 -m coverxygen --xml-dir doc/_build/html/doxygen/xml/ --src-dir include/ --output doc-coverage.info @@ -208,7 +217,7 @@ jobs: - name: install-pkgs run: | apt-get update - apt-get install -y python3-pip python3-venv ninja-build doxygen graphviz librsvg2-bin + apt-get install -y python3-pip python3-venv ninja-build doxygen graphviz librsvg2-bin imagemagick - name: cache-pip uses: actions/cache@v4 @@ -243,7 +252,10 @@ jobs: DOC_TAG="development" fi - DOC_TAG=${DOC_TAG} SPHINXOPTS="-q -j auto" LATEXMKOPTS="-quiet -halt-on-error" make -C doc pdf + DOC_TAG=${DOC_TAG} \ + SPHINXOPTS="-q -j ${JOB_COUNT}" \ + LATEXMKOPTS="-quiet -halt-on-error" \ + make -C doc pdf - name: upload-build if: always() diff --git a/.github/workflows/errno.yml b/.github/workflows/errno.yml index 593fe916deb69..b1f7e6f4e6250 100644 --- a/.github/workflows/errno.yml +++ b/.github/workflows/errno.yml @@ -10,7 +10,7 @@ jobs: check-errno: runs-on: ubuntu-22.04 container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.11 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.13 steps: - name: Apply container owner mismatch workaround diff --git a/.github/workflows/footprint-tracking.yml b/.github/workflows/footprint-tracking.yml index ede9f52602eed..5b39c94a9c009 100644 --- a/.github/workflows/footprint-tracking.yml +++ b/.github/workflows/footprint-tracking.yml @@ -26,7 +26,7 @@ jobs: group: zephyr-runner-v2-linux-x64-4xlarge if: github.repository_owner == 'zephyrproject-rtos' container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' strategy: fail-fast: false diff --git a/.github/workflows/twister.yaml b/.github/workflows/twister.yaml index 40f9fe04c2dde..c2e44c830d05d 100644 --- a/.github/workflows/twister.yaml +++ b/.github/workflows/twister.yaml @@ -25,7 +25,7 @@ jobs: runs-on: group: zephyr-runner-v2-linux-x64-4xlarge container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' outputs: subset: ${{ steps.output-services.outputs.subset }} @@ -129,7 +129,7 @@ jobs: needs: twister-build-prep if: needs.twister-build-prep.outputs.size != 0 container: - image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.11.20240324 + image: ghcr.io/zephyrproject-rtos/ci-repo-cache:v0.26.13.20240601 options: '--entrypoint /bin/bash' strategy: fail-fast: false diff --git a/.github/workflows/twister_tests_blackbox.yml b/.github/workflows/twister_tests_blackbox.yml index edec21e28d393..1176afc729907 100644 --- a/.github/workflows/twister_tests_blackbox.yml +++ b/.github/workflows/twister_tests_blackbox.yml @@ -24,7 +24,7 @@ jobs: python-version: ['3.10', '3.11', '3.12'] os: [ubuntu-22.04] container: - image: ghcr.io/zephyrproject-rtos/ci:v0.26.11 + image: ghcr.io/zephyrproject-rtos/ci:v0.26.13 steps: - name: Apply Container Owner Mismatch Workaround diff --git a/.gitignore b/.gitignore index 15636eaaeac0e..66441114df291 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,10 @@ *.swp *.swo *~ -.\#* + +# Emacs \#*\# + build*/ !doc/build/ !scripts/build @@ -27,6 +29,8 @@ outdir outdir-* scripts/basic/fixdep scripts/gen_idt/gen_idt +coverage-report +doc-coverage.info doc/_build doc/doxygen doc/xml @@ -39,6 +43,7 @@ sanity-out* twister-out* bsim_out bsim_bt_out +myresults.xml tests/RunResults.xml scripts/grub doc/reference/kconfig/*.rst @@ -52,6 +57,7 @@ venv .venv .DS_Store .clangd +new.info # CI output compliance.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 8f654bf224b8d..d4dd40cf66f39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,10 @@ add_library(zephyr_interface INTERFACE) # flags that come with zephyr_interface. zephyr_library_named(zephyr) +if(CONFIG_LEGACY_GENERATED_INCLUDE_PATH) + zephyr_include_directories(${PROJECT_BINARY_DIR}/include/generated/zephyr) +endif() + zephyr_include_directories( include ${PROJECT_BINARY_DIR}/include/generated @@ -219,6 +223,26 @@ if(CONFIG_LTO) add_link_options($) endif() +if(CONFIG_STD_C23) + set(CSTD c2x) +elseif(CONFIG_STD_C17) + set(CSTD c17) +elseif(CONFIG_STD_C11) + set(CSTD c11) +elseif(CONFIG_STD_C99) + set(CSTD c99) +elseif(CONFIG_STD_C90) + set(CSTD c90) +else() + message(FATAL_ERROR "Unreachable code. Expected C standard to have been chosen.") +endif() + +if(CONFIG_GNU_C_EXTENSIONS) + string(REPLACE "c" "gnu" CSTD "${CSTD}") +endif() + +list(APPEND CMAKE_C_COMPILE_FEATURES ${compile_features_${CSTD}}) + # @Intent: Obtain compiler specific flags related to C++ that are not influenced by kconfig zephyr_compile_options($<$:$>) @@ -521,9 +545,9 @@ if(ZEPHYR_GIT_INDEX) endif() add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/include/generated/version.h + OUTPUT ${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} - -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/version.h + -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h -DVERSION_TYPE=KERNEL -DVERSION_FILE=${ZEPHYR_BASE}/VERSION -DKERNEL_VERSION_CUSTOMIZATION="$" @@ -532,13 +556,13 @@ add_custom_command( DEPENDS ${ZEPHYR_BASE}/VERSION ${git_dependency} COMMAND_EXPAND_LISTS ) -add_custom_target(version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/version.h) +add_custom_target(version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h) if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION) add_custom_command( - OUTPUT ${PROJECT_BINARY_DIR}/include/generated/app_version.h + OUTPUT ${PROJECT_BINARY_DIR}/include/generated/zephyr/app_version.h COMMAND ${CMAKE_COMMAND} -DZEPHYR_BASE=${ZEPHYR_BASE} - -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/app_version.h + -DOUT_FILE=${PROJECT_BINARY_DIR}/include/generated/zephyr/app_version.h -DVERSION_TYPE=APP -DVERSION_FILE=${APPLICATION_SOURCE_DIR}/VERSION -DAPP_VERSION_CUSTOMIZATION="$" @@ -547,7 +571,9 @@ if(EXISTS ${APPLICATION_SOURCE_DIR}/VERSION) DEPENDS ${APPLICATION_SOURCE_DIR}/VERSION ${git_dependency} COMMAND_EXPAND_LISTS ) - add_custom_target(app_version_h DEPENDS ${PROJECT_BINARY_DIR}/include/generated/app_version.h) + add_custom_target( + app_version_h + DEPENDS ${PROJECT_BINARY_DIR}/include/generated/zephyr/app_version.h) add_dependencies(zephyr_interface app_version_h) endif() @@ -602,7 +628,8 @@ set(ZEPHYR_CURRENT_CMAKE_DIR) get_property(LIBC_LINK_LIBRARIES TARGET zephyr_interface PROPERTY LIBC_LINK_LIBRARIES) zephyr_link_libraries(${LIBC_LINK_LIBRARIES}) -set(syscall_list_h ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscall_list.h) +set(syscall_list_h ${CMAKE_CURRENT_BINARY_DIR}/include/generated/zephyr/syscall_list.h) +set(edk_syscall_list_h ${CMAKE_CURRENT_BINARY_DIR}/edk/include/generated/zephyr/syscall_list.h) set(syscalls_json ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/syscalls.json) set(struct_tags_json ${CMAKE_CURRENT_BINARY_DIR}/misc/generated/struct_tags.json) @@ -740,7 +767,7 @@ add_custom_target(${SYSCALL_LIST_H_TARGET} DEPENDS ${syscall_list_h} ${picolibc_ set_property(TARGET ${SYSCALL_LIST_H_TARGET} APPEND PROPERTY ADDITIONAL_CLEAN_FILES - ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscalls + ${CMAKE_CURRENT_BINARY_DIR}/include/generated/zephyr/syscalls ) add_custom_target(${PARSE_SYSCALLS_TARGET} @@ -760,19 +787,30 @@ if(CONFIG_TIMEOUT_64BIT) set(SYSCALL_SPLIT_TIMEOUT_ARG --split-type k_timeout_t --split-type k_ticks_t) endif() -add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h} - # Also, some files are written to include/generated/syscalls/ +# percepio/TraceRecorder/kernelports/Zephyr/scripts/tz_parse_syscalls.py hardcodes the path +# to the `syscall_list.h`, make a copy of the generated file so that percepio is able to build +if(CONFIG_LEGACY_GENERATED_INCLUDE_PATH) + set(LEGACY_SYSCALL_LIST_H_ARGS + ${CMAKE_COMMAND} -E copy + ${syscall_list_h} + ${CMAKE_CURRENT_BINARY_DIR}/include/generated/syscall_list.h) +endif() + +add_custom_command(OUTPUT include/generated/zephyr/syscall_dispatch.c ${syscall_list_h} + # Also, some files are written to include/generated/zephyr/syscalls/ COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/gen_syscalls.py --json-file ${syscalls_json} # Read this file - --base-output include/generated/syscalls # Write to this dir - --syscall-dispatch include/generated/syscall_dispatch.c # Write this file - --syscall-export-llext include/generated/syscall_export_llext.c + --base-output include/generated/zephyr/syscalls # Write to this dir + --syscall-dispatch include/generated/zephyr/syscall_dispatch.c # Write this file + --syscall-export-llext include/generated/zephyr/syscall_export_llext.c --syscall-list ${syscall_list_h} $<$:--gen-mrsh-files> ${SYSCALL_LONG_REGISTERS_ARG} ${SYSCALL_SPLIT_TIMEOUT_ARG} + COMMAND + ${LEGACY_SYSCALL_LIST_H_ARGS} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} DEPENDS ${PARSE_SYSCALLS_TARGET} ) @@ -780,7 +818,7 @@ add_custom_command(OUTPUT include/generated/syscall_dispatch.c ${syscall_list_h} # This is passed into all calls to the gen_kobject_list.py script. set(gen_kobject_list_include_args --include-subsystem-list ${struct_tags_json}) -set(DRV_VALIDATION ${PROJECT_BINARY_DIR}/include/generated/driver-validation.h) +set(DRV_VALIDATION ${PROJECT_BINARY_DIR}/include/generated/zephyr/driver-validation.h) add_custom_command( OUTPUT ${DRV_VALIDATION} COMMAND @@ -813,7 +851,7 @@ add_dependencies(zephyr_generated_headers set(OFFSETS_LIB offsets) set(OFFSETS_C_PATH ${ARCH_DIR}/${ARCH}/core/offsets/offsets.c) -set(OFFSETS_H_PATH ${PROJECT_BINARY_DIR}/include/generated/offsets.h) +set(OFFSETS_H_PATH ${PROJECT_BINARY_DIR}/include/generated/zephyr/offsets.h) add_library( ${OFFSETS_LIB} OBJECT ${OFFSETS_C_PATH}) target_include_directories(${OFFSETS_LIB} PRIVATE @@ -886,7 +924,7 @@ foreach(zephyr_lib ${ZEPHYR_LIBS_PROPERTY}) add_dependencies(${zephyr_lib} zephyr_generated_headers) endforeach() -if(CONFIG_LLEXT) +if(CONFIG_KERNEL_WHOLE_ARCHIVE) set(WHOLE_ARCHIVE_LIBS ${ZEPHYR_LIBS_PROPERTY} kernel) else() set(WHOLE_ARCHIVE_LIBS ${ZEPHYR_LIBS_PROPERTY}) @@ -956,35 +994,19 @@ if(CONFIG_USERSPACE) set(PROCESS_GPERF ${ZEPHYR_BASE}/scripts/build/process_gperf.py) endif() -get_property(CSTD GLOBAL PROPERTY CSTD) -if(NOT DEFINED CSTD) - if(CONFIG_STD_C23) - set(CSTD c2x) - elseif(CONFIG_STD_C17) - set(CSTD c17) - elseif(CONFIG_STD_C11) - set(CSTD c11) - elseif(CONFIG_STD_C99) - set(CSTD c99) - elseif(CONFIG_STD_C90) - set(CSTD c90) - else() - message(FATAL_ERROR "Unreachable code. Expected C standard to have been chosen.") - endif() - - if(CONFIG_GNU_C_EXTENSIONS) - string(REPLACE "c" "gnu" CSTD "${CSTD}") - endif() -else() +get_property(GLOBAL_CSTD GLOBAL PROPERTY CSTD) +if(DEFINED GLOBAL_CSTD) message(DEPRECATION "Global CSTD property is deprecated, see Kconfig.zephyr for C Standard options.") + set(CSTD ${GLOBAL_CSTD}) + list(APPEND CMAKE_C_COMPILE_FEATURES ${compile_features_${CSTD}}) endif() # @Intent: Obtain compiler specific flag for specifying the c standard zephyr_compile_options( $<$:$${CSTD}> ) -set(CMAKE_C_COMPILE_FEATURES ${compile_features_${CSTD}} PARENT_SCOPE) +set(CMAKE_C_COMPILE_FEATURES ${CMAKE_C_COMPILE_FEATURES} PARENT_SCOPE) # @Intent: Configure linker scripts, i.e. generate linker scripts with variables substituted toolchain_ld_configure_files() @@ -1192,7 +1214,7 @@ if(CONFIG_USERSPACE) PUBLIC $ ) - set(KOBJECT_LINKER_HEADER_DATA "${PROJECT_BINARY_DIR}/include/generated/linker-kobject-prebuilt-data.h") + set(KOBJECT_LINKER_HEADER_DATA "${PROJECT_BINARY_DIR}/include/generated/zephyr/linker-kobject-prebuilt-data.h") add_custom_command( OUTPUT ${KOBJECT_LINKER_HEADER_DATA} @@ -1200,7 +1222,7 @@ if(CONFIG_USERSPACE) ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/build/gen_kobject_placeholders.py --object $ - --outdir ${PROJECT_BINARY_DIR}/include/generated + --outdir ${PROJECT_BINARY_DIR}/include/generated/zephyr --datapct ${CONFIG_KOBJECT_DATA_AREA_RESERVE_EXTRA_PERCENT} --rodata ${CONFIG_KOBJECT_RODATA_AREA_EXTRA_BYTES} $<$:--verbose> @@ -1292,6 +1314,20 @@ if(CONFIG_GEN_ISR_TABLES) set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_SOURCE_FILES isr_tables.c) endif() +if(CONFIG_SYMTAB) + add_custom_command( + OUTPUT symtab.c + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/gen_symtab.py + -k $ + -o symtab.c + DEPENDS ${ZEPHYR_LINK_STAGE_EXECUTABLE} + COMMAND_EXPAND_LISTS + ) + set_property(GLOBAL APPEND PROPERTY GENERATED_KERNEL_SOURCE_FILES symtab.c) +endif() + if(CONFIG_USERSPACE) set(KOBJECT_HASH_LIST kobject_hash.gperf) set(KOBJECT_HASH_OUTPUT_SRC_PRE kobject_hash_preprocessed.c) @@ -1792,6 +1828,17 @@ if(CONFIG_BUILD_OUTPUT_STRIPPED) ) endif() +if(CONFIG_BUILD_OUTPUT_COMPRESS_DEBUG_SECTIONS) + list(APPEND + post_build_commands + COMMAND $ + $ + $ + $${KERNEL_ELF_NAME} + $ +) +endif() + if(CONFIG_BUILD_OUTPUT_EXE) if (NOT CONFIG_NATIVE_LIBRARY) list(APPEND @@ -1836,6 +1883,21 @@ if(CONFIG_BUILD_OUTPUT_INFO_HEADER) ) endif() +if (CONFIG_LLEXT AND CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) + #slidgen must be the first post-build command to be executed + #on the Zephyr ELF to ensure that all other commands, such as + #binary file generation, are operating on a preparated ELF. + list(PREPEND + post_build_commands + COMMAND ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/llext_prepare_exptab.py + --elf-file ${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME} + --slid-listing ${PROJECT_BINARY_DIR}/slid_listing.txt + -vvv + ) + +endif() + if(NOT CMAKE_C_COMPILER_ID STREQUAL "ARMClang") set(check_init_priorities_input $,${BYPRODUCT_KERNEL_EXE_NAME},${BYPRODUCT_KERNEL_ELF_NAME}> @@ -1932,7 +1994,7 @@ if(LOG_DICT_DB_NAME_ARG) ${ZEPHYR_BASE}/scripts/logging/dictionary/database_gen.py ${KERNEL_ELF_NAME} ${LOG_DICT_DB_NAME_ARG}=${LOG_DICT_DB_NAME} - --build-header ${PROJECT_BINARY_DIR}/include/generated/version.h + --build-header ${PROJECT_BINARY_DIR}/include/generated/zephyr/version.h WORKING_DIRECTORY ${PROJECT_BINARY_DIR} COMMENT "Generating logging dictionary database: ${LOG_DICT_DB_NAME}" DEPENDS ${logical_target_for_zephyr_elf} @@ -2046,6 +2108,50 @@ if((CMAKE_BUILD_TYPE IN_LIST build_types) AND (NOT NO_BUILD_TYPE_WARNING)) endif() endif() +# Extension Development Kit (EDK) generation. +set(llext_edk_file ${PROJECT_BINARY_DIR}/${CONFIG_LLEXT_EDK_NAME}.tar.xz) + +# TODO maybe generate flags for C CXX ASM +zephyr_get_compile_options_for_lang(C zephyr_flags) + +# Filter out non LLEXT and LLEXT_EDK flags - and add required ones +llext_filter_zephyr_flags(LLEXT_REMOVE_FLAGS ${zephyr_flags} llext_edk_cflags) +llext_filter_zephyr_flags(LLEXT_EDK_REMOVE_FLAGS ${llext_edk_cflags} llext_edk_cflags) + +list(APPEND llext_edk_cflags ${LLEXT_APPEND_FLAGS}) +list(APPEND llext_edk_cflags ${LLEXT_EDK_APPEND_FLAGS}) + +add_custom_command( + OUTPUT ${llext_edk_file} + # Regenerate syscalls in case CONFIG_LLEXT_EDK_USERSPACE_ONLY + COMMAND ${CMAKE_COMMAND} + -E make_directory edk/include/generated/zephyr + COMMAND + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/gen_syscalls.py + --json-file ${syscalls_json} # Read this file + --base-output edk/include/generated/zephyr/syscalls # Write to this dir + --syscall-dispatch edk/include/generated/zephyr/syscall_dispatch.c # Write this file + --syscall-list ${edk_syscall_list_h} + $<$:--userspace-only> + ${SYSCALL_LONG_REGISTERS_ARG} + ${SYSCALL_SPLIT_TIMEOUT_ARG} + COMMAND ${CMAKE_COMMAND} + -DPROJECT_BINARY_DIR=${PROJECT_BINARY_DIR} + -DAPPLICATION_SOURCE_DIR=${APPLICATION_SOURCE_DIR} + -DINTERFACE_INCLUDE_DIRECTORIES="$" + -Dllext_edk_file=${llext_edk_file} + -Dllext_cflags="${llext_edk_cflags}" + -Dllext_edk_name=${CONFIG_LLEXT_EDK_NAME} + -DWEST_TOPDIR=${WEST_TOPDIR} + -DZEPHYR_BASE=${ZEPHYR_BASE} + -DCONFIG_LLEXT_EDK_USERSPACE_ONLY=${CONFIG_LLEXT_EDK_USERSPACE_ONLY} + -P ${ZEPHYR_BASE}/cmake/llext-edk.cmake + DEPENDS ${logical_target_for_zephyr_elf} + COMMAND_EXPAND_LISTS +) +add_custom_target(llext-edk DEPENDS ${llext_edk_file}) + # @Intent: Set compiler specific flags for standard C/C++ includes # Done at the very end, so any other system includes which may # be added by Zephyr components were first in list. diff --git a/CODEOWNERS b/CODEOWNERS index 60ce1a2533a62..0526619f0ad29 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -26,8 +26,6 @@ /soc/arm/infineon_xmc/ @parthitce /soc/arm/silabs_exx32/efm32pg1b/ @rdmeneze /soc/arm/silabs_exx32/efr32mg21/ @l-alfred -/soc/arm/st_stm32/ @erwango -/soc/arm/st_stm32/*/power.c @FRASTM /soc/arm/st_stm32/stm32mp1/ @arnopo /soc/arm/st_stm32/stm32h7/*stm32h735* @benediktibk /soc/arm/st_stm32/stm32l4/*stm32l451* @benediktibk @@ -55,8 +53,6 @@ /boards/arm/acn52832/ @sven-hm /boards/arm/arduino_mkrzero/ @soburi /boards/arm/bbc_microbit_v2/ @LingaoM -/boards/arm/bl5340_dvk/ @lairdjm -/boards/arm/bl65*/ @lairdjm /boards/arm/blackpill_f401ce/ @coderkalyan /boards/arm/blackpill_f411ce/ @coderkalyan /boards/arm/bt*10/ @greg-leach @@ -67,7 +63,6 @@ /boards/arm/cy8ckit_062s4/ @DaWei8823 /boards/arm/cy8ckit_062_wifi_bt/ @ifyall @npal-cy /boards/arm/cy8cproto_062_4343w/ @ifyall @npal-cy -/boards/arm/disco_l475_iot1/ @erwango /boards/arm/efm32pg_stk3401a/ @rdmeneze /boards/arm/faze/ @mbittan @simonguinot /boards/arm/frdm*/ @mmahadevan108 @dleach02 @@ -77,7 +72,6 @@ /boards/arm/ip_k66f/ @parthitce @lmajewski /boards/arm/legend/ @mbittan @simonguinot /boards/arm/lpcxpresso*/ @mmahadevan108 @dleach02 -/boards/arm/mg100/ @rerickson1 /boards/arm/mimx8mm_evk/ @Mani-Sadhasivam /boards/arm/mimx8mm_phyboard_polis @pefech /boards/arm/mimxrt*/ @mmahadevan108 @dleach02 @@ -85,10 +79,8 @@ /boards/arm/msp_exp432p401r_launchxl/ @Mani-Sadhasivam /boards/arm/npcx7m6fb_evb/ @MulinChao @ChiHuaL /boards/arm/nrf*/ @carlescufi @lemrey -/boards/arm/nucleo*/ @erwango @ABOSTM @FRASTM /boards/arm/nucleo_f401re/ @idlethread /boards/arm/nuvoton_pfm_m487/ @ssekar15 -/boards/arm/pinnacle_100_dvk/ @rerickson1 /boards/arm/qemu_cortex_a9/ @ibirnbaum /boards/arm/qemu_cortex_r*/ @stephanosio /boards/arm/qemu_cortex_m*/ @ioannisg @stephanosio @@ -106,14 +98,13 @@ /boards/arm/sensortile_box/ @avisconti /boards/arm/steval_fcu001v1/ @Navin-Sankar /boards/arm/stm32l1_disco/ @karlp -/boards/arm/stm32*_disco/ @erwango @ABOSTM @FRASTM /boards/arm/stm32h735g_disco/ @benediktibk /boards/arm/stm32f3_disco/ @ydamigos -/boards/arm/stm32*_eval/ @erwango @ABOSTM @FRASTM /boards/arm/rcar_*/ @aaillet /boards/arm/ubx_bmd345eval_nrf52840/ @Navin-Sankar @brec-u-blox /boards/arm/nrf5340_audio_dk_nrf5340 @koffes @alexsven @erikrobstad @rick1082 @gWacey /boards/arm/stm32_min_dev/ @sidcha +/boards/ezurio/* @rerickson1 /boards/riscv/rv32m1_vega/ @dleach02 /boards/riscv/adp_xc7k_ae350/ @cwshu @kevinwang821020 @jimmyzhe /boards/riscv/longan_nano/ @soburi @@ -151,9 +142,7 @@ /drivers/*/*sam4l* @nandojve /drivers/*/*cc13xx_cc26xx* @bwitherspoon /drivers/*/*gd32* @nandojve -/drivers/*/*litex* @mateusz-holenko @kgugala @pgielda /drivers/*/*mcux* @mmahadevan108 @dleach02 -/drivers/*/*stm32* @erwango @ABOSTM @FRASTM /drivers/*/*native_posix* @aescolar @daor-oti /drivers/*/*lpc11u6x* @mbittan @simonguinot /drivers/*/*npcx* @MulinChao @ChiHuaL @@ -211,7 +200,6 @@ /drivers/entropy/*b91* @andy-liu-telink /drivers/entropy/*bt_hci* @JordanYates /drivers/entropy/*rv32m1* @dleach02 -/drivers/entropy/*litex* @mateusz-holenko @kgugala @pgielda /drivers/ethernet/*dwmac* @npitre /drivers/ethernet/*stm32* @Nukersson @lochej /drivers/ethernet/*w5500* @parthitce @@ -233,7 +221,6 @@ /drivers/gpio/*b91* @andy-liu-telink /drivers/gpio/*lmp90xxx* @henrikbrixandersen /drivers/gpio/*nct38xx* @MulinChao @ChiHuaL -/drivers/gpio/*stm32* @erwango /drivers/gpio/*eos_s3* @fkokosinski @kgugala /drivers/gpio/*rcar* @aaillet /drivers/gpio/*esp32* @sylvioalves @@ -257,13 +244,12 @@ /drivers/i2c/i2c_test.c @mbolivar-ampere /drivers/i2c/*rcar* @aaillet /drivers/i2c/*kb1200* @ene-steven -/drivers/i2s/*litex* @mateusz-holenko @kgugala @pgielda /drivers/i2s/i2s_ll_stm32* @avisconti /drivers/i2s/*nrfx* @anangl /drivers/i3c/i3c_cdns.c @XenuIsWatching /drivers/ieee802154/ @rlubos @tbursztyka @jukkar @fgrandel /drivers/ieee802154/*b91* @andy-liu-telink -/drivers/ieee802154/ieee802154_nrf5* @jciupis +/drivers/ieee802154/ieee802154_nrf5* @ankuns /drivers/ieee802154/ieee802154_rf2xx* @tbursztyka @nandojve /drivers/ieee802154/ieee802154_cc13xx* @bwitherspoon @cfriedt @vaishnavachath /drivers/interrupt_controller/ @dcpleung @nashif @@ -333,6 +319,7 @@ /drivers/sensor/qdec_stm32/ @valeriosetti /drivers/sensor/rpi_pico_temp/ @soburi /drivers/sensor/st*/ @avisconti +/drivers/sensor/veaa_x_3/ @jeppenodgaard @MaureenHelm /drivers/sensor/ene_tack_kb1200/ @ene-steven /drivers/serial/*b91* @andy-liu-telink /drivers/serial/uart_altera_jtag.c @nashif @gohshunjing @@ -376,7 +363,6 @@ /drivers/timer/*xlnx_psttc* @wjliang @stephanosio /drivers/timer/*cc13xx_cc26xx_rtc* @vanti /drivers/timer/*cavs* @dcpleung -/drivers/timer/*stm32_lptim* @FRASTM /drivers/timer/*leon_gptimer* @julius-barendt /drivers/timer/*mips_cp0* @frantony /drivers/timer/*rcar_cmt* @aaillet @@ -426,7 +412,6 @@ /dts/arm64/renesas/ @lorc @xakep-amatop /dts/arm/quicklogic/ @fkokosinski @kgugala /dts/arm/seeed_studio/ @str4t0m -/dts/arm/st/ @erwango /dts/arm/st/h7/*stm32h735* @benediktibk /dts/arm/st/l4/*stm32l451* @benediktibk /dts/arm/ti/cc13?2* @bwitherspoon @@ -449,7 +434,6 @@ /dts/riscv/ite/ @ite /dts/riscv/microchip/microchip-miv.dtsi @galak /dts/riscv/openisa/rv32m1* @dleach02 -/dts/riscv/riscv32-litex-vexriscv.dtsi @mateusz-holenko @kgugala @pgielda /dts/riscv/starfive/ @rajnesh-kanwal @pfarwsi /dts/riscv/andes/andes_v5* @cwshu @kevinwang821020 @jimmyzhe /dts/riscv/niosv/ @sweeaun @@ -481,11 +465,8 @@ /dts/bindings/*/nxp*s32* @manuargue /dts/bindings/*/openisa* @dleach02 /dts/bindings/*/raspberrypi*pico* @yonsch -/dts/bindings/*/st* @erwango /dts/bindings/sensor/ams* @alexanderwachter /dts/bindings/*/sifive* @mateusz-holenko @kgugala @pgielda -/dts/bindings/*/litex* @mateusz-holenko @kgugala @pgielda -/dts/bindings/*/vexriscv* @mateusz-holenko @kgugala @pgielda /dts/bindings/*/andes* @cwshu @kevinwang821020 @jimmyzhe /dts/bindings/*/neorv32* @henrikbrixandersen /dts/bindings/*/*lan91c111* @sgrrzhf diff --git a/Kconfig.zephyr b/Kconfig.zephyr index fd9076a38d94f..01b5f4497e095 100644 --- a/Kconfig.zephyr +++ b/Kconfig.zephyr @@ -784,6 +784,11 @@ config BUILD_OUTPUT_STRIPPED Build a stripped binary zephyr/zephyr.strip in the build directory. The name of this file can be customized with CONFIG_KERNEL_BIN_NAME. +config BUILD_OUTPUT_COMPRESS_DEBUG_SECTIONS + bool "Compress debug sections in the ELF file" + help + Compress debug sections in the ELF file to reduce the file size. + config BUILD_OUTPUT_ADJUST_LMA string help @@ -1043,3 +1048,20 @@ config BOOTLOADER_BOSSA_ADAFRUIT_UF2 endchoice endmenu + +menu "Compatibility" + +config LEGACY_GENERATED_INCLUDE_PATH + bool "Legacy include path for generated headers" + default y + help + Allow applications and libraries to use the Zephyr legacy include + path for the generated headers which does not use the `zephyr/` prefix. + + From now on, i.e., the preferred way to include the `version.h` header is to + use , this Kconfig is currently enabled by default so that + user applications won't immediately fail to compile. + + This Kconfig will be deprecated and eventually removed in the future releases. + +endmenu diff --git a/MAINTAINERS.yml b/MAINTAINERS.yml index f1d8a75b0a7eb..b110c29cde4fb 100644 --- a/MAINTAINERS.yml +++ b/MAINTAINERS.yml @@ -114,11 +114,7 @@ ACPI: status: maintained maintainers: - - jhedberg - najumon1980 - collaborators: - - finikorg - - tbursztyka files: - lib/acpi/ - include/zephyr/acpi/ @@ -244,7 +240,7 @@ Ambiq Platforms: status: odd fixes collaborators: - aaronyegx - - HaoLuo + - AlessandroLuo - RichardSWheatley files: - soc/ambiq/ @@ -441,18 +437,23 @@ Bluetooth Audio: - kruithofa - larsgk - pin-zephyr + - niym-ot + - jthm-ot files: - subsys/bluetooth/audio/ - include/zephyr/bluetooth/audio/ - tests/bluetooth/audio/ - tests/bsim/bluetooth/audio/ + - tests/bsim/bluetooth/audio_samples/ - tests/bluetooth/shell/audio.conf + - tests/bluetooth/tester/overlay-le-audio.conf + - tests/bluetooth/tester/src/audio/ - doc/connectivity/bluetooth/api/audio/ - - samples/bluetooth/broadcast_audio*/ + - samples/bluetooth/bap*/ + - samples/bluetooth/cap*/ - samples/bluetooth/hap*/ - - samples/bluetooth/public_broadcast*/ + - samples/bluetooth/pbp*/ - samples/bluetooth/tmap*/ - - samples/bluetooth/unicast_audio*/ labels: - "area: Bluetooth Audio" - "area: Bluetooth" @@ -649,6 +650,7 @@ Coding Guidelines: - nashif - carlescufi - jfischer-no + - simhein files: - .checkpatch.conf - .clang-format @@ -716,6 +718,20 @@ Debug: tests: - debug +"Debug: Symtab": + status: maintained + maintainers: + - ycsin + files: + - include/zephyr/debug/symtab.h + - subsys/debug/symtab/ + - tests/subsys/debug/symtab/ + - scripts/build/gen_symtab.py + labels: + - "area: Symtab" + tests: + - debug.symtab + Demand Paging: status: maintained maintainers: @@ -855,6 +871,7 @@ Documentation: - doc/project/ - doc/releases/ - doc/security/ + - doc/safety/ - README.rst - doc/substitutions.txt - doc/images/Zephyr-Kite-in-tree.png @@ -1009,7 +1026,7 @@ Release Notes: maintainers: - rriveramcrus collaborators: - - GRobertZieba + - RobertZ2011 files: - drivers/charger/ - dts/bindings/charger/ @@ -1093,6 +1110,7 @@ Release Notes: - include/zephyr/crypto/ - samples/drivers/crypto/ - tests/crypto/ + - doc/services/crypto/ labels: - "area: Crypto / RNG" tests: @@ -1235,6 +1253,7 @@ Release Notes: collaborators: - decsny - lmajewski + - pdgendt files: - drivers/ethernet/ - include/zephyr/dt-bindings/ethernet/ @@ -1422,7 +1441,7 @@ Release Notes: - fgrandel collaborators: - rlubos - - jciupis + - ankuns - cfriedt - jukkar files: @@ -1493,6 +1512,8 @@ Release Notes: "Drivers: Reset": status: odd fixes + collaborators: + - decsny files: - drivers/reset/ - include/zephyr/drivers/reset.h @@ -1673,10 +1694,6 @@ Release Notes: status: maintained maintainers: - dcpleung - collaborators: - - jhedberg - - finikorg - - tbursztyka files: - drivers/pcie/ - include/zephyr/drivers/pcie/ @@ -1819,6 +1836,8 @@ Release Notes: - teburd - yperess - tristan-google + - ubieda + - jeppenodgaard files: - drivers/sensor/ - include/zephyr/drivers/sensor.h @@ -1828,7 +1847,7 @@ Release Notes: - dts/bindings/sensor/ - include/zephyr/drivers/sensor/ - include/zephyr/dt-bindings/sensor/ - - doc/hardware/peripherals/sensor.rst + - doc/hardware/peripherals/sensor/ - tests/drivers/build_all/sensor/ labels: - "area: Sensors" @@ -2310,16 +2329,16 @@ Memory Management: tests: - mem_mgmt -Laird Connectivity platforms: +Ezurio platforms: status: maintained maintainers: - rerickson1 collaborators: - greg-leach files: - - boards/lairdconnect/ + - boards/ezurio/ labels: - - "platform: Laird Connectivity" + - "platform: Ezurio" Linker Scripts: status: maintained @@ -2416,7 +2435,6 @@ Mbed TLS: - ithinuel files: - tests/crypto/mbedtls/ - - doc/services/crypto/ - tests/benchmarks/mbedtls/ labels: - "area: Crypto / RNG" @@ -2571,9 +2589,11 @@ Networking: files-exclude: - doc/connectivity/networking/api/gptp.rst - doc/connectivity/networking/api/ieee802154.rst + - doc/connectivity/networking/api/ptp.rst - doc/connectivity/networking/api/wifi.rst - include/zephyr/net/gptp.h - include/zephyr/net/ieee802154*.h + - include/zephyr/net/ptp.h - include/zephyr/net/wifi*.h - include/zephyr/net/buf.h - include/zephyr/net/dhcpv4*.h @@ -2589,6 +2609,7 @@ Networking: - subsys/net/lib/coap/ - subsys/net/lib/config/ieee802154* - subsys/net/lib/lwm2m/ + - subsys/net/lib/ptp/ - subsys/net/lib/tls_credentials/ - subsys/net/lib/dhcpv4/ - tests/net/dhcpv4/ @@ -2744,6 +2765,20 @@ Networking: tests: - net.mqtt_sn +"Networking: PTP": + status: maintained + maintainers: + - awojasinski + files: + - doc/connectivity/networking/api/ptp.rst + - include/zephyr/net/ptp.h + - subsys/net/lib/ptp/ + - samples/net/ptp/ + labels: + - "area: Networking" + tests: + - sample.net.ptp + "Networking: Native IEEE 802.15.4": status: maintained maintainers: @@ -2966,6 +3001,7 @@ Sensor Subsystem: - doc/services/sensing/ - subsys/sensing/ - samples/subsys/sensing/ + - tests/subsys/sensing/ labels: - "area: Sensor Subsystem" tests: @@ -3082,11 +3118,13 @@ State machine framework: - sambhurst collaborators: - keith-zephyr + - glenn-andrews files: - doc/services/smf/ - include/zephyr/smf.h - lib/smf/ - tests/lib/smf/ + - samples/subsys/smf/ labels: - "area: State Machine Framework" tests: @@ -3101,16 +3139,18 @@ ADI Platforms: - microbuilder files: - boards/adi/ - - drivers/*/max* + - drivers/*/*max* - drivers/*/*max*/ - drivers/dac/dac_ltc* - drivers/ethernet/eth_adin* - drivers/mdio/mdio_adin* - drivers/regulator/regulator_adp5360* - drivers/sensor/adi/ + - dts/arm/adi/ - dts/bindings/*/adi,* - dts/bindings/*/lltc,* - dts/bindings/*/maxim,* + - soc/adi/ labels: - "platform: ADI" @@ -3149,11 +3189,17 @@ Synopsys Platforms: collaborators: - abrodkin - evgeniy-paltsev - - IRISZZW files: - soc/snps/ - boards/snps/ + - boards/qemu/arc/ - samples/boards/arc_secure_services/ + - scripts/west_commands/runners/mdb.py + - scripts/west_commands/tests/test_mdb.py + - scripts/west_commands/runners/nsim.py + - cmake/emu/nsim.cmake + - drivers/serial/uart_hostlink.c + - drivers/serial/Kconfig.hostlink labels: - "platform: Synopsys" @@ -3215,8 +3261,13 @@ Raspberry Pi Pico Platforms: labels: - "platform: Raspberry Pi Pico" -SiLabs Platforms: - status: odd fixes +Silabs Platforms: + status: maintained + maintainers: + - jhedberg + collaborators: + - jerome-pouiller + - asmellby files: - soc/silabs/ - boards/silabs/ @@ -3224,16 +3275,17 @@ SiLabs Platforms: - dts/bindings/*/silabs* - drivers/*/*_gecko* labels: - - "platform: SiLabs" + - "platform: Silabs" Intel Platforms (X86): status: maintained maintainers: - - jhedberg + - edersondisouza collaborators: - - tbursztyka - - laurenmurphyx64 - najumon1980 + - teburd + - dcpleung + - ceolin files: - boards/intel/adl/ - boards/intel/ehl/ @@ -3242,16 +3294,18 @@ Intel Platforms (X86): - soc/intel/atom/ - soc/intel/lakemont/ - soc/intel/*_lake/ + - drivers/timer/Kconfig.x86 + - drivers/timer/hpet.c + - drivers/timer/apic* labels: - "platform: X86" Intel Platforms (Xtensa): status: maintained maintainers: - - nashif + - dcpleung collaborators: - andyross - - dcpleung - lyakh - lgirdwood - marc-hb @@ -3261,6 +3315,7 @@ Intel Platforms (Xtensa): - softwarecki - jxstelter - marcinszkudlinski + - nashif files: - boards/intel/adsp/ - soc/intel/intel_adsp/ @@ -3279,6 +3334,7 @@ Intel Platforms (ISH): collaborators: - teburd - likongintel + - nashif files: - boards/intel/ish/ - soc/intel/intel_ish/ @@ -3346,6 +3402,7 @@ NXP Platforms (MCU): - yvanderv - EmilioCBen - decsny + - butok files: - boards/nxp/mimxrt*/ - boards/nxp/frdm*/ @@ -3466,11 +3523,11 @@ nRF Platforms: status: maintained maintainers: - anangl + - masz-nordic collaborators: - jaz1-nordic - kl-cruz - magp-nordic - - masz-nordic - nika-nordic files: - boards/nordic/ @@ -3485,12 +3542,29 @@ nRF Platforms: labels: - "platform: nRF" +OpenTitan Platforms: + status: maintained + maintainers: + - snematbakhsh + files: + - boards/lowrisc/opentitan_earlgrey/ + - drivers/*/*opentitan* + - dts/bindings/*/*opentitan* + - dts/riscv/lowrisc/*opentitan* + - soc/lowrisc/opentitan/ + labels: + - "platform: OpenTitan" + description: >- + OpenTitan boards, SOCs, dts files and related drivers. + Renesas SmartBond Platforms: status: maintained maintainers: - ioannis-karachalios - andrzej-kaczmarek - blauret + collaborators: + - ydamigos files: - boards/renesas/da14*/ - drivers/*/*smartbond* @@ -3570,6 +3644,7 @@ STM32 Platforms: - FRASTM - gautierg-st - GeorgeCGV + - marwaiehm-st files: - boards/st/ - drivers/*/*stm32*.c @@ -3623,7 +3698,7 @@ ITE Platforms: - drivers/sensor/ite/ - drivers/*/*it8xxx2*.c - drivers/*/*_ite_* - - dts/bindings/*/*ite* + - dts/bindings/*/ite* - dts/riscv/ite/ - soc/ite/ labels: @@ -3703,8 +3778,6 @@ Infineon Platforms: - drivers/*/*xmc* - drivers/sensor/infineon/ - dts/arm/infineon/ - - dts/arm/cypress/ - - soc/cypress/ - dts/bindings/*/*infineon* - soc/infineon/ labels: @@ -3713,6 +3786,29 @@ Infineon Platforms: Infineon SOCs, dts files and related drivers. Infineon Proto, Pioneer, Eval and Relax boards. +LiteX Platforms: + status: maintained + maintainers: + - tgorochowik + - kgugala + - fkokosinski + collaborators: + - mateusz-holenko + - maass-hamburg + files: + - boards/enjoydigital/litex_vexriscv/ + - drivers/*/*litex* + - drivers/spi/spi_litespi* + - drivers/*/Kconfig.litex + - dts/bindings/*/litex* + - dts/riscv/riscv32-litex-vexriscv.dtsi + - include/zephyr/drivers/*/*litex* + - samples/boards/litex/ + - samples/drivers/*litex/ + - soc/litex/ + labels: + - "platform: LiteX" + Panasonic Platforms: status: maintained maintainers: @@ -3728,6 +3824,7 @@ RTIO: - teburd collaborators: - yperess + - ubieda files: - samples/subsys/rtio/ - include/zephyr/rtio/ @@ -3760,12 +3857,12 @@ Sysbuild: - "57300" files: - share/sysbuild/ - - samples/application_development/sysbuild/ + - samples/sysbuild/ - doc/build/sysbuild/ labels: - "area: Sysbuild" tests: - - sample.application_development.sysbuild + - sample.sysbuild Task Watchdog: status: maintained @@ -3832,7 +3929,7 @@ TF-M Integration: labels: - "area: TF-M" tests: - - tfm + - trusted-firmware-m "Toolchain Integration": @@ -4012,9 +4109,6 @@ West: status: maintained maintainers: - najumon1980 - - jhedberg - collaborators: - - tbursztyka files: - modules/acpica/ labels: @@ -4189,6 +4283,16 @@ West: labels: - "area: Storage" +"West project: hal_adi": + status: maintained + maintainers: + - MaureenHelm + collaborators: + - ozersa + files: [] + labels: + - "platform: ADI" + "West project: hal_altera": status: odd fixes collaborators: @@ -4202,6 +4306,7 @@ West: status: odd fixes collaborators: - aaronyegx + - AlessandroLuo - RichardSWheatley files: - modules/hal_ambiq/ @@ -4352,7 +4457,11 @@ West: status: maintained maintainers: - KhiemNguyenT + - ioannis-karachalios + collaborators: + - blauret - andrzej-kaczmarek + - ydamigos files: [] labels: - "platform: Renesas" @@ -4367,15 +4476,19 @@ West: - "platform: Raspberry Pi Pico" "West project: hal_silabs": - status: odd fixes + status: maintained + maintainers: + - jhedberg collaborators: + - jerome-pouiller + - asmellby - sateeshkotapati - yonsch - mnkp files: - modules/Kconfig.silabs labels: - - "platform: SiLabs" + - "platform: Silabs" "West project: hal_st": status: maintained @@ -4392,9 +4505,8 @@ West: - erwango collaborators: - FRASTM - - ABOSTM - gautierg-st - - Desvauxm-st + - marwaiehm-st files: - modules/Kconfig.stm32 labels: @@ -4530,7 +4642,7 @@ West: - nordicjm files: - modules/Kconfig.mcuboot - - tests/boot/test_mcuboot/ + - tests/boot/ labels: - "area: MCUBoot" @@ -4784,15 +4896,14 @@ Xtensa arch: x86 arch: status: maintained maintainers: - - jhedberg + - edersondisouza collaborators: - - tbursztyka - andyross - - nashif - dcpleung - ceolin - laurenmurphyx64 - najumon1980 + - nashif files: - arch/x86/ - include/zephyr/arch/x86/ diff --git a/SDK_VERSION b/SDK_VERSION index e35e56114f44c..74aaa3f38cfe8 100644 --- a/SDK_VERSION +++ b/SDK_VERSION @@ -1 +1 @@ -0.16.5-1 +0.16.8 diff --git a/arch/Kconfig b/arch/Kconfig index b9e40d8ec20fa..6b8fa7dcb4bf0 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -24,6 +24,7 @@ config ARC imply XIP select ARCH_HAS_THREAD_LOCAL_STORAGE select ARCH_SUPPORTS_ROM_START + select ARCH_HAS_DIRECTED_IPIS help ARC architecture @@ -50,6 +51,7 @@ config ARM64 select USE_SWITCH_SUPPORTED select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD select BARRIER_OPERATIONS_ARCH + select ARCH_HAS_DIRECTED_IPIS help ARM64 (AArch64) architecture @@ -108,13 +110,15 @@ config RISCV bool select ARCH_IS_SET select ARCH_SUPPORTS_COREDUMP - select ARCH_SUPPORTS_ROM_START if !SOC_SERIES_ESP32C3 + select ARCH_SUPPORTS_ROM_START if !SOC_FAMILY_ESPRESSIF_ESP32 select ARCH_HAS_CODE_DATA_RELOCATION select ARCH_HAS_THREAD_LOCAL_STORAGE + select ARCH_HAS_STACKWALK select IRQ_OFFLOAD_NESTED if IRQ_OFFLOAD select USE_SWITCH_SUPPORTED select USE_SWITCH select SCHED_IPI_SUPPORTED if SMP + select ARCH_HAS_DIRECTED_IPIS select BARRIER_OPERATIONS_BUILTIN imply XIP help @@ -129,6 +133,7 @@ config XTENSA select ARCH_HAS_CODE_DATA_RELOCATION select ARCH_HAS_TIMING_FUNCTIONS select ARCH_MEM_DOMAIN_DATA if USERSPACE + select ARCH_HAS_DIRECTED_IPIS help Xtensa architecture @@ -221,6 +226,7 @@ DT_CHOSEN_Z_FLASH := zephyr,flash config FLASH_SIZE int "Flash Size in kB" default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_FLASH),0,K) if (XIP && (ARM ||ARM64)) || !ARM + default 0 if !XIP help This option specifies the size of the flash in kB. It is normally set by the board's defconfig file and the user should generally avoid modifying @@ -229,6 +235,7 @@ config FLASH_SIZE config FLASH_BASE_ADDRESS hex "Flash Base Address" default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_FLASH)) if (XIP && (ARM || ARM64)) || !ARM + default 0 if !XIP help This option specifies the base address of the flash on the board. It is normally set by the board's defconfig file and the user should generally @@ -398,6 +405,21 @@ config NOCACHE_MEMORY transfers when cache coherence issues are not optimal or can not be solved using cache maintenance operations. +config FRAME_POINTER + bool "Compile the kernel with frame pointers" + select OVERRIDE_FRAME_POINTER_DEFAULT + help + Select Y here to gain precise stack traces at the expense of slightly + increased size and decreased speed. + +config ARCH_STACKWALK_MAX_FRAMES + int "Max depth for stack walk function" + default 8 + depends on ARCH_HAS_STACKWALK + help + Depending on implementation, this can place a hard limit on the depths of the stack + for the stack walk function to examine. + menu "Interrupt Configuration" config ISR_TABLES_LOCAL_DECLARATION_SUPPORTED @@ -643,6 +665,11 @@ config ARCH_HAS_EXTRA_EXCEPTION_INFO config ARCH_HAS_GDBSTUB bool +config ARCH_HAS_STACKWALK + bool + help + This is selected when the architecture implemented the arch_stack_walk() API. + config ARCH_HAS_COHERENCE bool help @@ -739,6 +766,13 @@ config ARCH_HAS_RESERVED_PAGE_FRAMES memory mappings. The architecture will need to implement arch_reserved_pages_update(). +config ARCH_HAS_DIRECTED_IPIS + bool + help + This hidden configuration should be selected by the architecture if + it has an implementation for arch_sched_directed_ipi() which allows + for IPIs to be directed to specific CPUs. + config CPU_HAS_DCACHE bool help @@ -774,7 +808,7 @@ config ARCH_MAPS_ALL_RAM virtual addresses elsewhere, this is limited to only management of the virtual address space. The kernel's page frame ontology will not consider this mapping at all; non-kernel pages will be considered free (unless marked - as reserved) and Z_PAGE_FRAME_MAPPED will not be set. + as reserved) and K_MEM_PAGE_FRAME_MAPPED will not be set. config DCLS bool "Processor is configured in DCLS mode" diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig index 8a3bd5b1b3c2a..bd1b30517d4eb 100644 --- a/arch/arc/Kconfig +++ b/arch/arc/Kconfig @@ -18,6 +18,7 @@ config CPU_ARCEM config CPU_ARCHS bool select ATOMIC_OPERATIONS_BUILTIN + select BARRIER_OPERATIONS_BUILTIN help This option signifies the use of an ARC HS CPU diff --git a/arch/arc/core/fatal.c b/arch/arc/core/fatal.c index f193c0b09f1f2..512d1cc442c6f 100644 --- a/arch/arc/core/fatal.c +++ b/arch/arc/core/fatal.c @@ -23,7 +23,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); #ifdef CONFIG_EXCEPTION_DEBUG -static void dump_arc_esf(const z_arch_esf_t *esf) +static void dump_arc_esf(const struct arch_esf *esf) { ARC_EXCEPTION_DUMP(" r0: 0x%" PRIxPTR " r1: 0x%" PRIxPTR " r2: 0x%" PRIxPTR " r3: 0x%" PRIxPTR "", esf->r0, esf->r1, esf->r2, esf->r3); @@ -42,7 +42,7 @@ static void dump_arc_esf(const z_arch_esf_t *esf) } #endif -void z_arc_fatal_error(unsigned int reason, const z_arch_esf_t *esf) +void z_arc_fatal_error(unsigned int reason, const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG if (esf != NULL) { diff --git a/arch/arc/core/fault.c b/arch/arc/core/fault.c index 763ed7a2c737a..6f9da3cd1e0e9 100644 --- a/arch/arc/core/fault.c +++ b/arch/arc/core/fault.c @@ -346,7 +346,7 @@ static void dump_exception_info(uint32_t vector, uint32_t cause, uint32_t parame * invokes the user provided routine k_sys_fatal_error_handler() which is * responsible for implementing the error handling policy. */ -void _Fault(z_arch_esf_t *esf, uint32_t old_sp) +void _Fault(struct arch_esf *esf, uint32_t old_sp) { uint32_t vector, cause, parameter; uint32_t exc_addr = z_arc_v2_aux_reg_read(_ARC_V2_EFA); diff --git a/arch/arc/core/isr_wrapper.S b/arch/arc/core/isr_wrapper.S index 3471e4d73498d..4b486ed926da5 100644 --- a/arch/arc/core/isr_wrapper.S +++ b/arch/arc/core/isr_wrapper.S @@ -26,7 +26,7 @@ GTEXT(_isr_wrapper) GTEXT(_isr_demux) #if defined(CONFIG_PM) -GTEXT(z_pm_save_idle_exit) +GTEXT(pm_system_resume) #endif /* @@ -253,7 +253,7 @@ rirq_path: st 0, [r1, _kernel_offset_to_idle] /* zero idle duration */ PUSHR blink - jl z_pm_save_idle_exit + jl pm_system_resume POPR blink _skip_pm_save_idle_exit: diff --git a/arch/arc/core/mpu/Kconfig b/arch/arc/core/mpu/Kconfig index 7078d88d534ae..2f288de25c7d5 100644 --- a/arch/arc/core/mpu/Kconfig +++ b/arch/arc/core/mpu/Kconfig @@ -35,5 +35,7 @@ config ARC_MPU select GEN_PRIV_STACKS if !(ARC_MPU_VER = 4 || ARC_MPU_VER = 8) select MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT if !(ARC_MPU_VER = 4 || ARC_MPU_VER = 8) select MPU_REQUIRES_NON_OVERLAPPING_REGIONS if (ARC_MPU_VER = 4 || ARC_MPU_VER = 8) + select ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + select MEM_DOMAIN_ISOLATED_STACKS help Target has ARC MPU diff --git a/arch/arc/core/mpu/arc_core_mpu.c b/arch/arc/core/mpu/arc_core_mpu.c index 0ffcdc875b4e3..2d739d7a233ed 100644 --- a/arch/arc/core/mpu/arc_core_mpu.c +++ b/arch/arc/core/mpu/arc_core_mpu.c @@ -34,7 +34,7 @@ int arch_mem_domain_max_partitions_get(void) /* * Validate the given buffer is user accessible or not */ -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { return arc_core_mpu_buffer_validate(addr, size, write); } diff --git a/arch/arc/core/mpu/arc_mpu_common_internal.h b/arch/arc/core/mpu/arc_mpu_common_internal.h index 736a9742af96b..a9ff5518b2fd3 100644 --- a/arch/arc/core/mpu/arc_mpu_common_internal.h +++ b/arch/arc/core/mpu/arc_mpu_common_internal.h @@ -207,7 +207,7 @@ int arc_core_mpu_get_max_domain_partition_regions(void) /** * @brief validate the given buffer is user accessible or not */ -int arc_core_mpu_buffer_validate(void *addr, size_t size, int write) +int arc_core_mpu_buffer_validate(const void *addr, size_t size, int write) { /* * For ARC MPU, smaller region number takes priority. diff --git a/arch/arc/core/mpu/arc_mpu_v4_internal.h b/arch/arc/core/mpu/arc_mpu_v4_internal.h index e7e91fed93fd3..3bf6fca6c43b8 100644 --- a/arch/arc/core/mpu/arc_mpu_v4_internal.h +++ b/arch/arc/core/mpu/arc_mpu_v4_internal.h @@ -779,7 +779,7 @@ int arc_core_mpu_get_max_domain_partition_regions(void) /** * @brief validate the given buffer is user accessible or not */ -int arc_core_mpu_buffer_validate(void *addr, size_t size, int write) +int arc_core_mpu_buffer_validate(const void *addr, size_t size, int write) { int r_index; int key = arch_irq_lock(); diff --git a/arch/arc/core/smp.c b/arch/arc/core/smp.c index 9f8ee38a4a105..e8463b7b53b35 100644 --- a/arch/arc/core/smp.c +++ b/arch/arc/core/smp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -130,21 +131,27 @@ static void sched_ipi_handler(const void *unused) z_sched_ipi(); } -/* arch implementation of sched_ipi */ -void arch_sched_ipi(void) +void arch_sched_directed_ipi(uint32_t cpu_bitmap) { - uint32_t i; + unsigned int i; + unsigned int num_cpus = arch_num_cpus(); - /* broadcast sched_ipi request to other cores + /* Send sched_ipi request to other cores * if the target is current core, hardware will ignore it */ - unsigned int num_cpus = arch_num_cpus(); for (i = 0U; i < num_cpus; i++) { - z_arc_connect_ici_generate(i); + if ((cpu_bitmap & BIT(i)) != 0) { + z_arc_connect_ici_generate(i); + } } } +void arch_sched_broadcast_ipi(void) +{ + arch_sched_directed_ipi(IPI_ALL_CPUS_MASK); +} + int arch_smp_init(void) { struct arc_connect_bcr bcr; @@ -188,5 +195,4 @@ int arch_smp_init(void) return 0; } -SYS_INIT(arch_smp_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); #endif diff --git a/arch/arc/include/kernel_arch_data.h b/arch/arc/include/kernel_arch_data.h index efe2bd7d1c658..b0dc733446b08 100644 --- a/arch/arc/include/kernel_arch_data.h +++ b/arch/arc/include/kernel_arch_data.h @@ -36,7 +36,7 @@ extern "C" { #endif #ifdef CONFIG_ARC_HAS_SECURE -struct _irq_stack_frame { +struct arch_esf { #ifdef CONFIG_ARC_HAS_ZOL uintptr_t lp_end; uintptr_t lp_start; @@ -72,7 +72,7 @@ struct _irq_stack_frame { uintptr_t status32; }; #else -struct _irq_stack_frame { +struct arch_esf { uintptr_t r0; uintptr_t r1; uintptr_t r2; @@ -108,7 +108,7 @@ struct _irq_stack_frame { }; #endif -typedef struct _irq_stack_frame _isf_t; +typedef struct arch_esf _isf_t; diff --git a/arch/arc/include/kernel_arch_func.h b/arch/arc/include/kernel_arch_func.h index 1c46423cb4f03..ca382a274f4b1 100644 --- a/arch/arc/include/kernel_arch_func.h +++ b/arch/arc/include/kernel_arch_func.h @@ -62,9 +62,7 @@ extern void z_arc_userspace_enter(k_thread_entry_t user_entry, void *p1, void *p2, void *p3, uint32_t stack, uint32_t size, struct k_thread *thread); -extern void z_arc_fatal_error(unsigned int reason, const z_arch_esf_t *esf); - -extern void arch_sched_ipi(void); +extern void z_arc_fatal_error(unsigned int reason, const struct arch_esf *esf); extern void z_arc_switch(void *switch_to, void **switched_from); diff --git a/arch/arc/include/offsets_short_arch.h b/arch/arc/include/offsets_short_arch.h index 5bf2c23fc3a36..f461112ae7926 100644 --- a/arch/arc/include/offsets_short_arch.h +++ b/arch/arc/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_ARC_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_ARC_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3f5f3075777fc..c28cf8d29f9a4 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -34,6 +34,71 @@ config ARM_CUSTOM_INTERRUPT_CONTROLLER is assumed that the custom interrupt control interface implementation assumes responsibility for handling the NVIC. +config ROMSTART_RELOCATION_ROM + bool "Relocate rom_start region" + default n + help + Relocates the rom_start region containing the boot-vector data and + irq vectors to the region specified by configurations: + ROMSTART_REGION_ADDRESS and ROMSTART_REGION_SIZE + + This is useful for the Linux Remoteproc framework that uses the elf-loader + such that it is able to load the correct boot-vector (contained in rom_start) + into the correct memory location independent of the chosen zephyr,flash + ROM region. + + Most SOCs include an alias for the boot-vector at address 0x00000000 + so a default which might be supported by the corresponding Linux rproc driver. + If it is not, additionnal options allows to specify the addresses. + + In general this option should be chosen if the zephyr,flash chosen node + is not placed into the boot-vector memory area. + + While this aims at generating a correct zephyr.elf file, it has the side + effect of enlarging the bin file. If the zephyr.bin file is used to boot the + secondary core, this option should be disabled. + + Example: + on IMX7D, the chosen zephyr,flash can be OCRAM/OCRAM_S/TCM/DDR memories + for code location. But the boot-vector must be placed into OCRAM_S for the + CORTEX-M to boot (alias 0, real 0x00180000/32K available). + +if ROMSTART_RELOCATION_ROM + + config ROMSTART_REGION_ADDRESS + hex "Base address of the rom_start region" + default 0x00000000 + help + Start address of the rom_start region. + This setting can be derived from a DT node reg property or specified directly. + + A default value of 0x00000000 might work in most cases as SOCs have an alias + to the right memory region of the boot-vector. + + Examples: + -IMX7D the boot-vector is OCRAM_S (0x00180000, aliased at 0x0). + -IMX6SX the boot-vector is TCML (0x007F8000, aliased at 0x0). + -IMX8MQ the boot-vector is TCML (0x007E0000, aliased at 0x0). + -IMX8MN the boot-vector is ITCM (0x007E0000, aliased at 0x0). + + Example of DT definition: + $(dt_nodelabel_reg_addr_hex,ocram_s_sys) + + config ROMSTART_REGION_SIZE + hex "Size of the rom_start region" + default 1 + help + Size of the rom_start region in KB. + + Default is 1KB which is enough to store the boot and irq vectors. + + This setting can be derived from a DT node reg property or specified directly. + + Example for IMX7D that needs the boot-vector into OCRAM_S (0x00180000): + $(dt_nodelabel_reg_size_hex,ocram_s_sys,0,K) + +endif + config CODE_DATA_RELOCATION_SRAM bool "Relocate code/data sections to SRAM" depends on CPU_CORTEX_M diff --git a/arch/arm/core/cortex_a_r/Kconfig b/arch/arm/core/cortex_a_r/Kconfig index 3ec57cc408e1b..4095a277c6138 100644 --- a/arch/arm/core/cortex_a_r/Kconfig +++ b/arch/arm/core/cortex_a_r/Kconfig @@ -131,6 +131,7 @@ config AARCH32_ARMV8_R bool select ATOMIC_OPERATIONS_BUILTIN select SCHED_IPI_SUPPORTED if SMP + select ARCH_HAS_DIRECTED_IPIS help This option signifies the use of an ARMv8-R AArch32 processor implementation. diff --git a/arch/arm/core/cortex_a_r/fault.c b/arch/arm/core/cortex_a_r/fault.c index a39efeb96e027..d792fc57da8de 100644 --- a/arch/arm/core/cortex_a_r/fault.c +++ b/arch/arm/core/cortex_a_r/fault.c @@ -206,7 +206,7 @@ bool z_arm_fault_undef_instruction_fp(void) * * @return Returns true if the fault is fatal */ -bool z_arm_fault_undef_instruction(z_arch_esf_t *esf) +bool z_arm_fault_undef_instruction(struct arch_esf *esf) { #if defined(CONFIG_FPU_SHARING) /* @@ -243,7 +243,7 @@ bool z_arm_fault_undef_instruction(z_arch_esf_t *esf) * * @return Returns true if the fault is fatal */ -bool z_arm_fault_prefetch(z_arch_esf_t *esf) +bool z_arm_fault_prefetch(struct arch_esf *esf) { uint32_t reason = K_ERR_CPU_EXCEPTION; @@ -299,7 +299,7 @@ static const struct z_exc_handle exceptions[] = { * * @return true if error is recoverable, otherwise return false. */ -static bool memory_fault_recoverable(z_arch_esf_t *esf) +static bool memory_fault_recoverable(struct arch_esf *esf) { for (int i = 0; i < ARRAY_SIZE(exceptions); i++) { /* Mask out instruction mode */ @@ -321,7 +321,7 @@ static bool memory_fault_recoverable(z_arch_esf_t *esf) * * @return Returns true if the fault is fatal */ -bool z_arm_fault_data(z_arch_esf_t *esf) +bool z_arm_fault_data(struct arch_esf *esf) { uint32_t reason = K_ERR_CPU_EXCEPTION; diff --git a/arch/arm/core/cortex_a_r/irq_manage.c b/arch/arm/core/cortex_a_r/irq_manage.c index a381fad2a4871..48c9ede3327bb 100644 --- a/arch/arm/core/cortex_a_r/irq_manage.c +++ b/arch/arm/core/cortex_a_r/irq_manage.c @@ -71,7 +71,7 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) } #endif /* !CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER */ -void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf); /** * @@ -98,7 +98,7 @@ void _arch_isr_direct_pm(void) if (_kernel.idle) { _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } irq_unlock(key); diff --git a/arch/arm/core/cortex_a_r/isr_wrapper.S b/arch/arm/core/cortex_a_r/isr_wrapper.S index 0cd30e0a34313..56fd111ea3fe4 100644 --- a/arch/arm/core/cortex_a_r/isr_wrapper.S +++ b/arch/arm/core/cortex_a_r/isr_wrapper.S @@ -156,7 +156,7 @@ _vfp_not_enabled: * idle, this ensures that the calculation and programming of the * device for the next timer deadline is not interrupted. For * non-tickless idle, this ensures that the clearing of the kernel idle - * state is not interrupted. In each case, z_pm_save_idle_exit + * state is not interrupted. In each case, pm_system_resume * is called with interrupts disabled. */ @@ -170,7 +170,7 @@ _vfp_not_enabled: movs r1, #0 /* clear kernel idle state */ str r1, [r2, #_kernel_offset_to_idle] - bl z_pm_save_idle_exit + bl pm_system_resume _idle_state_cleared: #endif /* CONFIG_PM */ @@ -269,7 +269,7 @@ SECTION_FUNC(TEXT, _isr_wrapper) * idle, this ensures that the calculation and programming of the * device for the next timer deadline is not interrupted. For * non-tickless idle, this ensures that the clearing of the kernel idle - * state is not interrupted. In each case, z_pm_save_idle_exit + * state is not interrupted. In each case, pm_system_resume * is called with interrupts disabled. */ @@ -283,7 +283,7 @@ SECTION_FUNC(TEXT, _isr_wrapper) movs r1, #0 /* clear kernel idle state */ str r1, [r2, #_kernel_offset_to_idle] - bl z_pm_save_idle_exit + bl pm_system_resume _idle_state_cleared: #endif /* CONFIG_PM */ diff --git a/arch/arm/core/cortex_a_r/smp.c b/arch/arm/core/cortex_a_r/smp.c index 9e06730f91396..0214b4715f6e9 100644 --- a/arch/arm/core/cortex_a_r/smp.c +++ b/arch/arm/core/cortex_a_r/smp.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "boot.h" #include "zephyr/cache.h" #include "zephyr/kernel/thread_stack.h" @@ -210,7 +211,7 @@ void arch_secondary_cpu_init(void) #ifdef CONFIG_SMP -static void broadcast_ipi(unsigned int ipi) +static void send_ipi(unsigned int ipi, uint32_t cpu_bitmap) { uint32_t mpidr = MPIDR_TO_CORE(GET_MPIDR()); @@ -220,6 +221,10 @@ static void broadcast_ipi(unsigned int ipi) unsigned int num_cpus = arch_num_cpus(); for (int i = 0; i < num_cpus; i++) { + if ((cpu_bitmap & BIT(i)) == 0) { + continue; + } + uint32_t target_mpidr = cpu_map[i]; uint8_t aff0; @@ -239,10 +244,14 @@ void sched_ipi_handler(const void *unused) z_sched_ipi(); } -/* arch implementation of sched_ipi */ -void arch_sched_ipi(void) +void arch_sched_broadcast_ipi(void) { - broadcast_ipi(SGI_SCHED_IPI); + send_ipi(SGI_SCHED_IPI, IPI_ALL_CPUS_MASK); +} + +void arch_sched_directed_ipi(uint32_t cpu_bitmap) +{ + send_ipi(SGI_SCHED_IPI, cpu_bitmap); } int arch_smp_init(void) @@ -259,6 +268,4 @@ int arch_smp_init(void) return 0; } -SYS_INIT(arch_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); - #endif diff --git a/arch/arm/core/cortex_m/coredump.c b/arch/arm/core/cortex_m/coredump.c index 2b4a86a1bb9b2..c688c91d9819d 100644 --- a/arch/arm/core/cortex_m/coredump.c +++ b/arch/arm/core/cortex_m/coredump.c @@ -41,7 +41,7 @@ struct arm_arch_block { */ static struct arm_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/arm/core/cortex_m/fault.c b/arch/arm/core/cortex_m/fault.c index 5090381fa317d..78b87092976f6 100644 --- a/arch/arm/core/cortex_m/fault.c +++ b/arch/arm/core/cortex_m/fault.c @@ -146,7 +146,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); */ #if (CONFIG_FAULT_DUMP == 1) -static void fault_show(const z_arch_esf_t *esf, int fault) +static void fault_show(const struct arch_esf *esf, int fault) { PR_EXC("Fault! EXC #%d", fault); @@ -165,7 +165,7 @@ static void fault_show(const z_arch_esf_t *esf, int fault) * * For Dump level 0, no information needs to be generated. */ -static void fault_show(const z_arch_esf_t *esf, int fault) +static void fault_show(const struct arch_esf *esf, int fault) { (void)esf; (void)fault; @@ -185,7 +185,7 @@ static const struct z_exc_handle exceptions[] = { * * @return true if error is recoverable, otherwise return false. */ -static bool memory_fault_recoverable(z_arch_esf_t *esf, bool synchronous) +static bool memory_fault_recoverable(struct arch_esf *esf, bool synchronous) { #ifdef CONFIG_USERSPACE for (int i = 0; i < ARRAY_SIZE(exceptions); i++) { @@ -228,7 +228,7 @@ uint32_t z_check_thread_stack_fail(const uint32_t fault_addr, * * @return error code to identify the fatal error reason */ -static uint32_t mem_manage_fault(z_arch_esf_t *esf, int from_hard_fault, +static uint32_t mem_manage_fault(struct arch_esf *esf, int from_hard_fault, bool *recoverable) { uint32_t reason = K_ERR_ARM_MEM_GENERIC; @@ -387,7 +387,7 @@ static uint32_t mem_manage_fault(z_arch_esf_t *esf, int from_hard_fault, * @return error code to identify the fatal error reason. * */ -static int bus_fault(z_arch_esf_t *esf, int from_hard_fault, bool *recoverable) +static int bus_fault(struct arch_esf *esf, int from_hard_fault, bool *recoverable) { uint32_t reason = K_ERR_ARM_BUS_GENERIC; @@ -549,7 +549,7 @@ static int bus_fault(z_arch_esf_t *esf, int from_hard_fault, bool *recoverable) * * @return error code to identify the fatal error reason */ -static uint32_t usage_fault(const z_arch_esf_t *esf) +static uint32_t usage_fault(const struct arch_esf *esf) { uint32_t reason = K_ERR_ARM_USAGE_GENERIC; @@ -612,7 +612,7 @@ static uint32_t usage_fault(const z_arch_esf_t *esf) * * @return error code to identify the fatal error reason */ -static uint32_t secure_fault(const z_arch_esf_t *esf) +static uint32_t secure_fault(const struct arch_esf *esf) { uint32_t reason = K_ERR_ARM_SECURE_GENERIC; @@ -661,7 +661,7 @@ static uint32_t secure_fault(const z_arch_esf_t *esf) * See z_arm_fault_dump() for example. * */ -static void debug_monitor(z_arch_esf_t *esf, bool *recoverable) +static void debug_monitor(struct arch_esf *esf, bool *recoverable) { *recoverable = false; @@ -687,7 +687,7 @@ static void debug_monitor(z_arch_esf_t *esf, bool *recoverable) #error Unknown ARM architecture #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ -static inline bool z_arm_is_synchronous_svc(z_arch_esf_t *esf) +static inline bool z_arm_is_synchronous_svc(struct arch_esf *esf) { uint16_t *ret_addr = (uint16_t *)esf->basic.pc; /* SVC is a 16-bit instruction. On a synchronous SVC @@ -762,7 +762,7 @@ static inline bool z_arm_is_pc_valid(uintptr_t pc) * * @return error code to identify the fatal error reason */ -static uint32_t hard_fault(z_arch_esf_t *esf, bool *recoverable) +static uint32_t hard_fault(struct arch_esf *esf, bool *recoverable) { uint32_t reason = K_ERR_CPU_EXCEPTION; @@ -829,7 +829,7 @@ static uint32_t hard_fault(z_arch_esf_t *esf, bool *recoverable) * See z_arm_fault_dump() for example. * */ -static void reserved_exception(const z_arch_esf_t *esf, int fault) +static void reserved_exception(const struct arch_esf *esf, int fault) { ARG_UNUSED(esf); @@ -839,7 +839,7 @@ static void reserved_exception(const z_arch_esf_t *esf, int fault) } /* Handler function for ARM fault conditions. */ -static uint32_t fault_handle(z_arch_esf_t *esf, int fault, bool *recoverable) +static uint32_t fault_handle(struct arch_esf *esf, int fault, bool *recoverable) { uint32_t reason = K_ERR_CPU_EXCEPTION; @@ -893,7 +893,7 @@ static uint32_t fault_handle(z_arch_esf_t *esf, int fault, bool *recoverable) * * @param secure_esf Pointer to the secure stack frame. */ -static void secure_stack_dump(const z_arch_esf_t *secure_esf) +static void secure_stack_dump(const struct arch_esf *secure_esf) { /* * In case a Non-Secure exception interrupted the Secure @@ -918,7 +918,7 @@ static void secure_stack_dump(const z_arch_esf_t *secure_esf) * Non-Secure exception entry. */ top_of_sec_stack += ADDITIONAL_STATE_CONTEXT_WORDS; - secure_esf = (const z_arch_esf_t *)top_of_sec_stack; + secure_esf = (const struct arch_esf *)top_of_sec_stack; sec_ret_addr = secure_esf->basic.pc; } else { /* Exception during Non-Secure function call. @@ -947,11 +947,11 @@ static void secure_stack_dump(const z_arch_esf_t *secure_esf) * * @return ESF pointer on success, otherwise return NULL */ -static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_return, +static inline struct arch_esf *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_return, bool *nested_exc) { bool alternative_state_exc = false; - z_arch_esf_t *ptr_esf = NULL; + struct arch_esf *ptr_esf = NULL; *nested_exc = false; @@ -979,14 +979,14 @@ static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_ret alternative_state_exc = true; /* Dump the Secure stack before handling the actual fault. */ - z_arch_esf_t *secure_esf; + struct arch_esf *secure_esf; if (exc_return & EXC_RETURN_SPSEL_PROCESS) { /* Secure stack pointed by PSP */ - secure_esf = (z_arch_esf_t *)psp; + secure_esf = (struct arch_esf *)psp; } else { /* Secure stack pointed by MSP */ - secure_esf = (z_arch_esf_t *)msp; + secure_esf = (struct arch_esf *)msp; *nested_exc = true; } @@ -997,9 +997,9 @@ static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_ret * and supply it to the fault handing function. */ if (exc_return & EXC_RETURN_MODE_THREAD) { - ptr_esf = (z_arch_esf_t *)__TZ_get_PSP_NS(); + ptr_esf = (struct arch_esf *)__TZ_get_PSP_NS(); } else { - ptr_esf = (z_arch_esf_t *)__TZ_get_MSP_NS(); + ptr_esf = (struct arch_esf *)__TZ_get_MSP_NS(); } } #elif defined(CONFIG_ARM_NONSECURE_FIRMWARE) @@ -1024,10 +1024,10 @@ static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_ret if (exc_return & EXC_RETURN_SPSEL_PROCESS) { /* Non-Secure stack frame on PSP */ - ptr_esf = (z_arch_esf_t *)psp; + ptr_esf = (struct arch_esf *)psp; } else { /* Non-Secure stack frame on MSP */ - ptr_esf = (z_arch_esf_t *)msp; + ptr_esf = (struct arch_esf *)msp; } } else { /* Exception entry occurred in Non-Secure stack. */ @@ -1046,11 +1046,11 @@ static inline z_arch_esf_t *get_esf(uint32_t msp, uint32_t psp, uint32_t exc_ret if (!alternative_state_exc) { if (exc_return & EXC_RETURN_MODE_THREAD) { /* Returning to thread mode */ - ptr_esf = (z_arch_esf_t *)psp; + ptr_esf = (struct arch_esf *)psp; } else { /* Returning to handler mode */ - ptr_esf = (z_arch_esf_t *)msp; + ptr_esf = (struct arch_esf *)msp; *nested_exc = true; } } @@ -1095,12 +1095,12 @@ void z_arm_fault(uint32_t msp, uint32_t psp, uint32_t exc_return, uint32_t reason = K_ERR_CPU_EXCEPTION; int fault = SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk; bool recoverable, nested_exc; - z_arch_esf_t *esf; + struct arch_esf *esf; /* Create a stack-ed copy of the ESF to be used during * the fault handling process. */ - z_arch_esf_t esf_copy; + struct arch_esf esf_copy; /* Force unlock interrupts */ arch_irq_unlock(0); @@ -1123,13 +1123,13 @@ void z_arm_fault(uint32_t msp, uint32_t psp, uint32_t exc_return, /* Copy ESF */ #if !defined(CONFIG_EXTRA_EXCEPTION_INFO) - memcpy(&esf_copy, esf, sizeof(z_arch_esf_t)); + memcpy(&esf_copy, esf, sizeof(struct arch_esf)); ARG_UNUSED(callee_regs); #else /* the extra exception info is not present in the original esf * so we only copy the fields before those. */ - memcpy(&esf_copy, esf, offsetof(z_arch_esf_t, extra_info)); + memcpy(&esf_copy, esf, offsetof(struct arch_esf, extra_info)); esf_copy.extra_info = (struct __extra_esf_info) { .callee = callee_regs, .exc_return = exc_return, diff --git a/arch/arm/core/cortex_m/irq_manage.c b/arch/arm/core/cortex_m/irq_manage.c index 3940d5246d4b5..cc62386e8acad 100644 --- a/arch/arm/core/cortex_m/irq_manage.c +++ b/arch/arm/core/cortex_m/irq_manage.c @@ -94,7 +94,7 @@ void z_arm_irq_priority_set(unsigned int irq, unsigned int prio, uint32_t flags) #endif /* !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) */ -void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf); /** * @@ -122,7 +122,7 @@ void _arch_isr_direct_pm(void) #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) /* Lock all interrupts. irq_lock() will on this CPU only disable those * lower than BASEPRI, which is not what we want. See comments in - * arch/arm/core/isr_wrapper.S + * arch/arm/core/cortex_m/isr_wrapper.c */ __asm__ volatile("cpsid i" : : : "memory"); #else @@ -131,7 +131,7 @@ void _arch_isr_direct_pm(void) if (_kernel.idle) { _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) diff --git a/arch/arm/core/cortex_m/isr_wrapper.c b/arch/arm/core/cortex_m/isr_wrapper.c index 6e6016508c6a4..46aac160c3bf9 100644 --- a/arch/arm/core/cortex_m/isr_wrapper.c +++ b/arch/arm/core/cortex_m/isr_wrapper.c @@ -42,7 +42,7 @@ void _isr_wrapper(void) * idle, this ensures that the calculation and programming of the * device for the next timer deadline is not interrupted. For * non-tickless idle, this ensures that the clearing of the kernel idle - * state is not interrupted. In each case, z_pm_save_idle_exit + * state is not interrupted. In each case, pm_system_resume * is called with interrupts disabled. */ @@ -59,7 +59,7 @@ void _isr_wrapper(void) if (_kernel.idle != 0) { /* clear kernel idle state */ _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } /* re-enable interrupts */ __enable_irq(); diff --git a/arch/arm/core/cortex_m/pm_s2ram.S b/arch/arm/core/cortex_m/pm_s2ram.S index aa715c8bbb90d..1e5bca04fe294 100644 --- a/arch/arm/core/cortex_m/pm_s2ram.S +++ b/arch/arm/core/cortex_m/pm_s2ram.S @@ -14,12 +14,11 @@ #include #include -#define MAGIC (0xDABBAD00) - _ASM_FILE_PROLOGUE +GTEXT(pm_s2ram_mark_set) +GTEXT(pm_s2ram_mark_check_and_clear) GDATA(_cpu_context) -GDATA(marker) SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) /* @@ -64,11 +63,9 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) str r2, [r1, #___cpu_context_t_control_OFFSET] /* - * Set the marker to MAGIC value + * Mark entering suspend to RAM. */ - ldr r1, =marker - ldr r2, =MAGIC - str r2, [r1] + bl pm_s2ram_mark_set /* * Call the system_off function passed as parameter. This should never @@ -82,35 +79,29 @@ SECTION_FUNC(TEXT, arch_pm_s2ram_suspend) */ /* - * Reset the marker + * Reset the marking of suspend to RAM, return is ignored. */ - ldr r1, =marker - mov r2, #0x0 - str r2, [r1] + push {r0} + bl pm_s2ram_mark_check_and_clear + pop {r0} pop {r4-r12, lr} bx lr + GTEXT(arch_pm_s2ram_resume) SECTION_FUNC(TEXT, arch_pm_s2ram_resume) /* - * Check if the marker is set + * Check if reset occurred after suspending to RAM. */ - ldr r0, =marker - ldr r0, [r0] - ldr r1, =MAGIC - cmp r0, r1 + push {lr} + bl pm_s2ram_mark_check_and_clear + cmp r0, #0x1 + pop {lr} beq resume bx lr resume: - /* - * Reset the marker - */ - ldr r0, =marker - mov r1, #0x0 - str r1, [r0] - /* * Restore the CPU context */ diff --git a/arch/arm/core/cortex_m/pm_s2ram.c b/arch/arm/core/cortex_m/pm_s2ram.c index 7b499278dd277..2657d48dc32a1 100644 --- a/arch/arm/core/cortex_m/pm_s2ram.c +++ b/arch/arm/core/cortex_m/pm_s2ram.c @@ -9,12 +9,33 @@ #include +#define MAGIC (0xDABBAD00) + /** * CPU context for S2RAM */ __noinit _cpu_context_t _cpu_context; +#ifndef CONFIG_PM_S2RAM_CUSTOM_MARKING /** * S2RAM Marker */ -__noinit uint32_t marker; +static __noinit uint32_t marker; + +void pm_s2ram_mark_set(void) +{ + marker = MAGIC; +} + +bool pm_s2ram_mark_check_and_clear(void) +{ + if (marker == MAGIC) { + marker = 0; + + return true; + } + + return false; +} + +#endif /* CONFIG_PM_S2RAM_CUSTOM_MARKING */ diff --git a/arch/arm/core/cortex_m/swap.c b/arch/arm/core/cortex_m/swap.c index b60f6acd675d3..027fb47a01f06 100644 --- a/arch/arm/core/cortex_m/swap.c +++ b/arch/arm/core/cortex_m/swap.c @@ -96,11 +96,15 @@ uintptr_t z_arm_pendsv_c(uintptr_t exc_ret) /* restore mode */ IF_ENABLED(CONFIG_USERSPACE, ({ - CONTROL_Type ctrl = {.w = __get_CONTROL()}; - /* exit privileged state when returing to thread mode. */ - ctrl.b.nPRIV = 0; - __set_CONTROL(ctrl.w | current->arch.mode); - })); + CONTROL_Type ctrl = {.w = __get_CONTROL()}; + /* exit privileged state when returning to thread mode. */ + ctrl.b.nPRIV = 0; + /* __set_CONTROL inserts an ISB which is may not be necessary here + * (stack pointer may not be touched), but it's recommended to avoid + * executing pre-fetched instructions with the previous privilege. + */ + __set_CONTROL(ctrl.w | current->arch.mode); + })); return exc_ret; } diff --git a/arch/arm/core/fatal.c b/arch/arm/core/fatal.c index 4364d48d45d57..4532e238f05c9 100644 --- a/arch/arm/core/fatal.c +++ b/arch/arm/core/fatal.c @@ -18,7 +18,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); #ifdef CONFIG_EXCEPTION_DEBUG -static void esf_dump(const z_arch_esf_t *esf) +static void esf_dump(const struct arch_esf *esf) { LOG_ERR("r0/a1: 0x%08x r1/a2: 0x%08x r2/a3: 0x%08x", esf->basic.a1, esf->basic.a2, esf->basic.a3); @@ -66,7 +66,7 @@ static void esf_dump(const z_arch_esf_t *esf) } #endif /* CONFIG_EXCEPTION_DEBUG */ -void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf) +void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG if (esf != NULL) { @@ -102,7 +102,7 @@ void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf) * @param esf exception frame * @param callee_regs Callee-saved registers (R4-R11) */ -void z_do_kernel_oops(const z_arch_esf_t *esf, _callee_saved_t *callee_regs) +void z_do_kernel_oops(const struct arch_esf *esf, _callee_saved_t *callee_regs) { #if !(defined(CONFIG_EXTRA_EXCEPTION_INFO) && defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE)) ARG_UNUSED(callee_regs); @@ -130,9 +130,9 @@ void z_do_kernel_oops(const z_arch_esf_t *esf, _callee_saved_t *callee_regs) #if !defined(CONFIG_EXTRA_EXCEPTION_INFO) z_arm_fatal_error(reason, esf); #else - z_arch_esf_t esf_copy; + struct arch_esf esf_copy; - memcpy(&esf_copy, esf, offsetof(z_arch_esf_t, extra_info)); + memcpy(&esf_copy, esf, offsetof(struct arch_esf, extra_info)); #if defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) /* extra exception info is collected in callee_reg param * on CONFIG_ARMV7_M_ARMV8_M_MAINLINE @@ -156,7 +156,7 @@ void z_do_kernel_oops(const z_arch_esf_t *esf, _callee_saved_t *callee_regs) FUNC_NORETURN void arch_syscall_oops(void *ssf_ptr) { uint32_t *ssf_contents = ssf_ptr; - z_arch_esf_t oops_esf = { 0 }; + struct arch_esf oops_esf = { 0 }; /* TODO: Copy the rest of the register set out of ssf_ptr */ oops_esf.basic.pc = ssf_contents[3]; diff --git a/arch/arm/core/gdbstub.c b/arch/arm/core/gdbstub.c index 5386cfa619f1a..60d16b78c319c 100644 --- a/arch/arm/core/gdbstub.c +++ b/arch/arm/core/gdbstub.c @@ -42,7 +42,7 @@ static int is_bkpt(unsigned int exc_cause) } /* Wrapper function to save and restore execution c */ -void z_gdb_entry(z_arch_esf_t *esf, unsigned int exc_cause) +void z_gdb_entry(struct arch_esf *esf, unsigned int exc_cause) { /* Disable the hardware breakpoint in case it was set */ __asm__ volatile("mcr p14, 0, %0, c0, c0, 5" ::"r"(0x0) :); diff --git a/arch/arm/core/mpu/Kconfig b/arch/arm/core/mpu/Kconfig index dc540038e2b2c..c6d1bdc7da05a 100644 --- a/arch/arm/core/mpu/Kconfig +++ b/arch/arm/core/mpu/Kconfig @@ -14,6 +14,8 @@ config ARM_MPU select MPU_REQUIRES_POWER_OF_TWO_ALIGNMENT if !(CPU_HAS_NXP_MPU || ARMV8_M_BASELINE || ARMV8_M_MAINLINE || AARCH32_ARMV8_R) select MPU_REQUIRES_NON_OVERLAPPING_REGIONS if CPU_HAS_ARM_MPU && (ARMV8_M_BASELINE || ARMV8_M_MAINLINE || AARCH32_ARMV8_R) select MPU_GAP_FILLING if AARCH32_ARMV8_R + select ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + select MEM_DOMAIN_ISOLATED_STACKS help MCU implements Memory Protection Unit. diff --git a/arch/arm/core/mpu/arm_core_mpu.c b/arch/arm/core/mpu/arm_core_mpu.c index 2fb0f141125b0..dde98c0b07fa8 100644 --- a/arch/arm/core/mpu/arm_core_mpu.c +++ b/arch/arm/core/mpu/arm_core_mpu.c @@ -338,7 +338,7 @@ int arch_mem_domain_max_partitions_get(void) return ARM_CORE_MPU_MAX_DOMAIN_PARTITIONS_GET(available_regions); } -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { return arm_core_mpu_buffer_validate(addr, size, write); } diff --git a/arch/arm/core/mpu/arm_core_mpu_dev.h b/arch/arm/core/mpu/arm_core_mpu_dev.h index fd56131d7dc1b..254d6d9dda341 100644 --- a/arch/arm/core/mpu/arm_core_mpu_dev.h +++ b/arch/arm/core/mpu/arm_core_mpu_dev.h @@ -261,7 +261,7 @@ int arm_core_mpu_get_max_available_dyn_regions(void); * spans multiple enabled MPU regions (even if these regions all * permit user access). */ -int arm_core_mpu_buffer_validate(void *addr, size_t size, int write); +int arm_core_mpu_buffer_validate(const void *addr, size_t size, int write); #endif /* CONFIG_ARM_MPU */ diff --git a/arch/arm/core/mpu/arm_mpu.c b/arch/arm/core/mpu/arm_mpu.c index cd4c8ccd7a07f..fe5d86c822da5 100644 --- a/arch/arm/core/mpu/arm_mpu.c +++ b/arch/arm/core/mpu/arm_mpu.c @@ -130,12 +130,10 @@ static int mpu_configure_regions_from_dt(uint8_t *reg_index) break; #endif default: - /* Either the specified `ATTR_MPU_*` attribute does not - * exists or the `REGION_*_ATTR` macro is not defined - * for that attribute. + /* Attribute other than ARM-specific is set. + * This region should not be configured in MPU. */ - LOG_ERR("Invalid attribute for the region\n"); - return -EINVAL; + continue; } #if defined(CONFIG_ARMV7_R) region_conf.size = size_to_mpu_rasr_size(region[idx].dt_size); @@ -341,7 +339,7 @@ int arm_core_mpu_get_max_available_dyn_regions(void) * * Presumes the background mapping is NOT user accessible. */ -int arm_core_mpu_buffer_validate(void *addr, size_t size, int write) +int arm_core_mpu_buffer_validate(const void *addr, size_t size, int write) { return mpu_buffer_validate(addr, size, write); } diff --git a/arch/arm/core/mpu/arm_mpu_v7_internal.h b/arch/arm/core/mpu/arm_mpu_v7_internal.h index 1fe3417901ee9..9641ab250003c 100644 --- a/arch/arm/core/mpu/arm_mpu_v7_internal.h +++ b/arch/arm/core/mpu/arm_mpu_v7_internal.h @@ -169,7 +169,7 @@ static inline int is_user_accessible_region(uint32_t r_index, int write) * This internal function validates whether a given memory buffer * is user accessible or not. */ -static inline int mpu_buffer_validate(void *addr, size_t size, int write) +static inline int mpu_buffer_validate(const void *addr, size_t size, int write) { int32_t r_index; int rc = -EPERM; diff --git a/arch/arm/core/mpu/arm_mpu_v8_internal.h b/arch/arm/core/mpu/arm_mpu_v8_internal.h index 751786d5a4c99..66a00a452a7ad 100644 --- a/arch/arm/core/mpu/arm_mpu_v8_internal.h +++ b/arch/arm/core/mpu/arm_mpu_v8_internal.h @@ -408,7 +408,7 @@ static inline int is_user_accessible_region(uint32_t rnr, int write) * This internal function validates whether a given memory buffer * is user accessible or not. */ -static inline int mpu_buffer_validate(void *addr, size_t size, int write) +static inline int mpu_buffer_validate(const void *addr, size_t size, int write) { int32_t rnr; int rc = -EPERM; @@ -455,7 +455,7 @@ static inline int mpu_buffer_validate(void *addr, size_t size, int write) * in case the fast address range check fails. * */ -static inline int mpu_buffer_validate(void *addr, size_t size, int write) +static inline int mpu_buffer_validate(const void *addr, size_t size, int write) { uint32_t _addr = (uint32_t)addr; uint32_t _size = (uint32_t)size; diff --git a/arch/arm/core/mpu/nxp_mpu.c b/arch/arm/core/mpu/nxp_mpu.c index 39d7cde6f8f52..b0fe24c6bf617 100644 --- a/arch/arm/core/mpu/nxp_mpu.c +++ b/arch/arm/core/mpu/nxp_mpu.c @@ -602,7 +602,7 @@ static inline int is_user_accessible_region(uint32_t r_index, int write) /** * @brief validate the given buffer is user accessible or not */ -int arm_core_mpu_buffer_validate(void *addr, size_t size, int write) +int arm_core_mpu_buffer_validate(const void *addr, size_t size, int write) { uint8_t r_index; diff --git a/arch/arm/include/cortex_a_r/exception.h b/arch/arm/include/cortex_a_r/exception.h index 7519016176c5e..6daa9c106ee2b 100644 --- a/arch/arm/include/cortex_a_r/exception.h +++ b/arch/arm/include/cortex_a_r/exception.h @@ -38,7 +38,7 @@ static ALWAYS_INLINE bool arch_is_in_isr(void) return (arch_curr_cpu()->nested != 0U); } -static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) +static ALWAYS_INLINE bool arch_is_in_nested_exception(const struct arch_esf *esf) { return (arch_curr_cpu()->arch.exc_depth > 1U) ? (true) : (false); } @@ -48,7 +48,7 @@ static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) * This function is used by privileged code to determine if the thread * associated with the stack frame is in user mode. */ -static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const z_arch_esf_t *esf) +static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const struct arch_esf *esf) { return ((esf->basic.xpsr & CPSR_M_Msk) == CPSR_M_USR); } diff --git a/arch/arm/include/cortex_a_r/kernel_arch_func.h b/arch/arm/include/cortex_a_r/kernel_arch_func.h index 88f631ff4b487..3486d7d4d4e02 100644 --- a/arch/arm/include/cortex_a_r/kernel_arch_func.h +++ b/arch/arm/include/cortex_a_r/kernel_arch_func.h @@ -59,7 +59,7 @@ extern FUNC_NORETURN void z_arm_userspace_enter(k_thread_entry_t user_entry, uint32_t stack_end, uint32_t stack_start); -extern void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +extern void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf); #endif /* _ASMLANGUAGE */ diff --git a/arch/arm/include/cortex_m/exception.h b/arch/arm/include/cortex_m/exception.h index bf86abd77c70f..89bdd4b83e9a2 100644 --- a/arch/arm/include/cortex_m/exception.h +++ b/arch/arm/include/cortex_m/exception.h @@ -68,7 +68,7 @@ static ALWAYS_INLINE bool arch_is_in_isr(void) * @return true if execution state was in handler mode, before * the current exception occurred, otherwise false. */ -static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) +static ALWAYS_INLINE bool arch_is_in_nested_exception(const struct arch_esf *esf) { return (esf->basic.xpsr & IPSR_ISR_Msk) ? (true) : (false); } @@ -80,7 +80,7 @@ static ALWAYS_INLINE bool arch_is_in_nested_exception(const z_arch_esf_t *esf) * @param esf the exception stack frame (unused) * @return true if the current thread was in unprivileged mode */ -static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const z_arch_esf_t *esf) +static ALWAYS_INLINE bool z_arm_preempted_thread_in_user_mode(const struct arch_esf *esf) { return z_arm_thread_is_in_user_mode(); } diff --git a/arch/arm/include/cortex_m/kernel_arch_func.h b/arch/arm/include/cortex_m/kernel_arch_func.h index 77619c9d6c4f8..132c056c91022 100644 --- a/arch/arm/include/cortex_m/kernel_arch_func.h +++ b/arch/arm/include/cortex_m/kernel_arch_func.h @@ -76,7 +76,7 @@ extern FUNC_NORETURN void z_arm_userspace_enter(k_thread_entry_t user_entry, uint32_t stack_end, uint32_t stack_start); -extern void z_arm_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +extern void z_arm_fatal_error(unsigned int reason, const struct arch_esf *esf); #endif /* _ASMLANGUAGE */ diff --git a/arch/arm/include/kernel_arch_data.h b/arch/arm/include/kernel_arch_data.h index 5ad19db8f84b8..9b4ca04f66c56 100644 --- a/arch/arm/include/kernel_arch_data.h +++ b/arch/arm/include/kernel_arch_data.h @@ -42,7 +42,7 @@ extern "C" { #endif -typedef struct __esf _esf_t; +typedef struct arch_esf _esf_t; typedef struct __basic_sf _basic_sf_t; #if defined(CONFIG_FPU) && defined(CONFIG_FPU_SHARING) typedef struct __fpu_sf _fpu_sf_t; diff --git a/arch/arm/include/offsets_short_arch.h b/arch/arm/include/offsets_short_arch.h index 4ceb1fc3f7aec..ea6af4db92df3 100644 --- a/arch/arm/include/offsets_short_arch.h +++ b/arch/arm/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_ARM_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_ARM_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/arm64/core/CMakeLists.txt b/arch/arm64/core/CMakeLists.txt index 05e4be8c0ea6d..03a34e439bb21 100644 --- a/arch/arm64/core/CMakeLists.txt +++ b/arch/arm64/core/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_library() zephyr_library_sources( cpu_idle.S + early_mem_funcs.S fatal.c irq_init.c irq_manage.c @@ -43,7 +44,7 @@ if ((CONFIG_MP_MAX_NUM_CPUS GREATER 1) OR (CONFIG_SMP)) endif () zephyr_cc_option_ifdef(CONFIG_USERSPACE -mno-outline-atomics) -zephyr_cc_option_ifdef(CONFIG_ARM64_ENABLE_FRAME_POINTER -mno-omit-leaf-frame-pointer) +zephyr_cc_option_ifdef(CONFIG_FRAME_POINTER -mno-omit-leaf-frame-pointer) # GCC may generate ldp/stp instructions with the Advanced SIMD Qn registers for # consecutive 32-byte loads and stores. Saving and restoring the Advanced SIMD diff --git a/arch/arm64/core/Kconfig b/arch/arm64/core/Kconfig index 8f09d49a04c0f..367480015c4b1 100644 --- a/arch/arm64/core/Kconfig +++ b/arch/arm64/core/Kconfig @@ -145,13 +145,22 @@ config ARM64_SAFE_EXCEPTION_STACK config ARM64_ENABLE_FRAME_POINTER bool - default y depends on OVERRIDE_FRAME_POINTER_DEFAULT && !OMIT_FRAME_POINTER + depends on !FRAME_POINTER + select DEPRECATED help + Deprecated. Use CONFIG_FRAME_POINTER instead. Hidden option to simplify access to OVERRIDE_FRAME_POINTER_DEFAULT and OMIT_FRAME_POINTER. It is automatically enabled when the frame pointer unwinding is enabled. +config ARM64_EXCEPTION_STACK_TRACE + bool + default y + depends on FRAME_POINTER + help + Internal config to enable runtime stack traces on fatal exceptions. + config ARM64_SAFE_EXCEPTION_STACK_SIZE int "The stack size of the safe exception stack" default 4096 diff --git a/arch/arm64/core/coredump.c b/arch/arm64/core/coredump.c index 399cf85e3d0f4..0176b61612ec1 100644 --- a/arch/arm64/core/coredump.c +++ b/arch/arm64/core/coredump.c @@ -13,7 +13,7 @@ #define ARCH_HDR_VER 1 /* Structure to store the architecture registers passed arch_coredump_info_dump - * As callee saved registers are not provided in z_arch_esf_t structure in Zephyr + * As callee saved registers are not provided in struct arch_esf structure in Zephyr * we just need 22 registers. */ struct arm64_arch_block { @@ -50,7 +50,7 @@ struct arm64_arch_block { */ static struct arm64_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { /* Target architecture information header */ /* Information just relevant to the python parser */ @@ -69,7 +69,7 @@ void arch_coredump_info_dump(const z_arch_esf_t *esf) /* * Copies the thread registers to a memory block that will be printed out - * The thread registers are already provided by structure z_arch_esf_t + * The thread registers are already provided by structure struct arch_esf */ arch_blk.r.x0 = esf->x0; arch_blk.r.x1 = esf->x1; diff --git a/arch/arm64/core/early_mem_funcs.S b/arch/arm64/core/early_mem_funcs.S new file mode 100644 index 0000000000000..383cdec790195 --- /dev/null +++ b/arch/arm64/core/early_mem_funcs.S @@ -0,0 +1,83 @@ +/* + * Copyright (c) BayLibre SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +_ASM_FILE_PROLOGUE + +/* + * These simple memset and memcpy alternatives are necessary as the optimized + * ones depend on the MMU to be active (see commit c5b898743a20). + * + * Furthermore, we can't implement those in C as the compiler is just too + * smart for its own good and replaces our simple loops into direct calls + * to memset or memcpy on its own. + */ + +/* void z_early_memset(void *dst, int c, size_t n) */ +GTEXT(z_early_memset) +SECTION_FUNC(TEXT, z_early_memset) + + /* is dst pointer 8-bytes aligned? */ + tst x0, #0x7 + b.ne 2f + + /* at least 8 bytes to set? */ + cmp x2, #8 + b.lo 2f + + /* spread the byte value across whole 64 bits */ + and x8, x1, #0xff + mov x9, #0x0101010101010101 + mul x8, x8, x9 + +1: /* 8 bytes at a time */ + sub x2, x2, #8 + cmp x2, #7 + str x8, [x0], #8 + b.hi 1b + +2: /* at least one byte to set? */ + cbz x2, 4f + +3: /* one byte at a time */ + subs x2, x2, #1 + strb w8, [x0], #1 + b.ne 3b + +4: ret + +/* void z_early_memcpy(void *dst, const void *src, size_t n) */ +GTEXT(z_early_memcpy) +SECTION_FUNC(TEXT, z_early_memcpy) + + /* are dst and src pointers 8-bytes aligned? */ + orr x8, x1, x0 + tst x8, #0x7 + b.ne 2f + + /* at least 8 bytes to copy? */ + cmp x2, #8 + b.lo 2f + +1: /* 8 bytes at a time */ + ldr x8, [x1], #8 + sub x2, x2, #8 + cmp x2, #7 + str x8, [x0], #8 + b.hi 1b + +2: /* at least one byte to copy? */ + cbz x2, 4f + +3: /* one byte at a time */ + ldrb w8, [x1], #1 + subs x2, x2, #1 + strb w8, [x0], #1 + b.ne 3b + +4: ret diff --git a/arch/arm64/core/fatal.c b/arch/arm64/core/fatal.c index 84ff767508ed1..a02ae13acf89c 100644 --- a/arch/arm64/core/fatal.c +++ b/arch/arm64/core/fatal.c @@ -13,6 +13,7 @@ * exceptions */ +#include #include #include #include @@ -180,7 +181,7 @@ static void dump_esr(uint64_t esr, bool *dump_far) LOG_ERR(" ISS: 0x%llx", GET_ESR_ISS(esr)); } -static void esf_dump(const z_arch_esf_t *esf) +static void esf_dump(const struct arch_esf *esf) { LOG_ERR("x0: 0x%016llx x1: 0x%016llx", esf->x0, esf->x1); LOG_ERR("x2: 0x%016llx x3: 0x%016llx", esf->x2, esf->x3); @@ -194,8 +195,8 @@ static void esf_dump(const z_arch_esf_t *esf) LOG_ERR("x18: 0x%016llx lr: 0x%016llx", esf->x18, esf->lr); } -#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER -static void esf_unwind(const z_arch_esf_t *esf) +#ifdef CONFIG_EXCEPTION_STACK_TRACE +static void esf_unwind(const struct arch_esf *esf) { /* * For GCC: @@ -222,10 +223,18 @@ static void esf_unwind(const z_arch_esf_t *esf) uint64_t lr; LOG_ERR(""); - while (fp != NULL) { + for (int i = 0; (fp != NULL) && (i < CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES); i++) { lr = fp[1]; +#ifdef CONFIG_SYMTAB + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(lr, &offset); + + LOG_ERR("backtrace %2d: fp: 0x%016llx lr: 0x%016llx [%s+0x%x]", + count++, (uint64_t) fp, lr, name, offset); +#else LOG_ERR("backtrace %2d: fp: 0x%016llx lr: 0x%016llx", count++, (uint64_t) fp, lr); +#endif fp = (uint64_t *) fp[0]; } LOG_ERR(""); @@ -235,7 +244,7 @@ static void esf_unwind(const z_arch_esf_t *esf) #endif /* CONFIG_EXCEPTION_DEBUG */ #ifdef CONFIG_ARM64_STACK_PROTECTION -static bool z_arm64_stack_corruption_check(z_arch_esf_t *esf, uint64_t esr, uint64_t far) +static bool z_arm64_stack_corruption_check(struct arch_esf *esf, uint64_t esr, uint64_t far) { uint64_t sp, sp_limit, guard_start; /* 0x25 means data abort from current EL */ @@ -275,7 +284,7 @@ static bool z_arm64_stack_corruption_check(z_arch_esf_t *esf, uint64_t esr, uint } #endif -static bool is_recoverable(z_arch_esf_t *esf, uint64_t esr, uint64_t far, +static bool is_recoverable(struct arch_esf *esf, uint64_t esr, uint64_t far, uint64_t elr) { if (!esf) @@ -297,7 +306,7 @@ static bool is_recoverable(z_arch_esf_t *esf, uint64_t esr, uint64_t far, return false; } -void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf) +void z_arm64_fatal_error(unsigned int reason, struct arch_esf *esf) { uint64_t esr = 0; uint64_t elr = 0; @@ -354,9 +363,9 @@ void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf) esf_dump(esf); } -#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER +#ifdef CONFIG_EXCEPTION_STACK_TRACE esf_unwind(esf); -#endif /* CONFIG_ARM64_ENABLE_FRAME_POINTER */ +#endif /* CONFIG_EXCEPTION_STACK_TRACE */ #endif /* CONFIG_EXCEPTION_DEBUG */ z_fatal_error(reason, esf); @@ -370,7 +379,7 @@ void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf) * * @param esf exception frame */ -void z_arm64_do_kernel_oops(z_arch_esf_t *esf) +void z_arm64_do_kernel_oops(struct arch_esf *esf) { /* x8 holds the exception reason */ unsigned int reason = esf->x8; diff --git a/arch/arm64/core/fpu.c b/arch/arm64/core/fpu.c index 0133eed2dcaaf..a585165b94339 100644 --- a/arch/arm64/core/fpu.c +++ b/arch/arm64/core/fpu.c @@ -159,7 +159,7 @@ void z_arm64_fpu_enter_exc(void) * simulate them and leave the FPU access disabled. This also avoids the * need for disabling interrupts in syscalls and IRQ handlers as well. */ -static bool simulate_str_q_insn(z_arch_esf_t *esf) +static bool simulate_str_q_insn(struct arch_esf *esf) { /* * Support only the "FP in exception" cases for now. @@ -221,7 +221,7 @@ static bool simulate_str_q_insn(z_arch_esf_t *esf) * don't get interrupted that is. To ensure that we mask interrupts to * the triggering exception context. */ -void z_arm64_fpu_trap(z_arch_esf_t *esf) +void z_arm64_fpu_trap(struct arch_esf *esf) { __ASSERT(read_daif() & DAIF_IRQ_BIT, "must be called with IRQs disabled"); diff --git a/arch/arm64/core/irq_manage.c b/arch/arm64/core/irq_manage.c index 4e96ce77bfa20..6344d1e3696c0 100644 --- a/arch/arm64/core/irq_manage.c +++ b/arch/arm64/core/irq_manage.c @@ -18,7 +18,7 @@ #include #include -void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf); +void z_arm64_fatal_error(unsigned int reason, struct arch_esf *esf); #if !defined(CONFIG_ARM_CUSTOM_INTERRUPT_CONTROLLER) /* diff --git a/arch/arm64/core/mmu.c b/arch/arm64/core/mmu.c index 2260d22c101f7..5527fa347ad5d 100644 --- a/arch/arm64/core/mmu.c +++ b/arch/arm64/core/mmu.c @@ -28,9 +28,13 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); static uint64_t xlat_tables[CONFIG_MAX_XLAT_TABLES * Ln_XLAT_NUM_ENTRIES] __aligned(Ln_XLAT_NUM_ENTRIES * sizeof(uint64_t)); -static uint16_t xlat_use_count[CONFIG_MAX_XLAT_TABLES]; +static int xlat_use_count[CONFIG_MAX_XLAT_TABLES]; static struct k_spinlock xlat_lock; +/* Usage count value range */ +#define XLAT_PTE_COUNT_MASK GENMASK(15, 0) +#define XLAT_REF_COUNT_UNIT BIT(16) + /* Returns a reference to a free table */ static uint64_t *new_table(void) { @@ -39,9 +43,9 @@ static uint64_t *new_table(void) /* Look for a free table. */ for (i = 0U; i < CONFIG_MAX_XLAT_TABLES; i++) { - if (xlat_use_count[i] == 0U) { + if (xlat_use_count[i] == 0) { table = &xlat_tables[i * Ln_XLAT_NUM_ENTRIES]; - xlat_use_count[i] = 1U; + xlat_use_count[i] = XLAT_REF_COUNT_UNIT; MMU_DEBUG("allocating table [%d]%p\n", i, table); return table; } @@ -59,31 +63,74 @@ static inline unsigned int table_index(uint64_t *pte) return i; } -/* Makes a table free for reuse. */ -static void free_table(uint64_t *table) +/* Adjusts usage count and returns current count. */ +static int table_usage(uint64_t *table, int adjustment) { unsigned int i = table_index(table); + int prev_count = xlat_use_count[i]; + int new_count = prev_count + adjustment; + + if (IS_ENABLED(DUMP_PTE) || new_count == 0) { + MMU_DEBUG("table [%d]%p: usage %#x -> %#x\n", i, table, prev_count, new_count); + } - MMU_DEBUG("freeing table [%d]%p\n", i, table); - __ASSERT(xlat_use_count[i] == 1U, "table still in use"); - xlat_use_count[i] = 0U; + __ASSERT(new_count >= 0, + "table use count underflow"); + __ASSERT(new_count == 0 || new_count >= XLAT_REF_COUNT_UNIT, + "table in use with no reference to it"); + __ASSERT((new_count & XLAT_PTE_COUNT_MASK) <= Ln_XLAT_NUM_ENTRIES, + "table PTE count overflow"); + + xlat_use_count[i] = new_count; + return new_count; } -/* Adjusts usage count and returns current count. */ -static int table_usage(uint64_t *table, int adjustment) +static inline void inc_table_ref(uint64_t *table) { - unsigned int i = table_index(table); + table_usage(table, XLAT_REF_COUNT_UNIT); +} + +static inline void dec_table_ref(uint64_t *table) +{ + int ref_unit = XLAT_REF_COUNT_UNIT; - xlat_use_count[i] += adjustment; - __ASSERT(xlat_use_count[i] > 0, "usage count underflow"); - return xlat_use_count[i]; + table_usage(table, -ref_unit); } static inline bool is_table_unused(uint64_t *table) { - return table_usage(table, 0) == 1; + return (table_usage(table, 0) & XLAT_PTE_COUNT_MASK) == 0; } +#ifdef CONFIG_TEST +/* Hooks to let test code peek at table states */ + +int arm64_mmu_nb_free_tables(void) +{ + int count = 0; + + for (int i = 0; i < CONFIG_MAX_XLAT_TABLES; i++) { + if (xlat_use_count[i] == 0) { + count++; + } + } + + return count; +} + +int arm64_mmu_tables_total_usage(void) +{ + int count = 0; + + for (int i = 0; i < CONFIG_MAX_XLAT_TABLES; i++) { + count += xlat_use_count[i]; + } + + return count; +} + +#endif /* CONFIG_TEST */ + static inline bool is_free_desc(uint64_t desc) { return (desc & PTE_DESC_TYPE_MASK) == PTE_INVALID_DESC; @@ -225,20 +272,17 @@ static uint64_t *expand_to_table(uint64_t *pte, unsigned int level) /* Link the new table in place of the pte it replaces */ set_pte_table_desc(pte, table, level); - table_usage(table, 1); return table; } -static int set_mapping(struct arm_mmu_ptables *ptables, - uintptr_t virt, size_t size, +static int set_mapping(uint64_t *top_table, uintptr_t virt, size_t size, uint64_t desc, bool may_overwrite) { - uint64_t *pte, *ptes[XLAT_LAST_LEVEL + 1]; + uint64_t *table = top_table; + uint64_t *pte; uint64_t level_size; - uint64_t *table = ptables->base_xlat_table; unsigned int level = BASE_XLAT_LEVEL; - int ret = 0; while (size) { __ASSERT(level <= XLAT_LAST_LEVEL, @@ -246,7 +290,6 @@ static int set_mapping(struct arm_mmu_ptables *ptables, /* Locate PTE for given virtual address and page table level */ pte = &table[XLAT_TABLE_VA_IDX(virt, level)]; - ptes[level] = pte; if (is_table_desc(*pte, level)) { /* Move to the next translation table level */ @@ -260,8 +303,7 @@ static int set_mapping(struct arm_mmu_ptables *ptables, LOG_ERR("entry already in use: " "level %d pte %p *pte 0x%016llx", level, pte, *pte); - ret = -EBUSY; - break; + return -EBUSY; } level_size = 1ULL << LEVEL_TO_VA_SIZE_SHIFT(level); @@ -280,8 +322,7 @@ static int set_mapping(struct arm_mmu_ptables *ptables, /* Range doesn't fit, create subtable */ table = expand_to_table(pte, level); if (!table) { - ret = -ENOMEM; - break; + return -ENOMEM; } level++; continue; @@ -291,32 +332,58 @@ static int set_mapping(struct arm_mmu_ptables *ptables, if (is_free_desc(*pte)) { table_usage(pte, 1); } - if (!desc) { - table_usage(pte, -1); - } - /* Create (or erase) block/page descriptor */ + /* Create block/page descriptor */ set_pte_block_desc(pte, desc, level); - /* recursively free unused tables if any */ - while (level != BASE_XLAT_LEVEL && - is_table_unused(pte)) { - free_table(pte); - pte = ptes[--level]; - set_pte_block_desc(pte, 0, level); - table_usage(pte, -1); - } - move_on: virt += level_size; - desc += desc ? level_size : 0; + desc += level_size; size -= level_size; /* Range is mapped, start again for next range */ - table = ptables->base_xlat_table; + table = top_table; level = BASE_XLAT_LEVEL; } - return ret; + return 0; +} + +static void del_mapping(uint64_t *table, uintptr_t virt, size_t size, + unsigned int level) +{ + size_t step, level_size = 1ULL << LEVEL_TO_VA_SIZE_SHIFT(level); + uint64_t *pte, *subtable; + + for ( ; size; virt += step, size -= step) { + step = level_size - (virt & (level_size - 1)); + if (step > size) { + step = size; + } + pte = &table[XLAT_TABLE_VA_IDX(virt, level)]; + + if (is_free_desc(*pte)) { + continue; + } + + if (is_table_desc(*pte, level)) { + subtable = pte_desc_table(*pte); + del_mapping(subtable, virt, step, level + 1); + if (!is_table_unused(subtable)) { + continue; + } + dec_table_ref(subtable); + } else { + /* + * We assume that block mappings will be unmapped + * as a whole and not partially. + */ + __ASSERT(step == level_size, ""); + } + + /* free this entry */ + *pte = 0; + table_usage(pte, -1); + } } #ifdef CONFIG_USERSPACE @@ -347,8 +414,8 @@ static uint64_t *dup_table(uint64_t *src_table, unsigned int level) } dst_table[i] = src_table[i]; - if (is_table_desc(src_table[i], level)) { - table_usage(pte_desc_table(src_table[i]), 1); + if (is_table_desc(dst_table[i], level)) { + inc_table_ref(pte_desc_table(dst_table[i])); } if (!is_free_desc(dst_table[i])) { table_usage(dst_table, 1); @@ -388,8 +455,7 @@ static int privatize_table(uint64_t *dst_table, uint64_t *src_table, return -ENOMEM; } set_pte_table_desc(&dst_table[i], dst_subtable, level); - table_usage(dst_subtable, 1); - table_usage(src_subtable, -1); + dec_table_ref(src_subtable); } ret = privatize_table(dst_subtable, src_subtable, @@ -436,15 +502,14 @@ static void discard_table(uint64_t *table, unsigned int level) for (i = 0U; i < Ln_XLAT_NUM_ENTRIES; i++) { if (is_table_desc(table[i], level)) { - table_usage(pte_desc_table(table[i]), -1); discard_table(pte_desc_table(table[i]), level + 1); + dec_table_ref(pte_desc_table(table[i])); } if (!is_free_desc(table[i])) { table[i] = 0U; table_usage(table, -1); } } - free_table(table); } static int globalize_table(uint64_t *dst_table, uint64_t *src_table, @@ -466,6 +531,20 @@ static int globalize_table(uint64_t *dst_table, uint64_t *src_table, continue; } + if (is_free_desc(src_table[i]) && + is_table_desc(dst_table[i], level)) { + uint64_t *subtable = pte_desc_table(dst_table[i]); + + del_mapping(subtable, virt, step, level + 1); + if (is_table_unused(subtable)) { + /* unreference the empty table */ + dst_table[i] = 0; + table_usage(dst_table, -1); + dec_table_ref(subtable); + } + continue; + } + if (step != level_size) { /* boundary falls in the middle of this pte */ __ASSERT(is_table_desc(src_table[i], level), @@ -497,15 +576,15 @@ static int globalize_table(uint64_t *dst_table, uint64_t *src_table, table_usage(dst_table, -1); } if (is_table_desc(src_table[i], level)) { - table_usage(pte_desc_table(src_table[i]), 1); + inc_table_ref(pte_desc_table(src_table[i])); } dst_table[i] = src_table[i]; debug_show_pte(&dst_table[i], level); if (old_table) { /* we can discard the whole branch */ - table_usage(old_table, -1); discard_table(old_table, level + 1); + dec_table_ref(old_table); } } @@ -625,7 +704,7 @@ static int __add_map(struct arm_mmu_ptables *ptables, const char *name, __ASSERT(((virt | phys | size) & (CONFIG_MMU_PAGE_SIZE - 1)) == 0, "address/size are not page aligned\n"); desc |= phys; - return set_mapping(ptables, virt, size, desc, may_overwrite); + return set_mapping(ptables->base_xlat_table, virt, size, desc, may_overwrite); } static int add_map(struct arm_mmu_ptables *ptables, const char *name, @@ -640,20 +719,18 @@ static int add_map(struct arm_mmu_ptables *ptables, const char *name, return ret; } -static int remove_map(struct arm_mmu_ptables *ptables, const char *name, - uintptr_t virt, size_t size) +static void remove_map(struct arm_mmu_ptables *ptables, const char *name, + uintptr_t virt, size_t size) { k_spinlock_key_t key; - int ret; MMU_DEBUG("unmmap [%s]: virt %lx size %lx\n", name, virt, size); __ASSERT(((virt | size) & (CONFIG_MMU_PAGE_SIZE - 1)) == 0, "address/size are not page aligned\n"); key = k_spin_lock(&xlat_lock); - ret = set_mapping(ptables, virt, size, 0, true); + del_mapping(ptables->base_xlat_table, virt, size, BASE_XLAT_LEVEL); k_spin_unlock(&xlat_lock, key); - return ret; } static void invalidate_tlb_all(void) @@ -1005,14 +1082,9 @@ void arch_mem_map(void *virt, uintptr_t phys, size_t size, uint32_t flags) void arch_mem_unmap(void *addr, size_t size) { - int ret = remove_map(&kernel_ptables, "generic", (uintptr_t)addr, size); - - if (ret) { - LOG_ERR("remove_map() returned %d", ret); - } else { - sync_domains((uintptr_t)addr, size); - invalidate_tlb_all(); - } + remove_map(&kernel_ptables, "generic", (uintptr_t)addr, size); + sync_domains((uintptr_t)addr, size); + invalidate_tlb_all(); } int arch_page_phys_get(void *virt, uintptr_t *phys) diff --git a/arch/arm64/core/offsets/offsets.c b/arch/arm64/core/offsets/offsets.c index 4268692c498b5..772f0df3a8d05 100644 --- a/arch/arm64/core/offsets/offsets.c +++ b/arch/arm64/core/offsets/offsets.c @@ -40,7 +40,7 @@ GEN_NAMED_OFFSET_SYM(_callee_saved_t, x27, x27_x28); GEN_NAMED_OFFSET_SYM(_callee_saved_t, x29, x29_sp_el0); GEN_NAMED_OFFSET_SYM(_callee_saved_t, sp_elx, sp_elx_lr); -#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER +#ifdef CONFIG_FRAME_POINTER GEN_NAMED_OFFSET_SYM(_esf_t, fp, fp); #endif diff --git a/arch/arm64/core/prep_c.c b/arch/arm64/core/prep_c.c index bfd3b7c1eaa90..1aca46f23767e 100644 --- a/arch/arm64/core/prep_c.c +++ b/arch/arm64/core/prep_c.c @@ -21,29 +21,6 @@ extern void z_arm64_mm_init(bool is_primary_core); __weak void z_arm64_mm_init(bool is_primary_core) { } -/* - * These simple memset/memcpy alternatives are necessary as the optimized - * ones depend on the MMU to be active (see commit c5b898743a20). - */ -void z_early_memset(void *dst, int c, size_t n) -{ - uint8_t *d = dst; - - while (n--) { - *d++ = c; - } -} - -void z_early_memcpy(void *dst, const void *src, size_t n) -{ - uint8_t *d = dst; - const uint8_t *s = src; - - while (n--) { - *d++ = *s++; - } -} - /** * * @brief Prepare to and run C code diff --git a/arch/arm64/core/reset.S b/arch/arm64/core/reset.S index 5e406bea1323d..a01139ad70091 100644 --- a/arch/arm64/core/reset.S +++ b/arch/arm64/core/reset.S @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include "boot.h" #include "macro_priv.inc" diff --git a/arch/arm64/core/smp.c b/arch/arm64/core/smp.c index 8777c400766fc..bbb7f9634317d 100644 --- a/arch/arm64/core/smp.c +++ b/arch/arm64/core/smp.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -180,7 +181,7 @@ void arch_secondary_cpu_init(int cpu_num) #ifdef CONFIG_SMP -static void broadcast_ipi(unsigned int ipi) +static void send_ipi(unsigned int ipi, uint32_t cpu_bitmap) { uint64_t mpidr = MPIDR_TO_CORE(GET_MPIDR()); @@ -190,6 +191,10 @@ static void broadcast_ipi(unsigned int ipi) unsigned int num_cpus = arch_num_cpus(); for (int i = 0; i < num_cpus; i++) { + if ((cpu_bitmap & BIT(i)) == 0) { + continue; + } + uint64_t target_mpidr = cpu_map[i]; uint8_t aff0; @@ -209,10 +214,14 @@ void sched_ipi_handler(const void *unused) z_sched_ipi(); } -/* arch implementation of sched_ipi */ -void arch_sched_ipi(void) +void arch_sched_broadcast_ipi(void) +{ + send_ipi(SGI_SCHED_IPI, IPI_ALL_CPUS_MASK); +} + +void arch_sched_directed_ipi(uint32_t cpu_bitmap) { - broadcast_ipi(SGI_SCHED_IPI); + send_ipi(SGI_SCHED_IPI, cpu_bitmap); } #ifdef CONFIG_USERSPACE @@ -232,7 +241,7 @@ void mem_cfg_ipi_handler(const void *unused) void z_arm64_mem_cfg_ipi(void) { - broadcast_ipi(SGI_MMCFG_IPI); + send_ipi(SGI_MMCFG_IPI, IPI_ALL_CPUS_MASK); } #endif @@ -302,6 +311,5 @@ int arch_smp_init(void) return 0; } -SYS_INIT(arch_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); #endif diff --git a/arch/arm64/core/thread.c b/arch/arm64/core/thread.c index a0269501c19ac..18f49945eda49 100644 --- a/arch/arm64/core/thread.c +++ b/arch/arm64/core/thread.c @@ -87,7 +87,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, void *p1, void *p2, void *p3) { extern void z_arm64_exit_exc(void); - z_arch_esf_t *pInitCtx; + struct arch_esf *pInitCtx; /* * Clean the thread->arch to avoid unexpected behavior because the @@ -102,7 +102,7 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, * dropping into EL0. */ - pInitCtx = Z_STACK_PTR_TO_FRAME(struct __esf, stack_ptr); + pInitCtx = Z_STACK_PTR_TO_FRAME(struct arch_esf, stack_ptr); pInitCtx->x0 = (uint64_t)entry; pInitCtx->x1 = (uint64_t)p1; diff --git a/arch/arm64/core/userspace.S b/arch/arm64/core/userspace.S index 618aa6b2c20b1..968d2a436bc55 100644 --- a/arch/arm64/core/userspace.S +++ b/arch/arm64/core/userspace.S @@ -51,7 +51,7 @@ strlen_done: ret /* - * int arch_buffer_validate(void *addr, size_t size, int write) + * int arch_buffer_validate(const void *addr, size_t size, int write) */ GTEXT(arch_buffer_validate) diff --git a/arch/arm64/core/vector_table.S b/arch/arm64/core/vector_table.S index 1a1b649d4f295..632304b70299e 100644 --- a/arch/arm64/core/vector_table.S +++ b/arch/arm64/core/vector_table.S @@ -10,7 +10,7 @@ #include #include -#include +#include #include #include #include @@ -72,7 +72,7 @@ _ASM_FILE_PROLOGUE .endif #endif -#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER +#ifdef CONFIG_FRAME_POINTER str x29, [sp, ___esf_t_fp_OFFSET] #endif @@ -339,7 +339,7 @@ SECTION_FUNC(TEXT, z_arm64_exit_exc) ldp x16, x17, [sp, ___esf_t_x16_x17_OFFSET] ldp x18, lr, [sp, ___esf_t_x18_lr_OFFSET] -#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER +#ifdef CONFIG_FRAME_POINTER ldr x29, [sp, ___esf_t_fp_OFFSET] #endif diff --git a/arch/arm64/include/kernel_arch_data.h b/arch/arm64/include/kernel_arch_data.h index ec781fc902dd5..8b607c1dbf47d 100644 --- a/arch/arm64/include/kernel_arch_data.h +++ b/arch/arm64/include/kernel_arch_data.h @@ -36,7 +36,7 @@ extern "C" { #endif -typedef struct __esf _esf_t; +typedef struct arch_esf _esf_t; typedef struct __basic_sf _basic_sf_t; #ifdef __cplusplus diff --git a/arch/arm64/include/kernel_arch_func.h b/arch/arm64/include/kernel_arch_func.h index a5c3d59d87a6f..cc91abc3b49f3 100644 --- a/arch/arm64/include/kernel_arch_func.h +++ b/arch/arm64/include/kernel_arch_func.h @@ -43,7 +43,7 @@ static inline void arch_switch(void *switch_to, void **switched_from) z_arm64_context_switch(new, old); } -extern void z_arm64_fatal_error(unsigned int reason, z_arch_esf_t *esf); +extern void z_arm64_fatal_error(unsigned int reason, struct arch_esf *esf); extern void z_arm64_set_ttbr0(uint64_t ttbr0); extern void z_arm64_mem_cfg_ipi(void); diff --git a/arch/arm64/include/offsets_short_arch.h b/arch/arm64/include/offsets_short_arch.h index abd93bba7bace..11dd5f642561d 100644 --- a/arch/arm64/include/offsets_short_arch.h +++ b/arch/arm64/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_ARM64_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_ARM64_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_exception_depth \ (___thread_t_arch_OFFSET + ___thread_arch_t_exception_depth_OFFSET) diff --git a/arch/common/CMakeLists.txt b/arch/common/CMakeLists.txt index 78fc6396ed63a..407d028cffa77 100644 --- a/arch/common/CMakeLists.txt +++ b/arch/common/CMakeLists.txt @@ -22,6 +22,8 @@ zephyr_library_sources_ifdef( multilevel_irq.c ) +zephyr_library_sources_ifdef(CONFIG_LEGACY_MULTI_LEVEL_TABLE_GENERATION multilevel_irq_legacy.c) + zephyr_library_sources_ifdef(CONFIG_SHARED_INTERRUPTS shared_irq.c) if(NOT CONFIG_ARCH_HAS_TIMING_FUNCTIONS AND diff --git a/arch/common/Kconfig b/arch/common/Kconfig index aabc599a4d58a..ba74cf6dda75a 100644 --- a/arch/common/Kconfig +++ b/arch/common/Kconfig @@ -15,3 +15,18 @@ config SEMIHOST https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc This option is compatible with hardware and with QEMU, through the (automatic) use of the -semihosting-config switch when invoking it. + +config LEGACY_MULTI_LEVEL_TABLE_GENERATION + bool "Auto generates the multi-level interrupt LUT (deprecated)" + default y + select DEPRECATED + depends on MULTI_LEVEL_INTERRUPTS + depends on !PLIC + depends on !NXP_IRQSTEER + depends on !RV32M1_INTMUX + depends on !CAVS_ICTL + depends on !DW_ICTL_ACE + depends on !DW_ICTL + help + A make-shift Kconfig to continue generating the multi-level interrupt LUT + with the legacy way using DT macros. diff --git a/arch/common/isr_tables.c b/arch/common/isr_tables.c index 050597b7b1d82..b3bdd136e0c20 100644 --- a/arch/common/isr_tables.c +++ b/arch/common/isr_tables.c @@ -90,7 +90,7 @@ uintptr_t __irq_vector_table _irq_vector_table[IRQ_TABLE_SIZE] = { #ifdef CONFIG_GEN_SW_ISR_TABLE struct _isr_table_entry __sw_isr_table _sw_isr_table[IRQ_TABLE_SIZE] = { [0 ...(IRQ_TABLE_SIZE - 1)] = {(const void *)0x42, - (void *)&z_irq_spurious}, + &z_irq_spurious}, }; #endif diff --git a/arch/common/multilevel_irq.c b/arch/common/multilevel_irq.c index 53f8e03a4d849..be2e8892e1f27 100644 --- a/arch/common/multilevel_irq.c +++ b/arch/common/multilevel_irq.c @@ -15,162 +15,71 @@ BUILD_ASSERT((CONFIG_NUM_2ND_LEVEL_AGGREGATORS * CONFIG_MAX_IRQ_PER_AGGREGATOR) BIT(CONFIG_2ND_LEVEL_INTERRUPT_BITS), "L2 bits not enough to cover the number of L2 IRQs"); -/* - * Insert code if the node_id is an interrupt controller - */ -#define Z_IF_DT_IS_INTC(node_id, code) \ - IF_ENABLED(DT_NODE_HAS_PROP(node_id, interrupt_controller), (code)) - -/* - * Expands to node_id if its IRQN is equal to `_irq`, nothing otherwise - * This only works for `_irq` between 0 & 4095, see `IS_EQ` - */ -#define Z_IF_DT_INTC_IRQN_EQ(node_id, _irq) IF_ENABLED(IS_EQ(DT_IRQ(node_id, irq), _irq), (node_id)) - -/* - * Expands to node_id if it's an interrupt controller & its IRQN is `irq`, or nothing otherwise - */ -#define Z_DT_INTC_GET_IRQN(node_id, _irq) \ - Z_IF_DT_IS_INTC(node_id, Z_IF_DT_INTC_IRQN_EQ(node_id, _irq)) - /** - * Loop through child of "/soc" and get root interrupt controllers with `_irq` as IRQN, - * this assumes only one device has the IRQN - * @param _irq irq number - * @return node_id(s) that has the `_irq` number, or empty if none of them has the `_irq` + * @brief Get the aggregator that's responsible for the given irq + * + * @param irq IRQ number to query + * + * @return Aggregator entry, NULL if irq is level 1 or not found. */ -#define INTC_DT_IRQN_GET(_irq) \ - DT_FOREACH_CHILD_STATUS_OKAY_VARGS(DT_PATH(soc), Z_DT_INTC_GET_IRQN, _irq) - -/* If can't find any matching interrupt controller, fills with `NULL` */ -#define INTC_DEVICE_INIT(node_id) .dev = DEVICE_DT_GET_OR_NULL(node_id), - -#define INIT_IRQ_PARENT_OFFSET(d, i, o) { \ - INTC_DEVICE_INIT(d) \ - .irq = i, \ - .offset = o, \ -} - -#define IRQ_INDEX_TO_OFFSET(i, base) (base + i * CONFIG_MAX_IRQ_PER_AGGREGATOR) - -#define CAT_2ND_LVL_LIST(i, base) \ - INIT_IRQ_PARENT_OFFSET(INTC_DT_IRQN_GET(CONFIG_2ND_LVL_INTR_0##i##_OFFSET), \ - CONFIG_2ND_LVL_INTR_0##i##_OFFSET, IRQ_INDEX_TO_OFFSET(i, base)) -const struct _irq_parent_entry _lvl2_irq_list[CONFIG_NUM_2ND_LEVEL_AGGREGATORS] - = { LISTIFY(CONFIG_NUM_2ND_LEVEL_AGGREGATORS, CAT_2ND_LVL_LIST, (,), - CONFIG_2ND_LVL_ISR_TBL_OFFSET) }; - -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - -BUILD_ASSERT((CONFIG_NUM_3RD_LEVEL_AGGREGATORS * CONFIG_MAX_IRQ_PER_AGGREGATOR) <= - BIT(CONFIG_3RD_LEVEL_INTERRUPT_BITS), - "L3 bits not enough to cover the number of L3 IRQs"); - -#define CAT_3RD_LVL_LIST(i, base) \ - INIT_IRQ_PARENT_OFFSET(INTC_DT_IRQN_GET(CONFIG_3RD_LVL_INTR_0##i##_OFFSET), \ - CONFIG_3RD_LVL_INTR_0##i##_OFFSET, IRQ_INDEX_TO_OFFSET(i, base)) +static const struct _irq_parent_entry *get_intc_entry_for_irq(unsigned int irq) +{ + const unsigned int level = irq_get_level(irq); -const struct _irq_parent_entry _lvl3_irq_list[CONFIG_NUM_3RD_LEVEL_AGGREGATORS] - = { LISTIFY(CONFIG_NUM_3RD_LEVEL_AGGREGATORS, CAT_3RD_LVL_LIST, (,), - CONFIG_3RD_LVL_ISR_TBL_OFFSET) }; + /* 1st level aggregator is not registered */ + if (level == 1) { + return NULL; + } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + const unsigned int intc_irq = irq_get_intc_irq(irq); -static const struct _irq_parent_entry *get_parent_entry(unsigned int parent_irq, - const struct _irq_parent_entry list[], - unsigned int length) -{ - unsigned int i; - const struct _irq_parent_entry *entry = NULL; - - for (i = 0U; i < length; ++i) { - if (list[i].irq == parent_irq) { - entry = &list[i]; - break; + /* Find an aggregator entry that matches the level & intc_irq */ + STRUCT_SECTION_FOREACH_ALTERNATE(intc_table, _irq_parent_entry, intc) { + if ((intc->level == level) && (intc->irq == intc_irq)) { + return intc; } } - __ASSERT(i != length, "Invalid argument: %i", parent_irq); - - return entry; + return NULL; } const struct device *z_get_sw_isr_device_from_irq(unsigned int irq) { - const struct device *dev = NULL; - unsigned int level, parent_irq; - const struct _irq_parent_entry *entry = NULL; + const struct _irq_parent_entry *intc = get_intc_entry_for_irq(irq); - level = irq_get_level(irq); + __ASSERT(intc != NULL, "can't find an aggregator to handle irq(%X)", irq); - if (level == 2U) { - parent_irq = irq_parent_level_2(irq); - entry = get_parent_entry(parent_irq, - _lvl2_irq_list, - CONFIG_NUM_2ND_LEVEL_AGGREGATORS); - } -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - else if (level == 3U) { - parent_irq = irq_parent_level_3(irq); - entry = get_parent_entry(parent_irq, - _lvl3_irq_list, - CONFIG_NUM_3RD_LEVEL_AGGREGATORS); - } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - dev = entry != NULL ? entry->dev : NULL; - - return dev; + return intc != NULL ? intc->dev : NULL; } unsigned int z_get_sw_isr_irq_from_device(const struct device *dev) { - for (size_t i = 0U; i < CONFIG_NUM_2ND_LEVEL_AGGREGATORS; ++i) { - if (_lvl2_irq_list[i].dev == dev) { - return _lvl2_irq_list[i].irq; + /* Get the IRQN for the aggregator */ + STRUCT_SECTION_FOREACH_ALTERNATE(intc_table, _irq_parent_entry, intc) { + if (intc->dev == dev) { + return intc->irq; } } -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - for (size_t i = 0U; i < CONFIG_NUM_3RD_LEVEL_AGGREGATORS; ++i) { - if (_lvl3_irq_list[i].dev == dev) { - return _lvl3_irq_list[i].irq; - } - } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ + __ASSERT(false, "dev(%p) not found", dev); return 0; } unsigned int z_get_sw_isr_table_idx(unsigned int irq) { - unsigned int table_idx, level, parent_irq, local_irq, parent_offset; - const struct _irq_parent_entry *entry = NULL; - - level = irq_get_level(irq); + unsigned int table_idx, local_irq; + const struct _irq_parent_entry *intc = get_intc_entry_for_irq(irq); + const unsigned int level = irq_get_level(irq); - if (level == 2U) { - local_irq = irq_from_level_2(irq); + if (intc != NULL) { + local_irq = irq_from_level(irq, level); __ASSERT_NO_MSG(local_irq < CONFIG_MAX_IRQ_PER_AGGREGATOR); - parent_irq = irq_parent_level_2(irq); - entry = get_parent_entry(parent_irq, - _lvl2_irq_list, - CONFIG_NUM_2ND_LEVEL_AGGREGATORS); - parent_offset = entry != NULL ? entry->offset : 0U; - table_idx = parent_offset + local_irq; - } -#ifdef CONFIG_3RD_LEVEL_INTERRUPTS - else if (level == 3U) { - local_irq = irq_from_level_3(irq); - __ASSERT_NO_MSG(local_irq < CONFIG_MAX_IRQ_PER_AGGREGATOR); - parent_irq = irq_parent_level_3(irq); - entry = get_parent_entry(parent_irq, - _lvl3_irq_list, - CONFIG_NUM_3RD_LEVEL_AGGREGATORS); - parent_offset = entry != NULL ? entry->offset : 0U; - table_idx = parent_offset + local_irq; - } -#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ - else { + + table_idx = intc->offset + local_irq; + } else { + /* irq level must be 1 if no intc entry */ + __ASSERT(level == 1, "can't find an aggregator to handle irq(%X)", irq); table_idx = irq; } diff --git a/arch/common/multilevel_irq_legacy.c b/arch/common/multilevel_irq_legacy.c new file mode 100644 index 0000000000000..dd4fe68b5ac45 --- /dev/null +++ b/arch/common/multilevel_irq_legacy.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018 Intel Corporation. + * Copyright (c) 2024 Meta. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/** + * @file + * @brief This file houses the deprecated legacy macros-generated multi-level interrupt lookup + * table code, compiled when `CONFIG_LEGACY_MULTI_LEVEL_TABLE_GENERATION` is enabled. + */ + +/* + * Insert code if the node_id is an interrupt controller + */ +#define Z_IF_DT_IS_INTC(node_id, code) \ + IF_ENABLED(DT_NODE_HAS_PROP(node_id, interrupt_controller), (code)) + +/* + * Expands to node_id if its IRQN is equal to `_irq`, nothing otherwise + * This only works for `_irq` between 0 & 4095, see `IS_EQ` + */ +#define Z_IF_DT_INTC_IRQN_EQ(node_id, _irq) IF_ENABLED(IS_EQ(DT_IRQ(node_id, irq), _irq), (node_id)) + +/* + * Expands to node_id if it's an interrupt controller & its IRQN is `irq`, or nothing otherwise + */ +#define Z_DT_INTC_GET_IRQN(node_id, _irq) \ + Z_IF_DT_IS_INTC(node_id, Z_IF_DT_INTC_IRQN_EQ(node_id, _irq)) + +/** + * Loop through child of "/soc" and get root interrupt controllers with `_irq` as IRQN, + * this assumes only one device has the IRQN + * @param _irq irq number + * @return node_id(s) that has the `_irq` number, or empty if none of them has the `_irq` + */ +#define INTC_DT_IRQN_GET(_irq) \ + DT_FOREACH_CHILD_STATUS_OKAY_VARGS(DT_PATH(soc), Z_DT_INTC_GET_IRQN, _irq) + +#define INIT_IRQ_PARENT_OFFSET_2ND(n, d, i, o) \ + IRQ_PARENT_ENTRY_DEFINE(intc_l2_##n, DEVICE_DT_GET_OR_NULL(d), i, o, 2) + +#define IRQ_INDEX_TO_OFFSET(i, base) (base + i * CONFIG_MAX_IRQ_PER_AGGREGATOR) + +#define CAT_2ND_LVL_LIST(i, base) \ + INIT_IRQ_PARENT_OFFSET_2ND(i, INTC_DT_IRQN_GET(CONFIG_2ND_LVL_INTR_0##i##_OFFSET), \ + CONFIG_2ND_LVL_INTR_0##i##_OFFSET, \ + IRQ_INDEX_TO_OFFSET(i, base)) + +LISTIFY(CONFIG_NUM_2ND_LEVEL_AGGREGATORS, CAT_2ND_LVL_LIST, (;), CONFIG_2ND_LVL_ISR_TBL_OFFSET); + +#ifdef CONFIG_3RD_LEVEL_INTERRUPTS + +BUILD_ASSERT((CONFIG_NUM_3RD_LEVEL_AGGREGATORS * CONFIG_MAX_IRQ_PER_AGGREGATOR) <= + BIT(CONFIG_3RD_LEVEL_INTERRUPT_BITS), + "L3 bits not enough to cover the number of L3 IRQs"); + +#define INIT_IRQ_PARENT_OFFSET_3RD(n, d, i, o) \ + IRQ_PARENT_ENTRY_DEFINE(intc_l3_##n, DEVICE_DT_GET_OR_NULL(d), i, o, 3) + +#define CAT_3RD_LVL_LIST(i, base) \ + INIT_IRQ_PARENT_OFFSET_3RD(i, INTC_DT_IRQN_GET(CONFIG_3RD_LVL_INTR_0##i##_OFFSET), \ + CONFIG_3RD_LVL_INTR_0##i##_OFFSET, \ + IRQ_INDEX_TO_OFFSET(i, base)) + +LISTIFY(CONFIG_NUM_3RD_LEVEL_AGGREGATORS, CAT_3RD_LVL_LIST, (;), CONFIG_3RD_LVL_ISR_TBL_OFFSET); + +#endif /* CONFIG_3RD_LEVEL_INTERRUPTS */ diff --git a/arch/mips/core/fatal.c b/arch/mips/core/fatal.c index 16011241666ab..a53e5bb0f5e6c 100644 --- a/arch/mips/core/fatal.c +++ b/arch/mips/core/fatal.c @@ -9,7 +9,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); FUNC_NORETURN void z_mips_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG if (esf != NULL) { @@ -84,7 +84,7 @@ static char *cause_str(unsigned long cause) } } -void _Fault(z_arch_esf_t *esf) +void _Fault(struct arch_esf *esf) { unsigned long cause; diff --git a/arch/mips/core/isr.S b/arch/mips/core/isr.S index 44babb2149be2..86d05d1983356 100644 --- a/arch/mips/core/isr.S +++ b/arch/mips/core/isr.S @@ -14,7 +14,7 @@ #include #include -#define ESF_O(FIELD) __z_arch_esf_t_##FIELD##_OFFSET +#define ESF_O(FIELD) __struct_arch_esf_##FIELD##_OFFSET #define THREAD_O(FIELD) _thread_offset_to_##FIELD /* Convenience macros for loading/storing register states. */ @@ -58,12 +58,12 @@ op v1, ESF_O(v1)(sp) ; #define STORE_CALLER_SAVED() \ - addi sp, sp, -__z_arch_esf_t_SIZEOF ;\ + addi sp, sp, -__struct_arch_esf_SIZEOF ;\ DO_CALLER_SAVED(OP_STOREREG) ; #define LOAD_CALLER_SAVED() \ DO_CALLER_SAVED(OP_LOADREG) ;\ - addi sp, sp, __z_arch_esf_t_SIZEOF ; + addi sp, sp, __struct_arch_esf_SIZEOF ; /* imports */ GTEXT(_Fault) diff --git a/arch/mips/core/offsets/offsets.c b/arch/mips/core/offsets/offsets.c index 24b477e9558ea..c70ce3c39fc7e 100644 --- a/arch/mips/core/offsets/offsets.c +++ b/arch/mips/core/offsets/offsets.c @@ -23,32 +23,32 @@ GEN_OFFSET_SYM(_callee_saved_t, s6); GEN_OFFSET_SYM(_callee_saved_t, s7); GEN_OFFSET_SYM(_callee_saved_t, s8); -GEN_OFFSET_SYM(z_arch_esf_t, ra); -GEN_OFFSET_SYM(z_arch_esf_t, gp); -GEN_OFFSET_SYM(z_arch_esf_t, t0); -GEN_OFFSET_SYM(z_arch_esf_t, t1); -GEN_OFFSET_SYM(z_arch_esf_t, t2); -GEN_OFFSET_SYM(z_arch_esf_t, t3); -GEN_OFFSET_SYM(z_arch_esf_t, t4); -GEN_OFFSET_SYM(z_arch_esf_t, t5); -GEN_OFFSET_SYM(z_arch_esf_t, t6); -GEN_OFFSET_SYM(z_arch_esf_t, t7); -GEN_OFFSET_SYM(z_arch_esf_t, t8); -GEN_OFFSET_SYM(z_arch_esf_t, t9); -GEN_OFFSET_SYM(z_arch_esf_t, a0); -GEN_OFFSET_SYM(z_arch_esf_t, a1); -GEN_OFFSET_SYM(z_arch_esf_t, a2); -GEN_OFFSET_SYM(z_arch_esf_t, a3); -GEN_OFFSET_SYM(z_arch_esf_t, v0); -GEN_OFFSET_SYM(z_arch_esf_t, v1); -GEN_OFFSET_SYM(z_arch_esf_t, at); -GEN_OFFSET_SYM(z_arch_esf_t, epc); -GEN_OFFSET_SYM(z_arch_esf_t, badvaddr); -GEN_OFFSET_SYM(z_arch_esf_t, hi); -GEN_OFFSET_SYM(z_arch_esf_t, lo); -GEN_OFFSET_SYM(z_arch_esf_t, status); -GEN_OFFSET_SYM(z_arch_esf_t, cause); +GEN_OFFSET_STRUCT(arch_esf, ra); +GEN_OFFSET_STRUCT(arch_esf, gp); +GEN_OFFSET_STRUCT(arch_esf, t0); +GEN_OFFSET_STRUCT(arch_esf, t1); +GEN_OFFSET_STRUCT(arch_esf, t2); +GEN_OFFSET_STRUCT(arch_esf, t3); +GEN_OFFSET_STRUCT(arch_esf, t4); +GEN_OFFSET_STRUCT(arch_esf, t5); +GEN_OFFSET_STRUCT(arch_esf, t6); +GEN_OFFSET_STRUCT(arch_esf, t7); +GEN_OFFSET_STRUCT(arch_esf, t8); +GEN_OFFSET_STRUCT(arch_esf, t9); +GEN_OFFSET_STRUCT(arch_esf, a0); +GEN_OFFSET_STRUCT(arch_esf, a1); +GEN_OFFSET_STRUCT(arch_esf, a2); +GEN_OFFSET_STRUCT(arch_esf, a3); +GEN_OFFSET_STRUCT(arch_esf, v0); +GEN_OFFSET_STRUCT(arch_esf, v1); +GEN_OFFSET_STRUCT(arch_esf, at); +GEN_OFFSET_STRUCT(arch_esf, epc); +GEN_OFFSET_STRUCT(arch_esf, badvaddr); +GEN_OFFSET_STRUCT(arch_esf, hi); +GEN_OFFSET_STRUCT(arch_esf, lo); +GEN_OFFSET_STRUCT(arch_esf, status); +GEN_OFFSET_STRUCT(arch_esf, cause); -GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, STACK_ROUND_UP(sizeof(z_arch_esf_t))); +GEN_ABSOLUTE_SYM(__struct_arch_esf_SIZEOF, STACK_ROUND_UP(sizeof(struct arch_esf))); GEN_ABS_SYM_END diff --git a/arch/mips/core/thread.c b/arch/mips/core/thread.c index e551674d5215d..7966ff462f5fd 100644 --- a/arch/mips/core/thread.c +++ b/arch/mips/core/thread.c @@ -19,11 +19,11 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, char *stack_ptr, k_thread_entry_t entry, void *p1, void *p2, void *p3) { - struct __esf *stack_init; + struct arch_esf *stack_init; /* Initial stack frame for thread */ - stack_init = (struct __esf *)Z_STACK_PTR_ALIGN( - Z_STACK_PTR_TO_FRAME(struct __esf, stack_ptr) + stack_init = (struct arch_esf *)Z_STACK_PTR_ALIGN( + Z_STACK_PTR_TO_FRAME(struct arch_esf, stack_ptr) ); /* Setup the initial stack frame */ diff --git a/arch/mips/include/kernel_arch_func.h b/arch/mips/include/kernel_arch_func.h index ad89f75dd7f14..b01cc1a4c65da 100644 --- a/arch/mips/include/kernel_arch_func.h +++ b/arch/mips/include/kernel_arch_func.h @@ -35,7 +35,7 @@ arch_thread_return_value_set(struct k_thread *thread, unsigned int value) } FUNC_NORETURN void z_mips_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); static inline bool arch_is_in_isr(void) { diff --git a/arch/mips/include/offsets_short_arch.h b/arch/mips/include/offsets_short_arch.h index bd64deef114f5..8440f0ff70137 100644 --- a/arch/mips/include/offsets_short_arch.h +++ b/arch/mips/include/offsets_short_arch.h @@ -9,7 +9,7 @@ #ifndef ZEPHYR_ARCH_MIPS_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_MIPS_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_sp \ (___thread_t_callee_saved_OFFSET + ___callee_saved_t_sp_OFFSET) diff --git a/arch/nios2/core/exception.S b/arch/nios2/core/exception.S index 6b003262bb04d..ab2d3463dd437 100644 --- a/arch/nios2/core/exception.S +++ b/arch/nios2/core/exception.S @@ -35,35 +35,35 @@ GTEXT(_offload_routine) */ SECTION_FUNC(exception.entry, _exception) /* Reserve thread stack space for saving context */ - subi sp, sp, __z_arch_esf_t_SIZEOF + subi sp, sp, __struct_arch_esf_SIZEOF /* Preserve all caller-saved registers onto the thread's stack */ - stw ra, __z_arch_esf_t_ra_OFFSET(sp) - stw r1, __z_arch_esf_t_r1_OFFSET(sp) - stw r2, __z_arch_esf_t_r2_OFFSET(sp) - stw r3, __z_arch_esf_t_r3_OFFSET(sp) - stw r4, __z_arch_esf_t_r4_OFFSET(sp) - stw r5, __z_arch_esf_t_r5_OFFSET(sp) - stw r6, __z_arch_esf_t_r6_OFFSET(sp) - stw r7, __z_arch_esf_t_r7_OFFSET(sp) - stw r8, __z_arch_esf_t_r8_OFFSET(sp) - stw r9, __z_arch_esf_t_r9_OFFSET(sp) - stw r10, __z_arch_esf_t_r10_OFFSET(sp) - stw r11, __z_arch_esf_t_r11_OFFSET(sp) - stw r12, __z_arch_esf_t_r12_OFFSET(sp) - stw r13, __z_arch_esf_t_r13_OFFSET(sp) - stw r14, __z_arch_esf_t_r14_OFFSET(sp) - stw r15, __z_arch_esf_t_r15_OFFSET(sp) + stw ra, __struct_arch_esf_ra_OFFSET(sp) + stw r1, __struct_arch_esf_r1_OFFSET(sp) + stw r2, __struct_arch_esf_r2_OFFSET(sp) + stw r3, __struct_arch_esf_r3_OFFSET(sp) + stw r4, __struct_arch_esf_r4_OFFSET(sp) + stw r5, __struct_arch_esf_r5_OFFSET(sp) + stw r6, __struct_arch_esf_r6_OFFSET(sp) + stw r7, __struct_arch_esf_r7_OFFSET(sp) + stw r8, __struct_arch_esf_r8_OFFSET(sp) + stw r9, __struct_arch_esf_r9_OFFSET(sp) + stw r10, __struct_arch_esf_r10_OFFSET(sp) + stw r11, __struct_arch_esf_r11_OFFSET(sp) + stw r12, __struct_arch_esf_r12_OFFSET(sp) + stw r13, __struct_arch_esf_r13_OFFSET(sp) + stw r14, __struct_arch_esf_r14_OFFSET(sp) + stw r15, __struct_arch_esf_r15_OFFSET(sp) /* Store value of estatus control register */ rdctl et, estatus - stw et, __z_arch_esf_t_estatus_OFFSET(sp) + stw et, __struct_arch_esf_estatus_OFFSET(sp) /* ea-4 is the address of the instruction when the exception happened, * put this in the stack frame as well */ addi r15, ea, -4 - stw r15, __z_arch_esf_t_instr_OFFSET(sp) + stw r15, __struct_arch_esf_instr_OFFSET(sp) /* Figure out whether we are here because of an interrupt or an * exception. If an interrupt, switch stacks and enter IRQ handling @@ -157,7 +157,7 @@ not_interrupt: * * We earlier put ea - 4 in the stack frame, replace it with just ea */ - stw ea, __z_arch_esf_t_instr_OFFSET(sp) + stw ea, __struct_arch_esf_instr_OFFSET(sp) #ifdef CONFIG_IRQ_OFFLOAD /* Check the contents of _offload_routine. If non-NULL, jump into @@ -193,35 +193,35 @@ _exception_exit: * and return to the interrupted context */ /* Return address from the exception */ - ldw ea, __z_arch_esf_t_instr_OFFSET(sp) + ldw ea, __struct_arch_esf_instr_OFFSET(sp) /* Restore estatus * XXX is this right??? */ - ldw r5, __z_arch_esf_t_estatus_OFFSET(sp) + ldw r5, __struct_arch_esf_estatus_OFFSET(sp) wrctl estatus, r5 /* Restore caller-saved registers */ - ldw ra, __z_arch_esf_t_ra_OFFSET(sp) - ldw r1, __z_arch_esf_t_r1_OFFSET(sp) - ldw r2, __z_arch_esf_t_r2_OFFSET(sp) - ldw r3, __z_arch_esf_t_r3_OFFSET(sp) - ldw r4, __z_arch_esf_t_r4_OFFSET(sp) - ldw r5, __z_arch_esf_t_r5_OFFSET(sp) - ldw r6, __z_arch_esf_t_r6_OFFSET(sp) - ldw r7, __z_arch_esf_t_r7_OFFSET(sp) - ldw r8, __z_arch_esf_t_r8_OFFSET(sp) - ldw r9, __z_arch_esf_t_r9_OFFSET(sp) - ldw r10, __z_arch_esf_t_r10_OFFSET(sp) - ldw r11, __z_arch_esf_t_r11_OFFSET(sp) - ldw r12, __z_arch_esf_t_r12_OFFSET(sp) - ldw r13, __z_arch_esf_t_r13_OFFSET(sp) - ldw r14, __z_arch_esf_t_r14_OFFSET(sp) - ldw r15, __z_arch_esf_t_r15_OFFSET(sp) + ldw ra, __struct_arch_esf_ra_OFFSET(sp) + ldw r1, __struct_arch_esf_r1_OFFSET(sp) + ldw r2, __struct_arch_esf_r2_OFFSET(sp) + ldw r3, __struct_arch_esf_r3_OFFSET(sp) + ldw r4, __struct_arch_esf_r4_OFFSET(sp) + ldw r5, __struct_arch_esf_r5_OFFSET(sp) + ldw r6, __struct_arch_esf_r6_OFFSET(sp) + ldw r7, __struct_arch_esf_r7_OFFSET(sp) + ldw r8, __struct_arch_esf_r8_OFFSET(sp) + ldw r9, __struct_arch_esf_r9_OFFSET(sp) + ldw r10, __struct_arch_esf_r10_OFFSET(sp) + ldw r11, __struct_arch_esf_r11_OFFSET(sp) + ldw r12, __struct_arch_esf_r12_OFFSET(sp) + ldw r13, __struct_arch_esf_r13_OFFSET(sp) + ldw r14, __struct_arch_esf_r14_OFFSET(sp) + ldw r15, __struct_arch_esf_r15_OFFSET(sp) /* Put the stack pointer back where it was when we entered * exception state */ - addi sp, sp, __z_arch_esf_t_SIZEOF + addi sp, sp, __struct_arch_esf_SIZEOF /* All done, copy estatus into status and transfer to ea */ eret diff --git a/arch/nios2/core/fatal.c b/arch/nios2/core/fatal.c index ac64b5bc30944..b531bb41e1789 100644 --- a/arch/nios2/core/fatal.c +++ b/arch/nios2/core/fatal.c @@ -12,7 +12,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); FUNC_NORETURN void z_nios2_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { #if CONFIG_EXCEPTION_DEBUG if (esf != NULL) { @@ -102,7 +102,7 @@ static char *cause_str(uint32_t cause_code) } #endif -FUNC_NORETURN void _Fault(const z_arch_esf_t *esf) +FUNC_NORETURN void _Fault(const struct arch_esf *esf) { #if defined(CONFIG_PRINTK) || defined(CONFIG_LOG) /* Unfortunately, completely unavailable on Nios II/e cores */ diff --git a/arch/nios2/core/offsets/offsets.c b/arch/nios2/core/offsets/offsets.c index 8f3b3f748c1a1..9d381d87446c1 100644 --- a/arch/nios2/core/offsets/offsets.c +++ b/arch/nios2/core/offsets/offsets.c @@ -44,24 +44,24 @@ GEN_OFFSET_SYM(_callee_saved_t, sp); GEN_OFFSET_SYM(_callee_saved_t, key); GEN_OFFSET_SYM(_callee_saved_t, retval); -GEN_OFFSET_SYM(z_arch_esf_t, ra); -GEN_OFFSET_SYM(z_arch_esf_t, r1); -GEN_OFFSET_SYM(z_arch_esf_t, r2); -GEN_OFFSET_SYM(z_arch_esf_t, r3); -GEN_OFFSET_SYM(z_arch_esf_t, r4); -GEN_OFFSET_SYM(z_arch_esf_t, r5); -GEN_OFFSET_SYM(z_arch_esf_t, r6); -GEN_OFFSET_SYM(z_arch_esf_t, r7); -GEN_OFFSET_SYM(z_arch_esf_t, r8); -GEN_OFFSET_SYM(z_arch_esf_t, r9); -GEN_OFFSET_SYM(z_arch_esf_t, r10); -GEN_OFFSET_SYM(z_arch_esf_t, r11); -GEN_OFFSET_SYM(z_arch_esf_t, r12); -GEN_OFFSET_SYM(z_arch_esf_t, r13); -GEN_OFFSET_SYM(z_arch_esf_t, r14); -GEN_OFFSET_SYM(z_arch_esf_t, r15); -GEN_OFFSET_SYM(z_arch_esf_t, estatus); -GEN_OFFSET_SYM(z_arch_esf_t, instr); -GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, sizeof(z_arch_esf_t)); +GEN_OFFSET_STRUCT(arch_esf, ra); +GEN_OFFSET_STRUCT(arch_esf, r1); +GEN_OFFSET_STRUCT(arch_esf, r2); +GEN_OFFSET_STRUCT(arch_esf, r3); +GEN_OFFSET_STRUCT(arch_esf, r4); +GEN_OFFSET_STRUCT(arch_esf, r5); +GEN_OFFSET_STRUCT(arch_esf, r6); +GEN_OFFSET_STRUCT(arch_esf, r7); +GEN_OFFSET_STRUCT(arch_esf, r8); +GEN_OFFSET_STRUCT(arch_esf, r9); +GEN_OFFSET_STRUCT(arch_esf, r10); +GEN_OFFSET_STRUCT(arch_esf, r11); +GEN_OFFSET_STRUCT(arch_esf, r12); +GEN_OFFSET_STRUCT(arch_esf, r13); +GEN_OFFSET_STRUCT(arch_esf, r14); +GEN_OFFSET_STRUCT(arch_esf, r15); +GEN_OFFSET_STRUCT(arch_esf, estatus); +GEN_OFFSET_STRUCT(arch_esf, instr); +GEN_ABSOLUTE_SYM(__struct_arch_esf_SIZEOF, sizeof(struct arch_esf)); GEN_ABS_SYM_END diff --git a/arch/nios2/include/kernel_arch_func.h b/arch/nios2/include/kernel_arch_func.h index 2f2030c1c731c..2df268a1c6245 100644 --- a/arch/nios2/include/kernel_arch_func.h +++ b/arch/nios2/include/kernel_arch_func.h @@ -39,7 +39,7 @@ arch_thread_return_value_set(struct k_thread *thread, unsigned int value) } FUNC_NORETURN void z_nios2_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); static inline bool arch_is_in_isr(void) { diff --git a/arch/nios2/include/offsets_short_arch.h b/arch/nios2/include/offsets_short_arch.h index b3f60972c3b88..3b961e1fcb92c 100644 --- a/arch/nios2/include/offsets_short_arch.h +++ b/arch/nios2/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_NIOS2_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_NIOS2_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/posix/core/swap.c b/arch/posix/core/swap.c index 67ca4c5bb9bbf..d4ec5e50b5ea6 100644 --- a/arch/posix/core/swap.c +++ b/arch/posix/core/swap.c @@ -112,7 +112,7 @@ void posix_irq_check_idle_exit(void) { if (_kernel.idle) { _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } } #endif diff --git a/arch/posix/include/offsets_short_arch.h b/arch/posix/include/offsets_short_arch.h index b33414b3f6e1b..5281d68e092d5 100644 --- a/arch/posix/include/offsets_short_arch.h +++ b/arch/posix/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_POSIX_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_POSIX_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 77d1c7aa53adc..76ea74026ac3d 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -38,20 +38,9 @@ config RISCV_ALWAYS_SWITCH_THROUGH_ECALL and most people should say n here to minimize context switching overhead. -config RISCV_ENABLE_FRAME_POINTER - bool - default y - depends on OVERRIDE_FRAME_POINTER_DEFAULT && !OMIT_FRAME_POINTER - help - Hidden option to simplify access to OVERRIDE_FRAME_POINTER_DEFAULT - and OMIT_FRAME_POINTER. It is automatically enabled when the frame - pointer unwinding is enabled. - config RISCV_EXCEPTION_STACK_TRACE bool default y - depends on RISCV_ENABLE_FRAME_POINTER - depends on EXCEPTION_STACK_TRACE imply THREAD_STACK_INFO help Internal config to enable runtime stack traces on fatal exceptions. @@ -99,7 +88,7 @@ config RISCV_SOC_HAS_ISR_STACKING guarded by !_ASMLANGUAGE. The ESF should be defined to account for the hardware stacked registers in the proper order as they are saved on the stack by the hardware, and the registers saved by the - software macros. The structure must be called '__esf'. + software macros. The structure must be called 'struct arch_esf'. config RISCV_SOC_HAS_CUSTOM_IRQ_HANDLING bool @@ -267,6 +256,8 @@ config RISCV_PMP select ARCH_MEM_DOMAIN_SYNCHRONOUS_API if USERSPACE select ARCH_MEM_DOMAIN_DATA if USERSPACE select THREAD_LOCAL_STORAGE if USERSPACE + select ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + select MEM_DOMAIN_ISOLATED_STACKS help MCU implements Physical Memory Protection. @@ -378,6 +369,7 @@ config ARCH_IRQ_VECTOR_TABLE_ALIGN config RISCV_TRAP_HANDLER_ALIGNMENT int "Alignment of RISC-V trap handler in bytes" + default 64 if RISCV_HAS_CLIC default 4 help This value configures the alignment of RISC-V trap handling diff --git a/arch/riscv/core/CMakeLists.txt b/arch/riscv/core/CMakeLists.txt index 1d8daac060c26..74d520458ad20 100644 --- a/arch/riscv/core/CMakeLists.txt +++ b/arch/riscv/core/CMakeLists.txt @@ -6,7 +6,6 @@ zephyr_library_sources( cpu_idle.c fatal.c irq_manage.c - isr.S prep_c.c reboot.c reset.S @@ -21,8 +20,10 @@ endif () zephyr_library_sources_ifdef(CONFIG_FPU_SHARING fpu.c fpu.S) zephyr_library_sources_ifdef(CONFIG_DEBUG_COREDUMP coredump.c) zephyr_library_sources_ifdef(CONFIG_IRQ_OFFLOAD irq_offload.c) +zephyr_library_sources_ifdef(CONFIG_GEN_SW_ISR_TABLE isr.S) zephyr_library_sources_ifdef(CONFIG_RISCV_PMP pmp.c pmp.S) zephyr_library_sources_ifdef(CONFIG_THREAD_LOCAL_STORAGE tls.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE userspace.S) zephyr_library_sources_ifdef(CONFIG_SEMIHOST semihost.c) +zephyr_library_sources_ifdef(CONFIG_EXCEPTION_STACK_TRACE stacktrace.c) zephyr_linker_sources(ROM_START SORT_KEY 0x0vectors vector_table.ld) diff --git a/arch/riscv/core/coredump.c b/arch/riscv/core/coredump.c index f232816433a08..70d7a9976d4ad 100644 --- a/arch/riscv/core/coredump.c +++ b/arch/riscv/core/coredump.c @@ -67,7 +67,7 @@ struct riscv_arch_block { */ static struct riscv_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/riscv/core/fatal.c b/arch/riscv/core/fatal.c index 7152da2066c72..779d23905cab0 100644 --- a/arch/riscv/core/fatal.c +++ b/arch/riscv/core/fatal.c @@ -28,94 +28,41 @@ static const struct z_exc_handle exceptions[] = { #define NO_REG " " #endif -#ifdef CONFIG_RISCV_EXCEPTION_STACK_TRACE -#define MAX_STACK_FRAMES 8 +/* Stack trace function */ +void z_riscv_unwind_stack(const struct arch_esf *esf, const _callee_saved_t *csf); -struct stackframe { - uintptr_t fp; - uintptr_t ra; -}; - -static bool in_stack_bound(uintptr_t addr) +uintptr_t z_riscv_get_sp_before_exc(const struct arch_esf *esf) { -#ifdef CONFIG_THREAD_STACK_INFO - uintptr_t start, end; - - if (_current == NULL || arch_is_in_isr()) { - /* We were servicing an interrupt */ - int cpu_id; - -#ifdef CONFIG_SMP - cpu_id = arch_curr_cpu()->id; -#else - cpu_id = 0; -#endif + /* + * Kernel stack pointer prior this exception i.e. before + * storing the exception stack frame. + */ + uintptr_t sp = (uintptr_t)esf + sizeof(struct arch_esf); - start = (uintptr_t)K_KERNEL_STACK_BUFFER(z_interrupt_stacks[cpu_id]); - end = start + CONFIG_ISR_STACK_SIZE; #ifdef CONFIG_USERSPACE - /* TODO: handle user threads */ -#endif - } else { - start = _current->stack_info.start; - end = Z_STACK_PTR_ALIGN(_current->stack_info.start + _current->stack_info.size); + if ((esf->mstatus & MSTATUS_MPP) == PRV_U) { + /* + * Exception happened in user space: + * consider the saved user stack instead. + */ + sp = esf->sp; } +#endif - return (addr >= start) && (addr < end); -#else - ARG_UNUSED(addr); - return true; -#endif /* CONFIG_THREAD_STACK_INFO */ -} - -static inline bool in_text_region(uintptr_t addr) -{ - extern uintptr_t __text_region_start, __text_region_end; - - return (addr >= (uintptr_t)&__text_region_start) && (addr < (uintptr_t)&__text_region_end); -} - -static void unwind_stack(const z_arch_esf_t *esf) -{ - uintptr_t fp = esf->s0; - uintptr_t ra; - struct stackframe *frame; - - LOG_ERR("call trace:"); - - for (int i = 0; (i < MAX_STACK_FRAMES) && (fp != 0U) && in_stack_bound((uintptr_t)fp);) { - frame = (struct stackframe *)fp - 1; - ra = frame->ra; - if (in_text_region(ra)) { - LOG_ERR(" %2d: fp: " PR_REG " ra: " PR_REG, i, (uintptr_t)fp, ra); - /* - * Increment the iterator only if `ra` is within the text region to get the - * most out of it - */ - i++; - } - fp = frame->fp; - } + return sp; } -#endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */ FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { z_riscv_fatal_error_csf(reason, esf, NULL); } -FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf_t *esf, +FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const struct arch_esf *esf, const _callee_saved_t *csf) { #ifdef CONFIG_EXCEPTION_DEBUG if (esf != NULL) { - /* - * Kernel stack pointer prior this exception i.e. before - * storing the exception stack frame. - */ - uintptr_t sp = (uintptr_t)esf + sizeof(z_arch_esf_t); - LOG_ERR(" a0: " PR_REG " t0: " PR_REG, esf->a0, esf->t0); LOG_ERR(" a1: " PR_REG " t1: " PR_REG, esf->a1, esf->t1); LOG_ERR(" a2: " PR_REG " t2: " PR_REG, esf->a2, esf->t2); @@ -130,23 +77,11 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf LOG_ERR(" a6: " PR_REG " t6: " PR_REG, esf->a6, esf->t6); LOG_ERR(" a7: " PR_REG, esf->a7); #endif /* CONFIG_RISCV_ISA_RV32E */ -#ifdef CONFIG_USERSPACE - if ((esf->mstatus & MSTATUS_MPP) == 0) { - /* - * Exception happened in user space: - * consider the saved user stack instead. - */ - sp = esf->sp; - } -#endif - LOG_ERR(" sp: " PR_REG, sp); + LOG_ERR(" sp: " PR_REG, z_riscv_get_sp_before_exc(esf)); LOG_ERR(" ra: " PR_REG, esf->ra); LOG_ERR(" mepc: " PR_REG, esf->mepc); LOG_ERR("mstatus: " PR_REG, esf->mstatus); LOG_ERR(""); -#ifdef CONFIG_RISCV_EXCEPTION_STACK_TRACE - unwind_stack(esf); -#endif /* CONFIG_RISCV_EXCEPTION_STACK_TRACE */ } if (csf != NULL) { @@ -163,6 +98,11 @@ FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf #endif /* CONFIG_RISCV_ISA_RV32E */ LOG_ERR(""); } + + if (IS_ENABLED(CONFIG_EXCEPTION_STACK_TRACE)) { + z_riscv_unwind_stack(esf, csf); + } + #endif /* CONFIG_EXCEPTION_DEBUG */ z_fatal_error(reason, esf); CODE_UNREACHABLE; @@ -204,14 +144,14 @@ static char *cause_str(unsigned long cause) } } -static bool bad_stack_pointer(z_arch_esf_t *esf) +static bool bad_stack_pointer(struct arch_esf *esf) { #ifdef CONFIG_PMP_STACK_GUARD /* * Check if the kernel stack pointer prior this exception (before * storing the exception stack frame) was in the stack guard area. */ - uintptr_t sp = (uintptr_t)esf + sizeof(z_arch_esf_t); + uintptr_t sp = (uintptr_t)esf + sizeof(struct arch_esf); #ifdef CONFIG_USERSPACE if (_current->arch.priv_stack_start != 0 && @@ -249,7 +189,7 @@ static bool bad_stack_pointer(z_arch_esf_t *esf) return false; } -void _Fault(z_arch_esf_t *esf) +void _Fault(struct arch_esf *esf) { #ifdef CONFIG_USERSPACE /* @@ -301,7 +241,7 @@ FUNC_NORETURN void arch_syscall_oops(void *ssf_ptr) void z_impl_user_fault(unsigned int reason) { - z_arch_esf_t *oops_esf = _current->syscall_frame; + struct arch_esf *oops_esf = _current->syscall_frame; if (((_current->base.user_options & K_USER) != 0) && reason != K_ERR_STACK_CHK_FAIL) { @@ -315,6 +255,6 @@ static void z_vrfy_user_fault(unsigned int reason) z_impl_user_fault(reason); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/arch/riscv/core/fpu.S b/arch/riscv/core/fpu.S index 2708d11fec1c4..981bd576cb773 100644 --- a/arch/riscv/core/fpu.S +++ b/arch/riscv/core/fpu.S @@ -7,7 +7,7 @@ #include #include -#include +#include #ifdef CONFIG_CPU_HAS_FPU_DOUBLE_PRECISION #define LOAD fld diff --git a/arch/riscv/core/fpu.c b/arch/riscv/core/fpu.c index da5d07b314640..318e97e0002a9 100644 --- a/arch/riscv/core/fpu.c +++ b/arch/riscv/core/fpu.c @@ -204,7 +204,7 @@ void z_riscv_fpu_enter_exc(void) * Note that the exception depth count was not incremented before this call * as no further exceptions are expected before returning to normal mode. */ -void z_riscv_fpu_trap(z_arch_esf_t *esf) +void z_riscv_fpu_trap(struct arch_esf *esf) { __ASSERT((esf->mstatus & MSTATUS_FS) == 0 && (csr_read(mstatus) & MSTATUS_FS) == 0, @@ -293,7 +293,7 @@ static bool fpu_access_allowed(unsigned int exc_update_level) * This is called on every exception exit except for z_riscv_fpu_trap(). * In that case the exception level of interest is 1 (soon to be 0). */ -void z_riscv_fpu_exit_exc(z_arch_esf_t *esf) +void z_riscv_fpu_exit_exc(struct arch_esf *esf) { if (fpu_access_allowed(1)) { esf->mstatus &= ~MSTATUS_FS; diff --git a/arch/riscv/core/irq_manage.c b/arch/riscv/core/irq_manage.c index b60deceefab25..358b07534be69 100644 --- a/arch/riscv/core/irq_manage.c +++ b/arch/riscv/core/irq_manage.c @@ -9,6 +9,7 @@ #include #include #include +#include #ifdef CONFIG_RISCV_HAS_PLIC #include @@ -53,4 +54,17 @@ int arch_irq_connect_dynamic(unsigned int irq, unsigned int priority, #endif return irq; } + +#ifdef CONFIG_SHARED_INTERRUPTS +int arch_irq_disconnect_dynamic(unsigned int irq, unsigned int priority, + void (*routine)(const void *parameter), const void *parameter, + uint32_t flags) +{ + ARG_UNUSED(priority); + ARG_UNUSED(flags); + + return z_isr_uninstall(irq + CONFIG_RISCV_RESERVED_IRQ_ISR_TABLES_OFFSET, routine, + parameter); +} +#endif /* CONFIG_SHARED_INTERRUPTS */ #endif /* CONFIG_DYNAMIC_INTERRUPTS */ diff --git a/arch/riscv/core/isr.S b/arch/riscv/core/isr.S index 2a8ed28deae76..8a829fd66b17f 100644 --- a/arch/riscv/core/isr.S +++ b/arch/riscv/core/isr.S @@ -24,22 +24,22 @@ /* Convenience macro for loading/storing register states. */ #define DO_CALLER_SAVED(op) \ - RV_E( op t0, __z_arch_esf_t_t0_OFFSET(sp) );\ - RV_E( op t1, __z_arch_esf_t_t1_OFFSET(sp) );\ - RV_E( op t2, __z_arch_esf_t_t2_OFFSET(sp) );\ - RV_I( op t3, __z_arch_esf_t_t3_OFFSET(sp) );\ - RV_I( op t4, __z_arch_esf_t_t4_OFFSET(sp) );\ - RV_I( op t5, __z_arch_esf_t_t5_OFFSET(sp) );\ - RV_I( op t6, __z_arch_esf_t_t6_OFFSET(sp) );\ - RV_E( op a0, __z_arch_esf_t_a0_OFFSET(sp) );\ - RV_E( op a1, __z_arch_esf_t_a1_OFFSET(sp) );\ - RV_E( op a2, __z_arch_esf_t_a2_OFFSET(sp) );\ - RV_E( op a3, __z_arch_esf_t_a3_OFFSET(sp) );\ - RV_E( op a4, __z_arch_esf_t_a4_OFFSET(sp) );\ - RV_E( op a5, __z_arch_esf_t_a5_OFFSET(sp) );\ - RV_I( op a6, __z_arch_esf_t_a6_OFFSET(sp) );\ - RV_I( op a7, __z_arch_esf_t_a7_OFFSET(sp) );\ - RV_E( op ra, __z_arch_esf_t_ra_OFFSET(sp) ) + RV_E( op t0, __struct_arch_esf_t0_OFFSET(sp) );\ + RV_E( op t1, __struct_arch_esf_t1_OFFSET(sp) );\ + RV_E( op t2, __struct_arch_esf_t2_OFFSET(sp) );\ + RV_I( op t3, __struct_arch_esf_t3_OFFSET(sp) );\ + RV_I( op t4, __struct_arch_esf_t4_OFFSET(sp) );\ + RV_I( op t5, __struct_arch_esf_t5_OFFSET(sp) );\ + RV_I( op t6, __struct_arch_esf_t6_OFFSET(sp) );\ + RV_E( op a0, __struct_arch_esf_a0_OFFSET(sp) );\ + RV_E( op a1, __struct_arch_esf_a1_OFFSET(sp) );\ + RV_E( op a2, __struct_arch_esf_a2_OFFSET(sp) );\ + RV_E( op a3, __struct_arch_esf_a3_OFFSET(sp) );\ + RV_E( op a4, __struct_arch_esf_a4_OFFSET(sp) );\ + RV_E( op a5, __struct_arch_esf_a5_OFFSET(sp) );\ + RV_I( op a6, __struct_arch_esf_a6_OFFSET(sp) );\ + RV_I( op a7, __struct_arch_esf_a7_OFFSET(sp) );\ + RV_E( op ra, __struct_arch_esf_ra_OFFSET(sp) ) #ifdef CONFIG_EXCEPTION_DEBUG /* Convenience macro for storing callee saved register [s0 - s11] states. */ @@ -157,7 +157,7 @@ SECTION_FUNC(exception.entry, _isr_wrapper) /* Save user stack value. Coming from user space, we know this * can't overflow the privileged stack. The esf will be allocated * later but it is safe to store our saved user sp here. */ - sr t0, (-__z_arch_esf_t_SIZEOF + __z_arch_esf_t_sp_OFFSET)(sp) + sr t0, (-__struct_arch_esf_SIZEOF + __struct_arch_esf_sp_OFFSET)(sp) /* Make sure tls pointer is sane */ lr t0, ___cpu_t_current_OFFSET(s0) @@ -180,21 +180,21 @@ SECTION_FUNC(exception.entry, _isr_wrapper) SOC_ISR_SW_STACKING #else /* Save caller-saved registers on current thread stack. */ - addi sp, sp, -__z_arch_esf_t_SIZEOF + addi sp, sp, -__struct_arch_esf_SIZEOF DO_CALLER_SAVED(sr) ; #endif /* CONFIG_RISCV_SOC_HAS_ISR_STACKING */ /* Save s0 in the esf and load it with &_current_cpu. */ - sr s0, __z_arch_esf_t_s0_OFFSET(sp) + sr s0, __struct_arch_esf_s0_OFFSET(sp) get_current_cpu s0 /* Save MEPC register */ csrr t0, mepc - sr t0, __z_arch_esf_t_mepc_OFFSET(sp) + sr t0, __struct_arch_esf_mepc_OFFSET(sp) /* Save MSTATUS register */ csrr t2, mstatus - sr t2, __z_arch_esf_t_mstatus_OFFSET(sp) + sr t2, __struct_arch_esf_mstatus_OFFSET(sp) #if defined(CONFIG_FPU_SHARING) /* determine if FPU access was disabled */ @@ -203,6 +203,8 @@ SECTION_FUNC(exception.entry, _isr_wrapper) bnez t1, no_fp /* determine if this is an Illegal Instruction exception */ csrr t2, mcause + li t1, CONFIG_RISCV_MCAUSE_EXCEPTION_MASK + and t2, t2, t1 li t1, 2 /* 2 = illegal instruction */ bne t1, t2, no_fp /* determine if we trapped on an FP instruction. */ @@ -299,7 +301,7 @@ no_fp: /* increment _current->arch.exception_depth */ #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE /* Handle context saving at SOC level. */ - addi a0, sp, __z_arch_esf_t_soc_context_OFFSET + addi a0, sp, __struct_arch_esf_soc_context_OFFSET jal ra, __soc_save_context #endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ @@ -349,7 +351,7 @@ no_fp: /* increment _current->arch.exception_depth */ /* * Call _Fault to handle exception. - * Stack pointer is pointing to a z_arch_esf_t structure, pass it + * Stack pointer is pointing to a struct_arch_esf structure, pass it * to _Fault (via register a0). * If _Fault shall return, set return address to * no_reschedule to restore stack. @@ -368,9 +370,9 @@ is_kernel_syscall: * It's safe to always increment by 4, even with compressed * instructions, because the ecall instruction is always 4 bytes. */ - lr t0, __z_arch_esf_t_mepc_OFFSET(sp) + lr t0, __struct_arch_esf_mepc_OFFSET(sp) addi t0, t0, 4 - sr t0, __z_arch_esf_t_mepc_OFFSET(sp) + sr t0, __struct_arch_esf_mepc_OFFSET(sp) #ifdef CONFIG_PMP_STACK_GUARD /* Re-activate PMP for m-mode */ @@ -381,7 +383,7 @@ is_kernel_syscall: #endif /* Determine what to do. Operation code is in t0. */ - lr t0, __z_arch_esf_t_t0_OFFSET(sp) + lr t0, __struct_arch_esf_t0_OFFSET(sp) .if RV_ECALL_RUNTIME_EXCEPT != 0; .err; .endif beqz t0, do_fault @@ -394,8 +396,8 @@ is_kernel_syscall: #ifdef CONFIG_RISCV_ALWAYS_SWITCH_THROUGH_ECALL li t1, RV_ECALL_SCHEDULE bne t0, t1, skip_schedule - lr a0, __z_arch_esf_t_a0_OFFSET(sp) - lr a1, __z_arch_esf_t_a1_OFFSET(sp) + lr a0, __struct_arch_esf_a0_OFFSET(sp) + lr a1, __struct_arch_esf_a1_OFFSET(sp) j reschedule skip_schedule: #endif @@ -406,7 +408,7 @@ skip_schedule: do_fault: /* Handle RV_ECALL_RUNTIME_EXCEPT. Retrieve reason in a0, esf in A1. */ - lr a0, __z_arch_esf_t_a0_OFFSET(sp) + lr a0, __struct_arch_esf_a0_OFFSET(sp) 1: mv a1, sp #ifdef CONFIG_EXCEPTION_DEBUG @@ -429,8 +431,8 @@ do_irq_offload: * Routine pointer is in saved a0, argument in saved a1 * so we load them with a1/a0 (reversed). */ - lr a1, __z_arch_esf_t_a0_OFFSET(sp) - lr a0, __z_arch_esf_t_a1_OFFSET(sp) + lr a1, __struct_arch_esf_a0_OFFSET(sp) + lr a0, __struct_arch_esf_a1_OFFSET(sp) /* Increment _current_cpu->nested */ lw t1, ___cpu_t_nested_OFFSET(s0) @@ -472,18 +474,18 @@ is_user_syscall: * Same as for is_kernel_syscall: increment saved MEPC by 4 to * prevent triggering the same ecall again upon exiting the ISR. */ - lr t1, __z_arch_esf_t_mepc_OFFSET(sp) + lr t1, __struct_arch_esf_mepc_OFFSET(sp) addi t1, t1, 4 - sr t1, __z_arch_esf_t_mepc_OFFSET(sp) + sr t1, __struct_arch_esf_mepc_OFFSET(sp) /* Restore argument registers from user stack */ - lr a0, __z_arch_esf_t_a0_OFFSET(sp) - lr a1, __z_arch_esf_t_a1_OFFSET(sp) - lr a2, __z_arch_esf_t_a2_OFFSET(sp) - lr a3, __z_arch_esf_t_a3_OFFSET(sp) - lr a4, __z_arch_esf_t_a4_OFFSET(sp) - lr a5, __z_arch_esf_t_a5_OFFSET(sp) - lr t0, __z_arch_esf_t_t0_OFFSET(sp) + lr a0, __struct_arch_esf_a0_OFFSET(sp) + lr a1, __struct_arch_esf_a1_OFFSET(sp) + lr a2, __struct_arch_esf_a2_OFFSET(sp) + lr a3, __struct_arch_esf_a3_OFFSET(sp) + lr a4, __struct_arch_esf_a4_OFFSET(sp) + lr a5, __struct_arch_esf_a5_OFFSET(sp) + lr t0, __struct_arch_esf_t0_OFFSET(sp) #if defined(CONFIG_RISCV_ISA_RV32E) /* Stack alignment for RV32E is 4 bytes */ addi sp, sp, -4 @@ -517,7 +519,7 @@ valid_syscall_id: #endif /* CONFIG_RISCV_ISA_RV32E */ /* Update a0 (return value) on the stack */ - sr a0, __z_arch_esf_t_a0_OFFSET(sp) + sr a0, __struct_arch_esf_a0_OFFSET(sp) /* Disable IRQs again before leaving */ csrc mstatus, MSTATUS_IEN @@ -532,7 +534,7 @@ is_interrupt: * If we came from userspace then we need to reconfigure the * PMP for kernel mode stack guard. */ - lr t0, __z_arch_esf_t_mstatus_OFFSET(sp) + lr t0, __struct_arch_esf_mstatus_OFFSET(sp) li t1, MSTATUS_MPP and t0, t0, t1 bnez t0, 1f @@ -663,7 +665,7 @@ no_reschedule: #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE /* Restore context at SOC level */ - addi a0, sp, __z_arch_esf_t_soc_context_OFFSET + addi a0, sp, __struct_arch_esf_soc_context_OFFSET jal ra, __soc_restore_context #endif /* CONFIG_RISCV_SOC_CONTEXT_SAVE */ @@ -681,8 +683,8 @@ fp_trap_exit: #endif /* Restore MEPC and MSTATUS registers */ - lr t0, __z_arch_esf_t_mepc_OFFSET(sp) - lr t2, __z_arch_esf_t_mstatus_OFFSET(sp) + lr t0, __struct_arch_esf_mepc_OFFSET(sp) + lr t2, __struct_arch_esf_mstatus_OFFSET(sp) csrw mepc, t0 csrw mstatus, t2 @@ -709,7 +711,7 @@ fp_trap_exit: sb t1, %tprel_lo(is_user_mode)(t0) /* preserve stack pointer for next exception entry */ - add t0, sp, __z_arch_esf_t_SIZEOF + add t0, sp, __struct_arch_esf_SIZEOF sr t0, _curr_cpu_arch_user_exc_sp(s0) j 2f @@ -718,13 +720,13 @@ fp_trap_exit: * We are returning to kernel mode. Store the stack pointer to * be re-loaded further down. */ - addi t0, sp, __z_arch_esf_t_SIZEOF - sr t0, __z_arch_esf_t_sp_OFFSET(sp) + addi t0, sp, __struct_arch_esf_SIZEOF + sr t0, __struct_arch_esf_sp_OFFSET(sp) 2: #endif /* Restore s0 (it is no longer ours) */ - lr s0, __z_arch_esf_t_s0_OFFSET(sp) + lr s0, __struct_arch_esf_s0_OFFSET(sp) #ifdef CONFIG_RISCV_SOC_HAS_ISR_STACKING SOC_ISR_SW_UNSTACKING @@ -734,10 +736,10 @@ fp_trap_exit: #ifdef CONFIG_USERSPACE /* retrieve saved stack pointer */ - lr sp, __z_arch_esf_t_sp_OFFSET(sp) + lr sp, __struct_arch_esf_sp_OFFSET(sp) #else /* remove esf from the stack */ - addi sp, sp, __z_arch_esf_t_SIZEOF + addi sp, sp, __struct_arch_esf_SIZEOF #endif #endif /* CONFIG_RISCV_SOC_HAS_ISR_STACKING */ diff --git a/arch/riscv/core/offsets/offsets.c b/arch/riscv/core/offsets/offsets.c index 9bc9306c2e9d1..7b2d55953b29b 100644 --- a/arch/riscv/core/offsets/offsets.c +++ b/arch/riscv/core/offsets/offsets.c @@ -13,6 +13,7 @@ * structures. */ +#include #include #include #include @@ -88,43 +89,43 @@ GEN_OFFSET_SYM(_thread_arch_t, exception_depth); #endif /* CONFIG_FPU_SHARING */ /* esf member offsets */ -GEN_OFFSET_SYM(z_arch_esf_t, ra); -GEN_OFFSET_SYM(z_arch_esf_t, t0); -GEN_OFFSET_SYM(z_arch_esf_t, t1); -GEN_OFFSET_SYM(z_arch_esf_t, t2); -GEN_OFFSET_SYM(z_arch_esf_t, a0); -GEN_OFFSET_SYM(z_arch_esf_t, a1); -GEN_OFFSET_SYM(z_arch_esf_t, a2); -GEN_OFFSET_SYM(z_arch_esf_t, a3); -GEN_OFFSET_SYM(z_arch_esf_t, a4); -GEN_OFFSET_SYM(z_arch_esf_t, a5); +GEN_OFFSET_STRUCT(arch_esf, ra); +GEN_OFFSET_STRUCT(arch_esf, t0); +GEN_OFFSET_STRUCT(arch_esf, t1); +GEN_OFFSET_STRUCT(arch_esf, t2); +GEN_OFFSET_STRUCT(arch_esf, a0); +GEN_OFFSET_STRUCT(arch_esf, a1); +GEN_OFFSET_STRUCT(arch_esf, a2); +GEN_OFFSET_STRUCT(arch_esf, a3); +GEN_OFFSET_STRUCT(arch_esf, a4); +GEN_OFFSET_STRUCT(arch_esf, a5); #if !defined(CONFIG_RISCV_ISA_RV32E) -GEN_OFFSET_SYM(z_arch_esf_t, t3); -GEN_OFFSET_SYM(z_arch_esf_t, t4); -GEN_OFFSET_SYM(z_arch_esf_t, t5); -GEN_OFFSET_SYM(z_arch_esf_t, t6); -GEN_OFFSET_SYM(z_arch_esf_t, a6); -GEN_OFFSET_SYM(z_arch_esf_t, a7); +GEN_OFFSET_STRUCT(arch_esf, t3); +GEN_OFFSET_STRUCT(arch_esf, t4); +GEN_OFFSET_STRUCT(arch_esf, t5); +GEN_OFFSET_STRUCT(arch_esf, t6); +GEN_OFFSET_STRUCT(arch_esf, a6); +GEN_OFFSET_STRUCT(arch_esf, a7); #endif /* !CONFIG_RISCV_ISA_RV32E */ -GEN_OFFSET_SYM(z_arch_esf_t, mepc); -GEN_OFFSET_SYM(z_arch_esf_t, mstatus); +GEN_OFFSET_STRUCT(arch_esf, mepc); +GEN_OFFSET_STRUCT(arch_esf, mstatus); -GEN_OFFSET_SYM(z_arch_esf_t, s0); +GEN_OFFSET_STRUCT(arch_esf, s0); #ifdef CONFIG_USERSPACE -GEN_OFFSET_SYM(z_arch_esf_t, sp); +GEN_OFFSET_STRUCT(arch_esf, sp); #endif #if defined(CONFIG_RISCV_SOC_CONTEXT_SAVE) -GEN_OFFSET_SYM(z_arch_esf_t, soc_context); +GEN_OFFSET_STRUCT(arch_esf, soc_context); #endif #if defined(CONFIG_RISCV_SOC_OFFSETS) GEN_SOC_OFFSET_SYMS(); #endif -GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, sizeof(z_arch_esf_t)); +GEN_ABSOLUTE_SYM(__struct_arch_esf_SIZEOF, sizeof(struct arch_esf)); #ifdef CONFIG_EXCEPTION_DEBUG GEN_ABSOLUTE_SYM(__callee_saved_t_SIZEOF, ROUND_UP(sizeof(_callee_saved_t), ARCH_STACK_PTR_ALIGN)); diff --git a/arch/riscv/core/pmp.c b/arch/riscv/core/pmp.c index 3807b3b103b2c..50b5dd58f5d72 100644 --- a/arch/riscv/core/pmp.c +++ b/arch/riscv/core/pmp.c @@ -667,7 +667,7 @@ int arch_mem_domain_thread_remove(struct k_thread *thread) ((inner_start) >= (outer_start) && (inner_size) <= (outer_size) && \ ((inner_start) - (outer_start)) <= ((outer_size) - (inner_size))) -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { uintptr_t start = (uintptr_t)addr; int ret = -1; diff --git a/arch/riscv/core/reset.S b/arch/riscv/core/reset.S index e9424e7a8e2af..89c488faa9475 100644 --- a/arch/riscv/core/reset.S +++ b/arch/riscv/core/reset.S @@ -8,7 +8,7 @@ #include #include #include -#include +#include #include "asm_macros.inc" /* exports */ diff --git a/arch/riscv/core/smp.c b/arch/riscv/core/smp.c index 68147f8880a65..4ef287c4a7a56 100644 --- a/arch/riscv/core/smp.c +++ b/arch/riscv/core/smp.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -86,14 +87,15 @@ static atomic_val_t cpu_pending_ipi[CONFIG_MP_MAX_NUM_CPUS]; #define IPI_SCHED 0 #define IPI_FPU_FLUSH 1 -void arch_sched_ipi(void) +void arch_sched_directed_ipi(uint32_t cpu_bitmap) { unsigned int key = arch_irq_lock(); unsigned int id = _current_cpu->id; unsigned int num_cpus = arch_num_cpus(); for (unsigned int i = 0; i < num_cpus; i++) { - if (i != id && _kernel.cpus[i].arch.online) { + if ((i != id) && _kernel.cpus[i].arch.online && + ((cpu_bitmap & BIT(i)) != 0)) { atomic_set_bit(&cpu_pending_ipi[i], IPI_SCHED); MSIP(_kernel.cpus[i].arch.hartid) = 1; } @@ -102,6 +104,11 @@ void arch_sched_ipi(void) arch_irq_unlock(key); } +void arch_sched_broadcast_ipi(void) +{ + arch_sched_directed_ipi(IPI_ALL_CPUS_MASK); +} + #ifdef CONFIG_FPU_SHARING void arch_flush_fpu_ipi(unsigned int cpu) { @@ -165,5 +172,4 @@ int arch_smp_init(void) return 0; } -SYS_INIT(arch_smp_init, PRE_KERNEL_2, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); #endif /* CONFIG_SMP */ diff --git a/arch/riscv/core/stacktrace.c b/arch/riscv/core/stacktrace.c new file mode 100644 index 0000000000000..563d6cad14454 --- /dev/null +++ b/arch/riscv/core/stacktrace.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); + +uintptr_t z_riscv_get_sp_before_exc(const struct arch_esf *esf); + +#define MAX_STACK_FRAMES \ + MAX(CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES, CONFIG_ARCH_STACKWALK_MAX_FRAMES) + +struct stackframe { + uintptr_t fp; + uintptr_t ra; +}; + +typedef bool (*stack_verify_fn)(uintptr_t, const struct k_thread *const, const struct arch_esf *); + +static inline bool in_irq_stack_bound(uintptr_t addr, uint8_t cpu_id) +{ + uintptr_t start, end; + + start = (uintptr_t)K_KERNEL_STACK_BUFFER(z_interrupt_stacks[cpu_id]); + end = start + CONFIG_ISR_STACK_SIZE; + + return (addr >= start) && (addr < end); +} + +static inline bool in_kernel_thread_stack_bound(uintptr_t addr, const struct k_thread *const thread) +{ +#ifdef CONFIG_THREAD_STACK_INFO + uintptr_t start, end; + + start = thread->stack_info.start; + end = Z_STACK_PTR_ALIGN(thread->stack_info.start + thread->stack_info.size); + + return (addr >= start) && (addr < end); +#else + ARG_UNUSED(addr); + ARG_UNUSED(thread); + /* Return false as we can't check if the addr is in the thread stack without stack info */ + return false; +#endif +} + +#ifdef CONFIG_USERSPACE +static inline bool in_user_thread_stack_bound(uintptr_t addr, const struct k_thread *const thread) +{ + uintptr_t start, end; + + /* See: zephyr/include/zephyr/arch/riscv/arch.h */ + if (IS_ENABLED(CONFIG_PMP_POWER_OF_TWO_ALIGNMENT)) { + start = thread->arch.priv_stack_start - CONFIG_PRIVILEGED_STACK_SIZE; + end = thread->arch.priv_stack_start; + } else { + start = thread->stack_info.start - CONFIG_PRIVILEGED_STACK_SIZE; + end = thread->stack_info.start; + } + + return (addr >= start) && (addr < end); +} +#endif /* CONFIG_USERSPACE */ + +static bool in_fatal_stack_bound(uintptr_t addr, const struct k_thread *const thread, + const struct arch_esf *esf) +{ + ARG_UNUSED(thread); + + if (!IS_ALIGNED(addr, sizeof(uintptr_t))) { + return false; + } + + if (_current == NULL || arch_is_in_isr()) { + /* We were servicing an interrupt */ + uint8_t cpu_id = IS_ENABLED(CONFIG_SMP) ? arch_curr_cpu()->id : 0U; + + return in_irq_stack_bound(addr, cpu_id); + } +#ifdef CONFIG_USERSPACE + if ((esf != NULL) && ((esf->mstatus & MSTATUS_MPP) == PRV_U) && + ((_current->base.user_options & K_USER) != 0)) { + return in_user_thread_stack_bound(addr, _current); + } +#endif /* CONFIG_USERSPACE */ + + return in_kernel_thread_stack_bound(addr, _current); +} + +static bool in_stack_bound(uintptr_t addr, const struct k_thread *const thread, + const struct arch_esf *esf) +{ + ARG_UNUSED(esf); + + if (!IS_ALIGNED(addr, sizeof(uintptr_t))) { + return false; + } + +#ifdef CONFIG_USERSPACE + if ((thread->base.user_options & K_USER) != 0) { + return in_user_thread_stack_bound(addr, thread); + } +#endif /* CONFIG_USERSPACE */ + + return in_kernel_thread_stack_bound(addr, thread); +} + +static inline bool in_text_region(uintptr_t addr) +{ + extern uintptr_t __text_region_start, __text_region_end; + + return (addr >= (uintptr_t)&__text_region_start) && (addr < (uintptr_t)&__text_region_end); +} + +#ifdef CONFIG_FRAME_POINTER +static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const struct k_thread *thread, + const struct arch_esf *esf, stack_verify_fn vrfy, + const _callee_saved_t *csf) +{ + uintptr_t fp, last_fp = 0; + uintptr_t ra; + struct stackframe *frame; + + if (esf != NULL) { + /* Unwind the provided exception stack frame */ + fp = esf->s0; + ra = esf->mepc; + } else if ((csf == NULL) || (csf == &_current->callee_saved)) { + /* Unwind current thread (default case when nothing is provided ) */ + fp = (uintptr_t)__builtin_frame_address(0); + ra = (uintptr_t)walk_stackframe; + thread = _current; + } else { + /* Unwind the provided thread */ + fp = csf->s0; + ra = csf->ra; + } + + for (int i = 0; (i < MAX_STACK_FRAMES) && vrfy(fp, thread, esf) && (fp > last_fp);) { + if (in_text_region(ra)) { + if (!cb(cookie, ra)) { + break; + } + /* + * Increment the iterator only if `ra` is within the text region to get the + * most out of it + */ + i++; + } + last_fp = fp; + /* Unwind to the previous frame */ + frame = (struct stackframe *)fp - 1; + ra = frame->ra; + fp = frame->fp; + } +} +#else /* !CONFIG_FRAME_POINTER */ +register uintptr_t current_stack_pointer __asm__("sp"); +static void walk_stackframe(stack_trace_callback_fn cb, void *cookie, const struct k_thread *thread, + const struct arch_esf *esf, stack_verify_fn vrfy, + const _callee_saved_t *csf) +{ + uintptr_t sp; + uintptr_t ra; + uintptr_t *ksp, last_ksp = 0; + + if (esf != NULL) { + /* Unwind the provided exception stack frame */ + sp = z_riscv_get_sp_before_exc(esf); + ra = esf->mepc; + } else if ((csf == NULL) || (csf == &_current->callee_saved)) { + /* Unwind current thread (default case when nothing is provided ) */ + sp = current_stack_pointer; + ra = (uintptr_t)walk_stackframe; + thread = _current; + } else { + /* Unwind the provided thread */ + sp = csf->sp; + ra = csf->ra; + + } + + ksp = (uintptr_t *)sp; + for (int i = 0; (i < MAX_STACK_FRAMES) && vrfy((uintptr_t)ksp, thread, esf) && + ((uintptr_t)ksp > last_ksp);) { + if (in_text_region(ra)) { + if (!cb(cookie, ra)) { + break; + } + /* + * Increment the iterator only if `ra` is within the text region to get the + * most out of it + */ + i++; + } + last_ksp = (uintptr_t)ksp; + /* Unwind to the previous frame */ + ra = ((struct arch_esf *)ksp++)->ra; + } +} +#endif /* CONFIG_FRAME_POINTER */ + +void arch_stack_walk(stack_trace_callback_fn callback_fn, void *cookie, + const struct k_thread *thread, const struct arch_esf *esf) +{ + walk_stackframe(callback_fn, cookie, thread, esf, in_stack_bound, + thread != NULL ? &thread->callee_saved : NULL); +} + +#if __riscv_xlen == 32 +#define PR_REG "%08" PRIxPTR +#elif __riscv_xlen == 64 +#define PR_REG "%016" PRIxPTR +#endif + +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB +#define LOG_STACK_TRACE(idx, ra, name, offset) \ + LOG_ERR(" %2d: ra: " PR_REG " [%s+0x%x]", idx, ra, name, offset) +#else +#define LOG_STACK_TRACE(idx, ra, name, offset) LOG_ERR(" %2d: ra: " PR_REG, idx, ra) +#endif /* CONFIG_EXCEPTION_STACK_TRACE_SYMTAB */ + +static bool print_trace_address(void *arg, unsigned long ra) +{ + int *i = arg; +#ifdef CONFIG_EXCEPTION_STACK_TRACE_SYMTAB + uint32_t offset = 0; + const char *name = symtab_find_symbol_name(ra, &offset); +#endif + + LOG_STACK_TRACE((*i)++, ra, name, offset); + + return true; +} + +void z_riscv_unwind_stack(const struct arch_esf *esf, const _callee_saved_t *csf) +{ + int i = 0; + + LOG_ERR("call trace:"); + walk_stackframe(print_trace_address, &i, NULL, esf, in_fatal_stack_bound, csf); + LOG_ERR(""); +} diff --git a/arch/riscv/core/thread.c b/arch/riscv/core/thread.c index 38d5dbde092c6..aeb33b31f3b1f 100644 --- a/arch/riscv/core/thread.c +++ b/arch/riscv/core/thread.c @@ -23,15 +23,15 @@ void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, void *p1, void *p2, void *p3) { extern void z_riscv_thread_start(void); - struct __esf *stack_init; + struct arch_esf *stack_init; #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE const struct soc_esf soc_esf_init = {SOC_ESF_INIT}; #endif /* Initial stack frame for thread */ - stack_init = (struct __esf *)Z_STACK_PTR_ALIGN( - Z_STACK_PTR_TO_FRAME(struct __esf, stack_ptr) + stack_init = (struct arch_esf *)Z_STACK_PTR_ALIGN( + Z_STACK_PTR_TO_FRAME(struct arch_esf, stack_ptr) ); /* Setup the initial stack frame */ @@ -212,6 +212,8 @@ FUNC_NORETURN void z_riscv_switch_to_main_no_multithreading(k_thread_entry_t mai main_stack = (K_THREAD_STACK_BUFFER(z_main_stack) + K_THREAD_STACK_SIZEOF(z_main_stack)); + irq_unlock(MSTATUS_IEN); + __asm__ volatile ( "mv sp, %0; jalr ra, %1, 0" : diff --git a/arch/riscv/include/kernel_arch_func.h b/arch/riscv/include/kernel_arch_func.h index bdfc0527b9502..c5ed6ff3f7f42 100644 --- a/arch/riscv/include/kernel_arch_func.h +++ b/arch/riscv/include/kernel_arch_func.h @@ -71,9 +71,9 @@ arch_switch(void *switch_to, void **switched_from) /* Thin wrapper around z_riscv_fatal_error_csf */ FUNC_NORETURN void z_riscv_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); -FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const z_arch_esf_t *esf, +FUNC_NORETURN void z_riscv_fatal_error_csf(unsigned int reason, const struct arch_esf *esf, const _callee_saved_t *csf); static inline bool arch_is_in_isr(void) diff --git a/arch/riscv/include/offsets_short_arch.h b/arch/riscv/include/offsets_short_arch.h index 3d3a878f16ea1..27c01a77461d3 100644 --- a/arch/riscv/include/offsets_short_arch.h +++ b/arch/riscv/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_RISCV_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_RISCV_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_sp \ (___thread_t_callee_saved_OFFSET + ___callee_saved_t_sp_OFFSET) diff --git a/arch/sparc/core/fatal.c b/arch/sparc/core/fatal.c index 55100606b9242..40fd9d16792bc 100644 --- a/arch/sparc/core/fatal.c +++ b/arch/sparc/core/fatal.c @@ -122,7 +122,7 @@ static const struct { { .tt = 0x0A, .desc = "tag_overflow", }, }; -static void print_trap_type(const z_arch_esf_t *esf) +static void print_trap_type(const struct arch_esf *esf) { const int tt = (esf->tbr & TBR_TT) >> TBR_TT_BIT; const char *desc = "unknown"; @@ -142,7 +142,7 @@ static void print_trap_type(const z_arch_esf_t *esf) LOG_ERR("tt = 0x%02X, %s", tt, desc); } -static void print_integer_registers(const z_arch_esf_t *esf) +static void print_integer_registers(const struct arch_esf *esf) { const struct savearea *flushed = (struct savearea *) esf->out[6]; @@ -159,7 +159,7 @@ static void print_integer_registers(const z_arch_esf_t *esf) } } -static void print_special_registers(const z_arch_esf_t *esf) +static void print_special_registers(const struct arch_esf *esf) { LOG_ERR( "psr: %08x wim: %08x tbr: %08x y: %08x", @@ -168,7 +168,7 @@ static void print_special_registers(const z_arch_esf_t *esf) LOG_ERR(" pc: %08x npc: %08x", esf->pc, esf->npc); } -static void print_backtrace(const z_arch_esf_t *esf) +static void print_backtrace(const struct arch_esf *esf) { const int MAX_LOGLINES = 40; const struct savearea *s = (struct savearea *) esf->out[6]; @@ -190,7 +190,7 @@ static void print_backtrace(const z_arch_esf_t *esf) } } -static void print_all(const z_arch_esf_t *esf) +static void print_all(const struct arch_esf *esf) { LOG_ERR(""); print_trap_type(esf); @@ -205,7 +205,7 @@ static void print_all(const z_arch_esf_t *esf) #endif /* CONFIG_EXCEPTION_DEBUG */ FUNC_NORETURN void z_sparc_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { #if CONFIG_EXCEPTION_DEBUG if (esf != NULL) { diff --git a/arch/sparc/core/fault_trap.S b/arch/sparc/core/fault_trap.S index c1a8977ba233c..53b3d9f0b98cd 100644 --- a/arch/sparc/core/fault_trap.S +++ b/arch/sparc/core/fault_trap.S @@ -72,7 +72,7 @@ SECTION_FUNC(TEXT, __sparc_trap_except_reason) mov %l5, %g3 /* Allocate an ABI stack frame and exception stack frame */ - sub %fp, 96 + __z_arch_esf_t_SIZEOF, %sp + sub %fp, 96 + __struct_arch_esf_SIZEOF, %sp /* * %fp: %sp of interrupted task * %sp: %sp of interrupted task - ABI_frame - esf @@ -81,19 +81,19 @@ SECTION_FUNC(TEXT, __sparc_trap_except_reason) mov %l7, %o0 /* Fill in the content of the exception stack frame */ #if defined(CONFIG_EXTRA_EXCEPTION_INFO) - std %i0, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x00] - std %i2, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x08] - std %i4, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x10] - std %i6, [%sp + 96 + __z_arch_esf_t_out_OFFSET + 0x18] - std %g0, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x00] - std %g2, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x08] - std %g4, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x10] - std %g6, [%sp + 96 + __z_arch_esf_t_global_OFFSET + 0x18] + std %i0, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x00] + std %i2, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x08] + std %i4, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x10] + std %i6, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x18] + std %g0, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x00] + std %g2, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x08] + std %g4, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x10] + std %g6, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x18] #endif - std %l0, [%sp + 96 + __z_arch_esf_t_psr_OFFSET] /* psr pc */ - std %l2, [%sp + 96 + __z_arch_esf_t_npc_OFFSET] /* npc wim */ + std %l0, [%sp + 96 + __struct_arch_esf_psr_OFFSET] /* psr pc */ + std %l2, [%sp + 96 + __struct_arch_esf_npc_OFFSET] /* npc wim */ rd %y, %l7 - std %l6, [%sp + 96 + __z_arch_esf_t_tbr_OFFSET] /* tbr y */ + std %l6, [%sp + 96 + __struct_arch_esf_tbr_OFFSET] /* tbr y */ /* Enable traps, raise PIL to mask all maskable interrupts. */ or %l0, PSR_PIL, %o2 diff --git a/arch/sparc/core/offsets/offsets.c b/arch/sparc/core/offsets/offsets.c index 3796117ac0945..023ef7452c443 100644 --- a/arch/sparc/core/offsets/offsets.c +++ b/arch/sparc/core/offsets/offsets.c @@ -31,11 +31,11 @@ GEN_OFFSET_SYM(_callee_saved_t, i6); GEN_OFFSET_SYM(_callee_saved_t, o6); /* esf member offsets */ -GEN_OFFSET_SYM(z_arch_esf_t, out); -GEN_OFFSET_SYM(z_arch_esf_t, global); -GEN_OFFSET_SYM(z_arch_esf_t, npc); -GEN_OFFSET_SYM(z_arch_esf_t, psr); -GEN_OFFSET_SYM(z_arch_esf_t, tbr); -GEN_ABSOLUTE_SYM(__z_arch_esf_t_SIZEOF, STACK_ROUND_UP(sizeof(z_arch_esf_t))); +GEN_OFFSET_STRUCT(arch_esf, out); +GEN_OFFSET_STRUCT(arch_esf, global); +GEN_OFFSET_STRUCT(arch_esf, npc); +GEN_OFFSET_STRUCT(arch_esf, psr); +GEN_OFFSET_STRUCT(arch_esf, tbr); +GEN_ABSOLUTE_SYM(__struct_arch_esf_SIZEOF, sizeof(struct arch_esf)); GEN_ABS_SYM_END diff --git a/arch/sparc/include/kernel_arch_func.h b/arch/sparc/include/kernel_arch_func.h index 41f48ccc44a4e..8b79b130ad655 100644 --- a/arch/sparc/include/kernel_arch_func.h +++ b/arch/sparc/include/kernel_arch_func.h @@ -43,7 +43,7 @@ static inline void arch_switch(void *switch_to, void **switched_from) } FUNC_NORETURN void z_sparc_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); static inline bool arch_is_in_isr(void) { diff --git a/arch/sparc/include/offsets_short_arch.h b/arch/sparc/include/offsets_short_arch.h index c53f2b3705bea..0f9272f332b66 100644 --- a/arch/sparc/include/offsets_short_arch.h +++ b/arch/sparc/include/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_SPARC_INCLUDE_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_SPARC_INCLUDE_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_y \ (___thread_t_callee_saved_OFFSET + ___callee_saved_t_y_OFFSET) diff --git a/arch/x86/core/Kconfig.ia32 b/arch/x86/core/Kconfig.ia32 index d789c87eb809a..2e2cf1d0fc27f 100644 --- a/arch/x86/core/Kconfig.ia32 +++ b/arch/x86/core/Kconfig.ia32 @@ -166,7 +166,8 @@ endmenu config X86_EXCEPTION_STACK_TRACE bool default y - depends on EXCEPTION_STACK_TRACE + select DEBUG_INFO + depends on !OMIT_FRAME_POINTER help Internal config to enable runtime stack traces on fatal exceptions. diff --git a/arch/x86/core/Kconfig.intel64 b/arch/x86/core/Kconfig.intel64 index 913bb0e794d5e..a287de6eb09e7 100644 --- a/arch/x86/core/Kconfig.intel64 +++ b/arch/x86/core/Kconfig.intel64 @@ -32,7 +32,8 @@ config X86_EXCEPTION_STACK_SIZE config X86_EXCEPTION_STACK_TRACE bool default y - depends on EXCEPTION_STACK_TRACE + select DEBUG_INFO + depends on !OMIT_FRAME_POINTER depends on NO_OPTIMIZATIONS help Internal config to enable runtime stack traces on fatal exceptions. @@ -88,7 +89,4 @@ config X86_USERSPACE supporting user-level threads that are protected from each other and from crashing the kernel. -config MP_MAX_NUM_CPUS - range 1 4 - endif # X86_64 diff --git a/arch/x86/core/early_serial.c b/arch/x86/core/early_serial.c index 3a0bc7465e1ff..53fb8af7e3ac1 100644 --- a/arch/x86/core/early_serial.c +++ b/arch/x86/core/early_serial.c @@ -25,8 +25,8 @@ * together. */ static mm_reg_t mmio; -#define IN(reg) (sys_read32(mmio + reg * 4) & 0xff) -#define OUT(reg, val) sys_write32((val) & 0xff, mmio + reg * 4) +#define IN(reg) (sys_read32(mmio + (reg) * 4) & 0xff) +#define OUT(reg, val) sys_write32((val) & 0xff, mmio + (reg) * 4) #elif defined(X86_SOC_EARLY_SERIAL_MMIO8_ADDR) /* Still other devices use a MMIO region containing packed byte * registers diff --git a/arch/x86/core/efi.c b/arch/x86/core/efi.c index 425b0dcde86f2..e5470e6d8a364 100644 --- a/arch/x86/core/efi.c +++ b/arch/x86/core/efi.c @@ -33,8 +33,8 @@ void efi_init(struct efi_boot_arg *efi_arg) return; } - z_phys_map((uint8_t **)&efi, (uintptr_t)efi_arg, - sizeof(struct efi_boot_arg), 0); + k_mem_map_phys_bare((uint8_t **)&efi, (uintptr_t)efi_arg, + sizeof(struct efi_boot_arg), 0); } /* EFI thunk. Not a lot of code, but lots of context: diff --git a/arch/x86/core/fatal.c b/arch/x86/core/fatal.c index 370386d4af96b..4eafd999bc784 100644 --- a/arch/x86/core/fatal.c +++ b/arch/x86/core/fatal.c @@ -35,7 +35,7 @@ FUNC_NORETURN void arch_system_halt(unsigned int reason) #ifdef CONFIG_THREAD_STACK_INFO -static inline uintptr_t esf_get_sp(const z_arch_esf_t *esf) +static inline uintptr_t esf_get_sp(const struct arch_esf *esf) { #ifdef CONFIG_X86_64 return esf->rsp; @@ -122,7 +122,7 @@ bool z_x86_check_guard_page(uintptr_t addr) #ifdef CONFIG_EXCEPTION_DEBUG -static inline uintptr_t esf_get_code(const z_arch_esf_t *esf) +static inline uintptr_t esf_get_code(const struct arch_esf *esf) { #ifdef CONFIG_X86_64 return esf->code; @@ -131,7 +131,7 @@ static inline uintptr_t esf_get_code(const z_arch_esf_t *esf) #endif } -#if defined(CONFIG_X86_EXCEPTION_STACK_TRACE) +#if defined(CONFIG_EXCEPTION_STACK_TRACE) struct stack_frame { uintptr_t next; uintptr_t ret_addr; @@ -140,7 +140,7 @@ struct stack_frame { #endif }; -#define MAX_STACK_FRAMES 8 +#define MAX_STACK_FRAMES CONFIG_EXCEPTION_STACK_TRACE_MAX_FRAMES __pinned_func static void unwind_stack(uintptr_t base_ptr, uint16_t cs) @@ -186,9 +186,9 @@ static void unwind_stack(uintptr_t base_ptr, uint16_t cs) base_ptr = frame->next; } } -#endif /* CONFIG_X86_EXCEPTION_STACK_TRACE */ +#endif /* CONFIG_EXCEPTION_STACK_TRACE */ -static inline uintptr_t get_cr3(const z_arch_esf_t *esf) +static inline uintptr_t get_cr3(const struct arch_esf *esf) { #if defined(CONFIG_USERSPACE) && defined(CONFIG_X86_KPTI) /* If the interrupted thread was in user mode, we did a page table @@ -206,14 +206,14 @@ static inline uintptr_t get_cr3(const z_arch_esf_t *esf) return z_x86_cr3_get(); } -static inline pentry_t *get_ptables(const z_arch_esf_t *esf) +static inline pentry_t *get_ptables(const struct arch_esf *esf) { - return z_mem_virt_addr(get_cr3(esf)); + return k_mem_virt_addr(get_cr3(esf)); } #ifdef CONFIG_X86_64 __pinned_func -static void dump_regs(const z_arch_esf_t *esf) +static void dump_regs(const struct arch_esf *esf) { LOG_ERR("RAX: 0x%016lx RBX: 0x%016lx RCX: 0x%016lx RDX: 0x%016lx", esf->rax, esf->rbx, esf->rcx, esf->rdx); @@ -226,17 +226,17 @@ static void dump_regs(const z_arch_esf_t *esf) LOG_ERR("RSP: 0x%016lx RFLAGS: 0x%016lx CS: 0x%04lx CR3: 0x%016lx", esf->rsp, esf->rflags, esf->cs & 0xFFFFU, get_cr3(esf)); -#ifdef CONFIG_X86_EXCEPTION_STACK_TRACE +#ifdef CONFIG_EXCEPTION_STACK_TRACE LOG_ERR("call trace:"); #endif LOG_ERR("RIP: 0x%016lx", esf->rip); -#ifdef CONFIG_X86_EXCEPTION_STACK_TRACE +#ifdef CONFIG_EXCEPTION_STACK_TRACE unwind_stack(esf->rbp, esf->cs); #endif } #else /* 32-bit */ __pinned_func -static void dump_regs(const z_arch_esf_t *esf) +static void dump_regs(const struct arch_esf *esf) { LOG_ERR("EAX: 0x%08x, EBX: 0x%08x, ECX: 0x%08x, EDX: 0x%08x", esf->eax, esf->ebx, esf->ecx, esf->edx); @@ -245,11 +245,11 @@ static void dump_regs(const z_arch_esf_t *esf) LOG_ERR("EFLAGS: 0x%08x CS: 0x%04x CR3: 0x%08lx", esf->eflags, esf->cs & 0xFFFFU, get_cr3(esf)); -#ifdef CONFIG_X86_EXCEPTION_STACK_TRACE +#ifdef CONFIG_EXCEPTION_STACK_TRACE LOG_ERR("call trace:"); #endif LOG_ERR("EIP: 0x%08x", esf->eip); -#ifdef CONFIG_X86_EXCEPTION_STACK_TRACE +#ifdef CONFIG_EXCEPTION_STACK_TRACE unwind_stack(esf->ebp, esf->cs); #endif } @@ -327,7 +327,7 @@ static void log_exception(uintptr_t vector, uintptr_t code) } __pinned_func -static void dump_page_fault(z_arch_esf_t *esf) +static void dump_page_fault(struct arch_esf *esf) { uintptr_t err; void *cr2; @@ -362,7 +362,7 @@ static void dump_page_fault(z_arch_esf_t *esf) __pinned_func FUNC_NORETURN void z_x86_fatal_error(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { if (esf != NULL) { #ifdef CONFIG_EXCEPTION_DEBUG @@ -385,7 +385,7 @@ FUNC_NORETURN void z_x86_fatal_error(unsigned int reason, __pinned_func FUNC_NORETURN void z_x86_unhandled_cpu_exception(uintptr_t vector, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG log_exception(vector, esf_get_code(esf)); @@ -404,7 +404,7 @@ static const struct z_exc_handle exceptions[] = { #endif __pinned_func -void z_x86_page_fault_handler(z_arch_esf_t *esf) +void z_x86_page_fault_handler(struct arch_esf *esf) { #ifdef CONFIG_DEMAND_PAGING if ((esf->errorCode & PF_P) == 0) { @@ -434,7 +434,7 @@ void z_x86_page_fault_handler(z_arch_esf_t *esf) } else #else { - was_valid_access = z_page_fault(virt); + was_valid_access = k_mem_page_fault(virt); } #endif /* CONFIG_X86_KPTI */ if (was_valid_access) { @@ -488,7 +488,7 @@ void z_x86_page_fault_handler(z_arch_esf_t *esf) } __pinned_func -void z_x86_do_kernel_oops(const z_arch_esf_t *esf) +void z_x86_do_kernel_oops(const struct arch_esf *esf) { uintptr_t reason; diff --git a/arch/x86/core/ia32/coredump.c b/arch/x86/core/ia32/coredump.c index b49373aab771e..fb7d0fcfd8cc5 100644 --- a/arch/x86/core/ia32/coredump.c +++ b/arch/x86/core/ia32/coredump.c @@ -34,7 +34,7 @@ struct x86_arch_block { */ static struct x86_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/x86/core/ia32/crt0.S b/arch/x86/core/ia32/crt0.S index 32513a9579037..26500079a02b1 100644 --- a/arch/x86/core/ia32/crt0.S +++ b/arch/x86/core/ia32/crt0.S @@ -60,7 +60,7 @@ * Until we enable these page tables, only physical memory addresses * work. */ - movl $Z_MEM_PHYS_ADDR(z_x86_kernel_ptables), %eax + movl $K_MEM_PHYS_ADDR(z_x86_kernel_ptables), %eax movl %eax, %cr3 #ifdef CONFIG_X86_PAE @@ -89,7 +89,7 @@ orl $(CR0_PG | CR0_WP), %eax movl %eax, %cr0 -#ifdef Z_VM_KERNEL +#ifdef K_MEM_IS_VM_KERNEL /* Jump to a virtual address, which works because the identity and * virtual mappings both are to the same physical address. */ @@ -98,7 +98,7 @@ vm_enter: /* We are now executing in virtual memory. We'll un-map the identity * mappings later once we are in the C domain */ -#endif /* Z_VM_KERNEL */ +#endif /* K_MEM_IS_VM_KERNEL */ #endif /* CONFIG_X86_MMU */ .endm @@ -126,7 +126,7 @@ SECTION_FUNC(BOOT_TEXT, __start) */ #if CONFIG_SET_GDT /* load 32-bit operand size GDT */ - lgdt Z_MEM_PHYS_ADDR(_gdt_rom) + lgdt K_MEM_PHYS_ADDR(_gdt_rom) /* If we set our own GDT, update the segment registers as well. */ @@ -138,7 +138,7 @@ SECTION_FUNC(BOOT_TEXT, __start) movw %ax, %fs /* Zero FS */ movw %ax, %gs /* Zero GS */ - ljmp $CODE_SEG, $Z_MEM_PHYS_ADDR(__csSet) /* set CS = 0x08 */ + ljmp $CODE_SEG, $K_MEM_PHYS_ADDR(__csSet) /* set CS = 0x08 */ __csSet: #endif /* CONFIG_SET_GDT */ @@ -180,7 +180,8 @@ __csSet: andl $~0x400, %eax /* CR4[OSXMMEXCPT] = 0 */ movl %eax, %cr4 /* move EAX to CR4 */ - ldmxcsr Z_MEM_PHYS_ADDR(_sse_mxcsr_default_value) /* initialize SSE control/status reg */ + /* initialize SSE control/status reg */ + ldmxcsr K_MEM_PHYS_ADDR(_sse_mxcsr_default_value) #endif /* CONFIG_X86_SSE */ @@ -199,7 +200,7 @@ __csSet: */ #ifdef CONFIG_INIT_STACKS movl $0xAAAAAAAA, %eax - leal Z_MEM_PHYS_ADDR(z_interrupt_stacks), %edi + leal K_MEM_PHYS_ADDR(z_interrupt_stacks), %edi #ifdef CONFIG_X86_STACK_PROTECTION addl $4096, %edi #endif @@ -208,7 +209,7 @@ __csSet: rep stosl #endif - movl $Z_MEM_PHYS_ADDR(z_interrupt_stacks), %esp + movl $K_MEM_PHYS_ADDR(z_interrupt_stacks), %esp #ifdef CONFIG_X86_STACK_PROTECTION /* In this configuration, all stacks, including IRQ stack, are declared * with a 4K non-present guard page preceding the stack buffer @@ -243,7 +244,7 @@ __csSet: ltr %ax #endif -#ifdef Z_VM_KERNEL +#ifdef K_MEM_IS_VM_KERNEL /* Need to reset the stack to virtual address after * page table is loaded. */ @@ -254,7 +255,7 @@ __csSet: #else addl $CONFIG_ISR_STACK_SIZE, %esp #endif -#endif /* Z_VM_KERNEL */ +#endif /* K_MEM_IS_VM_KERNEL */ #ifdef CONFIG_THREAD_LOCAL_STORAGE pushl %esp @@ -347,9 +348,9 @@ _gdt: * descriptor here */ /* Limit on GDT */ - .word Z_MEM_PHYS_ADDR(_gdt_rom_end) - Z_MEM_PHYS_ADDR(_gdt_rom) - 1 + .word K_MEM_PHYS_ADDR(_gdt_rom_end) - K_MEM_PHYS_ADDR(_gdt_rom) - 1 /* table address: _gdt_rom */ - .long Z_MEM_PHYS_ADDR(_gdt_rom) + .long K_MEM_PHYS_ADDR(_gdt_rom) .word 0x0000 /* Entry 1 (selector=0x0008): Code descriptor: DPL0 */ diff --git a/arch/x86/core/ia32/excstub.S b/arch/x86/core/ia32/excstub.S index 9c5f3f0319152..6c0a13a37cde3 100644 --- a/arch/x86/core/ia32/excstub.S +++ b/arch/x86/core/ia32/excstub.S @@ -161,12 +161,12 @@ SECTION_FUNC(PINNED_TEXT, _exception_enter) /* ESP is still pointing to the ESF at this point */ - testl $0x200, __z_arch_esf_t_eflags_OFFSET(%esp) + testl $0x200, __struct_arch_esf_eflags_OFFSET(%esp) je allDone sti allDone: - pushl %esp /* push z_arch_esf_t * parameter */ + pushl %esp /* push struct_arch_esf * parameter */ call *%ecx /* call exception handler */ addl $0x4, %esp diff --git a/arch/x86/core/ia32/fatal.c b/arch/x86/core/ia32/fatal.c index 597f21a01adc6..3ae8a6b67da3a 100644 --- a/arch/x86/core/ia32/fatal.c +++ b/arch/x86/core/ia32/fatal.c @@ -27,10 +27,10 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); unsigned int z_x86_exception_vector; #endif -__weak void z_debug_fatal_hook(const z_arch_esf_t *esf) { ARG_UNUSED(esf); } +__weak void z_debug_fatal_hook(const struct arch_esf *esf) { ARG_UNUSED(esf); } __pinned_func -void z_x86_spurious_irq(const z_arch_esf_t *esf) +void z_x86_spurious_irq(const struct arch_esf *esf) { int vector = z_irq_controller_isr_vector_get(); @@ -46,7 +46,7 @@ void arch_syscall_oops(void *ssf) { struct _x86_syscall_stack_frame *ssf_ptr = (struct _x86_syscall_stack_frame *)ssf; - z_arch_esf_t oops = { + struct arch_esf oops = { .eip = ssf_ptr->eip, .cs = ssf_ptr->cs, .eflags = ssf_ptr->eflags @@ -66,7 +66,7 @@ NANO_CPU_INT_REGISTER(_kernel_oops_handler, NANO_SOFT_IRQ, #if CONFIG_EXCEPTION_DEBUG __pinned_func FUNC_NORETURN static void generic_exc_handle(unsigned int vector, - const z_arch_esf_t *pEsf) + const struct arch_esf *pEsf) { #ifdef CONFIG_DEBUG_COREDUMP z_x86_exception_vector = vector; @@ -77,7 +77,7 @@ FUNC_NORETURN static void generic_exc_handle(unsigned int vector, #define _EXC_FUNC(vector) \ __pinned_func \ -FUNC_NORETURN __used static void handle_exc_##vector(const z_arch_esf_t *pEsf) \ +FUNC_NORETURN __used static void handle_exc_##vector(const struct arch_esf *pEsf) \ { \ generic_exc_handle(vector, pEsf); \ } @@ -120,7 +120,7 @@ EXC_FUNC_NOCODE(IV_MACHINE_CHECK, 0); _EXCEPTION_CONNECT_CODE(z_x86_page_fault_handler, IV_PAGE_FAULT, 0); #ifdef CONFIG_X86_ENABLE_TSS -static __pinned_noinit volatile z_arch_esf_t _df_esf; +static __pinned_noinit volatile struct arch_esf _df_esf; /* Very tiny stack; just enough for the bogus error code pushed by the CPU * and a frame pointer push by the compiler. All df_handler_top does is @@ -156,7 +156,7 @@ struct task_state_segment _df_tss = { .ss = DATA_SEG, .eip = (uint32_t)df_handler_top, .cr3 = (uint32_t) - Z_MEM_PHYS_ADDR(POINTER_TO_UINT(&z_x86_kernel_ptables[0])) + K_MEM_PHYS_ADDR(POINTER_TO_UINT(&z_x86_kernel_ptables[0])) }; __pinned_func @@ -182,14 +182,14 @@ static __used void df_handler_bottom(void) reason = K_ERR_STACK_CHK_FAIL; } #endif - z_x86_fatal_error(reason, (z_arch_esf_t *)&_df_esf); + z_x86_fatal_error(reason, (struct arch_esf *)&_df_esf); } __pinned_func static FUNC_NORETURN __used void df_handler_top(void) { /* State of the system when the double-fault forced a task switch - * will be in _main_tss. Set up a z_arch_esf_t and copy system state into + * will be in _main_tss. Set up a struct arch_esf and copy system state into * it */ _df_esf.esp = _main_tss.esp; @@ -213,7 +213,7 @@ static FUNC_NORETURN __used void df_handler_top(void) _main_tss.es = DATA_SEG; _main_tss.ss = DATA_SEG; _main_tss.eip = (uint32_t)df_handler_bottom; - _main_tss.cr3 = z_mem_phys_addr(z_x86_kernel_ptables); + _main_tss.cr3 = k_mem_phys_addr(z_x86_kernel_ptables); _main_tss.eflags = 0U; /* NT bit is set in EFLAGS so we will task switch back to _main_tss diff --git a/arch/x86/core/ia32/float.c b/arch/x86/core/ia32/float.c index a33a40a0a7832..c89bf7accd5a1 100644 --- a/arch/x86/core/ia32/float.c +++ b/arch/x86/core/ia32/float.c @@ -302,7 +302,7 @@ int z_float_disable(struct k_thread *thread) * instruction is executed while CR0[TS]=1. The handler then enables the * current thread to use all supported floating point registers. */ -void _FpNotAvailableExcHandler(z_arch_esf_t *pEsf) +void _FpNotAvailableExcHandler(struct arch_esf *pEsf) { ARG_UNUSED(pEsf); diff --git a/arch/x86/core/ia32/gdbstub.c b/arch/x86/core/ia32/gdbstub.c index 692ea78baf41c..252f15d79ffeb 100644 --- a/arch/x86/core/ia32/gdbstub.c +++ b/arch/x86/core/ia32/gdbstub.c @@ -78,7 +78,7 @@ static unsigned int get_exception(unsigned int vector) /* * Debug exception handler. */ -static void z_gdb_interrupt(unsigned int vector, z_arch_esf_t *esf) +static void z_gdb_interrupt(unsigned int vector, struct arch_esf *esf) { debug_ctx.exception = get_exception(vector); @@ -212,7 +212,7 @@ size_t arch_gdb_reg_writeone(struct gdb_ctx *ctx, uint8_t *hex, size_t hexlen, return ret; } -static __used void z_gdb_debug_isr(z_arch_esf_t *esf) +static __used void z_gdb_debug_isr(struct arch_esf *esf) { #ifdef CONFIG_GDBSTUB_TRACE printk("gdbstub:enter %s (IV_DEBUG)\n", __func__); @@ -225,7 +225,7 @@ static __used void z_gdb_debug_isr(z_arch_esf_t *esf) #endif } -static __used void z_gdb_break_isr(z_arch_esf_t *esf) +static __used void z_gdb_break_isr(struct arch_esf *esf) { #ifdef CONFIG_GDBSTUB_TRACE printk("gdbstub:enter %s (IV_BREAKPOINT)\n", __func__); diff --git a/arch/x86/core/ia32/intstub.S b/arch/x86/core/ia32/intstub.S index 0dc08c67c245d..4cd5c0bee9040 100644 --- a/arch/x86/core/ia32/intstub.S +++ b/arch/x86/core/ia32/intstub.S @@ -33,7 +33,7 @@ GTEXT(arch_swap) #ifdef CONFIG_PM - GTEXT(z_pm_save_idle_exit) + GTEXT(pm_system_resume) #endif /** @@ -314,13 +314,13 @@ handle_idle: movl $0, _kernel_offset_to_idle(%ecx) /* - * Beware that a timer driver's z_pm_save_idle_exit() implementation might + * Beware that a timer driver's pm_system_resume() implementation might * expect that interrupts are disabled when invoked. This ensures that * the calculation and programming of the device for the next timer * deadline is not interrupted. */ - call z_pm_save_idle_exit + call pm_system_resume popl %edx popl %eax jmp alreadyOnIntStack diff --git a/arch/x86/core/ia32/userspace.S b/arch/x86/core/ia32/userspace.S index bf21a0cc1a227..a4ad4c69fb875 100644 --- a/arch/x86/core/ia32/userspace.S +++ b/arch/x86/core/ia32/userspace.S @@ -51,7 +51,7 @@ SECTION_FUNC(PINNED_TEXT, z_x86_trampoline_to_kernel) pushl %edi /* Switch to kernel page table */ - movl $Z_MEM_PHYS_ADDR(z_x86_kernel_ptables), %esi + movl $K_MEM_PHYS_ADDR(z_x86_kernel_ptables), %esi movl %esi, %cr3 /* Save old trampoline stack pointer in %edi */ @@ -156,7 +156,7 @@ SECTION_FUNC(TEXT, z_x86_syscall_entry_stub) pushl %edi /* Switch to kernel page table */ - movl $Z_MEM_PHYS_ADDR(z_x86_kernel_ptables), %esi + movl $K_MEM_PHYS_ADDR(z_x86_kernel_ptables), %esi movl %esi, %cr3 /* Save old trampoline stack pointer in %edi */ diff --git a/arch/x86/core/intel64/coredump.c b/arch/x86/core/intel64/coredump.c index f1c1a15eaff37..65a9306ca07da 100644 --- a/arch/x86/core/intel64/coredump.c +++ b/arch/x86/core/intel64/coredump.c @@ -46,7 +46,7 @@ struct x86_64_arch_block { */ static struct x86_64_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/x86/core/intel64/cpu.c b/arch/x86/core/intel64/cpu.c index d1aedcd4deca6..8d68afa2a1913 100644 --- a/arch/x86/core/intel64/cpu.c +++ b/arch/x86/core/intel64/cpu.c @@ -3,7 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include +#include #include #include #include @@ -12,125 +14,32 @@ #include #include #ifdef CONFIG_ACPI +#include #include #endif -BUILD_ASSERT(CONFIG_MP_MAX_NUM_CPUS <= 4, "Only supports max 4 CPUs"); - /* * Map of CPU logical IDs to CPU local APIC IDs. By default, * we assume this simple identity mapping, as found in QEMU. * The symbol is weak so that boards/SoC files can override. */ -__weak uint8_t x86_cpu_loapics[] = { 0, 1, 2, 3 }; - -extern char x86_ap_start[]; /* AP entry point in locore.S */ - -extern uint8_t z_x86_exception_stack[]; -extern uint8_t z_x86_exception_stack1[]; -extern uint8_t z_x86_exception_stack2[]; -extern uint8_t z_x86_exception_stack3[]; - -extern uint8_t z_x86_nmi_stack[]; -extern uint8_t z_x86_nmi_stack1[]; -extern uint8_t z_x86_nmi_stack2[]; -extern uint8_t z_x86_nmi_stack3[]; - -#ifdef CONFIG_X86_KPTI -extern uint8_t z_x86_trampoline_stack[]; -extern uint8_t z_x86_trampoline_stack1[]; -extern uint8_t z_x86_trampoline_stack2[]; -extern uint8_t z_x86_trampoline_stack3[]; -#endif /* CONFIG_X86_KPTI */ - -Z_GENERIC_SECTION(.tss) -struct x86_tss64 tss0 = { -#ifdef CONFIG_X86_KPTI - .ist2 = (uint64_t) z_x86_trampoline_stack + Z_X86_TRAMPOLINE_STACK_SIZE, -#endif - .ist6 = (uint64_t) z_x86_nmi_stack + CONFIG_X86_EXCEPTION_STACK_SIZE, - .ist7 = (uint64_t) z_x86_exception_stack + CONFIG_X86_EXCEPTION_STACK_SIZE, - .iomapb = 0xFFFF, - .cpu = &(_kernel.cpus[0]) -}; - -#if CONFIG_MP_MAX_NUM_CPUS > 1 -Z_GENERIC_SECTION(.tss) -struct x86_tss64 tss1 = { -#ifdef CONFIG_X86_KPTI - .ist2 = (uint64_t) z_x86_trampoline_stack1 + Z_X86_TRAMPOLINE_STACK_SIZE, -#endif - .ist6 = (uint64_t) z_x86_nmi_stack1 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .ist7 = (uint64_t) z_x86_exception_stack1 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .iomapb = 0xFFFF, - .cpu = &(_kernel.cpus[1]) -}; -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 2 -Z_GENERIC_SECTION(.tss) -struct x86_tss64 tss2 = { -#ifdef CONFIG_X86_KPTI - .ist2 = (uint64_t) z_x86_trampoline_stack2 + Z_X86_TRAMPOLINE_STACK_SIZE, -#endif - .ist6 = (uint64_t) z_x86_nmi_stack2 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .ist7 = (uint64_t) z_x86_exception_stack2 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .iomapb = 0xFFFF, - .cpu = &(_kernel.cpus[2]) -}; -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 3 -Z_GENERIC_SECTION(.tss) -struct x86_tss64 tss3 = { -#ifdef CONFIG_X86_KPTI - .ist2 = (uint64_t) z_x86_trampoline_stack3 + Z_X86_TRAMPOLINE_STACK_SIZE, -#endif - .ist6 = (uint64_t) z_x86_nmi_stack3 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .ist7 = (uint64_t) z_x86_exception_stack3 + CONFIG_X86_EXCEPTION_STACK_SIZE, - .iomapb = 0xFFFF, - .cpu = &(_kernel.cpus[3]) -}; +#if defined(CONFIG_ACPI) +__weak uint8_t x86_cpu_loapics[CONFIG_MP_MAX_NUM_CPUS]; +#else +#define INIT_CPUID(n, _) n +__weak uint8_t x86_cpu_loapics[] = { + LISTIFY(CONFIG_MP_MAX_NUM_CPUS, INIT_CPUID, (,)),}; #endif +extern char x86_ap_start[]; /* AP entry point in locore.S */ +LISTIFY(CONFIG_MP_MAX_NUM_CPUS, ACPI_CPU_INIT, (;)); -/* We must put this in a dedicated section, or else it will land into .bss: - * in this case, though locore.S initalizes it relevantly, all will be - * lost when calling z_bss_zero() in z_x86_cpu_init prior to using it. - */ Z_GENERIC_SECTION(.boot_arg) x86_boot_arg_t x86_cpu_boot_arg; struct x86_cpuboot x86_cpuboot[] = { - { - .tr = X86_KERNEL_CPU0_TR, - .gs_base = &tss0, - .sp = (uint64_t) z_interrupt_stacks[0] + - K_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE), - .stack_size = - K_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE), - .fn = z_prep_c, - .arg = &x86_cpu_boot_arg, - }, -#if CONFIG_MP_MAX_NUM_CPUS > 1 - { - .tr = X86_KERNEL_CPU1_TR, - .gs_base = &tss1 - }, -#endif -#if CONFIG_MP_MAX_NUM_CPUS > 2 - { - .tr = X86_KERNEL_CPU2_TR, - .gs_base = &tss2 - }, -#endif -#if CONFIG_MP_MAX_NUM_CPUS > 3 - { - .tr = X86_KERNEL_CPU3_TR, - .gs_base = &tss3 - }, -#endif + LISTIFY(CONFIG_MP_MAX_NUM_CPUS, X86_CPU_BOOT_INIT, (,)), }; /* @@ -151,6 +60,12 @@ void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz, if (lapic != NULL) { /* We update the apic_id, __start will need it. */ x86_cpu_loapics[cpu_num] = lapic->Id; + } else { + /* TODO: kernel need to handle the error scenario if someone config + * CONFIG_MP_MAX_NUM_CPUS more than what platform supported. + */ + __ASSERT(false, "CPU reached more than maximum supported!"); + return; } })); @@ -160,6 +75,7 @@ void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz, x86_cpuboot[cpu_num].stack_size = sz; x86_cpuboot[cpu_num].fn = fn; x86_cpuboot[cpu_num].arg = arg; + x86_cpuboot[cpu_num].cpu_id = cpu_num; z_loapic_ipi(apic_id, LOAPIC_ICR_IPI_INIT, 0); k_busy_wait(10000); @@ -181,18 +97,19 @@ void arch_cpu_start(int cpu_num, k_thread_stack_t *stack, int sz, */ FUNC_NORETURN void z_x86_cpu_init(struct x86_cpuboot *cpuboot) { +#if defined(CONFIG_ACPI) + __ASSERT(z_x86_cpuid_get_current_physical_apic_id() == + x86_cpu_loapics[cpuboot->cpu_id], "APIC ID miss match!"); +#endif x86_sse_init(NULL); - /* The internal cpu_number is the index to x86_cpuboot[] */ - unsigned char cpu_num = (unsigned char)(cpuboot - x86_cpuboot); - - if (cpu_num == 0U) { + if (cpuboot->cpu_id == 0U) { /* Only need to do these once per boot */ z_bss_zero(); z_data_copy(); } - z_loapic_enable(cpu_num); + z_loapic_enable(cpuboot->cpu_id); #ifdef CONFIG_USERSPACE /* Set landing site for 'syscall' instruction */ diff --git a/arch/x86/core/intel64/fatal.c b/arch/x86/core/intel64/fatal.c index 9dd97614dc1e3..9eed95bfaa3ad 100644 --- a/arch/x86/core/intel64/fatal.c +++ b/arch/x86/core/intel64/fatal.c @@ -13,14 +13,14 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); /* NMI handlers should override weak implementation * return true if NMI is handled, false otherwise */ -__weak bool z_x86_do_kernel_nmi(const z_arch_esf_t *esf) +__weak bool z_x86_do_kernel_nmi(const struct arch_esf *esf) { ARG_UNUSED(esf); return false; } -void z_x86_exception(z_arch_esf_t *esf) +void z_x86_exception(struct arch_esf *esf) { switch (esf->vector) { case Z_X86_OOPS_VECTOR: diff --git a/arch/x86/core/intel64/irq_offload.c b/arch/x86/core/intel64/irq_offload.c index 0146321f7d9d9..c2771d735cfc2 100644 --- a/arch/x86/core/intel64/irq_offload.c +++ b/arch/x86/core/intel64/irq_offload.c @@ -9,6 +9,7 @@ */ #include +#include #include #include @@ -17,12 +18,37 @@ extern void (*x86_irq_funcs[NR_IRQ_VECTORS])(const void *arg); extern const void *x86_irq_args[NR_IRQ_VECTORS]; +static void (*irq_offload_funcs[CONFIG_MP_NUM_CPUS])(const void *arg); +static const void *irq_offload_args[CONFIG_MP_NUM_CPUS]; + +static void dispatcher(const void *arg) +{ + uint8_t cpu_id = _current_cpu->id; + + if (irq_offload_funcs[cpu_id] != NULL) { + irq_offload_funcs[cpu_id](irq_offload_args[cpu_id]); + } +} void arch_irq_offload(irq_offload_routine_t routine, const void *parameter) { - x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = routine; - x86_irq_args[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = parameter; + int key = arch_irq_lock(); + uint8_t cpu_id = _current_cpu->id; + + irq_offload_funcs[cpu_id] = routine; + irq_offload_args[cpu_id] = parameter; + __asm__ volatile("int %0" : : "i" (CONFIG_IRQ_OFFLOAD_VECTOR) : "memory"); - x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = NULL; + + arch_irq_unlock(key); +} + +int irq_offload_init(void) +{ + x86_irq_funcs[CONFIG_IRQ_OFFLOAD_VECTOR - IV_IRQS] = dispatcher; + + return 0; } + +SYS_INIT(irq_offload_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/arch/x86/core/intel64/locore.S b/arch/x86/core/intel64/locore.S index d68e80c423f4d..108d9f15d378f 100644 --- a/arch/x86/core/intel64/locore.S +++ b/arch/x86/core/intel64/locore.S @@ -44,7 +44,7 @@ /* Page tables created at build time by gen_mmu.py * NOTE: Presumes phys=virt */ - movl $Z_MEM_PHYS_ADDR(z_x86_kernel_ptables), %eax + movl $K_MEM_PHYS_ADDR(z_x86_kernel_ptables), %eax movl %eax, %cr3 set_efer @@ -66,7 +66,7 @@ clts /* NOTE: Presumes phys=virt */ - movq $Z_MEM_PHYS_ADDR(z_x86_kernel_ptables), %rax + movq $K_MEM_PHYS_ADDR(z_x86_kernel_ptables), %rax movq %rax, %cr3 set_efer @@ -80,6 +80,15 @@ movq %rax, %cr0 .endm +.macro DEFINE_TSS_STACK_ARRAY + .irp idx, DEFINE_STACK_ARRAY_IDX + .word __X86_TSS64_SIZEOF-1 + .word tss\idx + .word 0x8900 + .word 0, 0, 0, 0, 0 + .endr +.endm + /* The .locore section begins the page-aligned initialization region * of low memory. The first address is used as the architectural * entry point for auxiliary CPUs being brought up (in real mode!) @@ -113,17 +122,13 @@ __start: nop nop -#if CONFIG_MP_MAX_NUM_CPUS > 1 - .code16 .global x86_ap_start x86_ap_start: - /* * First, we move to 32-bit protected mode, and set up the * same flat environment that the BSP gets from the loader. */ - lgdt gdt48 lidt idt48 movl %cr0, %eax @@ -145,7 +150,7 @@ x86_ap_start: movl LOAPIC_BASE_ADDRESS+LOAPIC_ID, %eax shrl $24, %eax - andl $0x0F, %eax /* local APIC ID -> EAX */ + andl $0xFF, %eax /* local APIC ID -> EAX */ movl $x86_cpuboot, %ebp xorl %ebx, %ebx @@ -160,8 +165,6 @@ x86_ap_start: unknown_loapic_id: jmp unknown_loapic_id -#endif /* CONFIG_MP_MAX_NUM_CPUS > 1 */ - .code32 .globl __start32 __start32: @@ -1094,31 +1097,7 @@ gdt: /* Remaining entries are TSS for each enabled CPU */ - .word __X86_TSS64_SIZEOF-1 /* 0x40: 64-bit TSS (16-byte entry) */ - .word tss0 - .word 0x8900 - .word 0, 0, 0, 0, 0 - -#if CONFIG_MP_MAX_NUM_CPUS > 1 - .word __X86_TSS64_SIZEOF-1 /* 0x50: 64-bit TSS (16-byte entry) */ - .word tss1 - .word 0x8900 - .word 0, 0, 0, 0, 0 -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 2 - .word __X86_TSS64_SIZEOF-1 /* 0x60: 64-bit TSS (16-byte entry) */ - .word tss2 - .word 0x8900 - .word 0, 0, 0, 0, 0 -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 3 - .word __X86_TSS64_SIZEOF-1 /* 0x70: 64-bit TSS (16-byte entry) */ - .word tss3 - .word 0x8900 - .word 0, 0, 0, 0, 0 -#endif + DEFINE_TSS_STACK_ARRAY gdt_end: @@ -1129,80 +1108,3 @@ gdt48: /* LGDT descriptor for 32 bit mode */ gdt80: /* LGDT descriptor for long mode */ .word (gdt_end - gdt - 1) .quad gdt -.section .lodata,"ad" - -/* - * Known-good stack for handling CPU exceptions. - */ - -.global z_x86_exception_stack -.align 16 -z_x86_exception_stack: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -.global z_x86_nmi_stack -.align 16 -z_x86_nmi_stack: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA - -#if CONFIG_MP_MAX_NUM_CPUS > 1 -.global z_x86_exception_stack1 -.align 16 -z_x86_exception_stack1: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -.global z_x86_nmi_stack1 -.align 16 -z_x86_nmi_stack1: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 2 -.global z_x86_exception_stack2 -.align 16 -z_x86_exception_stack2: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -.global z_x86_nmi_stack2 -.align 16 -z_x86_nmi_stack2: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 3 -.global z_x86_exception_stack3 -.align 16 -z_x86_exception_stack3: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -.global z_x86_nmi_stack3 -.align 16 -z_x86_nmi_stack3: - .fill CONFIG_X86_EXCEPTION_STACK_SIZE, 1, 0xAA -#endif - -#ifdef CONFIG_X86_KPTI -.section .trampolines,"ad" - -.global z_x86_trampoline_stack -.align 16 -z_x86_trampoline_stack: - .fill Z_X86_TRAMPOLINE_STACK_SIZE, 1, 0xAA - -#if CONFIG_MP_MAX_NUM_CPUS > 1 -.global z_x86_trampoline_stack1 -.align 16 -z_x86_trampoline_stack1: - .fill Z_X86_TRAMPOLINE_STACK_SIZE, 1, 0xAA -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 2 -.global z_x86_trampoline_stack2 -.align 16 -z_x86_trampoline_stack2: - .fill Z_X86_TRAMPOLINE_STACK_SIZE, 1, 0xAA -#endif - -#if CONFIG_MP_MAX_NUM_CPUS > 3 -.global z_x86_trampoline_stack3 -.align 16 -z_x86_trampoline_stack3: - .fill Z_X86_TRAMPOLINE_STACK_SIZE, 1, 0xAA -#endif -#endif /* CONFIG_X86_KPTI */ diff --git a/arch/x86/core/intel64/smp.c b/arch/x86/core/intel64/smp.c index a73ba9c8f38c3..1e0aeb3e443aa 100644 --- a/arch/x86/core/intel64/smp.c +++ b/arch/x86/core/intel64/smp.c @@ -34,9 +34,7 @@ int arch_smp_init(void) * it is not clear exactly how/where/why to abstract this, as it * assumes the use of a local APIC (but there's no other mechanism). */ -void arch_sched_ipi(void) +void arch_sched_broadcast_ipi(void) { z_loapic_ipi(0, LOAPIC_ICR_IPI_OTHERS, CONFIG_SCHED_IPI_VECTOR); } - -SYS_INIT(arch_smp_init, PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT); diff --git a/arch/x86/core/intel64/userspace.S b/arch/x86/core/intel64/userspace.S index ab09381c7af9c..d3610c300cb9f 100644 --- a/arch/x86/core/intel64/userspace.S +++ b/arch/x86/core/intel64/userspace.S @@ -87,7 +87,7 @@ z_x86_syscall_entry_stub: pushq %rax /* NOTE: Presumes phys=virt */ - movq $Z_MEM_PHYS_ADDR(z_x86_kernel_ptables), %rax + movq $K_MEM_PHYS_ADDR(z_x86_kernel_ptables), %rax movq %rax, %cr3 popq %rax movq $0, -8(%rsp) /* Delete stashed RAX data */ diff --git a/arch/x86/core/legacy_bios.c b/arch/x86/core/legacy_bios.c index 6a7159a9b1c13..6245a6175c58d 100644 --- a/arch/x86/core/legacy_bios.c +++ b/arch/x86/core/legacy_bios.c @@ -17,18 +17,18 @@ static uintptr_t bios_search_rsdp_buff(uintptr_t search_phy_add, uint32_t search { uint64_t *search_buff; - z_phys_map((uint8_t **)&search_buff, search_phy_add, search_length, 0); + k_mem_map_phys_bare((uint8_t **)&search_buff, search_phy_add, search_length, 0); if (!search_buff) { return 0; } for (int i = 0; i < search_length / 8u; i++) { if (search_buff[i] == RSDP_SIGNATURE) { - z_phys_unmap((uint8_t *)search_buff, search_length); + k_mem_unmap_phys_bare((uint8_t *)search_buff, search_length); return (search_phy_add + (i * 8u)); } } - z_phys_unmap((uint8_t *)search_buff, search_length); + k_mem_unmap_phys_bare((uint8_t *)search_buff, search_length); return 0; } @@ -38,10 +38,10 @@ void *bios_acpi_rsdp_get(void) uint8_t *bios_ext_data, *zero_page_base; uintptr_t search_phy_add, rsdp_phy_add; - z_phys_map(&zero_page_base, 0, DATA_SIZE_K(4u), 0); + k_mem_map_phys_bare(&zero_page_base, 0, DATA_SIZE_K(4u), 0); bios_ext_data = EBDA_ADD + zero_page_base; search_phy_add = (uintptr_t)((*(uint16_t *)bios_ext_data) << 4u); - z_phys_unmap(zero_page_base, DATA_SIZE_K(4u)); + k_mem_unmap_phys_bare(zero_page_base, DATA_SIZE_K(4u)); if ((search_phy_add >= BIOS_EXT_DATA_LOW) && (search_phy_add < BIOS_EXT_DATA_HIGH)) { rsdp_phy_add = bios_search_rsdp_buff(search_phy_add, DATA_SIZE_K(1u)); diff --git a/arch/x86/core/multiboot.c b/arch/x86/core/multiboot.c index 2dab56128d111..06d03c7b80714 100644 --- a/arch/x86/core/multiboot.c +++ b/arch/x86/core/multiboot.c @@ -41,8 +41,8 @@ void z_multiboot_init(struct multiboot_info *info_pa) */ info = info_pa; #else - z_phys_map((uint8_t **)&info, POINTER_TO_UINT(info_pa), - sizeof(*info_pa), K_MEM_CACHE_NONE); + k_mem_map_phys_bare((uint8_t **)&info, POINTER_TO_UINT(info_pa), + sizeof(*info_pa), K_MEM_CACHE_NONE); #endif /* CONFIG_ARCH_MAPS_ALL_RAM */ if (info == NULL) { @@ -70,8 +70,8 @@ void z_multiboot_init(struct multiboot_info *info_pa) #else uint8_t *address_va; - z_phys_map(&address_va, info->mmap_addr, info->mmap_length, - K_MEM_CACHE_NONE); + k_mem_map_phys_bare(&address_va, info->mmap_addr, info->mmap_length, + K_MEM_CACHE_NONE); address = POINTER_TO_UINT(address_va); #endif /* CONFIG_ARCH_MAPS_ALL_RAM */ diff --git a/arch/x86/core/offsets/ia32_offsets.c b/arch/x86/core/offsets/ia32_offsets.c index 61a7f25bb2a40..2dfbb5c38ef28 100644 --- a/arch/x86/core/offsets/ia32_offsets.c +++ b/arch/x86/core/offsets/ia32_offsets.c @@ -52,7 +52,6 @@ GEN_ABSOLUTE_SYM(_K_THREAD_NO_FLOAT_SIZEOF, GEN_OFFSET_SYM(_callee_saved_t, esp); -/* z_arch_esf_t structure member offsets */ - -GEN_OFFSET_SYM(z_arch_esf_t, eflags); +/* struct arch_esf structure member offsets */ +GEN_OFFSET_STRUCT(arch_esf, eflags); #endif /* _X86_OFFSETS_INC_ */ diff --git a/arch/x86/core/prep_c.c b/arch/x86/core/prep_c.c index d9b62b0b7115d..4ff5ffcdc7eb8 100644 --- a/arch/x86/core/prep_c.c +++ b/arch/x86/core/prep_c.c @@ -73,10 +73,6 @@ FUNC_NORETURN void z_prep_c(void *arg) } #endif -#if defined(CONFIG_SMP) - arch_smp_init(); -#endif - z_cstart(); CODE_UNREACHABLE; } diff --git a/arch/x86/core/x86_mmu.c b/arch/x86/core/x86_mmu.c index 5540cebce7061..566dd2cdfd40e 100644 --- a/arch/x86/core/x86_mmu.c +++ b/arch/x86/core/x86_mmu.c @@ -313,7 +313,7 @@ static inline uintptr_t get_entry_phys(pentry_t entry, int level) __pinned_func static inline pentry_t *next_table(pentry_t entry, int level) { - return z_mem_virt_addr(get_entry_phys(entry, level)); + return k_mem_virt_addr(get_entry_phys(entry, level)); } /* Number of table entries at this level */ @@ -416,12 +416,12 @@ void z_x86_tlb_ipi(const void *arg) * if KPTI is turned on */ ptables_phys = z_x86_cr3_get(); - __ASSERT(ptables_phys == z_mem_phys_addr(&z_x86_kernel_ptables), ""); + __ASSERT(ptables_phys == k_mem_phys_addr(&z_x86_kernel_ptables), ""); #else /* We might have been moved to another memory domain, so always invoke * z_x86_thread_page_tables_get() instead of using current CR3 value. */ - ptables_phys = z_mem_phys_addr(z_x86_thread_page_tables_get(_current)); + ptables_phys = k_mem_phys_addr(z_x86_thread_page_tables_get(_current)); #endif /* * In the future, we can consider making this smarter, such as @@ -593,7 +593,7 @@ static void print_entries(pentry_t entries_array[], uint8_t *base, int level, if (phys == virt) { /* Identity mappings */ COLOR(YELLOW); - } else if (phys + Z_MEM_VM_OFFSET == virt) { + } else if (phys + K_MEM_VIRT_OFFSET == virt) { /* Permanent RAM mappings */ COLOR(GREEN); } else { @@ -661,7 +661,7 @@ static void dump_ptables(pentry_t *table, uint8_t *base, int level) #endif printk("%s at %p (0x%" PRIxPTR "): ", info->name, table, - z_mem_phys_addr(table)); + k_mem_phys_addr(table)); if (level == 0) { printk("entire address space\n"); } else { @@ -826,7 +826,7 @@ static inline pentry_t pte_finalize_value(pentry_t val, bool user_table, { #ifdef CONFIG_X86_KPTI static const uintptr_t shared_phys_addr = - Z_MEM_PHYS_ADDR(POINTER_TO_UINT(&z_shared_kernel_page_start)); + K_MEM_PHYS_ADDR(POINTER_TO_UINT(&z_shared_kernel_page_start)); if (user_table && (val & MMU_US) == 0 && (val & MMU_P) != 0 && get_entry_phys(val, level) != shared_phys_addr) { @@ -848,7 +848,7 @@ static inline pentry_t pte_finalize_value(pentry_t val, bool user_table, __pinned_func static inline pentry_t atomic_pte_get(const pentry_t *target) { - return (pentry_t)atomic_ptr_get((atomic_ptr_t *)target); + return (pentry_t)atomic_ptr_get((const atomic_ptr_t *)target); } __pinned_func @@ -1169,8 +1169,8 @@ static int range_map(void *virt, uintptr_t phys, size_t size, { int ret = 0, ret2; - LOG_DBG("%s: %p -> %p (%zu) flags " PRI_ENTRY " mask " - PRI_ENTRY " opt 0x%x", __func__, (void *)phys, virt, size, + LOG_DBG("%s: 0x%" PRIxPTR " -> %p (%zu) flags " PRI_ENTRY " mask " + PRI_ENTRY " opt 0x%x", __func__, phys, virt, size, entry_flags, mask, options); #ifdef CONFIG_X86_64 @@ -1301,13 +1301,13 @@ void arch_mem_unmap(void *addr, size_t size) { int ret; - ret = range_map_unlocked((void *)addr, 0, size, 0, 0, + ret = range_map_unlocked(addr, 0, size, 0, 0, OPTION_FLUSH | OPTION_CLEAR); __ASSERT_NO_MSG(ret == 0); ARG_UNUSED(ret); } -#ifdef Z_VM_KERNEL +#ifdef K_MEM_IS_VM_KERNEL __boot_func static void identity_map_remove(uint32_t level) { @@ -1346,7 +1346,7 @@ static void identity_map_remove(uint32_t level) __boot_func void z_x86_mmu_init(void) { -#ifdef Z_VM_KERNEL +#ifdef K_MEM_IS_VM_KERNEL /* We booted with physical address space being identity mapped. * As we are now executing in virtual address space, * the identity map is no longer needed. So remove them. @@ -1387,7 +1387,7 @@ void z_x86_set_stack_guard(k_thread_stack_t *stack) __pinned_func static bool page_validate(pentry_t *ptables, uint8_t *addr, bool write) { - pentry_t *table = (pentry_t *)ptables; + pentry_t *table = ptables; for (int level = 0; level < NUM_LEVELS; level++) { pentry_t entry = get_entry(table, addr, level); @@ -1432,7 +1432,7 @@ static inline void bcb_fence(void) } __pinned_func -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { pentry_t *ptables = z_x86_thread_page_tables_get(_current); uint8_t *virt; @@ -1720,7 +1720,7 @@ static int copy_page_table(pentry_t *dst, pentry_t *src, int level) * cast needed for PAE case where sizeof(void *) and * sizeof(pentry_t) are not the same. */ - dst[i] = ((pentry_t)z_mem_phys_addr(child_dst) | + dst[i] = ((pentry_t)k_mem_phys_addr(child_dst) | INT_FLAGS); ret = copy_page_table(child_dst, @@ -1781,8 +1781,8 @@ static inline int apply_region(pentry_t *ptables, void *start, __pinned_func static void set_stack_perms(struct k_thread *thread, pentry_t *ptables) { - LOG_DBG("update stack for thread %p's ptables at %p: %p (size %zu)", - thread, ptables, (void *)thread->stack_info.start, + LOG_DBG("update stack for thread %p's ptables at %p: 0x%" PRIxPTR " (size %zu)", + thread, ptables, thread->stack_info.start, thread->stack_info.size); apply_region(ptables, (void *)thread->stack_info.start, thread->stack_info.size, @@ -1924,13 +1924,13 @@ int arch_mem_domain_thread_add(struct k_thread *thread) * z_x86_current_stack_perms() */ if (is_migration) { - old_ptables = z_mem_virt_addr(thread->arch.ptables); + old_ptables = k_mem_virt_addr(thread->arch.ptables); set_stack_perms(thread, domain->arch.ptables); } - thread->arch.ptables = z_mem_phys_addr(domain->arch.ptables); - LOG_DBG("set thread %p page tables to %p", thread, - (void *)thread->arch.ptables); + thread->arch.ptables = k_mem_phys_addr(domain->arch.ptables); + LOG_DBG("set thread %p page tables to 0x%" PRIxPTR, thread, + thread->arch.ptables); /* Check if we're doing a migration from a different memory domain * and have to remove permissions from its old domain. @@ -2004,13 +2004,12 @@ static void mark_addr_page_reserved(uintptr_t addr, size_t len) uintptr_t end = ROUND_UP(addr + len, CONFIG_MMU_PAGE_SIZE); for (; pos < end; pos += CONFIG_MMU_PAGE_SIZE) { - if (!z_is_page_frame(pos)) { + if (!k_mem_is_page_frame(pos)) { continue; } - struct z_page_frame *pf = z_phys_to_page_frame(pos); - - pf->flags |= Z_PAGE_FRAME_RESERVED; + k_mem_page_frame_set(k_mem_phys_to_page_frame(pos), + K_MEM_PAGE_FRAME_RESERVED); } } @@ -2114,7 +2113,7 @@ void arch_mem_page_in(void *addr, uintptr_t phys) __pinned_func void arch_mem_scratch(uintptr_t phys) { - page_map_set(z_x86_page_tables_get(), Z_SCRATCH_PAGE, + page_map_set(z_x86_page_tables_get(), K_MEM_SCRATCH_PAGE, phys | MMU_P | MMU_RW | MMU_XD, NULL, MASK_ALL, OPTION_FLUSH); } @@ -2232,7 +2231,7 @@ bool z_x86_kpti_is_access_ok(void *addr, pentry_t *ptables) /* Might as well also check if it's un-mapped, normally we don't * fetch the PTE from the page tables until we are inside - * z_page_fault() and call arch_page_fault_status_get() + * k_mem_page_fault() and call arch_page_fault_status_get() */ if (level != PTE_LEVEL || pte == 0 || is_flipped_pte(pte)) { return false; diff --git a/arch/x86/include/ia32/exception.h b/arch/x86/include/ia32/exception.h index 27119709c2ade..1b0ce9ee3b52d 100644 --- a/arch/x86/include/ia32/exception.h +++ b/arch/x86/include/ia32/exception.h @@ -62,7 +62,7 @@ * Assign an exception handler to a particular vector in the IDT. * * @param handler A handler function of the prototype - * void handler(const z_arch_esf_t *esf) + * void handler(const struct arch_esf *esf) * @param vector Vector index in the IDT */ #define _EXCEPTION_CONNECT_NOCODE(handler, vector, dpl) \ @@ -75,7 +75,7 @@ * The error code will be accessible in esf->errorCode * * @param handler A handler function of the prototype - * void handler(const z_arch_esf_t *esf) + * void handler(const struct arch_esf *esf) * @param vector Vector index in the IDT */ #define _EXCEPTION_CONNECT_CODE(handler, vector, dpl) \ diff --git a/arch/x86/include/ia32/offsets_short_arch.h b/arch/x86/include/ia32/offsets_short_arch.h index 2033a5585f711..cb5cdb218f0ae 100644 --- a/arch/x86/include/ia32/offsets_short_arch.h +++ b/arch/x86/include/ia32/offsets_short_arch.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_ARCH_X86_INCLUDE_IA32_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_X86_INCLUDE_IA32_OFFSETS_SHORT_ARCH_H_ -#include +#include /* kernel */ diff --git a/arch/x86/include/intel64/kernel_arch_data.h b/arch/x86/include/intel64/kernel_arch_data.h index 6cbf18a831d87..af3b0d1c8165e 100644 --- a/arch/x86/include/intel64/kernel_arch_data.h +++ b/arch/x86/include/intel64/kernel_arch_data.h @@ -26,6 +26,7 @@ struct x86_cpuboot { size_t stack_size; /* size of stack */ arch_cpustart_t fn; /* kernel entry function */ void *arg; /* argument for above function */ + uint8_t cpu_id; /* CPU ID */ }; typedef struct x86_cpuboot x86_cpuboot_t; @@ -38,4 +39,44 @@ extern uint8_t x86_cpu_loapics[]; /* CPU logical ID -> local APIC ID */ #define Z_X86_TRAMPOLINE_STACK_SIZE 128 #endif +#ifdef CONFIG_X86_KPTI +#define TRAMPOLINE_STACK(n) \ + uint8_t z_x86_trampoline_stack##n[Z_X86_TRAMPOLINE_STACK_SIZE] \ + __attribute__ ((section(".trampolines"))); + +#define TRAMPOLINE_INIT(n) \ + .ist2 = (uint64_t)z_x86_trampoline_stack##n + Z_X86_TRAMPOLINE_STACK_SIZE, +#else +#define TRAMPOLINE_STACK(n) +#define TRAMPOLINE_INIT(n) +#endif /* CONFIG_X86_KPTI */ + +#define ACPI_CPU_INIT(n, _) \ + uint8_t z_x86_exception_stack##n[CONFIG_X86_EXCEPTION_STACK_SIZE] __aligned(16); \ + uint8_t z_x86_nmi_stack##n[CONFIG_X86_EXCEPTION_STACK_SIZE] __aligned(16); \ + TRAMPOLINE_STACK(n); \ + Z_GENERIC_SECTION(.tss) \ + struct x86_tss64 tss##n = { \ + TRAMPOLINE_INIT(n) \ + .ist6 = (uint64_t)z_x86_nmi_stack##n + CONFIG_X86_EXCEPTION_STACK_SIZE, \ + .ist7 = (uint64_t)z_x86_exception_stack##n + CONFIG_X86_EXCEPTION_STACK_SIZE, \ + .iomapb = 0xFFFF, .cpu = &(_kernel.cpus[n]) \ + } + +#define X86_CPU_BOOT_INIT(n, _) \ + { \ + .tr = (0x40 + (16 * n)), \ + .gs_base = &tss##n, \ + .sp = (uint64_t)z_interrupt_stacks[n] + \ + K_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE), \ + .stack_size = K_KERNEL_STACK_LEN(CONFIG_ISR_STACK_SIZE), \ + .fn = z_prep_c, \ + .arg = &x86_cpu_boot_arg, \ + } + +#define STACK_ARRAY_IDX(n, _) n + +#define DEFINE_STACK_ARRAY_IDX\ + LISTIFY(CONFIG_MP_MAX_NUM_CPUS, STACK_ARRAY_IDX, (,)) + #endif /* ZEPHYR_ARCH_X86_INCLUDE_INTEL64_KERNEL_ARCH_DATA_H_ */ diff --git a/arch/x86/include/intel64/kernel_arch_func.h b/arch/x86/include/intel64/kernel_arch_func.h index a749a9b9af178..abf022fe5fd55 100644 --- a/arch/x86/include/intel64/kernel_arch_func.h +++ b/arch/x86/include/intel64/kernel_arch_func.h @@ -36,7 +36,7 @@ void x86_sse_init(struct k_thread *thread); void z_x86_syscall_entry_stub(void); -bool z_x86_do_kernel_nmi(const z_arch_esf_t *esf); +bool z_x86_do_kernel_nmi(const struct arch_esf *esf); #endif /* _ASMLANGUAGE */ diff --git a/arch/x86/include/intel64/offsets_short_arch.h b/arch/x86/include/intel64/offsets_short_arch.h index 4252ac687dba7..1ffabc899c204 100644 --- a/arch/x86/include/intel64/offsets_short_arch.h +++ b/arch/x86/include/intel64/offsets_short_arch.h @@ -6,7 +6,7 @@ #ifndef ZEPHYR_ARCH_X86_INCLUDE_INTEL64_OFFSETS_SHORT_ARCH_H_ #define ZEPHYR_ARCH_X86_INCLUDE_INTEL64_OFFSETS_SHORT_ARCH_H_ -#include +#include #define _thread_offset_to_rsp \ (___thread_t_callee_saved_OFFSET + ___callee_saved_t_rsp_OFFSET) diff --git a/arch/x86/include/kernel_arch_func.h b/arch/x86/include/kernel_arch_func.h index 00b411978ec65..9bc7cfe4212f8 100644 --- a/arch/x86/include/kernel_arch_func.h +++ b/arch/x86/include/kernel_arch_func.h @@ -49,16 +49,16 @@ void z_x86_early_serial_init(void); * interesting info and call z_x86_fatal_error() */ FUNC_NORETURN void z_x86_unhandled_cpu_exception(uintptr_t vector, - const z_arch_esf_t *esf); + const struct arch_esf *esf); /* Called upon unrecoverable error; dump registers and transfer control to * kernel via z_fatal_error() */ FUNC_NORETURN void z_x86_fatal_error(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); /* Common handling for page fault exceptions */ -void z_x86_page_fault_handler(z_arch_esf_t *esf); +void z_x86_page_fault_handler(struct arch_esf *esf); #ifdef CONFIG_THREAD_STACK_INFO /** @@ -90,7 +90,7 @@ void *z_x86_userspace_prepare_thread(struct k_thread *thread); #endif /* CONFIG_USERSPACE */ -void z_x86_do_kernel_oops(const z_arch_esf_t *esf); +void z_x86_do_kernel_oops(const struct arch_esf *esf); /* * Find a free IRQ vector at the specified priority, or return -1 if none left. diff --git a/arch/x86/include/x86_mmu.h b/arch/x86/include/x86_mmu.h index 31c8526cb7a0b..ed6bb59b37cb4 100644 --- a/arch/x86/include/x86_mmu.h +++ b/arch/x86/include/x86_mmu.h @@ -182,7 +182,7 @@ static inline uintptr_t z_x86_cr3_get(void) /* Return the virtual address of the page tables installed in this CPU in CR3 */ static inline pentry_t *z_x86_page_tables_get(void) { - return z_mem_virt_addr(z_x86_cr3_get()); + return k_mem_virt_addr(z_x86_cr3_get()); } /* Return cr2 value, which contains the page fault linear address. @@ -215,7 +215,7 @@ static inline pentry_t *z_x86_thread_page_tables_get(struct k_thread *thread) * the kernel's page tables and not the page tables associated * with their memory domain. */ - return z_mem_virt_addr(thread->arch.ptables); + return k_mem_virt_addr(thread->arch.ptables); } #else ARG_UNUSED(thread); diff --git a/arch/x86/zefi/printf.h b/arch/x86/zefi/printf.h index f90a54ec3fb31..a3960064029b5 100644 --- a/arch/x86/zefi/printf.h +++ b/arch/x86/zefi/printf.h @@ -45,14 +45,18 @@ static void prdec(struct _pfr *r, long v) char digs[11 * sizeof(long)/4]; int i = sizeof(digs) - 1; - digs[i--] = 0; + digs[i] = 0; + --i; while (v || i == 9) { - digs[i--] = '0' + (v % 10); + digs[i] = '0' + (v % 10); + --i; v /= 10; } - while (digs[++i] != '\0') { + ++i; + while (digs[i] != '\0') { pc(r, digs[i]); + ++i; } } @@ -101,8 +105,10 @@ static int vpf(struct _pfr *r, const char *f, va_list ap) case 's': { char *s = va_arg(ap, char *); - while (*s != '\0') - pc(r, *s++); + while (*s != '\0') { + pc(r, *s); + ++s; + } break; } case 'p': diff --git a/arch/x86/zefi/zefi.c b/arch/x86/zefi/zefi.c index 015a6ff50a26e..56d0701e79bb0 100644 --- a/arch/x86/zefi/zefi.c +++ b/arch/x86/zefi/zefi.c @@ -56,7 +56,8 @@ static void efi_putchar(int c) efi_putchar('\r'); } - efibuf[n++] = c; + efibuf[n] = c; + ++n; if (c == '\n' || n == PUTCHAR_BUFSZ) { efibuf[n] = 0U; diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig index 8aa3d0fa96cc6..82a44f820c58a 100644 --- a/arch/xtensa/Kconfig +++ b/arch/xtensa/Kconfig @@ -22,6 +22,16 @@ config XTENSA_RESET_VECTOR This is always needed for the simulator. Real boards may already implement this in boot ROM. +config XTENSA_GEN_HANDLERS + bool "Automatically generate interrupt handlers" + default n + help + When set, an "xtensa_handlers.h" file is generated + containing definitions for the interrupt entry code of the + target Xtensa core, based automatically on the details in + the core-isa.h file. This replaces the previous scheme + where a _soc_inthandlers.h file would be generated offline. + config XTENSA_USE_CORE_CRT1 bool "Use crt1.S from core" default y diff --git a/arch/xtensa/core/CMakeLists.txt b/arch/xtensa/core/CMakeLists.txt index fab15a803dad8..56ca1071b0130 100644 --- a/arch/xtensa/core/CMakeLists.txt +++ b/arch/xtensa/core/CMakeLists.txt @@ -48,7 +48,7 @@ add_subdirectory(startup) # are the official places where we find core-isa.h. (Also that we # undefine __XCC_ because that compiler actually trips an error trying # to build this file to protect against mismatched versions.) -set(CORE_ISA_DM ${CMAKE_BINARY_DIR}/zephyr/include/generated/core-isa-dM.h) +set(CORE_ISA_DM ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/core-isa-dM.h) set(CORE_ISA_IN ${CMAKE_BINARY_DIR}/zephyr/include/generated/core-isa-dM.c) file(WRITE ${CORE_ISA_IN} "#include \n") add_custom_command(OUTPUT ${CORE_ISA_DM} @@ -73,7 +73,7 @@ else() endif() # Generates a list of device-specific scratch register choices -set(ZSR_H ${CMAKE_BINARY_DIR}/zephyr/include/generated/zsr.h) +set(ZSR_H ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/zsr.h) add_custom_command(OUTPUT ${ZSR_H} DEPENDS ${CORE_ISA_DM} COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen_zsr.py $<$:--mmu> @@ -84,3 +84,30 @@ add_custom_target(zsr_h DEPENDS ${ZSR_H}) add_dependencies(zephyr_interface zsr_h) unset(MAY_NEED_SYSCALL_SCRATCH_REG) + +# Similar: auto-generate interrupt handlers +set(HANDLERS ${CMAKE_BINARY_DIR}/zephyr/include/generated/xtensa_handlers) + +add_custom_command( + OUTPUT ${HANDLERS}_tmp.c + COMMAND ${CMAKE_C_COMPILER} -E -U__XCC__ + -I${ZEPHYR_XTENSA_MODULE_DIR}/zephyr/soc/${CONFIG_SOC} + -o ${HANDLERS}_tmp.c + - < ${CMAKE_CURRENT_SOURCE_DIR}/xtensa_intgen.tmpl) + +add_custom_command( + OUTPUT ${HANDLERS}.h + DEPENDS ${HANDLERS}_tmp.c + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/xtensa_intgen.py + ${HANDLERS}_tmp.c > ${HANDLERS}.h) + +add_custom_target(xtensa_handlers_h DEPENDS ${HANDLERS}.h) +add_dependencies(zephyr_interface xtensa_handlers_h) + +# Auto-generate interrupt vector entry +set(VECS_LD ${CMAKE_BINARY_DIR}/zephyr/include/generated/xtensa_vectors.ld) +add_custom_command(OUTPUT ${VECS_LD} DEPENDS ${CORE_ISA_DM} + COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gen_vectors.py + ${CORE_ISA_DM} > ${VECS_LD}) +add_custom_target(xtensa_vectors_ld DEPENDS ${VECS_LD}) +add_dependencies(zephyr_interface xtensa_vectors_ld) diff --git a/arch/xtensa/core/coredump.c b/arch/xtensa/core/coredump.c index a2eec6207743c..0ee1f8992a6b7 100644 --- a/arch/xtensa/core/coredump.c +++ b/arch/xtensa/core/coredump.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #define ARCH_HDR_VER 1 #define XTENSA_BLOCK_HDR_VER 2 @@ -91,7 +91,7 @@ struct xtensa_arch_block { */ static struct xtensa_arch_block arch_blk; -void arch_coredump_info_dump(const z_arch_esf_t *esf) +void arch_coredump_info_dump(const struct arch_esf *esf) { struct coredump_arch_hdr_t hdr = { .id = COREDUMP_ARCH_HDR_ID, diff --git a/arch/xtensa/core/debug_helpers_asm.S b/arch/xtensa/core/debug_helpers_asm.S index 3dacc1a4587f5..6ed5ced8c61a8 100644 --- a/arch/xtensa/core/debug_helpers_asm.S +++ b/arch/xtensa/core/debug_helpers_asm.S @@ -10,7 +10,7 @@ #include #include -#include +#include .section .iram1, "ax" .align 4 diff --git a/arch/xtensa/core/fatal.c b/arch/xtensa/core/fatal.c index 6ec5549f2e469..39e84b86f6b13 100644 --- a/arch/xtensa/core/fatal.c +++ b/arch/xtensa/core/fatal.c @@ -84,7 +84,7 @@ char *xtensa_exccause(unsigned int cause_code) #endif } -void xtensa_fatal_error(unsigned int reason, const z_arch_esf_t *esf) +void xtensa_fatal_error(unsigned int reason, const struct arch_esf *esf) { #ifdef CONFIG_EXCEPTION_DEBUG if (esf) { @@ -154,6 +154,6 @@ static void z_vrfy_xtensa_user_fault(unsigned int reason) z_impl_xtensa_user_fault(reason); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/arch/xtensa/core/gdbstub.c b/arch/xtensa/core/gdbstub.c index 4df72f0d355c7..0ebc9cc68ccd5 100644 --- a/arch/xtensa/core/gdbstub.c +++ b/arch/xtensa/core/gdbstub.c @@ -422,7 +422,7 @@ static unsigned int get_gdb_exception_reason(unsigned int reason) * @param ctx GDB context * @param stack Pointer to the stack frame */ -static void copy_to_ctx(struct gdb_ctx *ctx, const z_arch_esf_t *stack) +static void copy_to_ctx(struct gdb_ctx *ctx, const struct arch_esf *stack) { struct xtensa_register *reg; int idx, num_laddr_regs; @@ -513,7 +513,7 @@ static void copy_to_ctx(struct gdb_ctx *ctx, const z_arch_esf_t *stack) * @param ctx GDB context * @param stack Pointer to the stack frame */ -static void restore_from_ctx(struct gdb_ctx *ctx, const z_arch_esf_t *stack) +static void restore_from_ctx(struct gdb_ctx *ctx, const struct arch_esf *stack) { struct xtensa_register *reg; int idx, num_laddr_regs; @@ -913,7 +913,7 @@ int arch_gdb_remove_breakpoint(struct gdb_ctx *ctx, uint8_t type, return ret; } -void z_gdb_isr(z_arch_esf_t *esf) +void z_gdb_isr(struct arch_esf *esf) { uint32_t reg; diff --git a/arch/xtensa/core/gen_vectors.py b/arch/xtensa/core/gen_vectors.py new file mode 100755 index 0000000000000..e9e60e30fe529 --- /dev/null +++ b/arch/xtensa/core/gen_vectors.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 +import sys +import re + +# Xtensa Vector Table linker generator +# +# Takes a pre-processed (gcc -dM) core-isa.h file as its first +# argument, and emits a GNU linker section declartion which will +# correctly load the exception vectors and literals as long as their +# code is declared using standard conventions (see below). +# +# The section name will be ".z_xtensa_vectors", and a symbol +# "z_xtensa_vecbase" is emitted containing a valid value for the +# VECBASE SR at runtime. +# +# Obviously, this requires that XCHAL_HAVE_VECBASE=1. A similar trick +# could be played to load vectors at fixed addresses on hardware that +# lacks VECBASE, but the core-isa.h interface is inexplicably +# different. +# +# Because the "standard conventions" (which descend from somewhere in +# Cadence) are not documented anywhere and just end up cut and pasted +# between devices, here's an attempt at a specification: +# +# + The six register window exception vectors are defined with offsets +# internal to their assembly code. They are linked in a single +# section named ".WindowVectors.text". +# +# + The "kernel", "user" and "double exception" vectors are emitted in +# sections named ".KernelExceptionVector.text", +# "UserExceptionVector.text" and "DoubleExceptionVector.text" +# respectively. +# +# + XEA2 interrupt vectors are in sections named +# ".LevelInterruptVector.text", except (!) for ones which are +# given special names. The "debug" and "NMI" interrupts (if they +# exist) are technically implemented as standard interrupt vectors +# (of a platform-dependent level), but the code for them is emitted +# in ".DebugExceptionVector.text" and ".NMIExceptionVector.text", +# and not a section corresponding to their interrupt level. +# +# + Any unused bytes at the end of a vector are made available as +# storage for immediate values used by the following vector (Xtensa +# can only back-reference immediates for MOVI/L32R instructions) as +# a "Vector.literal" section. Note that there is no guarantee +# of how much space is available, it depends on the previous +# vector's code size. Zephyr code has historically not used this +# space, as support in existing linker scripts is inconsistent. But +# it's exposed here. + +coreisa = sys.argv[1] + +debug_level = 0 + +# Translation for the core-isa.h vs. linker section naming conventions +sect_names = { "DOUBLEEXC" : "DoubleException", + "KERNEL" : "KernelException", + "NMI" : "NMIException", + "USER" : "UserException" } + +offsets = {} + +with open(coreisa) as infile: + for line in infile.readlines(): + m = re.match(r"^#define\s+XCHAL_([^ ]+)_VECOFS\s*(.*)", line.rstrip()) + if m: + (sym, val) = (m.group(1), m.group(2)) + if sym == "WINDOW_OF4": + # This must be the start of the section + assert eval(val) == 0 + elif sym.startswith("WINDOW"): + # Ignore the other window exceptions, they're internally sorted + pass + elif sym == "RESET": + # Ignore, not actually part of the vector table + pass + elif sym == "DEBUG": + # This one is a recursive macro that doesn't expand, + # so handle manually + m = re.match(r"XCHAL_INTLEVEL(\d+)_VECOFS", val) + if not m: + print(f"no intlevel match for debug val {val}") + assert m + debug_level = eval(m.group(1)) + else: + if val == "XCHAL_NMI_VECOFS": + # This gets recursively defined in the other + # direction, so ignore the INTLEVEL + pass + else: + addr = eval(val) + m = re.match(r"^INTLEVEL(\d+)", sym) + if m: + offsets[f"Level{m.group(1)}Interrupt"] = addr + else: + offsets[sect_names[sym]] = addr + +if debug_level > 0: + old = f"Level{debug_level}Interrupt" + offsets[f"DebugException"] = offsets[old] + del offsets[old] + +sects = list(offsets) +sects.sort(key=lambda s: offsets[s]) + +print("/* Automatically Generated Code - Do Not Edit */") +print("/* See arch/xtensa/core/gen_vector.py */") +print("") + +# The 1k alignment is experimental, the docs on the Relocatable Vector +# Option doesn't specify an alignment at all, but writes to the +# bottom bits don't take... +print( " .z_xtensa_vectors : ALIGN(1024) {") +print( " z_xtensa_vecbase = .;") +print(f" KEEP(*(.WindowVectors.text));") +for s in sects: + print(f" KEEP(*(.{s}Vector.literal));") + print( " . = 0x%3.3x;" % (offsets[s])) + print(f" KEEP(*(.{s}Vector.text));") +print(" }") diff --git a/arch/xtensa/core/irq_offload.c b/arch/xtensa/core/irq_offload.c index ad35ef4cd0e4d..c142bfc5fc669 100644 --- a/arch/xtensa/core/irq_offload.c +++ b/arch/xtensa/core/irq_offload.c @@ -5,7 +5,7 @@ #include #include -#include +#include #include static struct { diff --git a/arch/xtensa/core/mpu.c b/arch/xtensa/core/mpu.c index 29e336297717f..2b16ff912411f 100644 --- a/arch/xtensa/core/mpu.c +++ b/arch/xtensa/core/mpu.c @@ -443,6 +443,8 @@ static int mpu_map_region_add(struct xtensa_mpu_map *map, xtensa_mpu_entry_set(entry_slot_s, start_addr, true, access_rights, memory_type); + first_enabled_idx = XTENSA_MPU_NUM_ENTRIES - 1; + goto end; } else { /* * Populate the last two entries to indicate @@ -459,6 +461,8 @@ static int mpu_map_region_add(struct xtensa_mpu_map *map, xtensa_mpu_entry_set(entry_slot_e, end_addr, false, XTENSA_MPU_ACCESS_P_NA_U_NA, CONFIG_XTENSA_MPU_DEFAULT_MEM_TYPE); + first_enabled_idx = XTENSA_MPU_NUM_ENTRIES - 2; + goto end; } ret = 0; @@ -595,6 +599,7 @@ static int mpu_map_region_add(struct xtensa_mpu_map *map, xtensa_mpu_entry_attributes_set(&entries[idx], access_rights, memory_type); } +end: if (first_idx != NULL) { *first_idx = first_enabled_idx; } @@ -969,7 +974,7 @@ int arch_mem_domain_thread_remove(struct k_thread *thread) return ret; } -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { uintptr_t aligned_addr; size_t aligned_size, addr_offset; diff --git a/arch/xtensa/core/ptables.c b/arch/xtensa/core/ptables.c index dc33d6fd5f050..d934f16a213c8 100644 --- a/arch/xtensa/core/ptables.c +++ b/arch/xtensa/core/ptables.c @@ -214,15 +214,18 @@ static inline uint32_t *alloc_l2_table(void) } static void map_memory_range(const uint32_t start, const uint32_t end, - const uint32_t attrs, bool shared) + const uint32_t attrs) { uint32_t page, *table; + bool shared = !!(attrs & XTENSA_MMU_MAP_SHARED); + uint32_t sw_attrs = (attrs & XTENSA_MMU_PTE_ATTR_ORIGINAL) == XTENSA_MMU_PTE_ATTR_ORIGINAL ? + attrs : 0; for (page = start; page < end; page += CONFIG_MMU_PAGE_SIZE) { uint32_t pte = XTENSA_MMU_PTE(page, shared ? XTENSA_MMU_SHARED_RING : XTENSA_MMU_KERNEL_RING, - attrs); + sw_attrs, attrs); uint32_t l2_pos = XTENSA_MMU_L2_POS(page); uint32_t l1_pos = XTENSA_MMU_L1_POS(page); @@ -236,7 +239,7 @@ static void map_memory_range(const uint32_t start, const uint32_t end, xtensa_kernel_ptables[l1_pos] = XTENSA_MMU_PTE((uint32_t)table, XTENSA_MMU_KERNEL_RING, - XTENSA_MMU_PAGE_TABLE_ATTR); + sw_attrs, XTENSA_MMU_PAGE_TABLE_ATTR); } table = (uint32_t *)(xtensa_kernel_ptables[l1_pos] & XTENSA_MMU_PTE_PPN_MASK); @@ -245,18 +248,18 @@ static void map_memory_range(const uint32_t start, const uint32_t end, } static void map_memory(const uint32_t start, const uint32_t end, - const uint32_t attrs, bool shared) + const uint32_t attrs) { - map_memory_range(start, end, attrs, shared); + map_memory_range(start, end, attrs); #ifdef CONFIG_XTENSA_MMU_DOUBLE_MAP if (sys_cache_is_ptr_uncached((void *)start)) { map_memory_range(POINTER_TO_UINT(sys_cache_cached_ptr_get((void *)start)), POINTER_TO_UINT(sys_cache_cached_ptr_get((void *)end)), - attrs | XTENSA_MMU_CACHED_WB, shared); + attrs | XTENSA_MMU_CACHED_WB); } else if (sys_cache_is_ptr_cached((void *)start)) { map_memory_range(POINTER_TO_UINT(sys_cache_uncached_ptr_get((void *)start)), - POINTER_TO_UINT(sys_cache_uncached_ptr_get((void *)end)), attrs, shared); + POINTER_TO_UINT(sys_cache_uncached_ptr_get((void *)end)), attrs); } #endif } @@ -270,24 +273,14 @@ static void xtensa_init_page_tables(void) for (entry = 0; entry < ARRAY_SIZE(mmu_zephyr_ranges); entry++) { const struct xtensa_mmu_range *range = &mmu_zephyr_ranges[entry]; - bool shared; - uint32_t attrs; - shared = !!(range->attrs & XTENSA_MMU_MAP_SHARED); - attrs = range->attrs & ~XTENSA_MMU_MAP_SHARED; - - map_memory(range->start, range->end, attrs, shared); + map_memory(range->start, range->end, range->attrs | XTENSA_MMU_PTE_ATTR_ORIGINAL); } for (entry = 0; entry < xtensa_soc_mmu_ranges_num; entry++) { const struct xtensa_mmu_range *range = &xtensa_soc_mmu_ranges[entry]; - bool shared; - uint32_t attrs; - - shared = !!(range->attrs & XTENSA_MMU_MAP_SHARED); - attrs = range->attrs & ~XTENSA_MMU_MAP_SHARED; - map_memory(range->start, range->end, attrs, shared); + map_memory(range->start, range->end, range->attrs | XTENSA_MMU_PTE_ATTR_ORIGINAL); } /* Finally, the direct-mapped pages used in the page tables @@ -297,10 +290,10 @@ static void xtensa_init_page_tables(void) */ map_memory_range((uint32_t) &l1_page_table[0], (uint32_t) &l1_page_table[CONFIG_XTENSA_MMU_NUM_L1_TABLES], - XTENSA_MMU_PAGE_TABLE_ATTR | XTENSA_MMU_PERM_W, false); + XTENSA_MMU_PAGE_TABLE_ATTR | XTENSA_MMU_PERM_W); map_memory_range((uint32_t) &l2_page_tables[0], (uint32_t) &l2_page_tables[CONFIG_XTENSA_MMU_NUM_L2_TABLES], - XTENSA_MMU_PAGE_TABLE_ATTR | XTENSA_MMU_PERM_W, false); + XTENSA_MMU_PAGE_TABLE_ATTR | XTENSA_MMU_PERM_W); sys_cache_data_flush_all(); } @@ -327,6 +320,24 @@ void xtensa_mmu_init(void) arch_xtensa_mmu_post_init(_current_cpu->id == 0); } +void xtensa_mmu_reinit(void) +{ + /* First initialize the hardware */ + xtensa_init_paging(xtensa_kernel_ptables); + +#ifdef CONFIG_USERSPACE + struct k_thread *thread = _current_cpu->current; + struct arch_mem_domain *domain = + &(thread->mem_domain_info.mem_domain->arch); + + + /* Set the page table for current context */ + xtensa_set_paging(domain->asid, domain->ptables); +#endif /* CONFIG_USERSPACE */ + + arch_xtensa_mmu_post_init(_current_cpu->id == 0); +} + #ifdef CONFIG_ARCH_HAS_RESERVED_PAGE_FRAMES /* Zephyr's linker scripts for Xtensa usually puts * something before z_mapped_start (aka .text), @@ -337,15 +348,12 @@ void xtensa_mmu_init(void) __weak void arch_reserved_pages_update(void) { uintptr_t page; - struct z_page_frame *pf; int idx; for (page = CONFIG_SRAM_BASE_ADDRESS, idx = 0; page < (uintptr_t)z_mapped_start; page += CONFIG_MMU_PAGE_SIZE, idx++) { - pf = &z_page_frames[idx]; - - pf->flags |= Z_PAGE_FRAME_RESERVED; + k_mem_page_frame_set(&k_mem_page_frames[idx], K_MEM_PAGE_FRAME_RESERVED); } } #endif /* CONFIG_ARCH_HAS_RESERVED_PAGE_FRAMES */ @@ -369,7 +377,7 @@ static bool l2_page_table_map(uint32_t *l1_table, void *vaddr, uintptr_t phys, init_page_table(table, XTENSA_L2_PAGE_TABLE_ENTRIES); l1_table[l1_pos] = XTENSA_MMU_PTE((uint32_t)table, XTENSA_MMU_KERNEL_RING, - XTENSA_MMU_PAGE_TABLE_ATTR); + 0, XTENSA_MMU_PAGE_TABLE_ATTR); sys_cache_data_flush_range((void *)&l1_table[l1_pos], sizeof(l1_table[0])); } @@ -377,7 +385,7 @@ static bool l2_page_table_map(uint32_t *l1_table, void *vaddr, uintptr_t phys, table = (uint32_t *)(l1_table[l1_pos] & XTENSA_MMU_PTE_PPN_MASK); table[l2_pos] = XTENSA_MMU_PTE(phys, is_user ? XTENSA_MMU_USER_RING : XTENSA_MMU_KERNEL_RING, - flags); + 0, flags); sys_cache_data_flush_range((void *)&table[l2_pos], sizeof(table[0])); xtensa_tlb_autorefill_invalidate(); @@ -725,7 +733,7 @@ static inline uint32_t *alloc_l1_table(void) return NULL; } -static uint32_t *dup_table(uint32_t *source_table) +static uint32_t *dup_table(void) { uint16_t i, j; uint32_t *dst_table = alloc_l1_table(); @@ -737,27 +745,38 @@ static uint32_t *dup_table(uint32_t *source_table) for (i = 0; i < XTENSA_L1_PAGE_TABLE_ENTRIES; i++) { uint32_t *l2_table, *src_l2_table; - if (is_pte_illegal(source_table[i]) || + if (is_pte_illegal(xtensa_kernel_ptables[i]) || (i == XTENSA_MMU_L1_POS(XTENSA_MMU_PTEVADDR))) { dst_table[i] = XTENSA_MMU_PTE_ILLEGAL; continue; } - src_l2_table = (uint32_t *)(source_table[i] & XTENSA_MMU_PTE_PPN_MASK); + src_l2_table = (uint32_t *)(xtensa_kernel_ptables[i] & XTENSA_MMU_PTE_PPN_MASK); l2_table = alloc_l2_table(); if (l2_table == NULL) { goto err; } for (j = 0; j < XTENSA_L2_PAGE_TABLE_ENTRIES; j++) { + uint32_t original_attr = XTENSA_MMU_PTE_SW_GET(src_l2_table[j]); + l2_table[j] = src_l2_table[j]; + if (original_attr != 0x0) { + uint8_t ring; + + ring = XTENSA_MMU_PTE_RING_GET(l2_table[j]); + l2_table[j] = XTENSA_MMU_PTE_ATTR_SET(l2_table[j], original_attr); + l2_table[j] = XTENSA_MMU_PTE_RING_SET(l2_table[j], + ring == XTENSA_MMU_SHARED_RING ? + XTENSA_MMU_SHARED_RING : XTENSA_MMU_KERNEL_RING); + } } /* The page table is using kernel ASID because we don't * user thread manipulate it. */ dst_table[i] = XTENSA_MMU_PTE((uint32_t)l2_table, XTENSA_MMU_KERNEL_RING, - XTENSA_MMU_PAGE_TABLE_ATTR); + 0, XTENSA_MMU_PAGE_TABLE_ATTR); sys_cache_data_flush_range((void *)l2_table, XTENSA_L2_PAGE_TABLE_SIZE); } @@ -784,7 +803,19 @@ int arch_mem_domain_init(struct k_mem_domain *domain) __ASSERT(asid_count < (XTENSA_MMU_SHARED_ASID), "Reached maximum of ASID available"); key = k_spin_lock(&xtensa_mmu_lock); - ptables = dup_table(xtensa_kernel_ptables); + /* If this is the default domain, we don't need + * to create a new set of page tables. We can just + * use the kernel page tables and save memory. + */ + + if (domain == &k_mem_domain_default) { + domain->arch.ptables = xtensa_kernel_ptables; + domain->arch.asid = asid_count; + goto end; + } + + + ptables = dup_table(); if (ptables == NULL) { ret = -ENOMEM; @@ -796,6 +827,7 @@ int arch_mem_domain_init(struct k_mem_domain *domain) sys_slist_append(&xtensa_domain_list, &domain->arch.node); +end: ret = 0; err: @@ -1044,7 +1076,7 @@ static bool page_validate(uint32_t *ptables, uint32_t page, uint8_t ring, bool w return true; } -int arch_buffer_validate(void *addr, size_t size, int write) +int arch_buffer_validate(const void *addr, size_t size, int write) { int ret = 0; uint8_t *virt; diff --git a/arch/xtensa/core/smp.c b/arch/xtensa/core/smp.c index ffd08ab805c29..71d8150025b07 100644 --- a/arch/xtensa/core/smp.c +++ b/arch/xtensa/core/smp.c @@ -19,3 +19,13 @@ void arch_spin_relax(void) #undef NOP1 } #endif /* CONFIG_XTENSA_MORE_SPIN_RELAX_NOPS */ + + +/** + * init for multi-core/smp is done on the SoC level. Add this here for + * compatibility with other SMP systems. + */ +int arch_smp_init(void) +{ + return 0; +} diff --git a/arch/xtensa/core/userspace.S b/arch/xtensa/core/userspace.S index 1578e3be971a5..507ae17267e84 100644 --- a/arch/xtensa/core/userspace.S +++ b/arch/xtensa/core/userspace.S @@ -5,10 +5,10 @@ */ #include -#include +#include #include #include -#include +#include #include diff --git a/arch/xtensa/core/vector_handlers.c b/arch/xtensa/core/vector_handlers.c index b8dca1c19679c..471a67c086304 100644 --- a/arch/xtensa/core/vector_handlers.c +++ b/arch/xtensa/core/vector_handlers.c @@ -10,13 +10,18 @@ #include #include #include -#include <_soc_inthandlers.h> #include #include -#include -#include +#include +#include #include +#ifdef CONFIG_XTENSA_GEN_HANDLERS +#include +#else +#include <_soc_inthandlers.h> +#endif + #include LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); @@ -32,7 +37,7 @@ static const struct z_exc_handle exceptions[] = { }; #endif /* CONFIG_USERSPACE */ -void xtensa_dump_stack(const z_arch_esf_t *stack) +void xtensa_dump_stack(const void *stack) { _xtensa_irq_stack_frame_raw_t *frame = (void *)stack; _xtensa_irq_bsa_t *bsa = frame->ptr_to_bsa; @@ -213,9 +218,10 @@ static inline DEF_INT_C_HANDLER(1) * different because exceptions and interrupts land at the same * vector; other interrupt levels have their own vectors. */ -void *xtensa_excint1_c(int *interrupted_stack) +void *xtensa_excint1_c(void *esf) { int cause; + int *interrupted_stack = &((struct arch_esf *)esf)->dummy; _xtensa_irq_bsa_t *bsa = (void *)*(int **)interrupted_stack; bool is_fatal_error = false; bool is_dblexc = false; @@ -359,7 +365,7 @@ void *xtensa_excint1_c(int *interrupted_stack) * thread. */ __asm__ volatile("rsil %0, %1" - : "=r" (ignore) : "i"(XCHAL_NMILEVEL)); + : "=r" (ignore) : "i"(XCHAL_EXCM_LEVEL)); _current_cpu->nested = 1; } @@ -380,7 +386,7 @@ void *xtensa_excint1_c(int *interrupted_stack) #if defined(CONFIG_GDBSTUB) void *xtensa_debugint_c(int *interrupted_stack) { - extern void z_gdb_isr(z_arch_esf_t *esf); + extern void z_gdb_isr(struct arch_esf *esf); z_gdb_isr((void *)interrupted_stack); diff --git a/arch/xtensa/core/window_vectors.S b/arch/xtensa/core/window_vectors.S index 90eba495bde80..6c4e8c4480321 100644 --- a/arch/xtensa/core/window_vectors.S +++ b/arch/xtensa/core/window_vectors.S @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include +#include /* WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION * HANDLER diff --git a/arch/xtensa/core/xtensa_asm2_util.S b/arch/xtensa/core/xtensa_asm2_util.S index dad8f1993594f..58ca9b46eec3c 100644 --- a/arch/xtensa/core/xtensa_asm2_util.S +++ b/arch/xtensa/core/xtensa_asm2_util.S @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ #include -#include -#include +#include +#include #if defined(CONFIG_SIMULATOR_XTENSA) || defined(XT_SIMULATOR) #include diff --git a/arch/xtensa/core/xtensa_hifi.S b/arch/xtensa/core/xtensa_hifi.S index 3c311acab0f4b..dff714cce183b 100644 --- a/arch/xtensa/core/xtensa_hifi.S +++ b/arch/xtensa/core/xtensa_hifi.S @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include diff --git a/arch/xtensa/core/xtensa_intgen.py b/arch/xtensa/core/xtensa_intgen.py index 6a7935d409cfd..2770cb4662c8a 100755 --- a/arch/xtensa/core/xtensa_intgen.py +++ b/arch/xtensa/core/xtensa_intgen.py @@ -105,13 +105,11 @@ def emit_int_handler(ints): cprint("#endif") cprint("") -# Populate empty levels just for sanity. The second-to-last interrupt -# level (usually "debug") typically doesn't have any associated -# vectors, but we don't have any way to know that a-prioi. -max = 0 -for lvl in ints_by_lvl: - if lvl > max: - max = lvl +# Populate all theoretical levels just in case. Odd cores have been +# seen in the wild with "empty" interrupt levels that exist in the +# hardware but without any interrupts associated with them. The +# unused handlers will be ignored if uncalled. +max = 15 for lvl in range(0, max+1): if not lvl in ints_by_lvl: diff --git a/arch/xtensa/include/kernel_arch_func.h b/arch/xtensa/include/kernel_arch_func.h index 48599f0e76927..29a8982660a0c 100644 --- a/arch/xtensa/include/kernel_arch_func.h +++ b/arch/xtensa/include/kernel_arch_func.h @@ -14,7 +14,7 @@ #include #include #include -#include +#include #ifdef __cplusplus extern "C" { diff --git a/arch/xtensa/include/xtensa_asm2_s.h b/arch/xtensa/include/xtensa_asm2_s.h index dddf7bb309c67..0af8c4cb51fdc 100644 --- a/arch/xtensa/include/xtensa_asm2_s.h +++ b/arch/xtensa/include/xtensa_asm2_s.h @@ -7,10 +7,10 @@ #ifndef ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_S_H #define ZEPHYR_ARCH_XTENSA_INCLUDE_XTENSA_ASM2_S_H -#include +#include #include "xtensa_asm2_context.h" -#include +#include /* Assembler header! This file contains macros designed to be included * only by the assembler. diff --git a/arch/xtensa/include/xtensa_internal.h b/arch/xtensa/include/xtensa_internal.h index 60b512ab57135..f3e1ab4f44e20 100644 --- a/arch/xtensa/include/xtensa_internal.h +++ b/arch/xtensa/include/xtensa_internal.h @@ -25,7 +25,7 @@ * * @param stack Pointer to stack frame. */ -void xtensa_dump_stack(const z_arch_esf_t *stack); +void xtensa_dump_stack(const void *stack); /** * @brief Get string description from an exception code. @@ -43,7 +43,7 @@ char *xtensa_exccause(unsigned int cause_code); * @param esf Exception context, with details and partial or full register * state when the error occurred. May in some cases be NULL. */ -void xtensa_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +void xtensa_fatal_error(unsigned int reason, const struct arch_esf *esf); /** * @brief Perform a one-way transition from supervisor to user mode. diff --git a/arch/xtensa/include/xtensa_mmu_priv.h b/arch/xtensa/include/xtensa_mmu_priv.h index 631760f03cb18..608cbac9c4652 100644 --- a/arch/xtensa/include/xtensa_mmu_priv.h +++ b/arch/xtensa/include/xtensa_mmu_priv.h @@ -41,11 +41,6 @@ #define XTENSA_MMU_PTEBASE_MASK 0xFFC00000 -#define XTENSA_MMU_PTE(paddr, ring, attr) \ - (((paddr) & XTENSA_MMU_PTE_PPN_MASK) | \ - (((ring) << XTENSA_MMU_PTE_RING_SHIFT) & XTENSA_MMU_PTE_RING_MASK) | \ - ((attr) & XTENSA_MMU_PTE_ATTR_MASK)) - /** Number of bits to shift for PPN in PTE */ #define XTENSA_MMU_PTE_PPN_SHIFT 12U @@ -55,10 +50,24 @@ /** Number of bits to shift for ring in PTE */ #define XTENSA_MMU_PTE_RING_SHIFT 4U +/** Number of bits to shift for SW reserved ared in PTE */ +#define XTENSA_MMU_PTE_SW_SHIFT 6U + +/** Mask for SW bits in PTE */ +#define XTENSA_MMU_PTE_SW_MASK 0x00000FC0U + +/** + * Internal bit just used to indicate that the attr field must + * be set in the SW bits too. It is used later when duplicating the + * kernel page tables. + */ +#define XTENSA_MMU_PTE_ATTR_ORIGINAL BIT(31) + /** Construct a page table entry (PTE) */ -#define XTENSA_MMU_PTE(paddr, ring, attr) \ +#define XTENSA_MMU_PTE(paddr, ring, sw, attr) \ (((paddr) & XTENSA_MMU_PTE_PPN_MASK) | \ (((ring) << XTENSA_MMU_PTE_RING_SHIFT) & XTENSA_MMU_PTE_RING_MASK) | \ + (((sw) << XTENSA_MMU_PTE_SW_SHIFT) & XTENSA_MMU_PTE_SW_MASK) | \ ((attr) & XTENSA_MMU_PTE_ATTR_MASK)) /** Get the attributes from a PTE */ @@ -67,7 +76,15 @@ /** Set the attributes in a PTE */ #define XTENSA_MMU_PTE_ATTR_SET(pte, attr) \ - (((pte) & ~XTENSA_MMU_PTE_ATTR_MASK) | (attr)) + (((pte) & ~XTENSA_MMU_PTE_ATTR_MASK) | (attr & XTENSA_MMU_PTE_ATTR_MASK)) + +/** Set the SW field in a PTE */ +#define XTENSA_MMU_PTE_SW_SET(pte, sw) \ + (((pte) & ~XTENSA_MMU_PTE_SW_MASK) | (sw << XTENSA_MMU_PTE_SW_SHIFT)) + +/** Get the SW field from a PTE */ +#define XTENSA_MMU_PTE_SW_GET(pte) \ + (((pte) & XTENSA_MMU_PTE_SW_MASK) >> XTENSA_MMU_PTE_SW_SHIFT) /** Set the ring in a PTE */ #define XTENSA_MMU_PTE_RING_SET(pte, ring) \ @@ -76,7 +93,7 @@ /** Get the ring from a PTE */ #define XTENSA_MMU_PTE_RING_GET(pte) \ - (((pte) & ~XTENSA_MMU_PTE_RING_MASK) >> XTENSA_MMU_PTE_RING_SHIFT) + (((pte) & XTENSA_MMU_PTE_RING_MASK) >> XTENSA_MMU_PTE_RING_SHIFT) /** Get the ASID from the RASID register corresponding to the ring in a PTE */ #define XTENSA_MMU_PTE_ASID_GET(pte, rasid) \ diff --git a/boards/96boards/carbon/96b_carbon_stm32f401xe.dts b/boards/96boards/carbon/96b_carbon_stm32f401xe.dts index d94c67dc79d99..4f2365f303ebd 100644 --- a/boards/96boards/carbon/96b_carbon_stm32f401xe.dts +++ b/boards/96boards/carbon/96b_carbon_stm32f401xe.dts @@ -20,6 +20,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &hci_spi; }; leds { @@ -124,7 +125,7 @@ pinctrl-names = "default"; /* Nordic nRF51822-QFAC */ - bt-hci@0 { + hci_spi: bt-hci@0 { compatible = "zephyr,bt-hci-spi"; reg = <0>; reset-gpios = <&gpiob 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; diff --git a/boards/96boards/carbon/Kconfig.defconfig b/boards/96boards/carbon/Kconfig.defconfig index cede46b95fe39..2cf1bbdc6fcec 100644 --- a/boards/96boards/carbon/Kconfig.defconfig +++ b/boards/96boards/carbon/Kconfig.defconfig @@ -14,9 +14,8 @@ if BT config SPI default y -choice BT_HCI_BUS_TYPE - default BT_SPI -endchoice +config BT_SPI + default y endif # BT diff --git a/boards/96boards/meerkat96/Kconfig.defconfig b/boards/96boards/meerkat96/Kconfig.defconfig deleted file mode 100644 index a401b7ecb89bc..0000000000000 --- a/boards/96boards/meerkat96/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# 96Boards Meerkat96 board - -# Copyright (c) 2019, Linaro Ltd. -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_96B_MEERKAT96 - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_96B_MEERKAT96 diff --git a/boards/actinius/icarus/actinius_icarus_common_2_0_0.dtsi b/boards/actinius/icarus/actinius_icarus_common_2_0_0.dtsi index 9c63a8de3351c..802437900a8de 100644 --- a/boards/actinius/icarus/actinius_icarus_common_2_0_0.dtsi +++ b/boards/actinius/icarus/actinius_icarus_common_2_0_0.dtsi @@ -39,10 +39,6 @@ }; / { - aliases { - spi-flash0 = &w25q64; - }; - charger_enable: charger-enable { compatible = "actinius-charger-enable"; gpios = <&gpio0 7 GPIO_ACTIVE_LOW>; diff --git a/boards/actinius/icarus/actinius_icarus_nrf9160_1_4_0.yaml b/boards/actinius/icarus/actinius_icarus_nrf9160_1_4_0.yaml index 1f3d3d9e0c0d3..119745e52edeb 100644 --- a/boards/actinius/icarus/actinius_icarus_nrf9160_1_4_0.yaml +++ b/boards/actinius/icarus/actinius_icarus_nrf9160_1_4_0.yaml @@ -1,5 +1,5 @@ identifier: actinius_icarus@1.4.0/nrf9160 -name: Actinius Icarus +name: Actinius Icarus (rev. 1.4.0) type: mcu arch: arm toolchain: diff --git a/boards/actinius/icarus/actinius_icarus_nrf9160_2_0_0.yaml b/boards/actinius/icarus/actinius_icarus_nrf9160_2_0_0.yaml index d8bce88855696..f017d9c6f3c35 100644 --- a/boards/actinius/icarus/actinius_icarus_nrf9160_2_0_0.yaml +++ b/boards/actinius/icarus/actinius_icarus_nrf9160_2_0_0.yaml @@ -1,5 +1,5 @@ identifier: actinius_icarus@2.0.0/nrf9160 -name: Actinius Icarus +name: Actinius Icarus (rev. 2.0.0) type: mcu arch: arm toolchain: diff --git a/boards/actinius/icarus/actinius_icarus_nrf9160_ns_1_4_0.yaml b/boards/actinius/icarus/actinius_icarus_nrf9160_ns_1_4_0.yaml index 46005a7da105c..0733824966130 100644 --- a/boards/actinius/icarus/actinius_icarus_nrf9160_ns_1_4_0.yaml +++ b/boards/actinius/icarus/actinius_icarus_nrf9160_ns_1_4_0.yaml @@ -1,5 +1,5 @@ identifier: actinius_icarus@1.4.0/nrf9160/ns -name: Actinius Icarus Non-Secure +name: Actinius Icarus Non-Secure (rev. 1.4.0) type: mcu arch: arm toolchain: diff --git a/boards/actinius/icarus/actinius_icarus_nrf9160_ns_2_0_0.yaml b/boards/actinius/icarus/actinius_icarus_nrf9160_ns_2_0_0.yaml index e8d9256f3f0c9..a6a5ecc7738bb 100644 --- a/boards/actinius/icarus/actinius_icarus_nrf9160_ns_2_0_0.yaml +++ b/boards/actinius/icarus/actinius_icarus_nrf9160_ns_2_0_0.yaml @@ -1,5 +1,5 @@ identifier: actinius_icarus@2.0.0/nrf9160/ns -name: Actinius Icarus Non-Secure +name: Actinius Icarus Non-Secure (rev. 2.0.0) type: mcu arch: arm toolchain: diff --git a/boards/actinius/icarus_bee/actinius_icarus_bee_common.dtsi b/boards/actinius/icarus_bee/actinius_icarus_bee_common.dtsi index 0bc57cd205acd..f4972923e6907 100644 --- a/boards/actinius/icarus_bee/actinius_icarus_bee_common.dtsi +++ b/boards/actinius/icarus_bee/actinius_icarus_bee_common.dtsi @@ -79,7 +79,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &blue_led; watchdog0 = &wdt0; - spi-flash0 = &w25q64; accel0 = &lis2dh12_accel; }; diff --git a/boards/actinius/icarus_som_dk/actinius_icarus_som_dk_common.dtsi b/boards/actinius/icarus_som_dk/actinius_icarus_som_dk_common.dtsi index 317b0d153b7a7..683edc7bc5793 100644 --- a/boards/actinius/icarus_som_dk/actinius_icarus_som_dk_common.dtsi +++ b/boards/actinius/icarus_som_dk/actinius_icarus_som_dk_common.dtsi @@ -55,7 +55,6 @@ mcuboot-led0 = &blue_led; watchdog0 = &wdt0; accel0 = &lis2dh12_accel; - spi-flash0 = &w25q64; led-strip = &neopixel_led; }; diff --git a/boards/adafruit/feather/adafruit_feather_nrf52840.dts b/boards/adafruit/feather/adafruit_feather_nrf52840.dts index 2333e5becbeda..5c5eba7c503a1 100644 --- a/boards/adafruit/feather/adafruit_feather_nrf52840.dts +++ b/boards/adafruit/feather/adafruit_feather_nrf52840.dts @@ -60,7 +60,6 @@ led1 = &led1; sw0 = &button0; watchdog0 = &wdt0; - spi-flash0 = &gd25q16; }; }; diff --git a/boards/adafruit/feather/adafruit_feather_nrf52840.yaml b/boards/adafruit/feather/adafruit_feather_nrf52840.yaml index 487c78377a13b..332c29857db30 100644 --- a/boards/adafruit/feather/adafruit_feather_nrf52840.yaml +++ b/boards/adafruit/feather/adafruit_feather_nrf52840.yaml @@ -9,7 +9,6 @@ toolchain: supported: - adc - usb_device - - usb_cdc - ble - watchdog - counter diff --git a/boards/adafruit/feather_stm32f405/adafruit_feather_stm32f405.dts b/boards/adafruit/feather_stm32f405/adafruit_feather_stm32f405.dts index cc1cb7020626b..7995e35959307 100644 --- a/boards/adafruit/feather_stm32f405/adafruit_feather_stm32f405.dts +++ b/boards/adafruit/feather_stm32f405/adafruit_feather_stm32f405.dts @@ -31,7 +31,6 @@ aliases { led0 = &led; - spi-flash0 = &gd25q16; }; }; diff --git a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts index 56a31b1310694..af2640954a5f0 100644 --- a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts +++ b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.dts @@ -8,6 +8,7 @@ #include #include "adafruit_itsybitsy_nrf52840-pinctrl.dtsi" #include +#include / { model = "Adafruit ItsyBitsy nRF52840 Express"; @@ -47,7 +48,6 @@ led0 = &led0; sw0 = &button0; watchdog0 = &wdt0; - spi-flash0 = &gd25q16; led-strip = &apa102; }; }; @@ -107,6 +107,10 @@ compatible = "apa,apa102"; reg = <0>; spi-max-frequency = <5250000>; + chain-length = <1>; + color-mapping = ; }; }; diff --git a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.yaml b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.yaml index 3e571954bf1ab..9bf0ea72176c3 100644 --- a/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.yaml +++ b/boards/adafruit/itsybitsy/adafruit_itsybitsy_nrf52840.yaml @@ -16,7 +16,6 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog vendor: adafruit diff --git a/boards/adafruit/itsybitsy_m4_express/support/openocd.cfg b/boards/adafruit/itsybitsy_m4_express/support/openocd.cfg index 096e396efc5f9..4423471225930 100644 --- a/boards/adafruit/itsybitsy_m4_express/support/openocd.cfg +++ b/boards/adafruit/itsybitsy_m4_express/support/openocd.cfg @@ -7,7 +7,7 @@ source [find target/atsame5x.cfg] # TODO(http://openocd.zylin.com/#/c/5706/): lower the clock speed to workaround # an erase timeout. -adapter_khz 500 +adapter speed 500 reset_config srst_only $_TARGETNAME configure -event gdb-attach { diff --git a/boards/adafruit/trinket_m0/adafruit_trinket_m0.dts b/boards/adafruit/trinket_m0/adafruit_trinket_m0.dts index b94b0e1ed7369..21fc54fb9e9a0 100644 --- a/boards/adafruit/trinket_m0/adafruit_trinket_m0.dts +++ b/boards/adafruit/trinket_m0/adafruit_trinket_m0.dts @@ -8,6 +8,7 @@ #include #include #include "adafruit_trinket_m0-pinctrl.dtsi" +#include / { model = "Adafruit Trinket M0"; @@ -87,6 +88,10 @@ compatible = "apa,apa102"; reg = <0>; spi-max-frequency = <24000000>; + chain-length = <1>; + color-mapping = ; }; }; diff --git a/boards/adi/apard32690/Kconfig.apard32690 b/boards/adi/apard32690/Kconfig.apard32690 new file mode 100644 index 0000000000000..44ff6d5d8580b --- /dev/null +++ b/boards/adi/apard32690/Kconfig.apard32690 @@ -0,0 +1,7 @@ +# MAX32690 board configuration + +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_APARD32690 + select SOC_MAX32690_M4 if BOARD_APARD32690_MAX32690_M4 diff --git a/boards/adi/apard32690/Kconfig.defconfig b/boards/adi/apard32690/Kconfig.defconfig new file mode 100644 index 0000000000000..d6fb445a4ed05 --- /dev/null +++ b/boards/adi/apard32690/Kconfig.defconfig @@ -0,0 +1,20 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 +if BOARD_APARD32690 + +config MDIO_INIT_PRIORITY + default 81 + depends on MDIO + +config PHY_INIT_PRIORITY + default 82 + depends on NET_L2_ETHERNET && ETH_DRIVER + +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + +endif # BOARD_APARD32690 diff --git a/boards/adi/apard32690/apard32690_max32690_m4.dts b/boards/adi/apard32690/apard32690_max32690_m4.dts new file mode 100644 index 0000000000000..0de11f8f30de7 --- /dev/null +++ b/boards/adi/apard32690/apard32690_max32690_m4.dts @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include +#include + +/ { + model = "Analog Devices AD-APARD32690-SL"; + compatible = "adi,apard32690"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + blue_led: blue_led { + gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>; + label = "LED1"; + }; + red_led: red_led { + gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + label = "LED2"; + }; + green_led: green_led { + gpios = <&gpio0 11 GPIO_ACTIVE_HIGH>; + label = "LED3"; + }; + }; + + buttons { + compatible = "gpio-keys"; + usr_btn: usr_btn { + gpios = <&gpio1 27 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + label = "S2"; + zephyr,code = ; + }; + }; + + aliases { + led0 = &blue_led; + led1 = &red_led; + led2 = &green_led; + sw0 = &usr_btn; + }; +}; + +&clk_ipo { + status = "okay"; +}; + +&clk_ibro { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; + +&gpio4 { + status = "okay"; +}; + +&uart0 { + clock-source = ; + pinctrl-0 = <&uart0a_tx_p2_12 &uart0a_rx_p2_11>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +arduino_serial: &uart1 { + clock-source = ; + pinctrl-0 = <&uart1a_tx_p2_16 &uart1a_rx_p2_14>; + pinctrl-names = "default"; + current-speed = <115200>; +}; + +arduino_spi: &spi1 { + pinctrl-0 = <&spi1a_miso_p1_28 &spi1a_mosi_p1_29 &spi1a_sck_p1_26 + &spi1a_ss0_p1_23>; + pinctrl-names = "default"; +}; + +&spi3a_miso_p0_20 { + power-source = ; +}; + +&spi3a_mosi_p0_21 { + power-source = ; +}; + +&spi3a_sck_p0_16 { + power-source = ; +}; + +&spi3a_ss0_p0_19 { + power-source = ; +}; + +&spi3 { + pinctrl-0 = <&spi3a_miso_p0_20 &spi3a_mosi_p0_21 &spi3a_sck_p0_16 + &spi3a_ss0_p0_19>; + pinctrl-names = "default"; + status = "okay"; + + adin1110: adin1110@0 { + compatible = "adi,adin1110"; + reg = <0x0>; + spi-max-frequency = ; + int-gpios = <&gpio0 17 (GPIO_ACTIVE_LOW | MAX32_GPIO_VSEL_VDDIOH)>; + reset-gpios = <&gpio0 15 (GPIO_ACTIVE_LOW | MAX32_GPIO_VSEL_VDDIOH)>; + status = "okay"; + + port1 { + local-mac-address = [ 00 E0 22 FE DA C9 ]; + }; + mdio { + compatible = "adi,adin2111-mdio"; + #address-cells = <1>; + #size-cells = <0>; + + ethernet-phy@1 { + reg = <0x1>; + compatible = "adi,adin2111-phy"; + }; + }; + }; +}; diff --git a/boards/adi/apard32690/apard32690_max32690_m4.yaml b/boards/adi/apard32690/apard32690_max32690_m4.yaml new file mode 100644 index 0000000000000..f108af976f17f --- /dev/null +++ b/boards/adi/apard32690/apard32690_max32690_m4.yaml @@ -0,0 +1,16 @@ +identifier: apard32690/max32690/m4 +name: apard32690 m4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - arduino_serial + - arduino_spi + - gpio + - serial + - spi +ram: 1024 +flash: 3072 diff --git a/boards/adi/apard32690/apard32690_max32690_m4_defconfig b/boards/adi/apard32690/apard32690_max32690_m4_defconfig new file mode 100644 index 0000000000000..a048ab2608ff0 --- /dev/null +++ b/boards/adi/apard32690/apard32690_max32690_m4_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/adi/apard32690/board.cmake b/boards/adi/apard32690/board.cmake new file mode 100644 index 0000000000000..409b85f0bc14a --- /dev/null +++ b/boards/adi/apard32690/board.cmake @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32690.cfg]") +board_runner_args(jlink "--device=MAX32690" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/adi/apard32690/board.yml b/boards/adi/apard32690/board.yml new file mode 100644 index 0000000000000..269b578934502 --- /dev/null +++ b/boards/adi/apard32690/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: apard32690 + vendor: adi + socs: + - name: max32690 diff --git a/boards/adi/apard32690/doc/img/apard32690_img.webp b/boards/adi/apard32690/doc/img/apard32690_img.webp new file mode 100644 index 0000000000000..b5d5372230965 Binary files /dev/null and b/boards/adi/apard32690/doc/img/apard32690_img.webp differ diff --git a/boards/adi/apard32690/doc/index.rst b/boards/adi/apard32690/doc/index.rst new file mode 100644 index 0000000000000..78e39723ed6f2 --- /dev/null +++ b/boards/adi/apard32690/doc/index.rst @@ -0,0 +1,216 @@ +.. _ad_apard32690_sl: + +AD-APARD32690-SL +################ + +Overview +******** +The AD-APARD32690-SL is a platform for prototyping intelligent, secure, and connected field devices. +It has an Arduino Mega-compatible form factor and two Pmod-compatible connectors. +The system includes the MAX32690 ARM Cortex-M4 with FPU-Based Microcontroller and Bluetooth LE 5.2. +The MCU is coupled with external RAM (2 x 512 Mb) and Flash (64 Mb) memories to meet the requirements +of the most demanding applications. The MAXQ1065 security coprocessor enables state of the art +security features such as for root-of-trust, mutual authentication, data confidentiality and +integrity, secure boot, and secure communications. +A 10 Mbps single-pair Ethernet link using the ADIN1110 10BASE-T1L MAC/PHY, enables remote +data acquisition and system configuration. The 10BASE-T1L interface also supports Single-pair +Power over Ethernet (SPoE) and be used for powering the system via an Arduino shield implementing +the required power circuitry. + +The Zephyr port is running on the MAX32690 MCU. + +.. image:: img/apard32690_img.webp + :align: center + :alt: AD-APARD32690-SL Front + +Hardware +******** + +- MAX32690 MCU: + + - Ultra-Efficient Microcontroller for Battery-Powered Applications + + - 120MHz Arm Cortex-M4 Processor with FPU + - 7.3728MHz and 60MHz Low-Power Oscillators + - External Crystal Support (32MHz required for BLE) + - 32.768kHz RTC Clock (Requires External Crystal) + - 8kHz Always-On Ultra-Low Power Oscillator + - 3MB Internal Flash, 1MB Internal SRAM (832kB ECC ON) + - TBDμW/MHz Executing from Cache at 1.1V + - 1.8V and 3.3V I/O with No Level Translators + - External Flash & SRAM Expansion Interfaces + + - Bluetooth 5.2 LE Radio + + - Dedicated, Ultra-Low-Power, 32-Bit RISC-V Coprocessor to Offload Timing-Critical Bluetooth Processing + - Fully Open-Source Bluetooth 5.2 Stack Available + - Supports AoA, AoD, LE Audio, and Mesh + - High-Throughput (2Mbps) Mode + - Long-Range (125kbps and 500kbps) Modes + - Rx Sensitivity: -97.5dBm; Tx Power: +4.5dBm + - Single-Ended Antenna Connection (50Ω) + + - Multiple Peripherals for System Control + + - 16-Channel DMA + - Up To Five Quad SPI Master (60MHz)/Slave (48MHz) + - Up To Four 1Mbaud UARTs with Flow Control + - Up To Two 1MHz I2C Master/Slave + - I2S Master/Slave + - Eight External Channel, 12-bit 1MSPS SAR ADC w/ on-die temperature sensor + - USB 2.0 Hi-Speed Device + - 16 Pulse Train Engines + - Up To Six 32-Bit Timers with 8mA High Drive + - Up To Two CAN 2.0 Controllers + - Up To Four Micro-Power Comparators + - 1-Wire Master + + - Security and Integrity + + - ChipDNA Physically Un-clonable Function (PUF) + - Modular Arithmetic Accelerator (MAA), True Random Number Generator (TRNG) + - Secure Nonvolatile Key Storage, SHA-256, AES-128/192/256 + - Secure Boot ROM + +- External devices connected to the APARD32690: + + - On-Board HyperRAM + - On-Board SPI Flash + - USB 2.0 Type-C interface to the MAX32690 + - SPI PMOD connector + - I2C PMOD connector + - SWD 10-Pin Header + - On-Board Bluetooth 5.2 LE Radio antenna + - MAXQ1065 Ultralow Power Cryptographic Controller with ChipDNA + - ADIN1110 Robust, Industrial, Low Power 10BASE-T1L Ethernet MAC-PHY + - U-Blox NINA-W102 802.11b/g/n module with dual-mode Bluetooth v4.2 + - On-Board 5V, 3.3V, 1.8V, and 1.1V voltage regulators + - 2-Pin external power supply terminal block (5V - 28V DC) + - Board Power Provided by either the USB Port or the 2-Pin connector + - Arduino Mega compatible header. + - Two general-purpose LEDs and one general purpose push button. + + +Supported Features +================== + +Below interfaces are supported by Zephyr on APARD32690. + ++-----------+------------+------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+------------------------------------+ +| ADIN1110 | spi | ADIN1110 10BASE-T1L mac/phy | ++-----------+------------+------------------------------------+ + + +Connections and IOs +=================== + ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| Name | Name | Settings | Description | ++===========+===============+===============+==================================================================================================+ +| P55 | SWD TX | | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the SWD UART TX to the (UART) RX port of the U-Blox Nina W102. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the SWD UART TX to the UART0 TX pin of the MAX32690. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| P50 | SWD RX | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the SWD UART RX to the (UART) TX port of the U-Blox Nina W102. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the SWD UART RX to the UART0 RX pin of the MAX32690. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| P51 | SWD POW | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the SWD Vcc pin to 3.3V. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the SWD Vcc pin to 1.8V. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| P38 | UART RX WIFI | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connect the U-Blox Nina W102 UART RX to the UART2A TX pin of the MAX32690 | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects the U-Blox Nina W102 UART RX from the UART2A TX pin | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| P58 | UART TX WIFI | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connect the U-Blox Nina W102 UART TX to the UART2A RX pin of the MAX32690. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects the U-Blox Nina W102 UART TX from the UART2A RX pin. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| S4 | SW1 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | On | | | Pulls the ADIN1110's SWPD_EN pin to 3.3V through a resistor. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Off | | | Leaves the ADIN1110's SWPD_EN pin floating. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| S4 | SW2 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | On | | | Pulls the ADIN1110's CFG0 pin to 3.3V through a resistor. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Off | | | Leaves the ADIN1110's CFG0 pin floating. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| S4 | SW3 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | On | | | Pulls the ADIN1110's CFG1 pin to 3.3V through a resistor. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Off | | | Leaves the ADIN1110's CFG1 pin floating. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ + + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32690 MCU can be flashed by connecting an external debug probe to the +SWD port. SWD debug can be accessed through the Cortex 10-pin connector, P9. +Logic levels are either 1.8V or 3.3V (based on P51 selection). + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +.. note:: + + This board uses OpenOCD as the default debug interface. You can also use + a Segger J-Link with Segger's native tooling by overriding the runner, + appending ``--runner jlink`` to your ``west`` command(s). The J-Link should + be connected to the standard 2*5 pin debug connector (P9) using an + appropriate adapter board and cable. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `AD-APARD32690-SL web page`_ + +.. _AD-APARD32690-SL web page: + https://www.analog.com/en/resources/evaluation-hardware-and-software/evaluation-boards-kits/ad-apard32690-sl.html diff --git a/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts b/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts index 00f00777a2371..3b6934062e9cd 100644 --- a/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts +++ b/boards/adi/eval_adin1110ebz/adi_eval_adin1110ebz.dts @@ -34,19 +34,19 @@ leds { /* Respecting pcb silkscreen naming */ compatible = "gpio-leds"; green_led: led_uC0 { - gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; label = "Status uC0"; }; red_led: led_uC1 { - gpios = <&gpioe 2 GPIO_ACTIVE_HIGH>; + gpios = <&gpioe 2 GPIO_ACTIVE_LOW>; label = "Status uC1 "; }; yellow_led: led_uC2 { - gpios = <&gpioe 6 GPIO_ACTIVE_HIGH>; + gpios = <&gpioe 6 GPIO_ACTIVE_LOW>; label = "Status uC2"; }; blue_led: led_uC3 { - gpios = <&gpiog 15 GPIO_ACTIVE_HIGH>; + gpios = <&gpiog 15 GPIO_ACTIVE_LOW>; label = "Status uC3"; }; }; @@ -54,7 +54,6 @@ aliases { led0 = &green_led; watchdog0 = &iwdg; - spi-flash0 = &mx25r6435f; ambient-temp0 = &adt7420; }; diff --git a/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts b/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts index 5db24f04e80da..3a990815857f0 100644 --- a/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts +++ b/boards/adi/eval_adin2111ebz/adi_eval_adin2111ebz.dts @@ -24,23 +24,23 @@ leds { compatible = "gpio-leds"; blue_led: uC_led1 { - gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>; + gpios = <&gpiob 6 GPIO_ACTIVE_LOW>; label = "Debug led uC1"; }; net_red_led: led_NET1 { - gpios = <&gpiob 10 GPIO_ACTIVE_HIGH>; + gpios = <&gpiob 10 GPIO_ACTIVE_LOW>; label = "NET led 1"; }; net_green_led: led_NET2 { - gpios = <&gpiob 11 GPIO_ACTIVE_HIGH>; + gpios = <&gpiob 11 GPIO_ACTIVE_LOW>; label = "NET led 2"; }; mod_red_led: led_MOD1 { - gpios = <&gpioe 2 GPIO_ACTIVE_HIGH>; + gpios = <&gpioe 2 GPIO_ACTIVE_LOW>; label = "Mod led 1"; }; mod_green_led: led_MOD2 { - gpios = <&gpioe 6 GPIO_ACTIVE_HIGH>; + gpios = <&gpioe 6 GPIO_ACTIVE_LOW>; label = "Mod led 2"; }; }; @@ -48,7 +48,6 @@ aliases { led0 = &blue_led; watchdog0 = &iwdg; - spi-flash0 = &flash_ext; }; }; diff --git a/boards/adi/max32655evkit/Kconfig.max32655evkit b/boards/adi/max32655evkit/Kconfig.max32655evkit new file mode 100644 index 0000000000000..2eed6e48c6089 --- /dev/null +++ b/boards/adi/max32655evkit/Kconfig.max32655evkit @@ -0,0 +1,7 @@ +# MAX32655EVKIT boards configuration + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32655EVKIT + select SOC_MAX32655_M4 if BOARD_MAX32655EVKIT_MAX32655_M4 diff --git a/boards/adi/max32655evkit/board.cmake b/boards/adi/max32655evkit/board.cmake new file mode 100644 index 0000000000000..965de9e4de2aa --- /dev/null +++ b/boards/adi/max32655evkit/board.cmake @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32655.cfg]") +board_runner_args(jlink "--device=MAX32655" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/adi/max32655evkit/board.yml b/boards/adi/max32655evkit/board.yml new file mode 100644 index 0000000000000..4824c6fe8e596 --- /dev/null +++ b/boards/adi/max32655evkit/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32655evkit + vendor: adi + socs: + - name: max32655 diff --git a/boards/adi/max32655evkit/doc/img/max32655evkit_img1.jpg b/boards/adi/max32655evkit/doc/img/max32655evkit_img1.jpg new file mode 100644 index 0000000000000..3b449c043495b Binary files /dev/null and b/boards/adi/max32655evkit/doc/img/max32655evkit_img1.jpg differ diff --git a/boards/adi/max32655evkit/doc/img/max32655evkit_img2.jpg b/boards/adi/max32655evkit/doc/img/max32655evkit_img2.jpg new file mode 100644 index 0000000000000..12b6444e361d5 Binary files /dev/null and b/boards/adi/max32655evkit/doc/img/max32655evkit_img2.jpg differ diff --git a/boards/adi/max32655evkit/doc/index.rst b/boards/adi/max32655evkit/doc/index.rst new file mode 100644 index 0000000000000..30ee39c9ce003 --- /dev/null +++ b/boards/adi/max32655evkit/doc/index.rst @@ -0,0 +1,177 @@ +.. _max32655_evkit: + +MAX32655EVKIT +############# + +Overview +******** +The MAX32655 evaluation kit (EV kit) provides a platform for evaluation capabilities +of the MAX32655 microcontroller, which is an advanced system-on-chip (SoC). +It features an Arm® Cortex®-M4F CPU for efficient computation of complex functions and +algorithms, integrated power management (SIMO), and the newest generation +Bluetooth® 5.0 Low Energy (Bluetooth LE), long-range radio for wearable and hearable device applications. + +The Zephyr port is running on the MAX32655 MCU. + +.. image:: img/max32655evkit_img1.jpg + :align: center + :alt: MAX32655 EVKIT Front + +.. image:: img/max32655evkit_img2.jpg + :align: center + :alt: MAX32655 Back + +Hardware +******** + +- MAX32655 MCU: + + - Ultra-Low-Power Wireless Microcontroller + - Internal 100MHz Oscillator + - Flexible Low-Power Modes with 7.3728MHz System Clock Option + - 512KB Flash and 128KB SRAM (Optional ECC on One 32KB SRAM Bank) + - 16KB Instruction Cache + - Bluetooth 5.2 LE Radio + - Dedicated, Ultra-Low-Power, 32-Bit RISC-V Coprocessor to Offload Timing-Critical Bluetooth Processing + - Fully Open-Source Bluetooth 5.2 Stack Available + - Supports AoA, AoD, LE Audio, and Mesh + - High-Throughput (2Mbps) Mode + - Long-Range (125kbps and 500kbps) Modes + - Rx Sensitivity: -97.5dBm; Tx Power: +4.5dBm + - Single-Ended Antenna Connection (50Ω) + - Power Management Maximizes Battery Life + - 2.0V to 3.6V Supply Voltage Range + - Integrated SIMO Power Regulator + - Dynamic Voltage Scaling (DVS) + - 23.8μA/MHz Active Current at 3.0V + - 4.4μA at 3.0V Retention Current for 32KB + - Selectable SRAM Retention + RTC in Low-Power Modes + - Multiple Peripherals for System Control + - Up to Two High-Speed SPI Master/Slave + - Up to Three High-Speed I2C Master/Slave (3.4Mbps) + - Up to Four UART, One I2S Master/Slave + - Up to 8-Input, 10-Bit Sigma-Delta ADC 7.8ksps + - Up to Four Micro-Power Comparators + - Timers: Up to Two Four 32-Bit, Two LP, TwoWatchdog Timers + - 1-Wire® Master + - Up to Four Pulse Train (PWM) Engines + - RTC with Wake-Up Timer + - Up to 52 GPIOs + - Security and Integrity​ + - Available Secure Boot + - TRNG Seed Generator + - AES 128/192/256 Hardware Acceleration Engine + +- External devices connected to the MAX32655 EVKIT: + + - Color TFT Display + - Audio Stereo Codec Interface + - Digital Microphone + - A 128Mb QSPI flash + +Supported Features +================== + +Below are the interfaces supported by Zephyr on MAX32655EVKIT. + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + +Connections and IOs +=================== + ++-----------+---------------+-----------------------------------------------------------------------+ +| Name | Signal | Usage | ++===========+===============+=======================================================================+ +| JP1 | VREGI | Connect/Disconnect VREGIO power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP2 | P0_24 | Enable/Disable LED1 | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP3 | P0_25 | Enable/Disable LED2 | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP4 | P2_6/ P2_7 | Connect/Disconnect the USB to serial UART to GPIO P2_6 (LPUART_RX) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP5 | P2_7/ P0_1 | Connect/Disconnect the USB to serial UART to GPIO P2_7 (LPUART_TX) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP6 | P0_2 | Connect/Disconnect the USB to serial UART to GPIO P0_2 (UART0_CTS) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP7 | P0_3 | Connect/Disconnect he USB to serial UART to GPIO P0_3 (UART0_RTS) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP8 | VREGI | Select VDDIO_EN power source (3V3 or coin cell) | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP9 | VDDIOH_EN | Select VDDIOH_EN power source 3V3/VREGI | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP10 | VDDIOH | Connect/Disconnect VDDIOH power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP11 | VDDIO_EN | Select VDDIO_EN power source 1V8/VREGO_A | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP12 | VDDIO | Connect/Disconnect VDDIO power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP13 | VDDA_EN | Select VDDA_EN power source 1V8/VREGO_A | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP14 | VDDA | Connect/Disconnect VDDA power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP15 | VCOREA_EN | Select VCOREA_EN power source 1V1/VREGO_C | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP16 | VCOREA | Connect/Disconnect VCOREA power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP17 | VCOREB_EN | Select VCOREB_EN power source 1V1/VREGO_B | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP18 | VCOREB | Connect/Disconnect VCOREB power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP19 | BLE_LDO | Connect/Disconnect BLE_LDO power | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP20 | VREF | Select VREF power source VDDIO/VDDIOH | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP21 | I2C0_PU | Select I2C0_PU power source VDDIO/VDDIOH | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP22 | I2C1_PU | Select I2C1_PU power source VDDIO/VDDIOH | ++-----------+---------------+-----------------------------------------------------------------------+ +| JP23 | BOARD RESET | Connect/Disconnect RV JTAG NRESET from the BOARD RESET circuitry | ++-----------+---------------+-----------------------------------------------------------------------+ + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32655 MCU can be flashed by connecting an external debug probe to the +SWD port. SWD debug can be accessed through the Cortex 10-pin connector, JH3. +Logic levels are fixed to VDDIO (1.8V). + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +.. note:: + + This board uses OpenOCD as the default debug interface. You can also use + a Segger J-Link with Segger's native tooling by overriding the runner, + appending ``--runner jlink`` to your ``west`` command(s). The J-Link should + be connected to the standard 2*5 pin debug connector (JW3) using an + appropriate adapter board and cable. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `MAX32655EVKIT web page`_ + +.. _MAX32655EVKIT web page: + https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/max32655evkit.html#eb-overview diff --git a/boards/adi/max32655evkit/max32655evkit_max32655_m4.dts b/boards/adi/max32655evkit/max32655evkit_max32655_m4.dts new file mode 100644 index 0000000000000..b1323a9bd3cd8 --- /dev/null +++ b/boards/adi/max32655evkit/max32655evkit_max32655_m4.dts @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + + #include + #include + #include + +/ { + model = "Analog Devices MAX32655EVKIT"; + compatible = "adi,max32655evkit"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram2; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 18 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + }; + pb2: pb2 { + gpios = <&gpio0 19 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW3"; + }; + pb_wakeup: pb_wakeup { + gpios = <&gpio3 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW + | MAX32_GPIO_VSEL_VDDIOH)>; + label = "Wakeup"; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + sw0 = &pb1; + sw1 = &pb2; + }; +}; + +&uart0 { + pinctrl-0 = <&uart0a_tx_p0_1 &uart0a_rx_p0_0>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; diff --git a/boards/adi/max32655evkit/max32655evkit_max32655_m4.yaml b/boards/adi/max32655evkit/max32655evkit_max32655_m4.yaml new file mode 100644 index 0000000000000..257a0d060a940 --- /dev/null +++ b/boards/adi/max32655evkit/max32655evkit_max32655_m4.yaml @@ -0,0 +1,13 @@ +identifier: max32655evkit/max32655/m4 +name: max32655evkit m4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 128 +flash: 512 diff --git a/boards/adi/max32655evkit/max32655evkit_max32655_m4_defconfig b/boards/adi/max32655evkit/max32655evkit_max32655_m4_defconfig new file mode 100644 index 0000000000000..4fa0a46410634 --- /dev/null +++ b/boards/adi/max32655evkit/max32655evkit_max32655_m4_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/adi/max32655fthr/Kconfig.max32655fthr b/boards/adi/max32655fthr/Kconfig.max32655fthr new file mode 100644 index 0000000000000..589209a2fb3e2 --- /dev/null +++ b/boards/adi/max32655fthr/Kconfig.max32655fthr @@ -0,0 +1,7 @@ +# MAX32655FTHR boards configuration + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32655FTHR + select SOC_MAX32655_M4 if BOARD_MAX32655FTHR_MAX32655_M4 diff --git a/boards/adi/max32655fthr/board.cmake b/boards/adi/max32655fthr/board.cmake new file mode 100644 index 0000000000000..d2353452cbe3c --- /dev/null +++ b/boards/adi/max32655fthr/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32655.cfg]") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/adi/max32655fthr/board.yml b/boards/adi/max32655fthr/board.yml new file mode 100644 index 0000000000000..087b51d8d958c --- /dev/null +++ b/boards/adi/max32655fthr/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32655fthr + vendor: adi + socs: + - name: max32655 diff --git a/boards/adi/max32655fthr/doc/img/max32655fthr_img1.jpg b/boards/adi/max32655fthr/doc/img/max32655fthr_img1.jpg new file mode 100644 index 0000000000000..075a68e15fb6d Binary files /dev/null and b/boards/adi/max32655fthr/doc/img/max32655fthr_img1.jpg differ diff --git a/boards/adi/max32655fthr/doc/img/max32655fthr_img2.jpg b/boards/adi/max32655fthr/doc/img/max32655fthr_img2.jpg new file mode 100644 index 0000000000000..9976dfd48c4ba Binary files /dev/null and b/boards/adi/max32655fthr/doc/img/max32655fthr_img2.jpg differ diff --git a/boards/adi/max32655fthr/doc/img/max32655fthr_img3.jpg b/boards/adi/max32655fthr/doc/img/max32655fthr_img3.jpg new file mode 100644 index 0000000000000..f523ef2aed256 Binary files /dev/null and b/boards/adi/max32655fthr/doc/img/max32655fthr_img3.jpg differ diff --git a/boards/adi/max32655fthr/doc/index.rst b/boards/adi/max32655fthr/doc/index.rst new file mode 100644 index 0000000000000..f6ba1b94f5929 --- /dev/null +++ b/boards/adi/max32655fthr/doc/index.rst @@ -0,0 +1,193 @@ +.. _max32655_fthr: + +MAX32655FTHR +############ + +Overview +******** +The MAX32655FTHR is a rapid development platform to help engineers quickly implement +ultra low-power wireless solutions using MAX32655 Arm© Cortex®-M4F and Bluetooth® 5.2 Low Energy (LE). +The board also includes the MAX20303 PMIC for battery and power management. +The form factor is a small 0.9in x 2.6in dual-row header footprint that is compatible +with Adafruit Feather Wing peripheral expansion boards. The board includes a variety of peripherals, +such as a digital microphone, lowpower stereo audio CODEC, 128MB QSPI Flash, micro SD card connector, +RGB indicator LED, and pushbutton. +The MAX32655FTHR provides a power-optimized flexible platform for quick proof-of-concepts and +early software development to enhance time to market. Go to +https://www.analog.com/MAX32655FTHR to get started developing with this board. + + +The Zephyr port is running on the MAX32655 MCU. + +.. image:: img/max32655fthr_img1.jpg + :align: center + :alt: MAX32655FTHR Front + +.. image:: img/max32655fthr_img2.jpg + :align: center + :alt: MAX32655FTHR Front Modules + +.. image:: img/max32655fthr_img3.jpg + :align: center + :alt: MAX32655FTHR Back + +Hardware +******** + +- MAX32655 MCU: + + - Ultra-Low-Power Wireless Microcontroller + - Internal 100MHz Oscillator + - Flexible Low-Power Modes with 7.3728MHz System Clock Option + - 512KB Flash and 128KB SRAM (Optional ECC on One 32KB SRAM Bank) + - 16KB Instruction Cache + - Bluetooth 5.2 LE Radio + - Dedicated, Ultra-Low-Power, 32-Bit RISC-V Coprocessor to Offload Timing-Critical Bluetooth Processing + - Fully Open-Source Bluetooth 5.2 Stack Available + - Supports AoA, AoD, LE Audio, and Mesh + - High-Throughput (2Mbps) Mode + - Long-Range (125kbps and 500kbps) Modes + - Rx Sensitivity: -97.5dBm; Tx Power: +4.5dBm + - Single-Ended Antenna Connection (50Ω) + - Power Management Maximizes Battery Life + - 2.0V to 3.6V Supply Voltage Range + - Integrated SIMO Power Regulator + - Dynamic Voltage Scaling (DVS) + - 23.8μA/MHz Active Current at 3.0V + - 4.4μA at 3.0V Retention Current for 32KB + - Selectable SRAM Retention + RTC in Low-Power Modes + - Multiple Peripherals for System Control + - Up to Two High-Speed SPI Master/Slave + - Up to Three High-Speed I2C Master/Slave (3.4Mbps) + - Up to Four UART, One I2S Master/Slave + - Up to 8-Input, 10-Bit Sigma-Delta ADC 7.8ksps + - Up to Four Micro-Power Comparators + - Timers: Up to Two Four 32-Bit, Two LP, TwoWatchdog Timers + - 1-Wire® Master + - Up to Four Pulse Train (PWM) Engines + - RTC with Wake-Up Timer + - Up to 52 GPIOs + - Security and Integrity​ + - Available Secure Boot + - TRNG Seed Generator + - AES 128/192/256 Hardware Acceleration Engine + +- External devices connected to the MAX32655FTHR: + + - Audio Stereo Codec Interface + - Digital Microphone + - PMIC and Battery Charger + - A 128Mb QSPI flash + - Micro SDCard Interface + - RGB LEDs + - Push Buttons + +Supported Features +================== + +Below are the interfaces supported by Zephyr on MAX32655FTHR. + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + +Push Buttons +************ +There are six pushbuttons on the MAX32655FTHR board + +SW1 +=== +PMIC Power Button, when the board is powered on state, pressing +this button for 12 seconds performs a hard powerdown. +When the board is in a powered-off state, pressing this button powers on the board. +This button can also be read by MAX32655 firmware, PMIC_PFN2 signal connected to Port 0.13 +is a buffered input of the button status. When the button is pressed, this signal goes to a logic-low +state. + +SW2 +=== +User-programmable function button connected to +MAX32655 Port 0.2 through a debouncer IC. + +SW3 +=== +User-programmable function button connected to +MAX32655 Port 0.3 through a debouncer IC. + +SW4 +=== +Wake-up button connected to MAX32655 Port 3.1. + +SW5 +=== +Resets the MAX32655 through RSTN input of the MAX32655. + +SW6 +=== +DAPLink adapter button. Keep this button +pressed while applying power to the board to +put the MAX32625 DAPLink adapter on board +to MAINTENANCE mode for DAPLink firmware +updates. + + +LEDs +**** +There are three RGB LEDs on the MAX32655FTHR board + +LED1 (D1) +========= +Connected to the MAX32655FTHR GPIO ports. +This LED can be controlled by user firmware. +Port 0.18: Red color +Port 0.19: Green color +Port 0.26: Blue color + +LED2 (D2) +========= +Connected to MAX20303 PMIC LEDx outputs. +These LEDs can be controlled through I2C commands. +They also can be configured as charge +status indicators by issuing I2C commands. + +LED3 (D3) +========= +DAPLink adapter MAX32625 status LED. +Controlled by the DAPLink adapter and cannot be +used as a user LED. + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32625 microcontroller on the board is flashed with DAPLink firmware at the factory. +It allows debugging and flashing the MAX32655 Arm Core over USB. + +Once the USB cable is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `MAX32655FTHR web page`_ + +.. _MAX32655FTHR web page: + https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/max32655fthr.html diff --git a/boards/adi/max32655fthr/max32655fthr_max32655_m4.dts b/boards/adi/max32655fthr/max32655fthr_max32655_m4.dts new file mode 100644 index 0000000000000..256e433091de2 --- /dev/null +++ b/boards/adi/max32655fthr/max32655fthr_max32655_m4.dts @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include + +/ { + model = "Analog Devices MAX32655FTHR"; + compatible = "adi,max32655fthr"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram2; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 19 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + led3: led_3 { + gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 2 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + }; + pb2: pb2 { + gpios = <&gpio0 3 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW3"; + }; + pb_wakeup: pb_wakeup { + gpios = <&gpio3 1 (GPIO_PULL_UP | GPIO_ACTIVE_LOW + | MAX32_GPIO_VSEL_VDDIOH)>; + label = "Wakeup"; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + led2 = &led3; + sw0 = &pb1; + sw1 = &pb2; + }; + + /* Used for accessing other pins */ + feather_header: feather_connector { + compatible = "adafruit-feather-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <12 0 &gpio0 31 0>, /* SDA */ + <13 0 &gpio0 30 0>, /* SCL */ + <14 0 &gpio1 9 0>, /* GPIO */ + <15 0 &gpio1 8 0>, /* GPIO */ + <16 0 &gpio0 20 0>, /* GPIO */ + <17 0 &gpio0 24 0>, /* GPIO */ + <18 0 &gpio0 25 0>, /* GPIO */ + <19 0 &gpio1 7 0>, /* GPIO */ + <20 0 &gpio1 6 0>, /* GPIO */ + /* 11 not connected */ + <10 0 &gpio2 7 0>, /* TX */ + <9 0 &gpio2 6 0>, /* RX */ + <8 0 &gpio0 22 0>, /* MISO */ + <7 0 &gpio0 21 0>, /* MOSI */ + <6 0 &gpio0 23 0>, /* SCK */ + <5 0 &gpio2 5 0>, /* AIN5 */ + <4 0 &gpio2 4 0>, /* AIN4 */ + <3 0 &gpio2 3 0>, /* AIN3 */ + <2 0 &gpio2 2 0>, /* AIN2 */ + <1 0 &gpio2 1 0>, /* AIN1 */ + <0 0 &gpio2 0 0>; /* AIN0 */ + }; +}; + +&uart0 { + pinctrl-0 = <&uart0a_tx_p0_1 &uart0a_rx_p0_0>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; diff --git a/boards/adi/max32655fthr/max32655fthr_max32655_m4.yaml b/boards/adi/max32655fthr/max32655fthr_max32655_m4.yaml new file mode 100644 index 0000000000000..af17994f344e7 --- /dev/null +++ b/boards/adi/max32655fthr/max32655fthr_max32655_m4.yaml @@ -0,0 +1,13 @@ +identifier: max32655fthr/max32655/m4 +name: max32655fthr m4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 128 +flash: 512 diff --git a/boards/adi/max32655fthr/max32655fthr_max32655_m4_defconfig b/boards/adi/max32655fthr/max32655fthr_max32655_m4_defconfig new file mode 100644 index 0000000000000..4fa0a46410634 --- /dev/null +++ b/boards/adi/max32655fthr/max32655fthr_max32655_m4_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/adi/max32672evkit/Kconfig.max32672evkit b/boards/adi/max32672evkit/Kconfig.max32672evkit new file mode 100644 index 0000000000000..4b7207a0c90e4 --- /dev/null +++ b/boards/adi/max32672evkit/Kconfig.max32672evkit @@ -0,0 +1,7 @@ +# MAX32672EVKIT boards configuration + +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32672EVKIT + select SOC_MAX32672 diff --git a/boards/adi/max32672evkit/board.cmake b/boards/adi/max32672evkit/board.cmake new file mode 100644 index 0000000000000..454ec897d2a69 --- /dev/null +++ b/boards/adi/max32672evkit/board.cmake @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32672.cfg]") +board_runner_args(jlink "--device=MAX32672" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/adi/max32672evkit/board.yml b/boards/adi/max32672evkit/board.yml new file mode 100644 index 0000000000000..5df99f681bf3c --- /dev/null +++ b/boards/adi/max32672evkit/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32672evkit + vendor: adi + socs: + - name: max32672 diff --git a/boards/adi/max32672evkit/doc/img/max32672evkit.webp b/boards/adi/max32672evkit/doc/img/max32672evkit.webp new file mode 100644 index 0000000000000..9b9e2245d3832 Binary files /dev/null and b/boards/adi/max32672evkit/doc/img/max32672evkit.webp differ diff --git a/boards/adi/max32672evkit/doc/index.rst b/boards/adi/max32672evkit/doc/index.rst new file mode 100644 index 0000000000000..fd0a4e2fb7fa7 --- /dev/null +++ b/boards/adi/max32672evkit/doc/index.rst @@ -0,0 +1,341 @@ +.. _max32672_evkit: + +MAX32672EVKIT +############# + +Overview +******** +The MAX32672 evaluation kit (EV kit) provides a platform for evaluating the capabilities +of the MAX32672 microcontroller, which is a small, high-reliability, ultra-low power, +32-bit microcontroller. The MAX32672 is a secure and cost-effective solution +for motion/motor control, industrial sensors, and battery-powered medical devices and offers legacy +designs an easy, cost-optimal upgrade path from 8-bit or 16-bit microcontrollers. + +The Zephyr port is running on the MAX32672 MCU. + +.. image:: img/max32672evkit.webp + :align: center + :alt: MAX32672EVKIT + +Hardware +******** + +- MAX32672 MCU: + + - High-Efficiency Microcontroller for Low-Power High-Reliability Devices + + - Arm Cortex-M4 Processor with FPU up to 100MHz + - 1MB Dual-Bank Flash with Error Correction + - 200KB SRAM (160KB with ECC Enabled), Optionally Preserved in Lowest Power Modes + - EEPROM Emulation on Flash + - 16KB Unified Cache with ECC + - Resource Protection Unit (RPU) and MemoryProtection Unit (MPU) + - Dual- or Single-Supply Operation, 1.7V to 3.6V + - Wide Operating Temperature: -40°C to +105°C + + - Flexible Clocking Schemes + + - Internal High-Speed 100MHz Oscillator + - Internal Low-Power 7.3728MHz and Ultra-Low-Power 80kHz Oscillators + - 16MHz–32MHz Oscillator, 32.768kHz Oscillator(External Crystal Required) + - External Clock Input for CPU, LPUART, LPTMR + + - Power Management Maximizes Uptime for Battery Applications + + - 59.8μA/MHz ACTIVE at 0.9V up to 12MHz(CoreMark®) + - 56.6μA/MHz ACTIVE at 1.1V up to 100MHz(While(1)) + - 3.09μA Full Memory Retention Power in BACKUPMode at VDD = 1.8V + - 350nA Ultra-Low-Power RTC at + - Wake from LPUART or LPTMR + + - Optimal Peripheral Mix Provides Platform Scalability + + - Up to 42 General-Purpose I/O Pins + - Up to Three SPI Master/Slave (up to 50Mbps) + - Up to Three 4-Wire UART + - Up to Three I2C Master/Slave 3.4Mbps High Speed + - Up to Four 32-Bit Timers (TMR) + - Up to Two Low-Power 32-Bit Timers (LPTMR) + - One I2S Master/Slave for Digital Audio Interface + - 12-Channel, 12-Bit, 1Msps SAR ADC with On-DieTemperature Sensor + + - Security and Integrity + + - Optional ECDSA-Based Cryptographic SecureBootloader in ROM + - Secure Cryptographic Accelerator for Elliptic Curve + - AES-128/192/256 Hardware Acceleration Engine + +- Benefits and Features of MAX32672EVKIT: + + - Selectable, On-Board, High-Precision Voltage Reference + - 128 x 128 (1.45in) Color TFT Display with SPI Interface + - Breadboard-Compatible Headers + - USB 2.0 Micro B-to-Serial UARTs + - UART0 and LPUART0 Interface Is Selectable through On-Board Jumpers + - All GPIOs Signals Accessed through 0.1in Headers + - 12 Analog Inputs Accessed through 0.1in Headers with Optional Filtering + - 10-Pin Arm® Cortex® SWD Connector + - Board Power Provided by USB Port + - On-Board, 3.3V LDO Regulator + - Test Loops Provided to Supply Optional VCORE Power Externally + - Individual Power Measurement on All IC Rails through Jumpers + - Two General-Purpose LEDs and One General-Purpose Pushbutton Switch + +Supported Features +================== + +Below interfaces are supported by Zephyr on MAX32672EVKIT. + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + + +Connections and IOs +=================== + ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| Name | Name | Settings | Description | ++===========+===============+===============+==================================================================================================+ +| JP1 | VREF | | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects on-board, high-precision voltage reference. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects on-board, high-precision voltage reference. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP2 | P0_22 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects red LED D1 from P0_22. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects red LED D1 to P0_22. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP3 | P0_23 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects green LED D2 from P0_23. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects green LED D2 to P0_23. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP4 | I2C0_SCL | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 2.2K pullup sourced by 3V3 from I2C0_SCL. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects 2.2K pullup sourced by 3V3 to I2C0_SCL. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP5 | I2C0_SDA | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 2.2K pullup sourced by 3V3 from I2C0_SDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects 2.2K pullup sourced by 3V3 to I2C0_SDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP6 | I2C1_SCL | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 2.2K pullup sourced by 3V3 from I2C1_SCL. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects 2.2K pullup sourced by 3V3 to I2C1_SCL. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP7 | I2C1_SDA | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 2.2K pullup sourced by 3V3 from I2C1_SDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects 2.2K pullup sourced by 3V3 to I2C1_SDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP8 | I2C2_SCL | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 2.2K pullup sourced by 3V3 from I2C2_SCL. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects 2.2K pullup sourced by 3V3 to I2C2_SCL. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP9 | I2C2_SDA | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 2.2K pullup sourced by 3V3 from I2C2_SDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects 2.2K pullup sourced by 3V3 to I2C2_SDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP10 | UART_RX | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects the USB serial bridge to UART0_RX (P0.8). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the USB serial bridge to LUART0_RX (P0.26). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP11 | UART_TX | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects the USB serial bridge to UART0_TX (P0.9). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the USB serial bridge to LUART0_TX (P0.27). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP12 | VDDA | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects power from VDDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects power to VDDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP13 | VDD | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects power from VDD. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects power to VDD. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP14 | VCORE | +-----------+ | +----------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects power from VCORE from an external power supply through test loop TP6.| | +| | | +-----------+ | +----------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects power to VCORE from an external power supply through test loop TP6. | | +| | | +-----------+ | +----------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP15 | LDO DUT | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects power from 3.3V LDO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects power to 3.3V LDO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ + + +Detailed Description of Hardware +================================ + +Power Supply +************ + +The EV kit is powered by +5V, which is made available through VBUS on the Micro USB type-B +connector CN1. The blue VBUS LED (DS1) and the green 3.3V LED will illuminate +when the board is powered. + +Single- or Dual-Supply Operation +******************************** + +The EV kit is configured for single-supply operation. For dual-supply operation, +install a jumper on JP14 and connect an external supply to TP6 (VCORE_EXT) and ground. +Refer to the MAX32672 data sheet for acceptable voltage values. + +Current Monitoring +****************** + +Two pin headers provide convenient current monitoring points for VDDA EN (JP12), VDD EN (JP13), +and VCORE EN (JP14). JP14 is only used for current measurements when VCORE is supplied externally. + +Low-Power Mode Current Measurements +*********************************** + +To accurately achieve the low-power current values, the EV kit must be configured such that +no outside influence (such as a pullup, external clock, or debugger connector) causes +a current source or sink on that GPIO. For these measurements, the board will be needed to be +configured as follows: + +1. Remove jumpers JP2 through JP11. +2. Set SW2 to the DIS position and remove resistor R12. +3. Unplug the SWD connector. + +Clocking +******** + +The MAX32672 clocking is provided by an external 16MHz crystal (Y1). + +External Voltage Reference +************************** + +The external voltage reference input VREF for the ADC can be sourced externally by a high-precision +external reference source (the MAX6071). VREF (JP1) allows the external reference +to be disconnected so that VREF can be sourced internally by VDDA. + + +UART Interface +************** + +The EV kit provides a USB-to-UART bridge chip (the FTDI FT230XS-R). This bridge eliminates +the requirement for a physical RS-232 COM port. Instead, the IC’s UART access is through +the Micro USB type-B connector (CN1). The USB-to-UART bridge can be connected to the IC’s UART0 or +LPUART0 with jumpers JP10 (RX0) and JP11 (TX0). Virtual COM port drivers and guides for +installing Windows® drivers are available on the FTDI Chip website. + + +Boot Loader +*********** + +The boot loader is activated by the boot-load-enable slide switch (SW2). +This pulls P0_10 low and, upon a power cycle or reset, the device will enter boot loader mode. + +GPIO and Alternate Function Headers +*********************************** + +GPIO and alternate function signals from the MAX32672 +can be accessed through 0.1in-spaced headers J3 and J4. + + +Analog Headers +************** + +The 12 analog inputs can be accessed through 0.1inspaced headers JH1, JH2, and JH3. + + +I2C Pullups +*********** + +The I2C ports can independently pulled up to V_AUX (3.3V default) through JP4 (I2C0_CL_PU) and JP5 +(I2C0_DA_PU), JP6 (I2C1_CL_PU) and JP7 (I2C1_DA_PU), and JP8 (I2C2_CL_PU) and JP9 (I2C2_DA_PU). + +Programming and Debugging +************************* + +The IC can be reset by pushbutton SW1. + + +Programming and Debugging +************************* + +Flashing +======== + +SWD debug can be accessed through an Arm Cortex 10-pin connector (J5). +Logic levels are set to 3V3 by default, but they can be set to 1.8V if TP5 (VDD_VDDA_EXT) +is supplied externally. Be sure to remove jumper JP15 (LDO_DUT_EN) to disconnect the 3.3V +LDO if supplying VDD and VDDA externally. + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +.. note:: + + This board uses OpenOCD as the default debug interface. You can also use + a Segger J-Link with Segger's native tooling by overriding the runner, + appending ``--runner jlink`` to your ``west`` command(s). The J-Link should + be connected to the standard 2*5 pin debug connector (JH2) using an + appropriate adapter board and cable. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `MAX32672EVKIT web page`_ + +.. _MAX32672EVKIT web page: + https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/max32672evkit.html diff --git a/boards/adi/max32672evkit/max32672evkit.dts b/boards/adi/max32672evkit/max32672evkit.dts new file mode 100644 index 0000000000000..42a0ca378dc6f --- /dev/null +++ b/boards/adi/max32672evkit/max32672evkit.dts @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include +#include + +/ { + model = "Analog Devices MAX32672EVKIT"; + compatible = "adi,max32672evkit"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram3; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 22 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 18 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW3"; + zephyr,code = ; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + sw0 = &pb1; + }; +}; + +&uart0 { + pinctrl-0 = <&uart0a_tx_p0_9 &uart0a_rx_p0_8>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; diff --git a/boards/adi/max32672evkit/max32672evkit.yaml b/boards/adi/max32672evkit/max32672evkit.yaml new file mode 100644 index 0000000000000..a7f285ff4cc59 --- /dev/null +++ b/boards/adi/max32672evkit/max32672evkit.yaml @@ -0,0 +1,13 @@ +identifier: max32672evkit +name: max32672evkit +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 200 +flash: 1024 diff --git a/boards/adi/max32672evkit/max32672evkit_defconfig b/boards/adi/max32672evkit/max32672evkit_defconfig new file mode 100644 index 0000000000000..a048ab2608ff0 --- /dev/null +++ b/boards/adi/max32672evkit/max32672evkit_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/adi/max32672fthr/Kconfig.max32672fthr b/boards/adi/max32672fthr/Kconfig.max32672fthr new file mode 100644 index 0000000000000..71f33f5214a05 --- /dev/null +++ b/boards/adi/max32672fthr/Kconfig.max32672fthr @@ -0,0 +1,7 @@ +# MAX32672FTHR boards configuration + +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32672FTHR + select SOC_MAX32672 diff --git a/boards/adi/max32672fthr/board.cmake b/boards/adi/max32672fthr/board.cmake new file mode 100644 index 0000000000000..815111de6b74e --- /dev/null +++ b/boards/adi/max32672fthr/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32672.cfg]") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/adi/max32672fthr/board.yml b/boards/adi/max32672fthr/board.yml new file mode 100644 index 0000000000000..c99d16ad4a1f3 --- /dev/null +++ b/boards/adi/max32672fthr/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32672fthr + vendor: adi + socs: + - name: max32672 diff --git a/boards/adi/max32672fthr/doc/img/max32672fthr_img1.webp b/boards/adi/max32672fthr/doc/img/max32672fthr_img1.webp new file mode 100644 index 0000000000000..9f0e49b247b67 Binary files /dev/null and b/boards/adi/max32672fthr/doc/img/max32672fthr_img1.webp differ diff --git a/boards/adi/max32672fthr/doc/img/max32672fthr_img2.webp b/boards/adi/max32672fthr/doc/img/max32672fthr_img2.webp new file mode 100644 index 0000000000000..38f5e9db7580f Binary files /dev/null and b/boards/adi/max32672fthr/doc/img/max32672fthr_img2.webp differ diff --git a/boards/adi/max32672fthr/doc/index.rst b/boards/adi/max32672fthr/doc/index.rst new file mode 100644 index 0000000000000..6656657881480 --- /dev/null +++ b/boards/adi/max32672fthr/doc/index.rst @@ -0,0 +1,206 @@ +.. _max32672_fthr: + +MAX32672FTHR +############ + +Overview +******** +The MAX32672FTHR is a rapid development platform that helps engineers quickly implement complex +sensor solutions using the MAX32672 Arm® Cortex®-M4. The board also includes the MAX8819 PMIC for +battery and power management. The form factor is a small, 0.9in by 2.6in, dual row header footprint +that is compatible with Adafruit® FeatherWing peripheral expansion boards. The board includes +an OLED display, a RGB indicator LED, and a user pushbutton. The MAX32672FTHR provides +a power-optimized flexible platform for quick proof-ofconcepts and early software development +to enhance time to market. + +The Zephyr port is running on the MAX32672 MCU. + +.. image:: img/max32672fthr_img1.webp + :align: center + :alt: MAX32672FTHR Front + +.. image:: img/max32672fthr_img2.webp + :align: center + :alt: MAX32672FTHR Back + +Hardware +******** + +- MAX32672 MCU: + + - High-Efficiency Microcontroller for Low-Power High-Reliability Devices + + - Arm Cortex-M4 Processor with FPU up to 100MHz + - 1MB Dual-Bank Flash with Error Correction + - 200KB SRAM (160KB with ECC Enabled), Optionally Preserved in Lowest Power Modes + - EEPROM Emulation on Flash + - 16KB Unified Cache with ECC + - Resource Protection Unit (RPU) and MemoryProtection Unit (MPU) + - Dual- or Single-Supply Operation, 1.7V to 3.6V + - Wide Operating Temperature: -40°C to +105°C + + - Flexible Clocking Schemes + + - Internal High-Speed 100MHz Oscillator + - Internal Low-Power 7.3728MHz and Ultra-Low-Power 80kHz Oscillators + - 16MHz–32MHz Oscillator, 32.768kHz Oscillator(External Crystal Required) + - External Clock Input for CPU, LPUART, LPTMR + + - Power Management Maximizes Uptime for Battery Applications + + - 59.8μA/MHz ACTIVE at 0.9V up to 12MHz(CoreMark®) + - 56.6μA/MHz ACTIVE at 1.1V up to 100MHz(While(1)) + - 3.09μA Full Memory Retention Power in BACKUPMode at VDD = 1.8V + - 350nA Ultra-Low-Power RTC at + - Wake from LPUART or LPTMR + + - Optimal Peripheral Mix Provides Platform Scalability + + - Up to 42 General-Purpose I/O Pins + - Up to Three SPI Master/Slave (up to 50Mbps) + - Up to Three 4-Wire UART + - Up to Three I2C Master/Slave 3.4Mbps High Speed + - Up to Four 32-Bit Timers (TMR) + - Up to Two Low-Power 32-Bit Timers (LPTMR) + - One I2S Master/Slave for Digital Audio Interface + - 12-Channel, 12-Bit, 1Msps SAR ADC with On-DieTemperature Sensor + + - Security and Integrity + + - Optional ECDSA-Based Cryptographic SecureBootloader in ROM + - Secure Cryptographic Accelerator for Elliptic Curve + - AES-128/192/256 Hardware Acceleration Engine + +- Benefits and Features of MAX32672FTHR: + + - MAX8819 PMIC with Integrated Charger + - On-Board DAPLink Debug and Programming Interface for Arm Cortex-M4 + - Breadboard-Compatible Headers + - Micro USB Connector + - RGB Indicator LED + - User Pushbutton + - OLED Display + - SWD Debugger + - Virtual UART Console + +Supported Features +================== + +Below interfaces are supported by Zephyr on MAX32672FTHR. + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + + +Connections and IOs +=================== + +J9 Pinout +********** + ++---------+----------+-------------------------------------------------------------------------------------------------+ +| Pin | Name | Description | ++=========+==========+=================================================================================================+ +| 1 | RST | Master Reset Signal | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 2 | 3V3 | 3.3V Output. Typically used to provide 3.3V to peripherals connected to the expansion headers. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 3 | 1V8 | 1.8V Output. Typically used to provide 1.8V to peripherals connected to the expansion headers. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 4 | GND | Ground | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 5 | P0_11 | GPIO or Analog Input (AIN3 channel). | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 6 | P0_12 | GPIO or Analog Input (AIN4 channel). | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 7 | P0_13 | GPIO or Analog Input (AIN5 channel). | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 8 | P0_22 | GPIO or ADC_TRIG signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 9 | P0_27 | GPIO or QERR signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 10 | P0_26 | GPIO or QDIR signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 11 | P0_16 | GPIO or SPI1 clock signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 12 | P0_15 | GPIO or SPI1 MOSI signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 13 | P0_14 | GPIO or SPI1 MISO signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 14 | P0_28 | GPIO or UART1 Rx signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 15 | P0_29 | GPIO or UART1 Tx signal. | ++---------+----------+-------------------------------------------------------------------------------------------------+ +| 16 | GND | Ground | ++---------+----------+-------------------------------------------------------------------------------------------------+ + + +J7 Pinout +********** + ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| Pin | Name | Description | ++=========+==========+===========================================================================================================+ +| 1 | SYS | SYS Switched Connection to the Battery. This is the primary system power supply and automatically | +| | | switches between the battery voltage and the USB supply when available. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 2 | PWR | In battery-powered mode, turns off the PMIC if shorted to ground. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 3 | VBUS | USB VBUS Signal. This can be used as a 5V supply when connected to USB. This pin can also be | +| | | used as an input to power the board. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 4 | P0_5 | GPIO or HFX_CLK_OUT signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 5 | P0_6 | GPIO or QEA signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 6 | P0_7 | GPIO or QEB signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 7 | P0_23 | GPIO or QEI signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 8 | P0_17 | GPIO or SPI1 slave select signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 9 | P0_24 | GPIO or QES signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 10 | P0_25 | GPIO or QMATCH signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 11 | P0_18 | GPIO or I2C2 SCL signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ +| 12 | P0_19 | GPIO or I2C2 SDA signal. | ++---------+----------+-----------------------------------------------------------------------------------------------------------+ + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32625 microcontroller on the board is flashed with DAPLink firmware at the factory. +It allows debugging and flashing the MAX32672 Arm Core over USB. + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `MAX32672FTHR web page`_ + +.. _MAX32672FTHR web page: + https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/max32672fthr.html diff --git a/boards/adi/max32672fthr/max32672fthr.dts b/boards/adi/max32672fthr/max32672fthr.dts new file mode 100644 index 0000000000000..963235b42a914 --- /dev/null +++ b/boards/adi/max32672fthr/max32672fthr.dts @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include +#include + +/ { + model = "Analog Devices MAX32672FTHR"; + compatible = "adi,max32672fthr"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram3; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + led3: led_3 { + gpios = <&gpio0 4 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + zephyr,code = ; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + led2 = &led3; + sw0 = &pb1; + }; + + /* Used for accessing other pins */ + feather_header: feather_connector { + compatible = "adafruit-feather-header"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <12 0 &gpio0 19 0>, /* SDA */ + <13 0 &gpio0 18 0>, /* SCL */ + <14 0 &gpio0 25 0>, /* I2S LRCLK */ + <15 0 &gpio0 24 0>, /* I2S SDO */ + <16 0 &gpio0 17 0>, /* SPI1 SS */ + <17 0 &gpio0 23 0>, /* QEI */ + <18 0 &gpio0 7 0>, /* QEB */ + <19 0 &gpio0 6 0>, /* QEA */ + <20 0 &gpio0 5 0>, /* HFX CLK OUT */ + /* 11 not connected */ + <10 0 &gpio0 29 0>, /* TX */ + <9 0 &gpio0 28 0>, /* RX */ + <8 0 &gpio0 14 0>, /* MISO */ + <7 0 &gpio0 15 0>, /* MOSI */ + <6 0 &gpio0 16 0>, /* SCK */ + <5 0 &gpio0 26 0>, /* I2S BCLK */ + <4 0 &gpio0 27 0>, /* I2S SDI */ + <3 0 &gpio0 22 0>, /* ADC_TRG */ + <2 0 &gpio0 13 0>, /* AIN5 */ + <1 0 &gpio0 12 0>, /* AIN4 */ + <0 0 &gpio0 11 0>; /* AIN3 */ + }; +}; + +&uart0 { + pinctrl-0 = <&uart0a_tx_p0_9 &uart0a_rx_p0_8>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; diff --git a/boards/adi/max32672fthr/max32672fthr.yaml b/boards/adi/max32672fthr/max32672fthr.yaml new file mode 100644 index 0000000000000..e8272a41146b3 --- /dev/null +++ b/boards/adi/max32672fthr/max32672fthr.yaml @@ -0,0 +1,13 @@ +identifier: max32672fthr +name: max32672fthr +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 200 +flash: 1024 diff --git a/boards/adi/max32672fthr/max32672fthr_defconfig b/boards/adi/max32672fthr/max32672fthr_defconfig new file mode 100644 index 0000000000000..a048ab2608ff0 --- /dev/null +++ b/boards/adi/max32672fthr/max32672fthr_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/adi/max32680evkit/Kconfig.max32680evkit b/boards/adi/max32680evkit/Kconfig.max32680evkit new file mode 100644 index 0000000000000..ad5115590bd6b --- /dev/null +++ b/boards/adi/max32680evkit/Kconfig.max32680evkit @@ -0,0 +1,7 @@ +# MAX32680EVKIT boards configuration + +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32680EVKIT + select SOC_MAX32680_M4 if BOARD_MAX32680EVKIT_MAX32680_M4 diff --git a/boards/adi/max32680evkit/board.cmake b/boards/adi/max32680evkit/board.cmake new file mode 100644 index 0000000000000..bd318bb200d32 --- /dev/null +++ b/boards/adi/max32680evkit/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32680.cfg]") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/adi/max32680evkit/board.yml b/boards/adi/max32680evkit/board.yml new file mode 100644 index 0000000000000..23b5102a97fdb --- /dev/null +++ b/boards/adi/max32680evkit/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32680evkit + vendor: adi + socs: + - name: max32680 diff --git a/boards/adi/max32680evkit/doc/img/max32680evkit_img1.jpg b/boards/adi/max32680evkit/doc/img/max32680evkit_img1.jpg new file mode 100644 index 0000000000000..c334dfe867ea7 Binary files /dev/null and b/boards/adi/max32680evkit/doc/img/max32680evkit_img1.jpg differ diff --git a/boards/adi/max32680evkit/doc/index.rst b/boards/adi/max32680evkit/doc/index.rst new file mode 100644 index 0000000000000..a06cffcc1386d --- /dev/null +++ b/boards/adi/max32680evkit/doc/index.rst @@ -0,0 +1,334 @@ +.. _max32680_evkit: + +MAX32680EVKIT +############# + +Overview +******** + +The MAX32680 evaluation kit (EV kit) provides a platform +for evaluation capabilities of the MAX32680 microcontroller, +which is an advanced system-on-chip (SoC) +designed for industrial and medical sensors. Power regulation +and management is provided by a single-inductor +multiple-output (SIMO) buck regulator system and contains +the latest generation Bluetooth® 5.2 Low Energy +(LE) radio. + +The Zephyr port is running on the MAX32680 MCU. + +.. image:: img/max32680evkit_img1.jpg + :align: center + :alt: MAX32680 EVKIT + + +Hardware +******** + +- MAX32680 MCU: + + - Ultra-Low-Power Wireless Microcontroller + + - Internal 100MHz Oscillator + - 512KB Flash and 128KB SRAM, Optional ECC on One 32KB SRAM Bank + + - Bluetooth 5.2 LE Radio + + - Dedicated, Ultra-Low-Power, 32-Bit RISC-VCoprocessor to Offload + + Timing-Critical Bluetooth Processing + + - Fully Open-Source Bluetooth 5.2 Stack Available + - Supports AoA, AoD, LE Audio, and Mesh + - High-Throughput (2Mbps) Mode•Long-Range (125kbps and 500kbps) Modes + - Rx Sensitivity: -97.5dBm; Tx Power: +4.5dBm + - Single-Ended Antenna Connection (50Ω) + + - Smart Integration Reduces BOM, Cost, and PCB Size + + - Two 16-Bit to 24-Bit Sigma-Delta ADCs + - 12 Channels, Assignable to Either ADC + - Flexible Resolution and Sample Rates + - 24-Bits at 0.4ksps, 16-Bits at 4ksps + - Four External Input, 10-Bit Sigma-Delta ADC 7.8ksps + - 12-Bit DAC + - On-Die Temperature Sensor + - Digital Peripherals: Two SPI, Two I2C, up to FourUART, and up to 36 GPIOs + - Timers: Six 32-Bit Timers, Two Watchdog Timers,Two Pulse Trains, 1-Wire® Master + + - Power Management Maximizes Battery Life + + - 2.0V to 3.6V Supply Voltage Range + - Integrated SIMO Power Regulator + - Dynamic Voltage Scaling (DVS) + - 23.8μA/MHz ACTIVE Mode Current at 3.0VCoremark® + - 4.4μA at 3.0V Retention Current for 32KB SRAM + - Selectable SRAM Retention in Low-Power Modes + + - Robust Security and Reliability + + - TRNG + - Secure Nonvolatile Key Storage and AES-128/192/256 + - Secure Boot to Protect IP/Firmware + - Wide, -40°C to +85°C Operating Temperature + +- External devices connected to the MAX32680 EVKIT: + + - SMA Connector for Attaching an External Bluetooth Antenna + - 128 x 128 (1.45in) Color TFT Display with SPI Interface + - Two Selectable On-Board, High-Precision Voltage References + - USB 2.0 Micro B to Serial UARTs + - UART1 and LPUART0 Interface is Selectable Through On-Board Jumpers + - All GPIOs Signals Accessed Through 0.1in Headers + - Access to Four Analog Inputs Through SMA Connectors Configured as Differential + - Access to Eight Analog Inputs Through 0.1in Headers Configured as Single-End + - Optional Discrete Filter for the Twelve Analog Inputs + - DAC Accessed Through SMA Connector or Test Point + - 10-Pin SWD Connector + - 10-Pin RV JTAG Connector + - Board Power Provided by USB Port + - On-Board 3.3V LDO Regulator to Power MAX32680 Internal SIMO + - Test Loops Provided to Supply Optional VCORE Power Externally + - Individual Power Measurement on All IC Rails Through Jumpers + - Two General Purpose LEDs and Two General Purpose Pushbutton Switches + +Supported Features +================== + +Below interfaces are supported by Zephyr on MAX32680EVKIT. + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + +Connections and IOs +=================== + ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| Name | Name | Settings | Description | ++===========+===============+===============+==================================================================================================+ +| JP1 | VREGI | | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 3.3V power from the MAX32680 SIMO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects 3.3V power to the MAX32680 SIMO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP2 | REF0P | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects the external high-precision voltage refernce to REF0P. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the internal voltage refernce to REF0P. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP3 | REF0N | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects REF0N from ground. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects REF0N to ground. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP4 | VDDIO_AUX | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects VDDIO_AUX from pull-ups and reference voltages. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects VDDIO_AUX to pull-ups and reference voltages. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP5 | VDDIOH | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Connects VREGO_A to VDDIOH. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects the 3.3V from the estrenal LDO to VDDIOH. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP6 | REF1P | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects the external high-precision voltage refernce to REF1P. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the internal voltage refernce to REF1P. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP7 | REF1N | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects REF1N from ground. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects REF1N to ground. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP8 | I2C0_SDA | +-----------+ | +-------------------------------------------------------------------------------+ | +| | I2C0_SCL | | 2-1 | | | Connects I2C0 pullups to VDDIO_AUX (1.8V). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects I2C0 pullups to 3.3V. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP9 | I2C1_SDA | +-----------+ | +-------------------------------------------------------------------------------+ | +| | I2C1_SCL | | 2-1 | | | Connects I2C1 pullups to VDDIO_AUX (1.8V). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects I2C1 pullups to 3.3V. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP10 | P0_24 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects red LED D1 from P0_24. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects red LED D1 to P0_24. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP11 | P0_25 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects green LED D2 from P0_25. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects green LED D2 to P0_25. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP12 | FSK_IN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects FSK_IN from HART analog circuitry. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects FSK_IN to HART analog circuitry. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP13 | RCV_FSK | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects RCV_FSK from CC LOOP. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects RCV_FSK to CC LOOP. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP14 | FSK_OUT | +-----------+ | +--------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects FSK_OUT from HART analog circuitry. | | +| | | +-----------+ | +--------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects FSK_OUT to HART analog circuitry. | | +| | | +-----------+ | +--------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP15 | RCV_FSK | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects RCV_FSK from XFMR LOOP. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects RCV_FSK to XFMR LOOP. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP16 | RLOAD | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 249 ohm resistor shunt from CC LOOP. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects 249 ohm resistor shunt to CC LOOP. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP17 | FSK AMP GAIN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Enables FSK variable amp gain. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Disables FSK variable amp gain. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP18 | AMP BYPASS | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Enables FSK amp. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Bypasses FSK amp. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP19 | FSK AMP GAIN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Enables FSK fixed amp gain. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Disables FSK fixed amp gain. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP20 | HART_RTS | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Enables HART_RTS optical transceiver. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Bypasses HART_RTS optical transceiver. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP21 | RLOAD | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 249 ohm resistor shunt from XFMR LOOP. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Closed | | | Connects 249 ohm resistor shunt to XFMR LOOP. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP22 | UART0_RX | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Disconnects the USB - serial bridge from UART1_RX (P0.12). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the USB - serial bridge to LPUART_RX (P2.6). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP23 | UART0_TX | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Disonnects the USB - serial bridge from UART1_TX (P0.13). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects the USB - serial bridge to LPUART_TX (P2.7). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP24 | +-----------+ | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | HART_IN | | | Open | | | Disconnects TX of USB - serial bridge from HART_IN (P0.1) | | +| | +-----------+ | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | HART_IN | | | 1-2 | | | Connects TX of USB - serial bridge to HART_IN (P0.1). | | +| | +-----------+ | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | HART_OUT | | | Open | | | Disconnects RX of USB - serial bridge from HART_OUT (P0.0). | | +| | +-----------+ | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | HART_OUT | | | 2-3 | | | Connects RX of USB - serial bridge to HART_OUT (P0.0). | | +| | +-----------+ | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | HART_RTS | | | Open | | | Disconnects RTS of USB - serial bridge from HART_RTS (P0.3). | | +| | +-----------+ | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | HART_RTS | | | 3-4 | | | Connects TX of USB - serial bridge to HART_RTS (P0.3). | | +| | +-----------+ | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | HART_OCD | | | Open | | | Disconnects RTS of USB - serial bridge from HART_OCD (P0.2). | | +| | +-----------+ | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | HART_OCD | | | 4-5 | | | Connects TX of USB - serial bridge to HART_OCD (P0.2). | | +| | +-----------+ | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP25 | RSTN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects DUT_3V3_RSTN from RSTN. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Close | | | Connects DUT_3V3_RSTN to RSTN. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32680 MCU can be flashed by connecting an external debug probe to the +SWD port. SWD debug can be accessed through the Cortex 10-pin connector, JH10. +Logic levels are set to 1.8V (VDDIO_AUX). + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `MAX32680EVKIT web page`_ + +.. _MAX32680EVKIT web page: + https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/max32680evkit.html#eb-overview diff --git a/boards/adi/max32680evkit/max32680evkit_max32680_m4.dts b/boards/adi/max32680evkit/max32680evkit_max32680_m4.dts new file mode 100644 index 0000000000000..5fce323ce4156 --- /dev/null +++ b/boards/adi/max32680evkit/max32680evkit_max32680_m4.dts @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + + #include + #include + #include + +/ { + model = "Analog Devices MAX32680EVKIT"; + compatible = "adi,max32680evkit"; + + chosen { + zephyr,console = &uart1; + zephyr,shell-uart = &uart1; + zephyr,sram = &sram2; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led1: led_1 { + gpios = <&gpio0 24 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + led2: led_2 { + gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb1: pb1 { + gpios = <&gpio0 26 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW1"; + }; + pb2: pb2 { + gpios = <&gpio0 27 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + }; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led1; + led1 = &led2; + sw0 = &pb1; + sw1 = &pb2; + }; +}; + +&uart1 { + pinctrl-0 = <&uart1a_tx_p0_13 &uart1a_rx_p0_12>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; + +&clk_ipo { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; diff --git a/boards/adi/max32680evkit/max32680evkit_max32680_m4.yaml b/boards/adi/max32680evkit/max32680evkit_max32680_m4.yaml new file mode 100644 index 0000000000000..68e2baa65d733 --- /dev/null +++ b/boards/adi/max32680evkit/max32680evkit_max32680_m4.yaml @@ -0,0 +1,13 @@ +identifier: max32680evkit/max32680/m4 +name: max32680evkit m4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial +ram: 128 +flash: 512 diff --git a/boards/adi/max32680evkit/max32680evkit_max32680_m4_defconfig b/boards/adi/max32680evkit/max32680evkit_max32680_m4_defconfig new file mode 100644 index 0000000000000..a048ab2608ff0 --- /dev/null +++ b/boards/adi/max32680evkit/max32680evkit_max32680_m4_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/adi/max32690evkit/Kconfig.max32690evkit b/boards/adi/max32690evkit/Kconfig.max32690evkit new file mode 100644 index 0000000000000..d475a30f4c894 --- /dev/null +++ b/boards/adi/max32690evkit/Kconfig.max32690evkit @@ -0,0 +1,7 @@ +# MAX32690 board configuration + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MAX32690EVKIT + select SOC_MAX32690_M4 if BOARD_MAX32690EVKIT_MAX32690_M4 diff --git a/boards/adi/max32690evkit/board.cmake b/boards/adi/max32690evkit/board.cmake new file mode 100644 index 0000000000000..443c84cc5e85a --- /dev/null +++ b/boards/adi/max32690evkit/board.cmake @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd --cmd-pre-init "source [find interface/cmsis-dap.cfg]") +board_runner_args(openocd --cmd-pre-init "source [find target/max32690.cfg]") +board_runner_args(jlink "--device=MAX32690" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/adi/max32690evkit/board.yml b/boards/adi/max32690evkit/board.yml new file mode 100644 index 0000000000000..53f531e193b8e --- /dev/null +++ b/boards/adi/max32690evkit/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +board: + name: max32690evkit + vendor: adi + socs: + - name: max32690 diff --git a/boards/adi/max32690evkit/doc/img/max32690evkit_img1.jpg b/boards/adi/max32690evkit/doc/img/max32690evkit_img1.jpg new file mode 100644 index 0000000000000..7ecfdcb3b2665 Binary files /dev/null and b/boards/adi/max32690evkit/doc/img/max32690evkit_img1.jpg differ diff --git a/boards/adi/max32690evkit/doc/img/max32690evkit_img2.jpg b/boards/adi/max32690evkit/doc/img/max32690evkit_img2.jpg new file mode 100644 index 0000000000000..24b665d288d80 Binary files /dev/null and b/boards/adi/max32690evkit/doc/img/max32690evkit_img2.jpg differ diff --git a/boards/adi/max32690evkit/doc/index.rst b/boards/adi/max32690evkit/doc/index.rst new file mode 100644 index 0000000000000..7da8592ff4f15 --- /dev/null +++ b/boards/adi/max32690evkit/doc/index.rst @@ -0,0 +1,296 @@ +.. _max32690_evkit: + +MAX32690EVKIT +############# + +Overview +******** +The MAX32690 evaluation kit (EV kit) provides a platform for evaluating the capabilities +of the MAX32690 microcontroller, which is an advanced system-on-chip (SoC). +It features an Arm® Cortex®-M4F CPU for efficient computation of complex functions and +algorithms, and the latest generation Bluetooth® 5 Low Energy (Bluetooth LE) radio designed +for wearable and hearable fitness devices, portable and wearable wireless medical devices, +industrial sensors/networks, internet of things (IoT), and asset tracking. + +The Zephyr port is running on the MAX32690 MCU. + +.. image:: img/max32690evkit_img1.jpg + :align: center + :alt: MAX32690 EVKIT Front + +.. image:: img/max32690evkit_img2.jpg + :align: center + :alt: MAX32690 Back + +Hardware +******** + +- MAX32690 MCU: + + - Ultra-Efficient Microcontroller for Battery-Powered Applications + + - 120MHz Arm Cortex-M4 Processor with FPU + - 7.3728MHz and 60MHz Low-Power Oscillators + - External Crystal Support (32MHz required for BLE) + - 32.768kHz RTC Clock (Requires External Crystal) + - 8kHz Always-On Ultra-Low Power Oscillator + - 3MB Internal Flash, 1MB Internal SRAM (832kB ECC ON) + - TBDμW/MHz Executing from Cache at 1.1V + - 1.8V and 3.3V I/O with No Level Translators + - External Flash & SRAM Expansion Interfaces + + - Bluetooth 5.2 LE Radio + + - Dedicated, Ultra-Low-Power, 32-Bit RISC-V Coprocessor to Offload Timing-Critical Bluetooth Processing + - Fully Open-Source Bluetooth 5.2 Stack Available + - Supports AoA, AoD, LE Audio, and Mesh + - High-Throughput (2Mbps) Mode + - Long-Range (125kbps and 500kbps) Modes + - Rx Sensitivity: -97.5dBm; Tx Power: +4.5dBm + - Single-Ended Antenna Connection (50Ω) + + - Multiple Peripherals for System Control + + - 16-Channel DMA + - Up To Five Quad SPI Master (60MHz)/Slave (48MHz) + - Up To Four 1Mbaud UARTs with Flow Control + - Up To Two 1MHz I2C Master/Slave + - I2S Master/Slave + - Eight External Channel, 12-bit 1MSPS SAR ADC w/ on-die temperature sensor + - USB 2.0 Hi-Speed Device + - 16 Pulse Train Engines + - Up To Six 32-Bit Timers with 8mA High Drive + - Up To Two CAN 2.0 Controllers + - Up To Four Micro-Power Comparators + - 1-Wire Master + + - Security and Integrity​ + + - ChipDNA Physically Un-clonable Function (PUF) + - Modular Arithmetic Accelerator (MAA), True Random Number Generator (TRNG) + - Secure Nonvolatile Key Storage, SHA-256, AES-128/192/256 + - Secure Boot ROM + +- External devices connected to the MAX32690EVKIT: + + - Bluetooth SMA Connector with a Hinged 2.4GHz Whip Antenna + - 3-Pin Terminal Block for CAN Bus 2.0 + - Selectable On-Board High-Precision Voltage Reference + - On-Board HyperRAM + - Stereo Audio Codec with Line-In and Line-Out 3.5mm Jacks + - 128 x 128 (1.45in) Color TFT Display + - USB 2.0 Micro-B Interface to the MAX32690 + - USB 2.0 Micro-B to Serial UART + - Board Power Provided by either USB Port + - Jumpers to Enable Optional Pull-Up Resistors on I2C port + - All GPIOs Signals Accessed through 0.1in Headers + - Three Analog Inputs Accessed through 0.1in Headers with Optional Filtering + - SWD 10-Pin Header + - On-Board 3.3V, 1.8V, and 1.1V LDO Regulators + - Individual Power Measurement on All IC Rails through Jumpers + - Two General-Purpose LEDs and One GeneralPurpose Push Button Switch + + +Supported Features +================== + +Below interfaces are supported by Zephyr on MAX32690EVKIT. + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock and reset control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++--------------------------------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ + + +Connections and IOs +=================== + ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| Name | Name | Settings | Description | ++===========+===============+===============+==================================================================================================+ +| JP1 | VREF | | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects external voltage reference to VREF pin, must be enabled in software. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects external voltage reference. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP2 | I2C0 PU | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects VDDIO (1V8) to I2C0 pull-up resistors. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects VDDIOH (3V3) to I2C0 pull-up resistors. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects power from I2C0 pull-up resistors. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP3 | I2C0_SDA_PU | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects pull-up to I2C0A_SDA (P2.7) sourced by I2C0 PU (JP2). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects pull-up from I2C0A_SDA (P2.7) sourced by I2C0 PU (JP2). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP4 | I2C0_SCL_PU | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects pull-up to I2C0A_SCL (P2.8) sourced by I2C0 PU (JP2). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects pull-up from I2C0A_SCL (P2.8) sourced by I2C0 PU (JP2). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP5 | LED0 EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects red LED D1 to P0.14. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects red LED D1 from P0.14. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP6 | LED1 EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects green LED D2 to P2.12. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects green LED D2 from P2.12. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP7 | RX EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the USB - serial bridge to UART2A_RX (P1.9). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects the USB - serial bridge from UART2A_RX (P1.9). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP8 | TX EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects the USB - serial bridge to UART2A_TX (P1.10). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects the USB - serial bridge from UART2A_TX (P1.10). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP9 | P1_7 SEL | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects the USB - serial bridge to UART2A_CTS (P1.7). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects I2C2C_SDA (P1.7) to the codec. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP10 | P1_8 SEL | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects the USB - serial bridge to UART2A_RTS (P1.8). | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects I2C2C_SCL (P1.8) to the codec. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP11 | V_AUX SEL | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-1 | | | Connects V_AUX to 1V8. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 2-3 | | | Connects V_AUX to 3V3. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP12 | VDD3A EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 3V3 to VDD3A. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 3V3 from VDD3A. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP13 | VDDIOH EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 3V3 to VDDIOH. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 3V3 from VDDIOH. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP14 | VDDB EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects a 3V3 LDO sourced by USB_VBUS (CN1) to VDDB. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects a 3V3 LDO sourced by USB_VBUS (CN1) from VDDB. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP15 | VDDA EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 1V8 to VDDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 1V8 from VDDA. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP16 | VDDIO EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 1V8 to VDDIO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 1V8 from VDDIO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP17 | VCORE EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 1V1 to VCORE. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 1V1 from VCORE. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JP18 | BLE LDO EN | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects 1V4 to BLE_LDO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects 1V4 from BLE_LDO. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ +| JH6 | ANALOG PORT3 | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 1-2 | | | Connects LPUART0B_RX (P3.0) to the SWD connector. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | 3-4 | | | Connects LPUART0B_TX (P3.1) to the SWD connector. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | Open | | | Disconnects LPUART0B_RX (P3.0) and LPUART0B_TX (P3.1) from the SWD connector. | | +| | | +-----------+ | +-------------------------------------------------------------------------------+ | +| | | | | ++-----------+---------------+---------------+--------------------------------------------------------------------------------------------------+ + +Programming and Debugging +************************* + +Flashing +======== + +The MAX32690 MCU can be flashed by connecting an external debug probe to the +SWD port. SWD debug can be accessed through the Cortex 10-pin connector, J3. +Logic levels are fixed to VDDIO (1.8V). + +Once the debug probe is connected to your host computer, then you can simply run the +``west flash`` command to write a firmware image into flash. + +.. note:: + + This board uses OpenOCD as the default debug interface. You can also use + a Segger J-Link with Segger's native tooling by overriding the runner, + appending ``--runner jlink`` to your ``west`` command(s). The J-Link should + be connected to the standard 2*5 pin debug connector (JW3) using an + appropriate adapter board and cable. + +Debugging +========= + +Please refer to the `Flashing`_ section and run the ``west debug`` command +instead of ``west flash``. + +References +********** + +- `MAX32690EVKIT web page`_ + +.. _MAX32690EVKIT web page: + https://www.analog.com/en/design-center/evaluation-hardware-and-software/evaluation-boards-kits/MAX32690EVKIT.html diff --git a/boards/adi/max32690evkit/max32690evkit_max32690_m4.dts b/boards/adi/max32690evkit/max32690evkit_max32690_m4.dts new file mode 100644 index 0000000000000..424794d022aa6 --- /dev/null +++ b/boards/adi/max32690evkit/max32690evkit_max32690_m4.dts @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include +#include + +/ { + model = "Analog Devices MAX32690EVKIT"; + compatible = "adi,max32690evkit"; + + chosen { + zephyr,console = &uart2; + zephyr,shell-uart = &uart2; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + label = "LED0"; + }; + green_led: led_1 { + gpios = <&gpio2 12 GPIO_ACTIVE_LOW>; + label = "LED1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + pb0: pb0 { + gpios = <&gpio4 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "SW2"; + }; + }; + + aliases { + led0 = &red_led; + led1 = &green_led; + sw0 = &pb0; + }; +}; + +&clk_ipo { + status = "okay"; +}; + +&clk_ibro { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpio3 { + status = "okay"; +}; + +&gpio4 { + status = "okay"; +}; + +&uart2 { + clock-source = ; + pinctrl-0 = <&uart2a_tx_p1_10 &uart2a_rx_p1_9>; + pinctrl-names = "default"; + current-speed = <115200>; + data-bits = <8>; + parity = "none"; + status = "okay"; +}; diff --git a/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml b/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml new file mode 100644 index 0000000000000..38989aa05f724 --- /dev/null +++ b/boards/adi/max32690evkit/max32690evkit_max32690_m4.yaml @@ -0,0 +1,15 @@ +identifier: max32690evkit/max32690/m4 +name: max32690evkit m4 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - serial + - spi + - i2c +ram: 1024 +flash: 3072 diff --git a/boards/adi/max32690evkit/max32690evkit_max32690_m4_defconfig b/boards/adi/max32690evkit/max32690evkit_max32690_m4_defconfig new file mode 100644 index 0000000000000..4fa0a46410634 --- /dev/null +++ b/boards/adi/max32690evkit/max32690evkit_max32690_m4_defconfig @@ -0,0 +1,13 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +# Enable GPIO +CONFIG_GPIO=y + +# Console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/adi/sdp_k1/adi_sdp_120pin_connector.dtsi b/boards/adi/sdp_k1/adi_sdp_120pin_connector.dtsi new file mode 100644 index 0000000000000..a6696d780bfde --- /dev/null +++ b/boards/adi/sdp_k1/adi_sdp_120pin_connector.dtsi @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2024 Analog Devices Inc. + * Copyright (c) 2024 Baylibre, SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + sdp_k1_120_hdr: connector { + compatible = "adi,sdp-120"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = + /* pin map */ /* sdp-120 */ + <32 0 &gpiof 7 0>, /* SPI_D2 */ + <33 0 &gpiod 13 0>, /* SPI_D3 */ + <34 0 &gpioc 11 0>, /* SERIAL_INT */ + <36 0 &gpioc 6 0>, /* SPI_SEL_B_N */ + <37 0 &gpioc 7 0>, /* SPI_SEL_C_N */ + <38 0 &gpiof 6 0>, /* SPI_SEL1/SPI_SS_N */ + + <42 0 &gpioj 0 0>, /* GPIO0 */ + <43 0 &gpioj 3 0>, /* GPIO2 */ + <44 0 &gpioj 5 0>, /* GPIO4 */ + <46 0 &gpioj 13 0>, /* GPIO6 */ + + /* TIMER A */ + <47 0 &gpiob 14 0>, /* TMR_A */ + + <58 0 &gpiod 6 0>, /* UART2_RX */ + <61 0 &gpiod 5 0>, /* UART2_TX */ + + /* TIMER D */ + <71 0 &gpioc 8 0>, /* TMR_D */ + + /* TIMER B */ + <72 0 &gpioe 6 0>, /* TMR_B */ + + <73 0 &gpioj 14 0>, /* GPIO7 */ + <75 0 &gpioj 12 0>, /* GPIO5 */ + <76 0 &gpioj 4 0>, /* GPIO3 */ + <77 0 &gpioj 1 0>, /* GPIO1 */ + + /* I2C3 */ + <78 0 &gpioh 7 0>, /* SCL_0 */ + <79 0 &gpioc 9 0>, /* SDA_0 */ + + /* SPI5 */ + <81 0 &gpioh 6 0>, /* SPI_CLK - spi5_sck_ph6 */ + <82 0 &gpiof 8 0>, /* SPI_MISO - spi5_miso_pf8 */ + <83 0 &gpiof 9 0>, /* SPI_MOSI - spi5_mosi_pf9 */ + <84 0 &gpiob 6 0>, /* SPI_SEL_A_N - could be PB6 or PB9 */ + + /* SPORT - no driver yet */ + <86 0 &gpiog 13 0>, /* SPORT_TSCLK */ + <87 0 &gpiog 14 0>, /* SPORT_DT0 */ + <88 0 &gpioa 8 0>, /* SPORT_TFS */ + <89 0 &gpioe 4 0>, /* SPORT_RFS */ + <90 0 &gpioe 5 0>, /* SPORT_DR0 */ + <91 0 &gpioe 2 0>; /* SPORT_RSCLK */ + }; + + pmod_spi { + compatible = "digilent,pmod"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &sdp_k1_120_hdr SDP_120_SPI_SEL_A_N 0>, // IO1 + <1 0 &sdp_k1_120_hdr SDP_120_SPI_MISO 0>, // IO2 + <2 0 &sdp_k1_120_hdr SDP_120_SPI_MOSI 0>, // IO3 + <3 0 &sdp_k1_120_hdr SDP_120_SPI_CLK 0>, // IO4 + <4 0 &sdp_k1_120_hdr SDP_120_SERIAL_INT 0>, // IO5 + <5 0 &sdp_k1_120_hdr SDP_120_GPIO5 0>, // IO6 + <6 0 &sdp_k1_120_hdr SDP_120_GPIO6 0>, // IO7 + <7 0 &sdp_k1_120_hdr SDP_120_GPIO7 0>; // IO8 + status = "disabled"; + }; + + pmod_usart { + compatible = "digilent,pmod"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &sdp_k1_120_hdr SDP_120_GPIO0 0>, // IO1 + <1 0 &sdp_k1_120_hdr SDP_120_UART_TX 0>, // IO2 + <2 0 &sdp_k1_120_hdr SDP_120_UART_RX 0>, // IO3 + <3 0 &sdp_k1_120_hdr SDP_120_GPIO3 0>, // IO4 + <4 0 &sdp_k1_120_hdr SDP_120_SERIAL_INT 0>, // IO5 + <5 0 &sdp_k1_120_hdr SDP_120_GPIO5 0>, // IO6 + <6 0 &sdp_k1_120_hdr SDP_120_GPIO6 0>, // IO7 + <7 0 &sdp_k1_120_hdr SDP_120_GPIO7 0>; // IO8 + status = "disabled"; + }; + +}; + +/* + * Note from sdp-k1 schematic for overlapping signals + * + * NOTE: SOME OF THE SPI & QUADSPI SIGNALS ON THE SDP + * CONNECTOR ON PAGE 9 ARE ROUTED TO MULTIPLE PINS ON THE + * STM32F469. TAKE CARE NOT TO ENABLE SPI AND QUADSPI ON + * THE SDP CONNECTOR SIMULTANEOUSLY. + */ + +sdp_spi: &spi5 { + pinctrl-0 = <&spi5_sck_ph6 &spi5_miso_pf8 &spi5_mosi_pf9>; + pinctrl-names = "default"; + cs-gpios = <&sdp_k1_120_hdr SDP_120_SPI_SEL_A_N (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + status = "okay"; +}; + +sdp_i2c: &i2c3 { }; + +sdp_serial: &usart2{ }; diff --git a/boards/adi/sdp_k1/adi_sdp_k1.dts b/boards/adi/sdp_k1/adi_sdp_k1.dts index 52c68f90c1897..a1b663867a5b1 100644 --- a/boards/adi/sdp_k1/adi_sdp_k1.dts +++ b/boards/adi/sdp_k1/adi_sdp_k1.dts @@ -8,6 +8,7 @@ #include #include #include "arduino_r3_connector.dtsi" +#include "adi_sdp_120pin_connector.dtsi" / { model = "Analog Devices Inc. SDP-K1 board"; diff --git a/boards/alientek/pandora_stm32l475/pandora_stm32l475.dts b/boards/alientek/pandora_stm32l475/pandora_stm32l475.dts index 1c28f6c817636..567e88a01523f 100644 --- a/boards/alientek/pandora_stm32l475/pandora_stm32l475.dts +++ b/boards/alientek/pandora_stm32l475/pandora_stm32l475.dts @@ -27,8 +27,6 @@ zephyr,shell-uart = &usart1; zephyr,sram = &sram0; zephyr,flash = &flash0; - - spi-flash0 = &w25q128jv; }; leds { diff --git a/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi b/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi index cfba01ba4dea6..25fda178797bf 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi +++ b/boards/ambiq/apollo3_evb/apollo3_evb-pinctrl.dtsi @@ -148,4 +148,15 @@ ambiq,iom-num = <6>; }; }; + + bleif_default: bleif_default{ + group1 { + pinmux = , + , + , + , + , + ; + }; + }; }; diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.dts b/boards/ambiq/apollo3_evb/apollo3_evb.dts index 181495a303825..51b19c55e236f 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.dts +++ b/boards/ambiq/apollo3_evb/apollo3_evb.dts @@ -14,16 +14,146 @@ zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,uart-pipe = &uart0; + zephyr,flash-controller = &flash; + zephyr,bt_hci = &bt_hci_apollo; }; aliases { watchdog0 = &wdt0; + led0 = &led0; + led1 = &led1; + led2 = &led2; + sw0 = &button0; + sw1 = &button1; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0_31 10 GPIO_ACTIVE_LOW>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpio0_31 30 GPIO_ACTIVE_LOW>; + label = "LED 1"; + }; + led2: led_2 { + gpios = <&gpio0_31 15 GPIO_ACTIVE_LOW>; + label = "LED 2"; + }; + led3: led_3 { + gpios = <&gpio0_31 14 GPIO_ACTIVE_LOW>; + label = "LED 3"; + }; + led4: led_4 { + gpios = <&gpio0_31 17 GPIO_ACTIVE_LOW>; + label = "LED 4"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0_31 16 GPIO_ACTIVE_LOW>; + label = "BTN0"; + }; + button1: button_1 { + gpios = <&gpio0_31 18 GPIO_ACTIVE_LOW>; + label = "BTN1"; + }; + button2: button_2 { + gpios = <&gpio0_31 19 GPIO_ACTIVE_LOW>; + label = "BTN2"; + }; + }; +}; + +&flash0 { + erase-block-size = <8192>; + write-block-size = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 16KB of storage at the end of the 976KB of flash */ + storage_partition: partition@f0000 { + label = "storage"; + reg = <0x000f0000 0x4000>; + }; }; }; +&bleif { + pinctrl-0 = <&bleif_default>; + pinctrl-names = "default"; + status = "okay"; +}; + &uart0 { current-speed = <115200>; pinctrl-0 = <&uart0_default>; pinctrl-names = "default"; status = "okay"; }; + +&wdt0 { + status = "okay"; +}; + +&spi0 { + compatible = "ambiq,spi"; + pinctrl-0 = <&spi0_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&i2c3 { + compatible = "ambiq,i2c"; + pinctrl-0 = <&i2c3_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&counter0 { + status = "okay"; +}; + +&counter1 { + status = "okay"; +}; + +&counter2 { + status = "okay"; +}; + +&counter3 { + status = "okay"; +}; + +&counter4 { + status = "okay"; +}; + +&counter5 { + status = "okay"; +}; + +&counter6 { + status = "okay"; +}; + +&counter7 { + status = "okay"; +}; + +&gpio0_31 { + status = "okay"; +}; + +&gpio32_63 { + status = "okay"; +}; diff --git a/boards/ambiq/apollo3_evb/apollo3_evb.yaml b/boards/ambiq/apollo3_evb/apollo3_evb.yaml index c76500facc455..18327a617a763 100644 --- a/boards/ambiq/apollo3_evb/apollo3_evb.yaml +++ b/boards/ambiq/apollo3_evb/apollo3_evb.yaml @@ -9,6 +9,11 @@ toolchain: - gnuarmemb supported: - uart + - watchdog + - counter + - gpio + - spi + - i2c testing: ignore_tags: - net diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi b/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi index 5619b134ee9ea..2f0b4acd54240 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb-pinctrl.dtsi @@ -193,4 +193,15 @@ ambiq,iom-num = <2>; }; }; + + bleif_default: bleif_default{ + group1 { + pinmux = , + , + , + , + , + ; + }; + }; }; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts index 46894814dbe42..277675449c4fa 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.dts +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.dts @@ -14,16 +14,150 @@ zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,uart-pipe = &uart0; + zephyr,flash-controller = &flash; + zephyr,bt_hci = &bt_hci_apollo; }; aliases { watchdog0 = &wdt0; + led0 = &led0; + led1 = &led1; + led2 = &led2; + sw0 = &button0; + sw1 = &button1; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0_31 10 GPIO_ACTIVE_LOW>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpio0_31 30 GPIO_ACTIVE_LOW>; + label = "LED 1"; + }; + led2: led_2 { + gpios = <&gpio0_31 15 GPIO_ACTIVE_LOW>; + label = "LED 2"; + }; + led3: led_3 { + gpios = <&gpio0_31 14 GPIO_ACTIVE_LOW>; + label = "LED 3"; + }; + led4: led_4 { + gpios = <&gpio0_31 17 GPIO_ACTIVE_LOW>; + label = "LED 4"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpio0_31 16 GPIO_ACTIVE_LOW>; + label = "BTN0"; + }; + button1: button_1 { + gpios = <&gpio0_31 18 GPIO_ACTIVE_LOW>; + label = "BTN1"; + }; + button2: button_2 { + gpios = <&gpio0_31 19 GPIO_ACTIVE_LOW>; + label = "BTN2"; + }; }; }; +&flash0 { + erase-block-size = <8192>; + write-block-size = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 16KB of storage at the end of the 2000KB of flash */ + storage_partition: partition@1f0000 { + label = "storage"; + reg = <0x001f0000 0x4000>; + }; + }; +}; + +&bleif { + pinctrl-0 = <&bleif_default>; + pinctrl-names = "default"; + status = "okay"; +}; + &uart0 { current-speed = <115200>; pinctrl-0 = <&uart0_default>; pinctrl-names = "default"; status = "okay"; }; + +&wdt0 { + status = "okay"; +}; + +&spi0 { + compatible = "ambiq,spi"; + pinctrl-0 = <&spi0_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&i2c3 { + compatible = "ambiq,i2c"; + pinctrl-0 = <&i2c3_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&counter0 { + status = "okay"; +}; + +&counter1 { + status = "okay"; +}; + +&counter2 { + status = "okay"; +}; + +&counter3 { + status = "okay"; +}; + +&counter4 { + status = "okay"; +}; + +&counter5 { + status = "okay"; +}; + +&counter6 { + status = "okay"; +}; + +&counter7 { + status = "okay"; +}; + +&gpio0_31 { + status = "okay"; +}; + +&gpio32_63 { + status = "okay"; +}; + +&gpio64_95 { + status = "okay"; +}; diff --git a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml index db00dbedcd647..1a54a4a9d159b 100644 --- a/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml +++ b/boards/ambiq/apollo3p_evb/apollo3p_evb.yaml @@ -9,6 +9,11 @@ toolchain: - gnuarmemb supported: - uart + - watchdog + - counter + - gpio + - spi + - i2c testing: ignore_tags: - net diff --git a/boards/ambiq/apollo4p_blue_kxr_evb/Kconfig.defconfig b/boards/ambiq/apollo4p_blue_kxr_evb/Kconfig.defconfig index 87e1c5a8764f9..7303c78a28644 100644 --- a/boards/ambiq/apollo4p_blue_kxr_evb/Kconfig.defconfig +++ b/boards/ambiq/apollo4p_blue_kxr_evb/Kconfig.defconfig @@ -9,10 +9,6 @@ if BT config MAIN_STACK_SIZE default 2048 -choice BT_HCI_BUS_TYPE - default BT_AMBIQ_HCI -endchoice - config BT_BUF_ACL_TX_COUNT default 14 diff --git a/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts b/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts index f9aa3c11c31c1..130a195154c8b 100644 --- a/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts +++ b/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.dts @@ -15,6 +15,7 @@ zephyr,shell-uart = &uart0; zephyr,uart-pipe = &uart0; zephyr,flash-controller = &flash; + zephyr,bt-hci = &bt_hci_apollo; }; aliases { diff --git a/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.yaml b/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.yaml index d9e9f244d861a..9bd2496b1244b 100644 --- a/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.yaml +++ b/boards/ambiq/apollo4p_blue_kxr_evb/apollo4p_blue_kxr_evb.yaml @@ -20,3 +20,7 @@ testing: ignore_tags: - net vendor: ambiq +# Provisional hack to prevent tests being run in this board, as it fails in many test & samples: +twister: false +# Once https://github.com/zephyrproject-rtos/zephyr/issues/74212, 73443 & 72775 are fixed +# this should be removed diff --git a/boards/ambiq/apollo4p_evb/apollo4p_evb.yaml b/boards/ambiq/apollo4p_evb/apollo4p_evb.yaml index 1aa0fbf75d4b2..8b67616a27b32 100644 --- a/boards/ambiq/apollo4p_evb/apollo4p_evb.yaml +++ b/boards/ambiq/apollo4p_evb/apollo4p_evb.yaml @@ -14,8 +14,13 @@ supported: - gpio - spi - i2c + - hwinfo testing: ignore_tags: - net - bluetooth vendor: ambiq +# Provisional hack to prevent tests being run in this board, as it fails in many test & samples: +twister: false +# Once https://github.com/zephyrproject-rtos/zephyr/issues/74212, 73443 & 72775 are fixed +# this should be removed diff --git a/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts b/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts index 4459780243b1b..5d6e0dd7d883c 100644 --- a/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts +++ b/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.dts @@ -18,7 +18,7 @@ zephyr,console = &usart1; zephyr,shell-uart = &usart1; zephyr,uart-mcumgr = &usart1; - zephyr,bt-uart = &uart7; + zephyr,bt-hci = &bt_hci_uart; zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,canbus = &fdcan2; @@ -37,7 +37,6 @@ led0 = &red_led; led1 = &green_led; sw0 = &user_button; - spi-flash0 = &n25q128a1; }; }; @@ -98,12 +97,17 @@ status = "okay"; hw-flow-control; - murata-1dx { - compatible = "infineon,cyw43xxx-bt-hci"; - bt-reg-on-gpios = <&gpioa 10 GPIO_ACTIVE_HIGH>; - bt-host-wake-gpios = <&gpiog 3 GPIO_ACTIVE_HIGH>; - bt-dev-wake-gpios = <&gpioh 7 GPIO_ACTIVE_HIGH>; - fw-download-speed = <115200>; + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + + murata-1dx { + compatible = "infineon,cyw43xxx-bt-hci"; + bt-reg-on-gpios = <&gpioa 10 GPIO_ACTIVE_HIGH>; + bt-host-wake-gpios = <&gpiog 3 GPIO_ACTIVE_HIGH>; + bt-dev-wake-gpios = <&gpioh 7 GPIO_ACTIVE_HIGH>; + fw-download-speed = <115200>; + }; }; }; @@ -141,8 +145,6 @@ pinctrl-names = "default"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL1_Q FDCAN_SEL(1)>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flash0 { diff --git a/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.yaml b/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.yaml index cdcaeba7c77b2..b637d14017b44 100644 --- a/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.yaml +++ b/boards/arduino/giga_r1/arduino_giga_r1_stm32h747xx_m7.yaml @@ -14,6 +14,5 @@ supported: - arduino_spi - spi - memc - - usb_cdc - usb_device vendor: arduino diff --git a/boards/arduino/nano_33_ble/arduino_nano_33_ble.yaml b/boards/arduino/nano_33_ble/arduino_nano_33_ble.yaml index 733309555cb51..385d3bd1559cc 100644 --- a/boards/arduino/nano_33_ble/arduino_nano_33_ble.yaml +++ b/boards/arduino/nano_33_ble/arduino_nano_33_ble.yaml @@ -14,7 +14,6 @@ supported: - serial - spi - uart - - usb_cdc - usb_device - watchdog vendor: arduino diff --git a/boards/arduino/nano_33_ble/arduino_nano_33_ble_nrf52840_sense.yaml b/boards/arduino/nano_33_ble/arduino_nano_33_ble_nrf52840_sense.yaml index b8741e66b3575..6a80eaecf4814 100644 --- a/boards/arduino/nano_33_ble/arduino_nano_33_ble_nrf52840_sense.yaml +++ b/boards/arduino/nano_33_ble/arduino_nano_33_ble_nrf52840_sense.yaml @@ -14,7 +14,6 @@ supported: - serial - spi - uart - - usb_cdc - usb_device - watchdog vendor: arduino diff --git a/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts b/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts index 2329853a1a3bb..52e376ed1405e 100644 --- a/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts +++ b/boards/arduino/nicla_sense_me/arduino_nicla_sense_me.dts @@ -8,6 +8,7 @@ #include #include "arduino_nicla_sense_me-pinctrl.dtsi" #include +#include / { model = "Arduino Nicla Sense ME"; @@ -37,7 +38,6 @@ aliases { sw0 = &user_button; watchdog0 = &wdt0; - spi-flash0 = &mx25r1635f; }; }; @@ -73,6 +73,18 @@ pinctrl-0 = <&i2c0_default>; pinctrl-1 = <&i2c0_sleep>; pinctrl-names = "default", "sleep"; + + is31fl3194@53 { + compatible = "issi,is31fl3194"; + reg = <0x53>; + led_rgb { + label = "RGB LED"; + color-mapping = , + , + ; + current-limit = <10>; + }; + }; }; /* I2C1 in datasheet */ diff --git a/boards/arduino/portenta_h7/Kconfig.defconfig b/boards/arduino/portenta_h7/Kconfig.defconfig new file mode 100644 index 0000000000000..002ff75b5a551 --- /dev/null +++ b/boards/arduino/portenta_h7/Kconfig.defconfig @@ -0,0 +1,43 @@ +# Copyright 2024 Rahul Arasikere +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_ARDUINO_PORTENTA_H7 + +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + +if USB_DEVICE_STACK + +config USB_DEVICE_PRODUCT + default "Arduino SA Portenta H7" + +config USB_DEVICE_PID + default 0x035b + +config USB_DEVICE_VID + default 0x2341 + +config USB_DEVICE_INITIALIZE_AT_BOOT + default y + +if LOG + +# Logger cannot use itself to log +choice USB_CDC_ACM_LOG_LEVEL_CHOICE + default USB_CDC_ACM_LOG_LEVEL_OFF +endchoice + +# Set USB log level to error only +choice USB_DEVICE_LOG_LEVEL_CHOICE + default USB_DEVICE_LOG_LEVEL_ERR +endchoice + +endif # LOG + +endif # USB_DEVICE_STACK + +endif # BOARD_ARDUINO_PORTENTA_H7 diff --git a/boards/arduino/portenta_h7/arduino_portenta_h7-common.dtsi b/boards/arduino/portenta_h7/arduino_portenta_h7-common.dtsi index 87d85f2726352..e030d9d1cd056 100644 --- a/boards/arduino/portenta_h7/arduino_portenta_h7-common.dtsi +++ b/boards/arduino/portenta_h7/arduino_portenta_h7-common.dtsi @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { leds { compatible = "gpio-leds"; @@ -18,6 +20,12 @@ }; }; + otghs_ulpi_phy: otghs_ulpis_phy { + compatible = "usb-ulpi-phy"; + reset-gpios = < &gpioj 4 GPIO_ACTIVE_LOW >; + #phy-cells = <0>; + }; + aliases { led0 = &red_led; led1 = &green_led; @@ -31,12 +39,12 @@ }; &rcc { - d1cpre = <1>; - hpre = <1>; - d1ppre = <1>; - d2ppre1 = <1>; - d2ppre2 = <2>; - d3ppre = <1>; + d1cpre = < 1 >; + hpre = < 2 >; + d1ppre = < 2 >; + d2ppre1 = < 2 >; + d2ppre2 = < 2 >; + d3ppre = < 2 >; }; /* UART0 in datasheet */ @@ -113,12 +121,129 @@ status = "okay"; }; -zephyr_udc0: &usbotg_fs { - pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12>; +&mailbox { + status = "okay"; +}; + +&fmc { + status = "okay"; + pinctrl-0 = < &fmc_d2_pd0 &fmc_d3_pd1 &fmc_d13_pd8 &fmc_d14_pd9 + &fmc_d15_pd10 &fmc_d0_pd14 &fmc_d1_pd15 &fmc_nbl0_pe0 + &fmc_nbl1_pe1 &fmc_d4_pe7 &fmc_d5_pe8 &fmc_d6_pe9 + &fmc_d7_pe10 &fmc_d8_pe11 &fmc_d9_pe12 &fmc_d10_pe13 + &fmc_d11_pe14 &fmc_d12_pe15 &fmc_a0_pf0 &fmc_a1_pf1 + &fmc_a2_pf2 &fmc_a3_pf3 &fmc_a4_pf4 &fmc_a5_pf5 + &fmc_sdnras_pf11 &fmc_a6_pf12 &fmc_a7_pf13 &fmc_a8_pf14 + &fmc_a9_pf15 &fmc_a10_pg0 &fmc_a11_pg1 &fmc_a12_pg2 + &fmc_a14_pg4 /* FMC_BA0 */ &fmc_a15_pg5 /* FMC_BA1 */ + &fmc_sdclk_pg8 &fmc_sdncas_pg15 &fmc_sdcke0_ph2 &fmc_sdne0_ph3 + &fmc_sdnwe_ph5 >; pinctrl-names = "default"; - status = "disabled"; + st,mem-swap = "disable"; + sdram { + status = "okay"; + mode-register = < 0x220 >; + + /** From Arduino github repository: + * RefreshRate = 64 ms / 8192 cyc = 7.8125 us/cyc + * RefreshCycles = 7.8125 us * 90 MHz = 703 + * According to the formula on p.1665 of the reference manual, + * we also need to subtract 20 from the value, so the target + * refresh rate is 703 - 20 = 683. + */ + refresh-rate = < 683 >; + num-auto-refresh = < 8 >; + + bank@0 { + reg = < 0 >; + st,sdram-control = < STM32_FMC_SDRAM_NC_8 + STM32_FMC_SDRAM_NR_12 + STM32_FMC_SDRAM_MWID_16 + STM32_FMC_SDRAM_NB_4 + STM32_FMC_SDRAM_CAS_2 + STM32_FMC_SDRAM_SDCLK_PERIOD_2 + STM32_FMC_SDRAM_RBURST_ENABLE + STM32_FMC_SDRAM_RPIPE_0 >; + st,sdram-timing = < 2 7 5 7 2 3 3 >; + }; + }; }; -&mailbox { +&quadspi { + pinctrl-0 = < &quadspi_bk1_io0_pd11 + &quadspi_bk1_io1_pd12 + &quadspi_bk1_io2_pf7 + &quadspi_bk1_io3_pd13 + &quadspi_bk1_ncs_pg6 + &quadspi_clk_pf10 >; + pinctrl-names = "default"; status = "okay"; + + mx25l12833f: qspi-nor-flash@90000000 { + compatible = "st,stm32-qspi-nor"; + reg = < 0x90000000 DT_SIZE_M(16) >; /* 128 MBits */ + qspi-max-frequency = < 40000000 >; + sfdp-bfp = [ e5 20 f1 ff ff ff ff 07 44 eb 08 6b 08 3b 04 bb + fe ff ff ff ff ff 00 ff ff ff 44 eb 0c 20 0f 52 + 10 d8 00 ff 82 41 bd 00 81 e5 7b c6 44 03 67 38 + 30 b0 30 b0 f7 bd d5 5c 4a be 29 ff e1 d0 ff ff ]; + jedec-id = [ 66 66 20 ]; + spi-bus-width = <4>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = < 1 >; + #size-cells = < 1 >; + + storage_partition: partition@0 { + label = "storage"; + reg=< 0x0 DT_SIZE_K(15872) >; + }; + + wifi_firmware: partition@f80000 { + label = "wifi-firmware"; + reg = < 0xf80000 DT_SIZE_K(512) >; + }; + }; + }; +}; + +&mac { + pinctrl-0 = < ð_ref_clk_pa1 + ð_mdio_pa2 + ð_crs_dv_pa7 + ð_mdc_pc1 + ð_rxd0_pc4 + ð_rxd1_pc5 + ð_tx_en_pg11 + ð_txd1_pg12 + ð_txd0_pg13 >; + pinctrl-names = "default"; +}; + +zephyr_udc0: &usbotg_hs { + pinctrl-0 = < &usb_otg_hs_ulpi_d0_pa3 + &usb_otg_hs_ulpi_ck_pa5 + &usb_otg_hs_ulpi_d1_pb0 + &usb_otg_hs_ulpi_d2_pb1 + &usb_otg_hs_ulpi_d7_pb5 + &usb_otg_hs_ulpi_d3_pb10 + &usb_otg_hs_ulpi_d4_pb11 + &usb_otg_hs_ulpi_d5_pb12 + &usb_otg_hs_ulpi_d6_pb13 + &usb_otg_hs_ulpi_stp_pc0 + &usb_otg_hs_ulpi_nxt_ph4 + &usb_otg_hs_ulpi_dir_pi11 >; + pinctrl-names = "default"; + phys = < &otghs_ulpi_phy >; + maximum-speed = "high-speed"; + /* Include the USB1ULPIEN | USB1OTGHSULPIEN clock enable bit */ + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x6000000>, + <&rcc STM32_SRC_HSI48 USB_SEL(3)>; + num-bidir-endpoints = < 4 >; + status = "okay"; + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; }; diff --git a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m4.dts b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m4.dts index e214fbdecd4d4..12190a28715b3 100644 --- a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m4.dts +++ b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m4.dts @@ -24,7 +24,7 @@ }; &rcc { - clock-frequency = ; + clock-frequency = ; }; &usart1 { diff --git a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m4.yaml b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m4.yaml index afbca313573eb..352ae2b3cce89 100644 --- a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m4.yaml +++ b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m4.yaml @@ -14,4 +14,5 @@ testing: ignore_tags: - mpu - nfc + - flash vendor: arduino diff --git a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7.dts b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7.dts index 4ad43a01c1cbc..4b43bb6cbd4f8 100644 --- a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7.dts +++ b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7.dts @@ -15,11 +15,12 @@ /* HW resources are split between CM7 and CM4 */ chosen { - zephyr,console = &usart1; - zephyr,shell-uart = &usart1; + zephyr,console = &cdc_acm_uart0; + zephyr,shell-uart = &cdc_acm_uart0; + zephyr,cdc-acm-uart0 = &cdc_acm_uart0; zephyr,sram = &sram0; zephyr,flash = &flash0; - zephyr,code-partition = &code_partition; + zephyr,code-partition = &slot0_partition; }; oscen: oscen { @@ -27,27 +28,56 @@ regulator-name = "oscen"; enable-gpios = <&gpioh 1 GPIO_ACTIVE_HIGH>; regulator-boot-on; + status = "okay"; + }; + + ethernet_phy_en: ethernet_phy_en { + compatible = "regulator-fixed"; + regulator-name = "ethernet-phy-reset-release"; + enable-gpios = <&gpioj 15 GPIO_ACTIVE_HIGH>; + regulator-boot-on; + status = "okay"; + }; + + sdram1: sdram@c0000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + device_type = "memory"; + reg = <0xc0000000 DT_SIZE_M(8)>; + zephyr,memory-region = "SDRAM1"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; }; +&clk_hse { + clock-frequency = ; + hse-bypass; + status = "okay"; +}; + &clk_hsi { - hsi-div = <8>; + hsi-div = <1>; status = "okay"; }; &pll { - div-m = <1>; - mul-n = <24>; + div-m = <5>; + mul-n = <160>; div-p = <2>; - div-q = <4>; + div-q = <10>; div-r = <2>; - clocks = <&clk_hsi>; + clocks = <&clk_hse>; status = "okay"; }; +/** The power supply for the Portenta H7 is based on a ST PSU reference design. + * The design specification from this reference design limits the maximum + * clock speed to 400 MHz. + * Refer: section 8.1 of the reference design guide. + */ + &rcc { clocks = <&pll>; - clock-frequency = ; + clock-frequency = ; }; @@ -59,7 +89,16 @@ status = "okay"; }; +/* Only one should be enabled */ &usbotg_fs { + status = "disabled"; +}; + +&usbotg_hs { + status = "okay"; +}; + +&cdc_acm_uart0 { status = "okay"; }; @@ -70,27 +109,31 @@ #size-cells = <1>; boot_partition: partition@0 { - label = "bootloader"; - reg = <0x0 0x00040000>; + label = "mcuboot"; + reg = <0x00000000 0x00010000>; read-only; }; - - code_partition: partition@40000 { - label = "code"; - reg = <0x40000 0x000c0000>; - read-only; - }; - /* - * The flash starting at 0x000f8000 and ending at - * 0x000fffff is reserved for use by the application. - * - * Storage partition will be used by FCB/LittleFS/NVS - * if enabled. + * The flash starting at 0x00010000 and ending at + * 0x0001ffff (sectors 16-31) is reserved for use + * by the application. */ - storage_partition: partition@f8000 { - label = "storage"; - reg = <0x000f8000 0x00008000>; + scratch_partition: partition@10000 { + label = "image-scratch"; + reg = <0x00010000 0x00030000>; + }; + /* The arduino default bootloader occupies the address space 0x0 - 0x40000. + * This way regardless of the user's choice to use the mcuboot bootloader, + * applications will be located at 0x40000 which will be loaded by the + * arduino bootloader. + */ + slot0_partition: partition@40000 { + label = "image-0"; + reg = <0x00040000 0x00060000>; + }; + slot1_partition: partition@A0000 { + label = "image-1"; + reg = <0x000A0000 0x00060000>; }; }; }; diff --git a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_1_0_0.overlay b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_1_0_0.overlay new file mode 100644 index 0000000000000..b60fff37ae065 --- /dev/null +++ b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_1_0_0.overlay @@ -0,0 +1,9 @@ +/** + * Copyright (c) 2024 Rahul Arasikere . + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&clk_lsi { + status = "okay"; +}; diff --git a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_4_10_0.overlay b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_4_10_0.overlay new file mode 100644 index 0000000000000..1860e51e1975a --- /dev/null +++ b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_4_10_0.overlay @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2024 Rahul Arasikere . + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&clk_lse { + clock-frequency = <32768>; + status = "okay"; +}; diff --git a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_defconfig b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_defconfig index 18f533bf91d91..eef0bde3c4639 100644 --- a/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_defconfig +++ b/boards/arduino/portenta_h7/arduino_portenta_h7_stm32h747xx_m7_defconfig @@ -30,7 +30,11 @@ CONFIG_SERIAL=y # Enable console CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y +CONFIG_UART_LINE_CTRL=y # Enable regulator CONFIG_REGULATOR=y CONFIG_REGULATOR_FIXED=y + +# Enable USB Stack +CONFIG_USB_DEVICE_STACK=y diff --git a/boards/arduino/portenta_h7/board.yml b/boards/arduino/portenta_h7/board.yml index be2ba58da962f..01e28f0b5fdf0 100644 --- a/boards/arduino/portenta_h7/board.yml +++ b/boards/arduino/portenta_h7/board.yml @@ -3,3 +3,9 @@ board: vendor: arduino socs: - name: stm32h747xx + revision: + format: major.minor.patch + default: 1.0.0 + revisions: + - name: 1.0.0 + - name: 4.10.0 diff --git a/boards/arduino/portenta_h7/doc/index.rst b/boards/arduino/portenta_h7/doc/index.rst index 87b7aefdfe5d7..63d6e2da069c5 100644 --- a/boards/arduino/portenta_h7/doc/index.rst +++ b/boards/arduino/portenta_h7/doc/index.rst @@ -56,9 +56,23 @@ The current Zephyr arduino_portenta_h7 board configuration supports the followin +-----------+------------+-------------------------------------+ | IPM | on-chip | virtual mailbox based on HSEM | +-----------+------------+-------------------------------------+ +| EXTFLASH | on-chip | qspi | ++-----------+------------+-------------------------------------+ +| SDRAM | on-chip | sdram | ++-----------+------------+-------------------------------------+ +| USB | on-board | usb-hs | ++-----------+------------+-------------------------------------+ +| ETHERNET | on-board | eth | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on Zephyr porting. +The high precision low speed external (LSE) clock is only fully supported on +boards with hardware revision 4.10 or greater. By default the internal source +is used; to enable the use of the external oscillator, manually specify the +hardware revision at build time (see :ref:`application_board_version` for +information on how to build for specific revisions of the board). + Resources sharing ================= diff --git a/boards/arm/fvp_baser_aemv8r/board.cmake b/boards/arm/fvp_baser_aemv8r/board.cmake index f7753bc5099b1..8f5b70f5f330d 100644 --- a/boards/arm/fvp_baser_aemv8r/board.cmake +++ b/boards/arm/fvp_baser_aemv8r/board.cmake @@ -5,7 +5,8 @@ set(SUPPORTED_EMU_PLATFORMS armfvp) set(ARMFVP_BIN_NAME FVP_BaseR_AEMv8R) set(ARMFVP_MIN_VERSION 11.16.16) -if(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH64) +if(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH64 OR + CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH64_SMP) set(ARMFVP_FLAGS -C cluster0.has_aarch64=1 -C cluster0.VMSA_supported=0 @@ -38,7 +39,8 @@ if(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH64) -C bp.vis.rate_limit-enable=0 -C cache_state_modelled=1 ) -elseif(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH32) +elseif(CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH32 OR + CONFIG_BOARD_FVP_BASER_AEMV8R_FVP_AEMV8R_AARCH32_SMP) set(ARMFVP_FLAGS -C cluster0.has_aarch64=0 -C cluster0.VMSA_supported=0 diff --git a/boards/arm/mps2/mps2_an521_cpu0_ns.yaml b/boards/arm/mps2/mps2_an521_cpu0_ns.yaml index b5dcadf7fe94e..6a24f38878587 100644 --- a/boards/arm/mps2/mps2_an521_cpu0_ns.yaml +++ b/boards/arm/mps2/mps2_an521_cpu0_ns.yaml @@ -14,6 +14,5 @@ testing: only_tags: - arm - kernel - - tfm - userspace - trusted-firmware-m diff --git a/boards/arm/mps3/mps3_an547.dts b/boards/arm/mps3/mps3_an547.dts index 50700e8278e02..8b6585a13e294 100644 --- a/boards/arm/mps3/mps3_an547.dts +++ b/boards/arm/mps3/mps3_an547.dts @@ -132,8 +132,9 @@ }; sram: sram@11000000 { /* alias @ 0x01000000 */ - compatible = "mmio-sram"; + compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x11000000 DT_SIZE_M(2)>; + zephyr,memory-region = "SRAM"; }; dtcm: dtcm@30000000 { /* alias @ 0x20000000 */ @@ -143,8 +144,9 @@ }; isram: sram@31000000 {/* alias @ 0x21000000 */ - compatible = "mmio-sram"; + compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x31000000 DT_SIZE_M(4)>; + zephyr,memory-region = "ISRAM"; }; /* DDR4 - 2G, alternates non-secure/secure every 256M */ diff --git a/boards/arm/mps3/mps3_an547_ns.dts b/boards/arm/mps3/mps3_an547_ns.dts index dd8c9c4571c85..1c6a0fc2605c1 100644 --- a/boards/arm/mps3/mps3_an547_ns.dts +++ b/boards/arm/mps3/mps3_an547_ns.dts @@ -77,27 +77,34 @@ /* We utilize the secure addresses, if you subtract 0x10000000 * you'll get the non-secure alias */ - itcm: itcm@10000000 { /* alias @ 0x0 */ - reg = <0x10000000 DT_SIZE_K(512)>; + itcm: itcm@0 { + compatible = "zephyr,memory-region"; + reg = <0x0 DT_SIZE_K(512)>; + zephyr,memory-region = "ITCM"; }; - sram: sram@1000000 { /* alias @ 0x11000000 */ - compatible = "mmio-sram"; + sram: sram@1000000 { + compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x1000000 DT_SIZE_M(2)>; + zephyr,memory-region = "SRAM"; }; - dtcm: dtcm@20000000 { /* alias @ 0x30000000 */ + dtcm: dtcm@20000000 { + compatible = "zephyr,memory-region"; reg = <0x20000000 DT_SIZE_K(512)>; + zephyr,memory-region = "DTCM"; }; - isram: sram@31000000 {/* alias @ 0x21000000 */ - compatible = "mmio-sram"; - reg = <0x31000000 DT_SIZE_M(4)>; + isram: sram@21000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x21000000 DT_SIZE_M(4)>; + zephyr,memory-region = "ISRAM"; }; /* DDR4 - 2G, alternates non-secure/secure every 256M */ ddr4: memory@60000000 { device_type = "memory"; + compatible = "zephyr,memory-region"; reg = <0x60000000 DT_SIZE_M(256) 0x70000000 DT_SIZE_M(256) 0x80000000 DT_SIZE_M(256) @@ -106,6 +113,7 @@ 0xb0000000 DT_SIZE_M(256) 0xc0000000 DT_SIZE_M(256) 0xd0000000 DT_SIZE_M(256)>; + zephyr,memory-region = "DDR4"; }; reserved-memory { diff --git a/boards/arm/mps3/mps3_an547_ns.yaml b/boards/arm/mps3/mps3_an547_ns.yaml index 3852415834f69..e58f636b55571 100644 --- a/boards/arm/mps3/mps3_an547_ns.yaml +++ b/boards/arm/mps3/mps3_an547_ns.yaml @@ -18,4 +18,4 @@ toolchain: testing: default: true only_tags: - - tfm + - trusted-firmware-m diff --git a/boards/arm/v2m_beetle/support/openocd.cfg b/boards/arm/v2m_beetle/support/openocd.cfg index e1d1062ca08f3..36004576d093f 100644 --- a/boards/arm/v2m_beetle/support/openocd.cfg +++ b/boards/arm/v2m_beetle/support/openocd.cfg @@ -22,7 +22,7 @@ if { [info exists CPUTAPID] } { set _CPUTAPID 0x2ba01477 } -adapter_khz 1000 +adapter speed 1000 set _TARGETNAME $_CHIPNAME.cpu diff --git a/boards/atmel/sam/sam_e70_xplained/sam_e70_xplained-common.dtsi b/boards/atmel/sam/sam_e70_xplained/sam_e70_xplained-common.dtsi index 93dc9b1f35684..ded3866acfe67 100644 --- a/boards/atmel/sam/sam_e70_xplained/sam_e70_xplained-common.dtsi +++ b/boards/atmel/sam/sam_e70_xplained/sam_e70_xplained-common.dtsi @@ -206,9 +206,6 @@ zephyr_udc0: &usbhs { pinctrl-0 = <&can0_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; - can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/atmel/sam/sam_v71_xult/sam_v71_xult-common.dtsi b/boards/atmel/sam/sam_v71_xult/sam_v71_xult-common.dtsi index 9864c7ae50a1f..f6981455b5122 100644 --- a/boards/atmel/sam/sam_v71_xult/sam_v71_xult-common.dtsi +++ b/boards/atmel/sam/sam_v71_xult/sam_v71_xult-common.dtsi @@ -331,9 +331,6 @@ zephyr_udc0: &usbhs { pinctrl-0 = <&can1_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; - can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts index 79ff5b90ecfd7..3827dc104d993 100644 --- a/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts +++ b/boards/atmel/sam0/samc21n_xpro/samc21n_xpro.dts @@ -162,9 +162,6 @@ pinctrl-0 = <&can0_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; - can-transceiver { max-bitrate = <5000000>; }; @@ -174,9 +171,6 @@ pinctrl-0 = <&can1_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; - can-transceiver { max-bitrate = <5000000>; }; diff --git a/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml b/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml index d5e6a725003b5..c41c94432857c 100644 --- a/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml +++ b/boards/atmel/sam0/samd21_xpro/samd21_xpro.yaml @@ -20,7 +20,6 @@ supported: - pwm - spi - uart - - usb_cdc - usb_device - watchdog vendor: atmel diff --git a/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml b/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml index 3d531f6628718..be39f0dc5173e 100644 --- a/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml +++ b/boards/atmel/sam0/saml21_xpro/saml21_xpro.yaml @@ -20,7 +20,6 @@ supported: - pwm - spi - uart - - usb_cdc - usb_device - watchdog vendor: atmel diff --git a/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml b/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml index be66ff6cde536..488fba3bb324e 100644 --- a/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml +++ b/boards/atmel/sam0/samr34_xpro/samr34_xpro.yaml @@ -20,7 +20,6 @@ supported: - pwm - spi - uart - - usb_cdc - usb_device - watchdog vendor: atmel diff --git a/boards/bcdevices/plt_demo_v2/blueclover_plt_demo_v2_nrf52832.dts b/boards/bcdevices/plt_demo_v2/blueclover_plt_demo_v2_nrf52832.dts index 48bcacff102c6..245b2eb1aad23 100644 --- a/boards/bcdevices/plt_demo_v2/blueclover_plt_demo_v2_nrf52832.dts +++ b/boards/bcdevices/plt_demo_v2/blueclover_plt_demo_v2_nrf52832.dts @@ -8,6 +8,7 @@ #include #include "blueclover_plt_demo_v2_nrf52832-pinctrl.dtsi" #include +#include / { model = "Blue Clover PLT Demo Board V2"; @@ -107,6 +108,10 @@ compatible = "apa,apa102"; reg = <0>; spi-max-frequency = <5250000>; + chain-length = <4>; + color-mapping = ; }; }; diff --git a/boards/beagle/beagleconnect_freedom/beagleconnect_freedom.dts b/boards/beagle/beagleconnect_freedom/beagleconnect_freedom.dts index 9f8c84df95601..f3eb05c6eb9b7 100644 --- a/boards/beagle/beagleconnect_freedom/beagleconnect_freedom.dts +++ b/boards/beagle/beagleconnect_freedom/beagleconnect_freedom.dts @@ -23,7 +23,6 @@ mcuboot-button0 = &button0; sensor0 = &light; sensor1 = &humidity; - spi-flash0 = &spi_flash0; }; chosen { diff --git a/boards/bytesatwork/bytesensi_l/Kconfig b/boards/bytesatwork/bytesensi_l/Kconfig new file mode 100644 index 0000000000000..fd8429f038965 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ENABLE_DCDC + bool "DCDC mode" + select SOC_DCDC_NRF52X + default y + depends on BOARD_BYTESENSI_L diff --git a/boards/bytesatwork/bytesensi_l/Kconfig.bytesensi_l b/boards/bytesatwork/bytesensi_l/Kconfig.bytesensi_l new file mode 100644 index 0000000000000..530e716b540d4 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/Kconfig.bytesensi_l @@ -0,0 +1,6 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_BYTESENSI_L + bool "bytesatwork bytesSENSI-L nRF52832" + select SOC_NRF52832_QFAA diff --git a/boards/bytesatwork/bytesensi_l/Kconfig.defconfig b/boards/bytesatwork/bytesensi_l/Kconfig.defconfig new file mode 100644 index 0000000000000..52c2d397af856 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_BYTESENSI_L + +config BT_CTLR + default BT + +endif # BOARD_BYTESENSI_L diff --git a/boards/bytesatwork/bytesensi_l/board.cmake b/boards/bytesatwork/bytesensi_l/board.cmake new file mode 100644 index 0000000000000..efeed46003eff --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=nRF52832_xxAA" "--speed=4000") +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/bytesatwork/bytesensi_l/board.yml b/boards/bytesatwork/bytesensi_l/board.yml new file mode 100644 index 0000000000000..04e4cd9ad1153 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/board.yml @@ -0,0 +1,7 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 +board: + name: bytesensi_l + vendor: bytesatwork + socs: + - name: nrf52832 diff --git a/boards/bytesatwork/bytesensi_l/bytesensi_l.dts b/boards/bytesatwork/bytesensi_l/bytesensi_l.dts new file mode 100644 index 0000000000000..e54908293fb2b --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/bytesensi_l.dts @@ -0,0 +1,151 @@ +/* + * Copyrigtt (c) 2024 bytesatwork AG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "bytesensi_l_pinctrl.dtsi" + +#include + +/ { + model = "bytesatwork BLE/LORA sensor board"; + compatible = "bytesatwork,bytesensi-l"; + + chosen { + zephyr,console = &uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + aliases { + /* Alias for lora samples */ + lora0 = &lora; + }; +}; + +&flash0 { + 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 0x32000>; + }; + slot1_partition: partition@3e000 { + label = "image-1"; + reg = <0x0003E000 0x32000>; + }; + scratch_partition: partition@70000 { + label = "image-scratch"; + reg = <0x00070000 0xa000>; + }; + storage_partition: partition@7a000 { + label = "storage"; + reg = <0x0007a000 0x00005000>; + }; + }; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; + + /* Enable 1-wire to enable i2c bus as well */ + one-wire-gpio { + gpio-hog; + gpios = <7 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&i2c0 { + compatible = "nordic,nrf-twi"; + status = "okay"; + clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-1 = <&i2c0_sleep>; + pinctrl-names = "default", "sleep"; + + light_sensor: apds9960@39 { + status = "okay"; + compatible = "avago,apds9960"; + reg = <0x39>; + int-gpios = <&gpio0 25 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + }; + + temperature_sensor: tmp116@4a { + status = "okay"; + compatible = "ti,tmp116"; + reg = <0x4a>; + #address-cells = <1>; + #size-cells = <0>; + + eeprom: ti_tmp116_eeprom@0 { + compatible = "ti,tmp116-eeprom"; + reg = <0x0>; + read-only; + }; + }; + + gas_sensor: ccs811@5a { + status = "okay"; + compatible = "ams,ccs811"; + reg = <0x5a>; + irq-gpios = <&gpio0 28 GPIO_ACTIVE_LOW>; + wake-gpios = <&gpio0 27 GPIO_ACTIVE_LOW>; + }; + + pressure_sensor: lps22hb-press@5c { + status = "okay"; + compatible = "st,lps22hb-press"; + reg = <0x5c>; + }; +}; + +&spi1 { + status = "okay"; + compatible = "nordic,nrf-spi"; + pinctrl-0 = <&spi1_default>; + pinctrl-1 = <&spi1_sleep>; + pinctrl-names = "default", "sleep"; + cs-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>, + <&gpio0 5 GPIO_ACTIVE_LOW>; + + lora: lora@0 { + status = "okay"; + compatible = "semtech,sx1276"; + reg = <0>; + reset-gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + dio-gpios = + <&gpio0 19 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpio0 20 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpio0 22 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + <&gpio0 23 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + spi-max-frequency = <1000000>; + power-amplifier-output = "pa-boost"; + }; + + nor_flash: mx25r6435f@1 { + status = "okay"; + compatible ="jedec,spi-nor"; + size = <0x4000000>; + reg = <1>; + spi-max-frequency = <8000000>; + status = "okay"; + jedec-id = [c2 28 17]; + }; +}; diff --git a/boards/bytesatwork/bytesensi_l/bytesensi_l.yaml b/boards/bytesatwork/bytesensi_l/bytesensi_l.yaml new file mode 100644 index 0000000000000..362508e67a2fa --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/bytesensi_l.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 +identifier: bytesensi_l +name: bytesatwork byteSENSI-L +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 64 +flash: 512 +supported: + - ble + - gpio + - i2c + - lora + - spi +vendor: bytesatwork diff --git a/boards/bytesatwork/bytesensi_l/bytesensi_l_defconfig b/boards/bytesatwork/bytesensi_l/bytesensi_l_defconfig new file mode 100644 index 0000000000000..80cef47e86781 --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/bytesensi_l_defconfig @@ -0,0 +1,16 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable console over segger RTT +CONFIG_CONSOLE=y +CONFIG_RTT_CONSOLE=y +CONFIG_USE_SEGGER_RTT=y diff --git a/boards/bytesatwork/bytesensi_l/bytesensi_l_pinctrl.dtsi b/boards/bytesatwork/bytesensi_l/bytesensi_l_pinctrl.dtsi new file mode 100644 index 0000000000000..8b31ab2d3b04a --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/bytesensi_l_pinctrl.dtsi @@ -0,0 +1,54 @@ +/* + * Copyrigtt (c) 2024 bytesatwork AG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + uart0_default: uart0_default { + group1 { + psels = , + ; + }; + }; + + uart0_sleep: uart0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c0_default: i2c0_default { + group1 { + psels = , + ; + }; + }; + + i2c0_sleep: i2c0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + spi1_default: spi1_default{ + group1 { + psels = , + , + ; + }; + }; + + spi1_sleep: spi1_sleep{ + group1 { + psels = , + , + ; + low-power-enable; + }; + }; +}; diff --git a/boards/bytesatwork/bytesensi_l/doc/img/byteSENSI-L.jpg b/boards/bytesatwork/bytesensi_l/doc/img/byteSENSI-L.jpg new file mode 100644 index 0000000000000..5baccde618f44 Binary files /dev/null and b/boards/bytesatwork/bytesensi_l/doc/img/byteSENSI-L.jpg differ diff --git a/boards/bytesatwork/bytesensi_l/doc/index.rst b/boards/bytesatwork/bytesensi_l/doc/index.rst new file mode 100644 index 0000000000000..5c9ca7f7b9ffc --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/doc/index.rst @@ -0,0 +1,157 @@ +.. _bytesensi_l: + +bytesatwork byteSENSI-L +####################### + +Overview +******** + +The byteSENSI-L is a fun LoRa device based on nRF52 MCU that integrates many +sensors. + +.. image:: img/byteSENSI-L.jpg + :width: 800px + :align: center + :alt: byteSENSI-L + +Hardware +******** + +Supported Features +================== + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| RADIO | on-chip | Bluetooth | ++-----------+------------+----------------------+ +| RADIO | Semtech | LoRa | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| RTT | Segger | console | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ + +Connections and IOs +=================== + +External Connectors +------------------- + +External Supply @ X1 + ++-------+--------------+---------------------------------------+ +| PIN # | Signal Name | Function | ++=======+==============+=======================================+ +| 1 | VBAT | Power input instead of CR2477 battery | ++-------+--------------+---------------------------------------+ +| 2 | GND | Ground | ++-------+--------------+---------------------------------------+ + +Programming Connector @ SL1 + ++-------+--------------+ +| PIN # | Signal Name | ++=======+==============+ +| 1 | VBAT | ++-------+--------------+ +| 2 | SWDIO | ++-------+--------------+ +| 3 | GND | ++-------+--------------+ +| 4 | SWDCLK | ++-------+--------------+ +| 5 | GND | ++-------+--------------+ +| 6 | NC (SWO) | ++-------+--------------+ +| 7 | NC (Key) | ++-------+--------------+ +| 8 | NC | ++-------+--------------+ +| 9 | GND | ++-------+--------------+ +| 10 | nReset | ++-------+--------------+ + +I2C Sensor @ X3 + ++-------+--------------+-------------------------+ +| PIN # | Signal Name | Function | ++=======+==============+=========================+ +| 1 | VBAT | Power out | ++-------+--------------+-------------------------+ +| 2 | SCL | I2C clock at P0.15 | ++-------+--------------+-------------------------+ +| 3 | SDA | I2C data at P0.16 | ++-------+--------------+-------------------------+ +| 4 | INT | Interrupt at P0.13 | ++-------+--------------+-------------------------+ +| 5 | I2C_ADDR | tied to VBAT | ++-------+--------------+-------------------------+ +| 6 | GND | Ground | ++-------+--------------+-------------------------+ + +One Wire Sensor @ X2 + ++-------+----------------+-------------------------+ +| PIN # | Signal Name | Function | ++=======+================+=========================+ +| 1 | VDD | 4V8 | ++-------+----------------+-------------------------+ +| 2 | IO | One Wire | ++-------+----------------+-------------------------+ +| 3 | GND | Ground | ++-------+----------------+-------------------------+ + +External BLE Antenna @ J1 + +External LoRa Antenna @ J2 + +External GPS Antenna @ J3 + +Programming and Debugging +************************* + +Flashing +======== +The byteSENSI-L board can be flashed with the SEGGER JLink programmer. + +You can build and flash applications in the usual way. Here is an example for +the :ref:`hello_world` application. + + .. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: bytesensi_l + :goals: build flash + :compact: + +Debugging +========= + +Debugging your application can be done with ``west debug``. + +Serial console +============== + +The byteSENSI-L board only uses Segger's RTT console for providing serial +console. There is no physical serial port available. + +References +********** +* `bytesatwork website `_ +* `bytesatwork wiki `_ diff --git a/boards/bytesatwork/bytesensi_l/pre_dt_board.cmake b/boards/bytesatwork/bytesensi_l/pre_dt_board.cmake new file mode 100644 index 0000000000000..4bcc2f7a610ae --- /dev/null +++ b/boards/bytesatwork/bytesensi_l/pre_dt_board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2024 bytesatwork AG +# SPDX-License-Identifier: Apache-2.0 + +# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: +# - power@40000000 & clock@40000000 & bprot@40000000 +# - acl@4001e000 & flash-controller@4001e000 +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/bytesatwork/index.rst b/boards/bytesatwork/index.rst new file mode 100644 index 0000000000000..cb47fbff33325 --- /dev/null +++ b/boards/bytesatwork/index.rst @@ -0,0 +1,10 @@ +.. _boards-bytesatwork: + +bytesatwork +########### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/boards/circuitdojo/feather/circuitdojo_feather_nrf9160_common.dtsi b/boards/circuitdojo/feather/circuitdojo_feather_nrf9160_common.dtsi index 00ce5dcf6c00c..ced868614da98 100644 --- a/boards/circuitdojo/feather/circuitdojo_feather_nrf9160_common.dtsi +++ b/boards/circuitdojo/feather/circuitdojo_feather_nrf9160_common.dtsi @@ -50,7 +50,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &blue_led; watchdog0 = &wdt0; - spi-flash0 = &w25q32jv; accel0 = &lis2dh; }; diff --git a/boards/common/renode.board.cmake b/boards/common/renode.board.cmake new file mode 100644 index 0000000000000..c7c9b02ec59fd --- /dev/null +++ b/boards/common/renode.board.cmake @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_set_sim_runner_ifnset(renode) + +board_runner_args(renode "--renode-command=$elf=@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}") +board_runner_args(renode "--renode-command=include @${RENODE_SCRIPT}") + +board_finalize_runner_args(renode) diff --git a/boards/common/renode_robot.board.cmake b/boards/common/renode_robot.board.cmake new file mode 100644 index 0000000000000..3d42b3b8de1ac --- /dev/null +++ b/boards/common/renode_robot.board.cmake @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_set_robot_runner_ifnset(renode-robot) + +# `--variable` is a renode-test argument, for setting a variable that can be later used in a .robot file: +# ELF: used in common.robot to set the `elf` variable in the default .resc script defined in board.cmake +# RESC: path to the .resc script, defined in board.cmake +# UART: default UART used by Robot in tests, defined in board.cmake +# KEYWORDS: path to common.robot, which contains common Robot keywords +# RESULTS_DIR: directory in which Robot artifacts will be generated after running a testsuite +board_runner_args(renode-robot "--renode-robot-arg=--variable=ELF:@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}") +board_runner_args(renode-robot "--renode-robot-arg=--variable=RESC:@${RENODE_SCRIPT}") +board_runner_args(renode-robot "--renode-robot-arg=--variable=UART:${RENODE_UART}") +board_runner_args(renode-robot "--renode-robot-arg=--variable=KEYWORDS:${ZEPHYR_BASE}/tests/robot/common.robot") +board_runner_args(renode-robot "--renode-robot-arg=--variable=RESULTS_DIR:${APPLICATION_BINARY_DIR}") + +board_finalize_runner_args(renode-robot) diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_common.dtsi b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_common.dtsi index 437ea9ad225a0..764348106c9f7 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_common.dtsi +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_common.dtsi @@ -86,7 +86,8 @@ &spi6 { cs-gpios = <&gpio_prt12 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>, - <&gpio_prt13 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + <&gpio_prt13 0 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; - pinctrl-0 = <&p12_0_spi6_mosi &p12_1_spi6_miso &p12_2_spi6_clk>; + pinctrl-0 = <&p12_0_scb6_spi_m_mosi &p12_1_scb6_spi_m_miso &p12_2_scb6_spi_m_clk>; + pinctrl-names = "default"; }; diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347-pinctrl.dtsi b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347-pinctrl.dtsi new file mode 100644 index 0000000000000..1e42a6e464699 --- /dev/null +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347-pinctrl.dtsi @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* Configure pin control bias mode for uart5 pins */ +&p5_1_scb5_uart_tx { + drive-push-pull; +}; + +&p5_0_scb5_uart_rx { + input-enable; +}; + +&p9_1_scb2_uart_tx { + drive-push-pull; +}; + +&p9_0_scb2_uart_rx { + input-enable; +}; + +&p13_1_scb6_uart_tx { + drive-push-pull; +}; + +&p13_0_scb6_uart_rx { + input-enable; +}; + +/* Configure pin control bias mode for SPI pins */ +&p12_0_scb6_spi_m_mosi { + drive-push-pull; +}; + +&p12_1_scb6_spi_m_miso { + input-enable; +}; + +&p12_2_scb6_spi_m_clk { + drive-push-pull; +}; diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0.dts b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0.dts index 8f5176e2623d2..0fae593a8794a 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0.dts +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0.dts @@ -7,7 +7,7 @@ /dts-v1/; -#include +#include #include "cy8ckit_062_ble_common.dtsi" / { diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.overlay b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.overlay index eab076f247cb8..9ef0f747cd06a 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.overlay +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.overlay @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include "cy8ckit_062_ble_cy8c6347-pinctrl.dtsi" / { aliases { @@ -21,7 +22,8 @@ interrupt-parent = <&intmux_ch21>; - pinctrl-0 = <&p5_0_uart5_rx &p5_1_uart5_tx>; + pinctrl-0 = <&p5_0_scb5_uart_rx &p5_1_scb5_uart_tx>; + pinctrl-names = "default"; }; arduino_serial: &uart5 {}; diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.yaml b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.yaml index 311c88f58acbf..a8e935bd50ae9 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.yaml +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_0_0_0.yaml @@ -6,7 +6,7 @@ # identifier: cy8ckit_062_ble@0.0.0/cy8c6347/m0 -name: Cypress PSoC6 BLE Pioneer Kit (M0) +name: Cypress PSoC6 BLE Pioneer Kit (M0, rev. 0.0.0) type: mcu arch: arm ram: 288 diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.overlay b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.overlay index 49944a6dea498..ea63d017a6515 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.overlay +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "cy8ckit_062_ble_cy8c6347-pinctrl.dtsi" + / { aliases { uart-2 = &uart2; @@ -21,7 +23,9 @@ interrupt-parent = <&intmux_ch21>; - pinctrl-0 = <&p9_0_uart2_rx &p9_1_uart2_tx>; + pinctrl-0 = <&p9_0_scb2_uart_rx &p9_1_scb2_uart_tx>; + pinctrl-names = "default"; + }; &uart5 { @@ -30,7 +34,9 @@ interrupt-parent = <&intmux_ch22>; - pinctrl-0 = <&p5_0_uart5_rx &p5_1_uart5_tx>; + pinctrl-0 = <&p5_0_scb5_uart_rx &p5_1_scb5_uart_tx>; + pinctrl-names = "default"; + }; arduino_serial: &uart5 {}; diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.yaml b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.yaml index c3bcfac49c518..27b02fa4bedba 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.yaml +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m0_1_0_0.yaml @@ -6,7 +6,7 @@ # identifier: cy8ckit_062_ble@1.0.0/cy8c6347/m0 -name: Cypress PSoC6 BLE Pioneer Kit (M0) +name: Cypress PSoC6 BLE Pioneer Kit (M0, rev. 1.0.0) type: mcu arch: arm ram: 288 diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4.dts b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4.dts index 8288742042241..e232445e811a6 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4.dts +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4.dts @@ -7,7 +7,7 @@ /dts-v1/; -#include +#include #include "cy8ckit_062_ble_common.dtsi" / { diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.overlay b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.overlay index 9284d41cea78e..26f422a9b4dc3 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.overlay +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.overlay @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include "cy8ckit_062_ble_cy8c6347-pinctrl.dtsi" + / { aliases { uart-6 = &uart6; @@ -19,5 +21,6 @@ status = "okay"; current-speed = <115200>; - pinctrl-0 = <&p13_0_uart6_rx &p13_1_uart6_tx>; + pinctrl-0 = <&p13_0_scb6_uart_rx &p13_1_scb6_uart_tx>; + pinctrl-names = "default"; }; diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.yaml b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.yaml index ba22e8aa624b3..30708da7fa423 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.yaml +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_0_0_0.yaml @@ -6,7 +6,7 @@ # identifier: cy8ckit_062_ble@0.0.0/cy8c6347/m4 -name: Cypress PSoC6 BLE Pioneer Kit (M4) +name: Cypress PSoC6 BLE Pioneer Kit (M4, rev. 0.0.0) type: mcu arch: arm ram: 288 diff --git a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_1_0_0.yaml b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_1_0_0.yaml index bd4a3affce9f2..c75724709788d 100644 --- a/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_1_0_0.yaml +++ b/boards/cypress/cy8ckit_062_ble/cy8ckit_062_ble_cy8c6347_m4_1_0_0.yaml @@ -6,7 +6,7 @@ # identifier: cy8ckit_062_ble@1.0.0/cy8c6347/m4 -name: Cypress PSoC6 BLE Pioneer Kit (M4) +name: Cypress PSoC6 BLE Pioneer Kit (M4, rev. 1.0.0) type: mcu arch: arm ram: 288 diff --git a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi new file mode 100644 index 0000000000000..1e42a6e464699 --- /dev/null +++ b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* Configure pin control bias mode for uart5 pins */ +&p5_1_scb5_uart_tx { + drive-push-pull; +}; + +&p5_0_scb5_uart_rx { + input-enable; +}; + +&p9_1_scb2_uart_tx { + drive-push-pull; +}; + +&p9_0_scb2_uart_rx { + input-enable; +}; + +&p13_1_scb6_uart_tx { + drive-push-pull; +}; + +&p13_0_scb6_uart_rx { + input-enable; +}; + +/* Configure pin control bias mode for SPI pins */ +&p12_0_scb6_spi_m_mosi { + drive-push-pull; +}; + +&p12_1_scb6_spi_m_miso { + input-enable; +}; + +&p12_2_scb6_spi_m_clk { + drive-push-pull; +}; diff --git a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m0.dts b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m0.dts index fff6d89ea5d01..73766b76c1049 100644 --- a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m0.dts +++ b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m0.dts @@ -7,8 +7,9 @@ /dts-v1/; -#include +#include #include +#include "cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi" / { model = "cy8ckit_062_wifi_bt_m0 with a Cypress PSoC6 SoC"; @@ -61,5 +62,6 @@ interrupt-parent = <&intmux_ch21>; - pinctrl-0 = <&p13_0_uart6_rx &p13_1_uart6_tx>; + pinctrl-0 = <&p13_0_scb6_uart_rx &p13_1_scb6_uart_tx>; + pinctrl-names = "default"; }; diff --git a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m4.dts b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m4.dts index e192f94580d8e..29ea4b85134c3 100644 --- a/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m4.dts +++ b/boards/cypress/cy8ckit_062_wifi_bt/cy8ckit_062_wifi_bt_cy8c6247_m4.dts @@ -6,7 +6,8 @@ /dts-v1/; -#include +#include +#include "cy8ckit_062_wifi_bt_cy8c6247-pinctrl.dtsi" / { model = "cy8ckit_062_wifi_bt_m4 with a Cypress PSoC6 SoC"; @@ -28,5 +29,6 @@ status = "okay"; current-speed = <115200>; - pinctrl-0 = <&p5_0_uart5_rx &p5_1_uart5_tx>; + pinctrl-0 = <&p5_0_scb5_uart_rx &p5_1_scb5_uart_tx>; + pinctrl-names = "default"; }; diff --git a/boards/cypress/cy8ckit_062s4/board.yml b/boards/cypress/cy8ckit_062s4/board.yml deleted file mode 100644 index adb45b87c0795..0000000000000 --- a/boards/cypress/cy8ckit_062s4/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: cy8ckit_062s4 - vendor: cypress - socs: - - name: cy8c6244lqi_s4d92 diff --git a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4.dts b/boards/cypress/cy8ckit_062s4/cy8ckit_062s4.dts deleted file mode 100644 index 6695a24a4b88b..0000000000000 --- a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4.dts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2023 David Ullmann - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include - -/ { - model = "Infineon PSoC 62S4 Pioneer Kit"; - compatible ="cypress,psoc6"; - chosen { - zephyr,sram = &sram0; - zephyr,flash = &flash0; - zephyr,console = &uart2; - zephyr,shell-uart = &uart2; - }; - - aliases { - led0 = &user_led; - }; - - leds { - compatible = "gpio-leds"; - user_led: led_0 { - label = "LED_0"; - gpios = <&gpio_prt2 5 GPIO_ACTIVE_HIGH>; - }; - - }; - -}; - -&p3_1_scb2_uart_tx { - drive-push-pull; -}; - -&p3_0_scb2_uart_rx { - input-enable; -}; - - -uart2: &scb2 { - compatible = "infineon,cat1-uart"; - status = "okay"; - current-speed = <115200>; - pinctrl-0 = <&p3_0_scb2_uart_rx &p3_1_scb2_uart_tx>; - pinctrl-names = "default"; -}; - -&gpio_prt3 { - status = "okay"; -}; - -&gpio_prt2 { - status = "okay"; -}; diff --git a/boards/cypress/cy8ckit_062s4/doc/index.rst b/boards/cypress/cy8ckit_062s4/doc/index.rst deleted file mode 100644 index f3a026b3b6bc8..0000000000000 --- a/boards/cypress/cy8ckit_062s4/doc/index.rst +++ /dev/null @@ -1,115 +0,0 @@ -.. _cy8ckit_062s4: - -[INFINEON PSoC 62S4 Pioneer Kit] -################################ - -Overview -******** -The PSOC 62S4 Pioneer kit has a CY8C62x4 MCU, which is an ultra-low-power PSoC device specifically designed for battery-operated analog -sensing applications. It includes a 150-MHz Arm® Cortex®-M4 CPU as the primary application processor, a 100-MHz Arm® Cortex®-M0+ CPU that -supports low-power operations, up to 256 KB Flash and 128 KB SRAM, programmable analog sensing, -CapSense™ touch-sensing, and programmable digital peripherals. - -The board features an onboard -programmer/debugger (KitProg3), a 512-Mbit Quad SPI NOR flash, a micro-B connector for USB device -interface, a thermistor, an ambient light sensor, a 5-segment CapSense™ slider, two CapSense™ buttons, two -user LEDs, and a push button. The board supports operating voltages from 1.8 V to 3.3 V for PSoC™ 6 MCU. - -.. figure::img/cy8ckit_062s4.png - :width: 800px - :align: center - :alt: Board Name - - Board Name (Credit: ) - -Hardware -******** - -`CY8CKIT 062S4 Pioneer Kit Website`_ -`CY8CKIT 062S4 Pioneer Kit Guide`_ -`CY8CKIT 062S4 Pioneer Kit Schematic`_ -`CY8CKIT 062S4 Pioneer Kit Technical Reference Manual`_ -`CY8CKIT 062S4 Pioneer Kit Datasheet`_ - -Supported Features -================== - -The board configuration supports the following hardware features: - -+-----------+------------+-----------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=======================+ -| NVIC | on-chip | nested vectored | -| | | interrupt controller | -+-----------+------------+-----------------------+ -| SYSTICK | on-chip | system clock | -+-----------+------------+-----------------------+ -| PINCTRL | on-chip | pin control | -+-----------+------------+-----------------------+ -| UART | on-chip | serial port-polling; | -+-----------+------------+-----------------------+ - -The default configuration can be found in the Kconfig -:zephyr_file:`boards/cypress/cy8ckit_062s4/cy8ckit_062s4_defconfig`. - -Clock Configuration -=================== - -+-----------+------------+-----------------------+ -| Clock | Source | Output Frequency | -+===========+============+=======================+ -| FLL | IMO | 100.0 MHz | -+-----------+------------+-----------------------+ -| PLL | IMO | 48.0 MHz | -+-----------+------------+-----------------------+ -| CLK_HF0 | CLK_PATH0 | 100.0 MHz | -+-----------+------------+-----------------------+ - -Fetch Binary Blobs -================== - -.. code-block:: console - - west blobs fetch hal_infineon - - -Build and flash hello world sample -********************************** - - -.. code-block:: console - - cd zephyr/samples/hello_world - west build -p auto -b cy8ckit_062s4 --pristine - west flash - picocom /dev/ttyACM0 -b 115200 - -OpenOCD Installation -==================== - -To get the OpenOCD package, it is required that you - -1. Download the software ModusToolbox 3.1. https://softwaretools.infineon.com/tools/com.ifx.tb.tool.modustoolbox -2. Once downloaded add the path to access the Scripts folder provided by ModusToolbox - export PATH=$PATH:/path/to/ModusToolbox/tools_3.1/openocd/scripts -3. Add the OpenOCD executable file's path to west flash/debug. -4. Flash using: west flash --openocd path/to/infineon/openocd/bin/openocd -5. Debug using: west debug --openocd path/to/infineon/openocd/bin/openocd - -References -********** - -.. _CY8CKIT 062S4 Pioneer Kit Guide: - https://www.infineon.com/dgdl/Infineon-CY8CKIT_062S4_PSoC62S4_pioneer_kit_guide-UserManual-v01_00-EN.pdf?fileId=8ac78c8c7e7124d1017e962f98992207 - -.. _CY8CKIT 062S4 Pioneer Kit Website: - https://www.infineon.com/cms/en/product/evaluation-boards/cy8ckit-062s4/?redirId=VL1508&utm_medium=referral&utm_source=cypress&utm_campaign=202110_globe_en_all_integration-dev_kit - -.. _CY8CKIT 062S4 Pioneer Kit Schematic: - https://www.infineon.com/dgdl/Infineon-CY8CKIT-062S4_PSoC_62S4_Pioneer_Kit_Schematic-PCBDesignData-v01_00-EN.pdf?fileId=8ac78c8c7d710014017d7153484d2081 - -.. _CY8CKIT 062S4 Pioneer Kit Technical Reference Manual: - https://www.infineon.com/dgdl/Infineon-PSOC_6_MCU_CY8C61X4CY8C62X4_REGISTERS_TECHNICAL_REFERENCE_MANUAL_(TRM)_PSOC_61_PSOC_62_MCU-AdditionalTechnicalInformation-v03_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0fb34f0627a7 - -.. _CY8CKIT 062S4 Pioneer Kit Datasheet: - https://www.infineon.com/dgdl/Infineon-PSoC_6_MCU_CY8C62X4-DataSheet-v12_00-EN.pdf?fileId=8ac78c8c7ddc01d7017ddd026d585901 diff --git a/boards/cypress/cy8cproto_062_4343w/Kconfig.defconfig b/boards/cypress/cy8cproto_062_4343w/Kconfig.defconfig deleted file mode 100644 index 270370c766015..0000000000000 --- a/boards/cypress/cy8cproto_062_4343w/Kconfig.defconfig +++ /dev/null @@ -1,54 +0,0 @@ -# CY8CPROTO-062-4343W PSoC™ 6 Wi-Fi BT Prototyping Kit configuration - -# Copyright (c) 2021 Cypress Semiconductor Corporation. -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_CY8CPROTO_062_4343W - -if WIFI || BT - -# Select AIROC part and module -choice AIROC_PART - default CYW4343W -endchoice - -choice CYW4343W_MODULE - default CYW4343W_MURATA_1DX -endchoice - -endif # WIFI || BT - -if WIFI - -config WIFI_AIROC - default y - -# Enable L2 Ethernet -config NET_L2_ETHERNET - default y - -endif # WIFI - -if BT - -# Select HCI components -config UART - bool - default y - -config BT_UART - default y - -choice BT_HCI_BUS_TYPE - default BT_H4 -endchoice - -endif # BT - -# Heap Pool Size -config HEAP_MEM_POOL_ADD_SIZE_BOARD - int - default 15000 if WIFI - default 4096 - -endif # BOARD_CY8CPROTO_062_4343W diff --git a/boards/cypress/cy8cproto_062_4343w/board.yml b/boards/cypress/cy8cproto_062_4343w/board.yml deleted file mode 100644 index 575dbf8341487..0000000000000 --- a/boards/cypress/cy8cproto_062_4343w/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: cy8cproto_062_4343w - vendor: cypress - socs: - - name: cy8c624abzi_s2d44 diff --git a/boards/cypress/cy8cproto_062_4343w/doc/index.rst b/boards/cypress/cy8cproto_062_4343w/doc/index.rst deleted file mode 100644 index e1be366086c4e..0000000000000 --- a/boards/cypress/cy8cproto_062_4343w/doc/index.rst +++ /dev/null @@ -1,184 +0,0 @@ -.. _cy8cproto_062_4343w: - -INFINEON CY8CPROTO-062-4343W -############################ - -Overview -******** - -The CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Prototyping Kit is a low-cost hardware -platform that enables design and debug of PSoC 6 MCUs. It comes with a Murata -LBEE5KL1DX module, based on the CYW4343W combo device, industry-leading CAPSENSE -for touch buttons and slider, on-board debugger/programmer with KitProg3, microSD -card interface, 512-Mb Quad-SPI NOR flash, PDM-PCM microphone, and a thermistor. - -This kit is designed with a snap-away form-factor, allowing the user to separate -the different components and features that come with this kit and use independently. -In addition, support for Digilent's Pmod interface is also provided with this kit. - -.. image:: img/board.jpg - :align: center - :alt: CY8CPROTO-062-4343W - -Hardware -******** - -For more information about the PSoC 62 MCU SoC and CY8CPROTO-062-4343W board: - -- `PSoC 62 MCU SoC Website`_ -- `PSoC 62 MCU Datasheet`_ -- `PSoC 62 MCU Architecture Reference Manual`_ -- `PSoC 62 MCU Register Reference Manual`_ -- `CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Website`_ -- `CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT User Guide`_ -- `CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Schematics`_ - -Kit Features: -============= - -- Support of up to 2MB Flash and 1MB SRAM -- Dedicated SDHC to interface with WICED wireless devices. -- Delivers dual-cores, with a 150-MHz Arm Cortex-M4 as the primary - application processor and a 100-MHz Arm Cortex-M0+ as the secondary - processor for low-power operations. -- Supports Full-Speed USB, capacitive-sensing with CAPSENSE, a PDM-PCM - digital microphone interface, a Quad-SPI interface, 13 serial communication - blocks, 7 programmable analog blocks, and 56 programmable digital blocks. - -Kit Contents: -============= - -- PSoC 6 Wi-Fi BT Prototyping Board -- USB Type-A to Micro-B cable -- Quick Start Guide - -Supported Features -================== - -The board configuration supports the following hardware features: - -+-----------+------------+-----------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=======================+ -| NVIC | on-chip | nested vectored | -| | | interrupt controller | -+-----------+------------+-----------------------+ -| SYSTICK | on-chip | system clock | -+-----------+------------+-----------------------+ -| GPIO | on-chip | GPIO | -+-----------+------------+-----------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-----------------------+ - - -The default configuration can be found in the Kconfig - -:zephyr_file:`boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig` - - -System Clock -============ - -The PSoC 62 MCU SoC is configured to use the internal IMO+FLL as a source for -the system clock. CM0+ works at 50MHz, CM4 - at 100MHz. Other sources for the -system clock are provided in the SOC, depending on your system requirements. - - -Fetch Binary Blobs -****************** - -cy8cproto_062_4343w board optionally uses binary blobs for features -(e.g WIFI/Bluetooth chip firmware, CM0p prebuilt images, etc). - -To fetch Binary Blobs: - -.. code-block:: console - - west blobs fetch hal_infineon - - -Build blinking led sample -************************* - -Here is an example for the :zephyr:code-sample:`blinky` application. - -.. code-block:: console - - cd zephyr - west build -p auto -b cy8cproto_062_4343w samples/basic/blink - -OpenOCD Installation -==================== - -To get the OpenOCD package, it is required that you - -1. Download the software ModusToolbox 3.1. https://softwaretools.infineon.com/tools/com.ifx.tb.tool.modustoolbox -2. Once downloaded add the path to access the Scripts folder provided by ModusToolbox - export PATH=$PATH:/path/to/ModusToolbox/tools_3.1/openocd/scripts -3. Add the OpenOCD executable file's path to west flash/debug. -4. Flash using: west flash --openocd path/to/infineon/openocd/bin/openocd -5. Debug using: west debug --openocd path/to/infineon/openocd/bin/openocd - - -Programming and Debugging -************************* - -The CY8CPROTO-062-4343W includes an onboard programmer/debugger (KitProg2) with -mass storage programming to provide debugging, flash programming, and serial -communication over USB. Flash and debug commands must be pointed to the Cypress -OpenOCD you downloaded above. - -On Windows: - -.. code-block:: console - - west flash --openocd path/to/infineon/openocd/bin/openocd.exe - west debug --openocd path/to/infineon/openocd/bin/openocd.exe - -On Linux: - -.. code-block:: console - - west flash --openocd path/to/infineon/openocd/bin/openocd - west debug --openocd path/to/infineon/openocd/bin/openocd - -Once the gdb console starts after executing the west debug command, you may -now set breakpoints and perform other standard GDB debugging on the PSoC 6 CM4 core. - -Errata -====== - -+------------------------------------------------+----------------------------------------+ -| Problem | Solution | -+================================================+========================================+ -| The GPIO_INT_TRIG_BOTH interrupt is not raised | This will be fixed in a future release.| -| when the associated GPIO is asserted. | | -+------------------------------------------------+----------------------------------------+ -| GDB experiences a timeout error connecting to | This will be fixed in a future release.| -| a server instance started by west debugserver. | | -+------------------------------------------------+----------------------------------------+ - -.. _PSoC 62 MCU SoC Website: - https://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 - -.. _PSoC 62 MCU Datasheet: - https://www.cypress.com/documentation/datasheets/psoc-6-mcu-psoc-62-datasheet-programmable-system-chip-psoc-preliminary - -.. _PSoC 62 MCU Architecture Reference Manual: - https://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-architecture-technical-reference-manual - -.. _PSoC 62 MCU Register Reference Manual: - https://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-register-technical-reference-manual-trm - -.. _CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Website: - https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-062-4343w/ - -.. _CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT User Guide: - https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-062-4343w/#!?fileId=8ac78c8c7d0d8da4017d0f0118571844 - -.. _CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Schematics: - https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-062-4343w/#!?fileId=8ac78c8c7d0d8da4017d0f01126b183f - -.. _Infineon OpenOCD: - https://github.com/infineon/openocd/releases/tag/release-v4.3.0 diff --git a/boards/cypress/cy8cproto_063_ble/Kconfig.defconfig b/boards/cypress/cy8cproto_063_ble/Kconfig.defconfig deleted file mode 100644 index 2d079f63a6b48..0000000000000 --- a/boards/cypress/cy8cproto_063_ble/Kconfig.defconfig +++ /dev/null @@ -1,13 +0,0 @@ -# CY8CPROTO-063-BLE PSoC™ 6 BLE Prototyping Kit - -# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or -# an affiliate of Cypress Semiconductor Corporation -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_CY8CPROTO_063_BLE - -choice BT_HCI_BUS_TYPE - default BT_PSOC6_BLESS if BT -endchoice - -endif # BOARD_CY8CPROTO_063_BLE diff --git a/boards/cypress/cy8cproto_063_ble/board.yml b/boards/cypress/cy8cproto_063_ble/board.yml deleted file mode 100644 index b35cb08ec2fcf..0000000000000 --- a/boards/cypress/cy8cproto_063_ble/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: cy8cproto_063_ble - vendor: cypress - socs: - - name: cyble_416045_02 diff --git a/boards/cypress/cy8cproto_063_ble/doc/index.rst b/boards/cypress/cy8cproto_063_ble/doc/index.rst deleted file mode 100644 index 8ef38711c8f8e..0000000000000 --- a/boards/cypress/cy8cproto_063_ble/doc/index.rst +++ /dev/null @@ -1,144 +0,0 @@ -.. _cy8cproto_063_ble: - -INFINEON CY8CPROTO-063-BLE -########################### - -Overview -******** - -The PSoC 6 BLE Proto Kit (CY8CPROTO-063-BLE) is a hardware platform that -enables design and debug of the Cypress PSoC 63 BLE MCU. - -.. image:: img/cy8cproto-063-ble.jpg - :align: center - :alt: CY8CPROTO-063-BLE - -Hardware -******** - -For more information about the PSoC 63 BLE MCU SoC and CY8CPROTO-063-BLE board: - -- `PSoC 63 BLE MCU SoC Website`_ -- `PSoC 63 BLE MCU Datasheet`_ -- `PSoC 63 BLE MCU Architecture Reference Manual`_ -- `PSoC 63 BLE MCU Register Reference Manual`_ -- `CY8CPROTO-063-BLE Website`_ -- `CY8CPROTO-063-BLE User Guide`_ -- `CY8CPROTO-063-BLE Schematics`_ - -Supported Features -================== - -The board configuration supports the following hardware features: - -+-----------+------------+-----------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=======================+ -| NVIC | on-chip | nested vectored | -| | | interrupt controller | -+-----------+------------+-----------------------+ -| SYSTICK | on-chip | system clock | -+-----------+------------+-----------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-----------------------+ -| PINCTRL | on-chip | pin control | -+-----------+------------+-----------------------+ -| SPI | on-chip | spi | -+-----------+------------+-----------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-----------------------+ -| I2C | on-chip | I2C | -+-----------+------------+-----------------------+ -| PWM | on-chip | PWM | -+-----------+------------+-----------------------+ -| Counter | on-chip | Counter | -+-----------+------------+-----------------------+ -| Bluetooth | on-chip | Bluetooth | -+-----------+------------+-----------------------+ - - -The default configurations can be found in -:zephyr_file:`boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble_defconfig` - -System Clock -============ - -The PSoC 63 BLE MCU SoC is configured to use the internal IMO+FLL as a source for -the system clock. CM0+ works at 50MHz, CM4 - at 100MHz. Other sources for the -system clock are provided in the SOC, depending on your system requirements. - - -OpenOCD Installation -==================== - -To get the OpenOCD package, it is required that you - -1. Download the software ModusToolbox 3.1. https://softwaretools.infineon.com/tools/com.ifx.tb.tool.modustoolbox -2. Once downloaded add the path to access the Scripts folder provided by ModusToolbox - export PATH=$PATH:/path/to/ModusToolbox/tools_3.1/openocd/scripts -3. Add the OpenOCD executable file's path to west flash/debug. -4. Flash using: west flash --openocd path/to/infineon/openocd/bin/openocd -5. Debug using: west debug --openocd path/to/infineon/openocd/bin/openocd - - -Fetch Binary Blobs -****************** - -cy8cproto_063_ble board requires fetch binary files -(e.g Bluetooth controller firmware, CM0p prebuilt images, etc). - -To fetch Binary Blobs: - -.. code-block:: console - - west blobs fetch hal_infineon - -Programming and Debugging -************************* - -The CY8CPROTO-063-BLE includes an onboard programmer/debugger (KitProg3) with -mass storage programming to provide debugging, flash programming, and serial -communication over USB. Flash and debug commands must be pointed to the Cypress -OpenOCD you downloaded above. - -On Windows: - -.. code-block:: console - - west flash --openocd path/to/infineon/openocd/bin/openocd.exe - west debug --openocd path/to/infineon/openocd/bin/openocd.exe - -On Linux: - -.. code-block:: console - - west flash --openocd path/to/infineon/openocd/bin/openocd - west debug --openocd path/to/infineon/openocd/bin/openocd - -References -********** - -.. _PSoC 63 BLE MCU SoC Website: - https://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 - -.. _PSoC 63 BLE MCU Datasheet: - https://www.infineon.com/dgdl/Infineon-PSoC_6_MCU_PSoC_63_with_BLE_Datasheet_Programmable_System-on-Chip_(PSoC)-DataSheet-v16_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0ee4efe46c37&utm_source=cypress&utm_medium=referral&utm_campaign=202110_globe_en_all_integration-files - -.. _PSoC 63 BLE MCU Architecture Reference Manual: - https://documentation.infineon.com/html/psoc6/zrs1651212645947.html - -.. _PSoC 63 BLE MCU Register Reference Manual: - https://documentation.infineon.com/html/psoc6/bnm1651211483724.html - -.. _CY8CPROTO-063-BLE Website: - https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-063-ble/ - -.. _CY8CPROTO-063-BLE User Guide: - https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-063-ble/#!?fileId=8ac78c8c7d0d8da4017d0f00d7eb1812 - -.. _CY8CPROTO-063-BLE Schematics: - https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-063-ble/#!?fileId=8ac78c8c7d0d8da4017d0f00ea3c1821 - -.. _Infineon OpenOCD: - https://github.com/infineon/openocd/releases/tag/release-v4.3.0 diff --git a/boards/deprecated.cmake b/boards/deprecated.cmake index 89a8b463e69e5..f1a40a8b31872 100644 --- a/boards/deprecated.cmake +++ b/boards/deprecated.cmake @@ -138,31 +138,61 @@ set(ebyte_e73_tbb_nrf52832_DEPRECATED ebyte_e73_tbb ) set(efm32pg_stk3402a_DEPRECATED - efm32pg_stk3402a/efm32pg12b500f1024gl125 + slstk3402a/efm32pg12b500f1024gl125 ) set(efm32pg_stk3402a_jg_DEPRECATED - efm32pg_stk3402a/efm32jg12b500f1024gl125 + slstk3402a/efm32jg12b500f1024gl125 +) +set(efm32hg_slstk3400a_DEPRECATED + slstk3400a +) +set(efm32pg_stk3401a_DEPRECATED + slstk3401a +) +set(efm32gg_stk3701a_DEPRECATED + slstk3701a +) +set(efm32gg_slwstk6121a_DEPRECATED + slwrb4321a ) set(efr32_radio_brd4104a_DEPRECATED - efr32_radio/efr32bg13p632f512gm48 + slwrb4104a ) set(efr32_radio_brd4161a_DEPRECATED - efr32_radio/efr32mg12p432f1024gl125 + slwrb4161a ) set(efr32_radio_brd4170a_DEPRECATED - efr32_radio/efr32mg12p433f1024gm68 + slwrb4170a ) set(efr32_radio_brd4180a_DEPRECATED - efr32_radio/efr32mg21a020f1024im32 + slwrb4180a ) set(efr32_radio_brd4187c_DEPRECATED - efr32_radio/efr32mg24b220f1536im48 + xg24_rb4187c ) set(efr32_radio_brd4250b_DEPRECATED - efr32_radio/efr32fg1p133f256gm48 + slwrb4250b ) set(efr32_radio_brd4255a_DEPRECATED - efr32_radio/efr32fg13p233f512gm48 + slwrb4255a +) +set(efm32gg_sltb009a_DEPRECATED + sltb009a +) +set(efr32mg_sltb004a_DEPRECATED + sltb004a +) +set(efr32bg22_brd4184a_DEPRECATED + sltb010a@0 +) +set(efr32bg22_brd4184b_DEPRECATED + sltb010a@2 +) +set(efr32xg24_dk2601b_DEPRECATED + xg24_dk2601b +) +set(efr32bg27_brd2602a_DEPRECATED + xg27_dk2602a ) set(em_starterkit_DEPRECATED em_starterkit/emsk_em9d diff --git a/boards/digilent/arty_a7/dts/arty_a7_arm_designstart.dtsi b/boards/digilent/arty_a7/dts/arty_a7_arm_designstart.dtsi index 0f51819e18076..8162b47d7d3d7 100644 --- a/boards/digilent/arty_a7/dts/arty_a7_arm_designstart.dtsi +++ b/boards/digilent/arty_a7/dts/arty_a7_arm_designstart.dtsi @@ -26,7 +26,6 @@ sw1 = &sw1; sw2 = &sw2; sw3 = &sw3; - spi-flash0 = &flash0; }; leds { diff --git a/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m1.cfg b/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m1.cfg index cf9f88347ecbb..213703a924752 100644 --- a/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m1.cfg +++ b/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m1.cfg @@ -1,7 +1,7 @@ source [find interface/cmsis-dap.cfg] source [find target/swj-dp.tcl] -adapter_khz 5000 +adapter speed 5000 set _CHIPNAME cortex_m1 set _ENDIAN little diff --git a/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m3.cfg b/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m3.cfg index 17dbbb997ffd4..9491c2df0d7e6 100644 --- a/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m3.cfg +++ b/boards/digilent/arty_a7/support/openocd_arty_a7_arm_designstart_m3.cfg @@ -1,7 +1,7 @@ source [find interface/cmsis-dap.cfg] source [find target/swj-dp.tcl] -adapter_khz 5000 +adapter speed 5000 set _CHIPNAME cortex_m3 set _ENDIAN little diff --git a/boards/element14/warp7/Kconfig.defconfig b/boards/element14/warp7/Kconfig.defconfig index b73424093e074..fcb09419c3524 100644 --- a/boards/element14/warp7/Kconfig.defconfig +++ b/boards/element14/warp7/Kconfig.defconfig @@ -13,11 +13,4 @@ config FXAS21002_DRDY_INT1 default y depends on FXAS21002_TRIGGER -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - endif # BOARD_WARP7 diff --git a/boards/enjoydigital/litex_vexriscv/litex_vexriscv.dts b/boards/enjoydigital/litex_vexriscv/litex_vexriscv.dts index eab0c15266616..98971ae4f1a46 100644 --- a/boards/enjoydigital/litex_vexriscv/litex_vexriscv.dts +++ b/boards/enjoydigital/litex_vexriscv/litex_vexriscv.dts @@ -23,6 +23,10 @@ }; }; +&ctrl0 { + status = "okay"; +}; + &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/espressif/esp32_devkitc_wroom/Kconfig.defconfig b/boards/espressif/esp32_devkitc_wroom/Kconfig.defconfig index 6da35bf9735f0..374b423b5483c 100644 --- a/boards/espressif/esp32_devkitc_wroom/Kconfig.defconfig +++ b/boards/espressif/esp32_devkitc_wroom/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_ESP32_DEVKITC_WROOM_ESP32_PROCPU if BOARD_ESP32_DEVKITC_WROOM_ESP32_APPCPU diff --git a/boards/espressif/esp32_devkitc_wroom/doc/index.rst b/boards/espressif/esp32_devkitc_wroom/doc/index.rst index ec1248da38e7b..58106b69ab6e0 100644 --- a/boards/espressif/esp32_devkitc_wroom/doc/index.rst +++ b/boards/espressif/esp32_devkitc_wroom/doc/index.rst @@ -61,7 +61,6 @@ Current Zephyr's ESP32-WROOM board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_appcpu.dts b/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_appcpu.dts index c52b029ea552a..ae7a2e1e7f653 100644 --- a/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_appcpu.dts +++ b/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_procpu.dts b/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_procpu.dts index 1708a7badf987..37a117d80dbe9 100644 --- a/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_procpu.dts +++ b/boards/espressif/esp32_devkitc_wroom/esp32_devkitc_wroom_procpu.dts @@ -36,18 +36,10 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; }; -&cpu0 { - clock-frequency = ; - cpu-power-states = <&light_sleep &deep_sleep>; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -174,3 +166,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/espressif/esp32_devkitc_wrover/Kconfig.defconfig b/boards/espressif/esp32_devkitc_wrover/Kconfig.defconfig index ba249b4a0a6af..c56c404a40e7f 100644 --- a/boards/espressif/esp32_devkitc_wrover/Kconfig.defconfig +++ b/boards/espressif/esp32_devkitc_wrover/Kconfig.defconfig @@ -10,10 +10,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_ESP32_DEVKITC_WROVER_ESP32_PROCPU if BOARD_ESP32_DEVKITC_WROVER_ESP32_APPCPU diff --git a/boards/espressif/esp32_devkitc_wrover/doc/index.rst b/boards/espressif/esp32_devkitc_wrover/doc/index.rst index 1f66f3da8a923..7a29912dfbc9d 100644 --- a/boards/espressif/esp32_devkitc_wrover/doc/index.rst +++ b/boards/espressif/esp32_devkitc_wrover/doc/index.rst @@ -61,7 +61,6 @@ Current Zephyr's ESP32-devkitc board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.dts b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.dts index 7298148a2c34d..42c30a1079c4d 100644 --- a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.dts +++ b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.yaml b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.yaml index 8c8e8ae15778e..0408282380163 100644 --- a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.yaml +++ b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_appcpu.yaml @@ -1,5 +1,5 @@ identifier: esp32_devkitc_wrover/esp32/appcpu -name: ESP32-DevkitC-WROVER-E +name: ESP32-DevkitC-WROVER-E APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.dts b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.dts index 60a063bc87561..f6ad45109c398 100644 --- a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.dts +++ b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.dts @@ -36,17 +36,10 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -169,3 +162,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.yaml b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.yaml index bf130d7d3a8cd..a2089253a3c6b 100644 --- a/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.yaml +++ b/boards/espressif/esp32_devkitc_wrover/esp32_devkitc_wrover_procpu.yaml @@ -1,5 +1,5 @@ identifier: esp32_devkitc_wrover/esp32/procpu -name: ESP32-DevkitC-WROVER-E +name: ESP32-DevkitC-WROVER-E PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp32_ethernet_kit/Kconfig.defconfig b/boards/espressif/esp32_ethernet_kit/Kconfig.defconfig index e7f2edb7c059f..75b0cc9f631ef 100644 --- a/boards/espressif/esp32_ethernet_kit/Kconfig.defconfig +++ b/boards/espressif/esp32_ethernet_kit/Kconfig.defconfig @@ -6,7 +6,7 @@ if BOARD_ESP32_ETHERNET_KIT_ESP32_PROCPU config ESP_SPIRAM - default y + default y if !MCUBOOT choice SPIRAM_TYPE default SPIRAM_TYPE_ESPPSRAM64 @@ -19,10 +19,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_ESP32_ETHERNET_KIT_ESP32_PROCPU if BOARD_ESP32_ETHERNET_KIT_ESP32_APPCPU diff --git a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.dts b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.dts index c5e1217b25c56..eb613c2cc0683 100644 --- a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.dts +++ b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.yaml b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.yaml index 1984dea8da3c2..7f2f067d72c67 100644 --- a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.yaml +++ b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_appcpu.yaml @@ -1,5 +1,5 @@ identifier: esp32_ethernet_kit/esp32/appcpu -name: ESP32 ETHERNET KIT +name: ESP32 ETHERNET KIT APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.dts b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.dts index 7e8310c9605b4..124fa29df4e99 100644 --- a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.dts +++ b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.dts @@ -23,17 +23,10 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -130,3 +123,7 @@ ð { phy-handle = <&phy>; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.yaml b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.yaml index d7d4958d2e73f..ca098c1ef773d 100644 --- a/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.yaml +++ b/boards/espressif/esp32_ethernet_kit/esp32_ethernet_kit_procpu.yaml @@ -1,5 +1,5 @@ identifier: esp32_ethernet_kit/esp32/procpu -name: ESP32 ETHERNET KIT +name: ESP32 ETHERNET KIT PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp32c3_devkitm/Kconfig.defconfig b/boards/espressif/esp32c3_devkitm/Kconfig.defconfig index 9944bb871951b..cf5aeac8382d0 100644 --- a/boards/espressif/esp32c3_devkitm/Kconfig.defconfig +++ b/boards/espressif/esp32c3_devkitm/Kconfig.defconfig @@ -9,7 +9,3 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 51200 if WIFI default 40960 if BT default 4096 - -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice diff --git a/boards/espressif/esp32c3_devkitm/doc/index.rst b/boards/espressif/esp32c3_devkitm/doc/index.rst index c2d6551170cfe..9028d0c3cabd2 100644 --- a/boards/espressif/esp32c3_devkitm/doc/index.rst +++ b/boards/espressif/esp32c3_devkitm/doc/index.rst @@ -40,7 +40,6 @@ Current Zephyr's ESP32-C3-Devkitm board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts b/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts index e636089ba03e3..ae11ed41aa2e2 100644 --- a/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts +++ b/boards/espressif/esp32c3_devkitm/esp32c3_devkitm.dts @@ -11,7 +11,7 @@ #include / { - model = "Espressif ESP32-DevkitM"; + model = "Espressif ESP32C3-DevkitM"; compatible = "espressif,esp32c3"; chosen { @@ -20,6 +20,7 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -38,10 +39,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -94,7 +91,6 @@ status = "disabled"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &flash0 { @@ -135,3 +131,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/espressif/esp32c3_devkitm/support/openocd.cfg b/boards/espressif/esp32c3_devkitm/support/openocd.cfg index 214a4aabf3fc6..92a792fecb8eb 100644 --- a/boards/espressif/esp32c3_devkitm/support/openocd.cfg +++ b/boards/espressif/esp32c3_devkitm/support/openocd.cfg @@ -8,4 +8,4 @@ set ESP_RTOS none source [find interface/ftdi/esp32_devkitj_v1.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/espressif/esp32c6_devkitc/Kconfig.defconfig b/boards/espressif/esp32c6_devkitc/Kconfig.defconfig new file mode 100644 index 0000000000000..fccfb36845b2b --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/Kconfig.defconfig @@ -0,0 +1,11 @@ +# ESP32C6 devkitc board configuration + +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config HEAP_MEM_POOL_ADD_SIZE_BOARD + int + default 65535 if WIFI && BT + default 51200 if WIFI + default 40960 if BT + default 4096 diff --git a/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc b/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc new file mode 100644 index 0000000000000..4bd1fce4efc33 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/Kconfig.esp32c6_devkitc @@ -0,0 +1,7 @@ +# ESP32C6 devkitc board configuration + +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ESP32C6_DEVKITC + select SOC_ESP32_C6_WROOM_1U_N8 diff --git a/boards/espressif/esp32c6_devkitc/Kconfig.sysbuild b/boards/espressif/esp32c6_devkitc/Kconfig.sysbuild new file mode 100644 index 0000000000000..3a2d17ac5cfd0 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/espressif/esp32c6_devkitc/board.cmake b/boards/espressif/esp32c6_devkitc/board.cmake new file mode 100644 index 0000000000000..2f04d1fe8861e --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/espressif/esp32c6_devkitc/board.yml b/boards/espressif/esp32c6_devkitc/board.yml new file mode 100644 index 0000000000000..ad88f3a931573 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/board.yml @@ -0,0 +1,5 @@ +board: + name: esp32c6_devkitc + vendor: espressif + socs: + - name: esp32c6 diff --git a/boards/espressif/esp32c6_devkitc/doc/index.rst b/boards/espressif/esp32c6_devkitc/doc/index.rst new file mode 100644 index 0000000000000..9eb87fe2a8acf --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/doc/index.rst @@ -0,0 +1,274 @@ +.. _esp32c6_devkitc: + +ESP32-C6-DevKitC-1 +################## + +Overview +******** + +ESP32-C6 is Espressif's first Wi-Fi 6 SoC integrating 2.4 GHz Wi-Fi 6, Bluetooth 5.3 (LE) and the +802.15.4 protocol. ESP32-C6 achieves an industry-leading RF performance, with reliable security +features and multiple memory resources for IoT products. +It consists of a high-performance (HP) 32-bit RISC-V processor, which can be clocked up to 160 MHz, +and a low-power (LP) 32-bit RISC-V processor, which can be clocked up to 20 MHz. +It has a 320KB ROM, a 512KB SRAM, and works with external flash. [1]_ + +ESP32-C6-DevKitC-1 is an entry-level development board based on ESP32-C6-WROOM-1(U), +a general-purpose module with a 8 MB SPI flash. + +Most of the I/O pins are broken out to the pin headers on both sides for easy interfacing. +Developers can either connect peripherals with jumper wires or mount ESP32-C6-DevKitC-1 on +a breadboard. [2]_ + +ESP32-C6 includes the following features: + +- 32-bit core RISC-V microcontroller with a clock speed of up to 160 MHz +- 400 KB of internal RAM +- WiFi 802.11 ax 2.4GHz +- Fully compatible with IEEE 802.11b/g/n protocol +- Bluetooth LE: Bluetooth 5.3 certified +- Internal co-existence mechanism between Wi-Fi and Bluetooth to share the same antenna +- IEEE 802.15.4 (Zigbee and Thread) + +Digital interfaces: + +- 30x GPIOs (QFN40), or 22x GPIOs (QFN32) +- 2x UART +- 1x Low-power (LP) UART +- 1x General purpose SPI +- 1x I2C +- 1x Low-power (LP) I2C +- 1x I2S +- 1x Pulse counter +- 1x USB Serial/JTAG controller +- 1x TWAI® controller, compatible with ISO 11898-1 (CAN Specification 2.0) +- 1x SDIO 2.0 slave controller +- LED PWM controller, up to 6 channels +- 1x Motor control PWM (MCPWM) +- 1x Remote control peripehral +- 1x Parallel IO interface (PARLIO) +- General DMA controller (GDMA), with 3 transmit channels and 3 receive channels +- Event task matrix (ETM) + +Analog interfaces: + +- 1x 12-bit SAR ADCs, up to 7 channels +- 1x temperature sensor + +Timers: + +- 1x 52-bit system timer +- 1x 54-bit general-purpose timers +- 3x Watchdog timers +- 1x Analog watchdog timer + +Low Power: + +- Four power modes designed for typical scenarios: Active, Modem-sleep, Light-sleep, Deep-sleep + +Security: + +- Secure boot +- Flash encryption +- 4-Kbit OTP, up to 1792 bits for users +- Cryptographic hardware acceleration: (AES-128/256, ECC, HMAC, RSA, SHA, Digital signature, Hash) +- Random number generator (RNG) + +For more information, check the datasheet at `ESP32C6 Datasheet`_ + +Supported Features +================== + +Current Zephyr's ESP32-C6-DevKitC board supports the following features: + ++------------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++============+============+=====================================+ +| UART | on-chip | serial port | ++------------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++------------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++------------+------------+-------------------------------------+ +| USB-JTAG | on-chip | hardware interface | ++------------+------------+-------------------------------------+ +| SPI Master | on-chip | spi | ++------------+------------+-------------------------------------+ +| Watchdog | on-chip | watchdog | ++------------+------------+-------------------------------------+ +| LEDC | on-chip | pwm | ++------------+------------+-------------------------------------+ +| SPI DMA | on-chip | spi | ++------------+------------+-------------------------------------+ + +System requirements +******************* + +Prerequisites +============= + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +******************* + +Simple boot +=========== + +The board could be loaded using the single binary image, without 2nd stage bootloader. +It is the default option when building the application without additional configuration. + +.. note:: + + Simple boot does not provide any security features nor OTA updates. + +MCUboot bootloader +================== + +User may choose to use MCUboot bootloader instead. In that case the bootloader +must be build (and flash) at least once. + +There are two options to be used when building an application: + +1. Sysbuild +2. Manual build + +.. note:: + + User can select the MCUboot bootloader by adding the following line + to the board default configuration file. + ``` + CONFIG_BOOTLOADER_MCUBOOT=y + ``` + +Sysbuild +======== + +The sysbuild makes possible to build and flash all necessary images needed to +bootstrap the board with the EPS32 SoC. + +To build the sample application using sysbuild use the command: + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: esp32c6_devkitc + :goals: build + :west-args: --sysbuild + :compact: + +By default, the ESP32 sysbuild creates bootloader (MCUboot) and application +images. But it can be configured to create other kind of images. + +Build directory structure created by sysbuild is different from traditional +Zephyr build. Output is structured by the domain subdirectories: + +.. code-block:: + + build/ + ├── hello_world + │   └── zephyr + │   ├── zephyr.elf + │   └── zephyr.bin + ├── mcuboot + │ └── zephyr + │ ├── zephyr.elf + │ └── zephyr.bin + └── domains.yaml + +.. note:: + + With ``--sysbuild`` option the bootloader will be re-build and re-flash + every time the pristine build is used. + +For more information about the system build please read the :ref:`sysbuild` documentation. + +Manual build +============ + +During the development cycle, it is intended to build & flash as quickly possible. +For that reason, images can be build one at a time using traditional build. + +The instructions following are relevant for both manual build and sysbuild. +The only difference is the structure of the build directory. + +.. note:: + + Remember that bootloader (MCUboot) needs to be flash at least once. + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c6_devkitc + :goals: build + +The usual ``flash`` target will work with the ``esp32c6_devkitc`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c6_devkitc + :goals: flash + +Open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! esp32c6_devkitc + +Debugging +********* + +As with much custom hardware, the ESP32-C6 modules require patches to +OpenOCD that are not upstreamed yet. Espressif maintains their own fork of +the project. The custom OpenOCD can be obtained at `OpenOCD ESP32`_ + +The Zephyr SDK uses a bundled version of OpenOCD by default. You can overwrite that behavior by adding the +``-DOPENOCD= -DOPENOCD_DEFAULT_PATH=`` +parameter when building. + +Here is an example for building the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c6_devkitc + :goals: build flash + :gen-args: -DOPENOCD= -DOPENOCD_DEFAULT_PATH= + +You can debug an application in the usual way. Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: esp32c6_devkitc + :goals: debug + +.. _`OpenOCD ESP32`: https://github.com/espressif/openocd-esp32/releases + +References +********** + +.. [1] https://www.espressif.com/en/products/socs/esp32-c6 +.. [2] https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/user_guide.html +.. _ESP32C6 Devkitm User Guide: https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/user_guide.html +.. _ESP32C6 Technical Reference Manual: https://espressif.com/sites/default/files/documentation/esp32-c6_technical_reference_manual_en.pdf +.. _ESP32C6 Datasheet: https://www.espressif.com/sites/default/files/documentation/esp32-c6_datasheet_en.pdf diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi new file mode 100644 index 0000000000000..a9cda93d22a35 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc-pinctrl.dtsi @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + spim2_default: spim2_default { + group1 { + pinmux = , + , + ; + }; + group2 { + pinmux = ; + output-low; + }; + }; +}; diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts new file mode 100644 index 0000000000000..3917430cdb282 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.dts @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "esp32c6_devkitc-pinctrl.dtsi" +#include + +/ { + model = "esp32c6_devkitc"; + compatible = "espressif,esp32c6"; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + aliases { + sw0 = &user_button1; + watchdog0 = &wdt0; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button1: button_1 { + label = "User SW1"; + gpios = <&gpio0 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + }; + }; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&spi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim2_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&wdt0 { + status = "okay"; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml new file mode 100644 index 0000000000000..06f7d8d8d29c0 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc.yaml @@ -0,0 +1,18 @@ +identifier: esp32c6_devkitc +name: ESP32-C6 +vendor: espressif +type: mcu +arch: riscv +toolchain: + - zephyr +supported: + - gpio + - watchdog + - uart + - spi +testing: + ignore_tags: + - net + - bluetooth + - pm + - tracing diff --git a/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_defconfig b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_defconfig new file mode 100644 index 0000000000000..6539bd42e5947 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/esp32c6_devkitc_defconfig @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=y diff --git a/boards/espressif/esp32c6_devkitc/support/openocd.cfg b/boards/espressif/esp32c6_devkitc/support/openocd.cfg new file mode 100644 index 0000000000000..d86a5517a4ca9 --- /dev/null +++ b/boards/espressif/esp32c6_devkitc/support/openocd.cfg @@ -0,0 +1,4 @@ +# ESP32C6 has built-in JTAG interface over USB port in pins GPIO13/GPIO12 (D-/D+). +set ESP_RTOS none + +source [find board/esp32c6-builtin.cfg] diff --git a/boards/espressif/esp32s2_devkitc/doc/index.rst b/boards/espressif/esp32s2_devkitc/doc/index.rst index bfe8eb3fc7de1..427596e31473b 100644 --- a/boards/espressif/esp32s2_devkitc/doc/index.rst +++ b/boards/espressif/esp32s2_devkitc/doc/index.rst @@ -38,7 +38,6 @@ Current Zephyr's ESP32-S2-devkitc board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts b/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts index 25b1c599c571f..f2c9d8cd3c92f 100644 --- a/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts +++ b/boards/espressif/esp32s2_devkitc/esp32s2_devkitc.dts @@ -39,10 +39,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -163,3 +159,7 @@ &wdt0 { status = "okay"; }; + +&dac { + status = "okay"; +}; diff --git a/boards/espressif/esp32s2_saola/doc/index.rst b/boards/espressif/esp32s2_saola/doc/index.rst index 1e7c1627fd132..485614db8e7d8 100644 --- a/boards/espressif/esp32s2_saola/doc/index.rst +++ b/boards/espressif/esp32s2_saola/doc/index.rst @@ -38,7 +38,6 @@ Current Zephyr's ESP32-S2-saola board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32s2_saola/esp32s2_saola.dts b/boards/espressif/esp32s2_saola/esp32s2_saola.dts index f7e73bb8f2755..b204efab94bac 100644 --- a/boards/espressif/esp32s2_saola/esp32s2_saola.dts +++ b/boards/espressif/esp32s2_saola/esp32s2_saola.dts @@ -39,10 +39,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/espressif/esp32s3_devkitc/Kconfig.defconfig b/boards/espressif/esp32s3_devkitc/Kconfig.defconfig index 9b109ab4525bd..d539cd6652349 100644 --- a/boards/espressif/esp32s3_devkitc/Kconfig.defconfig +++ b/boards/espressif/esp32s3_devkitc/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_ESP32S3_DEVKITC_ESP32S3_PROCPU if BOARD_ESP32S3_DEVKITC_ESP32S3_APPCPU diff --git a/boards/espressif/esp32s3_devkitc/doc/index.rst b/boards/espressif/esp32s3_devkitc/doc/index.rst index 60edc732b5687..a7d6c7d60d5ae 100644 --- a/boards/espressif/esp32s3_devkitc/doc/index.rst +++ b/boards/espressif/esp32s3_devkitc/doc/index.rst @@ -88,7 +88,6 @@ Current Zephyr's ESP32-S3-DevKitC board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_appcpu.dts b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_appcpu.dts index 5e5a1e2be4821..886aae0527009 100644 --- a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_appcpu.dts +++ b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts index 253731fc7212b..afff520f7ba14 100644 --- a/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts +++ b/boards/espressif/esp32s3_devkitc/esp32s3_devkitc_procpu.dts @@ -25,6 +25,7 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -42,14 +43,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "disabled"; }; @@ -112,7 +105,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { @@ -177,3 +169,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/espressif/esp32s3_devkitm/Kconfig.defconfig b/boards/espressif/esp32s3_devkitm/Kconfig.defconfig index 1905ae5f5515b..26339590ee31e 100644 --- a/boards/espressif/esp32s3_devkitm/Kconfig.defconfig +++ b/boards/espressif/esp32s3_devkitm/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_ESP32S3_DEVKITM_ESP32S3_PROCPU if BOARD_ESP32S3_DEVKITM_ESP32S3_APPCPU diff --git a/boards/espressif/esp32s3_devkitm/doc/index.rst b/boards/espressif/esp32s3_devkitm/doc/index.rst index abef4294733eb..17af80ed31869 100644 --- a/boards/espressif/esp32s3_devkitm/doc/index.rst +++ b/boards/espressif/esp32s3_devkitm/doc/index.rst @@ -88,7 +88,6 @@ Current Zephyr's ESP32-S3-DevKitM board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts index 3815ebdacf9b8..8a259eb99be50 100644 --- a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts +++ b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts index e0d4461a33bc0..95390a0324bf0 100644 --- a/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts +++ b/boards/espressif/esp32s3_devkitm/esp32s3_devkitm_procpu.dts @@ -25,6 +25,7 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -42,18 +43,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - -&usb_serial { - status = "okay"; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -112,7 +101,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { @@ -181,3 +169,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/espressif/esp_wrover_kit/Kconfig.defconfig b/boards/espressif/esp_wrover_kit/Kconfig.defconfig index a05a1684d6b14..adf8cd7e3980e 100644 --- a/boards/espressif/esp_wrover_kit/Kconfig.defconfig +++ b/boards/espressif/esp_wrover_kit/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - config DISK_DRIVER_SDMMC default y diff --git a/boards/espressif/esp_wrover_kit/doc/index.rst b/boards/espressif/esp_wrover_kit/doc/index.rst index 521307376a054..fdef0efd6c709 100644 --- a/boards/espressif/esp_wrover_kit/doc/index.rst +++ b/boards/espressif/esp_wrover_kit/doc/index.rst @@ -447,7 +447,6 @@ Current Zephyr's ESP32-Wrover-Kit board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.dts b/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.dts index f0a046705ee00..ee3321726f2aa 100644 --- a/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.dts +++ b/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.yaml b/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.yaml index 64f7ef2124f65..57971b3571c15 100644 --- a/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.yaml +++ b/boards/espressif/esp_wrover_kit/esp_wrover_kit_appcpu.yaml @@ -1,5 +1,5 @@ identifier: esp_wrover_kit/esp32/appcpu -name: ESP WROVER KIT +name: ESP WROVER KIT APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.dts b/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.dts index ac0bacd604ceb..5edfe4f761caa 100644 --- a/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.dts +++ b/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.dts @@ -36,6 +36,7 @@ zephyr,code-partition = &slot0_partition; zephyr,display = &ili9341; zephyr,sdhc = &sdhc1; + zephyr,bt-hci = &esp32_bt_hci; }; leds { @@ -94,14 +95,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -251,3 +244,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.yaml b/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.yaml index ecec50611c35b..d316dd1b8d029 100644 --- a/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.yaml +++ b/boards/espressif/esp_wrover_kit/esp_wrover_kit_procpu.yaml @@ -1,5 +1,5 @@ identifier: esp_wrover_kit/esp32/procpu -name: ESP WROVER KIT +name: ESP WROVER KIT PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/lairdconnect/bl5340_dvk/CMakeLists.txt b/boards/ezurio/bl5340_dvk/CMakeLists.txt similarity index 100% rename from boards/lairdconnect/bl5340_dvk/CMakeLists.txt rename to boards/ezurio/bl5340_dvk/CMakeLists.txt diff --git a/boards/lairdconnect/bl5340_dvk/Kconfig b/boards/ezurio/bl5340_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/bl5340_dvk/Kconfig rename to boards/ezurio/bl5340_dvk/Kconfig diff --git a/boards/lairdconnect/bl5340_dvk/Kconfig.bl5340_dvk b/boards/ezurio/bl5340_dvk/Kconfig.bl5340_dvk similarity index 100% rename from boards/lairdconnect/bl5340_dvk/Kconfig.bl5340_dvk rename to boards/ezurio/bl5340_dvk/Kconfig.bl5340_dvk diff --git a/boards/ezurio/bl5340_dvk/Kconfig.defconfig b/boards/ezurio/bl5340_dvk/Kconfig.defconfig new file mode 100644 index 0000000000000..ece5d8d8d3960 --- /dev/null +++ b/boards/ezurio/bl5340_dvk/Kconfig.defconfig @@ -0,0 +1,118 @@ +# BL5340-DVK board configuration + +# Copyright (c) 2019-2020 Nordic Semiconductor ASA +# Copyright (c) 2021-2023 Laird Connectivity +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_BL5340_DVK_NRF5340_CPUAPP || BOARD_BL5340_DVK_NRF5340_CPUAPP_NS + +config I2C + default GPIO || DAC + +# 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_BL5340_DVK_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_BL5340_DVK_NRF5340_CPUAPP && TRUSTED_EXECUTION_SECURE + +if BOARD_BL5340_DVK_NRF5340_CPUAPP_NS + +config FLASH_LOAD_OFFSET + default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +config FLASH_LOAD_SIZE + default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) + +endif # BOARD_BL5340_DVK_NRF5340_CPUAPP_NS + +config BT_HCI_IPC + default y if BT + +config HEAP_MEM_POOL_ADD_SIZE_BOARD + int + default 4096 if BT_HCI_IPC + +config BT_HCI_VS + default y if BT + +# 2.8" TFT Touch Shield for Arduino w/Capacitive Touch Screen Module +# is mounted to the DVK using standoffs. +# https://www.buydisplay.com/2-8-inch-tft-touch-shield-for-arduino-w-capacitive-touch-screen-module +if DISPLAY + +config INPUT_FT5336_INTERRUPT + default y + +if LVGL + +config LV_Z_VDB_SIZE + default 64 + +config LV_Z_BITS_PER_PIXEL + default 16 + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_16 +endchoice + +config LV_COLOR_16_SWAP + default y + +config INPUT + default y + +endif # LVGL + +endif # DISPLAY + +endif # BOARD_BL5340_DVK_NRF5340_CPUAPP || BOARD_BL5340_DVK_NRF5340_CPUAPP_NS + +config IPM_NRFX + default IPM + +config MBOX_NRFX_IPC + default MBOX + +if BOARD_BL5340_DVK_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 + +endif # BOARD_BL5340_DVK_NRF5340_CPUNET diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts similarity index 80% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts index 7640e86e4aad1..a1ef13d63e543 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,8 +10,8 @@ #include "bl5340_dvk_nrf5340_cpuapp_common.dtsi" / { - model = "Laird Connectivity BL5340 (nRF5340) Application"; - compatible = "lairdconnect,bl5340-dvk-cpuapp"; + model = "Ezurio BL5340 (nRF5340) Application"; + compatible = "ezurio,bl5340-dvk-cpuapp"; chosen { zephyr,sram = &sram0_image; diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml similarity index 88% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml index 1b23d5f23ecb6..cf432d7ab6e24 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp.yaml @@ -16,7 +16,6 @@ supported: - qspi - spi - uart - - usb_cdc - usb_device - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common-pinctrl.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi similarity index 98% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi index ff29e1f176ea2..372144f15b097 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_common.dtsi @@ -15,7 +15,7 @@ zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; zephyr,display = &ili9340; - zephyr,bt-hci-ipc = &ipc0; + zephyr,bt-hci = &bt_hci_ipc0; }; /* Main LEDs and buttons are on an I2C TCA9538 GPIO port expander */ @@ -105,7 +105,6 @@ watchdog0 = &wdt0; accel0 = &lis3dh; bbram0 = &extrtc0; - spi-flash0 = &mx25r64; }; mipi_dbi { @@ -152,7 +151,7 @@ pinctrl-1 = <&i2c1_sleep>; pinctrl-names = "default", "sleep"; at24c256@50 { - compatible = "atmel,at24"; + compatible = "atmel,at24c256", "atmel,at24"; reg = <0x50>; size = <32768>; pagesize = <64>; diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_defconfig diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts similarity index 76% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts index d159b8c4afe1b..35410c51b70cb 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,8 +10,8 @@ #include "bl5340_dvk_nrf5340_cpuapp_common.dtsi" / { - model = "Laird Connectivity BL5340 (nRF5340) Application"; - compatible = "lairdconnect,bl5340-dvk-cpuapp"; + model = "Ezurio BL5340 (nRF5340) Application"; + compatible = "ezurio,bl5340-dvk-cpuapp"; chosen { zephyr,sram = &sram0_ns; diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml similarity index 88% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml index 087975c8d0da7..89d29c79e055e 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns.yaml @@ -15,7 +15,6 @@ supported: - pwm - spi - uart - - usb_cdc - usb_device - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns_defconfig b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns_defconfig similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns_defconfig rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_ns_defconfig diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpuapp_partition_conf.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet-pinctrl.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts similarity index 86% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts index 4df761d04879a..ef70281f16670 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021-2023 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include "bl5340_dvk_nrf5340_cpunet_common.dtsi" / { - model = "Laird Connectivity BL5340 (nRF5340) Network"; - compatible = "lairdconnect,bl5340-dvk-cpunet"; + model = "Ezurio BL5340 (nRF5340) Network"; + compatible = "ezurio,bl5340-dvk-cpunet"; chosen { zephyr,console = &uart0; diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml similarity index 91% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml index d972729671459..ab6f60bdd3ab5 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet.yaml @@ -15,4 +15,4 @@ supported: - spi - uart - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_common.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_common.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_common.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_common.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_defconfig diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c similarity index 95% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c index c4f3946731434..49c0e5a1c730e 100644 --- a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c +++ b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_cpunet_reset.c @@ -10,7 +10,7 @@ #include #include -#include +#include LOG_MODULE_REGISTER(bl5340_dvk_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -50,7 +50,7 @@ static int remoteproc_mgr_boot(void) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_shared_sram_planning_conf.dtsi b/boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_shared_sram_planning_conf.dtsi similarity index 100% rename from boards/lairdconnect/bl5340_dvk/bl5340_dvk_nrf5340_shared_sram_planning_conf.dtsi rename to boards/ezurio/bl5340_dvk/bl5340_dvk_nrf5340_shared_sram_planning_conf.dtsi diff --git a/boards/lairdconnect/bl5340_dvk/board.cmake b/boards/ezurio/bl5340_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/bl5340_dvk/board.cmake rename to boards/ezurio/bl5340_dvk/board.cmake diff --git a/boards/ezurio/bl5340_dvk/board.yml b/boards/ezurio/bl5340_dvk/board.yml new file mode 100644 index 0000000000000..69be46ffe62ec --- /dev/null +++ b/boards/ezurio/bl5340_dvk/board.yml @@ -0,0 +1,8 @@ +board: + name: bl5340_dvk + vendor: ezurio + socs: + - name: 'nrf5340' + variants: + - name: 'ns' + cpucluster: 'cpuapp' diff --git a/boards/lairdconnect/bl5340_dvk/doc/img/bl5340_dvk_top.jpg b/boards/ezurio/bl5340_dvk/doc/img/bl5340_dvk_top.jpg similarity index 100% rename from boards/lairdconnect/bl5340_dvk/doc/img/bl5340_dvk_top.jpg rename to boards/ezurio/bl5340_dvk/doc/img/bl5340_dvk_top.jpg diff --git a/boards/ezurio/bl5340_dvk/doc/index.rst b/boards/ezurio/bl5340_dvk/doc/index.rst new file mode 100644 index 0000000000000..700838f0764ab --- /dev/null +++ b/boards/ezurio/bl5340_dvk/doc/index.rst @@ -0,0 +1,436 @@ +.. _bl5340_dvk: + +Ezurio BL5340 DVK +################# + +Overview +******** +The BL5340 Development Kit provides support for the Ezurio +BL5340 module which is powered by a dual-core Nordic Semiconductor +nRF5340 ARM Cortex-M33F CPU. The nRF5340 inside the BL5340 module is a +dual-core SoC based on the Arm® Cortex®-M33 architecture, with: + +* a full-featured Arm Cortex-M33F core with DSP instructions, FPU, and + Armv8-M Security Extension, running at up to 128 MHz, referred to as + the **application core** +* a secondary Arm Cortex-M33 core, with a reduced feature set, running + at a fixed 64 MHz, referred to as the **network core**. + +The ``bl5340_dvk/nrf5340/cpuapp`` build target provides support for the application +core on the BL5340 module. The ``bl5340_dvk/nrf5340/cpunet`` build target provides +support for the network core on the BL5340 module. If ARM TrustZone is +used then the ``bl5340_dvk/nrf5340/cpuapp`` build target provides support for the +non-secure partition of the application core on the BL5340 module. + +This development kit has the following features: + +* :abbr:`ADC (Analog to Digital Converter)` +* CLOCK +* FLASH +* :abbr:`GPIO (General Purpose Input Output)` +* :abbr:`IDAU (Implementation Defined Attribution Unit)` +* :abbr:`I2C (Inter-Integrated Circuit)` +* :abbr:`I2S (Inter-Integrated Sound)` +* :abbr:`MPU (Memory Protection Unit)` +* :abbr:`NVIC (Nested Vectored Interrupt Controller)` +* :abbr:`PWM (Pulse Width Modulation)` +* :abbr:`QSPI (Quad Serial Peripheral Interface)` +* RADIO (Bluetooth Low Energy and 802.15.4) +* :abbr:`RTC (nRF RTC System Clock)` +* Segger RTT (RTT Console) +* :abbr:`SPI (Serial Peripheral Interface)` +* :abbr:`UARTE (Universal asynchronous receiver-transmitter)` +* :abbr:`USB (Universal Serial Bus)` +* :abbr:`WDT (Watchdog Timer)` + +.. figure:: img/bl5340_dvk_top.jpg + :align: center + :alt: BL5340 DVK + + BL5340 DVK (Credit: Ezurio) + +More information about the module can be found on the +`BL5340 homepage`_. + +The `Nordic Semiconductor Infocenter`_ +contains the processor's information and the datasheet. + +Hardware +******** + +The BL5340 DVK has two external oscillators. The frequency of +the slow clock is 32.768KHz. The frequency of the main clock +is 32MHz. + +Supported Features +================== + +The ``bl5340_dvk/nrf5340/cpuapp`` board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| ADC | on-chip | adc | ++-----------+------------+----------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| QSPI(M) | on-chip | nor | ++-----------+------------+----------------------+ +| PWM | on-chip | pwm | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| RTT | Segger | console | ++-----------+------------+----------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+----------------------+ +| SPU | on-chip | system protection | ++-----------+------------+----------------------+ +| UARTE | on-chip | serial | ++-----------+------------+----------------------+ +| USB | on-chip | usb | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ + +The ``bl5340_dvk/nrf5340/cpunet`` board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| RADIO | on-chip | Bluetooth, | +| | | ieee802154 | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| RTT | Segger | console | ++-----------+------------+----------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+----------------------+ +| UARTE | on-chip | serial | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ + +Other hardware features have not been enabled yet for this board. +See `Nordic Semiconductor Infocenter`_ +for a complete list of hardware features. + +Connections and IOs +=================== + +An eight-pin GPIO port expander is used to provide additional inputs +and outputs to the BL5340 module. + +Refer to the `TI TCA9538 datasheet`_ for further details. + +LEDs +---- + +* LED1 (blue) = via TCA9538 port expander channel P4 (active low) +* LED2 (blue) = via TCA9538 port expander channel P5 (active low) +* LED3 (blue) = via TCA9538 port expander channel P6 (active low) +* LED4 (blue) = via TCA9538 port expander channel P7 (active low) + +Push buttons +------------ + +* BUTTON1 = SW1 = via TCA9538 port expander channel P0 (active low) +* BUTTON2 = SW2 = via TCA9538 port expander channel P1 (active low) +* BUTTON3 = SW3 = via TCA9538 port expander channel P2 (active low) +* BUTTON4 = SW4 = via TCA9538 port expander channel P3 (active low) +* BOOT = boot (active low) + +External Memory +=============== + +Several external memory sources are available for the BL5340 DVK. These +are described as follows. + +Flash Memory +------------ + +A Macronix MX25R6435FZNIL0 8MB external QSPI Flash memory part is +incorporated for application image storage and large datasets. + +Refer to the `Macronix MX25R6435FZNIL0 datasheet`_ for further details. + +EEPROM Memory +------------- + +A 32KB Giantec GT24C256C-2GLI-TR EEPROM is available via I2C for +storage of infrequently updated data and small datasets. + +Refer to the `Giantec GT24C256C-2GLI-TR datasheet`_ for further details. + +External Memory +--------------- + +An on-board micro SD card slot is available for use with micro SD cards. + +Sensors +======= + +The BL5340 DVK incorporates two sensors for user application testing. +These are described as follows. + +Temperature, Pressure, Humidity & Air Quality Sensor +---------------------------------------------------- + +A Bosch BME680 Temperature, Pressure, Humidity & Air Quality sensor is +available via I2C for environmental measurement applications. + +Refer to the `Bosch BME680 datasheet`_ for further details. + +3-Axis Accelerometer +-------------------- + +An ST Microelectronics LIS3DH 3-Axis Accelerometer is available via I2C +for vibration and motion detection applications. + +Refer to the `ST Microelectronics LIS3DH datasheet`_ for further details. + +Ethernet +======== + +Cabled 10/100 Base-T Ethernet Connectivity is available via a Microchip +ENC424J600 Ethernet controller. + +Refer to the `Microchip ENC424J600 datasheet`_ for further details. + +TFT Display & Capacitive Touch Screen Controller +================================================ + +A 2.8 inch, 240 x 320 pixel TFT display with capacitive touch +controller is included with the BL5340 DVK for user interface +application features. + +Refer to the `ER_TFTM028_4 datasheet`_ for a high level overview of the +display. + +An ILI9341 TFT controller is incorporated in the TFT module and +acts as the main controller, controlled via SPI. + +Refer to the `ILI9341 datasheet`_ for further details. + +An FT6206 Capacitive Touch Controller, controlled via I2C is +also incorporated in the TFT module. + +Refer to the `FT6206 datasheet`_ for further details. + +Real-Time Clock +=============== + +A real-time clock is available for accurate time data availability. + +Refer to the `Microchip MCP7940N datasheet`_ for further details. + +DAC +=== + +A 10-bit Digital to Analog Converter is incorporated for generation of +variable voltages. + +Refer to the `Microchip MCP4725 datasheet`_ for further details. + +Security components +=================== + +- Implementation Defined Attribution Unit (`IDAU`_) on the application + core. The IDAU is implemented with the System Protection Unit and is + used to define secure and non-secure memory maps. By default, all of + the memory space (Flash, SRAM, and peripheral address space) is + defined to be secure accessible only. +- Secure boot. + +Programming and Debugging +************************* + +The BL5340's application core supports the Armv8-M Security Extension. +Applications built for the ``bl5340_dvk/nrf5340/cpuapp`` board by default +boot in the Secure state. + +The BL5340's network core does not support the Armv8-M Security +Extension. The IDAU may configure bus accesses by the network core to +have Secure attribute set; the latter allows to build and run Secure +only applications on the BL5340 module. + +Building Secure/Non-Secure Zephyr applications with Arm |reg| TrustZone |reg| +============================================================================= + +Applications on the BL5340 module may contain a Secure and a Non-Secure +firmware image for the application core. The Secure image can be built +using either Zephyr or `Trusted Firmware M`_ (TF-M). Non-Secure +firmware images are always built using Zephyr. The two alternatives are +described below. + +.. note:: + + By default the Secure image for BL5340's application core is + built using TF-M. + +Building the Secure firmware with TF-M +-------------------------------------- + +The process to build the Secure firmware image using TF-M and the +Non-Secure firmware image using Zephyr requires the following steps: + +1. Build the Non-Secure Zephyr application + for the application core using ``-DBOARD=bl5340_dvk/nrf5340/cpuapp/ns``. + To invoke the building of TF-M the Zephyr build system requires the + Kconfig option ``BUILD_WITH_TFM`` to be enabled, which is done by + default when building Zephyr as a Non-Secure application. + The Zephyr build system will perform the following steps automatically: + + * Build the Non-Secure firmware image as a regular Zephyr application + * Build a TF-M (secure) firmware image + * Merge the output image binaries together + * Optionally build a bootloader image (MCUboot) + +.. note:: + + Depending on the TF-M configuration, an application DTS overlay may + be required, to adjust the Non-Secure image Flash and SRAM starting + address and sizes. + +2. Build the application firmware for the network core using + ``-DBOARD=bl5340_dvk/nrf5340/cpunet``. + +Building the Secure firmware using Zephyr +----------------------------------------- + +The process to build the Secure and the Non-Secure firmware images +using Zephyr requires the following steps: + +1. Build the Secure Zephyr application for the application core + using ``-DBOARD=bl5340_dvk/nrf5340/cpuapp`` and + ``CONFIG_TRUSTED_EXECUTION_SECURE=y`` and ``CONFIG_BUILD_WITH_TFM=n`` + in the application project configuration file. +2. Build the Non-Secure Zephyr application for the application core + using ``-DBOARD=bl5340_dvk/nrf5340/cpuapp/ns``. +3. Merge the two binaries together. +4. Build the application firmware for the network core using + ``-DBOARD=bl5340_dvk/nrf5340/cpunet``. + +When building a Secure/Non-Secure application for the BL5340's +application core, the Secure application will have to set the IDAU +(SPU) configuration to allow Non-Secure access to all CPU resources +utilized by the Non-Secure application firmware. SPU configuration +shall take place before jumping to the Non-Secure application. + +Building a Secure only application +================================== + +Build the Zephyr app in the usual way (see :ref:`build_an_application` +and :ref:`application_run`), using ``-DBOARD=bl5340_dvk/nrf5340/cpuapp`` for +the firmware running on the BL5340's application core, and using +``-DBOARD=bl5340_dvk/nrf5340/cpunet`` for the firmware running +on the BL5340's network core. + +Flashing +======== + +Follow the instructions in the :ref:`nordic_segger` page to install +and configure all the necessary software. Further information can be +found in :ref:`nordic_segger_flashing`. Then you can build and flash +applications as usual (:ref:`build_an_application` and +:ref:`application_run` for more details). + +.. warning:: + + The BL5340 has a flash read-back protection feature. When flash + read-back protection is active, you will need to recover the chip + before reflashing. If you are flashing with + :ref:`west `, run this command for more + details on the related ``--recover`` option: + + .. code-block:: console + + west flash -H -r nrfjprog --skip-rebuild + +.. note:: + + Flashing and debugging applications on the BL5340 DVK requires + upgrading the nRF Command Line Tools to version 10.12.0 or newer. + Further information on how to install the nRF Command Line Tools can + be found in :ref:`nordic_segger_flashing`. + +Here is an example for the :ref:`hello_world` application running on the +BL5340's application core. + +First, run your favorite terminal program to listen for output. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the port where the BL5340 DVK board +can be found. For example, under Linux, :code:`/dev/ttyACM0`. + +Then build and flash the application in the usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: bl5340_dvk/nrf5340/cpuapp + :goals: build flash + +Debugging +========= + +Refer to the :ref:`nordic_segger` page to learn about debugging +boards with a Segger IC. + +Testing Bluetooth on the BL5340 DVK +*********************************** +Many of the Bluetooth examples will work on the BL5340 DVK. +Try them out: + +* :ref:`ble_peripheral` +* :ref:`bluetooth-eddystone-sample` +* :ref:`bluetooth-ibeacon-sample` + +References +********** + +.. target-notes:: + +.. _IDAU: + https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau +.. _BL5340 homepage: https://www.ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl5340-series-multi-core-bluetooth-52-802154-nfc-modules +.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _TI TCA9538 datasheet: https://www.ti.com/lit/gpn/TCA9538 +.. _Macronix MX25R6435FZNIL0 datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/8868/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.6.pdf +.. _Giantec GT24C256C-2GLI-TR datasheet: https://www.giantec-semi.com/juchen1123/uploads/pdf/GT24C256C_DS_Cu.pdf +.. _Bosch BME680 datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme680-ds001.pdf +.. _ST Microelectronics LIS3DH datasheet: https://www.st.com/resource/en/datasheet/lis3dh.pdf +.. _Microchip ENC424J600 datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/39935c.pdf +.. _ER_TFTM028_4 datasheet: https://www.buydisplay.com/download/manual/ER-TFTM028-4_Datasheet.pdf +.. _ILI9341 datasheet: https://www.buydisplay.com/download/ic/ILI9341.pdf +.. _FT6206 datasheet: https://www.buydisplay.com/download/ic/FT6206.pdf +.. _Microchip MCP7940N datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/20005010H.pdf +.. _Microchip MCP4725 datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/22039d.pdf +.. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/lairdconnect/bl5340_dvk/pre_dt_board.cmake b/boards/ezurio/bl5340_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl5340_dvk/pre_dt_board.cmake rename to boards/ezurio/bl5340_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl652_dvk/Kconfig b/boards/ezurio/bl652_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/bl652_dvk/Kconfig rename to boards/ezurio/bl652_dvk/Kconfig diff --git a/boards/lairdconnect/bl652_dvk/Kconfig.bl652_dvk b/boards/ezurio/bl652_dvk/Kconfig.bl652_dvk similarity index 100% rename from boards/lairdconnect/bl652_dvk/Kconfig.bl652_dvk rename to boards/ezurio/bl652_dvk/Kconfig.bl652_dvk diff --git a/boards/lairdconnect/bl652_dvk/Kconfig.defconfig b/boards/ezurio/bl652_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl652_dvk/Kconfig.defconfig rename to boards/ezurio/bl652_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/bl652_dvk/bl652_dvk-pinctrl.dtsi b/boards/ezurio/bl652_dvk/bl652_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl652_dvk/bl652_dvk-pinctrl.dtsi rename to boards/ezurio/bl652_dvk/bl652_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/bl652_dvk/bl652_dvk.dts b/boards/ezurio/bl652_dvk/bl652_dvk.dts similarity index 97% rename from boards/lairdconnect/bl652_dvk/bl652_dvk.dts rename to boards/ezurio/bl652_dvk/bl652_dvk.dts index f2cffbd819b96..8a537a8979664 100644 --- a/boards/lairdconnect/bl652_dvk/bl652_dvk.dts +++ b/boards/ezurio/bl652_dvk/bl652_dvk.dts @@ -1,6 +1,7 @@ /* * Copyright (c) 2019 Laird Connectivity * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,8 +12,8 @@ #include / { - model = "Laird BL652 DVK"; - compatible = "lairdconnect,bl652_dvk"; + model = "Ezurio BL652 DVK"; + compatible = "ezurio,bl652_dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/lairdconnect/bl652_dvk/bl652_dvk.yaml b/boards/ezurio/bl652_dvk/bl652_dvk.yaml similarity index 89% rename from boards/lairdconnect/bl652_dvk/bl652_dvk.yaml rename to boards/ezurio/bl652_dvk/bl652_dvk.yaml index a2fd4370d7f4b..a549fcfdd6698 100644 --- a/boards/lairdconnect/bl652_dvk/bl652_dvk.yaml +++ b/boards/ezurio/bl652_dvk/bl652_dvk.yaml @@ -15,4 +15,4 @@ supported: - pwm - spi - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bl652_dvk/bl652_dvk_defconfig b/boards/ezurio/bl652_dvk/bl652_dvk_defconfig similarity index 100% rename from boards/lairdconnect/bl652_dvk/bl652_dvk_defconfig rename to boards/ezurio/bl652_dvk/bl652_dvk_defconfig diff --git a/boards/lairdconnect/bl652_dvk/board.cmake b/boards/ezurio/bl652_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/bl652_dvk/board.cmake rename to boards/ezurio/bl652_dvk/board.cmake diff --git a/boards/ezurio/bl652_dvk/board.yml b/boards/ezurio/bl652_dvk/board.yml new file mode 100644 index 0000000000000..b573627457f80 --- /dev/null +++ b/boards/ezurio/bl652_dvk/board.yml @@ -0,0 +1,5 @@ +board: + name: bl652_dvk + vendor: ezurio + socs: + - name: nrf52832 diff --git a/boards/lairdconnect/bl652_dvk/doc/bl652_dvk.rst b/boards/ezurio/bl652_dvk/doc/bl652_dvk.rst similarity index 95% rename from boards/lairdconnect/bl652_dvk/doc/bl652_dvk.rst rename to boards/ezurio/bl652_dvk/doc/bl652_dvk.rst index 9acbb30d46ebc..b6fffcc4aa78b 100644 --- a/boards/lairdconnect/bl652_dvk/doc/bl652_dvk.rst +++ b/boards/ezurio/bl652_dvk/doc/bl652_dvk.rst @@ -1,13 +1,13 @@ .. _bl652_dvk: -Laird Connectivity BL652 DVK -############################ +Ezurio BL652 DVK +################ Overview ******** The BL652 Development Kit hardware provides -support for the Laird Connectivity BL652 module powered by a Nordic Semiconductor nRF52832 ARM Cortex-M4F CPU. +support for the Ezurio BL652 module powered by a Nordic Semiconductor nRF52832 ARM Cortex-M4F CPU. This development kit has the following features: @@ -260,11 +260,11 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl652_dvk/bl652_dvk.dts`. +:zephyr_file:`boards/ezurio/bl652_dvk/bl652_dvk.dts`. References ********** .. target-notes:: -.. _BL652 Module Website: https://connectivity.lairdtech.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl652-series-bluetooth-v5-nfc +.. _BL652 Module Website: https://ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl652-series-bluetooth-v5-nfc diff --git a/boards/lairdconnect/bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg b/boards/ezurio/bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg similarity index 100% rename from boards/lairdconnect/bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg rename to boards/ezurio/bl652_dvk/doc/img/BL652-SA_DVK_BoxContents.jpg diff --git a/boards/lairdconnect/bl652_dvk/doc/img/bl652_dvk.jpg b/boards/ezurio/bl652_dvk/doc/img/bl652_dvk.jpg similarity index 100% rename from boards/lairdconnect/bl652_dvk/doc/img/bl652_dvk.jpg rename to boards/ezurio/bl652_dvk/doc/img/bl652_dvk.jpg diff --git a/boards/lairdconnect/bl652_dvk/pre_dt_board.cmake b/boards/ezurio/bl652_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl652_dvk/pre_dt_board.cmake rename to boards/ezurio/bl652_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl653_dvk/Kconfig b/boards/ezurio/bl653_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/bl653_dvk/Kconfig rename to boards/ezurio/bl653_dvk/Kconfig diff --git a/boards/lairdconnect/bl653_dvk/Kconfig.bl653_dvk b/boards/ezurio/bl653_dvk/Kconfig.bl653_dvk similarity index 100% rename from boards/lairdconnect/bl653_dvk/Kconfig.bl653_dvk rename to boards/ezurio/bl653_dvk/Kconfig.bl653_dvk diff --git a/boards/lairdconnect/bl653_dvk/Kconfig.defconfig b/boards/ezurio/bl653_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl653_dvk/Kconfig.defconfig rename to boards/ezurio/bl653_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/bl653_dvk/bl653_dvk-pinctrl.dtsi b/boards/ezurio/bl653_dvk/bl653_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl653_dvk/bl653_dvk-pinctrl.dtsi rename to boards/ezurio/bl653_dvk/bl653_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/bl653_dvk/bl653_dvk.dts b/boards/ezurio/bl653_dvk/bl653_dvk.dts similarity index 97% rename from boards/lairdconnect/bl653_dvk/bl653_dvk.dts rename to boards/ezurio/bl653_dvk/bl653_dvk.dts index 4c536eb451255..35de9a2a80278 100644 --- a/boards/lairdconnect/bl653_dvk/bl653_dvk.dts +++ b/boards/ezurio/bl653_dvk/bl653_dvk.dts @@ -1,6 +1,7 @@ /* * Copyright (c) 2020 Laird Connectivity * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,8 +12,8 @@ #include / { - model = "Laird BL653 Dev Kit"; - compatible = "lairdconnect,bl653_dvk"; + model = "Ezurio BL653 Dev Kit"; + compatible = "ezurio,bl653_dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/lairdconnect/bl653_dvk/bl653_dvk.yaml b/boards/ezurio/bl653_dvk/bl653_dvk.yaml similarity index 90% rename from boards/lairdconnect/bl653_dvk/bl653_dvk.yaml rename to boards/ezurio/bl653_dvk/bl653_dvk.yaml index 6a2792ea5219d..ee1b610f312b9 100644 --- a/boards/lairdconnect/bl653_dvk/bl653_dvk.yaml +++ b/boards/ezurio/bl653_dvk/bl653_dvk.yaml @@ -16,4 +16,4 @@ supported: - counter - spi - i2c -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bl653_dvk/bl653_dvk_defconfig b/boards/ezurio/bl653_dvk/bl653_dvk_defconfig similarity index 100% rename from boards/lairdconnect/bl653_dvk/bl653_dvk_defconfig rename to boards/ezurio/bl653_dvk/bl653_dvk_defconfig diff --git a/boards/lairdconnect/bl653_dvk/board.cmake b/boards/ezurio/bl653_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/bl653_dvk/board.cmake rename to boards/ezurio/bl653_dvk/board.cmake diff --git a/boards/ezurio/bl653_dvk/board.yml b/boards/ezurio/bl653_dvk/board.yml new file mode 100644 index 0000000000000..dc42555309a23 --- /dev/null +++ b/boards/ezurio/bl653_dvk/board.yml @@ -0,0 +1,5 @@ +board: + name: bl653_dvk + vendor: ezurio + socs: + - name: nrf52833 diff --git a/boards/lairdconnect/bl653_dvk/doc/bl653_dvk.rst b/boards/ezurio/bl653_dvk/doc/bl653_dvk.rst similarity index 94% rename from boards/lairdconnect/bl653_dvk/doc/bl653_dvk.rst rename to boards/ezurio/bl653_dvk/doc/bl653_dvk.rst index 71270f6f4e850..ec8fdb0e02d8c 100644 --- a/boards/lairdconnect/bl653_dvk/doc/bl653_dvk.rst +++ b/boards/ezurio/bl653_dvk/doc/bl653_dvk.rst @@ -1,13 +1,13 @@ .. _bl653_dvk: -Laird Connectivity BL653 DVK -############################ +Ezurio BL653 DVK +################ Overview ******** The BL653 Development Kit (453-00039-K1, 453-00041-K1) hardware provides -support for the Laird Connectivity BL653 module powered by a Nordic Semiconductor nRF52833 ARM Cortex-M4F CPU. +support for the Ezurio BL653 module powered by a Nordic Semiconductor nRF52833 ARM Cortex-M4F CPU. This development kit has the following features: @@ -167,7 +167,7 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl653_dvk/bl653_dvk.dts`. +:zephyr_file:`boards/ezurio/bl653_dvk/bl653_dvk.dts`. Using UART1 *********** @@ -225,5 +225,5 @@ References .. target-notes:: -.. _BL653 website: https://www.lairdconnect.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl653-series-bluetooth-51-802154-nfc-module +.. _BL653 website: https://www.ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl653-series-bluetooth-51-802154-nfc-module .. _nRF52833 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52833_OPS_v0.7.pdf diff --git a/boards/lairdconnect/bl653_dvk/doc/img/bl653_dvk.jpg b/boards/ezurio/bl653_dvk/doc/img/bl653_dvk.jpg similarity index 100% rename from boards/lairdconnect/bl653_dvk/doc/img/bl653_dvk.jpg rename to boards/ezurio/bl653_dvk/doc/img/bl653_dvk.jpg diff --git a/boards/lairdconnect/bl653_dvk/pre_dt_board.cmake b/boards/ezurio/bl653_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl653_dvk/pre_dt_board.cmake rename to boards/ezurio/bl653_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl654_dvk/Kconfig b/boards/ezurio/bl654_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/bl654_dvk/Kconfig rename to boards/ezurio/bl654_dvk/Kconfig diff --git a/boards/lairdconnect/bl654_dvk/Kconfig.bl654_dvk b/boards/ezurio/bl654_dvk/Kconfig.bl654_dvk similarity index 100% rename from boards/lairdconnect/bl654_dvk/Kconfig.bl654_dvk rename to boards/ezurio/bl654_dvk/Kconfig.bl654_dvk diff --git a/boards/lairdconnect/bl654_dvk/Kconfig.defconfig b/boards/ezurio/bl654_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl654_dvk/Kconfig.defconfig rename to boards/ezurio/bl654_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk-pinctrl.dtsi b/boards/ezurio/bl654_dvk/bl654_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk-pinctrl.dtsi rename to boards/ezurio/bl654_dvk/bl654_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk.dts b/boards/ezurio/bl654_dvk/bl654_dvk.dts similarity index 97% rename from boards/lairdconnect/bl654_dvk/bl654_dvk.dts rename to boards/ezurio/bl654_dvk/bl654_dvk.dts index 7ede69427de75..6e9848f03cd32 100644 --- a/boards/lairdconnect/bl654_dvk/bl654_dvk.dts +++ b/boards/ezurio/bl654_dvk/bl654_dvk.dts @@ -1,6 +1,7 @@ /* * Copyright (c) 2019 Laird Connectivity * Copyright (c) 2023 Nordic Semiconductor ASA + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,8 +12,8 @@ #include / { - model = "Laird BL654 Dev Kit"; - compatible = "lairdconnect,bl654_dvk"; + model = "Ezurio BL654 Dev Kit"; + compatible = "ezurio,bl654_dvk"; chosen { zephyr,console = &uart0; diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk.yaml b/boards/ezurio/bl654_dvk/bl654_dvk.yaml similarity index 88% rename from boards/lairdconnect/bl654_dvk/bl654_dvk.yaml rename to boards/ezurio/bl654_dvk/bl654_dvk.yaml index 27eec7dcaebac..c4d016d63b699 100644 --- a/boards/lairdconnect/bl654_dvk/bl654_dvk.yaml +++ b/boards/ezurio/bl654_dvk/bl654_dvk.yaml @@ -12,4 +12,4 @@ supported: - ble - pwm - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk_defconfig b/boards/ezurio/bl654_dvk/bl654_dvk_defconfig similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk_defconfig rename to boards/ezurio/bl654_dvk/bl654_dvk_defconfig diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa.dts b/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.dts similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa.dts rename to boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.dts diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa.yaml b/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.yaml similarity index 90% rename from boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa.yaml rename to boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.yaml index d02d93862843d..6ecf919159136 100644 --- a/boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa.yaml +++ b/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa.yaml @@ -12,4 +12,4 @@ supported: - ble - pwm - watchdog -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa_defconfig b/boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa_defconfig similarity index 100% rename from boards/lairdconnect/bl654_dvk/bl654_dvk_nrf52840_pa_defconfig rename to boards/ezurio/bl654_dvk/bl654_dvk_nrf52840_pa_defconfig diff --git a/boards/lairdconnect/bl654_dvk/board.cmake b/boards/ezurio/bl654_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/bl654_dvk/board.cmake rename to boards/ezurio/bl654_dvk/board.cmake diff --git a/boards/ezurio/bl654_dvk/board.yml b/boards/ezurio/bl654_dvk/board.yml new file mode 100644 index 0000000000000..fdc9035ff68b0 --- /dev/null +++ b/boards/ezurio/bl654_dvk/board.yml @@ -0,0 +1,7 @@ +board: + name: bl654_dvk + vendor: ezurio + socs: + - name: nrf52840 + variants: + - name: pa diff --git a/boards/lairdconnect/bl654_dvk/doc/bl654_dvk.rst b/boards/ezurio/bl654_dvk/doc/bl654_dvk.rst similarity index 94% rename from boards/lairdconnect/bl654_dvk/doc/bl654_dvk.rst rename to boards/ezurio/bl654_dvk/doc/bl654_dvk.rst index 7ccb6294f4bc8..fba2bafba9cbb 100644 --- a/boards/lairdconnect/bl654_dvk/doc/bl654_dvk.rst +++ b/boards/ezurio/bl654_dvk/doc/bl654_dvk.rst @@ -1,13 +1,13 @@ .. _bl654_dvk: -Laird Connectivity BL654 DVK -############################ +Ezurio BL654 DVK +################ Overview ******** The BL654 Development Kit hardware provides -support for the Laird Connectivity BL654 module powered by a Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU. +support for the Ezurio BL654 module powered by a Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU. It is also pin compatible with the BL654PA which adds a power amplifier. The "pa" variant provides this compatibility. Use board ``bl654_dvk/nrf52840/pa`` to build for that target. @@ -178,7 +178,7 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl654_dvk/bl654_dvk.dts`. +:zephyr_file:`boards/ezurio/bl654_dvk/bl654_dvk.dts`. References @@ -186,5 +186,5 @@ References .. target-notes:: -.. _BL654 website: https://connectivity.lairdtech.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series +.. _BL654 website: https://ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html diff --git a/boards/lairdconnect/bl654_dvk/doc/img/455-00001_BoxContents.jpg b/boards/ezurio/bl654_dvk/doc/img/455-00001_BoxContents.jpg similarity index 100% rename from boards/lairdconnect/bl654_dvk/doc/img/455-00001_BoxContents.jpg rename to boards/ezurio/bl654_dvk/doc/img/455-00001_BoxContents.jpg diff --git a/boards/lairdconnect/bl654_dvk/doc/img/bl654_dvk.jpg b/boards/ezurio/bl654_dvk/doc/img/bl654_dvk.jpg similarity index 100% rename from boards/lairdconnect/bl654_dvk/doc/img/bl654_dvk.jpg rename to boards/ezurio/bl654_dvk/doc/img/bl654_dvk.jpg diff --git a/boards/lairdconnect/bl654_dvk/pre_dt_board.cmake b/boards/ezurio/bl654_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl654_dvk/pre_dt_board.cmake rename to boards/ezurio/bl654_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl654_sensor_board/Kconfig b/boards/ezurio/bl654_sensor_board/Kconfig similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/Kconfig rename to boards/ezurio/bl654_sensor_board/Kconfig diff --git a/boards/lairdconnect/bl654_sensor_board/Kconfig.bl654_sensor_board b/boards/ezurio/bl654_sensor_board/Kconfig.bl654_sensor_board similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/Kconfig.bl654_sensor_board rename to boards/ezurio/bl654_sensor_board/Kconfig.bl654_sensor_board diff --git a/boards/lairdconnect/bl654_sensor_board/Kconfig.defconfig b/boards/ezurio/bl654_sensor_board/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/Kconfig.defconfig rename to boards/ezurio/bl654_sensor_board/Kconfig.defconfig diff --git a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi b/boards/ezurio/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi rename to boards/ezurio/bl654_sensor_board/bl654_sensor_board-pinctrl.dtsi diff --git a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.dts b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts similarity index 95% rename from boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.dts rename to boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts index c43354f2705f7..8b5993d864dc8 100644 --- a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.dts +++ b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include / { - model = "Laird BL654 Sensor Board"; - compatible = "lairdconnect,bl654-sensor-board"; + model = "Ezurio BL654 Sensor Board"; + compatible = "ezurio,bl654-sensor-board"; chosen { zephyr,console = &uart0; diff --git a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.yaml b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.yaml similarity index 92% rename from boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.yaml rename to boards/ezurio/bl654_sensor_board/bl654_sensor_board.yaml index 856805fbd1691..bcaafe5669ac5 100644 --- a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.yaml +++ b/boards/ezurio/bl654_sensor_board/bl654_sensor_board.yaml @@ -17,4 +17,4 @@ supported: - pwm - watchdog - netif:openthread -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bl654_sensor_board/bl654_sensor_board_defconfig b/boards/ezurio/bl654_sensor_board/bl654_sensor_board_defconfig similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/bl654_sensor_board_defconfig rename to boards/ezurio/bl654_sensor_board/bl654_sensor_board_defconfig diff --git a/boards/lairdconnect/bl654_sensor_board/board.cmake b/boards/ezurio/bl654_sensor_board/board.cmake similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/board.cmake rename to boards/ezurio/bl654_sensor_board/board.cmake diff --git a/boards/ezurio/bl654_sensor_board/board.yml b/boards/ezurio/bl654_sensor_board/board.yml new file mode 100644 index 0000000000000..566c992411db1 --- /dev/null +++ b/boards/ezurio/bl654_sensor_board/board.yml @@ -0,0 +1,5 @@ +board: + name: bl654_sensor_board + vendor: ezurio + socs: + - name: nrf52840 diff --git a/boards/lairdconnect/bl654_sensor_board/doc/bl654_sensor_board.rst b/boards/ezurio/bl654_sensor_board/doc/bl654_sensor_board.rst similarity index 92% rename from boards/lairdconnect/bl654_sensor_board/doc/bl654_sensor_board.rst rename to boards/ezurio/bl654_sensor_board/doc/bl654_sensor_board.rst index c990c934952ea..50eb94cf5b266 100644 --- a/boards/lairdconnect/bl654_sensor_board/doc/bl654_sensor_board.rst +++ b/boards/ezurio/bl654_sensor_board/doc/bl654_sensor_board.rst @@ -1,12 +1,12 @@ .. _bl654_sensor_board: -Laird Connectivity BL654 Sensor Board -##################################### +Ezurio BL654 Sensor Board +######################### Overview ******** -The BL654 Sensor Board hardware provides support for the Laird Connectivity +The BL654 Sensor Board hardware provides support for the Ezurio BL654 module which is powered by a Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU. @@ -132,7 +132,7 @@ Applications for the ``bl654_sensor_board`` board configuration can be built, flashed, and debugged in the usual way. See :ref:`build_an_application` and :ref:`application_run` for more details on building and running. An external debugger/programmer is required which can be connected to using a Tag-Connect -TC2030-CTX cable, a Laird Connectivity USB-SWD Programmer board or Segger JLink +TC2030-CTX cable, a Ezurio USB-SWD Programmer board or Segger JLink programmer can be used to program and debug the BL654 sensor board. Flashing @@ -142,14 +142,14 @@ If using an external JLink, follow the instructions in the :ref:`nordic_segger` page to install and configure all the necessary software. Further information can be found in :ref:`nordic_segger_flashing`. Then build and flash applications as usual (see :ref:`build_an_application` and :ref:`application_run` for more -details). If using a Laird Connectivity USB-SWD Programmer Board, see the +details). If using a Ezurio USB-SWD Programmer Board, see the `pyOCD website`_ to find details about the software and how to install it. Here is an example for the :ref:`hello_world` application. First, run your favorite terminal program to listen for output - note that an external UART is required to be connected to the BL654 sensor board's UART, if -using the Laird Connectivity USB-SWD Programmer Board, the BL654 sensor board +using the Ezurio USB-SWD Programmer Board, the BL654 sensor board can be plugged in to the UART header. An FTDI cable can also be used - the voltage of the I/O lines and power line must be between 1.8v and 3.3v, do not connect an FTDI cable with a 5v power line to the BL654 sensor board. @@ -181,7 +181,7 @@ can be found. For example, under Linux, :code:`/dev/ttyACM0`. The BL654 sensor board needs an external programmer to program it, any SWD programmer which has a 9-pin ARM debug port can be used with a Tag-Connect -TC2030-CTX cable. If using the Laird Connectivity USB-SWD Programmer Board, +TC2030-CTX cable. If using the Ezurio USB-SWD Programmer Board, connect the cable to P1 and ensure the board is set to supply power to the target at 3.3v. @@ -214,7 +214,7 @@ Debugging ========= Refer to the :ref:`nordic_segger` page to learn about debugging Nordic based -boards if using an external JLink debugger. If using a Laird Connectivity +boards if using an external JLink debugger. If using a Ezurio USB-SWD Programmer Board, pyOCD can be used for debugging. Testing Bluetooth on the BL654 Sensor Board @@ -238,7 +238,7 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl654_sensor_board/bl654_sensor_board.dts`. +:zephyr_file:`boards/ezurio/bl654_sensor_board/bl654_sensor_board.dts`. References @@ -247,6 +247,6 @@ References .. target-notes:: .. _Bosch BME280 sensor website: https://www.bosch-sensortec.com/products/environmental-sensors/humidity-sensors-bme280/ -.. _BL654 website: https://connectivity.lairdtech.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series +.. _BL654 website: https://ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series .. _pyOCD website: https://github.com/pyocd/pyOCD -.. _USB-SWD Programmer website: https://www.lairdconnect.com/usb-swd-programmer +.. _USB-SWD Programmer website: https://www.ezurio.com/usb-swd-programmer diff --git a/boards/lairdconnect/bl654_sensor_board/doc/img/bl654_sensor_board.jpg b/boards/ezurio/bl654_sensor_board/doc/img/bl654_sensor_board.jpg similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/doc/img/bl654_sensor_board.jpg rename to boards/ezurio/bl654_sensor_board/doc/img/bl654_sensor_board.jpg diff --git a/boards/lairdconnect/bl654_sensor_board/doc/img/bl654_sensor_board_usb_swd_programmer.jpg b/boards/ezurio/bl654_sensor_board/doc/img/bl654_sensor_board_usb_swd_programmer.jpg similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/doc/img/bl654_sensor_board_usb_swd_programmer.jpg rename to boards/ezurio/bl654_sensor_board/doc/img/bl654_sensor_board_usb_swd_programmer.jpg diff --git a/boards/lairdconnect/bl654_sensor_board/pre_dt_board.cmake b/boards/ezurio/bl654_sensor_board/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl654_sensor_board/pre_dt_board.cmake rename to boards/ezurio/bl654_sensor_board/pre_dt_board.cmake diff --git a/boards/lairdconnect/bl654_usb/Kconfig b/boards/ezurio/bl654_usb/Kconfig similarity index 100% rename from boards/lairdconnect/bl654_usb/Kconfig rename to boards/ezurio/bl654_usb/Kconfig diff --git a/boards/lairdconnect/bl654_usb/Kconfig.bl654_usb b/boards/ezurio/bl654_usb/Kconfig.bl654_usb similarity index 100% rename from boards/lairdconnect/bl654_usb/Kconfig.bl654_usb rename to boards/ezurio/bl654_usb/Kconfig.bl654_usb diff --git a/boards/lairdconnect/bl654_usb/Kconfig.defconfig b/boards/ezurio/bl654_usb/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bl654_usb/Kconfig.defconfig rename to boards/ezurio/bl654_usb/Kconfig.defconfig diff --git a/boards/lairdconnect/bl654_usb/bl654_usb-pinctrl.dtsi b/boards/ezurio/bl654_usb/bl654_usb-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bl654_usb/bl654_usb-pinctrl.dtsi rename to boards/ezurio/bl654_usb/bl654_usb-pinctrl.dtsi diff --git a/boards/lairdconnect/bl654_usb/bl654_usb.dts b/boards/ezurio/bl654_usb/bl654_usb.dts similarity index 95% rename from boards/lairdconnect/bl654_usb/bl654_usb.dts rename to boards/ezurio/bl654_usb/bl654_usb.dts index fa814f4b80e42..8cde4ae008f98 100644 --- a/boards/lairdconnect/bl654_usb/bl654_usb.dts +++ b/boards/ezurio/bl654_usb/bl654_usb.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,8 +10,8 @@ #include "bl654_usb-pinctrl.dtsi" / { - model = "Laird Connectivity BL654 USB adapter"; - compatible = "lairdconnect,bl654_usb"; + model = "Ezurio BL654 USB adapter"; + compatible = "ezurio,bl654_usb"; chosen { zephyr,sram = &sram0; diff --git a/boards/lairdconnect/bl654_usb/bl654_usb.yaml b/boards/ezurio/bl654_usb/bl654_usb.yaml similarity index 83% rename from boards/lairdconnect/bl654_usb/bl654_usb.yaml rename to boards/ezurio/bl654_usb/bl654_usb.yaml index 620275a516d5b..4bf396760cc64 100644 --- a/boards/lairdconnect/bl654_usb/bl654_usb.yaml +++ b/boards/ezurio/bl654_usb/bl654_usb.yaml @@ -8,9 +8,8 @@ toolchain: - xtools supported: - usb_device - - usb_cdc - ble - pwm - watchdog - counter -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bl654_usb/bl654_usb_defconfig b/boards/ezurio/bl654_usb/bl654_usb_defconfig similarity index 100% rename from boards/lairdconnect/bl654_usb/bl654_usb_defconfig rename to boards/ezurio/bl654_usb/bl654_usb_defconfig diff --git a/boards/ezurio/bl654_usb/board.yml b/boards/ezurio/bl654_usb/board.yml new file mode 100644 index 0000000000000..13642fbe7124d --- /dev/null +++ b/boards/ezurio/bl654_usb/board.yml @@ -0,0 +1,5 @@ +board: + name: bl654_usb + vendor: ezurio + socs: + - name: nrf52840 diff --git a/boards/lairdconnect/bl654_usb/doc/bl654_usb.rst b/boards/ezurio/bl654_usb/doc/bl654_usb.rst similarity index 86% rename from boards/lairdconnect/bl654_usb/doc/bl654_usb.rst rename to boards/ezurio/bl654_usb/doc/bl654_usb.rst index 3bb3139b61564..34a64c14aec47 100644 --- a/boards/lairdconnect/bl654_usb/doc/bl654_usb.rst +++ b/boards/ezurio/bl654_usb/doc/bl654_usb.rst @@ -1,13 +1,13 @@ .. _bl654_usb: -Laird Connectivity BL654 USB (451-00004) -######################################## +Ezurio BL654 USB (451-00004) +############################ Overview ******** -The BL654 USB adapter hardware (Laird Connectivity part 451-00004) provides -support for the Laird Connectivity BL654 module powered by a Nordic +The BL654 USB adapter hardware (Ezurio part 451-00004) provides +support for the Ezurio BL654 module powered by a Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU. This USB adapter has the following features: @@ -105,14 +105,14 @@ Applications for the ``bl654_usb`` board configuration can be built in the usual way (see :ref:`build_an_application` for more details). The ``bl654_usb`` board cannot be used for debugging. The compatible BL654 DVK board can be used for development. Documentation can be found at the :ref:`bl654_dvk` -site and :zephyr_file:`boards/lairdconnect/bl654_dvk/doc/bl654_dvk.rst` +site and :zephyr_file:`boards/ezurio/bl654_dvk/doc/bl654_dvk.rst` Flashing ======== The board supports programming using the built-in bootloader. -The board is factory-programmed with a Laird Connectivity variation of Nordic's +The board is factory-programmed with a Ezurio variation of Nordic's open bootloader from Nordic's nRF5x SDK. With this option, you'll use Nordic's `nrfutil`_ program to create firmware packages supported by this bootloader and flash them to the device. Make sure ``nrfutil`` is installed @@ -175,7 +175,7 @@ the board is working properly with Zephyr: You can build and flash the example to make sure Zephyr is running correctly on your board. The LED definitions can be found in -:zephyr_file:`boards/lairdconnect/bl654_usb/bl654_usb.dts`. +:zephyr_file:`boards/ezurio/bl654_usb/bl654_usb.dts`. References @@ -183,8 +183,8 @@ References .. target-notes:: -.. _BL654 USB Dongle Quick Start Guide: https://www.lairdconnect.com/documentation/user-guide-bl654-usb-nordic-sdk-zephyr -.. _BL654 website: https://connectivity.lairdtech.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series +.. _BL654 USB Dongle Quick Start Guide: https://www.ezurio.com/documentation/user-guide-bl654-usb-nordic-sdk-zephyr +.. _BL654 website: https://ezurio.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl654-series .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _Creating a secure bootloader image: https://www.lairdconnect.com/documentation/application-note-creating-secure-bootloader-image-bl654-usb +.. _Creating a secure bootloader image: https://www.ezurio.com/documentation/application-note-creating-secure-bootloader-image-bl654-usb .. _nrfutil: https://github.com/NordicSemiconductor/pc-nrfutil diff --git a/boards/lairdconnect/bl654_usb/doc/img/bl654_usb.jpg b/boards/ezurio/bl654_usb/doc/img/bl654_usb.jpg similarity index 100% rename from boards/lairdconnect/bl654_usb/doc/img/bl654_usb.jpg rename to boards/ezurio/bl654_usb/doc/img/bl654_usb.jpg diff --git a/boards/lairdconnect/bl654_usb/doc/img/bl654_usb_pcb.jpg b/boards/ezurio/bl654_usb/doc/img/bl654_usb_pcb.jpg similarity index 100% rename from boards/lairdconnect/bl654_usb/doc/img/bl654_usb_pcb.jpg rename to boards/ezurio/bl654_usb/doc/img/bl654_usb_pcb.jpg diff --git a/boards/lairdconnect/bl654_usb/doc/img/bl654_usb_reset.jpg b/boards/ezurio/bl654_usb/doc/img/bl654_usb_reset.jpg similarity index 100% rename from boards/lairdconnect/bl654_usb/doc/img/bl654_usb_reset.jpg rename to boards/ezurio/bl654_usb/doc/img/bl654_usb_reset.jpg diff --git a/boards/lairdconnect/bl654_usb/pre_dt_board.cmake b/boards/ezurio/bl654_usb/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bl654_usb/pre_dt_board.cmake rename to boards/ezurio/bl654_usb/pre_dt_board.cmake diff --git a/boards/lairdconnect/bt510/Kconfig b/boards/ezurio/bt510/Kconfig similarity index 100% rename from boards/lairdconnect/bt510/Kconfig rename to boards/ezurio/bt510/Kconfig diff --git a/boards/lairdconnect/bt510/Kconfig.bt510 b/boards/ezurio/bt510/Kconfig.bt510 similarity index 100% rename from boards/lairdconnect/bt510/Kconfig.bt510 rename to boards/ezurio/bt510/Kconfig.bt510 diff --git a/boards/lairdconnect/bt510/Kconfig.defconfig b/boards/ezurio/bt510/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bt510/Kconfig.defconfig rename to boards/ezurio/bt510/Kconfig.defconfig diff --git a/boards/lairdconnect/bt510/board.cmake b/boards/ezurio/bt510/board.cmake similarity index 100% rename from boards/lairdconnect/bt510/board.cmake rename to boards/ezurio/bt510/board.cmake diff --git a/boards/ezurio/bt510/board.yml b/boards/ezurio/bt510/board.yml new file mode 100644 index 0000000000000..e4692ed452673 --- /dev/null +++ b/boards/ezurio/bt510/board.yml @@ -0,0 +1,5 @@ +board: + name: bt510 + vendor: ezurio + socs: + - name: nrf52840 diff --git a/boards/lairdconnect/bt510/bt510-pinctrl.dtsi b/boards/ezurio/bt510/bt510-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bt510/bt510-pinctrl.dtsi rename to boards/ezurio/bt510/bt510-pinctrl.dtsi diff --git a/boards/lairdconnect/bt510/bt510.dts b/boards/ezurio/bt510/bt510.dts similarity index 96% rename from boards/lairdconnect/bt510/bt510.dts rename to boards/ezurio/bt510/bt510.dts index 984b098e5d53d..adc8337862c08 100644 --- a/boards/lairdconnect/bt510/bt510.dts +++ b/boards/ezurio/bt510/bt510.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include / { - model = "Laird Sentrius BT510 Sensor"; - compatible = "lairdconnect,bt510"; + model = "Ezurio Sentrius BT510 Sensor"; + compatible = "ezurio,bt510"; chosen { zephyr,console = &uart0; diff --git a/boards/lairdconnect/bt510/bt510.yaml b/boards/ezurio/bt510/bt510.yaml similarity index 88% rename from boards/lairdconnect/bt510/bt510.yaml rename to boards/ezurio/bt510/bt510.yaml index c9b6823d18815..198b538eecd44 100644 --- a/boards/lairdconnect/bt510/bt510.yaml +++ b/boards/ezurio/bt510/bt510.yaml @@ -13,4 +13,4 @@ supported: - watchdog - i2c - sm351lt -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bt510/bt510_defconfig b/boards/ezurio/bt510/bt510_defconfig similarity index 100% rename from boards/lairdconnect/bt510/bt510_defconfig rename to boards/ezurio/bt510/bt510_defconfig diff --git a/boards/lairdconnect/bt510/doc/bt510.rst b/boards/ezurio/bt510/doc/bt510.rst similarity index 94% rename from boards/lairdconnect/bt510/doc/bt510.rst rename to boards/ezurio/bt510/doc/bt510.rst index 13459f69ea722..2d0dbcbf5069b 100644 --- a/boards/lairdconnect/bt510/doc/bt510.rst +++ b/boards/ezurio/bt510/doc/bt510.rst @@ -1,7 +1,7 @@ .. _bt510: -Laird Connectivity Sentrius BT510 Sensor -######################################## +Ezurio Sentrius BT510 Sensor +############################ Overview ******** @@ -162,7 +162,7 @@ A non-standard layout is used to include access to the sensor debug UART. Connectivity to the programmer/debugger must be modified to match the pinout shown above. -Laird Connectivity provide the USB-SWD programming board (750-03239) that supports +Ezurio provide the USB-SWD programming board (750-03239) that supports this connector layout, refer to the `USB SWD Programmer product page`_ . @@ -244,7 +244,7 @@ the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button, LED and sensor device definitions can be found in -:zephyr_file:`boards/lairdconnect/bt510/bt510.dts`. +:zephyr_file:`boards/ezurio/bt510/bt510.dts`. References @@ -252,9 +252,9 @@ References .. target-notes:: -.. _Sentrius BT510 website: https://www.lairdconnect.com/iot-devices/iot-sensors/bt510-bluetooth-5-long-range-ip67-multi-sensor +.. _Sentrius BT510 website: https://www.ezurio.com/iot-devices/iot-sensors/bt510-bluetooth-5-long-range-ip67-multi-sensor .. _TagConnect TC2050 product page: https://www.tag-connect.com/product/tc2050-idc-050 -.. _USB SWD Programmer product page: https://www.lairdconnect.com/wireless-modules/programming-kits/usb-swd-programming-kit +.. _USB SWD Programmer product page: https://www.ezurio.com/wireless-modules/programming-kits/usb-swd-programming-kit .. _MAX3232 datasheet: https://www.ti.com/lit/ds/symlink/max3232.pdf .. _Silabs 7055 datasheet: https://www.silabs.com/documents/public/data-sheets/Si7050-1-3-4-5-A20.pdf .. _ST Microelectronics LIS2DH datasheet: https://www.st.com/resource/en/datasheet/lis2dh.pdf diff --git a/boards/lairdconnect/bt510/doc/img/bt510.jpg b/boards/ezurio/bt510/doc/img/bt510.jpg similarity index 100% rename from boards/lairdconnect/bt510/doc/img/bt510.jpg rename to boards/ezurio/bt510/doc/img/bt510.jpg diff --git a/boards/lairdconnect/bt510/doc/img/bt510_back.jpg b/boards/ezurio/bt510/doc/img/bt510_back.jpg similarity index 100% rename from boards/lairdconnect/bt510/doc/img/bt510_back.jpg rename to boards/ezurio/bt510/doc/img/bt510_back.jpg diff --git a/boards/lairdconnect/bt510/doc/img/bt510_prog.jpg b/boards/ezurio/bt510/doc/img/bt510_prog.jpg similarity index 100% rename from boards/lairdconnect/bt510/doc/img/bt510_prog.jpg rename to boards/ezurio/bt510/doc/img/bt510_prog.jpg diff --git a/boards/lairdconnect/bt510/pre_dt_board.cmake b/boards/ezurio/bt510/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bt510/pre_dt_board.cmake rename to boards/ezurio/bt510/pre_dt_board.cmake diff --git a/boards/lairdconnect/bt610/Kconfig b/boards/ezurio/bt610/Kconfig similarity index 100% rename from boards/lairdconnect/bt610/Kconfig rename to boards/ezurio/bt610/Kconfig diff --git a/boards/lairdconnect/bt610/Kconfig.bt610 b/boards/ezurio/bt610/Kconfig.bt610 similarity index 100% rename from boards/lairdconnect/bt610/Kconfig.bt610 rename to boards/ezurio/bt610/Kconfig.bt610 diff --git a/boards/lairdconnect/bt610/Kconfig.defconfig b/boards/ezurio/bt610/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/bt610/Kconfig.defconfig rename to boards/ezurio/bt610/Kconfig.defconfig diff --git a/boards/lairdconnect/bt610/board.cmake b/boards/ezurio/bt610/board.cmake similarity index 100% rename from boards/lairdconnect/bt610/board.cmake rename to boards/ezurio/bt610/board.cmake diff --git a/boards/ezurio/bt610/board.yml b/boards/ezurio/bt610/board.yml new file mode 100644 index 0000000000000..0e4f29742c5d4 --- /dev/null +++ b/boards/ezurio/bt610/board.yml @@ -0,0 +1,5 @@ +board: + name: bt610 + vendor: ezurio + socs: + - name: nrf52840 diff --git a/boards/lairdconnect/bt610/bt610-pinctrl.dtsi b/boards/ezurio/bt610/bt610-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/bt610/bt610-pinctrl.dtsi rename to boards/ezurio/bt610/bt610-pinctrl.dtsi diff --git a/boards/lairdconnect/bt610/bt610.dts b/boards/ezurio/bt610/bt610.dts similarity index 98% rename from boards/lairdconnect/bt610/bt610.dts rename to boards/ezurio/bt610/bt610.dts index c6b9bad9910ac..9570f499d5463 100644 --- a/boards/lairdconnect/bt610/bt610.dts +++ b/boards/ezurio/bt610/bt610.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include / { - model = "Laird BT610 Sensor"; - compatible = "lairdconnect,bt610"; + model = "Ezurio BT610 Sensor"; + compatible = "ezurio,bt610"; chosen { zephyr,console = &uart0; @@ -77,7 +78,6 @@ mcuboot-button0 = &button1; mcuboot-led0 = &led1; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; mag1: mag_1 { diff --git a/boards/lairdconnect/bt610/bt610.yaml b/boards/ezurio/bt610/bt610.yaml similarity index 91% rename from boards/lairdconnect/bt610/bt610.yaml rename to boards/ezurio/bt610/bt610.yaml index 80cbe9975da15..5b96d98c5275e 100644 --- a/boards/lairdconnect/bt610/bt610.yaml +++ b/boards/ezurio/bt610/bt610.yaml @@ -19,4 +19,4 @@ supported: - counter - sm351lt - qspi -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/bt610/bt610_defconfig b/boards/ezurio/bt610/bt610_defconfig similarity index 100% rename from boards/lairdconnect/bt610/bt610_defconfig rename to boards/ezurio/bt610/bt610_defconfig diff --git a/boards/lairdconnect/bt610/doc/bt610.rst b/boards/ezurio/bt610/doc/bt610.rst similarity index 98% rename from boards/lairdconnect/bt610/doc/bt610.rst rename to boards/ezurio/bt610/doc/bt610.rst index baf9827e3d62d..20527ceb1e08a 100644 --- a/boards/lairdconnect/bt610/doc/bt610.rst +++ b/boards/ezurio/bt610/doc/bt610.rst @@ -1,7 +1,7 @@ .. _bt610: -Laird Connectivity Sentrius BT610 Sensor -######################################## +Ezurio Sentrius BT610 Sensor +############################ Overview ******** @@ -598,7 +598,7 @@ on the board are working properly with Zephyr: You can build and flash the examples to make sure Zephyr is running correctly on your board. The button, LED and sensor device definitions can be found in -:zephyr_file:`boards/lairdconnect/bt610/bt610.dts`. +:zephyr_file:`boards/ezurio/bt610/bt610.dts`. References @@ -606,10 +606,10 @@ References .. target-notes:: -.. _Sentrius BT610 website: https://www.lairdconnect.com/iot-devices/iot-sensors/sentrius-bt610-io-sensor +.. _Sentrius BT610 website: https://www.ezurio.com/iot-devices/iot-sensors/sentrius-bt610-io-sensor .. _Honeywell SM351LT datasheet: https://sensing.honeywell.com/honeywell-sensing-nanopower-series-datasheet-50095501-c-en.pdf .. _MAX3232 datasheet: https://www.ti.com/lit/ds/symlink/max3232.pdf .. _TI TMUX1204 datasheet: https://www.ti.com/lit/gpn/TMUX1204 .. _TI TCA9538 datasheet: https://www.ti.com/lit/gpn/TCA9538 .. _Macronix MX25R6435FZNIL0 datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/7913/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.5.pdf -.. _BT610 Zephyr Application Thermistor Calibration: https://www.lairdconnect.com/technology/bt610-thermistor-coefficient-calculator +.. _BT610 Zephyr Application Thermistor Calibration: https://www.ezurio.com/technology/bt610-thermistor-coefficient-calculator diff --git a/boards/lairdconnect/bt610/doc/img/bt610_back.jpg b/boards/ezurio/bt610/doc/img/bt610_back.jpg similarity index 100% rename from boards/lairdconnect/bt610/doc/img/bt610_back.jpg rename to boards/ezurio/bt610/doc/img/bt610_back.jpg diff --git a/boards/lairdconnect/bt610/doc/img/bt610_board.jpg b/boards/ezurio/bt610/doc/img/bt610_board.jpg similarity index 100% rename from boards/lairdconnect/bt610/doc/img/bt610_board.jpg rename to boards/ezurio/bt610/doc/img/bt610_board.jpg diff --git a/boards/lairdconnect/bt610/doc/img/bt610_front.jpg b/boards/ezurio/bt610/doc/img/bt610_front.jpg similarity index 100% rename from boards/lairdconnect/bt610/doc/img/bt610_front.jpg rename to boards/ezurio/bt610/doc/img/bt610_front.jpg diff --git a/boards/lairdconnect/bt610/pre_dt_board.cmake b/boards/ezurio/bt610/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/bt610/pre_dt_board.cmake rename to boards/ezurio/bt610/pre_dt_board.cmake diff --git a/boards/ezurio/index.rst b/boards/ezurio/index.rst new file mode 100644 index 0000000000000..5352513a1f378 --- /dev/null +++ b/boards/ezurio/index.rst @@ -0,0 +1,10 @@ +.. _boards-ezurio: + +Ezurio +################## + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/boards/lairdconnect/mg100/Kconfig b/boards/ezurio/mg100/Kconfig similarity index 100% rename from boards/lairdconnect/mg100/Kconfig rename to boards/ezurio/mg100/Kconfig diff --git a/boards/lairdconnect/mg100/Kconfig.defconfig b/boards/ezurio/mg100/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/mg100/Kconfig.defconfig rename to boards/ezurio/mg100/Kconfig.defconfig diff --git a/boards/lairdconnect/mg100/Kconfig.mg100 b/boards/ezurio/mg100/Kconfig.mg100 similarity index 100% rename from boards/lairdconnect/mg100/Kconfig.mg100 rename to boards/ezurio/mg100/Kconfig.mg100 diff --git a/boards/lairdconnect/mg100/board.cmake b/boards/ezurio/mg100/board.cmake similarity index 100% rename from boards/lairdconnect/mg100/board.cmake rename to boards/ezurio/mg100/board.cmake diff --git a/boards/ezurio/mg100/board.yml b/boards/ezurio/mg100/board.yml new file mode 100644 index 0000000000000..4c62320fc5eb7 --- /dev/null +++ b/boards/ezurio/mg100/board.yml @@ -0,0 +1,5 @@ +board: + name: mg100 + vendor: ezurio + socs: + - name: nrf52840 diff --git a/boards/lairdconnect/mg100/doc/img/mg100.jpg b/boards/ezurio/mg100/doc/img/mg100.jpg similarity index 100% rename from boards/lairdconnect/mg100/doc/img/mg100.jpg rename to boards/ezurio/mg100/doc/img/mg100.jpg diff --git a/boards/ezurio/mg100/doc/index.rst b/boards/ezurio/mg100/doc/index.rst new file mode 100644 index 0000000000000..b665997a762ca --- /dev/null +++ b/boards/ezurio/mg100/doc/index.rst @@ -0,0 +1,248 @@ +.. _mg100: + +Ezurio Sentrius™ MG100 Gateway +############################## + +Overview +******** +The Sentrius™ MG100 Gateway offers a compact, out of box Bluetooth to low power cellular gateway +solution. + +Based on the Pinnacle 100 socket modem, the Sentrius™ MG100 gateway captures data from any +Bluetooth 5 modules or devices and sends it to the cloud via a global low power cellular +(LTE-M/NB-IoT) connection. The MG100 seamlessly incorporates a powerful Cortex M4F controller, +full Bluetooth 5 connectivity, and dual-mode LTE-M/NB-IoT capabilities. The MG100 has full regulatory +and network certifications and End Device carrier approvals. + +Develop your application directly on the integrated Cortex M4F microcontroller using Zephyr RTOS, +enabling your application development with a secure, open source RTOS with more than just kernel +services. Remotely debug your fleet of devices with the `Memfault Platform`_. Take advantage of the +Zephyr community and Ezurio’s `Canvas Software Suite`_ to accelerate your development. +covering all aspects of the product's capabilities and hardware interfaces. The MG100 also delivers +complete antenna flexibility with internal or external antenna options available, and the optional +battery backup provides uninterrupted reporting of remote Bluetooth sensor data. + +More information about the board can be found at the `MG100 website`_. + +The MG100 hardware provides support for the Nordic Semiconductor `nRF52840`_ ARM Cortex-M4F CPU, +`Sierra Wireless HL7800`_ +and the following devices: + +* :abbr:`ADC (Analog to Digital Converter)` +* CLOCK +* FLASH +* :abbr:`GPIO (General Purpose Input Output)` +* :abbr:`I2C (Inter-Integrated Circuit)` +* :abbr:`MPU (Memory Protection Unit)` +* :abbr:`NVIC (Nested Vectored Interrupt Controller)` +* :abbr:`PWM (Pulse Width Modulation)` +* RADIO (Bluetooth Low Energy and 802.15.4) +* :abbr:`RTC (nRF RTC System Clock)` +* :abbr:`SPI (Serial Peripheral Interface)` +* :abbr:`UART (Universal asynchronous receiver-transmitter)` +* :abbr:`WDT (Watchdog Timer)` +* :abbr:`QSPI (Quad Serial Peripheral Interface)` +* :abbr:`LIS3DH (ST Micro 3-axis MEMS accelerometer)` +* :abbr:`HL7800 (Sierra Wireless HL7800 LTE-M1/NB-IoT modem)` +* :abbr:`SD Card` + +.. figure:: img/mg100.jpg + :align: center + :alt: MG100 + + MG100 (450-00054-K1) + +Hardware +******** + +Supported Features +================== + +The MG100 board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| ADC | on-chip | adc | ++-----------+------------+----------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| PWM | on-chip | pwm | ++-----------+------------+----------------------+ +| RADIO | on-chip | Bluetooth, | +| | | ieee802154 | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+----------------------+ +| UART | on-chip | serial | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ +| QSPI | on-chip | qspi/MX25R64(8MB) | ++-----------+------------+----------------------+ +| LIS3DH | I2C(M) | sensor/lis3dh | ++-----------+------------+----------------------+ +| HL7800 | UART | HL7800 modem driver | ++-----------+------------+----------------------+ +| SDMMC | SPI(M) | SD Card via SPI | ++-----------+------------+----------------------+ + +See `MG100 website`_ for a complete list +of MG100 hardware features. + +Connections and IOs +=================== + +LED +--- + +* LED1 (red) = P1.7 +* LED2 (blue) = P1.6 +* LED3 (green) = P1.5 + +Push buttons +------------ + +* BUTTON1 = P0.3 + +External flash memory +--------------------- + +A 64Mbit external flash memory part is available for storage of application +images and data. Refer to the `Macronix MX25R6435F datasheet`_ for further +details. + +The flash memory is connected to the on-board QSPI device controller. + +* MX25R64 = QSPI + +SCK = P0.19 +IO0 = P0.20 +IO1 = P0.21 +IO2 = P0.22 +IO3 = P0.23 +CSN = P0.17 + +LIS3DH Motion Sensor +-------------------- + +Motion sensor to detect if the gateway moves. + +IRQ IO = P0.28 +I2C SDA = P0.26 +I2C SCL = P0.27 + +SD Card +------- + +SD card used to store large amounts of data. + +SPI CS = P0.29 +SPI SCK = P1.09 +SPI MOSI = P0.11 +SPI MISO = P0.12 + +Programming and Debugging +************************* + +Applications for the ``mg100`` board configuration can be +built and flashed in the usual way. (see :ref:`build_an_application` +and :ref:`application_run` for more details) + +The `Ezurio USB-SWD Programming Kit`_ contains all the necessary +hardware to enable programming and debugging an MG100. + +Flashing +======== + +Follow the instructions in the :ref:`nordic_segger` page to install +and configure all the necessary software. Further information can be +found in :ref:`nordic_segger_flashing`. Then build and flash +applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Here is an example for the :ref:`hello_world` application. + +First, run your favorite terminal program to listen for output. + +.. note:: On the MG100, + the USB connector should be used to access the UART console. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the port where the board MG100 +can be found. For example, under Linux, :code:`/dev/ttyUSB0`. + +Then build and flash the application in the usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: mg100 + :goals: build flash + +Debugging +========= + +Refer to the :ref:`nordic_segger` page to learn about debugging Nordic boards with a +Segger IC. + +Software +******** + +Canvas Software Suite +============================== +The MG100 is a supported hardware platform for `Canvas Software Suite`_. + +Testing Bluetooth on the MG100 +============================== +Many of the Bluetooth examples will work on the MG100. +Try them out: + +* :ref:`ble_peripheral` +* :ref:`bluetooth-eddystone-sample` +* :ref:`bluetooth-ibeacon-sample` + +Testing the LEDs and buttons in the MG100 +==================================================== + +There are 2 samples that allow you to test that the buttons (switches) and LEDs on +the board are working properly with Zephyr: + +.. code-block:: console + + samples/basic/blinky + samples/basic/button + +You can build and flash the examples to make sure Zephyr is running correctly on +your board. The button and LED definitions can be found in +:zephyr_file:`boards/ezurio/mg100/mg100.dts`. + +References +********** + +.. target-notes:: + +.. _MG100 website: https://www.ezurio.com/iot-devices/iot-gateways/sentrius-mg100-gateway-lte-mnb-iot-and-bluetooth-5 +.. _nRF52840 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.1.pdf +.. _Sierra Wireless HL7800: https://source.sierrawireless.com/devices/hl-series/hl7800/#sthash.641qTTwA.dpbs +.. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html +.. _Macronix MX25R6435F datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/7913/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.5.pdf +.. _Ezurio USB-SWD Programming Kit: https://www.ezurio.com/wireless-modules/programming-kits/usb-swd-programming-kit +.. _Memfault Platform: https://docs.memfault.com/docs/mcu/pinnacle-100-guide +.. _nRF52840: https://www.nordicsemi.com/products/nrf52840 +.. _Canvas Software Suite: https://www.ezurio.com/canvas/software-suite diff --git a/boards/lairdconnect/mg100/mg100-pinctrl.dtsi b/boards/ezurio/mg100/mg100-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/mg100/mg100-pinctrl.dtsi rename to boards/ezurio/mg100/mg100-pinctrl.dtsi diff --git a/boards/lairdconnect/mg100/mg100.dts b/boards/ezurio/mg100/mg100.dts similarity index 98% rename from boards/lairdconnect/mg100/mg100.dts rename to boards/ezurio/mg100/mg100.dts index 7c6fbb92d246a..a9b782eb67cee 100644 --- a/boards/lairdconnect/mg100/mg100.dts +++ b/boards/ezurio/mg100/mg100.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2022 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,7 +12,7 @@ / { model = "MG100"; - compatible = "lairdconnect,mg100"; + compatible = "ezurio,mg100"; chosen { zephyr,console = &uart0; @@ -65,7 +66,6 @@ mcuboot-button0 = &button1; mcuboot-led0 = &led1; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/lairdconnect/mg100/mg100.yaml b/boards/ezurio/mg100/mg100.yaml similarity index 91% rename from boards/lairdconnect/mg100/mg100.yaml rename to boards/ezurio/mg100/mg100.yaml index 917eb7f0d8600..54de18e63ee29 100644 --- a/boards/lairdconnect/mg100/mg100.yaml +++ b/boards/ezurio/mg100/mg100.yaml @@ -18,4 +18,4 @@ supported: - spi - watchdog - netif:modem -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/mg100/mg100_defconfig b/boards/ezurio/mg100/mg100_defconfig similarity index 100% rename from boards/lairdconnect/mg100/mg100_defconfig rename to boards/ezurio/mg100/mg100_defconfig diff --git a/boards/lairdconnect/mg100/pre_dt_board.cmake b/boards/ezurio/mg100/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/mg100/pre_dt_board.cmake rename to boards/ezurio/mg100/pre_dt_board.cmake diff --git a/boards/lairdconnect/pinnacle_100_dvk/Kconfig b/boards/ezurio/pinnacle_100_dvk/Kconfig similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/Kconfig rename to boards/ezurio/pinnacle_100_dvk/Kconfig diff --git a/boards/lairdconnect/pinnacle_100_dvk/Kconfig.defconfig b/boards/ezurio/pinnacle_100_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/Kconfig.defconfig rename to boards/ezurio/pinnacle_100_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/pinnacle_100_dvk/Kconfig.pinnacle_100_dvk b/boards/ezurio/pinnacle_100_dvk/Kconfig.pinnacle_100_dvk similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/Kconfig.pinnacle_100_dvk rename to boards/ezurio/pinnacle_100_dvk/Kconfig.pinnacle_100_dvk diff --git a/boards/lairdconnect/pinnacle_100_dvk/board.cmake b/boards/ezurio/pinnacle_100_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/board.cmake rename to boards/ezurio/pinnacle_100_dvk/board.cmake diff --git a/boards/ezurio/pinnacle_100_dvk/board.yml b/boards/ezurio/pinnacle_100_dvk/board.yml new file mode 100644 index 0000000000000..8ed639a9a0a21 --- /dev/null +++ b/boards/ezurio/pinnacle_100_dvk/board.yml @@ -0,0 +1,5 @@ +board: + name: pinnacle_100_dvk + vendor: ezurio + socs: + - name: nrf52840 diff --git a/boards/lairdconnect/pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg b/boards/ezurio/pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg rename to boards/ezurio/pinnacle_100_dvk/doc/img/pinnacle_100_dvk.jpg diff --git a/boards/ezurio/pinnacle_100_dvk/doc/index.rst b/boards/ezurio/pinnacle_100_dvk/doc/index.rst new file mode 100644 index 0000000000000..9650d0c8e25ea --- /dev/null +++ b/boards/ezurio/pinnacle_100_dvk/doc/index.rst @@ -0,0 +1,219 @@ +.. _pinnacle_100_dvk: + +Ezurio Pinnacle 100 DVK +####################### + +Overview +******** +The Pinnacle™ 100 cellular modem seamlessly incorporates a powerful Cortex M4F +controller, full Bluetooth 5 and LTE-M/NB-IoT capabilities – all with full +regulatory certifications and LTE carrier approvals. The Pinnacle 100 also +delivers complete antenna flexibility, with pre-integrated internal or external +antenna options such as the Revie Flex family of LTE and NB-IoT +internal antennas. + +Develop your application directly on the M4F controller using Zephyr RTOS to +cut BOM costs and power consumption. Take advantage of the Zephyr community, +Ezurio’s sample code (cellular, Bluetooth) and hardware interfaces, +or use our hosted mode AT commands set firmware. + +Extremely power conscious, the Pinnacle 100 is ideal for battery-powered +devices operating at the edge of your IoT networks, seamlessly bridging the +cellular WAN to BLE. It’s never been easier to bridge wireless +Bluetooth 5 sensor data to cloud services like AWS IoT over a +low-power LTE connection. + +More information about the board can be found at the `Pinnacle 100 website`_. + +The Pinnacle 100 Development Kit (453-00010-K1 or 453-00011-K1) hardware +provides support for the +Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU, `Sierra Wireless HL7800`_ (Altair ALT1250) +and the following devices: + +* :abbr:`ADC (Analog to Digital Converter)` +* CLOCK +* FLASH +* :abbr:`GPIO (General Purpose Input Output)` +* :abbr:`I2C (Inter-Integrated Circuit)` +* :abbr:`MPU (Memory Protection Unit)` +* :abbr:`NVIC (Nested Vectored Interrupt Controller)` +* :abbr:`PWM (Pulse Width Modulation)` +* RADIO (Bluetooth Low Energy and 802.15.4) +* :abbr:`RTC (nRF RTC System Clock)` +* Segger RTT (RTT Console) +* :abbr:`SPI (Serial Peripheral Interface)` +* :abbr:`UART (Universal asynchronous receiver-transmitter)` +* :abbr:`USB (Universal Serial Bus)` +* :abbr:`WDT (Watchdog Timer)` +* :abbr:`QSPI (Quad Serial Peripheral Interface)` +* :abbr:`BME680 (Bosch Sensortec BME680 environmental sensor)` +* :abbr:`HL7800 (Sierra Wireless HL7800 LTE-M1/NB-IoT modem)` + +.. figure:: img/pinnacle_100_dvk.jpg + :align: center + :alt: Pinnacle 100 DVK + + Pinnacle 100 DVK (453-00010-K1) + +Hardware +******** + +Supported Features +================== + +The Pinnacle 100 development board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| ADC | on-chip | adc | ++-----------+------------+----------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| PWM | on-chip | pwm | ++-----------+------------+----------------------+ +| RADIO | on-chip | Bluetooth, | +| | | ieee802154 | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| RTT | Segger | console | ++-----------+------------+----------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+----------------------+ +| UART | on-chip | serial | ++-----------+------------+----------------------+ +| USB | on-chip | usb | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ +| QSPI | on-chip | qspi/MX25R64(8MB) | ++-----------+------------+----------------------+ +| BME680 | I2C(M) | sensor/bme680 | ++-----------+------------+----------------------+ +| HL7800 | UART | HL7800 modem driver | ++-----------+------------+----------------------+ + +See `Pinnacle 100 website`_ for a complete list +of Pinnacle 100 Development Kit hardware features. + +Connections and IOs +=================== + +LED +--- + +* LED1 (blue) = P1.4 +* LED2 (green) = P1.5 +* LED3 (red) = P1.6 +* LED4 (green) = P1.7 + +Push buttons +------------ + +* BUTTON1 = SW1 = P0.31 +* BUTTON2 = SW2 = P0.3 +* BUTTON3 = SW3 = P0.4 +* BUTTON4 = SW4 = P0.2 +* NRF RESET = SW5 = reset + +Programming and Debugging +************************* + +Applications for the ``pinnacle_100_dvk`` board configuration can be +built and flashed in the usual way. (see :ref:`build_an_application` +and :ref:`application_run` for more details) + +Flashing +======== + +Follow the instructions in the :ref:`nordic_segger` page to install +and configure all the necessary software. Further information can be +found in :ref:`nordic_segger_flashing`. Then build and flash +applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Here is an example for the :ref:`hello_world` application. + +First, run your favorite terminal program to listen for output. + +.. note:: On the Pinnacle 100 development board, + the FTDI USB should be used to access the UART console. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the port where the board Pinnacle 100 DVK +can be found. For example, under Linux, :code:`/dev/ttyUSB0`. + +Then build and flash the application in the usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: pinnacle_100_dvk + :goals: build flash + +Debugging +========= + +Refer to the :ref:`nordic_segger` page to learn about debugging Nordic boards with a +Segger IC. + +Software +******** + +Canvas Software Suite +============================== +The Pinnacle 100 is a supported hardware platform for `Canvas Software Suite`_. + +Sample Applications +=================== +`Pinnacle 100 Sample Applications`_ are available. + +Testing Bluetooth on the Pinnacle 100 DVK +========================================= +Many of the Bluetooth examples will work on the Pinnacle 100 DVK. +Try them out: + +* :ref:`ble_peripheral` +* :ref:`bluetooth-eddystone-sample` +* :ref:`bluetooth-ibeacon-sample` + +Testing the LEDs and buttons in the Pinnacle 100 DVK +==================================================== + +There are 2 samples that allow you to test that the buttons (switches) and LEDs on +the board are working properly with Zephyr: + +.. code-block:: console + + samples/basic/blinky + samples/basic/button + +You can build and flash the examples to make sure Zephyr is running correctly on +your board. The button and LED definitions can be found in +:zephyr_file:`boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts`. + +References +********** + +.. target-notes:: + +.. _Pinnacle 100 website: https://www.ezurio.com/wireless-modules/cellular-solutions/pinnacle-100-cellular-modem +.. _nRF52840 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.1.pdf +.. _Sierra Wireless HL7800: https://source.sierrawireless.com/devices/hl-series/hl7800/#sthash.641qTTwA.dpbs +.. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html +.. _Pinnacle 100 Sample Applications: https://github.com/LairdCP/Pinnacle_100_Sample_Applications +.. _Canvas Software Suite: https://www.ezurio.com/canvas/software-suite diff --git a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi rename to boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.dts b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts similarity index 98% rename from boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.dts rename to boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts index 1e3006dd0d325..175f71938c73a 100644 --- a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.dts +++ b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2019 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,7 +12,7 @@ / { model = "Pinnacle 100 Dev Kit"; - compatible = "lairdconnect,pinnacle-100-dvk"; + compatible = "ezurio,pinnacle-100-dvk"; chosen { zephyr,console = &uart0; @@ -81,7 +82,6 @@ mcuboot-button0 = &button1; mcuboot-led0 = &led1; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.yaml similarity index 88% rename from boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml rename to boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.yaml index 153fb6cab0863..3d44a009e2d06 100644 --- a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.yaml +++ b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk.yaml @@ -16,8 +16,7 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog - netif:modem -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk_defconfig b/boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk_defconfig similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk_defconfig rename to boards/ezurio/pinnacle_100_dvk/pinnacle_100_dvk_defconfig diff --git a/boards/lairdconnect/pinnacle_100_dvk/pre_dt_board.cmake b/boards/ezurio/pinnacle_100_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/pinnacle_100_dvk/pre_dt_board.cmake rename to boards/ezurio/pinnacle_100_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/rm1xx_dvk/Kconfig.defconfig b/boards/ezurio/rm1xx_dvk/Kconfig.defconfig similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/Kconfig.defconfig rename to boards/ezurio/rm1xx_dvk/Kconfig.defconfig diff --git a/boards/lairdconnect/rm1xx_dvk/Kconfig.rm1xx_dvk b/boards/ezurio/rm1xx_dvk/Kconfig.rm1xx_dvk similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/Kconfig.rm1xx_dvk rename to boards/ezurio/rm1xx_dvk/Kconfig.rm1xx_dvk diff --git a/boards/lairdconnect/rm1xx_dvk/board.cmake b/boards/ezurio/rm1xx_dvk/board.cmake similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/board.cmake rename to boards/ezurio/rm1xx_dvk/board.cmake diff --git a/boards/ezurio/rm1xx_dvk/board.yml b/boards/ezurio/rm1xx_dvk/board.yml new file mode 100644 index 0000000000000..4a8792eecc57d --- /dev/null +++ b/boards/ezurio/rm1xx_dvk/board.yml @@ -0,0 +1,5 @@ +board: + name: rm1xx_dvk + vendor: ezurio + socs: + - name: nrf51822 diff --git a/boards/lairdconnect/rm1xx_dvk/doc/img/RM186-DVK.jpg b/boards/ezurio/rm1xx_dvk/doc/img/RM186-DVK.jpg similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/doc/img/RM186-DVK.jpg rename to boards/ezurio/rm1xx_dvk/doc/img/RM186-DVK.jpg diff --git a/boards/lairdconnect/rm1xx_dvk/doc/img/RM186-SM.jpg b/boards/ezurio/rm1xx_dvk/doc/img/RM186-SM.jpg similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/doc/img/RM186-SM.jpg rename to boards/ezurio/rm1xx_dvk/doc/img/RM186-SM.jpg diff --git a/boards/ezurio/rm1xx_dvk/doc/index.rst b/boards/ezurio/rm1xx_dvk/doc/index.rst new file mode 100644 index 0000000000000..f530c9b791fd5 --- /dev/null +++ b/boards/ezurio/rm1xx_dvk/doc/index.rst @@ -0,0 +1,179 @@ +.. _rm1xx_dvk: + +Ezurio RM1xx DVK +################ + +Overview +******** + +Ezurio's RM1xx is a module which integrates both LoRa and +BLE communications, powered by a Nordic Semiconductor nRF51822 ARM +Cortex-M0 CPU and on-board Semtech SX1272 LoRa RF chip. This board +supports the RM1xx on the RM1xx development board - RM191 for the +915MHz version and RM186 for the 868MHz version. + +This development kit has the following features: + +* :abbr:`ADC (Analog to Digital Converter)` +* CLOCK +* FLASH +* :abbr:`GPIO (General Purpose Input Output)` +* :abbr:`I2C (Inter-Integrated Circuit)` +* :abbr:`NVIC (Nested Vectored Interrupt Controller)` +* :abbr:`PWM (Pulse Width Modulation)` +* RADIO (Bluetooth Low Energy) +* :abbr:`RTC (nRF RTC System Clock)` +* Segger RTT (RTT Console) +* :abbr:`SPI (Serial Peripheral Interface)` +* :abbr:`UART (Universal asynchronous receiver-transmitter)` +* :abbr:`WDT (Watchdog Timer)` + +.. figure:: img/RM186-DVK.jpg + :align: center + :alt: RM1xx development kit (DVK) + + RM1xx development kit (DVK) (Credit: Ezurio) + +.. figure:: img/RM186-SM.jpg + :align: center + :alt: RM1xx module + + RM1xx module (Credit: Ezurio) + +More information about the module can be found on the +`RM1xx homepage`_. + +The `Nordic Semiconductor Infocenter`_ +contains the processor's information and the datasheet. + +Hardware +******** + +The RM1xx has two internal oscillators. The frequency of +the slow clock is 32.768KHz. The frequency of the main clock +is 16MHz. + + +Supported Features +================== + +The rm1xx_dvk board configuration supports the following +hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| ADC | on-chip | adc | ++-----------+------------+----------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+----------------------+ +| FLASH | on-chip | flash | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| I2C(M) | on-chip | i2c | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| PWM | on-chip | pwm | ++-----------+------------+----------------------+ +| RTC | on-chip | system clock | ++-----------+------------+----------------------+ +| RTT | Segger | console | ++-----------+------------+----------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+----------------------+ +| SPU | on-chip | system protection | ++-----------+------------+----------------------+ +| UART | on-chip | serial | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ + +Other hardware features have not been enabled yet for this board. +See `Nordic Semiconductor Infocenter`_ +for a complete list of hardware features. + +Connections and IOs +=================== + +The development board features a Microchip MCP23S08 SPI port expander - +note that this is not currently supported in Zephyr. + +Refer to the `Microchip MCP23S08 datasheet`_ for further details. + +Push buttons +------------ + +* BUTTON2 = SW0 = P0.05 + + +Internal Memory +=============== + +EEPROM Memory +------------- + +A 512KB (4Mb) Adesto AT25DF041B EEPROM is available via SPI for storage +of infrequently updated data and small datasets and can be used with +the spi-nor driver. Note that the EEPROM shares the same SPI bus as the +SX1272 LoRa transceiver so priority access should be given to the LoRa +radio. + +Refer to the `Adesto AT25DF041B datasheet`_ for further details. + +LoRa +==== + +A Semtech SX1272 transceiver chip is present in the module which can be +used in 915MHz LoRa frequency ranges if using an RM191 module or 868MHz +LoRa frequency ranges if uses an RM186 module + +Refer to the `Semtech SX1272 datasheet`_ for further details. + +Programming and Debugging +************************* + +Flashing +======== + +Follow the instructions in the :ref:`nordic_segger` page to install +and configure all the necessary software. Further information can be +found in :ref:`nordic_segger_flashing`. Then build and flash +applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Here is an example for the :ref:`hello_world` application. + +First, run your favorite terminal program to listen for output. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the port where the board nRF51 DK +can be found. For example, under Linux, :code:`/dev/ttyACM0`. + +Then build and flash the application in the usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: rm1xx_dvk + :goals: build flash + +Debugging +========= + +Refer to the :ref:`nordic_segger` page to learn about debugging boards +with a Segger IC. + +References +********** + +.. target-notes:: + +.. _RM1xx homepage: https://www.ezurio.com/wireless-modules/lorawan-solutions/sentrius-rm1xx-lora-ble-module +.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _Adesto AT25DF041B datasheet: https://www.dialog-semiconductor.com/sites/default/files/ds-at25df041b_040.pdf +.. _Semtech SX1272 datasheet: https://semtech.my.salesforce.com/sfc/p/#E0000000JelG/a/440000001NCE/v_VBhk1IolDgxwwnOpcS_vTFxPfSEPQbuneK3mWsXlU +.. _Microchip MCP23S08 datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/MCP23008-MCP23S08-Data-Sheet-20001919F.pdf diff --git a/boards/lairdconnect/rm1xx_dvk/pre_dt_board.cmake b/boards/ezurio/rm1xx_dvk/pre_dt_board.cmake similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/pre_dt_board.cmake rename to boards/ezurio/rm1xx_dvk/pre_dt_board.cmake diff --git a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi b/boards/ezurio/rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi rename to boards/ezurio/rm1xx_dvk/rm1xx_dvk-pinctrl.dtsi diff --git a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.dts b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts similarity index 96% rename from boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.dts rename to boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts index 8d364bfa27aa0..f0b860ac45381 100644 --- a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.dts +++ b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Laird Connectivity + * Copyright (c) 2024 Ezurio * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,8 +11,8 @@ #include / { - model = "Laird Connectivity RM1XX_DVK"; - compatible = "lairdconnect,rm1xx_dvk"; + model = "Ezurio RM1XX_DVK"; + compatible = "ezurio,rm1xx_dvk"; chosen { zephyr,console = &uart0; @@ -37,7 +38,6 @@ sw0 = &button2; lora0 = &lora0; watchdog0 = &wdt0; - spi-flash0 = &at25; }; }; diff --git a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.yaml b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml similarity index 89% rename from boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.yaml rename to boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml index c673fd4d55ec2..2dd24375a5b7d 100644 --- a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk.yaml +++ b/boards/ezurio/rm1xx_dvk/rm1xx_dvk.yaml @@ -14,4 +14,4 @@ supported: testing: ignore_tags: - net -vendor: lairdconnect +vendor: ezurio diff --git a/boards/lairdconnect/rm1xx_dvk/rm1xx_dvk_defconfig b/boards/ezurio/rm1xx_dvk/rm1xx_dvk_defconfig similarity index 100% rename from boards/lairdconnect/rm1xx_dvk/rm1xx_dvk_defconfig rename to boards/ezurio/rm1xx_dvk/rm1xx_dvk_defconfig diff --git a/boards/fanke/fk7b0m1_vbt6/fk7b0m1_vbt6.dts b/boards/fanke/fk7b0m1_vbt6/fk7b0m1_vbt6.dts index 090a29a198187..a8db5b677f23e 100644 --- a/boards/fanke/fk7b0m1_vbt6/fk7b0m1_vbt6.dts +++ b/boards/fanke/fk7b0m1_vbt6/fk7b0m1_vbt6.dts @@ -41,7 +41,6 @@ aliases { led0 = &user_led; sw0 = &user_button; - spi-flash0 = &w25q64jvssiq_spi; }; }; diff --git a/boards/franzininho/esp32s2_franzininho/esp32s2_franzininho.dts b/boards/franzininho/esp32s2_franzininho/esp32s2_franzininho.dts index d8a6f1c70706b..74d5f7610a94e 100644 --- a/boards/franzininho/esp32s2_franzininho/esp32s2_franzininho.dts +++ b/boards/franzininho/esp32s2_franzininho/esp32s2_franzininho.dts @@ -43,10 +43,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/boards/gaisler/gr716a_mini/gr716a_mini.dts b/boards/gaisler/gr716a_mini/gr716a_mini.dts index 745caa64f671b..fb42de635a066 100644 --- a/boards/gaisler/gr716a_mini/gr716a_mini.dts +++ b/boards/gaisler/gr716a_mini/gr716a_mini.dts @@ -12,9 +12,7 @@ / { model = "GR716-MINI Development Board"; compatible = "gaisler,gr716a-mini"; - aliases { - spi-flash0 = &flash0; - }; + chosen { zephyr,console = &uart0; zephyr,shell-uart = &uart0; diff --git a/boards/gd/gd32a503v_eval/gd32a503v_eval.dts b/boards/gd/gd32a503v_eval/gd32a503v_eval.dts index dc6e0325452be..41fd7b2d75d97 100644 --- a/boards/gd/gd32a503v_eval/gd32a503v_eval.dts +++ b/boards/gd/gd32a503v_eval/gd32a503v_eval.dts @@ -35,7 +35,6 @@ aliases { led0 = &led1; led1 = &led2; - spi-flash0 = &nor_flash; }; }; diff --git a/boards/gd/gd32f450i_eval/gd32f450i_eval.dts b/boards/gd/gd32f450i_eval/gd32f450i_eval.dts index 4e2f87c4015b8..4a9f9d4fb6a88 100644 --- a/boards/gd/gd32f450i_eval/gd32f450i_eval.dts +++ b/boards/gd/gd32f450i_eval/gd32f450i_eval.dts @@ -71,7 +71,6 @@ sw0 = &user_key; pwm-led0 = &pwm_led; eeprom-0 = &eeprom0; - spi-flash0 = &nor_flash; watchdog0 = &fwdgt; }; }; diff --git a/boards/gd/gd32f450z_eval/gd32f450z_eval.dts b/boards/gd/gd32f450z_eval/gd32f450z_eval.dts index c636a5647c7d0..f01fd488b4c3e 100644 --- a/boards/gd/gd32f450z_eval/gd32f450z_eval.dts +++ b/boards/gd/gd32f450z_eval/gd32f450z_eval.dts @@ -71,7 +71,6 @@ sw0 = &user_key; pwm-led0 = &pwm_led; eeprom-0 = &eeprom0; - spi-flash0 = &nor_flash; watchdog0 = &fwdgt; }; }; diff --git a/boards/gd/gd32f470i_eval/gd32f470i_eval.dts b/boards/gd/gd32f470i_eval/gd32f470i_eval.dts index 306d190b3d4a8..1bff660f1c6f6 100644 --- a/boards/gd/gd32f470i_eval/gd32f470i_eval.dts +++ b/boards/gd/gd32f470i_eval/gd32f470i_eval.dts @@ -71,7 +71,6 @@ sw0 = &user_key; pwm-led0 = &pwm_led; eeprom-0 = &eeprom0; - spi-flash0 = &nor_flash; watchdog0 = &fwdgt; }; }; diff --git a/boards/gd/gd32vf103v_eval/gd32vf103v_eval.dts b/boards/gd/gd32vf103v_eval/gd32vf103v_eval.dts index cea9c00b7e99e..bee944f7fdc9f 100644 --- a/boards/gd/gd32vf103v_eval/gd32vf103v_eval.dts +++ b/boards/gd/gd32vf103v_eval/gd32vf103v_eval.dts @@ -84,7 +84,6 @@ led1 = &led2; sw0 = &key_cet; pwm-led0 = &pwm_led; - spi-flash0 = &nor_flash; watchdog0 = &fwdgt; }; }; diff --git a/boards/google/dragonclaw/google_dragonclaw.yaml b/boards/google/dragonclaw/google_dragonclaw.yaml index ddb4f3a77133a..bf535af2c1e63 100644 --- a/boards/google/dragonclaw/google_dragonclaw.yaml +++ b/boards/google/dragonclaw/google_dragonclaw.yaml @@ -9,3 +9,11 @@ toolchain: ram: 256 flash: 1024 vendor: google +supported: + - counter + - dma + - gpio + - i2c + - spi + - pwm + - rtc diff --git a/boards/hardkernel/odroid_go/Kconfig.defconfig b/boards/hardkernel/odroid_go/Kconfig.defconfig index 345a0f4f64ee6..58874c1f51408 100644 --- a/boards/hardkernel/odroid_go/Kconfig.defconfig +++ b/boards/hardkernel/odroid_go/Kconfig.defconfig @@ -12,7 +12,7 @@ config SPI default y if DISK_DRIVER_SDMMC config ESP_SPIRAM - default y + default y if !MCUBOOT choice SPIRAM_TYPE default SPIRAM_TYPE_ESPPSRAM64 @@ -25,10 +25,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_ODROID_GO_ESP32_PROCPU if BOARD_ODROID_GO_ESP32_APPCPU diff --git a/boards/hardkernel/odroid_go/odroid_go_appcpu.dts b/boards/hardkernel/odroid_go/odroid_go_appcpu.dts index 6b59353de6d78..1733da93f7464 100644 --- a/boards/hardkernel/odroid_go/odroid_go_appcpu.dts +++ b/boards/hardkernel/odroid_go/odroid_go_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/hardkernel/odroid_go/odroid_go_appcpu.yaml b/boards/hardkernel/odroid_go/odroid_go_appcpu.yaml index a5a1c003ef35c..946166f95b49d 100644 --- a/boards/hardkernel/odroid_go/odroid_go_appcpu.yaml +++ b/boards/hardkernel/odroid_go/odroid_go_appcpu.yaml @@ -1,5 +1,5 @@ identifier: odroid_go/esp32/appcpu -name: ODROID-GO +name: ODROID-GO APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/hardkernel/odroid_go/odroid_go_procpu.dts b/boards/hardkernel/odroid_go/odroid_go_procpu.dts index c17c25823e216..c7de3a9c576e4 100644 --- a/boards/hardkernel/odroid_go/odroid_go_procpu.dts +++ b/boards/hardkernel/odroid_go/odroid_go_procpu.dts @@ -20,6 +20,7 @@ zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; zephyr,display = &ili9341; + zephyr,bt-hci = &esp32_bt_hci; }; leds { @@ -99,14 +100,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -214,3 +207,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/hardkernel/odroid_go/odroid_go_procpu.yaml b/boards/hardkernel/odroid_go/odroid_go_procpu.yaml index 59363bb4ee92e..f2eafb526763f 100644 --- a/boards/hardkernel/odroid_go/odroid_go_procpu.yaml +++ b/boards/hardkernel/odroid_go/odroid_go_procpu.yaml @@ -1,5 +1,5 @@ identifier: odroid_go/esp32/procpu -name: ODROID-GO +name: ODROID-GO PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/heltec/heltec_wifi_lora32_v2/Kconfig.defconfig b/boards/heltec/heltec_wifi_lora32_v2/Kconfig.defconfig index 4f459aa0ca425..a2979499b658f 100644 --- a/boards/heltec/heltec_wifi_lora32_v2/Kconfig.defconfig +++ b/boards/heltec/heltec_wifi_lora32_v2/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_HELTEC_WIFI_LORA32_V2_ESP32_PROCPU if BOARD_HELTEC_WIFI_LORA32_V2_ESP32_APPCPU diff --git a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.dts b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.dts index 4cf9e26b89d45..1b9f7dff7006d 100644 --- a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.dts +++ b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.yaml b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.yaml index 373c6b0eae994..d838e27766ea2 100644 --- a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.yaml +++ b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_appcpu.yaml @@ -1,5 +1,5 @@ identifier: heltec_wifi_lora32_v2/esp32/appcpu -name: ESP32 DEVKITC WROVER APPCPU +name: HELTEC WiFi LoRa 32 (V2) Board APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.dts b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.dts index 5e1c8c6c6ff12..4c7cedf82b5fc 100644 --- a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.dts +++ b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.dts @@ -55,17 +55,10 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -157,5 +150,9 @@ }; }; +&esp32_bt_hci { + status = "okay"; +}; + /* Required by the ssd1306_128x64 shield which enables the OLED display */ arduino_i2c: &i2c0 {}; diff --git a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.yaml b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.yaml index f8571589d7a12..d516f1e1c5c89 100644 --- a/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.yaml +++ b/boards/heltec/heltec_wifi_lora32_v2/heltec_wifi_lora32_v2_procpu.yaml @@ -1,5 +1,5 @@ identifier: heltec_wifi_lora32_v2/esp32/procpu -name: HELTEC WiFi LoRa 32 (V2) Board +name: HELTEC WiFi LoRa 32 (V2) Board PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/heltec/heltec_wireless_stick_lite_v3/Kconfig.defconfig b/boards/heltec/heltec_wireless_stick_lite_v3/Kconfig.defconfig index 82915e44b949b..c1aa6f030c767 100644 --- a/boards/heltec/heltec_wireless_stick_lite_v3/Kconfig.defconfig +++ b/boards/heltec/heltec_wireless_stick_lite_v3/Kconfig.defconfig @@ -13,10 +13,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_HELTEC_WIRELESS_STICK_LITE_V3_ESP32S3_PROCPU if BOARD_HELTEC_WIRELESS_STICK_LITE_V3_ESP32S3_APPCPU diff --git a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.dts b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.dts index 6c49e64e8d1c9..92bde107bc3a8 100644 --- a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.dts +++ b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.yaml b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.yaml index a465da8f94dc9..d738477900dfb 100644 --- a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.yaml +++ b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_appcpu.yaml @@ -1,5 +1,5 @@ identifier: heltec_wireless_stick_lite_v3/esp32s3/appcpu -name: ESP32-S3 DevKitM APPCPU +name: Heltec Wireless Stick Lite (V3) APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_procpu.dts b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_procpu.dts index 38d870a6fbb26..854eb101fe4d7 100644 --- a/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_procpu.dts +++ b/boards/heltec/heltec_wireless_stick_lite_v3/heltec_wireless_stick_lite_v3_procpu.dts @@ -72,17 +72,10 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &adc1 { status ="okay"; }; @@ -142,7 +135,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { @@ -214,3 +206,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/cypress/cy8ckit_062s4/Kconfig.cy8ckit_062s4 b/boards/infineon/cy8ckit_062s4/Kconfig.cy8ckit_062s4 similarity index 100% rename from boards/cypress/cy8ckit_062s4/Kconfig.cy8ckit_062s4 rename to boards/infineon/cy8ckit_062s4/Kconfig.cy8ckit_062s4 diff --git a/boards/cypress/cy8ckit_062s4/board.cmake b/boards/infineon/cy8ckit_062s4/board.cmake similarity index 100% rename from boards/cypress/cy8ckit_062s4/board.cmake rename to boards/infineon/cy8ckit_062s4/board.cmake diff --git a/boards/infineon/cy8ckit_062s4/board.yml b/boards/infineon/cy8ckit_062s4/board.yml new file mode 100644 index 0000000000000..c460d9f050396 --- /dev/null +++ b/boards/infineon/cy8ckit_062s4/board.yml @@ -0,0 +1,5 @@ +board: + name: cy8ckit_062s4 + vendor: infineon + socs: + - name: cy8c6244lqi_s4d92 diff --git a/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts new file mode 100644 index 0000000000000..9328a0cf60dcf --- /dev/null +++ b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.dts @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2024 David Ullmann + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include + +/ { + model = "Infineon PSoC 62S4 Pioneer Kit"; + compatible ="cypress,psoc6"; + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart2; + zephyr,shell-uart = &uart2; + }; + + aliases { + led0 = &user_led; + }; + + leds { + compatible = "gpio-leds"; + user_led: led_0 { + label = "LED_0"; + gpios = <&gpio_prt2 5 GPIO_ACTIVE_HIGH>; + }; + + }; + + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; /* shared */ + gpio-map = <0 0 &gpio_prt10 0 0>, /* A0 */ + <1 0 &gpio_prt10 1 0>, /* A1 */ + <2 0 &gpio_prt10 2 0>, /* A2 */ + <3 0 &gpio_prt10 3 0>, /* A3 */ + <4 0 &gpio_prt10 4 0>, /* A4 */ + <5 0 &gpio_prt10 5 0>, /* A5 */ + <6 0 &gpio_prt0 2 0>, /* D0-RX-5 */ + <7 0 &gpio_prt0 3 0>, /* D1-TX-5 */ + <8 0 &gpio_prt5 0 0>, /* D2-RTS-5 */ + <9 0 &gpio_prt5 1 0>, /* D3-CTS-5 */ + <10 0 &gpio_prt5 6 0>, /* D4 */ + <11 0 &gpio_prt5 7 0>, /* D5 */ + <12 0 &gpio_prt6 2 0>, /* D6 */ + <13 0 &gpio_prt6 3 0>, /* D7 */ + <14 0 &gpio_prt2 4 0>, /* D8-RX-6 */ + <15 0 &gpio_prt2 6 0>, /* D9-TX-6 */ + <16 0 &gpio_prt2 3 0>, /* D10 */ + <17 0 &gpio_prt2 0 0>, /* D11 */ + <18 0 &gpio_prt2 1 0>, /* D12 */ + <19 0 &gpio_prt2 2 0>; /* D13 */ + }; +}; + +&p3_1_scb2_uart_tx { + drive-push-pull; +}; + +&p3_0_scb2_uart_rx { + input-enable; +}; + + +uart2: &scb2 { + compatible = "infineon,cat1-uart"; + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&p3_0_scb2_uart_rx &p3_1_scb2_uart_tx>; + pinctrl-names = "default"; +}; + +&gpio_prt3 { + status = "okay"; +}; + +&gpio_prt2 { + status = "okay"; +}; + +uart0: &scb0 { + compatible = "infineon,cat1-uart"; +}; + +arduino_serial: &uart0 {}; diff --git a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4.yaml b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.yaml similarity index 93% rename from boards/cypress/cy8ckit_062s4/cy8ckit_062s4.yaml rename to boards/infineon/cy8ckit_062s4/cy8ckit_062s4.yaml index aaa7d0c830551..4ab5c7580ecdd 100644 --- a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4.yaml +++ b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4.yaml @@ -12,4 +12,4 @@ toolchain: - gnuarmemb supported: - gpio -vendor: cypress +vendor: infineon diff --git a/boards/cypress/cy8ckit_062s4/cy8ckit_062s4_defconfig b/boards/infineon/cy8ckit_062s4/cy8ckit_062s4_defconfig similarity index 100% rename from boards/cypress/cy8ckit_062s4/cy8ckit_062s4_defconfig rename to boards/infineon/cy8ckit_062s4/cy8ckit_062s4_defconfig diff --git a/boards/cypress/cy8ckit_062s4/doc/img/cy8ckit_062s4.png b/boards/infineon/cy8ckit_062s4/doc/img/cy8ckit_062s4.png similarity index 100% rename from boards/cypress/cy8ckit_062s4/doc/img/cy8ckit_062s4.png rename to boards/infineon/cy8ckit_062s4/doc/img/cy8ckit_062s4.png diff --git a/boards/infineon/cy8ckit_062s4/doc/index.rst b/boards/infineon/cy8ckit_062s4/doc/index.rst new file mode 100644 index 0000000000000..1dfdb93bd307d --- /dev/null +++ b/boards/infineon/cy8ckit_062s4/doc/index.rst @@ -0,0 +1,115 @@ +.. _cy8ckit_062s4: + +[INFINEON PSoC 62S4 Pioneer Kit] +################################ + +Overview +******** +The PSOC 62S4 Pioneer kit has a CY8C62x4 MCU, which is an ultra-low-power PSoC device specifically designed for battery-operated analog +sensing applications. It includes a 150-MHz Arm® Cortex®-M4 CPU as the primary application processor, a 100-MHz Arm® Cortex®-M0+ CPU that +supports low-power operations, up to 256 KB Flash and 128 KB SRAM, programmable analog sensing, +CapSense™ touch-sensing, and programmable digital peripherals. + +The board features an onboard +programmer/debugger (KitProg3), a 512-Mbit Quad SPI NOR flash, a micro-B connector for USB device +interface, a thermistor, an ambient light sensor, a 5-segment CapSense™ slider, two CapSense™ buttons, two +user LEDs, and a push button. The board supports operating voltages from 1.8 V to 3.3 V for PSoC™ 6 MCU. + +.. figure::img/cy8ckit_062s4.png + :width: 800px + :align: center + :alt: Board Name + + Board Name (Credit: ) + +Hardware +******** + +`CY8CKIT 062S4 Pioneer Kit Website`_ +`CY8CKIT 062S4 Pioneer Kit Guide`_ +`CY8CKIT 062S4 Pioneer Kit Schematic`_ +`CY8CKIT 062S4 Pioneer Kit Technical Reference Manual`_ +`CY8CKIT 062S4 Pioneer Kit Datasheet`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=======================+ +| NVIC | on-chip | nested vectored | +| | | interrupt controller | ++-----------+------------+-----------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-----------------------+ +| PINCTRL | on-chip | pin control | ++-----------+------------+-----------------------+ +| UART | on-chip | serial port-polling; | ++-----------+------------+-----------------------+ + +The default configuration can be found in the Kconfig +:zephyr_file:`boards/infineon/cy8ckit_062s4/cy8ckit_062s4_defconfig`. + +Clock Configuration +=================== + ++-----------+------------+-----------------------+ +| Clock | Source | Output Frequency | ++===========+============+=======================+ +| FLL | IMO | 100.0 MHz | ++-----------+------------+-----------------------+ +| PLL | IMO | 48.0 MHz | ++-----------+------------+-----------------------+ +| CLK_HF0 | CLK_PATH0 | 100.0 MHz | ++-----------+------------+-----------------------+ + +Fetch Binary Blobs +================== + +.. code-block:: console + + west blobs fetch hal_infineon + + +Build and flash hello world sample +********************************** + + +.. code-block:: console + + cd zephyr/samples/hello_world + west build -p auto -b cy8ckit_062s4 --pristine + west flash + picocom /dev/ttyACM0 -b 115200 + +OpenOCD Installation +==================== + +To get the OpenOCD package, it is required that you + +1. Download the software ModusToolbox 3.1. https://softwaretools.infineon.com/tools/com.ifx.tb.tool.modustoolbox +2. Once downloaded add the path to access the Scripts folder provided by ModusToolbox + export PATH=$PATH:/path/to/ModusToolbox/tools_3.1/openocd/scripts +3. Add the OpenOCD executable file's path to west flash/debug. +4. Flash using: west flash --openocd path/to/infineon/openocd/bin/openocd +5. Debug using: west debug --openocd path/to/infineon/openocd/bin/openocd + +References +********** + +.. _CY8CKIT 062S4 Pioneer Kit Guide: + https://www.infineon.com/dgdl/Infineon-CY8CKIT_062S4_PSoC62S4_pioneer_kit_guide-UserManual-v01_00-EN.pdf?fileId=8ac78c8c7e7124d1017e962f98992207 + +.. _CY8CKIT 062S4 Pioneer Kit Website: + https://www.infineon.com/cms/en/product/evaluation-boards/cy8ckit-062s4/?redirId=VL1508&utm_medium=referral&utm_source=cypress&utm_campaign=202110_globe_en_all_integration-dev_kit + +.. _CY8CKIT 062S4 Pioneer Kit Schematic: + https://www.infineon.com/dgdl/Infineon-CY8CKIT-062S4_PSoC_62S4_Pioneer_Kit_Schematic-PCBDesignData-v01_00-EN.pdf?fileId=8ac78c8c7d710014017d7153484d2081 + +.. _CY8CKIT 062S4 Pioneer Kit Technical Reference Manual: + https://www.infineon.com/dgdl/Infineon-PSOC_6_MCU_CY8C61X4CY8C62X4_REGISTERS_TECHNICAL_REFERENCE_MANUAL_(TRM)_PSOC_61_PSOC_62_MCU-AdditionalTechnicalInformation-v03_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0fb34f0627a7 + +.. _CY8CKIT 062S4 Pioneer Kit Datasheet: + https://www.infineon.com/dgdl/Infineon-PSoC_6_MCU_CY8C62X4-DataSheet-v12_00-EN.pdf?fileId=8ac78c8c7ddc01d7017ddd026d585901 diff --git a/boards/cypress/cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w b/boards/infineon/cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w rename to boards/infineon/cy8cproto_062_4343w/Kconfig.cy8cproto_062_4343w diff --git a/boards/infineon/cy8cproto_062_4343w/Kconfig.defconfig b/boards/infineon/cy8cproto_062_4343w/Kconfig.defconfig new file mode 100644 index 0000000000000..5573b7f041773 --- /dev/null +++ b/boards/infineon/cy8cproto_062_4343w/Kconfig.defconfig @@ -0,0 +1,47 @@ +# CY8CPROTO-062-4343W PSoC™ 6 Wi-Fi BT Prototyping Kit configuration + +# Copyright (c) 2021 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_CY8CPROTO_062_4343W + +if WIFI || BT + +# Select AIROC part and module +choice AIROC_PART + default CYW4343W +endchoice + +choice CYW4343W_MODULE + default CYW4343W_MURATA_1DX +endchoice + +endif # WIFI || BT + +if WIFI + +config WIFI_AIROC + default y + +# Enable L2 Ethernet +config NET_L2_ETHERNET + default y + +endif # WIFI + +if BT + +# Select HCI components +config UART + bool + default y + +endif # BT + +# Heap Pool Size +config HEAP_MEM_POOL_ADD_SIZE_BOARD + int + default 15000 if WIFI + default 4096 + +endif # BOARD_CY8CPROTO_062_4343W diff --git a/boards/cypress/cy8cproto_062_4343w/board.cmake b/boards/infineon/cy8cproto_062_4343w/board.cmake similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/board.cmake rename to boards/infineon/cy8cproto_062_4343w/board.cmake diff --git a/boards/infineon/cy8cproto_062_4343w/board.yml b/boards/infineon/cy8cproto_062_4343w/board.yml new file mode 100644 index 0000000000000..f89df6ee65e02 --- /dev/null +++ b/boards/infineon/cy8cproto_062_4343w/board.yml @@ -0,0 +1,5 @@ +board: + name: cy8cproto_062_4343w + vendor: infineon + socs: + - name: cy8c624abzi_s2d44 diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w-common.dtsi diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w-pinctrl.dtsi diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.dts b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.dts similarity index 79% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.dts rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.dts index 726b1c9894e9b..b9e74ac685d0b 100644 --- a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.dts +++ b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.dts @@ -4,8 +4,8 @@ */ /dts-v1/; -#include -#include +#include +#include #include "cy8cproto_062_4343w-common.dtsi" #include "cy8cproto_062_4343w-pinctrl.dtsi" @@ -25,7 +25,7 @@ zephyr,flash = &flash0; zephyr,console = &uart5; zephyr,shell-uart = &uart5; - zephyr,bt_uart = &uart2; + zephyr,bt-hci = &bt_hci_uart; }; }; @@ -58,17 +58,22 @@ uart2: &scb2 { /* HW Flow control must be enabled for HCI H4 */ hw-flow-control; - bt-hci { - status = "okay"; - compatible = "infineon,cyw43xxx-bt-hci"; - bt-reg-on-gpios = <&gpio_prt3 4 (GPIO_ACTIVE_HIGH)>; - - /* Configuration UART speeds for firmware download (fw-download-speed) and - * HCI operation (hci-operation-speed). - * If hci-operation-speed or fw-download-speed are not defined in bt-hci{...} - * node, cyw43xx driver will use bus/current-speed as default speed. - */ - fw-download-speed = <3000000>; + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + + murata-1dx { + status = "okay"; + compatible = "infineon,cyw43xxx-bt-hci"; + bt-reg-on-gpios = <&gpio_prt3 4 (GPIO_ACTIVE_HIGH)>; + + /* Configuration UART speeds for firmware download (fw-download-speed) + * and HCI operation (hci-operation-speed). + * If hci-operation-speed or fw-download-speed are not defined in + * bt-hci{...} node, cyw43xx driver will use bus/current-speed as + * default speed. + */ + fw-download-speed = <3000000>; + }; }; }; diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml similarity index 87% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml index 8300a160c5a98..113c686db0371 100644 --- a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml +++ b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w.yaml @@ -22,4 +22,7 @@ supported: - gpio - uart - i2c -vendor: cypress + - thermistor + - uart + - timer +vendor: infineon diff --git a/boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig b/boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig rename to boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig diff --git a/boards/cypress/cy8cproto_062_4343w/doc/img/board.jpg b/boards/infineon/cy8cproto_062_4343w/doc/img/board.jpg similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/doc/img/board.jpg rename to boards/infineon/cy8cproto_062_4343w/doc/img/board.jpg diff --git a/boards/infineon/cy8cproto_062_4343w/doc/index.rst b/boards/infineon/cy8cproto_062_4343w/doc/index.rst new file mode 100644 index 0000000000000..a5934089f0b31 --- /dev/null +++ b/boards/infineon/cy8cproto_062_4343w/doc/index.rst @@ -0,0 +1,184 @@ +.. _cy8cproto_062_4343w: + +INFINEON CY8CPROTO-062-4343W +############################ + +Overview +******** + +The CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Prototyping Kit is a low-cost hardware +platform that enables design and debug of PSoC 6 MCUs. It comes with a Murata +LBEE5KL1DX module, based on the CYW4343W combo device, industry-leading CAPSENSE +for touch buttons and slider, on-board debugger/programmer with KitProg3, microSD +card interface, 512-Mb Quad-SPI NOR flash, PDM-PCM microphone, and a thermistor. + +This kit is designed with a snap-away form-factor, allowing the user to separate +the different components and features that come with this kit and use independently. +In addition, support for Digilent's Pmod interface is also provided with this kit. + +.. image:: img/board.jpg + :align: center + :alt: CY8CPROTO-062-4343W + +Hardware +******** + +For more information about the PSoC 62 MCU SoC and CY8CPROTO-062-4343W board: + +- `PSoC 62 MCU SoC Website`_ +- `PSoC 62 MCU Datasheet`_ +- `PSoC 62 MCU Architecture Reference Manual`_ +- `PSoC 62 MCU Register Reference Manual`_ +- `CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Website`_ +- `CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT User Guide`_ +- `CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Schematics`_ + +Kit Features: +============= + +- Support of up to 2MB Flash and 1MB SRAM +- Dedicated SDHC to interface with WICED wireless devices. +- Delivers dual-cores, with a 150-MHz Arm Cortex-M4 as the primary + application processor and a 100-MHz Arm Cortex-M0+ as the secondary + processor for low-power operations. +- Supports Full-Speed USB, capacitive-sensing with CAPSENSE, a PDM-PCM + digital microphone interface, a Quad-SPI interface, 13 serial communication + blocks, 7 programmable analog blocks, and 56 programmable digital blocks. + +Kit Contents: +============= + +- PSoC 6 Wi-Fi BT Prototyping Board +- USB Type-A to Micro-B cable +- Quick Start Guide + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=======================+ +| NVIC | on-chip | nested vectored | +| | | interrupt controller | ++-----------+------------+-----------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-----------------------+ +| GPIO | on-chip | GPIO | ++-----------+------------+-----------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-----------------------+ + + +The default configuration can be found in the Kconfig + +:zephyr_file:`boards/infineon/cy8cproto_062_4343w/cy8cproto_062_4343w_defconfig` + + +System Clock +============ + +The PSoC 62 MCU SoC is configured to use the internal IMO+FLL as a source for +the system clock. CM0+ works at 50MHz, CM4 - at 100MHz. Other sources for the +system clock are provided in the SOC, depending on your system requirements. + + +Fetch Binary Blobs +****************** + +cy8cproto_062_4343w board optionally uses binary blobs for features +(e.g WIFI/Bluetooth chip firmware, CM0p prebuilt images, etc). + +To fetch Binary Blobs: + +.. code-block:: console + + west blobs fetch hal_infineon + + +Build blinking led sample +************************* + +Here is an example for the :zephyr:code-sample:`blinky` application. + +.. code-block:: console + + cd zephyr + west build -p auto -b cy8cproto_062_4343w samples/basic/blink + +OpenOCD Installation +==================== + +To get the OpenOCD package, it is required that you + +1. Download the software ModusToolbox 3.1. https://softwaretools.infineon.com/tools/com.ifx.tb.tool.modustoolbox +2. Once downloaded add the path to access the Scripts folder provided by ModusToolbox + export PATH=$PATH:/path/to/ModusToolbox/tools_3.1/openocd/scripts +3. Add the OpenOCD executable file's path to west flash/debug. +4. Flash using: west flash --openocd path/to/infineon/openocd/bin/openocd +5. Debug using: west debug --openocd path/to/infineon/openocd/bin/openocd + + +Programming and Debugging +************************* + +The CY8CPROTO-062-4343W includes an onboard programmer/debugger (KitProg2) with +mass storage programming to provide debugging, flash programming, and serial +communication over USB. Flash and debug commands must be pointed to the Cypress +OpenOCD you downloaded above. + +On Windows: + +.. code-block:: console + + west flash --openocd path/to/infineon/openocd/bin/openocd.exe + west debug --openocd path/to/infineon/openocd/bin/openocd.exe + +On Linux: + +.. code-block:: console + + west flash --openocd path/to/infineon/openocd/bin/openocd + west debug --openocd path/to/infineon/openocd/bin/openocd + +Once the gdb console starts after executing the west debug command, you may +now set breakpoints and perform other standard GDB debugging on the PSoC 6 CM4 core. + +Errata +====== + ++------------------------------------------------+----------------------------------------+ +| Problem | Solution | ++================================================+========================================+ +| The GPIO_INT_TRIG_BOTH interrupt is not raised | This will be fixed in a future release.| +| when the associated GPIO is asserted. | | ++------------------------------------------------+----------------------------------------+ +| GDB experiences a timeout error connecting to | This will be fixed in a future release.| +| a server instance started by west debugserver. | | ++------------------------------------------------+----------------------------------------+ + +.. _PSoC 62 MCU SoC Website: + https://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 + +.. _PSoC 62 MCU Datasheet: + https://www.cypress.com/documentation/datasheets/psoc-6-mcu-psoc-62-datasheet-programmable-system-chip-psoc-preliminary + +.. _PSoC 62 MCU Architecture Reference Manual: + https://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-architecture-technical-reference-manual + +.. _PSoC 62 MCU Register Reference Manual: + https://www.cypress.com/documentation/technical-reference-manuals/psoc-6-mcu-psoc-62-register-technical-reference-manual-trm + +.. _CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Website: + https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-062-4343w/ + +.. _CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT User Guide: + https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-062-4343w/#!?fileId=8ac78c8c7d0d8da4017d0f0118571844 + +.. _CY8CPROTO-062-4343W PSoC 6 Wi-Fi BT Schematics: + https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-062-4343w/#!?fileId=8ac78c8c7d0d8da4017d0f01126b183f + +.. _Infineon OpenOCD: + https://github.com/infineon/openocd/releases/tag/release-v4.3.0 diff --git a/boards/cypress/cy8cproto_062_4343w/support/openocd.cfg b/boards/infineon/cy8cproto_062_4343w/support/openocd.cfg similarity index 100% rename from boards/cypress/cy8cproto_062_4343w/support/openocd.cfg rename to boards/infineon/cy8cproto_062_4343w/support/openocd.cfg diff --git a/boards/cypress/cy8cproto_063_ble/Kconfig.cy8cproto_063_ble b/boards/infineon/cy8cproto_063_ble/Kconfig.cy8cproto_063_ble similarity index 100% rename from boards/cypress/cy8cproto_063_ble/Kconfig.cy8cproto_063_ble rename to boards/infineon/cy8cproto_063_ble/Kconfig.cy8cproto_063_ble diff --git a/boards/infineon/cy8cproto_063_ble/Kconfig.defconfig b/boards/infineon/cy8cproto_063_ble/Kconfig.defconfig new file mode 100644 index 0000000000000..4123455e9f93b --- /dev/null +++ b/boards/infineon/cy8cproto_063_ble/Kconfig.defconfig @@ -0,0 +1,11 @@ +# CY8CPROTO-063-BLE PSoC™ 6 BLE Prototyping Kit + +# Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_CY8CPROTO_063_BLE + +# No defaults to change for now + +endif # BOARD_CY8CPROTO_063_BLE diff --git a/boards/cypress/cy8cproto_063_ble/board.cmake b/boards/infineon/cy8cproto_063_ble/board.cmake similarity index 100% rename from boards/cypress/cy8cproto_063_ble/board.cmake rename to boards/infineon/cy8cproto_063_ble/board.cmake diff --git a/boards/infineon/cy8cproto_063_ble/board.yml b/boards/infineon/cy8cproto_063_ble/board.yml new file mode 100644 index 0000000000000..6ef5bd8e9d7b8 --- /dev/null +++ b/boards/infineon/cy8cproto_063_ble/board.yml @@ -0,0 +1,5 @@ +board: + name: cy8cproto_063_ble + vendor: infineon + socs: + - name: cyble_416045_02 diff --git a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble-pinctrl.dtsi b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble-pinctrl.dtsi similarity index 100% rename from boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble-pinctrl.dtsi rename to boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble-pinctrl.dtsi diff --git a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.dts b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.dts similarity index 94% rename from boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.dts rename to boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.dts index e918f547bd26f..5516895fddd8b 100644 --- a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.dts +++ b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.dts @@ -6,8 +6,8 @@ /dts-v1/; -#include -#include +#include +#include #include "cy8cproto_063_ble-pinctrl.dtsi" #include @@ -27,6 +27,7 @@ zephyr,flash = &flash0; zephyr,console = &uart5; zephyr,shell-uart = &uart5; + zephyr,bt-hci = &bluetooth; }; /delete-node/ cpu@0; diff --git a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.yaml b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.yaml similarity index 92% rename from boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.yaml rename to boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.yaml index 1aaef3040d38e..db4f1ec95b001 100644 --- a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble.yaml +++ b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble.yaml @@ -19,4 +19,5 @@ supported: - i2c - watchdog - spi -vendor: cypress + - timer +vendor: infineon diff --git a/boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble_defconfig b/boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble_defconfig similarity index 100% rename from boards/cypress/cy8cproto_063_ble/cy8cproto_063_ble_defconfig rename to boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble_defconfig diff --git a/boards/cypress/cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg b/boards/infineon/cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg similarity index 100% rename from boards/cypress/cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg rename to boards/infineon/cy8cproto_063_ble/doc/img/cy8cproto-063-ble.jpg diff --git a/boards/infineon/cy8cproto_063_ble/doc/index.rst b/boards/infineon/cy8cproto_063_ble/doc/index.rst new file mode 100644 index 0000000000000..86cc9cd5c1595 --- /dev/null +++ b/boards/infineon/cy8cproto_063_ble/doc/index.rst @@ -0,0 +1,144 @@ +.. _cy8cproto_063_ble: + +INFINEON CY8CPROTO-063-BLE +########################### + +Overview +******** + +The PSoC 6 BLE Proto Kit (CY8CPROTO-063-BLE) is a hardware platform that +enables design and debug of the Cypress PSoC 63 BLE MCU. + +.. image:: img/cy8cproto-063-ble.jpg + :align: center + :alt: CY8CPROTO-063-BLE + +Hardware +******** + +For more information about the PSoC 63 BLE MCU SoC and CY8CPROTO-063-BLE board: + +- `PSoC 63 BLE MCU SoC Website`_ +- `PSoC 63 BLE MCU Datasheet`_ +- `PSoC 63 BLE MCU Architecture Reference Manual`_ +- `PSoC 63 BLE MCU Register Reference Manual`_ +- `CY8CPROTO-063-BLE Website`_ +- `CY8CPROTO-063-BLE User Guide`_ +- `CY8CPROTO-063-BLE Schematics`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=======================+ +| NVIC | on-chip | nested vectored | +| | | interrupt controller | ++-----------+------------+-----------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-----------------------+ +| PINCTRL | on-chip | pin control | ++-----------+------------+-----------------------+ +| SPI | on-chip | spi | ++-----------+------------+-----------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-----------------------+ +| I2C | on-chip | I2C | ++-----------+------------+-----------------------+ +| PWM | on-chip | PWM | ++-----------+------------+-----------------------+ +| Counter | on-chip | Counter | ++-----------+------------+-----------------------+ +| Bluetooth | on-chip | Bluetooth | ++-----------+------------+-----------------------+ + + +The default configurations can be found in +:zephyr_file:`boards/infineon/cy8cproto_063_ble/cy8cproto_063_ble_defconfig` + +System Clock +============ + +The PSoC 63 BLE MCU SoC is configured to use the internal IMO+FLL as a source for +the system clock. CM0+ works at 50MHz, CM4 - at 100MHz. Other sources for the +system clock are provided in the SOC, depending on your system requirements. + + +OpenOCD Installation +==================== + +To get the OpenOCD package, it is required that you + +1. Download the software ModusToolbox 3.1. https://softwaretools.infineon.com/tools/com.ifx.tb.tool.modustoolbox +2. Once downloaded add the path to access the Scripts folder provided by ModusToolbox + export PATH=$PATH:/path/to/ModusToolbox/tools_3.1/openocd/scripts +3. Add the OpenOCD executable file's path to west flash/debug. +4. Flash using: west flash --openocd path/to/infineon/openocd/bin/openocd +5. Debug using: west debug --openocd path/to/infineon/openocd/bin/openocd + + +Fetch Binary Blobs +****************** + +cy8cproto_063_ble board requires fetch binary files +(e.g Bluetooth controller firmware, CM0p prebuilt images, etc). + +To fetch Binary Blobs: + +.. code-block:: console + + west blobs fetch hal_infineon + +Programming and Debugging +************************* + +The CY8CPROTO-063-BLE includes an onboard programmer/debugger (KitProg3) with +mass storage programming to provide debugging, flash programming, and serial +communication over USB. Flash and debug commands must be pointed to the Cypress +OpenOCD you downloaded above. + +On Windows: + +.. code-block:: console + + west flash --openocd path/to/infineon/openocd/bin/openocd.exe + west debug --openocd path/to/infineon/openocd/bin/openocd.exe + +On Linux: + +.. code-block:: console + + west flash --openocd path/to/infineon/openocd/bin/openocd + west debug --openocd path/to/infineon/openocd/bin/openocd + +References +********** + +.. _PSoC 63 BLE MCU SoC Website: + https://www.cypress.com/products/32-bit-arm-cortex-m4-psoc-6 + +.. _PSoC 63 BLE MCU Datasheet: + https://www.infineon.com/dgdl/Infineon-PSoC_6_MCU_PSoC_63_with_BLE_Datasheet_Programmable_System-on-Chip_(PSoC)-DataSheet-v16_00-EN.pdf?fileId=8ac78c8c7d0d8da4017d0ee4efe46c37&utm_source=cypress&utm_medium=referral&utm_campaign=202110_globe_en_all_integration-files + +.. _PSoC 63 BLE MCU Architecture Reference Manual: + https://documentation.infineon.com/html/psoc6/zrs1651212645947.html + +.. _PSoC 63 BLE MCU Register Reference Manual: + https://documentation.infineon.com/html/psoc6/bnm1651211483724.html + +.. _CY8CPROTO-063-BLE Website: + https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-063-ble/ + +.. _CY8CPROTO-063-BLE User Guide: + https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-063-ble/#!?fileId=8ac78c8c7d0d8da4017d0f00d7eb1812 + +.. _CY8CPROTO-063-BLE Schematics: + https://www.infineon.com/cms/en/product/evaluation-boards/cy8cproto-063-ble/#!?fileId=8ac78c8c7d0d8da4017d0f00ea3c1821 + +.. _Infineon OpenOCD: + https://github.com/infineon/openocd/releases/tag/release-v4.3.0 diff --git a/boards/cypress/cy8cproto_063_ble/support/openocd.cfg b/boards/infineon/cy8cproto_063_ble/support/openocd.cfg similarity index 100% rename from boards/cypress/cy8cproto_063_ble/support/openocd.cfg rename to boards/infineon/cy8cproto_063_ble/support/openocd.cfg diff --git a/boards/infineon/cyw920829m2evk_02/Kconfig.cyw920829m2evk_02 b/boards/infineon/cyw920829m2evk_02/Kconfig.cyw920829m2evk_02 new file mode 100644 index 0000000000000..1565606bbbe28 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/Kconfig.cyw920829m2evk_02 @@ -0,0 +1,7 @@ +# The Infineon AIROC™ CYW20829 Bluetooth® LE evaluation kit (CYW92089M2EVK-02) + +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_CYW920829M2EVK_02 + select SOC_CYW20829B0LKML diff --git a/boards/infineon/cyw920829m2evk_02/Kconfig.defconfig b/boards/infineon/cyw920829m2evk_02/Kconfig.defconfig new file mode 100644 index 0000000000000..645567a40c7ef --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/Kconfig.defconfig @@ -0,0 +1,13 @@ +# The Infineon AIROC™ CYW20829 Bluetooth® LE evaluation kit (CYW92089M2EVK-02) + +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +choice AIROC_PART + default CYW20829 if BT +endchoice + +# Heap Pool Size +config HEAP_MEM_POOL_ADD_SIZE_BOARD + int + default 10096 diff --git a/boards/infineon/cyw920829m2evk_02/board.cmake b/boards/infineon/cyw920829m2evk_02/board.cmake new file mode 100644 index 0000000000000..9fa085b7448b3 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/board.cmake @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/infineon/cyw920829m2evk_02/board.yml b/boards/infineon/cyw920829m2evk_02/board.yml new file mode 100644 index 0000000000000..e25e3922b5359 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/board.yml @@ -0,0 +1,5 @@ +board: + name: cyw920829m2evk_02 + vendor: infineon + socs: + - name: cyw20829b0lkml diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-common.dtsi b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-common.dtsi new file mode 100644 index 0000000000000..d795ccce728be --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-common.dtsi @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + aliases { + led0 = &user_led0; + led1 = &user_led1; + sw0 = &user_bt0; + sw1 = &user_bt1; + }; + + leds { + compatible = "gpio-leds"; + user_led0: led_0 { + label = "LED_0"; + gpios = <&gpio_prt1 1 GPIO_ACTIVE_LOW>; + }; + + user_led1: led_1 { + label = "LED_1"; + gpios = <&gpio_prt5 2 GPIO_ACTIVE_LOW>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + + user_bt0: user_btn0 { + label = "SW_1"; + gpios = <&gpio_prt0 5 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + }; + + user_bt1: user_btn1 { + label = "SW_2"; + gpios = <&gpio_prt1 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + zephyr,code = ; + }; + }; +}; + +&gpio_prt0 { + status = "okay"; +}; + +&gpio_prt1 { + status = "okay"; +}; + +&gpio_prt3 { + status = "okay"; +}; + +&gpio_prt5 { + status = "okay"; +}; diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-pinctrl.dtsi b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-pinctrl.dtsi new file mode 100644 index 0000000000000..fb6b4571ff5d0 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02-pinctrl.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation. + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Configure pin control bias mode for uart2 pins */ +&p3_3_scb2_uart_tx { + drive-push-pull; +}; + +&p3_2_scb2_uart_rx { + input-enable; +}; diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts new file mode 100644 index 0000000000000..334704b98e038 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.dts @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation. + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "cyw920829m2evk_02-common.dtsi" +#include "cyw920829m2evk_02-pinctrl.dtsi" + +/ { + model = "The Infineon AIROC™ CYW20829 Bluetooth® LE evaluation kit (CYW92089M2EVK-02)"; + compatible = "infineon,cyw920829m2evk_02", "infineon,CYW20829"; + + aliases { + watchdog0 = &watchdog0; + }; + + chosen { + zephyr,sram = &sram0; + zephyr,flash = &app_region; + zephyr,console = &uart2; + zephyr,shell-uart = &uart2; + zephyr,bt-hci = &bluetooth; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; + +uart2: &scb2 { + compatible = "infineon,cat1-uart"; + status = "okay"; + current-speed = <115200>; + + pinctrl-0 = <&p3_3_scb2_uart_tx &p3_2_scb2_uart_rx>; + pinctrl-names = "default"; +}; + +&fll0 { + status = "okay"; +}; + +&path_mux0 { + status = "okay"; +}; + +&path_mux1 { + status = "okay"; +}; + +&path_mux2 { + status = "okay"; +}; + +&path_mux3 { + status = "okay"; +}; + +&clk_hf0 { + status = "okay"; + clocks = <&fll0>; +}; + +&clk_hf1 { + status = "okay"; +}; + +&clk_hf2 { + status = "okay"; +}; + +&clk_hf3 { + status = "okay"; +}; + +&watchdog0 { + status = "okay"; +}; + +&bluetooth { + status = "okay"; +}; + +/ { + flash0: flash@60000000 { + compatible = "soc-nv-flash"; + reg = <0x60000000 DT_SIZE_K(512)>; + write-block-size = <16>; + erase-block-size = <256>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + toc2_region: flash@60000000 { + compatible = "zephyr,memory-region", "soc-nv-flash"; + zephyr,memory-region = "APP_HEADER_FLASH"; + reg = <0x60000000 0x50>; + }; + bootstrap_region: flash@60000050 { + compatible = "zephyr,memory-region", "soc-nv-flash"; + zephyr,memory-region = "BOOTSTRAP_FLASH"; + reg = <0x60000050 DT_SIZE_K(12)>; + }; + app_region: flash@60003050 { + compatible = "soc-nv-flash"; + reg = <0x60003050 0x6CFB0>; /* 435kb */ + }; + storage_partition: flash@60070000 { + compatible = "soc-nv-flash"; + reg = <0x60070000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml new file mode 100644 index 0000000000000..a02da7d193780 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02.yaml @@ -0,0 +1,24 @@ +# +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: cyw920829m2evk_02 +name: The Infineon AIROC™ CYW20829 Bluetooth® LE evaluation kit (CYW92089M2EVK-02) +type: mcu +arch: arm +ram: 1024 +flash: 2048 +toolchain: + - zephyr + - gnuarmemb +supported: + - gpio + - uart + - clock_control + - bluetooth + - watchdog + - spi + - i2c + +vendor: infineon diff --git a/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02_defconfig b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02_defconfig new file mode 100644 index 0000000000000..a59cfbf692a1d --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02_defconfig @@ -0,0 +1,31 @@ +# +# Copyright (c) 2024 Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 +# + +# General configuration +CONFIG_CORTEX_M_SYSTICK=y +CONFIG_BUILD_OUTPUT_HEX=y +CONFIG_BUILD_OUTPUT_BIN=y + +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable UART driver +CONFIG_SERIAL=y + +# Enable pin controller +CONFIG_PINCTRL=y + +# Enable GPIO driver +CONFIG_GPIO=y + +# Enable clock controller +CONFIG_CLOCK_CONTROL=y + +# Main Stack Size +CONFIG_MAIN_STACK_SIZE=2048 diff --git a/boards/infineon/cyw920829m2evk_02/doc/img/cyw920829m2evk_02.webp b/boards/infineon/cyw920829m2evk_02/doc/img/cyw920829m2evk_02.webp new file mode 100644 index 0000000000000..130fc8dac6575 Binary files /dev/null and b/boards/infineon/cyw920829m2evk_02/doc/img/cyw920829m2evk_02.webp differ diff --git a/boards/infineon/cyw920829m2evk_02/doc/index.rst b/boards/infineon/cyw920829m2evk_02/doc/index.rst new file mode 100644 index 0000000000000..fbb6e02439261 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/doc/index.rst @@ -0,0 +1,136 @@ +.. _cyw920829m2evk_02: + +INFINEON CYW920829M2EVK-02 +############################ + +Overview +******** + +The AIROC™ CYW20829 Bluetooth® LE MCU Evaluation Kit (CYW920829M2EVK-02) with its included on-board peripherals enables evaluation, prototyping, and development of a wide array of Bluetooth® Low Energy applications, all on Infineon's low power, high performance AIROC™ CYW20829. The AIROC™ CYW20829's robust RF performance and 10 dBm TX output power without an external power amplifier (PA). This provides enough link budget for the entire spectrum of Bluetooth® LE use cases including industrial IoT applications, smart home, asset tracking, beacons and sensors, and medical devices. + +The system features Dual Arm® Cortex® - M33s for powering the MCU and Bluetooth subsystem with programmable and reconfigurable analog and digital blocks. In addition, on the kit, there is a suite of on-board peripherals including six-axis inertial measurement unit (IMU), thermistor, analog mic, user programmable buttons (2), LEDs (2), and RGB LED. There is also extensive GPIO support with extended headers and Arduino Uno R3 compatibility for third-party shields. + +.. image:: img/cyw920829m2evk_02.webp + :align: center + :alt: CYW920829M2EVK_02 + +Hardware +******** + +For more information about the CYW20829 SoC and CYW920829M2EVK-02 board: + +- `CYW920829M2EVK-02 Website`_ +- `CYW920829M2EVK-02 BT User Guide`_ + + +Kit Features: +============= + +- AIROC™ CYW20829 Bluetooth® LE MCU in 56 pin QFN package +- Arduino compatible headers for hardware expansion +- On-board sensors - 6-axis IMU, Thermistor, Infineon analog microphone, and Infineon digital microphone +- User switches, RGB LED and user LEDs +- USB connector for power, programming and USB-UART bridge + +Kit Contents: +============= + +- CYW20829 evaluation board (CYW9BTM2BASE3+CYW920829M2IPA2) +- USB Type-A to Micro-B cable +- Six jumper wires (five inches each) +- Quick start guide + + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=======================+ +| NVIC | on-chip | nested vectored | +| | | interrupt controller | ++-----------+------------+-----------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-----------------------+ +| GPIO | on-chip | GPIO | ++-----------+------------+-----------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-----------------------+ + + +The default configuration can be found in the Kconfig + +:zephyr_file:`boards/infineon/cyw920829m2evk_02/cyw920829m2evk_02_defconfig` + +System Clock +============ + +The AIROC™ CYW20829 Bluetooth® MCU SoC is configured to use the internal IMO+FLL as a source for +the system clock. Other sources for the system clock are provided in the SOC, depending on your +system requirements. + +Fetch Binary Blobs +****************** + +cyw920829m2evk_02 board requires fetch binary files (e.g Bluetooth controller firmware). + +To fetch Binary Blobs: + +.. code-block:: console + + west blobs fetch hal_infineon + +Build blinking led sample +************************* + +Here is an example for the :zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: cyw920829m2evk_02 + :goals: build flash + +OpenOCD Installation +==================== + +To get the OpenOCD package, it is required that you + +1. Download and install the `ModusToolbox`_ software. +2. After the installation, add the directory containing the OpenOCD scripts to your environment's PATH variable. + + +Programming and Debugging +************************* + +The CYW920829M2EVK-02 includes an onboard programmer/debugger (KitProg3) to provide debugging, flash programming, and serial communication over USB. Flash and debug commands must be pointed to the Cypress OpenOCD you downloaded above. + +On Windows: + +.. code-block:: shell + + west flash --openocd path/to/infineon/openocd/bin/openocd.exe + west debug --openocd path/to/infineon/openocd/bin/openocd.exe + +On Linux: + +.. code-block:: shell + + west flash --openocd path/to/infineon/openocd/bin/openocd + west debug --openocd path/to/infineon/openocd/bin/openocd + +Once the gdb console starts after executing the west debug command, you may now set breakpoints and perform other standard GDB debugging on the CYW20829 CM33 core. + +.. _CYW920829M2EVK-02 Website: + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-bluetooth-le-bluetooth-multiprotocol/airoc-bluetooth-le/cyw20829/ + +.. _CYW920829M2EVK-02 BT User Guide: + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-bluetooth-le-bluetooth-multiprotocol/airoc-bluetooth-le/cyw20829/#!?fileId=8ac78c8c8929aa4d018a16f726c46b26 + +.. _ModusToolbox: + https://softwaretools.infineon.com/tools/com.ifx.tb.tool.modustoolbox + +.. _Infineon OpenOCD: + https://github.com/infineon/openocd/releases/tag/release-v4.3.0 diff --git a/boards/infineon/cyw920829m2evk_02/support/openocd.cfg b/boards/infineon/cyw920829m2evk_02/support/openocd.cfg new file mode 100644 index 0000000000000..fe70fb383a8a3 --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/support/openocd.cfg @@ -0,0 +1,14 @@ +# +# Copyright (c) 2018 Linaro Limited. +# +# SPDX-License-Identifier: Apache-2.0 + +source [find interface/kitprog3.cfg] + +transport select swd + +source [find target/cyw20829.cfg] + +if { [info exists _ZEPHYR_BOARD_SERIAL] } { + adapter serial $_ZEPHYR_BOARD_SERIAL +} diff --git a/boards/infineon/cyw920829m2evk_02/support/qspi_config.cfg b/boards/infineon/cyw920829m2evk_02/support/qspi_config.cfg new file mode 100644 index 0000000000000..f702d5409dc0b --- /dev/null +++ b/boards/infineon/cyw920829m2evk_02/support/qspi_config.cfg @@ -0,0 +1,29 @@ +################################################################################ +# File Name: qspi_config.cfg +# +# Description: +# This file contains a SMIF Bank layout for use with OpenOCD. +# This file was automatically generated and should not be modified. +# QSPI Configurator: 4.22.0.1756 +# +################################################################################ +# Copyright 2024 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +################################################################################ + +set SMIF_BANKS { + 0 {addr 0x60000000 size 0x100000 psize 0x0000100 esize 0x0001000} +} diff --git a/boards/infineon/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi b/boards/infineon/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi index 936733ea02a83..b8bb7b42a8c0c 100644 --- a/boards/infineon/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi +++ b/boards/infineon/xmc45_relax_kit/xmc45_relax_kit-pinctrl.dtsi @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include &uart_tx_p0_1_u1c1 { drive-strength = "strong-soft-edge"; diff --git a/boards/infineon/xmc45_relax_kit/xmc45_relax_kit.dts b/boards/infineon/xmc45_relax_kit/xmc45_relax_kit.dts index 6b1519a455383..feb0a8e5aba64 100644 --- a/boards/infineon/xmc45_relax_kit/xmc45_relax_kit.dts +++ b/boards/infineon/xmc45_relax_kit/xmc45_relax_kit.dts @@ -8,8 +8,8 @@ /dts-v1/; -#include -#include +#include +#include #include #include "xmc45_relax_kit-pinctrl.dtsi" diff --git a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi index e6688a7ebb247..75b35c388b77a 100644 --- a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi +++ b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit-pinctrl.dtsi @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include &uart_tx_p1_5_u0c0 { drive-strength = "strong-soft-edge"; diff --git a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts index df37b32e3c781..ec8879bcb4008 100644 --- a/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts +++ b/boards/infineon/xmc47_relax_kit/xmc47_relax_kit.dts @@ -7,8 +7,8 @@ /dts-v1/; -#include -#include +#include +#include #include #include "xmc47_relax_kit-pinctrl.dtsi" #include "arduino_r3_connector.dtsi" @@ -207,7 +207,6 @@ &can_node1 { status = "okay"; - bus-speed = <125000>; input-src = "RXDC"; pinctrl-0 = <&can_tx_p1_12_node1 &can_rx_p1_13_node1>; pinctrl-names = "default"; diff --git a/boards/intel/adl/Kconfig.defconfig b/boards/intel/adl/Kconfig.defconfig index 518f0c01ee2dc..3a6bcaf9ce02a 100644 --- a/boards/intel/adl/Kconfig.defconfig +++ b/boards/intel/adl/Kconfig.defconfig @@ -16,6 +16,8 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/boards/intel/adsp/Kconfig.intel_adsp b/boards/intel/adsp/Kconfig.intel_adsp index 2e4c98447203b..f5a81c6dfcc63 100644 --- a/boards/intel/adsp/Kconfig.intel_adsp +++ b/boards/intel/adsp/Kconfig.intel_adsp @@ -6,3 +6,4 @@ config BOARD_INTEL_ADSP select SOC_INTEL_CAVS_V25 if BOARD_INTEL_ADSP_CAVS25_TGPH select SOC_INTEL_ACE15_MTPM if BOARD_INTEL_ADSP_ACE15_MTPM select SOC_INTEL_ACE20_LNL if BOARD_INTEL_ADSP_ACE20_LNL + select SOC_INTEL_ACE30_PTL if BOARD_INTEL_ADSP_ACE30_PTL diff --git a/boards/intel/adsp/board.cmake b/boards/intel/adsp/board.cmake index bcdfc3286467c..584474544bf2d 100644 --- a/boards/intel/adsp/board.cmake +++ b/boards/intel/adsp/board.cmake @@ -39,4 +39,12 @@ elseif(CONFIG_BOARD_INTEL_ADSP_ACE20_LNL) set(RIMAGE_SIGN_KEY "otc_private_key_3k.pem" CACHE STRING "default in ace20_lnl/board.cmake") +elseif(CONFIG_BOARD_INTEL_ADSP_ACE30_PTL) + + board_set_rimage_target(ptl) + + set(RIMAGE_SIGN_KEY "otc_private_key.pem" CACHE STRING "default rimage key") + + board_finalize_runner_args(intel_adsp) + endif() diff --git a/boards/intel/adsp/board.yml b/boards/intel/adsp/board.yml index 9295ae0c3eb2f..8e35014dd66f9 100644 --- a/boards/intel/adsp/board.yml +++ b/boards/intel/adsp/board.yml @@ -7,3 +7,4 @@ boards: - name: 'tgph' - name: ace15_mtpm - name: ace20_lnl + - name: ace30_ptl diff --git a/boards/intel/adsp/intel_adsp_ace30_ptl.dts b/boards/intel/adsp/intel_adsp_ace30_ptl.dts new file mode 100644 index 0000000000000..9e25712bc2c3e --- /dev/null +++ b/boards/intel/adsp/intel_adsp_ace30_ptl.dts @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + model = "intel_adsp_ace30_ptl"; + compatible = "intel"; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &mem_window3; + }; +}; diff --git a/boards/intel/adsp/intel_adsp_ace30_ptl.yaml b/boards/intel/adsp/intel_adsp_ace30_ptl.yaml new file mode 100644 index 0000000000000..bdfe837bd082f --- /dev/null +++ b/boards/intel/adsp/intel_adsp_ace30_ptl.yaml @@ -0,0 +1,10 @@ +identifier: intel_adsp/ace30_ptl +name: ACE 3.0 Panther Lake Audio DSP +type: mcu +arch: xtensa +toolchain: + - xt-clang +testing: + ignore_tags: + - net + - bluetooth diff --git a/boards/intel/adsp/intel_adsp_ace30_ptl_defconfig b/boards/intel/adsp/intel_adsp_ace30_ptl_defconfig new file mode 100644 index 0000000000000..913d2a8c3e3a9 --- /dev/null +++ b/boards/intel/adsp/intel_adsp_ace30_ptl_defconfig @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=4096 + +CONFIG_GEN_ISR_TABLES=y +CONFIG_GEN_IRQ_VECTOR_TABLE=n + +CONFIG_BUILD_OUTPUT_BIN=n + +CONFIG_DAI_SSP_HAS_POWER_CONTROL=y + +CONFIG_DCACHE_LINE_SIZE=64 diff --git a/boards/intel/ehl/Kconfig.defconfig b/boards/intel/ehl/Kconfig.defconfig index 9e7dcf48a0458..8b8c89800dab2 100644 --- a/boards/intel/ehl/Kconfig.defconfig +++ b/boards/intel/ehl/Kconfig.defconfig @@ -27,6 +27,8 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/boards/intel/ish/Kconfig.defconfig b/boards/intel/ish/Kconfig.defconfig index fdedc70fd29b5..6112d43c0499e 100644 --- a/boards/intel/ish/Kconfig.defconfig +++ b/boards/intel/ish/Kconfig.defconfig @@ -9,4 +9,5 @@ config TEST_EXTRA_STACK_SIZE endif # TEST config SYS_CLOCK_TICKS_PER_SEC - default 2048 if HPET_TIMER # HPET is 32768 HZ + default 2048 if HPET_TIMER # HPET timer's frequency is 32768 HZ + default 2000 if APIC_TIMER_TSC # APIC timer's frequency is 19.2 MHZ or 100 MHZ diff --git a/boards/intel/rpl/Kconfig.defconfig b/boards/intel/rpl/Kconfig.defconfig index ca8a77426881b..4eb5d8c3126c7 100644 --- a/boards/intel/rpl/Kconfig.defconfig +++ b/boards/intel/rpl/Kconfig.defconfig @@ -17,6 +17,8 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/boards/intel/socfpga_std/cyclonev_socdk/cyclonev_socdk.dts b/boards/intel/socfpga_std/cyclonev_socdk/cyclonev_socdk.dts index 5218c62f2c7bd..a45c0768273ec 100644 --- a/boards/intel/socfpga_std/cyclonev_socdk/cyclonev_socdk.dts +++ b/boards/intel/socfpga_std/cyclonev_socdk/cyclonev_socdk.dts @@ -63,7 +63,7 @@ status = "okay"; eeprom: eeprom@51 { - compatible = "atmel,at24"; + compatible = "microchip,at24lc32a", "atmel,at24"; status = "okay"; reg = <0x51>; size = <4096>; diff --git a/boards/ite/it82xx2_evb/it82xx2_evb.dts b/boards/ite/it82xx2_evb/it82xx2_evb.dts index bd623e969c54f..29e8ad721c88d 100644 --- a/boards/ite/it82xx2_evb/it82xx2_evb.dts +++ b/boards/ite/it82xx2_evb/it82xx2_evb.dts @@ -25,7 +25,7 @@ chosen { zephyr,console = &uart1; zephyr,shell-uart = &uart1; - zephyr,bt-uart = &uart2; + zephyr,bt-hci = &bt_hci_uart; zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,flash-controller = &flashctrl; @@ -115,6 +115,11 @@ status = "okay"; current-speed = <460800>; clock-frequency = <1843200>; + + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + }; }; &ite_uart1_wrapper { diff --git a/boards/ite/it8xxx2_evb/it8xxx2_evb.dts b/boards/ite/it8xxx2_evb/it8xxx2_evb.dts index c111e9092aa15..0ee42f981f084 100644 --- a/boards/ite/it8xxx2_evb/it8xxx2_evb.dts +++ b/boards/ite/it8xxx2_evb/it8xxx2_evb.dts @@ -25,7 +25,7 @@ chosen { zephyr,console = &uart1; zephyr,shell-uart = &uart1; - zephyr,bt-uart = &uart2; + zephyr,bt-hci = &bt_hci_uart; zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,flash-controller = &flashctrl; @@ -105,6 +105,11 @@ status = "okay"; current-speed = <460800>; clock-frequency = <1843200>; + + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + }; }; &ite_uart1_wrapper { status = "okay"; diff --git a/boards/ite/it8xxx2_evb/support/it8xxx2_evb.resc b/boards/ite/it8xxx2_evb/support/it8xxx2_evb.resc index 987fed77bac33..5ef1ae4e5bbc5 100644 --- a/boards/ite/it8xxx2_evb/support/it8xxx2_evb.resc +++ b/boards/ite/it8xxx2_evb/support/it8xxx2_evb.resc @@ -12,6 +12,6 @@ cpu PerformanceInMips 80 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/kincony/kincony_kc868_a32/Kconfig.defconfig b/boards/kincony/kincony_kc868_a32/Kconfig.defconfig index e8705a11f9850..4d4613b36ad53 100644 --- a/boards/kincony/kincony_kc868_a32/Kconfig.defconfig +++ b/boards/kincony/kincony_kc868_a32/Kconfig.defconfig @@ -10,10 +10,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_KINCONY_KC868_A32_ESP32_PROCPU if BOARD_KINCONY_KC868_A32_ESP32_APPCPU diff --git a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.dts b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.dts index 7940256ff2969..4717ca7fa628b 100644 --- a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.dts +++ b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.yaml b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.yaml index af75ec0edbcf8..8a80a51872e17 100644 --- a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.yaml +++ b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_appcpu.yaml @@ -1,5 +1,5 @@ identifier: kincony_kc868_a32/esp32/appcpu -name: ESP32 DEVKITC WROVER APPCPU +name: KINCONY-KC868-A32 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.dts b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.dts index 0f459d7f7c5c5..be7da2765efaf 100644 --- a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.dts +++ b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.dts @@ -23,18 +23,10 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; }; -&cpu0 { - clock-frequency = ; - cpu-power-states = <&light_sleep &deep_sleep>; -}; - -&cpu1 { - clock-frequency = ; -}; - &gpio0 { status = "okay"; }; @@ -212,3 +204,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.yaml b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.yaml index 51ac12191f6dd..325c3794c29da 100644 --- a/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.yaml +++ b/boards/kincony/kincony_kc868_a32/kincony_kc868_a32_procpu.yaml @@ -1,5 +1,5 @@ identifier: kincony_kc868_a32/esp32/procpu -name: KINCONY-KC868-A32 +name: KINCONY-KC868-A32 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/lairdconnect/bl5340_dvk/Kconfig.defconfig b/boards/lairdconnect/bl5340_dvk/Kconfig.defconfig deleted file mode 100644 index 65c005ee28605..0000000000000 --- a/boards/lairdconnect/bl5340_dvk/Kconfig.defconfig +++ /dev/null @@ -1,119 +0,0 @@ -# BL5340-DVK board configuration - -# Copyright (c) 2019-2020 Nordic Semiconductor ASA -# Copyright (c) 2021-2023 Laird Connectivity -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_BL5340_DVK_NRF5340_CPUAPP || BOARD_BL5340_DVK_NRF5340_CPUAPP_NS - -config I2C - default GPIO || DAC - -# 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_BL5340_DVK_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_BL5340_DVK_NRF5340_CPUAPP && TRUSTED_EXECUTION_SECURE - -if BOARD_BL5340_DVK_NRF5340_CPUAPP_NS - -config FLASH_LOAD_OFFSET - default $(dt_chosen_reg_addr_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - -config FLASH_LOAD_SIZE - default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) - -endif # BOARD_BL5340_DVK_NRF5340_CPUAPP_NS - -choice BT_HCI_BUS_TYPE - default BT_HCI_IPC if BT -endchoice - -config HEAP_MEM_POOL_ADD_SIZE_BOARD - int - default 4096 if BT_HCI_IPC - -config BT_HCI_VS - default y if BT - -# 2.8" TFT Touch Shield for Arduino w/Capacitive Touch Screen Module -# is mounted to the DVK using standoffs. -# https://www.buydisplay.com/2-8-inch-tft-touch-shield-for-arduino-w-capacitive-touch-screen-module -if DISPLAY - -config INPUT_FT5336_INTERRUPT - default y - -if LVGL - -config LV_Z_VDB_SIZE - default 64 - -config LV_Z_BITS_PER_PIXEL - default 16 - -choice LV_COLOR_DEPTH - default LV_COLOR_DEPTH_16 -endchoice - -config LV_COLOR_16_SWAP - default y - -config INPUT - default y - -endif # LVGL - -endif # DISPLAY - -endif # BOARD_BL5340_DVK_NRF5340_CPUAPP || BOARD_BL5340_DVK_NRF5340_CPUAPP_NS - -config IPM_NRFX - default IPM - -config MBOX_NRFX_IPC - default MBOX - -if BOARD_BL5340_DVK_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 - -endif # BOARD_BL5340_DVK_NRF5340_CPUNET diff --git a/boards/lairdconnect/bl5340_dvk/board.yml b/boards/lairdconnect/bl5340_dvk/board.yml deleted file mode 100644 index 71343692f4cb1..0000000000000 --- a/boards/lairdconnect/bl5340_dvk/board.yml +++ /dev/null @@ -1,8 +0,0 @@ -board: - name: bl5340_dvk - vendor: lairdconnect - socs: - - name: 'nrf5340' - variants: - - name: 'ns' - cpucluster: 'cpuapp' diff --git a/boards/lairdconnect/bl5340_dvk/doc/index.rst b/boards/lairdconnect/bl5340_dvk/doc/index.rst deleted file mode 100644 index 4148b639a6d3a..0000000000000 --- a/boards/lairdconnect/bl5340_dvk/doc/index.rst +++ /dev/null @@ -1,436 +0,0 @@ -.. _bl5340_dvk: - -Laird Connectivity BL5340 DVK -############################# - -Overview -******** -The BL5340 Development Kit provides support for the Laird Connectivity -BL5340 module which is powered by a dual-core Nordic Semiconductor -nRF5340 ARM Cortex-M33F CPU. The nRF5340 inside the BL5340 module is a -dual-core SoC based on the Arm® Cortex®-M33 architecture, with: - -* a full-featured Arm Cortex-M33F core with DSP instructions, FPU, and - Armv8-M Security Extension, running at up to 128 MHz, referred to as - the **application core** -* a secondary Arm Cortex-M33 core, with a reduced feature set, running - at a fixed 64 MHz, referred to as the **network core**. - -The ``bl5340_dvk/nrf5340/cpuapp`` build target provides support for the application -core on the BL5340 module. The ``bl5340_dvk/nrf5340/cpunet`` build target provides -support for the network core on the BL5340 module. If ARM TrustZone is -used then the ``bl5340_dvk/nrf5340/cpuapp`` build target provides support for the -non-secure partition of the application core on the BL5340 module. - -This development kit has the following features: - -* :abbr:`ADC (Analog to Digital Converter)` -* CLOCK -* FLASH -* :abbr:`GPIO (General Purpose Input Output)` -* :abbr:`IDAU (Implementation Defined Attribution Unit)` -* :abbr:`I2C (Inter-Integrated Circuit)` -* :abbr:`I2S (Inter-Integrated Sound)` -* :abbr:`MPU (Memory Protection Unit)` -* :abbr:`NVIC (Nested Vectored Interrupt Controller)` -* :abbr:`PWM (Pulse Width Modulation)` -* :abbr:`QSPI (Quad Serial Peripheral Interface)` -* RADIO (Bluetooth Low Energy and 802.15.4) -* :abbr:`RTC (nRF RTC System Clock)` -* Segger RTT (RTT Console) -* :abbr:`SPI (Serial Peripheral Interface)` -* :abbr:`UARTE (Universal asynchronous receiver-transmitter)` -* :abbr:`USB (Universal Serial Bus)` -* :abbr:`WDT (Watchdog Timer)` - -.. figure:: img/bl5340_dvk_top.jpg - :align: center - :alt: BL5340 DVK - - BL5340 DVK (Credit: Laird Connectivity) - -More information about the module can be found on the -`BL5340 homepage`_. - -The `Nordic Semiconductor Infocenter`_ -contains the processor's information and the datasheet. - -Hardware -******** - -The BL5340 DVK has two external oscillators. The frequency of -the slow clock is 32.768KHz. The frequency of the main clock -is 32MHz. - -Supported Features -================== - -The ``bl5340_dvk/nrf5340/cpuapp`` board configuration supports the following -hardware features: - -+-----------+------------+----------------------+ -| Interface | Controller | Driver/Component | -+===========+============+======================+ -| ADC | on-chip | adc | -+-----------+------------+----------------------+ -| CLOCK | on-chip | clock_control | -+-----------+------------+----------------------+ -| FLASH | on-chip | flash | -+-----------+------------+----------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+----------------------+ -| I2C(M) | on-chip | i2c | -+-----------+------------+----------------------+ -| MPU | on-chip | arch/arm | -+-----------+------------+----------------------+ -| NVIC | on-chip | arch/arm | -+-----------+------------+----------------------+ -| QSPI(M) | on-chip | nor | -+-----------+------------+----------------------+ -| PWM | on-chip | pwm | -+-----------+------------+----------------------+ -| RTC | on-chip | system clock | -+-----------+------------+----------------------+ -| RTT | Segger | console | -+-----------+------------+----------------------+ -| SPI(M/S) | on-chip | spi | -+-----------+------------+----------------------+ -| SPU | on-chip | system protection | -+-----------+------------+----------------------+ -| UARTE | on-chip | serial | -+-----------+------------+----------------------+ -| USB | on-chip | usb | -+-----------+------------+----------------------+ -| WDT | on-chip | watchdog | -+-----------+------------+----------------------+ - -The ``bl5340_dvk/nrf5340/cpunet`` board configuration supports the following -hardware features: - -+-----------+------------+----------------------+ -| Interface | Controller | Driver/Component | -+===========+============+======================+ -| CLOCK | on-chip | clock_control | -+-----------+------------+----------------------+ -| FLASH | on-chip | flash | -+-----------+------------+----------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+----------------------+ -| I2C(M) | on-chip | i2c | -+-----------+------------+----------------------+ -| MPU | on-chip | arch/arm | -+-----------+------------+----------------------+ -| NVIC | on-chip | arch/arm | -+-----------+------------+----------------------+ -| RADIO | on-chip | Bluetooth, | -| | | ieee802154 | -+-----------+------------+----------------------+ -| RTC | on-chip | system clock | -+-----------+------------+----------------------+ -| RTT | Segger | console | -+-----------+------------+----------------------+ -| SPI(M/S) | on-chip | spi | -+-----------+------------+----------------------+ -| UARTE | on-chip | serial | -+-----------+------------+----------------------+ -| WDT | on-chip | watchdog | -+-----------+------------+----------------------+ - -Other hardware features have not been enabled yet for this board. -See `Nordic Semiconductor Infocenter`_ -for a complete list of hardware features. - -Connections and IOs -=================== - -An eight-pin GPIO port expander is used to provide additional inputs -and outputs to the BL5340 module. - -Refer to the `TI TCA9538 datasheet`_ for further details. - -LEDs ----- - -* LED1 (blue) = via TCA9538 port expander channel P4 (active low) -* LED2 (blue) = via TCA9538 port expander channel P5 (active low) -* LED3 (blue) = via TCA9538 port expander channel P6 (active low) -* LED4 (blue) = via TCA9538 port expander channel P7 (active low) - -Push buttons ------------- - -* BUTTON1 = SW1 = via TCA9538 port expander channel P0 (active low) -* BUTTON2 = SW2 = via TCA9538 port expander channel P1 (active low) -* BUTTON3 = SW3 = via TCA9538 port expander channel P2 (active low) -* BUTTON4 = SW4 = via TCA9538 port expander channel P3 (active low) -* BOOT = boot (active low) - -External Memory -=============== - -Several external memory sources are available for the BL5340 DVK. These -are described as follows. - -Flash Memory ------------- - -A Macronix MX25R6435FZNIL0 8MB external QSPI Flash memory part is -incorporated for application image storage and large datasets. - -Refer to the `Macronix MX25R6435FZNIL0 datasheet`_ for further details. - -EEPROM Memory -------------- - -A 32KB Giantec GT24C256C-2GLI-TR EEPROM is available via I2C for -storage of infrequently updated data and small datasets. - -Refer to the `Giantec GT24C256C-2GLI-TR datasheet`_ for further details. - -External Memory ---------------- - -An on-board micro SD card slot is available for use with micro SD cards. - -Sensors -======= - -The BL5340 DVK incorporates two sensors for user application testing. -These are described as follows. - -Temperature, Pressure, Humidity & Air Quality Sensor ----------------------------------------------------- - -A Bosch BME680 Temperature, Pressure, Humidity & Air Quality sensor is -available via I2C for environmental measurement applications. - -Refer to the `Bosch BME680 datasheet`_ for further details. - -3-Axis Accelerometer --------------------- - -An ST Microelectronics LIS3DH 3-Axis Accelerometer is available via I2C -for vibration and motion detection applications. - -Refer to the `ST Microelectronics LIS3DH datasheet`_ for further details. - -Ethernet -======== - -Cabled 10/100 Base-T Ethernet Connectivity is available via a Microchip -ENC424J600 Ethernet controller. - -Refer to the `Microchip ENC424J600 datasheet`_ for further details. - -TFT Display & Capacitive Touch Screen Controller -================================================ - -A 2.8 inch, 240 x 320 pixel TFT display with capacitive touch -controller is included with the BL5340 DVK for user interface -application features. - -Refer to the `ER_TFTM028_4 datasheet`_ for a high level overview of the -display. - -An ILI9341 TFT controller is incorporated in the TFT module and -acts as the main controller, controlled via SPI. - -Refer to the `ILI9341 datasheet`_ for further details. - -An FT6206 Capacitive Touch Controller, controlled via I2C is -also incorporated in the TFT module. - -Refer to the `FT6206 datasheet`_ for further details. - -Real-Time Clock -=============== - -A real-time clock is available for accurate time data availability. - -Refer to the `Microchip MCP7940N datasheet`_ for further details. - -DAC -=== - -A 10-bit Digital to Analog Converter is incorporated for generation of -variable voltages. - -Refer to the `Microchip MCP4725 datasheet`_ for further details. - -Security components -=================== - -- Implementation Defined Attribution Unit (`IDAU`_) on the application - core. The IDAU is implemented with the System Protection Unit and is - used to define secure and non-secure memory maps. By default, all of - the memory space (Flash, SRAM, and peripheral address space) is - defined to be secure accessible only. -- Secure boot. - -Programming and Debugging -************************* - -The BL5340's application core supports the Armv8-M Security Extension. -Applications built for the ``bl5340_dvk/nrf5340/cpuapp`` board by default -boot in the Secure state. - -The BL5340's network core does not support the Armv8-M Security -Extension. The IDAU may configure bus accesses by the network core to -have Secure attribute set; the latter allows to build and run Secure -only applications on the BL5340 module. - -Building Secure/Non-Secure Zephyr applications with Arm |reg| TrustZone |reg| -============================================================================= - -Applications on the BL5340 module may contain a Secure and a Non-Secure -firmware image for the application core. The Secure image can be built -using either Zephyr or `Trusted Firmware M`_ (TF-M). Non-Secure -firmware images are always built using Zephyr. The two alternatives are -described below. - -.. note:: - - By default the Secure image for BL5340's application core is - built using TF-M. - -Building the Secure firmware with TF-M --------------------------------------- - -The process to build the Secure firmware image using TF-M and the -Non-Secure firmware image using Zephyr requires the following steps: - -1. Build the Non-Secure Zephyr application - for the application core using ``-DBOARD=bl5340_dvk/nrf5340/cpuapp/ns``. - To invoke the building of TF-M the Zephyr build system requires the - Kconfig option ``BUILD_WITH_TFM`` to be enabled, which is done by - default when building Zephyr as a Non-Secure application. - The Zephyr build system will perform the following steps automatically: - - * Build the Non-Secure firmware image as a regular Zephyr application - * Build a TF-M (secure) firmware image - * Merge the output image binaries together - * Optionally build a bootloader image (MCUboot) - -.. note:: - - Depending on the TF-M configuration, an application DTS overlay may - be required, to adjust the Non-Secure image Flash and SRAM starting - address and sizes. - -2. Build the application firmware for the network core using - ``-DBOARD=bl5340_dvk/nrf5340/cpunet``. - -Building the Secure firmware using Zephyr ------------------------------------------ - -The process to build the Secure and the Non-Secure firmware images -using Zephyr requires the following steps: - -1. Build the Secure Zephyr application for the application core - using ``-DBOARD=bl5340_dvk/nrf5340/cpuapp`` and - ``CONFIG_TRUSTED_EXECUTION_SECURE=y`` and ``CONFIG_BUILD_WITH_TFM=n`` - in the application project configuration file. -2. Build the Non-Secure Zephyr application for the application core - using ``-DBOARD=bl5340_dvk/nrf5340/cpuapp/ns``. -3. Merge the two binaries together. -4. Build the application firmware for the network core using - ``-DBOARD=bl5340_dvk/nrf5340/cpunet``. - -When building a Secure/Non-Secure application for the BL5340's -application core, the Secure application will have to set the IDAU -(SPU) configuration to allow Non-Secure access to all CPU resources -utilized by the Non-Secure application firmware. SPU configuration -shall take place before jumping to the Non-Secure application. - -Building a Secure only application -================================== - -Build the Zephyr app in the usual way (see :ref:`build_an_application` -and :ref:`application_run`), using ``-DBOARD=bl5340_dvk/nrf5340/cpuapp`` for -the firmware running on the BL5340's application core, and using -``-DBOARD=bl5340_dvk/nrf5340/cpunet`` for the firmware running -on the BL5340's network core. - -Flashing -======== - -Follow the instructions in the :ref:`nordic_segger` page to install -and configure all the necessary software. Further information can be -found in :ref:`nordic_segger_flashing`. Then you can build and flash -applications as usual (:ref:`build_an_application` and -:ref:`application_run` for more details). - -.. warning:: - - The BL5340 has a flash read-back protection feature. When flash - read-back protection is active, you will need to recover the chip - before reflashing. If you are flashing with - :ref:`west `, run this command for more - details on the related ``--recover`` option: - - .. code-block:: console - - west flash -H -r nrfjprog --skip-rebuild - -.. note:: - - Flashing and debugging applications on the BL5340 DVK requires - upgrading the nRF Command Line Tools to version 10.12.0 or newer. - Further information on how to install the nRF Command Line Tools can - be found in :ref:`nordic_segger_flashing`. - -Here is an example for the :ref:`hello_world` application running on the -BL5340's application core. - -First, run your favorite terminal program to listen for output. - -.. code-block:: console - - $ minicom -D -b 115200 - -Replace :code:`` with the port where the BL5340 DVK board -can be found. For example, under Linux, :code:`/dev/ttyACM0`. - -Then build and flash the application in the usual way. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: bl5340_dvk/nrf5340/cpuapp - :goals: build flash - -Debugging -========= - -Refer to the :ref:`nordic_segger` page to learn about debugging -boards with a Segger IC. - -Testing Bluetooth on the BL5340 DVK -*********************************** -Many of the Bluetooth examples will work on the BL5340 DVK. -Try them out: - -* :ref:`ble_peripheral` -* :ref:`bluetooth-eddystone-sample` -* :ref:`bluetooth-ibeacon-sample` - -References -********** - -.. target-notes:: - -.. _IDAU: - https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau -.. _BL5340 homepage: https://www.lairdconnect.com/wireless-modules/bluetooth-modules/bluetooth-5-modules/bl5340-series-multi-core-bluetooth-52-802154-nfc-modules -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com -.. _TI TCA9538 datasheet: https://www.ti.com/lit/gpn/TCA9538 -.. _Macronix MX25R6435FZNIL0 datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/8868/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.6.pdf -.. _Giantec GT24C256C-2GLI-TR datasheet: https://www.giantec-semi.com/juchen1123/uploads/pdf/GT24C256C_DS_Cu.pdf -.. _Bosch BME680 datasheet: https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bme680-ds001.pdf -.. _ST Microelectronics LIS3DH datasheet: https://www.st.com/resource/en/datasheet/lis3dh.pdf -.. _Microchip ENC424J600 datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/39935c.pdf -.. _ER_TFTM028_4 datasheet: https://www.buydisplay.com/download/manual/ER-TFTM028-4_Datasheet.pdf -.. _ILI9341 datasheet: https://www.buydisplay.com/download/ic/ILI9341.pdf -.. _FT6206 datasheet: https://www.buydisplay.com/download/ic/FT6206.pdf -.. _Microchip MCP7940N datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/20005010H.pdf -.. _Microchip MCP4725 datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/22039d.pdf -.. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/lairdconnect/bl652_dvk/board.yml b/boards/lairdconnect/bl652_dvk/board.yml deleted file mode 100644 index 2c2e672ec80ac..0000000000000 --- a/boards/lairdconnect/bl652_dvk/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: bl652_dvk - vendor: lairdconnect - socs: - - name: nrf52832 diff --git a/boards/lairdconnect/bl653_dvk/board.yml b/boards/lairdconnect/bl653_dvk/board.yml deleted file mode 100644 index c898247f1f383..0000000000000 --- a/boards/lairdconnect/bl653_dvk/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: bl653_dvk - vendor: lairdconnect - socs: - - name: nrf52833 diff --git a/boards/lairdconnect/bl654_dvk/board.yml b/boards/lairdconnect/bl654_dvk/board.yml deleted file mode 100644 index 788824c7af192..0000000000000 --- a/boards/lairdconnect/bl654_dvk/board.yml +++ /dev/null @@ -1,7 +0,0 @@ -board: - name: bl654_dvk - vendor: lairdconnect - socs: - - name: nrf52840 - variants: - - name: pa diff --git a/boards/lairdconnect/bl654_sensor_board/board.yml b/boards/lairdconnect/bl654_sensor_board/board.yml deleted file mode 100644 index ebe40b44601f3..0000000000000 --- a/boards/lairdconnect/bl654_sensor_board/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: bl654_sensor_board - vendor: lairdconnect - socs: - - name: nrf52840 diff --git a/boards/lairdconnect/bl654_usb/board.yml b/boards/lairdconnect/bl654_usb/board.yml deleted file mode 100644 index dc616554605c4..0000000000000 --- a/boards/lairdconnect/bl654_usb/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: bl654_usb - vendor: lairdconnect - socs: - - name: nrf52840 diff --git a/boards/lairdconnect/bt510/board.yml b/boards/lairdconnect/bt510/board.yml deleted file mode 100644 index 1a9760895ecf1..0000000000000 --- a/boards/lairdconnect/bt510/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: bt510 - vendor: lairdconnect - socs: - - name: nrf52840 diff --git a/boards/lairdconnect/bt610/board.yml b/boards/lairdconnect/bt610/board.yml deleted file mode 100644 index c5a846a0d8d4a..0000000000000 --- a/boards/lairdconnect/bt610/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: bt610 - vendor: lairdconnect - socs: - - name: nrf52840 diff --git a/boards/lairdconnect/index.rst b/boards/lairdconnect/index.rst deleted file mode 100644 index 5c3a6d6621a2a..0000000000000 --- a/boards/lairdconnect/index.rst +++ /dev/null @@ -1,10 +0,0 @@ -.. _boards-lairdconnect: - -Laird Connectivity -################## - -.. toctree:: - :maxdepth: 1 - :glob: - - **/* diff --git a/boards/lairdconnect/mg100/board.yml b/boards/lairdconnect/mg100/board.yml deleted file mode 100644 index 25a3ace314f71..0000000000000 --- a/boards/lairdconnect/mg100/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: mg100 - vendor: lairdconnect - socs: - - name: nrf52840 diff --git a/boards/lairdconnect/mg100/doc/index.rst b/boards/lairdconnect/mg100/doc/index.rst deleted file mode 100644 index 611f0db54658a..0000000000000 --- a/boards/lairdconnect/mg100/doc/index.rst +++ /dev/null @@ -1,249 +0,0 @@ -.. _mg100: - -Laird Connectivity Sentrius™ MG100 Gateway -########################################## - -Overview -******** -The Sentrius™ MG100 Gateway offers a compact, out of box Bluetooth to low power cellular gateway -solution. - -Based on the Pinnacle 100 socket modem, the Sentrius™ MG100 gateway captures data from any -Bluetooth 5 modules or devices and sends it to the cloud via a global low power cellular -(LTE-M/NB-IoT) connection. The MG100 seamlessly incorporates a powerful Cortex M4F controller, -full Bluetooth 5 connectivity, and dual-mode LTE-M/NB-IoT capabilities. The MG100 has full regulatory -and network certifications and End Device carrier approvals. - -Develop your application directly on the integrated Cortex M4F microcontroller using Zephyr RTOS, -enabling your application development with a secure, open source RTOS with more than just kernel -services. Remotely debug your fleet of devices with the `Memfault Platform`_. Take advantage of the -Zephyr community and Laird Connectivity’s multi featured Out of Box (OOB) sample source code -covering all aspects of the product's capabilities and hardware interfaces. The MG100 also delivers -complete antenna flexibility with internal or external antenna options available, and the optional -battery backup provides uninterrupted reporting of remote Bluetooth sensor data. - -More information about the board can be found at the `MG100 website`_. - -The MG100 hardware provides support for the Nordic Semiconductor `nRF52840`_ ARM Cortex-M4F CPU, -`Sierra Wireless HL7800`_ -and the following devices: - -* :abbr:`ADC (Analog to Digital Converter)` -* CLOCK -* FLASH -* :abbr:`GPIO (General Purpose Input Output)` -* :abbr:`I2C (Inter-Integrated Circuit)` -* :abbr:`MPU (Memory Protection Unit)` -* :abbr:`NVIC (Nested Vectored Interrupt Controller)` -* :abbr:`PWM (Pulse Width Modulation)` -* RADIO (Bluetooth Low Energy and 802.15.4) -* :abbr:`RTC (nRF RTC System Clock)` -* :abbr:`SPI (Serial Peripheral Interface)` -* :abbr:`UART (Universal asynchronous receiver-transmitter)` -* :abbr:`WDT (Watchdog Timer)` -* :abbr:`QSPI (Quad Serial Peripheral Interface)` -* :abbr:`LIS3DH (ST Micro 3-axis MEMS accelerometer)` -* :abbr:`HL7800 (Sierra Wireless HL7800 LTE-M1/NB-IoT modem)` -* :abbr:`SD Card` - -.. figure:: img/mg100.jpg - :align: center - :alt: MG100 - - MG100 (450-00054-K1) - -Hardware -******** - -Supported Features -================== - -The MG100 board configuration supports the following -hardware features: - -+-----------+------------+----------------------+ -| Interface | Controller | Driver/Component | -+===========+============+======================+ -| ADC | on-chip | adc | -+-----------+------------+----------------------+ -| CLOCK | on-chip | clock_control | -+-----------+------------+----------------------+ -| FLASH | on-chip | flash | -+-----------+------------+----------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+----------------------+ -| I2C(M) | on-chip | i2c | -+-----------+------------+----------------------+ -| MPU | on-chip | arch/arm | -+-----------+------------+----------------------+ -| NVIC | on-chip | arch/arm | -+-----------+------------+----------------------+ -| PWM | on-chip | pwm | -+-----------+------------+----------------------+ -| RADIO | on-chip | Bluetooth, | -| | | ieee802154 | -+-----------+------------+----------------------+ -| RTC | on-chip | system clock | -+-----------+------------+----------------------+ -| SPI(M/S) | on-chip | spi | -+-----------+------------+----------------------+ -| UART | on-chip | serial | -+-----------+------------+----------------------+ -| WDT | on-chip | watchdog | -+-----------+------------+----------------------+ -| QSPI | on-chip | qspi/MX25R64(8MB) | -+-----------+------------+----------------------+ -| LIS3DH | I2C(M) | sensor/lis3dh | -+-----------+------------+----------------------+ -| HL7800 | UART | HL7800 modem driver | -+-----------+------------+----------------------+ -| SDMMC | SPI(M) | SD Card via SPI | -+-----------+------------+----------------------+ - -See `MG100 website`_ for a complete list -of MG100 hardware features. - -Connections and IOs -=================== - -LED ---- - -* LED1 (red) = P1.7 -* LED2 (blue) = P1.6 -* LED3 (green) = P1.5 - -Push buttons ------------- - -* BUTTON1 = P0.3 - -External flash memory ---------------------- - -A 64Mbit external flash memory part is available for storage of application -images and data. Refer to the `Macronix MX25R6435F datasheet`_ for further -details. - -The flash memory is connected to the on-board QSPI device controller. - -* MX25R64 = QSPI - -SCK = P0.19 -IO0 = P0.20 -IO1 = P0.21 -IO2 = P0.22 -IO3 = P0.23 -CSN = P0.17 - -LIS3DH Motion Sensor --------------------- - -Motion sensor to detect if the gateway moves. - -IRQ IO = P0.28 -I2C SDA = P0.26 -I2C SCL = P0.27 - -SD Card -------- - -SD card used to store large amounts of data. - -SPI CS = P0.29 -SPI SCK = P1.09 -SPI MOSI = P0.11 -SPI MISO = P0.12 - -Programming and Debugging -************************* - -Applications for the ``mg100`` board configuration can be -built and flashed in the usual way. (see :ref:`build_an_application` -and :ref:`application_run` for more details) - -The `Laird Connectivity USB-SWD Programming Kit`_ contains all the necessary -hardware to enable programming and debugging an MG100. - -Flashing -======== - -Follow the instructions in the :ref:`nordic_segger` page to install -and configure all the necessary software. Further information can be -found in :ref:`nordic_segger_flashing`. Then build and flash -applications as usual (see :ref:`build_an_application` and -:ref:`application_run` for more details). - -Here is an example for the :ref:`hello_world` application. - -First, run your favorite terminal program to listen for output. - -.. note:: On the MG100, - the USB connector should be used to access the UART console. - -.. code-block:: console - - $ minicom -D -b 115200 - -Replace :code:`` with the port where the board MG100 -can be found. For example, under Linux, :code:`/dev/ttyUSB0`. - -Then build and flash the application in the usual way. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: mg100 - :goals: build flash - -Debugging -========= - -Refer to the :ref:`nordic_segger` page to learn about debugging Nordic boards with a -Segger IC. - -Software -******** - -MG100 Out-of-Box Demo Software -============================== -The MG100 ships with an out of the box software demo. -Check out the `BLE Gateway OOB Demo`_ source code and documentation. - -Testing Bluetooth on the MG100 -============================== -Many of the Bluetooth examples will work on the MG100. -Try them out: - -* :ref:`ble_peripheral` -* :ref:`bluetooth-eddystone-sample` -* :ref:`bluetooth-ibeacon-sample` - -Testing the LEDs and buttons in the MG100 -==================================================== - -There are 2 samples that allow you to test that the buttons (switches) and LEDs on -the board are working properly with Zephyr: - -.. code-block:: console - - samples/basic/blinky - samples/basic/button - -You can build and flash the examples to make sure Zephyr is running correctly on -your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/mg100/mg100.dts`. - -References -********** - -.. target-notes:: - -.. _MG100 website: https://www.lairdconnect.com/iot-devices/iot-gateways/sentrius-mg100-gateway-lte-mnb-iot-and-bluetooth-5 -.. _nRF52840 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.1.pdf -.. _Sierra Wireless HL7800: https://source.sierrawireless.com/devices/hl-series/hl7800/#sthash.641qTTwA.dpbs -.. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _BLE Gateway OOB Demo: https://github.com/LairdCP/Pinnacle-100-Firmware-Manifest -.. _Macronix MX25R6435F datasheet: https://www.macronix.com/Lists/Datasheet/Attachments/7913/MX25R6435F,%20Wide%20Range,%2064Mb,%20v1.5.pdf -.. _Laird Connectivity USB-SWD Programming Kit: https://www.lairdconnect.com/wireless-modules/programming-kits/usb-swd-programming-kit -.. _Memfault Platform: https://docs.memfault.com/docs/mcu/pinnacle-100-guide -.. _nRF52840: https://www.nordicsemi.com/products/nrf52840 diff --git a/boards/lairdconnect/pinnacle_100_dvk/board.yml b/boards/lairdconnect/pinnacle_100_dvk/board.yml deleted file mode 100644 index 1741e687ace1b..0000000000000 --- a/boards/lairdconnect/pinnacle_100_dvk/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: pinnacle_100_dvk - vendor: lairdconnect - socs: - - name: nrf52840 diff --git a/boards/lairdconnect/pinnacle_100_dvk/doc/index.rst b/boards/lairdconnect/pinnacle_100_dvk/doc/index.rst deleted file mode 100644 index 6feaa13833d46..0000000000000 --- a/boards/lairdconnect/pinnacle_100_dvk/doc/index.rst +++ /dev/null @@ -1,220 +0,0 @@ -.. _pinnacle_100_dvk: - -Laird Connectivity Pinnacle 100 DVK -################################### - -Overview -******** -The Pinnacle™ 100 cellular modem seamlessly incorporates a powerful Cortex M4F -controller, full Bluetooth 5 and LTE-M/NB-IoT capabilities – all with full -regulatory certifications and LTE carrier approvals. The Pinnacle 100 also -delivers complete antenna flexibility, with pre-integrated internal or external -antenna options such as the Revie Flex family of LTE and NB-IoT -internal antennas. - -Develop your application directly on the M4F controller using Zephyr RTOS to -cut BOM costs and power consumption. Take advantage of the Zephyr community, -Laird Connectivity’s sample code (cellular, Bluetooth) and hardware interfaces, -or use our hosted mode AT commands set firmware. - -Extremely power conscious, the Pinnacle 100 is ideal for battery-powered -devices operating at the edge of your IoT networks, seamlessly bridging the -cellular WAN to BLE. It’s never been easier to bridge wireless -Bluetooth 5 sensor data to cloud services like AWS IoT over a -low-power LTE connection. - -More information about the board can be found at the `Pinnacle 100 website`_. - -The Pinnacle 100 Development Kit (453-00010-K1 or 453-00011-K1) hardware -provides support for the -Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU, `Sierra Wireless HL7800`_ (Altair ALT1250) -and the following devices: - -* :abbr:`ADC (Analog to Digital Converter)` -* CLOCK -* FLASH -* :abbr:`GPIO (General Purpose Input Output)` -* :abbr:`I2C (Inter-Integrated Circuit)` -* :abbr:`MPU (Memory Protection Unit)` -* :abbr:`NVIC (Nested Vectored Interrupt Controller)` -* :abbr:`PWM (Pulse Width Modulation)` -* RADIO (Bluetooth Low Energy and 802.15.4) -* :abbr:`RTC (nRF RTC System Clock)` -* Segger RTT (RTT Console) -* :abbr:`SPI (Serial Peripheral Interface)` -* :abbr:`UART (Universal asynchronous receiver-transmitter)` -* :abbr:`USB (Universal Serial Bus)` -* :abbr:`WDT (Watchdog Timer)` -* :abbr:`QSPI (Quad Serial Peripheral Interface)` -* :abbr:`BME680 (Bosch Sensortec BME680 environmental sensor)` -* :abbr:`HL7800 (Sierra Wireless HL7800 LTE-M1/NB-IoT modem)` - -.. figure:: img/pinnacle_100_dvk.jpg - :align: center - :alt: Pinnacle 100 DVK - - Pinnacle 100 DVK (453-00010-K1) - -Hardware -******** - -Supported Features -================== - -The Pinnacle 100 development board configuration supports the following -hardware features: - -+-----------+------------+----------------------+ -| Interface | Controller | Driver/Component | -+===========+============+======================+ -| ADC | on-chip | adc | -+-----------+------------+----------------------+ -| CLOCK | on-chip | clock_control | -+-----------+------------+----------------------+ -| FLASH | on-chip | flash | -+-----------+------------+----------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+----------------------+ -| I2C(M) | on-chip | i2c | -+-----------+------------+----------------------+ -| MPU | on-chip | arch/arm | -+-----------+------------+----------------------+ -| NVIC | on-chip | arch/arm | -+-----------+------------+----------------------+ -| PWM | on-chip | pwm | -+-----------+------------+----------------------+ -| RADIO | on-chip | Bluetooth, | -| | | ieee802154 | -+-----------+------------+----------------------+ -| RTC | on-chip | system clock | -+-----------+------------+----------------------+ -| RTT | Segger | console | -+-----------+------------+----------------------+ -| SPI(M/S) | on-chip | spi | -+-----------+------------+----------------------+ -| UART | on-chip | serial | -+-----------+------------+----------------------+ -| USB | on-chip | usb | -+-----------+------------+----------------------+ -| WDT | on-chip | watchdog | -+-----------+------------+----------------------+ -| QSPI | on-chip | qspi/MX25R64(8MB) | -+-----------+------------+----------------------+ -| BME680 | I2C(M) | sensor/bme680 | -+-----------+------------+----------------------+ -| HL7800 | UART | HL7800 modem driver | -+-----------+------------+----------------------+ - -See `Pinnacle 100 website`_ for a complete list -of Pinnacle 100 Development Kit hardware features. - -Connections and IOs -=================== - -LED ---- - -* LED1 (blue) = P1.4 -* LED2 (green) = P1.5 -* LED3 (red) = P1.6 -* LED4 (green) = P1.7 - -Push buttons ------------- - -* BUTTON1 = SW1 = P0.31 -* BUTTON2 = SW2 = P0.3 -* BUTTON3 = SW3 = P0.4 -* BUTTON4 = SW4 = P0.2 -* NRF RESET = SW5 = reset - -Programming and Debugging -************************* - -Applications for the ``pinnacle_100_dvk`` board configuration can be -built and flashed in the usual way. (see :ref:`build_an_application` -and :ref:`application_run` for more details) - -Flashing -======== - -Follow the instructions in the :ref:`nordic_segger` page to install -and configure all the necessary software. Further information can be -found in :ref:`nordic_segger_flashing`. Then build and flash -applications as usual (see :ref:`build_an_application` and -:ref:`application_run` for more details). - -Here is an example for the :ref:`hello_world` application. - -First, run your favorite terminal program to listen for output. - -.. note:: On the Pinnacle 100 development board, - the FTDI USB should be used to access the UART console. - -.. code-block:: console - - $ minicom -D -b 115200 - -Replace :code:`` with the port where the board Pinnacle 100 DVK -can be found. For example, under Linux, :code:`/dev/ttyUSB0`. - -Then build and flash the application in the usual way. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: pinnacle_100_dvk - :goals: build flash - -Debugging -========= - -Refer to the :ref:`nordic_segger` page to learn about debugging Nordic boards with a -Segger IC. - -Software -******** - -Pinnacle 100 Out-of-Box Demo Software -===================================== -The Pinnacle 100 development kit ships with an out of the box software demo. -Check out the `Pinnacle 100 OOB Demo`_ source code and documentation. - -Sample Applications -=================== -`Pinnacle 100 Sample Applications`_ are available. - -Testing Bluetooth on the Pinnacle 100 DVK -========================================= -Many of the Bluetooth examples will work on the Pinnacle 100 DVK. -Try them out: - -* :ref:`ble_peripheral` -* :ref:`bluetooth-eddystone-sample` -* :ref:`bluetooth-ibeacon-sample` - -Testing the LEDs and buttons in the Pinnacle 100 DVK -==================================================== - -There are 2 samples that allow you to test that the buttons (switches) and LEDs on -the board are working properly with Zephyr: - -.. code-block:: console - - samples/basic/blinky - samples/basic/button - -You can build and flash the examples to make sure Zephyr is running correctly on -your board. The button and LED definitions can be found in -:zephyr_file:`boards/lairdconnect/pinnacle_100_dvk/pinnacle_100_dvk.dts`. - -References -********** - -.. target-notes:: - -.. _Pinnacle 100 website: https://www.lairdconnect.com/wireless-modules/cellular-solutions/pinnacle-100-cellular-modem -.. _nRF52840 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.1.pdf -.. _Sierra Wireless HL7800: https://source.sierrawireless.com/devices/hl-series/hl7800/#sthash.641qTTwA.dpbs -.. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _Pinnacle 100 OOB Demo: https://github.com/LairdCP/Pinnacle_100_oob_demo -.. _Pinnacle 100 Sample Applications: https://github.com/LairdCP/Pinnacle_100_Sample_Applications diff --git a/boards/lairdconnect/rm1xx_dvk/board.yml b/boards/lairdconnect/rm1xx_dvk/board.yml deleted file mode 100644 index 1e7ddd8f80678..0000000000000 --- a/boards/lairdconnect/rm1xx_dvk/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: rm1xx_dvk - vendor: lairdconnect - socs: - - name: nrf51822 diff --git a/boards/lairdconnect/rm1xx_dvk/doc/index.rst b/boards/lairdconnect/rm1xx_dvk/doc/index.rst deleted file mode 100644 index bd006dc058a52..0000000000000 --- a/boards/lairdconnect/rm1xx_dvk/doc/index.rst +++ /dev/null @@ -1,179 +0,0 @@ -.. _rm1xx_dvk: - -Laird Connectivity RM1xx DVK -############################ - -Overview -******** - -Laird Connectivity's RM1xx is a module which integrates both LoRa and -BLE communications, powered by a Nordic Semiconductor nRF51822 ARM -Cortex-M0 CPU and on-board Semtech SX1272 LoRa RF chip. This board -supports the RM1xx on the RM1xx development board - RM191 for the -915MHz version and RM186 for the 868MHz version. - -This development kit has the following features: - -* :abbr:`ADC (Analog to Digital Converter)` -* CLOCK -* FLASH -* :abbr:`GPIO (General Purpose Input Output)` -* :abbr:`I2C (Inter-Integrated Circuit)` -* :abbr:`NVIC (Nested Vectored Interrupt Controller)` -* :abbr:`PWM (Pulse Width Modulation)` -* RADIO (Bluetooth Low Energy) -* :abbr:`RTC (nRF RTC System Clock)` -* Segger RTT (RTT Console) -* :abbr:`SPI (Serial Peripheral Interface)` -* :abbr:`UART (Universal asynchronous receiver-transmitter)` -* :abbr:`WDT (Watchdog Timer)` - -.. figure:: img/RM186-DVK.jpg - :align: center - :alt: RM1xx development kit (DVK) - - RM1xx development kit (DVK) (Credit: Laird Connectivity) - -.. figure:: img/RM186-SM.jpg - :align: center - :alt: RM1xx module - - RM1xx module (Credit: Laird Connectivity) - -More information about the module can be found on the -`RM1xx homepage`_. - -The `Nordic Semiconductor Infocenter`_ -contains the processor's information and the datasheet. - -Hardware -******** - -The RM1xx has two internal oscillators. The frequency of -the slow clock is 32.768KHz. The frequency of the main clock -is 16MHz. - - -Supported Features -================== - -The rm1xx_dvk board configuration supports the following -hardware features: - -+-----------+------------+----------------------+ -| Interface | Controller | Driver/Component | -+===========+============+======================+ -| ADC | on-chip | adc | -+-----------+------------+----------------------+ -| CLOCK | on-chip | clock_control | -+-----------+------------+----------------------+ -| FLASH | on-chip | flash | -+-----------+------------+----------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+----------------------+ -| I2C(M) | on-chip | i2c | -+-----------+------------+----------------------+ -| NVIC | on-chip | arch/arm | -+-----------+------------+----------------------+ -| PWM | on-chip | pwm | -+-----------+------------+----------------------+ -| RTC | on-chip | system clock | -+-----------+------------+----------------------+ -| RTT | Segger | console | -+-----------+------------+----------------------+ -| SPI(M/S) | on-chip | spi | -+-----------+------------+----------------------+ -| SPU | on-chip | system protection | -+-----------+------------+----------------------+ -| UART | on-chip | serial | -+-----------+------------+----------------------+ -| WDT | on-chip | watchdog | -+-----------+------------+----------------------+ - -Other hardware features have not been enabled yet for this board. -See `Nordic Semiconductor Infocenter`_ -for a complete list of hardware features. - -Connections and IOs -=================== - -The development board features a Microchip MCP23S08 SPI port expander - -note that this is not currently supported in Zephyr. - -Refer to the `Microchip MCP23S08 datasheet`_ for further details. - -Push buttons ------------- - -* BUTTON2 = SW0 = P0.05 - - -Internal Memory -=============== - -EEPROM Memory -------------- - -A 512KB (4Mb) Adesto AT25DF041B EEPROM is available via SPI for storage -of infrequently updated data and small datasets and can be used with -the spi-nor driver. Note that the EEPROM shares the same SPI bus as the -SX1272 LoRa transceiver so priority access should be given to the LoRa -radio. - -Refer to the `Adesto AT25DF041B datasheet`_ for further details. - -LoRa -==== - -A Semtech SX1272 transceiver chip is present in the module which can be -used in 915MHz LoRa frequency ranges if using an RM191 module or 868MHz -LoRa frequency ranges if uses an RM186 module - -Refer to the `Semtech SX1272 datasheet`_ for further details. - -Programming and Debugging -************************* - -Flashing -======== - -Follow the instructions in the :ref:`nordic_segger` page to install -and configure all the necessary software. Further information can be -found in :ref:`nordic_segger_flashing`. Then build and flash -applications as usual (see :ref:`build_an_application` and -:ref:`application_run` for more details). - -Here is an example for the :ref:`hello_world` application. - -First, run your favorite terminal program to listen for output. - -.. code-block:: console - - $ minicom -D -b 115200 - -Replace :code:`` with the port where the board nRF51 DK -can be found. For example, under Linux, :code:`/dev/ttyACM0`. - -Then build and flash the application in the usual way. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: rm1xx_dvk - :goals: build flash - -Debugging -========= - -Refer to the :ref:`nordic_segger` page to learn about debugging boards -with a Segger IC. - -References -********** - -.. target-notes:: - -.. _RM1xx homepage: https://www.lairdconnect.com/wireless-modules/lorawan-solutions/sentrius-rm1xx-lora-ble-module -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com -.. _Adesto AT25DF041B datasheet: https://www.dialog-semiconductor.com/sites/default/files/ds-at25df041b_040.pdf -.. _Semtech SX1272 datasheet: https://semtech.my.salesforce.com/sfc/p/#E0000000JelG/a/440000001NCE/v_VBhk1IolDgxwwnOpcS_vTFxPfSEPQbuneK3mWsXlU -.. _Microchip MCP23S08 datasheet: https://ww1.microchip.com/downloads/en/DeviceDoc/MCP23008-MCP23S08-Data-Sheet-20001919F.pdf diff --git a/boards/lilygo/index.rst b/boards/lilygo/index.rst new file mode 100644 index 0000000000000..8333f6918677f --- /dev/null +++ b/boards/lilygo/index.rst @@ -0,0 +1,10 @@ +.. _boards-lilygo: + +Lilygo +###### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/boards/lilygo/ttgo_lora32/Kconfig.defconfig b/boards/lilygo/ttgo_lora32/Kconfig.defconfig new file mode 100644 index 0000000000000..d77a95c89b076 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/Kconfig.defconfig @@ -0,0 +1,25 @@ +# Lilygo ttgo LoRa32 board configuration + +# Copyright (c) 2024 Lothar Felten +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_TTGO_LORA32_ESP32_PROCPU + +config ENTROPY_GENERATOR + default y + +config HEAP_MEM_POOL_ADD_SIZE_BOARD + int + default 65535 if WIFI && BT + default 51200 if WIFI + default 40960 if BT + default 4096 + +endif # BOARD_TTGO_LORA32_ESP32_PROCPU + +if BOARD_TTGO_LORA32_ESP32_APPCPU + +config HEAP_MEM_POOL_ADD_SIZE_BOARD + default 256 + +endif # BOARD_TTGO_LORA32_ESP32_APPCPU diff --git a/boards/lilygo/ttgo_lora32/Kconfig.sysbuild b/boards/lilygo/ttgo_lora32/Kconfig.sysbuild new file mode 100644 index 0000000000000..3a2d17ac5cfd0 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/lilygo/ttgo_lora32/Kconfig.ttgo_lora32 b/boards/lilygo/ttgo_lora32/Kconfig.ttgo_lora32 new file mode 100644 index 0000000000000..b1cac2dac488d --- /dev/null +++ b/boards/lilygo/ttgo_lora32/Kconfig.ttgo_lora32 @@ -0,0 +1,9 @@ +# TTGO LoRa32 board configuration + +# Copyright (c) 2024 Lothar Felten +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_TTGO_LORA32 + select SOC_ESP32_PICO_D4 + select SOC_ESP32_PROCPU if BOARD_TTGO_LORA32_ESP32_PROCPU + select SOC_ESP32_APPCPU if BOARD_TTGO_LORA32_ESP32_APPCPU diff --git a/boards/lilygo/ttgo_lora32/board.cmake b/boards/lilygo/ttgo_lora32/board.cmake new file mode 100644 index 0000000000000..91b3caa2c75d5 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/board.cmake @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) + +# the default ESP32 baud rate is not supported +board_runner_args(esp32 "--esp-baud-rate=1500000") diff --git a/boards/lilygo/ttgo_lora32/board.yml b/boards/lilygo/ttgo_lora32/board.yml new file mode 100644 index 0000000000000..8cccfbbf7d267 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/board.yml @@ -0,0 +1,5 @@ +board: + name: ttgo_lora32 + vendor: lilygo + socs: + - name: esp32 diff --git a/boards/lilygo/ttgo_lora32/doc/img/ttgo_lora32.webp b/boards/lilygo/ttgo_lora32/doc/img/ttgo_lora32.webp new file mode 100644 index 0000000000000..4d240e9d6b996 Binary files /dev/null and b/boards/lilygo/ttgo_lora32/doc/img/ttgo_lora32.webp differ diff --git a/boards/lilygo/ttgo_lora32/doc/index.rst b/boards/lilygo/ttgo_lora32/doc/index.rst new file mode 100644 index 0000000000000..b149fa6fa0c55 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/doc/index.rst @@ -0,0 +1,245 @@ +.. _ttgo_lora32: + +Lilygo TTGO LoRa32 +################## + +Overview +******** + +The Lilygo TTGO LoRa32 is a development board for LoRa applications baesed on the ESP32-PICO-D4. + +It's available in two versions supporting two different frequency ranges and features the following integrated components: + +- ESP32-PICO-D4 chip (240MHz dual core, 600 DMIPS, 520KB SRAM, Wi-Fi) +- SSD1306, 128x64 px, 0.96" screen +- SX1278 (433MHz) or SX1276 (868/915/923MHz) LoRa radio frontend +- JST GH 2-pin battery connector +- TF card slot + +Some of the ESP32 I/O pins are accessible on the board's pin headers. + +.. figure:: img/ttgo_lora32.webp + :align: center + :alt: Lilygo TTGO LoRa32 module + :width: 400 px + + Lilygo TTGO LoRa32 module + +Functional Description +********************** + +The following table below describes the key components, interfaces, and controls +of the Lilygo TTGO LoRa32 board. + +.. _SX127x: https://www.semtech.com/products/wireless-rf/lora-connect/sx1276#documentation +.. _ESP32-PICO-D4: https://www.espressif.com/sites/default/files/documentation/esp32-pico-d4_datasheet_en.pdf +.. _SSD1306: https://cdn-shop.adafruit.com/datasheets/SSD1306.pdf + ++------------------+-------------------------------------------------------------------------+ +| Key Component | Description | ++==================+=========================================================================+ +| ESP32-PICO-D4 | This `ESP32-PICO-D4`_ module provides complete Wi-Fi and Bluetooth | +| | functionalities and integrates a 4-MB SPI flash. | ++------------------+-------------------------------------------------------------------------+ +| Diagnostic LED | One user LED connected to the GPIO pin. | ++------------------+-------------------------------------------------------------------------+ +| USB Port | USB interface. Power supply for the board as well as the | +| | serial communication interface between a computer and the board. | +| | Micro-USB type connector. | ++------------------+-------------------------------------------------------------------------+ +| Power Switch | Sliding power switch. | ++------------------+-------------------------------------------------------------------------+ +| LCD screen | Built-in OLED display \(`SSD1306`_, 0.96", 128x64 px\) controlled | +| | by I2C interface | ++------------------+-------------------------------------------------------------------------+ +| SX1276/SX1278 | LoRa radio frontend chip, connected via SPI. | +| | Use SX1276 for 433MHz and SX1276 for 868/915/923MHz. | ++------------------+-------------------------------------------------------------------------+ +| TF card slot | TF card slot wired to the SD interface of the MCU. | ++------------------+-------------------------------------------------------------------------+ + + +Start Application Development +***************************** + +Before powering up your Lilygo TTGO LoRa32, please make sure that the board is in good +condition with no obvious signs of damage. + +System requirements +******************* + +Prerequisites +============= + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +******************* + +Simple boot +=========== + +The board could be loaded using the single binary image, without 2nd stage bootloader. +It is the default option when building the application without additional configuration. + +.. note:: + + Simple boot does not provide any security features nor OTA updates. + +MCUboot bootloader +================== + +User may choose to use MCUboot bootloader instead. In that case the bootloader +must be build (and flash) at least once. + +There are two options to be used when building an application: + +1. Sysbuild +2. Manual build + +.. note:: + + User can select the MCUboot bootloader by adding the following line + to the board default configuration file. + +.. code-block:: cfg + + CONFIG_BOOTLOADER_MCUBOOT=y + +Sysbuild +======== + +The sysbuild makes possible to build and flash all necessary images needed to +bootstrap the board with the ESP32-PICO-D4 SoC. + +To build the sample application using sysbuild use the command: + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: ttgo_lora32/esp32/procpu + :goals: build + :west-args: --sysbuild + :compact: + +By default, the ESP32-PICO-D4 sysbuild creates bootloader (MCUboot) and application +images. But it can be configured to create other kind of images. + +Build directory structure created by sysbuild is different from traditional +Zephyr build. Output is structured by the domain subdirectories: + +.. code-block:: + + build/ + ├── hello_world + │   └── zephyr + │   ├── zephyr.elf + │   └── zephyr.bin + ├── mcuboot + │ └── zephyr + │ ├── zephyr.elf + │ └── zephyr.bin + └── domains.yaml + +.. note:: + + With ``--sysbuild`` option the bootloader will be re-build and re-flash + every time the pristine build is used. + +For more information about the system build please read the :ref:`sysbuild` documentation. + +Manual build +============ + +During the development cycle, it is intended to build & flash as quickly possible. +For that reason, images can be build one at a time using traditional build. + +The instructions following are relevant for both manual build and sysbuild. +The only difference is the structure of the build directory. + +.. note:: + + Remember that bootloader (MCUboot) needs to be flash at least once. + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: ttgo_lora32/esp32/procpu + :goals: build + +The usual ``flash`` target will work with the ``ttgo_lora32`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: ttgo_lora32/esp32/procpu + :goals: flash + +The default baud rate for the Lilygo TTGO LoRa32 is set to 1500000bps. If experiencing issues when flashing, +try using different values by using ``--esp-baud-rate `` option during +``west flash`` (e.g. ``west flash --esp-baud-rate 115200``). + +You can also open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! ttgo_lora32 + +LoRa samples +============ + +There are two LoRa samples that will work out of the box with this board. + +To build the LoRa transmit sample application using sysbuild use the command: + +.. zephyr-app-commands:: + :tool: west + :app: samples/drivers/lora/send + :board: ttgo_lora32/esp32/procpu + :goals: build + :west-args: --sysbuild + :compact: + +To build the LoRa receive sample application using sysbuild use the command: + +.. zephyr-app-commands:: + :tool: west + :app: samples/drivers/lora/receive + :board: ttgo_lora32/esp32/procpu + :goals: build + :west-args: --sysbuild + :compact: + +Debugging +********* + +Lilygo TTGO LoRa32 debugging is not supported due to pinout limitations. + +Related Documents +***************** +- `Lilygo TTGO LoRa32 schematic `_ (PDF) +- `Lilygo TTGO LoRa32 documentation `_ +- `Lilygo github repo `_ +- `ESP32-PICO-D4 Datasheet `_ (PDF) +- `ESP32 Datasheet `_ (PDF) +- `ESP32 Hardware Reference `_ diff --git a/boards/lilygo/ttgo_lora32/support/openocd.cfg b/boards/lilygo/ttgo_lora32/support/openocd.cfg new file mode 100644 index 0000000000000..338e6e4e6eae9 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/support/openocd.cfg @@ -0,0 +1,5 @@ +set ESP_RTOS none +set ESP32_ONLYCPU 1 + +source [find interface/ftdi/esp32_devkitj_v1.cfg] +source [find target/esp32.cfg] diff --git a/boards/lilygo/ttgo_lora32/ttgo_lora32-pinctrl.dtsi b/boards/lilygo/ttgo_lora32/ttgo_lora32-pinctrl.dtsi new file mode 100644 index 0000000000000..5f043ddb945d6 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/ttgo_lora32-pinctrl.dtsi @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Lothar Felten + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + spim3_default: spim3_default { + group1 { + pinmux = , + ; + }; + group2 { + pinmux = ; + output-low; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , + ; + bias-pull-up; + drive-open-drain; + output-high; + }; + }; + +}; diff --git a/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_appcpu.dts b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_appcpu.dts new file mode 100644 index 0000000000000..c5eb19c240f3d --- /dev/null +++ b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_appcpu.dts @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +/dts-v1/; + +#include + +/ { + model = "ttgo LoRa32 APPCPU"; + compatible = "espressif,esp32"; + + chosen { + zephyr,sram = &sram0; + zephyr,ipc_shm = &shm0; + zephyr,ipc = &ipm0; + }; +}; + +&ipm0 { + status = "okay"; +}; + +&trng0 { + status = "okay"; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@1000 { + label = "mcuboot"; + reg = <0x00001000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_appcpu.yaml b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_appcpu.yaml new file mode 100644 index 0000000000000..f048566726012 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_appcpu.yaml @@ -0,0 +1,27 @@ +identifier: ttgo_lora32/esp32/appcpu +name: TTGO LoRa32 APPCPU +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - uart +testing: + ignore_tags: + - net + - bluetooth + - flash + - cpp + - posix + - watchdog + - logging + - kernel + - pm + - gpio + - crypto + - eeprom + - heap + - cmsis_rtos + - jwt + - zdsp +vendor: lilygo diff --git a/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_appcpu_defconfig b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_appcpu_defconfig new file mode 100644 index 0000000000000..100bb88256761 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_appcpu_defconfig @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=2048 +CONFIG_CLOCK_CONTROL=y +CONFIG_MINIMAL_LIBC=y diff --git a/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_procpu.dts b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_procpu.dts new file mode 100644 index 0000000000000..d8dfad087e3e9 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_procpu.dts @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2024 Lothar Felten + * + * SPDX-License-Identifier: Apache-2.0 + */ +/dts-v1/; + +#include +#include "ttgo_lora32-pinctrl.dtsi" +#include + +/ { + model = "ttgo LoRa32 PROCPU"; + compatible = "lilygo,ttgo-lora32"; + + aliases { + led0 = &green_led; + uart-0 = &uart0; + i2c-0 = &i2c0; + watchdog0 = &wdt0; + lora0 = &lora0; + }; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,display = &ssd1306_128x64; + }; + + leds { + compatible = "gpio-leds"; + + green_led: led_0 { + gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; + label = "Green - LED0"; + }; + }; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +/* OLED display */ +&i2c0 { + status = "okay"; + clock-frequency = ; + sda-gpios = <&gpio0 21 GPIO_OPEN_DRAIN>; + scl-gpios = <&gpio0 22 GPIO_OPEN_DRAIN>; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + ssd1306_128x64: ssd1306@3c { + compatible = "solomon,ssd1306fb"; + reg = <0x3c>; + width = <128>; + height = <64>; + segment-offset = <0>; + page-offset = <0>; + display-offset = <0>; + multiplex-ratio = <63>; + segment-remap; + com-invdir; + prechargep = <0x22>; + }; +}; + +&spi3 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim3_default>; + pinctrl-names = "default"; + cs-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + lora0: lora@0 { + compatible = "semtech,sx1276"; + reg = <0>; + reset-gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; + dio-gpios = + /* SX1276 D0 -> GPIO26 */ + <&gpio0 26 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + /* SX1276 D1 -> GPIO35 */ + <&gpio1 3 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>, + /* SX1276 D1 -> GPIO34 */ + <&gpio1 2 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + spi-max-frequency = <1000000>; + power-amplifier-output = "pa-boost"; + }; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&timer2 { + status = "okay"; +}; + +&timer3 { + status = "okay"; +}; + +&trng0 { + status = "okay"; +}; + +&flash0 { + status = "okay"; + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 60kB for the bootloader */ + boot_partition: partition@1000 { + label = "mcuboot"; + reg = <0x00001000 0x0000F000>; + read-only; + }; + + /* Reserve 1024kB for the application in slot 0 */ + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + /* Reserve 1024kB for the application in slot 1 */ + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + /* Reserve 256kB for the scratch partition */ + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_procpu.yaml b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_procpu.yaml new file mode 100644 index 0000000000000..f4d0e25cc59d2 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_procpu.yaml @@ -0,0 +1,21 @@ +identifier: ttgo_lora32/esp32/procpu +name: TTGO LoRa32 PROCPU +type: mcu +arch: xtensa +toolchain: + - zephyr +supported: + - gpio + - i2c + - spi + - watchdog + - uart + - pinmux + - display + - lora + - nvs +testing: + ignore_tags: + - net + - bluetooth +vendor: lilygo diff --git a/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_procpu_defconfig b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_procpu_defconfig new file mode 100644 index 0000000000000..ee9920cda6870 --- /dev/null +++ b/boards/lilygo/ttgo_lora32/ttgo_lora32_esp32_procpu_defconfig @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y + +CONFIG_GPIO=y +CONFIG_I2C=y diff --git a/boards/lilygo/ttgo_t8c3/Kconfig.defconfig b/boards/lilygo/ttgo_t8c3/Kconfig.defconfig new file mode 100644 index 0000000000000..eb2f107cd0d3e --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Lothar Felten +# SPDX-License-Identifier: Apache-2.0 + +config HEAP_MEM_POOL_ADD_SIZE_BOARD + int + default 65535 if WIFI && BT + default 51200 if WIFI + default 40960 if BT + default 4096 diff --git a/boards/lilygo/ttgo_t8c3/Kconfig.sysbuild b/boards/lilygo/ttgo_t8c3/Kconfig.sysbuild new file mode 100644 index 0000000000000..3a2d17ac5cfd0 --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/Kconfig.sysbuild @@ -0,0 +1,10 @@ +# Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +choice BOOTLOADER + default BOOTLOADER_MCUBOOT +endchoice + +choice BOOT_SIGNATURE_TYPE + default BOOT_SIGNATURE_TYPE_NONE +endchoice diff --git a/boards/lilygo/ttgo_t8c3/Kconfig.ttgo_t8c3 b/boards/lilygo/ttgo_t8c3/Kconfig.ttgo_t8c3 new file mode 100644 index 0000000000000..60cd233a9b4a3 --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/Kconfig.ttgo_t8c3 @@ -0,0 +1,5 @@ +# Copyright 2024 Lothar Felten +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_TTGO_T8C3 + select SOC_ESP32C3_FX4 diff --git a/boards/lilygo/ttgo_t8c3/board.cmake b/boards/lilygo/ttgo_t8c3/board.cmake new file mode 100644 index 0000000000000..2f04d1fe8861e --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(NOT "${OPENOCD}" MATCHES "^${ESPRESSIF_TOOLCHAIN_PATH}/.*") + set(OPENOCD OPENOCD-NOTFOUND) +endif() +find_program(OPENOCD openocd PATHS ${ESPRESSIF_TOOLCHAIN_PATH}/openocd-esp32/bin NO_DEFAULT_PATH) + +include(${ZEPHYR_BASE}/boards/common/esp32.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/lilygo/ttgo_t8c3/board.yml b/boards/lilygo/ttgo_t8c3/board.yml new file mode 100644 index 0000000000000..8b1084a449353 --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/board.yml @@ -0,0 +1,5 @@ +board: + name: ttgo_t8c3 + vendor: lilygo + socs: + - name: esp32c3 diff --git a/boards/lilygo/ttgo_t8c3/doc/img/ttgo_t8c3.webp b/boards/lilygo/ttgo_t8c3/doc/img/ttgo_t8c3.webp new file mode 100644 index 0000000000000..ea11307794fac Binary files /dev/null and b/boards/lilygo/ttgo_t8c3/doc/img/ttgo_t8c3.webp differ diff --git a/boards/lilygo/ttgo_t8c3/doc/index.rst b/boards/lilygo/ttgo_t8c3/doc/index.rst new file mode 100644 index 0000000000000..73e092bb94ca0 --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/doc/index.rst @@ -0,0 +1,233 @@ +.. _ttgo_t8c3: + +Lilygo TTGO T8-C3 +################# + +Overview +******** + +Lilygo TTGO T8-C3 is an IoT mini development board based on the +Espressif ESP32-C3 WiFi/Bluetooth dual-mode chip. + +It features the following integrated components: + +- ESP32-C3 chip (160MHz single core, 400KB SRAM, Wi-Fi) +- on board antenna and IPEX connector +- USB-C connector for power and communication +- JST GH 2-pin battery connector +- LED + +.. figure:: img/ttgo_t8c3.webp + :align: center + :alt: TTGO T8-C3 + + Lilygo TTGO T8-C3 + +Functional Description +********************** +This board is based on the ESP32-C3 with 4MB of flash, WiFi and BLE support. It +has an USB-C port for programming and debugging, integrated battery charging +and an on-board antenna. The fitted U.FL external antenna connector can be +enabled by moving a 0-ohm resistor. + +Connections and IOs +=================== + +The TTGO T8-C3 board configuration supports the following hardware features: + ++-----------+------------+------------------+ +| Interface | Controller | Driver/Component | ++===========+============+==================+ +| PMP | on-chip | arch/riscv | ++-----------+------------+------------------+ +| INTMTRX | on-chip | intc_esp32c3 | ++-----------+------------+------------------+ +| PINMUX | on-chip | pinctrl_esp32 | ++-----------+------------+------------------+ +| USB UART | on-chip | serial_esp32_usb | ++-----------+------------+------------------+ +| GPIO | on-chip | gpio_esp32 | ++-----------+------------+------------------+ +| UART | on-chip | uart_esp32 | ++-----------+------------+------------------+ +| I2C | on-chip | i2c_esp32 | ++-----------+------------+------------------+ +| SPI | on-chip | spi_esp32_spim | ++-----------+------------+------------------+ +| TWAI | on-chip | can_esp32_twai | ++-----------+------------+------------------+ + +Start Application Development +***************************** + +Before powering up your Lilygo TTGO T8-C3, please make sure that the board is in good +condition with no obvious signs of damage. + +System requirements +******************* + +Prerequisites +============= + +Espressif HAL requires WiFi and Bluetooth binary blobs in order work. Run the command +below to retrieve those files. + +.. code-block:: console + + west blobs fetch hal_espressif + +.. note:: + + It is recommended running the command above after :file:`west update`. + +Building & Flashing +******************* + +Simple boot +=========== + +The board could be loaded using the single binary image, without 2nd stage bootloader. +It is the default option when building the application without additional configuration. + +.. note:: + + Simple boot does not provide any security features nor OTA updates. + +MCUboot bootloader +================== + +User may choose to use MCUboot bootloader instead. In that case the bootloader +must be build (and flash) at least once. + +There are two options to be used when building an application: + +1. Sysbuild +2. Manual build + +.. note:: + + User can select the MCUboot bootloader by adding the following line + to the board default configuration file. + ``` + CONFIG_BOOTLOADER_MCUBOOT=y + ``` + +Sysbuild +======== + +The sysbuild makes possible to build and flash all necessary images needed to +bootstrap the board with the ESP32-C3 SoC. + +To build the sample application using sysbuild use the command: + +.. zephyr-app-commands:: + :tool: west + :app: samples/hello_world + :board: ttgo_t8c3 + :goals: build + :west-args: --sysbuild + :compact: + +By default, the ESP32-C3 sysbuild creates bootloader (MCUboot) and application +images. But it can be configured to create other kind of images. + +Build directory structure created by sysbuild is different from traditional +Zephyr build. Output is structured by the domain subdirectories: + +.. code-block:: + + build/ + ├── hello_world + │   └── zephyr + │   ├── zephyr.elf + │   └── zephyr.bin + ├── mcuboot + │ └── zephyr + │ ├── zephyr.elf + │ └── zephyr.bin + └── domains.yaml + +.. note:: + + With ``--sysbuild`` option the bootloader will be re-build and re-flash + every time the pristine build is used. + +For more information about the system build please read the :ref:`sysbuild` documentation. + +Manual build +============ + +During the development cycle, it is intended to build & flash as quickly possible. +For that reason, images can be build one at a time using traditional build. + +The instructions following are relevant for both manual build and sysbuild. +The only difference is the structure of the build directory. + +.. note:: + + Remember that bootloader (MCUboot) needs to be flash at least once. + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: ttgo_t8c3 + :goals: build + +The usual ``flash`` target will work with the ``ttgo_t8c3`` board +configuration. Here is an example for the :ref:`hello_world` +application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: ttgo_t8c3 + :goals: flash + +The default baud rate for the Lilygo TTGO T8-C3 is set to 1500000bps. If experiencing issues when flashing, +try using different values by using ``--esp-baud-rate `` option during +``west flash`` (e.g. ``west flash --esp-baud-rate 115200``). + +You can also open the serial monitor using the following command: + +.. code-block:: shell + + west espressif monitor + +After the board has automatically reset and booted, you should see the following +message in the monitor: + +.. code-block:: console + + ***** Booting Zephyr OS vx.x.x-xxx-gxxxxxxxxxxxx ***** + Hello World! ttgo_t8c3 + +Sample applications +=================== + +The following samples will run out of the box on the TTGO T8-C3 board. + +To build the blinky sample: + +.. zephyr-app-commands:: + :tool: west + :app: samples/basic/blinky + :board: ttgo_t8c3 + :goals: build + +To build the bluetooth beacon sample: + +.. zephyr-app-commands:: + :tool: west + :app: samples/bluetooth/beacon + :board: ttgo_t8c3 + :goals: build + + +Related Documents +***************** +.. _`Lilygo TTGO T8-C3 schematic`: https://github.com/Xinyuan-LilyGO/T8-C3/blob/main/Schematic/T8-C3_V1.1.pdf +.. _`Lilygo github repo`: https://github.com/Xinyuan-LilyGo +.. _`Espressif ESP32-C3 datasheet`: https://www.espressif.com/sites/default/files/documentation/esp32-c3_datasheet_en.pdf +.. _`Espressif ESP32-C3 technical reference manual`: https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf +.. _`OpenOCD ESP32`: https://github.com/espressif/openocd-esp32/releases diff --git a/boards/lilygo/ttgo_t8c3/support/openocd.cfg b/boards/lilygo/ttgo_t8c3/support/openocd.cfg new file mode 100644 index 0000000000000..02754ff2a73c1 --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/support/openocd.cfg @@ -0,0 +1,6 @@ +set ESP_RTOS none + +source [find interface/esp_usb_jtag.cfg] + +source [find target/esp32c3.cfg] +adapter_khz 5000 diff --git a/boards/lilygo/ttgo_t8c3/ttgo_t8c3-pinctrl.dtsi b/boards/lilygo/ttgo_t8c3/ttgo_t8c3-pinctrl.dtsi new file mode 100644 index 0000000000000..72cf16f3765ae --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/ttgo_t8c3-pinctrl.dtsi @@ -0,0 +1,51 @@ +/* + * Copyright 2024 Lothar Felten + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + output-high; + }; + group2 { + pinmux = ; + bias-pull-up; + }; + }; + + spim2_default: spim2_default { + group1 { + pinmux = , + ; + }; + /* GPIO6 is CS */ + group2 { + pinmux = ; + output-low; + }; + }; + + i2c0_default: i2c0_default { + group1 { + pinmux = , + ; + bias-pull-up; + drive-open-drain; + output-high; + }; + }; + + twai_default: twai_default { + group1 { + pinmux = , + ; + }; + }; +}; diff --git a/boards/lilygo/ttgo_t8c3/ttgo_t8c3.dts b/boards/lilygo/ttgo_t8c3/ttgo_t8c3.dts new file mode 100644 index 0000000000000..a38f5777762dd --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/ttgo_t8c3.dts @@ -0,0 +1,133 @@ +/* + * Copyright 2024 Lothar Felten + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "ttgo_t8c3-pinctrl.dtsi" + +/ { + model = "Lilygo TTGO T8-C3"; + compatible = "lilygo,ttgo-t8c3"; + + aliases { + led0 = &green_led; + i2c-0 = &i2c0; + watchdog0 = &wdt0; + }; + + chosen { + zephyr,sram = &sram0; + zephyr,console = &usb_serial; + zephyr,shell-uart = &usb_serial; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; + zephyr,canbus = &twai; + }; + + leds { + compatible = "gpio-leds"; + green_led: led_0 { + gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>; + label = "Green - LED0"; + }; + }; +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&usb_serial { + status = "okay"; +}; + +&i2c0 { + status = "okay"; + clock-frequency = ; + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; +}; + +&trng0 { + status = "okay"; +}; + +&spi2 { + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + pinctrl-0 = <&spim2_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; + +&wdt0 { + status = "okay"; +}; + +&timer0 { + status = "okay"; +}; + +&timer1 { + status = "okay"; +}; + +&twai { + status = "okay"; + pinctrl-0 = <&twai_default>; + pinctrl-names = "default"; +}; + +&wifi { + status = "okay"; +}; + +&esp32_bt_hci{ + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000F000>; + read-only; + }; + + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 0x00100000>; + }; + + slot1_partition: partition@110000 { + label = "image-1"; + reg = <0x00110000 0x00100000>; + }; + + scratch_partition: partition@210000 { + label = "image-scratch"; + reg = <0x00210000 0x00040000>; + }; + + storage_partition: partition@250000 { + label = "storage"; + reg = <0x00250000 0x00006000>; + }; + }; +}; diff --git a/boards/lilygo/ttgo_t8c3/ttgo_t8c3.yaml b/boards/lilygo/ttgo_t8c3/ttgo_t8c3.yaml new file mode 100644 index 0000000000000..e2fc320098a43 --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/ttgo_t8c3.yaml @@ -0,0 +1,18 @@ +identifier: ttgo_t8c3 +name: TTGO T8C3 +type: mcu +arch: riscv +toolchain: + - zephyr +supported: + - gpio + - i2c + - spi + - uart + - watchdog + - can +testing: + ignore_tags: + - net + - bluetooth +vendor: lilygo diff --git a/boards/lilygo/ttgo_t8c3/ttgo_t8c3_defconfig b/boards/lilygo/ttgo_t8c3/ttgo_t8c3_defconfig new file mode 100644 index 0000000000000..ef633ce56a18e --- /dev/null +++ b/boards/lilygo/ttgo_t8c3/ttgo_t8c3_defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_MAIN_STACK_SIZE=2048 + +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=y diff --git a/boards/luatos/esp32c3_luatos_core/Kconfig.defconfig b/boards/luatos/esp32c3_luatos_core/Kconfig.defconfig index 054ac2567296e..f6ad1adaa1cb9 100644 --- a/boards/luatos/esp32c3_luatos_core/Kconfig.defconfig +++ b/boards/luatos/esp32c3_luatos_core/Kconfig.defconfig @@ -9,7 +9,3 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 51200 if WIFI default 40960 if BT default 4096 - -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice diff --git a/boards/luatos/esp32c3_luatos_core/doc/index.rst b/boards/luatos/esp32c3_luatos_core/doc/index.rst index 7b6bbacf98213..21c9a7bfc5998 100644 --- a/boards/luatos/esp32c3_luatos_core/doc/index.rst +++ b/boards/luatos/esp32c3_luatos_core/doc/index.rst @@ -54,7 +54,6 @@ Current Zephyr's ESP32C3_LUATOS_CORE board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dts b/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dts index 00a6983355781..cfdfd771d13ec 100644 --- a/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dts +++ b/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dts @@ -15,5 +15,6 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; }; diff --git a/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi b/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi index 2972e4725f1d2..c7b5b62754759 100644 --- a/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi +++ b/boards/luatos/esp32c3_luatos_core/esp32c3_luatos_core.dtsi @@ -43,10 +43,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -94,7 +90,6 @@ status = "disabled"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &flash0 { @@ -135,3 +130,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/luatos/esp32c3_luatos_core/support/openocd.cfg b/boards/luatos/esp32c3_luatos_core/support/openocd.cfg index b93b20ba46ea5..12065b5e63047 100644 --- a/boards/luatos/esp32c3_luatos_core/support/openocd.cfg +++ b/boards/luatos/esp32c3_luatos_core/support/openocd.cfg @@ -9,4 +9,4 @@ source [find interface/esp_usb_jtag.cfg] # source [find interface/ftdi/esp32_devkitj_v1.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/luatos/esp32s3_luatos_core/Kconfig.defconfig b/boards/luatos/esp32s3_luatos_core/Kconfig.defconfig index 093805f235b01..a14482e325d1c 100644 --- a/boards/luatos/esp32s3_luatos_core/Kconfig.defconfig +++ b/boards/luatos/esp32s3_luatos_core/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_ESP32S3_LUATOS_CORE_ESP32S3_PROCPU || BOARD_ESP32S3_LUATOS_CORE_ESP32S3_PROCPU_USB if BOARD_ESP32S3_LUATOS_CORE_ESP32S3_APPCPU || BOARD_ESP32S3_LUATOS_CORE_ESP32S3_APPCPU_USB diff --git a/boards/luatos/esp32s3_luatos_core/doc/index.rst b/boards/luatos/esp32s3_luatos_core/doc/index.rst index 94bc0f685d392..687851ea6a441 100644 --- a/boards/luatos/esp32s3_luatos_core/doc/index.rst +++ b/boards/luatos/esp32s3_luatos_core/doc/index.rst @@ -89,7 +89,6 @@ Current Zephyr's ESP32S3-LUATOS-Core board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | @@ -232,7 +231,7 @@ If CH343 chip is disabled, You need use the following command to build: .. zephyr-app-commands:: :zephyr-app: samples/hello_world - :board: esp32s3_luatos_core_usb/esp32s3/procpu + :board: esp32s3_luatos_core/esp32s3/procpu/usb :goals: build The usual ``flash`` target will work with the ``esp32s3_luatos_core`` board diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi index efaded4d02d6f..60365fdcd65a3 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core.dtsi @@ -31,14 +31,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -85,7 +77,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { @@ -150,3 +141,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.dts b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.dts index e33c7f43401af..510e587925ea7 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.dts +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.yaml b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.yaml index 05aac04c00fb8..ae7e008793e8b 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.yaml +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu.yaml @@ -1,5 +1,5 @@ identifier: esp32s3_luatos_core/esp32s3/appcpu -name: ESP32-S3 LuatOS Core +name: ESP32-S3 LuatOS Core APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.dts b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.dts index 7a251b40e04f1..b36963af0134b 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.dts +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.yaml b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.yaml index cb2ac02717b5f..3a80a65a46a91 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.yaml +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_appcpu_usb.yaml @@ -1,5 +1,5 @@ identifier: esp32s3_luatos_core/esp32s3/appcpu/usb -name: ESP32-S3 LuatOS Core USB +name: ESP32-S3 LuatOS Core APPCPU USB type: mcu arch: xtensa toolchain: diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.dts b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.dts index 8c44d0cebd794..2a04d5680668a 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.dts +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.dts @@ -26,5 +26,6 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; }; diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.yaml b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.yaml index 2a1bb02cc2f2c..6d564843a1c32 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.yaml +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu.yaml @@ -1,5 +1,5 @@ identifier: esp32s3_luatos_core/esp32s3/procpu -name: ESP32-S3 LuatOS Core +name: ESP32-S3 LuatOS Core PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.dts b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.dts index 0a707724f9f0a..a4182a4ba80ae 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.dts +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.dts @@ -25,6 +25,7 @@ zephyr,console = &usb_serial; zephyr,shell-uart = &usb_serial; zephyr,flash = &flash0; + zephyr,bt_hci = &esp32_bt_hci; }; }; diff --git a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.yaml b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.yaml index f1cd4d19d5a6b..7e160d6811716 100644 --- a/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.yaml +++ b/boards/luatos/esp32s3_luatos_core/esp32s3_luatos_core_procpu_usb.yaml @@ -1,5 +1,5 @@ identifier: esp32s3_luatos_core/esp32s3/procpu/usb -name: ESP32-S3 LuatOS Core USB +name: ESP32-S3 LuatOS Core PROCPU USB type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_atom_lite/Kconfig.defconfig b/boards/m5stack/m5stack_atom_lite/Kconfig.defconfig index d56d34b22d783..2b223f5409bed 100644 --- a/boards/m5stack/m5stack_atom_lite/Kconfig.defconfig +++ b/boards/m5stack/m5stack_atom_lite/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_M5STACK_ATOM_LITE_ESP32_PROCPU if BOARD_M5STACK_ATOM_LITE_ESP32_APPCPU diff --git a/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_appcpu.dts b/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_appcpu.dts index 59a908a3feff8..f5db6e76116e0 100644 --- a/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_appcpu.dts +++ b/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_procpu.dts b/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_procpu.dts index 53f6175e4d1ef..3a8557f679436 100644 --- a/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_procpu.dts +++ b/boards/m5stack/m5stack_atom_lite/m5stack_atom_lite_procpu.dts @@ -24,6 +24,7 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -53,14 +54,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -188,3 +181,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/m5stack/m5stack_atoms3/Kconfig.defconfig b/boards/m5stack/m5stack_atoms3/Kconfig.defconfig index c0dadaceeb4d1..f3b59178417ce 100644 --- a/boards/m5stack/m5stack_atoms3/Kconfig.defconfig +++ b/boards/m5stack/m5stack_atoms3/Kconfig.defconfig @@ -14,10 +14,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_M5STACK_ATOMS3_ESP32S3_PROCPU if BOARD_M5STACK_ATOMS3_ESP32S3_APPCPU diff --git a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.dts b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.dts index 91bcff6c0079d..a117ee02922fb 100644 --- a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.dts +++ b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.yaml b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.yaml index a8efc9aad007d..30c20695c27e7 100644 --- a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.yaml +++ b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_atoms3/esp32s3/appcpu -name: M5Stack AtomS3 +name: M5Stack AtomS3 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.dts b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.dts index 1b5a5da32da10..dd20fb00a8d9e 100644 --- a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.dts +++ b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.dts @@ -9,6 +9,7 @@ #include "m5stack_atoms3-pinctrl.dtsi" #include "grove_connectors.dtsi" #include +#include / { model = "M5Stack AtomS3 PROCPU"; @@ -21,6 +22,7 @@ zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; zephyr,display = &st7789v; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -48,14 +50,45 @@ regulator-boot-on; }; -}; + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi2>; + dc-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; /* G33 */ + reset-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; /* G34 */ + write-only; + #address-cells = <1>; + #size-cells = <0>; + + st7789v: st7789v@0 { + compatible = "sitronix,st7789v"; + reg = <0>; + mipi-max-frequency = <27000000>; + + width = <128>; + height = <128>; + x-offset = <2>; + y-offset = <1>; + + vcom = <0x28>; + gctrl = <0x35>; + vrhs = <0x10>; + vdvs = <0x20>; + mdac = <0x00>; + gamma = <0x01>; + colmod = <0x55>; + lcm = <0x0c>; + porch-param = [0c 0c 00 33 33]; + cmd2en-param = [5a 69 02 00]; + pwctrl1-param = [a4 a1]; + pvgam-param = [d0 00 02 07 0a 28 32 44 42 06 0e 12 14 17]; + nvgam-param = [d0 00 02 07 0a 28 31 54 47 0e 1c 17 1b 1e]; + ram-param = [00 E0]; + rgb-param = [40 02 14]; + mipi-mode = ; + }; -&cpu0 { - clock-frequency = ; -}; + }; -&cpu1 { - clock-frequency = ; }; &usb_serial { @@ -99,36 +132,6 @@ status = "okay"; pinctrl-0 = <&spim2_default>; pinctrl-names = "default"; - - st7789v: st7789v@0 { - compatible = "sitronix,st7789v"; - reg = <0>; - spi-max-frequency = <27000000>; - cmd-data-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; /* G33 */ - reset-gpios = <&gpio1 2 GPIO_ACTIVE_LOW>; /* G34 */ - - width = <128>; - height = <128>; - x-offset = <2>; - y-offset = <1>; - - vcom = <0x28>; - gctrl = <0x35>; - vrhs = <0x10>; - vdvs = <0x20>; - mdac = <0x00>; - gamma = <0x01>; - colmod = <0x55>; - lcm = <0x0c>; - porch-param = [0c 0c 00 33 33]; - cmd2en-param = [5a 69 02 00]; - pwctrl1-param = [a4 a1]; - pvgam-param = [d0 00 02 07 0a 28 32 44 42 06 0e 12 14 17]; - nvgam-param = [d0 00 02 07 0a 28 31 54 47 0e 1c 17 1b 1e]; - ram-param = [00 E0]; - rgb-param = [40 02 14]; - }; - }; &gpio0 { @@ -185,3 +188,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.yaml b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.yaml index 4be28b02f83eb..082aa4e569925 100644 --- a/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.yaml +++ b/boards/m5stack/m5stack_atoms3/m5stack_atoms3_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_atoms3/esp32s3/procpu -name: M5Stack AtomS3 +name: M5Stack AtomS3 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_atoms3_lite/Kconfig.defconfig b/boards/m5stack/m5stack_atoms3_lite/Kconfig.defconfig index 8039b4762cde2..f0f262cd1f3a6 100644 --- a/boards/m5stack/m5stack_atoms3_lite/Kconfig.defconfig +++ b/boards/m5stack/m5stack_atoms3_lite/Kconfig.defconfig @@ -14,10 +14,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD config KERNEL_MEM_POOL default y -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_M5STACK_ATOMS3_LITE_ESP32S3_PROCPU if BOARD_M5STACK_ATOMS3_LITE_ESP32S3_APPCPU diff --git a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.dts b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.dts index 994c9b9a3b2b2..2323548e7fcd9 100644 --- a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.dts +++ b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.yaml b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.yaml index 0a641e9ef1275..004ed974675bd 100644 --- a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.yaml +++ b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_atoms3_lite/esp32s3/appcpu -name: M5Stack AtomS3-Lite +name: M5Stack AtomS3-Lite APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.dts b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.dts index 430de46a5548c..166ee2014ca01 100644 --- a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.dts +++ b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.dts @@ -22,6 +22,7 @@ zephyr,shell-uart = &usb_serial; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -42,14 +43,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "okay"; }; @@ -153,3 +146,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.yaml b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.yaml index 3012207d36de9..996732bc3dd00 100644 --- a/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.yaml +++ b/boards/m5stack/m5stack_atoms3_lite/m5stack_atoms3_lite_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_atoms3_lite/esp32s3/procpu -name: M5Stack AtomS3-Lite +name: M5Stack AtomS3-Lite PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_core2/Kconfig.defconfig b/boards/m5stack/m5stack_core2/Kconfig.defconfig index 2c0a21ef88da2..fd9614d6cbbfb 100644 --- a/boards/m5stack/m5stack_core2/Kconfig.defconfig +++ b/boards/m5stack/m5stack_core2/Kconfig.defconfig @@ -15,10 +15,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD config KERNEL_MEM_POOL default y -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - config GPIO_HOGS_INIT_PRIORITY default 70 diff --git a/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.dts b/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.dts index cd5cf5d0bf228..875d0eaea2ad0 100644 --- a/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.dts +++ b/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.yaml b/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.yaml index 8e5a51d07c7f0..a49668e954770 100644 --- a/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.yaml +++ b/boards/m5stack/m5stack_core2/m5stack_core2_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_core2/esp32/appcpu -name: M5Stack Core2 +name: M5Stack Core2 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_core2/m5stack_core2_procpu.dts b/boards/m5stack/m5stack_core2/m5stack_core2_procpu.dts index 7cd5bc187c9a4..841dcdf38bef1 100644 --- a/boards/m5stack/m5stack_core2/m5stack_core2_procpu.dts +++ b/boards/m5stack/m5stack_core2/m5stack_core2_procpu.dts @@ -34,6 +34,7 @@ zephyr,display = &ili9342c; zephyr,code-partition = &slot0_partition; zephyr,rtc = &pfc8563_rtc; + zephyr,bt-hci = &esp32_bt_hci; }; leds { @@ -73,14 +74,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &psram0 { reg = <0x3f800000 DT_SIZE_M(8)>; status = "disabled"; @@ -291,3 +284,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/m5stack/m5stack_core2/m5stack_core2_procpu.yaml b/boards/m5stack/m5stack_core2/m5stack_core2_procpu.yaml index b5f7a37910dde..5a95351e16df3 100644 --- a/boards/m5stack/m5stack_core2/m5stack_core2_procpu.yaml +++ b/boards/m5stack/m5stack_core2/m5stack_core2_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_core2/esp32/procpu -name: M5Stack Core2 +name: M5Stack Core2 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_stamps3/Kconfig.defconfig b/boards/m5stack/m5stack_stamps3/Kconfig.defconfig index 70493b8d4751d..903059dffbc8a 100644 --- a/boards/m5stack/m5stack_stamps3/Kconfig.defconfig +++ b/boards/m5stack/m5stack_stamps3/Kconfig.defconfig @@ -14,10 +14,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD config KERNEL_MEM_POOL default y -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_M5STACK_STAMPS3_ESP32S3_PROCPU if BOARD_M5STACK_STAMPS3_ESP32S3_APPCPU diff --git a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.dts b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.dts index a9e590b9bbf8b..ce947b579724c 100644 --- a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.dts +++ b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.yaml b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.yaml index eb4fcfcd02809..9443a7e09c65f 100644 --- a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.yaml +++ b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_stamps3/esp32s3/appcpu -name: M5Stack StampS3 +name: M5Stack StampS3 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.dts b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.dts index f832f4618ba4b..9e231fba57f0d 100644 --- a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.dts +++ b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.dts @@ -23,6 +23,7 @@ zephyr,shell-uart = &usb_serial; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -45,14 +46,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "okay"; }; @@ -193,3 +186,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.yaml b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.yaml index 99e14f59b1976..746a5d2916e7c 100644 --- a/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.yaml +++ b/boards/m5stack/m5stack_stamps3/m5stack_stamps3_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stack_stamps3/esp32s3/procpu -name: M5Stack StampS3 +name: M5Stack StampS3 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stickc_plus/Kconfig.defconfig b/boards/m5stack/m5stickc_plus/Kconfig.defconfig index aea1b614a01ac..a6b957227be56 100644 --- a/boards/m5stack/m5stickc_plus/Kconfig.defconfig +++ b/boards/m5stack/m5stickc_plus/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - config GPIO_HOGS_INIT_PRIORITY default 70 diff --git a/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.dts b/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.dts index 8b7e74fdd988c..1911e4fe56d55 100644 --- a/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.dts +++ b/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.yaml b/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.yaml index e436849ced4d1..ac94218909779 100644 --- a/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.yaml +++ b/boards/m5stack/m5stickc_plus/m5stickc_plus_appcpu.yaml @@ -1,5 +1,5 @@ identifier: m5stickc_plus/esp32/appcpu -name: M5StickC PLUS +name: M5StickC PLUS APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.dts b/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.dts index c1418ed51c335..28779d87ecb4b 100644 --- a/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.dts +++ b/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.dts @@ -9,6 +9,7 @@ #include "m5stickc_plus-pinctrl.dtsi" #include #include +#include / { model = "M5StickC Plus PROCPU"; @@ -33,6 +34,7 @@ zephyr,code-partition = &slot0_partition; zephyr,rtc = &bm8563; zephyr,display = &st7789v; + zephyr,bt-hci = &esp32_bt_hci; }; leds { @@ -58,14 +60,44 @@ zephyr,code = ; }; }; -}; - -&cpu0 { - clock-frequency = ; -}; -&cpu1 { - clock-frequency = ; + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi3>; + dc-gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + st7789v: st7789v@0 { + compatible = "sitronix,st7789v"; + reg = <0>; + mipi-max-frequency = <20000000>; + + width = <135>; + height = <240>; + x-offset = <53>; + y-offset = <40>; + + vcom = <0x28>; + gctrl = <0x35>; + vrhs = <0x10>; + vdvs = <0x20>; + mdac = <0x00>; + gamma = <0x01>; + colmod = <0x55>; + lcm = <0x2c>; + porch-param = [0c 0c 00 33 33]; + cmd2en-param = [5a 69 02 00]; + pwctrl1-param = [a4 a1]; + pvgam-param = [d0 00 02 07 0a 28 32 44 42 06 0e 12 14 17]; + nvgam-param = [d0 00 02 07 0a 28 31 54 47 0e 1c 17 1b 1e]; + ram-param = [00 F0]; + rgb-param = [40 02 14]; + mipi-mode = ; + }; + }; }; &uart0 { @@ -160,34 +192,6 @@ status = "okay"; pinctrl-0 = <&spim3_default>; pinctrl-names = "default"; - st7789v: st7789v@0 { - compatible = "sitronix,st7789v"; - reg = <0>; - spi-max-frequency = <20000000>; - cmd-data-gpios = <&gpio0 23 GPIO_ACTIVE_LOW>; - reset-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; - - width = <135>; - height = <240>; - x-offset = <53>; - y-offset = <40>; - - vcom = <0x28>; - gctrl = <0x35>; - vrhs = <0x10>; - vdvs = <0x20>; - mdac = <0x00>; - gamma = <0x01>; - colmod = <0x55>; - lcm = <0x2c>; - porch-param = [0c 0c 00 33 33]; - cmd2en-param = [5a 69 02 00]; - pwctrl1-param = [a4 a1]; - pvgam-param = [d0 00 02 07 0a 28 32 44 42 06 0e 12 14 17]; - nvgam-param = [d0 00 02 07 0a 28 31 54 47 0e 1c 17 1b 1e]; - ram-param = [00 F0]; - rgb-param = [40 02 14]; - }; }; &timer0 { @@ -248,3 +252,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.yaml b/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.yaml index ad8985b55db08..69741a72d8f51 100644 --- a/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.yaml +++ b/boards/m5stack/m5stickc_plus/m5stickc_plus_procpu.yaml @@ -1,5 +1,5 @@ identifier: m5stickc_plus/esp32/procpu -name: M5StickC PLUS +name: M5StickC PLUS PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/m5stack/stamp_c3/Kconfig.defconfig b/boards/m5stack/stamp_c3/Kconfig.defconfig index 4ce7fe02e1200..dcc3a4225487d 100644 --- a/boards/m5stack/stamp_c3/Kconfig.defconfig +++ b/boards/m5stack/stamp_c3/Kconfig.defconfig @@ -9,11 +9,3 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 51200 if WIFI default 40960 if BT default 4096 - -if BT - -choice BT_HCI_BUS_TYPE - default BT_ESP32 -endchoice - -endif # BT diff --git a/boards/m5stack/stamp_c3/stamp_c3.dts b/boards/m5stack/stamp_c3/stamp_c3.dts index 56353da3d8135..ef026e9445441 100644 --- a/boards/m5stack/stamp_c3/stamp_c3.dts +++ b/boards/m5stack/stamp_c3/stamp_c3.dts @@ -20,6 +20,7 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -38,10 +39,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -93,7 +90,6 @@ status = "disabled"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &flash0 { @@ -134,3 +130,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/m5stack/stamp_c3/support/openocd.cfg b/boards/m5stack/stamp_c3/support/openocd.cfg index 5db52f70d8340..92e47fabefb39 100644 --- a/boards/m5stack/stamp_c3/support/openocd.cfg +++ b/boards/m5stack/stamp_c3/support/openocd.cfg @@ -6,4 +6,4 @@ set ESP_RTOS none source [find interface/esp_usb_jtag.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/madmachine/mm_swiftio/mm_swiftio.dts b/boards/madmachine/mm_swiftio/mm_swiftio.dts index b9994d1e8c115..e4212cd8294c6 100644 --- a/boards/madmachine/mm_swiftio/mm_swiftio.dts +++ b/boards/madmachine/mm_swiftio/mm_swiftio.dts @@ -192,7 +192,7 @@ &csi { status = "okay"; - sensor = <&ov7725>; + source = <&ov7725>; pinctrl-0 = <&pinmux_csi>; pinctrl-names = "default"; diff --git a/boards/makerdiary/nrf52840_mdk/nrf52840_mdk.dts b/boards/makerdiary/nrf52840_mdk/nrf52840_mdk.dts index 2439b0c2aca0b..e405794d79573 100644 --- a/boards/makerdiary/nrf52840_mdk/nrf52840_mdk.dts +++ b/boards/makerdiary/nrf52840_mdk/nrf52840_mdk.dts @@ -82,7 +82,6 @@ red-pwm-led = &pwm_led1_red; blue-pwm-led = &pwm_led2_blue; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/makerdiary/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.yaml b/boards/makerdiary/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.yaml index 5aac2cd57016e..e714e1cafb5ee 100644 --- a/boards/makerdiary/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.yaml +++ b/boards/makerdiary/nrf52840_mdk_usb_dongle/nrf52840_mdk_usb_dongle.yaml @@ -10,7 +10,6 @@ toolchain: - xtools supported: - usb_device - - usb_cdc - ble - watchdog - counter diff --git a/boards/mediatek/mt8195_adsp/Kconfig.defconfig b/boards/mediatek/mt8195_adsp/Kconfig.defconfig new file mode 100644 index 0000000000000..31f557670b15f --- /dev/null +++ b/boards/mediatek/mt8195_adsp/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_MT8195_ADSP + +config BOARD + default "mt8195_adsp" + +endif # BOARD_MT8195_ADSP diff --git a/boards/mediatek/mt8195_adsp/Kconfig.mt8195_adsp b/boards/mediatek/mt8195_adsp/Kconfig.mt8195_adsp new file mode 100644 index 0000000000000..2cffa50962ed1 --- /dev/null +++ b/boards/mediatek/mt8195_adsp/Kconfig.mt8195_adsp @@ -0,0 +1,5 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MT8195_ADSP + bool "Mediatek MT8195 Audio DSP" diff --git a/boards/mediatek/mt8195_adsp/board.yml b/boards/mediatek/mt8195_adsp/board.yml new file mode 100644 index 0000000000000..22c31deb1a010 --- /dev/null +++ b/boards/mediatek/mt8195_adsp/board.yml @@ -0,0 +1,5 @@ +boards: + - name: mt8195_adsp + vendor: mediatek + socs: + - name: mt8195_adsp diff --git a/boards/mediatek/mt8195_adsp/mt8195_adsp.dts b/boards/mediatek/mt8195_adsp/mt8195_adsp.dts new file mode 100644 index 0000000000000..c26e2dd0f4017 --- /dev/null +++ b/boards/mediatek/mt8195_adsp/mt8195_adsp.dts @@ -0,0 +1,95 @@ +/* Copyright 2023 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/dts-v1/; +/ { + +#address-cells = <1>; +#size-cells = <1>; + +sram0: memory@40000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x40000000 DT_SIZE_K(256)>; +}; + +dram0: memory@60000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0x60000000 DT_SIZE_M(17)>; +}; + +soc { + #address-cells = <1>; + #size-cells = <1>; + + cpuclk: cpuclk@10000000 { + compatible = "mediatek,mt8195_cpuclk"; + reg = <0x10000000 380>; + cg_reg = <0x10720180>; + pll_ctrl_reg = <0x1000c7e0>; + freqs_mhz = <26 370 540 720>; + }; + + core_intc: core_intc@0 { + compatible = "cdns,xtensa-core-intc"; + reg = <0 4>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + intc1: intc@10680130 { + compatible = "mediatek,adsp_intc"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x10680130 4>; + status-reg = <0x10680150>; + interrupts = <1 0 0>; + mask = <0x3ffffff0>; + interrupt-parent = <&core_intc>; + }; + + intc23: intc@108030f4 { + compatible = "mediatek,adsp_intc"; + interrupt-controller; + #interrupt-cells = <3>; + reg = <0x108030f4 4>; + status-reg = <0x108030fc>; + interrupts = <23 0 0>; + mask = <0xffff>; + interrupt-parent = <&core_intc>; + }; + + ostimer64: ostimer64@1080d080 { + compatible = "mediatek,ostimer64"; + reg = <0x1080d080 28>; + }; + + ostimer0: ostimer@1080d000 { + compatible = "mediatek,ostimer"; + reg = <0x1080d000 16>; + interrupt-parent = <&intc23>; + interrupts = <11 0 0>; + }; + + mbox0: mbox@10816000 { + compatible = "mediatek,mbox"; + reg = <0x10816000 56>; + interrupt-parent = <&intc23>; + interrupts = <0 0 0>; + }; + + mbox1: mbox@10817000 { + compatible = "mediatek,mbox"; + reg = <0x10817000 56>; + interrupt-parent = <&intc23>; + interrupts = <1 0 0>; + }; +}; /* soc */ + +chosen { }; +aliases { }; + +}; diff --git a/boards/mediatek/mt8195_adsp/mt8195_adsp_defconfig b/boards/mediatek/mt8195_adsp/mt8195_adsp_defconfig new file mode 100644 index 0000000000000..15579f71ae808 --- /dev/null +++ b/boards/mediatek/mt8195_adsp/mt8195_adsp_defconfig @@ -0,0 +1,5 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_MT8195_ADSP=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=13000000 diff --git a/boards/microchip/m2gl025_miv/board.cmake b/boards/microchip/m2gl025_miv/board.cmake index 2919ac7874201..b2d72a05eca3d 100644 --- a/boards/microchip/m2gl025_miv/board.cmake +++ b/boards/microchip/m2gl025_miv/board.cmake @@ -3,3 +3,8 @@ set(SUPPORTED_EMU_PLATFORMS renode) set(RENODE_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/support/m2gl025_miv.resc) set(RENODE_UART sysbus.uart) + +set_ifndef(BOARD_SIM_RUNNER renode) +set_ifndef(BOARD_ROBOT_RUNNER renode-robot) +include(${ZEPHYR_BASE}/boards/common/renode.board.cmake) +include(${ZEPHYR_BASE}/boards/common/renode_robot.board.cmake) diff --git a/boards/microchip/m2gl025_miv/m2gl025_miv.yaml b/boards/microchip/m2gl025_miv/m2gl025_miv.yaml index 3f60b02c59e8f..4ba9e126a7fea 100644 --- a/boards/microchip/m2gl025_miv/m2gl025_miv.yaml +++ b/boards/microchip/m2gl025_miv/m2gl025_miv.yaml @@ -12,4 +12,7 @@ testing: ignore_tags: - net - bluetooth + renode: + uart: sysbus.uart + resc: boards/microchip/m2gl025_miv/support/m2gl025_miv.resc vendor: microchip diff --git a/boards/microchip/m2gl025_miv/support/m2gl025_miv.resc b/boards/microchip/m2gl025_miv/support/m2gl025_miv.resc index 2227e89bff282..d45eb5e7855d6 100644 --- a/boards/microchip/m2gl025_miv/support/m2gl025_miv.resc +++ b/boards/microchip/m2gl025_miv/support/m2gl025_miv.resc @@ -12,6 +12,6 @@ cpu PerformanceInMips 4 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/microchip/mpfs_icicle/board.yml b/boards/microchip/mpfs_icicle/board.yml index a4976aa909b42..f97e2409c14cd 100644 --- a/boards/microchip/mpfs_icicle/board.yml +++ b/boards/microchip/mpfs_icicle/board.yml @@ -3,3 +3,5 @@ board: vendor: microchip socs: - name: polarfire + variants: + - name: 'smp' diff --git a/boards/microchip/mpfs_icicle/doc/index.rst b/boards/microchip/mpfs_icicle/doc/index.rst index 7a599081793c4..203745dc4eeb3 100644 --- a/boards/microchip/mpfs_icicle/doc/index.rst +++ b/boards/microchip/mpfs_icicle/doc/index.rst @@ -23,6 +23,11 @@ Applications for the ``mpfs_icicle`` board configuration can be built as usual :board: mpfs_icicle :goals: build +To build the default SMP capable variant + +.. zephyr-app-commands:: + :board: mpfs_icicle/polarfire/smp + :goals: build Flashing ======== diff --git a/boards/microchip/mpfs_icicle/mpfs_icicle_smp.dts b/boards/microchip/mpfs_icicle/mpfs_icicle_smp.dts new file mode 100644 index 0000000000000..6d122ed5d97b7 --- /dev/null +++ b/boards/microchip/mpfs_icicle/mpfs_icicle_smp.dts @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2020-2021 Microchip Technology Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include + +/ { + model = "Microchip PolarFire-SoC Icicle Kit"; + compatible = "microchip,mpfs-icicle-kit", "microchip,mpfs"; + + cpus { + cpu@0 { + status = "disabled"; + }; + }; + + aliases { + led0 = &led0; + sw0 = &sw0; + i2c0 = &i2c0; + i2c1 = &i2c1; + }; + + chosen { + zephyr,console = &uart1; + zephyr,shell-uart = &uart1; + zephyr,sram = &sram1; + }; + + leds { + compatible = "gpio-leds"; + + led0: led0 { + gpios = <&gpio2 16 GPIO_ACTIVE_LOW>; + label = "LED_0"; + }; + }; + + keys { + compatible = "gpio-keys"; + sw0: sw0 { + gpios = <&gpio2 30 GPIO_ACTIVE_LOW>; + label = "SW_0"; + zephyr,code = ; + }; + }; +}; + +&uart1 { + status = "okay"; + current-speed = <115200>; + clock-frequency = <150000000>; +}; + +&qspi0 { + status = "okay"; + qspi_flash: spi-nor-flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <5000000>; + size = ; + jedec-id = [20 ba 19]; + }; +}; + +&spi1 { + status = "okay"; +}; + +&syscontroller_qspi { + status = "okay"; + sys_ctrl_flash: spi-nor-flash@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <5000000>; + }; +}; + +&gpio2 { + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "okay"; +}; diff --git a/boards/microchip/mpfs_icicle/mpfs_icicle_smp.yaml b/boards/microchip/mpfs_icicle/mpfs_icicle_smp.yaml new file mode 100644 index 0000000000000..2f7983ca09292 --- /dev/null +++ b/boards/microchip/mpfs_icicle/mpfs_icicle_smp.yaml @@ -0,0 +1,12 @@ +identifier: mpfs_icicle/polarfire/smp +name: Microchip PolarFire ICICLE kit (SMP) +type: mcu +arch: riscv +toolchain: + - zephyr +ram: 3840 +testing: + ignore_tags: + - net + - bluetooth +vendor: microchip diff --git a/boards/microchip/mpfs_icicle/mpfs_icicle_smp_defconfig b/boards/microchip/mpfs_icicle/mpfs_icicle_smp_defconfig new file mode 100644 index 0000000000000..529171d1c46da --- /dev/null +++ b/boards/microchip/mpfs_icicle/mpfs_icicle_smp_defconfig @@ -0,0 +1,14 @@ +CONFIG_MPFS_HAL=n +CONFIG_BASE64=y +CONFIG_INCLUDE_RESET_VECTOR=y +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_XIP=n +CONFIG_INIT_STACKS=y +CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000 +CONFIG_GPIO=y +CONFIG_I2C=y +CONFIG_SMP=y +CONFIG_RV_BOOT_HART=1 +CONFIG_MP_MAX_NUM_CPUS=4 diff --git a/boards/microchip/mpfs_icicle/support/mpfs250t.resc b/boards/microchip/mpfs_icicle/support/mpfs250t.resc index 8892b2839ded9..29005c8f1988a 100644 --- a/boards/microchip/mpfs_icicle/support/mpfs250t.resc +++ b/boards/microchip/mpfs_icicle/support/mpfs250t.resc @@ -12,6 +12,6 @@ e51 PerformanceInMips 80 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/mikroe/clicker_ra4m1/Kconfig.mikroe_clicker_ra4m1 b/boards/mikroe/clicker_ra4m1/Kconfig.mikroe_clicker_ra4m1 new file mode 100644 index 0000000000000..1fe44feec084a --- /dev/null +++ b/boards/mikroe/clicker_ra4m1/Kconfig.mikroe_clicker_ra4m1 @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Ian Morris +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MIKROE_CLICKER_RA4M1 + select SOC_R7FA4M1AB3CFM diff --git a/boards/mikroe/clicker_ra4m1/board.cmake b/boards/mikroe/clicker_ra4m1/board.cmake new file mode 100644 index 0000000000000..3f00aea418dfe --- /dev/null +++ b/boards/mikroe/clicker_ra4m1/board.cmake @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Ian Morris +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(pyocd "--target=r7fa4m1ab") + +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/mikroe/clicker_ra4m1/board.yml b/boards/mikroe/clicker_ra4m1/board.yml new file mode 100644 index 0000000000000..1635cd26a5dc0 --- /dev/null +++ b/boards/mikroe/clicker_ra4m1/board.yml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Ian Morris +# SPDX-License-Identifier: Apache-2.0 + +board: + name: mikroe_clicker_ra4m1 + vendor: mikroe + socs: + - name: r7fa4m1ab3cfm diff --git a/boards/mikroe/clicker_ra4m1/doc/img/mikroe_clicker_ra4m1.jpg b/boards/mikroe/clicker_ra4m1/doc/img/mikroe_clicker_ra4m1.jpg new file mode 100644 index 0000000000000..0d9acc54989eb Binary files /dev/null and b/boards/mikroe/clicker_ra4m1/doc/img/mikroe_clicker_ra4m1.jpg differ diff --git a/boards/mikroe/clicker_ra4m1/doc/index.rst b/boards/mikroe/clicker_ra4m1/doc/index.rst new file mode 100644 index 0000000000000..5af9aa1125af2 --- /dev/null +++ b/boards/mikroe/clicker_ra4m1/doc/index.rst @@ -0,0 +1,87 @@ +.. _mikroe_clicker_ra4m1: + +Mikroe Clicker RA4M1 +#################### + +Overview +******** + +The Mikroe Clicker RA4M1 development board contains a Renesas Cortex-M4 based +R7FA4M1AB3CFM Microcontroller operating at up to 48 MHz with 256 KB of Flash +memory and 32 KB of SRAM. + +.. figure:: img/mikroe_clicker_ra4m1.jpg + :align: center + :alt: Clicker RA4M1 + + Clicker RA4M1 (Credit: MikroElektronika d.o.o.) + +Hardware +******** + +The Clicker RA4M1 board contains a USB Type-C connector, two LEDs, two push +buttons, and a reset button. It has J-Link onboard and mikroBUS socket for +interfacing with external electronics. For more information about the +development board see the `Clicker RA4M1 website`_. + +Supported Features +================== + +The Zephyr Mikroe Clicker RA4M1 configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | GPIO output | +| | | GPIO input | ++-----------+------------+-------------------------------------+ + +Other hardware features have not been enabled yet for this board. + +The default configuration can be found in the defconfig file: +:zephyr_file:`boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1_defconfig`. + +Programming and debugging +************************* + +Building & Flashing +=================== + +You can build and flash an application in the usual way (See +:ref:`build_an_application` and +:ref:`application_run` for more details). + +Here is an example for building and flashing the :zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: mikroe_clicker_ra4m1 + :goals: build flash + +Debugging +========= + +Debugging also can be done in the usual way. +The following command is debugging the :zephyr:code-sample:`blinky` application. +Also, see the instructions specific to the debug server that you use. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: mikroe_clicker_ra4m1 + :maybe-skip-config: + :goals: debug + +References +********** + +.. target-notes:: + +.. _Clicker RA4M1 website: + https://www.mikroe.com/ra4m1-clicker diff --git a/boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1.dts b/boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1.dts new file mode 100644 index 0000000000000..b15242c5fea89 --- /dev/null +++ b/boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1.dts @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2024 Ian Morris + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include +#include + +/ { + model = "Mikroe Clicker RA4M1"; + compatible = "renesas,r7fa4m1ab3cfm"; + + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + ld1: led_1 { + gpios = <&ioport4 9 GPIO_ACTIVE_HIGH>; + label = "User LED 1"; + }; + ld2: led_2 { + gpios = <&ioport4 8 GPIO_ACTIVE_HIGH>; + label = "User LED 2"; + }; + }; + + buttons { + compatible = "gpio-keys"; + btn1: button_1 { + gpios = <&ioport3 4 GPIO_ACTIVE_LOW>; + label = "User Button 1"; + zephyr,code = ; + }; + }; + + aliases { + led0 = &ld1; + led1 = &ld2; + sw0 = &btn1; + }; +}; + +&pinctrl { + sci0_default: sci0_default { + group1 { + pinmux = , ; + }; + }; +}; + +&sci0 { + status = "okay"; + pinctrl-0 = <&sci0_default>; + pinctrl-names = "default"; + uart0: uart { + current-speed = <115200>; + status = "okay"; + }; +}; + +&ioport3 { + status = "okay"; +}; + +&ioport4 { + status = "okay"; +}; + +&fcu { + status = "okay"; +}; + +&mosc { + status = "okay"; + clock-frequency = <12000000>; +}; + +&cgc { + clock-source = <&mosc>; + iclk-div = <1>; + pclka-div = <1>; + pclkb-div = <2>; + pclkc-div = <1>; + pclkd-div = <1>; + fclk-div = <2>; +}; diff --git a/boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1.yaml b/boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1.yaml new file mode 100644 index 0000000000000..9cc16dc9c8df9 --- /dev/null +++ b/boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1.yaml @@ -0,0 +1,14 @@ +identifier: mikroe_clicker_ra4m1 +name: Mikroe Clicker RA4M1 +vendor: mikroe +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 32 +flash: 256 +supported: + - gpio + - uart diff --git a/boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1_defconfig b/boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1_defconfig new file mode 100644 index 0000000000000..3d89bdc283d4e --- /dev/null +++ b/boards/mikroe/clicker_ra4m1/mikroe_clicker_ra4m1_defconfig @@ -0,0 +1,22 @@ +# Copyright (c) 2024 Ian Morris +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=12000000 + +CONFIG_BUILD_OUTPUT_HEX=y + +# enable uart driver +CONFIG_SERIAL=y + +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# enable GPIO +CONFIG_GPIO=y + +# enable pin controller +CONFIG_PINCTRL=y + +# enable Clocks +CONFIG_CLOCK_CONTROL=y diff --git a/boards/mikroe/mini_m4_for_stm32/support/openocd.cfg b/boards/mikroe/mini_m4_for_stm32/support/openocd.cfg index b97b1a0527a27..4d5e4008c4039 100644 --- a/boards/mikroe/mini_m4_for_stm32/support/openocd.cfg +++ b/boards/mikroe/mini_m4_for_stm32/support/openocd.cfg @@ -6,8 +6,8 @@ transport select hla_swd source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate connect_assert_srst diff --git a/boards/native/doc/bsim_boards_design.rst b/boards/native/doc/bsim_boards_design.rst index 6165f76a438dc..7fef9d1b5228b 100644 --- a/boards/native/doc/bsim_boards_design.rst +++ b/boards/native/doc/bsim_boards_design.rst @@ -7,6 +7,7 @@ Bsim boards * :ref:`Simulated nRF52833 (nrf52_bsim)` * :ref:`Simulated nRF5340 (nrf5340bsim)` +* :ref:`Simulated nRF54L15 (nrf54l15bsim)` .. contents:: Table of contents :depth: 2 @@ -20,8 +21,8 @@ These boards are postfixed with `_bsim` as they use BabbleSim_ These boards use the `native simulator`_ and the :ref:`POSIX architecture` to build and execute the embedded code natively on Linux. -Particular details on the :ref:`nRF52` and :ref:`nRF5340` -simulation boards, including how to use them, +Particular details on the :ref:`nRF52`, :ref:`nRF5340` and +:ref:`nRF54l15` simulation boards, including how to use them, can be found in their respective documentation. .. _BabbleSim: diff --git a/boards/native/native_posix/Kconfig.defconfig b/boards/native/native_posix/Kconfig.defconfig index 9132dd9c14d48..70d597b4192e0 100644 --- a/boards/native/native_posix/Kconfig.defconfig +++ b/boards/native/native_posix/Kconfig.defconfig @@ -22,11 +22,6 @@ config ETH_NATIVE_POSIX endif # NETWORKING -choice BT_HCI_BUS_TYPE - default BT_USERCHAN - depends on BT_HCI -endchoice - if CONSOLE config POSIX_ARCH_CONSOLE @@ -37,11 +32,4 @@ config UART_CONSOLE endif # CONSOLE -if I2C - -config EMUL - default y - -endif # I2C - endif # BOARD_NATIVE_POSIX diff --git a/boards/native/native_sim/Kconfig.defconfig b/boards/native/native_sim/Kconfig.defconfig index e154d43a52531..0cb80bbcf4524 100644 --- a/boards/native/native_sim/Kconfig.defconfig +++ b/boards/native/native_sim/Kconfig.defconfig @@ -22,11 +22,6 @@ config ETH_NATIVE_POSIX endif # NETWORKING -choice BT_HCI_BUS_TYPE - default BT_USERCHAN - depends on BT_HCI -endchoice - if CONSOLE config POSIX_ARCH_CONSOLE @@ -37,11 +32,5 @@ config UART_CONSOLE endif # CONSOLE -if I2C - -config EMUL - default y - -endif # I2C endif # BOARD_NATIVE_SIM diff --git a/boards/native/native_sim/native_sim.dts b/boards/native/native_sim/native_sim.dts index aa4f2eab0c818..95b5ee5c06522 100644 --- a/boards/native/native_sim/native_sim.dts +++ b/boards/native/native_sim/native_sim.dts @@ -24,6 +24,7 @@ zephyr,display = &sdl_dc; zephyr,canbus = &can_loopback0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &bt_hci_userchan; }; aliases { @@ -161,10 +162,9 @@ compatible = "zephyr,native-posix-counter"; }; - gpio0: gpio@800 { + gpio0: gpio_emul { status = "okay"; compatible = "zephyr,gpio-emul"; - reg = <0x800 0x4>; rising-edge; falling-edge; high-level; @@ -190,7 +190,6 @@ can_loopback0: can_loopback0 { status = "okay"; compatible = "zephyr,can-loopback"; - bus-speed = <125000>; }; can0: can { @@ -200,7 +199,6 @@ * name, e.g.: sudo ip link property add dev vcan0 altname zcan0 */ host-interface = "zcan0"; - bus-speed = <125000>; }; rtc: rtc { @@ -221,4 +219,9 @@ #dma-cells = <1>; stack-size = <4096>; }; + + bt_hci_userchan: bt_hci_userchan { + compatible = "zephyr,bt-hci-userchan"; + status = "okay"; + }; }; diff --git a/boards/native/nrf_bsim/CMakeLists.txt b/boards/native/nrf_bsim/CMakeLists.txt index a4329cd888007..d55a52e1a5311 100644 --- a/boards/native/nrf_bsim/CMakeLists.txt +++ b/boards/native/nrf_bsim/CMakeLists.txt @@ -6,6 +6,10 @@ find_package(BabbleSim) zephyr_library() +if (CONFIG_BOARD_NRF54L15BSIM_NRF54L15_CPUFLPR) + message(FATAL_ERROR "Targeting the nrf54l15bsim/nrf54l15/cpuflpr core is not yet supported") +endif() + # Due to the BLE controller assumption about enum size zephyr_compile_options( -fshort-enums diff --git a/boards/native/nrf_bsim/Kconfig b/boards/native/nrf_bsim/Kconfig index caed5baf8b6a9..0273667c4152a 100644 --- a/boards/native/nrf_bsim/Kconfig +++ b/boards/native/nrf_bsim/Kconfig @@ -34,6 +34,17 @@ config BOARD_NRF5340BSIM_NRF5340_CPUAPP Will produce a console Linux process which can be executed natively. It needs the BabbleSim simulator both in compile time and to execute +config BOARD_NRF54L15BSIM_NRF54L15_CPUAPP + bool + select SOC_SERIES_BSIM_NRF54LX + select SOC_COMPATIBLE_NRF54L15 + select SOC_COMPATIBLE_NRF54L15_CPUAPP + select CLOCK_CONTROL + help + Simulated NRF54L15 Application core + Will produce a console Linux process which can be executed natively. + It needs the BabbleSim simulator both in compile time and to execute + if SOC_SERIES_BSIM_NRFXX @@ -76,6 +87,13 @@ config SOC_SERIES_BSIM_NRF53X help Any NRF53 simulated SOC with BabbleSim, based on the POSIX arch +config SOC_SERIES_BSIM_NRF54LX + bool + select SOC_SERIES_BSIM_NRFXX + select SOC_COMPATIBLE_NRF54LX + help + Any NRF54L simulated SOC with BabbleSim, based on the POSIX arch + if BOARD_NRF5340BSIM_NRF5340_CPUAPP # Replica of the option provided by the BOARD_NRF5340DK_NRF5340_CPUAPP board so samples can be diff --git a/boards/native/nrf_bsim/Kconfig.defconfig b/boards/native/nrf_bsim/Kconfig.defconfig index f0d1dde660b9a..2ff17802977fd 100644 --- a/boards/native/nrf_bsim/Kconfig.defconfig +++ b/boards/native/nrf_bsim/Kconfig.defconfig @@ -30,14 +30,16 @@ config NATIVE_SIMULATOR_PRIMARY_MCU_INDEX default 0 config SYS_CLOCK_HW_CYCLES_PER_SEC + default 1000000 if NRF_GRTC_TIMER default 32768 config SYS_CLOCK_TICKS_PER_SEC default 128 if !TICKLESS_KERNEL + default 10000 if NRF_GRTC_TIMER default 32768 config BT_CTLR - default y if BOARD_NRF52_BSIM || BOARD_NRF5340BSIM_NRF5340_CPUNET + default y if BOARD_NRF52_BSIM || BOARD_NRF5340BSIM_NRF5340_CPUNET || BOARD_NRF54L15BSIM_NRF54L15_CPUAPP depends on BT config HEAP_MEM_POOL_ADD_SIZE_BOARD @@ -58,9 +60,8 @@ if BOARD_NRF5340BSIM_NRF5340_CPUAPP config IPC_SERVICE_BACKEND_RPMSG_SHMEM_RESET default y if IPC_SERVICE_BACKEND_RPMSG -choice BT_HCI_BUS_TYPE - default BT_HCI_IPC -endchoice +config BT_HCI_IPC + default y if BT endif # BOARD_NRF5340BSIM_NRF5340_CPUAPP diff --git a/boards/native/nrf_bsim/Kconfig.nrf54l15bsim b/boards/native/nrf_bsim/Kconfig.nrf54l15bsim new file mode 100644 index 0000000000000..d3ef1f5ffa2bf --- /dev/null +++ b/boards/native/nrf_bsim/Kconfig.nrf54l15bsim @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NRF54L15BSIM + select SOC_POSIX diff --git a/boards/native/nrf_bsim/board.yml b/boards/native/nrf_bsim/board.yml index 874c661c380a1..ba14ed8aef6f6 100644 --- a/boards/native/nrf_bsim/board.yml +++ b/boards/native/nrf_bsim/board.yml @@ -6,6 +6,10 @@ boards: - name: nrf5340bsim vendor: zephyr socs: - # Note this is referring to the real SOC yaml, but we only use its name and cpu-cluster definition - # In practice this board uses the same native SOC (SOC_POSIX) as the nrf52_bsim - name: nrf5340 +- name: nrf54l15bsim + vendor: zephyr + socs: + - name: nrf54l15 +# Note the 53 and 54 are referring to the real SOC yamls, but we only use their name and cpu-cluster +# definitions. In practice these board uses the same native SOC (SOC_POSIX) as the nrf52_bsim diff --git a/boards/native/nrf_bsim/board_soc.h b/boards/native/nrf_bsim/board_soc.h index d75a187aa6109..e0b1cb60a594a 100644 --- a/boards/native/nrf_bsim/board_soc.h +++ b/boards/native/nrf_bsim/board_soc.h @@ -31,12 +31,15 @@ #include "cmsis.h" #include "soc_nrf_common.h" +/* For offloading interrupts we can use any free interrupt */ #if defined(CONFIG_BOARD_NRF52_BSIM) #define OFFLOAD_SW_IRQ SWI0_EGU0_IRQn #elif defined(CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUAPP) #define OFFLOAD_SW_IRQ EGU0_IRQn #elif defined(CONFIG_BOARD_NRF5340BSIM_NRF5340_CPUNET) #define OFFLOAD_SW_IRQ SWI0_IRQn +#elif defined(CONFIG_BOARD_NRF54L15BSIM) +#define OFFLOAD_SW_IRQ SWI00_IRQn #endif #define FLASH_PAGE_ERASE_MAX_TIME_US 89700UL diff --git a/boards/native/nrf_bsim/common/cmsis/cmsis.c b/boards/native/nrf_bsim/common/cmsis/cmsis.c index 1694bc1da3406..e80aea6b4ff60 100644 --- a/boards/native/nrf_bsim/common/cmsis/cmsis.c +++ b/boards/native/nrf_bsim/common/cmsis/cmsis.c @@ -35,6 +35,11 @@ void NVIC_EnableIRQ(IRQn_Type IRQn) hw_irq_ctrl_enable_irq(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); } +uint32_t NVIC_GetEnableIRQ(IRQn_Type IRQn) +{ + return hw_irq_ctrl_is_irq_enabled(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn); +} + void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) { hw_irq_ctrl_prio_set(CONFIG_NATIVE_SIMULATOR_MCU_N, IRQn, priority); diff --git a/boards/native/nrf_bsim/doc/nrf54l15bsim.rst b/boards/native/nrf_bsim/doc/nrf54l15bsim.rst new file mode 100644 index 0000000000000..8c0b2fb64f01d --- /dev/null +++ b/boards/native/nrf_bsim/doc/nrf54l15bsim.rst @@ -0,0 +1,92 @@ +.. _nrf54l15bsim: + +NRF54L15 simulated boards (BabbleSim) +##################################### + +.. contents:: + :depth: 1 + :backlinks: entry + :local: + + +Overview +******** + +To allow simulating nRF54L15 SOCs a Zephyr target boards is provided: the +``nrf54l15bsim/nrf54l15/cpuapp``. + +This uses `BabbleSim`_ to simulate the radio activity, and the +:ref:`POSIX architecture` and the `native simulator`_ to +run applications natively on the development system. This has the benefit of +providing native code execution performance and easy debugging using +native tools, but inherits :ref:`its limitations `. + +Just like for the nrf54l15pdk target, +the nrf54l15bsim/nrf54l15/cpuapp build target provides support for the application core, +on the simulated nRF54L15 SOC. + +.. note:: + + This simulated target does **not** yet support targeting the cpuflpr core. + +.. warning:: + + This target is experimental, and even though it includes models of the RADIO, it does not yet + include models of the AAR, CCM or ECB peripherals, so the BLE and 802.15.4 stacks can only be + run without encryption or privacy features so far. + +This boards include models of some of the nRF54L15 SOC peripherals: + +* CLOCK (Clock control) +* DPPI (Distributed Programmable Peripheral Interconnect) +* EGU (Event Generator Unit) +* FICR (Factory Information Configuration Registers) +* GRTC (Global Real-time Counter) +* PPIB (PPI Bridge) +* RADIO +* RRAMC (Resistive RAM Controller) +* RTC (Real Time Counter) +* TEMP (Temperature sensor) +* TIMER +* UICR (User Information Configuration Registers) + +and will use the same drivers as the nrf54l15pdk targets for these. +For more information on what is modeled to which level of detail, +check the `HW models implementation status`_. + +Note that unlike a real nrf54l15 device, the nrf54l15bsim boards have unlimited RAM, and code does +not occupy their RRAM. + +.. _BabbleSim: + https://BabbleSim.github.io + +.. _native simulator: + https://github.com/BabbleSim/native_simulator/blob/main/docs/README.md + +.. _HW models implementation status: + https://github.com/BabbleSim/ext_nRF_hw_models/blob/main/docs/README_impl_status.md + + +Building for, and using this board +********************************** + +You can follow the instructions from the :ref:`nrf52_bsim board `. +Simply change the board/target appropriately when building. + + +TrustZone, TF-M and other security considerations +************************************************* + +ARM's TrustZone is not modeled in this board. This means that: + +* There is no differentiation between secure and non secure execution states or bus accesses. +* All RAM, flash and peripherals are in principle accessible from all SW. Peripherals with their + own interconnect master ports can, in principle, access any other peripheral or RAM area. +* There is no nrf54l15bsim/nrf54l15/cpuapp/ns board/build target, or possibility of mixing secure + and non-secure images. +* Currently there is no model of the SPU, and therefore neither RRAM, RAM areas or peripherals + can be labeled as restricted for secure or non secure access. +* TF-M cannot be used. + +Note that the CRACEN peripheral is not modeled. The mbedTLS library can still be used +but with a SW crypto backend. diff --git a/boards/native/nrf_bsim/nrf52_bsim.dts b/boards/native/nrf_bsim/nrf52_bsim.dts index bb6321c4d5310..ad3ac181ae7d6 100644 --- a/boards/native/nrf_bsim/nrf52_bsim.dts +++ b/boards/native/nrf_bsim/nrf52_bsim.dts @@ -38,8 +38,6 @@ zephyr,flash = &flash0; /* UART used by the BT controller UART HCI driver by default: */ zephyr,bt-c2h-uart = &uart1; - /* UART used by the BT host UART HCI driver by default: */ - zephyr,bt-uart = &uart1; }; soc { @@ -117,4 +115,9 @@ pinctrl-1 = <&uart1_sleep>; pinctrl-names = "default", "sleep"; hw-flow-control; + + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + }; }; diff --git a/boards/native/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts b/boards/native/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts index aa1f235e16e58..11073e6182de3 100644 --- a/boards/native/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts +++ b/boards/native/nrf_bsim/nrf5340bsim_nrf5340_cpuapp.dts @@ -43,7 +43,7 @@ chosen { zephyr,entropy = &rng_hci; zephyr,flash = &flash0; - zephyr,bt-hci-ipc = &ipc0; + zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; }; diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts new file mode 100644 index 0000000000000..bdcd1f2300bc4 --- /dev/null +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.dts @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include + +/ { + model = "Nordic NRF54L15 BSIM NRF54L15 Application"; + compatible = "bsim,nrf54l15-bsim-nrf54l15-cpuapp", "bsim,nrf54"; + + chosen { + zephyr,entropy = &rng; + zephyr,flash-controller = &rram_controller; + zephyr,flash = &cpuapp_rram; + }; + + /delete-node/ cpus; + /delete-node/ clocks; + /delete-node/ sw-pwm; + + soc { + /delete-node/ memory@20000000; + /delete-node/ memory@2002f000; + peripheral@50000000 { + /delete-node/ spi@4a000; + /delete-node/ uart@4a000; + /delete-node/ vpr@4c000; + /delete-node/ mailbox@0; + /delete-node/ interrupt-controller@f0000000; + /delete-node/ gpio@50400; + /delete-node/ i2c@c6000; + /delete-node/ spi@c6000; + /delete-node/ uart@c6000; + /delete-node/ i2c@c7000; + /delete-node/ spi@c7000; + /delete-node/ uart@c7000; + /delete-node/ i2c@c8000; + /delete-node/ spi@c8000; + /delete-node/ uart@c8000; + /delete-node/ pwm@d2000; + /delete-node/ pwm@d3000; + /delete-node/ pwm@d4000; + /delete-node/ adc@d5000; + /delete-node/ nfct@d6000; + /delete-node/ gpio@d8200; + /delete-node/ gpiote@da000; + /delete-node/ i2s@dd000; + /delete-node/ qdec@e0000; + /delete-node/ qdec@e1000; + /delete-node/ i2c@104000; + /delete-node/ spi@104000; + /delete-node/ uart@104000; + /delete-node/ watchdog@108000; + /delete-node/ watchdog@109000; + /delete-node/ gpio@10a000; + /delete-node/ gpiote@10c000; + }; + /delete-node/ spu@50003000; + /delete-node/ gpiote@5000d000; + /delete-node/ crypto@50844000; + }; + + rng: rng { + status = "okay"; + compatible = "zephyr,native-posix-rng"; + }; +}; + +&grtc { + owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>; + /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ + child-owned-channels = <3 4 7 8 9 10 11>; + status = "okay"; +}; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + storage_partition: partition@0 { + label = "storage"; + reg = <0x0 DT_SIZE_K(500)>; + }; + }; +}; + +&temp { + status = "okay"; +}; + +&radio { + status = "okay"; + /* This feature is not yet supported by the RADIO model */ + /delete-property/ dfe-supported; +}; + +&clock { + status = "okay"; +}; diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml new file mode 100644 index 0000000000000..cbdd257334f44 --- /dev/null +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp.yaml @@ -0,0 +1,17 @@ +identifier: nrf54l15bsim/nrf54l15/cpuapp +name: NRF54L15 BabbleSim - Application Core target +type: native +arch: posix +simulation: native +env: + - BSIM_OUT_PATH +toolchain: + - zephyr +supported: + - counter +testing: + ignore_tags: + - gpio + - modem + - uart + - bsim_skip_CI diff --git a/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp_defconfig b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp_defconfig new file mode 100644 index 0000000000000..0fde4e01b5838 --- /dev/null +++ b/boards/native/nrf_bsim/nrf54l15bsim_nrf54l15_cpuapp_defconfig @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2023 Nordic Semiconductor ASA + +CONFIG_CONSOLE=y +CONFIG_NO_OPTIMIZATIONS=y + +# Start SYSCOUNTER on driver init +CONFIG_NRF_GRTC_START_SYSCOUNTER=y diff --git a/boards/nordic/nrf21540dk/doc/index.rst b/boards/nordic/nrf21540dk/doc/index.rst index fdc726056360d..8ea583edb1a09 100644 --- a/boards/nordic/nrf21540dk/doc/index.rst +++ b/boards/nordic/nrf21540dk/doc/index.rst @@ -32,7 +32,7 @@ The CPU provides support for the following devices: nRF21540 DK (Credit: Nordic Semiconductor) More information about the board can be found at the `nRF21540 website`_. -The `Nordic Semiconductor Infocenter`_ contains the processor's and front end +`nRF21540 Product Specification`_ contains the processor's and front end module's information and the datasheet. Hardware @@ -83,7 +83,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52840 Product Specification`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52840 Product Specification`_ and `nRF21540 DK Hardware guide`_ for a complete list of nRF21540 Development Kit board hardware features. Connections and IOs @@ -229,8 +229,8 @@ References .. target-notes:: -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF21540 DK Hardware guide: https://docs.nordicsemi.com/bundle/ug_nrf21540_dk/page/UG/nrf21540_DK/intro.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html .. _nRF21540 website: https://www.nordicsemi.com/Products/Low-power-short-range-wireless/nRF21540 -.. _nRF52840 Product Specification: http://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.0.pdf -.. _nRF21540 Product Specification: http://infocenter.nordicsemi.com/pdf/nRF21540_PS_v1.0.pdf +.. _nRF52840 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52840/page/keyfeatures_html5.html +.. _nRF21540 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf21540/page/keyfeatures_html5.html diff --git a/boards/nordic/nrf21540dk/nrf21540dk_nrf52840.yaml b/boards/nordic/nrf21540dk/nrf21540dk_nrf52840.yaml index a1bcc36e034d7..b84c5371d877b 100644 --- a/boards/nordic/nrf21540dk/nrf21540dk_nrf52840.yaml +++ b/boards/nordic/nrf21540dk/nrf21540dk_nrf52840.yaml @@ -18,7 +18,6 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/nordic/nrf51dk/doc/index.rst b/boards/nordic/nrf51dk/doc/index.rst index b97e70e961319..c905dc0f4764b 100644 --- a/boards/nordic/nrf51dk/doc/index.rst +++ b/boards/nordic/nrf51dk/doc/index.rst @@ -29,7 +29,7 @@ Semiconductor nRF51822 ARM Cortex-M0 CPU and the following devices: nRF51 DK (Credit: Nordic Semiconductor) More information about the board can be found at the -`nRF51 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF51 DK website`_. The `nRF51 Development Kit User Guide`_ contains the processor's information and the datasheet. @@ -75,7 +75,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF51 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF51 DK website`_ and `nRF51 Development Kit User Guide`_ for a complete list of nRF51 Development Kit board hardware features. Connections and IOs @@ -156,4 +156,4 @@ References .. target-notes:: .. _nRF51 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF51-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF51 Development Kit User Guide: https://docs.nordicsemi.com/bundle/nRF51-Series-DK/resource/nRF51_Development_Kit_User_Guide_v1.2.pdf diff --git a/boards/nordic/nrf51dongle/doc/index.rst b/boards/nordic/nrf51dongle/doc/index.rst index 720ff3a59861d..d8183371654a8 100644 --- a/boards/nordic/nrf51dongle/doc/index.rst +++ b/boards/nordic/nrf51dongle/doc/index.rst @@ -29,7 +29,7 @@ Semiconductor nRF51822 ARM Cortex-M0 CPU and the following devices: nRF51 Dongle (Credit: Nordic Semiconductor) More information about the board can be found at the -`nRF51 Dongle website`_. The `Nordic Semiconductor Infocenter`_ +`nRF51 Dongle website`_. The `Nordic Semiconductor TechDocs`_ contains the processor's information and the datasheet. @@ -75,7 +75,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF51 Dongle website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF51 Dongle website`_ and `Nordic Semiconductor TechDocs`_ for a complete list of nRF51 Dongle hardware features. Connections and IOs @@ -141,4 +141,4 @@ References .. target-notes:: .. _nRF51 Dongle website: http://www.nordicsemi.com/eng/Products/nRF51-Dongle -.. _Nordic Semiconductor Infocenter: http://infocenter.nordicsemi.com/ +.. _Nordic Semiconductor TechDocs: https://docs.nordicsemi.com/ diff --git a/boards/nordic/nrf52833dk/doc/index.rst b/boards/nordic/nrf52833dk/doc/index.rst index d182053d50647..027f471586fed 100644 --- a/boards/nordic/nrf52833dk/doc/index.rst +++ b/boards/nordic/nrf52833dk/doc/index.rst @@ -27,7 +27,7 @@ the following devices: * :abbr:`WDT (Watchdog Timer)` More information about the board can be found at the -`nRF52833 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF52833 DK website`_. `nRF52833 Product Specification`_ contains the processor's information and the datasheet. @@ -80,7 +80,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52833 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52833 DK website`_ and `nRF52833 DK Hardware guide`_ for a complete list of nRF52833 Development Kit board hardware features. Connections and IOs @@ -212,9 +212,9 @@ References .. target-notes:: .. _nRF52833 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF52833 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52833/page/keyfeatures_html5.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _nRF52833 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52833_OPS_v0.7.pdf +.. _nRF52833 DK Hardware guide: https://docs.nordicsemi.com/bundle/ug_nrf52833_dk/page/UG/dk/intro.html .. _nrf52833dk_nrf52820: diff --git a/boards/nordic/nrf52833dk/nrf52833dk_nrf52820.yaml b/boards/nordic/nrf52833dk/nrf52833dk_nrf52820.yaml index b2d59ed4e4157..62e323927982e 100644 --- a/boards/nordic/nrf52833dk/nrf52833dk_nrf52820.yaml +++ b/boards/nordic/nrf52833dk/nrf52833dk_nrf52820.yaml @@ -10,6 +10,7 @@ ram: 32 flash: 256 supported: - usb_device + - usbd - ble - gpio - watchdog diff --git a/boards/nordic/nrf52833dk/nrf52833dk_nrf52833.yaml b/boards/nordic/nrf52833dk/nrf52833dk_nrf52833.yaml index cd3ed1b54d234..8ab244fd648b1 100644 --- a/boards/nordic/nrf52833dk/nrf52833dk_nrf52833.yaml +++ b/boards/nordic/nrf52833dk/nrf52833dk_nrf52833.yaml @@ -14,6 +14,7 @@ supported: - arduino_i2c - arduino_spi - usb_device + - usbd - ble - gpio - pwm diff --git a/boards/nordic/nrf52840dk/doc/index.rst b/boards/nordic/nrf52840dk/doc/index.rst index 953c86fd19022..faa7f07d5c931 100644 --- a/boards/nordic/nrf52840dk/doc/index.rst +++ b/boards/nordic/nrf52840dk/doc/index.rst @@ -32,7 +32,7 @@ Nordic Semiconductor nRF52840 ARM Cortex-M4F CPU and the following devices: nRF52840 DK (Credit: Nordic Semiconductor) More information about the board can be found at the `nRF52840 DK website`_. -The `Nordic Semiconductor Infocenter`_ contains the processor's information +`nRF52840 Product Specification`_ contains the processor's information and the datasheet. @@ -84,7 +84,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52840 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52840 DK website`_ and `nRF52840 DK Hardware guide`_ for a complete list of nRF52840 Development Kit board hardware features. Connections and IOs @@ -244,7 +244,7 @@ References .. target-notes:: .. _nRF52840 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF52840 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52840/page/keyfeatures_html5.html +.. _nRF52840 DK Hardware guide: https://docs.nordicsemi.com/bundle/ug_nrf52840_dk/page/UG/dk/intro.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html -.. _nRF52840 Product Specification: http://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.0.pdf .. _nRF52811 website: https://www.nordicsemi.com/Products/Low-power-short-range-wireless/nRF52811 diff --git a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts index 60c3ecf55a127..2bcffc80b0ab9 100644 --- a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts +++ b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.dts @@ -131,7 +131,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.yaml b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.yaml index 30a96d563c947..313a975e6d04f 100644 --- a/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.yaml +++ b/boards/nordic/nrf52840dk/nrf52840dk_nrf52840.yaml @@ -21,8 +21,8 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device + - usbd - watchdog - netif:openthread vendor: nordic diff --git a/boards/nordic/nrf52840dongle/doc/index.rst b/boards/nordic/nrf52840dongle/doc/index.rst index 235b0ea4b35b4..9aa6f74811f3e 100644 --- a/boards/nordic/nrf52840dongle/doc/index.rst +++ b/boards/nordic/nrf52840dongle/doc/index.rst @@ -31,7 +31,7 @@ Semiconductor nRF52840 ARM Cortex-M4F CPU and the following devices: nRF52840 Dongle More information about the board can be found at the -`nRF52840 Dongle website`_. The `Nordic Semiconductor Infocenter`_ +`nRF52840 Dongle website`_. The `nRF52840 Dongle guide`_ contains the processor's information and the datasheet. @@ -82,7 +82,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52840 Dongle website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52840 Dongle website`_ and `nRF52840 Dongle Hardware description`_ for a complete list of nRF52840 Dongle board hardware features. Connections and IOs @@ -334,12 +334,12 @@ References .. _nRF52840 Dongle website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52840-Dongle -.. _Nordic Semiconductor Infocenter: - https://infocenter.nordicsemi.com +.. _nRF52840 Dongle guide: https://docs.nordicsemi.com/bundle/ug_nrf52840_dk/page/UG/dk/intro.html +.. _nRF52840 Dongle Hardware description: https://docs.nordicsemi.com/bundle/ug_nrf52840_dongle/page/UG/nrf52840_Dongle/hw_description.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html .. _Nordic Semiconductor USB DFU: - https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v15.2.0%2Fsdk_app_serial_dfu_bootloader.html + https://docs.nordicsemi.com/bundle/sdk_nrf5_v17.1.0/page/sdk_app_serial_dfu_bootloader.html .. _nrfutil: https://github.com/NordicSemiconductor/pc-nrfutil .. _MCUboot: diff --git a/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.yaml b/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.yaml index 1e61b0e71e478..e5410c74c7111 100644 --- a/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.yaml +++ b/boards/nordic/nrf52840dongle/nrf52840dongle_nrf52840.yaml @@ -11,7 +11,6 @@ toolchain: supported: - adc - usb_device - - usb_cdc - ble - pwm - spi diff --git a/boards/nordic/nrf52dk/doc/index.rst b/boards/nordic/nrf52dk/doc/index.rst index 07f241eac1efe..4ebcac44e6c25 100644 --- a/boards/nordic/nrf52dk/doc/index.rst +++ b/boards/nordic/nrf52dk/doc/index.rst @@ -32,7 +32,7 @@ the following devices: nRF52 DK (Credit: Nordic Semiconductor) More information about the board can be found at the -`nRF52 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF52 DK website`_. `nRF52832 Product Specification`_ contains the processor's information and the datasheet. @@ -82,7 +82,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `nRF52 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF52 DK website`_ and `nRF52832 Product Specification`_ for a complete list of nRF52 Development Kit board hardware features. Connections and IOs @@ -403,7 +403,7 @@ References .. target-notes:: .. _nRF52 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF52832 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52832/page/nrf52832_ps.html .. _nrf52dk_nrf52805: diff --git a/boards/nordic/nrf5340_audio_dk/Kconfig.defconfig b/boards/nordic/nrf5340_audio_dk/Kconfig.defconfig index c8d07e2adfab8..62316a2aeb096 100644 --- a/boards/nordic/nrf5340_audio_dk/Kconfig.defconfig +++ b/boards/nordic/nrf5340_audio_dk/Kconfig.defconfig @@ -53,9 +53,8 @@ config FLASH_LOAD_SIZE endif # BOARD_NRF5340_AUDIO_DK_NRF5340_CPUAPP_NS -choice BT_HCI_BUS_TYPE - default BT_HCI_IPC if BT -endchoice +config BT_HCI_IPC + default y if BT config HEAP_MEM_POOL_ADD_SIZE_BOARD int diff --git a/boards/nordic/nrf5340_audio_dk/doc/index.rst b/boards/nordic/nrf5340_audio_dk/doc/index.rst index 558f995be6625..f7b23c0d6de63 100644 --- a/boards/nordic/nrf5340_audio_dk/doc/index.rst +++ b/boards/nordic/nrf5340_audio_dk/doc/index.rst @@ -35,7 +35,7 @@ The nRF5340 Audio DK comes with the following hardware features: :align: center :alt: nRF5340 DK -More information about the board can be found at the `nRF5340 Audio DK website`_. The `Nordic Semiconductor Infocenter`_ +More information about the board can be found at the `nRF5340 Audio DK website`_. The `nRF5340 Audio DK hardware guide`_ contains the processor's information and the datasheet. nRF5340 SoC @@ -53,13 +53,13 @@ The ``nrf5340_audio_dk/nrf5340/cpuapp`` build target provides support for the ap core on the nRF5340 SoC. The ``nrf5340_audio_dk/nrf5340/cpunet`` build target provides support for the network core on the nRF5340 SoC. -The `Nordic Semiconductor Infocenter`_ contains the processor's information and +The `nRF5340 Audio DK hardware guide`_ contains the processor's information and the datasheet. Supported Features ================== -See :ref:`nrf5340dk_nrf5340` and `Nordic Semiconductor Infocenter`_ +See :ref:`nrf5340dk_nrf5340` and `nRF5340 Audio DK hardware guide`_ for a complete list of nRF5340 Audio DK board hardware features. @@ -106,4 +106,4 @@ References .. _nRF5340 Audio DK website: https://www.nordicsemi.com/Products/Development-hardware/nrf5340-audio-dk -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF5340 Audio DK hardware guide: https://docs.nordicsemi.com/bundle/ug_nrf5340_audio/page/UG/nrf5340_audio/intro.html diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_cpunet_reset.c b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_cpunet_reset.c index 3d08a5dd4cd6f..f9082e6ca4006 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_cpunet_reset.c +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_cpunet_reset.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include LOG_MODULE_REGISTER(nrf5340_audio_dk_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -71,7 +71,7 @@ static int remoteproc_mgr_boot(void) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp.yaml b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp.yaml index 9c131a6c9d46b..8d8e378179577 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp.yaml +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp.yaml @@ -9,12 +9,15 @@ toolchain: ram: 448 flash: 1024 supported: + - arduino_adc + - arduino_i2c + - arduino_serial + - arduino_spi - gpio - i2s - spi - i2c - pwm - watchdog - - usb_cdc - usb_device vendor: nordic diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi index 6ad1591bd4533..7f62b86263945 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_common.dtsi @@ -13,7 +13,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-ipc = &ipc0; + zephyr,bt-hci = &bt_hci_ipc0; watchdog0 = &wdt0; }; @@ -25,6 +25,17 @@ }; }; + arduino_adc: analog-connector { + compatible = "arduino,uno-adc"; + #io-channel-cells = <1>; + io-channel-map = <0 &adc 1>, /* A0 = P0.4 = AIN1 */ + <1 &adc 2>, /* A1 = P0.5 = AIN2 */ + <2 &adc 4>, /* A2 = P0.6 = AIN4 */ + <3 &adc 5>, /* A3 = P0.7 = AIN5 */ + <4 &adc 6>, /* A4 = P0.25 = AIN6 */ + <5 &adc 7>; /* A5 = P0.26 = AIN7 */ + }; + pmic { compatible = "nordic,npm1100"; nordic,iset-gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; @@ -120,7 +131,7 @@ arduino_serial: &uart1 { pinctrl-names = "default", "sleep"; }; -&i2c1 { +arduino_i2c: &i2c1 { compatible = "nordic,nrf-twim"; status = "okay"; pinctrl-0 = <&i2c1_default>; @@ -172,16 +183,17 @@ arduino_serial: &uart1 { }; }; -&spi4 { +arduino_spi: &spi4 { compatible = "nordic,nrf-spim"; status = "okay"; - cs-gpios = <&gpio0 11 GPIO_ACTIVE_LOW>, <&gpio0 17 GPIO_ACTIVE_LOW>; + cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>, + <&gpio0 11 GPIO_ACTIVE_LOW>, <&gpio0 17 GPIO_ACTIVE_LOW>; pinctrl-0 = <&spi4_default>; pinctrl-1 = <&spi4_sleep>; pinctrl-names = "default", "sleep"; - sdhc0: sdhc@0 { + sdhc0: sdhc@1 { compatible = "zephyr,sdhc-spi-slot"; - reg = <0>; + reg = <1>; status = "okay"; sdmmc { compatible = "zephyr,sdmmc-disk"; @@ -191,9 +203,9 @@ arduino_serial: &uart1 { spi-max-frequency = <8000000>; }; - cs47l63: cs47l63@1 { + cs47l63: cs47l63@2 { compatible = "cirrus,cs47l63"; - reg = <1>; + reg = <2>; spi-max-frequency = <8000000>; irq-gpios = <&gpio0 19 GPIO_ACTIVE_LOW>; reset-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; diff --git a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml index 4194fc6357480..28a295758911b 100644 --- a/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml +++ b/boards/nordic/nrf5340_audio_dk/nrf5340_audio_dk_nrf5340_cpuapp_ns.yaml @@ -14,6 +14,5 @@ supported: - spi - pwm - watchdog - - usb_cdc - usb_device vendor: nordic diff --git a/boards/nordic/nrf5340dk/Kconfig.defconfig b/boards/nordic/nrf5340dk/Kconfig.defconfig index 67d7c7db9d553..972d8433c9016 100644 --- a/boards/nordic/nrf5340dk/Kconfig.defconfig +++ b/boards/nordic/nrf5340dk/Kconfig.defconfig @@ -60,9 +60,8 @@ config MBOX_NRFX_IPC if BOARD_NRF5340DK_NRF5340_CPUAPP || BOARD_NRF5340DK_NRF5340_CPUAPP_NS -choice BT_HCI_BUS_TYPE - default BT_HCI_IPC if BT -endchoice +config BT_HCI_IPC + default y if BT config HEAP_MEM_POOL_ADD_SIZE_BOARD int diff --git a/boards/nordic/nrf5340dk/doc/index.rst b/boards/nordic/nrf5340dk/doc/index.rst index f8ce8a2a84b8a..e933f43bdb4b5 100644 --- a/boards/nordic/nrf5340dk/doc/index.rst +++ b/boards/nordic/nrf5340dk/doc/index.rst @@ -48,7 +48,7 @@ nRF5340 SoC provides support for the following devices: More information about the board can be found at the `nRF5340 DK website`_. -The `Nordic Semiconductor Infocenter`_ +The `nRF5340 DK Product Specification`_ contains the processor's information and the datasheet. @@ -132,7 +132,7 @@ hardware features: +-----------+------------+----------------------+ Other hardware features have not been enabled yet for this board. -See `Nordic Semiconductor Infocenter`_ +See `nRF5340 DK Product Specification`_ for a complete list of nRF5340 DK board hardware features. Connections and IOs @@ -326,5 +326,5 @@ References https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau .. _nRF5340 DK website: https://www.nordicsemi.com/Software-and-tools/Development-Kits/nRF5340-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF5340 DK Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf5340/page/keyfeatures_html5.html .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi b/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi index 70ba32524500e..df46b7c64277c 100644 --- a/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi +++ b/boards/nordic/nrf5340dk/nrf5340_cpuapp_common.dtsi @@ -14,7 +14,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-ipc = &ipc0; + zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; }; @@ -133,7 +133,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/nordic/nrf5340dk/nrf5340_cpunet_reset.c b/boards/nordic/nrf5340dk/nrf5340_cpunet_reset.c index 3b85d55dfd071..dadba8c0f54a8 100644 --- a/boards/nordic/nrf5340dk/nrf5340_cpunet_reset.c +++ b/boards/nordic/nrf5340dk/nrf5340_cpunet_reset.c @@ -9,7 +9,7 @@ #include #include -#include +#include LOG_MODULE_REGISTER(nrf5340dk_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -49,7 +49,7 @@ static int remoteproc_mgr_boot(void) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp.yaml b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp.yaml index 0a8bfabf5c468..50ed473387143 100644 --- a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp.yaml +++ b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp.yaml @@ -14,8 +14,8 @@ supported: - i2s - pwm - watchdog - - usb_cdc - usb_device + - usbd - netif:openthread - gpio - spi diff --git a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns.yaml b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns.yaml index 4b311f76e25d6..4c366d2f363f5 100644 --- a/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns.yaml +++ b/boards/nordic/nrf5340dk/nrf5340dk_nrf5340_cpuapp_ns.yaml @@ -12,8 +12,8 @@ supported: - i2c - pwm - watchdog - - usb_cdc - usb_device + - usbd - netif:openthread - gpio - spi diff --git a/boards/nordic/nrf54h20dk/Kconfig.defconfig b/boards/nordic/nrf54h20dk/Kconfig.defconfig index 74fe93905ac33..e37975f96adf4 100644 --- a/boards/nordic/nrf54h20dk/Kconfig.defconfig +++ b/boards/nordic/nrf54h20dk/Kconfig.defconfig @@ -3,9 +3,8 @@ if BOARD_NRF54H20DK_NRF54H20_CPUAPP -choice BT_HCI_BUS_TYPE - default BT_HCI_IPC if BT -endchoice +config BT_HCI_IPC + default y if BT endif # BOARD_NRF54H20DK_NRF54H20_CPUAPP diff --git a/boards/nordic/nrf54h20dk/board.cmake b/boards/nordic/nrf54h20dk/board.cmake index 6361f7fe7b4a0..0c8376c1714e1 100644 --- a/boards/nordic/nrf54h20dk/board.cmake +++ b/boards/nordic/nrf54h20dk/board.cmake @@ -3,13 +3,12 @@ include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake) if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP OR CONFIG_BOARD_NRF54H20DK_NRF54H20_CPURAD) - if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPURAD) - set( - JLINK_TOOL_OPT - "-jlinkscriptfile ${CMAKE_CURRENT_LIST_DIR}/support/nrf54h20_cpurad.JLinkScript" - ) + if(CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP) + set(JLINKSCRIPTFILE ${CMAKE_CURRENT_LIST_DIR}/support/nrf54h20_cpuapp.JLinkScript) + else() + set(JLINKSCRIPTFILE ${CMAKE_CURRENT_LIST_DIR}/support/nrf54h20_cpurad.JLinkScript) endif() - board_runner_args(jlink "--device=CORTEX-M33" "--speed=4000" "--tool-opt=${JLINK_TOOL_OPT}") + board_runner_args(jlink "--device=CORTEX-M33" "--speed=4000" "--tool-opt=-jlinkscriptfile ${JLINKSCRIPTFILE}") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) endif() diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi index 91899e2cf86b6..e7181c4fba98f 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-memory_map.dtsi @@ -3,6 +3,7 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include / { reserved-memory { @@ -70,11 +71,7 @@ }; shared_ram20_region: memory@2f88f000 { - compatible = "nordic,owned-memory"; reg = <0x2f88f000 DT_SIZE_K(4)>; - status = "disabled"; - perm-read; - perm-write; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x2f88f000 0x1000>; @@ -96,6 +93,27 @@ }; }; + ram21_region: memory@2f890000 { + compatible = "nordic,owned-memory"; + status = "disabled"; + reg = <0x2f890000 DT_SIZE_K(64)>; + perm-read; + perm-write; + perm-secure; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x2f890000 0x10000>; + + dma_fast_region: memory@8000 { + compatible = "zephyr,memory-region"; + reg = <0x8000 DT_SIZE_K(16)>; + status = "disabled"; + #memory-region-cells = <0>; + zephyr,memory-region = "DMA_RAM21"; + zephyr,memory-attr = <( DT_MEM_DMA | DT_MEM_CACHEABLE )>; + }; + }; + cpuppr_ram3x_region: memory@2fc00000 { compatible = "nordic,owned-memory"; reg = <0x2fc00000 DT_SIZE_K(64)>; @@ -136,6 +154,7 @@ status = "disabled"; #memory-region-cells = <0>; zephyr,memory-region = "DMA_RAM3x_APP"; + zephyr,memory-attr = <( DT_MEM_DMA )>; }; cpurad_dma_region: memory@1e80 { @@ -144,6 +163,7 @@ status = "disabled"; #memory-region-cells = <0>; zephyr,memory-region = "DMA_RAM3x_RAD"; + zephyr,memory-attr = <( DT_MEM_DMA )>; }; }; }; @@ -174,11 +194,11 @@ #size-cells = <1>; cpuapp_slot0_partition: partition@a6000 { - reg = <0xa6000 DT_SIZE_K(512)>; + reg = <0xa6000 DT_SIZE_K(296)>; }; - cpuppr_code_partition: partition@126000 { - reg = <0x126000 DT_SIZE_K(64)>; + cpuppr_code_partition: partition@f0000 { + reg = <0xf0000 DT_SIZE_K(64)>; }; }; @@ -191,8 +211,12 @@ #address-cells = <1>; #size-cells = <1>; - storage_partition: partition@136000 { - reg = <0x136000 DT_SIZE_K(24)>; + dfu_partition: partition@100000 { + reg = < 0x100000 DT_SIZE_K(892) >; + }; + + storage_partition: partition@1df000 { + reg = < 0x1df000 DT_SIZE_K(24) >; }; }; }; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi index 0cfe8a24c43cc..da3effb5af8fe 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20-pinctrl.dtsi @@ -59,4 +59,24 @@ nordic,drive-mode = ; }; }; + + /omit-if-no-ref/ can120_default: can120_default { + group1 { + psels = , + ; + }; + }; + + /omit-if-no-ref/ pwm130_default: pwm130_default { + group1 { + psels = ; + }; + }; + + /omit-if-no-ref/ pwm130_sleep: pwm130_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; }; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts index fd838f3757df9..bf14d775f7218 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.dts @@ -24,7 +24,10 @@ zephyr,flash = &mram1x; zephyr,sram = &cpuapp_data; zephyr,shell-uart = &uart136; - zephyr,bt-hci-ipc = &ipc0; + zephyr,ieee802154 = &cpuapp_ieee802154; + zephyr,bt-hci = &bt_hci_ipc0; + nordic,802154-spinel-ipc = &ipc0; + zephyr,canbus = &can120; }; aliases { @@ -32,10 +35,14 @@ led1 = &led1; led2 = &led2; led3 = &led3; + resetinfo = &cpuapp_resetinfo; + pwm-led0 = &pwm_led2; sw0 = &button0; sw1 = &button1; sw2 = &button2; sw3 = &button3; + ipc-to-cpusys = &cpuapp_cpusys_ipc; + watchdog0 = &wdt010; }; buttons { @@ -89,6 +96,18 @@ label = "Green LED 3"; }; }; + + pwmleds { + compatible = "pwm-leds"; + /* + * LEDs are connected to GPIO Port 9 - pins 0-3. There is no valid hardware + * configuration to pass PWM signal on pis 0 and 1. First valid config is P9.2. + * Signal on PWM130's channel 0 can be passed directly on GPIO Port 9 pin 2. + */ + pwm_led2: pwm_led_2 { + pwms = <&pwm130 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; }; &cpuapp_ram0x_region { @@ -103,6 +122,10 @@ status = "okay"; }; +&ram21_region { + status = "okay"; +}; + &cpuapp_bellboard { status = "okay"; interrupts = <96 NRF_DEFAULT_IRQ_PRIORITY>; @@ -115,6 +138,10 @@ status = "okay"; }; +&cpusys_vevif { + status = "okay"; +}; + &cpusec_cpuapp_ipc { mbox-names = "tx", "rx"; tx-region = <&cpuapp_cpusec_ipc_shm>; @@ -128,9 +155,15 @@ ipc0: &cpuapp_cpurad_ipc { rx-region = <&cpurad_cpuapp_ipc_shm>; tx-blocks = <32>; rx-blocks = <32>; + + bt_hci_ipc0: bt_hci_ipc0 { + compatible = "zephyr,bt-hci-ipc"; + status = "okay"; + }; }; &cpuapp_cpusys_ipc { + status = "okay"; mbox-names = "rx", "tx"; tx-region = <&cpuapp_cpusys_ipc_shm>; rx-region = <&cpusys_cpuapp_ipc_shm>; @@ -146,6 +179,10 @@ ipc0: &cpuapp_cpurad_ipc { status = "okay"; }; +&dma_fast_region { + status = "okay"; +}; + &cpuapp_rx_partitions { status = "okay"; }; @@ -224,3 +261,34 @@ ipc0: &cpuapp_cpurad_ipc { t-exit-dpd = <30000>; }; }; + +&cpuapp_ieee802154 { + status = "okay"; +}; + +zephyr_udc0: &usbhs { + status = "okay"; +}; + +&canpll { + status = "okay"; +}; + +&can120 { + status = "okay"; + pinctrl-0 = <&can120_default>; + pinctrl-names = "default"; +}; + +&pwm130 { + status = "okay"; + pinctrl-0 = <&pwm130_default>; + pinctrl-1 = <&pwm130_sleep>; + pinctrl-names = "default", "sleep"; + memory-regions = <&cpuapp_dma_region>; +}; + +&adc { + memory-regions = <&cpuapp_dma_region>; + status = "okay"; +}; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml index 6ecde2cfdb103..1fb5a03987527 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuapp.yaml @@ -9,8 +9,16 @@ toolchain: - gnuarmemb - xtools - zephyr +sysbuild: true ram: 256 -flash: 512 +flash: 296 supported: + - adc + - can + - counter - gpio + - i2c - pwm + - spi + - watchdog + - usbd diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml index 190d835f58090..8bd648416b60e 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr.yaml @@ -7,8 +7,10 @@ type: mcu arch: riscv toolchain: - zephyr +sysbuild: true ram: 62 flash: 62 supported: - gpio - pwm + - spi diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip.yaml index d0b1f4481190d..8cfc343647ff9 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpuppr_xip.yaml @@ -7,6 +7,7 @@ type: mcu arch: riscv toolchain: - zephyr +sysbuild: true ram: 62 flash: 64 supported: diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts index ad08596f600aa..8bba620c45639 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.dts @@ -25,7 +25,13 @@ zephyr,flash = &mram1x; zephyr,sram = &cpurad_ram0; zephyr,shell-uart = &uart135; + zephyr,ieee802154 = &cpurad_ieee802154; zephyr,bt-hci-ipc = &ipc0; + nordic,802154-spinel-ipc = &ipc0; + }; + aliases { + ipc-to-cpusys = &cpurad_cpusys_ipc; + resetinfo = &cpurad_resetinfo; }; }; @@ -49,6 +55,10 @@ status = "okay"; }; +&cpusys_vevif { + status = "okay"; +}; + &cpusec_cpurad_ipc { mbox-names = "tx", "rx"; tx-region = <&cpurad_cpusec_ipc_shm>; @@ -65,6 +75,7 @@ ipc0: &cpuapp_cpurad_ipc { }; &cpurad_cpusys_ipc { + status = "okay"; mbox-names = "rx", "tx"; tx-region = <&cpurad_cpusys_ipc_shm>; rx-region = <&cpusys_cpurad_ipc_shm>; @@ -98,3 +109,7 @@ ipc0: &cpuapp_cpurad_ipc { pinctrl-1 = <&uart136_sleep>; pinctrl-names = "default", "sleep"; }; + +&cpurad_ieee802154 { + status = "okay"; +}; diff --git a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml index b199f65385f3f..36c0fc01dce13 100644 --- a/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml +++ b/boards/nordic/nrf54h20dk/nrf54h20dk_nrf54h20_cpurad.yaml @@ -9,8 +9,11 @@ toolchain: - gnuarmemb - xtools - zephyr +sysbuild: true ram: 192 flash: 256 supported: + - counter - gpio - pwm + - spi diff --git a/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript new file mode 100644 index 0000000000000..ffa1beed1ed65 --- /dev/null +++ b/boards/nordic/nrf54h20dk/support/nrf54h20_cpuapp.JLinkScript @@ -0,0 +1,41 @@ +// Debug Halting Control and Status Register +__constant U32 _DHCSR_ADDR = 0xE000EDF0; +__constant U32 _DHCSR_DBGKEY = (0xA05F << 16); +__constant U32 _DHCSR_C_DEBUGEN = (1 << 0); +__constant U32 _DHCSR_C_HALT = (1 << 1); + +// Debug Exception and Monitor Control Register +__constant U32 _DEMCR_ADDR = 0xE000EDFC; +__constant U32 _DEMCR_VC_CORERESET = (1 << 0); +__constant U32 _DEMCR_TRCENA = (1 << 24); + +// CPU wait enable register +__constant U32 _CPUCONF_CPUWAIT_ADDR = 0x5201150C; + +int ResetTarget(void) { + // ADAC reset + JLINK_CORESIGHT_WriteDP(2, 0x04000010); + JLINK_CORESIGHT_WriteAP(0, 0xA3030000); + JLINK_CORESIGHT_WriteAP(0, 0x00000004); + JLINK_CORESIGHT_WriteAP(0, 0x01020000); + + JLINK_SYS_Sleep(100); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + + // Halt the CPU + JLINK_MEM_WriteU32(_DHCSR_ADDR, (_DHCSR_DBGKEY | _DHCSR_C_HALT | _DHCSR_C_DEBUGEN)); + + // Set vector catch on reset (to halt the CPU immediately after reset) + JLINK_MEM_WriteU32(_DEMCR_ADDR, (_DEMCR_VC_CORERESET | _DEMCR_TRCENA)); + + // Disable CPU wait + JLINK_MEM_WriteU32(_CPUCONF_CPUWAIT_ADDR, 0); + + // Clear vector catch stuff + JLINK_MEM_WriteU32(_DEMCR_ADDR, _DEMCR_TRCENA); + + return 0; +} diff --git a/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript b/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript index 2fb7e32302e23..2f1802801c11c 100644 --- a/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript +++ b/boards/nordic/nrf54h20dk/support/nrf54h20_cpurad.JLinkScript @@ -1,4 +1,48 @@ -void ConfigTargetSettings(void) { - JLINK_ExecCommand("CORESIGHT_AddAP = Index=1 Type=AHB-AP"); - CORESIGHT_IndexAHBAPToUse = 1; +// Debug Halting Control and Status Register +__constant U32 _DHCSR_ADDR = 0xE000EDF0; +__constant U32 _DHCSR_DBGKEY = (0xA05F << 16); +__constant U32 _DHCSR_C_DEBUGEN = (1 << 0); +__constant U32 _DHCSR_C_HALT = (1 << 1); + +// Debug Exception and Monitor Control Register +__constant U32 _DEMCR_ADDR = 0xE000EDFC; +__constant U32 _DEMCR_VC_CORERESET = (1 << 0); +__constant U32 _DEMCR_TRCENA = (1 << 24); + +// CPU wait enable register +__constant U32 _CPUCONF_CPUWAIT_ADDR = 0x5301150C; + +int ConfigTargetSettings(void) { + JLINK_ExecCommand("CORESIGHT_AddAP = Index=1 Type=AHB-AP"); + CORESIGHT_IndexAHBAPToUse = 1; + + return 0; +} + +int ResetTarget(void) { + // ADAC reset + JLINK_CORESIGHT_WriteDP(2, 0x04000010); + JLINK_CORESIGHT_WriteAP(0, 0xA3030000); + JLINK_CORESIGHT_WriteAP(0, 0x00000004); + JLINK_CORESIGHT_WriteAP(0, 0x01030000); + + JLINK_SYS_Sleep(100); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + JLINK_CORESIGHT_ReadAP(2); + + // Halt the CPU + JLINK_MEM_WriteU32(_DHCSR_ADDR, (_DHCSR_DBGKEY | _DHCSR_C_HALT | _DHCSR_C_DEBUGEN)); + + // Set vector catch on reset (to halt the CPU immediately after reset) + JLINK_MEM_WriteU32(_DEMCR_ADDR, (_DEMCR_VC_CORERESET | _DEMCR_TRCENA)); + + // Disable CPU wait + JLINK_MEM_WriteU32(_CPUCONF_CPUWAIT_ADDR, 0); + + // Clear vector catch stuff + JLINK_MEM_WriteU32(_DEMCR_ADDR, _DEMCR_TRCENA); + + return 0; } diff --git a/boards/nordic/nrf54l15pdk/board.yml b/boards/nordic/nrf54l15pdk/board.yml index 6f1cfb2289332..e692040f7bd72 100644 --- a/boards/nordic/nrf54l15pdk/board.yml +++ b/boards/nordic/nrf54l15pdk/board.yml @@ -8,7 +8,7 @@ board: cpucluster: cpuflpr revision: format: major.minor.patch - default: "0.2.1" + default: "0.3.0" revisions: - name: "0.2.1" - name: "0.3.0" diff --git a/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi new file mode 100644 index 0000000000000..2938f33f22610 --- /dev/null +++ b/boards/nordic/nrf54l15pdk/nrf54l15_cpuapp_common.dtsi @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file is common to the secure and non-secure domain */ + +#include +#include "nrf54l15pdk_nrf54l15-common.dtsi" + +/ { + chosen { + zephyr,console = &uart20; + zephyr,shell-uart = &uart20; + zephyr,uart-mcumgr = &uart20; + zephyr,bt-mon-uart = &uart20; + zephyr,bt-c2h-uart = &uart20; + zephyr,flash-controller = &rram_controller; + zephyr,flash = &cpuapp_rram; + zephyr,ieee802154 = &ieee802154; + }; +}; + +&cpuapp_sram { + status = "okay"; +}; + +&lfxo { + load-capacitors = "internal"; + load-capacitance-femtofarad = <15500>; +}; + +&hfxo { + load-capacitors = "internal"; + load-capacitance-femtofarad = <15000>; +}; + +&grtc { + owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>; + /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ + child-owned-channels = <3 4 7 8 9 10 11>; + status = "okay"; +}; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(64)>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x10000 DT_SIZE_K(324)>; + }; + slot0_ns_partition: partition@61000 { + label = "image-0-nonsecure"; + reg = <0x61000 DT_SIZE_K(324)>; + }; + slot1_partition: partition@b2000 { + label = "image-1"; + reg = <0xb2000 DT_SIZE_K(324)>; + }; + slot1_ns_partition: partition@103000 { + label = "image-1-nonsecure"; + reg = <0x103000 DT_SIZE_K(324)>; + }; + /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ + storage_partition: partition@15c000 { + label = "storage"; + reg = <0x15c000 DT_SIZE_K(36)>; + }; + }; +}; + +&uart20 { + status = "okay"; + hw-flow-control; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&gpio2 { + status = "okay"; +}; + +&gpiote20 { + status = "okay"; +}; + +&gpiote30 { + status = "okay"; +}; + +&radio { + status = "okay"; +}; + +&ieee802154 { + status = "okay"; +}; + +&temp { + status = "okay"; +}; + +&clock { + status = "okay"; +}; + +&spi00 { + status = "okay"; + cs-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&spi00_default>; + pinctrl-1 = <&spi00_sleep>; + pinctrl-names = "default", "sleep"; + + mx25r64: mx25r6435f@0 { + compatible = "jedec,spi-nor"; + status = "disabled"; + reg = <0>; + spi-max-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 48 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>; + }; +}; + +&adc { + status = "okay"; +}; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi index e1931726e7162..9668cbe5bbf20 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-common.dtsi @@ -10,15 +10,15 @@ leds { compatible = "gpio-leds"; led0: led_0 { - gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; + gpios = <&gpio2 9 GPIO_ACTIVE_HIGH>; label = "Green LED 0"; }; led1: led_1 { - gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; + gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; label = "Green LED 1"; }; led2: led_2 { - gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; + gpios = <&gpio2 7 GPIO_ACTIVE_HIGH>; label = "Green LED 2"; }; led3: led_3 { @@ -27,25 +27,38 @@ }; }; + pwmleds { + compatible = "pwm-leds"; + /* + * PWM signal can be exposed on GPIO pin only within same domain. + * There is only one domain which contains both PWM and GPIO: + * PWM20/21/22 and GPIO Port P1. + * Only LEDs connected to P1 can work with PWM, for example LED1. + */ + pwm_led1: pwm_led_1 { + pwms = <&pwm20 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; + buttons { compatible = "gpio-keys"; button0: button_0 { - gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio1 13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Push button 0"; zephyr,code = ; }; button1: button_1 { - gpios = <&gpio1 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Push button 1"; zephyr,code = ; }; button2: button_2 { - gpios = <&gpio2 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio1 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Push button 2"; zephyr,code = ; }; button3: button_3 { - gpios = <&gpio2 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + gpios = <&gpio0 4 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; label = "Push button 3"; zephyr,code = ; }; @@ -56,11 +69,12 @@ led1 = &led1; led2 = &led2; led3 = &led3; + pwm-led0 = &pwm_led1; sw0 = &button0; sw1 = &button1; sw2 = &button2; sw3 = &button3; - watchdog0 = &wdt30; + watchdog0 = &wdt31; }; }; @@ -77,3 +91,10 @@ pinctrl-1 = <&uart30_sleep>; pinctrl-names = "default", "sleep"; }; + +&pwm20 { + status = "okay"; + pinctrl-0 = <&pwm20_default>; + pinctrl-1 = <&pwm20_sleep>; + pinctrl-names = "default", "sleep"; +}; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-pinctrl.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-pinctrl.dtsi index 043d35adcf41e..0b6e2056a82e1 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-pinctrl.dtsi +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15-pinctrl.dtsi @@ -64,4 +64,17 @@ low-power-enable; }; }; + + /omit-if-no-ref/ pwm20_default: pwm20_default { + group1 { + psels = ; + }; + }; + + /omit-if-no-ref/ pwm20_sleep: pwm20_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; }; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi new file mode 100644 index 0000000000000..a37cf23096670 --- /dev/null +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_2_1.dtsi @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&led0 { + gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>; +}; + +&led1 { + gpios = <&gpio1 8 GPIO_ACTIVE_HIGH>; +}; + +&led2 { + gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>; +}; + +&led3 { + gpios = <&gpio1 14 GPIO_ACTIVE_HIGH>; +}; + +&button0 { + gpios = <&gpio1 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; +}; + +&button1 { + gpios = <&gpio1 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; +}; + +&button2 { + gpios = <&gpio2 9 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; +}; + +&button3 { + gpios = <&gpio2 10 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; +}; + +&pinctrl { + /omit-if-no-ref/ pwm20_default: pwm20_default { + group1 { + psels = ; + }; + }; + + /omit-if-no-ref/ pwm20_sleep: pwm20_sleep { + group1 { + psels = ; + low-power-enable; + }; + }; +}; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_3_0.dtsi b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_3_0.dtsi deleted file mode 100644 index 282adfd6b1d69..0000000000000 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_common_0_3_0.dtsi +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&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/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts index 159bb224258c8..831479ea95037 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.dts @@ -5,146 +5,15 @@ */ /dts-v1/; -#include -#include "nrf54l15pdk_nrf54l15-common.dtsi" + +#include "nrf54l15_cpuapp_common.dtsi" / { compatible = "nordic,nrf54l15pdk_nrf54l15-cpuapp"; model = "Nordic nRF54L15 PDK nRF54L15 Application MCU"; chosen { - zephyr,console = &uart20; - zephyr,shell-uart = &uart20; - zephyr,uart-mcumgr = &uart20; - zephyr,flash-controller = &rram_controller; - zephyr,flash = &cpuapp_rram; zephyr,code-partition = &slot0_partition; zephyr,sram = &cpuapp_sram; - zephyr,ieee802154 = &ieee802154; - }; - - aliases { - spi-flash0 = &mx25r64; - }; -}; - -&cpuapp_sram { - status = "okay"; -}; - -&lfxo { - load-capacitors = "internal"; - load-capacitance-femtofarad = <15500>; -}; - -&hfxo { - load-capacitors = "internal"; - load-capacitance-femtofarad = <15000>; -}; - -&grtc { - owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>; - /* Channels 7-11 reserved for Zero Latency IRQs, 3-4 for FLPR */ - child-owned-channels = <3 4 7 8 9 10 11>; - status = "okay"; -}; - -&cpuapp_rram { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(64)>; - }; - slot0_partition: partition@10000 { - label = "image-0"; - reg = <0x10000 DT_SIZE_K(324)>; - }; - slot0_ns_partition: partition@61000 { - label = "image-0-nonsecure"; - reg = <0x61000 DT_SIZE_K(324)>; - }; - slot1_partition: partition@b2000 { - label = "image-1"; - reg = <0xb2000 DT_SIZE_K(324)>; - }; - slot1_ns_partition: partition@103000 { - label = "image-1-nonsecure"; - reg = <0x103000 DT_SIZE_K(324)>; - }; - /* 32k from 0x154000 to 0x15bfff reserved for TF-M partitions */ - storage_partition: partition@15c000 { - label = "storage"; - reg = <0x15c000 DT_SIZE_K(36)>; - }; - }; -}; - -&uart20 { - status = "okay"; - hw-flow-control; -}; - -&gpio0 { - status = "okay"; -}; - -&gpio1 { - status = "okay"; -}; - -&gpio2 { - status = "okay"; -}; - -&gpiote20 { - status = "okay"; -}; - -&gpiote30 { - status = "okay"; -}; - -&radio { - status = "okay"; -}; - -&ieee802154 { - status = "okay"; -}; - -&temp { - status = "okay"; -}; - -&clock { - status = "okay"; -}; - -&spi00 { - status = "okay"; - cs-gpios = <&gpio2 5 GPIO_ACTIVE_LOW>; - pinctrl-0 = <&spi00_default>; - pinctrl-1 = <&spi00_sleep>; - pinctrl-names = "default", "sleep"; - - mx25r64: mx25r6435f@0 { - compatible = "jedec,spi-nor"; - status = "disabled"; - reg = <0>; - spi-max-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 48 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>; }; }; diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml index 057c3b3f390bb..9213c49fdd7ba 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp.yaml @@ -9,9 +9,11 @@ toolchain: - gnuarmemb - xtools - zephyr +sysbuild: true ram: 188 flash: 324 supported: + - adc - counter - gpio - i2c diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_2_1.overlay b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_2_1.overlay new file mode 100644 index 0000000000000..1ca5cadaff999 --- /dev/null +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_2_1.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15pdk_nrf54l15_common_0_2_1.dtsi" diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay deleted file mode 100644 index a37482f7d1642..0000000000000 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.overlay +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "nrf54l15pdk_nrf54l15_common_0_3_0.dtsi" diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.yaml b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.yaml deleted file mode 100644 index a19bc8fdc8b2b..0000000000000 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuapp_0_3_0.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2024 Nordic Semiconductor ASA -# SPDX-License-Identifier: Apache-2.0 - -identifier: nrf54l15pdk@0.3.0/nrf54l15/cpuapp -name: nRF54l15-PDK-nRF54l15-Application -type: mcu -arch: arm -toolchain: - - gnuarmemb - - xtools - - zephyr -ram: 256 -flash: 1536 -supported: - - counter - - gpio - - i2c - - spi - - watchdog - - i2s diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr.yaml b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr.yaml index f05b6b74a8bec..6e8789aeab79f 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr.yaml +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr.yaml @@ -7,6 +7,7 @@ type: mcu arch: riscv toolchain: - zephyr +sysbuild: true ram: 96 flash: 96 supported: diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_2_1.overlay b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_2_1.overlay new file mode 100644 index 0000000000000..1ca5cadaff999 --- /dev/null +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_2_1.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15pdk_nrf54l15_common_0_2_1.dtsi" diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_3_0.overlay b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_3_0.overlay deleted file mode 100644 index a37482f7d1642..0000000000000 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_0_3_0.overlay +++ /dev/null @@ -1,7 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "nrf54l15pdk_nrf54l15_common_0_3_0.dtsi" diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip.yaml b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip.yaml index 0b9d635fb8dae..156cbb6f8b417 100644 --- a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip.yaml +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip.yaml @@ -7,6 +7,7 @@ type: mcu arch: riscv toolchain: - zephyr +sysbuild: true ram: 68 flash: 96 supported: diff --git a/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip_0_2_1.overlay b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip_0_2_1.overlay new file mode 100644 index 0000000000000..1ca5cadaff999 --- /dev/null +++ b/boards/nordic/nrf54l15pdk/nrf54l15pdk_nrf54l15_cpuflpr_xip_0_2_1.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf54l15pdk_nrf54l15_common_0_2_1.dtsi" diff --git a/boards/nordic/nrf9131ek/doc/index.rst b/boards/nordic/nrf9131ek/doc/index.rst index 4e328e0bb0ec8..accd403a28683 100644 --- a/boards/nordic/nrf9131ek/doc/index.rst +++ b/boards/nordic/nrf9131ek/doc/index.rst @@ -32,8 +32,8 @@ Cortex-M33F CPU with ARMv8-M Security Extension and the following devices: nRF9131 EK (Credit: Nordic Semiconductor) -The `Nordic Semiconductor Infocenter`_ -contains the processor's information and the datasheet. +The `Nordic Semiconductor TechDocs`_ will soon +contain the processor's information and the datasheet. Hardware @@ -225,5 +225,5 @@ References .. _IDAU: https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _Nordic Semiconductor TechDocs: https://docs.nordicsemi.com/ .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_common.dtsi b/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_common.dtsi index 2c3b8481d2ae8..9b87986d6f440 100644 --- a/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_common.dtsi +++ b/boards/nordic/nrf9131ek/nrf9131ek_nrf9131_common.dtsi @@ -67,7 +67,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &gd25wb256; }; }; diff --git a/boards/nordic/nrf9151dk/doc/index.rst b/boards/nordic/nrf9151dk/doc/index.rst index 40979cc90898c..4017347c4f84b 100644 --- a/boards/nordic/nrf9151dk/doc/index.rst +++ b/boards/nordic/nrf9151dk/doc/index.rst @@ -196,5 +196,5 @@ References .. _IDAU: https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau .. _nRF9151 website: https://www.nordicsemi.com/Products/nRF9151 -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _Nordic Semiconductor TechDocs: https://docs.nordicsemi.com/ .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_common.dtsi b/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_common.dtsi index 958e864c63cdc..ad4b623cf8f82 100644 --- a/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_common.dtsi +++ b/boards/nordic/nrf9151dk/nrf9151dk_nrf9151_common.dtsi @@ -128,7 +128,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &gd25wb256; }; }; diff --git a/boards/nordic/nrf9160dk/doc/index.rst b/boards/nordic/nrf9160dk/doc/index.rst index 0527bbe00b5ad..70fd2c2fc46ec 100644 --- a/boards/nordic/nrf9160dk/doc/index.rst +++ b/boards/nordic/nrf9160dk/doc/index.rst @@ -33,7 +33,7 @@ Cortex-M33F CPU with ARMv8-M Security Extension and the following devices: nRF9160 DK (Credit: Nordic Semiconductor) More information about the board can be found at the -`nRF9160 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF9160 DK website`_. `nRF9160 Product Specification`_ contains the processor's information and the datasheet. @@ -108,7 +108,7 @@ Remember to also enable routing for this additional hardware in the firmware for :ref:`nrf9160dk_nrf52840` (see :ref:`nrf9160dk_board_controller_firmware`). Other hardware features have not been enabled yet for this board. -See `nRF9160 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF9160 DK website`_ and `nRF9160 Product Specification`_ for a complete list of nRF9160 DK board hardware features. Connections and IOs @@ -282,7 +282,7 @@ SiP. More information about the board can be found at the `Nordic Low power cellular IoT`_ website. -The `Nordic Semiconductor Infocenter`_ +`nRF52840 Product Specification`_ contains the processor's information and the datasheet. @@ -526,6 +526,7 @@ References .. _nRF9160 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF9160-DK .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ .. _Nordic Low power cellular IoT: https://www.nordicsemi.com/Products/Low-power-cellular-IoT -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF9160 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf9160/page/nRF9160_html5_keyfeatures.html +.. _nRF52840 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf52840/page/keyfeatures_html5.html .. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.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 +.. _nRF9160 DK board control section in the nRF9160 DK User Guide: https://docs.nordicsemi.com/bundle/ug_nrf9160_dk/page/UG/nrf91_DK/hw_description/nrf9160_board_controller.html diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_0_7_0.yaml b/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_0_7_0.yaml index 20b765232869e..7613fabaed57c 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_0_7_0.yaml +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf52840_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9160dk@0.7.0/nrf52840 -name: nRF9160-DK-NRF52840 +name: nRF9160-DK-NRF52840 (rev. 0.7.0) type: mcu arch: arm ram: 64 diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_0_7_0.yaml b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_0_7_0.yaml index d66078fde8bb5..52a05c854556b 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_0_7_0.yaml +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9160dk@0.7.0/nrf9160 -name: nRF9160-DK-NRF9160 +name: nRF9160-DK-NRF9160 (rev. 0.7.0) type: mcu arch: arm toolchain: diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_common_0_14_0.dtsi b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_common_0_14_0.dtsi index ee4f736bf8b76..896531d75808f 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_common_0_14_0.dtsi +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_common_0_14_0.dtsi @@ -4,12 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/ { - aliases { - spi-flash0 = &mx25r64; - }; -}; - &interface_to_nrf52840 { gpio-map = <0 0 &gpio0 17 0>, <1 0 &gpio0 18 0>, diff --git a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_0_7_0.yaml b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_0_7_0.yaml index 1957bc3ad259b..0faa84b38c948 100644 --- a/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_0_7_0.yaml +++ b/boards/nordic/nrf9160dk/nrf9160dk_nrf9160_ns_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9160dk@0.7.0/nrf9160/ns -name: nRF9160-DK-NRF9160-Non-Secure +name: nRF9160-DK-NRF9160-Non-Secure (rev. 0.7.0) type: mcu arch: arm toolchain: diff --git a/boards/nordic/nrf9161dk/doc/index.rst b/boards/nordic/nrf9161dk/doc/index.rst index 8b3a7fb023682..251c8467a214c 100644 --- a/boards/nordic/nrf9161dk/doc/index.rst +++ b/boards/nordic/nrf9161dk/doc/index.rst @@ -27,7 +27,7 @@ Cortex-M33F CPU with ARMv8-M Security Extension and the following devices: * :abbr:`IDAU (Implementation Defined Attribution Unit)` More information about the board can be found at the -`nRF9161 DK website`_. The `Nordic Semiconductor Infocenter`_ +`nRF9161 DK website`_. `nRF9161 Product Specification`_ contains the processor's information and the datasheet. @@ -84,7 +84,7 @@ hardware features: .. _nrf9161dk_additional_hardware: Other hardware features have not been enabled yet for this board. -See `nRF9161 DK website`_ and `Nordic Semiconductor Infocenter`_ +See `nRF9161 DK website`_ and `nRF9161 Product Specification`_ for a complete list of nRF9161 DK board hardware features. Connections and IOs @@ -199,5 +199,5 @@ References .. _IDAU: https://developer.arm.com/docs/100690/latest/attribution-units-sau-and-idau .. _nRF9161 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF9161-DK -.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com +.. _nRF9161 Product Specification: https://docs.nordicsemi.com/bundle/ps_nrf9161/page/nRF9161_html5_keyfeatures.html .. _Trusted Firmware M: https://www.trustedfirmware.org/projects/tf-m/ diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_0_7_0.yaml b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_0_7_0.yaml index 47842c49d46d8..9d9f07dc48b85 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_0_7_0.yaml +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9161dk@0.7.0/nrf9161 -name: nRF9161-DK-NRF9161 +name: nRF9161-DK-NRF9161 (rev. 0.7.0) type: mcu arch: arm toolchain: diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common.dtsi b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common.dtsi index 8168a8317e417..93c9c140c6a6f 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common.dtsi +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common.dtsi @@ -128,7 +128,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &gd25wb256; }; }; diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common_0_7_0.dtsi b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common_0_7_0.dtsi index ae67df77b2244..5336ca3ba0667 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common_0_7_0.dtsi +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_common_0_7_0.dtsi @@ -23,9 +23,3 @@ t-exit-dpd = <30000>; }; }; - -/ { - aliases { - spi-flash0 = &gd25lb256; - }; -}; diff --git a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_0_7_0.yaml b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_0_7_0.yaml index fd95098a77345..c8224cafae41c 100644 --- a/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_0_7_0.yaml +++ b/boards/nordic/nrf9161dk/nrf9161dk_nrf9161_ns_0_7_0.yaml @@ -1,5 +1,5 @@ identifier: nrf9161dk@0.7.0/nrf9161/ns -name: nRF9161-DK-NRF9161-Non-Secure +name: nRF9161-DK-NRF9161-Non-Secure (rev. 0.7.0) type: mcu arch: arm toolchain: diff --git a/boards/nordic/thingy52/doc/index.rst b/boards/nordic/thingy52/doc/index.rst index e56f00df34370..e83968f746984 100644 --- a/boards/nordic/thingy52/doc/index.rst +++ b/boards/nordic/thingy52/doc/index.rst @@ -41,7 +41,7 @@ processor, a set of environmental sensors, a pushbutton, and two RGB LEDs. nRF52 Thingy:52 (Credit: Nordic Semiconductor) More information about the board can be found at the `nRF52 DK website`_. The -`Nordic Semiconductor Infocenter`_ contains the processor's information and the +`Nordic Thingy:52 guide`_ contains the processor's information and the datasheet. @@ -390,4 +390,4 @@ References .. target-notes:: .. _nRF52 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/Nordic-Thingy-52 -.. _Nordic Semiconductor Infocenter: http://infocenter.nordicsemi.com/ +.. _Nordic Thingy:52 guide: https://docs.nordicsemi.com/bundle/ug_thingy52/page/UG/thingy52/intro/frontpage.html diff --git a/boards/nordic/thingy53/Kconfig.defconfig b/boards/nordic/thingy53/Kconfig.defconfig index 701bd9be4e6fa..92eac11503dbe 100644 --- a/boards/nordic/thingy53/Kconfig.defconfig +++ b/boards/nordic/thingy53/Kconfig.defconfig @@ -55,9 +55,8 @@ endif # BOARD_THINGY53_NRF5340_CPUAPP_NS if !TRUSTED_EXECUTION_SECURE -choice BT_HCI_BUS_TYPE - default BT_HCI_IPC if BT -endchoice +config BT_HCI_IPC + default y if BT config HEAP_MEM_POOL_ADD_SIZE_BOARD int diff --git a/boards/nordic/thingy53/board.c b/boards/nordic/thingy53/board.c index 491808f236a22..67059bd4ee895 100644 --- a/boards/nordic/thingy53/board.c +++ b/boards/nordic/thingy53/board.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include LOG_MODULE_REGISTER(thingy53_board_init); @@ -52,7 +52,7 @@ static void enable_cpunet(void) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/nordic/thingy53/doc/index.rst b/boards/nordic/thingy53/doc/index.rst index e2f8b000f17ab..f82626e16842c 100644 --- a/boards/nordic/thingy53/doc/index.rst +++ b/boards/nordic/thingy53/doc/index.rst @@ -22,7 +22,7 @@ The ``thingy53/nrf5340/cpuapp`` build target provides support for the applicatio core on the nRF5340 SoC. The ``thingy53/nrf5340/cpunet`` build target provides support for the network core on the nRF5340 SoC. -The `Nordic Semiconductor Infocenter`_ contains the processor's information and +The `Nordic Thingy:53 Hardware guide`_ contains the processor's information and the datasheet. Programming and Debugging @@ -48,4 +48,4 @@ References .. target-notes:: -.. _Nordic Semiconductor Infocenter: http://infocenter.nordicsemi.com/ +.. _Nordic Thingy:53 Hardware guide: https://docs.nordicsemi.com/bundle/ug_thingy53/page/UG/thingy53/intro/frontpage.html diff --git a/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi b/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi index 694a6960584e4..782174d48b015 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi +++ b/boards/nordic/thingy53/thingy53_nrf5340_common.dtsi @@ -14,6 +14,7 @@ zephyr,bt-mon-uart = &cdc_acm_uart; zephyr,bt-c2h-uart = &cdc_acm_uart; zephyr,bt-hci-ipc = &ipc0; + zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; }; @@ -88,7 +89,7 @@ regulator-boot-on; }; - vbatt { + vbatt: vbatt { compatible = "voltage-divider"; io-channels = <&adc 2>; output-ohms = <180000>; @@ -155,7 +156,19 @@ }; &adc { + #address-cells = <1>; + #size-cells = <0>; status = "okay"; + + channel@2 { + reg = <2>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,vref-mv = <600>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = ; + }; }; &gpiote { diff --git a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp.yaml b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp.yaml index fbc4eb335798a..bc3d8de14b639 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp.yaml +++ b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp.yaml @@ -13,7 +13,6 @@ supported: - i2c - pwm - watchdog - - usb_cdc - usb_device - netif:openthread vendor: nordic diff --git a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns.yaml b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns.yaml index b534406ea0760..a48325cb57f63 100644 --- a/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns.yaml +++ b/boards/nordic/thingy53/thingy53_nrf5340_cpuapp_ns.yaml @@ -13,7 +13,6 @@ supported: - i2c - pwm - watchdog - - usb_cdc - usb_device - netif:openthread vendor: nordic diff --git a/boards/nuvoton/npcx4m8f_evb/npcx4m8f_evb.dts b/boards/nuvoton/npcx4m8f_evb/npcx4m8f_evb.dts index b90d94b0c9e93..2993b816956d3 100644 --- a/boards/nuvoton/npcx4m8f_evb/npcx4m8f_evb.dts +++ b/boards/nuvoton/npcx4m8f_evb/npcx4m8f_evb.dts @@ -26,7 +26,6 @@ i2c-0 = &i2c0_0; watchdog0 = &twd0; peci-0 = &peci0; - spi-flash0 = &int_flash; kscan0 = &kscan_input; }; diff --git a/boards/nuvoton/npcx7m6fb_evb/npcx7m6fb_evb.dts b/boards/nuvoton/npcx7m6fb_evb/npcx7m6fb_evb.dts index a1c6d72403be6..34a8cc9de74d5 100644 --- a/boards/nuvoton/npcx7m6fb_evb/npcx7m6fb_evb.dts +++ b/boards/nuvoton/npcx7m6fb_evb/npcx7m6fb_evb.dts @@ -28,8 +28,6 @@ i2c-0 = &i2c0_0; watchdog0 = &twd0; peci-0 = &peci0; - /* For samples/drivers/spi_flash */ - spi-flash0 = &int_flash; /* For kscan test suites */ kscan0 = &kscan_input; }; diff --git a/boards/nuvoton/npcx9m6f_evb/npcx9m6f_evb.dts b/boards/nuvoton/npcx9m6f_evb/npcx9m6f_evb.dts index 841883cc38c22..fe186dca26207 100644 --- a/boards/nuvoton/npcx9m6f_evb/npcx9m6f_evb.dts +++ b/boards/nuvoton/npcx9m6f_evb/npcx9m6f_evb.dts @@ -31,8 +31,6 @@ /* For watchdog sample */ watchdog0 = &twd0; peci-0 = &peci0; - /* For samples/drivers/spi_flash */ - spi-flash0 = &int_flash; /* For kscan test suites */ kscan0 = &kscan_input; }; diff --git a/boards/nuvoton/numaker_pfm_m467/numaker_pfm_m467.dts b/boards/nuvoton/numaker_pfm_m467/numaker_pfm_m467.dts index 28db9b9265a11..69b0aa3fafc92 100644 --- a/boards/nuvoton/numaker_pfm_m467/numaker_pfm_m467.dts +++ b/boards/nuvoton/numaker_pfm_m467/numaker_pfm_m467.dts @@ -111,8 +111,6 @@ }; &canfd0 { - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&canfd0_default>; pinctrl-names = "default"; status = "okay"; diff --git a/boards/nxp/frdm_k22f/doc/index.rst b/boards/nxp/frdm_k22f/doc/index.rst index f0f98048561c7..b92fa508cd022 100644 --- a/boards/nxp/frdm_k22f/doc/index.rst +++ b/boards/nxp/frdm_k22f/doc/index.rst @@ -26,7 +26,7 @@ MCUs. Hardware ******** -- MK22FN512VLH12 (120 MHz, 1 MB flash memory, 256 KB RAM, low-power, +- MK22FN512VLH12 (120 MHz, 512 KB flash memory, 128 KB RAM, low-power, crystal-less USB, and 64 pin Low profile Quad Flat Package (LQFP)) - Dual role USB interface with micro-B USB connector - RGB LED diff --git a/boards/nxp/frdm_k22f/frdm_k22f.dts b/boards/nxp/frdm_k22f/frdm_k22f.dts index 587aaa65ee108..5c1117a2b5791 100644 --- a/boards/nxp/frdm_k22f/frdm_k22f.dts +++ b/boards/nxp/frdm_k22f/frdm_k22f.dts @@ -1,12 +1,13 @@ /* * Copyright (c) 2018 Prevas A/S + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ /dts-v1/; -#include +#include #include #include "frdm_k22f-pinctrl.dtsi" #include @@ -203,23 +204,23 @@ zephyr_udc0: &usbotg { boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x00010000>; + reg = <0x00000000 DT_SIZE_K(64)>; read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x00028800>; + reg = <0x00010000 (DT_SIZE_K(180) + DT_SIZE_K(6))>; }; - slot1_partition: partition@38800 { + slot1_partition: partition@3E800 { label = "image-1"; - reg = <0x00038800 0x00028000>; + reg = <0x0003E800 DT_SIZE_K(180)>; }; - storage_partition: partition@60800 { + storage_partition: partition@6B800 { label = "storage"; - reg = <0x00060800 0x0001f800>; + reg = <0x0006B800 DT_SIZE_K(82)>; }; }; diff --git a/boards/nxp/frdm_k64f/frdm_k64f.dts b/boards/nxp/frdm_k64f/frdm_k64f.dts index 6fb7def19730b..7fbc1943ec902 100644 --- a/boards/nxp/frdm_k64f/frdm_k64f.dts +++ b/boards/nxp/frdm_k64f/frdm_k64f.dts @@ -233,23 +233,23 @@ zephyr_udc0: &usbotg { boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x00010000>; + reg = <0x00000000 DT_SIZE_K(64)>; read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x00069000>; + reg = <0x00010000 (DT_SIZE_K(416) + DT_SIZE_K(8))>; }; - slot1_partition: partition@79000 { + slot1_partition: partition@7a000 { label = "image-1"; - reg = <0x00079000 0x00068000>; + reg = <0x0007a000 DT_SIZE_K(416)>; }; - storage_partition: partition@e1000 { + storage_partition: partition@e2000 { label = "storage"; - reg = <0x000e1000 0x0001f000>; + reg = <0x000e2000 DT_SIZE_K(120)>; }; }; }; @@ -272,7 +272,7 @@ zephyr_udc0: &usbotg { compatible = "microchip,ksz8081"; reg = <0>; status = "okay"; - mc,interface-type = "rmii-25MHz"; + microchip,interface-type = "rmii-25MHz"; }; }; @@ -286,7 +286,6 @@ zephyr_udc0: &usbotg { status = "okay"; pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &edma0 { diff --git a/boards/nxp/frdm_k64f/frdm_k64f.yaml b/boards/nxp/frdm_k64f/frdm_k64f.yaml index b4de8b219e107..ca78929f69e12 100644 --- a/boards/nxp/frdm_k64f/frdm_k64f.yaml +++ b/boards/nxp/frdm_k64f/frdm_k64f.yaml @@ -25,5 +25,6 @@ supported: - pwm - spi - usb_device + - usbd - watchdog vendor: nxp diff --git a/boards/nxp/frdm_k82f/frdm_k82f.dts b/boards/nxp/frdm_k82f/frdm_k82f.dts index 44b88975f4d71..96640fe64323f 100644 --- a/boards/nxp/frdm_k82f/frdm_k82f.dts +++ b/boards/nxp/frdm_k82f/frdm_k82f.dts @@ -27,7 +27,6 @@ sw1 = &user_button_1; magn0 = &fxos8700; accel0 = &fxos8700; - spi-flash0 = &mx25u32; }; chosen { @@ -159,14 +158,14 @@ boot_partition: partition@0 { label = "mcuboot"; - reg = <0x0 DT_SIZE_K(48)>; + reg = <0x0 DT_SIZE_K(44)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@c000 { + slot0_partition: partition@b000 { label = "image-0"; - reg = <0xc000 DT_SIZE_K(100)>; + reg = <0xb000 (DT_SIZE_K(96) + DT_SIZE_K(8))>; }; slot1_partition: partition@25000 { label = "image-1"; diff --git a/boards/nxp/frdm_ke15z/Kconfig.frdm_ke15z b/boards/nxp/frdm_ke15z/Kconfig.frdm_ke15z new file mode 100644 index 0000000000000..32c3589c59119 --- /dev/null +++ b/boards/nxp/frdm_ke15z/Kconfig.frdm_ke15z @@ -0,0 +1,6 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_FRDM_KE15Z + select SOC_MKE15Z7 + select SOC_PART_NUMBER_MKE15Z256VLL7 diff --git a/boards/nxp/frdm_ke15z/board.cmake b/boards/nxp/frdm_ke15z/board.cmake new file mode 100644 index 0000000000000..d14370f54fa7a --- /dev/null +++ b/boards/nxp/frdm_ke15z/board.cmake @@ -0,0 +1,11 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +board_runner_args(linkserver "--device=MKE15Z256xxx7:FRDM-KE15Z") +board_runner_args(jlink "--device=MKE15Z256xxx7" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/nxp/frdm_ke15z/board.yml b/boards/nxp/frdm_ke15z/board.yml new file mode 100644 index 0000000000000..c637334b8b83e --- /dev/null +++ b/boards/nxp/frdm_ke15z/board.yml @@ -0,0 +1,5 @@ +board: + name: frdm_ke15z + vendor: nxp + socs: + - name: mke15z7 diff --git a/boards/nxp/frdm_ke15z/doc/frdm_ke15z.webp b/boards/nxp/frdm_ke15z/doc/frdm_ke15z.webp new file mode 100644 index 0000000000000..f45a78b66e24e Binary files /dev/null and b/boards/nxp/frdm_ke15z/doc/frdm_ke15z.webp differ diff --git a/boards/nxp/frdm_ke15z/doc/index.rst b/boards/nxp/frdm_ke15z/doc/index.rst new file mode 100644 index 0000000000000..fd1dec9bc67f6 --- /dev/null +++ b/boards/nxp/frdm_ke15z/doc/index.rst @@ -0,0 +1,187 @@ +.. _frdm_ke15z: + +NXP FRDM-KE15Z +############## + +Overview +******** + +The FRDM-KE15Z is a development board for NXP Kinetis KE1xZ 32-bit +MCU-based platforms. The FRDM-KE15Z contains a robust TSI module +with up to 50 channels which makes this board highly flexible +for touch keys. Offers options for serial +communication, flash programming, and run-control debugging. + +.. figure:: frdm_ke15z.webp + :align: center + :alt: FRDM-KE15Z + +Hardware +******** + +- MKE15Z256VLL7 MCU (up to 72 MHz, 256 KB flash memory, 32 KB RAM) +- OpenSDA Debug Circuit with a virtual serial port +- Touch electrodes in the self-capacitive mode +- Compatible with FRDM-TOUCH, FRDM-MC-LVBLDC, and Arduino® boards +- User Components such as Reset; RGB LED and two user buttons +- 6-axis FXOS8700CQ digital accelerometer and magnetometer + +For more information about the KE1xZ SoC and the FRDM-KE15Z board, see +these NXP reference documents: + +- `KE1XZ SOC Website`_ +- `FRDM-KE15Z Datasheet`_ +- `FRDM-KE15Z Reference Manual`_ +- `FRDM-KE15Z Website`_ +- `FRDM-KE15Z User Guide`_ +- `FRDM-KE15Z Schematics`_ + +Supported Features +================== + +The frdm_ke15z board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | uart polling; | +| | | uart interrupt | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: +:zephyr_file:`boards/nxp/frdm_ke15z/frdm_ke15z_defconfig`. + +Other hardware features are not currently supported by the port. + +System Clock +============ + +The KE15 SoC is configured to run at 48 MHz using the FIRC. + +Serial Port +=========== + +The KE15 SoC has three UARTs. UART1 is configured for the console. + +Programming and Debugging +************************* + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Configuring a Debug Probe +========================= + +A debug probe is used for both flashing and debugging the board. This board is +configured by default to use Linkserver. + +Early versions of this board have an outdated version of the OpenSDA bootloader +and require an update. Please see the `DAPLink Bootloader Update`_ page for +instructions to update from the CMSIS-DAP bootloader to the DAPLink bootloader. + +Option 1: Linkserver +------------------------------------------------------- + +Install the :ref:`linkserver-debug-host-tools` and make sure they are in your +search path. LinkServer works with the default CMSIS-DAP firmware included in +the on-board debugger. + +Linkserver is the default for this board, ``west flash`` and ``west debug`` will +call the linkserver runner. + +Option 2: :ref:`opensda-jlink-onboard-debug-probe` +-------------------------------------------------- + +Install the :ref:`jlink-debug-host-tools` and make sure they are in your search +path. + +Follow the instructions in :ref:`opensda-jlink-onboard-debug-probe` to program +the `OpenSDA J-Link Firmware for FRDM-KE15Z`_. +Use the ``-r jlink`` option with west to use the jlink runner. + +.. code-block:: console + + west flash -r jlink + +Configuring a Console +===================== + +Regardless of your choice in debug probe, we will use the OpenSDA +microcontroller as a usb-to-serial adapter for the serial console. + +Connect a USB cable from your PC to J5. + +Use the following settings with your serial terminal of choice (minicom, putty, +etc.): + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Flashing +======== + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_ke15z + :goals: flash + +Open a serial terminal, reset the board (press the SW1 button), and you should +see the following message in the terminal: + +.. code-block:: console + + *** Booting Zephyr OS build v3.6.0-3478-gb923667860b1 *** + Hello World! frdm_ke15z/mke15z7 + +Debugging +========= + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_ke15z + :goals: debug + +Open a serial terminal, step through the application in your debugger, and you +should see the following message in the terminal: + +.. code-block:: console + + ***** Booting Zephyr OS v3.6.0-xxx-gxxxxxxxxxxxx ***** + Hello World! frdm_ke15z + +.. _KE1XZ SoC Website: + https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/ke-series-arm-cortex-m4-m0-plus/ke1xz-arm-cortex-m0-plus-5v-main-stream-mcu-with-nxp-touch-and-can-control:KE1xZ + +.. _FRDM-KE15Z Datasheet: + https://www.nxp.com/docs/en/data-sheet/KE1xZP100M72SF0.pdf + +.. _FRDM-KE15Z Reference Manual: + https://www.nxp.com/webapp/Download?colCode=KE1XZP100M72SF0RM + +.. _FRDM-KE15Z Website: + https://www.nxp.com/design/design-center/development-boards-and-designs/general-purpose-mcus/freedom-development-platform-for-kinetis-ke1xmcus:FRDM-KE15Z + +.. _FRDM-KE15Z User Guide: + https://www.nxp.com/document/guide/get-started-with-the-frdm-ke15z:NGS-FRDM-KE15Z + +.. _FRDM-KE15Z Schematics: + https://www.nxp.com/webapp/Download?colCode=FRDM-KE15Z-SCH-DESIGNFILES + +.. _DAPLink Bootloader Update: + https://os.mbed.com/blog/entry/DAPLink-bootloader-update/ + +.. _OpenSDA J-Link Firmware for FRDM-KE15Z: + https://www.segger.com/downloads/jlink/OpenSDA_FRDM-KE15Z diff --git a/boards/nxp/frdm_ke15z/frdm_ke15z-pinctrl.dtsi b/boards/nxp/frdm_ke15z/frdm_ke15z-pinctrl.dtsi new file mode 100644 index 0000000000000..b004d91e60c04 --- /dev/null +++ b/boards/nxp/frdm_ke15z/frdm_ke15z-pinctrl.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright 2024 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + lpuart1_default: lpuart1_default { + group0 { + pinmux = , + ; + drive-strength = "low"; + slew-rate = "slow"; + }; + }; +}; diff --git a/boards/nxp/frdm_ke15z/frdm_ke15z.dts b/boards/nxp/frdm_ke15z/frdm_ke15z.dts new file mode 100644 index 0000000000000..0a1c341b0008d --- /dev/null +++ b/boards/nxp/frdm_ke15z/frdm_ke15z.dts @@ -0,0 +1,76 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "frdm_ke15z-pinctrl.dtsi" +#include + +/ { + model = "NXP Freedom KE15Z board"; + compatible = "nxp,ke15z", "nxp,mke15z7"; + + aliases { + led0 = &green_led; + led1 = &blue_led; + led2 = &red_led; + sw0 = &user_button_0; + sw1 = &user_button_1; + }; + + chosen { + zephyr,sram = &sram_u; + zephyr,flash = &flash0; + zephyr,console = &lpuart1; + zephyr,shell-uart = &lpuart1; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpiod 0 GPIO_ACTIVE_LOW>; + label = "RED LED"; + }; + green_led: led_1 { + gpios = <&gpiod 16 GPIO_ACTIVE_LOW>; + label = "GREEN LED"; + }; + blue_led: led_2 { + gpios = <&gpiod 15 GPIO_ACTIVE_LOW>; + label = "BLUE LED"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button_0: button_0 { + label = "User SW3"; + gpios = <&gpiod 3 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + user_button_1: button_1 { + label = "User SW2"; + gpios = <&gpiob 11 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; +}; + +&lpuart1 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&lpuart1_default>; + pinctrl-names = "default"; +}; + +&gpiob { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; diff --git a/boards/nxp/frdm_ke15z/frdm_ke15z.yaml b/boards/nxp/frdm_ke15z/frdm_ke15z.yaml new file mode 100644 index 0000000000000..9a2a7ac4b272b --- /dev/null +++ b/boards/nxp/frdm_ke15z/frdm_ke15z.yaml @@ -0,0 +1,13 @@ +identifier: frdm_ke15z +name: NXP FRDM-KE15Z +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +flash: 256 +ram: 24 +supported: + - gpio + - uart diff --git a/boards/nxp/frdm_ke15z/frdm_ke15z_defconfig b/boards/nxp/frdm_ke15z/frdm_ke15z_defconfig new file mode 100644 index 0000000000000..69a85bdc43dda --- /dev/null +++ b/boards/nxp/frdm_ke15z/frdm_ke15z_defconfig @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# GPIO Controller +CONFIG_GPIO=y + +# Clock Control +CONFIG_CLOCK_CONTROL=y + +# Enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/nxp/frdm_ke17z/Kconfig.frdm_ke17z b/boards/nxp/frdm_ke17z/Kconfig.frdm_ke17z new file mode 100644 index 0000000000000..a6285f73c3e91 --- /dev/null +++ b/boards/nxp/frdm_ke17z/Kconfig.frdm_ke17z @@ -0,0 +1,7 @@ +# FRDM-KE17Z board configuration +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_FRDM_KE17Z + select SOC_MKE17Z7 + select SOC_PART_NUMBER_MKE17Z256VLL7 diff --git a/boards/nxp/frdm_ke17z/board.cmake b/boards/nxp/frdm_ke17z/board.cmake new file mode 100644 index 0000000000000..9599e8d3fe650 --- /dev/null +++ b/boards/nxp/frdm_ke17z/board.cmake @@ -0,0 +1,8 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(linkserver "--device=MKE17Z256xxx7:FRDM-KE17Z") +board_runner_args(jlink "--device=MKE17Z256xxx7" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/nxp/frdm_ke17z/board.yml b/boards/nxp/frdm_ke17z/board.yml new file mode 100644 index 0000000000000..a6b72f27f206a --- /dev/null +++ b/boards/nxp/frdm_ke17z/board.yml @@ -0,0 +1,5 @@ +board: + name: frdm_ke17z + vendor: nxp + socs: + - name: mke17z7 diff --git a/boards/nxp/frdm_ke17z/doc/frdmke17z.webp b/boards/nxp/frdm_ke17z/doc/frdmke17z.webp new file mode 100644 index 0000000000000..0110e73bd2462 Binary files /dev/null and b/boards/nxp/frdm_ke17z/doc/frdmke17z.webp differ diff --git a/boards/nxp/frdm_ke17z/doc/index.rst b/boards/nxp/frdm_ke17z/doc/index.rst new file mode 100644 index 0000000000000..c389c02ddca82 --- /dev/null +++ b/boards/nxp/frdm_ke17z/doc/index.rst @@ -0,0 +1,198 @@ +.. _frdm_ke17z: + +NXP FRDM-KE17Z +############## + +Overview +******** + +The FRDM-KE17Z is a development board for NXP Kinetis KE1xZ 32-bit +MCU-based platforms. The FRDM-KE17Z contains a robust TSI module +with up to 50 channels which makes this board highly flexible +for touch keys. Offers options for serial +communication, flash programming, and run-control debugging. + +.. figure:: frdmke17z.webp + :align: center + :alt: FRDM-KE17Z + + FRDM-KE17Z (Credit: NXP) + +Hardware +******** + +- MKE17Z256VLL7 MCU (up to 72 MHz, 256 KB flash memory, 48 KB SRAM, + and 100 Low profile Quad Flat Package (LQFP)) +- 3.3 V or 5 V MCU operation +- 6-axis FXOS8700CQ digital accelerometer +- 3-axis digital angular rate gyroscope +- One RGB LED +- Two user push-buttons +- Thermistor +- Two capacitive touchpads +- Flex I/O pin header + +For more information about the KE1xZ SoC and the FRDM-KE17Z board, see +these NXP reference documents: + +- `FRDM-KE17Z Website`_ +- `FRDM-KE17Z User Guide`_ +- `FRDM-KE17Z Reference Manual`_ +- `FRDM-KE17Z Datasheet`_ + +Supported Features +================== + +The frdm_ke17z board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| PINCTRL | on-chip | pinctrl | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | uart | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in the defconfig file: +:zephyr_file:`boards/nxp/frdm_ke17z/frdm_ke17z_defconfig`. + +Other hardware features are not currently supported by the port. + +System Clock +============ + +The KE17Z SoC is configured to run at 48 MHz using the FIRC. + +Serial Port +=========== + +The KE17Z SoC has three UARTs. UART0 is configured for the console. + +Programming and Debugging +************************* + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Configuring a Debug Probe +========================= + +A debug probe is used for both flashing and debugging the board. This board is +configured by default to use Linkserver. + +Early versions of this board have an outdated version of the OpenSDA bootloader +and require an update. Please see the `DAPLink Bootloader Update`_ page for +instructions to update from the CMSIS-DAP bootloader to the DAPLink bootloader. + +Option 1: Linkserver +-------------------- + +Install the :ref:`linkserver-debug-host-tools` and make sure they are in your +search path. LinkServer works with the default CMSIS-DAP firmware included in +the on-board debugger. + + Linkserver is the default for this board, ``west flash`` and ``west debug`` will + call the linkserver runner. + +.. code-block:: console + + west flash + + +External JLink: :ref:`jlink-external-debug-probe` +------------------------------------------------- + +Install the :ref:`jlink-debug-host-tools` and make sure they are in your search +path. + +Attach a J-Link 10-pin connector to J14. Check that jumpers J8 and J9 are +**off** (they are on by default when boards ship from the factory) to ensure +SWD signals are disconnected from the OpenSDA microcontroller. +Use the ``-r jlink`` option with west to use the jlink runner. + +.. code-block:: console + + west flash -r jlink + +Configuring a Console +===================== + +Regardless of your choice in debug probe, we will use the OpenSDA +microcontroller as a usb-to-serial adapter for the serial console. + +Connect a USB cable from your PC to J6. + +Use the following settings with your serial terminal of choice (minicom, putty, +etc.): + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Flashing +======== + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_ke17z + :goals: flash + +Open a serial terminal, reset the board (press the SW1 button), and you should +see the following message in the terminal: + +.. code-block:: console + + *** Booting Zephyr OS build xxxxxxxxxxxx *** + Hello World! frdm_ke17z/mke17z7 + +Debugging +========= + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_ke17z + :goals: debug + +Open a serial terminal, step through the application in your debugger, and you +should see the following message in the terminal: + +.. code-block:: console + + *** Booting Zephyr OS build xxxxxxxxxxxx *** + Hello World! frdm_ke17z/mke17z7 + +.. _FRDM-KE17Z Website: + https://www.nxp.com/design/design-center/development-boards-and-designs/general-purpose-mcus/freedom-development-platform-for-72mhz-ke17z-ke13z-ke12z-mcus:FRDM-KE17Z + +.. _FRDM-KE17Z User Guide: + https://www.nxp.com/docs/en/user-guide/KE17ZHDG.pdf + +.. _FRDM-KE17Z Reference Manual: + https://www.nxp.com/docs/en/reference-manual/KE1xZP100M72SF1RM.pdf + +.. _FRDM-KE17Z Datasheet: + https://www.nxp.com/docs/en/data-sheet/KE1xZP100M72SF1.pdf + +.. _DAPLink Bootloader Update: + https://os.mbed.com/blog/entry/DAPLink-bootloader-update/ + +.. _OpenSDA DAPLink FRDM-KE17Z Firmware: + https://www.nxp.com/design/design-center/software/sensor-toolbox/opensda-serial-and-debug-adapter:OPENSDA?tid=vanOpenSDA + +.. _linkserver-debug-host-tools: + https://www.nxp.com/lgfiles/updates/mcuxpresso/LinkServer_1.5.30.exe + +.. _OpenSDA J-Link Firmware for FRDM-KE17Z: + https://www.segger.com/downloads/jlink/OpenSDA_FRDM-KE17Z diff --git a/boards/nxp/frdm_ke17z/frdm_ke17z-pinctrl.dtsi b/boards/nxp/frdm_ke17z/frdm_ke17z-pinctrl.dtsi new file mode 100644 index 0000000000000..6791b0f337e74 --- /dev/null +++ b/boards/nxp/frdm_ke17z/frdm_ke17z-pinctrl.dtsi @@ -0,0 +1,20 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include + +&pinctrl { + + lpuart0_default: lpuart0_default { + group0 { + pinmux = , + ; + drive-strength = "low"; + slew-rate = "slow"; + }; + }; +}; diff --git a/boards/nxp/frdm_ke17z/frdm_ke17z.dts b/boards/nxp/frdm_ke17z/frdm_ke17z.dts new file mode 100644 index 0000000000000..fb65ed9670c4d --- /dev/null +++ b/boards/nxp/frdm_ke17z/frdm_ke17z.dts @@ -0,0 +1,76 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "frdm_ke17z-pinctrl.dtsi" +#include + +/ { + model = "NXP Freedom KE17Z board"; + compatible = "nxp,frdm-ke17z", "nxp,ke17z", "nxp,mke17z7"; + + aliases { + led0 = &red_led; + led1 = &green_led; + led2 = &blue_led; + sw0 = &user_button_0; + sw1 = &user_button_1; + }; + + chosen { + zephyr,sram = &sram_u; + zephyr,flash = &flash0; + zephyr,console = &lpuart0; + zephyr,shell-uart = &lpuart0; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpiod 10 GPIO_ACTIVE_LOW>; + label = "RGB RED"; + }; + green_led: led_1 { + gpios = <&gpiod 11 GPIO_ACTIVE_LOW>; + label = "RGB GREEN"; + }; + blue_led: led_2 { + gpios = <&gpiod 12 GPIO_ACTIVE_LOW>; + label = "RGB BLUE"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button_0: button_0 { + label = "User SW2"; + gpios = <&gpiod 3 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + user_button_1: button_1 { + label = "User SW3"; + gpios = <&gpioe 14 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; +}; + +&lpuart0 { + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&lpuart0_default>; + pinctrl-names = "default"; +}; + +&gpiod { + status = "okay"; +}; + +&gpioe { + status = "okay"; +}; diff --git a/boards/nxp/frdm_ke17z/frdm_ke17z.yaml b/boards/nxp/frdm_ke17z/frdm_ke17z.yaml new file mode 100644 index 0000000000000..04755ea9eed64 --- /dev/null +++ b/boards/nxp/frdm_ke17z/frdm_ke17z.yaml @@ -0,0 +1,14 @@ +identifier: frdm_ke17z +name: NXP FRDM-KE17Z +type: mcu +arch: arm +ram: 32 +flash: 256 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - uart +vendor: nxp diff --git a/boards/nxp/frdm_ke17z/frdm_ke17z_defconfig b/boards/nxp/frdm_ke17z/frdm_ke17z_defconfig new file mode 100644 index 0000000000000..5d3e6d7ee2421 --- /dev/null +++ b/boards/nxp/frdm_ke17z/frdm_ke17z_defconfig @@ -0,0 +1,20 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y + +# GPIO Controller +CONFIG_GPIO=y + +# Clock Control +CONFIG_CLOCK_CONTROL=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000 + +# Enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/nxp/frdm_ke17z512/Kconfig.frdm_ke17z512 b/boards/nxp/frdm_ke17z512/Kconfig.frdm_ke17z512 new file mode 100644 index 0000000000000..0ac331398d2df --- /dev/null +++ b/boards/nxp/frdm_ke17z512/Kconfig.frdm_ke17z512 @@ -0,0 +1,6 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_FRDM_KE17Z512 + select SOC_MKE17Z9 + select SOC_PART_NUMBER_MKE17Z512VLL9 diff --git a/boards/nxp/frdm_ke17z512/board.cmake b/boards/nxp/frdm_ke17z512/board.cmake new file mode 100644 index 0000000000000..4c09a06e95ed4 --- /dev/null +++ b/boards/nxp/frdm_ke17z512/board.cmake @@ -0,0 +1,11 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +board_runner_args(linkserver "--device=MKE17Z512xxx9:FRDM-KE17Z512") +board_runner_args(jlink "--device=MKE17Z512xxx9" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/nxp/frdm_ke17z512/board.yml b/boards/nxp/frdm_ke17z512/board.yml new file mode 100644 index 0000000000000..46839e065b1dd --- /dev/null +++ b/boards/nxp/frdm_ke17z512/board.yml @@ -0,0 +1,5 @@ +board: + name: frdm_ke17z512 + vendor: nxp + socs: + - name: mke17z9 diff --git a/boards/nxp/frdm_ke17z512/doc/frdm_ke17z512.webp b/boards/nxp/frdm_ke17z512/doc/frdm_ke17z512.webp new file mode 100644 index 0000000000000..d068f9257636a Binary files /dev/null and b/boards/nxp/frdm_ke17z512/doc/frdm_ke17z512.webp differ diff --git a/boards/nxp/frdm_ke17z512/doc/index.rst b/boards/nxp/frdm_ke17z512/doc/index.rst new file mode 100644 index 0000000000000..46fe54c63d1ea --- /dev/null +++ b/boards/nxp/frdm_ke17z512/doc/index.rst @@ -0,0 +1,201 @@ +.. _frdm_ke17z512: + +NXP FRDM-KE17Z512 +################## + +Overview +******** + +The FRDM-KE17Z512 is a development board for NXP Kinetis KE1xZ 32-bit +MCU-based platforms. The onboard OpenSDAv2 serial and debug adapter, +running an open source bootloader, offers options for serial +communication, flash programming, and run-control debugging. + +.. figure:: frdm_ke17z512.webp + :align: center + :alt: FRDM-KE17Z512 + + FRDM-KE17Z512 (Credit: NXP) + +Hardware +******** + +- MKE17Z512VLL9 MCU (up to 96 MHz, 512 KB flash memory, 96 KB RAM, + and 100 Low profile Quad Flat Package (LQFP)) +- 3.3 V or 5 V MCU operation +- 6-axis FXOS8700CQ digital accelerometer and magnetometer +- RGB LED +- Two user push-buttons +- Thermistor +- Arduino compatible I/O pin header +- OpenSDA on-board debugger +- Two Touch Electrodes + +For more information about the KE1xZ SoC and the FRDM-KE17Z512 board, see +these NXP reference documents: + +- `KE1xZ Website`_ +- `KE1xZ Fact Sheet`_ +- `KE1xZ Reference Manual`_ +- `FRDM-KE17Z512 Website`_ +- `FRDM-KE17Z512 Quick Start Guide`_ +- `FRDM-KE17Z512 Reference Manual`_ + +Supported Features +================== + +The frdm_ke17z512 board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | uart polling; | +| | | uart interrupt | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | I2C | ++-----------+------------+-------------------------------------+ + + +The default configuration can be found in the defconfig file: +``boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig``. + +Other hardware features are not currently supported by the port. + +System Clock +============ + +The KE17Z9 SoC is configured to run at 48 MHz using the FIRC. + +Serial Port +=========== + +The KE17Z9 SoC has three LPUARTs. UART2 is configured for the console. + +Programming and Debugging +************************* + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Configuring a Debug Probe +========================= + +A debug probe is used for both flashing and debugging the board. This board is +configured by default to use Linkserver. + +Early versions of this board have an outdated version of the OpenSDA bootloader +and require an update. Please see the `DAPLink Bootloader Update`_ page for +instructions to update from the CMSIS-DAP bootloader to the DAPLink bootloader. + +Option 1: Linkserver +-------------------- + +Install the :ref:`linkserver-debug-host-tools` and make sure they are in your +search path. LinkServer works with the default CMSIS-DAP firmware included in +the on-board debugger. + +Linkserver is the default for this board, ``west flash`` and ``west debug`` will +call the linkserver runner. + +Option 2: :ref:`opensda-jlink-onboard-debug-probe` +-------------------------------------------------- + +Install the :ref:`jlink-debug-host-tools` and make sure they are in your search +path. + +Follow the instructions in :ref:`opensda-jlink-onboard-debug-probe` to program +the `Segger J-Link OpenSDA V2.1 Firmware`_. +Use the ``-r jlink`` option with west to use the jlink runner. + +.. code-block:: console + + west flash -r jlink + +Configuring a Console +===================== + +Regardless of your choice in debug probe, we will use the OpenSDA +microcontroller as a usb-to-serial adapter for the serial console. + +Connect a USB cable from your PC to J10. + +Use the following settings with your serial terminal of choice (minicom, putty, +etc.): + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Flashing +======== + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_ke17z512 + :goals: flash + +Open a serial terminal, reset the board (press the SW1 button), and you should +see the following message in the terminal: + +.. code-block:: console + + *** Booting Zephyr OS build v3.6.0-xxxx-gxxxxxxxxxxxx *** + Hello World! frdm_ke17z512/mke17z9 + +Debugging +========= + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_ke17z512 + :goals: debug + +Open a serial terminal, step through the application in your debugger, and you +should see the following message in the terminal: + +.. code-block:: console + + *** Booting Zephyr OS build v3.6.0-xxxx-gxxxxxxxxxxxx *** + Hello World! frdm_ke17z512/mke17z9 + +.. _FRDM-KE17Z512 Website: + https://www.nxp.com/design/design-center/development-boards-and-designs/general-purpose-mcus/frdm-development-board-for-96-mhz-ke17z-ke13z-ke12z-with-512-kb-flash-mcus:FRDM-KE17Z512 + +.. _FRDM-KE17Z512 Quick Start Guide: + https://www.nxp.com/docs/en/quick-reference-guide/FRDMKE17Z512QSG.pdf + +.. _FRDM-KE17Z512 Reference Manual: + https://www.nxp.com/docs/en/reference-manual/KE1XZP100M96SF0RM.pdf + +.. _KE1xZ Website: + https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/general-purpose-mcus/ke-series-arm-cortex-m4-m0-plus/ke1xz-arm-cortex-m0-plus-5v-main-stream-mcu-with-nxp-touch-and-can-control:KE1xZ + +.. _KE1xZ Fact Sheet: + https://www.nxp.com/docs/en/fact-sheet/KE1xZMCUFAMFS.pdf + +.. _KE1xZ Reference Manual: + https://www.nxp.com/webapp/Download?colCode=KE1XZP100M72SF0RM + +.. _linkserver-debug-host-tools: + https://www.nxp.com/lgfiles/updates/mcuxpresso/LinkServer_1.5.30.exe + +.. _Segger J-Link OpenSDA V2.1 Firmware: + https://www.segger.com/downloads/jlink/OpenSDA_V2_1.bin + +.. _DAPLink Bootloader Update: + https://os.mbed.com/blog/entry/DAPLink-bootloader-update/ + +.. _jlink-debug-host-tools: + https://www.segger.com/downloads/jlink/JLink_Windows_V794_x86_64.exe diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi b/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi new file mode 100644 index 0000000000000..7d745ff8bf628 --- /dev/null +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512-pinctrl.dtsi @@ -0,0 +1,41 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include + +&pinctrl { + + /* Configures pin routing and optionally pin electrical features. */ + lpuart2_default: lpuart2_default { + group0 { + pinmux = , + ; + drive-strength = "low"; + slew-rate = "slow"; + }; + }; + + lpi2c0_default: lpi2c0_default { + group0 { + pinmux = , + ; + bias-pull-up; + drive-strength = "low"; + slew-rate = "slow"; + }; + }; + + lpi2c1_default: lpi2c1_default { + group0 { + pinmux = , + ; + bias-pull-up; + drive-strength = "low"; + slew-rate = "slow"; + }; + }; +}; diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts b/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts new file mode 100644 index 0000000000000..704ef4811bc1f --- /dev/null +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512.dts @@ -0,0 +1,88 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "frdm_ke17z512-pinctrl.dtsi" +#include + +/ { + model = "NXP Freedom KE17Z512 board"; + compatible = "nxp,ke17z512", "nxp,mke17z9", "nxp,ke1xz"; + + chosen { + zephyr,sram = &sram_u; + zephyr,flash = &flash0; + zephyr,console = &lpuart2; + zephyr,shell-uart = &lpuart2; + }; + + aliases { + led0 = &red_led; + led1 = &green_led; + led2 = &blue_led; + sw0 = &user_button_2; + sw1 = &user_button_3; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_0 { + gpios = <&gpiod 10 GPIO_ACTIVE_LOW>; + label = "Red LED"; + }; + green_led: led_1 { + gpios = <&gpiod 5 GPIO_ACTIVE_LOW>; + label = "Green LED"; + }; + blue_led: led_2 { + gpios = <&gpiod 12 GPIO_ACTIVE_LOW>; + label = "Blue LED"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button_2: button_0 { + label = "User SW2"; + gpios = <&gpioe 14 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + user_button_3: button_1 { + label = "User SW3"; + gpios = <&gpiod 3 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; +}; + +&lpuart2 { + status = "okay"; + pinctrl-0 = <&lpuart2_default>; + pinctrl-names = "default"; + current-speed = <115200>; +}; + +&gpiod { + status = "okay"; +}; + +&gpioe { + status = "okay"; +}; + +&lpi2c0 { + status = "okay"; + pinctrl-0 = <&lpi2c0_default>; + pinctrl-names = "default"; +}; + +&lpi2c1 { + status = "okay"; + pinctrl-0 = <&lpi2c1_default>; + pinctrl-names = "default"; +}; diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml b/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml new file mode 100644 index 0000000000000..f836b931e1e4c --- /dev/null +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512.yaml @@ -0,0 +1,21 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: frdm_ke17z512 +name: NXP FRDM-KE17Z512 +type: mcu +arch: arm +ram: 64 +flash: 512 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - uart + - i2c +vendor: nxp diff --git a/boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig b/boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig new file mode 100644 index 0000000000000..d1237a34ce714 --- /dev/null +++ b/boards/nxp/frdm_ke17z512/frdm_ke17z512_defconfig @@ -0,0 +1,12 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_GPIO=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=48000000 +CONFIG_PINCTRL=y diff --git a/boards/nxp/frdm_mcxn947/Kconfig.defconfig b/boards/nxp/frdm_mcxn947/Kconfig.defconfig index 72cc76170b974..5334a121e40f4 100644 --- a/boards/nxp/frdm_mcxn947/Kconfig.defconfig +++ b/boards/nxp/frdm_mcxn947/Kconfig.defconfig @@ -6,4 +6,19 @@ if BOARD_FRDM_MCXN947 config NET_L2_ETHERNET default y if NETWORKING +if SD_STACK + +# SD stack requires larger main stack size +config MAIN_STACK_SIZE + default 1536 + +endif + +if BOOTLOADER_MCUBOOT +choice MCUBOOT_BOOTLOADER_MODE + # Board only supports MCUBoot via "upgrade only" method: + default MCUBOOT_BOOTLOADER_MODE_OVERWRITE_ONLY +endchoice +endif #BOOTLOADER_MCUBOOT + endif diff --git a/boards/nxp/frdm_mcxn947/board.c b/boards/nxp/frdm_mcxn947/board.c index 29b4bbf846129..ab41600737c6a 100644 --- a/boards/nxp/frdm_mcxn947/board.c +++ b/boards/nxp/frdm_mcxn947/board.c @@ -8,6 +8,15 @@ #include #include #include +#if CONFIG_USB_DC_NXP_EHCI +#include "usb_phy.h" +#include "usb.h" + +/* USB PHY condfiguration */ +#define BOARD_USB_PHY_D_CAL (0x04U) +#define BOARD_USB_PHY_TXCAL45DP (0x07U) +#define BOARD_USB_PHY_TXCAL45DM (0x07U) +#endif /* Board xtal frequency in Hz */ #define BOARD_XTAL0_CLK_HZ 24000000U @@ -95,6 +104,27 @@ static int frdm_mcxn947_init(void) /* Set AHBCLKDIV divider to value 1 */ CLOCK_SetClkDiv(kCLOCK_DivAhbClk, 1U); + CLOCK_SetupExtClocking(BOARD_XTAL0_CLK_HZ); + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan0), okay) + /* Set up PLL1 for 80 MHz FlexCAN clock */ + const pll_setup_t pll1Setup = { + .pllctrl = SCG_SPLLCTRL_SOURCE(1U) | SCG_SPLLCTRL_SELI(27U) | + SCG_SPLLCTRL_SELP(13U), + .pllndiv = SCG_SPLLNDIV_NDIV(3U), + .pllpdiv = SCG_SPLLPDIV_PDIV(1U), + .pllmdiv = SCG_SPLLMDIV_MDIV(10U), + .pllRate = 80000000U + }; + + /* Configure PLL1 to the desired values */ + CLOCK_SetPLL1Freq(&pll1Setup); + /* PLL1 Monitor is disabled */ + CLOCK_SetPll1MonitorMode(kSCG_Pll1MonitorDisable); + /* Set PLL1 CLK0 divider to value 1 */ + CLOCK_SetClkDiv(kCLOCK_DivPLL1Clk0, 1U); +#endif + #if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcomm1), okay) CLOCK_SetClkDiv(kCLOCK_DivFlexcom1Clk, 1u); CLOCK_AttachClk(kFRO12M_to_FLEXCOMM1); @@ -192,6 +222,16 @@ static int frdm_mcxn947_init(void) CLOCK_AttachClk(kPLL0_to_CTIMER4); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(flexcan0), okay) + CLOCK_SetClkDiv(kCLOCK_DivFlexcan0Clk, 1U); + CLOCK_AttachClk(kPLL1_CLK0_to_FLEXCAN0); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usdhc0), okay) + CLOCK_SetClkDiv(kCLOCK_DivUSdhcClk, 1u); + CLOCK_AttachClk(kFRO_HF_to_USDHC); +#endif + #if CONFIG_FLASH_MCUX_FLEXSPI_NOR /* We downclock the FlexSPI to 50MHz, it will be set to the * optimum speed supported by the Flash device during FLEXSPI @@ -200,6 +240,73 @@ static int frdm_mcxn947_init(void) flexspi_clock_set_freq(MCUX_FLEXSPI_CLK, MHZ(50)); #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(vref), okay) + CLOCK_EnableClock(kCLOCK_Vref); + SPC_EnableActiveModeAnalogModules(SPC0, kSPC_controlVref); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpadc0), okay) + CLOCK_SetClkDiv(kCLOCK_DivAdc0Clk, 1U); + CLOCK_AttachClk(kFRO_HF_to_ADC0); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) && CONFIG_USB_DC_NXP_EHCI + usb_phy_config_struct_t usbPhyConfig = { + BOARD_USB_PHY_D_CAL, BOARD_USB_PHY_TXCAL45DP, BOARD_USB_PHY_TXCAL45DM, + }; + + SPC0->ACTIVE_VDELAY = 0x0500; + /* Change the power DCDC to 1.8v (By default, DCDC is 1.8V), CORELDO to 1.1v (By default, + * CORELDO is 1.0V) + */ + SPC0->ACTIVE_CFG &= ~SPC_ACTIVE_CFG_CORELDO_VDD_DS_MASK; + SPC0->ACTIVE_CFG |= SPC_ACTIVE_CFG_DCDC_VDD_LVL(0x3) | SPC_ACTIVE_CFG_CORELDO_VDD_LVL(0x3) | + SPC_ACTIVE_CFG_SYSLDO_VDD_DS_MASK | SPC_ACTIVE_CFG_DCDC_VDD_DS(0x2u); + /* Wait until it is done */ + while (SPC0->SC & SPC_SC_BUSY_MASK) { + }; + if (0u == (SCG0->LDOCSR & SCG_LDOCSR_LDOEN_MASK)) { + SCG0->TRIM_LOCK = 0x5a5a0001U; + SCG0->LDOCSR |= SCG_LDOCSR_LDOEN_MASK; + /* wait LDO ready */ + while (0U == (SCG0->LDOCSR & SCG_LDOCSR_VOUT_OK_MASK)) { + }; + } + SYSCON->AHBCLKCTRLSET[2] |= SYSCON_AHBCLKCTRL2_USB_HS_MASK | + SYSCON_AHBCLKCTRL2_USB_HS_PHY_MASK; + SCG0->SOSCCFG &= ~(SCG_SOSCCFG_RANGE_MASK | SCG_SOSCCFG_EREFS_MASK); + /* xtal = 20 ~ 30MHz */ + SCG0->SOSCCFG = (1U << SCG_SOSCCFG_RANGE_SHIFT) | (1U << SCG_SOSCCFG_EREFS_SHIFT); + SCG0->SOSCCSR |= SCG_SOSCCSR_SOSCEN_MASK; + while (1) { + if (SCG0->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) { + break; + } + } + SYSCON->CLOCK_CTRL |= SYSCON_CLOCK_CTRL_CLKIN_ENA_MASK | + SYSCON_CLOCK_CTRL_CLKIN_ENA_FM_USBH_LPT_MASK; + CLOCK_EnableClock(kCLOCK_UsbHs); + CLOCK_EnableClock(kCLOCK_UsbHsPhy); + CLOCK_EnableUsbhsPhyPllClock(kCLOCK_Usbphy480M, BOARD_XTAL0_CLK_HZ); + CLOCK_EnableUsbhsClock(); + USB_EhciPhyInit(kUSB_ControllerEhci0, BOARD_XTAL0_CLK_HZ, &usbPhyConfig); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpcmp0), okay) + CLOCK_SetClkDiv(kCLOCK_DivCmp0FClk, 1U); + CLOCK_AttachClk(kFRO12M_to_CMP0F); + SPC_EnableActiveModeAnalogModules(SPC0, (kSPC_controlCmp0 | kSPC_controlCmp0Dac)); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(lptmr0), okay) + CLOCK_SetupClk16KClocking(kCLOCK_Clk16KToVsys); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(flexio0), okay) + CLOCK_SetClkDiv(kCLOCK_DivFlexioClk, 1u); + CLOCK_AttachClk(kPLL0_to_FLEXIO); +#endif + /* Set SystemCoreClock variable. */ SystemCoreClock = CLOCK_INIT_CORE_CLOCK; diff --git a/boards/nxp/frdm_mcxn947/board.cmake b/boards/nxp/frdm_mcxn947/board.cmake index 86cdff853d9b5..fa5862e5e008f 100644 --- a/boards/nxp/frdm_mcxn947/board.cmake +++ b/boards/nxp/frdm_mcxn947/board.cmake @@ -23,6 +23,9 @@ else() message(FATAL_ERROR "Support for cpu1 not available yet") endif() +# Pyocd support added with the NXP.MCXN947_DFP.17.0.0.pack CMSIS Pack +board_runner_args(pyocd "--target=mcxn947") include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/nxp/frdm_mcxn947/doc/index.rst b/boards/nxp/frdm_mcxn947/doc/index.rst index cf63ab6abff72..7b4a4d9b357b2 100644 --- a/boards/nxp/frdm_mcxn947/doc/index.rst +++ b/boards/nxp/frdm_mcxn947/doc/index.rst @@ -82,6 +82,25 @@ The FRDM-MCXN947 board configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | CTIMER | on-chip | counter | +-----------+------------+-------------------------------------+ +| USDHC | on-chip | sdhc | ++-----------+------------+-------------------------------------+ +| VREF | on-chip | REGULATOR | ++-----------+------------+-------------------------------------+ +| ADC | on-chip | adc | ++-----------+------------+-------------------------------------+ +| USBHS | on-chip | USB device | ++-----------+------------+-------------------------------------+ +| LPCMP | on-chip | sensor(comparator) | ++-----------+------------+-------------------------------------+ +| FLEXCAN | on-chip | CAN | ++-----------+------------+-------------------------------------+ +| LPTMR | on-chip | counter | ++-----------+------------+-------------------------------------+ +| FLEXIO | on-chip | flexio | ++-----------+------------+-------------------------------------+ +| DISPLAY | on-chip | flexio; MIPI-DBI. Tested with | +| | | :ref:`lcd_par_s035` | ++-----------+------------+-------------------------------------+ Targets available ================== diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi index 11bb253d66a98..68a1fa17301ff 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947-pinctrl.dtsi @@ -129,4 +129,93 @@ }; }; + pinmux_usdhc0: pinmux_usdhc0 { + group0 { + pinmux = , + , + , + , + ; + slew-rate = "fast"; + drive-strength = "low"; + bias-pull-up; + input-enable; + }; + group1 { + pinmux = ; + slew-rate = "fast"; + drive-strength = "low"; + input-enable; + }; + }; + + pinmux_lpadc0: pinmux_lpadc0 { + group0 { + pinmux = , + , + ; + slew-rate = "fast"; + drive-strength = "low"; + }; + }; + + pinmux_lpcmp0: pinmux_lpcmp0 { + group0 { + pinmux = ; + drive-strength = "low"; + slew-rate = "fast"; + bias-pull-up; + }; + }; + + pinmux_flexcan0: pinmux_flexcan0 { + group0 { + pinmux = , + ; + slew-rate = "fast"; + drive-strength = "low"; + input-enable; + }; + }; + + pinmux_flexio_lcd: pinmux_flexio_lcd { + group0 { + pinmux = , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + slew-rate = "fast"; + drive-strength = "low"; + input-enable; + }; + group1 { + pinmux = ; + slew-rate = "fast"; + drive-strength = "low"; + input-enable; + bias-pull-up; + }; + group2 { + pinmux = ; + slew-rate = "slow"; + drive-strength = "low"; + input-enable; + bias-pull-up; + }; + }; }; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi index e1543f19692a2..77708792e49d2 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947.dtsi @@ -6,6 +6,7 @@ #include "frdm_mcxn947-pinctrl.dtsi" #include +#include / { aliases{ @@ -14,6 +15,7 @@ led2 = &blue_led; sw0 = &user_button_2; sw1 = &user_button_3; + sdhc0 = &usdhc0; }; leds { @@ -40,11 +42,13 @@ user_button_2: button_0 { label = "User SW2"; gpios = <&gpio0 23 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; status = "disabled"; }; user_button_3: button_1 { label = "User SW3"; gpios = <&gpio0 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; status = "disabled"; }; }; @@ -79,6 +83,10 @@ * replace &os_timer with &systick */ &os_timer { + status = "disabled"; +}; + +&systick { status = "okay"; }; @@ -92,16 +100,16 @@ label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(64)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* For the MCUBoot "upgrade only" method, + * the slot sizes must be equal. */ slot0_partition: partition@10000 { label = "image-0"; reg = <0x00010000 DT_SIZE_K(992)>; }; - slot1_partition: partition@100000 { + slot1_partition: partition@108000 { label = "image-1"; - reg = <0x00108000 DT_SIZE_K(984)>; + reg = <0x00108000 DT_SIZE_K(992)>; }; /* storage_partition is placed in WINBOND flash memory*/ }; @@ -173,3 +181,43 @@ pinctrl-0 = <&pinmux_flexpwm1_pwm0>; pinctrl-names = "default"; }; + +&usdhc0 { + pinctrl-0 = <&pinmux_usdhc0>; + pinctrl-1 = <&pinmux_usdhc0>; + pinctrl-2 = <&pinmux_usdhc0>; + cd-gpios = <&gpio2 1 GPIO_ACTIVE_LOW>; + pinctrl-names = "default", "slow", "med"; + no-1-8-v; +}; + +&lpadc0 { + pinctrl-0 = <&pinmux_lpadc0>; + pinctrl-names = "default"; +}; + +nxp_flexio_lcd: &flexio0_lcd { + /* DMA channels 0, muxed to FlexIO TX */ + dmas = <&edma0 0 61>; + dma-names = "tx"; + shifters-count = <8>; + timers-count = <1>; + enwr-pin = <1>; + rd-pin = <0>; + data-pin-start = <16>; + reset-gpios = <&gpio4 7 GPIO_ACTIVE_HIGH>; + cs-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + rs-gpios = <&gpio0 7 GPIO_ACTIVE_HIGH>; + pinctrl-0 = <&pinmux_flexio_lcd>; + pinctrl-names = "default"; +}; + +&lpcmp0 { + pinctrl-0 = <&pinmux_lpcmp0>; + pinctrl-names = "default"; +}; + +&flexcan0 { + pinctrl-0 = <&pinmux_flexcan0>; + pinctrl-names = "default"; +}; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts index 4865e16784ea8..0651a532a1832 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.dts @@ -24,6 +24,7 @@ zephyr,code-partition = &slot0_partition; zephyr,console = &flexcomm4_lpuart4; zephyr,shell-uart = &flexcomm4_lpuart4; + zephyr,canbus = &flexcan0; }; aliases{ @@ -58,6 +59,10 @@ status = "okay"; }; +&gpio2 { + status = "okay"; +}; + &green_led { status = "okay"; }; @@ -138,6 +143,42 @@ status = "okay"; }; +&flexcan0 { + status = "okay"; +}; + &ctimer0 { status = "okay"; }; + +&usdhc0 { + status = "okay"; + sdmmc { + compatible = "zephyr,sdmmc-disk"; + status = "okay"; + }; +}; + +&vref { + status = "okay"; +}; + +&lpadc0 { + status = "okay"; +}; + +zephyr_udc0: &usb1 { + status = "okay"; +}; + +&lpcmp0 { + status = "okay"; +}; + +&lptmr0 { + status = "okay"; +}; + +&flexio0 { + status = "okay"; +}; diff --git a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml index 2e9c4f6c2830d..76f937fb1e562 100644 --- a/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml +++ b/boards/nxp/frdm_mcxn947/frdm_mcxn947_mcxn947_cpu0.yaml @@ -15,6 +15,7 @@ toolchain: - gnuarmemb - xtools supported: + - can - dma - gpio - spi @@ -23,4 +24,8 @@ supported: - watchdog - pwm - counter + - sdhc + - regulator + - adc + - usb_device vendor: nxp diff --git a/boards/nxp/frdm_rw612/CMakeLists.txt b/boards/nxp/frdm_rw612/CMakeLists.txt new file mode 100644 index 0000000000000..a2a0b1227353d --- /dev/null +++ b/boards/nxp/frdm_rw612/CMakeLists.txt @@ -0,0 +1,15 @@ +# +# Copyright 2022-2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +if(CONFIG_NXP_RW6XX_BOOT_HEADER) + zephyr_compile_definitions(BOARD_FLASH_SIZE=CONFIG_FLASH_SIZE*1024) + zephyr_library() + # This FCB is specific to the flash on this board, it won't work + # for boards with different flash chips. If you flash this FCB + # onto a board with a different flash chip you may break it. + # See MCUXpresso config tools for making a correct one. + zephyr_library_sources(W25Q512JVFIQ_FCB.c) +endif() diff --git a/boards/nxp/frdm_rw612/Kconfig.defconfig b/boards/nxp/frdm_rw612/Kconfig.defconfig new file mode 100644 index 0000000000000..84324bf402e20 --- /dev/null +++ b/boards/nxp/frdm_rw612/Kconfig.defconfig @@ -0,0 +1,14 @@ +# FRDM_RW612 board + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_FRDM_RW612 + +config FLASH_LOAD_SIZE + default 0x400000 if !BOOTLOADER_MCUBOOT && !NXP_MONOLITHIC_BT + +config NET_L2_ETHERNET + default y if DT_HAS_NXP_ENET_MAC_ENABLED && NETWORKING + +endif # BOARD_FRDM_RW612 diff --git a/boards/nxp/frdm_rw612/Kconfig.frdm_rw612 b/boards/nxp/frdm_rw612/Kconfig.frdm_rw612 new file mode 100644 index 0000000000000..53ccaf667f3a2 --- /dev/null +++ b/boards/nxp/frdm_rw612/Kconfig.frdm_rw612 @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_FRDM_RW612 + select SOC_PART_NUMBER_RW612ETA2I diff --git a/boards/nxp/frdm_rw612/W25Q512JVFIQ_FCB.c b/boards/nxp/frdm_rw612/W25Q512JVFIQ_FCB.c new file mode 100644 index 0000000000000..cecf36ad9a275 --- /dev/null +++ b/boards/nxp/frdm_rw612/W25Q512JVFIQ_FCB.c @@ -0,0 +1,106 @@ +/* + * Copyright 2021-2024 NXP + * All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +__attribute__((section(".flash_conf"), used)) const fc_flexspi_nor_config_t +flexspi_config = { + .memConfig = { + .tag = FC_BLOCK_TAG, + .version = FC_BLOCK_VERSION, + .readSampleClkSrc = 1, + .csHoldTime = 3, + .csSetupTime = 3, + .deviceModeCfgEnable = 1, + .deviceModeSeq = {.seqNum = 1, .seqId = 2}, + .deviceModeArg = 0x02, + .configCmdEnable = 0, + .deviceType = 0x1, + .sflashPadType = kSerialFlash_4Pads, + .serialClkFreq = 5, + .sflashA1Size = 0x4000000U, + .sflashA2Size = 0, + .sflashB1Size = 0, + .sflashB2Size = 0, + .lookupTable = { + + [0] = FC_FLEXSPI_LUT_SEQ( + FC_CMD_SDR, FC_FLEXSPI_1PAD, 0xEC, + FC_RADDR_SDR, FC_FLEXSPI_4PAD, + 0x20), + [1] = FC_FLEXSPI_LUT_SEQ( + FC_MODE8_SDR, FC_FLEXSPI_4PAD, 0xF0, + FC_DUMMY_SDR, FC_FLEXSPI_4PAD, + 0x04), + [2] = FC_FLEXSPI_LUT_SEQ( + FC_READ_SDR, FC_FLEXSPI_4PAD, 0x04, + FC_STOP_EXE, FC_FLEXSPI_1PAD, 0x00), + + + [4 * 1 + 0] = FC_FLEXSPI_LUT_SEQ( + FC_CMD_SDR, FC_FLEXSPI_1PAD, 0x05, + FC_READ_SDR, FC_FLEXSPI_1PAD, 0x04), + + + [4 * 2 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0x31, FC_WRITE_SDR, + FC_FLEXSPI_1PAD, + 0x01), + + + [4 * 3 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0x06, FC_STOP_EXE, FC_FLEXSPI_1PAD, + 0x00), + + + [4 * 5 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0x21, FC_RADDR_SDR, + FC_FLEXSPI_1PAD, + 0x20), + + + [4 * 8 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0xDC, FC_RADDR_SDR, + FC_FLEXSPI_1PAD, + 0x20), + + + [4 * 9 + 0] = + FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0x34, FC_RADDR_SDR, + FC_FLEXSPI_1PAD, + 0x20), + [4 * 9 + 1] = + FC_FLEXSPI_LUT_SEQ(FC_WRITE_SDR, + FC_FLEXSPI_4PAD, + 0x00, + FC_STOP_EXE, FC_FLEXSPI_1PAD, + 0x00), + + + [4 * 11 + 0] = FC_FLEXSPI_LUT_SEQ(FC_CMD_SDR, + FC_FLEXSPI_1PAD, + 0xC7, FC_STOP_EXE, + FC_FLEXSPI_1PAD, + 0x00), + }, + }, + .pageSize = 0x100, + .sectorSize = 0x1000, + .ipcmdSerialClkFreq = 0, + .blockSize = 0x10000, + .fcb_fill[0] = 0xFFFFFFFF, +}; diff --git a/boards/nxp/frdm_rw612/board.cmake b/boards/nxp/frdm_rw612/board.cmake new file mode 100644 index 0000000000000..c7b1d7d51d4a3 --- /dev/null +++ b/boards/nxp/frdm_rw612/board.cmake @@ -0,0 +1,9 @@ +# Copyright 2022-2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=RW612" "--reset-after-load") + +board_runner_args(linkserver "--device=RW612:RDRW612") + +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) diff --git a/boards/nxp/frdm_rw612/board.yml b/boards/nxp/frdm_rw612/board.yml new file mode 100644 index 0000000000000..e52333358c468 --- /dev/null +++ b/boards/nxp/frdm_rw612/board.yml @@ -0,0 +1,5 @@ +board: + name: frdm_rw612 + vendor: nxp + socs: + - name: rw612 diff --git a/boards/nxp/frdm_rw612/doc/index.rst b/boards/nxp/frdm_rw612/doc/index.rst new file mode 100644 index 0000000000000..f6aec20817682 --- /dev/null +++ b/boards/nxp/frdm_rw612/doc/index.rst @@ -0,0 +1,165 @@ +.. _frdm_rw612: + +NXP FRDM_RW612 +############## + +Overview +******** + +The RW612 is a highly integrated, low-power tri-radio wireless MCU with an +integrated 260 MHz ARM Cortex-M33 MCU and Wi-Fi 6 + Bluetooth Low Energy (LE) 5.3 / 802.15.4 +radios designed for a broad array of applications, including connected smart home devices, +gaming controllers, enterprise and industrial automation, smart accessories and smart energy. + +The RW612 MCU subsystem includes 1.2 MB of on-chip SRAM and a high-bandwidth Quad SPI interface +with an on-the-fly decryption engine for securely accessing off-chip XIP flash. + +The advanced design of the RW612 delivers tight integration, low power and highly secure +operation in a space- and cost-efficient wireless MCU requiring only a single 3.3 V power supply. + +Hardware +******** + +- 260 MHz ARM Cortex-M33, tri-radio cores for Wifi 6 + BLE 5.3 + 802.15.4 +- 1.2 MB on-chip SRAM + +Supported Features +================== + ++-----------+------------+-----------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+===================================+ +| NVIC | on-chip | nested vector interrupt controller| ++-----------+------------+-----------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-----------------------------------+ +| MCI_IOMUX | on-chip | pinmux | ++-----------+------------+-----------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-----------------------------------+ +| USART | on-chip | serial | ++-----------+------------+-----------------------------------+ +| BLE | on-chip | Bluetooth | ++-----------+------------+-----------------------------------+ +| DMA | on-chip | dma | ++-----------+------------+-----------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-----------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-----------------------------------+ +| TRNG | on-chip | entropy | ++-----------+------------+-----------------------------------+ +| WWDT | on-chip | watchdog | ++-----------+------------+-----------------------------------+ +| USBOTG | on-chip | usb | ++-----------+------------+-----------------------------------+ +| CTIMER | on-chip | counter | ++-----------+------------+-----------------------------------+ +| MRT | on-chip | counter | ++-----------+------------+-----------------------------------+ +| OS_TIMER | on-chip | os timer | ++-----------+------------+-----------------------------------+ + +The default configuration can be found in the defconfig file: + + :zephyr_file:`boards/nxp/frdm_rw612/frdm_rw612_defconfig` + +Other hardware features are not currently supported + +Fetch Binary Blobs +****************** + +To support Bluetooth, frdm_rw612 requires fetching binary blobs, which can be +achieved by running the following command: + +.. code-block:: console + + west blobs fetch hal_nxp + +Programming and Debugging +************************* + +Build and flash applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Configuring a Debug Probe +========================= + +A debug probe is used for both flashing and debugging the board. This board is +configured by default to use the JLink Firmware. + +Configuring a Console +===================== + +Connect a USB cable from your PC to J10, and use the serial terminal of your choice +(minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Flashing +======== + +Here is an example for the :ref:`hello_world` application. This example uses the +:ref:`jlink-debug-host-tools` as default. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_rw612 + :goals: flash + +Open a serial terminal, reset the board (press the RESET button), and you should +see the following message in the terminal: + +.. code-block:: console + + ***** Booting Zephyr OS v3.6.0 ***** + Hello World! frdm_rw612 + +Debugging +========= + +Here is an example for the :ref:`hello_world` application. This example uses the +:ref:`jlink-debug-host-tools` as default. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: frdm_rw612 + :goals: debug + +Open a serial terminal, step through the application in your debugger, and you +should see the following message in the terminal: + +.. code-block:: console + + ***** Booting Zephyr OS zephyr-v3.6.0 ***** + Hello World! frdm_rw612 + +Bluetooth +========= + +BLE functionality requires to fetch binary blobs, so make sure to follow +the ``Fetch Binary Blobs`` section first. + +Those binary blobs can be used in two different ways, depending if :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` +is enabled or not: + +- :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` is enabled (default): + +The required binary blob will be linked with the application image directly, forming +one single monolithic image. +The user has nothing else to do other than flashing the application to the board. + +- :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` is disabled: + +In this case, the BLE blob won't be linked with the application, so the user needs to manually +flash the BLE binary blob to the board at the address ``0x18540000``. +The binary blob will be located here: ``/modules/hal/nxp/zephyr/blobs/rw61x/rw61x_sb_ble_a2.bin`` + +Resources +========= + +.. _RW612 Website: + https://www.nxp.com/products/wireless-connectivity/wi-fi-plus-bluetooth-plus-802-15-4/wireless-mcu-with-integrated-tri-radiobr1x1-wi-fi-6-plus-bluetooth-low-energy-5-3-802-15-4:RW612 diff --git a/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi b/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi new file mode 100644 index 0000000000000..80a6caa12ed20 --- /dev/null +++ b/boards/nxp/frdm_rw612/frdm_rw612-pinctrl.dtsi @@ -0,0 +1,56 @@ +/* + * Copyright 2022-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + pinmux_flexcomm3_usart: pinmux_flexcomm3_usart { + group0 { + pinmux = ; + slew-rate = "normal"; + }; + }; + + pinmux_flexcomm0_usart: pinmux_flexcomm0_usart { + group0 { + pinmux = ; + slew-rate = "normal"; + }; + }; + + pinmux_enet: pinmux_enet { + group0 { + pinmux = ; + slew-rate = "fast"; + }; + }; + + pinmux_mdio: pinmux_mdio { + group0 { + pinmux = ; + slew-rate = "fast"; + }; + }; + + pinmux_flexcomm2_i2c: pinmux_flexcomm2_i2c { + group0 { + pinmux = ; + slew-rate = "normal"; + bias-pull-up; + }; + }; + + pinmux_flexcomm1_spi: pinmux_flexcomm1_spi { + group0 { + pinmux = ; + slew-rate = "ultra"; + }; + }; +}; diff --git a/boards/nxp/frdm_rw612/frdm_rw612.dts b/boards/nxp/frdm_rw612/frdm_rw612.dts new file mode 100644 index 0000000000000..083fd2edfe9fa --- /dev/null +++ b/boards/nxp/frdm_rw612/frdm_rw612.dts @@ -0,0 +1,166 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "frdm_rw612-pinctrl.dtsi" + +/ { + model = "nxp,frdm_rw612"; + + aliases { + led0 = &green_led; + watchdog0 = &wwdt; + usart-0 = &flexcomm3; + i2c-0 = &flexcomm2; + }; + + chosen { + zephyr,sram = &sram_data; + zephyr,flash = &w25q512jvfiq; + zephyr,console = &flexcomm3; + zephyr,shell-uart = &flexcomm3; + }; + + leds { + compatible = "gpio-leds"; + green_led: led_1 { + gpios = <&hsgpio0 12 0>; + }; + }; +}; + +&flexcomm3 { + compatible = "nxp,lpc-usart"; + status = "okay"; + current-speed = <115200>; + pinctrl-0 = <&pinmux_flexcomm3_usart>; + pinctrl-names = "default"; +}; + +&flexcomm0 { + compatible = "nxp,lpc-usart"; + status = "disabled"; + current-speed = <115200>; + pinctrl-0 = <&pinmux_flexcomm0_usart>; + pinctrl-names = "default"; +}; + +&hsgpio0 { + status = "okay"; +}; + +&flexspi { + status = "okay"; + /* Winbond external flash */ + w25q512jvfiq: w25q512jvfiq@0 { + compatible = "nxp,imx-flexspi-nor"; + reg = <0>; + size = <(DT_SIZE_M(512) / 8)>; + status = "okay"; + erase-block-size = <4096>; + write-block-size = <1>; + spi-max-frequency = <133000000>; + }; +}; + +&hci { + status = "okay"; + wakeup-source; +}; + +&enet_mac { + status = "okay"; + pinctrl-0 = <&pinmux_enet>; + pinctrl-names = "default"; + phy-handle = <&phy>; + zephyr,random-mac-address; + phy-connection-type = "rmii"; +}; + +&enet_mdio { + status = "okay"; + pinctrl-0 = <&pinmux_mdio>; + pinctrl-names = "default"; + phy: phy@2 { + compatible = "microchip,ksz8081"; + reg = <2>; + status = "okay"; + reset-gpios = <&hsgpio1 23 GPIO_ACTIVE_HIGH>; + int-gpios = <&hsgpio0 21 GPIO_ACTIVE_HIGH>; + microchip,interface-type = "rmii"; + }; +}; + +&wwdt { + status = "okay"; +}; + +&dma0 { + status = "okay"; +}; + +&mrt0_channel0 { + status = "okay"; +}; + +&ctimer0 { + status = "okay"; +}; + +&pmu { + reset-causes-en = , + , + ; +}; + +/* OS Timer is the wakeup source for PM mode 2 */ +&os_timer { + status = "okay"; + wakeup-source; +}; + +&systick { + status = "disabled"; +}; + +&adc0 { + status = "okay"; +}; + +&dac0 { + status = "okay"; +}; + +zephyr_udc0: &usb_otg { + status = "okay"; +}; + +/* + * the default resistors on the board breaks out the MOSI/MISO + * pins to the nets labelled "UART" which go to J1 2 and 4, + * but we are using it for spi mosi and miso here. + * SCK is on J2 6 as labelled. + */ +&flexcomm1 { + compatible = "nxp,lpc-spi"; + pinctrl-0 = <&pinmux_flexcomm1_spi>; + pinctrl-names = "default"; + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; +}; + +arduino_i2c: &flexcomm2 { + compatible = "nxp,lpc-i2c"; + status = "okay"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&pinmux_flexcomm2_i2c>; + pinctrl-names = "default"; +}; diff --git a/boards/nxp/frdm_rw612/frdm_rw612.yaml b/boards/nxp/frdm_rw612/frdm_rw612.yaml new file mode 100644 index 0000000000000..813330e2b5697 --- /dev/null +++ b/boards/nxp/frdm_rw612/frdm_rw612.yaml @@ -0,0 +1,28 @@ +# +# Copyright 2022-2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: frdm_rw612 +name: NXP FRDM_RW612 +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 960 +flash: 65536 +supported: + - gpio + - dma + - spi + - i2c + - entropy + - usb_device + - watchdog + - counter + - hwinfo + - adc + - dac diff --git a/boards/nxp/frdm_rw612/frdm_rw612_defconfig b/boards/nxp/frdm_rw612/frdm_rw612_defconfig new file mode 100644 index 0000000000000..b987fa24dc09b --- /dev/null +++ b/boards/nxp/frdm_rw612/frdm_rw612_defconfig @@ -0,0 +1,15 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_PINCTRL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_GPIO=y +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y +CONFIG_TRUSTED_EXECUTION_SECURE=y diff --git a/boards/nxp/frdm_rw612/pre_dt_board.cmake b/boards/nxp/frdm_rw612/pre_dt_board.cmake new file mode 100644 index 0000000000000..5da215a0a3bef --- /dev/null +++ b/boards/nxp/frdm_rw612/pre_dt_board.cmake @@ -0,0 +1,5 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +# Suppress "spi_bus_bridge" as flexcomm node can be used as a SPI device. +list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") diff --git a/boards/nxp/hexiwear/hexiwear_mk64f12.dts b/boards/nxp/hexiwear/hexiwear_mk64f12.dts index d530b6e9036a8..18cc0a3704526 100644 --- a/boards/nxp/hexiwear/hexiwear_mk64f12.dts +++ b/boards/nxp/hexiwear/hexiwear_mk64f12.dts @@ -28,7 +28,7 @@ zephyr,code-partition = &slot0_partition; zephyr,console = &uart0; zephyr,shell-uart = &uart0; - zephyr,bt-uart = &uart4; + zephyr,bt-hci = &bt_hci_uart; }; leds { @@ -153,6 +153,11 @@ current-speed = <115200>; pinctrl-0 = <&uart4_default>; pinctrl-names = "default"; + + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + }; }; &gpioa { @@ -181,26 +186,25 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x00010000>; + reg = <0x00000000 DT_SIZE_K(64)>; read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x00069000>; + reg = <0x00010000 (DT_SIZE_K(416) + DT_SIZE_K(8))>; }; - slot1_partition: partition@79000 { + slot1_partition: partition@7a000 { label = "image-1"; - reg = <0x00079000 0x00068000>; + reg = <0x0007a000 DT_SIZE_K(416)>; }; - storage_partition: partition@e1000 { + storage_partition: partition@e2000 { label = "storage"; - reg = <0x000e1000 0x0001f000>; + reg = <0x000e2000 DT_SIZE_K(120)>; }; }; }; diff --git a/boards/nxp/imx8mm_evk/Kconfig.defconfig b/boards/nxp/imx8mm_evk/Kconfig.defconfig deleted file mode 100644 index 5cc30c81ed197..0000000000000 --- a/boards/nxp/imx8mm_evk/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# MIMX8MM EVK board defconfig - -# Copyright (c) 2020, Manivannan Sadhasivam -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_IMX8MM_EVK_MIMX8MM6_M4 - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_IMX8MM_EVK_MIMX8MM6_M4 diff --git a/boards/nxp/imx8mp_evk/Kconfig.defconfig b/boards/nxp/imx8mp_evk/Kconfig.defconfig deleted file mode 100644 index 3fdc7b3cd9c18..0000000000000 --- a/boards/nxp/imx8mp_evk/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# MIMX8MP EVK board defconfig - -# Copyright (c) 2021, Laird Connectivity -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_IMX8MP_EVK_MIMX8ML8_M7 || BOARD_IMX8MP_EVK_MIMX8ML8_M7_DDR - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_IMX8MP_EVK_MIMX8ML8_M7 || BOARD_IMX8MP_EVK_MIMX8ML8_M7_DDR diff --git a/boards/nxp/imx8mp_evk/doc/index.rst b/boards/nxp/imx8mp_evk/doc/index.rst index 6d6e1b7b55664..684f03d5a5b04 100644 --- a/boards/nxp/imx8mp_evk/doc/index.rst +++ b/boards/nxp/imx8mp_evk/doc/index.rst @@ -55,8 +55,16 @@ features: +-----------+------------+-------------------------------------+ | ARM TIMER | on-chip | system clock | +-----------+------------+-------------------------------------+ +| CLOCK | on-chip | clock_control | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| RDC | on-chip | Resource Domain Controller | ++-----------+------------+-------------------------------------+ | UART | on-chip | serial port | +-----------+------------+-------------------------------------+ +| ENET | on-chip | ethernet port | ++-----------+------------+-------------------------------------+ The Zephyr mimx8mp_evk_m7 board configuration supports the following hardware features: @@ -226,4 +234,4 @@ References https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/evaluation-kit-for-the-i-mx-8m-plus-applications-processor:8MPLUSLPD4-EVK .. _i.MX 8M Applications Processor Reference Manual: - https://www.nxp.com/docs/en/reference-manual/IMX8MPRM.pdf + https://www.nxp.com/webapp/Download?colCode=IMX8MPRM diff --git a/boards/nxp/imx8mp_evk/imx8mp_evk-pinctrl.dtsi b/boards/nxp/imx8mp_evk/imx8mp_evk-pinctrl.dtsi index 949b622affb5d..f88555b13e276 100644 --- a/boards/nxp/imx8mp_evk/imx8mp_evk-pinctrl.dtsi +++ b/boards/nxp/imx8mp_evk/imx8mp_evk-pinctrl.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, NXP + * Copyright 2022-2024 NXP * SPDX-License-Identifier: Apache-2.0 * */ @@ -26,4 +26,44 @@ drive-strength = "x1"; }; }; + + pinmux_mdio: pinmux_mdio { + group0 { + pinmux = <&iomuxc_sai1_rxd2_enet_mdc_enet1_mdc>, + <&iomuxc_sai1_rxd3_enet_mdio_enet1_mdio>; + slew-rate = "slow"; + drive-strength = "x4"; + }; + }; + + pinmux_enet: pinmux_enet { + group0 { + pinmux = <&iomuxc_sai1_rxd4_enet_rgmii_rd_enet1_rgmii_rd0>, + <&iomuxc_sai1_rxd5_enet_rgmii_rd_enet1_rgmii_rd1>, + <&iomuxc_sai1_rxd6_enet_rgmii_rd_enet1_rgmii_rd2>, + <&iomuxc_sai1_rxd7_enet_rgmii_rd_enet1_rgmii_rd3>, + <&iomuxc_sai1_txc_enet_rgmii_rxc_enet1_rgmii_rxc>, + <&iomuxc_sai1_txfs_enet_rgmii_rx_ctl_enet1_rgmii_rx_ctl>; + input-schmitt-enable; + slew-rate = "fast"; + drive-strength = "x1"; + }; + + group1 { + pinmux = <&iomuxc_sai1_txd0_enet_rgmii_td_enet1_rgmii_td0>, + <&iomuxc_sai1_txd1_enet_rgmii_td_enet1_rgmii_td1>, + <&iomuxc_sai1_txd2_enet_rgmii_td_enet1_rgmii_td2>, + <&iomuxc_sai1_txd3_enet_rgmii_td_enet1_rgmii_td3>, + <&iomuxc_sai1_txd4_enet_rgmii_tx_ctl_enet1_rgmii_tx_ctl>, + <&iomuxc_sai1_txd5_enet_rgmii_txc_enet1_rgmii_txc>; + slew-rate = "fast"; + drive-strength = "x6"; + }; + + group2 { + pinmux = <&iomuxc_sai1_rxd0_gpio_io_gpio4_io2>; + slew-rate = "fast"; + drive-strength = "x1"; + }; + }; }; diff --git a/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53.dts b/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53.dts index 18cff6569d493..634092adbd4e5 100644 --- a/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53.dts +++ b/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53.dts @@ -1,5 +1,5 @@ /* - * Copyright 2021-2022 NXP + * Copyright 2021-2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,6 +34,31 @@ sram0: memory@c0000000 { reg = <0xc0000000 DT_SIZE_M(1)>; }; + +}; + +&enet { + status = "okay"; +}; + +&enet_mac { + pinctrl-0 = <&pinmux_enet>; + pinctrl-names = "default"; + phy-handle = <&phy>; + zephyr,random-mac-address; + phy-connection-type = "rgmii"; + status = "okay"; +}; + +&enet_mdio { + pinctrl-0 = <&pinmux_mdio>; + pinctrl-names = "default"; + status = "okay"; + phy: phy@0 { + compatible = "realtek,rtl8211f"; + reg = <1>; + status = "okay"; + }; }; &uart4 { diff --git a/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53_defconfig b/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53_defconfig index 4e31bf4e94605..03f341149702d 100644 --- a/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53_defconfig +++ b/boards/nxp/imx8mp_evk/imx8mp_evk_mimx8ml8_a53_defconfig @@ -13,6 +13,7 @@ CONFIG_ICACHE_LINE_SIZE_DETECT=y # Zephyr Kernel Configuration CONFIG_XIP=n +CONFIG_KERNEL_DIRECT_MAP=y # Serial Drivers CONFIG_SERIAL=y diff --git a/boards/nxp/imx8mq_evk/Kconfig.defconfig b/boards/nxp/imx8mq_evk/Kconfig.defconfig deleted file mode 100644 index 054cfde7fb7fb..0000000000000 --- a/boards/nxp/imx8mq_evk/Kconfig.defconfig +++ /dev/null @@ -1,16 +0,0 @@ -# MIMX8MQ EVK board defconfig - -# Copyright (c) 2021, Kwon Tae-young -# Copyright 2024 NXP -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_IMX8MQ_EVK - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_IMX8MQ_EVK diff --git a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts index 6cd176d0ce358..cd025a547e717 100644 --- a/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts +++ b/boards/nxp/imx93_evk/imx93_evk_mimx9352_a55.dts @@ -83,18 +83,45 @@ }; -&lpi2c1{ +&lpi2c1 { status = "disabled"; clock-frequency = ; pinctrl-0 = <&i2c1_default>; pinctrl-names = "default"; }; -&lpi2c2{ +&lpi2c2 { status = "disabled"; clock-frequency = ; pinctrl-0 = <&i2c2_default>; pinctrl-names = "default"; + + mfd0:adp5585@34 { + compatible = "adi,adp5585"; + reg = <0x34>; + status = "disabled"; + + gpio_exp0: adp5585_gpio { + compatible = "adi,adp5585-gpio"; + gpio-controller; + #gpio-cells = <2>; + ngpios = <13>; + gpio-reserved-ranges = <5 3>; + /* + * This device has non-contiguous gpio range: + * GPIO Pin R0~R4 are gpio0~4 + * GPIO Pin C0~C4 are gpio8~12 + */ + + gpiohog_exp_sel: exp-sel-hog { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + line-name = "exp_sel"; + output-low; + }; + status = "disabled"; + }; + }; }; &lpspi3 { diff --git a/boards/nxp/lpcxpresso11u68/pre_dt_board.cmake b/boards/nxp/lpcxpresso11u68/pre_dt_board.cmake deleted file mode 100644 index 2e3b3ff69ec50..0000000000000 --- a/boards/nxp/lpcxpresso11u68/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2019, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress DTC warnings due to all GPIO nodes sharing the same register address. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/flash@0 & /soc/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso11u68/support/openocd.cfg b/boards/nxp/lpcxpresso11u68/support/openocd.cfg index 3a59e2b51a500..9d3282f59abf6 100644 --- a/boards/nxp/lpcxpresso11u68/support/openocd.cfg +++ b/boards/nxp/lpcxpresso11u68/support/openocd.cfg @@ -39,4 +39,4 @@ $_TARGETNAME configure -event reset-end { # Enable Zephyr thread awareness. $_TARGETNAME configure -rtos Zephyr -adapter_khz 100 +adapter speed 100 diff --git a/boards/nxp/lpcxpresso51u68/pre_dt_board.cmake b/boards/nxp/lpcxpresso51u68/pre_dt_board.cmake deleted file mode 100644 index 665c78c7838fd..0000000000000 --- a/boards/nxp/lpcxpresso51u68/pre_dt_board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2021 metraTec GmbH -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") diff --git a/boards/nxp/lpcxpresso54114/pre_dt_board.cmake b/boards/nxp/lpcxpresso54114/pre_dt_board.cmake deleted file mode 100644 index 4918baef9a7f6..0000000000000 --- a/boards/nxp/lpcxpresso54114/pre_dt_board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2019, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") diff --git a/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi b/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi index aa2373b829ccf..42849ac568bf1 100644 --- a/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi +++ b/boards/nxp/lpcxpresso55s06/lpcxpresso55s06_common.dtsi @@ -151,8 +151,6 @@ &can0 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_can0>; pinctrl-names = "default"; diff --git a/boards/nxp/lpcxpresso55s06/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s06/pre_dt_board.cmake deleted file mode 100644 index 180748da25b36..0000000000000 --- a/boards/nxp/lpcxpresso55s06/pre_dt_board.cmake +++ /dev/null @@ -1,12 +0,0 @@ -# -# Copyright (c) 2022 metraTec -# -# SPDX-License-Identifier: Apache-2.0 -# - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso55s16/lpcxpresso55s16.dts b/boards/nxp/lpcxpresso55s16/lpcxpresso55s16.dts index f8646b24f59f2..ed219d1d8ea91 100644 --- a/boards/nxp/lpcxpresso55s16/lpcxpresso55s16.dts +++ b/boards/nxp/lpcxpresso55s16/lpcxpresso55s16.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2020 Henrik Brix Andersen + * Copyright 2024, NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,6 +15,15 @@ compatible = "nxp,lpc55xxx", "nxp,lpc"; }; +/* + * Default for this board is to allocate SRAM0-2 for data. But the + * application can have an application specific device tree to + * allocate the SRAMs differently. + */ +&sram0 { + reg = <0x20000000 DT_SIZE_K(64)>; +}; + zephyr_udc0: &usbhs { status = "okay"; }; diff --git a/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi b/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi index 1b68d976f3e8a..d081a79b96913 100644 --- a/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi +++ b/boards/nxp/lpcxpresso55s16/lpcxpresso55s16_common.dtsi @@ -147,8 +147,6 @@ &can0 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_can0>; pinctrl-names = "default"; diff --git a/boards/nxp/lpcxpresso55s16/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s16/pre_dt_board.cmake deleted file mode 100644 index dbc704b3f54ac..0000000000000 --- a/boards/nxp/lpcxpresso55s16/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2020 Henrik Brix Andersen -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso55s28/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s28/pre_dt_board.cmake deleted file mode 100644 index fcdd6b77a2bca..0000000000000 --- a/boards/nxp/lpcxpresso55s28/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2020 Lemonbeat GmbH -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts b/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts index be2b16c27f750..42b48e8c203f4 100644 --- a/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts +++ b/boards/nxp/lpcxpresso55s36/lpcxpresso55s36.dts @@ -126,8 +126,6 @@ }; &can0 { - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_mcan_can0>; pinctrl-names = "default"; status = "okay"; diff --git a/boards/nxp/lpcxpresso55s36/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s36/pre_dt_board.cmake deleted file mode 100644 index d97bfca8cf1f9..0000000000000 --- a/boards/nxp/lpcxpresso55s36/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright 2022 NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/lpcxpresso55s69/Kconfig.defconfig b/boards/nxp/lpcxpresso55s69/Kconfig.defconfig index 5a48b7afe2402..de1910595b4a3 100644 --- a/boards/nxp/lpcxpresso55s69/Kconfig.defconfig +++ b/boards/nxp/lpcxpresso55s69/Kconfig.defconfig @@ -42,6 +42,9 @@ config FLASH_LOAD_SIZE default 0x40000 if (!TFM_BL2 && BUILD_WITH_TFM) default $(dt_chosen_reg_size_hex,$(DT_CHOSEN_Z_CODE_PARTITION)) +config PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + default y if MBEDTLS_PSA_CRYPTO_CLIENT && MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + endif # TRUSTED_EXECUTION_NONSECURE || BOARD_LPCXPRESSO55S69_LPC55S69_CPU1 choice TFM_PROFILE_TYPE diff --git a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69.dtsi b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69.dtsi index e3d5b08fa19eb..af651dc9c90a0 100644 --- a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69.dtsi +++ b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, NXP + * Copyright 2019,2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -107,8 +107,6 @@ &flexcomm0 { compatible = "nxp,lpc-usart"; current-speed = <115200>; - dmas = <&dma0 4>, <&dma0 5>; - dma-names = "rx", "tx"; }; &flash0 { diff --git a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts index 14ba04fa448de..9c6f9b837cc3c 100644 --- a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts +++ b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, NXP + * Copyright 2019,2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -125,8 +125,6 @@ &hs_lspi { status = "okay"; - dmas = <&dma0 2>, <&dma0 3>; - dma-names = "rx", "tx"; cs-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; }; @@ -151,6 +149,14 @@ zephyr_udc0: &usbhs { status = "okay"; + phy_handle = <&usbphy1>; +}; + +&usbphy1 { + status = "okay"; + tx-d-cal = <5>; + tx-cal-45-dp-ohms = <10>; + tx-cal-45-dm-ohms = <10>; }; &ctimer0 { @@ -179,8 +185,6 @@ i2s0: &flexcomm6 { compatible = "nxp,lpc-i2s"; #address-cells = <1>; #size-cells = <0>; - dmas = <&dma0 16>; - dma-names = "rx"; }; /* I2S transmit channel */ @@ -189,8 +193,6 @@ i2s1: &flexcomm7 { compatible = "nxp,lpc-i2s"; #address-cells = <1>; #size-cells = <0>; - dmas = <&dma0 19>; - dma-names = "tx"; }; &sc_timer { diff --git a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0_ns.dts b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0_ns.dts index c68006a123fda..19d9ca8068ed8 100644 --- a/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0_ns.dts +++ b/boards/nxp/lpcxpresso55s69/lpcxpresso55s69_lpc55s69_cpu0_ns.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, NXP + * Copyright 2019,2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,8 +85,6 @@ &hs_lspi { status = "okay"; - dmas = <&dma0 2>, <&dma0 3>; - dma-names = "rx", "tx"; }; &wwdt0 { diff --git a/boards/nxp/lpcxpresso55s69/pre_dt_board.cmake b/boards/nxp/lpcxpresso55s69/pre_dt_board.cmake deleted file mode 100644 index a7c79990aa54f..0000000000000 --- a/boards/nxp/lpcxpresso55s69/pre_dt_board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2019, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on LPC boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") - -# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: -# - /soc/peripheral@40000000/syscon@0 & /soc/peripheral@40000000/gpio@0 -list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/nxp/mimxrt1010_evk/board.cmake b/boards/nxp/mimxrt1010_evk/board.cmake index d482b24e322a4..ec24e040231d3 100644 --- a/boards/nxp/mimxrt1010_evk/board.cmake +++ b/boards/nxp/mimxrt1010_evk/board.cmake @@ -6,5 +6,8 @@ board_runner_args(pyocd "--target=mimxrt1010") board_runner_args(jlink "--device=MIMXRT1011") +board_runner_args(linkserver "--device=MIMXRT1011xxxxx:EVK-MIMXRT1010") + +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/nxp/mimxrt1010_evk/doc/index.rst b/boards/nxp/mimxrt1010_evk/doc/index.rst index f830b49aab547..438b038baea32 100644 --- a/boards/nxp/mimxrt1010_evk/doc/index.rst +++ b/boards/nxp/mimxrt1010_evk/doc/index.rst @@ -181,6 +181,24 @@ Attach a J-Link 10-pin connector to J55. Check that jumpers J61 and J62 are **off** (they are on by default when boards ship from the factory) to ensure SWD signals are disconnected from the OpenSDA microcontroller. +Using LinkServer +---------------- + +Install the :ref:`linkserver-debug-host-tools` and make sure they are in your +search path. To use LinkServer the on board CMSIS-DAP firmware need updated with +LPCScrypt installed with LinkServer. + +To enter board debuger FW update mode, connect J22 first, and power cycle board. +For more details please refer to `Debug_Probe_Firmware_Programming.pdf`, which is +installed with LinkServer. + +.. code-block:: console + + :Ubuntu/Mac: scripts/program_CMSIS + :Windows: scripts/program_CMSIS.cmd + +You may also se the ``-r linkserver`` option with West to use the LinkServer. + Configuring a Console ===================== diff --git a/boards/nxp/mimxrt1010_evk/init.c b/boards/nxp/mimxrt1010_evk/init.c index 1fd4b67e457e8..3e2b49b112e8b 100644 --- a/boards/nxp/mimxrt1010_evk/init.c +++ b/boards/nxp/mimxrt1010_evk/init.c @@ -7,7 +7,7 @@ void SystemInitHook(void) { -#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(flash))) +#if DT_SAME_NODE(DT_NODELABEL(flexspi), DT_PARENT(DT_CHOSEN(zephyr_flash))) /* AT25SF128A SPI Flash on the RT1010-EVK requires special alignment * considerations, so set the READADDROPT bit in the FlexSPI so it * will fetch more data than each AHB burst requires to meet alignment diff --git a/boards/nxp/mimxrt1010_evk/mimxrt1010_evk.dts b/boards/nxp/mimxrt1010_evk/mimxrt1010_evk.dts index 39b65271fd4c9..de7a4d07a038c 100644 --- a/boards/nxp/mimxrt1010_evk/mimxrt1010_evk.dts +++ b/boards/nxp/mimxrt1010_evk/mimxrt1010_evk.dts @@ -105,19 +105,22 @@ arduino_serial: &lpuart1 {}; #size-cells = <1>; boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(64)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - slot0_partition: partition@10000 { + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. + */ + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00010000 DT_SIZE_M(7)>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@710000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00710000 DT_SIZE_M(7)>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@E10000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00E10000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(2) - DT_SIZE_K(140))>; }; }; }; diff --git a/boards/nxp/mimxrt1015_evk/mimxrt1015_evk.dts b/boards/nxp/mimxrt1015_evk/mimxrt1015_evk.dts index 0a28acc04ca40..1ed9a32421f58 100644 --- a/boards/nxp/mimxrt1015_evk/mimxrt1015_evk.dts +++ b/boards/nxp/mimxrt1015_evk/mimxrt1015_evk.dts @@ -102,19 +102,22 @@ arduino_serial: &lpuart4 { #size-cells = <1>; boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(64)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - slot0_partition: partition@10000 { + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. + */ + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00010000 DT_SIZE_M(7)>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@710000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00710000 DT_SIZE_M(7)>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@E10000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00E10000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(2) - DT_SIZE_K(140))>; }; }; }; diff --git a/boards/nxp/mimxrt1020_evk/doc/index.rst b/boards/nxp/mimxrt1020_evk/doc/index.rst index 4b409031729a6..0043cf5a8a309 100644 --- a/boards/nxp/mimxrt1020_evk/doc/index.rst +++ b/boards/nxp/mimxrt1020_evk/doc/index.rst @@ -106,6 +106,8 @@ already supported, which can also be re-used on this mimxrt1020_evk board: | UART | on-chip | serial port-polling; | | | | serial port-interrupt | +-----------+------------+-------------------------------------+ +| ENET | on-chip | ethernet | ++-----------+------------+-------------------------------------+ | USB | on-chip | USB device | +-----------+------------+-------------------------------------+ | ADC | on-chip | adc | diff --git a/boards/nxp/mimxrt1020_evk/mimxrt1020_evk-pinctrl.dtsi b/boards/nxp/mimxrt1020_evk/mimxrt1020_evk-pinctrl.dtsi index 9fe3a42bf9f38..8fdf5ebbc38d1 100644 --- a/boards/nxp/mimxrt1020_evk/mimxrt1020_evk-pinctrl.dtsi +++ b/boards/nxp/mimxrt1020_evk/mimxrt1020_evk-pinctrl.dtsi @@ -31,21 +31,29 @@ input-enable; }; group1 { - pinmux = <&iomuxc_gpio_ad_b0_04_gpio1_io04>; + pinmux = <&iomuxc_gpio_ad_b0_09_enet_rx_data1>, + <&iomuxc_gpio_ad_b0_11_enet_rx_en>, + <&iomuxc_gpio_ad_b0_14_enet_tx_data0>, + <&iomuxc_gpio_ad_b0_15_enet_tx_data1>, + <&iomuxc_gpio_ad_b0_13_enet_tx_en>, + <&iomuxc_gpio_ad_b0_12_enet_rx_er>; drive-strength = "r0-5"; bias-pull-up; bias-pull-up-value = "100k"; slew-rate = "fast"; - nxp,speed = "100-mhz"; + nxp,speed = "200-mhz"; }; group2 { - pinmux = <&iomuxc_gpio_ad_b0_09_enet_rx_data1>, - <&iomuxc_gpio_ad_b0_11_enet_rx_en>, - <&iomuxc_gpio_ad_b0_14_enet_tx_data0>, - <&iomuxc_gpio_ad_b0_15_enet_tx_data1>, - <&iomuxc_gpio_ad_b0_13_enet_tx_en>, - <&iomuxc_gpio_ad_b0_12_enet_rx_er>, - <&iomuxc_gpio_emc_40_enet_mdio>, + pinmux = <&iomuxc_gpio_ad_b0_10_enet_rx_data0>; + drive-strength = "r0-6"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + }; + + pinmux_enet_mdio: pinmux_enet_mdio { + group0 { + pinmux = <&iomuxc_gpio_emc_40_enet_mdio>, <&iomuxc_gpio_emc_41_enet_mdc>; drive-strength = "r0-5"; bias-pull-up; @@ -53,7 +61,7 @@ slew-rate = "fast"; nxp,speed = "200-mhz"; }; - group3 { + group1 { pinmux = <&iomuxc_gpio_ad_b1_06_gpio1_io22>; drive-strength = "r0-5"; bias-pull-up; @@ -61,14 +69,20 @@ slew-rate = "slow"; nxp,speed = "100-mhz"; }; - group4 { - pinmux = <&iomuxc_gpio_ad_b0_10_enet_rx_data0>; - drive-strength = "r0-6"; - slew-rate = "slow"; + group2 { + pinmux = <&iomuxc_gpio_ad_b0_04_gpio1_io04>; + drive-strength = "r0-5"; + bias-pull-up; + bias-pull-up-value = "100k"; + slew-rate = "fast"; nxp,speed = "100-mhz"; }; }; + pinmux_ptp: pinmux_ptp { + /* Intentionally empty */ + }; + pinmux_flexcan1: pinmux_flexcan1 { group0 { pinmux = <&iomuxc_gpio_sd_b1_00_flexcan1_tx>, @@ -173,9 +187,7 @@ }; }; - /* intentionally left empty */ - pinmux_ptp: pinmux_ptp { - }; + pinmux_sai3: pinmux_sai3 { group0 { diff --git a/boards/nxp/mimxrt1020_evk/mimxrt1020_evk.dts b/boards/nxp/mimxrt1020_evk/mimxrt1020_evk.dts index efa02f80add9a..54358e1588be9 100644 --- a/boards/nxp/mimxrt1020_evk/mimxrt1020_evk.dts +++ b/boards/nxp/mimxrt1020_evk/mimxrt1020_evk.dts @@ -107,30 +107,58 @@ arduino_serial: &lpuart2 { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(64)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@10000 { + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00010000 (DT_SIZE_M(3) + DT_SIZE_K(4))>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(8))>; }; - slot1_partition: partition@311000 { + slot1_partition: partition@322000 { label = "image-1"; - reg = <0x00311000 DT_SIZE_M(3)>; + reg = <0x00322000 DT_SIZE_M(3)>; }; - storage_partition: partition@611000 { + storage_partition: partition@622000 { label = "storage"; - reg = <0x00611000 DT_SIZE_K(1980)>; + reg = <0x00622000 (DT_SIZE_M(2) - DT_SIZE_K(136))>; }; }; }; }; +&enet_mac { + status = "okay"; + pinctrl-0 = <&pinmux_enet>; + pinctrl-names = "default"; + phy-handle = <&phy>; + zephyr,random-mac-address; + phy-connection-type = "rmii"; +}; + +&enet_mdio { + status = "okay"; + pinctrl-0 = <&pinmux_enet_mdio>; + pinctrl-names = "default"; + phy: phy@0 { + compatible = "microchip,ksz8081"; + reg = <0>; + status = "okay"; + reset-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + microchip,interface-type = "rmii"; + }; +}; + +&enet_ptp_clock { + status = "okay"; + pinctrl-0 = <&pinmux_ptp>; + pinctrl-names = "default"; +}; + &lpi2c1 { status = "okay"; pinctrl-0 = <&pinmux_lpi2c1>; diff --git a/boards/nxp/mimxrt1024_evk/mimxrt1024_evk.dts b/boards/nxp/mimxrt1024_evk/mimxrt1024_evk.dts index 472cd02630193..1dc4f3c6db711 100644 --- a/boards/nxp/mimxrt1024_evk/mimxrt1024_evk.dts +++ b/boards/nxp/mimxrt1024_evk/mimxrt1024_evk.dts @@ -100,25 +100,24 @@ arduino_serial: &lpuart2 { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(64)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@10000 { + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00010000 DT_SIZE_K(1924)>; + reg = <0x00020000 (DT_SIZE_K(1920) + DT_SIZE_K(8))>; }; - slot1_partition: partition@1f1000 { + slot1_partition: partition@202000 { label = "image-1"; - reg = <0x001F1000 DT_SIZE_K(1920)>; + reg = <0x00202000 DT_SIZE_K(1920)>; }; - storage_partition: partition@3d1000 { + storage_partition: partition@3E2000 { label = "storage"; - reg = <0x003D1000 DT_SIZE_K(188)>; + reg = <0x003E2000 DT_SIZE_K(120)>; }; }; }; @@ -140,9 +139,9 @@ arduino_serial: &lpuart2 { compatible = "microchip,ksz8081"; reg = <0>; status = "okay"; - mc,reset-gpio = <&gpio1 4 GPIO_ACTIVE_HIGH>; - mc,interrupt-gpio = <&gpio1 22 GPIO_ACTIVE_HIGH>; - mc,interface-type = "rmii"; + reset-gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; + microchip,interface-type = "rmii"; }; }; @@ -168,7 +167,6 @@ arduino_serial: &lpuart2 { &flexcan1 { status = "okay"; - bus-speed = <125000>; pinctrl-0 = <&pinmux_flexcan1>; pinctrl-names = "default"; diff --git a/boards/nxp/mimxrt1040_evk/CMakeLists.txt b/boards/nxp/mimxrt1040_evk/CMakeLists.txt index 9fc000a98ab3b..e5e2d4d414091 100644 --- a/boards/nxp/mimxrt1040_evk/CMakeLists.txt +++ b/boards/nxp/mimxrt1040_evk/CMakeLists.txt @@ -4,6 +4,11 @@ # SPDX-License-Identifier: Apache-2.0 # +if (CONFIG_DISPLAY) +message(WARNING " +CONFIG_DISPLAY: Running this firmware on a board without a display may damage the board +") +endif() if(CONFIG_NXP_IMXRT_BOOT_HEADER) zephyr_library() diff --git a/boards/nxp/mimxrt1040_evk/doc/index.rst b/boards/nxp/mimxrt1040_evk/doc/index.rst index a73b6a05b4d0e..67d3578189295 100644 --- a/boards/nxp/mimxrt1040_evk/doc/index.rst +++ b/boards/nxp/mimxrt1040_evk/doc/index.rst @@ -118,6 +118,10 @@ already supported, which can also be re-used on this mimxrt1040_evk board: +-----------+------------+-------------------------------------+ | I2C | on-chip | i2c | +-----------+------------+-------------------------------------+ +| DISPLAY | on-chip | eLCDIF. Tested with | +| | | :ref:`rk043fn02h_ct`, and | +| | | :ref:`rk043fn66hs_ctg` shields | ++-----------+------------+-------------------------------------+ The default configuration can be found in :zephyr_file:`boards/nxp/mimxrt1040_evk/mimxrt1040_evk_defconfig` diff --git a/boards/nxp/mimxrt1040_evk/mimxrt1040_evk-pinctrl.dtsi b/boards/nxp/mimxrt1040_evk/mimxrt1040_evk-pinctrl.dtsi index ad26eeecc3fdc..b9542c2362a56 100644 --- a/boards/nxp/mimxrt1040_evk/mimxrt1040_evk-pinctrl.dtsi +++ b/boards/nxp/mimxrt1040_evk/mimxrt1040_evk-pinctrl.dtsi @@ -94,5 +94,35 @@ }; }; + pinmux_lcdif: pinmux_lcdif { + group0 { + pinmux = <&iomuxc_gpio_b0_00_lcdif_clk>, + <&iomuxc_gpio_b0_01_lcdif_enable>, + <&iomuxc_gpio_b0_02_lcdif_hsync>, + <&iomuxc_gpio_b0_03_lcdif_vsync>, + <&iomuxc_gpio_b0_04_lcdif_data00>, + <&iomuxc_gpio_b0_05_lcdif_data01>, + <&iomuxc_gpio_b0_06_lcdif_data02>, + <&iomuxc_gpio_b0_07_lcdif_data03>, + <&iomuxc_gpio_b0_08_lcdif_data04>, + <&iomuxc_gpio_b0_09_lcdif_data05>, + <&iomuxc_gpio_b0_10_lcdif_data06>, + <&iomuxc_gpio_b0_11_lcdif_data07>, + <&iomuxc_gpio_b0_12_lcdif_data08>, + <&iomuxc_gpio_b0_13_lcdif_data09>, + <&iomuxc_gpio_b0_14_lcdif_data10>, + <&iomuxc_gpio_b0_15_lcdif_data11>, + <&iomuxc_gpio_b1_00_lcdif_data12>, + <&iomuxc_gpio_b1_01_lcdif_data13>, + <&iomuxc_gpio_b1_02_lcdif_data14>, + <&iomuxc_gpio_b1_03_lcdif_data15>; + drive-strength = "r0-6"; + input-schmitt-enable; + bias-pull-up; + bias-pull-up-value = "100k"; + slew-rate = "slow"; + nxp,speed = "100-mhz"; + }; + }; }; diff --git a/boards/nxp/mimxrt1040_evk/mimxrt1040_evk.dts b/boards/nxp/mimxrt1040_evk/mimxrt1040_evk.dts index 5beae5ffc40b8..a81167a17202b 100644 --- a/boards/nxp/mimxrt1040_evk/mimxrt1040_evk.dts +++ b/boards/nxp/mimxrt1040_evk/mimxrt1040_evk.dts @@ -37,6 +37,33 @@ reg = <0x80000000 DT_SIZE_M(32)>; }; + /* + * This node describes the GPIO pins of the parallel FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_parallel_lcd_connector: parallel-connector { + compatible = "nxp,parallel-lcd-connector"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio2 31 0>; /* Pin 1, BL+ */ + }; + + /* + * This node describes the GPIO pins of the I2C display FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_i2c_touch_fpc: i2c-touch-connector { + compatible = "nxp,i2c-tsc-fpc"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <1 0 &gpio1 19 0>, /* Pin 2, LCD touch RST */ + <2 0 &gpio1 11 0>; /* Pin 3, LCD touch INT */ + }; + leds { compatible = "gpio-leds"; green_led: led_0 { @@ -103,19 +130,22 @@ #size-cells = <1>; boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(64)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - slot0_partition: partition@10000 { + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. + */ + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00010000 DT_SIZE_M(3)>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(8))>; }; - slot1_partition: partition@310000 { + slot1_partition: partition@322000 { label = "image-1"; - reg = <0x00310000 DT_SIZE_M(3)>; + reg = <0x00322000 DT_SIZE_M(3)>; }; - storage_partition: partition@610000 { + storage_partition: partition@622000 { label = "storage"; - reg = <0x00610000 DT_SIZE_K(1984)>; + reg = <0x00622000 (DT_SIZE_M(2) - DT_SIZE_K(136))>; }; }; }; @@ -160,6 +190,13 @@ pinctrl-names = "default"; }; +nxp_touch_i2c: &lpi2c1 {}; + +zephyr_lcdif: &lcdif { + pinctrl-0 = <&pinmux_lcdif>; + pinctrl-names = "default"; +}; + /* Leave LPI2C3 disabled by default, since it conflicts with LPSPI1 pins */ &lpi2c3 { pinctrl-0 = <&pinmux_lpi2c3>; diff --git a/boards/nxp/mimxrt1050_evk/Kconfig.defconfig b/boards/nxp/mimxrt1050_evk/Kconfig.defconfig index bfb4a84e341b0..5660385019582 100644 --- a/boards/nxp/mimxrt1050_evk/Kconfig.defconfig +++ b/boards/nxp/mimxrt1050_evk/Kconfig.defconfig @@ -10,17 +10,6 @@ config DEVICE_CONFIGURATION_DATA config NXP_IMX_EXTERNAL_SDRAM default y - -config INPUT - default y if LVGL - -if INPUT - -config INPUT_FT5336_INTERRUPT - default y - -endif # INPUT - if NETWORKING config NET_L2_ETHERNET @@ -35,18 +24,4 @@ endif # ETH_MCUX endif # NETWORKING -if LVGL - -config LV_Z_VDB_SIZE - default 16 - -config LV_DPI_DEF - default 128 - -choice LV_COLOR_DEPTH - default LV_COLOR_DEPTH_16 -endchoice - -endif # LVGL - endif # BOARD_MIMXRT1050_EVK diff --git a/boards/nxp/mimxrt1050_evk/doc/index.rst b/boards/nxp/mimxrt1050_evk/doc/index.rst index c5351b9b63618..df2e4636c26a7 100644 --- a/boards/nxp/mimxrt1050_evk/doc/index.rst +++ b/boards/nxp/mimxrt1050_evk/doc/index.rst @@ -119,7 +119,9 @@ already supported, which can also be re-used on this mimxrt1050_evk board: +-----------+------------+-------------------------------------+ | SYSTICK | on-chip | systick | +-----------+------------+-------------------------------------+ -| DISPLAY | on-chip | display | +| DISPLAY | on-chip | eLCDIF. Tested with | +| | | :ref:`rk043fn02h_ct`, and | +| | | :ref:`rk043fn66hs_ctg` shields | +-----------+------------+-------------------------------------+ | GPIO | on-chip | gpio | +-----------+------------+-------------------------------------+ diff --git a/boards/nxp/mimxrt1050_evk/mimxrt1050_evk.dts b/boards/nxp/mimxrt1050_evk/mimxrt1050_evk.dts index 9c441f051d10d..bd439a372f980 100644 --- a/boards/nxp/mimxrt1050_evk/mimxrt1050_evk.dts +++ b/boards/nxp/mimxrt1050_evk/mimxrt1050_evk.dts @@ -8,7 +8,6 @@ #include #include "mimxrt1050_evk-pinctrl.dtsi" -#include #include / { @@ -30,7 +29,6 @@ zephyr,dtcm = &dtcm; zephyr,console = &lpuart1; zephyr,shell-uart = &lpuart1; - zephyr,display = &lcdif; }; sdram0: memory@80000000 { @@ -39,6 +37,33 @@ reg = <0x80000000 DT_SIZE_M(32)>; }; + /* + * This node describes the GPIO pins of the parallel FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_parallel_lcd_connector: parallel-connector { + compatible = "nxp,parallel-lcd-connector"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio2 31 0>; /* Pin 1, BL+ */ + }; + + /* + * This node describes the GPIO pins of the I2C display FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_i2c_touch_fpc: i2c-touch-connector { + compatible = "nxp,i2c-tsc-fpc"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <1 0 &gpio1 2 0>, /* Pin 2, LCD touch RST */ + <2 0 &gpio1 11 0>; /* Pin 3, LCD touch INT */ + }; + leds { compatible = "gpio-leds"; green_led: led_0 { @@ -56,11 +81,6 @@ }; }; - lvgl_pointer { - compatible = "zephyr,lvgl-pointer-input"; - input = <&ft5336>; - }; - arduino_header: connector { compatible = "arduino-header-r3"; #gpio-cells = <2>; @@ -89,15 +109,6 @@ <20 0 &gpio1 1 0>, /* D14 */ <21 0 &gpio1 0 0>; /* D15 */ }; - - panel { - compatible = "rocktech,rk043fn02h-ct"; - port { - lcd_panel_in: endpoint { - remote-endpoint = <&lcd_panel_out>; - }; - }; - }; }; arduino_serial: &lpuart3 { @@ -112,34 +123,11 @@ arduino_serial: &lpuart3 { pinctrl-names = "default"; }; -&lcdif { - status = "okay"; - width = <480>; - height = <272>; - display-timings { - compatible = "zephyr,panel-timing"; - hsync-len = <41>; - hfront-porch = <4>; - hback-porch = <8>; - vsync-len = <10>; - vfront-porch = <4>; - vback-porch = <2>; - de-active= <1>; - pixelclk-active = <1>; - hsync-active = <0>; - vsync-active = <0>; - clock-frequency = <9210240>; - }; - pixel-format = ; - data-bus-width = "16-bit"; +nxp_touch_i2c: &lpi2c1 {}; + +zephyr_lcdif: &lcdif { pinctrl-0 = <&pinmux_lcdif>; pinctrl-names = "default"; - backlight-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>; - port { - lcd_panel_out: endpoint { - remote-endpoint = <&lcd_panel_in>; - }; - }; }; &lpi2c1 { @@ -159,12 +147,6 @@ arduino_serial: &lpuart3 { int1-gpios = <&gpio1 10 GPIO_ACTIVE_LOW>; int2-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; }; - - ft5336: ft5336@38 { - compatible = "focaltech,ft5336"; - reg = <0x38>; - int-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; - }; }; &lpuart1 { @@ -210,9 +192,9 @@ arduino_serial: &lpuart3 { compatible = "microchip,ksz8081"; reg = <0>; status = "okay"; - mc,reset-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; - mc,interrupt-gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>; - mc,interface-type = "rmii"; + reset-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + microchip,interface-type = "rmii"; }; }; @@ -249,6 +231,10 @@ zephyr_udc0: &usb1 { status = "okay"; }; +&pxp { + status = "okay"; +}; + /* GPT and Systick are enabled. If power management is enabled, the GPT * timer will be used instead of systick, as allows the core clock to * be gated. diff --git a/boards/nxp/mimxrt1050_evk/mimxrt1050_evk_mimxrt1052_hyperflash.overlay b/boards/nxp/mimxrt1050_evk/mimxrt1050_evk_mimxrt1052_hyperflash.overlay index ccce00a56287b..4b3923c36d92b 100644 --- a/boards/nxp/mimxrt1050_evk/mimxrt1050_evk_mimxrt1052_hyperflash.overlay +++ b/boards/nxp/mimxrt1050_evk/mimxrt1050_evk_mimxrt1052_hyperflash.overlay @@ -46,25 +46,24 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(256)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 14 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@40000 { + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00040000 (DT_SIZE_M(3) + DT_SIZE_K(4))>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(56))>; }; - slot1_partition: partition@341000 { + slot1_partition: partition@32E000 { label = "image-1"; - reg = <0x00341000 DT_SIZE_M(3)>; + reg = <0x0032E000 DT_SIZE_M(3)>; }; - storage_partition: partition@641000 { + storage_partition: partition@62E000 { label = "storage"; - reg = <0x00641000 (DT_SIZE_M(57) + DT_SIZE_K(764))>; + reg = <0x0062E000 (DT_SIZE_M(58) - DT_SIZE_K(184))>; }; }; }; diff --git a/boards/nxp/mimxrt1050_evk/mimxrt1050_evk_mimxrt1052_qspi.overlay b/boards/nxp/mimxrt1050_evk/mimxrt1050_evk_mimxrt1052_qspi.overlay index 1fd770ec6558a..d18cda45c6025 100644 --- a/boards/nxp/mimxrt1050_evk/mimxrt1050_evk_mimxrt1052_qspi.overlay +++ b/boards/nxp/mimxrt1050_evk/mimxrt1050_evk_mimxrt1052_qspi.overlay @@ -27,30 +27,28 @@ jedec-id = [9d 70 17]; erase-block-size = <4096>; write-block-size = <1>; - partitions { compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(64)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@10000 { + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00010000 (DT_SIZE_M(3) + DT_SIZE_K(4))>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(8))>; }; - slot1_partition: partition@311000 { + slot1_partition: partition@322000 { label = "image-1"; - reg = <0x00311000 DT_SIZE_M(3)>; + reg = <0x00322000 DT_SIZE_M(3)>; }; - storage_partition: partition@611000 { + storage_partition: partition@622000 { label = "storage"; - reg = <0x00611000 DT_SIZE_K(1980)>; + reg = <0x00622000 (DT_SIZE_M(2) - DT_SIZE_K(136))>; }; }; }; diff --git a/boards/nxp/mimxrt1060_evk/Kconfig.defconfig b/boards/nxp/mimxrt1060_evk/Kconfig.defconfig index 37dc90279ddee..899e8b3ffe0f2 100644 --- a/boards/nxp/mimxrt1060_evk/Kconfig.defconfig +++ b/boards/nxp/mimxrt1060_evk/Kconfig.defconfig @@ -11,16 +11,6 @@ config DEVICE_CONFIGURATION_DATA config NXP_IMX_EXTERNAL_SDRAM default y -config INPUT - default y if LVGL - -if INPUT - -config INPUT_FT5336_INTERRUPT - default y - -endif # INPUT - if NETWORKING config NET_L2_ETHERNET @@ -35,39 +25,4 @@ endif # ETH_MCUX endif # NETWORKING -if LVGL - -# LVGL should allocate buffers equal to size of display -config LV_Z_VDB_SIZE - default 100 - -# Enable double buffering -config LV_Z_DOUBLE_VDB - default y - -# Force full refresh. This prevents memory copy associated with partial -# display refreshes, which is not necessary for the eLCDIF driver -config LV_Z_FULL_REFRESH - default y - -config LV_DPI_DEF - default 128 - -config LV_Z_BITS_PER_PIXEL - default 16 - -# Force display buffers to be aligned to cache line size (32 bytes) -config LV_Z_VDB_ALIGN - default 32 - -# Use offloaded render thread -config LV_Z_FLUSH_THREAD - default y - -choice LV_COLOR_DEPTH - default LV_COLOR_DEPTH_16 -endchoice - -endif # LVGL - endif # BOARD_MIMXRT1060_EVK || BOARD_MIMXRT1060_EVKB diff --git a/boards/nxp/mimxrt1060_evk/doc/index.rst b/boards/nxp/mimxrt1060_evk/doc/index.rst index e33336ea98648..0c9fdd6096eb9 100644 --- a/boards/nxp/mimxrt1060_evk/doc/index.rst +++ b/boards/nxp/mimxrt1060_evk/doc/index.rst @@ -115,7 +115,9 @@ already supported, which can also be re-used on this mimxrt1060_evk board: +-----------+------------+-------------------------------------+ | SYSTICK | on-chip | systick | +-----------+------------+-------------------------------------+ -| DISPLAY | on-chip | display | +| DISPLAY | on-chip | eLCDIF. Tested with | +| | | :ref:`rk043fn02h_ct`, and | +| | | :ref:`rk043fn66hs_ctg` shields | +-----------+------------+-------------------------------------+ | FLASH | on-chip | QSPI flash | +-----------+------------+-------------------------------------+ diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts index 43a440994307e..47f4901a22389 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk.dts @@ -8,7 +8,6 @@ #include #include "mimxrt1060_evk-pinctrl.dtsi" -#include #include / { @@ -30,7 +29,6 @@ zephyr,console = &lpuart1; zephyr,shell-uart = &lpuart1; zephyr,canbus = &flexcan3; - zephyr,display = &lcdif; }; sdram0: memory@80000000 { @@ -39,6 +37,33 @@ reg = <0x80000000 DT_SIZE_M(32)>; }; + /* + * This node describes the GPIO pins of the parallel FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_parallel_lcd_connector: parallel-connector { + compatible = "nxp,parallel-lcd-connector"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio2 31 0>; /* Pin 1, BL+ */ + }; + + /* + * This node describes the GPIO pins of the I2C display FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_i2c_touch_fpc: i2c-touch-connector { + compatible = "nxp,i2c-tsc-fpc"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <1 0 &gpio1 2 0>, /* Pin 2, LCD touch RST */ + <2 0 &gpio1 11 0>; /* Pin 3, LCD touch INT */ + }; + leds { compatible = "gpio-leds"; green_led: led-1 { @@ -63,11 +88,6 @@ }; }; - lvgl_pointer { - compatible = "zephyr,lvgl-pointer-input"; - input = <&ft5336>; - }; - arduino_header: connector { compatible = "arduino-header-r3"; #gpio-cells = <2>; @@ -96,15 +116,6 @@ <20 0 &gpio1 17 0>, /* D14 */ <21 0 &gpio1 16 0>; /* D15 */ }; - - panel { - compatible = "rocktech,rk043fn02h-ct"; - port { - lcd_panel_in: endpoint { - remote-endpoint = <&lcd_panel_out>; - }; - }; - }; }; arduino_serial: &lpuart3 { @@ -114,46 +125,17 @@ arduino_serial: &lpuart3 { pinctrl-names = "default", "flowcontrol", "sleep"; }; -&lcdif { - status = "okay"; - width = <480>; - height = <272>; - display-timings { - compatible = "zephyr,panel-timing"; - hsync-len = <41>; - hfront-porch = <4>; - hback-porch = <8>; - vsync-len = <10>; - vfront-porch = <4>; - vback-porch = <2>; - de-active= <1>; - pixelclk-active = <1>; - hsync-active = <0>; - vsync-active = <0>; - clock-frequency = <9210240>; - }; - pixel-format = ; - data-bus-width = "16-bit"; +zephyr_lcdif: &lcdif { pinctrl-0 = <&pinmux_lcdif>; pinctrl-names = "default"; - backlight-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>; - port { - lcd_panel_out: endpoint { - remote-endpoint = <&lcd_panel_in>; - }; - }; }; +nxp_touch_i2c: &lpi2c1 {}; + arduino_i2c: &lpi2c1 { status = "okay"; pinctrl-0 = <&pinmux_lpi2c1>; pinctrl-names = "default"; - - ft5336: ft5336@38 { - compatible = "focaltech,ft5336"; - reg = <0x38>; - int-gpios = <&gpio1 11 GPIO_ACTIVE_LOW>; - }; }; &lpuart1 { @@ -181,9 +163,9 @@ arduino_i2c: &lpi2c1 { compatible = "microchip,ksz8081"; reg = <0>; status = "okay"; - mc,reset-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; - mc,interrupt-gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>; - mc,interface-type = "rmii"; + reset-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + microchip,interface-type = "rmii"; }; }; @@ -201,6 +183,14 @@ arduino_i2c: &lpi2c1 { zephyr_udc0: &usb1 { status = "okay"; + phy_handle = <&usbphy1>; +}; + +&usbphy1 { + status = "okay"; + tx-d-cal = <12>; + tx-cal-45-dp-ohms = <6>; + tx-cal-45-dm-ohms = <6>; }; &flexpwm2_pwm3 { @@ -242,8 +232,6 @@ zephyr_udc0: &usb1 { &flexcan3 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.overlay b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.overlay index 4d94e82f6113f..25d33e462a058 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.overlay +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.overlay @@ -44,25 +44,24 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(256)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 14 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@40000 { + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00040000 (DT_SIZE_M(3) + DT_SIZE_K(4))>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(56))>; }; - slot1_partition: partition@341000 { + slot1_partition: partition@32E000 { label = "image-1"; - reg = <0x00341000 DT_SIZE_M(3)>; + reg = <0x0032E000 DT_SIZE_M(3)>; }; - storage_partition: partition@641000 { + storage_partition: partition@62E000 { label = "storage"; - reg = <0x00641000 (DT_SIZE_M(57) + DT_SIZE_K(764))>; + reg = <0x0062E000 (DT_SIZE_M(58) - DT_SIZE_K(184))>; }; }; }; diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.yaml b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.yaml index 93a7915e6fd9c..8dbd8533c1c26 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.yaml +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_hyperflash.yaml @@ -25,6 +25,7 @@ supported: - gpio - i2c - netif:eth + - pwm - sdhc - spi - usb_device diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.overlay b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.overlay index 9fddaea0c6293..8a0abae2fb3ba 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.overlay +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.overlay @@ -34,25 +34,24 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(64)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@10000 { + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00010000 (DT_SIZE_M(3) + DT_SIZE_K(4))>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(8))>; }; - slot1_partition: partition@311000 { + slot1_partition: partition@322000 { label = "image-1"; - reg = <0x00311000 DT_SIZE_M(3)>; + reg = <0x00322000 DT_SIZE_M(3)>; }; - storage_partition: partition@611000 { + storage_partition: partition@622000 { label = "storage"; - reg = <0x00611000 DT_SIZE_K(1980)>; + reg = <0x00622000 (DT_SIZE_M(2) - DT_SIZE_K(136))>; }; }; }; diff --git a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.yaml b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.yaml index 82e1548615918..1cd757e66d5be 100644 --- a/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.yaml +++ b/boards/nxp/mimxrt1060_evk/mimxrt1060_evk_mimxrt1062_qspi.yaml @@ -19,17 +19,17 @@ supported: - arduino_i2c - arduino_serial - arduino_spi + - adc + - can - counter - display - dma - gpio - i2c - netif:eth + - pwm - sdhc - spi - usb_device - - dma - - can - watchdog - - adc vendor: nxp diff --git a/boards/nxp/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts b/boards/nxp/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts index 73b9e9704050d..9e577f5debf29 100644 --- a/boards/nxp/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts +++ b/boards/nxp/mimxrt1062_fmurt6/mimxrt1062_fmurt6.dts @@ -109,7 +109,6 @@ status = "okay"; pinctrl-0 = <&pinmux_flexcan1>; pinctrl-names = "default"; - bus-speed = <125000>; can-transceiver { max-bitrate = <5000000>; }; @@ -119,7 +118,6 @@ status = "disabled"; pinctrl-0 = <&pinmux_flexcan2>; pinctrl-names = "default"; - bus-speed = <125000>; can-transceiver { max-bitrate = <5000000>; }; @@ -129,8 +127,6 @@ status = "disabled"; pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; @@ -210,22 +206,24 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(256)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - slot0_partition: partition@40000 { + /* The MCUBoot swap-move algorithm uses the last 14 sectors + * of the primary slot0 for swap status and move. + */ + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00040000 DT_SIZE_M(3)>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(56))>; }; - slot1_partition: partition@340000 { + slot1_partition: partition@32E000 { label = "image-1"; - reg = <0x00340000 DT_SIZE_M(3)>; + reg = <0x0032E000 DT_SIZE_M(3)>; }; - storage_partition: partition@640000 { + storage_partition: partition@62E000 { label = "storage"; - reg = <0x00640000 (DT_SIZE_M(557) + DT_SIZE_K(768))>; + reg = <0x0062E000 (DT_SIZE_M(58) - DT_SIZE_K(184))>; }; }; }; diff --git a/boards/nxp/mimxrt1064_evk/Kconfig.defconfig b/boards/nxp/mimxrt1064_evk/Kconfig.defconfig index 4ec3c9ebe2f90..6454f9b6329c2 100644 --- a/boards/nxp/mimxrt1064_evk/Kconfig.defconfig +++ b/boards/nxp/mimxrt1064_evk/Kconfig.defconfig @@ -11,16 +11,6 @@ config DEVICE_CONFIGURATION_DATA config NXP_IMX_EXTERNAL_SDRAM default y -config INPUT - default y if LVGL - -if INPUT - -config INPUT_FT5336_INTERRUPT - default y - -endif # INPUT - if NETWORKING config NET_L2_ETHERNET @@ -35,18 +25,4 @@ endif # ETH_MCUX endif # NETWORKING -if LVGL - -config LV_Z_VDB_SIZE - default 16 - -config LV_DPI_DEF - default 128 - -choice LV_COLOR_DEPTH - default LV_COLOR_DEPTH_16 -endchoice - -endif # LVGL - endif # BOARD_MIMXRT1064_EVK diff --git a/boards/nxp/mimxrt1064_evk/doc/index.rst b/boards/nxp/mimxrt1064_evk/doc/index.rst index fb9195693fd29..5974a47edf15b 100644 --- a/boards/nxp/mimxrt1064_evk/doc/index.rst +++ b/boards/nxp/mimxrt1064_evk/doc/index.rst @@ -111,7 +111,9 @@ configuration supports the following hardware features: +-----------+------------+-------------------------------------+ | SYSTICK | on-chip | systick | +-----------+------------+-------------------------------------+ -| DISPLAY | on-chip | display | +| DISPLAY | on-chip | eLCDIF. Tested with | +| | | :ref:`rk043fn02h_ct`, and | +| | | :ref:`rk043fn66hs_ctg` shields | +-----------+------------+-------------------------------------+ | VIDEO | on-chip | video, using CSI | +-----------+------------+-------------------------------------+ diff --git a/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts b/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts index c20be8ad6a892..7b1a0d0a7d41c 100644 --- a/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts +++ b/boards/nxp/mimxrt1064_evk/mimxrt1064_evk.dts @@ -8,7 +8,6 @@ #include #include "mimxrt1064_evk-pinctrl.dtsi" -#include #include / { @@ -33,7 +32,6 @@ zephyr,console = &lpuart1; zephyr,shell-uart = &lpuart1; zephyr,canbus = &flexcan2; - zephyr,display = &lcdif; }; sdram0: memory@80000000 { @@ -42,6 +40,33 @@ reg = <0x80000000 DT_SIZE_M(32)>; }; + /* + * This node describes the GPIO pins of the parallel FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_parallel_lcd_connector: parallel-connector { + compatible = "nxp,parallel-lcd-connector"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio2 31 0>; /* Pin 1, BL+ */ + }; + + /* + * This node describes the GPIO pins of the I2C display FPC interface, + * This interface is standard to several NXP EVKs, and is used with + * several parallel LCD displays (available as zephyr shields) + */ + nxp_i2c_touch_fpc: i2c-touch-connector { + compatible = "nxp,i2c-tsc-fpc"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <1 0 &gpio1 2 0>, /* Pin 2, LCD touch RST */ + <2 0 &gpio1 11 0>; /* Pin 3, LCD touch INT */ + }; + leds { compatible = "gpio-leds"; green_led: led-1 { @@ -100,67 +125,23 @@ <20 0 &gpio1 17 0>, /* D14 */ <21 0 &gpio1 16 0>; /* D15 */ }; - - panel { - compatible = "rocktech,rk043fn02h-ct"; - port { - lcd_panel_in: endpoint { - remote-endpoint = <&lcd_panel_out>; - }; - }; - }; }; -arduino_i2c: &lpi2c1 {}; +nxp_touch_i2c: &lpi2c1 {}; -&lcdif { - status = "okay"; - width = <480>; - height = <272>; - display-timings { - compatible = "zephyr,panel-timing"; - hsync-len = <41>; - hfront-porch = <4>; - hback-porch = <8>; - vsync-len = <10>; - vfront-porch = <4>; - vback-porch = <2>; - de-active= <1>; - pixelclk-active = <1>; - hsync-active = <0>; - vsync-active = <0>; - clock-frequency = <9210240>; - }; - pixel-format = ; - data-bus-width = "16-bit"; +zephyr_lcdif: &lcdif { pinctrl-0 = <&pinmux_lcdif>; pinctrl-names = "default"; - backlight-gpios = <&gpio2 31 GPIO_ACTIVE_HIGH>; - port { - lcd_panel_out: endpoint { - remote-endpoint = <&lcd_panel_in>; - }; - }; }; +nxp_parallel_i2c: &lpi2c1 {}; + &lpi2c1 { status = "okay"; pinctrl-0 = <&pinmux_lpi2c1>; pinctrl-names = "default"; - mt9m114: mt9m114@48 { - compatible = "aptina,mt9m114"; - reg = <0x48>; - status = "okay"; - - port { - mt9m114_ep_out: endpoint { - remote-endpoint = <&csi_ep_in>; - }; - }; - }; - ft5336: ft5336@38 { compatible = "focaltech,ft5336"; reg = <0x38>; @@ -202,22 +183,22 @@ arduino_i2c: &lpi2c1 {}; compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 DT_SIZE_K(64)>; + reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@10000 { + slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00010000 DT_SIZE_K(2016)>; + reg = <0x00020000 (DT_SIZE_K(1980) + DT_SIZE_K(8))>; }; - slot1_partition: partition@208000 { + slot1_partition: partition@211000 { label = "image-1"; - reg = <0x00208000 DT_SIZE_K(2012)>; + reg = <0x00211000 DT_SIZE_K(1980)>; }; + /* The storage partition is located in is25wp064 */ }; }; @@ -253,9 +234,9 @@ arduino_serial: &lpuart3 { compatible = "microchip,ksz8081"; reg = <0>; status = "okay"; - mc,reset-gpio = <&gpio1 9 GPIO_ACTIVE_HIGH>; - mc,interrupt-gpio = <&gpio1 10 GPIO_ACTIVE_HIGH>; - mc,interface-type = "rmii"; + reset-gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio1 10 GPIO_ACTIVE_HIGH>; + microchip,interface-type = "rmii"; }; }; @@ -271,16 +252,8 @@ zephyr_udc0: &usb1 { }; &csi { - status = "okay"; - sensor = <&mt9m114>; pinctrl-0 = <&pinmux_csi>; pinctrl-names = "default"; - - port { - csi_ep_in: endpoint { - remote-endpoint = <&mt9m114_ep_out>; - }; - }; }; &flexpwm2_pwm3 { @@ -310,7 +283,6 @@ zephyr_udc0: &usb1 { &flexcan2 { status = "okay"; - bus-speed = <125000>; pinctrl-0 = <&pinmux_flexcan2>; pinctrl-names = "default"; @@ -363,3 +335,7 @@ zephyr_udc0: &usb1 { pinctrl-0 = <&pinmux_swo>; pinctrl-names = "default"; }; + +dvp_fpc24_i2c: &lpi2c1 {}; + +dvp_fpc24_interface: &csi {}; diff --git a/boards/nxp/mimxrt1160_evk/board.cmake b/boards/nxp/mimxrt1160_evk/board.cmake index e9c7d7ea8c7e5..08c159f552a89 100644 --- a/boards/nxp/mimxrt1160_evk/board.cmake +++ b/boards/nxp/mimxrt1160_evk/board.cmake @@ -7,6 +7,7 @@ if(CONFIG_SOC_MIMXRT1166_CM7 OR CONFIG_SECOND_CORE_MCUX) board_runner_args(pyocd "--target=mimxrt1160_cm7") board_runner_args(jlink "--device=MIMXRT1166xxx6_M7" "--reset-after-load") +board_runner_args(linkserver "--device=MIMXRT1166xxxxx:MIMXRT1160-EVK") elseif(CONFIG_SOC_MIMXRT1166_CM4) board_runner_args(pyocd "--target=mimxrt1160_cm4") # Note: Please use JLINK above V7.50 (Only support run cm4 image when debugging due to default boot core on board is cm7 core) @@ -14,4 +15,5 @@ board_runner_args(jlink "--device=MIMXRT1166xxx6_M4") endif() include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/linkserver.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) diff --git a/boards/nxp/mimxrt1160_evk/doc/index.rst b/boards/nxp/mimxrt1160_evk/doc/index.rst index 861f0a3098a46..deaac1c22ece0 100644 --- a/boards/nxp/mimxrt1160_evk/doc/index.rst +++ b/boards/nxp/mimxrt1160_evk/doc/index.rst @@ -267,10 +267,8 @@ however the :ref:`pyocd-debug-host-tools` do not yet support programming the external flashes on this board so you must reconfigure the board for one of the following debug probes instead. -.. _Using J-Link RT1160: - Using J-Link ---------------------------------- +------------ Install the :ref:`jlink-debug-host-tools` and make sure they are in your search path. @@ -279,6 +277,17 @@ There are two options: the onboard debug circuit can be updated with Segger J-Link firmware, or :ref:`jlink-external-debug-probe` can be attached to the EVK. See `Using J-Link with MIMXRT1160-EVK or MIMXRT1170-EVK`_ for more details. +Using LinkServer +---------------- + +Install the :ref:`linkserver-debug-host-tools` and make sure they are in your +search path. LinkServer works with the CMSIS-DAP firmware include in LinkServer +install. Please follow the ``LPCScrypt\docs\Debug_Probe_Firmware_Programming.pdf`` +for more details. + +Linkserver is the default runner. You may also se the ``-r linkserver`` option +with West to use the LinkServer runner. + Configuring a Console ===================== diff --git a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi index 62d3bd59998e8..e3bb96e47f01c 100644 --- a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi +++ b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk.dtsi @@ -5,6 +5,7 @@ */ #include "mimxrt1160_evk-pinctrl.dtsi" +#include #include / { @@ -91,7 +92,7 @@ reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(16)>; is25wp128: is25wp128@0 { compatible = "nxp,imx-flexspi-nor"; - size = <134217728>; + size = ; reg = <0>; spi-max-frequency = <133000000>; status = "okay"; @@ -103,25 +104,24 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 0x301000>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00321000 0x300000>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@621000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00621000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(2) - DT_SIZE_K(140))>; }; }; }; @@ -150,9 +150,9 @@ compatible = "microchip,ksz8081"; reg = <0>; status = "okay"; - mc,reset-gpio = <&gpio12 12 GPIO_ACTIVE_HIGH>; - mc,interrupt-gpio = <&gpio9 11 GPIO_ACTIVE_HIGH>; - mc,interface-type = "rmii"; + reset-gpios = <&gpio12 12 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio9 11 GPIO_ACTIVE_HIGH>; + microchip,interface-type = "rmii"; }; }; diff --git a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk_mimxrt1166_cm7.dts b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk_mimxrt1166_cm7.dts index 9bdf8f088b1db..379db1b1da5cc 100644 --- a/boards/nxp/mimxrt1160_evk/mimxrt1160_evk_mimxrt1166_cm7.dts +++ b/boards/nxp/mimxrt1160_evk/mimxrt1160_evk_mimxrt1166_cm7.dts @@ -36,6 +36,21 @@ aliases { watchdog0 = &wdog1; }; + + /* + * This node describes the GPIO pins mapping of the 44-pin camera + * connector, J2 on the EVK. This camera interface is supported + * on several NXP RT11xx EVKs, such as RT1170 and RT1160 EVK and + * is used with an ov5640 camera module available as a Zephyr shield + */ + nxp_cam_connector: cam-connector { + compatible = "nxp,cam-44pins-connector"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <9 0 &gpio11 15 0>, /* Pin 9, RESETB */ + <17 0 &gpio9 25 0>; /* Pin 17, PWDN */ + }; }; &lpuart1 { @@ -45,8 +60,6 @@ &flexcan3 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; @@ -99,3 +112,9 @@ zephyr_udc0: &usb1 { &pit2 { status = "okay"; }; + +nxp_cam_i2c: &lpi2c6 {}; + +nxp_mipi_csi: &mipi_csi2rx {}; + +nxp_csi: &csi {}; diff --git a/boards/nxp/mimxrt1170_evk/CMakeLists.txt b/boards/nxp/mimxrt1170_evk/CMakeLists.txt index c564e77e49273..e87e07401d077 100644 --- a/boards/nxp/mimxrt1170_evk/CMakeLists.txt +++ b/boards/nxp/mimxrt1170_evk/CMakeLists.txt @@ -28,16 +28,16 @@ if(CONFIG_NXP_IMXRT_BOOT_HEADER) zephyr_library_sources(${RT1170_BOARD_DIR}/xip/${RT1170_BOARD_NAME}_flexspi_nor_config.c) zephyr_library_include_directories(${RT1170_BOARD_DIR}/xip) endif() - if(CONFIG_DEVICE_CONFIGURATION_DATA) - # Include device configuration data block for RT1170 EVK from NXP's HAL. + if(CONFIG_EXTERNAL_MEM_CONFIG_DATA) + # Include external memory configuration data block for RT1170 EVK from NXP's HAL. # This configuration block may need modification if another SDRAM chip # is used on your custom board. - zephyr_compile_definitions(XIP_BOOT_HEADER_DCD_ENABLE=1) - zephyr_library_sources(${RT1170_BOARD_DIR}/dcd.c) + zephyr_compile_definitions(XIP_BOOT_HEADER_XMCD_ENABLE=1) + zephyr_library_sources(${RT1170_BOARD_DIR}/xmcd/xmcd.c) else() if(CONFIG_SRAM_BASE_ADDRESS EQUAL 0x80000000) - message(WARNING "You are using SDRAM as RAM but no device " - "configuration data (DCD) is included. This configuration may not boot") + message(WARNING "You are using SDRAM as RAM but no external memory" + "configuration data (XMCD) is included. This configuration may not boot") endif() endif() endif() diff --git a/boards/nxp/mimxrt1170_evk/Kconfig.defconfig b/boards/nxp/mimxrt1170_evk/Kconfig.defconfig index 395d8351794c1..a54b1b8a145f8 100644 --- a/boards/nxp/mimxrt1170_evk/Kconfig.defconfig +++ b/boards/nxp/mimxrt1170_evk/Kconfig.defconfig @@ -5,8 +5,8 @@ if BOARD_MIMXRT1170_EVK -# Only use DCD when booting primary core (M7) -config DEVICE_CONFIGURATION_DATA +# Use External Memory Configuration Data (XMCD) by default when booting primary core (M7) +config EXTERNAL_MEM_CONFIG_DATA default y if CPU_CORTEX_M7 config NXP_IMX_EXTERNAL_SDRAM diff --git a/boards/nxp/mimxrt1170_evk/doc/index.rst b/boards/nxp/mimxrt1170_evk/doc/index.rst index d6a80009e7c79..40643137bdb82 100644 --- a/boards/nxp/mimxrt1170_evk/doc/index.rst +++ b/boards/nxp/mimxrt1170_evk/doc/index.rst @@ -69,6 +69,7 @@ Hardware - Expansion port - Arduino interface + - M.2 WIFI/BT interface - CAN bus connector @@ -144,8 +145,9 @@ RT1170 EVKB (`mimxrt1170_evk@B//cm7/cm4`) +-----------+------------+-------------------------------------+-----------------+-----------------+ | WATCHDOG | on-chip | watchdog | Supported (M7) | Supported (M7) | +-----------+------------+-------------------------------------+-----------------+-----------------+ -| ENET | on-chip | ethernet - 10/100M (ENET_QOS or | Supported (M7) | No support | -| ENET1G | | GigE not supported yet) | | | +| ENET | on-chip | ethernet - 10/100M | Supported (M7) | No support | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| ENET1G | on-chip | ethernet - 10/100/1000M | Supported (M7) | No support | +-----------+------------+-------------------------------------+-----------------+-----------------+ | SAI | on-chip | i2s | Supported | No support | +-----------+------------+-------------------------------------+-----------------+-----------------+ @@ -168,6 +170,11 @@ RT1170 EVKB (`mimxrt1170_evk@B//cm7/cm4`) +-----------+------------+-------------------------------------+-----------------+-----------------+ | PIT | on-chip | pit | Supported (M7) | Supported (M7) | +-----------+------------+-------------------------------------+-----------------+-----------------+ +| VIDEO | on-chip | CSI; MIPI CSI-2 Rx. Tested with | Supported (M7) | Supported (M7) | +| | | :ref:`nxp_btb44_ov5640` shield | | | ++-----------+------------+-------------------------------------+-----------------+-----------------+ +| UART | NXP NW61x | M.2 WIFI/BT module | Unsupported | Supported (M7) | ++-----------+------------+-------------------------------------+-----------------+-----------------+ The default configuration can be found in the defconfig files: :zephyr_file:`boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_defconfig` @@ -243,6 +250,14 @@ The MIMXRT1170 SoC has six pairs of pinmux/gpio controllers. +---------------------------+----------------+------------------+ | GPIO_AD_20_SAI1_RX_DATA00 | SAI1_RX_DATA00 | SAI | +---------------------------+----------------+------------------+ +| GPIO_DISP_B2_10 | LPUART2_TX | M.2 BT HCI | ++---------------------------+----------------+------------------+ +| GPIO_DISP_B2_11 | LPUART2_RX | M.2 BT HCI | ++---------------------------+----------------+------------------+ +| GPIO_DISP_B2_12 | LPUART2_CTS_B | M.2 BT HCI | ++---------------------------+----------------+------------------+ +| GPIO_DISP_B2_13 | LPUART1_RTS_B | M.2 BT HCI | ++---------------------------+----------------+------------------+ Dual Core samples ***************** @@ -287,9 +302,22 @@ cost of reduced resolution Serial Port =========== -The MIMXRT1170 SoC has 12 UARTs. One is configured for the console and the +The MIMXRT1170 SoC has 12 UARTs. ``LPUART1`` is configured for the console, +``LPUART2`` for the Bluetooth Host Controller Interface (BT HCI), and the remaining are not used. +Fetch Binary Blobs +================== + +The board Bluetooth/WiFi module requires fetching some binary blob files, to do +that run the command: + +.. code-block:: console + + west blobs fetch hal_nxp + +.. note:: Only Bluetooth functionality is currently supported. + Programming and Debugging ************************* @@ -444,3 +472,10 @@ should see the following message in the terminal: .. _NXP MCUXpresso for Visual Studio Code: https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-for-visual-studio-code:MCUXPRESSO-VSC + +ENET1G Driver +============= + +Current default of ethernet driver is to use 100M Ethernet instance ENET. +To use the 1G Ethernet instance ENET1G, include the overlay to west build with +the option `-DEXTRA_DTC_OVERLAY_FILE=nxp,enet1g.overlay` instead. diff --git a/boards/nxp/mimxrt1170_evk/dts/nxp,enet1g.overlay b/boards/nxp/mimxrt1170_evk/dts/nxp,enet1g.overlay new file mode 100644 index 0000000000000..cff3f6bad7c80 --- /dev/null +++ b/boards/nxp/mimxrt1170_evk/dts/nxp,enet1g.overlay @@ -0,0 +1,36 @@ +/* + * Copyright 2023-2024 NXP + * + * ENET_1G binding overlay + */ + +/ { + soc { + /delete-node/ ethernet@40424000; + }; +}; + +&enet1g { + status = "okay"; +}; + +&enet1g_mac { + status = "okay"; +}; + +&enet1g_mdio { + status = "okay"; + enet1g_phy: phy@1 { + status = "okay"; + }; +}; + +&enet1g_ptp_clock { + status = "okay"; +}; + +&pinctrl { + /delete-node/ pinmux_enet; + /delete-node/ pinmux_enet_mdio; + /delete-node/ pinmux_ptp; +}; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi index 26c910b55c52b..d33ed7cfb331f 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk-pinctrl.dtsi @@ -23,7 +23,10 @@ bias-pull-up; slew-rate = "fast"; }; - group2 { + }; + + pinmux_lpi2c6: pinmux_lpi2c6 { + group0 { pinmux = <&iomuxc_lpsr_gpio_lpsr_07_lpi2c6_scl>, <&iomuxc_lpsr_gpio_lpsr_06_lpi2c6_sda>; drive-strength = "high"; @@ -82,6 +85,64 @@ pinmux_ptp: pinmux_ptp { }; + pinmux_enet1g: pinmux_enet1g { + group0 { + pinmux = <&iomuxc_gpio_disp_b1_11_enet_1g_tx_clk_io>, // ENET_RGMII_TXC + <&iomuxc_gpio_disp_b1_01_enet_1g_rx_clk>; // ENET_RGMII_RXC + bias-disable; + drive-strength = "high"; + slew-rate = "fast"; + input-enable; + }; + group1 { + pinmux = <&iomuxc_gpio_disp_b1_09_enet_1g_tdata00>, // ENET_RGMII_TXD0 + <&iomuxc_gpio_disp_b1_08_enet_1g_tdata01>, // ENET_RGMII_TXD1 + <&iomuxc_gpio_disp_b1_07_enet_1g_tdata02>, // ENET_RGMII_TXD2 + <&iomuxc_gpio_disp_b1_06_enet_1g_tdata03>, // ENET_RGMII_TXD3 + <&iomuxc_gpio_disp_b1_10_enet_1g_tx_en>; // ENET_RGMII_TX_EN + drive-strength = "high"; + bias-pull-up; + slew-rate = "fast"; + }; + group2 { + pinmux = <&iomuxc_gpio_disp_b1_02_enet_1g_rdata00>, // ENET_RGMII_RXD0 + <&iomuxc_gpio_disp_b1_03_enet_1g_rdata01>, // ENET_RGMII_RXD1 + <&iomuxc_gpio_disp_b1_04_enet_1g_rdata02>, // ENET_RGMII_RXD2 + <&iomuxc_gpio_disp_b1_05_enet_1g_rdata03>, // ENET_RGMII_RXD3 + <&iomuxc_gpio_disp_b1_00_enet_1g_rx_en>; // ENET_RGMII_RX_EN + drive-strength = "high"; + bias-pull-down; + slew-rate = "fast"; + input-enable; + }; + }; + + pinmux_enet1g_mdio: pinmux_enet1g_mdio { + group0 { + pinmux = <&iomuxc_gpio_disp_b2_13_gpio11_io14>; // ETHPHY_RST_B + drive-strength = "high"; + bias-pull-down; + slew-rate = "slow"; + }; + group1 { + pinmux = <&iomuxc_gpio_disp_b2_12_gpio_mux5_io13>; // RGMII1_PHY_INTB + drive-strength = "high"; + bias-pull-down; + slew-rate = "fast"; + input-enable; + }; + group2 { + pinmux = <&iomuxc_gpio_emc_b2_19_enet_1g_mdc>, // ENET_RGMII_MDC + <&iomuxc_gpio_emc_b2_20_enet_1g_mdio>; // ENET_RGMII_MDIO + drive-strength = "high"; + bias-pull-down; + slew-rate = "fast"; + }; + }; + + pinmux_enet1g_ptp: pinmux_enet1g_ptp { + }; + pinmux_flexcan3: pinmux_flexcan3 { group0 { pinmux = <&iomuxc_lpsr_gpio_lpsr_01_can3_rx>, @@ -229,6 +290,17 @@ }; }; + pinmux_lpuart2_flowcontrol: pinmux_lpuart2_flowcontrol { + group0 { + pinmux = <&iomuxc_gpio_disp_b2_11_lpuart2_rx>, + <&iomuxc_gpio_disp_b2_10_lpuart2_tx>, + <&iomuxc_gpio_disp_b2_12_lpuart2_cts_b>, + <&iomuxc_gpio_disp_b2_13_lpuart2_rts_b>; + drive-strength = "high"; + slew-rate = "fast"; + }; + }; + pinmux_sai1: pinmux_sai1 { group0 { pinmux = <&iomuxc_gpio_ad_17_sai1_mclk>, diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi index a1d680a1e746d..c479300c8a9d0 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk.dtsi @@ -5,6 +5,7 @@ */ #include "mimxrt1170_evk-pinctrl.dtsi" +#include #include / { @@ -113,9 +114,9 @@ compatible = "microchip,ksz8081"; reg = <0>; status = "okay"; - mc,reset-gpio = <&gpio12 12 GPIO_ACTIVE_HIGH>; - mc,interrupt-gpio = <&gpio9 11 GPIO_ACTIVE_HIGH>; - mc,interface-type = "rmii"; + reset-gpios = <&gpio12 12 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio9 11 GPIO_ACTIVE_HIGH>; + microchip,interface-type = "rmii"; }; }; @@ -125,11 +126,44 @@ pinctrl-names = "default"; }; +&enet1g_mac { + status = "disabled"; + pinctrl-0 = <&pinmux_enet1g>; + pinctrl-names = "default"; + phy-handle = <&enet1g_phy>; + phy-connection-type = "rgmii"; + zephyr,random-mac-address; +}; + +&enet1g_mdio { + status = "disabled"; + pinctrl-0 = <&pinmux_enet1g_mdio>; + pinctrl-names = "default"; + enet1g_phy: phy@1 { + compatible = "realtek,rtl8211f"; + reg = <1>; + status = "disabled"; + reset-gpios = <&gpio11 14 GPIO_ACTIVE_HIGH>; + int-gpios = <&gpio5 13 GPIO_ACTIVE_LOW>; + }; +}; + +&enet1g_ptp_clock { + status = "disabled"; + pinctrl-0 = <&pinmux_enet1g_ptp>; + pinctrl-names = "default"; +}; + &csi { pinctrl-0 = <&pinmux_csi>; pinctrl-names = "default"; }; +&lpi2c6 { + pinctrl-0 = <&pinmux_lpi2c6>; + pinctrl-names = "default"; +}; + &flexcan3 { pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; @@ -185,7 +219,7 @@ reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(16)>; is25wp128: is25wp128@0 { compatible = "nxp,imx-flexspi-nor"; - size = <134217728>; + size = ; reg = <0>; spi-max-frequency = <133000000>; status = "okay"; @@ -202,20 +236,20 @@ label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 0x301000>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00321000 0x300000>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@621000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00621000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(2) - DT_SIZE_K(140))>; }; }; }; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm4_B.overlay b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm4_B.overlay index c92d197f548de..b65621ee63261 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm4_B.overlay +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm4_B.overlay @@ -22,9 +22,8 @@ status = "okay"; reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(64)>; w25q512nw:w25q512nw@0 { - /* IS25WP128 flash chip not currently enabled */ compatible = "nxp,imx-flexspi-nor"; - size = ; + size = ; reg = <0>; spi-max-frequency = <133000000>; status = "okay"; @@ -32,10 +31,6 @@ erase-block-size = <4096>; write-block-size = <1>; - /* - * Partitions are present to support dual core operation. - * as flash write is not supported, MCUBoot is not enabled. - */ partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -45,20 +40,20 @@ label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 0x301000>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00321000 0x300000>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@621000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00621000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(50) - DT_SIZE_K(140))>; }; }; }; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.dts b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.dts index d4400dea0f4ff..a9afb3fa4c8fe 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.dts +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.dts @@ -59,6 +59,21 @@ <32 0 &gpio11 16 0>, /* Pin 32, PWR_EN */ <34 0 &gpio9 29 0>; /* Pin 34, BL_PWM */ }; + + /* + * This node describes the GPIO pins mapping of the 44-pin camera + * connector, J2 on the EVK. This camera interface is supported + * on several NXP RT11xx EVKs, such as RT1170 and RT1160 EVK and + * is used with an ov5640 camera module available as a Zephyr shield + */ + nxp_cam_connector: cam-connector { + compatible = "nxp,cam-44pins-connector"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <9 0 &gpio11 15 0>, /* Pin 9, RESETB */ + <17 0 &gpio9 25 0>; /* Pin 17, PWDN */ + }; }; zephyr_lcdif: &lcdif {}; @@ -74,8 +89,6 @@ zephyr_mipi_dsi: &mipi_dsi { &flexcan3 { status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; @@ -148,3 +161,9 @@ zephyr_udc0: &usb1 { &pit2 { status = "okay"; }; + +nxp_cam_i2c: &lpi2c6 {}; + +nxp_mipi_csi: &mipi_csi2rx {}; + +nxp_csi: &csi {}; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.yaml b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.yaml index c7e846adf6ab3..da6ffa5b9c707 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.yaml +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7.yaml @@ -28,4 +28,5 @@ supported: - spi - usb_device - watchdog + - video vendor: nxp diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.overlay b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.overlay index a43339de27b61..bc7995fcb4e34 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.overlay +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.overlay @@ -7,8 +7,10 @@ / { chosen { zephyr,flash = &w25q512nw; - /delete-property/ zephyr,flash-controller; - /delete-property/ zephyr,code-partition; + zephyr,flash-controller = &w25q512nw; + zephyr,flash = &w25q512nw; + zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &bt_hci_uart; }; aliases { @@ -23,9 +25,8 @@ status = "okay"; reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(64)>; w25q512nw:w25q512nw@0 { - /* IS25WP128 flash chip not currently enabled */ compatible = "nxp,imx-flexspi-nor"; - size = ; + size = ; reg = <0>; spi-max-frequency = <133000000>; status = "okay"; @@ -33,10 +34,6 @@ erase-block-size = <4096>; write-block-size = <1>; - /* - * Partitions are present to support dual core operation. - * as flash write is not supported, MCUBoot is not enabled. - */ partitions { compatible = "fixed-partitions"; #address-cells = <1>; @@ -46,20 +43,20 @@ label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 3 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 0x301000>; + reg = <0x00020000 (DT_SIZE_M(7) + DT_SIZE_K(12))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@723000 { label = "image-1"; - reg = <0x00321000 0x300000>; + reg = <0x00723000 DT_SIZE_M(7)>; }; - storage_partition: partition@621000 { + storage_partition: partition@E23000 { label = "storage"; - reg = <0x00621000 DT_SIZE_K(1984)>; + reg = <0x00E23000 (DT_SIZE_M(50) - DT_SIZE_K(140))>; }; }; }; @@ -79,3 +76,29 @@ status = "okay"; }; }; + +m2_hci_uart: &lpuart2 { + pinctrl-0 = <&pinmux_lpuart2_flowcontrol>; + pinctrl-1 = <&pinmux_lpuart2_sleep>; + pinctrl-names = "default", "sleep"; + + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + + m2_bt_module { + compatible = "nxp,bt-hci-uart"; + sdio-reset-gpios = <&gpio9 15 GPIO_ACTIVE_HIGH>; + w-disable-gpios = <&gpio9 30 GPIO_ACTIVE_HIGH>; + hci-operation-speed = <115200>; + hw-flow-control; + fw-download-primary-speed = <115200>; + fw-download-secondary-speed = <3000000>; + fw-download-secondary-flowcontrol; + }; + }; +}; + +&m2_hci_uart { + status = "okay"; + current-speed = <115200>; +}; diff --git a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.yaml b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.yaml index 5cdfdf97c8757..62eeec200ea66 100644 --- a/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.yaml +++ b/boards/nxp/mimxrt1170_evk/mimxrt1170_evk_mimxrt1176_cm7_B.yaml @@ -26,4 +26,5 @@ supported: - spi - usb_device - watchdog + - video vendor: nxp diff --git a/boards/nxp/mimxrt595_evk/mimxrt595_evk_mimxrt595s_cm33.dts b/boards/nxp/mimxrt595_evk/mimxrt595_evk_mimxrt595s_cm33.dts index eccf7d453653f..c700bfe809fa9 100644 --- a/boards/nxp/mimxrt595_evk/mimxrt595_evk_mimxrt595s_cm33.dts +++ b/boards/nxp/mimxrt595_evk/mimxrt595_evk_mimxrt595s_cm33.dts @@ -407,17 +407,20 @@ zephyr_udc0: &usbhs { label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; + /* The MCUBoot swap-move algorithm uses the last 98 sectors + * of the primary slot0 for swap status and move. + */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 DT_SIZE_K(3076)>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(98 * 4))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@322000 { label = "image-1"; - reg = <0x00321000 DT_SIZE_K(3072)>; + reg = <0x00382000 DT_SIZE_M(3)>; }; - storage_partition: partition@621000 { + storage_partition: partition@622000 { label = "storage"; - reg = <0x00621000 DT_SIZE_M(57)>; + reg = <0x00682000 (DT_SIZE_M(58) - DT_SIZE_K(520))>; }; }; }; diff --git a/boards/nxp/mimxrt595_evk/pre_dt_board.cmake b/boards/nxp/mimxrt595_evk/pre_dt_board.cmake deleted file mode 100644 index 5dd7773bba415..0000000000000 --- a/boards/nxp/mimxrt595_evk/pre_dt_board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2022, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on RT5XX boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") diff --git a/boards/nxp/mimxrt685_evk/doc/index.rst b/boards/nxp/mimxrt685_evk/doc/index.rst index 109dfde16e685..4e8f9d79f516b 100644 --- a/boards/nxp/mimxrt685_evk/doc/index.rst +++ b/boards/nxp/mimxrt685_evk/doc/index.rst @@ -110,7 +110,7 @@ already supported, which can also be re-used on this mimxrt685_evk board: +-----------+------------+-------------------------------------+ The default configuration can be found in -:zephyr_file:`boards/nxp/mimxrt685_evk/mimxrt685_evk_defconfig` +:zephyr_file:`boards/nxp/mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33_defconfig` Other hardware features are not currently supported by the port. @@ -363,7 +363,7 @@ steps: https://www.nxp.com/products/processors-and-microcontrollers/arm-microcontrollers/i-mx-rt-crossover-mcus/i-mx-rt600-crossover-mcu-with-arm-cortex-m33-and-dsp-cores:i.MX-RT600 .. _i.MX RT685 Datasheet: - https://www.nxp.com/docs/en/data-sheet/DS-RT600.pdf + https://www.nxp.com/docs/en/data-sheet/RT600.pdf .. _i.MX RT685 Reference Manual: https://www.nxp.com/webapp/Download?colCode=UM11147 diff --git a/boards/nxp/mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33.dts b/boards/nxp/mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33.dts index a7df8a693efdd..7c7f9bd03b8d1 100644 --- a/boards/nxp/mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33.dts +++ b/boards/nxp/mimxrt685_evk/mimxrt685_evk_mimxrt685s_cm33.dts @@ -268,17 +268,20 @@ i2s1: &flexcomm3 { label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; + /* The MCUBoot swap-move algorithm uses the last 98 sectors + * of the primary slot0 for swap status and move. + */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 DT_SIZE_K(3076)>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(98 * 4))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@322000 { label = "image-1"; - reg = <0x00321000 DT_SIZE_K(3072)>; + reg = <0x00382000 DT_SIZE_M(3)>; }; - storage_partition: partition@621000 { + storage_partition: partition@622000 { label = "storage"; - reg = <0x00621000 DT_SIZE_M(57)>; + reg = <0x00682000 (DT_SIZE_M(58) - DT_SIZE_K(520))>; }; }; }; @@ -352,6 +355,14 @@ i2s1: &flexcomm3 { zephyr_udc0: &usbhs { status = "okay"; + phy_handle = <&usbphy>; +}; + +&usbphy { + status = "okay"; + tx-d-cal = <12>; + tx-cal-45-dp-ohms = <6>; + tx-cal-45-dm-ohms = <6>; }; &ctimer0 { diff --git a/boards/nxp/mimxrt685_evk/pre_dt_board.cmake b/boards/nxp/mimxrt685_evk/pre_dt_board.cmake deleted file mode 100644 index e23600abc7732..0000000000000 --- a/boards/nxp/mimxrt685_evk/pre_dt_board.cmake +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2020, NXP -# SPDX-License-Identifier: Apache-2.0 - -# Suppress "simple_bus_reg" on RT6XX boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") diff --git a/boards/nxp/mr_canhubk3/doc/index.rst b/boards/nxp/mr_canhubk3/doc/index.rst index f398e1708575c..67787ae3ad53b 100644 --- a/boards/nxp/mr_canhubk3/doc/index.rst +++ b/boards/nxp/mr_canhubk3/doc/index.rst @@ -60,6 +60,7 @@ EMAC on-chip ethernet mdio eMIOS on-chip pwm EDMA on-chip dma +FLEXIO PWM on-chip pwm ============ ========== ================================ The default configuration can be found in the Kconfig file diff --git a/boards/nxp/mr_canhubk3/mr_canhubk3-pinctrl.dtsi b/boards/nxp/mr_canhubk3/mr_canhubk3-pinctrl.dtsi index 49c4d164c817c..9a9e7894a7d04 100644 --- a/boards/nxp/mr_canhubk3/mr_canhubk3-pinctrl.dtsi +++ b/boards/nxp/mr_canhubk3/mr_canhubk3-pinctrl.dtsi @@ -300,6 +300,13 @@ }; }; + flexio0_pwm_default: flexio0_pwm_default { + group1 { + pinmux = , ; + output-enable; + }; + }; + qdec_s32: qdec_s32 { group1 { pinmux = , diff --git a/boards/nxp/mr_canhubk3/mr_canhubk3.dts b/boards/nxp/mr_canhubk3/mr_canhubk3.dts index 65f6c86d56942..66f7939340e3d 100644 --- a/boards/nxp/mr_canhubk3/mr_canhubk3.dts +++ b/boards/nxp/mr_canhubk3/mr_canhubk3.dts @@ -40,6 +40,7 @@ watchdog0 = &fs26_wdt; /* For pwm test suites */ pwm-0 = &emios0_pwm; + pwm-1 = &flexio0_pwm; red-pwm-led = &user_led1_red_pwm; green-pwm-led = &user_led1_green_pwm; blue-pwm-led = &user_led1_blue_pwm; @@ -358,8 +359,6 @@ pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; phys = <&can_phy0>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; @@ -367,40 +366,30 @@ pinctrl-0 = <&flexcan1_default>; pinctrl-names = "default"; phys = <&can_phy1>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flexcan2 { pinctrl-0 = <&flexcan2_default>; pinctrl-names = "default"; phys = <&can_phy2>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flexcan3 { pinctrl-0 = <&flexcan3_default>; pinctrl-names = "default"; phys = <&can_phy3>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flexcan4 { pinctrl-0 = <&flexcan4_default>; pinctrl-names = "default"; phys = <&can_phy4>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &flexcan5 { pinctrl-0 = <&flexcan5_default>; pinctrl-names = "default"; phys = <&can_phy5>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; &lpi2c0 { @@ -628,6 +617,27 @@ }; }; +&flexio0 { + status = "okay"; + + flexio0_pwm: flexio0_pwm { + pinctrl-0 = <&flexio0_pwm_default>; + pinctrl-names = "default"; + status = "okay"; + + pwm_0 { + pin-id = <19>; + prescaler = <1>; + }; + + pwm_1 { + pin-id = <11>; + prescaler = <1>; + }; + }; + +}; + &lcu1 { status = "okay"; }; diff --git a/boards/nxp/rd_rw612_bga/Kconfig.defconfig b/boards/nxp/rd_rw612_bga/Kconfig.defconfig index 713d8594e886a..e4c25b8924296 100644 --- a/boards/nxp/rd_rw612_bga/Kconfig.defconfig +++ b/boards/nxp/rd_rw612_bga/Kconfig.defconfig @@ -5,6 +5,9 @@ if BOARD_RD_RW612_BGA +config FLASH_LOAD_SIZE + default 0x400000 if !BOOTLOADER_MCUBOOT && !NXP_MONOLITHIC_BT + if LVGL # Enable DMA for LCDIC @@ -30,4 +33,15 @@ config LV_Z_FLUSH_THREAD endif # LVGL +# Enable interrupt support when using FT5336 driver +config INPUT_FT5336_INTERRUPT + default y if INPUT + +if DT_HAS_NXP_ENET_MAC_ENABLED && NETWORKING + +config NET_L2_ETHERNET + default y + +endif # DT_HAS_NXP_ENET_MAC_ENABLED && NETWORKING + endif # BOARD_RD_RW612_BGA diff --git a/boards/nxp/rd_rw612_bga/board.yml b/boards/nxp/rd_rw612_bga/board.yml index fe2573bfdbb4f..3316d69561420 100644 --- a/boards/nxp/rd_rw612_bga/board.yml +++ b/boards/nxp/rd_rw612_bga/board.yml @@ -3,3 +3,5 @@ board: vendor: nxp socs: - name: rw612 + variants: + - name: ethernet diff --git a/boards/nxp/rd_rw612_bga/doc/index.rst b/boards/nxp/rd_rw612_bga/doc/index.rst index dae43dd8aea77..51547c9e35400 100644 --- a/boards/nxp/rd_rw612_bga/doc/index.rst +++ b/boards/nxp/rd_rw612_bga/doc/index.rst @@ -61,7 +61,13 @@ Supported Features +-----------+------------+-----------------------------------+ | MRT | on-chip | counter | +-----------+------------+-----------------------------------+ - +| OS_TIMER | on-chip | os timer | ++-----------+------------+-----------------------------------+ +| PM | on-chip | power management; uses SoC Power | +| | | Modes 1 and 2 | ++-----------+------------+-----------------------------------+ +| BLE | on-chip | Bluetooth | ++-----------+------------+-----------------------------------+ The default configuration can be found in the defconfig file: @@ -69,6 +75,16 @@ The default configuration can be found in the defconfig file: Other hardware features are not currently supported +Fetch Binary Blobs +****************** + +To support Bluetooth, rd_rw612_bga requires fetching binary blobs, which can be +achieved by running the following command: + +.. code-block:: console + + west blobs fetch hal_nxp + Programming and Debugging ************************* @@ -130,9 +146,57 @@ should see the following message in the terminal: ***** Booting Zephyr OS zephyr-v3.6.0 ***** Hello World! rd_rw612_bga +Bluetooth +********* + +BLE functionality requires to fetch binary blobs, so make sure to follow +the ``Fetch Binary Blobs`` section first. + +Those binary blobs can be used in two different ways, depending if :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` +is enabled or not: + +- :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` is enabled (default): + +The required binary blob will be linked with the application image directly, forming +one single monolithic image. +The user has nothing else to do other than flashing the application to the board. + +- :kconfig:option:`CONFIG_NXP_MONOLITHIC_BT` is disabled: + +In this case, the BLE blob won't be linked with the application, so the user needs to manually +flash the BLE binary blob to the board at the address ``0x18540000``. +The binary blob will be located here: ``/modules/hal/nxp/zephyr/blobs/rw61x/rw61x_sb_ble_a2.bin`` + +Board variants +************** + +Ethernet +======== + +To use ethernet on the RD_RW612_BGA board, you first need to make the following +modifications to the board hardware: + +Add resistors: +- R485 +- R486 +- R487 +- R488 +- R489 +- R491 +- R490 +Remove resistors: +- R522 +- R521 +- R520 +- R524 +- R523 +- R508 +- R505 + +Then, build for the board target `rd_rw612_bga//ethernet`. Resources -========= +********* .. _RW612 Website: https://www.nxp.com/products/wireless-connectivity/wi-fi-plus-bluetooth-plus-802-15-4/wireless-mcu-with-integrated-tri-radiobr1x1-wi-fi-6-plus-bluetooth-low-energy-5-3-802-15-4:RW612 diff --git a/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay b/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay new file mode 100644 index 0000000000000..8b9dbe924911f --- /dev/null +++ b/boards/nxp/rd_rw612_bga/dts/goworld_16880_lcm.overlay @@ -0,0 +1,91 @@ +#include + +/ { + chosen { + zephyr,display = &st7796s_lcdic; + }; + + lvgl_pointer { + compatible = "zephyr,lvgl-pointer-input"; + input = <&ft7401>; + swap-xy; + invert-y; + }; +}; + +&lcdic { + status = "okay"; + nxp,swap-bytes; + /* + * Settings to connect this display: + * Populate the following resistors: + * - R125, R123, R12, R124, R15, R243, R239, R236, R233, R286, R246 + * Remove the following resistors: + * - R9, R11, R20, R19, R242, R241, R237, R235, R245 + * Remove JP30 to disconnect Flexcomm SPI CS + * Display can be connected to Arduino header (J5/J6) + * Pin # | Signal | Header + * ------------------------------- + * 1 | VDD | J5.8 (+3.3V) + * 2 | RST | J6.8 (LCD_SPI_RESETN) + * 3 | SDO | J5.5 (SPI_MISO) + * 4 | CS | J5.3 (LCD_SPI_SS) + * 5 | SCLK | J5.6 (LCD_SPI_SCK) + * 6 | GND | J5.7 (GND) + * 7 | MOSI | J5.4 (LCD_SPI_SDIO) + * 8 | CD | J5.1 (LCD_SPI_DC) + * 9 | TE | J5.2 (LCD_SPI_TE, not enabled) + * + * Pins 10 and 11 correspond to the backlight anode and cathode, + * and must be driven by an external circuit + */ + st7796s_lcdic: st7796s@0 { + compatible = "sitronix,st7796s"; + status = "okay"; + reg = <0>; + mipi-max-frequency = <23000000>; + duplex = ; + height = <320>; + width = <480>; + invert-mode = "1-dot"; + frmctl1 = [80 10]; + bpc = [1F 50 00 20]; + dfc = [8A 07 3B]; + pwr1 = [80 64]; + pwr2 = <0x13>; + pwr3 = <0xA7>; + vcmpctl = <0x09>; + doca = [40 8A 00 00 29 19 A5 38]; + pgc = [F0 06 0B 07 06 05 2E 33 47 3A 17 16 2E 31]; + ngc = [F0 09 0D 09 08 23 2E 33 46 38 13 13 2C 32]; + madctl = <0x28>; + }; +}; + +&flexcomm2 { + status = "okay"; + ft7401: ft7401@38 { + /* + * Settings to connect this touch controller: + * Populate JP3 and JP50 to connect I2C + * Controller can be connected to Arduino Header (J8/J5) + * Pin #1 | Signal | Header + * ------------------------------- + * 1 | VDD | J8.2 (+3.3V) + * 2 | IOVDD | J8.4 (+3.3V) + * 3 | SCL | J5.10 (SCL) + * 4 | SDA | J5.9 (SDA) + * 5 | INT | J6.3 (D2) + * 6 | RST | J6.4 (D3) + * 7 | GND | J8.6 (GND) + * 8 | GND | J8.7 (GND) + * + * Note- the actual controller present on this IC is a FT7401, + * but the FT5336 driver in Zephyr supports this IC. + */ + compatible = "focaltech,ft5336"; + reg = <0x38>; + reset-gpios = <&hsgpio0 15 GPIO_ACTIVE_LOW>; + int-gpios = <&hsgpio0 11 GPIO_ACTIVE_HIGH>; + }; +}; diff --git a/boards/nxp/rd_rw612_bga/pre_dt_board.cmake b/boards/nxp/rd_rw612_bga/pre_dt_board.cmake index 2c56668e4355a..5da215a0a3bef 100644 --- a/boards/nxp/rd_rw612_bga/pre_dt_board.cmake +++ b/boards/nxp/rd_rw612_bga/pre_dt_board.cmake @@ -1,7 +1,5 @@ # Copyright 2023 NXP # SPDX-License-Identifier: Apache-2.0 -# Suppress "simple_bus_reg" on RW6XX boards as all GPIO ports use the same register. -list(APPEND EXTRA_DTC_FLAGS "-Wno-simple_bus_reg") # Suppress "spi_bus_bridge" as flexcomm node can be used as a SPI device. list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi b/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi index db565403583f1..78193e6b5122a 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga-pinctrl.dtsi @@ -14,6 +14,13 @@ }; }; + pinmux_flexcomm0_usart: pinmux_flexcomm0_usart { + group0 { + pinmux = ; + slew-rate = "normal"; + }; + }; + pinmux_flexcomm0_spi: pinmux_flexcomm0_spi { group0 { pinmux = , @@ -87,4 +94,22 @@ bias-pull-down; }; }; + + pinmux_enet: pinmux_enet { + group0 { + pinmux = ; + slew-rate = "fast"; + }; + }; + + pinmux_mdio: pinmux_mdio { + group0 { + pinmux = ; + slew-rate = "fast"; + }; + }; }; diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dts b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dts index 4a3f958849422..41552feecff65 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dts +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dts @@ -6,10 +6,4 @@ /dts-v1/; -#include #include "rd_rw612_bga.dtsi" - -/ { - model = "nxp,rd_rw612_bga"; - compatible = "nxp,rd_rw612_bga"; -}; diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi index 21872376294bf..7260dd4e2db3a 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga.dtsi @@ -4,10 +4,13 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include "rd_rw612_bga-pinctrl.dtsi" #include / { + model = "nxp,rd_rw612_bga"; + compatible = "nxp,rd_rw612_bga"; aliases { usart-0 = &flexcomm3; @@ -147,6 +150,16 @@ arduino_i2c: &flexcomm2 { label = "image-0"; reg = <0x00020000 0x3e0000>; }; + + /* This partition is reserved for connectivity firmwares storage + * and shouldn't be moved. + */ + fw_storage: partition@400000 { + label = "fw_storage"; + reg = <0x400000 0x280000>; + read-only; + }; + slot1_partition: partition@680000 { label = "image-1"; reg = <0x680000 0x3e0000>; @@ -246,3 +259,26 @@ zephyr_udc0: &usb_otg { , ; }; + +&adc0 { + status = "okay"; +}; + +&dac0 { + status = "okay"; +}; + +/* OS Timer is the wakeup source for PM mode 2 */ +&os_timer { + status = "okay"; + wakeup-source; +}; + +&systick { + status = "disabled"; +}; + +&hci { + status = "okay"; + wakeup-source; +}; diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml b/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml index db7445f1c9541..919f10479ee43 100644 --- a/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga.yaml @@ -25,3 +25,5 @@ supported: - watchdog - counter - hwinfo + - adc + - dac diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga_rw612_ethernet.dts b/boards/nxp/rd_rw612_bga/rd_rw612_bga_rw612_ethernet.dts new file mode 100644 index 0000000000000..2a793e6cdcab7 --- /dev/null +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga_rw612_ethernet.dts @@ -0,0 +1,47 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include "rd_rw612_bga.dtsi" + +/* + * To use ethernet on RD_RW612_BGA board: + * + * Load R485, R486, R487, R488, R489, R491, R490, + * R522, R521, R520, R524, R523, R508, R505 + * Remove R518, R507, R506 + */ +&enet_mac { + status = "okay"; + pinctrl-0 = <&pinmux_enet>; + pinctrl-names = "default"; + phy-handle = <&phy>; + zephyr,random-mac-address; + phy-connection-type = "rmii"; +}; + +&enet_mdio { + status = "okay"; + pinctrl-0 = <&pinmux_mdio>; + pinctrl-names = "default"; + phy: phy@2 { + compatible = "microchip,ksz8081"; + reg = <2>; + status = "okay"; + reset-gpios = <&hsgpio1 23 GPIO_ACTIVE_HIGH>; + int-gpios = <&hsgpio0 21 GPIO_ACTIVE_HIGH>; + microchip,interface-type = "rmii"; + }; +}; + +/* XTAL is disconnected */ +/* TODO: this should be uncommented once it is added */ +/* + * &rtc { + * status = "disabled"; + * }; + */ diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga_rw612_ethernet.yaml b/boards/nxp/rd_rw612_bga/rd_rw612_bga_rw612_ethernet.yaml new file mode 100644 index 0000000000000..19d26ea8162f0 --- /dev/null +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga_rw612_ethernet.yaml @@ -0,0 +1,20 @@ +# +# Copyright 2023 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +identifier: rd_rw612_bga/rw612/ethernet +name: NXP RD_RW612_BGA ETHERNET +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb + - xtools +ram: 960 +flash: 65536 +supported: + - netif:eth +testing: + default: false diff --git a/boards/nxp/rd_rw612_bga/rd_rw612_bga_rw612_ethernet_defconfig b/boards/nxp/rd_rw612_bga/rd_rw612_bga_rw612_ethernet_defconfig new file mode 100644 index 0000000000000..b987fa24dc09b --- /dev/null +++ b/boards/nxp/rd_rw612_bga/rd_rw612_bga_rw612_ethernet_defconfig @@ -0,0 +1,15 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_PINCTRL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_GPIO=y +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y +CONFIG_TRUSTED_EXECUTION_SECURE=y diff --git a/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts b/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts index 2399766c0c2f2..729219dd670e1 100644 --- a/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts +++ b/boards/nxp/rddrone_fmuk66/rddrone_fmuk66.dts @@ -236,23 +236,23 @@ zephyr_udc0: &usbotg { boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x00010000>; + reg = <0x00000000 DT_SIZE_K(64)>; read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x000E9000>; + reg = <0x00010000 (DT_SIZE_K(928) + DT_SIZE_K(8))>; }; - slot1_partition: partition@F9000 { + slot1_partition: partition@FA000 { label = "image-1"; - reg = <0x000F9000 0x000E8000>; + reg = <0x000FA000 DT_SIZE_K(928)>; }; - storage_partition: partition@1e1000 { + storage_partition: partition@1E2000 { label = "storage"; - reg = <0x001e1000 0x0001f000>; + reg = <0x001E2000 DT_SIZE_K(120)>; }; }; }; @@ -281,7 +281,6 @@ zephyr_udc0: &usbotg { status = "okay"; pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; - bus-speed = <125000>; phys = <&transceiver0>; }; @@ -289,7 +288,6 @@ zephyr_udc0: &usbotg { status = "okay"; pinctrl-0 = <&flexcan1_default>; pinctrl-names = "default"; - bus-speed = <125000>; phys = <&transceiver1>; }; diff --git a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270.dtsi b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270.dtsi index 297b4926d11e1..1270676c77a56 100644 --- a/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270.dtsi +++ b/boards/nxp/s32z2xxdc2/s32z2xxdc2_s32z270.dtsi @@ -34,14 +34,10 @@ &can0 { pinctrl-0 = <&can0_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; &can1 { pinctrl-0 = <&can1_default>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; diff --git a/boards/nxp/twr_ke18f/twr_ke18f.dts b/boards/nxp/twr_ke18f/twr_ke18f.dts index 5bc591f0726c1..18bbbe7276975 100644 --- a/boards/nxp/twr_ke18f/twr_ke18f.dts +++ b/boards/nxp/twr_ke18f/twr_ke18f.dts @@ -293,7 +293,6 @@ &flexcan0 { status = "okay"; - bus-speed = <125000>; pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; @@ -336,25 +335,25 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0xc000>; + reg = <0x00000000 DT_SIZE_K(64)>; + read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ - slot0_partition: partition@c000 { + slot0_partition: partition@10000 { label = "image-0"; - reg = <0x0000c000 0x37000>; + reg = <0x00010000 (DT_SIZE_K(200) + DT_SIZE_K(8))>; }; - slot1_partition: partition@43000 { + slot1_partition: partition@44000 { label = "image-1"; - reg = <0x00043000 0x36000>; + reg = <0x00044000 DT_SIZE_K(200)>; }; - storage_partition: partition@79000 { + storage_partition: partition@76000 { label = "storage"; - reg = <0x00079000 0x00007000>; + reg = <0x00076000 DT_SIZE_K(40)>; }; }; }; diff --git a/boards/nxp/twr_kv58f220m/twr_kv58f220m.dts b/boards/nxp/twr_kv58f220m/twr_kv58f220m.dts index f79c840942c92..2a59adfd6ef3a 100644 --- a/boards/nxp/twr_kv58f220m/twr_kv58f220m.dts +++ b/boards/nxp/twr_kv58f220m/twr_kv58f220m.dts @@ -113,25 +113,25 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; - reg = <0x00000000 0x10000>; + reg = <0x00000000 DT_SIZE_K(64)>; + read-only; }; - /* Note slot 0 has one additional sector, - * this is intended for use with the swap move algorithm + /* The MCUBoot swap-move algorithm uses the last 2 sectors + * of the primary slot0 for swap status and move. */ slot0_partition: partition@10000 { label = "image-0"; - reg = <0x00010000 0x68000>; + reg = <0x00010000 (DT_SIZE_K(416) + DT_SIZE_K(16))>; }; - slot1_partition: partition@78000 { + slot1_partition: partition@7C000 { label = "image-1"; - reg = <0x00078000 0x66000>; + reg = <0x0007C000 DT_SIZE_K(416)>; }; - storage_partition: partition@de000 { - label = "image-scratch"; - reg = <0x000de000 0x22000>; + storage_partition: partition@E4000 { + label = "storage"; + reg = <0x000E4000 DT_SIZE_K(112)>; }; }; }; diff --git a/boards/nxp/ucans32k1sic/ucans32k1sic.dts b/boards/nxp/ucans32k1sic/ucans32k1sic.dts index 57ca5dd43b310..77b9523634386 100644 --- a/boards/nxp/ucans32k1sic/ucans32k1sic.dts +++ b/boards/nxp/ucans32k1sic/ucans32k1sic.dts @@ -179,8 +179,6 @@ pinctrl-0 = <&flexcan0_default>; pinctrl-names = "default"; phys = <&can_phy0>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; @@ -188,7 +186,5 @@ pinctrl-0 = <&flexcan1_default>; pinctrl-names = "default"; phys = <&can_phy1>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/nxp/vmu_rt1170/Kconfig.defconfig b/boards/nxp/vmu_rt1170/Kconfig.defconfig index f0f7bffa888b0..4bf5b36250753 100644 --- a/boards/nxp/vmu_rt1170/Kconfig.defconfig +++ b/boards/nxp/vmu_rt1170/Kconfig.defconfig @@ -26,9 +26,6 @@ if NETWORKING config NET_L2_ETHERNET default y if CPU_CORTEX_M7 # No cache memory support is required for driver -config ETH_MCUX_PHY_RESET - default n - config ETH_MCUX_RMII_EXT_CLK default y diff --git a/boards/nxp/vmu_rt1170/doc/index.rst b/boards/nxp/vmu_rt1170/doc/index.rst index a683fc8ad1ed4..89a2599aee2e1 100644 --- a/boards/nxp/vmu_rt1170/doc/index.rst +++ b/boards/nxp/vmu_rt1170/doc/index.rst @@ -61,6 +61,10 @@ Hardware - CAN bus JST-GH connectors +- RC IN + + - RC input connector for SBUS compatible RC receivers + For more information about the MIMXRT1176 SoC and VMU RT1170 board, see these references: @@ -94,7 +98,7 @@ following hardware features: +-----------+------------+-------------------------------------+ | I2C | on-chip | i2c | +-----------+------------+-------------------------------------+ -| PWM | on-chip | pwm | +| PWM | on-chip | flexpwm, qtmr | +-----------+------------+-------------------------------------+ | ADC | on-chip | adc | +-----------+------------+-------------------------------------+ @@ -125,7 +129,7 @@ following hardware features: +-----------+------------+-------------------------------------+ The default configuration can be found in -:zephyr_file:`boards/nxp/vmu_rt1170/vmu_rt1170_defconfig` +:zephyr_file:`boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7_defconfig` Other hardware features are not currently supported by the port. @@ -134,71 +138,337 @@ Connections and I/Os The MIMXRT1170 SoC has six pairs of pinmux/gpio controllers. -+---------------------------+----------------+------------------+ -| Name | Function | Usage | -+---------------------------+----------------+------------------+ -| WAKEUP | GPIO | SW7 | -+---------------------------+----------------+------------------+ -| GPIO_AD_04 | GPIO | LED | -+---------------------------+----------------+------------------+ -| GPIO_AD_24 | LPUART1_TX | UART Console | -+---------------------------+----------------+------------------+ -| GPIO_AD_25 | LPUART1_RX | UART Console | -+---------------------------+----------------+------------------+ -| GPIO_LPSR_00 | CAN3_TX | flexcan | -+---------------------------+----------------+------------------+ -| GPIO_LPSR_01 | CAN3_RX | flexcan | -+---------------------------+----------------+------------------+ -| GPIO_AD_29 | SPI1_CS0 | spi | -+---------------------------+----------------+------------------+ -| GPIO_AD_28 | SPI1_CLK | spi | -+---------------------------+----------------+------------------+ -| GPIO_AD_30 | SPI1_SDO | spi | -+---------------------------+----------------+------------------+ -| GPIO_AD_31 | SPI1_SDI | spi | -+---------------------------+----------------+------------------+ -| GPIO_AD_08 | LPI2C1_SCL | i2c | -+---------------------------+----------------+------------------+ -| GPIO_AD_09 | LPI2C1_SDA | i2c | -+---------------------------+----------------+------------------+ -| GPIO_LPSR_05 | LPI2C5_SCL | i2c | -+---------------------------+----------------+------------------+ -| GPIO_LPSR_04 | LPI2C5_SDA | i2c | -+---------------------------+----------------+------------------+ -| GPIO_AD_04 | FLEXPWM1_PWM2 | pwm | -+---------------------------+----------------+------------------+ -| GPIO_AD_32 | ENET_MDC | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_AD_33 | ENET_MDIO | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_02 | ENET_TX_DATA00 | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_03 | ENET_TX_DATA01 | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_04 | ENET_TX_EN | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_05 | ENET_REF_CLK | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_06 | ENET_RX_DATA00 | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_07 | ENET_RX_DATA01 | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_08 | ENET_RX_EN | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_DISP_B2_09 | ENET_RX_ER | Ethernet | -+---------------------------+----------------+------------------+ -| GPIO_AD_17_SAI1_MCLK | SAI_MCLK | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_21_SAI1_TX_DATA00 | SAI1_TX_DATA | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_22_SAI1_TX_BCLK | SAI1_TX_BCLK | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_23_SAI1_TX_SYNC | SAI1_TX_SYNC | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_17_SAI1_MCLK | SAI1_MCLK | SAI | -+---------------------------+----------------+------------------+ -| GPIO_AD_20_SAI1_RX_DATA00 | SAI1_RX_DATA00 | SAI | -+---------------------------+----------------+------------------+ ++-----------------+--------------------------------+----------------------------+ +| Name | Function | Usage | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_00 | FLEXCAN2_TX | CAN2_TX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_01 | FLEXCAN2_RX | CAN2_RX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_02 | LPUART8_TXD | UART8_TX_TELEM2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_03 | LPUART8_RXD | UART8_RX_TELEM2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_04 | LPUART8_CTS_B | UART8_CTS_TELEM2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_05 | LPUART8_RTS_B | UART8_RTS_TELEM2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_06 | FLEXCAN1_TX | CAN1_TX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_07 | FLEXCAN1_RX | CAN1_RX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_08 | LPI2C1_SCL | I2C1_SCL_GPS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_09 | LPI2C1_SDA | I2C1_SDA_GPS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_10 | LPADC1_CH2A | SCALED_VDD_3V3_SENSORS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_11 | LPADC1_CH2B | SCALED_VDD_3V3_SENSORS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_12 | LPADC1_CH3A | SCALED_VDD_3V3_SENSORS3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_13 | LPADC1_CH3B | SCALED_V5 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_14 | LPADC1_CH4A | ADC_6V6 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_15 | LPUART10_TXD | UART10_TX_TELEM3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_16 | LPADC1_CH5A | ADC_3V3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_17 | LPADC1_CHB | SCALED_VDD_3V3_SENSORS4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_18 | LPI2C2_SCL | I2C2_SCL_GPS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_19 | LPI2C2_SDA | I2C2_SDA_GPS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_20 | GPIO3_IO19 | SPI1_DRDY1_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_21 | GPIO3_IO20 | SPI3_DRDY1_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_22 | LPADC2_CH2A | HW_VER_SENSE | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_23 | LPADC2_CH2B | HW_REV_SENSE | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_24 | LPSPI2_SCK | SPI2_SCK_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_25 | LPSPI2_PCS0 | SPI2_nCS0_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_26 | LPSPI2_SOUT | SPI2_MOSI_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_27 | LPSPI2_SIN | SPI2_MISO_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_28 | LPUART5_TXD | UART5_TX_GPS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_29 | LPUART5_RXD | UART5_RX_GPS2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_30 | LPUART3_TXD | UART3_TX_GPS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_31 | LPUART3_RXD | UART3_RX_GPS1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_32 | USDHC1_CD_B | USDHC1_CD | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_33 | LPUART10_RXD | UART10_RX_TELEM3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_34 | LPUART10_CTS_B | UART10_CTS_TELEM3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_AD_35 | LPUART10_RTS_B | UART10_RTS_TELEM3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_00 | ENET_1G_RX_EN | ETH_CRS_DV | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_01 | ENET_1G_RX_ER | ETH_RX_ER | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_02 | LPUART1_TXD | UART1_TX_DEBUG | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_03 | LPUART1_RXD | UART1_RX_DEBUG | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_04 | LPUART4_RXD | UART4_RX_TELEM1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_05 | LPUART4_CTS_B | UART4_CTS_TELEM1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_06 | LPUART4_TXD | UART4_TX_TELEM1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_07 | LPUART4_RTS_B | UART4_RTS_TELEM1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_08 | ENET_1G_TDATA1 | ETH_TXD1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_09 | ENET_1G_TDATA0 | ETH_TXD0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_10 | ENET_1G_TX_EN | ETH_TX_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B1_11 | ENET_1G_REF_CLK | ETH_REF_CLK | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_00 | GPIO5_IO01 | nLED_RED | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_01 | GPIO5_IO02 | nLED_GREEN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_02 | ARM_TRACE0 | TRACED0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_03 | ARM_TRACE1 | TRACED1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_04 | ARM_TRACE2 | TRACED2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_05 | ARM_TRACE3 | TRACED3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_06 | ARM_TRACE_CLK | TRACECLK | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_07 | ARM_TRACE_SWO | TRACESWO | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_08 | GPIO5_IO09 | ETH_POWER_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_09 | GPIO5_IO10 | ETH_PHY_nINT | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_10 | LPI2C3_SCL | I2C3_SCL_FMU | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_11 | LPI2C3_SDA | I2C3_SDA_FMU | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_12 | LPSPI4_SCK | SPI4_SCK_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_13 | LPSPI4_SIN | SPI4_MISO_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_14 | LPSPI4_SOUT | SPI4_MOSI_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_DISP_B2_15 | LPSPI4_PCS0 | SPI4_nCS0_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_00 | FLEXPWM4_PWM0_A + FLEXIO1_IO00 | FMU_CH11 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_01 | GPIO1_IO01 | VDD_3V3_SD_CARD_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_02 | FLEXPWM4_PWM1_A + FLEXIO1_IO02 | FMU_CH12 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_03 | GPIO1_IO03 | FMU_nSAFETY_SWITCH_LED_OUT | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_04 | GPIO1_IO04 | NFC_GPIO | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_05 | GPIO1_IO05 | SPI6_DRDY1_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_06 | FLEXPWM2_PWM0_A + FLEXIO1_IO06 | FMU_CH4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_07 | GPIO1_IO07 | SPI6_DRDY2_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_08 | FLEXPWM2_PWM1_A + FLEXIO1_IO08 | FMU_CH5 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_09 | GPT5_CAPTURE1 | FMU_PPM_INPUT | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_10 | FLEXPWM2_PWM2_A + FLEXIO1_IO10 | FMU_CH6 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_11 | GPIO1_IO11 | SPI6_nRESET_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_12 | GPIO1_IO12 | VDD_5V_HIPOWER_nOC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_13 | GPIO1_IO13 | nLED_BLUE | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_14 | GPIO1_IO14 | VDD_3V3_SENSORS3_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_15 | GPIO1_IO15 | VDD_5V_PERIPH_nOC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_16 | GPIO1_IO16 | SPI4_DRDY1_SENSOR4 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_17 | GPIO1_IO17 | nARMED | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_18 | TMR2_TIMER0 | SPIX_SYNC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_19 | FLEXPWM2_PWM3_A + FLEXIO1_IO19 | FMU_CH7 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_20 | TMR4_TIMER0 | FMU_CAP1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_21 | FLEXPWM3_PWM3_A + FLEXIO1_IO21 | FMU_CH10 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_22 | GPIO1_IO22 | VDD_3V3_SENSORS2_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_23 | FLEXPWM1_PWM0_A | FMU_CH1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_24 | GPIO1_IO24 | FMU_SAFETY_SWITCH_IN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_25 | FLEXPWM1_PWM1_A + FLEXIO1_IO25 | FMU_CH2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_26 | GPIO1_IO26 | HW_VER_REV_DRIVE | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_27 | FLEXPWM1_PWM2_A + FLEXIO1_IO27 | FMU_CH3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_28 | GPIO1_IO28 | nPOWER_IN_A | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_29 | FLEXPWM3_PWM0_A + FLEXIO1_IO29 | FMU_CH8 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_30 | GPIO1_IO30 | nPOWER_IN_B | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_31 | FLEXPWM3_PWM1_A + FLEXIO1_IO31 | FMU_CH9 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_32 | GPIO2_IO00 | nPOWER_IN_C | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_33 | GPIO2_IO01 | VDD_3V3_SENSORS1_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_34 | GPIO2_IO02 | VDD_5V_PERIPH_nEN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_35 | GPIO2_IO03 | I2C2_DRDY1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_36 | GPIO2_IO04 | VDD_3V3_SENSORS4_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_37 | GPIO2_IO05 | VDD_5V_HIPOWER_nEN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_38 | GPIO2_IO06 | VDD_3V3_SPEKTRUM_POWER_EN | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_39 | GPIO2_IO07 | SPI2_DRDY1_SENSOR2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_40 | LPUART6_TXD | UART6_TX_TO_IO__RC_INPUT | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B1_41 | LPUART6_RXD | UART6_RX_FROM_IO__NC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_00 | LPSPI1_SCK | SPI1_SCK_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_01 | LPSPI1_PCS0 | SPI1_nCS0_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_02 | LPSPI1_SOUT | SPI1_MOSI_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_03 | LPSPI1_SIN | SPI1_MISO_SENSOR1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_04 | LPSPI3_SCK | SPI3_SCK_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_05 | LPSPI3_PCS0 | SPI3_nCS0_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_06 | LPSPI3_SOUT | SPI3_MOSI_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_07 | LPSPI3_SIN | SPI3_MISO_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_08 | LPSPI3_PCS1 | SPI3_nCS1_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_09 | TMR1_TIMER0 | BUZZER_1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_10 | FLEXSPI2_A_SCLK | FLEXSPI2_SCK_FRAM | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_11 | FLEXSPI2_A_SS0_B | FLEXSPI2_nCS0_FRAM | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_12 | GPIO2_IO22 | GPIO_EMC_B2_12 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_13 | FLEXSPI2_A_DATA0 | FLEXSPI2_DATA0_FRAM | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_14 | FLEXSPI2_A_DATA1 | FLEXSPI2_DATA1_FRAM | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_15 | ENET_1G_RDATA0 | ETH_RXD0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_16 | ENET_1G_RDATA1 | ETH_RXD1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_17 | TMR3_TIMER0 | HEATER | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_18 | GPIO2_IO28 | SPI3_DRDY2_SENSOR3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_19 | ENET_1G_MDC | ETH_MDC | ++-----------------+--------------------------------+----------------------------+ +| GPIO_EMC_B2_20 | ENET_1G_MDIO | ETH_MDIO | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_00 | FLEXCAN3_TX | CAN3_TX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_01 | FLEXCAN3_RX | CAN3_RX | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_02 | SRC_BOOT_MODE00 | BT_MODE0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_03 | SRC_BOOT_MODE01 | BT_MODE1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_04 | LPUART11_TXD | UART11_TX_EXTERNAL2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_05 | LPUART11_RXD | UART11_RX_EXTERNAL2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_06 | LPI2C6_SDA | I2C6_SDA_EXTERNAL2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_07 | LPI2C6_SCL | I2C6_SCL_EXTERNAL2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_08 | LPSPI6_PCS1 | SPI6_nCS1_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_09 | LPSPI6_PCS0 | SPI6_nCS0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_10 | LPSPI6_SCK | SPI6_SCK_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_11 | LPSPI6_SOUT | SPI6_MOSI_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_12 | LPSPI6_SIN | SPI6_MISO_EXTERNAL1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_13 | JTAG_MOD | NC_JTAG_MOD_PD | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_14 | SWD_CLK | FMU_SWCLK | ++-----------------+--------------------------------+----------------------------+ +| GPIO_LPSR_15 | SWD_DIO | FMU_SWDIO | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_00 | USDHC1_CMD | USDHC1_CMD | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_01 | USDHC1_CLK | USDHC1_CLK | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_02 | USDHC1_DATA0 | USDHC1_DATA0 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_03 | USDHC1_DATA1 | USDHC1_DATA1 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_04 | USDHC1_DATA2 | USDHC1_DATA2 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B1_05 | USDHC1_DATA3 | USDHC1_DATA3 | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_00 | FLEXSPI1_B_DATA3 | FLEXSPI1_DATA7_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_01 | FLEXSPI1_B_DATA2 | FLEXSPI1_DATA6_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_02 | FLEXSPI1_B_DATA1 | FLEXSPI1_DATA5_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_03 | FLEXSPI1_B_DATA0 | FLEXSPI1_DATA4_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_04 | FLEXSPI1_B_SCLK | FLEXSPI1_nSCK_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_05 | FLEXSPI1_A_DQS | FLEXSPI1_DQS_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_06 | FLEXSPI1_A_SS0_B | FLEXSPI1_nCS0_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_07 | FLEXSPI1_A_SCLK | FLEXSPI1_SCK_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_08 | FLEXSPI1_A_DATA0 | FLEXSPI1_DATA0_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_09 | FLEXSPI1_A_DATA0 | FLEXSPI1_DATA1_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_10 | FLEXSPI1_A_DATA2 | FLEXSPI1_DATA2_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| GPIO_SD_B2_11 | FLEXSPI1_A_DATA3 | FLEXSPI1_DATA3_HYPERFLASH | ++-----------------+--------------------------------+----------------------------+ +| USB1_DN | USB_OG1_DN | USB_D_N | ++-----------------+--------------------------------+----------------------------+ +| USB1_DP | USB_OTG1_DP | USB_D_P | ++-----------------+--------------------------------+----------------------------+ +| USB1_VBUS | USB_OTG1_VBUS | VBUS | ++-----------------+--------------------------------+----------------------------+ Serial Port =========== diff --git a/boards/nxp/vmu_rt1170/flexspi_nor_config.c b/boards/nxp/vmu_rt1170/flexspi_nor_config.c index 85ad476cf84c0..7a59acd6c54fe 100644 --- a/boards/nxp/vmu_rt1170/flexspi_nor_config.c +++ b/boards/nxp/vmu_rt1170/flexspi_nor_config.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2019, MADMACHINE LIMITED + * Copyright 2024 NXP * * refer to hal_nxp board file * @@ -101,7 +102,7 @@ const struct flexspi_nor_config_t g_flash_fast_config = { [0 + 0] = FLEXSPI_LUT_SEQ(CMD_DDR, FLEXSPI_8PAD, 0xEE, CMD_DDR, FLEXSPI_8PAD, 0x11), [0 + 1] = FLEXSPI_LUT_SEQ(RADDR_DDR, FLEXSPI_8PAD, - 0x20, DUMMY_DDR, FLEXSPI_8PAD, 0x04), + 0x20, DUMMY_DDR, FLEXSPI_8PAD, 0x28), [0 + 2] = FLEXSPI_LUT_SEQ(READ_DDR, FLEXSPI_8PAD, 0x04, STOP, FLEXSPI_1PAD, 0x00), diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi b/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi index ac50cfa8b76f3..e6d00911b1328 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi +++ b/boards/nxp/vmu_rt1170/vmu_rt1170-pinctrl.dtsi @@ -3,16 +3,15 @@ * SPDX-License-Identifier: Apache-2.0 * * Note: File generated by gen_board_pinctrl.py - * from vmu_rt1170.mex + * from vmu_rt1170.mex, then updated manually */ #include &pinctrl { - pinmux_enet: pinmux_enet { + pinmux_enet1g: pinmux_enet1g { group0 { - pinmux = <&iomuxc_gpio_disp_b2_09_gpio_mux5_io10>, - <&iomuxc_gpio_disp_b1_00_enet_1g_rx_en>, + pinmux = <&iomuxc_gpio_disp_b1_00_enet_1g_rx_en>, <&iomuxc_gpio_disp_b1_01_enet_1g_rx_er>; drive-strength = "high"; bias-pull-down; @@ -27,9 +26,7 @@ input-enable; }; group2 { - pinmux = <&iomuxc_gpio_emc_b2_19_enet_1g_mdc>, - <&iomuxc_gpio_emc_b2_20_enet_1g_mdio>, - <&iomuxc_gpio_disp_b1_09_enet_1g_tdata00>, + pinmux = <&iomuxc_gpio_disp_b1_09_enet_1g_tdata00>, <&iomuxc_gpio_disp_b1_08_enet_1g_tdata01>, <&iomuxc_gpio_disp_b1_10_enet_1g_tx_en>; drive-strength = "high"; @@ -44,6 +41,24 @@ }; }; + pinmux_enet1g_mdio: pinmux_enet1g_mdio { + group0 { + pinmux = <&iomuxc_gpio_emc_b2_19_enet_1g_mdc>, + <&iomuxc_gpio_emc_b2_20_enet_1g_mdio>; + drive-strength = "high"; + slew-rate = "fast"; + }; + group1 { + pinmux = <&iomuxc_gpio_disp_b2_09_gpio_mux5_io10>; + drive-strength = "high"; + bias-pull-down; + slew-rate = "fast"; + }; + }; + + pinmux_enet1g_ptp: pinmux_enet1g_ptp { + }; + pinmux_flexcan1: pinmux_flexcan1 { group0 { pinmux = <&iomuxc_gpio_ad_07_can1_rx>, @@ -156,6 +171,14 @@ }; }; + pinmux_qtmr_pwm_buzzer: pinmux_qtmr_pwm_buzzer { + group0 { + pinmux = <&iomuxc_gpio_emc_b2_09_qtimer1_timer0>; + drive-strength = "high"; + slew-rate = "fast"; + }; + }; + pinmux_lpadc1: pinmux_lpadc1 { group0 { pinmux = <&iomuxc_gpio_ad_10_adc1_ch2a>; @@ -344,20 +367,9 @@ <&iomuxc_gpio_sd_b1_02_usdhc1_data0>, <&iomuxc_gpio_sd_b1_03_usdhc1_data1>, <&iomuxc_gpio_sd_b1_04_usdhc1_data2>, - <&iomuxc_gpio_sd_b1_05_usdhc1_data3>; + <&iomuxc_gpio_sd_b1_05_usdhc1_data3>, + <&iomuxc_gpio_sd_b1_01_usdhc1_clk>; bias-pull-up; - drive-strength = "high"; - slew-rate = "fast"; - input-enable; - }; - group1 { - pinmux = <&iomuxc_gpio_sd_b1_01_usdhc1_clk>; - drive-strength = "high"; - slew-rate = "fast"; - }; - group2 { - pinmux = <&iomuxc_gpio_ad_32_usdhc1_cd_b>; - bias-pull-down; input-enable; }; }; diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi b/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi index 075dc1860dc36..ac8e6a1869461 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi +++ b/boards/nxp/vmu_rt1170/vmu_rt1170.dtsi @@ -5,6 +5,7 @@ */ #include "vmu_rt1170-pinctrl.dtsi" +#include / { aliases { @@ -97,8 +98,26 @@ status = "okay"; }; -&enet1g { - pinctrl-0 = <&pinmux_enet>; +&enet1g_mac { + pinctrl-0 = <&pinmux_enet1g>; + pinctrl-names = "default"; + phy-handle = <&enet1g_phy>; + phy-connection-type = "rmii"; + zephyr,random-mac-address; +}; + +&enet1g_mdio { + pinctrl-0 = <&pinmux_enet1g_mdio>; + pinctrl-names = "default"; + enet1g_phy: phy@1 { + compatible = "nxp,tja1103"; + reg = <1>; + master-slave = "master"; + }; +}; + +&enet1g_ptp_clock { + pinctrl-0 = <&pinmux_enet1g_ptp>; pinctrl-names = "default"; }; @@ -177,7 +196,7 @@ ahb-prefetch; ahb-read-addr-opt; rx-clock-source = <1>; - reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(16)>; + reg = <0x400cc000 0x4000>, <0x30000000 DT_SIZE_M(64)>; mx25um51345g: mx25um51345g@0 { compatible = "nxp,imx-flexspi-mx25um51345g"; /* MX25UM51245G is 64MB, 512MBit flash part */ @@ -193,22 +212,24 @@ compatible = "fixed-partitions"; #address-cells = <1>; #size-cells = <1>; - boot_partition: partition@0 { label = "mcuboot"; reg = <0x00000000 DT_SIZE_K(128)>; }; + /* The MCUBoot swap-move algorithm uses the last 14 sectors + * of the primary slot0 for swap status and move. + */ slot0_partition: partition@20000 { label = "image-0"; - reg = <0x00020000 DT_SIZE_K(3076)>; + reg = <0x00020000 (DT_SIZE_M(3) + DT_SIZE_K(56))>; }; - slot1_partition: partition@321000 { + slot1_partition: partition@32E000 { label = "image-1"; - reg = <0x00321000 DT_SIZE_K(3072)>; + reg = <0x0032E000 DT_SIZE_M(3)>; }; - storage_partition: partition@621000 { + storage_partition: partition@62E000 { label = "storage"; - reg = <0x00621000 DT_SIZE_M(57)>; + reg = <0x0062E000 (DT_SIZE_M(58) - DT_SIZE_K(184))>; }; }; }; diff --git a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts index 564164c5ae414..d4e9788faca05 100644 --- a/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts +++ b/boards/nxp/vmu_rt1170/vmu_rt1170_mimxrt1176_cm7.dts @@ -21,6 +21,7 @@ watchdog0 = &wdog1; sdhc0 = &usdhc1; sw0 = &arming_button; + pwm-led0 = &buzzer0; }; chosen { @@ -121,6 +122,13 @@ regulator-always-on; status = "okay"; }; + + pwm_shell: pwm_shell { + compatible = "pwm-leds"; + buzzer0: buzzer0 { + pwms = <&qtmr1 0 PWM_HZ(50) PWM_POLARITY_NORMAL>; + }; + }; }; @@ -170,13 +178,46 @@ current-speed = <115200>; }; +&lpuart6 { + status = "okay"; + single-wire; + rx-invert; + + sbus { + compatible = "futaba,sbus"; + right_stick_x { + channel = <1>; + type = ; + zephyr,code = ; + }; + right_stick_y { + channel = <2>; + type = ; + zephyr,code = ; + }; + left_stick_y { + channel = <3>; + type = ; + zephyr,code = ; + }; + left_stick_x { + channel = <4>; + type = ; + zephyr,code = ; + }; + kill_switch { + channel = <5>; + type = ; + zephyr,code = ; + }; + }; +}; + &flexcan1 { status = "okay"; pinctrl-0 = <&pinmux_flexcan1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; @@ -186,8 +227,6 @@ status = "okay"; pinctrl-0 = <&pinmux_flexcan2>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; @@ -197,8 +236,6 @@ status = "okay"; pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <5000000>; }; @@ -398,10 +435,20 @@ capture-channel = <1>; }; +&qtmr1 { + compatible = "nxp,qtmr-pwm"; + pinctrl-0 = <&pinmux_qtmr_pwm_buzzer>; + pinctrl-names = "default"; + #pwm-cells = <3>; + prescaler = <128>; + status = "okay"; +}; + &usdhc1 { status = "okay"; no-1-8-v; pwr-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio3 31 (GPIO_ACTIVE_LOW | GPIO_PULL_DOWN)>; sdmmc { compatible = "zephyr,sdmmc-disk"; status = "okay"; @@ -434,7 +481,18 @@ &enet1g { status = "okay"; - int-gpios = <&gpio5 10 GPIO_ACTIVE_HIGH>; +}; + +&enet1g_mac { + status = "okay"; +}; + +&enet1g_mdio { + status = "okay"; + enet1g_phy: phy@1 { + status = "okay"; + int-gpios = <&gpio5 10 GPIO_ACTIVE_HIGH>; + }; }; zephyr_udc0: &usb1 { diff --git a/boards/olimex/lora_stm32wl_devkit/olimex_lora_stm32wl_devkit_D.yaml b/boards/olimex/lora_stm32wl_devkit/olimex_lora_stm32wl_devkit_D.yaml index 29559d1e262dd..ead08879d1b7d 100644 --- a/boards/olimex/lora_stm32wl_devkit/olimex_lora_stm32wl_devkit_D.yaml +++ b/boards/olimex/lora_stm32wl_devkit/olimex_lora_stm32wl_devkit_D.yaml @@ -1,5 +1,5 @@ identifier: olimex_lora_stm32wl_devkit@D -name: Olimex LoRa STM32WL DevKit +name: Olimex LoRa STM32WL DevKit (rev. D) type: mcu arch: arm toolchain: diff --git a/boards/olimex/olimex_esp32_evb/Kconfig.defconfig b/boards/olimex/olimex_esp32_evb/Kconfig.defconfig index c15264f5538df..e326963903832 100644 --- a/boards/olimex/olimex_esp32_evb/Kconfig.defconfig +++ b/boards/olimex/olimex_esp32_evb/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_OLIMEX_ESP32_EVB_ESP32_PROCPU if BOARD_OLIMEX_ESP32_EVB_ESP32_APPCPU diff --git a/boards/olimex/olimex_esp32_evb/doc/index.rst b/boards/olimex/olimex_esp32_evb/doc/index.rst index bcfc8a3c34643..c5457d5612c7a 100644 --- a/boards/olimex/olimex_esp32_evb/doc/index.rst +++ b/boards/olimex/olimex_esp32_evb/doc/index.rst @@ -84,9 +84,9 @@ features: +-----------+------------+-------------------------------------+ The default configuration can be found in -:zephyr_file:`boards/olimex/olimex_esp32_evb/olimex_esp32_evb_esp32_appcpu_defconfig` +:zephyr_file:`boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu_defconfig` and -:zephyr_file:`boards/olimex/olimex_esp32_evb/olimex_esp32_evb_esp32_procpu_defconfig` +:zephyr_file:`boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu_defconfig` Other hardware features are not currently supported by the port. diff --git a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.dts b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.dts index c52b029ea552a..ae7a2e1e7f653 100644 --- a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.dts +++ b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.yaml b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.yaml index 9e81868de2181..fa3b6417b90f1 100644 --- a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.yaml +++ b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_appcpu.yaml @@ -1,5 +1,5 @@ identifier: olimex_esp32_evb/esp32/appcpu -name: Olimex ESP32-EVB +name: Olimex ESP32-EVB APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts index 11747f1a7b6e9..c239263ea537b 100644 --- a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts +++ b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.dts @@ -20,6 +20,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -53,14 +54,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - uext_serial: &uart1 {}; uext_i2c: &i2c0 {}; uext_spi: &spi2 {}; @@ -100,7 +93,6 @@ uext_spi: &spi2 {}; status = "okay"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; can-transceiver { max-bitrate = <1000000>; @@ -173,3 +165,7 @@ uext_spi: &spi2 {}; }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.yaml b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.yaml index f4929c52b4204..c897a54621493 100644 --- a/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.yaml +++ b/boards/olimex/olimex_esp32_evb/olimex_esp32_evb_procpu.yaml @@ -1,5 +1,5 @@ identifier: olimex_esp32_evb/esp32/procpu -name: Olimex ESP32-EVB +name: Olimex ESP32-EVB PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/olimex/olimexino_stm32/olimexino_stm32.dts b/boards/olimex/olimexino_stm32/olimexino_stm32.dts index 931012548fd6a..8c3a3b1491a10 100644 --- a/boards/olimex/olimexino_stm32/olimexino_stm32.dts +++ b/boards/olimex/olimexino_stm32/olimexino_stm32.dts @@ -166,7 +166,6 @@ zephyr_udc0: &usb { &can1 { pinctrl-0 = <&can_rx_remap1_pb8 &can_tx_remap1_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; phys = <&transceiver0>; status = "okay"; }; diff --git a/boards/olimex/olimexino_stm32/olimexino_stm32.yaml b/boards/olimex/olimexino_stm32/olimexino_stm32.yaml index b4cf8b26bfbf1..266ff00218497 100644 --- a/boards/olimex/olimexino_stm32/olimexino_stm32.yaml +++ b/boards/olimex/olimexino_stm32/olimexino_stm32.yaml @@ -11,7 +11,6 @@ supported: - gpio - i2c - pwm - - sdhc - spi - usb_device - watchdog diff --git a/boards/olimex/stm32_e407/support/openocd.cfg b/boards/olimex/stm32_e407/support/openocd.cfg index d97149f96918b..c416c6958c01d 100644 --- a/boards/olimex/stm32_e407/support/openocd.cfg +++ b/boards/olimex/stm32_e407/support/openocd.cfg @@ -1,13 +1,12 @@ -source [find interface/stlink.cfg] +source [find interface/ftdi/olimex-arm-usb-tiny-h.cfg] +# source [find interface/stlink.cfg] set WORKAREASIZE 0x10000 -transport select hla_swd - source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/olimex/stm32_h103/support/openocd_olimex_jtag.cfg b/boards/olimex/stm32_h103/support/openocd_olimex_jtag.cfg index e953fd32a05c8..3020364ce9c0e 100644 --- a/boards/olimex/stm32_h103/support/openocd_olimex_jtag.cfg +++ b/boards/olimex/stm32_h103/support/openocd_olimex_jtag.cfg @@ -4,8 +4,8 @@ transport select jtag source [find board/olimex_stm32_h103.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/olimex/stm32_h405/support/openocd.cfg b/boards/olimex/stm32_h405/support/openocd.cfg index 1f577d2c243e8..427feadd2c193 100644 --- a/boards/olimex/stm32_h405/support/openocd.cfg +++ b/boards/olimex/stm32_h405/support/openocd.cfg @@ -6,8 +6,8 @@ transport select hla_swd source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/olimex/stm32_h407/support/openocd.cfg b/boards/olimex/stm32_h407/support/openocd.cfg index c48bab3646b36..a9db97fb87f5f 100644 --- a/boards/olimex/stm32_h407/support/openocd.cfg +++ b/boards/olimex/stm32_h407/support/openocd.cfg @@ -6,8 +6,8 @@ transport select jtag source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/olimex/stm32_p405/olimex_stm32_p405.dts b/boards/olimex/stm32_p405/olimex_stm32_p405.dts index 866a8318f3e8f..776bf4a3827c5 100644 --- a/boards/olimex/stm32_p405/olimex_stm32_p405.dts +++ b/boards/olimex/stm32_p405/olimex_stm32_p405.dts @@ -87,7 +87,6 @@ &can1 { pinctrl-0 = <&can1_rx_pb8 &can1_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; can-transceiver { diff --git a/boards/olimex/stm32_p405/support/openocd.cfg b/boards/olimex/stm32_p405/support/openocd.cfg index d97149f96918b..269578295d4f7 100644 --- a/boards/olimex/stm32_p405/support/openocd.cfg +++ b/boards/olimex/stm32_p405/support/openocd.cfg @@ -6,8 +6,8 @@ transport select hla_swd source [find target/stm32f4x.cfg] -adapter_khz 1000 -adapter_nsrst_delay 100 +adapter speed 1000 +adapter srst delay 100 jtag_ntrst_delay 100 reset_config srst_only srst_nogate diff --git a/boards/openisa/rv32m1_vega/rv32m1_vega_openisa_rv32m1_ri5cy.dts b/boards/openisa/rv32m1_vega/rv32m1_vega_openisa_rv32m1_ri5cy.dts index b21e9b960ec1a..ceba94b4794ae 100644 --- a/boards/openisa/rv32m1_vega/rv32m1_vega_openisa_rv32m1_ri5cy.dts +++ b/boards/openisa/rv32m1_vega/rv32m1_vega_openisa_rv32m1_ri5cy.dts @@ -19,11 +19,12 @@ zephyr,shell-uart = &lpuart0; zephyr,uart-pipe = &lpuart0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &bt_hci_controller; }; +}; - aliases { - spi-flash0 = &mx25r32; - }; +&bt_hci_controller { + status = "okay"; }; &m4_flash { diff --git a/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg b/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg index 11f5deb062da2..08a4880dc049c 100644 --- a/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg +++ b/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_ri5cy.cfg @@ -3,7 +3,7 @@ set _WORKAREASIZE 0x2000 -adapter_khz 1000 +adapter speed 1000 interface jlink transport select jtag diff --git a/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_zero_riscy.cfg b/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_zero_riscy.cfg index 491dc56a54dfa..71d23a125d3da 100644 --- a/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_zero_riscy.cfg +++ b/boards/openisa/rv32m1_vega/support/openocd_rv32m1_vega_zero_riscy.cfg @@ -3,7 +3,7 @@ set _WORKAREASIZE 0x2000 -adapter_khz 1000 +adapter speed 1000 interface jlink transport select jtag diff --git a/boards/others/black_f407ve/black_f407ve.dts b/boards/others/black_f407ve/black_f407ve.dts index 6a76109ce8444..2411e0e5a945c 100644 --- a/boards/others/black_f407ve/black_f407ve.dts +++ b/boards/others/black_f407ve/black_f407ve.dts @@ -57,7 +57,6 @@ led0 = &green_led_1; led1 = &green_led_2; sw0 = &user_button_UP; - spi-flash0 = &w25q16cv; }; }; @@ -126,14 +125,12 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "disabled"; }; &can2 { pinctrl-0 = <&can2_rx_pb12 &can2_tx_pb13>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/others/black_f407zg_pro/black_f407zg_pro.dts b/boards/others/black_f407zg_pro/black_f407zg_pro.dts index 45a311c50307d..2d96ce6a4fbb3 100644 --- a/boards/others/black_f407zg_pro/black_f407zg_pro.dts +++ b/boards/others/black_f407zg_pro/black_f407zg_pro.dts @@ -125,14 +125,12 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "disabled"; }; &can2 { pinctrl-0 = <&can2_rx_pb12 &can2_tx_pb13>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/others/icev_wireless/Kconfig.defconfig b/boards/others/icev_wireless/Kconfig.defconfig index 96ed16249d4ae..b7c82093375ff 100644 --- a/boards/others/icev_wireless/Kconfig.defconfig +++ b/boards/others/icev_wireless/Kconfig.defconfig @@ -7,7 +7,3 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 51200 if WIFI default 40960 if BT default 4096 - -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice diff --git a/boards/others/icev_wireless/icev_wireless.dts b/boards/others/icev_wireless/icev_wireless.dts index 8ed474200e0bc..6209aeac7c21e 100644 --- a/boards/others/icev_wireless/icev_wireless.dts +++ b/boards/others/icev_wireless/icev_wireless.dts @@ -20,6 +20,7 @@ zephyr,shell-uart = &usb_serial; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -47,10 +48,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { current-speed = <115200>; pinctrl-0 = <&uart0_default>; @@ -130,3 +127,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/others/icev_wireless/support/openocd.cfg b/boards/others/icev_wireless/support/openocd.cfg index 02754ff2a73c1..7421637880c78 100644 --- a/boards/others/icev_wireless/support/openocd.cfg +++ b/boards/others/icev_wireless/support/openocd.cfg @@ -3,4 +3,4 @@ set ESP_RTOS none source [find interface/esp_usb_jtag.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/others/serpente/doc/index.rst b/boards/others/serpente/doc/index.rst index 4b6bf5e7390c3..c624c5ad0626e 100644 --- a/boards/others/serpente/doc/index.rst +++ b/boards/others/serpente/doc/index.rst @@ -56,7 +56,7 @@ following hardware features: Other hardware features are not currently supported by Zephyr. The default configuration can be found in the Kconfig file -:zephyr_file:`boards/arturo182/serpente/serpente_defconfig`. +:zephyr_file:`boards/others/serpente/serpente_defconfig`. Connections and IOs =================== diff --git a/boards/others/stm32_min_dev/stm32_min_dev_black.yaml b/boards/others/stm32_min_dev/stm32_min_dev_black.yaml index 0740dc17fafb3..543b58db8375e 100644 --- a/boards/others/stm32_min_dev/stm32_min_dev_black.yaml +++ b/boards/others/stm32_min_dev/stm32_min_dev_black.yaml @@ -1,5 +1,5 @@ identifier: stm32_min_dev@black -name: STM32 Minimum Development Board +name: STM32 Minimum Development Board (black) type: mcu arch: arm toolchain: diff --git a/boards/others/stm32_min_dev/stm32_min_dev_blue.yaml b/boards/others/stm32_min_dev/stm32_min_dev_blue.yaml index 8249d6f971992..3a7f4ad73082c 100644 --- a/boards/others/stm32_min_dev/stm32_min_dev_blue.yaml +++ b/boards/others/stm32_min_dev/stm32_min_dev_blue.yaml @@ -1,5 +1,5 @@ identifier: stm32_min_dev@blue -name: STM32 Minimum Development Board +name: STM32 Minimum Development Board (blue) type: mcu arch: arm toolchain: diff --git a/boards/panasonic/pan1770_evb/pan1770_evb.yaml b/boards/panasonic/pan1770_evb/pan1770_evb.yaml index d19c0f4e33a5c..35ada5617cc54 100644 --- a/boards/panasonic/pan1770_evb/pan1770_evb.yaml +++ b/boards/panasonic/pan1770_evb/pan1770_evb.yaml @@ -25,7 +25,6 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/panasonic/pan1780_evb/pan1780_evb.yaml b/boards/panasonic/pan1780_evb/pan1780_evb.yaml index 9f29b96007a7c..8833f01c3a233 100644 --- a/boards/panasonic/pan1780_evb/pan1780_evb.yaml +++ b/boards/panasonic/pan1780_evb/pan1780_evb.yaml @@ -25,7 +25,6 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/panasonic/pan1783/Kconfig.defconfig b/boards/panasonic/pan1783/Kconfig.defconfig index ec08e860bbde5..6c70d441e9150 100644 --- a/boards/panasonic/pan1783/Kconfig.defconfig +++ b/boards/panasonic/pan1783/Kconfig.defconfig @@ -8,9 +8,8 @@ config MBOX_NRFX_IPC if SOC_NRF5340_CPUAPP_QKAA -choice BT_HCI_BUS_TYPE - default BT_HCI_IPC if BT -endchoice +config BT_HCI_IPC + default y if BT config HEAP_MEM_POOL_ADD_SIZE_BOARD int diff --git a/boards/panasonic/pan1783/pan1783_evb_nrf5340_cpuapp.yaml b/boards/panasonic/pan1783/pan1783_evb_nrf5340_cpuapp.yaml index 401745b33336b..771055b508a31 100644 --- a/boards/panasonic/pan1783/pan1783_evb_nrf5340_cpuapp.yaml +++ b/boards/panasonic/pan1783/pan1783_evb_nrf5340_cpuapp.yaml @@ -14,7 +14,6 @@ supported: - i2s - pwm - watchdog - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/panasonic/pan1783/pan1783_nrf5340_cpuapp_common.dtsi b/boards/panasonic/pan1783/pan1783_nrf5340_cpuapp_common.dtsi index fae7f566fccfe..c1d4c5739e256 100644 --- a/boards/panasonic/pan1783/pan1783_nrf5340_cpuapp_common.dtsi +++ b/boards/panasonic/pan1783/pan1783_nrf5340_cpuapp_common.dtsi @@ -14,7 +14,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-ipc = &ipc0; + zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; }; @@ -156,7 +156,6 @@ mcuboot-button0 = &evb_sw1; mcuboot-led0 = &evb_led1; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/panasonic/pan1783/pan1783_nrf5340_cpunet_reset.c b/boards/panasonic/pan1783/pan1783_nrf5340_cpunet_reset.c index cd8281cb2bf25..bf0626ce30b2e 100644 --- a/boards/panasonic/pan1783/pan1783_nrf5340_cpunet_reset.c +++ b/boards/panasonic/pan1783/pan1783_nrf5340_cpunet_reset.c @@ -9,7 +9,7 @@ #include #include -#include +#include #if defined(CONFIG_BOARD_PAN1783_EVB_NRF5340_CPUAPP) LOG_MODULE_REGISTER(pan1783_evb_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -42,7 +42,7 @@ static int remoteproc_mgr_boot(void) remoteproc_mgr_config(); /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); diff --git a/boards/panasonic/pan1783/pan1783a_evb_nrf5340_cpuapp.yaml b/boards/panasonic/pan1783/pan1783a_evb_nrf5340_cpuapp.yaml index f5a789788bfc2..3d9bea542288a 100644 --- a/boards/panasonic/pan1783/pan1783a_evb_nrf5340_cpuapp.yaml +++ b/boards/panasonic/pan1783/pan1783a_evb_nrf5340_cpuapp.yaml @@ -14,7 +14,6 @@ supported: - i2s - pwm - watchdog - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/panasonic/pan1783/pan1783a_pa_evb_nrf5340_cpuapp.yaml b/boards/panasonic/pan1783/pan1783a_pa_evb_nrf5340_cpuapp.yaml index dc5600a999a57..d9936750286a2 100644 --- a/boards/panasonic/pan1783/pan1783a_pa_evb_nrf5340_cpuapp.yaml +++ b/boards/panasonic/pan1783/pan1783a_pa_evb_nrf5340_cpuapp.yaml @@ -14,7 +14,6 @@ supported: - i2s - pwm - watchdog - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/particle/argon/dts/mesh_feather.dtsi b/boards/particle/argon/dts/mesh_feather.dtsi index ee3c4340d5bbc..889fc75f83517 100644 --- a/boards/particle/argon/dts/mesh_feather.dtsi +++ b/boards/particle/argon/dts/mesh_feather.dtsi @@ -20,7 +20,6 @@ led3 = &status_blue; sw0 = &mode_button; sw1 = &reset_button; - spi-flash0 = &mx25l32; }; chosen { diff --git a/boards/particle/boron/dts/mesh_feather.dtsi b/boards/particle/boron/dts/mesh_feather.dtsi index 0005ca547ff26..13b7e238230db 100644 --- a/boards/particle/boron/dts/mesh_feather.dtsi +++ b/boards/particle/boron/dts/mesh_feather.dtsi @@ -20,7 +20,6 @@ led3 = &status_blue; sw0 = &mode_button; sw1 = &reset_button; - spi-flash0 = &mx25l32; }; chosen { diff --git a/boards/particle/xenon/particle_xenon.dts b/boards/particle/xenon/particle_xenon.dts index 2d64ba119b299..c297014ff363f 100644 --- a/boards/particle/xenon/particle_xenon.dts +++ b/boards/particle/xenon/particle_xenon.dts @@ -29,7 +29,6 @@ aliases { watchdog0 = &wdt0; - spi-flash0 = &mx25l32; }; }; diff --git a/boards/phytec/index.rst b/boards/phytec/index.rst index 0bde22965df24..bb484358db184 100644 --- a/boards/phytec/index.rst +++ b/boards/phytec/index.rst @@ -1,7 +1,7 @@ .. _boards-phytec: -PHYTEC Messtechnik GmbH -####################### +PHYTEC +###### .. toctree:: :maxdepth: 1 diff --git a/boards/phytec/mimx8mm_phyboard_polis/Kconfig.defconfig b/boards/phytec/mimx8mm_phyboard_polis/Kconfig.defconfig deleted file mode 100644 index ec8c8486351c7..0000000000000 --- a/boards/phytec/mimx8mm_phyboard_polis/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# MIMX8MM_PHYBOARD_POLIS board defconfig -# -# Copyright (c) 2022 PHYTEC Messtechnik GmbH -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_MIMX8MM_PHYBOARD_POLIS - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_MIMX8MM_PHYBOARD_POLIS diff --git a/boards/phytec/mimx8mp_phyboard_pollux/Kconfig.defconfig b/boards/phytec/mimx8mp_phyboard_pollux/Kconfig.defconfig deleted file mode 100644 index e860faf97cfb0..0000000000000 --- a/boards/phytec/mimx8mp_phyboard_pollux/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# PhyBOARD Pollux (i.MX8MP) defconfig - -# Copyright (c) 2022 PHYTEC Messtechnik GmbH -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_MIMX8MP_PHYBOARD_POLLUX - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_MIMX8MP_PHYBOARD_POLLUX diff --git a/boards/phytec/phyboard_lyra/board.cmake b/boards/phytec/phyboard_lyra/board.cmake new file mode 100644 index 0000000000000..5f42441db6941 --- /dev/null +++ b/boards/phytec/phyboard_lyra/board.cmake @@ -0,0 +1,10 @@ +# PHYTEC phyBOARD-Lyra AM62x M4/A53 +# +# Copyright (c) 2024, PHYTEC Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_SOC_AM6234_M4) + board_runner_args(openocd "--no-init" "--no-halt" "--no-targets" "--gdb-client-port=3339") + include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +endif() diff --git a/boards/phytec/phyboard_lyra/doc/phyboard_lyra_am62xx_m4.rst b/boards/phytec/phyboard_lyra/doc/phyboard_lyra_am62xx_m4.rst index a8765c0fcc379..0736292446cdd 100644 --- a/boards/phytec/phyboard_lyra/doc/phyboard_lyra_am62xx_m4.rst +++ b/boards/phytec/phyboard_lyra/doc/phyboard_lyra_am62xx_m4.rst @@ -131,6 +131,21 @@ The board should boot into Linux and the binary will run and print Hello world t port. +Debugging +********* + +The board is equipped with an XDS110 JTAG debugger. To debug a binary, utilize the `debug` build target: + +.. zephyr-app-commands:: + :zephyr-app: + :board: phyboard_lyra/am6234/m4 + :maybe-skip-config: + :goals: debug + +.. hint:: + To utilize this feature, you'll need OpenOCD version 0.12 or higher. Due to the possibility of + older versions being available in package feeds, it's advisable to `build OpenOCD from source`_. + .. _PHYTEC AM62x Product Page: https://www.phytec.com/product/phycore-am62x/ @@ -143,3 +158,6 @@ port. .. _phyBOARD SD Card Booting Essentials: https://docs.phytec.com/projects/yocto-phycore-am62x/en/bsp-yocto-ampliphy-am62x-pd23.2.1/bootingessentials/sdcard.html + +.. _build OpenOCD from source: + https://docs.u-boot.org/en/latest/board/ti/k3.html#building-openocd-from-source diff --git a/boards/phytec/phyboard_lyra/support/openocd.cfg b/boards/phytec/phyboard_lyra/support/openocd.cfg new file mode 100644 index 0000000000000..39eed02c40156 --- /dev/null +++ b/boards/phytec/phyboard_lyra/support/openocd.cfg @@ -0,0 +1,7 @@ +# PHYTEC phyBOARD-Lyra AM62x M4/A53 +# +# Copyright (c) 2024, PHYTEC Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +source [find board/ti_am625evm.cfg] diff --git a/boards/phytec/reel_board/reel_board.dts b/boards/phytec/reel_board/reel_board.dts index c20cf01c0ef00..59c671bc121bc 100644 --- a/boards/phytec/reel_board/reel_board.dts +++ b/boards/phytec/reel_board/reel_board.dts @@ -46,6 +46,54 @@ pwm-led3 = &back_pwm_led; watchdog0 = &wdt0; }; + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi1>; + reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + + ssd16xx: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0213b1", "solomon,ssd1673"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <122>; + busy-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + + full { + gdv = [10 0a]; + sdv = [19]; + vcom = <0xa8>; + border-waveform = <0x71>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 22 55 AA 55 AA 55 AA 11 + 00 00 00 00 00 00 00 00 + 1E 1E 1E 1E 1E 1E 1E 1E + 01 00 00 00 00 + ]; + }; + + partial { + gdv = [10 0a]; + sdv = [19]; + vcom = <0xa8>; + border-waveform = <0x71>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 18 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 0F 01 00 00 00 00 00 00 + 00 00 00 00 00 + ]; + }; + }; + }; }; &spi1 { @@ -56,44 +104,4 @@ pinctrl-0 = <&spi1_default>; pinctrl-1 = <&spi1_sleep>; pinctrl-names = "default", "sleep"; - ssd16xx: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0213b1", "solomon,ssd1673"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <250>; - height = <122>; - reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; - dc-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; - busy-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; - - full { - gdv = [10 0a]; - sdv = [19]; - vcom = <0xa8>; - border-waveform = <0x71>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 22 55 AA 55 AA 55 AA 11 - 00 00 00 00 00 00 00 00 - 1E 1E 1E 1E 1E 1E 1E 1E - 01 00 00 00 00 - ]; - }; - - partial { - gdv = [10 0a]; - sdv = [19]; - vcom = <0xa8>; - border-waveform = <0x71>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 18 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 0F 01 00 00 00 00 00 00 - 00 00 00 00 00 - ]; - }; - }; }; diff --git a/boards/phytec/reel_board/reel_board_1.yaml b/boards/phytec/reel_board/reel_board_1.yaml index 07b5087b6c6f5..b357f545511b1 100644 --- a/boards/phytec/reel_board/reel_board_1.yaml +++ b/boards/phytec/reel_board/reel_board_1.yaml @@ -13,7 +13,6 @@ supported: - spi - gpio - usb_device - - usb_cdc - ble - pwm - arduino_i2c diff --git a/boards/phytec/reel_board/reel_board_nrf52840_2.overlay b/boards/phytec/reel_board/reel_board_nrf52840_2.overlay index b6652cbf4e8c1..1e7c0ff529dc0 100644 --- a/boards/phytec/reel_board/reel_board_nrf52840_2.overlay +++ b/boards/phytec/reel_board/reel_board_nrf52840_2.overlay @@ -27,6 +27,91 @@ aliases { watchdog0 = &wdt0; }; + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi1>; + reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 16 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + + ssd16xx: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0213b72", "solomon,ssd1675a"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <122>; + busy-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; + + full { + gdv = [15]; + sdv = [41 a8 32]; + vcom = <0x26>; + border-waveform = <0x03>; + dummy-line = <0x30>; + gate-line-width = <0x0a>; + lut = [ + /* + * Waveform Composition + * + * There are 7 Voltage Source (VS) Level groups + * n = {0,1,2...6}, each group contains + * 4 phases x = {A,B,C,D}. + * 2 bits represent the voltage in a phase: + * 00 – VSS, 01 – VSH1, 10 – VSL, 11 - VSH2 + * + * For example 0x80 represents sequence VSL-VSS-VSS-VSS, + */ + 80 60 40 00 00 00 00 /* LUT0: BB: VS 0..6 */ + 10 60 20 00 00 00 00 /* LUT1: BW: VS 0..6 */ + 80 60 40 00 00 00 00 /* LUT2: WB: VS 0..6 */ + 10 60 20 00 00 00 00 /* LUT3: WW: VS 0..6 */ + 00 00 00 00 00 00 00 /* LUT4: VCOM: VS 0..6 */ + /* + * TPnx determines the length of each phase, + * and RPn repeat count of a sequence. + * TPnA, TPnB, TPnC, TPnD, RPn + * + * For example TP0A=3, TP0B=3, and RP0=2: + * VS sequence : VSL-VSS-VSS-VSS + * number of Gate Pulses (length) : 3 3 0 0 + * repeat count : 2 + */ + 03 03 00 00 02 /* TP0A TP0B TP0C TP0D RP0 */ + 09 09 00 00 02 /* TP1A TP1B TP1C TP1D RP1 */ + 03 03 00 00 02 /* TP2A TP2B TP2C TP2D RP2 */ + 00 00 00 00 00 /* TP3A TP3B TP3C TP3D RP3 */ + 00 00 00 00 00 /* TP4A TP4B TP4C TP4D RP4 */ + 00 00 00 00 00 /* TP5A TP5B TP5C TP5D RP5 */ + 00 00 00 00 00 /* TP6A TP6B TP6C TP6D RP6 */ + ]; + }; + + partial { + gdv = [15]; + sdv = [41 a8 32]; + vcom = <0x26>; + border-waveform = <0x01>; + dummy-line = <0x30>; + gate-line-width = <0x0a>; + lut = [ + 00 00 00 00 00 00 00 /* LUT0: BB: VS0..6 */ + 80 00 00 00 00 00 00 /* LUT1: BW: VS0..6 */ + 40 00 00 00 00 00 00 /* LUT2: WB: VS0..6 */ + 80 00 00 00 00 00 00 /* LUT3: WW: VS0..6 */ + 00 00 00 00 00 00 00 /* LUT4: VCOM: VS0..6 */ + 0A 00 00 00 04 /* TP0A TP0B TP0C TP0D RP0 */ + 00 00 00 00 00 /* TP1A TP1B TP1C TP1D RP1 */ + 00 00 00 00 00 /* TP2A TP2B TP2C TP2D RP2 */ + 00 00 00 00 00 /* TP3A TP3B TP3C TP3D RP3 */ + 00 00 00 00 00 /* TP4A TP4B TP4C TP4D RP4 */ + 00 00 00 00 00 /* TP5A TP5B TP5C TP5D RP5 */ + 00 00 00 00 00 /* TP6A TP6B TP6C TP6D RP6 */ + ]; + }; + }; + }; }; &spi1 { @@ -37,81 +122,4 @@ pinctrl-0 = <&spi1_default>; pinctrl-1 = <&spi1_sleep>; pinctrl-names = "default", "sleep"; - ssd16xx: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0213b72", "solomon,ssd1675a"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <250>; - height = <122>; - reset-gpios = <&gpio0 15 GPIO_ACTIVE_LOW>; - dc-gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; - busy-gpios = <&gpio0 14 GPIO_ACTIVE_HIGH>; - - full { - gdv = [15]; - sdv = [41 a8 32]; - vcom = <0x26>; - border-waveform = <0x03>; - dummy-line = <0x30>; - gate-line-width = <0x0a>; - lut = [ - /* - * Waveform Composition - * - * There are 7 Voltage Source (VS) Level groups - * n = {0,1,2...6}, each group contains - * 4 phases x = {A,B,C,D}. - * 2 bits represent the voltage in a phase: - * 00 – VSS, 01 – VSH1, 10 – VSL, 11 - VSH2 - * - * For example 0x80 represents sequence VSL-VSS-VSS-VSS, - */ - 80 60 40 00 00 00 00 /* LUT0: BB: VS 0..6 */ - 10 60 20 00 00 00 00 /* LUT1: BW: VS 0..6 */ - 80 60 40 00 00 00 00 /* LUT2: WB: VS 0..6 */ - 10 60 20 00 00 00 00 /* LUT3: WW: VS 0..6 */ - 00 00 00 00 00 00 00 /* LUT4: VCOM: VS 0..6 */ - /* - * TPnx determines the length of each phase, - * and RPn repeat count of a sequence. - * TPnA, TPnB, TPnC, TPnD, RPn - * - * For example TP0A=3, TP0B=3, and RP0=2: - * VS sequence : VSL-VSS-VSS-VSS - * number of Gate Pulses (length) : 3 3 0 0 - * repeat count : 2 - */ - 03 03 00 00 02 /* TP0A TP0B TP0C TP0D RP0 */ - 09 09 00 00 02 /* TP1A TP1B TP1C TP1D RP1 */ - 03 03 00 00 02 /* TP2A TP2B TP2C TP2D RP2 */ - 00 00 00 00 00 /* TP3A TP3B TP3C TP3D RP3 */ - 00 00 00 00 00 /* TP4A TP4B TP4C TP4D RP4 */ - 00 00 00 00 00 /* TP5A TP5B TP5C TP5D RP5 */ - 00 00 00 00 00 /* TP6A TP6B TP6C TP6D RP6 */ - ]; - }; - - partial { - gdv = [15]; - sdv = [41 a8 32]; - vcom = <0x26>; - border-waveform = <0x01>; - dummy-line = <0x30>; - gate-line-width = <0x0a>; - lut = [ - 00 00 00 00 00 00 00 /* LUT0: BB: VS0..6 */ - 80 00 00 00 00 00 00 /* LUT1: BW: VS0..6 */ - 40 00 00 00 00 00 00 /* LUT2: WB: VS0..6 */ - 80 00 00 00 00 00 00 /* LUT3: WW: VS0..6 */ - 00 00 00 00 00 00 00 /* LUT4: VCOM: VS0..6 */ - 0A 00 00 00 04 /* TP0A TP0B TP0C TP0D RP0 */ - 00 00 00 00 00 /* TP1A TP1B TP1C TP1D RP1 */ - 00 00 00 00 00 /* TP2A TP2B TP2C TP2D RP2 */ - 00 00 00 00 00 /* TP3A TP3B TP3C TP3D RP3 */ - 00 00 00 00 00 /* TP4A TP4B TP4C TP4D RP4 */ - 00 00 00 00 00 /* TP5A TP5B TP5C TP5D RP5 */ - 00 00 00 00 00 /* TP6A TP6B TP6C TP6D RP6 */ - ]; - }; - }; }; diff --git a/boards/phytec/reel_board/reel_board_nrf52840_2.yaml b/boards/phytec/reel_board/reel_board_nrf52840_2.yaml index dc6361d4f5019..e98f366b969e4 100644 --- a/boards/phytec/reel_board/reel_board_nrf52840_2.yaml +++ b/boards/phytec/reel_board/reel_board_nrf52840_2.yaml @@ -1,5 +1,5 @@ identifier: reel_board@2 -name: reel-board +name: reel-board (rev. 2) type: mcu arch: arm ram: 512 @@ -13,7 +13,6 @@ supported: - spi - gpio - usb_device - - usb_cdc - ble - pwm - arduino_i2c diff --git a/boards/pine64/pinetime_devkit0/pinetime_devkit0.dts b/boards/pine64/pinetime_devkit0/pinetime_devkit0.dts index 207c893488018..7bdf52d79e4cf 100644 --- a/boards/pine64/pinetime_devkit0/pinetime_devkit0.dts +++ b/boards/pine64/pinetime_devkit0/pinetime_devkit0.dts @@ -12,6 +12,7 @@ #include #include "pinetime_devkit0-pinctrl.dtsi" #include +#include / { model = "Pine64 PineTime DevKit0"; @@ -77,6 +78,42 @@ output-ohms = <1000000>; full-ohms = <(1000000 + 1000000)>; }; + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi1>; + dc-gpios = <&gpio0 18 GPIO_ACTIVE_HIGH>; /* DET */ + reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; /* RESX reset */ + write-only; + #address-cells = <1>; + #size-cells = <0>; + /* Sitronix ST7789V LCD */ + st7789v: st7789v@1 { + compatible = "sitronix,st7789v"; + reg = <1>; + mipi-max-frequency = <8000000>; /* 8MHz */ + width = <240>; + height = <240>; + x-offset = <0>; + y-offset = <0>; + vcom = <0x19>; + gctrl = <0x35>; + vrhs = <0x12>; + vdvs = <0x20>; + mdac = <0x00>; + gamma = <0x01>; + colmod = <0x05>; + lcm = <0x2c>; + porch-param = [0c 0c 00 33 33]; + cmd2en-param = [5a 69 02 01]; + pwctrl1-param = [a4 a1]; + pvgam-param = [D0 04 0D 11 13 2B 3F 54 4C 18 0D 0B 1F 23]; + nvgam-param = [D0 04 0C 11 13 2C 3F 44 51 2F 1F 1F 20 23]; + ram-param = [00 F0]; + rgb-param = [CD 08 14]; + mipi-mode = ; + }; + }; }; &adc { @@ -178,34 +215,6 @@ }; }; }; - - /* Sitronix ST7789V LCD */ - st7789v: st7789v@1 { - compatible = "sitronix,st7789v"; - reg = <1>; - spi-max-frequency = <8000000>; /* 8MHz */ - cmd-data-gpios = <&gpio0 18 GPIO_ACTIVE_LOW>; /* DET */ - reset-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>; /* RESX reset */ - width = <240>; - height = <240>; - x-offset = <0>; - y-offset = <0>; - vcom = <0x19>; - gctrl = <0x35>; - vrhs = <0x12>; - vdvs = <0x20>; - mdac = <0x00>; - gamma = <0x01>; - colmod = <0x05>; - lcm = <0x2c>; - porch-param = [0c 0c 00 33 33]; - cmd2en-param = [5a 69 02 01]; - pwctrl1-param = [a4 a1]; - pvgam-param = [D0 04 0D 11 13 2B 3F 54 4C 18 0D 0B 1F 23]; - nvgam-param = [D0 04 0C 11 13 2C 3F 44 51 2F 1F 1F 20 23]; - ram-param = [00 F0]; - rgb-param = [CD 08 14]; - }; }; &flash0 { diff --git a/boards/pjrc/teensy4/teensy40.dts b/boards/pjrc/teensy4/teensy40.dts index 4b676664956cc..63775c3d1c618 100644 --- a/boards/pjrc/teensy4/teensy40.dts +++ b/boards/pjrc/teensy4/teensy40.dts @@ -66,11 +66,6 @@ zephyr_udc0: &usb1 { current-speed = < 115200 >; }; -&flexcan1 { - status = "okay"; - bus-speed = < 125000 >; -}; - &edma0 { status = "okay"; }; @@ -98,11 +93,7 @@ zephyr_udc0: &usb1 { &flexcan1 { pinctrl-0 = <&pinmux_flexcan1>; pinctrl-names = "default"; -}; - -&flexcan1 { - pinctrl-0 = <&pinmux_flexcan1>; - pinctrl-names = "default"; + status = "okay"; }; &flexcan2 { diff --git a/boards/qemu/cortex_m3/qemu_cortex_m3.dts b/boards/qemu/cortex_m3/qemu_cortex_m3.dts index 2e0bd95755f27..b035736a9f7b7 100644 --- a/boards/qemu/cortex_m3/qemu_cortex_m3.dts +++ b/boards/qemu/cortex_m3/qemu_cortex_m3.dts @@ -20,7 +20,7 @@ zephyr,flash = &flash0; zephyr,console = &uart0; zephyr,shell-uart = &uart0; - zephyr,bt-uart = &uart2; + zephyr,bt-hci = &bt_hci_uart; zephyr,uart-pipe = &uart1; zephyr,bt-mon-uart = &uart2; }; @@ -39,6 +39,11 @@ &uart2 { status = "okay"; current-speed = <115200>; + + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + }; }; ð { diff --git a/boards/qemu/riscv32/qemu_riscv32.dts b/boards/qemu/riscv32/qemu_riscv32.dts index 6c820813021c6..2c38ca1da1d7c 100644 --- a/boards/qemu/riscv32/qemu_riscv32.dts +++ b/boards/qemu/riscv32/qemu_riscv32.dts @@ -2,7 +2,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_smp.dts b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_smp.dts index 6c820813021c6..2c38ca1da1d7c 100644 --- a/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_smp.dts +++ b/boards/qemu/riscv32/qemu_riscv32_qemu_virt_riscv32_smp.dts @@ -2,7 +2,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/boards/qemu/riscv32e/qemu_riscv32e.dts b/boards/qemu/riscv32e/qemu_riscv32e.dts index 7596ee0d6eb1d..403d75cb74206 100644 --- a/boards/qemu/riscv32e/qemu_riscv32e.dts +++ b/boards/qemu/riscv32e/qemu_riscv32e.dts @@ -7,7 +7,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/boards/qemu/riscv64/qemu_riscv64.dts b/boards/qemu/riscv64/qemu_riscv64.dts index fb96f6d3d38a0..673d46680192f 100644 --- a/boards/qemu/riscv64/qemu_riscv64.dts +++ b/boards/qemu/riscv64/qemu_riscv64.dts @@ -3,7 +3,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/boards/qemu/riscv64/qemu_riscv64_qemu_virt_riscv64_smp.dts b/boards/qemu/riscv64/qemu_riscv64_qemu_virt_riscv64_smp.dts index fb96f6d3d38a0..673d46680192f 100644 --- a/boards/qemu/riscv64/qemu_riscv64_qemu_virt_riscv64_smp.dts +++ b/boards/qemu/riscv64/qemu_riscv64_qemu_virt_riscv64_smp.dts @@ -3,7 +3,7 @@ /dts-v1/; -#include +#include / { chosen { diff --git a/boards/qemu/x86/qemu_x86.dts b/boards/qemu/x86/qemu_x86.dts index fbe6042c1781c..907e8a1ec1cb7 100644 --- a/boards/qemu/x86/qemu_x86.dts +++ b/boards/qemu/x86/qemu_x86.dts @@ -37,8 +37,8 @@ zephyr,sram = &dram0; zephyr,flash = &flash0; zephyr,console = &uart0; + zephyr,bt-hci = &bt_hci_uart; zephyr,shell-uart = &uart0; - zephyr,bt-uart = &uart1; zephyr,uart-pipe = &uart1; zephyr,bt-mon-uart = &uart1; zephyr,code-partition = &slot0_partition; @@ -61,7 +61,6 @@ device-id = <0x8406>; interrupts = <11 IRQ_TYPE_LOWEST_LEVEL_LOW 3>; interrupt-parent = <&intc>; - bus-speed = <125000>; can-transceiver { max-bitrate = <1000000>; @@ -126,6 +125,11 @@ &uart1 { status = "okay"; current-speed = <115200>; + + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + }; }; &hpet { diff --git a/boards/qemu/x86/qemu_x86_tiny.ld b/boards/qemu/x86/qemu_x86_tiny.ld index 623a11fb41699..c3188c6e891a8 100644 --- a/boards/qemu/x86/qemu_x86_tiny.ld +++ b/boards/qemu/x86/qemu_x86_tiny.ld @@ -6,7 +6,7 @@ */ #include -#include +#include #include #include #include @@ -25,7 +25,7 @@ * the same as its physical location, although an identity mapping for RAM * is still supported by setting CONFIG_KERNEL_VM_BASE=CONFIG_SRAM_BASE_ADDRESS. */ -#ifdef Z_VM_KERNEL +#ifdef K_MEM_IS_VM_KERNEL #define KERNEL_BASE_ADDR \ (CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_OFFSET) @@ -55,7 +55,7 @@ MEMORY { -#if defined(Z_VM_KERNEL) +#if defined(K_MEM_IS_VM_KERNEL) ROM (rx) : ORIGIN = PHYS_LOAD_ADDR, LENGTH = PHYS_RAM_AVAIL #endif RAM (wx) : ORIGIN = KERNEL_BASE_ADDR, LENGTH = KERNEL_RAM_SIZE @@ -75,7 +75,7 @@ MEMORY IDT_LIST : ORIGIN = 0xFFFF1000, LENGTH = 2K } -#if defined(Z_VM_KERNEL) +#if defined(K_MEM_IS_VM_KERNEL) #define ROMABLE_REGION ROM #define RAMABLE_REGION RAM #else @@ -245,7 +245,7 @@ MEMORY *mpsc_pbuf.c.obj(.##lsect) \ *mpsc_pbuf.c.obj(.##lsect.*) -epoint = Z_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY); +epoint = K_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY); ENTRY(epoint) /* SECTIONS definitions */ @@ -254,6 +254,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /DISCARD/ : { *(.plt) diff --git a/boards/rak/rak11720/Kconfig.rak11720 b/boards/rak/rak11720/Kconfig.rak11720 new file mode 100644 index 0000000000000..a91bc261d333a --- /dev/null +++ b/boards/rak/rak11720/Kconfig.rak11720 @@ -0,0 +1,6 @@ +# Copyright (c) 2024 RAKwireless Technology Co., Ltd. +# Sercan Erat +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RAK11720 + select SOC_APOLLO3_BLUE diff --git a/boards/rak/rak11720/board.cmake b/boards/rak/rak11720/board.cmake new file mode 100644 index 0000000000000..026b5a25115bc --- /dev/null +++ b/boards/rak/rak11720/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2024 RAKwireless Technology Co., Ltd. +# Sercan Erat +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=AMA3B1KK-KBR" "--iface=swd" "--speed=1000") + +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/rak/rak11720/board.yml b/boards/rak/rak11720/board.yml new file mode 100644 index 0000000000000..827beef7e7648 --- /dev/null +++ b/boards/rak/rak11720/board.yml @@ -0,0 +1,5 @@ +board: + name: rak11720 + vendor: rakwireless + socs: + - name: apollo3_blue diff --git a/boards/rak/rak11720/doc/img/rak11720.webp b/boards/rak/rak11720/doc/img/rak11720.webp new file mode 100644 index 0000000000000..4c513024c782b Binary files /dev/null and b/boards/rak/rak11720/doc/img/rak11720.webp differ diff --git a/boards/rak/rak11720/doc/index.rst b/boards/rak/rak11720/doc/index.rst new file mode 100644 index 0000000000000..7f4054a90d5ff --- /dev/null +++ b/boards/rak/rak11720/doc/index.rst @@ -0,0 +1,122 @@ +.. _rak11720: + +RAK11720 +######## + +The RAK11720 is a WisBlock Core module for RAK WisBlock. +It is based on the powerful ultra-low power Apollo3 Blue SoC (AMA3B1KK-KBR-B0) +from Ambiq together with a Semtech SX1262 LoRa® transceiver. + +The AMA3B1KK-KBR-B0 has an integrated Bluetooth Low Energy transceiver +that enhances the communication capabilities. The RAK11720 stamp module +comes in the same size and footprint as our RAK3172 module which gives +you the opportunity to enhance your existing designs +with BLE without designing a new PCB. + +.. image:: img/rak11720.webp + :align: center + :alt: RAK11720 + +Hardware +******** + +The easiset way to use a RAK11720, is the WisBlock Modular system. +A WisBlock Base board (RAK19007) which provides the power +supply and programming/debug interface is the base to plug a +RAK11722 (WisBlock Core module with the RAK11720) in. + +- Apollo3 Blue SoC with up to 96 MHz operating frequency +- ARM® Cortex® M4F core +- 16 kB 2-way Associative/Direct-Mapped Cache per core +- Up to 1 MB of flash memory for code/data +- Up to 384 KB of low leakage / low power RAM for code/data +- Integrated Bluetooth 5 Low-energy controller +- Semtech SX1262 low power high range LoRa transceiver +- iPEX connectors for the LORA antenna and BLE antenna. +- 2 user LEDs on RAK19007 WisBlock Base board +- Powered by either Micro USB, 3.7V rechargeable battery or a 5V Solar Panel Port + +For more information about the RAK11720 stamp module: + +- `WisDuo RAK11720 Website`_ +- `WisBlock RAK11722 Website`_ + +Supported Features +================== + +The RAK11720 module configuration supports the following hardware features: + ++-----------+------------+----------------------+ +| Interface | Controller | Driver/Component | ++===========+============+======================+ +| MPU | on-chip | arch/arm | ++-----------+------------+----------------------+ +| NVIC | on-chip | arch/arm | ++-----------+------------+----------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+----------------------+ +| STIMER | on-chip | stimer | ++-----------+------------+----------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+----------------------+ +| UART | on-chip | serial | ++-----------+------------+----------------------+ +| WDT | on-chip | watchdog | ++-----------+------------+----------------------+ +| RADIO | on-chip | bluetooth | ++-----------+------------+----------------------+ +| RADIO | on-board | LoRa (SX1262) | ++-----------+------------+----------------------+ + +The default configuration can be found in the defconfig file: +``boards/rak/rak11720/rak11720_defconfig``. + +Programming and Debugging +========================= + +The RAK11720 board shall be connected to a Segger Embedded Debugger Unit +`J-Link OB `_. This provides a debug +interface to the Apollo3 Blue chip. You can use JLink to communicate with +the Apollo3 Blue. + +Flashing an application +----------------------- + +Connect your device to your host computer using the JLINK USB port. +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application, then flash it to the device: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: rak11720 + :goals: flash + +.. note:: + `west flash` requires `SEGGER J-Link software`_ and `pylink`_ Python module + to be installed on you host computer. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should be able to see on the corresponding Serial Port +the following message: + +.. code-block:: console + + Hello World! rak11720/apollo3_blue + +.. _WisDuo RAK11720 Website: + https://docs.rakwireless.com/Product-Categories/WisDuo/RAK11720-Module/Overview/#product-description + +.. _WisBlock RAK11722 Website: + https://docs.rakwireless.com/Product-Categories/WisBlock/RAK11722/Overview/#product-description + +.. _SEGGER J-Link software: + https://www.segger.com/downloads/jlink + +.. _pylink: + https://github.com/Square/pylink diff --git a/boards/rak/rak11720/rak11720.dts b/boards/rak/rak11720/rak11720.dts new file mode 100644 index 0000000000000..4a2a5f1845729 --- /dev/null +++ b/boards/rak/rak11720/rak11720.dts @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2024 RAKwireless Technology Co., Ltd. + * Sercan Erat + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "rak11720_apollo3-pinctrl.dtsi" + +/ { + model = "RAKwireless RAK11720 WisBlock LPWAN Module"; + compatible = "ambiq,rak11720"; + + chosen { + zephyr,itcm = &tcm; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,uart-pipe = &uart0; + zephyr,flash-controller = &flash; + }; + + aliases { + watchdog0 = &wdt0; + led0 = &blue_led; + led1 = &green_led; + lora0 = &lora; + }; + + leds { + compatible = "gpio-leds"; + blue_led: led_2 { + gpios = <&gpio32_63 13 GPIO_ACTIVE_HIGH>; + label = "Blue LED"; + }; + green_led: led_1 { + gpios = <&gpio32_63 12 GPIO_ACTIVE_HIGH>; + label = "Green LED"; + }; + }; +}; + +&flash0 { + erase-block-size = <8192>; + write-block-size = <4>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 16KB of storage at the end of the 976KB of flash */ + storage_partition: partition@f0000 { + label = "storage"; + reg = <0x000f0000 0x4000>; + }; + }; +}; + +&bleif { + pinctrl-0 = <&bleif_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&uart0 { + current-speed = <115200>; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&wdt0 { + status = "okay"; +}; + +&i2c2 { + compatible = "ambiq,i2c"; + pinctrl-0 = <&i2c2_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&spi0 { + compatible = "ambiq,spi"; + pinctrl-0 = <&spi0_default>; + pinctrl-names = "default"; + clock-frequency = ; + status = "okay"; +}; + +&spi1 { + compatible = "ambiq,spi"; + status = "okay"; + pinctrl-0 = <&spi1_default>; + pinctrl-names = "default"; + clock-frequency = ; + cs-gpios = <&gpio0_31 11 GPIO_ACTIVE_LOW>; + + lora: lora@0 { + compatible = "semtech,sx1262"; + reg = <0>; + reset-gpios = <&gpio0_31 17 GPIO_ACTIVE_LOW>; + busy-gpios = <&gpio0_31 16 GPIO_ACTIVE_HIGH>; + dio1-gpios = <&gpio0_31 15 GPIO_ACTIVE_HIGH>; + antenna-enable-gpios = <&gpio0_31 18 GPIO_ACTIVE_LOW>; + dio2-tx-enable; + dio3-tcxo-voltage = ; + tcxo-power-startup-delay-ms = <5>; + spi-max-frequency = ; + }; +}; + +&counter0 { + status = "okay"; +}; + +&counter1 { + status = "okay"; +}; + +&counter2 { + status = "okay"; +}; + +&counter3 { + status = "okay"; +}; + +&counter4 { + status = "okay"; +}; + +&counter5 { + status = "okay"; +}; + +&counter6 { + status = "okay"; +}; + +&counter7 { + status = "okay"; +}; + +&gpio0_31 { + status = "okay"; +}; + +&gpio32_63 { + status = "okay"; +}; diff --git a/boards/rak/rak11720/rak11720.yaml b/boards/rak/rak11720/rak11720.yaml new file mode 100644 index 0000000000000..43efd09ce87e9 --- /dev/null +++ b/boards/rak/rak11720/rak11720.yaml @@ -0,0 +1,21 @@ +identifier: rak11720 +name: RAK11720 +type: mcu +arch: arm +ram: 384 +flash: 976 +toolchain: + - zephyr + - gnuarmemb +supported: + - uart + - watchdog + - counter + - gpio + - spi + - i2c + - lora +testing: + ignore_tags: + - net +vendor: rak diff --git a/boards/rak/rak11720/rak11720_apollo3-pinctrl.dtsi b/boards/rak/rak11720/rak11720_apollo3-pinctrl.dtsi new file mode 100644 index 0000000000000..df81c2098e049 --- /dev/null +++ b/boards/rak/rak11720/rak11720_apollo3-pinctrl.dtsi @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2024 RAKwireless Technology Co., Ltd. + * Sercan Erat + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + i2c0_default: i2c0_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c1_default: i2c1_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c2_default: i2c2_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c3_default: i2c3_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c4_default: i2c4_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + i2c5_default: i2c5_default { + group1 { + pinmux = , ; + drive-open-drain; + drive-strength = "0.5"; + bias-pull-up; + }; + }; + + spi0_default: spi0_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <0>; + }; + }; + spi1_default: spi1_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <1>; + ambiq,iom-num = <1>; + }; + }; + spi2_default: spi2_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <3>; + ambiq,iom-num = <2>; + }; + }; + spi3_default: spi3_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <3>; + }; + }; + spi4_default: spi4_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <1>; + ambiq,iom-num = <4>; + }; + }; + spi5_default: spi5_default { + group1 { + pinmux = , , ; + }; + group2 { + pinmux = ; + drive-push-pull; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <5>; + }; + }; + + mspi0_default: mspi0_default{ + group1 { + pinmux = , + , + , + , + ; + }; + group2 { + pinmux = ; + drive-push-pull; + drive-strength = "0.5"; + ambiq,iom-nce-module = <0>; + ambiq,iom-num = <6>; + }; + }; + + bleif_default: bleif_default{ + group1 { + pinmux = , + , + , + , + , + ; + }; + }; +}; diff --git a/boards/rak/rak11720/rak11720_defconfig b/boards/rak/rak11720/rak11720_defconfig new file mode 100644 index 0000000000000..33690ff27206c --- /dev/null +++ b/boards/rak/rak11720/rak11720_defconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2024 RAKwireless Technology Co., Ltd. +# Sercan Erat +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/rak/rak4631/Kconfig b/boards/rak/rak4631/Kconfig new file mode 100644 index 0000000000000..b313c721fb6a7 --- /dev/null +++ b/boards/rak/rak4631/Kconfig @@ -0,0 +1,18 @@ +# RAKWIRELESS RAK4631 Board configuration + +# Copyright (c) 2024 Kelly Helmut Lord +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RAK4631 + +config BOARD_ENABLE_DCDC + bool "DCDC mode" + select SOC_DCDC_NRF52X + default y + +config BOARD_ENABLE_DCDC_HV + bool "High Voltage DCDC converter" + select SOC_DCDC_NRF52X_HV + default y + +endif # BOARD_RAK4631 diff --git a/boards/rak/rak4631/rak4631_nrf52840.yaml b/boards/rak/rak4631/rak4631_nrf52840.yaml index 42c638ac35c71..f8b3e23582699 100644 --- a/boards/rak/rak4631/rak4631_nrf52840.yaml +++ b/boards/rak/rak4631/rak4631_nrf52840.yaml @@ -15,7 +15,6 @@ supported: - gpio - i2c - pwm - - usb_cdc - usb_device - watchdog - lora diff --git a/boards/rak/rak5010/board.cmake b/boards/rak/rak5010/board.cmake index 1bf111421e2b7..d91b58c847d8a 100644 --- a/boards/rak/rak5010/board.cmake +++ b/boards/rak/rak5010/board.cmake @@ -7,3 +7,4 @@ include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake) +include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake) diff --git a/boards/rak/rak5010/rak5010_nrf52840.yaml b/boards/rak/rak5010/rak5010_nrf52840.yaml index 21b8e12297041..2b947436b2620 100644 --- a/boards/rak/rak5010/rak5010_nrf52840.yaml +++ b/boards/rak/rak5010/rak5010_nrf52840.yaml @@ -15,7 +15,6 @@ supported: - gpio - i2c - pwm - - usb_cdc - usb_device - watchdog vendor: rak diff --git a/boards/raspberrypi/rpi_pico/doc/index.rst b/boards/raspberrypi/rpi_pico/doc/index.rst index 8db18d96f043b..a2c3468e34f04 100644 --- a/boards/raspberrypi/rpi_pico/doc/index.rst +++ b/boards/raspberrypi/rpi_pico/doc/index.rst @@ -179,7 +179,7 @@ Here is an example of building and flashing the :zephyr:code-sample:`blinky` app Using OpenOCD ------------- -To use PicoProbe, You must configure **udev**. +To use CMSIS-DAP, You must configure **udev**. Create a file in /etc/udev.rules.d with any name, and write the line below. @@ -206,7 +206,7 @@ Here is an example of building and flashing the :zephyr:code-sample:`blinky` app :zephyr-app: samples/basic/blinky :board: rpi_pico :goals: build flash - :gen-args: -DOPENOCD=/usr/local/bin/openocd -DOPENOCD_DEFAULT_PATH=/usr/local/share/openocd/scripts -DRPI_PICO_DEBUG_ADAPTER=picoprobe + :gen-args: -DOPENOCD=/usr/local/bin/openocd -DOPENOCD_DEFAULT_PATH=/usr/local/share/openocd/scripts -DRPI_PICO_DEBUG_ADAPTER=cmsis-dap Set the environment variables **OPENOCD** to `/usr/local/bin/openocd` and **OPENOCD_DEFAULT_PATH** to `/usr/local/share/openocd/scripts`. This should work @@ -215,9 +215,9 @@ This configuration also works with an environment that is set up by the `pico_se **RPI_PICO_DEBUG_ADAPTER** specifies what debug adapter is used for debugging. -If **RPI_PICO_DEBUG_ADAPTER** was not assigned, `picoprobe` is used by default. +If **RPI_PICO_DEBUG_ADAPTER** was not assigned, `cmsis-dap` is used by default. The other supported adapters are `raspberrypi-swd`, `jlink` and `blackmagicprobe`. -How to connect `picoprobe` and `raspberrypi-swd` is described in `Getting Started with Raspberry Pi Pico`_. +How to connect `cmsis-dap` and `raspberrypi-swd` is described in `Getting Started with Raspberry Pi Pico`_. Any other SWD debug adapter maybe also work with this configuration. The value of **RPI_PICO_DEBUG_ADAPTER** is cached, so it can be omitted from diff --git a/boards/raytac/mdbt50q_db_33/raytac_mdbt50q_db_33_nrf52833.yaml b/boards/raytac/mdbt50q_db_33/raytac_mdbt50q_db_33_nrf52833.yaml index 673705fa1237b..e0698628e71a5 100644 --- a/boards/raytac/mdbt50q_db_33/raytac_mdbt50q_db_33_nrf52833.yaml +++ b/boards/raytac/mdbt50q_db_33/raytac_mdbt50q_db_33_nrf52833.yaml @@ -21,7 +21,6 @@ supported: - ieee802154 - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/raytac/mdbt50q_db_40/raytac_mdbt50q_db_40_nrf52840.yaml b/boards/raytac/mdbt50q_db_40/raytac_mdbt50q_db_40_nrf52840.yaml index 15ba012594ee8..cc99eab1a53a4 100644 --- a/boards/raytac/mdbt50q_db_40/raytac_mdbt50q_db_40_nrf52840.yaml +++ b/boards/raytac/mdbt50q_db_40/raytac_mdbt50q_db_40_nrf52840.yaml @@ -23,7 +23,6 @@ supported: - ieee802154 - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/raytac/mdbt53_db_40/Kconfig.defconfig b/boards/raytac/mdbt53_db_40/Kconfig.defconfig index 7bb0e9da9484c..bb53d3ae8f477 100644 --- a/boards/raytac/mdbt53_db_40/Kconfig.defconfig +++ b/boards/raytac/mdbt53_db_40/Kconfig.defconfig @@ -53,9 +53,8 @@ config FLASH_LOAD_SIZE endif # BOARD_RAYTAC_MDBT53_DB_40_NRF5340_CPUAPP_NS -choice BT_HCI_BUS_TYPE - default BT_HCI_IPC if BT -endchoice +config BT_HCI_IPC + default y if BT config HEAP_MEM_POOL_ADD_SIZE_BOARD int diff --git a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml index f962784606bd3..44596dc8a5bc7 100644 --- a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml +++ b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp.yaml @@ -17,6 +17,5 @@ supported: - spi - uart - watchdog - - usb_cdc - usb_device - netif:openthread diff --git a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_common.dts b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_common.dts index 3af7de1f17edf..62a49e520698a 100644 --- a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_common.dts +++ b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_common.dts @@ -14,7 +14,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-ipc = &ipc0; + zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; }; diff --git a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml index 46fbe1ea1928e..d77e8d5c8f0f9 100644 --- a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml +++ b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpuapp_ns.yaml @@ -15,7 +15,6 @@ supported: - watchdog - spi - uart - - usb_cdc - usb_device - netif:openthread - gpio diff --git a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c index 64e335869fb59..9596b3453be20 100644 --- a/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c +++ b/boards/raytac/mdbt53_db_40/raytac_mdbt53_db_40_nrf5340_cpunet_reset.c @@ -10,7 +10,7 @@ #include #include -#include +#include LOG_MODULE_REGISTER(raytac_mdbt53_db_40_nrf5340_cpuapp, CONFIG_LOG_DEFAULT_LEVEL); @@ -50,7 +50,7 @@ static int remoteproc_mgr_boot(const struct device *dev) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/raytac/mdbt53v_db_40/Kconfig.defconfig b/boards/raytac/mdbt53v_db_40/Kconfig.defconfig index 9cdb1683eed02..9573720773d15 100644 --- a/boards/raytac/mdbt53v_db_40/Kconfig.defconfig +++ b/boards/raytac/mdbt53v_db_40/Kconfig.defconfig @@ -53,9 +53,8 @@ config FLASH_LOAD_SIZE endif # BOARD_RAYTAC_MDBT53V_DB_40_NRF5340_CPUAPP_NS -choice BT_HCI_BUS_TYPE - default BT_HCI_IPC if BT -endchoice +config BT_HCI_IPC + default y if BT config HEAP_MEM_POOL_ADD_SIZE_BOARD int diff --git a/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpuapp_common.dts b/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpuapp_common.dts index c7d7521d08b05..3c1b42307a6ec 100644 --- a/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpuapp_common.dts +++ b/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpuapp_common.dts @@ -14,7 +14,7 @@ zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; - zephyr,bt-hci-ipc = &ipc0; + zephyr,bt-hci = &bt_hci_ipc0; nordic,802154-spinel-ipc = &ipc0; zephyr,ieee802154 = &ieee802154; }; diff --git a/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c b/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c index ec4567274c40d..31b8bf5a75e5a 100644 --- a/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c +++ b/boards/raytac/mdbt53v_db_40/raytac_mdbt53v_db_40_nrf5340_cpunet_reset.c @@ -49,7 +49,7 @@ static int remoteproc_mgr_boot(const struct device *dev) */ /* Release the Network MCU, 'Release force off signal' */ - nrf53_cpunet_enable(true); + nrf_reset_network_force_off(NRF_RESET, false); LOG_DBG("Network MCU released."); #endif /* !CONFIG_TRUSTED_EXECUTION_SECURE */ diff --git a/boards/renesas/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi b/boards/renesas/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi index d16ad945fa855..1db25444b6cd6 100644 --- a/boards/renesas/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi +++ b/boards/renesas/da14695_dk_usb/da14695_dk_usb-pinctrl.dtsi @@ -52,6 +52,14 @@ }; }; + /omit-if-no-ref/ spi_sleep: spi_sleep { + group1 { + pinmux = , + , + ; + }; + }; + spi_controller: spi_controller { group1 { pinmux = < SMARTBOND_PINMUX(SPI_CLK, 0, 21) >, @@ -64,6 +72,14 @@ }; }; + /omit-if-no-ref/ spi2_sleep: spi2_sleep { + group1 { + pinmux = , + , + ; + }; + }; + spi2_controller: spi2_controller { group1 { pinmux = < SMARTBOND_PINMUX(SPI2_CLK, 1, 3) >, diff --git a/boards/renesas/da14695_dk_usb/da14695_dk_usb.dts b/boards/renesas/da14695_dk_usb/da14695_dk_usb.dts index eff5299dcff60..4e86ee9221b9b 100644 --- a/boards/renesas/da14695_dk_usb/da14695_dk_usb.dts +++ b/boards/renesas/da14695_dk_usb/da14695_dk_usb.dts @@ -201,13 +201,15 @@ zephyr_udc0: &usbd { &spi { status = "okay"; pinctrl-0 = <&spi_controller>; - pinctrl-names = "default"; + pinctrl-1 = <&spi_sleep>; + pinctrl-names = "default", "sleep"; }; &spi2 { status = "okay"; pinctrl-0 = <&spi2_controller>; - pinctrl-names = "default"; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; }; mikrobus_1_i2c: &i2c {}; diff --git a/boards/renesas/da1469x_dk_pro/Kconfig.defconfig b/boards/renesas/da1469x_dk_pro/Kconfig.defconfig index 34b4913118160..4ef15e108a440 100644 --- a/boards/renesas/da1469x_dk_pro/Kconfig.defconfig +++ b/boards/renesas/da1469x_dk_pro/Kconfig.defconfig @@ -5,6 +5,20 @@ if BOARD_DA1469X_DK_PRO +# Enable sleep and voltage rails manager so that +# the device consumes the lowest possible current +config PM + default y + +config PM_DEVICE + default y + +config REGULATOR + default y + +config I2C_CALLBACK + default y if I2C_SMARTBOND + if LVGL config LV_Z_BITS_PER_PIXEL @@ -34,13 +48,28 @@ config LV_Z_POINTER_INPUT_MSGQ_COUNT endif # INPUT -#if PM || PM_DEVICE +if PM || PM_DEVICE || PM_DEVICE_RUNTIME # Increase stack size to avoid raising usage-fault # exceptions due to stack overflow. config IDLE_STACK_SIZE default 2048 -#endif # PM || PM_DEVICE +# Make sure the serial device has higher +# initialization priority. +config SERIAL_INIT_PRIORITY + default KERNEL_INIT_PRIORITY_DEFAULT + +endif # PM || PM_DEVICE + +if BT + +config BT_WAIT_NOP + default y + +config TEST_RANDOM_GENERATOR + default y + +endif # BT endif # BOARD_DA1469X_DK_PRO diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi index 39daff3ff162d..50396701632a8 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro-pinctrl.dtsi @@ -24,6 +24,15 @@ }; }; + /omit-if-no-ref/ i2c_sleep: i2c_sleep { + group1 { + pinmux = , + ; + bias-pull-up; + + }; + }; + i2c2_default: i2c2_default { group1 { pinmux = , @@ -32,6 +41,14 @@ }; }; + /omit-if-no-ref/ i2c2_sleep: i2c2_sleep { + group1 { + pinmux = , + ; + bias-pull-up; + }; + }; + display_controller_default: display_controller_default { group1 { pinmux = , @@ -47,18 +64,49 @@ }; }; + /omit-if-no-ref/ display_controller_sleep: display_controller_sleep { + group1 { + pinmux = , + , + , + , + , + , + , + , + , + ; + }; + }; + + /omit-if-no-ref/ spi_sleep: spi_sleep { + group1 { + pinmux = , + , + ; + }; + }; + spi_controller: spi_controller { group1 { - pinmux = , - ; + pinmux = , + ; output-enable; }; group2 { - pinmux = ; + pinmux = ; input-enable; }; }; + /omit-if-no-ref/ spi2_sleep: spi2_sleep { + group1 { + pinmux = , + , + ; + }; + }; + spi2_controller: spi2_controller { group1 { pinmux = < SMARTBOND_PINMUX(SPI2_CLK, 1, 3) >, diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts index f83098f6f197c..f866df49a859a 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.dts @@ -19,6 +19,7 @@ zephyr,console = &uart; zephyr,shell-uart = &uart; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &bt_hci_da1469x; }; lvgl_pointer { @@ -119,6 +120,7 @@ status = "okay"; pinctrl-0 = <&uart_default>; pinctrl-names = "default"; + rx-wake-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>; }; zephyr_udc0: &usbd { @@ -138,6 +140,14 @@ zephyr_udc0: &usbd { status = "okay"; }; +/* + * On board level we switch to XTAL32K and + * so RCX can be disabled. + */ +&rcx { + status = "disabled"; +}; + &lp_clk { clock-src = <&xtal32k>; }; @@ -146,29 +156,30 @@ zephyr_udc0: &usbd { clock-src = <&xtal32m>; }; -&pll { - status = "okay"; -}; &i2c { - status = "okay"; pinctrl-0 = <&i2c_default>; - pinctrl-names = "default"; + pinctrl-1 = <&i2c_sleep>; + pinctrl-names = "default", "sleep"; }; &i2c2 { - status = "okay"; pinctrl-0 = <&i2c2_default>; - pinctrl-names = "default"; + pinctrl-1 = <&i2c2_sleep>; + pinctrl-names = "default", "sleep"; }; &spi { - status = "okay"; pinctrl-0 = <&spi_controller>; - pinctrl-names = "default"; + pinctrl-1 = <&spi_sleep>; + pinctrl-names = "default", "sleep"; }; &spi2 { - status = "okay"; pinctrl-0 = <&spi2_controller>; - pinctrl-names = "default"; + pinctrl-1 = <&spi2_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&bt_hci_da1469x { + status = "okay"; }; diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.yaml b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.yaml index eb29fd6c55907..942bfe3e07e5f 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.yaml +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro.yaml @@ -21,4 +21,5 @@ supported: - dma - mipi_dbi - display + - memc vendor: renesas diff --git a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro_defconfig b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro_defconfig index e31b6eb8457f3..9ce790fe46b01 100644 --- a/boards/renesas/da1469x_dk_pro/da1469x_dk_pro_defconfig +++ b/boards/renesas/da1469x_dk_pro/da1469x_dk_pro_defconfig @@ -9,6 +9,3 @@ CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_BUILD_OUTPUT_HEX=n - -CONFIG_I2C=y -CONFIG_I2C_CALLBACK=y diff --git a/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_lcdc.overlay b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_lcdc.overlay index c147201adc483..053e96efd105f 100644 --- a/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_lcdc.overlay +++ b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_lcdc.overlay @@ -31,10 +31,19 @@ bias-pull-up; }; }; + + i2c2_sleep: i2c2_sleep { + group1 { + pinmux = , + ; + bias-pull-up; + }; + }; }; &i2c2 { clock-frequency = <400000>; + status = "okay"; display_touch: ft6206@38 { compatible = "focaltech,ft5336"; @@ -47,7 +56,8 @@ &lcdc { status = "okay"; pinctrl-0 = <&display_controller_default>; - pinctrl-names = "default"; + pinctrl-1 = <&display_controller_sleep>; + pinctrl-names = "default", "sleep"; width = <480>; height = <272>; disp-gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; diff --git a/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_mipi_dbi.overlay b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_mipi_dbi.overlay index 81dbc363d6217..2ed161097da57 100644 --- a/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_mipi_dbi.overlay +++ b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_mipi_dbi.overlay @@ -23,6 +23,7 @@ &i2c2 { clock-frequency = <400000>; + status = "okay"; display_touch: ft6206@38 { compatible = "focaltech,ft5336"; @@ -32,6 +33,10 @@ }; }; +&spi2 { + status = "okay"; +}; + &lcdc { compatible = "renesas,smartbond-mipi-dbi"; status = "okay"; diff --git a/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_psram.overlay b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_psram.overlay new file mode 100644 index 0000000000000..5707f111d97ff --- /dev/null +++ b/boards/renesas/da1469x_dk_pro/dts/da1469x_dk_pro_psram.overlay @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + aliases { + sram-ext = &memc; + }; +}; + +/* QSPIC settings for the APS6404L-3SQR QSPI PSRAM memory in QPI mode. */ +&memc { + status = "okay"; + is-ram; + dev-size = ; + dev-type = <0x5D>; + dev-id = <0x0D>; + dev-density = <0xE040>; + reset-delay-us = <50>; + read-cs-idle-min-ns = <18>; + tcem-max-us = <2>; + enter-qpi-mode; + enter-qpi-cmd = <0x35>; + extra-byte-enable; + extra-byte = <0x0>; + dummy-bytes-count = "dummy-bytes-count2"; + read-cmd = <0xEB>; + write-cmd = <0x38>; + rx-inst-mode = "quad-spi"; + rx-addr-mode = "quad-spi"; + rx-data-mode = "quad-spi"; + rx-dummy-mode = "quad-spi"; + rx-extra-mode = "quad-spi"; + tx-inst-mode = "quad-spi"; + tx-addr-mode = "quad-spi"; + tx-data-mode = "quad-spi"; +}; diff --git a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi index 6dc65b033137e..37c6c09917604 100644 --- a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi +++ b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi @@ -15,44 +15,126 @@ pin = ; }; + sd0_clk: sd0_clk { + pin = ; + power-source = ; + }; + + sd0_cmd: sd0_cmd { + pin = ; + power-source = ; + }; + + sd0_data0: sd0_data0 { + pin = ; + power-source = ; + }; + + sd0_data1: sd0_data1 { + pin = ; + power-source = ; + }; + + sd0_data2: sd0_data2 { + pin = ; + power-source = ; + }; + + sd0_data3: sd0_data3 { + pin = ; + power-source = ; + }; + + sd0_clk_uhs: sd0_clk_uhs { + pin = ; + power-source = ; + }; + + sd0_cmd_uhs: sd0_cmd_uhs { + pin = ; + power-source = ; + }; + + sd0_data0_uhs: sd0_data0_uhs { + pin = ; + power-source = ; + }; + + sd0_data1_uhs: sd0_data1_uhs { + pin = ; + power-source = ; + }; + + sd0_data2_uhs: sd0_data2_uhs { + pin = ; + power-source = ; + }; + + sd0_data3_uhs: sd0_data3_uhs { + pin = ; + power-source = ; + }; + + /* note: CD pin is fixed at 3.3V */ + sd0_cd: sd0_cd { + pin = ; + power-source = ; + }; + + /* note: WP pin is fixed at 3.3V */ + sd0_wp: sd0_wp { + pin = ; + power-source = ; + }; + emmc2_clk: emmc2_clk { pin = ; + power-source = ; }; emmc2_cmd: emmc2_cmd { pin = ; + power-source = ; }; emmc2_data0: emmc2_data0 { pin = ; + power-source = ; }; emmc2_data1: emmc2_data1 { pin = ; + power-source = ; }; emmc2_data2: emmc2_data2 { pin = ; + power-source = ; }; emmc2_data3: emmc2_data3 { pin = ; + power-source = ; }; emmc2_data4: emmc2_data4 { pin = ; + power-source = ; }; emmc2_data5: emmc2_data5 { pin = ; + power-source = ; }; emmc2_data6: emmc2_data6 { pin = ; + power-source = ; }; emmc2_data7: emmc2_data7 { pin = ; + power-source = ; }; emmc2_ds: emmc2_ds { diff --git a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57.dts b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57.dts index 599a0f25314be..117b6bb4e741b 100644 --- a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57.dts +++ b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_a57.dts @@ -8,6 +8,7 @@ /dts-v1/; #include #include +#include #include "rcar_h3ulcb_r8a77951_a57-pinctrl.dtsi" / { @@ -28,6 +29,52 @@ aliases { sdhc0 = &emmc2; }; + + vcc_sd0: regulator-vcc-sd0 { + compatible = "regulator-fixed"; + + regulator-name = "SD0 Vcc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + + enable-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>; + }; + + vccq_sd0: regulator-vccq-sd0 { + compatible = "regulator-gpio"; + + regulator-name = "SD0 VccQ"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <3300000>; + + gpios = <&gpio5 1 GPIO_ACTIVE_HIGH>; + states = <3300000 1>, <1800000 0>; + + regulator-always-on; + }; +}; + +&gpio5 { + status = "okay"; +}; + +&sd0 { + pinctrl-0 = <&sd0_clk &sd0_cmd &sd0_cd &sd0_wp + &sd0_data0 &sd0_data1 &sd0_data2 &sd0_data3>; + pinctrl-1 = <&sd0_clk_uhs &sd0_cmd_uhs &sd0_cd &sd0_wp + &sd0_data0_uhs &sd0_data1_uhs &sd0_data2_uhs &sd0_data3_uhs>; + pinctrl-names = "default", "uhs"; + disk { + compatible = "zephyr,sdmmc-disk"; + status = "okay"; + }; + + vmmc-supply = <&vcc_sd0>; + vqmmc-supply = <&vccq_sd0>; + + bus-width = <4>; + mmc-sdr104-support; + status = "okay"; }; &scif2 { diff --git a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_r7.dts b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_r7.dts index a5a23e779d819..cadd4dc979974 100644 --- a/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_r7.dts +++ b/boards/renesas/rcar_h3ulcb/rcar_h3ulcb_r8a77951_r7.dts @@ -63,7 +63,6 @@ pinctrl-0 = <&can0_data_a_tx_default &can0_data_a_rx_default>; pinctrl-names = "default"; status = "okay"; - bus-speed = <125000>; can-transceiver { max-bitrate = <5000000>; diff --git a/boards/renesas/rcar_salvator_x/rcar_salvator_x_r8a77951_r7.dts b/boards/renesas/rcar_salvator_x/rcar_salvator_x_r8a77951_r7.dts index ce5c046f54ad9..d0db253f12734 100644 --- a/boards/renesas/rcar_salvator_x/rcar_salvator_x_r8a77951_r7.dts +++ b/boards/renesas/rcar_salvator_x/rcar_salvator_x_r8a77951_r7.dts @@ -75,7 +75,6 @@ pinctrl-0 = <&can0_data_a_tx_default &can0_data_a_rx_default>; pinctrl-names = "default"; status = "okay"; - bus-speed = <125000>; }; &scif1 { diff --git a/boards/renesas/rcar_salvator_xs/rcar_salvator_xs-pinctrl.dtsi b/boards/renesas/rcar_salvator_xs/rcar_salvator_xs-pinctrl.dtsi index b563a720079f8..f23f4b3c1b1af 100644 --- a/boards/renesas/rcar_salvator_xs/rcar_salvator_xs-pinctrl.dtsi +++ b/boards/renesas/rcar_salvator_xs/rcar_salvator_xs-pinctrl.dtsi @@ -17,42 +17,52 @@ emmc2_clk: emmc2_clk { pin = ; + power-source = ; }; emmc2_cmd: emmc2_cmd { pin = ; + power-source = ; }; emmc2_data0: emmc2_data0 { pin = ; + power-source = ; }; emmc2_data1: emmc2_data1 { pin = ; + power-source = ; }; emmc2_data2: emmc2_data2 { pin = ; + power-source = ; }; emmc2_data3: emmc2_data3 { pin = ; + power-source = ; }; emmc2_data4: emmc2_data4 { pin = ; + power-source = ; }; emmc2_data5: emmc2_data5 { pin = ; + power-source = ; }; emmc2_data6: emmc2_data6 { pin = ; + power-source = ; }; emmc2_data7: emmc2_data7 { pin = ; + power-source = ; }; emmc2_ds: emmc2_ds { diff --git a/boards/renesas/rcar_spider_s4/rcar_spider_s4_r8a779f0_a55-pinctrl.dtsi b/boards/renesas/rcar_spider_s4/rcar_spider_s4_r8a779f0_a55-pinctrl.dtsi index 50739a237bea1..9d99d8cb89ce8 100644 --- a/boards/renesas/rcar_spider_s4/rcar_spider_s4_r8a779f0_a55-pinctrl.dtsi +++ b/boards/renesas/rcar_spider_s4/rcar_spider_s4_r8a779f0_a55-pinctrl.dtsi @@ -14,4 +14,58 @@ hscif0_data_rx_default: hscif0_data_rx_default { pin = ; }; + + mmc_clk: mmc_clk { + pin = ; + power-source = ; + }; + + mmc_cmd: mmc_cmd { + pin = ; + power-source = ; + }; + + mmc_data0: mmc_data0 { + pin = ; + power-source = ; + }; + + mmc_data1: mmc_data1 { + pin = ; + power-source = ; + }; + + mmc_data2: mmc_data2 { + pin = ; + power-source = ; + }; + + mmc_data3: mmc_data3 { + pin = ; + power-source = ; + }; + + mmc_data4: mmc_data4 { + pin = ; + power-source = ; + }; + + mmc_data5: mmc_data5 { + pin = ; + power-source = ; + }; + + mmc_data6: mmc_data6 { + pin = ; + power-source = ; + }; + + mmc_data7: mmc_data7 { + pin = ; + power-source = ; + }; + + mmc_ds: mmc_ds { + pin = ; + }; }; diff --git a/boards/renesas/rcar_spider_s4/rcar_spider_s4_r8a779f0_a55.dts b/boards/renesas/rcar_spider_s4/rcar_spider_s4_r8a779f0_a55.dts index 2075b90495cb4..3a7b5c4eb829b 100644 --- a/boards/renesas/rcar_spider_s4/rcar_spider_s4_r8a779f0_a55.dts +++ b/boards/renesas/rcar_spider_s4/rcar_spider_s4_r8a779f0_a55.dts @@ -30,3 +30,22 @@ current-speed = <1843200>; status = "okay"; }; + +&mmc0 { + pinctrl-0 = <&mmc_clk &mmc_cmd &mmc_ds + &mmc_data0 &mmc_data1 &mmc_data2 &mmc_data3 + &mmc_data4 &mmc_data5 &mmc_data6 &mmc_data7>; + pinctrl-1 = <&mmc_clk &mmc_cmd &mmc_ds + &mmc_data0 &mmc_data1 &mmc_data2 &mmc_data3 + &mmc_data4 &mmc_data5 &mmc_data6 &mmc_data7>; + pinctrl-names = "default", "uhs"; + disk { + compatible = "zephyr,mmc-disk"; + status = "okay"; + }; + bus-width = <8>; + mmc-hs200-1_8v; + mmc-hs400-1_8v; + non-removable; + status = "okay"; +}; diff --git a/boards/renode/riscv32_virtual/riscv32_virtual.yaml b/boards/renode/riscv32_virtual/riscv32_virtual.yaml index 600a5679f7e0c..64cab1f32ba5e 100644 --- a/boards/renode/riscv32_virtual/riscv32_virtual.yaml +++ b/boards/renode/riscv32_virtual/riscv32_virtual.yaml @@ -12,5 +12,8 @@ testing: ignore_tags: - net - bluetooth + renode: + uart: sysbus.uart0 + resc: boards/renode/riscv32_virtual/support/riscv32_virtual.resc supported: - uart diff --git a/boards/renode/riscv32_virtual/support/riscv32_virtual.resc b/boards/renode/riscv32_virtual/support/riscv32_virtual.resc index 87e327287b61a..dedbc699078b1 100644 --- a/boards/renode/riscv32_virtual/support/riscv32_virtual.resc +++ b/boards/renode/riscv32_virtual/support/riscv32_virtual.resc @@ -12,6 +12,6 @@ cpu PerformanceInMips 4 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/seagate/faze/support/openocd.cfg b/boards/seagate/faze/support/openocd.cfg index d7dc6d82c0d4b..770d566fadd67 100644 --- a/boards/seagate/faze/support/openocd.cfg +++ b/boards/seagate/faze/support/openocd.cfg @@ -36,4 +36,4 @@ $_TARGETNAME configure -event reset-end { # Enable Zephyr thread awareness. $_TARGETNAME configure -rtos Zephyr -adapter_khz 100 +adapter speed 100 diff --git a/boards/seagate/legend/legend.dts b/boards/seagate/legend/legend.dts index 245d2c8de7da9..d230345dd0794 100644 --- a/boards/seagate/legend/legend.dts +++ b/boards/seagate/legend/legend.dts @@ -21,7 +21,6 @@ aliases { watchdog0 = &iwdg; - spi-flash0 = &spi_nor; led-strip = &led_strip_spi; }; diff --git a/boards/seagate/legend/legend_stm32f070xb_25hdd.yaml b/boards/seagate/legend/legend_stm32f070xb_25hdd.yaml index a9eb85aee47a2..e94bd6e2faa01 100644 --- a/boards/seagate/legend/legend_stm32f070xb_25hdd.yaml +++ b/boards/seagate/legend/legend_stm32f070xb_25hdd.yaml @@ -1,5 +1,5 @@ identifier: legend@25hdd -name: Legend +name: Legend (25hdd) type: mcu arch: arm ram: 16 diff --git a/boards/seagate/legend/legend_stm32f070xb_25ssd.yaml b/boards/seagate/legend/legend_stm32f070xb_25ssd.yaml index db494bd878cb8..b1aa3766f7728 100644 --- a/boards/seagate/legend/legend_stm32f070xb_25ssd.yaml +++ b/boards/seagate/legend/legend_stm32f070xb_25ssd.yaml @@ -1,5 +1,5 @@ identifier: legend@25ssd -name: Legend +name: Legend (25sdd) type: mcu arch: arm ram: 16 diff --git a/boards/seagate/legend/legend_stm32f070xb_35.yaml b/boards/seagate/legend/legend_stm32f070xb_35.yaml index 37ed59788d9bb..851fb36a8b41a 100644 --- a/boards/seagate/legend/legend_stm32f070xb_35.yaml +++ b/boards/seagate/legend/legend_stm32f070xb_35.yaml @@ -1,5 +1,5 @@ identifier: legend@35 -name: Legend +name: Legend (35) type: mcu arch: arm ram: 16 diff --git a/boards/seco/stm32f3_seco_d23/stm32f3_seco_d23.dts b/boards/seco/stm32f3_seco_d23/stm32f3_seco_d23.dts index 79577593ddbf5..bfd1fc3c30bdb 100644 --- a/boards/seco/stm32f3_seco_d23/stm32f3_seco_d23.dts +++ b/boards/seco/stm32f3_seco_d23/stm32f3_seco_d23.dts @@ -177,7 +177,6 @@ zephyr_udc0: &usb { &can1 { pinctrl-0 = <&can_rx_pb8 &can_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; phys = <&transceiver0>; status = "okay"; }; diff --git a/boards/seeed/wio_terminal/support/openocd.cfg b/boards/seeed/wio_terminal/support/openocd.cfg index ce9baa8012f1e..6b329e98de806 100644 --- a/boards/seeed/wio_terminal/support/openocd.cfg +++ b/boards/seeed/wio_terminal/support/openocd.cfg @@ -8,7 +8,7 @@ set CHIPNAME atsamd51p19 source [find target/atsame5x.cfg] -adapter_khz 500 +adapter speed 500 reset_config srst_only $_TARGETNAME configure -event gdb-attach { diff --git a/boards/seeed/wio_terminal/wio_terminal.yaml b/boards/seeed/wio_terminal/wio_terminal.yaml index e78e041719bc4..66a97ebefc01c 100644 --- a/boards/seeed/wio_terminal/wio_terminal.yaml +++ b/boards/seeed/wio_terminal/wio_terminal.yaml @@ -16,7 +16,6 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog vendor: seeed diff --git a/boards/seeed/xiao_ble/xiao_ble.yaml b/boards/seeed/xiao_ble/xiao_ble.yaml index f8dfa743a86d0..3351b8f609e4d 100644 --- a/boards/seeed/xiao_ble/xiao_ble.yaml +++ b/boards/seeed/xiao_ble/xiao_ble.yaml @@ -17,7 +17,6 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/seeed/xiao_ble/xiao_ble_common.dtsi b/boards/seeed/xiao_ble/xiao_ble_common.dtsi index d031ce4b5b3d4..8ce71198e176e 100644 --- a/boards/seeed/xiao_ble/xiao_ble_common.dtsi +++ b/boards/seeed/xiao_ble/xiao_ble_common.dtsi @@ -54,7 +54,6 @@ bootloader-led0 = &led0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &p25q16h; }; }; diff --git a/boards/seeed/xiao_ble/xiao_ble_nrf52840_sense.yaml b/boards/seeed/xiao_ble/xiao_ble_nrf52840_sense.yaml index dfb8bc4e8afb7..9de9481776ab7 100644 --- a/boards/seeed/xiao_ble/xiao_ble_nrf52840_sense.yaml +++ b/boards/seeed/xiao_ble/xiao_ble_nrf52840_sense.yaml @@ -17,7 +17,6 @@ supported: - i2s - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/seeed/xiao_esp32c3/Kconfig.defconfig b/boards/seeed/xiao_esp32c3/Kconfig.defconfig index f70e724ed8e0c..4171bb04bc276 100644 --- a/boards/seeed/xiao_esp32c3/Kconfig.defconfig +++ b/boards/seeed/xiao_esp32c3/Kconfig.defconfig @@ -7,7 +7,3 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 51200 if WIFI default 40960 if BT default 4096 - -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice diff --git a/boards/seeed/xiao_esp32c3/support/openocd.cfg b/boards/seeed/xiao_esp32c3/support/openocd.cfg index 02754ff2a73c1..7421637880c78 100644 --- a/boards/seeed/xiao_esp32c3/support/openocd.cfg +++ b/boards/seeed/xiao_esp32c3/support/openocd.cfg @@ -3,4 +3,4 @@ set ESP_RTOS none source [find interface/esp_usb_jtag.cfg] source [find target/esp32c3.cfg] -adapter_khz 5000 +adapter speed 5000 diff --git a/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts b/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts index 5cea1004af625..68687958b8a2a 100644 --- a/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts +++ b/boards/seeed/xiao_esp32c3/xiao_esp32c3.dts @@ -21,6 +21,7 @@ zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; zephyr,canbus = &twai; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -29,10 +30,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -83,7 +80,6 @@ status = "okay"; pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &wifi { @@ -123,3 +119,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/seeed/xiao_esp32s3/Kconfig.defconfig b/boards/seeed/xiao_esp32s3/Kconfig.defconfig index 424820d78adc9..b9222985d8dd0 100644 --- a/boards/seeed/xiao_esp32s3/Kconfig.defconfig +++ b/boards/seeed/xiao_esp32s3/Kconfig.defconfig @@ -10,10 +10,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_XIAO_ESP32S3_ESP32S3_PROCPU if BOARD_XIAO_ESP32S3_ESP32S3_APPCPU diff --git a/boards/seeed/xiao_esp32s3/doc/index.rst b/boards/seeed/xiao_esp32s3/doc/index.rst index bbb1bf528aef5..cca9a3d8a274f 100644 --- a/boards/seeed/xiao_esp32s3/doc/index.rst +++ b/boards/seeed/xiao_esp32s3/doc/index.rst @@ -38,7 +38,6 @@ Current Zephyr's XIAO ESP32S3 board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.dts b/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.dts index 672c52a5cbac5..f2cf95742ac14 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.dts +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.dts @@ -17,14 +17,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &trng0 { status = "okay"; }; diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.yaml b/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.yaml index 5d66048e03880..53055263f3465 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.yaml +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_appcpu.yaml @@ -1,5 +1,5 @@ identifier: xiao_esp32s3/esp32s3/appcpu -name: XIAO ESP32S3 +name: XIAO ESP32S3 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts index 99d7f0deb75fb..2c1349b735c4c 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.dts @@ -20,6 +20,7 @@ zephyr,shell-uart = &usb_serial; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; aliases { @@ -38,14 +39,6 @@ }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &usb_serial { status = "okay"; }; @@ -91,7 +84,6 @@ &twai { pinctrl-0 = <&twai_default>; pinctrl-names = "default"; - bus-speed = <125000>; }; &timer0 { @@ -136,3 +128,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.yaml b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.yaml index 8a1ace79ba69a..d438611cb3373 100644 --- a/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.yaml +++ b/boards/seeed/xiao_esp32s3/xiao_esp32s3_procpu.yaml @@ -1,5 +1,5 @@ identifier: xiao_esp32s3/esp32s3/procpu -name: XIAO ESP32S3 +name: XIAO ESP32S3 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/seeed/xiao_rp2040/Kconfig.defconfig b/boards/seeed/xiao_rp2040/Kconfig.defconfig new file mode 100644 index 0000000000000..e2af832cdcaec --- /dev/null +++ b/boards/seeed/xiao_rp2040/Kconfig.defconfig @@ -0,0 +1,19 @@ +# Copyright (c) 2023 Seeed Studio inc. +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_XIAO_RP2040 + +config RP2_FLASH_W25Q080 + default y + +if I2C_DW + +config I2C_DW_CLOCK_SPEED + default 125 + +endif # I2C_DW + +config USB_SELF_POWERED + default n + +endif # BOARD_XIAO_RP2040 diff --git a/boards/seeed/xiao_rp2040/Kconfig.xiao_rp2040 b/boards/seeed/xiao_rp2040/Kconfig.xiao_rp2040 new file mode 100644 index 0000000000000..8bd3d0d2d1554 --- /dev/null +++ b/boards/seeed/xiao_rp2040/Kconfig.xiao_rp2040 @@ -0,0 +1,7 @@ +# XIAO RP2040 board configuration + +# Copyright (c) 2023 Seeed Studio inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_XIAO_RP2040 + select SOC_RP2040 diff --git a/boards/seeed/xiao_rp2040/board.cmake b/boards/seeed/xiao_rp2040/board.cmake new file mode 100644 index 0000000000000..4103e36e63569 --- /dev/null +++ b/boards/seeed/xiao_rp2040/board.cmake @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(uf2 "--board-id=RPI-RP2") + +include(${ZEPHYR_BASE}/boards/common/uf2.board.cmake) diff --git a/boards/seeed/xiao_rp2040/board.yml b/boards/seeed/xiao_rp2040/board.yml new file mode 100644 index 0000000000000..7eaca9159728c --- /dev/null +++ b/boards/seeed/xiao_rp2040/board.yml @@ -0,0 +1,5 @@ +board: + name: xiao_rp2040 + vendor: seeed + socs: + - name: rp2040 diff --git a/boards/seeed/xiao_rp2040/doc/img/xiao_rp2040.webp b/boards/seeed/xiao_rp2040/doc/img/xiao_rp2040.webp new file mode 100644 index 0000000000000..5233046000ae6 Binary files /dev/null and b/boards/seeed/xiao_rp2040/doc/img/xiao_rp2040.webp differ diff --git a/boards/seeed/xiao_rp2040/doc/img/xiao_rp2040_pinout.webp b/boards/seeed/xiao_rp2040/doc/img/xiao_rp2040_pinout.webp new file mode 100644 index 0000000000000..cb295b073d46b Binary files /dev/null and b/boards/seeed/xiao_rp2040/doc/img/xiao_rp2040_pinout.webp differ diff --git a/boards/seeed/xiao_rp2040/doc/index.rst b/boards/seeed/xiao_rp2040/doc/index.rst new file mode 100644 index 0000000000000..7206e9be07f58 --- /dev/null +++ b/boards/seeed/xiao_rp2040/doc/index.rst @@ -0,0 +1,138 @@ +.. _xiao_rp2040: + +XIAO RP2040 +########### + +Overview +******** + +The XIAO RP2040 is an IoT mini development board from Seeed Studio. +It is equipped with an RP2040 SoC, an on-board WS2812 addressable +LED, and USB connector. The USB bootloader allows it +to be flashed without any adapter, in a drag-and-drop manner. + +For more details see the `Seeed Studio XIAO RP2040`_ wiki page. + +.. figure:: img/xiao_rp2040.webp + :align: center + :alt: XIAO RP2040 + + XIAO RP2040 + +Hardware +******** + +The Seeed Studio XIAO RP2040 is a low-power microcontroller that +carries the powerful Dual-core RP2040 processor with a flexible +clock running up to 133 MHz. There is also 264KB of SRAM, and 2MB of +on-board Flash memory. + +There are 14 GPIO PINs on Seeed Studio XIAO RP2040, on which there +are 11 digital pins, 4 analog pins, 11 PWM Pins,1 I2C interface, +1 UART interface, 1 SPI interface, 1 SWD Bonding pad interface. + +Supported Features +================== + +The ``xiao_rp2040`` board target supports the following hardware +features: + +.. list-table:: + :header-rows: 1 + + * - Peripheral + - Kconfig option + - Devicetree compatible + * - NVIC + - N/A + - :dtcompatible:`arm,v6m-nvic` + * - UART + - :kconfig:option:`CONFIG_SERIAL` + - :dtcompatible:`raspberrypi,pico-uart` + * - GPIO + - :kconfig:option:`CONFIG_GPIO` + - :dtcompatible:`raspberrypi,pico-gpio` + * - ADC + - :kconfig:option:`CONFIG_ADC` + - :dtcompatible:`raspberrypi,pico-adc` + * - I2C + - :kconfig:option:`CONFIG_I2C` + - :dtcompatible:`snps,designware-i2c` + * - SPI + - :kconfig:option:`CONFIG_SPI` + - :dtcompatible:`raspberrypi,pico-spi` + * - USB Device + - :kconfig:option:`CONFIG_USB_DEVICE_STACK` + - :dtcompatible:`raspberrypi,pico-usbd` + * - HWINFO + - :kconfig:option:`CONFIG_HWINFO` + - N/A + * - Watchdog Timer (WDT) + - :kconfig:option:`CONFIG_WATCHDOG` + - :dtcompatible:`raspberrypi,pico-watchdog` + * - PWM + - :kconfig:option:`CONFIG_PWM` + - :dtcompatible:`raspberrypi,pico-pwm` + * - Flash + - :kconfig:option:`CONFIG_FLASH` + - :dtcompatible:`raspberrypi,pico-flash-controller` + * - Clock controller + - :kconfig:option:`CONFIG_CLOCK_CONTROL` + - :dtcompatible:`raspberrypi,pico-clock-controller` + * - UART (PIO) + - :kconfig:option:`CONFIG_SERIAL` + - :dtcompatible:`raspberrypi,pico-uart-pio` + +Pin Mapping +=========== + +The peripherals of the RP2040 SoC can be routed to various pins on the board. +The configuration of these routes can be modified through DTS. Please refer to +the datasheet to see the possible routings for each peripheral. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +.. rst-class:: rst-columns + +- UART0_TX : P0 +- UART0_RX : P1 +- I2C1_SDA : P6 +- I2C1_SCL : P7 +- SPI0_RX : P4 +- SPI0_SCK : P2 +- SPI0_TX : P3 + +Connections and IOs +=================== + +The board uses a standard XIAO pinout, the default pin mapping is the following: + +.. figure:: img/xiao_rp2040_pinout.webp + :align: center + :alt: XIAO RP2040 Pinout + + XIAO RP2040 Pinout + +Programming and Debugging +************************* + +Flashing +======== + +Using UF2 +--------- + +You can flash the Xiao RP2040 with a UF2 file. +By default, building an app for this board will generate a +:file:`build/zephyr/zephyr.uf2` file. If the Xiao RP2040 is powered on with +the ``BOOTSEL`` button pressed, it will appear on the host as a mass storage +device. The UF2 file should be copied to the device, which will +flash the Xiao RP2040. + +References +********** + +.. target-notes:: + +.. _`Seeed Studio XIAO RP2040`: https://wiki.seeedstudio.com/XIAO-RP2040/ diff --git a/boards/seeed/xiao_rp2040/seeed_xiao_connector.dtsi b/boards/seeed/xiao_rp2040/seeed_xiao_connector.dtsi new file mode 100644 index 0000000000000..d0e9152cefd08 --- /dev/null +++ b/boards/seeed/xiao_rp2040/seeed_xiao_connector.dtsi @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2023 Seeed Studio inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + xiao_d: connector { + compatible = "seeed,xiao-gpio"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map + = <0 0 &gpio0 26 0> /* D0 */ + , <1 0 &gpio0 27 0> /* D1 */ + , <2 0 &gpio0 28 0> /* D2 */ + , <3 0 &gpio0 29 0> /* D3 */ + , <4 0 &gpio0 6 0> /* D4 */ + , <5 0 &gpio0 7 0> /* D5 */ + , <6 0 &gpio0 0 0> /* D6 */ + , <7 0 &gpio0 1 0> /* D7 */ + , <8 0 &gpio0 2 0> /* D8 */ + , <9 0 &gpio0 4 0> /* D9 */ + , <10 0 &gpio0 3 0> /* D10 */ + ; + }; +}; + +xiao_i2c: &i2c1 { +}; +xiao_spi: &spi0 { +}; +xiao_serial: &uart0 { +}; diff --git a/boards/seeed/xiao_rp2040/xiao_rp2040-pinctrl.dtsi b/boards/seeed/xiao_rp2040/xiao_rp2040-pinctrl.dtsi new file mode 100644 index 0000000000000..0e235884bf22c --- /dev/null +++ b/boards/seeed/xiao_rp2040/xiao_rp2040-pinctrl.dtsi @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021 Yonatan Schachter + * Copyright (c) 2023 Seeed Studio inc. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + i2c1_default: i2c1_default { + group1 { + pinmux = ; + input-enable; + }; + group2 { + pinmux = ; + input-enable; + }; + }; + + pwm_ch4b_default: pwm_ch4b_default { + group1 { + pinmux = ; + }; + }; + + spi0_default: spi0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + group3 { + pinmux = ; + }; + }; + + adc_default: adc_default { + group1 { + pinmux = , + , + , + ; + input-enable; + }; + }; + + clocks_default: clocks_default { + }; + + ws2812_pio0_default: ws2812_pio0_default { + ws2812 { + pinmux = ; + }; + }; +}; diff --git a/boards/seeed/xiao_rp2040/xiao_rp2040.dts b/boards/seeed/xiao_rp2040/xiao_rp2040.dts new file mode 100644 index 0000000000000..0a52f47d672d4 --- /dev/null +++ b/boards/seeed/xiao_rp2040/xiao_rp2040.dts @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021 Yonatan Schachter + * Copyright (c) 2023 Seeed Studio inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "xiao_rp2040-pinctrl.dtsi" +#include "seeed_xiao_connector.dtsi" +#include +#include +#include + +/ { + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,flash-controller = &ssi; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,code-partition = &code_partition; + }; + + aliases { + watchdog0 = &wdt0; + led-strip = &ws2812; + pwm-led0 = &pwm_led0; + led0 = &blue_led; + led1 = &green_led; + led2 = &red_led; + }; + + pwm_leds { + compatible = "pwm-leds"; + status = "disabled"; + pwm_led0: pwm_led_0 { + pwms = <&pwm 9 PWM_MSEC(20) PWM_POLARITY_INVERTED>; + label = "PWM_LED"; + }; + }; + + leds { + compatible = "gpio-leds"; + + blue_led: blue_led { + gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + label = "BLUE_LED"; + }; + + green_led: green_led { + gpios = <&gpio0 16 GPIO_ACTIVE_LOW>; + label = "GREEN_LED"; + }; + + red_led: red_led { + gpios = <&gpio0 17 GPIO_ACTIVE_LOW>; + label = "RED_LED"; + }; + }; +}; + +&pwm { + pinctrl-0 = <&pwm_ch4b_default>; + pinctrl-names = "default"; + divider-int-0 = <255>; +}; + +&flash0 { + /* + * 2MB of flash minus the 0x100 used for the second stage bootloader + */ + reg = <0x10000000 DT_SIZE_M(2)>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + code_partition: partition@100 { + label = "code"; + reg = <0x100 (DT_SIZE_M(2) - 0x100)>; + read-only; + }; + }; +}; + +&clocks { + pinctrl-0 = <&clocks_default>; + pinctrl-names = "default"; +}; + +&timer { + status = "okay"; +}; + +&uart0 { + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&i2c1 { + status = "okay"; + pinctrl-0 = <&i2c1_default>; + pinctrl-names = "default"; + clock-frequency = ; +}; + +&spi0 { + status = "okay"; + pinctrl-0 = <&spi0_default>; + pinctrl-names = "default"; + clock-frequency = ; +}; + +&gpio0 { + status = "okay"; + + /* + * The neopixel on this board has its positive side hooked up to a GPIO pin + * rather than a positive voltage rail to save on power. This will enable + * the LED on board initialization. + */ + neopixel-power-enable { + gpio-hog; + gpios = <11 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&wdt0 { + status = "okay"; +}; + +&adc { + status = "okay"; + pinctrl-0 = <&adc_default>; + pinctrl-names = "default"; +}; + +&pio0 { + status = "okay"; + + pio-ws2812 { + compatible = "worldsemi,ws2812-rpi_pico-pio"; + status = "okay"; + pinctrl-0 = <&ws2812_pio0_default>; + pinctrl-names = "default"; + bit-waveform = <3>, <3>, <4>; + + ws2812: ws2812 { + status = "okay"; + gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + chain-length = <1>; + color-mapping = ; + reset-delay = <280>; + frequency = <800000>; + }; + }; +}; + +zephyr_udc0: &usbd { + status = "okay"; +}; + +&vreg { + regulator-always-on; + regulator-allowed-modes = ; +}; diff --git a/boards/seeed/xiao_rp2040/xiao_rp2040.yaml b/boards/seeed/xiao_rp2040/xiao_rp2040.yaml new file mode 100644 index 0000000000000..b2852757aa3af --- /dev/null +++ b/boards/seeed/xiao_rp2040/xiao_rp2040.yaml @@ -0,0 +1,24 @@ +identifier: xiao_rp2040 +name: XIAO RP2040 +type: mcu +arch: arm +flash: 2048 +ram: 256 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - uart + - gpio + - adc + - i2c + - spi + - hwinfo + - watchdog + - pwm + - flash + - dma + - counter + - clock +vendor: seeed diff --git a/boards/seeed/xiao_rp2040/xiao_rp2040_defconfig b/boards/seeed/xiao_rp2040/xiao_rp2040_defconfig new file mode 100644 index 0000000000000..ef4e863884ab5 --- /dev/null +++ b/boards/seeed/xiao_rp2040/xiao_rp2040_defconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=125000000 +CONFIG_RESET=y + +# Enable UART driver +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y + +# Enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable clock control by default +CONFIG_CLOCK_CONTROL=y + +# Code partition needed to target the correct flash range +CONFIG_USE_DT_CODE_PARTITION=y + +# Output UF2 by default, native bootloader supports it. +CONFIG_BUILD_OUTPUT_UF2=y diff --git a/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay b/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay index 59136c9b45bca..8c44347e63f1d 100644 --- a/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay +++ b/boards/shields/adafruit_2_8_tft_touch_v2/boards/rd_rw612_bga.overlay @@ -16,6 +16,7 @@ * directly and does not require the MIPI DBI SPI node */ /delete-node/ mipi_dbi; + /delete-node/ adafruit_2_8_tft_touch_v2_mipi_dbi; }; &lcdic { diff --git a/boards/shields/adafruit_2_8_tft_touch_v2/dts/adafruit_2_8_tft_touch_v2.dtsi b/boards/shields/adafruit_2_8_tft_touch_v2/dts/adafruit_2_8_tft_touch_v2.dtsi index 9413a7834d981..9a8d5069c3785 100644 --- a/boards/shields/adafruit_2_8_tft_touch_v2/dts/adafruit_2_8_tft_touch_v2.dtsi +++ b/boards/shields/adafruit_2_8_tft_touch_v2/dts/adafruit_2_8_tft_touch_v2.dtsi @@ -19,7 +19,7 @@ invert-y; }; - adafruit_2_8_tft_touch_v2_mipi_dbi { + adafruit_2_8_tft_touch_v2_mipi_dbi: adafruit_2_8_tft_touch_v2_mipi_dbi { compatible = "zephyr,mipi-dbi-spi"; spi-dev = <&arduino_spi>; dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ diff --git a/boards/shields/arceli_eth_w5500/doc/index.rst b/boards/shields/arceli_eth_w5500/doc/index.rst index 467559be88163..fa1f4baf90fe5 100644 --- a/boards/shields/arceli_eth_w5500/doc/index.rst +++ b/boards/shields/arceli_eth_w5500/doc/index.rst @@ -6,7 +6,7 @@ ARCELI W5500 ETH Overview ******** -ARCELI W5500 etherner is breakout board with SPI bus access over 10 pin header. +ARCELI W5500 Ethernet is breakout board with SPI bus access over 10 pin header. `W5500`_ is 10/100 MBPS stand alone Ethernet controller with on-board MAC & PHY, 16 KiloBytes for FIFO buffer and SPI serial interface. @@ -53,4 +53,4 @@ References .. target-notes:: .. _W5500: - https://www.wiznet.io/product-item/w5500/ + https://wiznet.io/products/iethernet-chips/w5500 diff --git a/boards/shields/arduino_uno_click/boards/nrf9160dk_nrf9160.overlay b/boards/shields/arduino_uno_click/boards/nrf9160dk_nrf9160.overlay new file mode 100644 index 0000000000000..539c112fd639c --- /dev/null +++ b/boards/shields/arduino_uno_click/boards/nrf9160dk_nrf9160.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024 Golioth, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf9160dk_nrf9160_arduino_uno_click_common.dtsi" diff --git a/boards/shields/arduino_uno_click/boards/nrf9160dk_nrf9160_arduino_uno_click_common.dtsi b/boards/shields/arduino_uno_click/boards/nrf9160dk_nrf9160_arduino_uno_click_common.dtsi new file mode 100644 index 0000000000000..925a4c41e482f --- /dev/null +++ b/boards/shields/arduino_uno_click/boards/nrf9160dk_nrf9160_arduino_uno_click_common.dtsi @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 Golioth, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + /* + * The original Arduino Uno provides the same SCL/SDA on two sets of + * pins, but the nRF9160 DK maps these pins to two different pairs of + * GPIO. When using the Arduino Uno Click Shield board with the nRF9160 + * DK, the P0.18/P0.19 pair must be used. + */ + i2c2_default: i2c2_default { + group1 { + psels = , + ; + }; + }; + + i2c2_sleep: i2c2_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + /* + * The default pin group for the nRF9160 DK includes RTS/CTS HW flow + * control, but the Arduino Uno Click Shield board does not connect + * these pins (only TX/RX are connected on the shield). This keeps RX/TX + * on the same pins, but just removes RTS/CTS from the pin groups. + */ + uart1_default: uart1_default { + group1 { + psels = , + ; + }; + }; + + uart1_sleep: uart1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; +}; diff --git a/boards/shields/arduino_uno_click/boards/nrf9160dk_nrf9160_ns.overlay b/boards/shields/arduino_uno_click/boards/nrf9160dk_nrf9160_ns.overlay new file mode 100644 index 0000000000000..539c112fd639c --- /dev/null +++ b/boards/shields/arduino_uno_click/boards/nrf9160dk_nrf9160_ns.overlay @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024 Golioth, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrf9160dk_nrf9160_arduino_uno_click_common.dtsi" diff --git a/boards/shields/dvp_fpc24_mt9m114/Kconfig.shield b/boards/shields/dvp_fpc24_mt9m114/Kconfig.shield new file mode 100644 index 0000000000000..187fbec05cba6 --- /dev/null +++ b/boards/shields/dvp_fpc24_mt9m114/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_DVP_FPC24_MT9M114 + def_bool $(shields_list_contains,DVP_FPC24_MT9M114) diff --git a/boards/shields/dvp_fpc24_mt9m114/boards/mimxrt1064_evk.overlay b/boards/shields/dvp_fpc24_mt9m114/boards/mimxrt1064_evk.overlay new file mode 100644 index 0000000000000..a4aa7a273080d --- /dev/null +++ b/boards/shields/dvp_fpc24_mt9m114/boards/mimxrt1064_evk.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&dvp_fpc24_interface { + source = <&mt9m114>; +}; diff --git a/boards/shields/dvp_fpc24_mt9m114/doc/index.rst b/boards/shields/dvp_fpc24_mt9m114/doc/index.rst new file mode 100644 index 0000000000000..3acf9693f06de --- /dev/null +++ b/boards/shields/dvp_fpc24_mt9m114/doc/index.rst @@ -0,0 +1,92 @@ +.. _dvp_fpc24_mt9m114: + +DVP FPC-24 MT9M114 Camera Module +################################ + +Overview +******** + +This shield supports mt9m114 camera modules which use a 24-pin FPC connector and a DVP +(Digital Video Port), aka parallel interface. These camera modules are compatible and provided +together with the i.MX RT1050, RT1060 and RT1064 EVKs as specified here `Camera iMXRT`_. + +Pins assignment of the DVP FPC-24 MT9M114 camera module +======================================================= + ++-------------------+--------------+ +| FPC Connector Pin | Function | ++===================+==============+ +| 1 | NC | ++-------------------+--------------+ +| 2 | AGND | ++-------------------+--------------+ +| 3 | SDA | ++-------------------+--------------+ +| 4 | AVDD | ++-------------------+--------------+ +| 5 | SCL | ++-------------------+--------------+ +| 6 | Reset | ++-------------------+--------------+ +| 7 | Vsync | ++-------------------+--------------+ +| 8 | Powerdown | ++-------------------+--------------+ +| 9 | Hsync | ++-------------------+--------------+ +| 10 | DVDD | ++-------------------+--------------+ +| 11 | DOVDD | ++-------------------+--------------+ +| 12 | Data 9 | ++-------------------+--------------+ +| 13 | Master Clock | ++-------------------+--------------+ +| 14 | Data 8 | ++-------------------+--------------+ +| 15 | DGND | ++-------------------+--------------+ +| 16 | Data 7 | ++-------------------+--------------+ +| 17 | Pixel Clock | ++-------------------+--------------+ +| 18 | Data 6 | ++-------------------+--------------+ +| 19 | Data 2 | ++-------------------+--------------+ +| 20 | Data 5 | ++-------------------+--------------+ +| 21 | Data 3 | ++-------------------+--------------+ +| 22 | Data 4 | ++-------------------+--------------+ +| 23 | Data 1 | ++-------------------+--------------+ +| 24 | Data 0 | ++-------------------+--------------+ + + +Requirements +************ + +This shield can only be used with a board which provides a configuration for a 24-pins FPC +connector with DVP (parallel) interface, such as the i.MX RT1050, RT1060, RT1064 EVKs. + +Programming +*********** + +Set ``-DSHIELD=dvp_fpc24_mt9m114`` when you invoke ``west build``. For example: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/video/capture + :board: mimxrt1064_evk + :shield: dvp_fpc24_mt9m114 + :goals: build + +References +********** + +.. target-notes:: + +.. _Camera iMXRT: + https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/Connecting-camera-and-LCD-to-i-MX-RT-EVKs/ta-p/1122183 diff --git a/boards/shields/dvp_fpc24_mt9m114/dvp_fpc24_mt9m114.overlay b/boards/shields/dvp_fpc24_mt9m114/dvp_fpc24_mt9m114.overlay new file mode 100644 index 0000000000000..52988535182d3 --- /dev/null +++ b/boards/shields/dvp_fpc24_mt9m114/dvp_fpc24_mt9m114.overlay @@ -0,0 +1,34 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/{ + chosen { + zephyr,camera = &dvp_fpc24_interface; + }; +}; + +&dvp_fpc24_i2c { + mt9m114: mt9m114@48 { + compatible = "aptina,mt9m114"; + reg = <0x48>; + + port { + mt9m114_ep_out: endpoint { + remote-endpoint = <&dfi_ep_in>; + }; + }; + }; +}; + +&dvp_fpc24_interface { + status = "okay"; + + port { + dfi_ep_in: endpoint { + remote-endpoint = <&mt9m114_ep_out>; + }; + }; +}; diff --git a/boards/shields/frdm_kw41z/frdm_kw41z.overlay b/boards/shields/frdm_kw41z/frdm_kw41z.overlay index 3807b2f6a2dab..8e9f14fbfb433 100644 --- a/boards/shields/frdm_kw41z/frdm_kw41z.overlay +++ b/boards/shields/frdm_kw41z/frdm_kw41z.overlay @@ -6,11 +6,16 @@ / { chosen { - zephyr,bt-uart = &arduino_serial; + zephyr,bt-hci = &bt_hci_uart; }; }; &arduino_serial { status = "okay"; current-speed = <115200>; + + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + }; }; diff --git a/boards/shields/lcd_par_s035/Kconfig.defconfig b/boards/shields/lcd_par_s035/Kconfig.defconfig new file mode 100644 index 0000000000000..07f0bb7bab1af --- /dev/null +++ b/boards/shields/lcd_par_s035/Kconfig.defconfig @@ -0,0 +1,16 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_LCD_PAR_S035 +if LVGL + +# Enable double buffering +config LV_Z_DOUBLE_VDB + default y + +config LV_Z_BITS_PER_PIXEL + default 16 + +endif # LVGL + +endif # SHIELD_LCD_PAR_S035 diff --git a/boards/shields/lcd_par_s035/Kconfig.shield b/boards/shields/lcd_par_s035/Kconfig.shield new file mode 100644 index 0000000000000..4dba938831b0a --- /dev/null +++ b/boards/shields/lcd_par_s035/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_LCD_PAR_S035 + def_bool $(shields_list_contains,lcd_par_s035_8080) diff --git a/boards/shields/lcd_par_s035/doc/index.rst b/boards/shields/lcd_par_s035/doc/index.rst new file mode 100644 index 0000000000000..fdaa6307e6856 --- /dev/null +++ b/boards/shields/lcd_par_s035/doc/index.rst @@ -0,0 +1,40 @@ +.. _lcd_par_s035: + +NXP LCD_PAR_S035 TFT LCD Module +############################### + +Overview +******** + +The LCD-PAR-S035 is a 3.5” 480x320 IPS TFT LCD module with wide viewing angle +and 5-point capacitive touch functionality. The LCD module can be controlled +through either SPI or parallel (8/16bit) 8080/6800. +More information about the shield can be found +at the `LCD-PAR-S035 product page`_. + +Requirements +************ + +This shield can only be used with FRDM-X evaluation kits with a parallel LCD +connector or a PMOD connector. Currently only the parallel LCD connector is +enabled. + +Programming +*********** + +Set ``-DSHIELD=lcd_par_s035_8080`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/display + :board: frdm_mcxn947/mcxn947/cpu0 + :shield: lcd_par_s035_8080 + :goals: build + +References +********** + +.. target-notes:: + +.. _LCD-PAR-S035 product page: + https://www.nxp.com/design/design-center/development-boards-and-designs/general-purpose-mcus/3-5-480x320-ips-tft-lcd-module:LCD-PAR-S035 diff --git a/boards/shields/lcd_par_s035/lcd_par_s035_8080.overlay b/boards/shields/lcd_par_s035/lcd_par_s035_8080.overlay new file mode 100644 index 0000000000000..eaf7b8b9c03fb --- /dev/null +++ b/boards/shields/lcd_par_s035/lcd_par_s035_8080.overlay @@ -0,0 +1,41 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + chosen { + zephyr,display = &st7796s; + }; +}; + +&nxp_flexio_lcd { + status = "okay"; + #address-cells = <1>; + #size-cells = <0>; + st7796s: st7796s@0 { + compatible = "sitronix,st7796s"; + reg = <0>; + /* Baud rate on each pin is 1MHz */ + mipi-max-frequency = <10000000>; + mipi-mode = ; + height = <320>; + width = <480>; + invert-mode = "1-dot"; + frmctl1 = [80 10]; + bpc = [1F 50 00 20]; + dfc = [8A 07 3B]; + pwr1 = [80 64]; + pwr2 = <0x13>; + pwr3 = <0xA7>; + vcmpctl = <0x09>; + doca = [40 8A 00 00 29 19 A5 33]; + pgc = [F0 06 0B 07 06 05 2E 33 47 3A 17 16 2E 31]; + ngc = [F0 09 0D 09 08 23 2E 33 46 38 13 13 2C 32]; + madctl = <0x28>; + color-invert; + }; +}; diff --git a/boards/shields/lmp90100_evb/doc/index.rst b/boards/shields/lmp90100_evb/doc/index.rst index f3a1ff36ed3ed..689257e251fb7 100644 --- a/boards/shields/lmp90100_evb/doc/index.rst +++ b/boards/shields/lmp90100_evb/doc/index.rst @@ -50,7 +50,7 @@ Set ``-DSHIELD=lmp90100_evb`` when you invoke ``west build``. For example: :goals: build .. _LMP90100 Sensor AFE Evaluation Board User's Guide: - http://www.ti.com/lit/pdf/snau028 + https://www.farnell.com/datasheets/1604987.pdf .. _LMP90100 Multi-Channel, Low Power 24-Bit Sensor AFE: http://www.ti.com/product/LMP90100 diff --git a/boards/shields/lmp90100_evb/lmp90100_evb.overlay b/boards/shields/lmp90100_evb/lmp90100_evb.overlay index 7271c9c7c3deb..e30840dd10bde 100644 --- a/boards/shields/lmp90100_evb/lmp90100_evb.overlay +++ b/boards/shields/lmp90100_evb/lmp90100_evb.overlay @@ -32,7 +32,7 @@ status = "okay"; eeprom0_lmp90100_evb: eeprom@57 { - compatible = "atmel,at24"; + compatible = "atmel,at24c02", "atmel,at24"; reg = <0x57>; size = <256>; pagesize = <8>; diff --git a/boards/shields/mcp2515/adafruit_can_picowbell.overlay b/boards/shields/mcp2515/adafruit_can_picowbell.overlay index 8a9d719e641ab..9e86a3236d35a 100644 --- a/boards/shields/mcp2515/adafruit_can_picowbell.overlay +++ b/boards/shields/mcp2515/adafruit_can_picowbell.overlay @@ -15,7 +15,6 @@ status = "okay"; reg = <0x0>; osc-freq = <16000000>; - bus-speed = <125000>; can-transceiver { max-bitrate = <1000000>; diff --git a/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay b/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay index e520218830ec5..290522d8c921f 100644 --- a/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay +++ b/boards/shields/mcp2515/dfrobot_can_bus_v2_0.overlay @@ -15,7 +15,6 @@ status = "okay"; reg = <0x0>; osc-freq = <16000000>; - bus-speed = <125000>; can-transceiver { min-bitrate = <60000>; diff --git a/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay b/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay index e4136cf577bf3..d1f988f281ed7 100644 --- a/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay +++ b/boards/shields/mcp2515/keyestudio_can_bus_ks0411.overlay @@ -15,7 +15,6 @@ status = "okay"; reg = <0x0>; osc-freq = <16000000>; - bus-speed = <125000>; can-transceiver { max-bitrate = <1000000>; diff --git a/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay b/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay index 43094d1d72ae7..522017c81eac6 100644 --- a/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay +++ b/boards/shields/mikroe_mcp2518fd_click/mikroe_mcp2518fd_click.overlay @@ -10,8 +10,6 @@ reg = <0x0>; osc-freq = <40000000>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; }; diff --git a/boards/shields/nxp_btb44_ov5640/Kconfig.shield b/boards/shields/nxp_btb44_ov5640/Kconfig.shield new file mode 100644 index 0000000000000..608188a2c54b0 --- /dev/null +++ b/boards/shields/nxp_btb44_ov5640/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_NXP_BTB44_OV5640 + def_bool $(shields_list_contains,nxp_btb44_ov5640) diff --git a/boards/shields/nxp_btb44_ov5640/doc/index.rst b/boards/shields/nxp_btb44_ov5640/doc/index.rst new file mode 100644 index 0000000000000..299878dc2d119 --- /dev/null +++ b/boards/shields/nxp_btb44_ov5640/doc/index.rst @@ -0,0 +1,134 @@ +.. _nxp_btb44_ov5640: + +NXP BTB-44 OV5640 Camera Module +############################### + +Overview +******** + +This shield supports ov5640 camera modules which use a 44-pin board-to-board connector and +a MIPI CSI or DVP (parallel) interface. These camera modules are made specifically for and +provided together with NXP's i.MX RT1160 and RT1170 EVK boards. + +More information about this OV5640 camera module can be found at `Camera iMXRT`_. + +Pins assignment of the NXP board-to-board 44-pin OV5640 camera module +====================================================================== + ++----------------------+--------------------+ +| Camera Connector Pin | Function | ++======================+====================+ +| 1 | AGND | ++----------------------+--------------------+ +| 2 | AF_GND | ++----------------------+--------------------+ +| 3 | STROBE | ++----------------------+--------------------+ +| 4 | AF_VCC | ++----------------------+--------------------+ +| 5 | SDA | ++----------------------+--------------------+ +| 6 | VCMSINK | ++----------------------+--------------------+ +| 7 | SCL | ++----------------------+--------------------+ +| 8 | AVDD | ++----------------------+--------------------+ +| 9 | RESETB | ++----------------------+--------------------+ +| 10 | GPIO1 | ++----------------------+--------------------+ +| 11 | PCLK | ++----------------------+--------------------+ +| 12 | GPIO0 | ++----------------------+--------------------+ +| 13 | VSYNC | ++----------------------+--------------------+ +| 14 | FREX | ++----------------------+--------------------+ +| 15 | HREF | ++----------------------+--------------------+ +| 16 | MIPI_CSI_DP1 / D9 | ++----------------------+--------------------+ +| 17 | PWDN | ++----------------------+--------------------+ +| 18 | MIPI_CSI_DN1 / D8 | ++----------------------+--------------------+ +| 19 | MIPI_CSI_DP1 / D9 | ++----------------------+--------------------+ +| 20 | DGND | ++----------------------+--------------------+ +| 21 | MIPI_CSI_DN1 / D8 | ++----------------------+--------------------+ +| 22 | MIPI_CSI_CLKP / D7 | ++----------------------+--------------------+ +| 23 | MIPI_CSI_CLKP / D7 | ++----------------------+--------------------+ +| 24 | MIPI_CSI_CLKN / D6 | ++----------------------+--------------------+ +| 25 | MIPI_CSI_CLKN / D6 | ++----------------------+--------------------+ +| 26 | DGND | ++----------------------+--------------------+ +| 27 | MIPI_CSI_DP0 / D5 | ++----------------------+--------------------+ +| 28 | MIPI_CSI_DP0 / D5 | ++----------------------+--------------------+ +| 29 | MIPI_CSI_DN0 / D4 | ++----------------------+--------------------+ +| 30 | MIPI_CSI_DN0 / D4 | ++----------------------+--------------------+ +| 31 | D3 | ++----------------------+--------------------+ +| 32 | DGND | ++----------------------+--------------------+ +| 33 | D2 | ++----------------------+--------------------+ +| 34 | XCLK | ++----------------------+--------------------+ +| 35 | D1 | ++----------------------+--------------------+ +| 36 | DVDD | ++----------------------+--------------------+ +| 37 | D0 | ++----------------------+--------------------+ +| 38 | DOVDD | ++----------------------+--------------------+ +| 39 | DGND | ++----------------------+--------------------+ +| 40 | DGND | ++----------------------+--------------------+ +| 41 | GND | ++----------------------+--------------------+ +| 42 | GND | ++----------------------+--------------------+ +| 43 | GND | ++----------------------+--------------------+ +| 44 | AF_GND | ++----------------------+--------------------+ + +Requirements +************ + +This shield can only be used with a board which provides a 44-pin board-to-board +connector with MIPI CSI or DVP (parallel) interface where the pinouts are defined +as above, such as i.MX RT1160 and RT1170 EVK boards. + +Programming +*********** + +Set ``-DSHIELD=nxp_btb44_ov5640`` when you invoke ``west build``. For example: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/video/capture + :board: mimxrt1170_evk/mimxrt1176/cm7 + :shield: nxp_btb44_ov5640 + :goals: build + +References +********** + +.. target-notes:: + +.. _Camera iMXRT: + https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/Connecting-camera-and-LCD-to-i-MX-RT-EVKs/ta-p/1122183 diff --git a/boards/shields/nxp_btb44_ov5640/nxp_btb44_ov5640.overlay b/boards/shields/nxp_btb44_ov5640/nxp_btb44_ov5640.overlay new file mode 100644 index 0000000000000..7f9848fd7a29e --- /dev/null +++ b/boards/shields/nxp_btb44_ov5640/nxp_btb44_ov5640.overlay @@ -0,0 +1,48 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/{ + chosen { + zephyr,camera = &nxp_csi; + }; +}; + +&nxp_cam_i2c { + status = "okay"; + + ov5640: ov5640@3c { + compatible = "ovti,ov5640"; + reg = <0x3c>; + reset-gpios = <&nxp_cam_connector 9 GPIO_ACTIVE_LOW>; + powerdown-gpios = <&nxp_cam_connector 17 GPIO_ACTIVE_HIGH>; + + port { + ov5640_ep_out: endpoint { + remote-endpoint = <&mipi_csi2rx_ep_in>; + }; + }; + }; +}; + +&nxp_mipi_csi { + status = "okay"; + + sensor = <&ov5640>; + + ports { + port@1 { + reg = <1>; + + mipi_csi2rx_ep_in: endpoint { + remote-endpoint = <&ov5640_ep_out>; + }; + }; + }; +}; + +&nxp_csi { + status = "okay"; +}; diff --git a/boards/shields/reyax_lora/Kconfig.shield b/boards/shields/reyax_lora/Kconfig.shield new file mode 100644 index 0000000000000..c82a3eacc27b4 --- /dev/null +++ b/boards/shields/reyax_lora/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2024 David Ullmann +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_REYAX_LORA + def_bool $(shields_list_contains,reyax_lora) diff --git a/boards/shields/reyax_lora/boards/cy8ckit_062s4.conf b/boards/shields/reyax_lora/boards/cy8ckit_062s4.conf new file mode 100644 index 0000000000000..30752249749fa --- /dev/null +++ b/boards/shields/reyax_lora/boards/cy8ckit_062s4.conf @@ -0,0 +1,6 @@ +# Copyright (c) 2024 David Ullmann +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LORA=y +CONFIG_LORA_RYLRXXX=y +CONFIG_UART_INTERRUPT_DRIVEN=y diff --git a/boards/shields/reyax_lora/boards/cy8ckit_062s4.overlay b/boards/shields/reyax_lora/boards/cy8ckit_062s4.overlay new file mode 100644 index 0000000000000..d45be1daa4107 --- /dev/null +++ b/boards/shields/reyax_lora/boards/cy8ckit_062s4.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 David Ullmann + * SPDX-License-Identifier: Apache-2.0 + */ + + +&p0_2_scb0_uart_rx { + input-enable; +}; + +&p0_3_scb0_uart_tx { + drive-push-pull; +}; + +&arduino_serial { + pinctrl-0 = <&p0_2_scb0_uart_rx &p0_3_scb0_uart_tx>; + pinctrl-names = "default"; +}; + +&gpio_prt0 { + status = "okay"; +}; + +&gpio_prt2 { + status = "okay"; +}; diff --git a/boards/shields/reyax_lora/doc/index.rst b/boards/shields/reyax_lora/doc/index.rst new file mode 100644 index 0000000000000..aa5cc1a781dfc --- /dev/null +++ b/boards/shields/reyax_lora/doc/index.rst @@ -0,0 +1,29 @@ +.. lora_reyax: + +Reyax LoRa RYLR896 and RYLR915 Modules +###################################### + +Overview +******** + +These modules expose a simple uart interface for the Semtech SX1276 chip,which implements the LoRa PHY. + +More information about the board can be found at the +`Reyax RYLR page`_. + +Hardware Description +******************** +The Module contains 4 pins + +- VDD: Power Supply +- NRST: Active low reset +- RXD: Serial data input +- TXD: Serial data output +- GND: Ground + +References +********** + +.. target-notes:: +.. _Reyax RYLR page: + https://reyax.com/products/RYLR896 diff --git a/boards/shields/reyax_lora/reyax_lora.overlay b/boards/shields/reyax_lora/reyax_lora.overlay new file mode 100644 index 0000000000000..080d78d92d0dd --- /dev/null +++ b/boards/shields/reyax_lora/reyax_lora.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 David Ullmann + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + aliases { + lora0 = &rylr_lora_modem; + }; +}; + + +&arduino_serial { + current-speed = <115200>; + status = "okay"; + rylr_lora_modem: rylr_lora_modem { + compatible = "reyax,rylrxxx"; + status = "okay"; + reset-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; + }; +}; diff --git a/boards/shields/rk043fn02h_ct/Kconfig.defconfig b/boards/shields/rk043fn02h_ct/Kconfig.defconfig new file mode 100644 index 0000000000000..f2b199d916968 --- /dev/null +++ b/boards/shields/rk043fn02h_ct/Kconfig.defconfig @@ -0,0 +1,47 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_RK043FN02H_CT + +if LVGL + +config INPUT + default y + +config INPUT_FT5336_INTERRUPT + default y + +# LVGL should allocate buffers equal to size of display +config LV_Z_VDB_SIZE + default 100 + +# Enable double buffering +config LV_Z_DOUBLE_VDB + default y + +# Force full refresh. This prevents memory copy associated with partial +# display refreshes, which is not necessary for the eLCDIF driver +config LV_Z_FULL_REFRESH + default y + +config LV_Z_BITS_PER_PIXEL + default 16 + +config LV_DPI_DEF + default 128 + +# Use offloaded render thread +config LV_Z_FLUSH_THREAD + default y + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_16 +endchoice + +# Force display buffers to be aligned to cache line size (32 bytes) +config LV_Z_VDB_ALIGN + default 32 + +endif # LVGL + +endif # SHIELD_RK043FN02H_CT diff --git a/boards/shields/rk043fn02h_ct/Kconfig.shield b/boards/shields/rk043fn02h_ct/Kconfig.shield new file mode 100644 index 0000000000000..4cf0c812ae89e --- /dev/null +++ b/boards/shields/rk043fn02h_ct/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_RK043FN02H_CT + def_bool $(shields_list_contains,rk043fn02h_ct) diff --git a/boards/shields/rk043fn02h_ct/doc/index.rst b/boards/shields/rk043fn02h_ct/doc/index.rst new file mode 100644 index 0000000000000..8fe083d61c5e5 --- /dev/null +++ b/boards/shields/rk043fn02h_ct/doc/index.rst @@ -0,0 +1,105 @@ +.. _rk043fn02h_ct: + +RK043FN02H-CT Parallel Display +############################## + +Overview +******** + +RK043FN02H-CT is a 4.3 inch TFT 480*272 pixels with LED backlight and +capacitive touch panel from Rocktech. This LCD panel can work with several i.MX +RT EVKs and LPC MCUs for evaluation of applications with display. + +More information about the shield can be found at the `RK043FN02H-CT product +page`_. + +This display uses a 40 pin parallel FPC interface plus 6 pin I2C interface, +available on many NXP EVKs. Note that this parallel FPC interface is not +compatible with the MIPI FPC interface present on other NXP EVKs. + +Pins Assignment of the Rocktech RK043FN02H-CT Parallel Display +============================================================== + ++-----------------------+------------------------+ +| Parallel FPC Pin | Function | ++=======================+========================+ +| 1 | LED backlight cathode | ++-----------------------+------------------------+ +| 2 | LED backlight anode | ++-----------------------+------------------------+ +| 3 | GND | ++-----------------------+------------------------+ +| 4 | VDD (3v3) | ++-----------------------+------------------------+ +| 5-7 | GND | ++-----------------------+------------------------+ +| 8-12 | LCD D11-D15 | ++-----------------------+------------------------+ +| 13-14 | GND | ++-----------------------+------------------------+ +| 15-20 | LCD D5-D10 | ++-----------------------+------------------------+ +| 21-23 | GND | ++-----------------------+------------------------+ +| 24-28 | LCD D0-D4 | ++-----------------------+------------------------+ +| 29 | GND | ++-----------------------+------------------------+ +| 30 | LCD CLK | ++-----------------------+------------------------+ +| 31 | LCD DISP | ++-----------------------+------------------------+ +| 32 | LCD HSYNC | ++-----------------------+------------------------+ +| 33 | LCD VSYNC | ++-----------------------+------------------------+ +| 34 | LCD DE | ++-----------------------+------------------------+ +| 35 | NC | ++-----------------------+------------------------+ +| 36 | GND | ++-----------------------+------------------------+ +| 37-40 | NC | ++-----------------------+------------------------+ + ++-----------------------+------------------------+ +| I2C Connector Pin | Function | ++=======================+========================+ +| 1 | VDD (3v3) | ++-----------------------+------------------------+ +| 2 | LCD Touch Reset | ++-----------------------+------------------------+ +| 3 | LCD Touch Interrupt | ++-----------------------+------------------------+ +| 4 | LCD I2C SCL | ++-----------------------+------------------------+ +| 5 | LCD I2C SDA | ++-----------------------+------------------------+ +| 6 | GND | ++-----------------------+------------------------+ + +Requirements +************ + +This shield can only be used with a board which provides a configuration +for the 40+6 pin parallel/I2C FPC interface + +Programming +*********** + +Set ``-DSHIELD=rk043fn02h_ct`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/display + :board: mimxrt1060_evk + :shield: rk043fn02h_ct + :goals: build + +References +********** + +.. target-notes:: + +.. _RK043FN02H-CT product page: + https://www.nxp.com/design/design-center/development-boards-and-designs/i-mx-evaluation-and-development-boards/4-3-lcd-panel:RK043FN02H-CT diff --git a/boards/shields/rk043fn02h_ct/rk043fn02h_ct.overlay b/boards/shields/rk043fn02h_ct/rk043fn02h_ct.overlay new file mode 100644 index 0000000000000..ab0b10d70af2a --- /dev/null +++ b/boards/shields/rk043fn02h_ct/rk043fn02h_ct.overlay @@ -0,0 +1,50 @@ +/* + * Copyright 2024, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + chosen { + zephyr,display = &zephyr_lcdif; + }; + + lvgl_pointer { + compatible = "zephyr,lvgl-pointer-input"; + input = <&ft5336_rk043fn02h_ct>; + }; +}; + +&nxp_touch_i2c { + status = "okay"; + ft5336_rk043fn02h_ct: ft5336@38 { + compatible = "focaltech,ft5336"; + reg = <0x38>; + int-gpios = <&nxp_i2c_touch_fpc 2 GPIO_ACTIVE_LOW>; + }; +}; + +&zephyr_lcdif { + status = "okay"; + width = <480>; + height = <272>; + display-timings { + compatible = "zephyr,panel-timing"; + hsync-len = <41>; + hfront-porch = <4>; + hback-porch = <8>; + vsync-len = <10>; + vfront-porch = <4>; + vback-porch = <2>; + de-active= <1>; + pixelclk-active = <1>; + hsync-active = <0>; + vsync-active = <0>; + clock-frequency = <9210240>; + }; + pixel-format = ; + data-bus-width = "16-bit"; + backlight-gpios = <&nxp_parallel_lcd_connector 0 GPIO_ACTIVE_HIGH>; +}; diff --git a/boards/shields/rk043fn66hs_ctg/Kconfig.defconfig b/boards/shields/rk043fn66hs_ctg/Kconfig.defconfig new file mode 100644 index 0000000000000..58e4b93b08860 --- /dev/null +++ b/boards/shields/rk043fn66hs_ctg/Kconfig.defconfig @@ -0,0 +1,47 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_RK043FN66HS_CTG + +if LVGL + +config INPUT + default y + +config INPUT_GT911_INTERRUPT + default y + +# LVGL should allocate buffers equal to size of display +config LV_Z_VDB_SIZE + default 100 + +# Enable double buffering +config LV_Z_DOUBLE_VDB + default y + +# Force full refresh. This prevents memory copy associated with partial +# display refreshes, which is not necessary for the eLCDIF driver +config LV_Z_FULL_REFRESH + default y + +config LV_Z_BITS_PER_PIXEL + default 16 + +config LV_DPI_DEF + default 128 + +# Use offloaded render thread +config LV_Z_FLUSH_THREAD + default y + +choice LV_COLOR_DEPTH + default LV_COLOR_DEPTH_16 +endchoice + +# Force display buffers to be aligned to cache line size (32 bytes) +config LV_Z_VDB_ALIGN + default 32 + +endif # LVGL + +endif # SHIELD_RK043FN66HS_CTG diff --git a/boards/shields/rk043fn66hs_ctg/Kconfig.shield b/boards/shields/rk043fn66hs_ctg/Kconfig.shield new file mode 100644 index 0000000000000..02a15503e4c7d --- /dev/null +++ b/boards/shields/rk043fn66hs_ctg/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_RK043FN66HS_CTG + def_bool $(shields_list_contains,rk043fn66hs_ctg) diff --git a/boards/shields/rk043fn66hs_ctg/doc/index.rst b/boards/shields/rk043fn66hs_ctg/doc/index.rst new file mode 100644 index 0000000000000..29d031e8305e3 --- /dev/null +++ b/boards/shields/rk043fn66hs_ctg/doc/index.rst @@ -0,0 +1,105 @@ +.. _rk043fn66hs_ctg: + +RK043FN66HS-CTG Parallel Display +################################ + +Overview +******** + +RK043FN66HS-CTG is a 4.3 inch TFT 480*272 pixels with LED backlight and +capacitive touch panel from Rocktech. This LCD panel can work with several i.MX +RT EVKs and LPC MCUs for evaluation of applications with display. + +More information about the shield can be found at the `RK043FN66HS-CTG product +page`_. + +This display uses a 40 pin parallel FPC interface plus 6 pin I2C interface, +available on many NXP EVKs. Note that this parallel FPC interface is not +compatible with the MIPI FPC interface present on other NXP EVKs. + +Pins Assignment of the Rocktech RK043FN66HS-CTG Parallel Display +================================================================ + ++-----------------------+------------------------+ +| Parallel FPC Pin | Function | ++=======================+========================+ +| 1 | LED backlight cathode | ++-----------------------+------------------------+ +| 2 | LED backlight anode | ++-----------------------+------------------------+ +| 3 | GND | ++-----------------------+------------------------+ +| 4 | VDD (3v3) | ++-----------------------+------------------------+ +| 5-7 | GND | ++-----------------------+------------------------+ +| 8-12 | LCD D11-D15 | ++-----------------------+------------------------+ +| 13-14 | GND | ++-----------------------+------------------------+ +| 15-20 | LCD D5-D10 | ++-----------------------+------------------------+ +| 21-23 | GND | ++-----------------------+------------------------+ +| 24-28 | LCD D0-D4 | ++-----------------------+------------------------+ +| 29 | GND | ++-----------------------+------------------------+ +| 30 | LCD CLK | ++-----------------------+------------------------+ +| 31 | LCD DISP | ++-----------------------+------------------------+ +| 32 | LCD HSYNC | ++-----------------------+------------------------+ +| 33 | LCD VSYNC | ++-----------------------+------------------------+ +| 34 | LCD DE | ++-----------------------+------------------------+ +| 35 | NC | ++-----------------------+------------------------+ +| 36 | GND | ++-----------------------+------------------------+ +| 37-40 | NC | ++-----------------------+------------------------+ + ++-----------------------+------------------------+ +| I2C Connector Pin | Function | ++=======================+========================+ +| 1 | VDD (3v3) | ++-----------------------+------------------------+ +| 2 | LCD Touch Reset | ++-----------------------+------------------------+ +| 3 | LCD Touch Interrupt | ++-----------------------+------------------------+ +| 4 | LCD I2C SCL | ++-----------------------+------------------------+ +| 5 | LCD I2C SDA | ++-----------------------+------------------------+ +| 6 | GND | ++-----------------------+------------------------+ + +Requirements +************ + +This shield can only be used with a board which provides a configuration +for the 40+6 pin parallel/I2C FPC interface + +Programming +*********** + +Set ``-DSHIELD=rk043fn66hs_ctg`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/display + :board: mimxrt1060_evk + :shield: rk043fn66hs_ctg + :goals: build + +References +********** + +.. target-notes:: + +.. _RK043FN66HS-CTG product page: + https://www.nxp.com/design/design-center/development-boards-and-designs/i-mx-evaluation-and-development-boards/4-3-lcd-panel:RK043FN66HS-CTG diff --git a/boards/shields/rk043fn66hs_ctg/rk043fn66hs_ctg.overlay b/boards/shields/rk043fn66hs_ctg/rk043fn66hs_ctg.overlay new file mode 100644 index 0000000000000..b992ec932b819 --- /dev/null +++ b/boards/shields/rk043fn66hs_ctg/rk043fn66hs_ctg.overlay @@ -0,0 +1,51 @@ +/* + * Copyright 2024, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/{ + chosen { + zephyr,display = &zephyr_lcdif; + }; + + lvgl_pointer { + compatible = "zephyr,lvgl-pointer-input"; + input = <>911_rk043fn66hs_ctg>; + }; +}; + +&nxp_touch_i2c { + status = "okay"; + gt911_rk043fn66hs_ctg: gt911@5d { + compatible = "goodix,gt911"; + reg = <0x5d>; + irq-gpios = <&nxp_i2c_touch_fpc 2 GPIO_ACTIVE_HIGH>; + reset-gpios = <&nxp_i2c_touch_fpc 1 GPIO_ACTIVE_LOW>; + }; +}; + +&zephyr_lcdif { + status = "okay"; + width = <480>; + height = <272>; + display-timings { + compatible = "zephyr,panel-timing"; + hsync-len = <4>; + hfront-porch = <8>; + hback-porch = <43>; + vsync-len = <4>; + vfront-porch = <8>; + vback-porch = <12>; + de-active= <1>; + pixelclk-active = <1>; + hsync-active = <0>; + vsync-active = <0>; + clock-frequency = <9210240>; + }; + pixel-format = ; + data-bus-width = "16-bit"; + backlight-gpios = <&nxp_parallel_lcd_connector 0 GPIO_ACTIVE_HIGH>; +}; diff --git a/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay b/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay index dab060bb60404..d4a3ad1329e73 100644 --- a/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay +++ b/boards/shields/seeed_xiao_round_display/seeed_xiao_round_display.overlay @@ -27,6 +27,26 @@ aliases { rtc = &pcf8563_xiao_round_display; }; + + xiao_round_display_mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&xiao_spi>; + dc-gpios = <&xiao_d 3 GPIO_ACTIVE_HIGH>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + gc9a01_xiao_round_display: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + mipi-max-frequency = ; + pixel-format = ; + width = <240>; + height = <240>; + display-inversion; + }; + }; }; &xiao_adc { @@ -62,18 +82,6 @@ status = "okay"; cs-gpios = <&xiao_d 1 GPIO_ACTIVE_LOW>, <&xiao_d 2 GPIO_ACTIVE_LOW>; - gc9a01_xiao_round_display: gc9a01@0 { - status = "okay"; - compatible = "galaxycore,gc9x01x"; - reg = <0>; - spi-max-frequency = ; - cmd-data-gpios = <&xiao_d 3 GPIO_ACTIVE_HIGH>; - pixel-format = ; - width = <240>; - height = <240>; - display-inversion; - }; - sdhc_xiao_round_display: sdhc@1 { compatible = "zephyr,sdhc-spi-slot"; reg = <1>; diff --git a/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.defconfig b/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.defconfig new file mode 100644 index 0000000000000..da44e62a05f1c --- /dev/null +++ b/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.defconfig @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +if SHIELD_SPARKFUN_CARRIER_ASSET_TRACKER + +config SERIAL + default y + +config UART_INTERRUPT_DRIVEN + default y + +config UART_ASYNC_API + default y + +config I2C + default y + +config SPI + default y + +endif # SHIELD_SPARKFUN_CARRIER_ASSET_TRACKER diff --git a/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.shield b/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.shield new file mode 100644 index 0000000000000..71cff2673512b --- /dev/null +++ b/boards/shields/sparkfun_carrier_asset_tracker/Kconfig.shield @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +config SHIELD_SPARKFUN_CARRIER_ASSET_TRACKER + def_bool $(shields_list_contains,sparkfun_carrier_asset_tracker) diff --git a/boards/shields/sparkfun_carrier_asset_tracker/doc/img/sparkfun_carrier_asset_tracker.webp b/boards/shields/sparkfun_carrier_asset_tracker/doc/img/sparkfun_carrier_asset_tracker.webp new file mode 100644 index 0000000000000..a76682a0cef84 Binary files /dev/null and b/boards/shields/sparkfun_carrier_asset_tracker/doc/img/sparkfun_carrier_asset_tracker.webp differ diff --git a/boards/shields/sparkfun_carrier_asset_tracker/doc/index.rst b/boards/shields/sparkfun_carrier_asset_tracker/doc/index.rst new file mode 100644 index 0000000000000..93093906fce61 --- /dev/null +++ b/boards/shields/sparkfun_carrier_asset_tracker/doc/index.rst @@ -0,0 +1,117 @@ +.. _sparkfun_carrier_asset_tracker: + +Sparkfun SparkFun MicroMod Asset Tracker Shield +############################################### + +Overview +******** + +The SparkFun MicroMod Asset Tracker Carrier Shield is part of the Sparkfun +Micromod standard, a modular interface ecosystem that uses the M.2 standard +to mix and match your choice of processor with specific Functions Boards. + +The Asset Tracker Carrier Shield is built around the u-blox SARA-R510M8S +module, which offers Secure Cloud LTE-M and NB-IoT data communication for +multi-regional use and GNSS capabilities via an integrated u-blox M8 GNSS +receiver for accurate positioning information. + +Besides, this shield has an integrated ICM-20948 Inertial Measurement Unit +(IMU) for Nine Degree-Of-Freedom, a built-in micro-SD card socket for data +logging as well as a nano SIM card port. + +.. figure:: img/sparkfun_carrier_asset_tracker.webp + :align: center + :alt: Sparkfun SparkFun MicroMod Asset Tracker Shield + + Sparkfun SparkFun MicroMod Asset Tracker Shield (Credit: Sparkfun) + +More information about the shield can be found at the `SparkFun MicroMod +Asset Tracker guide website`_. + +Pins Assignment of Sparkfun SparkFun MicroMod Asset Tracker Shield +================================================================== + +The SparkFun MicroMod Asset Tracker Carrier Shield uses a 76 pins M.2 +connector. The following table depicts the interfaces and pins supported: +by Zephyr: ++-----------------------+---------------------------------+ +| Shield Connector Pin | Function | ++=======================+=================================+ +| micromod_1_uart alias | UART 1 (with CTS and RTS pins) | ++-----------------------+---------------------------------+ +| micromod_2_uart alias | UART 2 | ++-----------------------+---------------------------------+ +| micromod_0_i2c alias | i2c 0 | ++-----------------------+---------------------------------+ +| micromod_1_i2c alias | i2c 1 | ++-----------------------+---------------------------------+ +| micromod_0_spi alias | SPI 0 | ++-----------------------+---------------------------------+ +| A0 | Analog pin | ++-----------------------+---------------------------------+ +| A1 | Analog pin | ++-----------------------+---------------------------------+ +| D0 | Digital pin | ++-----------------------+---------------------------------+ +| D1/CAM_TRIG | Digital pin | ++-----------------------+---------------------------------+ +| I2C_INT# | i2c interrupt pin | ++-----------------------+---------------------------------+ +| G0/BUS0 | General purpose pin | ++-----------------------+---------------------------------+ +| G1/BUS1 | General purpose pin | ++-----------------------+---------------------------------+ +| G2/BUS2 | General purpose pin | ++-----------------------+---------------------------------+ +| G3/BUS3 | General purpose pin | ++-----------------------+---------------------------------+ +| G4/BUS4 | General purpose pin | ++-----------------------+---------------------------------+ +| G5/BUS5 | General purpose pin | ++-----------------------+---------------------------------+ +| G6/BUS6 | General purpose pin | ++-----------------------+---------------------------------+ +| G7/BUS7 | General purpose pin | ++-----------------------+---------------------------------+ +| G8 | General purpose pin | ++-----------------------+---------------------------------+ +| G9/ADC_D-/CAM_HSYNC | General purpose pin | ++-----------------------+---------------------------------+ +| G10/ADC_D+/CAM_VSYNC | General purpose pin | ++-----------------------+---------------------------------+ +| G11/SWO | General purpose pin | ++-----------------------+---------------------------------+ +| SPI_CS | General purpose pin | ++-----------------------+---------------------------------+ + +A detailed definition of the Micromod standard can be found on the +`Micromod specification website`_ + +Requirements +************ + +This shield can only be used with a board which provides a configuration for +Micromod connectors and defines node aliases for UART, I2C and SPI interfaces (see +:ref:`shields` for more details). + +Programming +*********** + +Set ``-DSHIELD=sparkfun_carrier_asset_tracker`` when you invoke ``west build``. For +example: + +.. zephyr-app-commands:: + :zephyr-app: samples/net/cellular_modem/ + :board: micromod/nrf52840 + :shield: sparkfun_carrier_asset_tracker + :goals: build + +References +********** + +.. target-notes:: + +.. _SparkFun MicroMod Asset Tracker guide website: + https://learn.sparkfun.com/tutorials/micromod-asset-tracker-carrier-board-hookup-guide +.. _Micromod specification website: + https://www.sparkfun.com/micromod diff --git a/boards/shields/sparkfun_carrier_asset_tracker/sparkfun_carrier_asset_tracker.overlay b/boards/shields/sparkfun_carrier_asset_tracker/sparkfun_carrier_asset_tracker.overlay new file mode 100644 index 0000000000000..6c7a9383c27f0 --- /dev/null +++ b/boards/shields/sparkfun_carrier_asset_tracker/sparkfun_carrier_asset_tracker.overlay @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Jerónimo Agulló + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + modem-uart = µmod_1_uart; + modem = &modem; + }; +}; + +µmod_1_uart { + current-speed = <115200>; + hw-flow-control; + status = "okay"; + + modem: sara_r5 { + compatible = "u-blox,sara-r5"; + mdm-power-gpios = <µmod_header 7 0>; /* G2 */ + mdm-reset-gpios = <µmod_header 12 0>; /* D6 */ + status = "okay"; + }; +}; + +µmod_0_spi { + status = "okay"; + /* G0 (SD_CS) */ + cs-gpios = <µmod_header 5 GPIO_ACTIVE_LOW>; + + sdhc0: sdhc@0 { + compatible = "zephyr,sdhc-spi-slot"; + reg = <0>; + status = "okay"; + mmc { + compatible = "zephyr,sdmmc-disk"; + status = "okay"; + }; + spi-max-frequency = ; + }; +}; + +µmod_0_i2c { + max17048: max17048@36 { + compatible = "maxim,max17048"; + reg = <0x36>; + status = "okay"; + }; +}; diff --git a/boards/shields/st7735r/st7735r_ada_160x128.overlay b/boards/shields/st7735r/st7735r_ada_160x128.overlay index 42d7cd890603d..d769b9a1a4dd5 100644 --- a/boards/shields/st7735r/st7735r_ada_160x128.overlay +++ b/boards/shields/st7735r/st7735r_ada_160x128.overlay @@ -4,38 +4,48 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { chosen { zephyr,display = &st7735r_st7735r_ada_160x128; }; + + mipi_dbi_st7735r_ada_160x128 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ + reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ + #address-cells = <1>; + #size-cells = <0>; + + st7735r_st7735r_ada_160x128: st7735r@0 { + compatible = "sitronix,st7735r"; + mipi-max-frequency = <20000000>; + mipi-mode = ; + reg = <0>; + width = <160>; + height = <128>; + x-offset = <0>; + y-offset = <0>; + madctl = <0x60>; + colmod = <0x55>; + vmctr1 = <0x0e>; + pwctr1 = [a2 02 84]; + pwctr2 = [c5]; + pwctr3 = [0a 00]; + pwctr4 = [8a 2a]; + pwctr5 = [8a ee]; + frmctr1 = [01 2c 2d]; + frmctr2 = [01 2c 2d]; + frmctr3 = [01 2c 2d 01 2c 2d]; + gamctrp1 = [02 1c 07 12 37 32 29 2d 29 25 2b 39 00 01 03 10]; + gamctrn1 = [03 1d 07 06 2e 2c 29 2d 2e 2e 37 3f 00 00 02 10]; + }; + }; }; &arduino_spi { status = "okay"; cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */ - - st7735r_st7735r_ada_160x128: st7735r@0 { - compatible = "sitronix,st7735r"; - spi-max-frequency = <20000000>; - reg = <0>; - cmd-data-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ - reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - width = <160>; - height = <128>; - x-offset = <0>; - y-offset = <0>; - madctl = <0x60>; - colmod = <0x55>; - vmctr1 = <0x0e>; - pwctr1 = [a2 02 84]; - pwctr2 = [c5]; - pwctr3 = [0a 00]; - pwctr4 = [8a 2a]; - pwctr5 = [8a ee]; - frmctr1 = [01 2c 2d]; - frmctr2 = [01 2c 2d]; - frmctr3 = [01 2c 2d 01 2c 2d]; - gamctrp1 = [02 1c 07 12 37 32 29 2d 29 25 2b 39 00 01 03 10]; - gamctrn1 = [03 1d 07 06 2e 2c 29 2d 2e 2e 37 3f 00 00 02 10]; - }; }; diff --git a/boards/shields/st7789v_generic/st7789v_tl019fqv01.overlay b/boards/shields/st7789v_generic/st7789v_tl019fqv01.overlay index c12ee45515b9c..46c863b5ac896 100644 --- a/boards/shields/st7789v_generic/st7789v_tl019fqv01.overlay +++ b/boards/shields/st7789v_generic/st7789v_tl019fqv01.overlay @@ -3,41 +3,51 @@ * * SPDX-License-Identifier: Apache-2.0 */ +#include / { chosen { zephyr,display = &st7789v_st7789v_tl019fqv01; }; + + mipi_dbi_st7789v_tl019fqv01 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ + reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ + write-only; + #address-cells = <1>; + #size-cells = <0>; + + st7789v_st7789v_tl019fqv01: st7789v@0 { + compatible = "sitronix,st7789v"; + mipi-max-frequency = <20000000>; + reg = <0>; + width = <320>; + height = <170>; + x-offset = <0>; + y-offset = <35>; + vcom = <0x2b>; + gctrl = <0x35>; + vrhs = <0x0f>; + vdvs = <0x20>; + mdac = <0x60>; + gamma = <0x01>; + colmod = <0x55>; + lcm = <0x2c>; + porch-param = [0c 0c 00 33 33]; + cmd2en-param = [5a 69 02 01]; + pwctrl1-param = [52 a1]; + pvgam-param = [D0 00 02 07 0B 1A 31 54 40 29 12 12 12 17]; + nvgam-param = [D0 00 02 07 05 15 2D 44 44 1C 18 16 1C 1D]; + ram-param = [00 F8]; + rgb-param = [CD 08 14]; + mipi-mode = ; + }; + }; }; &arduino_spi { status = "okay"; cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */ - - st7789v_st7789v_tl019fqv01: st7789v@0 { - compatible = "sitronix,st7789v"; - spi-max-frequency = <20000000>; - reg = <0>; - cmd-data-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ - reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - width = <320>; - height = <170>; - x-offset = <0>; - y-offset = <35>; - vcom = <0x2b>; - gctrl = <0x35>; - vrhs = <0x0f>; - vdvs = <0x20>; - mdac = <0x60>; - gamma = <0x01>; - colmod = <0x55>; - lcm = <0x2c>; - porch-param = [0c 0c 00 33 33]; - cmd2en-param = [5a 69 02 01]; - pwctrl1-param = [52 a1]; - pvgam-param = [D0 00 02 07 0B 1A 31 54 40 29 12 12 12 17]; - nvgam-param = [D0 00 02 07 05 15 2D 44 44 1C 18 16 1C 1D]; - ram-param = [00 F8]; - rgb-param = [CD 08 14]; - }; }; diff --git a/boards/shields/st7789v_generic/st7789v_waveshare_240x240.overlay b/boards/shields/st7789v_generic/st7789v_waveshare_240x240.overlay index 3c7205ce28700..0a92937a982fe 100644 --- a/boards/shields/st7789v_generic/st7789v_waveshare_240x240.overlay +++ b/boards/shields/st7789v_generic/st7789v_waveshare_240x240.overlay @@ -5,40 +5,51 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + / { chosen { zephyr,display = &st7789v_st7789v_waveshare_240x240; }; + + mipi_dbi_st7789v_waveshare_240x240 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ + reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ + write-only; + #address-cells = <1>; + #size-cells = <0>; + + st7789v_st7789v_waveshare_240x240: st7789v@0 { + compatible = "sitronix,st7789v"; + mipi-max-frequency = <20000000>; + reg = <0>; + width = <240>; + height = <240>; + x-offset = <0>; + y-offset = <0>; + vcom = <0x19>; + gctrl = <0x35>; + vrhs = <0x12>; + vdvs = <0x20>; + mdac = <0x00>; + gamma = <0x01>; + colmod = <0x05>; + lcm = <0x2c>; + porch-param = [0c 0c 00 33 33]; + cmd2en-param = [5a 69 02 01]; + pwctrl1-param = [a4 a1]; + pvgam-param = [D0 04 0D 11 13 2B 3F 54 4C 18 0D 0B 1F 23]; + nvgam-param = [D0 04 0C 11 13 2C 3F 44 51 2F 1F 1F 20 23]; + ram-param = [00 F0]; + rgb-param = [CD 08 14]; + mipi-mode = ; + }; + }; }; &arduino_spi { status = "okay"; cs-gpios = <&arduino_header 16 GPIO_ACTIVE_LOW>; /* D10 */ - - st7789v_st7789v_waveshare_240x240: st7789v@0 { - compatible = "sitronix,st7789v"; - spi-max-frequency = <20000000>; - reg = <0>; - cmd-data-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ - reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - width = <240>; - height = <240>; - x-offset = <0>; - y-offset = <0>; - vcom = <0x19>; - gctrl = <0x35>; - vrhs = <0x12>; - vdvs = <0x20>; - mdac = <0x00>; - gamma = <0x01>; - colmod = <0x05>; - lcm = <0x2c>; - porch-param = [0c 0c 00 33 33]; - cmd2en-param = [5a 69 02 01]; - pwctrl1-param = [a4 a1]; - pvgam-param = [D0 04 0D 11 13 2B 3F 54 4C 18 0D 0B 1F 23]; - nvgam-param = [D0 04 0C 11 13 2C 3F 44 51 2F 1F 1F 20 23]; - ram-param = [00 F0]; - rgb-param = [CD 08 14]; - }; }; diff --git a/boards/shields/tcan4550evm/tcan4550evm.overlay b/boards/shields/tcan4550evm/tcan4550evm.overlay index d25d8ff0e6208..7aeb3022a9a2d 100644 --- a/boards/shields/tcan4550evm/tcan4550evm.overlay +++ b/boards/shields/tcan4550evm/tcan4550evm.overlay @@ -28,8 +28,6 @@ reset-gpios = <&arduino_header 14 GPIO_ACTIVE_HIGH>; /* D8 */ int-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ bosch,mram-cfg = <0x0 15 15 7 7 0 10 10>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; can-transceiver { diff --git a/boards/shields/waveshare_epaper/Kconfig.defconfig b/boards/shields/waveshare_epaper/Kconfig.defconfig index 5f7f13a0b16e4..6087880f4f378 100644 --- a/boards/shields/waveshare_epaper/Kconfig.defconfig +++ b/boards/shields/waveshare_epaper/Kconfig.defconfig @@ -5,8 +5,7 @@ # SPDX-License-Identifier: Apache-2.0 # -if SHIELD_WAVESHARE_EPAPER_GDEH029A1 || SHIELD_WAVESHARE_EPAPER_GDEH0213B1 || SHIELD_WAVESHARE_EPAPER_GDEH0213B72 || SHIELD_WAVESHARE_EPAPER_GDEW075T7 || SHIELD_WAVESHARE_EPAPER_GDEH0154A07 || SHIELD_WAVESHARE_EPAPER_GDEW042T2 || SHIELD_WAVESHARE_EPAPER_GDEW042T2_P - +if SHIELD_WAVESHARE_EPAPER_GDEH029A1 || SHIELD_WAVESHARE_EPAPER_GDEH0213B1 || SHIELD_WAVESHARE_EPAPER_GDEH0213B72 || SHIELD_WAVESHARE_EPAPER_GDEW075T7 || SHIELD_WAVESHARE_EPAPER_GDEH0154A07 || SHIELD_WAVESHARE_EPAPER_GDEW042T2 || SHIELD_WAVESHARE_EPAPER_GDEW042T2_P || SHIELD_WAVESHARE_EPAPER_GDEY0213B74 if DISPLAY diff --git a/boards/shields/waveshare_epaper/Kconfig.shield b/boards/shields/waveshare_epaper/Kconfig.shield index 863059e57843c..b3fe949cb3ae3 100644 --- a/boards/shields/waveshare_epaper/Kconfig.shield +++ b/boards/shields/waveshare_epaper/Kconfig.shield @@ -21,3 +21,6 @@ config SHIELD_WAVESHARE_EPAPER_GDEW042T2 config SHIELD_WAVESHARE_EPAPER_GDEW042T2_P def_bool $(shields_list_contains,waveshare_epaper_gdew042t2-p) + +config SHIELD_WAVESHARE_EPAPER_GDEY0213B74 + def_bool $(shields_list_contains,waveshare_epaper_gdey0213b74) diff --git a/boards/shields/waveshare_epaper/doc/index.rst b/boards/shields/waveshare_epaper/doc/index.rst index 876ba1d107e8c..25c4ecd955e40 100644 --- a/boards/shields/waveshare_epaper/doc/index.rst +++ b/boards/shields/waveshare_epaper/doc/index.rst @@ -65,6 +65,9 @@ Current supported displays | Good Display | WFT0420CZ15 | UC8176 / | waveshare_epaper_gdew042t2 | | GDEW042T2 | | gd7965 | waveshare_epaper_gdew042t2-p | +--------------+-----------------+--------------+------------------------------+ +| Good Display | FPC-A002 | SSD1680 / | waveshare_epaper_gdey0213b74 | +| GDEY0213B74 | | ssd16xx | | ++--------------+-----------------+--------------+------------------------------+ Requirements diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0154a07.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0154a07.overlay index 7a4dc21f0b70d..6a877a0b08d2c 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0154a07.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0154a07.overlay @@ -10,27 +10,32 @@ chosen { zephyr,display = &ssd16xx_waveshare_epaper_gdeh0154a07; }; -}; -&arduino_spi { - ssd16xx_waveshare_epaper_gdeh0154a07: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0154a07", "solomon,ssd1681"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <200>; - height = <200>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdeh0154a07 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + #address-cells = <1>; + #size-cells = <0>; - tssv = <0x80>; + ssd16xx_waveshare_epaper_gdeh0154a07: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0154a07", "solomon,ssd1681"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <200>; + height = <200>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ - full { - border-waveform = <0x05>; - }; + tssv = <0x80>; + + full { + border-waveform = <0x05>; + }; - partial { - border-waveform = <0x3c>; + partial { + border-waveform = <0x3c>; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b1.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b1.overlay index d7c873df0c3ce..1936b48d16a78 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b1.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b1.overlay @@ -10,47 +10,52 @@ chosen { zephyr,display = &ssd16xx_waveshare_epaper_gdeh0213b1; }; -}; -&arduino_spi { - ssd16xx_waveshare_epaper_gdeh0213b1: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0213b1", "solomon,ssd1673"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <250>; - height = <120>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdeh0213b1 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + #address-cells = <1>; + #size-cells = <0>; - full { - gdv = [10 0a]; - sdv = [19]; - vcom = <0xa8>; - border-waveform = <0x71>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 22 55 AA 55 AA 55 AA 11 - 00 00 00 00 00 00 00 00 - 1E 1E 1E 1E 1E 1E 1E 1E - 01 00 00 00 00 - ]; - }; + ssd16xx_waveshare_epaper_gdeh0213b1: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0213b1", "solomon,ssd1673"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <120>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + + full { + gdv = [10 0a]; + sdv = [19]; + vcom = <0xa8>; + border-waveform = <0x71>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 22 55 AA 55 AA 55 AA 11 + 00 00 00 00 00 00 00 00 + 1E 1E 1E 1E 1E 1E 1E 1E + 01 00 00 00 00 + ]; + }; - partial { - gdv = [10 0a]; - sdv = [19]; - vcom = <0xa8>; - border-waveform = <0x71>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 18 00 00 00 00 00 00 00 - 00 00 00 00 00 00 00 00 - 0F 01 00 00 00 00 00 00 - 00 00 00 00 00 - ]; + partial { + gdv = [10 0a]; + sdv = [19]; + vcom = <0xa8>; + border-waveform = <0x71>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 18 00 00 00 00 00 00 00 + 00 00 00 00 00 00 00 00 + 0F 01 00 00 00 00 00 00 + 00 00 00 00 00 + ]; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b72.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b72.overlay index 37954c57cf19f..362e0905079c8 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b72.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh0213b72.overlay @@ -10,63 +10,68 @@ chosen { zephyr,display = &ssd16xx_waveshare_epaper_gdeh0213b72; }; -}; -&arduino_spi { - ssd16xx_waveshare_epaper_gdeh0213b72: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh0213b72", "solomon,ssd1675a"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <250>; - height = <120>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdeh0213b72 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + #address-cells = <1>; + #size-cells = <0>; - full { - gdv = [15]; - sdv = [41 a8 32]; - vcom = <0x55>; - border-waveform = <0x03>; - dummy-line = <0x30>; - gate-line-width = <0x0a>; - lut = [ - 80 60 40 00 00 00 00 - 10 60 20 00 00 00 00 - 80 60 40 00 00 00 00 - 10 60 20 00 00 00 00 - 00 00 00 00 00 00 00 - 03 03 00 00 02 - 09 09 00 00 02 - 03 03 00 00 02 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - ]; - }; + ssd16xx_waveshare_epaper_gdeh0213b72: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh0213b72", "solomon,ssd1675a"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <120>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + + full { + gdv = [15]; + sdv = [41 a8 32]; + vcom = <0x55>; + border-waveform = <0x03>; + dummy-line = <0x30>; + gate-line-width = <0x0a>; + lut = [ + 80 60 40 00 00 00 00 + 10 60 20 00 00 00 00 + 80 60 40 00 00 00 00 + 10 60 20 00 00 00 00 + 00 00 00 00 00 00 00 + 03 03 00 00 02 + 09 09 00 00 02 + 03 03 00 00 02 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + ]; + }; - partial { - gdv = [15]; - sdv = [41 a8 32]; - vcom = <0x26>; - border-waveform = <0x01>; - dummy-line = <0x30>; - gate-line-width = <0x0a>; - lut = [ - 00 00 00 00 00 00 00 - 80 00 00 00 00 00 00 - 40 00 00 00 00 00 00 - 80 00 00 00 00 00 00 - 00 00 00 00 00 00 00 - 0A 00 00 00 04 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - 00 00 00 00 00 - ]; + partial { + gdv = [15]; + sdv = [41 a8 32]; + vcom = <0x26>; + border-waveform = <0x01>; + dummy-line = <0x30>; + gate-line-width = <0x0a>; + lut = [ + 00 00 00 00 00 00 00 + 80 00 00 00 00 00 00 + 40 00 00 00 00 00 00 + 80 00 00 00 00 00 00 + 00 00 00 00 00 00 00 + 0A 00 00 00 04 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + 00 00 00 00 00 + ]; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh029a1.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh029a1.overlay index 0b1b6f4d14f42..734786fcc80be 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdeh029a1.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdeh029a1.overlay @@ -10,45 +10,50 @@ chosen { zephyr,display = &ssd16xx_waveshare_epaper_gdeh029a1; }; -}; -&arduino_spi { - ssd16xx_waveshare_epaper_gdeh029a1: ssd16xxfb@0 { - compatible = "gooddisplay,gdeh029a1", "solomon,ssd1608"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <296>; - height = <128>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdeh029a1 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + #address-cells = <1>; + #size-cells = <0>; - softstart = [d7 d6 9d]; + ssd16xx_waveshare_epaper_gdeh029a1: ssd16xxfb@0 { + compatible = "gooddisplay,gdeh029a1", "solomon,ssd1608"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <296>; + height = <128>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ - full { - vcom = <0x9a>; - border-waveform = <0x33>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 50 AA 55 AA 11 00 00 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 FF FF 1F 00 - 00 00 00 00 00 00 - ]; - }; + softstart = [d7 d6 9d]; + + full { + vcom = <0x9a>; + border-waveform = <0x33>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 50 AA 55 AA 11 00 00 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 FF FF 1F 00 + 00 00 00 00 00 00 + ]; + }; - partial { - vcom = <0xa8>; - border-waveform = <0x01>; - dummy-line = <0x1a>; - gate-line-width = <0x08>; - lut = [ - 10 18 18 08 18 18 08 00 - 00 00 00 00 00 00 00 00 - 00 00 00 00 13 14 44 12 - 00 00 00 00 00 00 - ]; + partial { + vcom = <0xa8>; + border-waveform = <0x01>; + dummy-line = <0x1a>; + gate-line-width = <0x08>; + lut = [ + 10 18 18 08 18 18 08 00 + 00 00 00 00 00 00 00 00 + 00 00 00 00 13 14 44 12 + 00 00 00 00 00 00 + ]; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay index 35f96d940e2ad..2a1024ece0d82 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2-p.overlay @@ -8,87 +8,93 @@ / { chosen { - zephyr,display = &uc8176_waveshare_epaper_gdew042t2-p; + zephyr,display = &uc8176_waveshare_epaper_gdew042t2_p; }; -}; -&arduino_spi { - /* - * GoodDisplay GDEW042T2 with fast partial refresh. Based on - * configuration from GoodDisplay's Arduino example. - */ - uc8176_waveshare_epaper_gdew042t2-p: uc8176@0 { - compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <400>; - height = <300>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdew042t2-p { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ + write-only; + #address-cells = <1>; + #size-cells = <0>; - softstart = [ 17 17 17 ]; + /* + * GoodDisplay GDEW042T2 with fast partial refresh. Based on + * configuration from GoodDisplay's Arduino example. + */ + uc8176_waveshare_epaper_gdew042t2_p: uc8176@0 { + compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <400>; + height = <300>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ - full { - cdi = <0x07>; - }; + softstart = [ 17 17 17 ]; + + full { + cdi = <0x07>; + }; - partial { - pwr = [ 03 02 2b 2b ]; - cdi = <0x07>; - pll = <0x3c>; - vdcs = <0x08>; + partial { + pwr = [ 03 02 2b 2b ]; + cdi = <0x07>; + pll = <0x3c>; + vdcs = <0x08>; - lutc = [ - 00 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 - ]; + lutc = [ + 00 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 + ]; - lutww = [ - 00 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - ]; + lutww = [ + 00 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + ]; - lutkw = [ - 20 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - ]; + lutkw = [ + 20 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + ]; - lutwk = [ - 10 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - ]; + lutwk = [ + 10 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + ]; - lutkk = [ - 00 01 0E 00 00 01 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - 00 00 00 00 00 00 - ]; + lutkk = [ + 00 01 0E 00 00 01 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + 00 00 00 00 00 00 + ]; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay index 0b8f994c97b19..035110ea5dcd9 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdew042t2.overlay @@ -9,25 +9,31 @@ chosen { zephyr,display = &uc8176_waveshare_epaper_gdew042t2; }; -}; -&arduino_spi { - uc8176_waveshare_epaper_gdew042t2: uc8176@0 { - compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <400>; - height = <300>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdew042t2 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ + write-only; + #address-cells = <1>; + #size-cells = <0>; + + uc8176_waveshare_epaper_gdew042t2: uc8176@0 { + compatible = "gooddisplay,gdew042t2", "ultrachip,uc8176"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <400>; + height = <300>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ - softstart = [17 17 17]; + softstart = [17 17 17]; - full { - pwr = [03 00 26 26 09]; - cdi = <0xd7>; - tcon = <0x22>; + full { + pwr = [03 00 26 26 09]; + cdi = <0xd7>; + tcon = <0x22>; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay index cccee41faaa28..8c8cbd9d636ed 100644 --- a/boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdew075t7.overlay @@ -10,25 +10,31 @@ chosen { zephyr,display = &uc8179_waveshare_epaper_gdew075t7; }; -}; -&arduino_spi { - uc8179_waveshare_epaper_gdew075t7: uc8179@0 { - compatible = "gooddisplay,gdew075t7", "ultrachip,uc8179"; - spi-max-frequency = <4000000>; - reg = <0>; - width = <800>; - height = <480>; - dc-gpios = <&arduino_header 15 GPIO_ACTIVE_LOW>; /* D9 */ + mipi_dbi_waveshare_epaper_gdew075t7 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ - busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ + write-only; + #address-cells = <1>; + #size-cells = <0>; + + uc8179_waveshare_epaper_gdew075t7: uc8179@0 { + compatible = "gooddisplay,gdew075t7", "ultrachip,uc8179"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <800>; + height = <480>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ - softstart = [17 17 17 17]; + softstart = [17 17 17 17]; - full { - pwr = [07 07 3f 3f]; - cdi = <07>; - tcon = <0x22>; + full { + pwr = [07 07 3f 3f]; + cdi = <07>; + tcon = <0x22>; + }; }; }; }; diff --git a/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay b/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay new file mode 100644 index 0000000000000..8299b7242745d --- /dev/null +++ b/boards/shields/waveshare_epaper/waveshare_epaper_gdey0213b74.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024, Kelly Helmut Lord + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "waveshare_epaper_common.dtsi" + +/ { + chosen { + zephyr,display = &ssd16xx_waveshare_epaper_gdey0213b74; + }; + + mipi_dbi_waveshare_epaper_gdey0213b74 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&arduino_spi>; + dc-gpios = <&arduino_header 15 GPIO_ACTIVE_HIGH>; /* D9 */ + reset-gpios = <&arduino_header 14 GPIO_ACTIVE_LOW>; /* D8 */ + #address-cells = <1>; + #size-cells = <0>; + + ssd16xx_waveshare_epaper_gdey0213b74: ssd16xxfb@0 { + compatible = "gooddisplay,gdey0213b74", "solomon,ssd1680"; + mipi-max-frequency = <4000000>; + reg = <0>; + width = <250>; + height = <122>; + busy-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + + tssv = <0x80>; + + full { + border-waveform = <0x05>; + }; + + partial { + border-waveform = <0x3c>; + }; + }; + }; +}; diff --git a/boards/shields/x_nucleo_bnrg2a1/Kconfig.defconfig b/boards/shields/x_nucleo_bnrg2a1/Kconfig.defconfig index 88f16f95dc56e..94ace9e384989 100644 --- a/boards/shields/x_nucleo_bnrg2a1/Kconfig.defconfig +++ b/boards/shields/x_nucleo_bnrg2a1/Kconfig.defconfig @@ -8,9 +8,8 @@ if BT config SPI default y -choice BT_HCI_BUS_TYPE - default BT_SPI -endchoice +config BT_SPI + default y config BT_BLUENRG_ACI default y diff --git a/boards/shields/x_nucleo_bnrg2a1/x_nucleo_bnrg2a1.overlay b/boards/shields/x_nucleo_bnrg2a1/x_nucleo_bnrg2a1.overlay index 177ac9eb9484d..535373ea307d7 100644 --- a/boards/shields/x_nucleo_bnrg2a1/x_nucleo_bnrg2a1.overlay +++ b/boards/shields/x_nucleo_bnrg2a1/x_nucleo_bnrg2a1.overlay @@ -4,10 +4,16 @@ * SPDX-License-Identifier: Apache-2.0 */ + / { + chosen { + zephyr,bt-hci = &hci_spi; + }; + }; + &arduino_spi { cs-gpios = <&arduino_header 1 GPIO_ACTIVE_LOW>; /* A1 */ - bluenrg-2@0 { + hci_spi: bluenrg-2@0 { compatible = "st,hci-spi-v2"; reg = <0>; reset-gpios = <&arduino_header 13 GPIO_ACTIVE_LOW>; /* D7 */ diff --git a/boards/shields/x_nucleo_eeprma2/x_nucleo_eeprma2.overlay b/boards/shields/x_nucleo_eeprma2/x_nucleo_eeprma2.overlay index a1c7c6813dc34..84f1cda1a3cfa 100644 --- a/boards/shields/x_nucleo_eeprma2/x_nucleo_eeprma2.overlay +++ b/boards/shields/x_nucleo_eeprma2/x_nucleo_eeprma2.overlay @@ -20,7 +20,7 @@ eeprom0_x_nucleo_eeprma2: eeprom@54 { /* M24C02-FMC6TG aka U1 (2 kbit eeprom in DFN8 package) */ - compatible = "st,m24xxx", "atmel,at24"; + compatible = "st,m24c02", "st,m24xxx", "atmel,at24"; reg = <0x54>; size = <256>; pagesize = <16>; @@ -33,7 +33,7 @@ eeprom1_x_nucleo_eeprma2: eeprom@55 { /* M24256-DFDW6TP aka U2 (256 kbit eeprom in TSSOP package) */ - compatible = "st,m24xxx", "atmel,at24"; + compatible = "st,m24256", "st,m24xxx", "atmel,at24"; reg = <0x55>; size = ; pagesize = <64>; @@ -46,7 +46,7 @@ eeprom2_x_nucleo_eeprma2: eeprom@56 { /* M24M01-DFMN6TP aka U3 (1 Mbit eeprom in SO8N package) */ - compatible = "st,m24xxx", "atmel,at24"; + compatible = "st,m24m01", "st,m24xxx", "atmel,at24"; reg = <0x56>; size = ; pagesize = <256>; @@ -82,7 +82,7 @@ eeprom4_x_nucleo_eeprma2: eeprom_m95040@0 { /* M95040-RMC6TG aka U5 (4 kbit eeprom in DFN8 package) */ - compatible = "st,m95xxx", "atmel,at25"; + compatible = "st,m95040", "st,m95xxx", "atmel,at25"; reg = <0x00>; size = <512>; pagesize = <16>; @@ -96,7 +96,7 @@ eeprom5_x_nucleo_eeprma2: eeprom_m95256@1 { /* M95256-DFDW6TP aka U6 (256 kbit eeprom in TSSOP package) */ - compatible = "st,m95xxx", "atmel,at25"; + compatible = "st,m95256", "st,m95xxx", "atmel,at25"; reg = <0x01>; size = ; pagesize = <64>; @@ -110,7 +110,7 @@ eeprom6_x_nucleo_eeprma2: eeprom_m95m04@2 { /* M95M04-DRMN6TP aka U7 (4 Mbit eeprom in SON8 package) */ - compatible = "st,m95xxx", "atmel,at25"; + compatible = "st,m95m04", "st,m95xxx", "atmel,at25"; reg = <0x02>; size = ; pagesize = <512>; diff --git a/boards/shields/x_nucleo_idb05a1/Kconfig.defconfig b/boards/shields/x_nucleo_idb05a1/Kconfig.defconfig index 430b8a860f7df..276ee66467992 100644 --- a/boards/shields/x_nucleo_idb05a1/Kconfig.defconfig +++ b/boards/shields/x_nucleo_idb05a1/Kconfig.defconfig @@ -8,16 +8,15 @@ if BT config SPI default y -choice BT_HCI_BUS_TYPE - default BT_SPI -endchoice +config BT_SPI + default y config BT_BLUENRG_ACI default y # Disable Flow control config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay b/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay index e6dff3c9c9f33..f508f0b26a0b4 100644 --- a/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay +++ b/boards/shields/x_nucleo_idb05a1/x_nucleo_idb05a1.overlay @@ -4,6 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ + / { + chosen { + zephyr,bt-hci = &spbtle_rf_x_nucleo_idb05a1; + }; + }; + &arduino_spi { cs-gpios = <&arduino_header 1 GPIO_ACTIVE_LOW>; /* A1 */ diff --git a/boards/sifive/hifive1/board.cmake b/boards/sifive/hifive1/board.cmake index 4f39320870c18..93a6487d6c85b 100644 --- a/boards/sifive/hifive1/board.cmake +++ b/boards/sifive/hifive1/board.cmake @@ -28,3 +28,8 @@ elseif("${BOARD_REVISION}" STREQUAL "B") board_runner_args(jlink "--tool-opt=-autoconnect 1") include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) endif() + +set_ifndef(BOARD_SIM_RUNNER renode) +set_ifndef(BOARD_ROBOT_RUNNER renode-robot) +include(${ZEPHYR_BASE}/boards/common/renode.board.cmake) +include(${ZEPHYR_BASE}/boards/common/renode_robot.board.cmake) diff --git a/boards/sifive/hifive1/hifive1.yaml b/boards/sifive/hifive1/hifive1.yaml index 345768fb2797a..99463674324ba 100644 --- a/boards/sifive/hifive1/hifive1.yaml +++ b/boards/sifive/hifive1/hifive1.yaml @@ -19,4 +19,7 @@ testing: - bluetooth - flash - newlib + renode: + uart: sysbus.uart0 + resc: boards/sifive/hifive1/support/hifive1.resc vendor: sifive diff --git a/boards/sifive/hifive1/support/hifive1.resc b/boards/sifive/hifive1/support/hifive1.resc index e9aaa1be62d57..bbe5f26c8add1 100644 --- a/boards/sifive/hifive1/support/hifive1.resc +++ b/boards/sifive/hifive1/support/hifive1.resc @@ -23,6 +23,6 @@ showAnalyzer uart0 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/sifive/hifive_unleashed/hifive_unleashed.yaml b/boards/sifive/hifive_unleashed/hifive_unleashed.yaml index 749c62f4dcae8..1fb91e4c2e0ed 100644 --- a/boards/sifive/hifive_unleashed/hifive_unleashed.yaml +++ b/boards/sifive/hifive_unleashed/hifive_unleashed.yaml @@ -14,6 +14,9 @@ testing: - flash - newlib - crypto + renode: + uart: sysbus.uart0 + resc: boards/sifive/hifive_unleashed/support/hifive_unleashed.resc supported: - gpio - spi diff --git a/boards/sifive/hifive_unleashed/support/hifive_unleashed.resc b/boards/sifive/hifive_unleashed/support/hifive_unleashed.resc index a46d377d7c2bc..4d06081c5c946 100644 --- a/boards/sifive/hifive_unleashed/support/hifive_unleashed.resc +++ b/boards/sifive/hifive_unleashed/support/hifive_unleashed.resc @@ -20,6 +20,6 @@ showAnalyzer uart0 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/sifive/hifive_unmatched/hifive_unmatched.yaml b/boards/sifive/hifive_unmatched/hifive_unmatched.yaml index 0743a9cc0f5d4..6fbfb696ce153 100644 --- a/boards/sifive/hifive_unmatched/hifive_unmatched.yaml +++ b/boards/sifive/hifive_unmatched/hifive_unmatched.yaml @@ -11,6 +11,9 @@ testing: ignore_tags: - net - bluetooth + renode: + uart: sysbus.uart0 + resc: boards/sifive/hifive_unmatched/support/hifive_unmatched.resc supported: - spi - memc diff --git a/boards/sifive/hifive_unmatched/support/hifive_unmatched.resc b/boards/sifive/hifive_unmatched/support/hifive_unmatched.resc index 535bb06c69cea..4d18a9b86dd78 100644 --- a/boards/sifive/hifive_unmatched/support/hifive_unmatched.resc +++ b/boards/sifive/hifive_unmatched/support/hifive_unmatched.resc @@ -20,6 +20,6 @@ showAnalyzer uart0 macro reset """ - sysbus LoadELF $bin + sysbus LoadELF $elf """ runMacro $reset diff --git a/boards/silabs/dev_kits/index.rst b/boards/silabs/dev_kits/index.rst new file mode 100644 index 0000000000000..4a0cf90ce3320 --- /dev/null +++ b/boards/silabs/dev_kits/index.rst @@ -0,0 +1,10 @@ +.. _dev_kits: + +Dev Kits and Thunderboards +########################## + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/boards/silabs/efr32mg_sltb004a/CMakeLists.txt b/boards/silabs/dev_kits/sltb004a/CMakeLists.txt similarity index 100% rename from boards/silabs/efr32mg_sltb004a/CMakeLists.txt rename to boards/silabs/dev_kits/sltb004a/CMakeLists.txt diff --git a/boards/silabs/dev_kits/sltb004a/Kconfig.defconfig b/boards/silabs/dev_kits/sltb004a/Kconfig.defconfig new file mode 100644 index 0000000000000..3a9256b44e1ee --- /dev/null +++ b/boards/silabs/dev_kits/sltb004a/Kconfig.defconfig @@ -0,0 +1,14 @@ +# EFR32MG SLTB004A board + +# Copyright (c) 2018, Diego Sueiro +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLTB004A + +config CMU_HFXO_FREQ + default 40000000 + +config CMU_LFXO_FREQ + default 32768 + +endif # BOARD_SLTB004A diff --git a/boards/silabs/dev_kits/sltb004a/Kconfig.sltb004a b/boards/silabs/dev_kits/sltb004a/Kconfig.sltb004a new file mode 100644 index 0000000000000..58f4485dd4ea7 --- /dev/null +++ b/boards/silabs/dev_kits/sltb004a/Kconfig.sltb004a @@ -0,0 +1,7 @@ +# EFR32MG SLTB004A board + +# Copyright (c) 2018, Diego Sueiro +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLTB004A + select SOC_PART_NUMBER_EFR32MG12P332F1024GL125 diff --git a/boards/silabs/efr32mg_sltb004a/board.c b/boards/silabs/dev_kits/sltb004a/board.c similarity index 100% rename from boards/silabs/efr32mg_sltb004a/board.c rename to boards/silabs/dev_kits/sltb004a/board.c diff --git a/boards/silabs/efr32mg_sltb004a/board.cmake b/boards/silabs/dev_kits/sltb004a/board.cmake similarity index 100% rename from boards/silabs/efr32mg_sltb004a/board.cmake rename to boards/silabs/dev_kits/sltb004a/board.cmake diff --git a/boards/silabs/dev_kits/sltb004a/board.yml b/boards/silabs/dev_kits/sltb004a/board.yml new file mode 100644 index 0000000000000..2141aa3817df9 --- /dev/null +++ b/boards/silabs/dev_kits/sltb004a/board.yml @@ -0,0 +1,5 @@ +board: + name: sltb004a + vendor: silabs + socs: + - name: efr32mg12p332f1024gl125 diff --git a/boards/silabs/dev_kits/sltb004a/doc/index.rst b/boards/silabs/dev_kits/sltb004a/doc/index.rst new file mode 100644 index 0000000000000..8ee2b64604d06 --- /dev/null +++ b/boards/silabs/dev_kits/sltb004a/doc/index.rst @@ -0,0 +1,211 @@ +.. _sltb004a: + +EFR32MG12 Thunderboard (SLTB004A) +################################# + +Overview +******** + +The EFR32MG12 Thunderboard (a.k.a Thunderboard Sense 2) contains an MCU +from the EFR32MG12 family built on ARM® Cortex®-M4F processor with low +power capabilities. + +.. image:: sltb004a.jpg + :align: center + :alt: EFR32MG12 SLTB004A + +Hardware +******** + +- EFR32MG12 Mighty Gecko Wireless SoC with 38.4 MHz operating frequency +- ARM® Cortex® M4 core with 256 kB RAM and 1024 kB Flash +- Macronix ultra low power 8-Mbit SPI flash (MX25R8035F) +- 2.4 GHz ceramic antenna for wireless transmission +- Silicon Labs Si7021 relative humidity and temperature sensor +- Silicon Labs Si1133 UV index and ambient light sensor +- Silicon Labs Si7210 hall effect sensor +- Bosch Sensortec BMP280 barometric pressure sensor +- ams CCS811 indoor air quality gas sensor +- TDK InvenSense ICM-20648 6-axis inertial sensor +- TDK InvenSense ICS-43434 MEMS microphone +- Four high brightness RGB LEDs from Broadcom Limited (ASMT-YTB7-0AA02) +- One bi-color LED and two push buttons +- Power enable signals for fine grained power-control +- On-board SEGGER J-Link debugger for easy programming and debugging, which + includes a USB virtual COM port +- Mini Simplicity connector for access to energy profiling and advanced wireless + network debugging +- Breakout pads for GPIO access and connection to external hardware +- Reset button +- Automatic switch-over between USB and battery power +- CR2032 coin cell holder and external battery connector + +For more information about the EFR32MG12 SoC and Thunderboard Sense 2 board: + +- `EFR32MG12 Datasheet`_ +- `EFR32MG12 Reference Manual`_ +- `SLTB004A User Guide`_ +- `SLTB004A Schematics`_ + +Supported Features +================== + +The sltb004a board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c port-polling | ++-----------+------------+-------------------------------------+ +| SPI(M) | on-chip | spi port-polling | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ +| TRNG | on-chip | true random number generator | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/dev_kits/sltb004a/sltb004a_defconfig` + +Other hardware features are currently not supported by the port. + +Connections and IOs +=================== + +The EFR32MG12 SoC has eight gpio controllers (PORTA, PORTB, PORTC, PORTD, +PORTF, PORTI, PORTJ and PORTK). + +In the following table, the column Name contains Pin names. For example, PE2 +means Pin number 2 on PORTE and #27 represents the location bitfield , as used +in the board's and microcontroller's datasheets and manuals. + ++------+-------------+-----------------------------------+ +| Name | Function | Usage | ++======+=============+===================================+ +| PD8 | GPIO | LED0 (RED) | ++------+-------------+-----------------------------------+ +| PD9 | GPIO | LED1 (GREEN) | ++------+-------------+-----------------------------------+ +| PD14 | GPIO | SW0 Push Button PB0 | ++------+-------------+-----------------------------------+ +| PD15 | GPIO | Push Button PB1 | ++------+-------------+-----------------------------------+ +| PA0 | UART_TX | UART TX Console VCOM_TX US0_TX #0 | ++------+-------------+-----------------------------------+ +| PA1 | UART_RX | UART RX Console VCOM_RX US0_RX #0 | ++------+-------------+-----------------------------------+ +| PF3 | UART_TX | EXP12_UART_TX LEU0_TX #27 | ++------+-------------+-----------------------------------+ +| PF4 | UART_RX | EXP14_UART_RX LEU0_RX #27 | ++------+-------------+-----------------------------------+ +| PC10 | I2C_SDA | EXP16_I2C_SDA I2C0_SDA #15 | ++------+-------------+-----------------------------------+ +| PC11 | I2C_SCL | EXP15_I2C_SCL I2C0_SCL #15 | ++------+-------------+-----------------------------------+ +| PB6 | I2C_SDA | CCS811_I2C_SDA I2C1_SDA #6 | ++------+-------------+-----------------------------------+ +| PB7 | I2C_SCL | CCS811_I2C_SCL I2C1_SCL #6 | ++------+-------------+-----------------------------------+ +| PK0 | SPI_MOSI | Flash MOSI US2_TX #29 | ++------+-------------+-----------------------------------+ +| PK2 | SPI_MISO | Flash MISO US2_RX #30 | ++------+-------------+-----------------------------------+ +| PF7 | SPI_SCLK | Flash SCLK US2_CLK #18 | ++------+-------------+-----------------------------------+ +| PK1 | SPI_CS | Flash Chip Select (GPIO) | ++------+-------------+-----------------------------------+ + +System Clock +============ + +The EFR32MG12 SoC is configured to use the 38.4 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32MG12 SoC has four USARTs and one Low Energy UARTs (LEUART with 9600 +maximum baudrate). USART0 is configured as the Zephyr console and is connected +to the On-Board J-Link Debugger that presents a virtual COM port for general +purpose application serial data transfer with this interface. + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The SLTB004A includes an `J-Link`_ serial and debug adaptor built into the +board. The adaptor provides: + +- A USB connection to the host computer, which exposes a Mass Storage and a + USB Serial Port. +- A Serial Flash device, which implements the USB flash disk file storage. +- A physical UART connection which is relayed over interface USB Serial port. + +Flashing an application to SLTB004A +----------------------------------- + +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: sltb004a + :goals: build + +Connect the SLTB004A to your host computer using the USB port and you +should see a USB connection which exposes a Mass Storage (TB004) and a +USB Serial Port. Copy the generated zephyr.bin in the SLTB004A drive. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should be able to see on the corresponding Serial Port +the following message: + +.. code-block:: console + + Hello World! sltb004a + + +.. _SLTB004A User Guide: + https://www.silabs.com/documents/public/user-guides/ug309-sltb004a-user-guide.pdf + +.. _SLTB004A Schematics: + https://www.silabs.com/documents/public/schematic-files/BRD4166A-D00-schematic.pdf + +.. _EFR32MG12 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32mg12-datasheet.pdf + +.. _EFR32MG12 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg12-rm.pdf + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efr32mg_sltb004a/doc/efr32mg_sltb004a.jpg b/boards/silabs/dev_kits/sltb004a/doc/sltb004a.jpg similarity index 100% rename from boards/silabs/efr32mg_sltb004a/doc/efr32mg_sltb004a.jpg rename to boards/silabs/dev_kits/sltb004a/doc/sltb004a.jpg diff --git a/boards/silabs/efr32_radio/pre_dt_board.cmake b/boards/silabs/dev_kits/sltb004a/pre_dt_board.cmake similarity index 100% rename from boards/silabs/efr32_radio/pre_dt_board.cmake rename to boards/silabs/dev_kits/sltb004a/pre_dt_board.cmake diff --git a/boards/silabs/dev_kits/sltb004a/sltb004a-pinctrl.dtsi b/boards/silabs/dev_kits/sltb004a/sltb004a-pinctrl.dtsi new file mode 100644 index 0000000000000..e500e3b18bdd9 --- /dev/null +++ b/boards/silabs/dev_kits/sltb004a/sltb004a-pinctrl.dtsi @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2022 Silicon Labs + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for uart0 device, default state */ + usart0_default: usart0_default { + group1 { + /* configure PA.1 as UART_RX */ + psels = , + ; + }; + group2 { + /* configure PA.0 as UART_TX */ + psels = , + ; + }; + }; +}; diff --git a/boards/silabs/dev_kits/sltb004a/sltb004a.dts b/boards/silabs/dev_kits/sltb004a/sltb004a.dts new file mode 100644 index 0000000000000..033984be00770 --- /dev/null +++ b/boards/silabs/dev_kits/sltb004a/sltb004a.dts @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2018 Diego Sueiro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "sltb004a-pinctrl.dtsi" +#include + +/ { + model = "Silabs EFR32MG12 SLTB004A board (aka Thunderboard Sense 2)"; + compatible = "silabs,sltb004a", "silabs,efr32mg"; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + pwm-led0 = &pwm_led0; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + watchdog1 = &wdog1; + }; + + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpiod 8 0>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpiod 9 0>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + /* gpio flags need validation */ + gpios = <&gpiod 14 GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + /* gpio flags need validation */ + gpios = <&gpiod 15 GPIO_ACTIVE_LOW>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + status = "okay"; + pwm_led0: pwm_led0 { + pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; +}; + +&cpu0 { + clock-frequency = <38400000>; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usart2 { + compatible = "silabs,gecko-spi-usart"; + + #address-cells = <1>; + #size-cells = <0>; + + location-rx = ; + location-tx = ; + location-clk = ; + + cs-gpios = <&gpiok 1 GPIO_ACTIVE_LOW>; + + status = "okay"; + + mx25r80: mx25r8035f@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <80000000>; + size = <0x800000>; + jedec-id = [c2 28 14]; + sfdp-bfp = [ + e5 20 f1 ff ff ff 7f 00 44 eb 08 6b 08 3b 04 bb + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 + 10 d8 00 ff 23 72 f5 00 82 ed 04 b7 44 83 38 44 + 30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff + ]; + }; +}; + +&leuart0 { + current-speed = <9600>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&pinctrl { + i2c0_default: i2c0_default { + group1 { + psels = , + , + , + ; + }; + }; + + i2c1_default: i2c1_default { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c1 { + /* This set selects for CCS811_I2C supporting CCS811 */ + pinctrl-0 = <&i2c1_default>; + pinctrl-names = "default"; + status = "okay"; + + ccs811: ccs811@5a { + compatible = "ams,ccs811"; + reg = <0x5a>; + supply-gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; + irq-gpios = <&gpiof 13 GPIO_ACTIVE_LOW>; + wake-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; + }; + + /* This set selects for ENV_I2C supporting Si7021, Si11330, BMP280 */ + /* + location-sda = ; + location-scl = ; + */ + + /* This set selects for HALL_I2C supporting Si7210 */ + /* + location-sda = ; + location-scl = ; + */ +}; + +&rtcc0 { + prescaler = <1>; + status = "okay"; +}; + +&timer0 { + status = "okay"; + + pwm0: pwm { + status = "okay"; + pin-location = ; + prescaler = <1024>; + }; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpioa { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&gpiof { + status = "okay"; +}; + +&gpiok { + status = "okay"; +}; + +&wdog0 { + status = "okay"; +}; + +&wdog1 { + status = "okay"; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 6Kb of storage at the end of the 1024Kb of flash */ + storage_partition: partition@fe800 { + label = "storage"; + reg = <0x000fe800 0x00001800>; + }; + + }; +}; + +&trng0 { + status = "okay"; +}; diff --git a/boards/silabs/dev_kits/sltb004a/sltb004a.yaml b/boards/silabs/dev_kits/sltb004a/sltb004a.yaml new file mode 100644 index 0000000000000..a610e85fdee1f --- /dev/null +++ b/boards/silabs/dev_kits/sltb004a/sltb004a.yaml @@ -0,0 +1,21 @@ +identifier: sltb004a +name: Thunderboard Sense 2 (SLTB004A, BRD4166A) +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - i2c + - nvs + - spi + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48_defconfig b/boards/silabs/dev_kits/sltb004a/sltb004a_defconfig similarity index 100% rename from boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48_defconfig rename to boards/silabs/dev_kits/sltb004a/sltb004a_defconfig diff --git a/boards/silabs/dev_kits/sltb009a/Kconfig.defconfig b/boards/silabs/dev_kits/sltb009a/Kconfig.defconfig new file mode 100644 index 0000000000000..6c21d423607ab --- /dev/null +++ b/boards/silabs/dev_kits/sltb009a/Kconfig.defconfig @@ -0,0 +1,20 @@ +# EFM32GG SLTB009A default board configuration +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLTB009A + +config CMU_HFXO_FREQ + default 50000000 + +config CMU_HFRCO_FREQ + default 72000000 + +config CMU_LFXO_FREQ + default 32768 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +endif # BOARD_SLTB009A diff --git a/boards/silabs/dev_kits/sltb009a/Kconfig.sltb009a b/boards/silabs/dev_kits/sltb009a/Kconfig.sltb009a new file mode 100644 index 0000000000000..d486de8476985 --- /dev/null +++ b/boards/silabs/dev_kits/sltb009a/Kconfig.sltb009a @@ -0,0 +1,6 @@ +# EFM32GG SLTB009A board configuration +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLTB009A + select SOC_PART_NUMBER_EFM32GG12B810F1024GM64 diff --git a/boards/silabs/efm32gg_sltb009a/board.cmake b/boards/silabs/dev_kits/sltb009a/board.cmake similarity index 100% rename from boards/silabs/efm32gg_sltb009a/board.cmake rename to boards/silabs/dev_kits/sltb009a/board.cmake diff --git a/boards/silabs/dev_kits/sltb009a/board.yml b/boards/silabs/dev_kits/sltb009a/board.yml new file mode 100644 index 0000000000000..af69758728d32 --- /dev/null +++ b/boards/silabs/dev_kits/sltb009a/board.yml @@ -0,0 +1,5 @@ +board: + name: sltb009a + vendor: silabs + socs: + - name: efm32gg12b810f1024gm64 diff --git a/boards/silabs/dev_kits/sltb009a/doc/index.rst b/boards/silabs/dev_kits/sltb009a/doc/index.rst new file mode 100644 index 0000000000000..2ec7a83f32574 --- /dev/null +++ b/boards/silabs/dev_kits/sltb009a/doc/index.rst @@ -0,0 +1,166 @@ +.. _efm32gg_sltb009a: + +EFM32GG12 Thunderboard (SLTB009A) +################################# + +Overview +******** + +The EFM32GG12 Thunderboard Kit (SLTB009A) is an evaluation platform for the +EFM32GG12 Giant Gecko Microcontroller, featuring an ARM Cortex-M4 with FPU, +1024kB flash, and 192kB RAM. + +.. figure:: sltb009a.jpg + :align: center + :alt: SLTB009A + + SLTB009A (Credit: Silicon Labs) + +Hardware +******** + +- PDM stereo microphones +- USB connectivity +- On-board Segger J-Link USB debugger +- 2 user buttons and 2 LEDs +- USB C connector + +For more information about the WGM160P and SLTB009A board: + +- `SLTB009A Website`_ +- `SLTB009A User Guide`_ +- `EFM32GG12 Datasheet`_ +- `EFM32GG12 Reference Manual`_ + +Supported Features +================== + +The efm32gg_sltb009a board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c port-polling | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/dev_kits/sltb009a/sltb009a_defconfig` + +Connections and IOs +=================== + +The EFM32GG12 MCU has six GPIO controllers (PORTA to PORTF), all of which are +currently enabled for the SLTB009A board. + +In the following table, the column **Name** contains pin names. For example, PE1 +means pin number 1 on PORTE, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PE12 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PA13 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PD5 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PD8 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PE7 | UART_TX | UART TX Console VCOM_TX US0_TX #1 | ++-------+-------------+-------------------------------------+ +| PE6 | UART_RX | UART RX Console VCOM_RX US0_RX #1 | ++-------+-------------+-------------------------------------+ +| PC0 | I2C_SDA | SENSOR_I2C_SDA I2C0_SDA #1 | ++-------+-------------+-------------------------------------+ +| PC1 | I2C_SCL | SENSOR_I2C_SCL I2C0_SCL #1 | ++-------+-------------+-------------------------------------+ +| PC4 | I2C_SDA | SENSOR_I2C_SDA I2C1_SDA #1 | ++-------+-------------+-------------------------------------+ +| PC5 | I2C_SCL | SENSOR_I2C_SCL I2C1_SCL #1 | ++-------+-------------+-------------------------------------+ + + +System Clock +============ + +The EFM32GG12 MCU is configured to work at 72 MHz. + +Serial Port +=========== + +The EFM32GG12 SoC has five USARTs, two UARTs and two Low Energy UARTs (LEUART). +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The SLTB009A includes an `J-Link`_ serial and debug adaptor built into the +board. The adaptor provides: + +- A USB connection to the host computer +- A physical UART connection which is relayed over interface USB serial port. + +Flashing an application to SLTB009A +----------------------------------- + +Connect the SLTB009A to your host computer using the USB port. + +Here is an example to build and flash the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: sltb009a + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you'll see the following message on the corresponding serial port +terminal session: + +.. code-block:: console + + Hello World! sltb009a + +.. _SLTB009A Website: + https://www.silabs.com/development-tools/thunderboard/thunderboard-gg12-kit + +.. _SLTB009A User Guide: + https://www.silabs.com/documents/public/user-guides/ug371-sltb009a-user-guide.pdf + +.. _EFM32GG12 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efm32gg12-datasheet.pdf + +.. _EFM32GG12 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efm32gg12-rm.pdf + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32gg_sltb009a/doc/efm32gg12-thunderboard-kit.jpg b/boards/silabs/dev_kits/sltb009a/doc/sltb009a.jpg similarity index 100% rename from boards/silabs/efm32gg_sltb009a/doc/efm32gg12-thunderboard-kit.jpg rename to boards/silabs/dev_kits/sltb009a/doc/sltb009a.jpg diff --git a/boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a-pinctrl.dtsi b/boards/silabs/dev_kits/sltb009a/sltb009a-pinctrl.dtsi similarity index 100% rename from boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a-pinctrl.dtsi rename to boards/silabs/dev_kits/sltb009a/sltb009a-pinctrl.dtsi diff --git a/boards/silabs/dev_kits/sltb009a/sltb009a.dts b/boards/silabs/dev_kits/sltb009a/sltb009a.dts new file mode 100644 index 0000000000000..1c36fb59f21fa --- /dev/null +++ b/boards/silabs/dev_kits/sltb009a/sltb009a.dts @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "sltb009a-pinctrl.dtsi" + +/ { + model = "Silicon Labs EFM32GG12 SLTB009A board"; + compatible = "silabs,sltb009a"; + + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpioe 12 GPIO_ACTIVE_HIGH>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpioa 13 GPIO_ACTIVE_HIGH>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpiod 5 GPIO_ACTIVE_HIGH>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + gpios = <&gpiod 8 GPIO_ACTIVE_HIGH>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usart4 { + current-speed = <115200>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&leuart0 { + current-speed = <9600>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rtcc0 { + prescaler = <1>; + status = "okay"; +}; + +&gpioa { + status = "okay"; + board-controller-enable { + // VCOM Isolation. Set PA15 to HIGH to enable VCOM_{RX,TX}. + gpio-hog; + gpios = <15 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&gpioe { + status = "okay"; +}; + +&gpiof { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 12Kb of storage at the end of the 2048Kb of flash */ + storage_partition: partition@1fd000 { + label = "storage"; + reg = <0x001fd000 0x00003000>; + }; + }; +}; + +&wdog0 { + status = "okay"; +}; + +&trng0 { + status = "okay"; +}; + +&cpu0 { + clock-frequency = <72000000>; +}; diff --git a/boards/silabs/dev_kits/sltb009a/sltb009a.yaml b/boards/silabs/dev_kits/sltb009a/sltb009a.yaml new file mode 100644 index 0000000000000..468b6b48d56f5 --- /dev/null +++ b/boards/silabs/dev_kits/sltb009a/sltb009a.yaml @@ -0,0 +1,16 @@ +identifier: sltb009a +name: Thunderboard EFM32GG12 (SLTB009A, BRD2207A) +type: mcu +arch: arm +ram: 192 +flash: 1024 +toolchain: + - zephyr +supported: + - i2c + - gpio + - nvs +testing: + ignore_tags: + - bluetooth +vendor: silabs diff --git a/boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a_defconfig b/boards/silabs/dev_kits/sltb009a/sltb009a_defconfig similarity index 100% rename from boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a_defconfig rename to boards/silabs/dev_kits/sltb009a/sltb009a_defconfig diff --git a/boards/silabs/efr32_thunderboard/CMakeLists.txt b/boards/silabs/dev_kits/sltb010a/CMakeLists.txt similarity index 100% rename from boards/silabs/efr32_thunderboard/CMakeLists.txt rename to boards/silabs/dev_kits/sltb010a/CMakeLists.txt diff --git a/boards/silabs/dev_kits/sltb010a/Kconfig b/boards/silabs/dev_kits/sltb010a/Kconfig new file mode 100644 index 0000000000000..6fdb24720ae40 --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/Kconfig @@ -0,0 +1,8 @@ +# EFR32 Thunderboard-style boards + +# Copyright (c) 2022, Silicon Labs +# SPDX-License-Identifier: Apache-2.0 + +module = BOARD_SLTB010A +module-str = Board Control +source "subsys/logging/Kconfig.template.log_config" diff --git a/boards/silabs/dev_kits/sltb010a/Kconfig.defconfig b/boards/silabs/dev_kits/sltb010a/Kconfig.defconfig new file mode 100644 index 0000000000000..9b45efccc9001 --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/Kconfig.defconfig @@ -0,0 +1,34 @@ +# Thunderboard-style boards + +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config CMU_HFXO_FREQ + default 38400000 + +config CMU_LFXO_FREQ + default 32768 + +if SOC_GECKO_USE_RAIL + +config FPU + default y + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config COMMON_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 3072 if PM + default 2304 + +endif # BT + +config REGULATOR + default y if SI7210 diff --git a/boards/silabs/dev_kits/sltb010a/Kconfig.sltb010a b/boards/silabs/dev_kits/sltb010a/Kconfig.sltb010a new file mode 100644 index 0000000000000..43710c2540871 --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/Kconfig.sltb010a @@ -0,0 +1,7 @@ +# EFR32BG SLTB010A board + +# Copyright (c) 2021, Sateesh Kotapati +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLTB010A + select SOC_PART_NUMBER_EFR32BG22C224F512IM40 diff --git a/boards/silabs/dev_kits/sltb010a/board.c b/boards/silabs/dev_kits/sltb010a/board.c new file mode 100644 index 0000000000000..e4dc2c3f62a79 --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/board.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Sateesh Kotapati + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#ifdef CONFIG_SOC_GECKO_DEV_INIT +#include "em_cmu.h" +#endif + + +LOG_MODULE_REGISTER(thunderboard, CONFIG_BOARD_SLTB010A_LOG_LEVEL); + +static int thunderboard_init_clocks(void); + +static int thunderboard_init(void) +{ + int ret; + +#ifdef CONFIG_SOC_GECKO_DEV_INIT + thunderboard_init_clocks(); +#endif + static struct gpio_dt_spec wake_up_gpio_dev = + GPIO_DT_SPEC_GET(DT_NODELABEL(wake_up_trigger), gpios); + + + if (!gpio_is_ready_dt(&wake_up_gpio_dev)) { + LOG_ERR("Wake-up GPIO device was not found!\n"); + return -ENODEV; + } + ret = gpio_pin_configure_dt(&wake_up_gpio_dev, GPIO_OUTPUT_ACTIVE); + if (ret < 0) + return ret; + + return 0; +} + +#ifdef CONFIG_SOC_GECKO_DEV_INIT +static int thunderboard_init_clocks(void) +{ + CMU_ClockSelectSet(cmuClock_SYSCLK, cmuSelect_HFRCODPLL); +#if defined(_CMU_EM01GRPACLKCTRL_MASK) + CMU_ClockSelectSet(cmuClock_EM01GRPACLK, cmuSelect_HFRCODPLL); +#endif +#if defined(_CMU_EM01GRPBCLKCTRL_MASK) + CMU_ClockSelectSet(cmuClock_EM01GRPBCLK, cmuSelect_HFRCODPLL); +#endif + CMU_ClockSelectSet(cmuClock_EM23GRPACLK, cmuSelect_LFRCO); +#if defined(RTCC_PRESENT) + CMU_ClockSelectSet(cmuClock_RTCC, cmuSelect_LFRCO); +#endif + CMU_ClockSelectSet(cmuClock_WDOG0, cmuSelect_LFRCO); + + return 0; +} +#endif + +/* needs to be done after GPIO driver init */ +SYS_INIT(thunderboard_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/silabs/dev_kits/sltb010a/board.cmake b/boards/silabs/dev_kits/sltb010a/board.cmake new file mode 100644 index 0000000000000..fdaebc0c84443 --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=EFR32BG22C224F512IM40" "--reset-after-load") +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/silabs/dev_kits/sltb010a/board.yml b/boards/silabs/dev_kits/sltb010a/board.yml new file mode 100644 index 0000000000000..4586a51ef722b --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/board.yml @@ -0,0 +1,11 @@ +boards: + - name: sltb010a + vendor: silabs + socs: + - name: efr32bg22c224f512im40 + revision: + format: number + default: "2" + revisions: + - name: "0" + - name: "2" diff --git a/boards/silabs/dev_kits/sltb010a/doc/index.rst b/boards/silabs/dev_kits/sltb010a/doc/index.rst new file mode 100644 index 0000000000000..1299bef0bc2cd --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/doc/index.rst @@ -0,0 +1,223 @@ +.. _sltb010a: + +EFR32BG22 Thunderboard (SLTB010A) +################################# + +SLTB010A is a development kit based on the EFR32BG22 SoC. Early revisions of +the kit (A00 and A01) use a slightly different PCB (BRD4184A) from later +revisions (BRD4184B). + +.. image:: ./sltb010a.jpg + :align: center + :alt: SLTB010A board + +Hardware +******** + +- EFR32BG22 Blue Gecko Wireless SoC with upto 76.8 MHz operating frequency +- ARM® Cortex® M33 core with 32 kB RAM and 512 kB Flash +- Macronix ultra low power 8-Mbit SPI flash (MX25R8035F) +- 2.4 GHz ceramic antenna for wireless transmission +- Silicon Labs Si7021 relative humidity and temperature sensor +- Silicon Labs Si1133 UV index and ambient light sensor (EFR32BG22-BRD4184A) +- Vishay VEML6035 ambient light sensor (EFR32BG22-BRD4184B) +- Silicon Labs Si7210 hall effect sensor +- TDK InvenSense ICM-20648 6-axis inertial sensor +- Two Knowles SPK0641HT4H-1 MEMS microphones with PDM output (EFR32BG22-BRD4184B) +- One LED and one push button +- Power enable signals and isolation switches for ultra low power operation +- On-board SEGGER J-Link debugger for easy programming and debugging, which + includes a USB virtual COM port and Packet Trace Interface (PTI) +- Mini Simplicity connector for access to energy profiling and advanced wireless + network debugging +- Breakout pads for GPIO access and connection to external hardware +- Reset button +- Automatic switch-over between USB and battery power +- CR2032 coin cell holder and external battery connector + +For more information about the EFR32BG SoC and Thunderboard EFR32BG22 board: + +- `EFR32BG22 Website`_ +- `EFR32BG22 Datasheet`_ +- `EFR32xG22 Reference Manual`_ +- `Thunderboard EFR32BG22 Website`_ +- `EFR32BG22-BRD4184A User Guide`_ +- `EFR32BG22-BRD4184B User Guide`_ +- `EFR32BG22-BRD4184A Schematics`_ +- `EFR32BG22-BRD4184B Schematics`_ + +Supported Features +================== + +The sltb010a board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | stimer | ++-----------+------------+-------------------------------------+ +| SPI(M/S) | on-chip | spi | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ +| TRNG | on-chip | true random number generator | ++-----------+------------+-------------------------------------+ +| I2C(M/S) | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| RADIO | on-chip | bluetooth | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/dev_kits/sltb010a/sltb010a_defconfig`. + +Connections and IOs +=================== + +The EFR32BG22 SoC has four gpio controllers (PORTA, PORTB, PORTC and PORTD). + +There are two variants of this board, "A" and "B". Please take a look at your PCB, +to determine which one you have, as the GPIO pin bindings vary between those two. + +BRD4184A (SLTB010A revision A00 and A01): + ++------+-------------+-----------------------------------+ +| Pin | Function | Usage | ++======+=============+===================================+ +| PB0 | GPIO | LED0 (YELLOW) | ++------+-------------+-----------------------------------+ +| PB1 | GPIO | SW0 Push Button PB0 | ++------+-------------+-----------------------------------+ +| PA5 | UART_TX | UART TX Console VCOM_TX US1_TX #1 | ++------+-------------+-----------------------------------+ +| PA6 | UART_RX | UART RX Console VCOM_RX US1_RX #1 | ++------+-------------+-----------------------------------+ + +BRD4184B (SLTB010A revision A02 and newer): + ++------+-------------+-----------------------------------+ +| Pin | Function | Usage | ++======+=============+===================================+ +| PA4 | GPIO | LED0 (YELLOW) | ++------+-------------+-----------------------------------+ +| PB3 | GPIO | SW0 Push Button PB0 | ++------+-------------+-----------------------------------+ +| PA5 | UART_TX | UART TX Console VCOM_TX US1_TX #1 | ++------+-------------+-----------------------------------+ +| PA6 | UART_RX | UART RX Console VCOM_RX US1_RX #1 | ++------+-------------+-----------------------------------+ + +System Clock +============ + +The EFR32BG22 SoC is configured to use the 38.4 MHz external oscillator on the +board. + +Programming and Debugging +========================= + +Flashing an application +----------------------- + +Connect your device to your host computer using the USB port. +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application, then flash it to the device: + +BRD4184A: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: sltb010a@0 + :goals: flash + +BRD4184B: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: sltb010a@2 + :goals: flash + +.. note:: + `west flash` requires `SEGGER J-Link software`_ to be installed on you host + computer. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should be able to see on the corresponding Serial Port +the following message: + +.. code-block:: console + + Hello World! sltb010a + +Bluetooth +========= + +To use the BLE function, run the command below to retrieve necessary binary +blobs from the SiLabs HAL repository. + +.. code-block:: console + + west blobs fetch hal_silabs + +Then build the Zephyr kernel and a Bluetooth sample with the following +command. The :ref:`bluetooth-observer-sample` sample application is used in +this example. + +BRD4184A: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/observer + :board: sltb010a@0 + :goals: build + +BRD4184B: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/observer + :board: sltb010a@2 + :goals: build + + +.. _Thunderboard EFR32BG22 Website: + https://www.silabs.com/development-tools/thunderboard/thunderboard-bg22-kit + +.. _EFR32BG22-BRD4184A User Guide: + https://www.silabs.com/documents/public/user-guides/ug415-sltb010a-user-guide.pdf + +.. _EFR32BG22-BRD4184B User Guide: + https://www.silabs.com/documents/public/user-guides/ug464-brd4184b-user-guide.pdf + +.. _EFR32BG22-BRD4184A Schematics: + https://www.silabs.com/documents/public/schematic-files/BRD4184A-A01-schematic.pdf + +.. _EFR32BG22-BRD4184B Schematics: + https://www.silabs.com/documents/public/schematic-files/BRD4184B-A02-schematic.pdf + +.. _EFR32BG22 Website: + https://www.silabs.com/wireless/bluetooth/efr32bg22-series-2-socs + +.. _EFR32BG22 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32bg22-datasheet.pdf + +.. _EFR32xG22 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg22-rm.pdf + +.. _SEGGER J-Link software: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efr32_thunderboard/doc/efr32bg_sltb010a.jpg b/boards/silabs/dev_kits/sltb010a/doc/sltb010a.jpg similarity index 100% rename from boards/silabs/efr32_thunderboard/doc/efr32bg_sltb010a.jpg rename to boards/silabs/dev_kits/sltb010a/doc/sltb010a.jpg diff --git a/boards/silabs/efr32_thunderboard/dts/bindings/silabs,gecko-wake-up-triggers.yaml b/boards/silabs/dev_kits/sltb010a/dts/bindings/silabs,gecko-wake-up-triggers.yaml similarity index 100% rename from boards/silabs/efr32_thunderboard/dts/bindings/silabs,gecko-wake-up-triggers.yaml rename to boards/silabs/dev_kits/sltb010a/dts/bindings/silabs,gecko-wake-up-triggers.yaml diff --git a/boards/silabs/efr32_thunderboard/pre_dt_board.cmake b/boards/silabs/dev_kits/sltb010a/pre_dt_board.cmake similarity index 100% rename from boards/silabs/efr32_thunderboard/pre_dt_board.cmake rename to boards/silabs/dev_kits/sltb010a/pre_dt_board.cmake diff --git a/boards/silabs/dev_kits/sltb010a/sltb010a.dts b/boards/silabs/dev_kits/sltb010a/sltb010a.dts new file mode 100644 index 0000000000000..3f352ea6008f1 --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/sltb010a.dts @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021 Sateesh Kotapati + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "thunderboard.dtsi" + +/ { + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + sw0 = &button0; + spi0 = &usart0; + watchdog0 = &wdog0; + /* If enabled, MCUboot uses this for recovery mode entrance */ + mcuboot-led0 = &led0; + mcuboot-button0 = &button0; + }; + + chosen { + zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &bt_hci_silabs; + }; +}; + +&flash0 { + partitions { + /* Reserve 48 KiB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000c000>; + read-only; + }; + + /* Reserve 224 KiB for the application in slot 0 */ + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000c000 0x00038000>; + }; + + /* Reserve 224 KiB for the application in slot 1 */ + slot1_partition: partition@44000 { + label = "image-1"; + reg = <0x00044000 0x00038000>; + }; + + /* Set 16 KiB of storage at the end of the 512 KiB of flash */ + storage_partition: partition@7c000 { + label = "storage"; + reg = <0x0007c000 0x00004000>; + }; + }; +}; + +&sw_imu_enable { + enable-gpios = <&gpiob GECKO_PIN(4) GPIO_ACTIVE_HIGH>; +}; + +&bt_hci_silabs { + status = "okay"; +}; diff --git a/boards/silabs/dev_kits/sltb010a/sltb010a_0.overlay b/boards/silabs/dev_kits/sltb010a/sltb010a_0.overlay new file mode 100644 index 0000000000000..c108c8e67db4c --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/sltb010a_0.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 Sateesh Kotapati + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + model = "Silicon Labs EFR32BG22 Thunderboard (SLTB010A) using BRD4184A"; + compatible = "silabs,efr32bg22c224f512im40", "silabs,sltb010a", + "silabs,efr32bg22"; +}; + +&sw_sensor_enable { + enable-gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_HIGH>; +}; + +&sw_mic_enable { + enable-gpios = <&gpioa GECKO_PIN(0) GPIO_ACTIVE_HIGH>; +}; diff --git a/boards/silabs/dev_kits/sltb010a/sltb010a_0.yaml b/boards/silabs/dev_kits/sltb010a/sltb010a_0.yaml new file mode 100644 index 0000000000000..ff50de0ccb681 --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/sltb010a_0.yaml @@ -0,0 +1,21 @@ +identifier: sltb010a@0 +name: Thunderboard EFR32BG22 (SLTB010A, BRD4184A) +type: mcu +arch: arm +ram: 32 +flash: 512 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - counter + - gpio + - uart + - i2c + - spi +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/dev_kits/sltb010a/sltb010a_2.overlay b/boards/silabs/dev_kits/sltb010a/sltb010a_2.overlay new file mode 100644 index 0000000000000..224722da280c3 --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/sltb010a_2.overlay @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021 Sateesh Kotapati + * Copyright (c) 2023 Piotr Dymacz + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + model = "Silicon Labs EFR32BG22 Thunderboard (SLTB010A) using BRD4184B"; + compatible = "silabs,efr32bg22c224f512im40", "silabs,sltb010a", + "silabs,efr32bg22"; +}; + +&button0 { + gpios = <&gpiob GECKO_PIN(3) GPIO_ACTIVE_LOW>; +}; + +&led0 { + gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_HIGH>; +}; + +&sw_sensor_enable { + enable-gpios = <&gpioc GECKO_PIN(6) GPIO_ACTIVE_HIGH>; +}; + +&sw_mic_enable { + enable-gpios = <&gpioc GECKO_PIN(7) GPIO_ACTIVE_HIGH>; +}; diff --git a/boards/silabs/dev_kits/sltb010a/sltb010a_2.yaml b/boards/silabs/dev_kits/sltb010a/sltb010a_2.yaml new file mode 100644 index 0000000000000..24e1dfb580d5e --- /dev/null +++ b/boards/silabs/dev_kits/sltb010a/sltb010a_2.yaml @@ -0,0 +1,21 @@ +identifier: sltb010a@2 +name: Thunderboard EFR32BG22 (SLTB010A, BRD4184B) +type: mcu +arch: arm +ram: 32 +flash: 512 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - counter + - gpio + - uart + - i2c + - spi +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184a_defconfig b/boards/silabs/dev_kits/sltb010a/sltb010a_defconfig similarity index 100% rename from boards/silabs/efr32_thunderboard/efr32bg22_brd4184a_defconfig rename to boards/silabs/dev_kits/sltb010a/sltb010a_defconfig diff --git a/boards/silabs/efr32_thunderboard/thunderboard.dtsi b/boards/silabs/dev_kits/sltb010a/thunderboard.dtsi similarity index 100% rename from boards/silabs/efr32_thunderboard/thunderboard.dtsi rename to boards/silabs/dev_kits/sltb010a/thunderboard.dtsi diff --git a/boards/silabs/dev_kits/xg24_dk2601b/Kconfig b/boards/silabs/dev_kits/xg24_dk2601b/Kconfig new file mode 100644 index 0000000000000..f346dac95afe3 --- /dev/null +++ b/boards/silabs/dev_kits/xg24_dk2601b/Kconfig @@ -0,0 +1,12 @@ +# EFR32XG24 DK2601B board + +# Copyright (c) 2022, Silicon Labs +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_XG24_DK2601B + +module = BOARD_EFR32MG24 +module-str = Board Control +source "subsys/logging/Kconfig.template.log_config" + +endif # BOARD_XG24_DK2601B diff --git a/boards/silabs/dev_kits/xg24_dk2601b/Kconfig.defconfig b/boards/silabs/dev_kits/xg24_dk2601b/Kconfig.defconfig new file mode 100644 index 0000000000000..a6a2953d6e514 --- /dev/null +++ b/boards/silabs/dev_kits/xg24_dk2601b/Kconfig.defconfig @@ -0,0 +1,45 @@ +# EFR32XG24 DK2601B board + +# Copyright (c) 2021, Sateesh Kotapati +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_XG24_DK2601B + +config CMU_HFXO_FREQ + default 40000000 + +config CMU_LFXO_FREQ + default 32768 + +config FLASH_BASE_ADDRESS + hex + default 0x08000000 + +if SOC_GECKO_USE_RAIL + +config FPU + default y + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config MINIMAL_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 2304 + +if SHELL + +config SHELL_STACK_SIZE + default 4096 + +endif # SHELL + +endif # BT + +endif # BOARD_XG24_DK2601B diff --git a/boards/silabs/dev_kits/xg24_dk2601b/Kconfig.xg24_dk2601b b/boards/silabs/dev_kits/xg24_dk2601b/Kconfig.xg24_dk2601b new file mode 100644 index 0000000000000..bf4ac3677f1f4 --- /dev/null +++ b/boards/silabs/dev_kits/xg24_dk2601b/Kconfig.xg24_dk2601b @@ -0,0 +1,7 @@ +# EFR32XG24 DK2601B board + +# Copyright (c) 2021, Sateesh Kotapati +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_XG24_DK2601B + select SOC_PART_NUMBER_EFR32MG24B310F1536IM48 diff --git a/boards/silabs/efr32xg24_dk2601b/board.c b/boards/silabs/dev_kits/xg24_dk2601b/board.c similarity index 100% rename from boards/silabs/efr32xg24_dk2601b/board.c rename to boards/silabs/dev_kits/xg24_dk2601b/board.c diff --git a/boards/silabs/efr32xg24_dk2601b/board.cmake b/boards/silabs/dev_kits/xg24_dk2601b/board.cmake similarity index 100% rename from boards/silabs/efr32xg24_dk2601b/board.cmake rename to boards/silabs/dev_kits/xg24_dk2601b/board.cmake diff --git a/boards/silabs/dev_kits/xg24_dk2601b/board.yml b/boards/silabs/dev_kits/xg24_dk2601b/board.yml new file mode 100644 index 0000000000000..f946744d228e6 --- /dev/null +++ b/boards/silabs/dev_kits/xg24_dk2601b/board.yml @@ -0,0 +1,5 @@ +board: + name: xg24_dk2601b + vendor: silabs + socs: + - name: efr32mg24b310f1536im48 diff --git a/boards/silabs/efr32xg24_dk2601b/doc/img/efr32xg24_dk2601b.jpg b/boards/silabs/dev_kits/xg24_dk2601b/doc/img/xg24_dk2601b.jpg similarity index 100% rename from boards/silabs/efr32xg24_dk2601b/doc/img/efr32xg24_dk2601b.jpg rename to boards/silabs/dev_kits/xg24_dk2601b/doc/img/xg24_dk2601b.jpg diff --git a/boards/silabs/dev_kits/xg24_dk2601b/doc/index.rst b/boards/silabs/dev_kits/xg24_dk2601b/doc/index.rst new file mode 100644 index 0000000000000..551d08765de88 --- /dev/null +++ b/boards/silabs/dev_kits/xg24_dk2601b/doc/index.rst @@ -0,0 +1,184 @@ +.. _efr32mg24_dk2601b: + +EFR32xG24 Dev Kit (xG24-DK2601B) +################################ + +Overview +******** + +The EFR32MG24 Mighty Gecko Board dev kit contains +a Wireless System-On-Chip from the EFR32MG24 family built on an +ARM Cortex®-M33F processor with excellent low power capabilities. + +.. figure:: ./img/xg24_dk2601b.jpg + :height: 260px + :align: center + :alt: xG24-DK2601B Dev Kit board + + xG24-DK2601B (image courtesy of Silicon Labs) + +Hardware +******** + +- EFR32MG24B310F1536IM48-B Mighty Gecko SoC +- CPU core: ARM Cortex®-M33 with FPU +- Flash memory: 1536 kB +- RAM: 256 kB +- Transmit power: up to +20 dBm +- Operation frequency: 2.4 GHz +- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). +- On board sensors: + + - Silicon Labs Si7021 relative humidity & temperature sensor + - Silicon Labs Si7210 hall effect sensor + - 2x TDK InvenSense ICS-43434 MEMS microphones with I2S output + - TDK InvenSense ICM-20689 6-axis inertial measurement sensor + - Vishay VEML6035 ambient light sensor + - Bosch BMP384 pressure sensor with internal temperature sensor + +For more information about the EFR32MG24 SoC and BRD2601B board, refer to these +documents: + +- `EFR32MG24 Website`_ +- `EFR32MG24 Datasheet`_ +- `EFR32xG24 Reference Manual`_ +- `BRD2601B User Guide`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | stimer | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ +| TRNG | on-chip | semailbox | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ +| I2C(M/S) | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| RADIO | on-chip | bluetooth | ++-----------+------------+-------------------------------------+ + +Other hardware features are currently not supported by the port. + +Connections and IOs +=================== + +In the following table, the column **Name** contains Pin names. For example, PA2 +means Pin number 2 on PORTA, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PA4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PB0 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PB2 | GPIO | Push Button 0 | ++-------+-------------+-------------------------------------+ +| PB3 | GPIO | Push Button 1 | ++-------+-------------+-------------------------------------+ +| PA5 | USART0_TX | UART Console VCOM_TX US0_TX | ++-------+-------------+-------------------------------------+ +| PA6 | USART0_RX | UART Console VCOM_RX US0_RX | ++-------+-------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b_defconfig` + +System Clock +============ + +The EFR32MG24 SoC is configured to use the 39 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32MG24 SoC has one USART and two EUSARTs. +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: xg24_dk2601b + :goals: build + +Connect the xg24_dk2601b to your host computer using the USB port and you +should see a USB connection. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you'll see the following message on the corresponding serial port +terminal session: + +.. code-block:: console + + Hello World! xg24_dk2601b + +Bluetooth +========= + +To use the BLE function, run the command below to retrieve necessary binary +blobs from the SiLabs HAL repository. + +.. code-block:: console + + west blobs fetch hal_silabs + +Then build the Zephyr kernel and a Bluetooth sample with the following +command. The :ref:`bluetooth-observer-sample` sample application is used in +this example. + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/observer + :board: xg24_dk2601b + :goals: build + +.. _EFR32MG24 Website: + https://www.silabs.com/wireless/zigbee/efr32mg24-series-2-socs# + +.. _EFR32MG24 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32mg24-datasheet.pdf + +.. _EFR32xG24 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg24-rm.pdf + +.. _BRD2601B User Guide: + https://www.silabs.com/documents/public/user-guides/ug524-brd2601b-user-guide.pdf + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efr32xg24_dk2601b/dts/bindings/silabs,gecko-wake-up-trigger.yaml b/boards/silabs/dev_kits/xg24_dk2601b/dts/bindings/silabs,gecko-wake-up-trigger.yaml similarity index 100% rename from boards/silabs/efr32xg24_dk2601b/dts/bindings/silabs,gecko-wake-up-trigger.yaml rename to boards/silabs/dev_kits/xg24_dk2601b/dts/bindings/silabs,gecko-wake-up-trigger.yaml diff --git a/boards/silabs/efr32mg_sltb004a/pre_dt_board.cmake b/boards/silabs/dev_kits/xg24_dk2601b/pre_dt_board.cmake similarity index 100% rename from boards/silabs/efr32mg_sltb004a/pre_dt_board.cmake rename to boards/silabs/dev_kits/xg24_dk2601b/pre_dt_board.cmake diff --git a/boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b.dts b/boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b.dts new file mode 100644 index 0000000000000..ac03b32ff37e5 --- /dev/null +++ b/boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b.dts @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2020 TriaGnoSys GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include + +/ { + model = "Silicon Labs BRD2601B (xG24 Dev Kit)"; + compatible = "silabs,xg24_brd2601b", "silabs,efr32mg24"; + + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &bt_hci_silabs; + }; + + aliases { + led0 = &red_led; + led1 = &green_led; + led2 = &blue_led; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + }; + + leds { + compatible = "gpio-leds"; + red_led: led_2 { + gpios = <&gpiod GECKO_PIN(2) GPIO_ACTIVE_LOW>; + }; + green_led: led_0 { + gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_LOW>; + }; + blue_led: led_1 { + gpios = <&gpiob GECKO_PIN(0) GPIO_ACTIVE_LOW>; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpiob GECKO_PIN(2) GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + button1: button_1 { + gpios = <&gpiob GECKO_PIN(3) GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; + + wake_up_trigger: gpio-wake-up { + compatible = "silabs,gecko-wake-up-trigger"; + gpios = <&gpioa GECKO_PIN(5) GPIO_ACTIVE_LOW>; + }; + + sensor_enable: gpio_switch_0 { + compatible = "regulator-fixed"; + regulator-name = "sensor_enable"; + enable-gpios = <&gpioc GECKO_PIN(9) GPIO_ACTIVE_HIGH>; + regulator-boot-on; + }; +}; + +&cpu0 { + clock-frequency = <78000000>; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; + + veml6035: veml6035@29 { + compatible = "vishay,veml7700"; + reg = <0x29>; + status = "okay"; + }; + + si7210: si7210@30 { + compatible = "silabs,si7210"; + reg = <0x30>; + status = "okay"; + }; + + si7021: si7021@40 { + compatible = "silabs,si7006"; + reg = <0x40>; + status = "okay"; + }; +}; + +&gpio { + status = "okay"; +}; + +&gpioa { + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&wdog0 { + status = "okay"; +}; + +&se { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 48 kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x0000c000>; + read-only; + }; + + /* Reserve 464 kB for the application in slot 0 */ + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000c000 0x00074000>; + }; + + /* Reserve 464 kB for the application in slot 1 */ + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00080000 0x00074000>; + }; + + /* Reserve 32 kB for the scratch partition */ + scratch_partition: partition@f4000 { + label = "image-scratch"; + reg = <0x000f4000 0x00008000>; + }; + + /* Set 528Kb of storage at the end of the 1024Kb of flash */ + storage_partition: partition@fc000 { + label = "storage"; + reg = <0x000fc000 0x00084000>; + }; + }; +}; + +&adc0 { + status = "okay"; +}; + +&stimer0 { + status = "okay"; +}; + +&bt_hci_silabs { + status = "okay"; +}; diff --git a/boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b.yaml b/boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b.yaml new file mode 100644 index 0000000000000..fece6ecddf557 --- /dev/null +++ b/boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b.yaml @@ -0,0 +1,21 @@ +identifier: xg24_dk2601b +name: xG24 Dev Kit (xG24-DK2601B, BRD2601B) +type: mcu +arch: arm +ram: 256 +flash: 1536 +toolchain: + - zephyr + - gnuarmemb +supported: + - counter + - gpio + - uart + - watchdog +testing: + ignore_tags: + - net + - bluetooth + - pm + - hwinfo +vendor: silabs diff --git a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b_defconfig b/boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b_defconfig similarity index 100% rename from boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b_defconfig rename to boards/silabs/dev_kits/xg24_dk2601b/xg24_dk2601b_defconfig diff --git a/boards/silabs/dev_kits/xg27_dk2602a/CMakeLists.txt b/boards/silabs/dev_kits/xg27_dk2602a/CMakeLists.txt new file mode 100644 index 0000000000000..ca93e65ac913a --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2021 Sateesh Kotapati +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_UART_GECKO) + zephyr_library() + zephyr_library_sources(board.c) +endif() diff --git a/boards/silabs/dev_kits/xg27_dk2602a/Kconfig b/boards/silabs/dev_kits/xg27_dk2602a/Kconfig new file mode 100644 index 0000000000000..965bfde207a38 --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/Kconfig @@ -0,0 +1,8 @@ +# EFR32 Thunderboard-style boards + +# Copyright (c) 2022, Silicon Labs +# SPDX-License-Identifier: Apache-2.0 + +module = BOARD_XG27_DK2602A +module-str = Board Control +source "subsys/logging/Kconfig.template.log_config" diff --git a/boards/silabs/dev_kits/xg27_dk2602a/Kconfig.defconfig b/boards/silabs/dev_kits/xg27_dk2602a/Kconfig.defconfig new file mode 100644 index 0000000000000..850f2cd8538bb --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/Kconfig.defconfig @@ -0,0 +1,32 @@ +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +config CMU_HFXO_FREQ + default 38400000 + +config CMU_LFXO_FREQ + default 32768 + +if SOC_GECKO_USE_RAIL + +config FPU + default y + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config COMMON_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 3072 if PM + default 2304 + +endif # BT + +config REGULATOR + default y if SI7210 diff --git a/boards/silabs/dev_kits/xg27_dk2602a/Kconfig.xg27_dk2602a b/boards/silabs/dev_kits/xg27_dk2602a/Kconfig.xg27_dk2602a new file mode 100644 index 0000000000000..d5f2945cdfdfe --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/Kconfig.xg27_dk2602a @@ -0,0 +1,7 @@ +# EFR32BG SLTB010A board + +# Copyright (c) 2021, Sateesh Kotapati +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_XG27_DK2602A + select SOC_PART_NUMBER_EFR32BG27C140F768IM40 diff --git a/boards/silabs/dev_kits/xg27_dk2602a/board.c b/boards/silabs/dev_kits/xg27_dk2602a/board.c new file mode 100644 index 0000000000000..fcdcab0f1b29a --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/board.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021 Sateesh Kotapati + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#ifdef CONFIG_SOC_GECKO_DEV_INIT +#include "em_cmu.h" +#endif + + +LOG_MODULE_REGISTER(dev_kit, CONFIG_BOARD_XG27_DK2602A_LOG_LEVEL); + +static int dev_kit_init_clocks(void); + +static int dev_kit_init(void) +{ + int ret; + +#ifdef CONFIG_SOC_GECKO_DEV_INIT + dev_kit_init_clocks(); +#endif + static struct gpio_dt_spec wake_up_gpio_dev = + GPIO_DT_SPEC_GET(DT_NODELABEL(wake_up_trigger), gpios); + + + if (!gpio_is_ready_dt(&wake_up_gpio_dev)) { + LOG_ERR("Wake-up GPIO device was not found!\n"); + return -ENODEV; + } + ret = gpio_pin_configure_dt(&wake_up_gpio_dev, GPIO_OUTPUT_ACTIVE); + if (ret < 0) + return ret; + + return 0; +} + +#ifdef CONFIG_SOC_GECKO_DEV_INIT +static int dev_kit_init_clocks(void) +{ + CMU_ClockSelectSet(cmuClock_SYSCLK, cmuSelect_HFRCODPLL); +#if defined(_CMU_EM01GRPACLKCTRL_MASK) + CMU_ClockSelectSet(cmuClock_EM01GRPACLK, cmuSelect_HFRCODPLL); +#endif +#if defined(_CMU_EM01GRPBCLKCTRL_MASK) + CMU_ClockSelectSet(cmuClock_EM01GRPBCLK, cmuSelect_HFRCODPLL); +#endif + CMU_ClockSelectSet(cmuClock_EM23GRPACLK, cmuSelect_LFRCO); +#if defined(RTCC_PRESENT) + CMU_ClockSelectSet(cmuClock_RTCC, cmuSelect_LFRCO); +#endif + CMU_ClockSelectSet(cmuClock_WDOG0, cmuSelect_LFRCO); + + return 0; +} +#endif + +/* needs to be done after GPIO driver init */ +SYS_INIT(dev_kit_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/silabs/dev_kits/xg27_dk2602a/board.cmake b/boards/silabs/dev_kits/xg27_dk2602a/board.cmake new file mode 100644 index 0000000000000..a5086fdebd91f --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Silicon Laboratories Inc. +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=EFR32BG27CxxxF768" "--reset-after-load") +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +board_runner_args(silabs_commander "--device=EFR32BG27C140F768IM40") +include(${ZEPHYR_BASE}/boards/common/silabs_commander.board.cmake) diff --git a/boards/silabs/dev_kits/xg27_dk2602a/board.yml b/boards/silabs/dev_kits/xg27_dk2602a/board.yml new file mode 100644 index 0000000000000..83a3037a1a785 --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/board.yml @@ -0,0 +1,5 @@ +boards: + - name: xg27_dk2602a + vendor: silabs + socs: + - name: efr32bg27c140f768im40 diff --git a/boards/silabs/dev_kits/xg27_dk2602a/doc/index.rst b/boards/silabs/dev_kits/xg27_dk2602a/doc/index.rst new file mode 100644 index 0000000000000..8bf44f5edbd8c --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/doc/index.rst @@ -0,0 +1,143 @@ +.. _xg27_dk2602a: + +EFR32xG27 Dev Kit (xG27-DK2602A) +################################ + +Silicon Labs xG27-DK2602A is a Dev Kit using the EFR32BG27 SoC. The kit +consists of the EFR32BG27 +8 dBm Dev Kit Board (BRD2602A). + +.. figure:: ./xg27_dk2602a.png + :height: 260px + :align: center + :alt: xG27-DK2602A + + xG27-DK2602A (image courtesy of Silicon Labs) + +Hardware +******** + +- EFR32BG27 Blue Gecko Wireless SoC with up to 76.8 MHz operating frequency +- ARM® Cortex® M33 core with 64 kB RAM and 768 kB Flash +- Macronix ultra low power 8-Mbit SPI flash (MX25R8035F) +- 2.4 GHz ceramic antenna for wireless transmission +- Silicon Labs Si7021 relative humidity and temperature sensor +- Vishay VEML6035 low power, high sensitivity ambient light Sensor +- Silicon Labs Si7210 hall effect sensor +- TDK InvenSense ICM-20689 6-axis inertial sensor +- Pair of PDM microphones +- One LED and one push button +- Power enable signals and isolation switches for ultra low power operation +- On-board SEGGER J-Link debugger for easy programming and debugging, which + includes a USB virtual COM port and Packet Trace Interface (PTI) +- Mini Simplicity connector for access to energy profiling and advanced wireless + network debugging +- Breakout pads for GPIO access and connection to external hardware +- Reset button +- CR2032 coin cell holder and external battery connector + +For more information, refer to these documents: + +- `xG27 Dev Kit User's Guide`_ + +Supported Features +================== + +The xg27_dk2602a board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ + +Flashing +======== + +The xG27 Dev Kit includes an embedded `J-Link`_ adapter built around +EFM32GG12 microcontroller (not user-programmable). +The adapter provides: + +- SWD interface to EFR32BG27 for flashing and debugging. +- SWO trace interface to EFR32BG27 for tracing. +- UART interface to EFR32BG27 for console access. +- A USB connection to the host computer, which exposes CDC-ACM Serial Port + endpoints for access to the console UART interface and proprietary J-Link + endpoints for access to the SWD and SWO interfaces. + +UART functionality of the adapter is accessible via standard CDC-ACM USB driver +present in most desktop operating systems and any standard serial port terminal +program e.g. `picocom`_. + +SWD and SWO functionality is accessible via `Simplicity Commander`_. + +The simplest way to flash the board is by using West, which runs Simplicity +Commander in unattended mode and passes all the necessary arguments to it. + +- If Simplicity Commander is installed in the system and the directory in + which `commander` executable is located is present in the `PATH` environment + variable: + + .. code-block:: console + + west flash + +- Otherwise, one should specify full path to the `commander` executable: + + .. code-block:: console + + west flash --commander /commander + +- In case several J-Link adapters are connected, you must specify serial number + of the adapter which should be used for flashing: + + .. code-block:: console + + west flash --dev-id + +Programming and Debugging +========================= + +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: xg27_dk2602a + :goals: build + +Connect your device to your host computer using the USB port and you +should see a USB connection. Use `west`'s flash command + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should be able to see on the corresponding Serial Port +the following message: + +.. code-block:: console + + Hello World! xg27_dk2602a + +.. _picocom: + https://github.com/npat-efault/picocom + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _Simplicity Commander: + https://www.silabs.com/developers/mcu-programming-options + +.. _xG27 Dev Kit User's Guide: + https://www.silabs.com/documents/public/user-guides/ug554-brd2602a-user-guide.pdf diff --git a/boards/silabs/dev_kits/xg27_dk2602a/doc/xg27_dk2602a.png b/boards/silabs/dev_kits/xg27_dk2602a/doc/xg27_dk2602a.png new file mode 100644 index 0000000000000..0bb9399b11baa Binary files /dev/null and b/boards/silabs/dev_kits/xg27_dk2602a/doc/xg27_dk2602a.png differ diff --git a/boards/silabs/dev_kits/xg27_dk2602a/dts/bindings/silabs,gecko-wake-up-triggers.yaml b/boards/silabs/dev_kits/xg27_dk2602a/dts/bindings/silabs,gecko-wake-up-triggers.yaml new file mode 100644 index 0000000000000..fd49c3732cad5 --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/dts/bindings/silabs,gecko-wake-up-triggers.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2022, Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: GPIO Wake Up Trigger for EFR32BG22/EFR32BG27 + +compatible: "silabs,gecko-wake-up-trigger" + +include: base.yaml + +properties: + gpios: + type: phandle-array + required: true + description: | + GPIO used as wake up trigger from EM4 sleep diff --git a/boards/silabs/efr32xg24_dk2601b/pre_dt_board.cmake b/boards/silabs/dev_kits/xg27_dk2602a/pre_dt_board.cmake similarity index 100% rename from boards/silabs/efr32xg24_dk2601b/pre_dt_board.cmake rename to boards/silabs/dev_kits/xg27_dk2602a/pre_dt_board.cmake diff --git a/boards/silabs/dev_kits/xg27_dk2602a/thunderboard.dtsi b/boards/silabs/dev_kits/xg27_dk2602a/thunderboard.dtsi new file mode 100644 index 0000000000000..7197983747670 --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/thunderboard.dtsi @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + chosen { + zephyr,bt-c2h-uart = &usart1; + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpiob GECKO_PIN(0) GPIO_ACTIVE_HIGH>; + label = "LED 0"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpiob GECKO_PIN(1) GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + }; + + wake_up_trigger: gpio-wake-up { + compatible = "silabs,gecko-wake-up-trigger"; + gpios = <&gpioa GECKO_PIN(5) GPIO_ACTIVE_LOW>; + }; + + /* GPIOs that power up different sensors */ + sw_sensor_enable: gpio_switch_0 { + compatible = "regulator-fixed"; + status = "okay"; + regulator-name = "sw_sensor_enable"; + startup-delay-us = <100000>; + /* Always on since sensor drivers won't enable it automatically */ + regulator-always-on; + }; + + sw_mic_enable: gpio_switch_1 { + compatible = "regulator-fixed"; + status = "okay"; + regulator-name = "sw_mic_enable"; + startup-delay-us = <100000>; + }; + + sw_imu_enable: gpio_switch_2 { + compatible = "regulator-fixed"; + status = "okay"; + regulator-name = "sw_imu_enable"; + startup-delay-us = <100000>; + }; + +}; + +&cpu0 { + clock-frequency = <76800000>; +}; + +&pstate_em3 { + status = "disabled"; +}; + +&usart0 { + status = "okay"; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + + cs-gpios = <&gpioc 3 GPIO_ACTIVE_LOW>; + + mx25r80: mx25r8035f@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <80000000>; + size = <0x800000>; + jedec-id = [c2 28 14]; + sfdp-bfp = [ + e5 20 f1 ff ff ff 7f 00 44 eb 08 6b 08 3b 04 bb + ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 + 10 d8 00 ff 23 72 f5 00 82 ed 04 b7 44 83 38 44 + 30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff + ]; + }; +}; + +&usart1 { + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&usart1_default>; + pinctrl-names = "default"; +}; + +&wdog0 { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpioa { + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&burtc0 { + status = "okay"; +}; + +&stimer0 { + status = "okay"; +}; + +&trng { + status = "okay"; +}; + +&pinctrl { + i2c0_default: i2c0_default { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; + + si7210@30 { + compatible = "silabs,si7210"; + status = "okay"; + reg = <0x30>; + }; +}; + +&adc0 { + status = "okay"; +}; diff --git a/boards/silabs/dev_kits/xg27_dk2602a/xg27_dk2602a.dts b/boards/silabs/dev_kits/xg27_dk2602a/xg27_dk2602a.dts new file mode 100644 index 0000000000000..6dba2bfa6485d --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/xg27_dk2602a.dts @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "thunderboard.dtsi" + +/ { + model = "Silicon Labs xG27-DK2602A Dev Kit"; + compatible = "silabs,efr32bg27c140f768im40", "silabs,xg27_dk2602a", + "silabs,efr32bg27"; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + sw0 = &button0; + spi0 = &usart0; + watchdog0 = &wdog0; + /* If enabled, MCUboot uses this for recovery mode entrance */ + mcuboot-led0 = &led0; + mcuboot-button0 = &button0; + }; + + chosen { + zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &bt_hci_silabs; + }; +}; + +&flash0 { + partitions { + /* Reserve 48 KiB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 0x0000c000>; + read-only; + }; + + /* Reserve 328 KiB for the application in slot 0 */ + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000c000 0x00052000>; + }; + + /* Reserve 328 KiB for the application in slot 1 */ + slot1_partition: partition@5e000 { + label = "image-1"; + reg = <0x0005e000 0x00052000>; + }; + + /* Set 64 KiB of storage at the end of the 768 KiB of flash */ + storage_partition: partition@b0000 { + label = "storage"; + reg = <0x000b0000 0x00010000>; + }; + }; +}; + +&led0 { + gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_HIGH>; +}; + +&sw_sensor_enable { + enable-gpios = <&gpioc GECKO_PIN(6) GPIO_ACTIVE_HIGH>; +}; + + +&sw_mic_enable { + enable-gpios = <&gpioc GECKO_PIN(7) GPIO_ACTIVE_HIGH>; +}; + + +&sw_imu_enable { + enable-gpios = <&gpiob GECKO_PIN(4) GPIO_ACTIVE_HIGH>; +}; + +&button0 { + gpios = <&gpiob GECKO_PIN(3) GPIO_ACTIVE_LOW>; +}; + +&bt_hci_silabs { + status = "okay"; +}; diff --git a/boards/silabs/dev_kits/xg27_dk2602a/xg27_dk2602a.yaml b/boards/silabs/dev_kits/xg27_dk2602a/xg27_dk2602a.yaml new file mode 100644 index 0000000000000..b965fa25afeb6 --- /dev/null +++ b/boards/silabs/dev_kits/xg27_dk2602a/xg27_dk2602a.yaml @@ -0,0 +1,19 @@ +identifier: xg27_dk2602a +name: xG27 Dev Kit (xG27-DK2602A, BRD2602A) +type: mcu +arch: arm +ram: 64 +flash: 768 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - counter + - gpio + - uart +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184b_defconfig b/boards/silabs/dev_kits/xg27_dk2602a/xg27_dk2602a_defconfig similarity index 100% rename from boards/silabs/efr32_thunderboard/efr32bg22_brd4184b_defconfig rename to boards/silabs/dev_kits/xg27_dk2602a/xg27_dk2602a_defconfig diff --git a/boards/silabs/efm32gg_sltb009a/Kconfig.defconfig b/boards/silabs/efm32gg_sltb009a/Kconfig.defconfig deleted file mode 100644 index a24eda68abd03..0000000000000 --- a/boards/silabs/efm32gg_sltb009a/Kconfig.defconfig +++ /dev/null @@ -1,20 +0,0 @@ -# EFM32GG SLTB009A default board configuration -# Copyright (c) 2023 Antmicro -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFM32GG_SLTB009A - -config CMU_HFXO_FREQ - default 50000000 - -config CMU_HFRCO_FREQ - default 72000000 - -config CMU_LFXO_FREQ - default 32768 - -config LOG_BACKEND_SWO_FREQ_HZ - default 875000 - depends on LOG_BACKEND_SWO - -endif # BOARD_EFM32GG_SLTB009A diff --git a/boards/silabs/efm32gg_sltb009a/Kconfig.efm32gg_sltb009a b/boards/silabs/efm32gg_sltb009a/Kconfig.efm32gg_sltb009a deleted file mode 100644 index e1f93ff9da904..0000000000000 --- a/boards/silabs/efm32gg_sltb009a/Kconfig.efm32gg_sltb009a +++ /dev/null @@ -1,6 +0,0 @@ -# EFM32GG SLTB009A board configuration -# Copyright (c) 2023 Antmicro -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFM32GG_SLTB009A - select SOC_PART_NUMBER_EFM32GG12B810F1024GM64 diff --git a/boards/silabs/efm32gg_sltb009a/board.yml b/boards/silabs/efm32gg_sltb009a/board.yml deleted file mode 100644 index 388301f55e1f2..0000000000000 --- a/boards/silabs/efm32gg_sltb009a/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: efm32gg_sltb009a - vendor: silabs - socs: - - name: efm32gg12b810f1024gm64 diff --git a/boards/silabs/efm32gg_sltb009a/doc/index.rst b/boards/silabs/efm32gg_sltb009a/doc/index.rst deleted file mode 100644 index e27fcc34ba0f0..0000000000000 --- a/boards/silabs/efm32gg_sltb009a/doc/index.rst +++ /dev/null @@ -1,165 +0,0 @@ -.. _efm32gg_sltb009a: - -EFM32GG12 Thunderboard Kit -########################## - -Overview -******** - -The EFM32GG12 Thunderboard Kit (SLTB009A) is an evaluation platform for the EFM32GG12 GiantGecko Microcontroller, -featuring an ARM Cortex-M4 with FPU, 1024kB flash, and 192kB RAM. - -.. figure:: efm32gg12-thunderboard-kit.jpg - :align: center - :alt: SLTB009A - - SLTB009A (Credit: Silicon Labs) - -Hardware -******** - -- PDM stereo microphones -- USB connectivity -- On-board Segger J-Link USB debugger -- 2 user buttons and 2 LEDs -- USB C connector - -For more information about the WGM160P and SLTB009A board: - -- `SLTB009A Website`_ -- `SLTB009A User Guide`_ -- `EFM32GG12 Datasheet`_ -- `EFM32GG12 Reference Manual`_ - -Supported Features -================== - -The efm32gg_sltb009a board configuration supports the following hardware -features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | rtcc | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| I2C | on-chip | i2c port-polling | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a_defconfig` - -Connections and IOs -=================== - -The EFM32GG12 MCU has six GPIO controllers (PORTA to PORTF), all of which are -currently enabled for the SLTB009A board. - -In the following table, the column **Name** contains pin names. For example, PE1 -means pin number 1 on PORTE, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PE12 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PA13 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PD5 | GPIO | Push Button PB0 | -+-------+-------------+-------------------------------------+ -| PD8 | GPIO | Push Button PB1 | -+-------+-------------+-------------------------------------+ -| PE7 | UART_TX | UART TX Console VCOM_TX US0_TX #1 | -+-------+-------------+-------------------------------------+ -| PE6 | UART_RX | UART RX Console VCOM_RX US0_RX #1 | -+-------+-------------+-------------------------------------+ -| PC0 | I2C_SDA | SENSOR_I2C_SDA I2C0_SDA #1 | -+-------+-------------+-------------------------------------+ -| PC1 | I2C_SCL | SENSOR_I2C_SCL I2C0_SCL #1 | -+-------+-------------+-------------------------------------+ -| PC4 | I2C_SDA | SENSOR_I2C_SDA I2C1_SDA #1 | -+-------+-------------+-------------------------------------+ -| PC5 | I2C_SCL | SENSOR_I2C_SCL I2C1_SCL #1 | -+-------+-------------+-------------------------------------+ - - -System Clock -============ - -The EFM32GG12 MCU is configured to work at 72 MHz. - -Serial Port -=========== - -The EFM32GG12 SoC has five USARTs, two UARTs and two Low Energy UARTs (LEUART). -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The SLTB009A includes an `J-Link`_ serial and debug adaptor built into the -board. The adaptor provides: - -- A USB connection to the host computer -- A physical UART connection which is relayed over interface USB serial port. - -Flashing an application to SLTB009A --------------------------------------- - -Connect the SLTB009A to your host computer using the USB port. - -Here is an example to build and flash the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efm32gg_stb009a - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you'll see the following message on the corresponding serial port -terminal session: - -.. code-block:: console - - Hello World! efm32gg_sltb009a - -.. _SLTB009A Website: - https://www.silabs.com/development-tools/thunderboard/thunderboard-gg12-kit - -.. _SLTB009A User Guide: - https://www.silabs.com/documents/public/user-guides/ug371-sltb009a-user-guide.pdf - -.. _EFM32GG12 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efm32gg12-datasheet.pdf - -.. _EFM32GG12 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efm32gg12-rm.pdf - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a.dts b/boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a.dts deleted file mode 100644 index eac47f561235a..0000000000000 --- a/boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a.dts +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2023 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "efm32gg_sltb009a-pinctrl.dtsi" - -/ { - model = "Silicon Labs EFM32GG SLTB009A board"; - compatible = "silabs,efm32gg_sltb009a"; - - chosen { - zephyr,console = &usart0; - zephyr,shell-uart = &usart0; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - }; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - sw0 = &button0; - sw1 = &button1; - watchdog0 = &wdog0; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpioe 12 GPIO_ACTIVE_HIGH>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpioa 13 GPIO_ACTIVE_HIGH>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - gpios = <&gpiod 5 GPIO_ACTIVE_HIGH>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - gpios = <&gpiod 8 GPIO_ACTIVE_HIGH>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&usart4 { - current-speed = <115200>; - location-rx = ; - location-tx = ; - status = "okay"; -}; - -&leuart0 { - current-speed = <9600>; - location-rx = ; - location-tx = ; - status = "okay"; -}; - -&i2c0 { - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&i2c1 { - pinctrl-0 = <&i2c1_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&rtcc0 { - prescaler = <1>; - status = "okay"; -}; - -&gpioa { - status = "okay"; - board-controller-enable { - // VCOM Isolation. Set PA15 to HIGH to enable VCOM_{RX,TX}. - gpio-hog; - gpios = <15 GPIO_ACTIVE_HIGH>; - output-high; - }; -}; - -&gpio { - location-swo = <0>; - status = "okay"; -}; - -&gpiob { - status = "okay"; -}; - -&gpioc { - status = "okay"; -}; - -&gpiod { - status = "okay"; -}; - -&gpioe { - status = "okay"; -}; - -&gpiof { - status = "okay"; -}; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Set 12Kb of storage at the end of the 2048Kb of flash */ - storage_partition: partition@1fd000 { - label = "storage"; - reg = <0x001fd000 0x00003000>; - }; - }; -}; - -&wdog0 { - status = "okay"; -}; - -&trng0 { - status = "okay"; -}; - -&cpu0 { - clock-frequency = <72000000>; -}; diff --git a/boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a.yaml b/boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a.yaml deleted file mode 100644 index ddea24692faf5..0000000000000 --- a/boards/silabs/efm32gg_sltb009a/efm32gg_sltb009a.yaml +++ /dev/null @@ -1,16 +0,0 @@ -identifier: efm32gg_sltb009a -name: EFM32GG-SLTB009A -type: mcu -arch: arm -ram: 192 -flash: 1024 -toolchain: - - zephyr -supported: - - i2c - - gpio - - nvs -testing: - ignore_tags: - - bluetooth -vendor: silabs diff --git a/boards/silabs/efm32gg_slwstk6121a/Kconfig.defconfig b/boards/silabs/efm32gg_slwstk6121a/Kconfig.defconfig deleted file mode 100644 index 33e5b1192c0fe..0000000000000 --- a/boards/silabs/efm32gg_slwstk6121a/Kconfig.defconfig +++ /dev/null @@ -1,29 +0,0 @@ -# EFM32GG SLWSTK6121A default board configuration -# Copyright (c) 2019 Interay Solutions B.V. -# Copyright (c) 2019 Oane Kingma -# Copyright (c) 2020 Thorvald Natvig -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFM32GG_SLWSTK6121A - -config CMU_HFXO_FREQ - default 50000000 - -config CMU_HFRCO_FREQ - default 72000000 - -config CMU_LFXO_FREQ - default 32768 - -config LOG_BACKEND_SWO_FREQ_HZ - default 875000 - depends on LOG_BACKEND_SWO - -if NETWORKING - -config NET_L2_ETHERNET - default y - -endif # NETWORKING - -endif # BOARD_EFM32GG_SLWSTK6121A diff --git a/boards/silabs/efm32gg_slwstk6121a/Kconfig.efm32gg_slwstk6121a b/boards/silabs/efm32gg_slwstk6121a/Kconfig.efm32gg_slwstk6121a deleted file mode 100644 index 2e064a306f119..0000000000000 --- a/boards/silabs/efm32gg_slwstk6121a/Kconfig.efm32gg_slwstk6121a +++ /dev/null @@ -1,8 +0,0 @@ -# EFM32GG SLWSTK6121A board configuration -# Copyright (c) 2019 Interay Solutions B.V. -# Copyright (c) 2019 Oane Kingma -# Copyright (c) 2020 Thorvald Natvig -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFM32GG_SLWSTK6121A - select SOC_PART_NUMBER_EFM32GG11B820F2048GM64 diff --git a/boards/silabs/efm32gg_slwstk6121a/board.yml b/boards/silabs/efm32gg_slwstk6121a/board.yml deleted file mode 100644 index 7f91de0275938..0000000000000 --- a/boards/silabs/efm32gg_slwstk6121a/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: efm32gg_slwstk6121a - vendor: silabs - socs: - - name: efm32gg11b820f2048gm64 diff --git a/boards/silabs/efm32gg_slwstk6121a/doc/index.rst b/boards/silabs/efm32gg_slwstk6121a/doc/index.rst deleted file mode 100644 index 47d2a5a93a10f..0000000000000 --- a/boards/silabs/efm32gg_slwstk6121a/doc/index.rst +++ /dev/null @@ -1,186 +0,0 @@ -.. _efm32gg_slwstk6121a: - -WGM160P Starter Kit -################### - -Overview -******** - -The WGM160P Starter Kit SLWSTK6121A comes with the BRD4321A radio board. -This radio boards contains a WGM160P module, which combines the WF200 Wi-Fi -transceiver with an EFM32GG11 microcontroller. - -.. figure:: wgm160p-starter-kit.jpg - :align: center - :alt: SLWSTK6121A - - SLWSTK6121A (image courtesy of Silicon Labs) - -Hardware -******** - -- Advanced Energy Monitoring provides real-time information about the energy - consumption of an application or prototype design. -- Ultra low power 128x128 pixel color Memory-LCD -- 2 user buttons and 2 LEDs -- Si7021 Humidity and Temperature Sensor -- On-board Segger J-Link USB and Ethernet debugger -- 10/100Base-TX ethernet PHY and RJ-45 jack (on included expansion board) -- MicroSD card slot -- USB Micro-AB connector - -For more information about the WGM160P and SLWSTK6121A board: - -- `WGM160P Website`_ -- `WGM160P Datasheet`_ -- `SLWSTK6121A Website`_ -- `SLWSTK6121A User Guide`_ -- `EFM32GG11 Datasheet`_ -- `EFM32GG11 Reference Manual`_ -- `WF200 Datasheet`_ - -Supported Features -================== - -The efm32gg_slwstk6121a board configuration supports the following hardware -features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | rtcc | -+-----------+------------+-------------------------------------+ -| ETHERNET | on-chip | ethernet | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| I2C | on-chip | i2c port-polling | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a_defconfig` - -Other hardware features, including the WF200 WiFi transceiver, are -currently not supported by the port. - -Connections and IOs -=================== - -The WGM160P's EFM32GG11 SoC has six GPIO controllers (PORTA to PORTF), all of which are -currently enabled for the SLWSTK6121A board. - -In the following table, the column **Name** contains pin names. For example, PE1 -means pin number 1 on PORTE, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PA4 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PA5 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PD6 | GPIO | Push Button PB0 | -+-------+-------------+-------------------------------------+ -| PD8 | GPIO | Push Button PB1 | -+-------+-------------+-------------------------------------+ -| PE7 | UART_TX | UART TX Console VCOM_TX US0_TX #1 | -+-------+-------------+-------------------------------------+ -| PE6 | UART_RX | UART RX Console VCOM_RX US0_RX #1 | -+-------+-------------+-------------------------------------+ -| PB11 | I2C_SDA | SENSOR_I2C_SDA I2C1_SDA #1 | -+-------+-------------+-------------------------------------+ -| PB12 | I2C_SCL | SENSOR_I2C_SCL I2C1_SCL #1 | -+-------+-------------+-------------------------------------+ - - -System Clock -============ - -The EFM32GG11 SoC is configured to use the 50 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFM32GG11 SoC has four USARTs, two UARTs and two Low Energy UARTs (LEUART). -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The SLWSTK6121A includes an `J-Link`_ serial and debug adaptor built into the -board. The adaptor provides: - -- A USB connection to the host computer -- A physical UART connection which is relayed over interface USB serial port. - -Flashing an application to SLWSTK6121A --------------------------------------- - -Connect the SLWSTK6121A to your host computer using the USB port. - -Here is an example to build and flash the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efm32gg_slwstk6121a - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you'll see the following message on the corresponding serial port -terminal session: - -.. code-block:: console - - Hello World! efm32gg_slwstk6121a - -.. _WGM160P Website: - https://www.silabs.com/wireless/wi-fi/wfm160-series-1-modules - -.. _WGM160P Datasheet: - https://www.silabs.com/documents/public/data-sheets/wgm160p-datasheet.pdf - -.. _SLWSTK6121A Website: - https://www.silabs.com/development-tools/wireless/wi-fi/wgm160p-wifi-module-starter-kit - -.. _SLWSTK6121A User Guide: - https://www.silabs.com/documents/public/user-guides/ug351-brd4321a-user-guide.pdf - -.. _EFM32GG11 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efm32gg11-datasheet.pdf - -.. _EFM32GG11 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efm32gg11-rm.pdf - -.. _WF200 Datasheet: - https://www.silabs.com/documents/public/data-sheets/wf200-datasheet.pdf - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a.dts b/boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a.dts deleted file mode 100644 index a82fa89672267..0000000000000 --- a/boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a.dts +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2019 Interay Solutions B.V. - * Copyright (c) 2019 Oane Kingma - * Copyright (c) 2020 Thorvald Natvig - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "efm32gg_slwstk6121a-pinctrl.dtsi" - -/ { - model = "Silicon Labs EFM32GG SLWSTK6121A board"; - compatible = "silabs,efm32gg_slwstk6121a", "silabs,efm32gg11b"; - - chosen { - zephyr,console = &usart0; - zephyr,shell-uart = &usart0; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - }; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - sw0 = &button0; - sw1 = &button1; - watchdog0 = &wdog0; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpioa 4 0>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpioa 5 0>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - /* gpio flags need validation */ - gpios = <&gpiod 6 GPIO_ACTIVE_LOW>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - /* gpio flags need validation */ - gpios = <&gpiod 8 GPIO_ACTIVE_LOW>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; -}; - -/* Connected to the WSTK VCOM */ -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -/* i2c unit 0 is not used on the board, but must be defined for i2c unit 1 - * to work properly. - */ -&i2c0 { - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -/* Connected to Si7021 sensor on WSTK */ -&i2c1 { - pinctrl-0 = <&i2c1_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&rtcc0 { - prescaler = <1>; - status = "okay"; -}; - -&gpio { - location-swo = <0>; - status = "okay"; -}; - -&gpioa { - status = "okay"; -}; - -&gpiob { - status = "okay"; -}; - -&gpioc { - status = "okay"; -}; - -&gpiod { - status = "okay"; -}; - -&gpioe { - status = "okay"; -}; - -&gpiof { - status = "okay"; -}; - -ð0 { - /* PHY address = 0 */ - phy-address = <0>; - - /* PHY management pins */ - location-mdio = ; - location-phy_mdc = ; - location-phy_mdio = ; - - /* RMII interface pins */ - location-rmii = ; - location-rmii_refclk = ; - location-rmii_crs_dv = ; - location-rmii_txd0 = ; - location-rmii_txd1 = ; - location-rmii_tx_en = ; - location-rmii_rxd0 = ; - location-rmii_rxd1 = ; - location-rmii_rx_er = ; - - status = "okay"; -}; - -&flash0 { - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Set 12Kb of storage at the end of the 2048Kb of flash */ - storage_partition: partition@1fd000 { - label = "storage"; - reg = <0x001fd000 0x00003000>; - }; - }; -}; - -&wdog0 { - status = "okay"; -}; - -&trng0 { - status = "okay"; -}; - -&cpu0 { - clock-frequency = <72000000>; -}; diff --git a/boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a.yaml b/boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a.yaml deleted file mode 100644 index 9e976e5ccaaba..0000000000000 --- a/boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a.yaml +++ /dev/null @@ -1,21 +0,0 @@ -identifier: efm32gg_slwstk6121a -name: EFM32GG-SLWSTK6121A -type: mcu -arch: arm -ram: 512 -flash: 2048 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - counter - - i2c - - gpio - - netif:eth - - nvs - - uart -testing: - ignore_tags: - - bluetooth -vendor: silabs diff --git a/boards/silabs/efm32gg_stk3701a/Kconfig.defconfig b/boards/silabs/efm32gg_stk3701a/Kconfig.defconfig deleted file mode 100644 index c56b944202f29..0000000000000 --- a/boards/silabs/efm32gg_stk3701a/Kconfig.defconfig +++ /dev/null @@ -1,28 +0,0 @@ -# EFM32GG STK3701A default board configuration -# Copyright (c) 2019 Interay Solutions B.V. -# Copyright (c) 2019 Oane Kingma -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFM32GG_STK3701A - -config CMU_HFXO_FREQ - default 50000000 - -config CMU_HFRCO_FREQ - default 72000000 - -config CMU_LFXO_FREQ - default 32768 - -config LOG_BACKEND_SWO_FREQ_HZ - default 875000 - depends on LOG_BACKEND_SWO - -if NETWORKING - -config NET_L2_ETHERNET - default y - -endif # NETWORKING - -endif # BOARD_EFM32GG_STK3701A diff --git a/boards/silabs/efm32gg_stk3701a/Kconfig.efm32gg_stk3701a b/boards/silabs/efm32gg_stk3701a/Kconfig.efm32gg_stk3701a deleted file mode 100644 index 058ea533a2146..0000000000000 --- a/boards/silabs/efm32gg_stk3701a/Kconfig.efm32gg_stk3701a +++ /dev/null @@ -1,7 +0,0 @@ -# EFM32GG STK3701A board configuration -# Copyright (c) 2019 Interay Solutions B.V. -# Copyright (c) 2019 Oane Kingma -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFM32GG_STK3701A - select SOC_PART_NUMBER_EFM32GG11B820F2048GL192 diff --git a/boards/silabs/efm32gg_stk3701a/board.yml b/boards/silabs/efm32gg_stk3701a/board.yml deleted file mode 100644 index d69afebb60bbe..0000000000000 --- a/boards/silabs/efm32gg_stk3701a/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: efm32gg_stk3701a - vendor: silabs - socs: - - name: efm32gg11b820f2048gl192 diff --git a/boards/silabs/efm32gg_stk3701a/doc/index.rst b/boards/silabs/efm32gg_stk3701a/doc/index.rst deleted file mode 100644 index ddb5a1f38d7cc..0000000000000 --- a/boards/silabs/efm32gg_stk3701a/doc/index.rst +++ /dev/null @@ -1,200 +0,0 @@ -.. _efm32gg_stk3701a: - -EFM32 Giant Gecko GG11 Starter Kit -################################## - -Overview -******** - -The EFM32 Giant Gecko Starter Kit EFM32GG-STK3701A contains an MCU from the -EFM32GG Series 1 family built on an ARM® Cortex®-M4F processor with excellent -low power capabilities. - -.. figure:: efm32gg_stk3701a.jpg - :align: center - :alt: EFM32GG-SLSTK3701A - - EFM32GG-SLSTK3701A (image courtesy of Silicon Labs) - -Hardware -******** - -- Advanced Energy Monitoring provides real-time information about the energy - consumption of an application or prototype design. -- Ultra low power 128x128 pixel color Memory-LCD -- 2 user buttons, 2 LEDs and a touch slider -- Relative humidity, magnetic Hall Effect and inductive-capacitive metal sensor -- USB interface for Host/Device/OTG -- 32 Mb Quad-SPI Flash memory -- SD card slot -- RJ-45 Ethernet jack -- 2 digital microphones -- On-board Segger J-Link USB debugger - -For more information about the EFM32GG11 SoC and EFM32GG-STK3701A board: - -- `EFM32GG Series 1 Website`_ -- `EFM32GG11 Datasheet`_ -- `EFM32GG11 Reference Manual`_ -- `EFM32GG-STK3701A Website`_ -- `EFM32GG-STK3701A User Guide`_ -- `EFM32GG-STK3701A Schematics`_ - -Supported Features -================== - -The efm32gg_stk3701a board configuration supports the following hardware -features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | rtcc | -+-----------+------------+-------------------------------------+ -| ETHERNET | on-chip | ethernet | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| I2C | on-chip | i2c port-polling | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a_defconfig` - -Other hardware features are currently not supported by the port. - -Connections and IOs -=================== - -The EFM32GG11 SoC has nine GPIO controllers (PORTA to PORTI), all of which are -currently enabled for the EFM32GG-STK3701A board. - -In the following table, the column **Name** contains pin names. For example, PE1 -means pin number 1 on PORTE, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PH10 | GPIO | LED0 red | -+-------+-------------+-------------------------------------+ -| PH11 | GPIO | LED0 green | -+-------+-------------+-------------------------------------+ -| PH12 | GPIO | LED0 blue | -+-------+-------------+-------------------------------------+ -| PH13 | GPIO | LED1 red | -+-------+-------------+-------------------------------------+ -| PH14 | GPIO | LED1 green | -+-------+-------------+-------------------------------------+ -| PH15 | GPIO | LED1 blue | -+-------+-------------+-------------------------------------+ -| PC8 | GPIO | Push Button PB0 | -+-------+-------------+-------------------------------------+ -| PC9 | GPIO | Push Button PB1 | -+-------+-------------+-------------------------------------+ -| PE1 | GPIO | Board Controller Enable | -| | | EFM_BC_EN | -+-------+-------------+-------------------------------------+ -| PH4 | UART_TX | UART TX Console VCOM_TX US0_TX #4 | -+-------+-------------+-------------------------------------+ -| PH5 | UART_RX | UART RX Console VCOM_RX US0_RX #4 | -+-------+-------------+-------------------------------------+ -| PI4 | I2C_SDA | SENSOR_I2C_SDA I2C2_SDA #7 | -+-------+-------------+-------------------------------------+ -| PI5 | I2C_SCL | SENSOR_I2C_SCL I2C2_SCL #7 | -+-------+-------------+-------------------------------------+ - - -System Clock -============ - -The EFM32GG11 SoC is configured to use the 50 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFM32GG11 SoC has six USARTs, two UARTs and two Low Energy UARTs (LEUART). -USART4 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The EFM32GG-STK3701A includes an `J-Link`_ serial and debug adaptor built into the -board. The adaptor provides: - -- A USB connection to the host computer, which exposes a mass storage device and a - USB serial port. -- A serial flash device, which implements the USB flash disk file storage. -- A physical UART connection which is relayed over interface USB serial port. - -Flashing an application to EFM32GG-STK3701A -------------------------------------------- - -The sample application :ref:`hello_world` is used for this example. -Build the Zephyr kernel and application: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efm32gg_stk3701a - :goals: build - -Connect the EFM32GG-STK3701A to your host computer using the USB port and you -should see a USB connection which exposes a mass storage device(STK3701A) and -a USB Serial Port. Copy the generated zephyr.bin to the STK3701A drive. - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you'll see the following message on the corresponding serial port -terminal session: - -.. code-block:: console - - Hello World! efm32gg_stk3701a - - -.. _EFM32GG-STK3701A Website: - https://www.silabs.com/products/development-tools/mcu/32-bit/efm32-giant-gecko-gg11-starter-kit - -.. _EFM32GG-STK3701A User Guide: - https://www.silabs.com/documents/public/user-guides/ug287-stk3701.pdf - -.. _EFM32GG-STK3701A Schematics: - https://www.silabs.com/documents/public/schematic-files/BRD2204A-B00-schematic.pdf - -.. _EFM32GG Series 1 Website: - https://www.silabs.com/products/mcu/32-bit/efm32-giant-gecko-s1 - -.. _EFM32GG11 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efm32gg11-datasheet.pdf - -.. _EFM32GG11 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efm32gg11-rm.pdf - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a.dts b/boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a.dts deleted file mode 100644 index 39589b6185506..0000000000000 --- a/boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a.dts +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2019 Interay Solutions B.V. - * Copyright (c) 2019 Oane Kingma - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "efm32gg_stk3701a-pinctrl.dtsi" - -/ { - model = "Silicon Labs EFM32GG STK3701A board"; - compatible = "silabs,efm32gg_stk3701a", "silabs,efm32gg11b"; - - chosen { - zephyr,console = &usart4; - zephyr,shell-uart = &usart4; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - }; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - sw0 = &button0; - sw1 = &button1; - watchdog0 = &wdog0; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpioh 10 0>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpioh 13 0>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - /* gpio flags need validation */ - gpios = <&gpioc 8 GPIO_ACTIVE_LOW>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - /* gpio flags need validation */ - gpios = <&gpioc 9 GPIO_ACTIVE_LOW>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&usart4 { - current-speed = <115200>; - pinctrl-0 = <&usart4_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&leuart0 { - current-speed = <9600>; - location-rx = ; - location-tx = ; - status = "okay"; -}; - -&i2c0 { - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&i2c1 { - pinctrl-0 = <&i2c1_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&rtcc0 { - prescaler = <1>; - status = "okay"; -}; - -&gpio { - location-swo = <0>; - status = "okay"; -}; - -&gpioa { - status = "okay"; -}; - -&gpiob { - status = "okay"; -}; - -&gpioc { - status = "okay"; -}; - -&gpiod { - status = "okay"; -}; - -&gpioe { - status = "okay"; - - board-controller-enable { - gpio-hog; - gpios = <1 GPIO_ACTIVE_HIGH>; - output-high; - }; -}; - -&gpiof { - status = "okay"; -}; - -&gpiog { - status = "okay"; -}; - -&gpioh { - status = "okay"; -}; - -&gpioi { - status = "okay"; -}; - -ð0 { - /* PHY address = 0 */ - phy-address = <0>; - - /* PHY management pins */ - location-mdio = ; - location-phy_mdc = ; - location-phy_mdio = ; - - /* RMII interface pins */ - location-rmii = ; - location-rmii_refclk = ; - location-rmii_crs_dv = ; - location-rmii_txd0 = ; - location-rmii_txd1 = ; - location-rmii_tx_en = ; - location-rmii_rxd0 = ; - location-rmii_rxd1 = ; - location-rmii_rx_er = ; - - status = "okay"; -}; - -&flash0 { - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Set 12Kb of storage at the end of the 2048Kb of flash */ - storage_partition: partition@1fd000 { - label = "storage"; - reg = <0x001fd000 0x00003000>; - }; - }; -}; - -&wdog0 { - status = "okay"; -}; - -&trng0 { - status = "okay"; -}; - -&cpu0 { - clock-frequency = <72000000>; -}; diff --git a/boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a.yaml b/boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a.yaml deleted file mode 100644 index 426328eae9711..0000000000000 --- a/boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a.yaml +++ /dev/null @@ -1,19 +0,0 @@ -identifier: efm32gg_stk3701a -name: EFM32GG-STK3701A -type: mcu -arch: arm -ram: 512 -flash: 2048 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - i2c - - gpio - - netif:eth - - nvs -testing: - ignore_tags: - - bluetooth -vendor: silabs diff --git a/boards/silabs/efm32hg_slstk3400a/Kconfig.defconfig b/boards/silabs/efm32hg_slstk3400a/Kconfig.defconfig deleted file mode 100644 index c15834e72295a..0000000000000 --- a/boards/silabs/efm32hg_slstk3400a/Kconfig.defconfig +++ /dev/null @@ -1,14 +0,0 @@ -# EFM32HG SLSTK3400A board - -# Copyright (c) 2018, Marcio Montenegro -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFM32HG_SLSTK3400A - -config CMU_HFXO_FREQ - default 24000000 - -config CMU_LFXO_FREQ - default 32768 - -endif # BOARD_EFM32HG_SLSTK3400A diff --git a/boards/silabs/efm32hg_slstk3400a/Kconfig.efm32hg_slstk3400a b/boards/silabs/efm32hg_slstk3400a/Kconfig.efm32hg_slstk3400a deleted file mode 100644 index 3ab1289920f45..0000000000000 --- a/boards/silabs/efm32hg_slstk3400a/Kconfig.efm32hg_slstk3400a +++ /dev/null @@ -1,7 +0,0 @@ -# EFM32HG SLSTK3400A board - -# Copyright (c) 2018, Marcio Montenegro -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFM32HG_SLSTK3400A - select SOC_PART_NUMBER_EFM32HG322F64 diff --git a/boards/silabs/efm32hg_slstk3400a/board.yml b/boards/silabs/efm32hg_slstk3400a/board.yml deleted file mode 100644 index 8aae393fcae68..0000000000000 --- a/boards/silabs/efm32hg_slstk3400a/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: efm32hg_slstk3400a - vendor: silabs - socs: - - name: efm32hg322f64 diff --git a/boards/silabs/efm32hg_slstk3400a/doc/index.rst b/boards/silabs/efm32hg_slstk3400a/doc/index.rst deleted file mode 100644 index a1e0b84f16d9c..0000000000000 --- a/boards/silabs/efm32hg_slstk3400a/doc/index.rst +++ /dev/null @@ -1,176 +0,0 @@ -.. _efm32hg_slstk3400a: - -EFM32HG-SLSTK3400A -################## - -Overview -******** - -The EFM32 Happy Gecko Starter Kit EFM32HG-SLSTK3400A contains a MCU from the -EFM32HG family built on ARM® Cortex®-M0+ processor with excellent low -power capabilities. - -.. figure:: efm32hg_slstk3400a.jpg - :align: center - :alt: EFM32HG-SLSTK3400A - - EFM32HG-SLSTK3400A (image courtesy of Silicon Labs) - -Hardware -******** - -- Advanced Energy Monitoring system for precise current tracking -- Real-time energy and power profiling -- ARM Cortex M0+ with 64 kB Flash and 8 kB RAM -- 128 X 128 pixel Memory LCD -- 2 user buttons, 2 user LEDs and 2 touch buttons -- 20 pin expansion header -- Silicon Labs Si7021 Relative Humidity/Temperature sensor -- USB device interface -- Integrated SEGGER J-Link USB debugger/emulator with debug out functionality - - -See these documents for more information - -- `EFM32HG Website`_ -- `EFM32HG Datasheet`_ -- `EFM32HG Reference Manual`_ -- `EFM32HG-SLSTK3400A Website`_ -- `EFM32HG-SLSTK3400A User Guide`_ -- `EFM32HG-SLSTK3400A Schematics`_ - -Supported Features -================== - -The efm32hg_slstk3400 board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| USART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efm32hg_slstk3400a/efm32hg_slstk3400a_defconfig` - -Other hardware features are currently not supported by the port. - -Connections and IOs -=================== - -The EFM32HG SoC has six GPIO controllers (PORTA to PORTF), but only three are -currently enabled (PORTB, PORTE and PORTF) for the EFM32HG-SLSTK3400A board. - -In the following table, the column Name contains Pin names. For example, PF4 -means Pin number 4 on PORTF, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PF4 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PF5 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PC9 | GPIO | Push Button PB0 | -+-------+-------------+-------------------------------------+ -| PC10 | GPIO | Push Button PB1 | -+-------+-------------+-------------------------------------+ -| PF7 | GPIO | Board Controller Enable | -| | | EFM_BC_EN | -+-------+-------------+-------------------------------------+ -| PF2 | USART0_TX | USART Console EFM_BC_TX U0_TX #4 | -+-------+-------------+-------------------------------------+ -| PA9 | USART0_RX | USART Console EFM_BC_RX U0_RX #4 | -+-------+-------------+-------------------------------------+ - -System Clock -============ - -The EFM32HG SoC is configured to use the 24 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFM32HG SoC has two USARTs, two UARTs and two Low Energy UARTs (LEUART). -USART1 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The EFM32HG-SLSTK3400 includes an `J-Link`_ serial and debug adaptor built into the -board. The adaptor provides: - -- A USB connection to the host computer, which exposes a Mass Storage and a - USB Serial Port. -- A Serial Flash device, which implements the USB flash disk file storage. -- A physical UART connection which is relayed over interface USB Serial port. - -Flashing an application to EFM32-SLSTK3400A -------------------------------------------- - -The sample application :ref:`hello_world` is used for this example. -Build the Zephyr kernel and application: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efm32hg_slstk3400a - :goals: build - -Connect the EFM32HG-SLSTK3400A to your host computer using the USB port and -you should see a USB connection that exposes a mass storage device (STK3400) -and a USB Serial Port. Copy the generated ``zephyr.bin`` in the STK3400 drive. - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you will see this message written to the serial port: - -.. code-block:: console - - Hello World! arm - - -.. _EFM32HG-SLSTK3400A Website: - https://www.silabs.com/products/development-tools/mcu/32-bit/efm32-happy-gecko-starter-kit - -.. _EFM32HG-SLSTK3400A User Guide: - https://www.silabs.com/documents/public/user-guides/ug255-stk3400-user-guide.pdf - -.. _EFM32HG-SLSTK3400A Schematics: - https://www.silabs.com/documents/public/schematic-files/BRD2012A-B01-schematic.pdf - -.. _EFM32HG Website: - https://www.silabs.com/products/mcu/32-bit/efm32-happy-gecko - -.. _EFM32HG Datasheet: - https://www.silabs.com/documents/public/data-sheets/EFM32HG322.pdf - -.. _EFM32HG Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/EFM32HG-RM.pdf - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32hg_slstk3400a/efm32hg_slstk3400a.dts b/boards/silabs/efm32hg_slstk3400a/efm32hg_slstk3400a.dts deleted file mode 100644 index 01c1f4d7766ab..0000000000000 --- a/boards/silabs/efm32hg_slstk3400a/efm32hg_slstk3400a.dts +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2017 Christian Taedcke - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include - -/ { - model = "Silicon Labs EFM32HG SLSTK3400A board"; - compatible = "silabs,efm32hg_slstk3400a", "silabs,efm32hg"; - - chosen { - zephyr,console = &usart1; - zephyr,shell-uart = &usart1; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - }; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - sw0 = &button0; - sw1 = &button1; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpiof 4 0>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpiof 5 0>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - /* gpio flags need validation */ - gpios = <&gpioc 9 GPIO_ACTIVE_LOW>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - /* gpio flags need validation */ - gpios = <&gpioc 10 GPIO_ACTIVE_LOW>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; - -}; - -&cpu0 { - clock-frequency = <24000000>; -}; - -&gpioa { - status = "okay"; - - board-controller-enable { - gpio-hog; - gpios = <9 GPIO_ACTIVE_HIGH>; - output-high; - }; -}; - -&gpioc { - status = "okay"; -}; - -&gpiof { - status = "okay"; -}; - -&usart1 { - current-speed = <115200>; - location-rx = ; - location-tx = ; - status = "okay"; -}; - -&flash0 { - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Set 4Kb of storage at the end of the 64Kb of flash */ - storage_partition: partition@f000 { - label = "storage"; - reg = <0x0000f000 0x00001000>; - }; - - }; -}; diff --git a/boards/silabs/efm32hg_slstk3400a/efm32hg_slstk3400a.yaml b/boards/silabs/efm32hg_slstk3400a/efm32hg_slstk3400a.yaml deleted file mode 100644 index d14ffbbd10ad1..0000000000000 --- a/boards/silabs/efm32hg_slstk3400a/efm32hg_slstk3400a.yaml +++ /dev/null @@ -1,18 +0,0 @@ -identifier: efm32hg_slstk3400a -name: EFM32HG-SLSTK3400A -type: mcu -arch: arm -ram: 8 -flash: 64 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - gpio - - nvs -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efm32pg_stk3401a/Kconfig.defconfig b/boards/silabs/efm32pg_stk3401a/Kconfig.defconfig deleted file mode 100644 index 9853bf434cca9..0000000000000 --- a/boards/silabs/efm32pg_stk3401a/Kconfig.defconfig +++ /dev/null @@ -1,14 +0,0 @@ -# EFM32PG STK3401A board - -# Copyright (c) 2020, Rafael Dias Menezes -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFM32PG_STK3401A - -config CMU_HFXO_FREQ - default 40000000 - -config CMU_LFXO_FREQ - default 32768 - -endif # BOARD_EFM32PG_STK3401A diff --git a/boards/silabs/efm32pg_stk3401a/Kconfig.efm32pg_stk3401a b/boards/silabs/efm32pg_stk3401a/Kconfig.efm32pg_stk3401a deleted file mode 100644 index 42de02a430aba..0000000000000 --- a/boards/silabs/efm32pg_stk3401a/Kconfig.efm32pg_stk3401a +++ /dev/null @@ -1,7 +0,0 @@ -# EFM32PG STK3401A board - -# Copyright (c) 2020, Rafael Dias Menezes -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFM32PG_STK3401A - select SOC_PART_NUMBER_EFM32PG1B200F256GM48 diff --git a/boards/silabs/efm32pg_stk3401a/board.yml b/boards/silabs/efm32pg_stk3401a/board.yml deleted file mode 100644 index 636c7e8c5621e..0000000000000 --- a/boards/silabs/efm32pg_stk3401a/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: efm32pg_stk3401a - vendor: silabs - socs: - - name: efm32pg1b200f256gm48 diff --git a/boards/silabs/efm32pg_stk3401a/doc/index.rst b/boards/silabs/efm32pg_stk3401a/doc/index.rst deleted file mode 100644 index a38930275a265..0000000000000 --- a/boards/silabs/efm32pg_stk3401a/doc/index.rst +++ /dev/null @@ -1,188 +0,0 @@ -.. _efm32pg_stk3401a: - -EFM32 Pearl Gecko Starter Kit -############################# - -Overview -******** - -The EFM32 Pearl Gecko Starter Kit EFM32PG-STK3401A contains an MCU from the -EFM32PG family built on an ARM® Cortex®-M4F processor with excellent low -power capabilities. - -.. figure:: efm32pg_stk3401a.jpg - :align: center - :alt: EFM32PG-SLSTK3401A - - EFM32PG-SLSTK3401A (image courtesy of Silicon Labs) - -Hardware -******** - -- Advanced Energy Monitoring provides real-time information about the energy - consumption of an application or prototype design. -- Ultra low power 128x128 pixel Memory-LCD -- 2 user buttons, 2 LEDs and 2 capacitive buttons -- Humidity and temperature sensor -- On-board Segger J-Link USB debugger - -For more information about the EFM32PG SoC and EFM32PG-STK3401A board: - -- `EFM32PG Website`_ -- `EFM32PG1 Datasheet`_ -- `EFM32PG1 Reference Manual`_ -- `EFM32PG-STK3401A Website`_ -- `EFM32PG-STK3401A User Guide`_ - -Supported Features -================== - -The efm32pg_stk3401a board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | rtcc | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ -| I2C | on-chip | i2c port-polling | -+-----------+------------+-------------------------------------+ -| WATCHDOG | on-chip | watchdog | -+-----------+------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a_defconfig` - -Other hardware features are currently not supported by the port. - -Connections and IOs -=================== - -The EFM32PG1 SoC has five GPIO controllers (PORTA to PORTD and PORTF) and -all are enabled for the EFM32PG-STK3401A board. - -In the following table, the column **Name** contains pin names. For example, PF4 -means pin number 4 on PORTF, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PF4 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PF5 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PF6 | GPIO | Push Button PB0 | -+-------+-------------+-------------------------------------+ -| PF7 | GPIO | Push Button PB1 | -+-------+-------------+-------------------------------------+ -| PA5 | GPIO | Board Controller Enable | -| | | EFM_BC_EN | -+-------+-------------+-------------------------------------+ -| PA0 | UART_TX | UART TX Console VCOM_TX US0_TX #0 | -+-------+-------------+-------------------------------------+ -| PA1 | UART_RX | UART RX Console VCOM_RX US0_RX #0 | -+-------+-------------+-------------------------------------+ -| PD10 | UART_TX | EXP12_UART_TX LEU0_TX #18 | -+-------+-------------+-------------------------------------+ -| PD11 | UART_RX | EXP14_UART_RX LEU0_RX #18 | -+-------+-------------+-------------------------------------+ -| PC10 | I2C_SDA | ENV_I2C_SDA I2C0_SDA #15 | -+-------+-------------+-------------------------------------+ -| PC11 | I2C_SCL | ENV_I2C_SCL I2C0_SCL #15 | -+-------+-------------+-------------------------------------+ - - -System Clock -============ - -The EFM32PG SoC is configured to use the 40 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFM32PG SoC has two USARTs and one Low Energy UART (LEUART). - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The EFM32PG-STK3401A includes an `J-Link`_ serial and debug adaptor built into the -board. The adaptor provides: - -- A USB connection to the host computer, which exposes a mass storage device and a - USB serial port. -- A serial flash device, which implements the USB flash disk file storage. -- A physical UART connection which is relayed over interface USB serial port. - -Flashing an application to EFM32PG-STK3401A -------------------------------------------- - -The sample application :ref:`hello_world` is used for this example. -Build the Zephyr kernel and application: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efm32pg_stk3401a - :goals: build - -Connect the EFM32PG-STK3401A to your host computer using the USB port and you -should see a USB connection which exposes a mass storage device(STK3401A). -Copy the generated zephyr.bin to the STK3401A drive. - -Use a USB-to-UART converter such as an FT232/CP2102 to connect to the UART on the -expansion header. - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you'll see the following message on the corresponding serial port -terminal session: - -.. code-block:: console - - Hello World! arm - - -.. _EFM32PG-STK3401A Website: - https://www.silabs.com/development-tools/mcu/32-bit/efm32pg1-starter-kit - -.. _EFM32PG-STK3401A User Guide: - https://www.silabs.com/documents/public/user-guides/ug154-stk3401-user-guide.pdf - -.. _EFM32PG Website: - https://www.silabs.com/products/mcu/32-bit/efm32-pearl-gecko - -.. _EFM32PG1 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efm32pg1-datasheet.pdf - -.. _EFM32PG1 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efm32pg1-rm.pdf - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a.dts b/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a.dts deleted file mode 100644 index 1a7f9eddec4ea..0000000000000 --- a/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a.dts +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2020 Rafael Dias Menezes - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include "efm32pg_stk3401a_common.dtsi" - -/ { - model = "Silicon Labs EFM32PG STK3401A board"; - compatible = "silabs,efm32pg_stk3401a", "silabs,efm32pg1b"; -}; diff --git a/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a.yaml b/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a.yaml deleted file mode 100644 index ee707a08caaf5..0000000000000 --- a/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a.yaml +++ /dev/null @@ -1,20 +0,0 @@ -identifier: efm32pg_stk3401a -name: EFM32PG-STK3401A -type: mcu -arch: arm -ram: 32 -flash: 256 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - i2c - - gpio - - nvs - - watchdog -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi b/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi deleted file mode 100644 index 97427b8581729..0000000000000 --- a/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a_common.dtsi +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2020 Rafael Dias Menezes - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "efm32pg_stk3401a-pinctrl.dtsi" - -/ { - model = "Silicon Labs EFM32PG STK3401A board"; - - chosen { - zephyr,console = &usart0; - zephyr,shell-uart = &usart0; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - }; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - sw0 = &button0; - sw1 = &button1; - watchdog0 = &wdog0; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpiof 4 0>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpiof 5 0>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - /* gpio flags need validation */ - gpios = <&gpiof 6 GPIO_ACTIVE_LOW>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - /* gpio flags need validation */ - gpios = <&gpiof 7 GPIO_ACTIVE_LOW>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; -}; - -&cpu0 { - clock-frequency = <40000000>; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&leuart0 { - current-speed = <9600>; - location-rx = ; - location-tx = ; - status = "okay"; -}; - -&i2c0 { - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&rtcc0 { - prescaler = <1>; - status = "okay"; -}; - -&gpio { - location-swo = <0>; - status = "okay"; -}; - -&gpioa { - status = "okay"; - - board-controller-enable { - gpio-hog; - gpios = <5 GPIO_ACTIVE_HIGH>; - output-high; - }; -}; - -&gpiob { - status = "okay"; -}; - -&gpioc { - status = "okay"; -}; - -&gpiod { - status = "okay"; -}; - -&gpiof { - status = "okay"; -}; - -&wdog0 { - status = "okay"; -}; - -&flash0 { - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Set 6Kb of storage at the end of the 256Kb of flash */ - storage_partition: partition@fe800 { - label = "storage"; - reg = <0x0003e800 0x00001800>; - }; - - }; -}; diff --git a/boards/silabs/efm32pg_stk3402a/Kconfig.defconfig b/boards/silabs/efm32pg_stk3402a/Kconfig.defconfig deleted file mode 100644 index 3d9a498ecd598..0000000000000 --- a/boards/silabs/efm32pg_stk3402a/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# EFM32PG STK3402A board - -# Copyright (c) 2018, Christian Taedcke -# Copyright (c) 2019 Lemonbeat GmbH -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFM32PG_STK3402A - -config CMU_HFXO_FREQ - default 40000000 - -config CMU_LFXO_FREQ - default 32768 - -endif # BOARD_EFM32PG_STK3402A diff --git a/boards/silabs/efm32pg_stk3402a/Kconfig.efm32pg_stk3402a b/boards/silabs/efm32pg_stk3402a/Kconfig.efm32pg_stk3402a deleted file mode 100644 index 7f4bea414753e..0000000000000 --- a/boards/silabs/efm32pg_stk3402a/Kconfig.efm32pg_stk3402a +++ /dev/null @@ -1,9 +0,0 @@ -# EFM32PG STK3402A board - -# Copyright (c) 2018, Christian Taedcke -# Copyright (c) 2019 Lemonbeat GmbH -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFM32PG_STK3402A - select SOC_PART_NUMBER_EFM32PG12B500F1024GL125 if BOARD_EFM32PG_STK3402A_EFM32PG12B500F1024GL125 - select SOC_PART_NUMBER_EFM32JG12B500F1024GL125 if BOARD_EFM32PG_STK3402A_EFM32JG12B500F1024GL125 diff --git a/boards/silabs/efm32pg_stk3402a/board.yml b/boards/silabs/efm32pg_stk3402a/board.yml deleted file mode 100644 index 068aa663798de..0000000000000 --- a/boards/silabs/efm32pg_stk3402a/board.yml +++ /dev/null @@ -1,6 +0,0 @@ -board: - name: efm32pg_stk3402a - vendor: silabs - socs: - - name: efm32pg12b500f1024gl125 - - name: efm32jg12b500f1024gl125 diff --git a/boards/silabs/efm32pg_stk3402a/doc/index.rst b/boards/silabs/efm32pg_stk3402a/doc/index.rst deleted file mode 100644 index 8014f310b0c2a..0000000000000 --- a/boards/silabs/efm32pg_stk3402a/doc/index.rst +++ /dev/null @@ -1,212 +0,0 @@ -.. _efm32pg_stk3402a: - -EFM32 Pearl Gecko Starter Kit -############################# - -Overview -******** - -The EFM32 Pearl Gecko Starter Kit EFM32PG-STK3402A contains an MCU from the -EFM32PG family built on an ARM® Cortex®-M4F processor with excellent low -power capabilities. - -.. figure:: efm32pg_stk3402a.jpg - :align: center - :alt: EFM32PG-SLSTK3402A - - EFM32PG-SLSTK3402A (image courtesy of Silicon Labs) - -Hardware -******** - -- Advanced Energy Monitoring provides real-time information about the energy - consumption of an application or prototype design. -- Ultra low power 128x128 pixel Memory-LCD -- 2 user buttons, 2 LEDs and a touch slider -- Humidity, temperature, and inductive-capacitive metal sensor -- On-board Segger J-Link USB debugger - -For more information about the EFM32PG SoC and EFM32PG-STK3402A board: - -- `EFM32PG Website`_ -- `EFM32PG12 Datasheet`_ -- `EFM32PG12 Reference Manual`_ -- `EFM32PG-STK3402A Website`_ -- `EFM32PG-STK3402A User Guide`_ -- `EFM32PG-STK3402A Schematics`_ - -Supported Features -================== - -The efm32pg_stk3402a board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | rtcc | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ -| I2C | on-chip | i2c port-polling | -+-----------+------------+-------------------------------------+ -| WATCHDOG | on-chip | watchdog | -+-----------+------------+-------------------------------------+ -| TRNG | on-chip | true random number generator | -+-----------+------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32pg12b500f1024gl125_defconfig` - -The default configuration when building for this EFM32JG12B SoC can be found in -:zephyr_file:`boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32jg12b500f1024gl125_defconfig` - -Other hardware features are currently not supported by the port. - -EFM32 Jade Gecko SoC --------------------- - -The EFM32 Pearl Gecko Starter Kit EFM32PG-STK3402A can also be used to evaluate -the EFM32 Jade Gecko SoC (EFM32JG12B). The only difference between the Pearl -Gecko and the Jade Gecko is their core. The Pearl Gecko contains an ARM® -Cortex®-M4F core, and the Jade Gecko an ARM® Cortex®-M3 core. Other features -such as memory and peripherals are the same. - -Code that is built for the Jade Gecko also runs on an equivalent Pearl Gecko. - -To build firmware for the Jade Gecko and run it on the EFM32 Pearl Gecko Starter -Kit, use the board ``efm32pg_stk3402a/efm32pg12b500f1024gl125`` instead of ``efm32pg_stk3402a/efm32jg12b500f1024gl125``. - -Connections and IOs -=================== - -The EFM32PG12 SoC has twelve GPIO controllers (PORTA to PORTL), but only four -are currently enabled (PORTA, PORTB, PORTD and PORTF) for the EFM32PG-STK3402A -board. - -In the following table, the column **Name** contains pin names. For example, PE2 -means pin number 2 on PORTE, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PF4 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PF5 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PF6 | GPIO | Push Button PB0 | -+-------+-------------+-------------------------------------+ -| PF7 | GPIO | Push Button PB1 | -+-------+-------------+-------------------------------------+ -| PA5 | GPIO | Board Controller Enable | -| | | EFM_BC_EN | -+-------+-------------+-------------------------------------+ -| PA0 | UART_TX | UART TX Console VCOM_TX US0_TX #0 | -+-------+-------------+-------------------------------------+ -| PA1 | UART_RX | UART RX Console VCOM_RX US0_RX #0 | -+-------+-------------+-------------------------------------+ -| PD10 | UART_TX | EXP12_UART_TX LEU0_TX #18 | -+-------+-------------+-------------------------------------+ -| PD11 | UART_RX | EXP14_UART_RX LEU0_RX #18 | -+-------+-------------+-------------------------------------+ -| PC10 | I2C_SDA | ENV_I2C_SDA I2C0_SDA #15 | -+-------+-------------+-------------------------------------+ -| PC11 | I2C_SCL | ENV_I2C_SCL I2C0_SCL #15 | -+-------+-------------+-------------------------------------+ - - -System Clock -============ - -The EFM32PG SoC is configured to use the 40 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFM32PG SoC has four USARTs and one Low Energy UART (LEUART). - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The EFM32PG-STK3402A includes an `J-Link`_ serial and debug adaptor built into the -board. The adaptor provides: - -- A USB connection to the host computer, which exposes a mass storage device and a - USB serial port. -- A serial flash device, which implements the USB flash disk file storage. -- A physical UART connection which is relayed over interface USB serial port. - -Flashing an application to EFM32PG-STK3402A -------------------------------------------- - -The sample application :ref:`hello_world` is used for this example. -Build the Zephyr kernel and application: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efm32pg_stk3402a/efm32pg12b500f1024gl125 - :goals: build - -Connect the EFM32PG-STK3402A to your host computer using the USB port and you -should see a USB connection which exposes a mass storage device(STK3402A). -Copy the generated zephyr.bin to the STK3402A drive. - -Use a USB-to-UART converter such as an FT232/CP2102 to connect to the UART on the -expansion header. - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you'll see the following message on the corresponding serial port -terminal session: - -.. code-block:: console - - Hello World! arm - - -.. _EFM32PG-STK3402A Website: - https://www.silabs.com/products/development-tools/mcu/32-bit/efm32-pearl-gecko-pg12-starter-kit - -.. _EFM32PG-STK3402A User Guide: - https://www.silabs.com/documents/public/user-guides/ug257-stk3402-usersguide.pdf - -.. _EFM32PG-STK3402A Schematics: - https://www.silabs.com/documents/public/schematic-files/BRD2501A-A01-schematic.pdf - -.. _EFM32PG Website: - https://www.silabs.com/products/mcu/32-bit/efm32-pearl-gecko - -.. _EFM32PG12 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efm32pg12-datasheet.pdf - -.. _EFM32PG12 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efm32pg12-rm.pdf - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_common.dtsi b/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_common.dtsi deleted file mode 100644 index 05729334fcdd3..0000000000000 --- a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_common.dtsi +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (c) 2017 Christian Taedcke - * Copyright (c) 2019 Lemonbeat GmbH - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "efm32pg_stk3402a-pinctrl.dtsi" -#include - -/ { - model = "Silicon Labs EFM32PG STK3402A board"; - - chosen { - zephyr,console = &usart0; - zephyr,shell-uart = &usart0; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - }; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - pwm-led0 = &pwm_led0; - sw0 = &button0; - sw1 = &button1; - watchdog0 = &wdog0; - watchdog1 = &wdog1; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpiof 4 0>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpiof 5 0>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - /* gpio flags need validation */ - gpios = <&gpiof 6 GPIO_ACTIVE_LOW>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - /* gpio flags need validation */ - gpios = <&gpiof 7 GPIO_ACTIVE_LOW>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; - - pwmleds { - compatible = "pwm-leds"; - status = "okay"; - pwm_led0: pwm_led0 { - pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; - }; - }; -}; - -&cpu0 { - clock-frequency = <40000000>; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&leuart0 { - current-speed = <9600>; - location-rx = ; - location-tx = ; - status = "okay"; -}; - -&i2c0 { - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&rtcc0 { - prescaler = <1>; - status = "okay"; -}; - -&timer0 { - status = "okay"; - - pwm0: pwm { - status = "okay"; - pin-location = ; - prescaler = <1024>; - }; -}; - -&gpio { - location-swo = <0>; - status = "okay"; -}; - -&gpioa { - status = "okay"; - - board-controller-enable { - gpio-hog; - gpios = <5 GPIO_ACTIVE_HIGH>; - output-high; - }; -}; - -&gpiob { - status = "okay"; -}; - -&gpiod { - status = "okay"; -}; - -&gpiof { - status = "okay"; -}; - -&wdog0 { - status = "okay"; -}; - -&wdog1 { - status = "okay"; -}; - - -&flash0 { - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Set 6Kb of storage at the end of the 1024Kb of flash */ - storage_partition: partition@fe800 { - label = "storage"; - reg = <0x000fe800 0x00001800>; - }; - - }; -}; - -&trng0 { - status = "okay"; -}; - -&adc0 { - status = "okay"; -}; diff --git a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32jg12b500f1024gl125.dts b/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32jg12b500f1024gl125.dts deleted file mode 100644 index 090b217e49a67..0000000000000 --- a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32jg12b500f1024gl125.dts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2019 Lemonbeat GmbH - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include "efm32pg_stk3402a_common.dtsi" - -/ { - model = "Silicon Labs EFM32PG STK3402A board (JG)"; - compatible = "silabs,efm32pg_stk3402a_jg", "silabs,efm32jg12b"; - -}; diff --git a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32jg12b500f1024gl125.yaml b/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32jg12b500f1024gl125.yaml deleted file mode 100644 index 7373e65edb28d..0000000000000 --- a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32jg12b500f1024gl125.yaml +++ /dev/null @@ -1,19 +0,0 @@ -identifier: efm32pg_stk3402a/efm32jg12b500f1024gl125 -name: EFM32PG-STK3402A-JG -type: mcu -arch: arm -ram: 256 -flash: 1024 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - i2c - - gpio - - nvs -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32pg12b500f1024gl125.dts b/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32pg12b500f1024gl125.dts deleted file mode 100644 index a4e98955ae337..0000000000000 --- a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32pg12b500f1024gl125.dts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2017 Christian Taedcke - * Copyright (c) 2019 Lemonbeat GmbH - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include "efm32pg_stk3402a_common.dtsi" - -/ { - model = "Silicon Labs EFM32PG STK3402A board"; - compatible = "silabs,efm32pg_stk3402a", "silabs,efm32pg12b"; -}; diff --git a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32pg12b500f1024gl125.yaml b/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32pg12b500f1024gl125.yaml deleted file mode 100644 index 153ebae67ef91..0000000000000 --- a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32pg12b500f1024gl125.yaml +++ /dev/null @@ -1,20 +0,0 @@ -identifier: efm32pg_stk3402a/efm32pg12b500f1024gl125 -name: EFM32PG-STK3402A -type: mcu -arch: arm -ram: 256 -flash: 1024 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - i2c - - gpio - - nvs - - watchdog -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efm32wg_stk3800/doc/index.rst b/boards/silabs/efm32wg_stk3800/doc/index.rst deleted file mode 100644 index 30810f0d71ec5..0000000000000 --- a/boards/silabs/efm32wg_stk3800/doc/index.rst +++ /dev/null @@ -1,177 +0,0 @@ -.. _efm32wg_stk3800: - -EFM32WG-STK3800 -############### - -Overview -******** - -The EFM32 Wonder Gecko Starter Kit EFM32WG-STK3800 contains a MCU from the -EFM32WG family built on ARM® Cortex®-M4F processor with excellent low -power capabilities. - -.. figure:: efm32wg_stk3800.jpg - :align: center - :alt: EFM32WG-STK3800 - - EFM32WG-STK3800 (image courtesy of Silicon Labs) - - -Hardware -******** - -- Advanced Energy Monitoring provides real-time information about the energy - consumption of an application or prototype design. -- 32MByte parallel NAND Flash -- 160 segment Energy Micro LCD -- 2 user buttons, 2 LEDs and a touch slider -- Ambient Light Sensor and Inductive-capacitive metal sensor -- On-board Segger J-Link USB debugger - -For more information about the EFM32WG SoC and EFM32WG-STK3800 board: - -- `EFM32WG Website`_ -- `EFM32WG Datasheet`_ -- `EFM32WG Reference Manual`_ -- `EFM32WG-STK3800 Website`_ -- `EFM32WG-STK3800 User Guide`_ -- `EFM32WG-STK3800 Schematics`_ - -Supported Features -================== - -The efm32wg_stk3800 board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efm32wg_stk3800/efm32wg_stk3800_defconfig` - -Other hardware features are currently not supported by the port. - -Connections and IOs -=================== - -The EFM32WG SoC has six gpio controllers (PORTA to PORTF), but only three are -currently enabled (PORTB, PORTE and PORTF) for the EFM32WG-STK3800 board. - -In the following table, the column Name contains Pin names. For example, PE2 -means Pin number 2 on PORTE, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PE2 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PE3 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PB9 | GPIO | Push Button PB0 | -+-------+-------------+-------------------------------------+ -| PB10 | GPIO | Push Button PB1 | -+-------+-------------+-------------------------------------+ -| PF7 | GPIO | Board Controller Enable | -| | | EFM_BC_EN | -+-------+-------------+-------------------------------------+ -| PE0 | UART0_TX | UART Console EFM_BC_TX U0_TX #1 | -+-------+-------------+-------------------------------------+ -| PE1 | UART0_RX | UART Console EFM_BC_RX U0_RX #1 | -+-------+-------------+-------------------------------------+ - -System Clock -============ - -The EFM32WG SoC is configured to use the 48 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFM32WG SoC has three USARTs, two UARTs and two Low Energy UARTs (LEUART). -UART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The EFM32WG-STK3800 includes an `J-Link`_ serial and debug adaptor built into the -board. The adaptor provides: - -- A USB connection to the host computer, which exposes a Mass Storage and a - USB Serial Port. -- A Serial Flash device, which implements the USB flash disk file storage. -- A physical UART connection which is relayed over interface USB Serial port. - -Flashing an application to EFM32-STK3800 ----------------------------------------- - -The sample application :ref:`hello_world` is used for this example. -Build the Zephyr kernel and application: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efm32wg_stk3800 - :goals: build - -Connect the EFM32WG-STK3800 to your host computer using the USB port and you -should see a USB connection which exposes a Mass Storage (STK3800) and a -USB Serial Port. Copy the generated zephyr.bin in the STK3800 drive. - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should be able to see on the corresponding Serial Port -the following message: - -.. code-block:: console - - Hello World! arm - - -.. _EFM32WG-STK3800 Website: - http://www.silabs.com/products/development-tools/mcu/32-bit/efm32-wonder-gecko-starter-kit - -.. _EFM32WG-STK3800 User Guide: - http://www.silabs.com/documents/public/user-guides/efm32wg-stk3800-ug.pdf - -.. _EFM32WG-STK3800 Schematics: - http://www.silabs.com/documents/public/schematic-files/BRD2400A_A00.pdf - -.. _EFM32WG Website: - http://www.silabs.com/products/mcu/32-bit/efm32-wonder-gecko - -.. _EFM32WG Datasheet: - http://www.silabs.com/documents/public/data-sheets/EFM32WG990.pdf - -.. _EFM32WG Reference Manual: - http://www.silabs.com/documents/public/reference-manuals/EFM32WG-RM.pdf - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efr32_radio/Kconfig.defconfig b/boards/silabs/efr32_radio/Kconfig.defconfig deleted file mode 100644 index ce20c2ef360b0..0000000000000 --- a/boards/silabs/efr32_radio/Kconfig.defconfig +++ /dev/null @@ -1,51 +0,0 @@ -# EFR32 radio board - -# Copyright (c) 2020 Piotr Mienkowski -# Copyright (c) 2020 TriaGnoSys GmbH -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFR32_RADIO - -config CMU_HFXO_FREQ - default 39000000 if BOARD_EFR32_RADIO_EFR32MG24B220F1536IM48 - default 38400000 - -config CMU_LFXO_FREQ - default 32768 - -config FLASH_BASE_ADDRESS - hex - default 0x08000000 if BOARD_EFR32_RADIO_EFR32MG24B220F1536IM48 - default 0x0 - -config LOG_BACKEND_SWO_FREQ_HZ - default 875000 - depends on LOG_BACKEND_SWO - -if SOC_GECKO_USE_RAIL - -config FPU - default n if SOC_FAMILY_SILABS_S1 - default y - -endif # SOC_GECKO_USE_RAIL - -if BT - -config FPU - default y - -config MINIMAL_LIBC_MALLOC_ARENA_SIZE - default 8192 - -config MAIN_STACK_SIZE - default 3072 if PM - default 2304 - -choice BT_HCI_BUS_TYPE - default BT_SILABS_HCI -endchoice - -endif # BT - -endif # BOARD_EFR32_RADIO diff --git a/boards/silabs/efr32_radio/Kconfig.efr32_radio b/boards/silabs/efr32_radio/Kconfig.efr32_radio deleted file mode 100644 index 1ebc6a94455fa..0000000000000 --- a/boards/silabs/efr32_radio/Kconfig.efr32_radio +++ /dev/null @@ -1,15 +0,0 @@ -# EFR32BG13 BRD4104A / EFR32MG21 BRD4180A / -# EFR32FG1P BRD4250B / EFR32FG13P BRD4255A board - -# Copyright (c) 2020 Piotr Mienkowski -# Copyright (c) 2020 TriaGnoSys GmbH -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFR32_RADIO - select SOC_PART_NUMBER_EFR32BG13P632F512GM48 if BOARD_EFR32_RADIO_EFR32BG13P632F512GM48 - select SOC_PART_NUMBER_EFR32MG12P433F1024GM68 if BOARD_EFR32_RADIO_EFR32MG12P433F1024GM68 - select SOC_PART_NUMBER_EFR32MG12P432F1024GL125 if BOARD_EFR32_RADIO_EFR32MG12P432F1024GL125 - select SOC_PART_NUMBER_EFR32FG1P133F256GM48 if BOARD_EFR32_RADIO_EFR32FG1P133F256GM48 - select SOC_PART_NUMBER_EFR32MG21A020F1024IM32 if BOARD_EFR32_RADIO_EFR32MG21A020F1024IM32 - select SOC_PART_NUMBER_EFR32MG24B220F1536IM48 if BOARD_EFR32_RADIO_EFR32MG24B220F1536IM48 - select SOC_PART_NUMBER_EFR32FG13P233F512GM48 if BOARD_EFR32_RADIO_EFR32FG13P233F512GM48 diff --git a/boards/silabs/efr32_radio/board.cmake b/boards/silabs/efr32_radio/board.cmake deleted file mode 100644 index 142165be8c794..0000000000000 --- a/boards/silabs/efr32_radio/board.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -board_runner_args(openocd) - -if(CONFIG_BOARD_EFR32_RADIO_EFR32BG13P632F512GM48) - board_runner_args(jlink "--device=EFR32BG13PxxxF512") -elseif(CONFIG_BOARD_EFR32_RADIO_EFR32FG1P133F256GM48) - board_runner_args(jlink "--device=EFR32FG1PxxxF256") -elseif(CONFIG_BOARD_EFR32_RADIO_EFR32MG12P433F1024GM68) - board_runner_args(jlink "--device=EFR32MG12PxxxF1024") -elseif(CONFIG_BOARD_EFR32_RADIO_EFR32MG12P432F1024GL125) - board_runner_args(jlink "--device=EFR32MG12PxxxF1024") -elseif(CONFIG_BOARD_EFR32_RADIO_EFR32MG21A020F1024IM32) - board_runner_args(jlink "--device=EFR32MG21AxxxF1024") -elseif(CONFIG_BOARD_EFR32_RADIO_EFR32MG24B220F1536IM48) - board_runner_args(jlink "--device=EFR32MG24BxxxF1536") -elseif(CONFIG_BOARD_EFR32_RADIO_EFR32FG13P233F512GM48) - board_runner_args(jlink "--device=EFR32FG13PxxxF512") -endif() - -include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) -include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/silabs/efr32_radio/board.yml b/boards/silabs/efr32_radio/board.yml deleted file mode 100644 index 5e68cef3826b4..0000000000000 --- a/boards/silabs/efr32_radio/board.yml +++ /dev/null @@ -1,10 +0,0 @@ -boards: - - name: efr32_radio - socs: - - name: efr32bg13p632f512gm48 - - name: efr32mg12p433f1024gm68 - - name: efr32mg12p432f1024gl125 - - name: efr32fg1p133f256gm48 - - name: efr32mg21a020f1024im32 - - name: efr32mg24b220f1536im48 - - name: efr32fg13p233f512gm48 diff --git a/boards/silabs/efr32_radio/doc/brd4104a.rst b/boards/silabs/efr32_radio/doc/brd4104a.rst deleted file mode 100644 index 7fa1336345c55..0000000000000 --- a/boards/silabs/efr32_radio/doc/brd4104a.rst +++ /dev/null @@ -1,122 +0,0 @@ -.. _efr32_radio_brd4104a: - -EFR32 BRD4104A (SLWRB4104A) -########################### - -Overview -******** - -The EFR32BG13 Blue Gecko Bluetooth® Low Energy Radio Board is one of the two -radio boards delivered with `SLWSTK6020B Bluetooth SoC Starter Kit`_. It -contains a Wireless System-On-Chip from the EFR32BG13 family built on an -ARM Cortex®-M4F processor with excellent low power capabilities. - -.. figure:: efr32bg13-slwrb4104a.jpg - :align: center - :alt: SLWRB4104A Blue Gecko Bluetooth® Low Energy Radio Board - - SLWRB4104A (image courtesy of Silicon Labs) - -The BRD4104A a.k.a. SLWRB4104A radio board plugs into the Wireless Starter Kit -Mainboard BRD4001A and is supported as one of :ref:`efr32_radio`. - -Hardware -******** - -- EFR32BG13P632F512GM48 Blue Gecko SoC -- CPU core: ARM Cortex®-M4 with FPU -- Flash memory: 512 kB -- RAM: 64 kB -- Transmit power: up to +10 dBm -- Operation frequency: 2.4 GHz -- 8Mbit SPI NOR Flash -- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). - -For more information about the EFR32BG13 SoC and BRD4104A board, refer to these -documents: - -- `EFR32BG13 Website`_ -- `EFR32BG13 Datasheet`_ -- `EFR32xG13 Reference Manual`_ -- `SLWSTK6020B Bluetooth SoC Starter Kit`_ -- `BRD4104A User Guide`_ -- `BRD4104A Reference Manual`_ -- `EFR32BG13-BRD4104A Schematics`_ - -Supported Features -================== - -Please refer to -:ref:`EFR32 Radio Board Supported Features ` -for details of the configuration and common features supported by the -``efr32_radio/efr32bg13p632f512gm48`` board. - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48_defconfig` - -System Clock -============ - -The EFR32BG13P SoC is configured to use the 38.4 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFR32BG13P SoC has three USARTs and one Low Energy UARTs (LEUART). -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -Please refer to -:ref:`Programming and Debugging EFR32 Radio Board ` -for details on the supported debug interfaces. - -Flashing -======== - -Connect the BRD4001A board with a mounted BRD4104A radio module to your host -computer using the USB port. - -Here is an example for the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32_radio/efr32bg13p632f512gm48 - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should see the following message in the terminal: - -.. code-block:: console - - Hello World! efr32_radio - - -.. _EFR32BG13 Website: - https://www.silabs.com/wireless/bluetooth/efr32bg13-series-1-socs - -.. _EFR32BG13 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32bg13-datasheet.pdf - -.. _EFR32xG13 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efr32xg13-rm.pdf - -.. _SLWSTK6020B Bluetooth SoC Starter Kit: - https://www.silabs.com/products/development-tools/wireless/bluetooth/blue-gecko-bluetooth-low-energy-soc-starter-kit - -.. _BRD4104A User Guide: - https://www.silabs.com/documents/public/user-guides/ug279-brd4104a-user-guide.pdf - -.. _BRD4104A Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/brd4104a-rm.pdf - -.. _EFR32BG13-BRD4104A Schematics: - https://www.silabs.com/documents/public/schematic-files/BRD4104A-A00-schematic.pdf diff --git a/boards/silabs/efr32_radio/doc/brd4161a.rst b/boards/silabs/efr32_radio/doc/brd4161a.rst deleted file mode 100644 index 992d5f7a4acd3..0000000000000 --- a/boards/silabs/efr32_radio/doc/brd4161a.rst +++ /dev/null @@ -1,108 +0,0 @@ -.. _efr32_radio_brd4161a: - -EFR32 BRD4161A (SLWRB4161A) -########################### - -Overview -******** - -The EFR32MG12 Mighty Gecko Radio Board contains a Wireless System-On-Chip -from the EFR32MG12 family built on an ARM Cortex®-M4F processor with excellent -low power capabilities. - -.. figure:: efr32mg12-slwrb4161a.jpeg - :align: center - :alt: SLWRB4161A Mighty Gecko Radio Board - - SLWRB4161A (image courtesy of Silicon Labs) - -The BRD4161A a.k.a. SLWRB4161A radio board plugs into the Wireless Starter Kit -Mainboard BRD4001A and is supported as one of :ref:`efr32_radio`. - -Hardware -******** - -- EFR32MG12P432F1024GL125 Mighty Gecko SoC -- CPU core: ARM Cortex®-M4 with FPU -- Flash memory: 1024 kB -- RAM: 256 kB -- Transmit power: up to +19 dBm -- Operation frequency: 2.4 GHz and Sub-Ghz -- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). - -For more information about the EFR32MG12 SoC and BRD4170A board, refer to these -documents: - -- `EFR32MG12 Website`_ -- `EFR32MG12 Datasheet`_ -- `EFR32xG12 Reference Manual`_ -- `BRD4161A User Guide`_ - -Supported Features -================== - -Please refer to -:ref:`EFR32 Radio Board Supported Features ` -for details of the configuration and common features supported by the -``efr32_radio/efr32mg12p432f1024gl125`` board. - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125_defconfig` - -System Clock -============ - -The EFR32MG12P SoC is configured to use the 38.4 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFR32MG12P SoC has four USARTs and one Low Energy UARTs (LEUART). -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -Please refer to -:ref:`Programming and Debugging EFR32 Radio Board ` -for details on the supported debug interfaces. - -Flashing -======== - -Connect the BRD4001A board with a mounted BRD4170A radio module to your host -computer using the USB port. - -Here is an example for the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32_radio/efr32mg12p432f1024gl125 - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should see the following message in the terminal: - -.. code-block:: console - - Hello World! efr32_radio - - -.. _EFR32MG12 Website: - https://www.silabs.com/wireless/zigbee/efr32mg12-series-1-socs - -.. _EFR32MG12 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32mg12-datasheet.pdf - -.. _EFR32xG12 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efr32xg12-rm.pdf - -.. _BRD4161A User Guide: - https://www.silabs.com/documents/public/user-guides/ug260-brd4161a-user-guide.pdf diff --git a/boards/silabs/efr32_radio/doc/brd4170a.rst b/boards/silabs/efr32_radio/doc/brd4170a.rst deleted file mode 100644 index a1751424f37c8..0000000000000 --- a/boards/silabs/efr32_radio/doc/brd4170a.rst +++ /dev/null @@ -1,108 +0,0 @@ -.. _efr32_radio_brd4170a: - -EFR32 BRD4170A (SLWRB4170A) -########################### - -Overview -******** - -The EFR32MG12 Mighty Gecko Radio Board contains a Wireless System-On-Chip -from the EFR32MG12 family built on an ARM Cortex®-M4F processor with excellent -low power capabilities. - -.. figure:: efr32mg12-slwrb4170a.jpg - :align: center - :alt: SLWRB4170A Mighty Gecko Radio Board - - SLWRB4170A (image courtesy of Silicon Labs) - -The BRD4170A a.k.a. SLWRB4170A radio board plugs into the Wireless Starter Kit -Mainboard BRD4001A and is supported as one of :ref:`efr32_radio`. - -Hardware -******** - -- EFR32MG12P433F1024GM68 Mighty Gecko SoC -- CPU core: ARM Cortex®-M4 with FPU -- Flash memory: 1024 kB -- RAM: 256 kB -- Transmit power: up to +19 dBm -- Operation frequency: 2.4 GHz and Sub-Ghz -- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). - -For more information about the EFR32MG12 SoC and BRD4170A board, refer to these -documents: - -- `EFR32MG12 Website`_ -- `EFR32MG12 Datasheet`_ -- `EFR32xG12 Reference Manual`_ -- `BRD4170A User Guide`_ - -Supported Features -================== - -Please refer to -:ref:`EFR32 Radio Board Supported Features ` -for details of the configuration and common features supported by the -``efr32_radio/efr32mg12p433f1024gm68`` board. - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68_defconfig` - -System Clock -============ - -The EFR32MG12P SoC is configured to use the 38.4 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFR32MG12P SoC has four USARTs and one Low Energy UARTs (LEUART). -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -Please refer to -:ref:`Programming and Debugging EFR32 Radio Board ` -for details on the supported debug interfaces. - -Flashing -======== - -Connect the BRD4001A board with a mounted BRD4170A radio module to your host -computer using the USB port. - -Here is an example for the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32_radio/efr32mg12p433f1024gm68 - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should see the following message in the terminal: - -.. code-block:: console - - Hello World! efr32_radio - - -.. _EFR32MG12 Website: - https://www.silabs.com/wireless/zigbee/efr32mg12-series-1-socs - -.. _EFR32MG12 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32mg12-datasheet.pdf - -.. _EFR32xG12 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efr32xg12-rm.pdf - -.. _BRD4170A User Guide: - https://www.silabs.com/documents/public/user-guides/ug342-brd4170a-user-guide.pdf diff --git a/boards/silabs/efr32_radio/doc/brd4180a.rst b/boards/silabs/efr32_radio/doc/brd4180a.rst deleted file mode 100644 index 4998122bbcdf5..0000000000000 --- a/boards/silabs/efr32_radio/doc/brd4180a.rst +++ /dev/null @@ -1,160 +0,0 @@ -.. _efr32_radio_brd4180a: - -EFR32 BRD4180A (SLWRB4180A) -########################### - -Overview -******** - -The EFR32MG21 Mighty Gecko Radio Board is one of the two -radio boards delivered with `EFR32-SLWSTK6006A Website`_. It contains -a Wireless System-On-Chip from the EFR32MG21 family built on an -ARM Cortex®-M33F processor with excellent low power capabilities. - -.. figure:: efr32mg21-slwrb4180a.jpg - :align: center - :alt: SLWRB4180A Mighty Gecko Radio Board - - SLWRB4180A (image courtesy of Silicon Labs) - -The BRD4180A a.k.a. SLWRB4180A radio board plugs into the Wireless Starter Kit -Mainboard BRD4001A and is supported as one of :ref:`efr32_radio`. - -Hardware -******** - -- EFR32MG21A020F1024IM32 Mighty Gecko SoC -- CPU core: ARM Cortex®-M33 with FPU -- Flash memory: 1024 kB -- RAM: 96 kB -- Transmit power: up to +20 dBm -- Operation frequency: 2.4 GHz -- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). - -For more information about the EFR32MG21 SoC and BRD4180A board, refer to these -documents: - -- `EFR32MG21 Website`_ -- `EFR32MG21 Datasheet`_ -- `EFR32xG21 Reference Manual`_ -- `EFR32-SLWSTK6006A Website`_ -- `BRD4180A User Guide`_ - -Supported Features -================== - -The board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | rtcc | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ -| I2C | on-chip | i2c port-polling | -+-----------+------------+-------------------------------------+ -| WATCHDOG | on-chip | watchdog | -+-----------+------------+-------------------------------------+ - -Other hardware features are currently not supported by the port. - -Connections and IOs -=================== - -In the following table, the column **Name** contains Pin names. For example, PA2 -means Pin number 2 on PORTA, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PB0 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PB1 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PD2 | GPIO | Push Button PB0 | -+-------+-------------+-------------------------------------+ -| PD3 | GPIO | Push Button PB1 | -+-------+-------------+-------------------------------------+ -| PD4 | GPIO | Board Controller Enable | -| | | EFM_BC_EN | -+-------+-------------+-------------------------------------+ -| PA5 | USART1_TX | UART Console EFM_BC_TX US1_TX | -+-------+-------------+-------------------------------------+ -| PA6 | USART1_RX | UART Console EFM_BC_RX US1_RX | -+-------+-------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32_defconfig` - -System Clock -============ - -The EFR32MG21 SoC is configured to use the 38.4 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFR32MG21 SoC has three USARTs. -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -Please refer to -:ref:`Programming and Debugging EFR32 Radio Board ` -for details on the supported debug interfaces. - -Flashing -======== - -Connect the BRD4001A board with a mounted BRD4180A radio module to your host -computer using the USB port. - -Here is an example for the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32_radio/efr32mg21a020f1024im32 - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should see the following message in the terminal: - -.. code-block:: console - - Hello World! efr32_radio - - -.. _EFR32-SLWSTK6006A Website: - https://www.silabs.com/products/development-tools/wireless/efr32xg21-wireless-starter-kit - -.. _BRD4180A User Guide: - https://www.silabs.com/documents/public/user-guides/ug385-brd4180a-user-guide.pdf - -.. _EFR32MG21 Website: - https://www.silabs.com/products/wireless/mesh-networking/efr32mg21-series-2-socs - -.. _EFR32MG21 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32mg21-datasheet.pdf - -.. _EFR32xG21 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efr32xg21-rm.pdf diff --git a/boards/silabs/efr32_radio/doc/brd4187c.rst b/boards/silabs/efr32_radio/doc/brd4187c.rst deleted file mode 100644 index f5a3cd808ddd0..0000000000000 --- a/boards/silabs/efr32_radio/doc/brd4187c.rst +++ /dev/null @@ -1,161 +0,0 @@ -.. _efr32_radio_brd4187c: - -EFR32 BRD4187C (xG24-RB4187C) -############################# - -Overview -******** - -The EFR32MG24 Mighty Gecko Radio Board is one of the two -radio boards delivered with `xG24-PK6010A Website`_. It contains -a Wireless System-On-Chip from the EFR32MG24 family built on an -ARM Cortex®-M33F processor with excellent low power capabilities. - -.. figure:: efr32mg24-xg24-rb4187c.jpg - :align: center - :alt: xG24-RB4187C Mighty Gecko Radio Board - - xG24-RB4187C (image courtesy of Silicon Labs) - -The BRD4187C a.k.a. xG24-RB4187C radio board plugs into the Wireless Pro Kit -Mainboard BRD4002A and is supported as one of :ref:`efr32_radio`. - -Hardware -******** - -- EFR32MG24B220F1536IM48 Mighty Gecko SoC -- CPU core: ARM Cortex®-M33 with FPU -- Flash memory: 1536 kB -- RAM: 256 kB -- Transmit power: up to +20 dBm -- Operation frequency: 2.4 GHz -- Crystals for LFXO (32.768 kHz) and HFXO (39 MHz). - -For more information about the EFR32MG24 SoC and BRD4187C board, refer to these -documents: - -- `EFR32MG24 Website`_ -- `EFR32MG24 Datasheet`_ -- `EFR32xG24 Reference Manual`_ -- `xG24-PK6010A Website`_ -- `BRD4187C User Guide`_ - -Supported Features -================== - -The board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | stimer | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial | -+-----------+------------+-------------------------------------+ -| I2C | on-chip | i2c | -+-----------+------------+-------------------------------------+ -| TRNG | on-chip | semailbox | -+-----------+------------+-------------------------------------+ -| WATCHDOG | on-chip | watchdog | -+-----------+------------+-------------------------------------+ - -Other hardware features are currently not supported by the port. - -Connections and IOs -=================== - -In the following table, the column **Name** contains Pin names. For example, PA2 -means Pin number 2 on PORTA, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PB2 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PB4 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PB1 | GPIO | Push Button 0 | -+-------+-------------+-------------------------------------+ -| PB3 | GPIO | Push Button 1 | -+-------+-------------+-------------------------------------+ -| PB0 | GPIO | Board Controller Enable | -| | | VCOM_ENABLE | -+-------+-------------+-------------------------------------+ -| PA8 | USART0_TX | UART Console VCOM_TX US0_TX | -+-------+-------------+-------------------------------------+ -| PA9 | USART0_RX | UART Console VCOM_RX US0_RX | -+-------+-------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48_defconfig` - -System Clock -============ - -The EFR32MG24 SoC is configured to use the 39 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFR32MG24 SoC has one USART and two EUSARTs. -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -Please refer to -:ref:`Programming and Debugging EFR32 Radio Board ` -for details on the supported debug interfaces. - -Flashing -======== - -Connect the BRD4002A board with a mounted BRD4187C radio module to your host -computer using the USB port. - -Here is an example for the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32_radio/efr32mg24b220f1536im48 - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should see the following message in the terminal: - -.. code-block:: console - - Hello World! efr32_radio - - -.. _xG24-PK6010A Website: - https://www.silabs.com/development-tools/wireless/efr32xg24-pro-kit-20-dbm - -.. _BRD4187C User Guide: - https://www.silabs.com/documents/public/user-guides/ug526-brd4187c-user-guide.pdf - -.. _EFR32MG24 Website: - https://www.silabs.com/wireless/zigbee/efr32mg24-series-2-socs - -.. _EFR32MG24 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32mg24-datasheet.pdf - -.. _EFR32xG24 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/brd4187c-rm.pdf diff --git a/boards/silabs/efr32_radio/doc/brd4250b.rst b/boards/silabs/efr32_radio/doc/brd4250b.rst deleted file mode 100644 index 6ccb4ca22caa0..0000000000000 --- a/boards/silabs/efr32_radio/doc/brd4250b.rst +++ /dev/null @@ -1,121 +0,0 @@ -.. _efr32_radio_brd4250b: - -EFR32 BRD4250B (SLWRB4250B) -########################### - -Overview -******** - -The EFR32FG1 Flex Gecko 2.4 GHz and 868 MHz Radio Board is delivered as part of -`SLWSTK6061B Proprietary Wireless Starter Kit`_. It contains a EFR32FG1 Wireless -SoC built on an ARM Cortex®-M4F processor with excellent low power capabilities. - -.. figure:: efr32fg1-slwrb4250b.jpg - :align: center - :alt: SLWRB4250B Flex Gecko 2.4 GHz and 868 MHz Radio Board - - SLWRB4250B (image courtesy of Silicon Labs) - -The BRD4250B a.k.a. SLWRB4250B radio board plugs into the Wireless Starter Kit -Mainboard BRD4001A and is supported as one of :ref:`efr32_radio`. - -Hardware -******** - -- EFR32FG1P133F256GM48 Flex Gecko SoC -- CPU core: ARM Cortex®-M4 with FPU -- Flash memory: 256 kB -- RAM: 32 kB -- Transmit power: up to +13 dBm -- Operation frequency: 2.4 GHz, 868 MHz -- 8Mbit SPI NOR Flash -- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). - -For more information about the EFR32FG1 SoC and BRD4250B board, refer to these -documents: - -- `EFR32FG1 Website`_ -- `EFR32FG1 Datasheet`_ -- `EFR32xG1 Reference Manual`_ -- `SLWSTK6061B Proprietary Wireless Starter Kit`_ -- `BRD4250B User Guide`_ -- `BRD4250B Reference Manual`_ -- `EFR32FG1-BRD4250B Schematics`_ - -Supported Features -================== - -Please refer to -:ref:`EFR32 Radio Board Supported Features ` -for details of the configuration and common features supported by the -``efr32_radio/efr32fg1p133f256gm48`` board. - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48_defconfig` - -System Clock -============ - -The EFR32FG1P SoC is configured to use the 38.4 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFR32FG1P SoC has two USARTs and one Low Energy UARTs (LEUART). -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -Please refer to -:ref:`Programming and Debugging EFR32 Radio Board ` -for details on the supported debug interfaces. - -Flashing -======== - -Connect the BRD4001A board with a mounted BRD4250B radio module to your host -computer using the USB port. - -Here is an example for the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32_radio/efr32fg1p133f256gm48 - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should see the following message in the terminal: - -.. code-block:: console - - Hello World! efr32_radio - - -.. _EFR32FG1 Website: - https://www.silabs.com/wireless/proprietary/efr32fg1-series-1-sub-ghz-2-4-ghz-socs - -.. _EFR32FG1 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32fg1-datasheet.pdf - -.. _EFR32xG1 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efr32xg1-rm.pdf - -.. _SLWSTK6061B Proprietary Wireless Starter Kit: - https://www.silabs.com/products/development-tools/wireless/proprietary/slwstk6061b-efr32-flex-gecko-868-mhz-2-4-ghz-and-sub-ghz-starter-kit - -.. _BRD4250B User Guide: - https://www.silabs.com/documents/public/user-guides/ug182-brd4250b-user-guide.pdf - -.. _BRD4250B Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/brd4250b-rm.pdf - -.. _EFR32FG1-BRD4250B Schematics: - https://www.silabs.com/documents/public/schematic-files/BRD4250B-B02-schematic.pdf diff --git a/boards/silabs/efr32_radio/doc/brd4255a.rst b/boards/silabs/efr32_radio/doc/brd4255a.rst deleted file mode 100644 index 60138f08610c0..0000000000000 --- a/boards/silabs/efr32_radio/doc/brd4255a.rst +++ /dev/null @@ -1,111 +0,0 @@ -.. _efr32_radio_brd4255a: - -EFR32 BRD4255A (SLWRB4255A) -########################### - -Overview -******** - -The EFR32FG13P Flex Gecko 2.4 GHz and 915 MHz Radio Board is delivered as a -`standalone Proprietary Wireless radio board`_. It contains a EFR32FG13P Wireless -SoC built on an ARM Cortex®-M4F processor with excellent low power capabilities. - -.. figure:: efr32fg13-slwrb4255a.jpg - :align: center - :alt: SLWRB4255A Flex Gecko 2.4 GHz and 915 MHz Radio Board - - SLWRB4255A (image courtesy of Silicon Labs) - -The BRD4255A a.k.a. SLWRB4255A radio board plugs into the Wireless Starter Kit -Mainboard BRD4001A and is supported as one of :ref:`efr32_radio`. - -Hardware -******** - -- EFR32FG13P233F512GM48 Flex Gecko SoC -- CPU core: ARM Cortex®-M4 with FPU -- Flash memory: 512 kB -- RAM: 64 kB -- Transmit power: up to 19 dBm -- Operation frequency: 2.4 GHz, 915 MHz -- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). - -For more information about the EFR32FG13 SoC and BRD4255A board, refer to these -documents: - -- `EFR32FG13 Website`_ -- `EFR32FG13 Datasheet`_ -- `EFR32xG13 Reference Manual`_ -- `BRD4255A Reference Manual`_ - -Supported Features -================== - -Please refer to -:ref:`EFR32 Radio Board Supported Features ` -for details of the configuration and common features supported by the -``efr32_radio/efr32fg13p233f512gm48`` board. - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32_radio/efr32_radio_efr32fg13p233f512gm48_defconfig` - -System Clock -============ - -The EFR32FG13P SoC is configured to use the 38.4 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFR32FG13P SoC has three USARTs and one Low Energy UARTs (LEUART). -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -Please refer to -:ref:`Programming and Debugging EFR32 Radio Board ` -for details on the supported debug interfaces. - -Flashing -======== - -Connect the BRD4001A board with a mounted BRD4255A radio module to your host -computer using the USB port. - -Here is an example for the :ref:`hello_world` application. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32_radio/efr32fg13p233f512gm48 - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should see the following message in the terminal: - -.. code-block:: console - - Hello World! efr32_radio - - -.. _EFR32FG13 Website: - https://www.silabs.com/wireless/proprietary/efr32fg13-series-1-sub-ghz-2-4-ghz-socs - -.. _EFR32FG13 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32fg13-datasheet.pdf - -.. _EFR32xG13 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efr32xg13-rm.pdf - -.. _standalone Proprietary Wireless radio board: - https://www.silabs.com/development-tools/wireless/proprietary/slwrb4255a-efr32fg13-915-mhz-radio-board - -.. _BRD4255A Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/brd4255a-rm.pdf diff --git a/boards/silabs/efr32_radio/doc/efr32_slwstk6020b.jpg b/boards/silabs/efr32_radio/doc/efr32_slwstk6020b.jpg deleted file mode 100644 index 5a93d75ff9484..0000000000000 Binary files a/boards/silabs/efr32_radio/doc/efr32_slwstk6020b.jpg and /dev/null differ diff --git a/boards/silabs/efr32_radio/doc/index.rst b/boards/silabs/efr32_radio/doc/index.rst deleted file mode 100644 index 31f79df34e0b5..0000000000000 --- a/boards/silabs/efr32_radio/doc/index.rst +++ /dev/null @@ -1,190 +0,0 @@ -.. _efr32_radio: - -EFR32 Radio Boards -################## - -.. toctree:: - :maxdepth: 1 - - brd4104a.rst - brd4170a.rst - brd4250b.rst - brd4180a.rst - brd4255a.rst - brd4187c.rst - -Overview -******** - -Support for EFR32 Radio boards is provided by one of the starter kits - -- `SLWSTK6020B Bluetooth SoC Starter Kit`_ -- `SLWSTK6000B Mighty Gecko Wireless Starter Kit`_ -- `SLWSTK6061B Proprietary Wireless Starter Kit`_ -- `SLWSTK6006A Mighty Gecko Wireless Starter Kit`_ - -.. figure:: efr32_slwstk6020b.jpg - :align: center - :alt: SLWSTK6020B Bluetooth SoC Starter Kit - - SLWSTK6020B (image courtesy of Silicon Labs) - -Hardware -******** - -Wireless Starter Kit Mainboard: - -- Advanced Energy Monitoring provides real-time information about the energy - consumption of an application or prototype design. -- Ultra-low power 128x128 pixel memory LCD -- 2 user buttons and 2 LEDs -- 20 pin expansion header -- Si7021 Humidity and Temperature Sensor -- On-board Segger J-Link USB and Ethernet debugger - -For more information about the BRD4001A board, refer to these documents: - -- `EFR32BG13 Blue Gecko Bluetooth Starter Kit User's Guide`_ -- `EFR32MG21 Mighty Gecko Wireless Starter Kit User's Guide`_ -- `WSTK Main Board BRD4001A Schematics`_ - -.. _efr32_radio_supported_features: - -Supported Features -================== - -The board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | rtcc | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ -| SPI(M) | on-chip | spi port-polling | -+-----------+------------+-------------------------------------+ -| WATCHDOG | on-chip | watchdog | -+-----------+------------+-------------------------------------+ - -Other hardware features are currently not supported by the port. - -Connections and IOs -=================== - -In the following table, the column **Name** contains Pin names. For example, PA2 -means Pin number 2 on PORTA, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PF4 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PF5 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PF6 | GPIO | Push Button PB0 | -+-------+-------------+-------------------------------------+ -| PF7 | GPIO | Push Button PB1 | -+-------+-------------+-------------------------------------+ -| PA5 | GPIO | Board Controller Enable | -| | | EFM_BC_EN | -+-------+-------------+-------------------------------------+ -| PA0 | USART0_TX | UART Console EFM_BC_TX US0_TX #0 | -+-------+-------------+-------------------------------------+ -| PA1 | USART0_RX | UART Console EFM_BC_RX US0_RX #0 | -+-------+-------------+-------------------------------------+ -| PC6 | SPI_MOSI | Flash MOSI US1_TX #11 | -+-------+-------------+-------------------------------------+ -| PC7 | SPI_MISO | Flash MISO US1_RX #11 | -+-------+-------------+-------------------------------------+ -| PC8 | SPI_SCLK | Flash SCLK US1_CLK #11 | -+-------+-------------+-------------------------------------+ -| PA4 | SPI_CS | Flash Chip Select (GPIO) | -+-------+-------------+-------------------------------------+ - -.. _efr32_radio_programming: - -Programming and Debugging -************************* - -The BRD4001A includes an `J-Link`_ serial and debug adaptor built into the -board. The adaptor provides: - -- A USB connection to the host computer, which exposes a debug interface and a - USB Serial Port. -- A physical UART connection which is relayed over interface USB Serial port. -- An Ethernet connection to support remote debugging. - -It is compatible with the following host debug tools: - -- :ref:`openocd-debug-host-tools` -- :ref:`jlink-debug-host-tools` - -OpenOCD is included in the Zephyr SDK. Refer to the links above for information -on how to install required host debug tools if you are not using the Zephyr SDK. - -Flashing -======== - -Connect the BRD4001A main board with the mounted radio module to your host -computer using the USB port. - -Following example shows how to build the :ref:`hello_world` application for -BRD4104A radio module. - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32_radio_brd4104a - :goals: flash - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should see the following message in the terminal: - -.. code-block:: console - - Hello World! efr32_radio_brd4104a - - -.. _SLWSTK6020B Bluetooth SoC Starter Kit: - https://www.silabs.com/products/development-tools/wireless/bluetooth/blue-gecko-bluetooth-low-energy-soc-starter-kit - -.. _SLWSTK6000B Mighty Gecko Wireless Starter Kit: - https://www.silabs.com/products/development-tools/wireless/mesh-networking/mighty-gecko-starter-kit - -.. _SLWSTK6061B Proprietary Wireless Starter Kit: - https://www.silabs.com/products/development-tools/wireless/proprietary/slwstk6061b-efr32-flex-gecko-868-mhz-2-4-ghz-and-sub-ghz-starter-kit - -.. _SLWSTK6006A Mighty Gecko Wireless Starter Kit: - https://www.silabs.com/products/development-tools/wireless/efr32xg21-wireless-starter-kit - -.. _EFR32BG13 Blue Gecko Bluetooth Starter Kit User's Guide: - https://www.silabs.com/documents/public/user-guides/ug279-brd4104a-user-guide.pdf - -.. _EFR32MG21 Mighty Gecko Wireless Starter Kit User's Guide: - https://www.silabs.com/documents/public/user-guides/ug385-brd4180a-user-guide.pdf - -.. _EFR32MG24 Mighty Gecko Wireless Starter Kit User's Guide: - https://www.silabs.com/documents/public/user-guides/ug526-brd4187c-user-guide.pdf - -.. _WSTK Main Board BRD4001A Schematics: - https://www.silabs.com/documents/public/schematic-files/BRD4001A-A01-schematic.pdf - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html diff --git a/boards/silabs/efr32_radio/efr32_radio-pinctrl.dtsi b/boards/silabs/efr32_radio/efr32_radio-pinctrl.dtsi deleted file mode 100644 index ade31fddfd824..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio-pinctrl.dtsi +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2023 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -&pinctrl { - /* configuration for usart0 device, default state - operating as UART */ - usart0_default: usart0_default { - group1 { - psels = , - , - , - ; - }; - }; -}; diff --git a/boards/silabs/efr32_radio/efr32_radio.dtsi b/boards/silabs/efr32_radio/efr32_radio.dtsi deleted file mode 100644 index 361b66b72df38..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio.dtsi +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (c) 2020 Piotr Mienkowski - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include "efr32_radio-pinctrl.dtsi" - -/ { - chosen { - zephyr,console = &usart0; - zephyr,shell-uart = &usart0; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - zephyr,code-partition = &slot0_partition; - }; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - sw0 = &button0; - sw1 = &button1; - watchdog0 = &wdog0; - spi-flash0 = &mx25r80; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpiof 4 0>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpiof 5 0>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - /* gpio flags need validation */ - gpios = <&gpiof 6 GPIO_ACTIVE_LOW>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - /* gpio flags need validation */ - gpios = <&gpiof 7 GPIO_ACTIVE_LOW>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; - -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&usart1 { - compatible = "silabs,gecko-spi-usart"; - - #address-cells = <1>; - #size-cells = <0>; - - location-rx = ; - location-tx = ; - location-clk = ; - - cs-gpios = <&gpioa 4 GPIO_ACTIVE_LOW>; - - status = "okay"; - - mx25r80: mx25r8035f@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <33000000>; - size = <0x800000>; - jedec-id = [c2 28 14]; - }; -}; - -&rtcc0 { - prescaler = <1>; - status = "okay"; -}; - -&gpio { - location-swo = <0>; - status = "okay"; -}; - -&gpioa { - status = "okay"; - - board-controller-enable { - gpio-hog; - gpios = <5 GPIO_ACTIVE_HIGH>; - output-high; - }; -}; - -&gpiob { - status = "okay"; -}; - -&gpioc { - status = "okay"; -}; - -&gpiod { - status = "okay"; -}; - -&gpiof { - status = "okay"; -}; - -&wdog0 { - status = "okay"; -}; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.dts b/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.dts deleted file mode 100644 index 9ded71ef5598a..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.dts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2020 Piotr Mienkowski - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include "efr32_radio.dtsi" - -/ { - model = "Silicon Labs BRD4104A (Blue Gecko Radio Board)"; - compatible = "silabs,efr32_radio_brd4104a", "silabs,efr32bg13p"; - - aliases { - spi-flash0 = &mx25r80; - }; -}; - -&cpu0 { - clock-frequency = <38400000>; -}; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Reserve 32 kB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 0x00008000>; - read-only; - }; - - /* Reserve 220 kB for the application in slot 0 */ - slot0_partition: partition@8000 { - label = "image-0"; - reg = <0x00008000 0x00037000>; - }; - - /* Reserve 220 kB for the application in slot 1 */ - slot1_partition: partition@3f000 { - label = "image-1"; - reg = <0x0003f000 0x00037000>; - }; - - /* Reserve 32 kB for the scratch partition */ - scratch_partition: partition@76000 { - label = "image-scratch"; - reg = <0x00076000 0x00008000>; - }; - - /* Set 8Kb of storage at the end of the 512KB of flash */ - storage_partition: partition@7e000 { - label = "storage"; - reg = <0x0007e000 0x00002000>; - }; - - }; -}; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.yaml b/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.yaml deleted file mode 100644 index 8edaadbadf72b..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32bg13p632f512gm48.yaml +++ /dev/null @@ -1,22 +0,0 @@ -identifier: efr32_radio/efr32bg13p632f512gm48 -name: BRD4104A -type: mcu -arch: arm -ram: 64 -flash: 512 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - counter - - gpio - - nvs - - spi - - uart - - watchdog -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32fg13p233f512gm48.dts b/boards/silabs/efr32_radio/efr32_radio_efr32fg13p233f512gm48.dts deleted file mode 100644 index cf146428322d2..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32fg13p233f512gm48.dts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2020 Piotr Mienkowski - * Copyright (c) 2021 Yonatan Schachter - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "efr32_radio.dtsi" - -/ { - model = "Silicon Labs BRD4255A (Flex Gecko Radio Board)"; - compatible = "silabs,efr32_radio_brd4255a", "silabs,efr32fg13p"; -}; - -&cpu0 { - clock-frequency = <38400000>; -}; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Reserve 32 kB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 0x00008000>; - read-only; - }; - - /* Reserve 220 kB for the application in slot 0 */ - slot0_partition: partition@8000 { - label = "image-0"; - reg = <0x00008000 0x00037000>; - }; - - /* Reserve 220 kB for the application in slot 1 */ - slot1_partition: partition@3f000 { - label = "image-1"; - reg = <0x0003f000 0x00037000>; - }; - - /* Reserve 32 kB for the scratch partition */ - scratch_partition: partition@76000 { - label = "image-scratch"; - reg = <0x00076000 0x00008000>; - }; - - /* Set 8Kb of storage at the end of the 512KB of flash */ - storage_partition: partition@7e000 { - label = "storage"; - reg = <0x0007e000 0x00002000>; - }; - - }; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32fg13p233f512gm48.yaml b/boards/silabs/efr32_radio/efr32_radio_efr32fg13p233f512gm48.yaml deleted file mode 100644 index af096e1af9e28..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32fg13p233f512gm48.yaml +++ /dev/null @@ -1,22 +0,0 @@ -identifier: efr32_radio/efr32fg13p233f512gm48 -name: BRD4255A -type: mcu -arch: arm -ram: 64 -flash: 512 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - counter - - gpio - - nvs - - spi - - uart - - watchdog -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.dts b/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.dts deleted file mode 100644 index 2167b1b69b786..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.dts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2020 Piotr Mienkowski - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "efr32_radio.dtsi" - -/ { - model = "Silicon Labs BRD4250B (Flex Gecko Radio Board)"; - compatible = "silabs,efr32_radio_brd4250b", "silabs,efr32fg1p"; - - pwmleds { - compatible = "pwm-leds"; - status = "okay"; - pwm_led0: pwm_led0 { - pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; - }; - }; - - aliases { - pwm-led0 = &pwm_led0; - spi-flash0 = &mx25r80; - }; -}; - -&cpu0 { - clock-frequency = <38400000>; -}; - -&timer0 { - status = "okay"; - - pwm0: pwm { - status = "okay"; - pin-location = ; - prescaler = <1024>; - }; -}; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Reserve 32 kB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 0x00008000>; - read-only; - }; - - /* Reserve 94 kB for the application in slot 0 */ - slot0_partition: partition@8000 { - label = "image-0"; - reg = <0x00008000 0x00017800>; - }; - - /* Reserve 94 kB for the application in slot 1 */ - slot1_partition: partition@1f800 { - label = "image-1"; - reg = <0x0001f800 0x00017800>; - }; - - /* Reserve 30 kB for the scratch partition */ - scratch_partition: partition@37000 { - label = "image-scratch"; - reg = <0x00037000 0x00007800>; - }; - - /* Set 6Kb of storage at the end of the 256Kb of flash */ - storage_partition: partition@3e800 { - label = "storage"; - reg = <0x0003e800 0x00001800>; - }; - - }; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.yaml b/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.yaml deleted file mode 100644 index 356d959514caf..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48.yaml +++ /dev/null @@ -1,22 +0,0 @@ -identifier: efr32_radio/efr32fg1p133f256gm48 -name: BRD4250B -type: mcu -arch: arm -ram: 32 -flash: 256 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - counter - - gpio - - nvs - - spi - - uart - - watchdog -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts deleted file mode 100644 index 64b9dce560dd8..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.dts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2020 Piotr Mienkowski - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include "efr32_radio.dtsi" - -/ { - model = "Silicon Labs BRD4161A (Mighty Gecko Radio Board)"; - compatible = "silabs,efr32_radio_brd4161a", "silabs,efr32mg12p"; - - aliases { - spi-flash0 = &mx25r80; - }; -}; - -&cpu0 { - clock-frequency = <38400000>; -}; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Reserve 32 kB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 0x00008000>; - read-only; - }; - - /* Reserve 220 kB for the application in slot 0 */ - slot0_partition: partition@8000 { - label = "image-0"; - reg = <0x00008000 0x00037000>; - }; - - /* Reserve 220 kB for the application in slot 1 */ - slot1_partition: partition@3f000 { - label = "image-1"; - reg = <0x0003f000 0x00037000>; - }; - - /* Reserve 32 kB for the scratch partition */ - scratch_partition: partition@76000 { - label = "image-scratch"; - reg = <0x00076000 0x00008000>; - }; - - /* Set 8Kb of storage at the end of the 512KB of flash */ - storage_partition: partition@7e000 { - label = "storage"; - reg = <0x0007e000 0x00002000>; - }; - - }; -}; - -&pinctrl { - i2c0_default: i2c0_default { - group1 { - psels = , - , - , - ; - }; - }; -}; - -&i2c0 { - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - status = "okay"; - - si7021: si7021@40 { - compatible = "silabs,si7006"; - reg = <0x40>; - status = "okay"; - }; -}; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.yaml b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.yaml deleted file mode 100644 index 8092040c67295..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125.yaml +++ /dev/null @@ -1,21 +0,0 @@ -identifier: efr32_radio/efr32mg12p432f1024gl125 -name: BRD4161A -type: mcu -arch: arm -ram: 256 -flash: 1024 -toolchain: - - zephyr - - gnuarmemb -supported: - - counter - - gpio - - nvs - - spi - - uart - - watchdog -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts deleted file mode 100644 index effd66a8515b9..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.dts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 2020 Piotr Mienkowski - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include "efr32_radio.dtsi" - -/ { - model = "Silicon Labs BRD4170A (Mighty Gecko Radio Board)"; - compatible = "silabs,efr32_radio_brd4170a", "silabs,efr32mg12p"; - - aliases { - spi-flash0 = &mx25r80; - }; -}; - -&cpu0 { - clock-frequency = <38400000>; -}; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Reserve 32 kB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 0x00008000>; - read-only; - }; - - /* Reserve 220 kB for the application in slot 0 */ - slot0_partition: partition@8000 { - label = "image-0"; - reg = <0x00008000 0x00037000>; - }; - - /* Reserve 220 kB for the application in slot 1 */ - slot1_partition: partition@3f000 { - label = "image-1"; - reg = <0x0003f000 0x00037000>; - }; - - /* Reserve 32 kB for the scratch partition */ - scratch_partition: partition@76000 { - label = "image-scratch"; - reg = <0x00076000 0x00008000>; - }; - - /* Set 8Kb of storage at the end of the 512KB of flash */ - storage_partition: partition@7e000 { - label = "storage"; - reg = <0x0007e000 0x00002000>; - }; - - }; -}; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.yaml b/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.yaml deleted file mode 100644 index ac0779d0d0176..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68.yaml +++ /dev/null @@ -1,21 +0,0 @@ -identifier: efr32_radio/efr32mg12p433f1024gm68 -name: BRD4170A -type: mcu -arch: arm -ram: 256 -flash: 1024 -toolchain: - - zephyr - - gnuarmemb -supported: - - counter - - gpio - - nvs - - spi - - uart - - watchdog -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32.dts b/boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32.dts deleted file mode 100644 index 379fd031e22dc..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32.dts +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2020 TriaGnoSys GmbH - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "efr32_radio_efr32mg21a020f1024im32-pinctrl.dtsi" - -/ { - model = "Silicon Labs BRD4180A (Mighty Gecko Radio Board)"; - compatible = "silabs,efr32mg21_brd4180a", "silabs,efr32mg21"; - - chosen { - zephyr,console = &usart0; - zephyr,shell-uart = &usart0; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - zephyr,code-partition = &slot0_partition; - }; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - sw0 = &button0; - sw1 = &button1; - watchdog0 = &wdog0; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpiob 0 0>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpiob 1 0>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - /* gpio flags need validation */ - gpios = <&gpiod 2 GPIO_ACTIVE_LOW>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - /* gpio flags need validation */ - gpios = <&gpiod 3 GPIO_ACTIVE_LOW>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; - -}; - -&cpu0 { - clock-frequency = <38400000>; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&rtcc0 { - prescaler = <1>; - status = "okay"; -}; - -&gpio { - status = "okay"; -}; - -&gpioa { - status = "okay"; -}; - -&gpiob { - status = "okay"; -}; - -&gpioc { - status = "okay"; -}; - -&gpiod { - status = "okay"; - - board-controller-enable { - gpio-hog; - gpios = <4 GPIO_ACTIVE_HIGH>; - output-high; - }; -}; - -&wdog0 { - status = "okay"; -}; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Reserve 48 kB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 0x0000c000>; - read-only; - }; - - /* Reserve 464 kB for the application in slot 0 */ - slot0_partition: partition@c000 { - label = "image-0"; - reg = <0x0000c000 0x00074000>; - }; - - /* Reserve 464 kB for the application in slot 1 */ - slot1_partition: partition@80000 { - label = "image-1"; - reg = <0x00080000 0x00074000>; - }; - - /* Reserve 32 kB for the scratch partition */ - scratch_partition: partition@f4000 { - label = "image-scratch"; - reg = <0x000f4000 0x00008000>; - }; - - /* Set 16Kb of storage at the end of the 1024Kb of flash */ - storage_partition: partition@fc000 { - label = "storage"; - reg = <0x000fc000 0x00004000>; - }; - - }; -}; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32.yaml b/boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32.yaml deleted file mode 100644 index c6103f5336b57..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32.yaml +++ /dev/null @@ -1,21 +0,0 @@ -identifier: efr32_radio/efr32mg21a020f1024im32 -name: BRD4180A -type: mcu -arch: arm -ram: 96 -flash: 1024 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - counter - - gpio - - nvs - - uart - - watchdog -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48.dts b/boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48.dts deleted file mode 100644 index 0fb0b4becc3a0..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48.dts +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2023 Fr. Sauter AG - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "efr32_radio_efr32mg24b220f1536im48-pinctrl.dtsi" - -/ { - model = "Silicon Labs BRD4187C (Mighty Gecko Radio Board)"; - compatible = "silabs,efr32mg24_brd4187c", "silabs,efr32mg24"; - - chosen { - zephyr,console = &usart0; - zephyr,shell-uart = &usart0; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - zephyr,code-partition = &slot0_partition; - }; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - sw0 = &button0; - sw1 = &button1; - watchdog0 = &wdog0; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpiob GECKO_PIN(2) GPIO_ACTIVE_HIGH>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpiob GECKO_PIN(4) GPIO_ACTIVE_HIGH>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - gpios = <&gpiob GECKO_PIN(1) GPIO_ACTIVE_LOW>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - gpios = <&gpiob GECKO_PIN(3) GPIO_ACTIVE_LOW>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; - -}; - -&cpu0 { - clock-frequency = <39000000>; -}; - -&pstate_em3 { - status = "disabled"; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&gpio { - location-swo = <0>; - status = "okay"; -}; - -&gpioa { - status = "okay"; -}; - -&gpiob { - status = "okay"; - - board-controller-enable { - gpio-hog; - gpios = <0 GPIO_ACTIVE_HIGH>; - output-high; - }; -}; - -&gpioc { - status = "okay"; -}; - -&gpiod { - status = "okay"; -}; - -&wdog0 { - status = "okay"; -}; - -&burtc0 { - status = "okay"; -}; - -&stimer0 { - status = "okay"; -}; - -&se { - status = "okay"; -}; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Reserve 48 kB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 DT_SIZE_K(48)>; - read-only; - }; - - /* Reserve 720 kB for the application in slot 0 */ - slot0_partition: partition@c000 { - label = "image-0"; - reg = <0x0000c000 0x000B4000>; - }; - - /* Reserve 720 kB for the application in slot 1 */ - slot1_partition: partition@C0000 { - label = "image-1"; - reg = <0x000C0000 0x000B4000>; - }; - - /* Reserve 32 kB for the scratch partition */ - scratch_partition: partition@174000 { - label = "image-scratch"; - reg = <0x00174000 DT_SIZE_K(32)>; - }; - - /* Set 16 kB of storage at the end of the 1536 kB of flash */ - storage_partition: partition@17c000 { - label = "storage"; - reg = <0x0017c000 DT_SIZE_K(16)>; - }; - }; -}; diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48.yaml b/boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48.yaml deleted file mode 100644 index 278f40a4866f6..0000000000000 --- a/boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48.yaml +++ /dev/null @@ -1,21 +0,0 @@ -identifier: efr32_radio/efr32mg24b220f1536im48 -name: BRD4187C -type: mcu -arch: arm -ram: 256 -flash: 1536 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - gpio - - uart - - watchdog -testing: - ignore_tags: - - net - - bluetooth - - pm - - hwinfo -vendor: silabs diff --git a/boards/silabs/efr32_thunderboard/Kconfig b/boards/silabs/efr32_thunderboard/Kconfig deleted file mode 100644 index f9cfc8b4499a2..0000000000000 --- a/boards/silabs/efr32_thunderboard/Kconfig +++ /dev/null @@ -1,8 +0,0 @@ -# EFR32 Thunderboard-style boards - -# Copyright (c) 2022, Silicon Labs -# SPDX-License-Identifier: Apache-2.0 - -module = BOARD_THUNDERBOARD -module-str = Board Control -source "subsys/logging/Kconfig.template.log_config" diff --git a/boards/silabs/efr32_thunderboard/Kconfig.defconfig b/boards/silabs/efr32_thunderboard/Kconfig.defconfig deleted file mode 100644 index 9c11626351895..0000000000000 --- a/boards/silabs/efr32_thunderboard/Kconfig.defconfig +++ /dev/null @@ -1,38 +0,0 @@ -# Thunderboard-style boards - -# Copyright (c) 2023 Antmicro -# SPDX-License-Identifier: Apache-2.0 - -config CMU_HFXO_FREQ - default 38400000 - -config CMU_LFXO_FREQ - default 32768 - -if SOC_GECKO_USE_RAIL - -config FPU - default y - -endif # SOC_GECKO_USE_RAIL - -if BT - -config FPU - default y - -config COMMON_LIBC_MALLOC_ARENA_SIZE - default 8192 - -config MAIN_STACK_SIZE - default 3072 if PM - default 2304 - -choice BT_HCI_BUS_TYPE - default BT_SILABS_HCI -endchoice - -endif # BT - -config REGULATOR - default y if SI7210 diff --git a/boards/silabs/efr32_thunderboard/Kconfig.efr32bg22_brd4184a b/boards/silabs/efr32_thunderboard/Kconfig.efr32bg22_brd4184a deleted file mode 100644 index 2cbcd4397614f..0000000000000 --- a/boards/silabs/efr32_thunderboard/Kconfig.efr32bg22_brd4184a +++ /dev/null @@ -1,7 +0,0 @@ -# EFR32BG SLTB010A board - -# Copyright (c) 2021, Sateesh Kotapati -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFR32BG22_BRD4184A - select SOC_PART_NUMBER_EFR32BG22C224F512IM40 diff --git a/boards/silabs/efr32_thunderboard/Kconfig.efr32bg22_brd4184b b/boards/silabs/efr32_thunderboard/Kconfig.efr32bg22_brd4184b deleted file mode 100644 index 48a8915cf5ae4..0000000000000 --- a/boards/silabs/efr32_thunderboard/Kconfig.efr32bg22_brd4184b +++ /dev/null @@ -1,7 +0,0 @@ -# EFR32BG SLTB010A board - -# Copyright (c) 2021, Sateesh Kotapati -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFR32BG22_BRD4184B - select SOC_PART_NUMBER_EFR32BG22C224F512IM40 diff --git a/boards/silabs/efr32_thunderboard/Kconfig.efr32bg27_brd2602a b/boards/silabs/efr32_thunderboard/Kconfig.efr32bg27_brd2602a deleted file mode 100644 index 7bf2e70d45533..0000000000000 --- a/boards/silabs/efr32_thunderboard/Kconfig.efr32bg27_brd2602a +++ /dev/null @@ -1,7 +0,0 @@ -# EFR32BG SLTB010A board - -# Copyright (c) 2021, Sateesh Kotapati -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFR32BG27_BRD2602A - select SOC_PART_NUMBER_EFR32BG27C140F768IM40 diff --git a/boards/silabs/efr32_thunderboard/board.c b/boards/silabs/efr32_thunderboard/board.c deleted file mode 100644 index 508d0ee68370e..0000000000000 --- a/boards/silabs/efr32_thunderboard/board.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2021 Sateesh Kotapati - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -#ifdef CONFIG_SOC_GECKO_DEV_INIT -#include "em_cmu.h" -#endif - - -LOG_MODULE_REGISTER(thunderboard, CONFIG_BOARD_THUNDERBOARD_LOG_LEVEL); - -static int thunderboard_init_clocks(void); - -static int thunderboard_init(void) -{ - int ret; - -#ifdef CONFIG_SOC_GECKO_DEV_INIT - thunderboard_init_clocks(); -#endif - static struct gpio_dt_spec wake_up_gpio_dev = - GPIO_DT_SPEC_GET(DT_NODELABEL(wake_up_trigger), gpios); - - - if (!gpio_is_ready_dt(&wake_up_gpio_dev)) { - LOG_ERR("Wake-up GPIO device was not found!\n"); - return -ENODEV; - } - ret = gpio_pin_configure_dt(&wake_up_gpio_dev, GPIO_OUTPUT_ACTIVE); - if (ret < 0) - return ret; - - return 0; -} - -#ifdef CONFIG_SOC_GECKO_DEV_INIT -static int thunderboard_init_clocks(void) -{ - CMU_ClockSelectSet(cmuClock_SYSCLK, cmuSelect_HFRCODPLL); -#if defined(_CMU_EM01GRPACLKCTRL_MASK) - CMU_ClockSelectSet(cmuClock_EM01GRPACLK, cmuSelect_HFRCODPLL); -#endif -#if defined(_CMU_EM01GRPBCLKCTRL_MASK) - CMU_ClockSelectSet(cmuClock_EM01GRPBCLK, cmuSelect_HFRCODPLL); -#endif - CMU_ClockSelectSet(cmuClock_EM23GRPACLK, cmuSelect_LFRCO); -#if defined(RTCC_PRESENT) - CMU_ClockSelectSet(cmuClock_RTCC, cmuSelect_LFRCO); -#endif - CMU_ClockSelectSet(cmuClock_WDOG0, cmuSelect_LFRCO); - - return 0; -} -#endif - -/* needs to be done after GPIO driver init */ -SYS_INIT(thunderboard_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/boards/silabs/efr32_thunderboard/board.cmake b/boards/silabs/efr32_thunderboard/board.cmake deleted file mode 100644 index d27a7983eb1db..0000000000000 --- a/boards/silabs/efr32_thunderboard/board.cmake +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_BOARD_EFR32BG22_BRD4184A OR CONFIG_BOARD_EFR32BG22_BRD4184B) - board_runner_args(jlink "--device=EFR32BG22C224F512IM40" "--reset-after-load") - include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) -elseif(CONFIG_BOARD_EFR32BG27_BRD2602A) - board_runner_args(silabs_commander "--device=EFR32BG27C140F768IM40") - include(${ZEPHYR_BASE}/boards/common/silabs_commander.board.cmake) -endif() diff --git a/boards/silabs/efr32_thunderboard/board.yml b/boards/silabs/efr32_thunderboard/board.yml deleted file mode 100644 index ebfe25a104c0c..0000000000000 --- a/boards/silabs/efr32_thunderboard/board.yml +++ /dev/null @@ -1,13 +0,0 @@ -boards: - - name: efr32bg22_brd4184a - vendor: silabs - socs: - - name: efr32bg22c224f512im40 - - name: efr32bg22_brd4184b - vendor: silabs - socs: - - name: efr32bg22c224f512im40 - - name: efr32bg27_brd2602a - vendor: silabs - socs: - - name: efr32bg27c140f768im40 diff --git a/boards/silabs/efr32_thunderboard/doc/brd2602.rst b/boards/silabs/efr32_thunderboard/doc/brd2602.rst deleted file mode 100644 index a9569d66518d3..0000000000000 --- a/boards/silabs/efr32_thunderboard/doc/brd2602.rst +++ /dev/null @@ -1,129 +0,0 @@ -.. _efr32BG27_brd2602: - -SiLabs EFR32BG27-BRD2602(A) (EFR32BG27 +8 dBm Dev Kit Board) -############################################################ - -BRD2602 is a board based on EFR32BG27 SoC and is one of -:ref:`efr32_thunderboard`. - -Hardware -******** - -- EFR32BG27 Blue Gecko Wireless SoC with up to 76.8 MHz operating frequency -- ARM® Cortex® M33 core with 64 kB RAM and 768 kB Flash -- Macronix ultra low power 8-Mbit SPI flash (MX25R8035F) -- 2.4 GHz ceramic antenna for wireless transmission -- Silicon Labs Si7021 relative humidity and temperature sensor -- Vishay VEML6035 low power, high sensitivity ambient light Sensor -- Silicon Labs Si7210 hall effect sensor -- TDK InvenSense ICM-20689 6-axis inertial sensor -- Pair of PDM microphones -- One LED and one push button -- Power enable signals and isolation switches for ultra low power operation -- On-board SEGGER J-Link debugger for easy programming and debugging, which - includes a USB virtual COM port and Packet Trace Interface (PTI) -- Mini Simplicity connector for access to energy profiling and advanced wireless - network debugging -- Breakout pads for GPIO access and connection to external hardware -- Reset button -- CR2032 coin cell holder and external battery connector - -Supported Features -================== - -The efr32bg27_brd2602 board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial | -+-----------+------------+-------------------------------------+ - -Flashing -======== - -The EFR32BG27-BRD2602A includes an embedded `J-Link`_ adapter built around -EFM32GG12 microcontroller (not user-programmable). -The adapter provides: - -- SWD interface to EFR32BG27 for flashing and debugging. -- SWO trace interface to EFR32BG27 for tracing. -- UART interface to EFR32BG27 for console access. -- A USB connection to the host computer, which exposes CDC-ACM Serial Port - endpoints for access to the console UART interface and proprietary J-Link - endpoints for access to the SWD and SWO interfaces. - -UART functionality of the adapter is accessible via standard CDC-ACM USB driver -present in most desktop operating systems and any standard serial port terminal -program e.g. `picocom`_. - -SWD and SWO functionality is accessible via `Simplicity Commander`_. - -The simplest way to flash the board is by using West, which runs Simplicity -Commander in unattended mode and passes all the necessary arguments to it. - -- If Simplicity Commander is installed in the system and the directory in - which `commander` executable is located is present in the `PATH` environment - variable: - - .. code-block:: console - - west flash - -- Otherwise, one should specify full path to the `commander` executable: - - .. code-block:: console - - west flash --commander /commander - -- In case several J-Link adapters are connected, you must specify serial number - of the adapter which should be used for flashing: - - .. code-block:: console - - west flash --dev-id - -Programming and Debugging -========================= - -The sample application :ref:`hello_world` is used for this example. -Build the Zephyr kernel and application: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32bg27_brd2602a - :goals: build - -Connect your device to your host computer using the USB port and you -should see a USB connection. Use `west`'s flash command - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should be able to see on the corresponding Serial Port -the following message: - -.. code-block:: console - - Hello World! efr32bg27_brd2602a - -.. _picocom: - https://github.com/npat-efault/picocom - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _Simplicity Commander: - https://www.silabs.com/developers/mcu-programming-options diff --git a/boards/silabs/efr32_thunderboard/doc/brd4184.rst b/boards/silabs/efr32_thunderboard/doc/brd4184.rst deleted file mode 100644 index a6f1c281d3c8e..0000000000000 --- a/boards/silabs/efr32_thunderboard/doc/brd4184.rst +++ /dev/null @@ -1,230 +0,0 @@ -.. _efr32bg22_brd4184: - -SiLabs EFR32BG22-BRD4184(A/B) (Thunderboard EFR32BG22) -###################################################### - -BRD4184 is a board based on EFR32BG22 SoC and is one of -:ref:`efr32_thunderboard`. It comes in two revisions, which differ from each -other slightly: BRD4184A and BRD4184B. - -.. image:: ./efr32bg_sltb010a.jpg - :align: center - :alt: EFR32BG-SLTB010A - -Hardware -******** - -- EFR32BG22 Blue Gecko Wireless SoC with upto 76.8 MHz operating frequency -- ARM® Cortex® M33 core with 32 kB RAM and 512 kB Flash -- Macronix ultra low power 8-Mbit SPI flash (MX25R8035F) -- 2.4 GHz ceramic antenna for wireless transmission -- Silicon Labs Si7021 relative humidity and temperature sensor -- Silicon Labs Si1133 UV index and ambient light sensor (EFR32BG22-BRD4184A) -- Vishay VEML6035 ambient light sensor (EFR32BG22-BRD4184B) -- Silicon Labs Si7210 hall effect sensor -- TDK InvenSense ICM-20648 6-axis inertial sensor -- Two Knowles SPK0641HT4H-1 MEMS microphones with PDM output (EFR32BG22-BRD4184B) -- One LED and one push button -- Power enable signals and isolation switches for ultra low power operation -- On-board SEGGER J-Link debugger for easy programming and debugging, which - includes a USB virtual COM port and Packet Trace Interface (PTI) -- Mini Simplicity connector for access to energy profiling and advanced wireless - network debugging -- Breakout pads for GPIO access and connection to external hardware -- Reset button -- Automatic switch-over between USB and battery power -- CR2032 coin cell holder and external battery connector - -For more information about the EFR32BG SoC and Thunderboard EFR32BG22 board: - -- `EFR32BG22 Website`_ -- `EFR32BG22 Datasheet`_ -- `EFR32xG22 Reference Manual`_ -- `Thunderboard EFR32BG22 Website`_ -- `EFR32BG22-BRD4184A User Guide`_ -- `EFR32BG22-BRD4184B User Guide`_ -- `EFR32BG22-BRD4184A Schematics`_ -- `EFR32BG22-BRD4184B Schematics`_ - -Supported Features -================== - -The efr32bg22_brd4184a/b board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | stimer | -+-----------+------------+-------------------------------------+ -| SPI(M/S) | on-chip | spi | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial | -+-----------+------------+-------------------------------------+ -| WATCHDOG | on-chip | watchdog | -+-----------+------------+-------------------------------------+ -| TRNG | on-chip | true random number generator | -+-----------+------------+-------------------------------------+ -| I2C(M/S) | on-chip | i2c | -+-----------+------------+-------------------------------------+ -| RADIO | on-chip | bluetooth | -+-----------+------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32_thunderboard/efr32bg22_brd4184a_defconfig` -and -:zephyr_file:`boards/silabs/efr32_thunderboard/efr32bg22_brd4184b_defconfig` - -Connections and IOs -=================== - -The EFR32BG SoC has six gpio controllers (PORTA, PORTB, PORTC, PORTD, -PORTE and PORTF). - -In the following tables, the column Name contains Pin names. For example, PE2 -means Pin number 2 on PORTE and #27 represents the location bitfield, as used -in the board's and microcontroller's datasheets and manuals. - -There are two variants of this board, "A" and "B". Please take a look at your PCB, -to determine which one you have, as the GPIO pin bindings vary between those two. - -BRD4184A: - -+------+-------------+-----------------------------------+ -| Name | Function | Usage | -+======+=============+===================================+ -| PB0 | GPIO | LED0 (YELLOW) | -+------+-------------+-----------------------------------+ -| PB1 | GPIO | SW0 Push Button PB0 | -+------+-------------+-----------------------------------+ -| PA5 | UART_TX | UART TX Console VCOM_TX US1_TX #1 | -+------+-------------+-----------------------------------+ -| PA6 | UART_RX | UART RX Console VCOM_RX US1_RX #1 | -+------+-------------+-----------------------------------+ - -BRD4184B: - -+------+-------------+-----------------------------------+ -| Name | Function | Usage | -+======+=============+===================================+ -| PA4 | GPIO | LED0 (YELLOW) | -+------+-------------+-----------------------------------+ -| PB3 | GPIO | SW0 Push Button PB0 | -+------+-------------+-----------------------------------+ -| PA5 | UART_TX | UART TX Console VCOM_TX US1_TX #1 | -+------+-------------+-----------------------------------+ -| PA6 | UART_RX | UART RX Console VCOM_RX US1_RX #1 | -+------+-------------+-----------------------------------+ - -System Clock -============ - -The EFR32BG SoC is configured to use the 38.4 MHz external oscillator on the -board. - -Programming and Debugging -========================= - -Flashing an application ------------------------ - -Connect your device to your host computer using the USB port. -The sample application :ref:`hello_world` is used for this example. -Build the Zephyr kernel and application, then flash it to the device: - -BRD4184A: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32bg22_brd4184a - :goals: flash - -BRD4184B: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32bg22_brd4184b - :goals: flash - -.. note:: - `west flash` requires `SEGGER J-Link software`_ to be installed on you host - computer. - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should be able to see on the corresponding Serial Port -the following message: - -.. code-block:: console - - Hello World! efr32bg22_brd4184 - -Bluetooth -========= - -To use the BLE function, run the command below to retrieve necessary binary -blobs from the SiLabs HAL repository. - -.. code-block:: console - - west blobs fetch silabs - -Then build the Zephyr kernel and a Bluetooth sample with the following -command. The :ref:`bluetooth-observer-sample` sample application is used in -this example. - -BRD4184A: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/observer - :board: efr32bg22_brd4184a - :goals: build - -BRD4184B: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/observer - :board: efr32bg22_brd4184b - :goals: build - - -.. _Thunderboard EFR32BG22 Website: - https://www.silabs.com/development-tools/thunderboard/thunderboard-bg22-kit - -.. _EFR32BG22-BRD4184A User Guide: - https://www.silabs.com/documents/public/user-guides/ug415-sltb010a-user-guide.pdf - -.. _EFR32BG22-BRD4184B User Guide: - https://www.silabs.com/documents/public/user-guides/ug464-brd4184b-user-guide.pdf - -.. _EFR32BG22-BRD4184A Schematics: - https://www.silabs.com/documents/public/schematic-files/BRD4184A-A01-schematic.pdf - -.. _EFR32BG22-BRD4184B Schematics: - https://www.silabs.com/documents/public/schematic-files/BRD4184B-A02-schematic.pdf - -.. _EFR32BG22 Website: - https://www.silabs.com/wireless/bluetooth/efr32bg22-series-2-socs - -.. _EFR32BG22 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32bg22-datasheet.pdf - -.. _EFR32xG22 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efr32xg22-rm.pdf - -.. _SEGGER J-Link software: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efr32_thunderboard/doc/index.rst b/boards/silabs/efr32_thunderboard/doc/index.rst deleted file mode 100644 index ca9bbcf99bd29..0000000000000 --- a/boards/silabs/efr32_thunderboard/doc/index.rst +++ /dev/null @@ -1,68 +0,0 @@ -.. _efr32_thunderboard: - -EFR32 Thunderboard-style boards -############################### - -Overview -******** - -There are a couple of very similar boards, which we categorize as -"Thunderboard-style boards". The name can be seen on some of Silicon Labs products -that use boards of this style, such as EFR32™ Blue Gecko Starter Kit, -a.k.a Thunderboard EFR32BG22. - -Those boards contains an MCU from the EFR32BG family built on ARM® Cortex®-M33F -processor with low power capabilities. - -For an example of such board, refer to the following site: - -- `Thunderboard EFR32BG22 Website`_ - -Currently the following devices are considered "Thunderboard-style": - -.. toctree:: - :maxdepth: 1 - - brd4184.rst - brd2602.rst - -Serial Port -=========== - -The SoCs used on these boards have two USARTs. -USART1 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The Thunderboard boards include `J-Link`_ serial and debug adapters built into the -board. The adapter provides: - -- A USB connection to a host computer running `J-Link software`_ or `Silicon Labs - Simplicity Commander`_. -- A physical UART connection which is relayed over a USB Serial port interface. - -For detailed instructions regarding flashing, refer to documentation of a specific -device. - -.. _Thunderboard EFR32BG22 Website: - https://www.silabs.com/development-tools/thunderboard/thunderboard-bg22-kit - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink - -.. _J-Link software: - https://www.segger.com/downloads/jlink - -.. _Silicon Labs Simplicity Commander: - https://www.silabs.com/developers/mcu-programming-options diff --git a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184.dtsi b/boards/silabs/efr32_thunderboard/efr32bg22_brd4184.dtsi deleted file mode 100644 index 7badab451585f..0000000000000 --- a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184.dtsi +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2021 Sateesh Kotapati - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "thunderboard.dtsi" - -/ { - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - sw0 = &button0; - spi-flash0 = &mx25r80; - spi0 = &usart0; - watchdog0 = &wdog0; - /* If enabled, MCUboot uses this for recovery mode entrance */ - mcuboot-led0 = &led0; - mcuboot-button0 = &button0; - }; - - chosen { - zephyr,code-partition = &slot0_partition; - }; -}; - -&flash0 { - partitions { - /* Reserve 48 KiB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x00000000 0x0000c000>; - read-only; - }; - - /* Reserve 224 KiB for the application in slot 0 */ - slot0_partition: partition@c000 { - label = "image-0"; - reg = <0x0000c000 0x00038000>; - }; - - /* Reserve 224 KiB for the application in slot 1 */ - slot1_partition: partition@44000 { - label = "image-1"; - reg = <0x00044000 0x00038000>; - }; - - /* Set 16 KiB of storage at the end of the 512 KiB of flash */ - storage_partition: partition@7c000 { - label = "storage"; - reg = <0x0007c000 0x00004000>; - }; - }; -}; - -&sw_imu_enable { - enable-gpios = <&gpiob GECKO_PIN(4) GPIO_ACTIVE_HIGH>; -}; diff --git a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184a.dts b/boards/silabs/efr32_thunderboard/efr32bg22_brd4184a.dts deleted file mode 100644 index 48a5997891192..0000000000000 --- a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184a.dts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2021 Sateesh Kotapati - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "efr32bg22_brd4184.dtsi" - -/ { - model = "Silicon Labs EFR32BG BRD4184A (aka Thunderboard BG22)"; - compatible = "silabs,efr32bg22c224f512im40", "silabs,efr32bg_brd4184a", - "silabs,efr32bg22"; -}; - -&sw_sensor_enable { - enable-gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_HIGH>; -}; - -&sw_mic_enable { - enable-gpios = <&gpioa GECKO_PIN(0) GPIO_ACTIVE_HIGH>; -}; diff --git a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184a.yaml b/boards/silabs/efr32_thunderboard/efr32bg22_brd4184a.yaml deleted file mode 100644 index 37bc5bed23934..0000000000000 --- a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184a.yaml +++ /dev/null @@ -1,21 +0,0 @@ -identifier: efr32bg22_brd4184a -name: EFR32BG22-BRD4184A -type: mcu -arch: arm -ram: 32 -flash: 512 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - counter - - gpio - - uart - - i2c - - spi -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184b.dts b/boards/silabs/efr32_thunderboard/efr32bg22_brd4184b.dts deleted file mode 100644 index 9dded5746bd67..0000000000000 --- a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184b.dts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2021 Sateesh Kotapati - * Copyright (c) 2023 Piotr Dymacz - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "efr32bg22_brd4184.dtsi" - -/ { - model = "Silicon Labs EFR32BG BRD4184B (aka Thunderboard BG22)"; - compatible = "silabs,efr32bg22c224f512im40", "silabs,efr32bg_brd4184b", - "silabs,efr32bg22"; -}; - -&button0 { - gpios = <&gpiob GECKO_PIN(3) GPIO_ACTIVE_LOW>; -}; - -&led0 { - gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_HIGH>; -}; - -&sw_sensor_enable { - enable-gpios = <&gpioc GECKO_PIN(6) GPIO_ACTIVE_HIGH>; -}; - -&sw_mic_enable { - enable-gpios = <&gpioc GECKO_PIN(7) GPIO_ACTIVE_HIGH>; -}; diff --git a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184b.yaml b/boards/silabs/efr32_thunderboard/efr32bg22_brd4184b.yaml deleted file mode 100644 index 40c6377a277fa..0000000000000 --- a/boards/silabs/efr32_thunderboard/efr32bg22_brd4184b.yaml +++ /dev/null @@ -1,21 +0,0 @@ -identifier: efr32bg22_brd4184b -name: EFR32BG22-BRD4184B -type: mcu -arch: arm -ram: 32 -flash: 512 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - counter - - gpio - - uart - - i2c - - spi -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.dts b/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.dts deleted file mode 100644 index b267cd8356bad..0000000000000 --- a/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.dts +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2023 Antmicro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include "thunderboard.dtsi" - -/ { - model = "Silicon Labs EFR32BG27C140F768IM40 Thunderboard-style board"; - compatible = "silabs,efr32bg27c140f768im40", "silabs,efr32bg27_brd2602a", - "silabs,efr32bg27"; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - sw0 = &button0; - spi-flash0 = &mx25r80; - spi0 = &usart0; - watchdog0 = &wdog0; - /* If enabled, MCUboot uses this for recovery mode entrance */ - mcuboot-led0 = &led0; - mcuboot-button0 = &button0; - }; - - chosen { - zephyr,code-partition = &slot0_partition; - }; -}; - -&flash0 { - partitions { - /* Reserve 48 KiB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x00000000 0x0000c000>; - read-only; - }; - - /* Reserve 328 KiB for the application in slot 0 */ - slot0_partition: partition@c000 { - label = "image-0"; - reg = <0x0000c000 0x00052000>; - }; - - /* Reserve 328 KiB for the application in slot 1 */ - slot1_partition: partition@5e000 { - label = "image-1"; - reg = <0x0005e000 0x00052000>; - }; - - /* Set 64 KiB of storage at the end of the 768 KiB of flash */ - storage_partition: partition@b0000 { - label = "storage"; - reg = <0x000b0000 0x00010000>; - }; - }; -}; - -&led0 { - gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_HIGH>; -}; - -&sw_sensor_enable { - enable-gpios = <&gpioc GECKO_PIN(6) GPIO_ACTIVE_HIGH>; -}; - - -&sw_mic_enable { - enable-gpios = <&gpioc GECKO_PIN(7) GPIO_ACTIVE_HIGH>; -}; - - -&sw_imu_enable { - enable-gpios = <&gpiob GECKO_PIN(4) GPIO_ACTIVE_HIGH>; -}; - -&button0 { - gpios = <&gpiob GECKO_PIN(3) GPIO_ACTIVE_LOW>; -}; diff --git a/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.yaml b/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.yaml deleted file mode 100644 index 844a48854d55e..0000000000000 --- a/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a.yaml +++ /dev/null @@ -1,19 +0,0 @@ -identifier: efr32bg27_brd2602a -name: EFR32BG27_BRD2602A -type: mcu -arch: arm -ram: 64 -flash: 768 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - counter - - gpio - - uart -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a_defconfig b/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a_defconfig deleted file mode 100644 index 50a14221ec99e..0000000000000 --- a/boards/silabs/efr32_thunderboard/efr32bg27_brd2602a_defconfig +++ /dev/null @@ -1,20 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -CONFIG_ARM_MPU=y -CONFIG_CONSOLE=y -CONFIG_UART_CONSOLE=y -CONFIG_SERIAL=y -CONFIG_GPIO=y -CONFIG_SOC_GECKO_EMU_DCDC=y -CONFIG_SOC_GECKO_EMU_DCDC_MODE_ON=y -CONFIG_HW_STACK_PROTECTION=y -CONFIG_PINCTRL=y - -# Used if SysTick is enabled, ignored for BURTC -# (BURTC uses TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) -CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=76800000 - -# Use BURTC as system clock source -CONFIG_GECKO_BURTC_TIMER=y -CONFIG_CMU_BURTCCLK_LFXO=y -CONFIG_SYS_CLOCK_TICKS_PER_SEC=1024 diff --git a/boards/silabs/efr32mg_sltb004a/Kconfig.defconfig b/boards/silabs/efr32mg_sltb004a/Kconfig.defconfig deleted file mode 100644 index 5dd6c6417a741..0000000000000 --- a/boards/silabs/efr32mg_sltb004a/Kconfig.defconfig +++ /dev/null @@ -1,14 +0,0 @@ -# EFR32MG SLTB004A board - -# Copyright (c) 2018, Diego Sueiro -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFR32MG_SLTB004A - -config CMU_HFXO_FREQ - default 40000000 - -config CMU_LFXO_FREQ - default 32768 - -endif # BOARD_EFR32MG_SLTB004A diff --git a/boards/silabs/efr32mg_sltb004a/Kconfig.efr32mg_sltb004a b/boards/silabs/efr32mg_sltb004a/Kconfig.efr32mg_sltb004a deleted file mode 100644 index 3f2245d372e3c..0000000000000 --- a/boards/silabs/efr32mg_sltb004a/Kconfig.efr32mg_sltb004a +++ /dev/null @@ -1,7 +0,0 @@ -# EFR32MG SLTB004A board - -# Copyright (c) 2018, Diego Sueiro -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFR32MG_SLTB004A - select SOC_PART_NUMBER_EFR32MG12P332F1024GL125 diff --git a/boards/silabs/efr32mg_sltb004a/board.yml b/boards/silabs/efr32mg_sltb004a/board.yml deleted file mode 100644 index cef6207cf03c5..0000000000000 --- a/boards/silabs/efr32mg_sltb004a/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: efr32mg_sltb004a - vendor: silabs - socs: - - name: efr32mg12p332f1024gl125 diff --git a/boards/silabs/efr32mg_sltb004a/doc/index.rst b/boards/silabs/efr32mg_sltb004a/doc/index.rst deleted file mode 100644 index ae06df99fc54a..0000000000000 --- a/boards/silabs/efr32mg_sltb004a/doc/index.rst +++ /dev/null @@ -1,220 +0,0 @@ -.. _efr32mg_sltb004a: - -EFR32MG-SLTB004A -################ - -Overview -******** - -The EFR32™ Mighty Gecko Starter Kit EFR32MG-SLTB004A (a.k.a Thunderboard -Sense 2) contains a MCU from the EFR32MG family built on ARM® Cortex®-M4F -processor with low power capabilities. - -.. image:: efr32mg_sltb004a.jpg - :align: center - :alt: EFR32MG-SLTB004A - -Hardware -******** - -- EFR32MG12 Mighty Gecko Wireless SoC with 38.4 MHz operating frequency -- ARM® Cortex® M4 core with 256 kB RAM and 1024 kB Flash -- Macronix ultra low power 8-Mbit SPI flash (MX25R8035F) -- 2.4 GHz ceramic antenna for wireless transmission -- Silicon Labs Si7021 relative humidity and temperature sensor -- Silicon Labs Si1133 UV index and ambient light sensor -- Silicon Labs Si7210 hall effect sensor -- Bosch Sensortec BMP280 barometric pressure sensor -- ams CCS811 indoor air quality gas sensor -- TDK InvenSense ICM-20648 6-axis inertial sensor -- TDK InvenSense ICS-43434 MEMS microphone -- Four high brightness RGB LEDs from Broadcom Limited (ASMT-YTB7-0AA02) -- One bi-color LED and two push buttons -- Power enable signals for fine grained power-control -- On-board SEGGER J-Link debugger for easy programming and debugging, which - includes a USB virtual COM port -- Mini Simplicity connector for access to energy profiling and advanced wireless - network debugging -- Breakout pads for GPIO access and connection to external hardware -- Reset button -- Automatic switch-over between USB and battery power -- CR2032 coin cell holder and external battery connector - -For more information about the EFR32MG SoC and Thunderboard Sense 2 -(EFR32MG-SLTB004A) board: - -- `EFR32MG Website`_ -- `EFR32MG Datasheet`_ -- `EFR32MG Reference Manual`_ -- `EFR32MG-SLTB004A Website`_ -- `EFR32MG-SLTB004A User Guide`_ -- `EFR32MG-SLTB004A Schematics`_ - -Supported Features -================== - -The efr32mg_sltb004a board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | rtcc | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial port-polling; | -| | | serial port-interrupt | -+-----------+------------+-------------------------------------+ -| I2C | on-chip | i2c port-polling | -+-----------+------------+-------------------------------------+ -| SPI(M) | on-chip | spi port-polling | -+-----------+------------+-------------------------------------+ -| WATCHDOG | on-chip | watchdog | -+-----------+------------+-------------------------------------+ -| TRNG | on-chip | true random number generator | -+-----------+------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a_defconfig` - -Other hardware features are currently not supported by the port. - -Connections and IOs -=================== - -The EFR32MG SoC has eight gpio controllers (PORTA, PORTB, PORTC, PORTD, -PORTF, PORTI, PORTJ and PORTK). - -In the following table, the column Name contains Pin names. For example, PE2 -means Pin number 2 on PORTE and #27 represents the location bitfield , as used -in the board's and microcontroller's datasheets and manuals. - -+------+-------------+-----------------------------------+ -| Name | Function | Usage | -+======+=============+===================================+ -| PD8 | GPIO | LED0 (RED) | -+------+-------------+-----------------------------------+ -| PD9 | GPIO | LED1 (GREEN) | -+------+-------------+-----------------------------------+ -| PD14 | GPIO | SW0 Push Button PB0 | -+------+-------------+-----------------------------------+ -| PD15 | GPIO | Push Button PB1 | -+------+-------------+-----------------------------------+ -| PA0 | UART_TX | UART TX Console VCOM_TX US0_TX #0 | -+------+-------------+-----------------------------------+ -| PA1 | UART_RX | UART RX Console VCOM_RX US0_RX #0 | -+------+-------------+-----------------------------------+ -| PF3 | UART_TX | EXP12_UART_TX LEU0_TX #27 | -+------+-------------+-----------------------------------+ -| PF4 | UART_RX | EXP14_UART_RX LEU0_RX #27 | -+------+-------------+-----------------------------------+ -| PC10 | I2C_SDA | EXP16_I2C_SDA I2C0_SDA #15 | -+------+-------------+-----------------------------------+ -| PC11 | I2C_SCL | EXP15_I2C_SCL I2C0_SCL #15 | -+------+-------------+-----------------------------------+ -| PB6 | I2C_SDA | CCS811_I2C_SDA I2C1_SDA #6 | -+------+-------------+-----------------------------------+ -| PB7 | I2C_SCL | CCS811_I2C_SCL I2C1_SCL #6 | -+------+-------------+-----------------------------------+ -| PK0 | SPI_MOSI | Flash MOSI US2_TX #29 | -+------+-------------+-----------------------------------+ -| PK2 | SPI_MISO | Flash MISO US2_RX #30 | -+------+-------------+-----------------------------------+ -| PF7 | SPI_SCLK | Flash SCLK US2_CLK #18 | -+------+-------------+-----------------------------------+ -| PK1 | SPI_CS | Flash Chip Select (GPIO) | -+------+-------------+-----------------------------------+ - -System Clock -============ - -The EFR32MG SoC is configured to use the 38.4 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFR32MG SoC has four USARTs and one Low Energy UARTs (LEUART with 9600 -maximum baudrate). USART0 is configured as the Zephyr console and is connected -to the On-Board J-Link Debugger that presents a virtual COM port for general -purpose application serial data transfer with this interface. - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The EFR32MG-SLTB004A includes an `J-Link`_ serial and debug adaptor built into the -board. The adaptor provides: - -- A USB connection to the host computer, which exposes a Mass Storage and a - USB Serial Port. -- A Serial Flash device, which implements the USB flash disk file storage. -- A physical UART connection which is relayed over interface USB Serial port. - -Flashing an application to EFR32-SLTB004A ------------------------------------------ - -The sample application :ref:`hello_world` is used for this example. -Build the Zephyr kernel and application: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32mg_sltb004a - :goals: build - -Connect the EFR32MG-SLTB004A to your host computer using the USB port and you -should see a USB connection which exposes a Mass Storage (TB004) and a -USB Serial Port. Copy the generated zephyr.bin in the SLTB004A drive. - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you should be able to see on the corresponding Serial Port -the following message: - -.. code-block:: console - - Hello World! arm - - -.. _EFR32MG-SLTB004A Website: - https://www.silabs.com/products/development-tools/thunderboard/thunderboard-sense-two-kit - -.. _EFR32MG-SLTB004A User Guide: - https://www.silabs.com/documents/public/user-guides/ug309-sltb004a-user-guide.pdf - -.. _EFR32MG-SLTB004A Schematics: - https://www.silabs.com/documents/public/schematic-files/BRD4166A-D00-schematic.pdf - -.. _EFR32MG Website: - https://www.silabs.com/products/wireless/mesh-networking/efr32mg-mighty-gecko-zigbee-thread-soc - -.. _EFR32MG Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32mg12-datasheet.pdf - -.. _EFR32MG Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efr32xg12-rm.pdf - -.. _J-Link: - https://www.segger.com/jlink-debug-probes.html - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.dts b/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.dts deleted file mode 100644 index 3819bd6ca94cf..0000000000000 --- a/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.dts +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2018 Diego Sueiro - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include - -/ { - model = "Silabs EFR32MG SLTB004A board (aka Thunderboard Sense 2)"; - compatible = "silabs,efr32mg_sltb004a", "silabs,efr32mg"; - - /* These aliases are provided for compatibility with samples */ - aliases { - led0 = &led0; - led1 = &led1; - pwm-led0 = &pwm_led0; - sw0 = &button0; - sw1 = &button1; - watchdog0 = &wdog0; - watchdog1 = &wdog1; - spi-flash0 = &mx25r80; - }; - - chosen { - zephyr,console = &usart0; - zephyr,shell-uart = &usart0; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - }; - - leds { - compatible = "gpio-leds"; - led0: led_0 { - gpios = <&gpiod 8 0>; - label = "LED 0"; - }; - led1: led_1 { - gpios = <&gpiod 9 0>; - label = "LED 1"; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - /* gpio flags need validation */ - gpios = <&gpiod 14 GPIO_ACTIVE_LOW>; - label = "User Push Button 0"; - zephyr,code = ; - }; - button1: button_1 { - /* gpio flags need validation */ - gpios = <&gpiod 15 GPIO_ACTIVE_LOW>; - label = "User Push Button 1"; - zephyr,code = ; - }; - }; - - pwmleds { - compatible = "pwm-leds"; - status = "okay"; - pwm_led0: pwm_led0 { - pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; - }; - }; -}; - -&cpu0 { - clock-frequency = <38400000>; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&usart2 { - compatible = "silabs,gecko-spi-usart"; - - #address-cells = <1>; - #size-cells = <0>; - - location-rx = ; - location-tx = ; - location-clk = ; - - cs-gpios = <&gpiok 1 GPIO_ACTIVE_LOW>; - - status = "okay"; - - mx25r80: mx25r8035f@0 { - compatible = "jedec,spi-nor"; - reg = <0>; - spi-max-frequency = <80000000>; - size = <0x800000>; - jedec-id = [c2 28 14]; - sfdp-bfp = [ - e5 20 f1 ff ff ff 7f 00 44 eb 08 6b 08 3b 04 bb - ee ff ff ff ff ff 00 ff ff ff 00 ff 0c 20 0f 52 - 10 d8 00 ff 23 72 f5 00 82 ed 04 b7 44 83 38 44 - 30 b0 30 b0 f7 c4 d5 5c 00 be 29 ff f0 d0 ff ff - ]; - }; -}; - -&leuart0 { - current-speed = <9600>; - location-rx = ; - location-tx = ; - status = "okay"; -}; - -&pinctrl { - i2c0_default: i2c0_default { - group1 { - psels = , - , - , - ; - }; - }; - - i2c1_default: i2c1_default { - group1 { - psels = , - , - , - ; - }; - }; -}; - -&i2c0 { - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&i2c1 { - /* This set selects for CCS811_I2C supporting CCS811 */ - pinctrl-0 = <&i2c1_default>; - pinctrl-names = "default"; - status = "okay"; - - ccs811: ccs811@5a { - compatible = "ams,ccs811"; - reg = <0x5a>; - supply-gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>; - irq-gpios = <&gpiof 13 GPIO_ACTIVE_LOW>; - wake-gpios = <&gpiof 15 GPIO_ACTIVE_LOW>; - }; - - /* This set selects for ENV_I2C supporting Si7021, Si11330, BMP280 */ - /* - location-sda = ; - location-scl = ; - */ - - /* This set selects for HALL_I2C supporting Si7210 */ - /* - location-sda = ; - location-scl = ; - */ -}; - -&rtcc0 { - prescaler = <1>; - status = "okay"; -}; - -&timer0 { - status = "okay"; - - pwm0: pwm { - status = "okay"; - pin-location = ; - prescaler = <1024>; - }; -}; - -&gpio { - location-swo = <0>; - status = "okay"; -}; - -&gpioa { - status = "okay"; -}; - -&gpiod { - status = "okay"; -}; - -&gpiof { - status = "okay"; -}; - -&gpiok { - status = "okay"; -}; - -&wdog0 { - status = "okay"; -}; - -&wdog1 { - status = "okay"; -}; - -&flash0 { - - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Set 6Kb of storage at the end of the 1024Kb of flash */ - storage_partition: partition@fe800 { - label = "storage"; - reg = <0x000fe800 0x00001800>; - }; - - }; -}; - -&trng0 { - status = "okay"; -}; diff --git a/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.yaml b/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.yaml deleted file mode 100644 index 3c8cbd773d01c..0000000000000 --- a/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a.yaml +++ /dev/null @@ -1,21 +0,0 @@ -identifier: efr32mg_sltb004a -name: EFR32MG-SLTB004A -type: mcu -arch: arm -ram: 256 -flash: 1024 -toolchain: - - zephyr - - gnuarmemb - - xtools -supported: - - gpio - - i2c - - nvs - - spi - - watchdog -testing: - ignore_tags: - - net - - bluetooth -vendor: silabs diff --git a/boards/silabs/efr32xg24_dk2601b/Kconfig b/boards/silabs/efr32xg24_dk2601b/Kconfig deleted file mode 100644 index c695033c2ff53..0000000000000 --- a/boards/silabs/efr32xg24_dk2601b/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -# EFR32XG24 DK2601B board - -# Copyright (c) 2022, Silicon Labs -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFR32XG24_DK2601B - -module = BOARD_EFR32MG24 -module-str = Board Control -source "subsys/logging/Kconfig.template.log_config" - -endif # BOARD_EFR32XG24_DK2601B diff --git a/boards/silabs/efr32xg24_dk2601b/Kconfig.defconfig b/boards/silabs/efr32xg24_dk2601b/Kconfig.defconfig deleted file mode 100644 index dbd2884e28ab7..0000000000000 --- a/boards/silabs/efr32xg24_dk2601b/Kconfig.defconfig +++ /dev/null @@ -1,49 +0,0 @@ -# EFR32XG24 DK2601B board - -# Copyright (c) 2021, Sateesh Kotapati -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_EFR32XG24_DK2601B - -config CMU_HFXO_FREQ - default 40000000 - -config CMU_LFXO_FREQ - default 32768 - -config FLASH_BASE_ADDRESS - hex - default 0x08000000 - -if SOC_GECKO_USE_RAIL - -config FPU - default y - -endif # SOC_GECKO_USE_RAIL - -if BT - -config FPU - default y - -config MINIMAL_LIBC_MALLOC_ARENA_SIZE - default 8192 - -config MAIN_STACK_SIZE - default 2304 - -choice BT_HCI_BUS_TYPE - default BT_SILABS_HCI -endchoice - -if SHELL - -config SHELL_STACK_SIZE - default 4096 - -endif # SHELL - -endif # BT - -endif # BOARD_EFR32XG24_DK2601B diff --git a/boards/silabs/efr32xg24_dk2601b/Kconfig.efr32xg24_dk2601b b/boards/silabs/efr32xg24_dk2601b/Kconfig.efr32xg24_dk2601b deleted file mode 100644 index 3826dc11b2a72..0000000000000 --- a/boards/silabs/efr32xg24_dk2601b/Kconfig.efr32xg24_dk2601b +++ /dev/null @@ -1,7 +0,0 @@ -# EFR32XG24 DK2601B board - -# Copyright (c) 2021, Sateesh Kotapati -# SPDX-License-Identifier: Apache-2.0 - -config BOARD_EFR32XG24_DK2601B - select SOC_PART_NUMBER_EFR32MG24B310F1536IM48 diff --git a/boards/silabs/efr32xg24_dk2601b/board.yml b/boards/silabs/efr32xg24_dk2601b/board.yml deleted file mode 100644 index d4efb7ba17892..0000000000000 --- a/boards/silabs/efr32xg24_dk2601b/board.yml +++ /dev/null @@ -1,5 +0,0 @@ -board: - name: efr32xg24_dk2601b - vendor: silabs - socs: - - name: efr32mg24b310f1536im48 diff --git a/boards/silabs/efr32xg24_dk2601b/doc/index.rst b/boards/silabs/efr32xg24_dk2601b/doc/index.rst deleted file mode 100644 index f6be0f828897d..0000000000000 --- a/boards/silabs/efr32xg24_dk2601b/doc/index.rst +++ /dev/null @@ -1,184 +0,0 @@ -.. _efr32mg24_dk2601b: - -xG24-DK2601B -########################### - -Overview -******** - -The EFR32MG24 Mighty Gecko Board dev kit contains -a Wireless System-On-Chip from the EFR32MG24 family built on an -ARM Cortex®-M33F processor with excellent low power capabilities. - -.. figure:: ./img/efr32xg24_dk2601b.jpg - :height: 260px - :align: center - :alt: SLWRB4180A Mighty Gecko Radio Board - - xG24-DK2601B (image courtesy of Silicon Labs) - -Hardware -******** - -- EFR32MG24B310F1536IM48-B Mighty Gecko SoC -- CPU core: ARM Cortex®-M33 with FPU -- Flash memory: 1536 kB -- RAM: 256 kB -- Transmit power: up to +20 dBm -- Operation frequency: 2.4 GHz -- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). -- On board sensors: - - - Silicon Labs Si7021 relative humidity & temperature sensor - - Silicon Labs Si7210 hall effect sensor - - 2x TDK InvenSense ICS-43434 MEMS microphones with I2S output - - TDK InvenSense ICM-20689 6-axis inertial measurement sensor - - Vishay VEML6035 ambient light sensor - - Bosch BMP384 pressure sensor with internal temperature sensor - -For more information about the EFR32MG24 SoC and BRD2601B board, refer to these -documents: - -- `EFR32MG24 Website`_ -- `EFR32MG24 Datasheet`_ -- `EFR32xG24 Reference Manual`_ -- `BRD2601B User Guide`_ - -Supported Features -================== - -The board configuration supports the following hardware features: - -+-----------+------------+-------------------------------------+ -| Interface | Controller | Driver/Component | -+===========+============+=====================================+ -| MPU | on-chip | memory protection unit | -+-----------+------------+-------------------------------------+ -| NVIC | on-chip | nested vector interrupt controller | -+-----------+------------+-------------------------------------+ -| SYSTICK | on-chip | systick | -+-----------+------------+-------------------------------------+ -| COUNTER | on-chip | stimer | -+-----------+------------+-------------------------------------+ -| FLASH | on-chip | flash memory | -+-----------+------------+-------------------------------------+ -| GPIO | on-chip | gpio | -+-----------+------------+-------------------------------------+ -| UART | on-chip | serial | -+-----------+------------+-------------------------------------+ -| TRNG | on-chip | semailbox | -+-----------+------------+-------------------------------------+ -| WATCHDOG | on-chip | watchdog | -+-----------+------------+-------------------------------------+ -| I2C(M/S) | on-chip | i2c | -+-----------+------------+-------------------------------------+ -| RADIO | on-chip | bluetooth | -+-----------+------------+-------------------------------------+ - -Other hardware features are currently not supported by the port. - -Connections and IOs -=================== - -In the following table, the column **Name** contains Pin names. For example, PA2 -means Pin number 2 on PORTA, as used in the board's datasheets and manuals. - -+-------+-------------+-------------------------------------+ -| Name | Function | Usage | -+=======+=============+=====================================+ -| PA4 | GPIO | LED0 | -+-------+-------------+-------------------------------------+ -| PB0 | GPIO | LED1 | -+-------+-------------+-------------------------------------+ -| PB2 | GPIO | Push Button 0 | -+-------+-------------+-------------------------------------+ -| PB3 | GPIO | Push Button 1 | -+-------+-------------+-------------------------------------+ -| PA5 | USART0_TX | UART Console EFM_BC_TX US0_TX | -+-------+-------------+-------------------------------------+ -| PA6 | USART0_RX | UART Console EFM_BC_RX US0_RX | -+-------+-------------+-------------------------------------+ - -The default configuration can be found in -:zephyr_file:`boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b_defconfig` - -System Clock -============ - -The EFR32MG24 SoC is configured to use the 39 MHz external oscillator on the -board. - -Serial Port -=========== - -The EFR32MG24 SoC has one USART and two EUSARTs. -USART0 is connected to the board controller and is used for the console. - -Programming and Debugging -************************* - -.. note:: - Before using the kit the first time, you should update the J-Link firmware - from `J-Link-Downloads`_ - -Flashing -======== - -The sample application :ref:`hello_world` is used for this example. -Build the Zephyr kernel and application: - -.. zephyr-app-commands:: - :zephyr-app: samples/hello_world - :board: efr32xg24_dk2601b - :goals: build - -Connect the efr32xg24_dk2601b to your host computer using the USB port and you -should see a USB connection. - -Open a serial terminal (minicom, putty, etc.) with the following settings: - -- Speed: 115200 -- Data: 8 bits -- Parity: None -- Stop bits: 1 - -Reset the board and you'll see the following message on the corresponding serial port -terminal session: - -.. code-block:: console - - Hello World! efr32xg24_dk2601b - -Bluetooth -========= - -To use the BLE function, run the command below to retrieve necessary binary -blobs from the SiLabs HAL repository. - -.. code-block:: console - - west blobs fetch silabs - -Then build the Zephyr kernel and a Bluetooth sample with the following -command. The :ref:`bluetooth-observer-sample` sample application is used in -this example. - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/observer - :board: efr32xg24_dk2601b - :goals: build - -.. _EFR32MG24 Website: - https://www.silabs.com/wireless/zigbee/efr32mg24-series-2-socs# - -.. _EFR32MG24 Datasheet: - https://www.silabs.com/documents/public/data-sheets/efr32mg24-datasheet.pdf - -.. _EFR32xG24 Reference Manual: - https://www.silabs.com/documents/public/reference-manuals/efr32xg24-rm.pdf - -.. _BRD2601B User Guide: - https://www.silabs.com/documents/public/user-guides/ug524-brd2601b-user-guide.pdf - -.. _J-Link-Downloads: - https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts b/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts deleted file mode 100644 index 3617191ed5b2c..0000000000000 --- a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.dts +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2020 TriaGnoSys GmbH - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/dts-v1/; -#include -#include -#include - -/ { - model = "Silicon Labs BRD2601B (Mighty Gecko Radio Board)"; - compatible = "silabs,efr32mg24_brd2601b", "silabs,efr32mg24"; - - chosen { - zephyr,console = &usart0; - zephyr,shell-uart = &usart0; - zephyr,sram = &sram0; - zephyr,flash = &flash0; - zephyr,code-partition = &slot0_partition; - }; - - aliases { - led0 = &red_led; - led1 = &green_led; - led2 = &blue_led; - sw0 = &button0; - sw1 = &button1; - }; - - leds { - compatible = "gpio-leds"; - red_led: led_2 { - gpios = <&gpiod GECKO_PIN(2) GPIO_ACTIVE_LOW>; - }; - green_led: led_0 { - gpios = <&gpioa GECKO_PIN(4) GPIO_ACTIVE_LOW>; - }; - blue_led: led_1 { - gpios = <&gpiob GECKO_PIN(0) GPIO_ACTIVE_LOW>; - }; - }; - - buttons { - compatible = "gpio-keys"; - button0: button_0 { - gpios = <&gpiob GECKO_PIN(2) GPIO_ACTIVE_LOW>; - zephyr,code = ; - }; - button1: button_1 { - gpios = <&gpiob GECKO_PIN(3) GPIO_ACTIVE_LOW>; - zephyr,code = ; - }; - }; - - wake_up_trigger: gpio-wake-up { - compatible = "silabs,gecko-wake-up-trigger"; - gpios = <&gpioa GECKO_PIN(5) GPIO_ACTIVE_LOW>; - }; - - sensor_enable: gpio_switch_0 { - compatible = "regulator-fixed"; - regulator-name = "sensor_enable"; - enable-gpios = <&gpioc GECKO_PIN(9) GPIO_ACTIVE_HIGH>; - regulator-boot-on; - }; -}; - -&cpu0 { - clock-frequency = <78000000>; -}; - -&usart0 { - current-speed = <115200>; - pinctrl-0 = <&usart0_default>; - pinctrl-names = "default"; - status = "okay"; -}; - -&i2c0 { - pinctrl-0 = <&i2c0_default>; - pinctrl-names = "default"; - status = "okay"; - - veml6035: veml6035@29 { - compatible = "vishay,veml7700"; - reg = <0x29>; - status = "okay"; - }; - - si7210: si7210@30 { - compatible = "silabs,si7210"; - reg = <0x30>; - status = "okay"; - }; - - si7021: si7021@40 { - compatible = "silabs,si7006"; - reg = <0x40>; - status = "okay"; - }; -}; - -&gpio { - status = "okay"; -}; - -&gpioa { - status = "okay"; -}; - -&gpiob { - status = "okay"; -}; - -&gpioc { - status = "okay"; -}; - -&gpiod { - status = "okay"; -}; - -&wdog0 { - status = "okay"; -}; - -&se { - status = "okay"; -}; - -&flash0 { - partitions { - compatible = "fixed-partitions"; - #address-cells = <1>; - #size-cells = <1>; - - /* Reserve 48 kB for the bootloader */ - boot_partition: partition@0 { - label = "mcuboot"; - reg = <0x0 0x0000c000>; - read-only; - }; - - /* Reserve 464 kB for the application in slot 0 */ - slot0_partition: partition@c000 { - label = "storage"; - reg = <0x0000c000 0x00074000>; - }; - - /* Reserve 464 kB for the application in slot 1 */ - slot1_partition: partition@80000 { - label = "image-0"; - reg = <0x00080000 0x00074000>; - }; - - /* Reserve 32 kB for the scratch partition */ - scratch_partition: partition@f4000 { - label = "image-1"; - reg = <0x000f4000 0x00008000>; - }; - - /* Set 528Kb of storage at the end of the 1024Kb of flash */ - storage_partition: partition@fc000 { - label = "image-scratch"; - reg = <0x000fc000 0x00084000>; - }; - }; -}; - -&adc0 { - status = "okay"; -}; diff --git a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml b/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml deleted file mode 100644 index 2b803cca1abb0..0000000000000 --- a/boards/silabs/efr32xg24_dk2601b/efr32xg24_dk2601b.yaml +++ /dev/null @@ -1,19 +0,0 @@ -identifier: efr32xg24_dk2601b -name: BRD4601B -type: mcu -arch: arm -ram: 256 -flash: 1536 -toolchain: - - zephyr - - gnuarmemb -supported: - - gpio - - uart -testing: - ignore_tags: - - net - - bluetooth - - pm - - hwinfo -vendor: silabs diff --git a/boards/silabs/index.rst b/boards/silabs/index.rst index 20a5d34136fc0..d4597d226ce17 100644 --- a/boards/silabs/index.rst +++ b/boards/silabs/index.rst @@ -4,7 +4,26 @@ Silicon Labs ############ .. toctree:: - :maxdepth: 1 + :maxdepth: 2 + :titlesonly: :glob: - **/* + */* + +Silicon Labs development hardware is represented in Zephyr by mapping +Silicon Labs *kits* to Zephyr *boards*. The name used is the orderable product +number (OPN) of the kit, as found on the packaging and on the Silicon Labs +website. The board name in Zephyr is created by normalizing the OPN to lowercase +and replacing dashes with underscores. + +You may find multiple other number and letter sequences silk-screened or lasered +onto Silicon Labs boards, including a PCB* number and a BRD* number. In most +cases, the digits of these sequences correspond to the numerical part of the kit +OPN. For instance, the kit ``xg24_dk2601b``, which is a Dev Kit for the +EFR32xG24 SoC, uses board BRD2601B, which again uses PCB2601A. It is possible to +use the ``west boards`` command to search for board names if you have a PCB and +you don't know what board name to use: + + .. code-block:: console + + west boards -n 2601 diff --git a/boards/silabs/radio_boards/common/efr32-series1-common-pinctrl.dtsi b/boards/silabs/radio_boards/common/efr32-series1-common-pinctrl.dtsi new file mode 100644 index 0000000000000..bb8f7802e6adc --- /dev/null +++ b/boards/silabs/radio_boards/common/efr32-series1-common-pinctrl.dtsi @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2023 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + /* configuration for usart0 device, default state - operating as UART */ + usart0_default: usart0_default { + group1 { + psels = , + , + , + ; + }; + }; + + usart1_default: usart1_default { + group1 { + psels = , + , + , + , + , + ; + }; + }; + + usart2_default: usart2_default { + group1 { + psels = , + , + , + , + , + ; + }; + }; +}; diff --git a/boards/silabs/radio_boards/common/efr32-series1-common.dtsi b/boards/silabs/radio_boards/common/efr32-series1-common.dtsi new file mode 100644 index 0000000000000..8ff361eccaaec --- /dev/null +++ b/boards/silabs/radio_boards/common/efr32-series1-common.dtsi @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2020 Piotr Mienkowski + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "efr32-series1-common-pinctrl.dtsi" + +/ { + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpiof 4 0>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpiof 5 0>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + /* gpio flags need validation */ + gpios = <&gpiof 6 GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + /* gpio flags need validation */ + gpios = <&gpiof 7 GPIO_ACTIVE_LOW>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; + +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usart1 { + compatible = "silabs,gecko-spi-usart"; + + #address-cells = <1>; + #size-cells = <0>; + + pinctrl-0 = <&usart1_default>; + pinctrl-names = "default"; + + cs-gpios = <&gpioa 4 GPIO_ACTIVE_LOW>; + + status = "okay"; + + mx25r80: mx25r8035f@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-max-frequency = <33000000>; + size = <0x800000>; + jedec-id = [c2 28 14]; + }; +}; + +&rtcc0 { + prescaler = <1>; + status = "okay"; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpioa { + status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&gpiof { + status = "okay"; +}; + +&wdog0 { + status = "okay"; +}; diff --git a/boards/silabs/radio_boards/index.rst b/boards/silabs/radio_boards/index.rst new file mode 100644 index 0000000000000..a4928294fada8 --- /dev/null +++ b/boards/silabs/radio_boards/index.rst @@ -0,0 +1,60 @@ +.. _silabs_radio_boards: + +Radio Boards +############ + +.. toctree:: + :maxdepth: 1 + :titlesonly: + :glob: + + **/* + +Overview +******** + +Radio Boards are used together with a Wireless Mainboard, which is a +development platform for application development and debugging of wireless +products. + +There are two main variants of the Mainboard: + +- Wireless Starter Kit Mainboard (board BRD4001A, available standalone as SLWMB4001A) +- Wireless Pro Kit Mainboard (board BRD4002A, available standalone as Si-MB4002A) + +The Wireless Pro Kit Mainboard is a strict superset of the Wireless Starter Kit, +the two boards are pin compatible for all shared functionality. + +Wireless Starter Kits and Wireless Pro Kits are kits that bundle one or more +Radio Boards with one or more Mainboards. + +In Zephyr, Radio Boards are used as board targets, irrespective of whether the +board was acquired standalone or as part of a Starter Kit or Pro Kit. The kit +name of the standalone Radio Board is used as the board target. + +Hardware +******** + +Wireless Starter Kit Mainboard: + +- Advanced Energy Monitor providing real-time information about energy consumption at up to 10 ksps +- Packet Trace Interface +- Virtual COM port +- On-board Segger J-Link debugger with USB and Ethernet interfaces +- Ultra-low power 128x128 pixel memory LCD +- 2 user buttons and 2 LEDs +- 20 pin 2.54mm expansion header +- Si7021 Relative Humidity and Temperature Sensor +- Breakout pads for Wireless SoC I/O + +Wireless Pro Kit Mainboard: + +- Advanced Energy Monitor providing real-time information about energy consumption at up to 100 ksps +- Packet Trace Interface +- Virtual COM port +- On-board Segger J-Link debugger with USB and Ethernet interfaces +- Ultra-low power 128x128 pixel memory LCD +- 2 user buttons, joystick and 2 LEDs +- 20 pin 2.54mm expansion header +- Si7021 Relative Humidity and Temperature Sensor +- Breakout pads for Wireless SoC I/O diff --git a/boards/silabs/radio_boards/slwrb4104a/Kconfig.defconfig b/boards/silabs/radio_boards/slwrb4104a/Kconfig.defconfig new file mode 100644 index 0000000000000..0a5a0795b5965 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4104a/Kconfig.defconfig @@ -0,0 +1,44 @@ +# EFR32 radio board + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLWRB4104A + +config CMU_HFXO_FREQ + default 38400000 + +config CMU_LFXO_FREQ + default 32768 + +config FLASH_BASE_ADDRESS + hex + default 0x0 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +if SOC_GECKO_USE_RAIL + +config FPU + default n + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config MINIMAL_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 3072 if PM + default 2304 + +endif # BT + +endif # BOARD_SLWRB4104A diff --git a/boards/silabs/radio_boards/slwrb4104a/Kconfig.slwrb4104a b/boards/silabs/radio_boards/slwrb4104a/Kconfig.slwrb4104a new file mode 100644 index 0000000000000..179b7f02c0a3c --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4104a/Kconfig.slwrb4104a @@ -0,0 +1,8 @@ +# EFR32BG13 BRD4104A + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLWRB4104A + select SOC_PART_NUMBER_EFR32BG13P632F512GM48 diff --git a/boards/silabs/radio_boards/slwrb4104a/board.cmake b/boards/silabs/radio_boards/slwrb4104a/board.cmake new file mode 100644 index 0000000000000..cf1d8ee0e7505 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4104a/board.cmake @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd) +board_runner_args(jlink "--device=EFR32BG13PxxxF512") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/silabs/radio_boards/slwrb4104a/board.yml b/boards/silabs/radio_boards/slwrb4104a/board.yml new file mode 100644 index 0000000000000..5ca377b2c8fbd --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4104a/board.yml @@ -0,0 +1,4 @@ +boards: + - name: slwrb4104a + socs: + - name: efr32bg13p632f512gm48 diff --git a/boards/silabs/efr32_radio/doc/efr32bg13-slwrb4104a.jpg b/boards/silabs/radio_boards/slwrb4104a/doc/efr32bg13-slwrb4104a.jpg similarity index 100% rename from boards/silabs/efr32_radio/doc/efr32bg13-slwrb4104a.jpg rename to boards/silabs/radio_boards/slwrb4104a/doc/efr32bg13-slwrb4104a.jpg diff --git a/boards/silabs/radio_boards/slwrb4104a/doc/index.rst b/boards/silabs/radio_boards/slwrb4104a/doc/index.rst new file mode 100644 index 0000000000000..6522489e79ac6 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4104a/doc/index.rst @@ -0,0 +1,171 @@ +.. _slwrb4104a: + +EFR32BG13 2.4 GHz 10 dBm (SLWRB4104A) +##################################### + +Overview +******** + +The EFR32BG13 Blue Gecko Bluetooth® Low Energy Radio Board is one of the two +radio boards delivered with `SLWSTK6020B Bluetooth SoC Starter Kit`_. It +contains a Wireless System-On-Chip from the EFR32BG13 family built on an +ARM Cortex®-M4F processor with excellent low power capabilities. + +.. figure:: efr32bg13-slwrb4104a.jpg + :align: center + :alt: SLWRB4104A Blue Gecko Bluetooth® Low Energy Radio Board + + SLWRB4104A (image courtesy of Silicon Labs) + +The BRD4104A a.k.a. SLWRB4104A radio board plugs into the Wireless Starter Kit +Mainboard BRD4001A and is supported as one of :ref:`silabs_radio_boards`. + +Hardware +******** + +- EFR32BG13P632F512GM48 Blue Gecko SoC +- CPU core: ARM Cortex®-M4 with FPU +- Flash memory: 512 kB +- RAM: 64 kB +- Transmit power: up to +10 dBm +- Operation frequency: 2.4 GHz +- 8Mbit SPI NOR Flash +- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). + +For more information about the EFR32BG13 SoC and BRD4104A board, refer to these +documents: + +- `EFR32BG13 Website`_ +- `EFR32BG13 Datasheet`_ +- `EFR32xG13 Reference Manual`_ +- `SLWSTK6020B Bluetooth SoC Starter Kit`_ +- `BRD4104A User Guide`_ +- `BRD4104A Reference Manual`_ +- `EFR32BG13-BRD4104A Schematics`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| SPI(M) | on-chip | spi port-polling | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/radio_boards/slwrb4104a/slwrb4104a_defconfig` + +Connections and IOs +=================== + +In the following table, the column **Pin** contains Pin names. For example, PA2 +means Pin number 2 on PORTA, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Pin | Function | Usage | ++=======+=============+=====================================+ +| PF4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PF5 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PF6 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PF7 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PA5 | GPIO | Board Controller Enable | +| | | VCOM_ENABLE | ++-------+-------------+-------------------------------------+ +| PA0 | USART0_TX | UART Console VCOM_TX US0_TX #0 | ++-------+-------------+-------------------------------------+ +| PA1 | USART0_RX | UART Console VCOM_RX US0_RX #0 | ++-------+-------------+-------------------------------------+ +| PC6 | SPI_MOSI | Flash MOSI US1_TX #11 | ++-------+-------------+-------------------------------------+ +| PC7 | SPI_MISO | Flash MISO US1_RX #11 | ++-------+-------------+-------------------------------------+ +| PC8 | SPI_SCLK | Flash SCLK US1_CLK #11 | ++-------+-------------+-------------------------------------+ +| PA4 | SPI_CS | Flash Chip Select (GPIO) | ++-------+-------------+-------------------------------------+ + +System Clock +============ + +The EFR32BG13P SoC is configured to use the 38.4 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32BG13P SoC has three USARTs and one Low Energy UARTs (LEUART). +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +Flashing +======== + +Connect the BRD4001A board with a mounted BRD4104A radio module to your host +computer using the USB port. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slwrb4104a + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should see the following message in the terminal: + +.. code-block:: console + + Hello World! slwrb4161a + + +.. _EFR32BG13 Website: + https://www.silabs.com/wireless/bluetooth/efr32bg13-series-1-socs + +.. _EFR32BG13 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32bg13-datasheet.pdf + +.. _EFR32xG13 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg13-rm.pdf + +.. _SLWSTK6020B Bluetooth SoC Starter Kit: + https://www.silabs.com/products/development-tools/wireless/bluetooth/blue-gecko-bluetooth-low-energy-soc-starter-kit + +.. _BRD4104A User Guide: + https://www.silabs.com/documents/public/user-guides/ug279-brd4104a-user-guide.pdf + +.. _BRD4104A Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/brd4104a-rm.pdf + +.. _EFR32BG13-BRD4104A Schematics: + https://www.silabs.com/documents/public/schematic-files/BRD4104A-A00-schematic.pdf diff --git a/boards/silabs/radio_boards/slwrb4104a/pre_dt_board.cmake b/boards/silabs/radio_boards/slwrb4104a/pre_dt_board.cmake new file mode 100644 index 0000000000000..beb76b85552d1 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4104a/pre_dt_board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# SPI is implemented via usart so node name isn't spi@... +list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") diff --git a/boards/silabs/radio_boards/slwrb4104a/slwrb4104a.dts b/boards/silabs/radio_boards/slwrb4104a/slwrb4104a.dts new file mode 100644 index 0000000000000..a2a6b76df675d --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4104a/slwrb4104a.dts @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020 Piotr Mienkowski + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "../common/efr32-series1-common.dtsi" + +/ { + model = "Silicon Labs BRD4104A (Blue Gecko 13 Radio Board)"; + compatible = "silabs,slwrb4104a", "silabs,efr32bg13p"; + + chosen { + zephyr,bt-hci = &bt_hci_silabs; + }; +}; + +&cpu0 { + clock-frequency = <38400000>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 32 kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x00008000>; + read-only; + }; + + /* Reserve 220 kB for the application in slot 0 */ + slot0_partition: partition@8000 { + label = "image-0"; + reg = <0x00008000 0x00037000>; + }; + + /* Reserve 220 kB for the application in slot 1 */ + slot1_partition: partition@3f000 { + label = "image-1"; + reg = <0x0003f000 0x00037000>; + }; + + /* Reserve 32 kB for the scratch partition */ + scratch_partition: partition@76000 { + label = "image-scratch"; + reg = <0x00076000 0x00008000>; + }; + + /* Set 8Kb of storage at the end of the 512KB of flash */ + storage_partition: partition@7e000 { + label = "storage"; + reg = <0x0007e000 0x00002000>; + }; + + }; +}; + +&bt_hci_silabs { + status = "okay"; +}; diff --git a/boards/silabs/radio_boards/slwrb4104a/slwrb4104a.yaml b/boards/silabs/radio_boards/slwrb4104a/slwrb4104a.yaml new file mode 100644 index 0000000000000..926a55f315044 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4104a/slwrb4104a.yaml @@ -0,0 +1,22 @@ +identifier: slwrb4104a +name: EFR32BG13 2.4 GHz 10 dBm Radio Board (SLWRB4104A) +type: mcu +arch: arm +ram: 64 +flash: 512 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - counter + - gpio + - nvs + - spi + - uart + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32fg13p233f512gm48_defconfig b/boards/silabs/radio_boards/slwrb4104a/slwrb4104a_defconfig similarity index 100% rename from boards/silabs/efr32_radio/efr32_radio_efr32fg13p233f512gm48_defconfig rename to boards/silabs/radio_boards/slwrb4104a/slwrb4104a_defconfig diff --git a/boards/silabs/efr32_radio/support/openocd.cfg b/boards/silabs/radio_boards/slwrb4104a/support/openocd.cfg similarity index 100% rename from boards/silabs/efr32_radio/support/openocd.cfg rename to boards/silabs/radio_boards/slwrb4104a/support/openocd.cfg diff --git a/boards/silabs/radio_boards/slwrb4161a/Kconfig.defconfig b/boards/silabs/radio_boards/slwrb4161a/Kconfig.defconfig new file mode 100644 index 0000000000000..1027e26c75c97 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4161a/Kconfig.defconfig @@ -0,0 +1,44 @@ +# EFR32 radio board + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLWRB4161A + +config CMU_HFXO_FREQ + default 38400000 + +config CMU_LFXO_FREQ + default 32768 + +config FLASH_BASE_ADDRESS + hex + default 0x0 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +if SOC_GECKO_USE_RAIL + +config FPU + default n + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config MINIMAL_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 3072 if PM + default 2304 + +endif # BT + +endif # BOARD_SLWRB4161A diff --git a/boards/silabs/radio_boards/slwrb4161a/Kconfig.slwrb4161a b/boards/silabs/radio_boards/slwrb4161a/Kconfig.slwrb4161a new file mode 100644 index 0000000000000..67291857e9f90 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4161a/Kconfig.slwrb4161a @@ -0,0 +1,8 @@ +# EFR32MG12 BRD4161A + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLWRB4161A + select SOC_PART_NUMBER_EFR32MG12P432F1024GL125 diff --git a/boards/silabs/radio_boards/slwrb4161a/board.cmake b/boards/silabs/radio_boards/slwrb4161a/board.cmake new file mode 100644 index 0000000000000..be43109892de5 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4161a/board.cmake @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd) +board_runner_args(jlink "--device=EFR32MG12PxxxF1024") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/silabs/radio_boards/slwrb4161a/board.yml b/boards/silabs/radio_boards/slwrb4161a/board.yml new file mode 100644 index 0000000000000..a05542a40d819 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4161a/board.yml @@ -0,0 +1,4 @@ +boards: + - name: slwrb4161a + socs: + - name: efr32mg12p432f1024gl125 diff --git a/boards/silabs/efr32_radio/doc/efr32mg12-slwrb4161a.jpeg b/boards/silabs/radio_boards/slwrb4161a/doc/efr32mg12-slwrb4161a.jpeg similarity index 100% rename from boards/silabs/efr32_radio/doc/efr32mg12-slwrb4161a.jpeg rename to boards/silabs/radio_boards/slwrb4161a/doc/efr32mg12-slwrb4161a.jpeg diff --git a/boards/silabs/radio_boards/slwrb4161a/doc/index.rst b/boards/silabs/radio_boards/slwrb4161a/doc/index.rst new file mode 100644 index 0000000000000..1f09e7d551c77 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4161a/doc/index.rst @@ -0,0 +1,156 @@ +.. _slwrb4161a: + +EFR32MG12 2.4 GHz 19 dBm (SLWRB4161A) +##################################### + +Overview +******** + +The EFR32MG12 Mighty Gecko Radio Board contains a Wireless System-On-Chip +from the EFR32MG12 family built on an ARM Cortex®-M4F processor with excellent +low power capabilities. + +.. figure:: efr32mg12-slwrb4161a.jpeg + :align: center + :alt: SLWRB4161A Mighty Gecko Radio Board + + SLWRB4161A (image courtesy of Silicon Labs) + +The BRD4161A a.k.a. SLWRB4161A radio board plugs into the Wireless Starter Kit +Mainboard BRD4001A and is supported as one of :ref:`silabs_radio_boards`. + +Hardware +******** + +- EFR32MG12P432F1024GL125 Mighty Gecko SoC +- CPU core: ARM Cortex®-M4 with FPU +- Flash memory: 1024 kB +- RAM: 256 kB +- Transmit power: up to +19 dBm +- Operation frequency: 2.4 GHz and Sub-Ghz +- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). + +For more information about the EFR32MG12 SoC and BRD4170A board, refer to these +documents: + +- `EFR32MG12 Website`_ +- `EFR32MG12 Datasheet`_ +- `EFR32xG12 Reference Manual`_ +- `BRD4161A User Guide`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| SPI(M) | on-chip | spi port-polling | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/radio_boards/slwrb4161a/slwrb4161a_defconfig` + +Connections and IOs +=================== + +In the following table, the column **Pin** contains Pin names. For example, PA2 +means Pin number 2 on PORTA, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Pin | Function | Usage | ++=======+=============+=====================================+ +| PF4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PF5 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PF6 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PF7 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PA5 | GPIO | Board Controller Enable VCOM_ENABLE | ++-------+-------------+-------------------------------------+ +| PA0 | USART0_TX | UART Console VCOM_TX US0_TX #0 | ++-------+-------------+-------------------------------------+ +| PA1 | USART0_RX | UART Console VCOM_RX US0_RX #0 | ++-------+-------------+-------------------------------------+ +| PC6 | SPI_MOSI | Flash MOSI US1_TX #11 | ++-------+-------------+-------------------------------------+ +| PC7 | SPI_MISO | Flash MISO US1_RX #11 | ++-------+-------------+-------------------------------------+ +| PC8 | SPI_SCLK | Flash SCLK US1_CLK #11 | ++-------+-------------+-------------------------------------+ +| PA4 | SPI_CS | Flash Chip Select (GPIO) | ++-------+-------------+-------------------------------------+ + +System Clock +============ + +The EFR32MG12P SoC is configured to use the 38.4 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32MG12P SoC has four USARTs and one Low Energy UARTs (LEUART). +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +Flashing +======== + +Connect the BRD4001A board with a mounted BRD4161A radio module to your host +computer using the USB port. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slwrb4161a + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should see the following message in the terminal: + +.. code-block:: console + + Hello World! slwrb4161a + + +.. _EFR32MG12 Website: + https://www.silabs.com/wireless/zigbee/efr32mg12-series-1-socs + +.. _EFR32MG12 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32mg12-datasheet.pdf + +.. _EFR32xG12 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg12-rm.pdf + +.. _BRD4161A User Guide: + https://www.silabs.com/documents/public/user-guides/ug260-brd4161a-user-guide.pdf diff --git a/boards/silabs/radio_boards/slwrb4161a/pre_dt_board.cmake b/boards/silabs/radio_boards/slwrb4161a/pre_dt_board.cmake new file mode 100644 index 0000000000000..beb76b85552d1 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4161a/pre_dt_board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# SPI is implemented via usart so node name isn't spi@... +list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") diff --git a/boards/silabs/radio_boards/slwrb4161a/slwrb4161a.dts b/boards/silabs/radio_boards/slwrb4161a/slwrb4161a.dts new file mode 100644 index 0000000000000..90804fbba0564 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4161a/slwrb4161a.dts @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020 Piotr Mienkowski + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "../common/efr32-series1-common.dtsi" + +/ { + model = "Silicon Labs BRD4161A (Mighty Gecko 12 Radio Board)"; + compatible = "silabs,slwrb4161a", "silabs,efr32mg12p"; + + chosen { + zephyr,bt-hci = &bt_hci_silabs; + }; +}; + +&cpu0 { + clock-frequency = <38400000>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 32 kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x00008000>; + read-only; + }; + + /* Reserve 220 kB for the application in slot 0 */ + slot0_partition: partition@8000 { + label = "image-0"; + reg = <0x00008000 0x00037000>; + }; + + /* Reserve 220 kB for the application in slot 1 */ + slot1_partition: partition@3f000 { + label = "image-1"; + reg = <0x0003f000 0x00037000>; + }; + + /* Reserve 32 kB for the scratch partition */ + scratch_partition: partition@76000 { + label = "image-scratch"; + reg = <0x00076000 0x00008000>; + }; + + /* Set 8Kb of storage at the end of the 512KB of flash */ + storage_partition: partition@7e000 { + label = "storage"; + reg = <0x0007e000 0x00002000>; + }; + + }; +}; + +&pinctrl { + i2c0_default: i2c0_default { + group1 { + psels = , + , + , + ; + }; + }; +}; + +&usart2 { + compatible = "silabs,gecko-spi-usart"; + #address-cells = <1>; + #size-cells = <0>; + pinctrl-0 = <&usart2_default>; + pinctrl-names = "default"; + cs-gpios = <&gpioa 9 GPIO_ACTIVE_LOW>; + status = "okay"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; + + si7021: si7021@40 { + compatible = "silabs,si7006"; + reg = <0x40>; + status = "okay"; + }; +}; + +&bt_hci_silabs { + status = "okay"; +}; diff --git a/boards/silabs/radio_boards/slwrb4161a/slwrb4161a.yaml b/boards/silabs/radio_boards/slwrb4161a/slwrb4161a.yaml new file mode 100644 index 0000000000000..6f46897683e9e --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4161a/slwrb4161a.yaml @@ -0,0 +1,21 @@ +identifier: slwrb4161a +name: EFR32MG12 2.4 GHz 19 dBm Radio Board (SLWRB4161A) +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb +supported: + - counter + - gpio + - nvs + - spi + - uart + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48_defconfig b/boards/silabs/radio_boards/slwrb4161a/slwrb4161a_defconfig similarity index 100% rename from boards/silabs/efr32_radio/efr32_radio_efr32fg1p133f256gm48_defconfig rename to boards/silabs/radio_boards/slwrb4161a/slwrb4161a_defconfig diff --git a/boards/silabs/radio_boards/slwrb4161a/support/openocd.cfg b/boards/silabs/radio_boards/slwrb4161a/support/openocd.cfg new file mode 100644 index 0000000000000..38409eb70ad79 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4161a/support/openocd.cfg @@ -0,0 +1,25 @@ +if {[info exists env(OPENOCD_INTERFACE)]} { + set INTERFACE $env(OPENOCD_INTERFACE) +} else { + # By default connect over Debug USB port using the J-Link interface + set INTERFACE "jlink" +} + +source [find interface/$INTERFACE.cfg] + +transport select swd + +set CHIPNAME efr32 + +source [find target/efm32.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/silabs/radio_boards/slwrb4170a/Kconfig.defconfig b/boards/silabs/radio_boards/slwrb4170a/Kconfig.defconfig new file mode 100644 index 0000000000000..1e7b4bee9382b --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4170a/Kconfig.defconfig @@ -0,0 +1,44 @@ +# EFR32 radio board + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLWRB4170A + +config CMU_HFXO_FREQ + default 38400000 + +config CMU_LFXO_FREQ + default 32768 + +config FLASH_BASE_ADDRESS + hex + default 0x0 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +if SOC_GECKO_USE_RAIL + +config FPU + default n + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config MINIMAL_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 3072 if PM + default 2304 + +endif # BT + +endif # BOARD_SLWRB4170A diff --git a/boards/silabs/radio_boards/slwrb4170a/Kconfig.slwrb4170a b/boards/silabs/radio_boards/slwrb4170a/Kconfig.slwrb4170a new file mode 100644 index 0000000000000..6ae34218fc3b7 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4170a/Kconfig.slwrb4170a @@ -0,0 +1,8 @@ +# EFR32MG12 BRD4170A + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLWRB4170A + select SOC_PART_NUMBER_EFR32MG12P433F1024GM68 diff --git a/boards/silabs/radio_boards/slwrb4170a/board.cmake b/boards/silabs/radio_boards/slwrb4170a/board.cmake new file mode 100644 index 0000000000000..be43109892de5 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4170a/board.cmake @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd) +board_runner_args(jlink "--device=EFR32MG12PxxxF1024") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/silabs/radio_boards/slwrb4170a/board.yml b/boards/silabs/radio_boards/slwrb4170a/board.yml new file mode 100644 index 0000000000000..3137d819edb34 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4170a/board.yml @@ -0,0 +1,4 @@ +boards: + - name: slwrb4170a + socs: + - name: efr32mg12p433f1024gm68 diff --git a/boards/silabs/efr32_radio/doc/efr32mg12-slwrb4170a.jpg b/boards/silabs/radio_boards/slwrb4170a/doc/efr32mg12-slwrb4170a.jpg similarity index 100% rename from boards/silabs/efr32_radio/doc/efr32mg12-slwrb4170a.jpg rename to boards/silabs/radio_boards/slwrb4170a/doc/efr32mg12-slwrb4170a.jpg diff --git a/boards/silabs/radio_boards/slwrb4170a/doc/index.rst b/boards/silabs/radio_boards/slwrb4170a/doc/index.rst new file mode 100644 index 0000000000000..b6a29d13ad138 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4170a/doc/index.rst @@ -0,0 +1,156 @@ +.. _slwrb4170a: + +EFR32MG12 2400/868-915 MHz 19 dBm Dual Band (SLWRB4170A) +######################################################## + +Overview +******** + +The EFR32MG12 Mighty Gecko Radio Board contains a Wireless System-On-Chip +from the EFR32MG12 family built on an ARM Cortex®-M4F processor with excellent +low power capabilities. + +.. figure:: efr32mg12-slwrb4170a.jpg + :align: center + :alt: SLWRB4170A Mighty Gecko Radio Board + + SLWRB4170A (image courtesy of Silicon Labs) + +The BRD4170A a.k.a. SLWRB4170A radio board plugs into the Wireless Starter Kit +Mainboard BRD4001A and is supported as one of :ref:`silabs_radio_boards`. + +Hardware +******** + +- EFR32MG12P433F1024GM68 Mighty Gecko SoC +- CPU core: ARM Cortex®-M4 with FPU +- Flash memory: 1024 kB +- RAM: 256 kB +- Transmit power: up to +19 dBm +- Operation frequency: 2.4 GHz and Sub-Ghz +- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). + +For more information about the EFR32MG12 SoC and BRD4170A board, refer to these +documents: + +- `EFR32MG12 Website`_ +- `EFR32MG12 Datasheet`_ +- `EFR32xG12 Reference Manual`_ +- `BRD4170A User Guide`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| SPI(M) | on-chip | spi port-polling | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/radio_boards/slwrb4170a/slwrb4170a_defconfig` + +Connections and IOs +=================== + +In the following table, the column **Pin** contains Pin names. For example, PA2 +means Pin number 2 on PORTA, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Pin | Function | Usage | ++=======+=============+=====================================+ +| PF4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PF5 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PF6 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PF7 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PA5 | GPIO | Board Controller Enable VCOM_ENABLE | ++-------+-------------+-------------------------------------+ +| PA0 | USART0_TX | UART Console VCOM_TX US0_TX #0 | ++-------+-------------+-------------------------------------+ +| PA1 | USART0_RX | UART Console VCOM_RX US0_RX #0 | ++-------+-------------+-------------------------------------+ +| PC6 | SPI_MOSI | Flash MOSI US1_TX #11 | ++-------+-------------+-------------------------------------+ +| PC7 | SPI_MISO | Flash MISO US1_RX #11 | ++-------+-------------+-------------------------------------+ +| PC8 | SPI_SCLK | Flash SCLK US1_CLK #11 | ++-------+-------------+-------------------------------------+ +| PA4 | SPI_CS | Flash Chip Select (GPIO) | ++-------+-------------+-------------------------------------+ + +System Clock +============ + +The EFR32MG12P SoC is configured to use the 38.4 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32MG12P SoC has four USARTs and one Low Energy UARTs (LEUART). +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +Flashing +======== + +Connect the BRD4001A board with a mounted BRD4170A radio module to your host +computer using the USB port. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slwrb4170a + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should see the following message in the terminal: + +.. code-block:: console + + Hello World! slwrb4170a + + +.. _EFR32MG12 Website: + https://www.silabs.com/wireless/zigbee/efr32mg12-series-1-socs + +.. _EFR32MG12 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32mg12-datasheet.pdf + +.. _EFR32xG12 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg12-rm.pdf + +.. _BRD4170A User Guide: + https://www.silabs.com/documents/public/user-guides/ug342-brd4170a-user-guide.pdf diff --git a/boards/silabs/radio_boards/slwrb4170a/pre_dt_board.cmake b/boards/silabs/radio_boards/slwrb4170a/pre_dt_board.cmake new file mode 100644 index 0000000000000..beb76b85552d1 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4170a/pre_dt_board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# SPI is implemented via usart so node name isn't spi@... +list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") diff --git a/boards/silabs/radio_boards/slwrb4170a/slwrb4170a.dts b/boards/silabs/radio_boards/slwrb4170a/slwrb4170a.dts new file mode 100644 index 0000000000000..f1ec87f183b15 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4170a/slwrb4170a.dts @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020 Piotr Mienkowski + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "../common/efr32-series1-common.dtsi" + +/ { + model = "Silicon Labs BRD4170A (Mighty Gecko 12 Radio Board)"; + compatible = "silabs,slwrb4170a", "silabs,efr32mg12p"; + + chosen { + zephyr,bt-hci = &bt_hci_silabs; + }; +}; + +&cpu0 { + clock-frequency = <38400000>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 32 kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x00008000>; + read-only; + }; + + /* Reserve 220 kB for the application in slot 0 */ + slot0_partition: partition@8000 { + label = "image-0"; + reg = <0x00008000 0x00037000>; + }; + + /* Reserve 220 kB for the application in slot 1 */ + slot1_partition: partition@3f000 { + label = "image-1"; + reg = <0x0003f000 0x00037000>; + }; + + /* Reserve 32 kB for the scratch partition */ + scratch_partition: partition@76000 { + label = "image-scratch"; + reg = <0x00076000 0x00008000>; + }; + + /* Set 8Kb of storage at the end of the 512KB of flash */ + storage_partition: partition@7e000 { + label = "storage"; + reg = <0x0007e000 0x00002000>; + }; + + }; +}; + +&bt_hci_silabs { + status = "okay"; +}; diff --git a/boards/silabs/radio_boards/slwrb4170a/slwrb4170a.yaml b/boards/silabs/radio_boards/slwrb4170a/slwrb4170a.yaml new file mode 100644 index 0000000000000..754d40f8840ba --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4170a/slwrb4170a.yaml @@ -0,0 +1,21 @@ +identifier: slwrb4170a +name: EFR32MG12 2400/868-915 MHz 19 dBm Dual Band Radio Board (SLWRB4170A) +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb +supported: + - counter + - gpio + - nvs + - spi + - uart + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125_defconfig b/boards/silabs/radio_boards/slwrb4170a/slwrb4170a_defconfig similarity index 100% rename from boards/silabs/efr32_radio/efr32_radio_efr32mg12p432f1024gl125_defconfig rename to boards/silabs/radio_boards/slwrb4170a/slwrb4170a_defconfig diff --git a/boards/silabs/radio_boards/slwrb4170a/support/openocd.cfg b/boards/silabs/radio_boards/slwrb4170a/support/openocd.cfg new file mode 100644 index 0000000000000..38409eb70ad79 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4170a/support/openocd.cfg @@ -0,0 +1,25 @@ +if {[info exists env(OPENOCD_INTERFACE)]} { + set INTERFACE $env(OPENOCD_INTERFACE) +} else { + # By default connect over Debug USB port using the J-Link interface + set INTERFACE "jlink" +} + +source [find interface/$INTERFACE.cfg] + +transport select swd + +set CHIPNAME efr32 + +source [find target/efm32.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/silabs/radio_boards/slwrb4180a/Kconfig.defconfig b/boards/silabs/radio_boards/slwrb4180a/Kconfig.defconfig new file mode 100644 index 0000000000000..ada9ac843a6ab --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4180a/Kconfig.defconfig @@ -0,0 +1,44 @@ +# EFR32 radio board + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLWRB4180A + +config CMU_HFXO_FREQ + default 38400000 + +config CMU_LFXO_FREQ + default 32768 + +config FLASH_BASE_ADDRESS + hex + default 0x0 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +if SOC_GECKO_USE_RAIL + +config FPU + default y + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config MINIMAL_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 3072 if PM + default 2304 + +endif # BT + +endif # BOARD_SLWRB4180A diff --git a/boards/silabs/radio_boards/slwrb4180a/Kconfig.slwrb4180a b/boards/silabs/radio_boards/slwrb4180a/Kconfig.slwrb4180a new file mode 100644 index 0000000000000..2e1e6c0fd3ed7 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4180a/Kconfig.slwrb4180a @@ -0,0 +1,8 @@ +# EFR32MG21 BRD4180A + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLWRB4180A + select SOC_PART_NUMBER_EFR32MG21A020F1024IM32 diff --git a/boards/silabs/radio_boards/slwrb4180a/board.cmake b/boards/silabs/radio_boards/slwrb4180a/board.cmake new file mode 100644 index 0000000000000..aa7247647d8ce --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4180a/board.cmake @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd) +board_runner_args(jlink "--device=EFR32MG21AxxxF1024") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/silabs/radio_boards/slwrb4180a/board.yml b/boards/silabs/radio_boards/slwrb4180a/board.yml new file mode 100644 index 0000000000000..c6f825f735a3c --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4180a/board.yml @@ -0,0 +1,4 @@ +boards: + - name: slwrb4180a + socs: + - name: efr32mg21a020f1024im32 diff --git a/boards/silabs/efr32_radio/doc/efr32mg21-slwrb4180a.jpg b/boards/silabs/radio_boards/slwrb4180a/doc/efr32mg21-slwrb4180a.jpg similarity index 100% rename from boards/silabs/efr32_radio/doc/efr32mg21-slwrb4180a.jpg rename to boards/silabs/radio_boards/slwrb4180a/doc/efr32mg21-slwrb4180a.jpg diff --git a/boards/silabs/radio_boards/slwrb4180a/doc/index.rst b/boards/silabs/radio_boards/slwrb4180a/doc/index.rst new file mode 100644 index 0000000000000..01864a54b1b3a --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4180a/doc/index.rst @@ -0,0 +1,156 @@ +.. _slwrb4180a: + +EFR32xG21 2.4 GHz 20 dBm (SLWRB4180A) +##################################### + +Overview +******** + +The EFR32MG21 Mighty Gecko Radio Board is one of the two +radio boards delivered with `EFR32-SLWSTK6006A Website`_. It contains +a Wireless System-On-Chip from the EFR32MG21 family built on an +ARM Cortex®-M33F processor with excellent low power capabilities. + +.. figure:: efr32mg21-slwrb4180a.jpg + :align: center + :alt: SLWRB4180A Mighty Gecko Radio Board + + SLWRB4180A (image courtesy of Silicon Labs) + +The BRD4180A a.k.a. SLWRB4180A radio board plugs into the Wireless Starter Kit +Mainboard BRD4001A and is supported as one of :ref:`silabs_radio_boards`. + +Hardware +******** + +- EFR32MG21A020F1024IM32 Mighty Gecko SoC +- CPU core: ARM Cortex®-M33 with FPU +- Flash memory: 1024 kB +- RAM: 96 kB +- Transmit power: up to +20 dBm +- Operation frequency: 2.4 GHz +- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). + +For more information about the EFR32MG21 SoC and BRD4180A board, refer to these +documents: + +- `EFR32MG21 Website`_ +- `EFR32MG21 Datasheet`_ +- `EFR32xG21 Reference Manual`_ +- `EFR32-SLWSTK6006A Website`_ +- `BRD4180A User Guide`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c port-polling | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ + +Other hardware features are currently not supported by the port. + +Connections and IOs +=================== + +In the following table, the column **Name** contains Pin names. For example, PA2 +means Pin number 2 on PORTA, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PB0 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PB1 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PD2 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PD3 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PD4 | GPIO | Board Controller Enable | +| | | EFM_BC_EN | ++-------+-------------+-------------------------------------+ +| PA5 | USART1_TX | UART Console EFM_BC_TX US1_TX | ++-------+-------------+-------------------------------------+ +| PA6 | USART1_RX | UART Console EFM_BC_RX US1_RX | ++-------+-------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/radio_boards/slwrb4180a/slwrb4180a_defconfig` + +System Clock +============ + +The EFR32MG21 SoC is configured to use the 38.4 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32MG21 SoC has three USARTs. +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +Flashing +======== + +Connect the BRD4001A board with a mounted BRD4180A radio module to your host +computer using the USB port. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slwrb4180a + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should see the following message in the terminal: + +.. code-block:: console + + Hello World! slwrb4180a + + +.. _EFR32-SLWSTK6006A Website: + https://www.silabs.com/products/development-tools/wireless/efr32xg21-wireless-starter-kit + +.. _BRD4180A User Guide: + https://www.silabs.com/documents/public/user-guides/ug385-brd4180a-user-guide.pdf + +.. _EFR32MG21 Website: + https://www.silabs.com/products/wireless/mesh-networking/efr32mg21-series-2-socs + +.. _EFR32MG21 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32mg21-datasheet.pdf + +.. _EFR32xG21 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg21-rm.pdf diff --git a/boards/silabs/radio_boards/slwrb4180a/pre_dt_board.cmake b/boards/silabs/radio_boards/slwrb4180a/pre_dt_board.cmake new file mode 100644 index 0000000000000..beb76b85552d1 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4180a/pre_dt_board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# SPI is implemented via usart so node name isn't spi@... +list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32-pinctrl.dtsi b/boards/silabs/radio_boards/slwrb4180a/slwrb4180a-pinctrl.dtsi similarity index 100% rename from boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32-pinctrl.dtsi rename to boards/silabs/radio_boards/slwrb4180a/slwrb4180a-pinctrl.dtsi diff --git a/boards/silabs/radio_boards/slwrb4180a/slwrb4180a.dts b/boards/silabs/radio_boards/slwrb4180a/slwrb4180a.dts new file mode 100644 index 0000000000000..9d7615047839a --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4180a/slwrb4180a.dts @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2020 TriaGnoSys GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "slwrb4180a-pinctrl.dtsi" + +/ { + model = "Silicon Labs BRD4180A (Mighty Gecko 21 Radio Board)"; + compatible = "silabs,slwrb4180a", "silabs,efr32mg21"; + + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpiob 0 0>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpiob 1 0>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + /* gpio flags need validation */ + gpios = <&gpiod 2 GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + /* gpio flags need validation */ + gpios = <&gpiod 3 GPIO_ACTIVE_LOW>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; + +}; + +&cpu0 { + clock-frequency = <38400000>; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rtcc0 { + prescaler = <1>; + status = "okay"; +}; + +&gpio { + status = "okay"; +}; + +&gpioa { + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <4 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&wdog0 { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 48 kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x0000c000>; + read-only; + }; + + /* Reserve 464 kB for the application in slot 0 */ + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000c000 0x00074000>; + }; + + /* Reserve 464 kB for the application in slot 1 */ + slot1_partition: partition@80000 { + label = "image-1"; + reg = <0x00080000 0x00074000>; + }; + + /* Reserve 32 kB for the scratch partition */ + scratch_partition: partition@f4000 { + label = "image-scratch"; + reg = <0x000f4000 0x00008000>; + }; + + /* Set 16Kb of storage at the end of the 1024Kb of flash */ + storage_partition: partition@fc000 { + label = "storage"; + reg = <0x000fc000 0x00004000>; + }; + + }; +}; diff --git a/boards/silabs/radio_boards/slwrb4180a/slwrb4180a.yaml b/boards/silabs/radio_boards/slwrb4180a/slwrb4180a.yaml new file mode 100644 index 0000000000000..ae9d5b7f2b85e --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4180a/slwrb4180a.yaml @@ -0,0 +1,21 @@ +identifier: slwrb4180a +name: EFR32xG21 2.4 GHz 20 dBm Radio Board (SLWRB4180A) +type: mcu +arch: arm +ram: 96 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - counter + - gpio + - nvs + - uart + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32_defconfig b/boards/silabs/radio_boards/slwrb4180a/slwrb4180a_defconfig similarity index 100% rename from boards/silabs/efr32_radio/efr32_radio_efr32mg21a020f1024im32_defconfig rename to boards/silabs/radio_boards/slwrb4180a/slwrb4180a_defconfig diff --git a/boards/silabs/radio_boards/slwrb4180a/support/openocd.cfg b/boards/silabs/radio_boards/slwrb4180a/support/openocd.cfg new file mode 100644 index 0000000000000..38409eb70ad79 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4180a/support/openocd.cfg @@ -0,0 +1,25 @@ +if {[info exists env(OPENOCD_INTERFACE)]} { + set INTERFACE $env(OPENOCD_INTERFACE) +} else { + # By default connect over Debug USB port using the J-Link interface + set INTERFACE "jlink" +} + +source [find interface/$INTERFACE.cfg] + +transport select swd + +set CHIPNAME efr32 + +source [find target/efm32.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/silabs/radio_boards/slwrb4250b/Kconfig.defconfig b/boards/silabs/radio_boards/slwrb4250b/Kconfig.defconfig new file mode 100644 index 0000000000000..4ddb0000ca66a --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4250b/Kconfig.defconfig @@ -0,0 +1,44 @@ +# EFR32 radio board + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLWRB4250B + +config CMU_HFXO_FREQ + default 38400000 + +config CMU_LFXO_FREQ + default 32768 + +config FLASH_BASE_ADDRESS + hex + default 0x0 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +if SOC_GECKO_USE_RAIL + +config FPU + default n + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config MINIMAL_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 3072 if PM + default 2304 + +endif # BT + +endif # BOARD_SLWRB4250B diff --git a/boards/silabs/radio_boards/slwrb4250b/Kconfig.slwrb4250b b/boards/silabs/radio_boards/slwrb4250b/Kconfig.slwrb4250b new file mode 100644 index 0000000000000..bab71ba23c9d3 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4250b/Kconfig.slwrb4250b @@ -0,0 +1,8 @@ +# EFR32FG1P BRD4250B + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLWRB4250B + select SOC_PART_NUMBER_EFR32FG1P133F256GM48 diff --git a/boards/silabs/radio_boards/slwrb4250b/board.cmake b/boards/silabs/radio_boards/slwrb4250b/board.cmake new file mode 100644 index 0000000000000..a17aad7a8955f --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4250b/board.cmake @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd) +board_runner_args(jlink "--device=EFR32FG1PxxxF256") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/silabs/radio_boards/slwrb4250b/board.yml b/boards/silabs/radio_boards/slwrb4250b/board.yml new file mode 100644 index 0000000000000..cffd4c63dbb30 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4250b/board.yml @@ -0,0 +1,4 @@ +boards: + - name: slwrb4250b + socs: + - name: efr32fg1p133f256gm48 diff --git a/boards/silabs/efr32_radio/doc/efr32fg1-slwrb4250b.jpg b/boards/silabs/radio_boards/slwrb4250b/doc/efr32fg1-slwrb4250b.jpg similarity index 100% rename from boards/silabs/efr32_radio/doc/efr32fg1-slwrb4250b.jpg rename to boards/silabs/radio_boards/slwrb4250b/doc/efr32fg1-slwrb4250b.jpg diff --git a/boards/silabs/radio_boards/slwrb4250b/doc/index.rst b/boards/silabs/radio_boards/slwrb4250b/doc/index.rst new file mode 100644 index 0000000000000..59a38cf26f8be --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4250b/doc/index.rst @@ -0,0 +1,169 @@ +.. _slwrb4250b: + +EFR32FG1 2400/868 MHz 13 dBm Dual Band (SLWRB4250B) +################################################### + +Overview +******** + +The EFR32FG1 Flex Gecko 2.4 GHz and 868 MHz Radio Board is delivered as part of +`SLWSTK6061B Proprietary Wireless Starter Kit`_. It contains a EFR32FG1 Wireless +SoC built on an ARM Cortex®-M4F processor with excellent low power capabilities. + +.. figure:: efr32fg1-slwrb4250b.jpg + :align: center + :alt: SLWRB4250B Flex Gecko 2.4 GHz and 868 MHz Radio Board + + SLWRB4250B (image courtesy of Silicon Labs) + +The BRD4250B a.k.a. SLWRB4250B radio board plugs into the Wireless Starter Kit +Mainboard BRD4001A and is supported as one of :ref:`silabs_radio_boards`. + +Hardware +******** + +- EFR32FG1P133F256GM48 Flex Gecko SoC +- CPU core: ARM Cortex®-M4 with FPU +- Flash memory: 256 kB +- RAM: 32 kB +- Transmit power: up to +13 dBm +- Operation frequency: 2.4 GHz, 868 MHz +- 8Mbit SPI NOR Flash +- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). + +For more information about the EFR32FG1 SoC and BRD4250B board, refer to these +documents: + +- `EFR32FG1 Website`_ +- `EFR32FG1 Datasheet`_ +- `EFR32xG1 Reference Manual`_ +- `SLWSTK6061B Proprietary Wireless Starter Kit`_ +- `BRD4250B User Guide`_ +- `BRD4250B Reference Manual`_ +- `EFR32FG1-BRD4250B Schematics`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| SPI(M) | on-chip | spi port-polling | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/radio_boards/slwrb4250b/slwrb4250b_defconfig` + +Connections and IOs +=================== + +In the following table, the column **Pin** contains Pin names. For example, PA2 +means Pin number 2 on PORTA, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Pin | Function | Usage | ++=======+=============+=====================================+ +| PF4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PF5 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PF6 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PF7 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PA5 | GPIO | Board Controller Enable VCOM_ENABLE | ++-------+-------------+-------------------------------------+ +| PA0 | USART0_TX | UART Console VCOM_TX US0_TX #0 | ++-------+-------------+-------------------------------------+ +| PA1 | USART0_RX | UART Console VCOM_RX US0_RX #0 | ++-------+-------------+-------------------------------------+ +| PC6 | SPI_MOSI | Flash MOSI US1_TX #11 | ++-------+-------------+-------------------------------------+ +| PC7 | SPI_MISO | Flash MISO US1_RX #11 | ++-------+-------------+-------------------------------------+ +| PC8 | SPI_SCLK | Flash SCLK US1_CLK #11 | ++-------+-------------+-------------------------------------+ +| PA4 | SPI_CS | Flash Chip Select (GPIO) | ++-------+-------------+-------------------------------------+ + +System Clock +============ + +The EFR32FG1P SoC is configured to use the 38.4 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32FG1P SoC has two USARTs and one Low Energy UARTs (LEUART). +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +Flashing +======== + +Connect the BRD4001A board with a mounted BRD4250B radio module to your host +computer using the USB port. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slwrb4250b + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should see the following message in the terminal: + +.. code-block:: console + + Hello World! slwrb4250b + + +.. _EFR32FG1 Website: + https://www.silabs.com/wireless/proprietary/efr32fg1-series-1-sub-ghz-2-4-ghz-socs + +.. _EFR32FG1 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32fg1-datasheet.pdf + +.. _EFR32xG1 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg1-rm.pdf + +.. _SLWSTK6061B Proprietary Wireless Starter Kit: + https://www.silabs.com/products/development-tools/wireless/proprietary/slwstk6061b-efr32-flex-gecko-868-mhz-2-4-ghz-and-sub-ghz-starter-kit + +.. _BRD4250B User Guide: + https://www.silabs.com/documents/public/user-guides/ug182-brd4250b-user-guide.pdf + +.. _BRD4250B Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/brd4250b-rm.pdf + +.. _EFR32FG1-BRD4250B Schematics: + https://www.silabs.com/documents/public/schematic-files/BRD4250B-B02-schematic.pdf diff --git a/boards/silabs/radio_boards/slwrb4250b/pre_dt_board.cmake b/boards/silabs/radio_boards/slwrb4250b/pre_dt_board.cmake new file mode 100644 index 0000000000000..beb76b85552d1 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4250b/pre_dt_board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# SPI is implemented via usart so node name isn't spi@... +list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") diff --git a/boards/silabs/radio_boards/slwrb4250b/slwrb4250b.dts b/boards/silabs/radio_boards/slwrb4250b/slwrb4250b.dts new file mode 100644 index 0000000000000..7ca9e7388cedc --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4250b/slwrb4250b.dts @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2020 Piotr Mienkowski + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "../common/efr32-series1-common.dtsi" + +/ { + model = "Silicon Labs BRD4250B (Flex Gecko 1 Radio Board)"; + compatible = "silabs,slwrb4250b", "silabs,efr32fg1p"; + + pwmleds { + compatible = "pwm-leds"; + status = "okay"; + pwm_led0: pwm_led0 { + pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; + + aliases { + pwm-led0 = &pwm_led0; + }; +}; + +&cpu0 { + clock-frequency = <38400000>; +}; + +&timer0 { + status = "okay"; + + pwm0: pwm { + status = "okay"; + pin-location = ; + prescaler = <1024>; + }; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 32 kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x00008000>; + read-only; + }; + + /* Reserve 94 kB for the application in slot 0 */ + slot0_partition: partition@8000 { + label = "image-0"; + reg = <0x00008000 0x00017800>; + }; + + /* Reserve 94 kB for the application in slot 1 */ + slot1_partition: partition@1f800 { + label = "image-1"; + reg = <0x0001f800 0x00017800>; + }; + + /* Reserve 30 kB for the scratch partition */ + scratch_partition: partition@37000 { + label = "image-scratch"; + reg = <0x00037000 0x00007800>; + }; + + /* Set 6Kb of storage at the end of the 256Kb of flash */ + storage_partition: partition@3e800 { + label = "storage"; + reg = <0x0003e800 0x00001800>; + }; + + }; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/silabs/radio_boards/slwrb4250b/slwrb4250b.yaml b/boards/silabs/radio_boards/slwrb4250b/slwrb4250b.yaml new file mode 100644 index 0000000000000..8f54bc217527d --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4250b/slwrb4250b.yaml @@ -0,0 +1,22 @@ +identifier: slwrb4250b +name: EFR32FG 2400/868 MHz 13 dBm Dual Band Radio Board (SLWRB4250B) +type: mcu +arch: arm +ram: 32 +flash: 256 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - counter + - gpio + - nvs + - spi + - uart + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68_defconfig b/boards/silabs/radio_boards/slwrb4250b/slwrb4250b_defconfig similarity index 100% rename from boards/silabs/efr32_radio/efr32_radio_efr32mg12p433f1024gm68_defconfig rename to boards/silabs/radio_boards/slwrb4250b/slwrb4250b_defconfig diff --git a/boards/silabs/radio_boards/slwrb4250b/support/openocd.cfg b/boards/silabs/radio_boards/slwrb4250b/support/openocd.cfg new file mode 100644 index 0000000000000..38409eb70ad79 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4250b/support/openocd.cfg @@ -0,0 +1,25 @@ +if {[info exists env(OPENOCD_INTERFACE)]} { + set INTERFACE $env(OPENOCD_INTERFACE) +} else { + # By default connect over Debug USB port using the J-Link interface + set INTERFACE "jlink" +} + +source [find interface/$INTERFACE.cfg] + +transport select swd + +set CHIPNAME efr32 + +source [find target/efm32.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/silabs/radio_boards/slwrb4255a/Kconfig.defconfig b/boards/silabs/radio_boards/slwrb4255a/Kconfig.defconfig new file mode 100644 index 0000000000000..eda39b9173d91 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4255a/Kconfig.defconfig @@ -0,0 +1,44 @@ +# EFR32 radio board + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLWRB4255A + +config CMU_HFXO_FREQ + default 38400000 + +config CMU_LFXO_FREQ + default 32768 + +config FLASH_BASE_ADDRESS + hex + default 0x0 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +if SOC_GECKO_USE_RAIL + +config FPU + default n + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config MINIMAL_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 3072 if PM + default 2304 + +endif # BT + +endif # BOARD_SLWRB4255A diff --git a/boards/silabs/radio_boards/slwrb4255a/Kconfig.slwrb4255a b/boards/silabs/radio_boards/slwrb4255a/Kconfig.slwrb4255a new file mode 100644 index 0000000000000..6f95623eb75d1 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4255a/Kconfig.slwrb4255a @@ -0,0 +1,8 @@ +# EFR32FG13P BRD4255A board + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLWRB4255A + select SOC_PART_NUMBER_EFR32FG13P233F512GM48 diff --git a/boards/silabs/radio_boards/slwrb4255a/board.cmake b/boards/silabs/radio_boards/slwrb4255a/board.cmake new file mode 100644 index 0000000000000..7e93e543d5500 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4255a/board.cmake @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd) +board_runner_args(jlink "--device=EFR32FG13PxxxF512") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/silabs/radio_boards/slwrb4255a/board.yml b/boards/silabs/radio_boards/slwrb4255a/board.yml new file mode 100644 index 0000000000000..4b76604b1708d --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4255a/board.yml @@ -0,0 +1,4 @@ +boards: + - name: slwrb4255a + socs: + - name: efr32fg13p233f512gm48 diff --git a/boards/silabs/efr32_radio/doc/efr32fg13-slwrb4255a.jpg b/boards/silabs/radio_boards/slwrb4255a/doc/efr32fg13-slwrb4255a.jpg similarity index 100% rename from boards/silabs/efr32_radio/doc/efr32fg13-slwrb4255a.jpg rename to boards/silabs/radio_boards/slwrb4255a/doc/efr32fg13-slwrb4255a.jpg diff --git a/boards/silabs/radio_boards/slwrb4255a/doc/index.rst b/boards/silabs/radio_boards/slwrb4255a/doc/index.rst new file mode 100644 index 0000000000000..d7e303c13262c --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4255a/doc/index.rst @@ -0,0 +1,159 @@ +.. _slwrb4255a: + +EFR32FG13 2400/915 MHz 19 dBm Dual Band (SLWRB4255A) +#################################################### + +Overview +******** + +The EFR32FG13P Flex Gecko 2.4 GHz and 915 MHz Radio Board is delivered as a +`standalone Proprietary Wireless radio board`_. It contains a EFR32FG13P Wireless +SoC built on an ARM Cortex®-M4F processor with excellent low power capabilities. + +.. figure:: efr32fg13-slwrb4255a.jpg + :align: center + :alt: SLWRB4255A Flex Gecko 2.4 GHz and 915 MHz Radio Board + + SLWRB4255A (image courtesy of Silicon Labs) + +The BRD4255A a.k.a. SLWRB4255A radio board plugs into the Wireless Starter Kit +Mainboard BRD4001A and is supported as one of :ref:`silabs_radio_boards`. + +Hardware +******** + +- EFR32FG13P233F512GM48 Flex Gecko SoC +- CPU core: ARM Cortex®-M4 with FPU +- Flash memory: 512 kB +- RAM: 64 kB +- Transmit power: up to 19 dBm +- Operation frequency: 2.4 GHz, 915 MHz +- Crystals for LFXO (32.768 kHz) and HFXO (38.4 MHz). + +For more information about the EFR32FG13 SoC and BRD4255A board, refer to these +documents: + +- `EFR32FG13 Website`_ +- `EFR32FG13 Datasheet`_ +- `EFR32xG13 Reference Manual`_ +- `BRD4255A Reference Manual`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| SPI(M) | on-chip | spi port-polling | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/radio_boards/slwrb4255/slwrb4255_defconfig` + +Connections and IOs +=================== + +In the following table, the column **Pin** contains Pin names. For example, PA2 +means Pin number 2 on PORTA, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Pin | Function | Usage | ++=======+=============+=====================================+ +| PF4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PF5 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PF6 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PF7 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PA5 | GPIO | Board Controller Enable VCOM_ENABLE | ++-------+-------------+-------------------------------------+ +| PA0 | USART0_TX | UART Console VCOM_TX US0_TX #0 | ++-------+-------------+-------------------------------------+ +| PA1 | USART0_RX | UART Console VCOM_RX US0_RX #0 | ++-------+-------------+-------------------------------------+ +| PC6 | SPI_MOSI | Flash MOSI US1_TX #11 | ++-------+-------------+-------------------------------------+ +| PC7 | SPI_MISO | Flash MISO US1_RX #11 | ++-------+-------------+-------------------------------------+ +| PC8 | SPI_SCLK | Flash SCLK US1_CLK #11 | ++-------+-------------+-------------------------------------+ +| PA4 | SPI_CS | Flash Chip Select (GPIO) | ++-------+-------------+-------------------------------------+ + +System Clock +============ + +The EFR32FG13P SoC is configured to use the 38.4 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32FG13P SoC has three USARTs and one Low Energy UARTs (LEUART). +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +Flashing +======== + +Connect the BRD4001A board with a mounted BRD4255A radio module to your host +computer using the USB port. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slwrb4255a + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should see the following message in the terminal: + +.. code-block:: console + + Hello World! slwrb4255a + + +.. _EFR32FG13 Website: + https://www.silabs.com/wireless/proprietary/efr32fg13-series-1-sub-ghz-2-4-ghz-socs + +.. _EFR32FG13 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32fg13-datasheet.pdf + +.. _EFR32xG13 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efr32xg13-rm.pdf + +.. _standalone Proprietary Wireless radio board: + https://www.silabs.com/development-tools/wireless/proprietary/slwrb4255a-efr32fg13-915-mhz-radio-board + +.. _BRD4255A Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/brd4255a-rm.pdf diff --git a/boards/silabs/radio_boards/slwrb4255a/pre_dt_board.cmake b/boards/silabs/radio_boards/slwrb4255a/pre_dt_board.cmake new file mode 100644 index 0000000000000..beb76b85552d1 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4255a/pre_dt_board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# SPI is implemented via usart so node name isn't spi@... +list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") diff --git a/boards/silabs/radio_boards/slwrb4255a/slwrb4255a.dts b/boards/silabs/radio_boards/slwrb4255a/slwrb4255a.dts new file mode 100644 index 0000000000000..299a3c8526328 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4255a/slwrb4255a.dts @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2020 Piotr Mienkowski + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "../common/efr32-series1-common.dtsi" + +/ { + model = "Silicon Labs BRD4255A (Flex Gecko Radio Board)"; + compatible = "silabs,slwrb4255a", "silabs,efr32fg13p"; +}; + +&cpu0 { + clock-frequency = <38400000>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 32 kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 0x00008000>; + read-only; + }; + + /* Reserve 220 kB for the application in slot 0 */ + slot0_partition: partition@8000 { + label = "image-0"; + reg = <0x00008000 0x00037000>; + }; + + /* Reserve 220 kB for the application in slot 1 */ + slot1_partition: partition@3f000 { + label = "image-1"; + reg = <0x0003f000 0x00037000>; + }; + + /* Reserve 32 kB for the scratch partition */ + scratch_partition: partition@76000 { + label = "image-scratch"; + reg = <0x00076000 0x00008000>; + }; + + /* Set 8Kb of storage at the end of the 512KB of flash */ + storage_partition: partition@7e000 { + label = "storage"; + reg = <0x0007e000 0x00002000>; + }; + + }; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; diff --git a/boards/silabs/radio_boards/slwrb4255a/slwrb4255a.yaml b/boards/silabs/radio_boards/slwrb4255a/slwrb4255a.yaml new file mode 100644 index 0000000000000..e1d6718fbce0d --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4255a/slwrb4255a.yaml @@ -0,0 +1,22 @@ +identifier: slwrb4255a +name: EFR32FG13 2400/915 MHz 19 dBm Dual Band Radio Board (SLWRB4255A) +type: mcu +arch: arm +ram: 64 +flash: 512 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - counter + - gpio + - nvs + - spi + - uart + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a_defconfig b/boards/silabs/radio_boards/slwrb4255a/slwrb4255a_defconfig similarity index 100% rename from boards/silabs/efr32mg_sltb004a/efr32mg_sltb004a_defconfig rename to boards/silabs/radio_boards/slwrb4255a/slwrb4255a_defconfig diff --git a/boards/silabs/radio_boards/slwrb4255a/support/openocd.cfg b/boards/silabs/radio_boards/slwrb4255a/support/openocd.cfg new file mode 100644 index 0000000000000..38409eb70ad79 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4255a/support/openocd.cfg @@ -0,0 +1,25 @@ +if {[info exists env(OPENOCD_INTERFACE)]} { + set INTERFACE $env(OPENOCD_INTERFACE) +} else { + # By default connect over Debug USB port using the J-Link interface + set INTERFACE "jlink" +} + +source [find interface/$INTERFACE.cfg] + +transport select swd + +set CHIPNAME efr32 + +source [find target/efm32.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/silabs/efm32gg_slwstk6121a/CMakeLists.txt b/boards/silabs/radio_boards/slwrb4321a/CMakeLists.txt similarity index 100% rename from boards/silabs/efm32gg_slwstk6121a/CMakeLists.txt rename to boards/silabs/radio_boards/slwrb4321a/CMakeLists.txt diff --git a/boards/silabs/radio_boards/slwrb4321a/Kconfig.defconfig b/boards/silabs/radio_boards/slwrb4321a/Kconfig.defconfig new file mode 100644 index 0000000000000..63ff16bbad634 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4321a/Kconfig.defconfig @@ -0,0 +1,29 @@ +# EFM32GG SLWSTK6121A default board configuration +# Copyright (c) 2019 Interay Solutions B.V. +# Copyright (c) 2019 Oane Kingma +# Copyright (c) 2020 Thorvald Natvig +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLWRB4321A + +config CMU_HFXO_FREQ + default 50000000 + +config CMU_HFRCO_FREQ + default 72000000 + +config CMU_LFXO_FREQ + default 32768 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + +endif # BOARD_SLWRB4321A diff --git a/boards/silabs/radio_boards/slwrb4321a/Kconfig.slwrb4321a b/boards/silabs/radio_boards/slwrb4321a/Kconfig.slwrb4321a new file mode 100644 index 0000000000000..1ce37ed64468f --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4321a/Kconfig.slwrb4321a @@ -0,0 +1,8 @@ +# EFM32GG11 SLWRB4321A board configuration +# Copyright (c) 2019 Interay Solutions B.V. +# Copyright (c) 2019 Oane Kingma +# Copyright (c) 2020 Thorvald Natvig +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLWRB4321A + select SOC_PART_NUMBER_EFM32GG11B820F2048GM64 diff --git a/boards/silabs/efm32gg_slwstk6121a/board.c b/boards/silabs/radio_boards/slwrb4321a/board.c similarity index 100% rename from boards/silabs/efm32gg_slwstk6121a/board.c rename to boards/silabs/radio_boards/slwrb4321a/board.c diff --git a/boards/silabs/efm32gg_slwstk6121a/board.cmake b/boards/silabs/radio_boards/slwrb4321a/board.cmake similarity index 100% rename from boards/silabs/efm32gg_slwstk6121a/board.cmake rename to boards/silabs/radio_boards/slwrb4321a/board.cmake diff --git a/boards/silabs/efm32gg_slwstk6121a/board.h b/boards/silabs/radio_boards/slwrb4321a/board.h similarity index 100% rename from boards/silabs/efm32gg_slwstk6121a/board.h rename to boards/silabs/radio_boards/slwrb4321a/board.h diff --git a/boards/silabs/radio_boards/slwrb4321a/board.yml b/boards/silabs/radio_boards/slwrb4321a/board.yml new file mode 100644 index 0000000000000..a86f5c2d6209a --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4321a/board.yml @@ -0,0 +1,5 @@ +board: + name: slwrb4321a + vendor: silabs + socs: + - name: efm32gg11b820f2048gm64 diff --git a/boards/silabs/radio_boards/slwrb4321a/doc/index.rst b/boards/silabs/radio_boards/slwrb4321a/doc/index.rst new file mode 100644 index 0000000000000..1170205e1b832 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4321a/doc/index.rst @@ -0,0 +1,186 @@ +.. _slwrb4321a: + +WGM160P Wi-Fi Module (SLWRB4321A) +################################# + +Overview +******** + +The WGM160P Starter Kit SLWSTK6121A comes with the BRD4321A radio board. +This radio boards contains a WGM160P module, which combines the WF200 Wi-Fi +transceiver with an EFM32GG11 microcontroller. + +.. figure:: wgm160p-starter-kit.jpg + :align: center + :alt: SLWSTK6121A + + SLWSTK6121A (image courtesy of Silicon Labs) + +Hardware +******** + +- Advanced Energy Monitoring provides real-time information about the energy + consumption of an application or prototype design. +- Ultra low power 128x128 pixel color Memory-LCD +- 2 user buttons and 2 LEDs +- Si7021 Humidity and Temperature Sensor +- On-board Segger J-Link USB and Ethernet debugger +- 10/100Base-TX ethernet PHY and RJ-45 jack (on included expansion board) +- MicroSD card slot +- USB Micro-AB connector + +For more information about the WGM160P and SLWSTK6121A board: + +- `WGM160P Website`_ +- `WGM160P Datasheet`_ +- `SLWSTK6121A Website`_ +- `SLWSTK6121A User Guide`_ +- `EFM32GG11 Datasheet`_ +- `EFM32GG11 Reference Manual`_ +- `WF200 Datasheet`_ + +Supported Features +================== + +The slwrb4321a board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| ETHERNET | on-chip | ethernet | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c port-polling | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/slwrb4321a/slwrb4321a_defconfig` + +Other hardware features, including the WF200 WiFi transceiver, are +currently not supported by the port. + +Connections and IOs +=================== + +The WGM160P's EFM32GG11 SoC has six GPIO controllers (PORTA to PORTF), all of which are +currently enabled for the SLWSTK6121A board. + +In the following table, the column **Name** contains pin names. For example, PE1 +means pin number 1 on PORTE, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PA4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PA5 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PD6 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PD8 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PE7 | UART_TX | UART TX Console VCOM_TX US0_TX #1 | ++-------+-------------+-------------------------------------+ +| PE6 | UART_RX | UART RX Console VCOM_RX US0_RX #1 | ++-------+-------------+-------------------------------------+ +| PB11 | I2C_SDA | SENSOR_I2C_SDA I2C1_SDA #1 | ++-------+-------------+-------------------------------------+ +| PB12 | I2C_SCL | SENSOR_I2C_SCL I2C1_SCL #1 | ++-------+-------------+-------------------------------------+ + + +System Clock +============ + +The EFM32GG11 SoC is configured to use the 50 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFM32GG11 SoC has four USARTs, two UARTs and two Low Energy UARTs (LEUART). +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The SLWSTK6121A includes an `J-Link`_ serial and debug adaptor built into the +board. The adaptor provides: + +- A USB connection to the host computer +- A physical UART connection which is relayed over interface USB serial port. + +Flashing an application to SLWSTK6121A +-------------------------------------- + +Connect the SLWSTK6121A to your host computer using the USB port. + +Here is an example to build and flash the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slwrb4321a + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you'll see the following message on the corresponding serial port +terminal session: + +.. code-block:: console + + Hello World! slwrb4321a + +.. _WGM160P Website: + https://www.silabs.com/wireless/wi-fi/wfm160-series-1-modules + +.. _WGM160P Datasheet: + https://www.silabs.com/documents/public/data-sheets/wgm160p-datasheet.pdf + +.. _SLWSTK6121A Website: + https://www.silabs.com/development-tools/wireless/wi-fi/wgm160p-wifi-module-starter-kit + +.. _SLWSTK6121A User Guide: + https://www.silabs.com/documents/public/user-guides/ug351-brd4321a-user-guide.pdf + +.. _EFM32GG11 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efm32gg11-datasheet.pdf + +.. _EFM32GG11 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efm32gg11-rm.pdf + +.. _WF200 Datasheet: + https://www.silabs.com/documents/public/data-sheets/wf200-datasheet.pdf + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32gg_slwstk6121a/doc/wgm160p-starter-kit.jpg b/boards/silabs/radio_boards/slwrb4321a/doc/wgm160p-starter-kit.jpg similarity index 100% rename from boards/silabs/efm32gg_slwstk6121a/doc/wgm160p-starter-kit.jpg rename to boards/silabs/radio_boards/slwrb4321a/doc/wgm160p-starter-kit.jpg diff --git a/boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a-pinctrl.dtsi b/boards/silabs/radio_boards/slwrb4321a/slwrb4321a-pinctrl.dtsi similarity index 100% rename from boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a-pinctrl.dtsi rename to boards/silabs/radio_boards/slwrb4321a/slwrb4321a-pinctrl.dtsi diff --git a/boards/silabs/radio_boards/slwrb4321a/slwrb4321a.dts b/boards/silabs/radio_boards/slwrb4321a/slwrb4321a.dts new file mode 100644 index 0000000000000..4dfff28a2dc82 --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4321a/slwrb4321a.dts @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2019 Interay Solutions B.V. + * Copyright (c) 2019 Oane Kingma + * Copyright (c) 2020 Thorvald Natvig + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "slwrb4321a-pinctrl.dtsi" + +/ { + model = "Silicon Labs EFM32GG SLWSTK6121A board"; + compatible = "silabs,slwrb4321a", "silabs,efm32gg11b"; + + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpioa 4 0>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpioa 5 0>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + /* gpio flags need validation */ + gpios = <&gpiod 6 GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + /* gpio flags need validation */ + gpios = <&gpiod 8 GPIO_ACTIVE_LOW>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; +}; + +/* Connected to the WSTK VCOM */ +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +/* i2c unit 0 is not used on the board, but must be defined for i2c unit 1 + * to work properly. + */ +&i2c0 { + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +/* Connected to Si7021 sensor on WSTK */ +&i2c1 { + pinctrl-0 = <&i2c1_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rtcc0 { + prescaler = <1>; + status = "okay"; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpioa { + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&gpioe { + status = "okay"; +}; + +&gpiof { + status = "okay"; +}; + +ð0 { + /* PHY address = 0 */ + phy-address = <0>; + + /* PHY management pins */ + location-mdio = ; + location-phy_mdc = ; + location-phy_mdio = ; + + /* RMII interface pins */ + location-rmii = ; + location-rmii_refclk = ; + location-rmii_crs_dv = ; + location-rmii_txd0 = ; + location-rmii_txd1 = ; + location-rmii_tx_en = ; + location-rmii_rxd0 = ; + location-rmii_rxd1 = ; + location-rmii_rx_er = ; + + status = "okay"; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 12Kb of storage at the end of the 2048Kb of flash */ + storage_partition: partition@1fd000 { + label = "storage"; + reg = <0x001fd000 0x00003000>; + }; + }; +}; + +&wdog0 { + status = "okay"; +}; + +&trng0 { + status = "okay"; +}; + +&cpu0 { + clock-frequency = <72000000>; +}; diff --git a/boards/silabs/radio_boards/slwrb4321a/slwrb4321a.yaml b/boards/silabs/radio_boards/slwrb4321a/slwrb4321a.yaml new file mode 100644 index 0000000000000..7b61761886f4c --- /dev/null +++ b/boards/silabs/radio_boards/slwrb4321a/slwrb4321a.yaml @@ -0,0 +1,21 @@ +identifier: slwrb4321a +name: WGM160P Wi-Fi Module Radio Board (SLWRB4321A) +type: mcu +arch: arm +ram: 512 +flash: 2048 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - counter + - i2c + - gpio + - netif:eth + - nvs + - uart +testing: + ignore_tags: + - bluetooth +vendor: silabs diff --git a/boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a_defconfig b/boards/silabs/radio_boards/slwrb4321a/slwrb4321a_defconfig similarity index 100% rename from boards/silabs/efm32gg_slwstk6121a/efm32gg_slwstk6121a_defconfig rename to boards/silabs/radio_boards/slwrb4321a/slwrb4321a_defconfig diff --git a/boards/silabs/efm32gg_slwstk6121a/support/openocd.cfg b/boards/silabs/radio_boards/slwrb4321a/support/openocd.cfg similarity index 100% rename from boards/silabs/efm32gg_slwstk6121a/support/openocd.cfg rename to boards/silabs/radio_boards/slwrb4321a/support/openocd.cfg diff --git a/boards/silabs/radio_boards/xg24_rb4187c/Kconfig.defconfig b/boards/silabs/radio_boards/xg24_rb4187c/Kconfig.defconfig new file mode 100644 index 0000000000000..92521052f3792 --- /dev/null +++ b/boards/silabs/radio_boards/xg24_rb4187c/Kconfig.defconfig @@ -0,0 +1,44 @@ +# EFR32 radio board + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_XG24_RB4187C + +config CMU_HFXO_FREQ + default 39000000 + +config CMU_LFXO_FREQ + default 32768 + +config FLASH_BASE_ADDRESS + hex + default 0x08000000 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +if SOC_GECKO_USE_RAIL + +config FPU + default y + +endif # SOC_GECKO_USE_RAIL + +if BT + +config FPU + default y + +config MINIMAL_LIBC_MALLOC_ARENA_SIZE + default 8192 + +config MAIN_STACK_SIZE + default 3072 if PM + default 2304 + +endif # BT + +endif # BOARD_XG24_RB4187C diff --git a/boards/silabs/radio_boards/xg24_rb4187c/Kconfig.xg24_rb4187c b/boards/silabs/radio_boards/xg24_rb4187c/Kconfig.xg24_rb4187c new file mode 100644 index 0000000000000..7d51709ba49b2 --- /dev/null +++ b/boards/silabs/radio_boards/xg24_rb4187c/Kconfig.xg24_rb4187c @@ -0,0 +1,8 @@ +# EFR32MG24 BRD4187C + +# Copyright (c) 2020 Piotr Mienkowski +# Copyright (c) 2020 TriaGnoSys GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_XG24_RB4187C + select SOC_PART_NUMBER_EFR32MG24B220F1536IM48 diff --git a/boards/silabs/radio_boards/xg24_rb4187c/board.cmake b/boards/silabs/radio_boards/xg24_rb4187c/board.cmake new file mode 100644 index 0000000000000..a6187e28f0f63 --- /dev/null +++ b/boards/silabs/radio_boards/xg24_rb4187c/board.cmake @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(openocd) +board_runner_args(jlink "--device=EFR32MG24BxxxF1536") + +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/silabs/radio_boards/xg24_rb4187c/board.yml b/boards/silabs/radio_boards/xg24_rb4187c/board.yml new file mode 100644 index 0000000000000..09a4d0743700d --- /dev/null +++ b/boards/silabs/radio_boards/xg24_rb4187c/board.yml @@ -0,0 +1,4 @@ +boards: + - name: xg24_rb4187c + socs: + - name: efr32mg24b220f1536im48 diff --git a/boards/silabs/efr32_radio/doc/efr32mg24-xg24-rb4187c.jpg b/boards/silabs/radio_boards/xg24_rb4187c/doc/efr32mg24-xg24-rb4187c.jpg similarity index 100% rename from boards/silabs/efr32_radio/doc/efr32mg24-xg24-rb4187c.jpg rename to boards/silabs/radio_boards/xg24_rb4187c/doc/efr32mg24-xg24-rb4187c.jpg diff --git a/boards/silabs/radio_boards/xg24_rb4187c/doc/index.rst b/boards/silabs/radio_boards/xg24_rb4187c/doc/index.rst new file mode 100644 index 0000000000000..5100a4bf045cb --- /dev/null +++ b/boards/silabs/radio_boards/xg24_rb4187c/doc/index.rst @@ -0,0 +1,157 @@ +.. _xg24_rb4187c: + +EFR32xG24 2.4 GHz 20 dBm (xG24-RB4187C) +####################################### + +Overview +******** + +The EFR32MG24 Mighty Gecko Radio Board is one of the two +radio boards delivered with `xG24-PK6010A Website`_. It contains +a Wireless System-On-Chip from the EFR32MG24 family built on an +ARM Cortex®-M33F processor with excellent low power capabilities. + +.. figure:: efr32mg24-xg24-rb4187c.jpg + :align: center + :alt: xG24-RB4187C Mighty Gecko Radio Board + + xG24-RB4187C (image courtesy of Silicon Labs) + +The BRD4187C a.k.a. xG24-RB4187C radio board plugs into the Wireless Pro Kit +Mainboard BRD4002A and is supported as one of :ref:`silabs_radio_boards`. + +Hardware +******** + +- EFR32MG24B220F1536IM48 Mighty Gecko SoC +- CPU core: ARM Cortex®-M33 with FPU +- Flash memory: 1536 kB +- RAM: 256 kB +- Transmit power: up to +20 dBm +- Operation frequency: 2.4 GHz +- Crystals for LFXO (32.768 kHz) and HFXO (39 MHz). + +For more information about the EFR32MG24 SoC and BRD4187C board, refer to these +documents: + +- `EFR32MG24 Website`_ +- `EFR32MG24 Datasheet`_ +- `EFR32xG24 Reference Manual`_ +- `xG24-PK6010A Website`_ +- `BRD4187C User Guide`_ + +Supported Features +================== + +The board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | stimer | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| TRNG | on-chip | semailbox | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ + +Other hardware features are currently not supported by the port. + +Connections and IOs +=================== + +In the following table, the column **Name** contains Pin names. For example, PA2 +means Pin number 2 on PORTA, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PB2 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PB4 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PB1 | GPIO | Push Button 0 | ++-------+-------------+-------------------------------------+ +| PB3 | GPIO | Push Button 1 | ++-------+-------------+-------------------------------------+ +| PB0 | GPIO | Board Controller Enable | +| | | VCOM_ENABLE | ++-------+-------------+-------------------------------------+ +| PA8 | USART0_TX | UART Console VCOM_TX US0_TX | ++-------+-------------+-------------------------------------+ +| PA9 | USART0_RX | UART Console VCOM_RX US0_RX | ++-------+-------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c_defconfig` + +System Clock +============ + +The EFR32MG24 SoC is configured to use the 39 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFR32MG24 SoC has one USART and two EUSARTs. +USART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +Flashing +======== + +Connect the BRD4002A board with a mounted BRD4187C radio module to your host +computer using the USB port. + +Here is an example for the :ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: xg24_rb4187c + :goals: flash + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should see the following message in the terminal: + +.. code-block:: console + + Hello World! xg24_rb4187c + + +.. _xG24-PK6010A Website: + https://www.silabs.com/development-tools/wireless/efr32xg24-pro-kit-20-dbm + +.. _BRD4187C User Guide: + https://www.silabs.com/documents/public/user-guides/ug526-brd4187c-user-guide.pdf + +.. _EFR32MG24 Website: + https://www.silabs.com/wireless/zigbee/efr32mg24-series-2-socs + +.. _EFR32MG24 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efr32mg24-datasheet.pdf + +.. _EFR32xG24 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/brd4187c-rm.pdf diff --git a/boards/silabs/radio_boards/xg24_rb4187c/pre_dt_board.cmake b/boards/silabs/radio_boards/xg24_rb4187c/pre_dt_board.cmake new file mode 100644 index 0000000000000..beb76b85552d1 --- /dev/null +++ b/boards/silabs/radio_boards/xg24_rb4187c/pre_dt_board.cmake @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Linaro Limited +# SPDX-License-Identifier: Apache-2.0 + +# SPI is implemented via usart so node name isn't spi@... +list(APPEND EXTRA_DTC_FLAGS "-Wno-spi_bus_bridge") diff --git a/boards/silabs/radio_boards/xg24_rb4187c/support/openocd.cfg b/boards/silabs/radio_boards/xg24_rb4187c/support/openocd.cfg new file mode 100644 index 0000000000000..38409eb70ad79 --- /dev/null +++ b/boards/silabs/radio_boards/xg24_rb4187c/support/openocd.cfg @@ -0,0 +1,25 @@ +if {[info exists env(OPENOCD_INTERFACE)]} { + set INTERFACE $env(OPENOCD_INTERFACE) +} else { + # By default connect over Debug USB port using the J-Link interface + set INTERFACE "jlink" +} + +source [find interface/$INTERFACE.cfg] + +transport select swd + +set CHIPNAME efr32 + +source [find target/efm32.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48-pinctrl.dtsi b/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c-pinctrl.dtsi similarity index 100% rename from boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48-pinctrl.dtsi rename to boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c-pinctrl.dtsi diff --git a/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.dts b/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.dts new file mode 100644 index 0000000000000..21a487e758fd5 --- /dev/null +++ b/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.dts @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2023 Fr. Sauter AG + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "xg24_rb4187c-pinctrl.dtsi" + +/ { + model = "Silicon Labs BRD4187C (Mighty Gecko 24 Radio Board)"; + compatible = "silabs,xg24_rb4187c", "silabs,efr32mg24"; + + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &bt_hci_silabs; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpiob GECKO_PIN(2) GPIO_ACTIVE_HIGH>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpiob GECKO_PIN(4) GPIO_ACTIVE_HIGH>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpiob GECKO_PIN(1) GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + gpios = <&gpiob GECKO_PIN(3) GPIO_ACTIVE_LOW>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; + +}; + +&cpu0 { + clock-frequency = <39000000>; +}; + +&pstate_em3 { + status = "disabled"; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpioa { + status = "okay"; +}; + +&gpiob { + status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <0 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&wdog0 { + status = "okay"; +}; + +&burtc0 { + status = "okay"; +}; + +&stimer0 { + status = "okay"; +}; + +&se { + status = "okay"; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserve 48 kB for the bootloader */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x0 DT_SIZE_K(48)>; + read-only; + }; + + /* Reserve 720 kB for the application in slot 0 */ + slot0_partition: partition@c000 { + label = "image-0"; + reg = <0x0000c000 0x000B4000>; + }; + + /* Reserve 720 kB for the application in slot 1 */ + slot1_partition: partition@C0000 { + label = "image-1"; + reg = <0x000C0000 0x000B4000>; + }; + + /* Reserve 32 kB for the scratch partition */ + scratch_partition: partition@174000 { + label = "image-scratch"; + reg = <0x00174000 DT_SIZE_K(32)>; + }; + + /* Set 16 kB of storage at the end of the 1536 kB of flash */ + storage_partition: partition@17c000 { + label = "storage"; + reg = <0x0017c000 DT_SIZE_K(16)>; + }; + }; +}; + +&bt_hci_silabs { + status = "okay"; +}; diff --git a/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.yaml b/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.yaml new file mode 100644 index 0000000000000..4fbaf3b6d0af5 --- /dev/null +++ b/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c.yaml @@ -0,0 +1,21 @@ +identifier: xg24_rb4187c +name: EFR32xG24 2.4 GHz 20 dBm Radio Board (xG24-RB4187C) +type: mcu +arch: arm +ram: 256 +flash: 1536 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - uart + - watchdog +testing: + ignore_tags: + - net + - bluetooth + - pm + - hwinfo +vendor: silabs diff --git a/boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48_defconfig b/boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c_defconfig similarity index 100% rename from boards/silabs/efr32_radio/efr32_radio_efr32mg24b220f1536im48_defconfig rename to boards/silabs/radio_boards/xg24_rb4187c/xg24_rb4187c_defconfig diff --git a/boards/silabs/efm32wg_stk3800/Kconfig.defconfig b/boards/silabs/starter_kits/efm32wg_stk3800/Kconfig.defconfig similarity index 100% rename from boards/silabs/efm32wg_stk3800/Kconfig.defconfig rename to boards/silabs/starter_kits/efm32wg_stk3800/Kconfig.defconfig diff --git a/boards/silabs/efm32wg_stk3800/Kconfig.efm32wg_stk3800 b/boards/silabs/starter_kits/efm32wg_stk3800/Kconfig.efm32wg_stk3800 similarity index 100% rename from boards/silabs/efm32wg_stk3800/Kconfig.efm32wg_stk3800 rename to boards/silabs/starter_kits/efm32wg_stk3800/Kconfig.efm32wg_stk3800 diff --git a/boards/silabs/efm32wg_stk3800/board.cmake b/boards/silabs/starter_kits/efm32wg_stk3800/board.cmake similarity index 100% rename from boards/silabs/efm32wg_stk3800/board.cmake rename to boards/silabs/starter_kits/efm32wg_stk3800/board.cmake diff --git a/boards/silabs/efm32wg_stk3800/board.yml b/boards/silabs/starter_kits/efm32wg_stk3800/board.yml similarity index 100% rename from boards/silabs/efm32wg_stk3800/board.yml rename to boards/silabs/starter_kits/efm32wg_stk3800/board.yml diff --git a/boards/silabs/efm32wg_stk3800/doc/efm32wg_stk3800.jpg b/boards/silabs/starter_kits/efm32wg_stk3800/doc/efm32wg_stk3800.jpg similarity index 100% rename from boards/silabs/efm32wg_stk3800/doc/efm32wg_stk3800.jpg rename to boards/silabs/starter_kits/efm32wg_stk3800/doc/efm32wg_stk3800.jpg diff --git a/boards/silabs/starter_kits/efm32wg_stk3800/doc/index.rst b/boards/silabs/starter_kits/efm32wg_stk3800/doc/index.rst new file mode 100644 index 0000000000000..139d89379b07e --- /dev/null +++ b/boards/silabs/starter_kits/efm32wg_stk3800/doc/index.rst @@ -0,0 +1,177 @@ +.. _efm32wg_stk3800: + +EFM32 Wonder Gecko (EFM32WG-STK3800) +#################################### + +Overview +******** + +The EFM32 Wonder Gecko Starter Kit EFM32WG-STK3800 contains a MCU from the +EFM32WG family built on ARM® Cortex®-M4F processor with excellent low +power capabilities. + +.. figure:: efm32wg_stk3800.jpg + :align: center + :alt: EFM32WG-STK3800 + + EFM32WG-STK3800 (image courtesy of Silicon Labs) + + +Hardware +******** + +- Advanced Energy Monitoring provides real-time information about the energy + consumption of an application or prototype design. +- 32MByte parallel NAND Flash +- 160 segment Energy Micro LCD +- 2 user buttons, 2 LEDs and a touch slider +- Ambient Light Sensor and Inductive-capacitive metal sensor +- On-board Segger J-Link USB debugger + +For more information about the EFM32WG SoC and EFM32WG-STK3800 board: + +- `EFM32WG Website`_ +- `EFM32WG Datasheet`_ +- `EFM32WG Reference Manual`_ +- `EFM32WG-STK3800 Website`_ +- `EFM32WG-STK3800 User Guide`_ +- `EFM32WG-STK3800 Schematics`_ + +Supported Features +================== + +The efm32wg_stk3800 board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/starter_kit/efm32wg_stk3800/efm32wg_stk3800_defconfig` + +Other hardware features are currently not supported by the port. + +Connections and IOs +=================== + +The EFM32WG SoC has six gpio controllers (PORTA to PORTF), but only three are +currently enabled (PORTB, PORTE and PORTF) for the EFM32WG-STK3800 board. + +In the following table, the column Name contains Pin names. For example, PE2 +means Pin number 2 on PORTE, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PE2 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PE3 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PB9 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PB10 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PF7 | GPIO | Board Controller Enable | +| | | EFM_BC_EN | ++-------+-------------+-------------------------------------+ +| PE0 | UART0_TX | UART Console EFM_BC_TX U0_TX #1 | ++-------+-------------+-------------------------------------+ +| PE1 | UART0_RX | UART Console EFM_BC_RX U0_RX #1 | ++-------+-------------+-------------------------------------+ + +System Clock +============ + +The EFM32WG SoC is configured to use the 48 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFM32WG SoC has three USARTs, two UARTs and two Low Energy UARTs (LEUART). +UART0 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The EFM32WG-STK3800 includes an `J-Link`_ serial and debug adaptor built into the +board. The adaptor provides: + +- A USB connection to the host computer, which exposes a Mass Storage and a + USB Serial Port. +- A Serial Flash device, which implements the USB flash disk file storage. +- A physical UART connection which is relayed over interface USB Serial port. + +Flashing an application to EFM32-STK3800 +---------------------------------------- + +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: efm32wg_stk3800 + :goals: build + +Connect the EFM32WG-STK3800 to your host computer using the USB port and you +should see a USB connection which exposes a Mass Storage (STK3800) and a +USB Serial Port. Copy the generated zephyr.bin in the STK3800 drive. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you should be able to see on the corresponding Serial Port +the following message: + +.. code-block:: console + + Hello World! efm32wg_stk3800 + + +.. _EFM32WG-STK3800 Website: + http://www.silabs.com/products/development-tools/mcu/32-bit/efm32-wonder-gecko-starter-kit + +.. _EFM32WG-STK3800 User Guide: + http://www.silabs.com/documents/public/user-guides/efm32wg-stk3800-ug.pdf + +.. _EFM32WG-STK3800 Schematics: + http://www.silabs.com/documents/public/schematic-files/BRD2400A_A00.pdf + +.. _EFM32WG Website: + http://www.silabs.com/products/mcu/32-bit/efm32-wonder-gecko + +.. _EFM32WG Datasheet: + http://www.silabs.com/documents/public/data-sheets/EFM32WG990.pdf + +.. _EFM32WG Reference Manual: + http://www.silabs.com/documents/public/reference-manuals/EFM32WG-RM.pdf + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32wg_stk3800/efm32wg_stk3800.dts b/boards/silabs/starter_kits/efm32wg_stk3800/efm32wg_stk3800.dts similarity index 100% rename from boards/silabs/efm32wg_stk3800/efm32wg_stk3800.dts rename to boards/silabs/starter_kits/efm32wg_stk3800/efm32wg_stk3800.dts diff --git a/boards/silabs/efm32wg_stk3800/efm32wg_stk3800.yaml b/boards/silabs/starter_kits/efm32wg_stk3800/efm32wg_stk3800.yaml similarity index 79% rename from boards/silabs/efm32wg_stk3800/efm32wg_stk3800.yaml rename to boards/silabs/starter_kits/efm32wg_stk3800/efm32wg_stk3800.yaml index acd28a6623d34..35dbe24db1fe4 100644 --- a/boards/silabs/efm32wg_stk3800/efm32wg_stk3800.yaml +++ b/boards/silabs/starter_kits/efm32wg_stk3800/efm32wg_stk3800.yaml @@ -1,5 +1,5 @@ identifier: efm32wg_stk3800 -name: EFM32WG-STK3800 +name: EFM32 Wonder Gecko Starter Kit (EFM32WG-STK3800) type: mcu arch: arm ram: 32 diff --git a/boards/silabs/efm32wg_stk3800/efm32wg_stk3800_defconfig b/boards/silabs/starter_kits/efm32wg_stk3800/efm32wg_stk3800_defconfig similarity index 100% rename from boards/silabs/efm32wg_stk3800/efm32wg_stk3800_defconfig rename to boards/silabs/starter_kits/efm32wg_stk3800/efm32wg_stk3800_defconfig diff --git a/boards/silabs/starter_kits/index.rst b/boards/silabs/starter_kits/index.rst new file mode 100644 index 0000000000000..06d6c58f98846 --- /dev/null +++ b/boards/silabs/starter_kits/index.rst @@ -0,0 +1,10 @@ +.. _starter_kits: + +Starter Kits +############ + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/boards/silabs/starter_kits/slstk3400a/Kconfig.defconfig b/boards/silabs/starter_kits/slstk3400a/Kconfig.defconfig new file mode 100644 index 0000000000000..78d39acd21af4 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3400a/Kconfig.defconfig @@ -0,0 +1,14 @@ +# EFM32HG SLSTK3400A board + +# Copyright (c) 2018, Marcio Montenegro +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLSTK3400A + +config CMU_HFXO_FREQ + default 24000000 + +config CMU_LFXO_FREQ + default 32768 + +endif # BOARD_SLSTK3400A diff --git a/boards/silabs/starter_kits/slstk3400a/Kconfig.slstk3400a b/boards/silabs/starter_kits/slstk3400a/Kconfig.slstk3400a new file mode 100644 index 0000000000000..bdbf1d8275056 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3400a/Kconfig.slstk3400a @@ -0,0 +1,7 @@ +# EFM32HG SLSTK3400A board + +# Copyright (c) 2018, Marcio Montenegro +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLSTK3400A + select SOC_PART_NUMBER_EFM32HG322F64 diff --git a/boards/silabs/starter_kits/slstk3400a/board.yml b/boards/silabs/starter_kits/slstk3400a/board.yml new file mode 100644 index 0000000000000..e6573ac89f5d3 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3400a/board.yml @@ -0,0 +1,5 @@ +board: + name: slstk3400a + vendor: silabs + socs: + - name: efm32hg322f64 diff --git a/boards/silabs/starter_kits/slstk3400a/doc/index.rst b/boards/silabs/starter_kits/slstk3400a/doc/index.rst new file mode 100644 index 0000000000000..a48cc3f65faa7 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3400a/doc/index.rst @@ -0,0 +1,176 @@ +.. _slstk3400a: + +EFM32 Happy Gecko (SLSTK3400A) +############################## + +Overview +******** + +The EFM32 Happy Gecko Starter Kit SLSTK3400A contains a MCU from the +EFM32HG family built on ARM® Cortex®-M0+ processor with excellent low +power capabilities. + +.. figure:: slstk3400a.jpg + :align: center + :alt: SLSTK3400A + + SLSTK3400A (image courtesy of Silicon Labs) + +Hardware +******** + +- Advanced Energy Monitoring system for precise current tracking +- Real-time energy and power profiling +- ARM Cortex M0+ with 64 kB Flash and 8 kB RAM +- 128 X 128 pixel Memory LCD +- 2 user buttons, 2 user LEDs and 2 touch buttons +- 20 pin expansion header +- Silicon Labs Si7021 Relative Humidity/Temperature sensor +- USB device interface +- Integrated SEGGER J-Link USB debugger/emulator with debug out functionality + + +See these documents for more information + +- `EFM32HG Website`_ +- `EFM32HG Datasheet`_ +- `EFM32HG Reference Manual`_ +- `SLSTK3400A Website`_ +- `SLSTK3400A User Guide`_ +- `SLSTK3400A Schematics`_ + +Supported Features +================== + +The efm32hg_slstk3400 board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| USART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/starter_kit/slstk3400a/slstk3400a_defconfig` + +Other hardware features are currently not supported by the port. + +Connections and IOs +=================== + +The EFM32HG SoC has six GPIO controllers (PORTA to PORTF), but only three are +currently enabled (PORTB, PORTE and PORTF) for the SLSTK3400A board. + +In the following table, the column Name contains Pin names. For example, PF4 +means Pin number 4 on PORTF, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PF4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PF5 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PC9 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PC10 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PF7 | GPIO | Board Controller Enable | +| | | EFM_BC_EN | ++-------+-------------+-------------------------------------+ +| PF2 | USART0_TX | USART Console EFM_BC_TX U0_TX #4 | ++-------+-------------+-------------------------------------+ +| PA9 | USART0_RX | USART Console EFM_BC_RX U0_RX #4 | ++-------+-------------+-------------------------------------+ + +System Clock +============ + +The EFM32HG SoC is configured to use the 24 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFM32HG SoC has two USARTs, two UARTs and two Low Energy UARTs (LEUART). +USART1 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The SLSTK3400 includes an `J-Link`_ serial and debug adaptor built into the +board. The adaptor provides: + +- A USB connection to the host computer, which exposes a Mass Storage and a + USB Serial Port. +- A Serial Flash device, which implements the USB flash disk file storage. +- A physical UART connection which is relayed over interface USB Serial port. + +Flashing an application to EFM32-SLSTK3400A +------------------------------------------- + +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slstk3400a + :goals: build + +Connect the SLSTK3400A to your host computer using the USB port and +you should see a USB connection that exposes a mass storage device (STK3400) +and a USB Serial Port. Copy the generated ``zephyr.bin`` in the STK3400 drive. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you will see this message written to the serial port: + +.. code-block:: console + + Hello World! slstk3400a + + +.. _SLSTK3400A Website: + https://www.silabs.com/products/development-tools/mcu/32-bit/efm32-happy-gecko-starter-kit + +.. _SLSTK3400A User Guide: + https://www.silabs.com/documents/public/user-guides/ug255-stk3400-user-guide.pdf + +.. _SLSTK3400A Schematics: + https://www.silabs.com/documents/public/schematic-files/BRD2012A-B01-schematic.pdf + +.. _EFM32HG Website: + https://www.silabs.com/products/mcu/32-bit/efm32-happy-gecko + +.. _EFM32HG Datasheet: + https://www.silabs.com/documents/public/data-sheets/EFM32HG322.pdf + +.. _EFM32HG Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/EFM32HG-RM.pdf + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32hg_slstk3400a/doc/efm32hg_slstk3400a.jpg b/boards/silabs/starter_kits/slstk3400a/doc/slstk3400a.jpg similarity index 100% rename from boards/silabs/efm32hg_slstk3400a/doc/efm32hg_slstk3400a.jpg rename to boards/silabs/starter_kits/slstk3400a/doc/slstk3400a.jpg diff --git a/boards/silabs/starter_kits/slstk3400a/slstk3400a.dts b/boards/silabs/starter_kits/slstk3400a/slstk3400a.dts new file mode 100644 index 0000000000000..d7baf87f753c8 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3400a/slstk3400a.dts @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017 Christian Taedcke + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include + +/ { + model = "Silicon Labs EFM32HG SLSTK3400A board"; + compatible = "silabs,slstk3400a", "silabs,efm32hg"; + + chosen { + zephyr,console = &usart1; + zephyr,shell-uart = &usart1; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + sw1 = &button1; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpiof 4 0>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpiof 5 0>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + /* gpio flags need validation */ + gpios = <&gpioc 9 GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + /* gpio flags need validation */ + gpios = <&gpioc 10 GPIO_ACTIVE_LOW>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; + +}; + +&cpu0 { + clock-frequency = <24000000>; +}; + +&gpioa { + status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <9 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&gpioc { + status = "okay"; +}; + +&gpiof { + status = "okay"; +}; + +&usart1 { + current-speed = <115200>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 4Kb of storage at the end of the 64Kb of flash */ + storage_partition: partition@f000 { + label = "storage"; + reg = <0x0000f000 0x00001000>; + }; + + }; +}; diff --git a/boards/silabs/starter_kits/slstk3400a/slstk3400a.yaml b/boards/silabs/starter_kits/slstk3400a/slstk3400a.yaml new file mode 100644 index 0000000000000..0739c38d85875 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3400a/slstk3400a.yaml @@ -0,0 +1,18 @@ +identifier: slstk3400a +name: EFM32 Happy Gecko Starter Kit (SLSTK3400A) +type: mcu +arch: arm +ram: 8 +flash: 64 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio + - nvs +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efm32hg_slstk3400a/efm32hg_slstk3400a_defconfig b/boards/silabs/starter_kits/slstk3400a/slstk3400a_defconfig similarity index 100% rename from boards/silabs/efm32hg_slstk3400a/efm32hg_slstk3400a_defconfig rename to boards/silabs/starter_kits/slstk3400a/slstk3400a_defconfig diff --git a/boards/silabs/starter_kits/slstk3401a/Kconfig.defconfig b/boards/silabs/starter_kits/slstk3401a/Kconfig.defconfig new file mode 100644 index 0000000000000..992f7da89d4fb --- /dev/null +++ b/boards/silabs/starter_kits/slstk3401a/Kconfig.defconfig @@ -0,0 +1,14 @@ +# EFM32PG SLSTK3401A board + +# Copyright (c) 2020, Rafael Dias Menezes +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLSTK3401A + +config CMU_HFXO_FREQ + default 40000000 + +config CMU_LFXO_FREQ + default 32768 + +endif # BOARD_SLSTK3401A diff --git a/boards/silabs/starter_kits/slstk3401a/Kconfig.slstk3401a b/boards/silabs/starter_kits/slstk3401a/Kconfig.slstk3401a new file mode 100644 index 0000000000000..ef6df9553d6ad --- /dev/null +++ b/boards/silabs/starter_kits/slstk3401a/Kconfig.slstk3401a @@ -0,0 +1,7 @@ +# EFM32PG SLSTK3401A board + +# Copyright (c) 2020, Rafael Dias Menezes +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLSTK3401A + select SOC_PART_NUMBER_EFM32PG1B200F256GM48 diff --git a/boards/silabs/efm32pg_stk3401a/board.cmake b/boards/silabs/starter_kits/slstk3401a/board.cmake similarity index 100% rename from boards/silabs/efm32pg_stk3401a/board.cmake rename to boards/silabs/starter_kits/slstk3401a/board.cmake diff --git a/boards/silabs/starter_kits/slstk3401a/board.yml b/boards/silabs/starter_kits/slstk3401a/board.yml new file mode 100644 index 0000000000000..98ae08c199216 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3401a/board.yml @@ -0,0 +1,5 @@ +board: + name: slstk3401a + vendor: silabs + socs: + - name: efm32pg1b200f256gm48 diff --git a/boards/silabs/starter_kits/slstk3401a/doc/index.rst b/boards/silabs/starter_kits/slstk3401a/doc/index.rst new file mode 100644 index 0000000000000..2de4948e2175e --- /dev/null +++ b/boards/silabs/starter_kits/slstk3401a/doc/index.rst @@ -0,0 +1,188 @@ +.. _slstk3401a: + +EFM32 Pearl Gecko (SLSTK3401A) +############################## + +Overview +******** + +The EFM32 Pearl Gecko Starter Kit SLSTK3401A contains an MCU from the +EFM32PG family built on an ARM® Cortex®-M4F processor with excellent low +power capabilities. + +.. figure:: slstk3401a.jpg + :align: center + :alt: EFM32PG-SLSTK3401A + + EFM32PG-SLSTK3401A (image courtesy of Silicon Labs) + +Hardware +******** + +- Advanced Energy Monitoring provides real-time information about the energy + consumption of an application or prototype design. +- Ultra low power 128x128 pixel Memory-LCD +- 2 user buttons, 2 LEDs and 2 capacitive buttons +- Humidity and temperature sensor +- On-board Segger J-Link USB debugger + +For more information about the EFM32PG SoC and SLSTK3401A board: + +- `EFM32PG Website`_ +- `EFM32PG1 Datasheet`_ +- `EFM32PG1 Reference Manual`_ +- `SLSTK3401A Website`_ +- `SLSTK3401A User Guide`_ + +Supported Features +================== + +The slstk3401a board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c port-polling | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/starter_kits/slstk3401a/slstk3401a_defconfig` + +Other hardware features are currently not supported by the port. + +Connections and IOs +=================== + +The EFM32PG1 SoC has five GPIO controllers (PORTA to PORTD and PORTF) and +all are enabled for the SLSTK3401A board. + +In the following table, the column **Name** contains pin names. For example, PF4 +means pin number 4 on PORTF, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PF4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PF5 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PF6 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PF7 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PA5 | GPIO | Board Controller Enable | +| | | EFM_BC_EN | ++-------+-------------+-------------------------------------+ +| PA0 | UART_TX | UART TX Console VCOM_TX US0_TX #0 | ++-------+-------------+-------------------------------------+ +| PA1 | UART_RX | UART RX Console VCOM_RX US0_RX #0 | ++-------+-------------+-------------------------------------+ +| PD10 | UART_TX | EXP12_UART_TX LEU0_TX #18 | ++-------+-------------+-------------------------------------+ +| PD11 | UART_RX | EXP14_UART_RX LEU0_RX #18 | ++-------+-------------+-------------------------------------+ +| PC10 | I2C_SDA | ENV_I2C_SDA I2C0_SDA #15 | ++-------+-------------+-------------------------------------+ +| PC11 | I2C_SCL | ENV_I2C_SCL I2C0_SCL #15 | ++-------+-------------+-------------------------------------+ + + +System Clock +============ + +The EFM32PG SoC is configured to use the 40 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFM32PG SoC has two USARTs and one Low Energy UART (LEUART). + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The SLSTK3401A includes an `J-Link`_ serial and debug adaptor built into the +board. The adaptor provides: + +- A USB connection to the host computer, which exposes a mass storage device and a + USB serial port. +- A serial flash device, which implements the USB flash disk file storage. +- A physical UART connection which is relayed over interface USB serial port. + +Flashing an application to SLSTK3401A +------------------------------------- + +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slstk3401a + :goals: build + +Connect the SLSTK3401A to your host computer using the USB port and you +should see a USB connection which exposes a mass storage device(SLSTK3401A). +Copy the generated zephyr.bin to the SLSTK3401A drive. + +Use a USB-to-UART converter such as an FT232/CP2102 to connect to the UART on the +expansion header. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you'll see the following message on the corresponding serial port +terminal session: + +.. code-block:: console + + Hello World! slstk3401a + + +.. _SLSTK3401A Website: + https://www.silabs.com/development-tools/mcu/32-bit/efm32pg1-starter-kit + +.. _SLSTK3401A User Guide: + https://www.silabs.com/documents/public/user-guides/ug154-stk3401-user-guide.pdf + +.. _EFM32PG Website: + https://www.silabs.com/products/mcu/32-bit/efm32-pearl-gecko + +.. _EFM32PG1 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efm32pg1-datasheet.pdf + +.. _EFM32PG1 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efm32pg1-rm.pdf + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32pg_stk3401a/doc/efm32pg_stk3401a.jpg b/boards/silabs/starter_kits/slstk3401a/doc/slstk3401a.jpg similarity index 100% rename from boards/silabs/efm32pg_stk3401a/doc/efm32pg_stk3401a.jpg rename to boards/silabs/starter_kits/slstk3401a/doc/slstk3401a.jpg diff --git a/boards/silabs/starter_kits/slstk3401a/slstk3401a-common.dtsi b/boards/silabs/starter_kits/slstk3401a/slstk3401a-common.dtsi new file mode 100644 index 0000000000000..9b1b8195a105f --- /dev/null +++ b/boards/silabs/starter_kits/slstk3401a/slstk3401a-common.dtsi @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2020 Rafael Dias Menezes + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "slstk3401a-pinctrl.dtsi" + +/ { + model = "Silicon Labs EFM32PG SLSTK3401A board"; + + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpiof 4 0>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpiof 5 0>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + /* gpio flags need validation */ + gpios = <&gpiof 6 GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + /* gpio flags need validation */ + gpios = <&gpiof 7 GPIO_ACTIVE_LOW>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; +}; + +&cpu0 { + clock-frequency = <40000000>; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&leuart0 { + current-speed = <9600>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rtcc0 { + prescaler = <1>; + status = "okay"; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpioa { + status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&gpiof { + status = "okay"; +}; + +&wdog0 { + status = "okay"; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 6Kb of storage at the end of the 256Kb of flash */ + storage_partition: partition@fe800 { + label = "storage"; + reg = <0x0003e800 0x00001800>; + }; + + }; +}; diff --git a/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a-pinctrl.dtsi b/boards/silabs/starter_kits/slstk3401a/slstk3401a-pinctrl.dtsi similarity index 100% rename from boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a-pinctrl.dtsi rename to boards/silabs/starter_kits/slstk3401a/slstk3401a-pinctrl.dtsi diff --git a/boards/silabs/starter_kits/slstk3401a/slstk3401a.dts b/boards/silabs/starter_kits/slstk3401a/slstk3401a.dts new file mode 100644 index 0000000000000..b2afe5d40cf8a --- /dev/null +++ b/boards/silabs/starter_kits/slstk3401a/slstk3401a.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020 Rafael Dias Menezes + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "slstk3401a-common.dtsi" + +/ { + model = "Silicon Labs EFM32PG SLSTK3401A board"; + compatible = "silabs,slstk3401a", "silabs,efm32pg1b"; +}; diff --git a/boards/silabs/starter_kits/slstk3401a/slstk3401a.yaml b/boards/silabs/starter_kits/slstk3401a/slstk3401a.yaml new file mode 100644 index 0000000000000..c2eab5f1756f5 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3401a/slstk3401a.yaml @@ -0,0 +1,20 @@ +identifier: slstk3401a +name: EFM32 Pearl Gecko Starter Kit (SLSTK3401A) +type: mcu +arch: arm +ram: 32 +flash: 256 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - i2c + - gpio + - nvs + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a_defconfig b/boards/silabs/starter_kits/slstk3401a/slstk3401a_defconfig similarity index 100% rename from boards/silabs/efm32pg_stk3401a/efm32pg_stk3401a_defconfig rename to boards/silabs/starter_kits/slstk3401a/slstk3401a_defconfig diff --git a/boards/silabs/starter_kits/slstk3402a/Kconfig.defconfig b/boards/silabs/starter_kits/slstk3402a/Kconfig.defconfig new file mode 100644 index 0000000000000..87181e6b602ad --- /dev/null +++ b/boards/silabs/starter_kits/slstk3402a/Kconfig.defconfig @@ -0,0 +1,15 @@ +# EFM32PG12 SLSTK3402A board + +# Copyright (c) 2018, Christian Taedcke +# Copyright (c) 2019 Lemonbeat GmbH +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLSTK3402A + +config CMU_HFXO_FREQ + default 40000000 + +config CMU_LFXO_FREQ + default 32768 + +endif # BOARD_SLSTK3402A diff --git a/boards/silabs/starter_kits/slstk3402a/Kconfig.slstk3402a b/boards/silabs/starter_kits/slstk3402a/Kconfig.slstk3402a new file mode 100644 index 0000000000000..e4d6444823bc5 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3402a/Kconfig.slstk3402a @@ -0,0 +1,9 @@ +# EFM32PG12 SLSTK3402A board + +# Copyright (c) 2018, Christian Taedcke +# Copyright (c) 2019 Lemonbeat GmbH +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLSTK3402A + select SOC_PART_NUMBER_EFM32PG12B500F1024GL125 if BOARD_SLSTK3402A_EFM32PG12B500F1024GL125 + select SOC_PART_NUMBER_EFM32JG12B500F1024GL125 if BOARD_SLSTK3402A_EFM32JG12B500F1024GL125 diff --git a/boards/silabs/efm32pg_stk3402a/board.cmake b/boards/silabs/starter_kits/slstk3402a/board.cmake similarity index 100% rename from boards/silabs/efm32pg_stk3402a/board.cmake rename to boards/silabs/starter_kits/slstk3402a/board.cmake diff --git a/boards/silabs/starter_kits/slstk3402a/board.yml b/boards/silabs/starter_kits/slstk3402a/board.yml new file mode 100644 index 0000000000000..539af134c6d8b --- /dev/null +++ b/boards/silabs/starter_kits/slstk3402a/board.yml @@ -0,0 +1,6 @@ +board: + name: slstk3402a + vendor: silabs + socs: + - name: efm32pg12b500f1024gl125 + - name: efm32jg12b500f1024gl125 diff --git a/boards/silabs/starter_kits/slstk3402a/doc/index.rst b/boards/silabs/starter_kits/slstk3402a/doc/index.rst new file mode 100644 index 0000000000000..8d6193e85cdc7 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3402a/doc/index.rst @@ -0,0 +1,214 @@ +.. _slstk3402a: + +EFM32 Pearl Gecko 12 (SLSTK3402A) +################################# + +Overview +******** + +The EFM32 Pearl Gecko 12 Starter Kit SLSTK3402A contains an MCU from the +EFM32PG family built on an ARM® Cortex®-M4F processor with excellent low +power capabilities. + +.. figure:: slstk3402a.jpg + :align: center + :alt: SLSTK3402A + + EFM32PG12 SLSTK3402A (image courtesy of Silicon Labs) + +Hardware +******** + +- Advanced Energy Monitoring provides real-time information about the energy + consumption of an application or prototype design. +- Ultra low power 128x128 pixel Memory-LCD +- 2 user buttons, 2 LEDs and a touch slider +- Humidity, temperature, and inductive-capacitive metal sensor +- On-board Segger J-Link USB debugger + +For more information about the EFM32PG SoC and SLSTK3402A board: + +- `EFM32PG Website`_ +- `EFM32PG12 Datasheet`_ +- `EFM32PG12 Reference Manual`_ +- `SLSTK3402A Website`_ +- `SLSTK3402A User Guide`_ +- `SLSTK3402A Schematics`_ + +Supported Features +================== + +The slstk3402a board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c port-polling | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | watchdog | ++-----------+------------+-------------------------------------+ +| TRNG | on-chip | true random number generator | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32pg12b500f1024gl125_defconfig` + +The default configuration when building using this board to develop for the +EFM32JG12 SoC can be found in +:zephyr_file:`boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32jg12b500f1024gl125_defconfig` + +Other hardware features are currently not supported by the port. + +EFM32 Jade Gecko SoC +-------------------- + +The EFM32 Pearl Gecko Starter Kit SLSTK3402A can also be used to evaluate +the EFM32 Jade Gecko SoC (EFM32JG12). The only difference between the Pearl +Gecko and the Jade Gecko is their core. The Pearl Gecko contains an ARM® +Cortex®-M4F core, and the Jade Gecko an ARM® Cortex®-M3 core. Other features +such as memory and peripherals are the same. + +Code that is built for the Jade Gecko also runs on an equivalent Pearl Gecko. + +To build firmware for the Jade Gecko and run it on the EFM32 Pearl Gecko Starter +Kit, use the board ``slstk3402a/efm32jg12b500f1024gl125`` instead of +``slstk3402a/efm32pg12b500f1024gl125``. + +Connections and IOs +=================== + +The EFM32PG12 SoC has twelve GPIO controllers (PORTA to PORTL), but only four +are currently enabled (PORTA, PORTB, PORTD and PORTF) for the SLSTK3402A +board. + +In the following table, the column **Name** contains pin names. For example, PE2 +means pin number 2 on PORTE, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PF4 | GPIO | LED0 | ++-------+-------------+-------------------------------------+ +| PF5 | GPIO | LED1 | ++-------+-------------+-------------------------------------+ +| PF6 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PF7 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PA5 | GPIO | Board Controller Enable | +| | | EFM_BC_EN | ++-------+-------------+-------------------------------------+ +| PA0 | UART_TX | UART TX Console VCOM_TX US0_TX #0 | ++-------+-------------+-------------------------------------+ +| PA1 | UART_RX | UART RX Console VCOM_RX US0_RX #0 | ++-------+-------------+-------------------------------------+ +| PD10 | UART_TX | EXP12_UART_TX LEU0_TX #18 | ++-------+-------------+-------------------------------------+ +| PD11 | UART_RX | EXP14_UART_RX LEU0_RX #18 | ++-------+-------------+-------------------------------------+ +| PC10 | I2C_SDA | ENV_I2C_SDA I2C0_SDA #15 | ++-------+-------------+-------------------------------------+ +| PC11 | I2C_SCL | ENV_I2C_SCL I2C0_SCL #15 | ++-------+-------------+-------------------------------------+ + + +System Clock +============ + +The EFM32PG12 SoC is configured to use the 40 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFM32PG12 SoC has four USARTs and one Low Energy UART (LEUART). + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The SLSTK3402A includes an `J-Link`_ serial and debug adaptor built into the +board. The adaptor provides: + +- A USB connection to the host computer, which exposes a mass storage device and a + USB serial port. +- A serial flash device, which implements the USB flash disk file storage. +- A physical UART connection which is relayed over interface USB serial port. + +Flashing an application to SLSTK3402A +------------------------------------- + +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slstk3402a/efm32pg12b500f1024gl125 + :goals: build + +Connect the SLSTK3402A to your host computer using the USB port and you +should see a USB connection which exposes a mass storage device(STK3402A). +Copy the generated zephyr.bin to the STK3402A drive. + +Use a USB-to-UART converter such as an FT232/CP2102 to connect to the UART on the +expansion header. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you'll see the following message on the corresponding serial port +terminal session: + +.. code-block:: console + + Hello World! slstk3402a + + +.. _SLSTK3402A Website: + https://www.silabs.com/products/development-tools/mcu/32-bit/efm32-pearl-gecko-pg12-starter-kit + +.. _SLSTK3402A User Guide: + https://www.silabs.com/documents/public/user-guides/ug257-stk3402-usersguide.pdf + +.. _SLSTK3402A Schematics: + https://www.silabs.com/documents/public/schematic-files/BRD2501A-A01-schematic.pdf + +.. _EFM32PG Website: + https://www.silabs.com/products/mcu/32-bit/efm32-pearl-gecko + +.. _EFM32PG12 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efm32pg12-datasheet.pdf + +.. _EFM32PG12 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efm32pg12-rm.pdf + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32pg_stk3402a/doc/efm32pg_stk3402a.jpg b/boards/silabs/starter_kits/slstk3402a/doc/slstk3402a.jpg similarity index 100% rename from boards/silabs/efm32pg_stk3402a/doc/efm32pg_stk3402a.jpg rename to boards/silabs/starter_kits/slstk3402a/doc/slstk3402a.jpg diff --git a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a-pinctrl.dtsi b/boards/silabs/starter_kits/slstk3402a/slstk3402a-pinctrl.dtsi similarity index 100% rename from boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a-pinctrl.dtsi rename to boards/silabs/starter_kits/slstk3402a/slstk3402a-pinctrl.dtsi diff --git a/boards/silabs/starter_kits/slstk3402a/slstk3402a_common.dtsi b/boards/silabs/starter_kits/slstk3402a/slstk3402a_common.dtsi new file mode 100644 index 0000000000000..db100cd289b3e --- /dev/null +++ b/boards/silabs/starter_kits/slstk3402a/slstk3402a_common.dtsi @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2017 Christian Taedcke + * Copyright (c) 2019 Lemonbeat GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "slstk3402a-pinctrl.dtsi" +#include + +/ { + model = "Silicon Labs EFM32PG12 STK3402A board"; + + chosen { + zephyr,console = &usart0; + zephyr,shell-uart = &usart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + pwm-led0 = &pwm_led0; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + watchdog1 = &wdog1; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpiof 4 0>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpiof 5 0>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + /* gpio flags need validation */ + gpios = <&gpiof 6 GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + /* gpio flags need validation */ + gpios = <&gpiof 7 GPIO_ACTIVE_LOW>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + status = "okay"; + pwm_led0: pwm_led0 { + pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; +}; + +&cpu0 { + clock-frequency = <40000000>; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&leuart0 { + current-speed = <9600>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rtcc0 { + prescaler = <1>; + status = "okay"; +}; + +&timer0 { + status = "okay"; + + pwm0: pwm { + status = "okay"; + pin-location = ; + prescaler = <1024>; + }; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpioa { + status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <5 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&gpiob { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&gpiof { + status = "okay"; +}; + +&wdog0 { + status = "okay"; +}; + +&wdog1 { + status = "okay"; +}; + + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 6Kb of storage at the end of the 1024Kb of flash */ + storage_partition: partition@fe800 { + label = "storage"; + reg = <0x000fe800 0x00001800>; + }; + + }; +}; + +&trng0 { + status = "okay"; +}; + +&adc0 { + status = "okay"; +}; diff --git a/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32jg12b500f1024gl125.dts b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32jg12b500f1024gl125.dts new file mode 100644 index 0000000000000..184c3c51a07da --- /dev/null +++ b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32jg12b500f1024gl125.dts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019 Lemonbeat GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "slstk3402a_common.dtsi" + +/ { + model = "Silicon Labs EFM32JG12 STK3402A board "; + compatible = "silabs,slstk3402a_jg", "silabs,efm32jg12b"; + +}; diff --git a/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32jg12b500f1024gl125.yaml b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32jg12b500f1024gl125.yaml new file mode 100644 index 0000000000000..f698109150093 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32jg12b500f1024gl125.yaml @@ -0,0 +1,19 @@ +identifier: slstk3402a/efm32jg12b500f1024gl125 +name: EFM32JG12 SLSTK3402A +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - i2c + - gpio + - nvs +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32jg12b500f1024gl125_defconfig b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32jg12b500f1024gl125_defconfig similarity index 100% rename from boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32jg12b500f1024gl125_defconfig rename to boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32jg12b500f1024gl125_defconfig diff --git a/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32pg12b500f1024gl125.dts b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32pg12b500f1024gl125.dts new file mode 100644 index 0000000000000..a35289d0cbf49 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32pg12b500f1024gl125.dts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017 Christian Taedcke + * Copyright (c) 2019 Lemonbeat GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "slstk3402a_common.dtsi" + +/ { + model = "Silicon Labs EFM32PG12 SLSTK3402A board"; + compatible = "silabs,slstk3402a", "silabs,efm32pg12b"; +}; diff --git a/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32pg12b500f1024gl125.yaml b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32pg12b500f1024gl125.yaml new file mode 100644 index 0000000000000..1ce7433a7aa49 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32pg12b500f1024gl125.yaml @@ -0,0 +1,20 @@ +identifier: slstk3402a/efm32pg12b500f1024gl125 +name: EFM32PG12 SLSTK3402A +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - i2c + - gpio + - nvs + - watchdog +testing: + ignore_tags: + - net + - bluetooth +vendor: silabs diff --git a/boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32pg12b500f1024gl125_defconfig b/boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32pg12b500f1024gl125_defconfig similarity index 100% rename from boards/silabs/efm32pg_stk3402a/efm32pg_stk3402a_efm32pg12b500f1024gl125_defconfig rename to boards/silabs/starter_kits/slstk3402a/slstk3402a_efm32pg12b500f1024gl125_defconfig diff --git a/boards/silabs/efm32gg_stk3701a/CMakeLists.txt b/boards/silabs/starter_kits/slstk3701a/CMakeLists.txt similarity index 100% rename from boards/silabs/efm32gg_stk3701a/CMakeLists.txt rename to boards/silabs/starter_kits/slstk3701a/CMakeLists.txt diff --git a/boards/silabs/starter_kits/slstk3701a/Kconfig.defconfig b/boards/silabs/starter_kits/slstk3701a/Kconfig.defconfig new file mode 100644 index 0000000000000..24d55ad5a9b35 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3701a/Kconfig.defconfig @@ -0,0 +1,28 @@ +# EFM32GG STK3701A default board configuration +# Copyright (c) 2019 Interay Solutions B.V. +# Copyright (c) 2019 Oane Kingma +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SLSTK3701A + +config CMU_HFXO_FREQ + default 50000000 + +config CMU_HFRCO_FREQ + default 72000000 + +config CMU_LFXO_FREQ + default 32768 + +config LOG_BACKEND_SWO_FREQ_HZ + default 875000 + depends on LOG_BACKEND_SWO + +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + +endif # BOARD_SLSTK3701A diff --git a/boards/silabs/starter_kits/slstk3701a/Kconfig.slstk3701a b/boards/silabs/starter_kits/slstk3701a/Kconfig.slstk3701a new file mode 100644 index 0000000000000..e0fd2b5412ee8 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3701a/Kconfig.slstk3701a @@ -0,0 +1,7 @@ +# EFM32GG11 SLSTK3701A board configuration +# Copyright (c) 2019 Interay Solutions B.V. +# Copyright (c) 2019 Oane Kingma +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_SLSTK3701A + select SOC_PART_NUMBER_EFM32GG11B820F2048GL192 diff --git a/boards/silabs/efm32gg_stk3701a/board.c b/boards/silabs/starter_kits/slstk3701a/board.c similarity index 100% rename from boards/silabs/efm32gg_stk3701a/board.c rename to boards/silabs/starter_kits/slstk3701a/board.c diff --git a/boards/silabs/efm32gg_stk3701a/board.cmake b/boards/silabs/starter_kits/slstk3701a/board.cmake similarity index 100% rename from boards/silabs/efm32gg_stk3701a/board.cmake rename to boards/silabs/starter_kits/slstk3701a/board.cmake diff --git a/boards/silabs/efm32gg_stk3701a/board.h b/boards/silabs/starter_kits/slstk3701a/board.h similarity index 100% rename from boards/silabs/efm32gg_stk3701a/board.h rename to boards/silabs/starter_kits/slstk3701a/board.h diff --git a/boards/silabs/starter_kits/slstk3701a/board.yml b/boards/silabs/starter_kits/slstk3701a/board.yml new file mode 100644 index 0000000000000..5c1db884a42bb --- /dev/null +++ b/boards/silabs/starter_kits/slstk3701a/board.yml @@ -0,0 +1,5 @@ +board: + name: slstk3701a + vendor: silabs + socs: + - name: efm32gg11b820f2048gl192 diff --git a/boards/silabs/starter_kits/slstk3701a/doc/index.rst b/boards/silabs/starter_kits/slstk3701a/doc/index.rst new file mode 100644 index 0000000000000..d270bf346c240 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3701a/doc/index.rst @@ -0,0 +1,200 @@ +.. _efm32gg_stk3701a: + +EFM32 Giant Gecko 11 (SLSTK3701A) +################################# + +Overview +******** + +The EFM32 Giant Gecko Starter Kit SLSTK3701A contains an MCU from the +EFM32GG Series 1 family built on an ARM® Cortex®-M4F processor with excellent +low power capabilities. + +.. figure:: slstk3701a.jpg + :align: center + :alt: EFM32GG11 SLSTK3701A + + EFM32GG11 SLSTK3701A (image courtesy of Silicon Labs) + +Hardware +******** + +- Advanced Energy Monitoring provides real-time information about the energy + consumption of an application or prototype design. +- Ultra low power 128x128 pixel color Memory-LCD +- 2 user buttons, 2 LEDs and a touch slider +- Relative humidity, magnetic Hall Effect and inductive-capacitive metal sensor +- USB interface for Host/Device/OTG +- 32 Mb Quad-SPI Flash memory +- SD card slot +- RJ-45 Ethernet jack +- 2 digital microphones +- On-board Segger J-Link USB debugger + +For more information about the EFM32GG11 SoC and SLSTK3701A board: + +- `EFM32GG Series 1 Website`_ +- `EFM32GG11 Datasheet`_ +- `EFM32GG11 Reference Manual`_ +- `SLSTK3701A Website`_ +- `SLSTK3701A User Guide`_ +- `SLSTK3701A Schematics`_ + +Supported Features +================== + +The slstk3701a board configuration supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| MPU | on-chip | memory protection unit | ++-----------+------------+-------------------------------------+ +| COUNTER | on-chip | rtcc | ++-----------+------------+-------------------------------------+ +| ETHERNET | on-chip | ethernet | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash memory | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c port-polling | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | systick | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ + +The default configuration can be found in +:zephyr_file:`boards/silabs/starter_kits/slstk3701a/slstk3701a_defconfig` + +Other hardware features are currently not supported by the port. + +Connections and IOs +=================== + +The EFM32GG11 SoC has nine GPIO controllers (PORTA to PORTI), all of which are +currently enabled for the SLSTK3701A board. + +In the following table, the column **Name** contains pin names. For example, PE1 +means pin number 1 on PORTE, as used in the board's datasheets and manuals. + ++-------+-------------+-------------------------------------+ +| Name | Function | Usage | ++=======+=============+=====================================+ +| PH10 | GPIO | LED0 red | ++-------+-------------+-------------------------------------+ +| PH11 | GPIO | LED0 green | ++-------+-------------+-------------------------------------+ +| PH12 | GPIO | LED0 blue | ++-------+-------------+-------------------------------------+ +| PH13 | GPIO | LED1 red | ++-------+-------------+-------------------------------------+ +| PH14 | GPIO | LED1 green | ++-------+-------------+-------------------------------------+ +| PH15 | GPIO | LED1 blue | ++-------+-------------+-------------------------------------+ +| PC8 | GPIO | Push Button PB0 | ++-------+-------------+-------------------------------------+ +| PC9 | GPIO | Push Button PB1 | ++-------+-------------+-------------------------------------+ +| PE1 | GPIO | Board Controller Enable | +| | | EFM_BC_EN | ++-------+-------------+-------------------------------------+ +| PH4 | UART_TX | UART TX Console VCOM_TX US0_TX #4 | ++-------+-------------+-------------------------------------+ +| PH5 | UART_RX | UART RX Console VCOM_RX US0_RX #4 | ++-------+-------------+-------------------------------------+ +| PI4 | I2C_SDA | SENSOR_I2C_SDA I2C2_SDA #7 | ++-------+-------------+-------------------------------------+ +| PI5 | I2C_SCL | SENSOR_I2C_SCL I2C2_SCL #7 | ++-------+-------------+-------------------------------------+ + + +System Clock +============ + +The EFM32GG11 SoC is configured to use the 50 MHz external oscillator on the +board. + +Serial Port +=========== + +The EFM32GG11 SoC has six USARTs, two UARTs and two Low Energy UARTs (LEUART). +USART4 is connected to the board controller and is used for the console. + +Programming and Debugging +************************* + +.. note:: + Before using the kit the first time, you should update the J-Link firmware + from `J-Link-Downloads`_ + +Flashing +======== + +The SLSTK3701A includes an `J-Link`_ serial and debug adaptor built into the +board. The adaptor provides: + +- A USB connection to the host computer, which exposes a mass storage device and a + USB serial port. +- A serial flash device, which implements the USB flash disk file storage. +- A physical UART connection which is relayed over interface USB serial port. + +Flashing an application to SLSTK3701A +------------------------------------- + +The sample application :ref:`hello_world` is used for this example. +Build the Zephyr kernel and application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: slstk3701a + :goals: build + +Connect the SLSTK3701A to your host computer using the USB port and you +should see a USB connection which exposes a mass storage device(STK3701A) and +a USB Serial Port. Copy the generated zephyr.bin to the STK3701A drive. + +Open a serial terminal (minicom, putty, etc.) with the following settings: + +- Speed: 115200 +- Data: 8 bits +- Parity: None +- Stop bits: 1 + +Reset the board and you'll see the following message on the corresponding serial port +terminal session: + +.. code-block:: console + + Hello World! slstk3701a + + +.. _SLSTK3701A Website: + https://www.silabs.com/products/development-tools/mcu/32-bit/efm32-giant-gecko-gg11-starter-kit + +.. _SLSTK3701A User Guide: + https://www.silabs.com/documents/public/user-guides/ug287-stk3701.pdf + +.. _SLSTK3701A Schematics: + https://www.silabs.com/documents/public/schematic-files/BRD2204A-B00-schematic.pdf + +.. _EFM32GG Series 1 Website: + https://www.silabs.com/products/mcu/32-bit/efm32-giant-gecko-s1 + +.. _EFM32GG11 Datasheet: + https://www.silabs.com/documents/public/data-sheets/efm32gg11-datasheet.pdf + +.. _EFM32GG11 Reference Manual: + https://www.silabs.com/documents/public/reference-manuals/efm32gg11-rm.pdf + +.. _J-Link: + https://www.segger.com/jlink-debug-probes.html + +.. _J-Link-Downloads: + https://www.segger.com/downloads/jlink diff --git a/boards/silabs/efm32gg_stk3701a/doc/efm32gg_stk3701a.jpg b/boards/silabs/starter_kits/slstk3701a/doc/slstk3701a.jpg similarity index 100% rename from boards/silabs/efm32gg_stk3701a/doc/efm32gg_stk3701a.jpg rename to boards/silabs/starter_kits/slstk3701a/doc/slstk3701a.jpg diff --git a/boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a-pinctrl.dtsi b/boards/silabs/starter_kits/slstk3701a/slstk3701a-pinctrl.dtsi similarity index 100% rename from boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a-pinctrl.dtsi rename to boards/silabs/starter_kits/slstk3701a/slstk3701a-pinctrl.dtsi diff --git a/boards/silabs/starter_kits/slstk3701a/slstk3701a.dts b/boards/silabs/starter_kits/slstk3701a/slstk3701a.dts new file mode 100644 index 0000000000000..1e67f024d7f43 --- /dev/null +++ b/boards/silabs/starter_kits/slstk3701a/slstk3701a.dts @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2019 Interay Solutions B.V. + * Copyright (c) 2019 Oane Kingma + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "slstk3701a-pinctrl.dtsi" + +/ { + model = "Silicon Labs EFM32GG11 SLSTK3701A board"; + compatible = "silabs,slstk3701a", "silabs,efm32gg11b"; + + chosen { + zephyr,console = &usart4; + zephyr,shell-uart = &usart4; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + led1 = &led1; + sw0 = &button0; + sw1 = &button1; + watchdog0 = &wdog0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpioh 10 GPIO_ACTIVE_LOW>; + label = "LED 0"; + }; + led1: led_1 { + gpios = <&gpioh 13 GPIO_ACTIVE_LOW>; + label = "LED 1"; + }; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + /* gpio flags need validation */ + gpios = <&gpioc 8 GPIO_ACTIVE_LOW>; + label = "User Push Button 0"; + zephyr,code = ; + }; + button1: button_1 { + /* gpio flags need validation */ + gpios = <&gpioc 9 GPIO_ACTIVE_LOW>; + label = "User Push Button 1"; + zephyr,code = ; + }; + }; +}; + +&usart0 { + current-speed = <115200>; + pinctrl-0 = <&usart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&usart4 { + current-speed = <115200>; + pinctrl-0 = <&usart4_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&leuart0 { + current-speed = <9600>; + location-rx = ; + location-tx = ; + status = "okay"; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&rtcc0 { + prescaler = <1>; + status = "okay"; +}; + +&gpio { + location-swo = <0>; + status = "okay"; +}; + +&gpioa { + status = "okay"; +}; + +&gpiob { + status = "okay"; +}; + +&gpioc { + status = "okay"; +}; + +&gpiod { + status = "okay"; +}; + +&gpioe { + status = "okay"; + + board-controller-enable { + gpio-hog; + gpios = <1 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +&gpiof { + status = "okay"; +}; + +&gpiog { + status = "okay"; +}; + +&gpioh { + status = "okay"; +}; + +&gpioi { + status = "okay"; +}; + +ð0 { + /* PHY address = 0 */ + phy-address = <0>; + + /* PHY management pins */ + location-mdio = ; + location-phy_mdc = ; + location-phy_mdio = ; + + /* RMII interface pins */ + location-rmii = ; + location-rmii_refclk = ; + location-rmii_crs_dv = ; + location-rmii_txd0 = ; + location-rmii_txd1 = ; + location-rmii_tx_en = ; + location-rmii_rxd0 = ; + location-rmii_rxd1 = ; + location-rmii_rx_er = ; + + status = "okay"; +}; + +&flash0 { + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Set 12Kb of storage at the end of the 2048Kb of flash */ + storage_partition: partition@1fd000 { + label = "storage"; + reg = <0x001fd000 0x00003000>; + }; + }; +}; + +&wdog0 { + status = "okay"; +}; + +&trng0 { + status = "okay"; +}; + +&cpu0 { + clock-frequency = <72000000>; +}; diff --git a/boards/silabs/starter_kits/slstk3701a/slstk3701a.yaml b/boards/silabs/starter_kits/slstk3701a/slstk3701a.yaml new file mode 100644 index 0000000000000..bfad741b9183b --- /dev/null +++ b/boards/silabs/starter_kits/slstk3701a/slstk3701a.yaml @@ -0,0 +1,19 @@ +identifier: slstk3701a +name: EFM32GG11 Giant Gecko Starter Kit (SLSTK3701A) +type: mcu +arch: arm +ram: 512 +flash: 2048 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - i2c + - gpio + - netif:eth + - nvs +testing: + ignore_tags: + - bluetooth +vendor: silabs diff --git a/boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a_defconfig b/boards/silabs/starter_kits/slstk3701a/slstk3701a_defconfig similarity index 100% rename from boards/silabs/efm32gg_stk3701a/efm32gg_stk3701a_defconfig rename to boards/silabs/starter_kits/slstk3701a/slstk3701a_defconfig diff --git a/boards/silabs/efm32gg_stk3701a/support/openocd.cfg b/boards/silabs/starter_kits/slstk3701a/support/openocd.cfg similarity index 100% rename from boards/silabs/efm32gg_stk3701a/support/openocd.cfg rename to boards/silabs/starter_kits/slstk3701a/support/openocd.cfg diff --git a/boards/sipeed/longan_nano/doc/index.rst b/boards/sipeed/longan_nano/doc/index.rst index b62d91c313007..6150c2378cf81 100644 --- a/boards/sipeed/longan_nano/doc/index.rst +++ b/boards/sipeed/longan_nano/doc/index.rst @@ -74,6 +74,11 @@ The board configuration supports the following hardware features: * - ADC - :kconfig:option:`CONFIG_ADC` - :dtcompatible:`gd,gd32-adc` + * - SPI + - :kconfig:option:`CONFIG_SPI` + - :dtcompatible:`gd,gd32-spi` + +The microSD card reader in Longan Nano board is connected to SPI1. Serial Port =========== diff --git a/boards/sipeed/longan_nano/longan_nano-common.dtsi b/boards/sipeed/longan_nano/longan_nano-common.dtsi index 6d272ddd53d4f..c5e9202e94f25 100644 --- a/boards/sipeed/longan_nano/longan_nano-common.dtsi +++ b/boards/sipeed/longan_nano/longan_nano-common.dtsi @@ -5,6 +5,7 @@ */ #include +#include / { chosen { @@ -65,6 +66,50 @@ sw0 = &button_boot0; watchdog0 = &fwdgt; }; + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + reset-gpios = <&gpiob 1 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpiob 0 GPIO_ACTIVE_HIGH>; + spi-dev = <&spi0>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + /* longan nano has LCD with st7735s controller. + * It can use with st7735r driver. + */ + lcd0: lcd@0 { + compatible = "sitronix,st7735r"; + reg = <0>; + status = "okay"; + width = <160>; + height = <80>; + inversion-on; + rgb-is-inverted; + x-offset = <1>; + y-offset = <26>; + pwctr1 = [62 02 04]; + pwctr2 = [C0]; + pwctr3 = [0D 00]; + pwctr4 = [8D 6A]; + pwctr5 = [8D EE]; + invctr = <3>; + frmctr1 = [05 3A 3A]; + frmctr2 = [05 3A 3A]; + frmctr3 = [05 3A 3A 05 3A 3A]; + vmctr1 = <14>; + gamctrp1 = [10 0E 02 03 0E 07 02 07 0A 12 27 37 00 0D 0E 10]; + gamctrn1 = [10 0E 03 03 0F 06 02 08 0A 13 26 36 00 0D 0E 10]; + colmod = <5>; + madctl = <120>; + caset = [00 01 00 a0]; + raset = [00 1a 00 69]; + + mipi-mode = ; + mipi-max-frequency = <4000000>; + }; + }; }; &gpioa { @@ -109,41 +154,6 @@ pinctrl-names = "default"; cs-gpios = <&gpiob 2 GPIO_ACTIVE_LOW>; - - /* longan nano has LCD with st7735s controller. - * It can use with st7735r driver. - */ - lcd0: lcd@0 { - compatible = "sitronix,st7735r"; - reg = <0>; - status = "okay"; - reset-gpios = <&gpiob 1 GPIO_ACTIVE_LOW>; - cmd-data-gpios = <&gpiob 0 GPIO_ACTIVE_LOW>; - width = <160>; - height = <80>; - inversion-on; - rgb-is-inverted; - x-offset = <1>; - y-offset = <26>; - pwctr1 = [62 02 04]; - pwctr2 = [C0]; - pwctr3 = [0D 00]; - pwctr4 = [8D 6A]; - pwctr5 = [8D EE]; - invctr = <3>; - frmctr1 = [05 3A 3A]; - frmctr2 = [05 3A 3A]; - frmctr3 = [05 3A 3A 05 3A 3A]; - vmctr1 = <14>; - gamctrp1 = [10 0E 02 03 0E 07 02 07 0A 12 27 37 00 0D 0E 10]; - gamctrn1 = [10 0E 03 03 0F 06 02 08 0A 13 26 36 00 0D 0E 10]; - colmod = <5>; - madctl = <120>; - caset = [00 01 00 a0]; - raset = [00 1a 00 69]; - - spi-max-frequency = <4000000>; - }; }; &spi1 { diff --git a/boards/sipeed/longan_nano/support/openocd.cfg b/boards/sipeed/longan_nano/support/openocd.cfg index 4ebb4a0505b53..c28b90767d736 100644 --- a/boards/sipeed/longan_nano/support/openocd.cfg +++ b/boards/sipeed/longan_nano/support/openocd.cfg @@ -13,7 +13,7 @@ ftdi_vid_pid 0x0403 0x6010 ftdi_layout_init 0x0008 0x001b ftdi_layout_signal nSRST -oe 0x0020 -data 0x0020 -adapter_khz 2000 +adapter speed 2000 transport select jtag proc gd32vf103-pre-load {} { diff --git a/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_2.yaml b/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_2.yaml index 498333044249e..29f4404ca9517 100644 --- a/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_2.yaml +++ b/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_2.yaml @@ -1,5 +1,5 @@ identifier: em_starterkit@2.2/emsk_em7d -name: EM Starterkit EM7D +name: EM Starterkit EM7D (rev. 2.2) type: mcu arch: arc toolchain: diff --git a/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_3.overlay b/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_3.overlay index bb7e6a3ee9bd7..590d0aefb8a8c 100644 --- a/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_3.overlay +++ b/boards/snps/em_starterkit/em_starterkit_emsk_em7d_2_3.overlay @@ -19,7 +19,6 @@ uart-0 = &uart0; uart-1 = &uart1; uart-2 = &uart2; - spi-flash0 = &w25q128bv; }; chosen { diff --git a/boards/snps/em_starterkit/em_starterkit_r23.dtsi b/boards/snps/em_starterkit/em_starterkit_r23.dtsi index 3de7425d97501..ef93abcfd46d3 100644 --- a/boards/snps/em_starterkit/em_starterkit_r23.dtsi +++ b/boards/snps/em_starterkit/em_starterkit_r23.dtsi @@ -5,10 +5,6 @@ */ / { - aliases { - spi-flash0 = &w25q128bv; - }; - soc { i2c@f0004000 { interrupts = <25 1>; diff --git a/boards/snps/emsdp/emsdp_emsdp_em11d.dts b/boards/snps/emsdp/emsdp_emsdp_em11d.dts index 6a24a9ec5bd6f..d3a9a10d0e73a 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em11d.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em11d.dts @@ -17,7 +17,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em4.dts b/boards/snps/emsdp/emsdp_emsdp_em4.dts index 0d0306065c09d..04414f10c6e64 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em4.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em4.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em5d.dts b/boards/snps/emsdp/emsdp_emsdp_em5d.dts index 66a544e95ef76..57ba196e1dde3 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em5d.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em5d.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em6.dts b/boards/snps/emsdp/emsdp_emsdp_em6.dts index 0d0306065c09d..04414f10c6e64 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em6.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em6.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em7d.dts b/boards/snps/emsdp/emsdp_emsdp_em7d.dts index 66a544e95ef76..57ba196e1dde3 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em7d.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em7d.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em7d_esp.dts b/boards/snps/emsdp/emsdp_emsdp_em7d_esp.dts index 89fc30499b7fb..1880de517b964 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em7d_esp.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em7d_esp.dts @@ -15,7 +15,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/emsdp/emsdp_emsdp_em9d.dts b/boards/snps/emsdp/emsdp_emsdp_em9d.dts index c28956b9f6002..c87bfe3e7f6a8 100644 --- a/boards/snps/emsdp/emsdp_emsdp_em9d.dts +++ b/boards/snps/emsdp/emsdp_emsdp_em9d.dts @@ -16,7 +16,6 @@ aliases { uart-0 = &uart0; - spi-flash0 = &s25fl256s; }; chosen { diff --git a/boards/snps/hsdk/hsdk_arc_hsdk_2cores_defconfig b/boards/snps/hsdk/hsdk_arc_hsdk_2cores_defconfig index 711d759a8fd78..bc0a91f60beca 100644 --- a/boards/snps/hsdk/hsdk_arc_hsdk_2cores_defconfig +++ b/boards/snps/hsdk/hsdk_arc_hsdk_2cores_defconfig @@ -9,7 +9,6 @@ CONFIG_ARCV2_TIMER=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y -CONFIG_UART_INTERRUPT_DRIVEN=y -CONFIG_ARC_MPU_ENABLE=y CONFIG_GPIO=y +CONFIG_SMP=y CONFIG_MP_MAX_NUM_CPUS=2 diff --git a/boards/snps/nsim/CMakeLists.txt b/boards/snps/nsim/arc_classic/CMakeLists.txt similarity index 100% rename from boards/snps/nsim/CMakeLists.txt rename to boards/snps/nsim/arc_classic/CMakeLists.txt diff --git a/boards/snps/nsim/Kconfig b/boards/snps/nsim/arc_classic/Kconfig similarity index 100% rename from boards/snps/nsim/Kconfig rename to boards/snps/nsim/arc_classic/Kconfig diff --git a/boards/snps/nsim/Kconfig.nsim b/boards/snps/nsim/arc_classic/Kconfig.nsim similarity index 100% rename from boards/snps/nsim/Kconfig.nsim rename to boards/snps/nsim/arc_classic/Kconfig.nsim diff --git a/boards/snps/nsim/arc_mpu_regions.c b/boards/snps/nsim/arc_classic/arc_mpu_regions.c similarity index 100% rename from boards/snps/nsim/arc_mpu_regions.c rename to boards/snps/nsim/arc_classic/arc_mpu_regions.c diff --git a/boards/snps/nsim/board.cmake b/boards/snps/nsim/arc_classic/board.cmake similarity index 100% rename from boards/snps/nsim/board.cmake rename to boards/snps/nsim/arc_classic/board.cmake diff --git a/boards/snps/nsim/board.yml b/boards/snps/nsim/arc_classic/board.yml similarity index 100% rename from boards/snps/nsim/board.yml rename to boards/snps/nsim/arc_classic/board.yml diff --git a/boards/snps/nsim/doc/index.rst b/boards/snps/nsim/arc_classic/doc/index.rst similarity index 100% rename from boards/snps/nsim/doc/index.rst rename to boards/snps/nsim/arc_classic/doc/index.rst diff --git a/boards/snps/nsim/haps_arcv3_init.c b/boards/snps/nsim/arc_classic/haps_arcv3_init.c similarity index 100% rename from boards/snps/nsim/haps_arcv3_init.c rename to boards/snps/nsim/arc_classic/haps_arcv3_init.c diff --git a/boards/snps/nsim/nsim-ccm-mem.dtsi b/boards/snps/nsim/arc_classic/nsim-ccm-mem.dtsi similarity index 100% rename from boards/snps/nsim/nsim-ccm-mem.dtsi rename to boards/snps/nsim/arc_classic/nsim-ccm-mem.dtsi diff --git a/boards/snps/nsim/nsim-flash-sram-mem.dtsi b/boards/snps/nsim/arc_classic/nsim-flash-sram-mem.dtsi similarity index 100% rename from boards/snps/nsim/nsim-flash-sram-mem.dtsi rename to boards/snps/nsim/arc_classic/nsim-flash-sram-mem.dtsi diff --git a/boards/snps/nsim/nsim-flat-mem.dtsi b/boards/snps/nsim/arc_classic/nsim-flat-mem.dtsi similarity index 100% rename from boards/snps/nsim/nsim-flat-mem.dtsi rename to boards/snps/nsim/arc_classic/nsim-flat-mem.dtsi diff --git a/boards/snps/nsim/nsim-smp.dtsi b/boards/snps/nsim/arc_classic/nsim-smp.dtsi similarity index 100% rename from boards/snps/nsim/nsim-smp.dtsi rename to boards/snps/nsim/arc_classic/nsim-smp.dtsi diff --git a/boards/snps/nsim/nsim-uart-hostlink.dtsi b/boards/snps/nsim/arc_classic/nsim-uart-hostlink.dtsi similarity index 100% rename from boards/snps/nsim/nsim-uart-hostlink.dtsi rename to boards/snps/nsim/arc_classic/nsim-uart-hostlink.dtsi diff --git a/boards/snps/nsim/nsim-uart-ns16550.dtsi b/boards/snps/nsim/arc_classic/nsim-uart-ns16550.dtsi similarity index 100% rename from boards/snps/nsim/nsim-uart-ns16550.dtsi rename to boards/snps/nsim/arc_classic/nsim-uart-ns16550.dtsi diff --git a/boards/snps/nsim/nsim.dtsi b/boards/snps/nsim/arc_classic/nsim.dtsi similarity index 100% rename from boards/snps/nsim/nsim.dtsi rename to boards/snps/nsim/arc_classic/nsim.dtsi diff --git a/boards/snps/nsim/nsim_em-sec.dtsi b/boards/snps/nsim/arc_classic/nsim_em-sec.dtsi similarity index 100% rename from boards/snps/nsim/nsim_em-sec.dtsi rename to boards/snps/nsim/arc_classic/nsim_em-sec.dtsi diff --git a/boards/snps/nsim/nsim_em.dtsi b/boards/snps/nsim/arc_classic/nsim_em.dtsi similarity index 100% rename from boards/snps/nsim/nsim_em.dtsi rename to boards/snps/nsim/arc_classic/nsim_em.dtsi diff --git a/boards/snps/nsim/nsim_nsim_em.dts b/boards/snps/nsim/arc_classic/nsim_nsim_em.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_em.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_em.dts diff --git a/boards/snps/nsim/nsim_nsim_em.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_em.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_em.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_em.yaml diff --git a/boards/snps/nsim/nsim_nsim_em11d.dts b/boards/snps/nsim/arc_classic/nsim_nsim_em11d.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_em11d.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_em11d.dts diff --git a/boards/snps/nsim/nsim_nsim_em11d.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_em11d.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_em11d.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_em11d.yaml diff --git a/boards/snps/nsim/nsim_nsim_em11d_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_em11d_defconfig similarity index 95% rename from boards/snps/nsim/nsim_nsim_em11d_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_em11d_defconfig index 1cdf8a0b67ebd..2146e4d8b06ea 100644 --- a/boards/snps/nsim/nsim_nsim_em11d_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_em11d_defconfig @@ -9,3 +9,4 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_em7d_v22.dts b/boards/snps/nsim/arc_classic/nsim_nsim_em7d_v22.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_em7d_v22.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_em7d_v22.dts diff --git a/boards/snps/nsim/nsim_nsim_em7d_v22.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_em7d_v22.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_em7d_v22.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_em7d_v22.yaml diff --git a/boards/snps/nsim/nsim_nsim_em7d_v22_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_em7d_v22_defconfig similarity index 95% rename from boards/snps/nsim/nsim_nsim_em7d_v22_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_em7d_v22_defconfig index 1cdf8a0b67ebd..2146e4d8b06ea 100644 --- a/boards/snps/nsim/nsim_nsim_em7d_v22_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_em7d_v22_defconfig @@ -9,3 +9,4 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_em_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_em_defconfig similarity index 95% rename from boards/snps/nsim/nsim_nsim_em_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_em_defconfig index 1cdf8a0b67ebd..2146e4d8b06ea 100644 --- a/boards/snps/nsim/nsim_nsim_em_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_em_defconfig @@ -9,3 +9,4 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_ARC_USE_UNALIGNED_MEM_ACCESS=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_hs.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs.dts diff --git a/boards/snps/nsim/nsim_nsim_hs.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs5x.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs5x.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs5x.dts diff --git a/boards/snps/nsim/nsim_nsim_hs5x.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs5x.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs5x.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs5x_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x_defconfig similarity index 94% rename from boards/snps/nsim/nsim_nsim_hs5x_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs5x_defconfig index 5a48971e06d4f..717569e757c97 100644 --- a/boards/snps/nsim/nsim_nsim_hs5x_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x_defconfig @@ -8,3 +8,4 @@ CONFIG_ARCV2_TIMER=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_hs5x_smp.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs5x_smp.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp.dts diff --git a/boards/snps/nsim/nsim_nsim_hs5x_smp.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs5x_smp.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs5x_smp_12cores.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp_12cores.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs5x_smp_12cores.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp_12cores.dts diff --git a/boards/snps/nsim/nsim_nsim_hs5x_smp_12cores.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp_12cores.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs5x_smp_12cores.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp_12cores.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs5x_smp_12cores_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp_12cores_defconfig similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs5x_smp_12cores_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp_12cores_defconfig diff --git a/boards/snps/nsim/nsim_nsim_hs5x_smp_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp_defconfig similarity index 95% rename from boards/snps/nsim/nsim_nsim_hs5x_smp_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp_defconfig index c55df123e9fde..0b02b73960aec 100644 --- a/boards/snps/nsim/nsim_nsim_hs5x_smp_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_hs5x_smp_defconfig @@ -11,3 +11,4 @@ CONFIG_SERIAL=y CONFIG_SMP=y CONFIG_MP_MAX_NUM_CPUS=2 CONFIG_TICKET_SPINLOCKS=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_hs6x.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs6x.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs6x.dts diff --git a/boards/snps/nsim/nsim_nsim_hs6x.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs6x.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs6x.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs6x_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x_defconfig similarity index 94% rename from boards/snps/nsim/nsim_nsim_hs6x_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs6x_defconfig index 5a48971e06d4f..717569e757c97 100644 --- a/boards/snps/nsim/nsim_nsim_hs6x_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x_defconfig @@ -8,3 +8,4 @@ CONFIG_ARCV2_TIMER=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_hs6x_smp.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs6x_smp.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp.dts diff --git a/boards/snps/nsim/nsim_nsim_hs6x_smp.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs6x_smp.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs6x_smp_12cores.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp_12cores.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs6x_smp_12cores.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp_12cores.dts diff --git a/boards/snps/nsim/nsim_nsim_hs6x_smp_12cores.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp_12cores.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs6x_smp_12cores.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp_12cores.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs6x_smp_12cores_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp_12cores_defconfig similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs6x_smp_12cores_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp_12cores_defconfig diff --git a/boards/snps/nsim/nsim_nsim_hs6x_smp_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp_defconfig similarity index 95% rename from boards/snps/nsim/nsim_nsim_hs6x_smp_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp_defconfig index c55df123e9fde..0b02b73960aec 100644 --- a/boards/snps/nsim/nsim_nsim_hs6x_smp_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_hs6x_smp_defconfig @@ -11,3 +11,4 @@ CONFIG_SERIAL=y CONFIG_SMP=y CONFIG_MP_MAX_NUM_CPUS=2 CONFIG_TICKET_SPINLOCKS=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_hs_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs_defconfig similarity index 94% rename from boards/snps/nsim/nsim_nsim_hs_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_defconfig index 123983e324157..d22ebd5ea25d4 100644 --- a/boards/snps/nsim/nsim_nsim_hs_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_hs_defconfig @@ -8,3 +8,4 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_ARC_MPU_ENABLE=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_hs_flash_xip.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs_flash_xip.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_flash_xip.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_flash_xip.dts diff --git a/boards/snps/nsim/nsim_nsim_hs_flash_xip.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs_flash_xip.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_flash_xip.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_flash_xip.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs_flash_xip_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs_flash_xip_defconfig similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_flash_xip_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_flash_xip_defconfig diff --git a/boards/snps/nsim/nsim_nsim_hs_hostlink.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs_hostlink.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_hostlink.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_hostlink.dts diff --git a/boards/snps/nsim/nsim_nsim_hs_hostlink.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs_hostlink.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_hostlink.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_hostlink.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs_hostlink_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs_hostlink_defconfig similarity index 94% rename from boards/snps/nsim/nsim_nsim_hs_hostlink_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_hostlink_defconfig index 123983e324157..d22ebd5ea25d4 100644 --- a/boards/snps/nsim/nsim_nsim_hs_hostlink_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_hs_hostlink_defconfig @@ -8,3 +8,4 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_ARC_MPU_ENABLE=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_hs_mpuv6.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs_mpuv6.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_mpuv6.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_mpuv6.dts diff --git a/boards/snps/nsim/nsim_nsim_hs_mpuv6.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs_mpuv6.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_mpuv6.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_mpuv6.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs_mpuv6_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs_mpuv6_defconfig similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_mpuv6_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_mpuv6_defconfig diff --git a/boards/snps/nsim/nsim_nsim_hs_smp.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs_smp.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_smp.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_smp.dts diff --git a/boards/snps/nsim/nsim_nsim_hs_smp.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs_smp.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_smp.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_smp.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs_smp_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs_smp_defconfig similarity index 95% rename from boards/snps/nsim/nsim_nsim_hs_smp_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_smp_defconfig index 351a2b9660bfb..60b058efa91be 100644 --- a/boards/snps/nsim/nsim_nsim_hs_smp_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_hs_smp_defconfig @@ -11,3 +11,4 @@ CONFIG_ARC_MPU_ENABLE=n CONFIG_SMP=y CONFIG_MP_MAX_NUM_CPUS=2 CONFIG_TICKET_SPINLOCKS=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_hs_sram.dts b/boards/snps/nsim/arc_classic/nsim_nsim_hs_sram.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_sram.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_sram.dts diff --git a/boards/snps/nsim/nsim_nsim_hs_sram.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_hs_sram.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_hs_sram.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_sram.yaml diff --git a/boards/snps/nsim/nsim_nsim_hs_sram_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_hs_sram_defconfig similarity index 95% rename from boards/snps/nsim/nsim_nsim_hs_sram_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_hs_sram_defconfig index 1ee8bc1dad001..0d0380c8e64b7 100644 --- a/boards/snps/nsim/nsim_nsim_hs_sram_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_hs_sram_defconfig @@ -9,3 +9,4 @@ CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_ARC_MPU_ENABLE=y CONFIG_HARVARD=n +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_sem.dts b/boards/snps/nsim/arc_classic/nsim_nsim_sem.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_sem.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_sem.dts diff --git a/boards/snps/nsim/nsim_nsim_sem.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_sem.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_sem.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_sem.yaml diff --git a/boards/snps/nsim/nsim_nsim_sem_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_sem_defconfig similarity index 95% rename from boards/snps/nsim/nsim_nsim_sem_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_sem_defconfig index deb2c9c05711e..fb80da7039073 100644 --- a/boards/snps/nsim/nsim_nsim_sem_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_sem_defconfig @@ -9,3 +9,4 @@ CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_TRUSTED_EXECUTION_SECURE=y +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_sem_mpu_stack_guard.dts b/boards/snps/nsim/arc_classic/nsim_nsim_sem_mpu_stack_guard.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_sem_mpu_stack_guard.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_sem_mpu_stack_guard.dts diff --git a/boards/snps/nsim/nsim_nsim_sem_mpu_stack_guard.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_sem_mpu_stack_guard.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_sem_mpu_stack_guard.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_sem_mpu_stack_guard.yaml diff --git a/boards/snps/nsim/nsim_nsim_sem_mpu_stack_guard_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_sem_mpu_stack_guard_defconfig similarity index 95% rename from boards/snps/nsim/nsim_nsim_sem_mpu_stack_guard_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_sem_mpu_stack_guard_defconfig index 1162d5f132b9d..ce7181282eae1 100644 --- a/boards/snps/nsim/nsim_nsim_sem_mpu_stack_guard_defconfig +++ b/boards/snps/nsim/arc_classic/nsim_nsim_sem_mpu_stack_guard_defconfig @@ -10,3 +10,4 @@ CONFIG_UART_CONSOLE=y CONFIG_SERIAL=y CONFIG_TRUSTED_EXECUTION_SECURE=y CONFIG_ARC_HAS_STACK_CHECKING=n +CONFIG_XIP=n diff --git a/boards/snps/nsim/nsim_nsim_vpx5.dts b/boards/snps/nsim/arc_classic/nsim_nsim_vpx5.dts similarity index 100% rename from boards/snps/nsim/nsim_nsim_vpx5.dts rename to boards/snps/nsim/arc_classic/nsim_nsim_vpx5.dts diff --git a/boards/snps/nsim/nsim_nsim_vpx5.yaml b/boards/snps/nsim/arc_classic/nsim_nsim_vpx5.yaml similarity index 100% rename from boards/snps/nsim/nsim_nsim_vpx5.yaml rename to boards/snps/nsim/arc_classic/nsim_nsim_vpx5.yaml diff --git a/boards/snps/nsim/nsim_nsim_vpx5_defconfig b/boards/snps/nsim/arc_classic/nsim_nsim_vpx5_defconfig similarity index 100% rename from boards/snps/nsim/nsim_nsim_vpx5_defconfig rename to boards/snps/nsim/arc_classic/nsim_nsim_vpx5_defconfig diff --git a/boards/snps/nsim/support/mdb_em.args b/boards/snps/nsim/arc_classic/support/mdb_em.args similarity index 100% rename from boards/snps/nsim/support/mdb_em.args rename to boards/snps/nsim/arc_classic/support/mdb_em.args diff --git a/boards/snps/nsim/support/mdb_em11d.args b/boards/snps/nsim/arc_classic/support/mdb_em11d.args similarity index 100% rename from boards/snps/nsim/support/mdb_em11d.args rename to boards/snps/nsim/arc_classic/support/mdb_em11d.args diff --git a/boards/snps/nsim/support/mdb_em7d_v22.args b/boards/snps/nsim/arc_classic/support/mdb_em7d_v22.args similarity index 100% rename from boards/snps/nsim/support/mdb_em7d_v22.args rename to boards/snps/nsim/arc_classic/support/mdb_em7d_v22.args diff --git a/boards/snps/nsim/support/mdb_hs.args b/boards/snps/nsim/arc_classic/support/mdb_hs.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs.args rename to boards/snps/nsim/arc_classic/support/mdb_hs.args diff --git a/boards/snps/nsim/support/mdb_hs5x.args b/boards/snps/nsim/arc_classic/support/mdb_hs5x.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs5x.args rename to boards/snps/nsim/arc_classic/support/mdb_hs5x.args diff --git a/boards/snps/nsim/support/mdb_hs5x_smp.args b/boards/snps/nsim/arc_classic/support/mdb_hs5x_smp.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs5x_smp.args rename to boards/snps/nsim/arc_classic/support/mdb_hs5x_smp.args diff --git a/boards/snps/nsim/support/mdb_hs5x_smp_12cores.args b/boards/snps/nsim/arc_classic/support/mdb_hs5x_smp_12cores.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs5x_smp_12cores.args rename to boards/snps/nsim/arc_classic/support/mdb_hs5x_smp_12cores.args diff --git a/boards/snps/nsim/support/mdb_hs6x.args b/boards/snps/nsim/arc_classic/support/mdb_hs6x.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs6x.args rename to boards/snps/nsim/arc_classic/support/mdb_hs6x.args diff --git a/boards/snps/nsim/support/mdb_hs6x_smp.args b/boards/snps/nsim/arc_classic/support/mdb_hs6x_smp.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs6x_smp.args rename to boards/snps/nsim/arc_classic/support/mdb_hs6x_smp.args diff --git a/boards/snps/nsim/support/mdb_hs6x_smp_12cores.args b/boards/snps/nsim/arc_classic/support/mdb_hs6x_smp_12cores.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs6x_smp_12cores.args rename to boards/snps/nsim/arc_classic/support/mdb_hs6x_smp_12cores.args diff --git a/boards/snps/nsim/support/mdb_hs_flash_xip.args b/boards/snps/nsim/arc_classic/support/mdb_hs_flash_xip.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs_flash_xip.args rename to boards/snps/nsim/arc_classic/support/mdb_hs_flash_xip.args diff --git a/boards/snps/nsim/support/mdb_hs_hostlink.args b/boards/snps/nsim/arc_classic/support/mdb_hs_hostlink.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs_hostlink.args rename to boards/snps/nsim/arc_classic/support/mdb_hs_hostlink.args diff --git a/boards/snps/nsim/support/mdb_hs_mpuv6.args b/boards/snps/nsim/arc_classic/support/mdb_hs_mpuv6.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs_mpuv6.args rename to boards/snps/nsim/arc_classic/support/mdb_hs_mpuv6.args diff --git a/boards/snps/nsim/support/mdb_hs_smp.args b/boards/snps/nsim/arc_classic/support/mdb_hs_smp.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs_smp.args rename to boards/snps/nsim/arc_classic/support/mdb_hs_smp.args diff --git a/boards/snps/nsim/support/mdb_hs_sram.args b/boards/snps/nsim/arc_classic/support/mdb_hs_sram.args similarity index 100% rename from boards/snps/nsim/support/mdb_hs_sram.args rename to boards/snps/nsim/arc_classic/support/mdb_hs_sram.args diff --git a/boards/snps/nsim/support/mdb_sem.args b/boards/snps/nsim/arc_classic/support/mdb_sem.args similarity index 100% rename from boards/snps/nsim/support/mdb_sem.args rename to boards/snps/nsim/arc_classic/support/mdb_sem.args diff --git a/boards/snps/nsim/support/mdb_sem_mpu_stack_guard.args b/boards/snps/nsim/arc_classic/support/mdb_sem_mpu_stack_guard.args similarity index 100% rename from boards/snps/nsim/support/mdb_sem_mpu_stack_guard.args rename to boards/snps/nsim/arc_classic/support/mdb_sem_mpu_stack_guard.args diff --git a/boards/snps/nsim/support/mdb_vpx5.args b/boards/snps/nsim/arc_classic/support/mdb_vpx5.args similarity index 100% rename from boards/snps/nsim/support/mdb_vpx5.args rename to boards/snps/nsim/arc_classic/support/mdb_vpx5.args diff --git a/boards/snps/nsim/support/nsim_em.props b/boards/snps/nsim/arc_classic/support/nsim_em.props similarity index 100% rename from boards/snps/nsim/support/nsim_em.props rename to boards/snps/nsim/arc_classic/support/nsim_em.props diff --git a/boards/snps/nsim/support/nsim_em11d.props b/boards/snps/nsim/arc_classic/support/nsim_em11d.props similarity index 100% rename from boards/snps/nsim/support/nsim_em11d.props rename to boards/snps/nsim/arc_classic/support/nsim_em11d.props diff --git a/boards/snps/nsim/support/nsim_em7d_v22.props b/boards/snps/nsim/arc_classic/support/nsim_em7d_v22.props similarity index 100% rename from boards/snps/nsim/support/nsim_em7d_v22.props rename to boards/snps/nsim/arc_classic/support/nsim_em7d_v22.props diff --git a/boards/snps/nsim/support/nsim_hs.props b/boards/snps/nsim/arc_classic/support/nsim_hs.props similarity index 100% rename from boards/snps/nsim/support/nsim_hs.props rename to boards/snps/nsim/arc_classic/support/nsim_hs.props diff --git a/boards/snps/nsim/support/nsim_hs5x.props b/boards/snps/nsim/arc_classic/support/nsim_hs5x.props similarity index 100% rename from boards/snps/nsim/support/nsim_hs5x.props rename to boards/snps/nsim/arc_classic/support/nsim_hs5x.props diff --git a/boards/snps/nsim/support/nsim_hs6x.props b/boards/snps/nsim/arc_classic/support/nsim_hs6x.props similarity index 100% rename from boards/snps/nsim/support/nsim_hs6x.props rename to boards/snps/nsim/arc_classic/support/nsim_hs6x.props diff --git a/boards/snps/nsim/support/nsim_hs_flash_xip.props b/boards/snps/nsim/arc_classic/support/nsim_hs_flash_xip.props similarity index 100% rename from boards/snps/nsim/support/nsim_hs_flash_xip.props rename to boards/snps/nsim/arc_classic/support/nsim_hs_flash_xip.props diff --git a/boards/snps/nsim/support/nsim_hs_hostlink.props b/boards/snps/nsim/arc_classic/support/nsim_hs_hostlink.props similarity index 100% rename from boards/snps/nsim/support/nsim_hs_hostlink.props rename to boards/snps/nsim/arc_classic/support/nsim_hs_hostlink.props diff --git a/boards/snps/nsim/support/nsim_hs_mpuv6.props b/boards/snps/nsim/arc_classic/support/nsim_hs_mpuv6.props similarity index 100% rename from boards/snps/nsim/support/nsim_hs_mpuv6.props rename to boards/snps/nsim/arc_classic/support/nsim_hs_mpuv6.props diff --git a/boards/snps/nsim/support/nsim_hs_sram.props b/boards/snps/nsim/arc_classic/support/nsim_hs_sram.props similarity index 100% rename from boards/snps/nsim/support/nsim_hs_sram.props rename to boards/snps/nsim/arc_classic/support/nsim_hs_sram.props diff --git a/boards/snps/nsim/support/nsim_sem.props b/boards/snps/nsim/arc_classic/support/nsim_sem.props similarity index 100% rename from boards/snps/nsim/support/nsim_sem.props rename to boards/snps/nsim/arc_classic/support/nsim_sem.props diff --git a/boards/snps/nsim/support/nsim_sem_mpu_stack_guard.props b/boards/snps/nsim/arc_classic/support/nsim_sem_mpu_stack_guard.props similarity index 100% rename from boards/snps/nsim/support/nsim_sem_mpu_stack_guard.props rename to boards/snps/nsim/arc_classic/support/nsim_sem_mpu_stack_guard.props diff --git a/boards/snps/nsim/support/nsim_vpx5.props b/boards/snps/nsim/arc_classic/support/nsim_vpx5.props similarity index 100% rename from boards/snps/nsim/support/nsim_vpx5.props rename to boards/snps/nsim/arc_classic/support/nsim_vpx5.props diff --git a/boards/snps/nsim/arc_v/Kconfig.defconfig b/boards/snps/nsim/arc_v/Kconfig.defconfig new file mode 100644 index 0000000000000..469d5e2a92b41 --- /dev/null +++ b/boards/snps/nsim/arc_v/Kconfig.defconfig @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Synopsys, Inc. +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_NSIM_ARC_V_RMX100 + +config SYS_CLOCK_TICKS_PER_SEC + default 1000 + +config SYS_CLOCK_HW_CYCLES_PER_SEC + default 5000000 + +endif # BOARD_NSIM_ARC_V_RMX100 diff --git a/boards/snps/nsim/arc_v/Kconfig.nsim_arc_v b/boards/snps/nsim/arc_v/Kconfig.nsim_arc_v new file mode 100644 index 0000000000000..600a7e7499d23 --- /dev/null +++ b/boards/snps/nsim/arc_v/Kconfig.nsim_arc_v @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Synopsys, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NSIM_ARC_V + select SOC_RMX100 if BOARD_NSIM_ARC_V_RMX100 diff --git a/boards/snps/nsim/arc_v/board.cmake b/boards/snps/nsim/arc_v/board.cmake new file mode 100644 index 0000000000000..2c0230917d1ed --- /dev/null +++ b/boards/snps/nsim/arc_v/board.cmake @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(SUPPORTED_EMU_PLATFORMS nsim) + +string(SUBSTRING "${BOARD_QUALIFIERS}" 1 -1 NSIM_BASE_FILENAME) +string(REPLACE "/" "_" NSIM_BASE_FILENAME "${NSIM_BASE_FILENAME}") + +board_set_flasher_ifnset(arc-nsim) +board_set_debugger_ifnset(arc-nsim) + +set(NSIM_PROPS "${NSIM_BASE_FILENAME}.props") +board_runner_args(arc-nsim "--props=${NSIM_PROPS}") + +board_finalize_runner_args(arc-nsim) +include(${ZEPHYR_BASE}/boards/common/mdb-nsim.board.cmake) +include(${ZEPHYR_BASE}/boards/common/mdb-hw.board.cmake) diff --git a/boards/snps/nsim/arc_v/board.yml b/boards/snps/nsim/arc_v/board.yml new file mode 100644 index 0000000000000..a91eaffd90a00 --- /dev/null +++ b/boards/snps/nsim/arc_v/board.yml @@ -0,0 +1,5 @@ +board: + name: nsim_arc_v + vendor: snps + socs: + - name: rmx100 diff --git a/boards/snps/nsim/arc_v/doc/index.rst b/boards/snps/nsim/arc_v/doc/index.rst new file mode 100644 index 0000000000000..8586758be7757 --- /dev/null +++ b/boards/snps/nsim/arc_v/doc/index.rst @@ -0,0 +1,194 @@ +.. _nsim_arc_v: + +DesignWare RISC-V nSIM and HAPS FPGA boards +########################################### + +Overview +******** + +This platform can be used to run Zephyr RTOS on the widest possible range of Synopsys RISC-V processors in +simulation with `Designware ARC nSIM`_ or run same images on FPGA prototyping platform `HAPS`_. The +platform includes the following features: + +* RISC-V processor core, which implements riscv32 ISA +* Virtual serial console (a standard ``ns16550`` UART model) + +Supported board targets for that platform are listed below: + +* ``nsim_arc_v/rmx100`` - Synopsys RISC-V RMX100 core + +.. _board_nsim_arc_v_prop_files: + +It is recommended to look at precise description of a particular board target in ``.props`` +files in :zephyr_file:`boards/snps/nsim_arc_v/support/` directory to understand +which options are configured and so will be used on invocation of the simulator. + +.. warning:: + All nSIM targets are used for demo and testing purposes. They are not meant to + represent any real system and so might be renamed, removed or modified at any point. + +Programming and Debugging +************************* + +Required Hardware and Software +============================== + +To run single-core Zephyr RTOS applications in simulation on this board, +either `DesignWare ARC nSIM`_ or `DesignWare ARC Free nSIM`_ is required. + +Building & Running Sample Applications +====================================== + +Most board targets support building with GNU toolchains, however +there might be exceptions from that, especially for newly added targets. You can check supported +toolchains for the board targets in the corresponding ``.yaml`` file. + +I.e. for the ``nsim_arc_v/rmx100`` board we can check :zephyr_file:`boards/snps/nsim_arc_v/nsim_arc_v_rmx100.yaml` + +The supported toolchains are listed in ``toolchain:`` array in ``.yaml`` file, where we can find: + +* **zephyr** - implies RISC-V GNU toolchain from Zephyr SDK. You can find more information about + Zephyr SDK :ref:`here `. +* **cross-compile** - implies RISC-V GNU cross toolchain, which is not a part of Zephyr SDK. Note that + some (especially new) board targets may declare ``cross-compile`` toolchain support without + ``zephyr`` toolchain support because corresponding target CPU support hasn't been added to Zephyr + SDK yet. You can find more information about its usage here: :ref:`here `. +* **arcmwdt** - implies proprietary ARC MWDT toolchain. You can find more information about its + usage here: :ref:`here `. Not yet supported: work in progress. + +Use this configuration to run basic Zephyr applications and kernel tests in +nSIM, for example, with the :zephyr:code-sample:`synchronization` sample: + +.. zephyr-app-commands:: + :zephyr-app: samples/synchronization + :host-os: unix + :board: nsim_arc_v/rmx100 + :goals: flash + +This will build an image with the synchronization sample app, boot it using +nSIM, and display the following console output: + +.. code-block:: console + + *** Booting Zephyr OS build zephyr-v3.2.0-3948-gd351a024dc87 *** + thread_a: Hello World from cpu 0 on nsim_arc_v! + thread_b: Hello World from cpu 0 on nsim_arc_v! + thread_a: Hello World from cpu 0 on nsim_arc_v! + thread_b: Hello World from cpu 0 on nsim_arc_v! + thread_a: Hello World from cpu 0 on nsim_arc_v! + +.. note:: + To exit the simulator, use :kbd:`Ctrl+]`, then :kbd:`Ctrl+c` + +.. _board_nsim_arc_v_verbose_build: + +.. tip:: + You can get more details about the building process by running build in verbose mode. It can be + done by passing ``-v`` flag to the west: ``west -v build -b nsim_hs samples/synchronization`` + +Debugging +========= + +.. _board_nsim_arc_v_debugging_gdb: + +Debugging with GDB +------------------ + +.. note:: + Debugging on nSIM via GDB is only supported on single-core targets (which use standalone + nSIM). + +.. note:: + The normal ``west debug`` command won't work for debugging applications using nsim boards + because both the nSIM simulator and the debugger use the same console for + input / output. + In case of GDB debugger it's possible to use a separate terminal windows for GDB and nSIM to + avoid intermixing their output. + +After building your application, open two terminal windows. In terminal one, use nSIM to start a GDB +server and wait for a remote connection with following command: + +.. code-block:: console + + west debugserver --runner arc-nsim + +In terminal two, connect to the GDB server using RISC-V GDB. You can find it in Zephyr SDK: + +* you should use :file:`riscv64-zephyr-elf-gdb` + +This command loads the symbol table from the elf binary file, for example the +:file:`build/zephyr/zephyr.elf` file: + +.. code-block:: console + + riscv64-zephyr-elf-gdb -ex 'target remote localhost:3333' -ex load build/zephyr/zephyr.elf + +Now the debug environment has been set up, and it's possible to debug the application with gdb +commands. + +Modifying the configuration +*************************** + +If modification of existing nsim configuration is required or even there's a need in creation of a +new one it's required to maintain alignment between + +* Zephyr OS configuration +* nSIM configuration +* GNU toolchain compiler options + +.. note:: + The ``.tcf`` configuration files are not supported by Zephyr directly. There are multiple + reasons for that. ``.tcf`` perfectly suits building of bare-metal single-thread application - + in that case all the compiler options from ``.tcf`` are passed to the compiler, so all the HW + features are used by the application and optimal code is being generated. + The situation is completely different when multi-thread feature-rich operation system is + considered. Of course it is still possible to build all the code with all the + options from ``.tcf`` - but that may be far from optimal solution. For example, such approach + require so save & restore full register context for all tasks (and sometimes even for + interrupts). And for DSP-enabled or for FPU-enabled systems that leads to dozens of extra + registers save and restore even if the most of the user and kernel tasks don't actually use + DSP or FPU. Instead we prefer to fine-tune the HW features usage which (with all its pros) + require us to maintain them separately from ``.tcf`` configuration. + + +Zephyr OS configuration +======================= + +Zephyr OS configuration is defined via Kconfig and Device tree. These are non RISC-V-specific +mechanisms which are described in :ref:`board porting guide `. + +It is advised to look for ``_defconfig``, ``.dts`` and +``.yaml`` as an entry point for board target. + +nSIM configuration +================== + +nSIM configuration is defined in :ref:`props files `. +Generally they are identical to the values from corresponding ``.tcf`` configuration with few +exceptions: + +* The UART model is added +* CLINT model is added + +GNU toolchain compiler options +===================================== + +The hardware-specific compiler options are set in corresponding SoC cmake file. For ``nsim_arc_v`` board +it is :zephyr_file:`soc/snps/nsim/arc_v/CMakeLists.txt`. + +For the GNU toolchain the basic configuration is set via ``-march`` which is defined in generic code +and based on the selected CPU model via Kconfig. It still can be forcefully set to required value +on SoC level. + +.. note:: + The non hardware-specific compiler options like optimizations, library selections, C / C++ + language options are still set in Zephyr generic code. It could be observed by + :ref:`running build in verbose mode `. + +References +********** + +.. _Designware ARC nSIM: https://www.synopsys.com/dw/ipdir.php?ds=sim_nsim +.. _DesignWare ARC Free nSIM: https://www.synopsys.com/cgi-bin/dwarcnsim/req1.cgi +.. _HAPS: https://www.synopsys.com/verification/prototyping/haps.html +.. _ARC MWDT: https://www.synopsys.com/dw/ipdir.php?ds=sw_metaware diff --git a/boards/snps/nsim/arc_v/nsim_arc_v_rmx100.dts b/boards/snps/nsim/arc_v/nsim_arc_v_rmx100.dts new file mode 100644 index 0000000000000..351b88c2679b8 --- /dev/null +++ b/boards/snps/nsim/arc_v/nsim_arc_v_rmx100.dts @@ -0,0 +1,24 @@ +/dts-v1/; + +#include "rmx100.dtsi" + +/ { + model = "Synopsys RMX100"; + compatible = "snps,rmx100"; + + aliases { + uart-0 = &uart0; + }; + + chosen { + zephyr,sram = &ddr0; + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + }; + +}; + +&uart0 { + status = "okay"; + current-speed = <115200>; +}; diff --git a/boards/snps/nsim/arc_v/nsim_arc_v_rmx100.yaml b/boards/snps/nsim/arc_v/nsim_arc_v_rmx100.yaml new file mode 100644 index 0000000000000..548d0f3dbf7fd --- /dev/null +++ b/boards/snps/nsim/arc_v/nsim_arc_v_rmx100.yaml @@ -0,0 +1,14 @@ +identifier: nsim_arc_v/rmx100 +name: Synopsys rmx100 +simulation: nsim +simulation_exec: nsimdrv +type: sim +arch: riscv +toolchain: + - zephyr + - cross-compile +testing: + ignore_tags: + - net + - bluetooth +vendor: snps diff --git a/boards/snps/nsim/arc_v/nsim_arc_v_rmx100_defconfig b/boards/snps/nsim/arc_v/nsim_arc_v_rmx100_defconfig new file mode 100644 index 0000000000000..17283e7b6649c --- /dev/null +++ b/boards/snps/nsim/arc_v/nsim_arc_v_rmx100_defconfig @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Synopsys, Inc. +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_XIP=n +CONFIG_CONSOLE=y +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y +CONFIG_BUILD_OUTPUT_HEX=y +CONFIG_INCLUDE_RESET_VECTOR=y +CONFIG_LOG=y diff --git a/boards/snps/nsim/arc_v/rmx100.dtsi b/boards/snps/nsim/arc_v/rmx100.dtsi new file mode 100644 index 0000000000000..89586284c61f2 --- /dev/null +++ b/boards/snps/nsim/arc_v/rmx100.dtsi @@ -0,0 +1,8 @@ +#include "rmx1xx.dtsi" + +/ { + ddr0: memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x10000000>; /* 256 MB */ + }; +}; diff --git a/boards/snps/nsim/arc_v/rmx1xx.dtsi b/boards/snps/nsim/arc_v/rmx1xx.dtsi new file mode 100644 index 0000000000000..9480922e2176d --- /dev/null +++ b/boards/snps/nsim/arc_v/rmx1xx.dtsi @@ -0,0 +1,55 @@ +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + timebase-frequency = <5000000>; + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "snps,av5rmx", "riscv"; + device_type = "cpu"; + reg = <0>; + clock-frequency = <5000000>; + riscv,isa = "rv32imac_zicsr_zifencei"; + + cpu0_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + interrupt-controller; + #address-cells = <0>; + #interrupt-cells = <1>; + }; + }; + }; + + soc { + compatible = "simple-bus"; + ranges; + interrupt-parent = <&clint>; + #address-cells = <1>; + #size-cells = <1>; + + clint: clint@2000000 { + compatible = "sifive,clint0"; + reg = <0x2000000 0x1000>; + interrupts-extended = <&cpu0_intc 3 &cpu0_intc 7>; + interrupt-names = "soft0", "timer0"; + }; + + uart0: serial@10000000{ + compatible = "ns16550", "snps,dw-apb-uart"; + reg = <0x10000000 0x400>; + reg-shift = <2>; + + /* AIA interrupt controller is not currently implemented, + * so connect UART interrupt to 17th line as a stub to + * make build system and test framework happy. + */ + interrupt-parent = <&cpu0_intc>; + interrupts = <17>; + clock-frequency = <50000000>; + status = "disabled"; + }; + }; +}; diff --git a/boards/snps/nsim/arc_v/support/rmx100.props b/boards/snps/nsim/arc_v/support/rmx100.props new file mode 100644 index 0000000000000..31aed21b49499 --- /dev/null +++ b/boards/snps/nsim/arc_v/support/rmx100.props @@ -0,0 +1,6 @@ + nsim_isa_family=rv32 + nsim_isa_ext=-all.i.zicsr.zifencei.zihintpause.a.m.zba.zbb.zbs.zca.zcb.zcmp.zcmt.zicbom + nsim_isa_big_endian=0 + nsim_mem-dev=clint,base=0x2000000,size=4096 + nsim_mem-dev=uart0,kind=16550,base=0x10000000,irq=24 + nsim_mem-dev=plic,base=0xc000000,size=0x04000000,interrupts=128,priorities=16 diff --git a/boards/sparkfun/micromod/Kconfig b/boards/sparkfun/micromod/Kconfig new file mode 100644 index 0000000000000..c85ad61572fd4 --- /dev/null +++ b/boards/sparkfun/micromod/Kconfig @@ -0,0 +1,19 @@ +# Sparkfun micromod board configuration + +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_MICROMOD_NRF52840 + +config BOARD_ENABLE_DCDC + bool "DCDC mode" + select SOC_DCDC_NRF52X + default y + +config BOARD_ENABLE_DCDC_HV + bool "High Voltage DCDC converter" + select SOC_DCDC_NRF52X_HV + default y + depends on SOC_NRF52840_QIAA + +endif # BOARD_MICROMOD_NRF52840 diff --git a/boards/sparkfun/micromod/Kconfig.defconfig b/boards/sparkfun/micromod/Kconfig.defconfig new file mode 100644 index 0000000000000..50f6c3f582aed --- /dev/null +++ b/boards/sparkfun/micromod/Kconfig.defconfig @@ -0,0 +1,11 @@ +# Sparkfun micromod board configuration + +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_MICROMOD_NRF52840 + +config BT_CTLR + default BT + +endif # BOARD_MICROMOD_NRF52840 diff --git a/boards/sparkfun/micromod/Kconfig.micromod b/boards/sparkfun/micromod/Kconfig.micromod new file mode 100644 index 0000000000000..ea40f13ad1a93 --- /dev/null +++ b/boards/sparkfun/micromod/Kconfig.micromod @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_MICROMOD + select SOC_NRF52840_QIAA if BOARD_MICROMOD_NRF52840 diff --git a/boards/sparkfun/micromod/board.cmake b/boards/sparkfun/micromod/board.cmake new file mode 100644 index 0000000000000..55900ba5975e1 --- /dev/null +++ b/boards/sparkfun/micromod/board.cmake @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=nRF52840_xxAA" "--speed=4000") +board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000") + +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/sparkfun/micromod/board.yml b/boards/sparkfun/micromod/board.yml new file mode 100644 index 0000000000000..851ac345bc538 --- /dev/null +++ b/boards/sparkfun/micromod/board.yml @@ -0,0 +1,5 @@ +board: + name: micromod + vendor: sparkfun + socs: + - name: nrf52840 diff --git a/boards/sparkfun/micromod/doc/img/sparkfun_micromod.webp b/boards/sparkfun/micromod/doc/img/sparkfun_micromod.webp new file mode 100644 index 0000000000000..423c7a3d0f6af Binary files /dev/null and b/boards/sparkfun/micromod/doc/img/sparkfun_micromod.webp differ diff --git a/boards/sparkfun/micromod/doc/index.rst b/boards/sparkfun/micromod/doc/index.rst new file mode 100644 index 0000000000000..0ba4c37bbefbf --- /dev/null +++ b/boards/sparkfun/micromod/doc/index.rst @@ -0,0 +1,204 @@ +.. _boardname_linkname: + +SparkFun MicroMod board Processor +################################# + +Overview +******** + +MicroMod is a solderless, modular interface ecosystem that uses the M.2 standard +to mix and match your choice of processor with specific Function Boards or +stand-alone Carrier Boards. A MicroMod processor board is approximately 22x22 mm, +and can insert into any MicroMod carrier board. More information can be found in +the `Micromod specification website`_. + +All Micromod board targets support the following hardware features: + +- USB host mode compliant to 2.0 specification +- GPIO +- 2 UART +- 2 I2C +- 2 SPI +- 2 ADC +- 2 PWM +- Watchdog Timer (WDT) + +.. figure:: img/sparkfun_micromod.webp + :align: center + :alt: Sparkfun Micromod board + + Sparkfun Micromod board (Credit: https://www.sparkfun.com) + +Zephyr currently supports the following SoCs: + +- ``micromod/nrf52840`` + +SparkFun MicroMod nRF52840 board Processor +########################################## + +Overview +******** + +The ``micromod/nrf52840`` board target features the nRF52840 SoC +from Nordic Semiconductor, the SparkFun MicroMod nRF52840 Processor offers +a powerful combination of ARM Cortex-M4 CPU and 2.4 GHz Bluetooth transceiver +in the MicroMod form-factor. More information can be found in +the `Micromod nRF52840 guide`_. + +Hardware +******** + +The ``micromod/nrf52840`` board target supports the following +hardware features: + +- ARM Cortex-M4 CPU with floating point unit (FPU) + + - 1MB internal Flash + - 256kB internal RAM + +- Integrated 2.4GHz radio with support for Bluetooth Low Energy (BLE) and ieee802154 +- USB 2.0 full speed (12 Mbps) controller +- QSPI with 128Mb flash memory +- ARM TrustZone Cryptocell 310 security subsystem +- USB host mode compliant to 2.0 specification +- GPIO +- 2 UART +- 2 I2C +- 2 SPI +- 2 ADC +- 2 PWM +- Watchdog Timer (WDT) + +Supported Features +================== + +The Zephyr ``micromod/nrf52840`` board target supports the following hardware +features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| SYSTICK | on-chip | system clock | ++-----------+------------+-------------------------------------+ +| RADIO | on-chip | Bluetooth, | +| | | ieee802154 | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| FLASH | on-chip | flash | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| USB | on-chip | usb | ++-----------+------------+-------------------------------------+ +| QSPI | on-chip | nordic,nrf-qspi | ++-----------+------------+-------------------------------------+ + + +Connections and IOs +=================== + +LED +--- + +* Led0 (blue) = P0.13 + +Micromod header +--------------- + +* micromod_1_uart = uart0 +* micromod_2_uart = uart1 +* micromod_0_i2c = i2c0 +* micromod_1_i2c = i2c1 +* micromod_0_spi = spi2 +* micromod_header compatible with ``sparkfun,micromod-gpio`` + +Programming and Debugging +************************* + +Applications for the ``micromod/nrf52840`` board target can be +built, flashed, and debugged in the usual way. See +:ref:`build_an_application` and :ref:`application_run` for more details on +building and running. + +Flashing +======== + +Follow the instructions in the :ref:`nordic_segger` page to install +and configure all the necessary software. Further information can be +found in :ref:`nordic_segger_flashing`. Then build and flash +applications as usual (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +The flashing tool will depend on the carrier used along with the board. +In the case of `Sparkfun asset tracking carrier`, it is possible to use +the SWD interface along with a J-Link. + +Here is an example for the :ref:`hello_world` application. + +First, run your favorite terminal program to listen for output. + +.. code-block:: console + + $ minicom -D -b 115200 + +Replace :code:`` with the port where the board nRF52840 DK +can be found. For example, under Linux, :code:`/dev/ttyACM0`. + +Then build and flash the application in the usual way. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: micromod/nrf52840 + :goals: build flash + +Debugging +========= + +Refer to the :ref:`nordic_segger` page to learn about debugging Nordic boards with a +Segger IC. + +In case of using a Nordic Segger Jlink, it is possible to configure the app to use Segger Real +Time Transfer (RTT) for debugging. In this case, build your app with the +:ref:`RTT snippet `. + +Testing the on-board LED +************************ + +There is a sample that allow you to test the LED on the board is working properly +with Zephyr: + +* :zephyr:code-sample:`blinky` + +You can build and flash the example to make sure Zephyr is running correctly on +your board. The button and LED definitions can be found in +:zephyr_file:`boards/sparkfun/micromod/micromod_nrf52840.dts`. + +Testing the 128Mb qspi memory flash +*********************************** + +The ``micromod/nrf52840`` board target has a built-in NOR flash memory connected +to the qspi interface. It can be tested with the samples/drivers/jesd216 app. + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/jesd216 + :board: micromod/nrf52840 + :goals: build flash + +References +********** + +.. target-notes:: + +.. _Micromod specification website: https://www.sparkfun.com/micromod +.. _Micromod nRF52840 guide: https://learn.sparkfun.com/tutorials/micromod-nrf52840-processor-hookup-guide +.. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html +.. _nRF52840 Product Specification: http://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.0.pdf diff --git a/boards/sparkfun/micromod/micromod_nrf52840-pinctrl.dtsi b/boards/sparkfun/micromod/micromod_nrf52840-pinctrl.dtsi new file mode 100644 index 0000000000000..4cba8a1d09814 --- /dev/null +++ b/boards/sparkfun/micromod/micromod_nrf52840-pinctrl.dtsi @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2024 Jerónimo Agulló + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&pinctrl { + 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; + }; + }; + + i2c0_default: i2c0_default { + group1 { + psels = , + ; + }; + }; + + i2c0_sleep: i2c0_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + i2c1_default: i2c1_default { + group1 { + psels = , + ; + }; + }; + + i2c1_sleep: i2c1_sleep { + group1 { + psels = , + ; + low-power-enable; + }; + }; + + spi0_default: spi0_default { + group1 { + psels = , + , + ; + }; + }; + + spi0_sleep: spi0_sleep { + group1 { + psels = , + , + ; + low-power-enable; + }; + }; + + qspi_default: qspi_default { + group1 { + psels = , + , + , + , + , + ; + nordic,drive-mode = ; + }; + }; + + qspi_sleep: qspi_sleep { + group1 { + psels = , + , + , + , + ; + low-power-enable; + }; + group2 { + psels = ; + low-power-enable; + bias-pull-up; + }; + }; +}; diff --git a/boards/sparkfun/micromod/micromod_nrf52840.dts b/boards/sparkfun/micromod/micromod_nrf52840.dts new file mode 100644 index 0000000000000..345714a5cd378 --- /dev/null +++ b/boards/sparkfun/micromod/micromod_nrf52840.dts @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2024 Jerónimo Agulló + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "micromod_nrf52840-pinctrl.dtsi" +#include + +/ { + model = "Sparkfun Micrmod nRF52840 board"; + compatible = "sparkfun,micromod-nrf52840"; + + chosen { + zephyr,console = &uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + zephyr,ieee802154 = &ieee802154; + }; + + /* These aliases are provided for compatibility with samples */ + aliases { + led0 = &led0; + watchdog0 = &wdt0; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 13 0>; + label = "Blue LED"; + }; + }; + + micromod_header: connector { + compatible = "sparkfun,micromod-gpio"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpio0 4 0>, /* A0 */ + <1 0 &gpio0 5 0>, /* A1 */ + <2 0 &gpio0 27 0>, /* D0 */ + <3 0 &gpio1 8 0>, /* D1/CAM_TRIG */ + <4 0 &gpio0 15 0>, /* I2C_INT# */ + <5 0 &gpio0 29 0>, /* G0/BUS0 */ + <6 0 &gpio0 3 0>, /* G1/BUS1 */ + <7 0 &gpio1 13 0>, /* G2/BUS2 */ + <8 0 &gpio1 12 0>, /* G3/BUS3 */ + <9 0 &gpio1 11 0>, /* G4/BUS4 */ + <10 0 &gpio0 17 0>, /* G5/BUS5 */ + <11 0 &gpio1 6 0>, /* G6/BUS6 */ + <12 0 &gpio1 4 0>, /* G7/BUS7 */ + <13 0 &gpio1 14 0>, /* G8 */ + <14 0 &gpio0 9 0>, /* G9/ADC_D-/CAM_HSYNC */ + <15 0 &gpio0 10 0>, /* G10/ADC_D+/CAM_VSYNC */ + //<16 NO CONNECTED /* G11/SWO */ + <17 0 &gpio0 20 0>; /* SPI_CS */ + }; +}; + +&adc { + status = "okay"; +}; + +&gpiote { + status = "okay"; +}; + +&gpio0 { + status = "okay"; +}; + +&gpio1 { + status = "okay"; +}; + +&uicr { + nfct-pins-as-gpios; + gpio-as-nreset; +}; + +&uart0 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&uart1 { + compatible = "nordic,nrf-uarte"; + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart1_default>; + pinctrl-1 = <&uart1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&i2c0 { + compatible = "nordic,nrf-twi"; + status = "okay"; + pinctrl-0 = <&i2c0_default>; + pinctrl-1 = <&i2c0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&i2c1 { + compatible = "nordic,nrf-twi"; + status = "okay"; + pinctrl-0 = <&i2c1_default>; + pinctrl-1 = <&i2c1_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&spi2 { + compatible = "nordic,nrf-spi"; + status = "okay"; + cs-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&spi0_default>; + pinctrl-1 = <&spi0_sleep>; + pinctrl-names = "default", "sleep"; +}; + +&qspi { + status = "okay"; + pinctrl-0 = <&qspi_default>; + pinctrl-1 = <&qspi_sleep>; + pinctrl-names = "default", "sleep"; + w25q128jv: w25q128jv@0 { + status="okay"; + compatible = "nordic,qspi-nor"; + reg = <0>; + writeoc = "pp4io"; + readoc = "read4io"; + sck-frequency = ; + jedec-id = [ef 70 18]; + size = ; + has-dpd; + t-enter-dpd = <3000>; + t-exit-dpd = <3000>; + }; +}; + +&ieee802154 { + status = "okay"; +}; + +&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 0x00076000>; + }; + + slot1_partition: partition@86000 { + label = "image-1"; + reg = <0x00086000 0x00074000>; + }; + + /* + * The flash starting at 0x000f8000 and ending at + * 0x000fffff is reserved for use by the application. + */ + + /* + * Storage partition will be used by FCB/LittleFS/NVS + * if enabled. + */ + + storage_partition: partition@fA000 { + label = "storage"; + reg = <0x000fA000 0x00006000>; + }; + }; +}; + +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; +}; + +// Sparkfun Micromod compatible pins +micromod_1_uart: &uart0 {}; +micromod_2_uart: &uart1 {}; +micromod_0_i2c: &i2c0 {}; +micromod_1_i2c: &i2c1 {}; +micromod_0_spi: &spi2 {}; diff --git a/boards/sparkfun/micromod/micromod_nrf52840.yaml b/boards/sparkfun/micromod/micromod_nrf52840.yaml new file mode 100644 index 0000000000000..3afd626931343 --- /dev/null +++ b/boards/sparkfun/micromod/micromod_nrf52840.yaml @@ -0,0 +1,26 @@ +identifier: micromod/nrf52840 +name: Sparkfun Micromod nRF52840 board +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - ble + - gpio + - spi + - qspi + - i2c + - pwm + - adc + - usb_device + - usb_cdc + - watchdog + - micromod_gpio + - micromod_uart + - micromod_i2c + - micromod_spi +vendor: Sparkfun diff --git a/boards/sparkfun/micromod/micromod_nrf52840_defconfig b/boards/sparkfun/micromod/micromod_nrf52840_defconfig new file mode 100644 index 0000000000000..f8f1759f51c15 --- /dev/null +++ b/boards/sparkfun/micromod/micromod_nrf52840_defconfig @@ -0,0 +1,19 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable RTT +CONFIG_USE_SEGGER_RTT=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable console +CONFIG_CONSOLE=y + +# Enable UART +CONFIG_SERIAL=y diff --git a/boards/sparkfun/micromod/pre_dt_board.cmake b/boards/sparkfun/micromod/pre_dt_board.cmake new file mode 100644 index 0000000000000..3369c21d3af5b --- /dev/null +++ b/boards/sparkfun/micromod/pre_dt_board.cmake @@ -0,0 +1,7 @@ +# Copyright (c) 2022 Nordic Semiconductor +# SPDX-License-Identifier: Apache-2.0 + +# Suppress "unique_unit_address_if_enabled" to handle the following overlaps: +# - power@40000000 & clock@40000000 & bprot@40000000 +# - acl@4001e000 & flash-controller@4001e000 +list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled") diff --git a/boards/st/b_l4s5i_iot01a/Kconfig.defconfig b/boards/st/b_l4s5i_iot01a/Kconfig.defconfig index 36b722dbf3819..317d096e0cea7 100644 --- a/boards/st/b_l4s5i_iot01a/Kconfig.defconfig +++ b/boards/st/b_l4s5i_iot01a/Kconfig.defconfig @@ -27,16 +27,15 @@ if BT config SPI default y -choice BT_HCI_BUS_TYPE - default BT_SPI -endchoice +config BT_SPI + default y config BT_BLUENRG_ACI default y # Disable Flow control config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/boards/st/b_l4s5i_iot01a/b_l4s5i_iot01a.dts b/boards/st/b_l4s5i_iot01a/b_l4s5i_iot01a.dts index 531c5a5b20d93..d41c75c44bf0d 100644 --- a/boards/st/b_l4s5i_iot01a/b_l4s5i_iot01a.dts +++ b/boards/st/b_l4s5i_iot01a/b_l4s5i_iot01a.dts @@ -22,6 +22,7 @@ zephyr,code-partition = &slot0_partition; zephyr,flash-controller = &mx25r6435f; zephyr,bt-c2h-uart = &usart1; + zephyr,bt-hci = &hci_spi; }; leds { @@ -50,7 +51,6 @@ sw0 = &user_button; watchdog0 = &iwdg; accel0 = &lsm6dsl; - spi-flash0 = &mx25r6435f; }; }; @@ -152,7 +152,7 @@ cs-gpios = <&gpiod 13 GPIO_ACTIVE_LOW>, <&gpioe 0 GPIO_ACTIVE_LOW>; - spbtle-rf@0 { + hci_spi: spbtle-rf@0 { compatible = "st,hci-spi-v1"; reg = <0>; reset-gpios = <&gpioa 8 GPIO_ACTIVE_LOW>; diff --git a/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi b/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi index 7912aa33deb4b..b3227455f6fc4 100644 --- a/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi +++ b/boards/st/b_u585i_iot02a/b_u585i_iot02a-common.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Linaro Limited + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -34,7 +35,6 @@ aliases { watchdog0 = &iwdg; - spi-flash0 = &mx25lm51245; die-temp0 = &die_temp; volt-sensor0 = &vref1; volt-sensor1 = &vbat4; @@ -246,6 +246,12 @@ zephyr_udc0: &usbotg_fs { status = "okay"; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &iwdg { status = "okay"; }; diff --git a/boards/st/b_u585i_iot02a/b_u585i_iot02a.dts b/boards/st/b_u585i_iot02a/b_u585i_iot02a.dts index 33093d701b78d..b452f4b3eba39 100644 --- a/boards/st/b_u585i_iot02a/b_u585i_iot02a.dts +++ b/boards/st/b_u585i_iot02a/b_u585i_iot02a.dts @@ -6,6 +6,8 @@ /dts-v1/; #include "b_u585i_iot02a-common.dtsi" +#include +#include / { model = "STMicroelectronics B-U585I-IOT02A discovery kit"; @@ -17,7 +19,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; - zephyr,bt-uart=&uart4; + zephyr,bt-hci = &bt_hci_uart; }; aliases { @@ -25,6 +27,14 @@ led1 = &red_led_1; sw0 = &user_button; }; + + octo_nor: memory@70000000 { + compatible = "zephyr,memory-region"; + reg = <0x70000000 DT_SIZE_M(64)>; + zephyr,memory-region = "EXTMEM"; + /* The ATTR_MPU_EXTMEM attribut causing a MPU FAULT */ + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; }; &flash0 { @@ -71,4 +81,9 @@ pinctrl-names = "default"; current-speed = <100000>; status = "okay"; + + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + }; }; diff --git a/boards/st/b_u585i_iot02a/b_u585i_iot02a.yaml b/boards/st/b_u585i_iot02a/b_u585i_iot02a.yaml index 27ba601cae56d..ef3e9b0a210a1 100644 --- a/boards/st/b_u585i_iot02a/b_u585i_iot02a.yaml +++ b/boards/st/b_u585i_iot02a/b_u585i_iot02a.yaml @@ -23,4 +23,5 @@ supported: - pwm - counter - i2c + - rtc vendor: st diff --git a/boards/st/b_u585i_iot02a/b_u585i_iot02a_stm32u585xx_ns_defconfig b/boards/st/b_u585i_iot02a/b_u585i_iot02a_stm32u585xx_ns_defconfig index 2141cc748f8a1..8dd715679bb04 100644 --- a/boards/st/b_u585i_iot02a/b_u585i_iot02a_stm32u585xx_ns_defconfig +++ b/boards/st/b_u585i_iot02a/b_u585i_iot02a_stm32u585xx_ns_defconfig @@ -19,3 +19,5 @@ CONFIG_PINCTRL=y CONFIG_ARM_TRUSTZONE_M=y CONFIG_RUNTIME_NMI=y CONFIG_TRUSTED_EXECUTION_NONSECURE=y + +CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE="RSA-3072" diff --git a/boards/st/b_u585i_iot02a/board.cmake b/boards/st/b_u585i_iot02a/board.cmake index 73320d749c616..dc59f6f17fb75 100644 --- a/boards/st/b_u585i_iot02a/board.cmake +++ b/boards/st/b_u585i_iot02a/board.cmake @@ -12,8 +12,12 @@ if(CONFIG_BUILD_WITH_TFM) endif() endif() -board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw") +if(CONFIG_STM32_MEMMAP) board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +board_runner_args(stm32cubeprogrammer "--extload=MX25LM51245G_STM32U585I-IOT02A.stldr") +else() +board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw") +endif() board_runner_args(openocd "--tcl-port=6666") board_runner_args(openocd --cmd-pre-init "gdb_report_data_abort enable") diff --git a/boards/st/b_u585i_iot02a/doc/index.rst b/boards/st/b_u585i_iot02a/doc/index.rst index 166d2ac390736..0631b5b1ada94 100644 --- a/boards/st/b_u585i_iot02a/doc/index.rst +++ b/boards/st/b_u585i_iot02a/doc/index.rst @@ -197,6 +197,8 @@ The Zephyr b_u585i_iot02a board configuration supports the following hardware fe +-----------+------------+-------------------------------------+ | RADIO | STM32WB5MMG| Bluetooth Low Energy (BLE) | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ The default configuration can be found in the defconfig file: :zephyr_file:`boards/st/b_u585i_iot02a/b_u585i_iot02a_defconfig` diff --git a/boards/st/disco_l475_iot1/Kconfig.defconfig b/boards/st/disco_l475_iot1/Kconfig.defconfig index 5679d2caff840..808425eae0569 100644 --- a/boards/st/disco_l475_iot1/Kconfig.defconfig +++ b/boards/st/disco_l475_iot1/Kconfig.defconfig @@ -27,16 +27,15 @@ if BT config SPI default y -choice BT_HCI_BUS_TYPE - default BT_SPI -endchoice +config BT_SPI + default y config BT_BLUENRG_ACI default y # Disable Flow control config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/boards/st/disco_l475_iot1/disco_l475_iot1.dts b/boards/st/disco_l475_iot1/disco_l475_iot1.dts index 572e8768c9e01..c57f9f01e91c0 100644 --- a/boards/st/disco_l475_iot1/disco_l475_iot1.dts +++ b/boards/st/disco_l475_iot1/disco_l475_iot1.dts @@ -22,6 +22,7 @@ zephyr,code-partition = &slot0_partition; zephyr,flash-controller = &mx25r6435f; zephyr,bt-c2h-uart = &usart1; + zephyr,bt-hci = &hci_spi; }; leds { @@ -67,7 +68,6 @@ sw0 = &user_button; eswifi0 = &wifi0; watchdog0 = &iwdg; - spi-flash0 = &mx25r6435f; accel0 = &lsm6dsl; volt-sensor0 = &vref; volt-sensor1 = &vbat; @@ -191,7 +191,7 @@ cs-gpios = <&gpiod 13 GPIO_ACTIVE_LOW>, <&gpioe 0 GPIO_ACTIVE_LOW>; - spbtle-rf@0 { + hci_spi: spbtle-rf@0 { compatible = "st,hci-spi-v1"; reg = <0>; reset-gpios = <&gpioa 8 GPIO_ACTIVE_LOW>; diff --git a/boards/st/disco_l475_iot1/disco_l475_iot1.yaml b/boards/st/disco_l475_iot1/disco_l475_iot1.yaml index ca90da9607a00..6600d0724a855 100644 --- a/boards/st/disco_l475_iot1/disco_l475_iot1.yaml +++ b/boards/st/disco_l475_iot1/disco_l475_iot1.yaml @@ -25,6 +25,7 @@ supported: - dac - qspi - dma + - rtc ram: 96 flash: 1024 vendor: st diff --git a/boards/st/disco_l475_iot1/doc/index.rst b/boards/st/disco_l475_iot1/doc/index.rst index dc49d4fcb2d68..63ccdd9582eac 100644 --- a/boards/st/disco_l475_iot1/doc/index.rst +++ b/boards/st/disco_l475_iot1/doc/index.rst @@ -131,6 +131,8 @@ The Zephyr Disco L475 IoT board configuration supports the following hardware fe +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_c031c6/doc/index.rst b/boards/st/nucleo_c031c6/doc/index.rst index 8ed5a7edfeae3..8f44ab9d3079b 100644 --- a/boards/st/nucleo_c031c6/doc/index.rst +++ b/boards/st/nucleo_c031c6/doc/index.rst @@ -90,6 +90,8 @@ The Zephyr nucleo_c031c6 board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | DMA | on-chip | Direct Memory Access | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_c031c6/nucleo_c031c6.yaml b/boards/st/nucleo_c031c6/nucleo_c031c6.yaml index c4766287cc564..7f311f93c489a 100644 --- a/boards/st/nucleo_c031c6/nucleo_c031c6.yaml +++ b/boards/st/nucleo_c031c6/nucleo_c031c6.yaml @@ -14,6 +14,7 @@ supported: - adc - i2c - dma + - rtc ram: 12 flash: 32 vendor: st diff --git a/boards/st/nucleo_f030r8/nucleo_f030r8_2.yaml b/boards/st/nucleo_f030r8/nucleo_f030r8_2.yaml index 194e1b451993b..0cdc0e8ee9d2e 100644 --- a/boards/st/nucleo_f030r8/nucleo_f030r8_2.yaml +++ b/boards/st/nucleo_f030r8/nucleo_f030r8_2.yaml @@ -1,5 +1,5 @@ identifier: nucleo_f030r8@2 -name: ST Nucleo F030R8 +name: ST Nucleo F030R8 (rev. 2) type: mcu arch: arm toolchain: diff --git a/boards/st/nucleo_f070rb/doc/index.rst b/boards/st/nucleo_f070rb/doc/index.rst index 5e6544e9cfb76..e8d9f40a77b37 100644 --- a/boards/st/nucleo_f070rb/doc/index.rst +++ b/boards/st/nucleo_f070rb/doc/index.rst @@ -94,6 +94,8 @@ The Zephyr nucleo_f070rb board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | SPI | on-chip | SPI controller | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_f070rb/nucleo_f070rb.dts b/boards/st/nucleo_f070rb/nucleo_f070rb.dts index 7cd2e3bd7b662..c504dad4de50c 100644 --- a/boards/st/nucleo_f070rb/nucleo_f070rb.dts +++ b/boards/st/nucleo_f070rb/nucleo_f070rb.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 qianfan Zhao + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -48,6 +49,10 @@ }; }; +&clk_lse { + status = "okay"; +}; + &clk_hse { hse-bypass; clock-frequency = ; /* STLink 8MHz clock */ @@ -121,6 +126,12 @@ status = "okay"; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &die_temp { status = "okay"; }; diff --git a/boards/st/nucleo_f070rb/nucleo_f070rb.yaml b/boards/st/nucleo_f070rb/nucleo_f070rb.yaml index 60af06296a94e..5ed0d28dd3d54 100644 --- a/boards/st/nucleo_f070rb/nucleo_f070rb.yaml +++ b/boards/st/nucleo_f070rb/nucleo_f070rb.yaml @@ -18,6 +18,7 @@ supported: - i2c - spi - watchdog + - rtc testing: ignore_tags: - net diff --git a/boards/st/nucleo_f091rc/doc/index.rst b/boards/st/nucleo_f091rc/doc/index.rst index eee47f79254e1..a83b00bd82a44 100644 --- a/boards/st/nucleo_f091rc/doc/index.rst +++ b/boards/st/nucleo_f091rc/doc/index.rst @@ -108,6 +108,8 @@ The Zephyr nucleo_f091rc board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_f091rc/nucleo_f091rc.dts b/boards/st/nucleo_f091rc/nucleo_f091rc.dts index b7a94b29e9e83..b24435909182a 100644 --- a/boards/st/nucleo_f091rc/nucleo_f091rc.dts +++ b/boards/st/nucleo_f091rc/nucleo_f091rc.dts @@ -116,7 +116,6 @@ &can1 { pinctrl-0 = <&can_rx_pa11 &can_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f091rc/nucleo_f091rc.yaml b/boards/st/nucleo_f091rc/nucleo_f091rc.yaml index c19aa47d955b9..d0ac388b263a6 100644 --- a/boards/st/nucleo_f091rc/nucleo_f091rc.yaml +++ b/boards/st/nucleo_f091rc/nucleo_f091rc.yaml @@ -23,6 +23,7 @@ supported: - dma - pwm - can + - rtc testing: ignore_tags: - net diff --git a/boards/st/nucleo_f103rb/doc/index.rst b/boards/st/nucleo_f103rb/doc/index.rst index 0ff1a60ef85f1..e2313c5e932fd 100644 --- a/boards/st/nucleo_f103rb/doc/index.rst +++ b/boards/st/nucleo_f103rb/doc/index.rst @@ -99,8 +99,6 @@ The Zephyr nucleo_f103rb board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | COUNTER | on-chip | rtc | +-----------+------------+-------------------------------------+ -| RTC | on-chip | rtc | -+-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_f103rb/nucleo_f103rb.dts b/boards/st/nucleo_f103rb/nucleo_f103rb.dts index 1f225b4131263..53b9089e55496 100644 --- a/boards/st/nucleo_f103rb/nucleo_f103rb.dts +++ b/boards/st/nucleo_f103rb/nucleo_f103rb.dts @@ -69,6 +69,7 @@ ahb-prescaler = <1>; apb1-prescaler = <2>; apb2-prescaler = <1>; + adc-prescaler = <2>; }; &usart1 { diff --git a/boards/st/nucleo_f207zg/doc/index.rst b/boards/st/nucleo_f207zg/doc/index.rst index a801f0bc1e9a6..032cf2ab85944 100644 --- a/boards/st/nucleo_f207zg/doc/index.rst +++ b/boards/st/nucleo_f207zg/doc/index.rst @@ -108,6 +108,8 @@ The Zephyr nucleo_207zg board configuration supports the following hardware feat +-------------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-------------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-------------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_f207zg/nucleo_f207zg.yaml b/boards/st/nucleo_f207zg/nucleo_f207zg.yaml index f89510912be0f..aeb13880f84ad 100644 --- a/boards/st/nucleo_f207zg/nucleo_f207zg.yaml +++ b/boards/st/nucleo_f207zg/nucleo_f207zg.yaml @@ -24,4 +24,5 @@ supported: - pwm - rng - dma + - rtc vendor: st diff --git a/boards/st/nucleo_f303k8/nucleo_f303k8.dts b/boards/st/nucleo_f303k8/nucleo_f303k8.dts index 1090ae23ab27c..efdf58a848fbe 100644 --- a/boards/st/nucleo_f303k8/nucleo_f303k8.dts +++ b/boards/st/nucleo_f303k8/nucleo_f303k8.dts @@ -63,6 +63,7 @@ ahb-prescaler = <1>; apb1-prescaler = <2>; apb2-prescaler = <1>; + adc12-prescaler = <0>; }; &timers2 { diff --git a/boards/st/nucleo_f303re/nucleo_f303re.dts b/boards/st/nucleo_f303re/nucleo_f303re.dts index 7259a9f34af0e..efa840c140ad4 100644 --- a/boards/st/nucleo_f303re/nucleo_f303re.dts +++ b/boards/st/nucleo_f303re/nucleo_f303re.dts @@ -69,6 +69,8 @@ ahb-prescaler = <1>; apb1-prescaler = <2>; apb2-prescaler = <1>; + adc12-prescaler = <0>; + adc34-prescaler = <0>; }; &usart2 { @@ -94,7 +96,6 @@ &can1 { pinctrl-0 = <&can_rx_pb8 &can_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f401re/doc/index.rst b/boards/st/nucleo_f401re/doc/index.rst index bd806a6378ace..4b848eb10171e 100644 --- a/boards/st/nucleo_f401re/doc/index.rst +++ b/boards/st/nucleo_f401re/doc/index.rst @@ -87,6 +87,8 @@ The Zephyr nucleo_401re board configuration supports the following hardware feat +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on Zephyr porting. diff --git a/boards/st/nucleo_f401re/nucleo_f401re.yaml b/boards/st/nucleo_f401re/nucleo_f401re.yaml index ea1d89798c0c6..457c4295196ce 100644 --- a/boards/st/nucleo_f401re/nucleo_f401re.yaml +++ b/boards/st/nucleo_f401re/nucleo_f401re.yaml @@ -17,6 +17,7 @@ supported: - spi - adc - watchdog + - rtc ram: 96 flash: 512 vendor: st diff --git a/boards/st/nucleo_f413zh/nucleo_f413zh.yaml b/boards/st/nucleo_f413zh/nucleo_f413zh.yaml index 415b1d08f563c..4a8dda323d2f6 100644 --- a/boards/st/nucleo_f413zh/nucleo_f413zh.yaml +++ b/boards/st/nucleo_f413zh/nucleo_f413zh.yaml @@ -17,5 +17,6 @@ supported: - spi - gpio - usb_device + - usbd - counter vendor: st diff --git a/boards/st/nucleo_f429zi/doc/index.rst b/boards/st/nucleo_f429zi/doc/index.rst index 9e795649a4ebf..c15e524238b76 100644 --- a/boards/st/nucleo_f429zi/doc/index.rst +++ b/boards/st/nucleo_f429zi/doc/index.rst @@ -111,6 +111,8 @@ The Zephyr nucleo_f429zi board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_f429zi/nucleo_f429zi.yaml b/boards/st/nucleo_f429zi/nucleo_f429zi.yaml index 762ede6fb2c4b..f8c167bc5ef4d 100644 --- a/boards/st/nucleo_f429zi/nucleo_f429zi.yaml +++ b/boards/st/nucleo_f429zi/nucleo_f429zi.yaml @@ -24,4 +24,5 @@ supported: - dac - dma - nvs + - rtc vendor: st diff --git a/boards/st/nucleo_f446re/nucleo_f446re.dts b/boards/st/nucleo_f446re/nucleo_f446re.dts index 6afc2996acc6c..3674692ec9763 100644 --- a/boards/st/nucleo_f446re/nucleo_f446re.dts +++ b/boards/st/nucleo_f446re/nucleo_f446re.dts @@ -147,14 +147,12 @@ /* CAUTION: PB8 and PB9 may conflict with same pins of I2C1 */ pinctrl-0 = <&can1_rx_pb8 &can1_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; &can2 { pinctrl-0 = <&can2_rx_pb12 &can2_tx_pb13>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f446ze/nucleo_f446ze.dts b/boards/st/nucleo_f446ze/nucleo_f446ze.dts index d6c7dd4be456a..5eaad0ca83db5 100644 --- a/boards/st/nucleo_f446ze/nucleo_f446ze.dts +++ b/boards/st/nucleo_f446ze/nucleo_f446ze.dts @@ -180,7 +180,6 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f722ze/doc/index.rst b/boards/st/nucleo_f722ze/doc/index.rst index f0c40595f3a41..83b5413040524 100644 --- a/boards/st/nucleo_f722ze/doc/index.rst +++ b/boards/st/nucleo_f722ze/doc/index.rst @@ -115,6 +115,8 @@ Supported Features +---------------+------------+-------------------------------+ | WWDG | on-chip | watchdog | +---------------+------------+-------------------------------+ +| RTC | on-chip | rtc | ++---------------+------------+-------------------------------+ Connections and IOs =================== diff --git a/boards/st/nucleo_f722ze/nucleo_f722ze.dts b/boards/st/nucleo_f722ze/nucleo_f722ze.dts index 8a128e61e6e60..988a1204a9fdd 100644 --- a/boards/st/nucleo_f722ze/nucleo_f722ze.dts +++ b/boards/st/nucleo_f722ze/nucleo_f722ze.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2023 Evan Perry Grove + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -69,6 +70,10 @@ status = "disabled"; }; +&clk_lsi { + status = "okay"; +}; + &pll { div-m = <4>; mul-n = <216>; @@ -118,7 +123,6 @@ &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f722ze/nucleo_f722ze.yaml b/boards/st/nucleo_f722ze/nucleo_f722ze.yaml index 94cdcb739143d..4286f55eca9a1 100644 --- a/boards/st/nucleo_f722ze/nucleo_f722ze.yaml +++ b/boards/st/nucleo_f722ze/nucleo_f722ze.yaml @@ -20,6 +20,7 @@ supported: - quadspi - spi - usb_device + - rtc ram: 256 flash: 512 vendor: st diff --git a/boards/st/nucleo_f746zg/board.cmake b/boards/st/nucleo_f746zg/board.cmake index 8bbeabfe48630..718b783f69df0 100644 --- a/boards/st/nucleo_f746zg/board.cmake +++ b/boards/st/nucleo_f746zg/board.cmake @@ -1,6 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") board_runner_args(jlink "--device=STM32F746ZG" "--speed=4000") +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/st/nucleo_f746zg/doc/index.rst b/boards/st/nucleo_f746zg/doc/index.rst index cc1ca6d95ed71..f06415451704e 100644 --- a/boards/st/nucleo_f746zg/doc/index.rst +++ b/boards/st/nucleo_f746zg/doc/index.rst @@ -122,6 +122,8 @@ features: +-------------+------------+-------------------------------------+ | Backup SRAM | on-chip | Backup SRAM | +-------------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-------------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. @@ -189,6 +191,17 @@ Nucleo F746ZG board includes an ST-LINK/V2-1 embedded debug tool interface. Flashing an application to Nucleo F746ZG ---------------------------------------- +The board is configured to be flashed using west `STM32CubeProgrammer`_ runner, +so its installation is required to be able to flash the board. + +Alternatively, openocd (provided in Zephyr SDK) or JLink can also be used to +flash the board using the ``--runner`` (or ``-r``) option: + +.. code-block:: console + + $ west flash --runner openocd + $ west flash --runner jlink + Here is an example for the :ref:`hello_world` application. Run a serial host program to connect with your Nucleo board. @@ -233,3 +246,6 @@ You can debug an application in the usual way. Here is an example for the .. _STM32F746 reference manual: https://www.st.com/resource/en/reference_manual/dm00124865.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/st/nucleo_f746zg/nucleo_f746zg.dts b/boards/st/nucleo_f746zg/nucleo_f746zg.dts index db57eb734dc20..90c4b4409a0eb 100644 --- a/boards/st/nucleo_f746zg/nucleo_f746zg.dts +++ b/boards/st/nucleo_f746zg/nucleo_f746zg.dts @@ -166,7 +166,6 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f746zg/nucleo_f746zg.yaml b/boards/st/nucleo_f746zg/nucleo_f746zg.yaml index 015b1e3e642f1..ce8b0322fcd3e 100644 --- a/boards/st/nucleo_f746zg/nucleo_f746zg.yaml +++ b/boards/st/nucleo_f746zg/nucleo_f746zg.yaml @@ -26,4 +26,5 @@ supported: - dac - dma - backup_sram + - rtc vendor: st diff --git a/boards/st/nucleo_f767zi/doc/index.rst b/boards/st/nucleo_f767zi/doc/index.rst index 8500f7fd3f17a..5dec0099d905a 100644 --- a/boards/st/nucleo_f767zi/doc/index.rst +++ b/boards/st/nucleo_f767zi/doc/index.rst @@ -122,6 +122,8 @@ features: +-----------+------------+-------------------------------------+ | DAC | on-chip | DAC Controller | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ (*) nucleo_f767zi with soc cut-A (Device marking A) has some ethernet diff --git a/boards/st/nucleo_f767zi/nucleo_f767zi.dts b/boards/st/nucleo_f767zi/nucleo_f767zi.dts index 8ae863248f226..4125f4e6bde13 100644 --- a/boards/st/nucleo_f767zi/nucleo_f767zi.dts +++ b/boards/st/nucleo_f767zi/nucleo_f767zi.dts @@ -165,7 +165,6 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pd0 &can1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_f767zi/nucleo_f767zi.yaml b/boards/st/nucleo_f767zi/nucleo_f767zi.yaml index e3be20e378061..1ca2d19993fb7 100644 --- a/boards/st/nucleo_f767zi/nucleo_f767zi.yaml +++ b/boards/st/nucleo_f767zi/nucleo_f767zi.yaml @@ -25,4 +25,5 @@ supported: - counter - can - dac + - rtc vendor: st diff --git a/boards/st/nucleo_g071rb/doc/index.rst b/boards/st/nucleo_g071rb/doc/index.rst index 9cc78b0f4c823..094666250f397 100644 --- a/boards/st/nucleo_g071rb/doc/index.rst +++ b/boards/st/nucleo_g071rb/doc/index.rst @@ -112,6 +112,8 @@ The Zephyr nucleo_g071rb board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_g071rb/nucleo_g071rb.dts b/boards/st/nucleo_g071rb/nucleo_g071rb.dts index ba832c389cc39..9237cd779b014 100644 --- a/boards/st/nucleo_g071rb/nucleo_g071rb.dts +++ b/boards/st/nucleo_g071rb/nucleo_g071rb.dts @@ -94,6 +94,10 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>, <&rcc STM32_SRC_LSI RTC_SEL(2)>; status = "okay"; + + backup_regs { + status = "okay"; + }; }; &iwdg { diff --git a/boards/st/nucleo_g071rb/nucleo_g071rb.yaml b/boards/st/nucleo_g071rb/nucleo_g071rb.yaml index 755196fec1697..8caf70832cded 100644 --- a/boards/st/nucleo_g071rb/nucleo_g071rb.yaml +++ b/boards/st/nucleo_g071rb/nucleo_g071rb.yaml @@ -25,4 +25,5 @@ supported: - dma - lptim - nvs + - rtc vendor: st diff --git a/boards/st/nucleo_g0b1re/nucleo_g0b1re.dts b/boards/st/nucleo_g0b1re/nucleo_g0b1re.dts index ec79bd3575d31..d86d7c6ae8eea 100644 --- a/boards/st/nucleo_g0b1re/nucleo_g0b1re.dts +++ b/boards/st/nucleo_g0b1re/nucleo_g0b1re.dts @@ -183,8 +183,6 @@ zephyr_udc0: &usb { <&rcc STM32_SRC_PLL_Q FDCAN_SEL(1)>; pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; @@ -193,8 +191,6 @@ zephyr_udc0: &usb { <&rcc STM32_SRC_PLL_Q FDCAN_SEL(1)>; pinctrl-0 = <&fdcan2_rx_pb0 &fdcan2_tx_pb1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/nucleo_g474re/doc/index.rst b/boards/st/nucleo_g474re/doc/index.rst index 9d23c072b7597..d826ce3718858 100644 --- a/boards/st/nucleo_g474re/doc/index.rst +++ b/boards/st/nucleo_g474re/doc/index.rst @@ -129,6 +129,8 @@ The Zephyr nucleo_g474re board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | FDCAN1 | on-chip | CAN controller | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_g474re/nucleo_g474re.dts b/boards/st/nucleo_g474re/nucleo_g474re.dts index 74b0308d706da..a91ec3ccb6034 100644 --- a/boards/st/nucleo_g474re/nucleo_g474re.dts +++ b/boards/st/nucleo_g474re/nucleo_g474re.dts @@ -223,8 +223,6 @@ stm32_lp_tick_source: &lptim1 { <&rcc STM32_SRC_HSE FDCAN_SEL(0)>; pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/nucleo_g474re/nucleo_g474re.yaml b/boards/st/nucleo_g474re/nucleo_g474re.yaml index d473be929bfde..26c4254294ffe 100644 --- a/boards/st/nucleo_g474re/nucleo_g474re.yaml +++ b/boards/st/nucleo_g474re/nucleo_g474re.yaml @@ -24,4 +24,5 @@ supported: - dac - dma - can + - rtc vendor: st diff --git a/boards/st/nucleo_h533re/Kconfig.nucleo_h533re b/boards/st/nucleo_h533re/Kconfig.nucleo_h533re new file mode 100644 index 0000000000000..3d48952fb5896 --- /dev/null +++ b/boards/st/nucleo_h533re/Kconfig.nucleo_h533re @@ -0,0 +1,5 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_NUCLEO_H533RE + select SOC_STM32H533XX diff --git a/boards/st/nucleo_h533re/arduino_r3_connector.dtsi b/boards/st/nucleo_h533re/arduino_r3_connector.dtsi new file mode 100644 index 0000000000000..15bb1aab0bf5e --- /dev/null +++ b/boards/st/nucleo_h533re/arduino_r3_connector.dtsi @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpioa 0 0>, /* A0 */ + <1 0 &gpioa 1 0>, /* A1 */ + <2 0 &gpiob 1 0>, /* A2 */ + <3 0 &gpiob 0 0>, /* A3 */ + <4 0 &gpioc 1 0>, /* A4 */ + <5 0 &gpioc 0 0>, /* A5 */ + <6 0 &gpiob 15 0>, /* D0 */ + <7 0 &gpiob 14 0>, /* D1 */ + <8 0 &gpioc 8 0>, /* D2 */ + <9 0 &gpiob 3 0>, /* D3 */ + <10 0 &gpiob 5 0>, /* D4 */ + <11 0 &gpiob 4 0>, /* D5 */ + <12 0 &gpiob 10 0>, /* D6 */ + <13 0 &gpioa 8 0>, /* D7 */ + <14 0 &gpioc 7 0>, /* D8 */ + <15 0 &gpioc 6 0>, /* D9 */ + <16 0 &gpioc 9 0>, /* D10 */ + <17 0 &gpioa 7 0>, /* D11 */ + <18 0 &gpioa 6 0>, /* D12 */ + <19 0 &gpioa 5 0>, /* D13 */ + <20 0 &gpiob 7 0>, /* D14 */ + <21 0 &gpiob 6 0>; /* D15 */ + }; +}; + +arduino_serial: &usart1 {}; diff --git a/boards/st/nucleo_h533re/board.cmake b/boards/st/nucleo_h533re/board.cmake new file mode 100644 index 0000000000000..cec3a36c40362 --- /dev/null +++ b/boards/st/nucleo_h533re/board.cmake @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw") + +board_runner_args(pyocd "--target=stm32h533retx") + +board_runner_args(jlink "--device=STM32H533RE" "--reset-after-load") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/st/nucleo_h533re/board.yml b/boards/st/nucleo_h533re/board.yml new file mode 100644 index 0000000000000..4b633011b714a --- /dev/null +++ b/boards/st/nucleo_h533re/board.yml @@ -0,0 +1,5 @@ +board: + name: nucleo_h533re + vendor: st + socs: + - name: stm32h533xx diff --git a/boards/st/nucleo_h533re/doc/img/nucleo_h533re.jpg b/boards/st/nucleo_h533re/doc/img/nucleo_h533re.jpg new file mode 100644 index 0000000000000..aed4a9752f909 Binary files /dev/null and b/boards/st/nucleo_h533re/doc/img/nucleo_h533re.jpg differ diff --git a/boards/st/nucleo_h533re/doc/index.rst b/boards/st/nucleo_h533re/doc/index.rst new file mode 100644 index 0000000000000..b2ddb225e137f --- /dev/null +++ b/boards/st/nucleo_h533re/doc/index.rst @@ -0,0 +1,306 @@ +.. _nucleo_h533re_board: + +ST Nucleo H533RE +################ + +Overview +******** + +The Nucleo H533RE board is designed as an affordable development platform for +STMicroelectronics ARM |reg| Cortex |reg|-M33 core-based STM32H533RET6 +microcontroller with TrustZone |reg|. +Here are some highlights of the Nucleo H533RE board: + +- STM32H533RE microcontroller featuring 512 kbytes of Flash memory and 272 Kbytes of + SRAM in LQFP64 package + +- Board connectors: + + - USB Type-C |trade| Sink device FS + - ST Zio expansion connector including Arduino Uno V3 connectivity (CN5, CN6, CN8, CN9) + - ST morpho extension connector (CN7, CN10) + +- Flexible board power supply: + + - 5V_USB_STLK from ST-Link USB connector + - VIN (7 - 12V, 0.8) supplied via pin header CN6 pin 8 or CN7 pin 24 + - ESV on the ST morpho connector CN7 Pin 6 (5V, O.5A) + - VBUS_STLK from a USB charger via the ST-LINK USB connector + - VBUSC from the USB user connector (5V, 0.5A) + - 3V3_EXT supplied via a pin header CN6 pin 4 or CN7 pin 16 (3.3V, 1.3A) + +- On-board ST-LINK/V3EC debugger/programmer + + - mass storage + - Virtual COM port + - debug port + +- One user LED shared with ARDUINO |reg| Uno V3 +- Two push-buttons: USER and RESET +- 32.768 kHz crystal oscillator + +More information about the board can be found at the `NUCLEO_H533RE website`_. + +.. image:: img/nucleo_h533re.jpg + :align: center + :alt: NUCLEO H533RE + +Hardware +******** + +The STM32H533xx devices are high-performance microcontrollers from the STM32H5 +Series based on the high-performance Arm |reg| Cortex |reg|-M33 32-bit RISC core. +They operate at a frequency of up to 250 MHz. + +- Core: ARM |reg| 32-bit Cortex |reg| -M33 CPU with TrustZone |reg| and FPU. +- Performance benchmark: + + - 375 DMPIS/MHz (Dhrystone 2.1) + +- Security + + - Arm |reg| TrustZone |reg| with Armv8-M mainline security extension + - Up to eight configurable SAU regions + - TrustZone |reg| aware and securable peripherals + - Flexible life cycle scheme with secure debug authentication + - SESIP3 and PSA Level 3 certified assurance target + - Preconfigured immutable root of trust (ST-iROT) + - SFI (secure firmware installation) + - Root of trust thanks to unique boot entry and secure hide protection area (HDP) + - Secure data storage with hardware unique key (HUK) + - Secure firmware upgrade support with TF-M + - Two AES coprocessors including one with DPA resistance + - Public key accelerator, DPA resistant + - On-the-fly decryption of Octo-SPI external memories + - HASH hardware accelerator + - True random number generator, NIST SP800-90B compliant + - 96-bit unique ID + - Active tampers + +- Clock management: + + - 24 MHz crystal oscillator (HSE) + - 32 kHz crystal oscillator for RTC (LSE) + - Internal 64 MHz (HSI) trimmable by software + - Internal low-power 32 kHz RC (LSI)( |plusminus| 5%) + - Internal 4 MHz oscillator (CSI), trimmable by software + - Internal 48 MHz (HSI48) with recovery system + - 3 PLLs for system clock, USB, audio, ADC + +- Power management + + - Embedded regulator (LDO) with three configurable range output to supply the digital circuitry + - Embedded SMPS step-down converter + +- RTC with HW calendar, alarms and calibration +- Up to 112 fast I/Os, most 5 V-tolerant, up to 10 I/Os with independent supply down to 1.08 V +- Up to 16 timers and 2 watchdogs + + - 8x 16-bit + - 2x 32-bit timers with up to 4 IC/OC/PWM or pulse counter and quadrature (incremental) encoder input + - 2x 16-bit low-power 16-bit timers (available in Stop mode) + - 2x watchdogs + - 2x SysTick timer + +- Memories + + - Up to 512 Kbytes Flash, 2 banks read-while-write + - 1 Kbyte OTP (one-time programmable) + - 272 Kbytes of SRAM (80-Kbyte SRAM2 with ECC) + - 2 Kbytes of backup SRAM available in the lowest power modes + - Flexible external memory controller with up to 16-bit data bus: SRAM, PSRAM, FRAM, NOR/NAND memories + - 1x OCTOSPI memory interface with on-the-fly decryption and support for serial PSRAM/NAND/NOR, Hyper RAM/Flash frame formats + - 1x SD/SDIO/MMC interfaces + +- Rich analog peripherals (independent supply) + + - 2x 12-bit ADC with up to 5 MSPS in 12-bit + - 1x 12-bit DAC with 2 channels + - 1x Digital temperature sensor + - Voltage reference buffer + +- 34x communication interfaces + + - 1x USB Type-C / USB power-delivery controller + - 1x USB 2.0 full-speed host and device (crystal-less) + - 3x I2C FM+ interfaces (SMBus/PMBus) + - 2x I3C interface + - 6x U(S)ARTS (ISO7816 interface, LIN, IrDA, modem control) + - 1x LP UART + - 4x SPIs including 3 muxed with full-duplex I2S + - 4x additional SPI from 4x USART when configured in Synchronous mode + - 2x FDCAN + - 1x SDMMC interface + - 2x 16 channel DMA controllers + - 1x 8- to 14- bit camera interface + - 1x HDMI-CEC + - 1x 16-bit parallel slave synchronous-interface + +- Development support: serial wire debug (SWD), JTAG, Embedded Trace Macrocell |trade| + +More information about STM32H533RE can be found here: + +- `STM32H533re on www.st.com`_ +- `STM32H533 reference manual`_ + +Supported Features +================== + +The Zephyr nucleo_h533re board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| PWM | on-chip | PWM | ++-----------+------------+-------------------------------------+ +| RNG | on-chip | True Random number generator | ++-----------+------------+-------------------------------------+ +| RTC | on-chip | Real Time Clock | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | independent watchdog | ++-----------+------------+-------------------------------------+ + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig and dts files: + +- Secure target: + + - :zephyr_file:`boards/st/nucleo_h533re/nucleo_h533re_defconfig` + - :zephyr_file:`boards/st/nucleo_h533re/nucleo_h533re.dts` + +Zephyr board options +==================== + +The STM32H533 is a SoC with Cortex-M33 architecture. Zephyr provides support +for building for Secure firmware. + +The BOARD options are summarized below: + ++----------------------+-----------------------------------------------+ +| BOARD | Description | ++======================+===============================================+ +| nucleo_h533re | For building Secure firmware | ++----------------------+-----------------------------------------------+ + +Connections and IOs +=================== + +Nucleo H533RE Board has 8 GPIO controllers. These controllers are responsible for pin muxing, +input/output, pull-up, etc. + +For more details please refer to `STM32H5 Nucleo-64 board User Manual`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- ADC1 channel 14 input: PB1 +- USART1 TX/RX : PB14/PB15 (Arduino USART1) +- SPI1 SCK/MISO/MOSI/NSS: PA5/PA6/PA7/PC9 +- UART2 TX/RX : PA2/PA3 (VCP) +- USER_PB : PC13 + +System Clock +------------ + +Nucleo H533RE System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by PLL clock at +240MHz, driven by an 24MHz high-speed external clock. + +Serial Port +----------- + +Nucleo H533RE board has up to 6 U(S)ARTs. The Zephyr console output is assigned +to USART2. Default settings are 115200 8N1. + +Programming and Debugging +************************* + +Applications for the ``nucleo_h533re`` board can be built and +flashed in the usual way (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Flashing +======== + +Nucleo H533RE board includes an ST-LINK/V3EC embedded debug tool interface. +This probe allows to flash the board using various tools. + +Board is configured to be flashed using west STM32CubeProgrammer runner. +Installation of `STM32CubeProgrammer`_ is then required to flash the board. + +Alternatively, pyocd or jlink via an external probe can also be used to flash +and debug the board if west is told to use it as runner, which can be done by +passing either or ``-r pyocd``, or ``-r jlink``. + +For pyocd additional target information needs to be installed. +This can be done by executing the following commands. + +.. code-block:: console + + $ pyocd pack --update + $ pyocd pack --install stm32h5 + + +Flashing an application to Nucleo H533RE +------------------------------------------ + +Connect the Nucleo H533RE to your host computer using the USB port. +Then build and flash an application. Here is an example for the +:ref:`hello_world` application. + +Run a serial host program to connect with your Nucleo board: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 + +Then build and flash the application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: nucleo_h533re + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + Hello World! nucleo_h533re + +Debugging +========= + +You can debug an application in the usual way. Here is an example for the +:zephyr:code-sample:`blinky` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: nucleo_h533re + :goals: debug + +.. _NUCLEO_H533RE website: + https://www.st.com/en/evaluation-tools/nucleo-h533re + +.. _STM32H5 Nucleo-64 board User Manual: + https://www.st.com/resource/en/user_manual/um3121-stm32h5-nucleo64-board-mb1814-stmicroelectronics.pdf + +.. _STM32H533RE on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32h533re + +.. _STM32H533 reference manual: + https://www.st.com/resource/en/reference_manual/rm0481-stm32h533-stm32h563-stm32h573-and-stm32h562-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/st/nucleo_h533re/nucleo_h533re.dts b/boards/st/nucleo_h533re/nucleo_h533re.dts new file mode 100644 index 0000000000000..7071a5e21a8fb --- /dev/null +++ b/boards/st/nucleo_h533re/nucleo_h533re.dts @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "arduino_r3_connector.dtsi" +#include "st_morpho_connector.dtsi" +#include + +/ { + model = "STMicroelectronics STM32H533RE-NUCLEO board"; + compatible = "st,stm32h533re-nucleo"; + + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + zephyr,sram = &sram1; + zephyr,flash = &flash0; + }; + + leds: leds { + compatible = "gpio-leds"; + green_led_2: led_42 { + gpios = <&gpioa 5 GPIO_ACTIVE_LOW>; + label = "User LD2"; + }; + }; + + + pwmleds { + compatible = "pwm-leds"; + + green_pwm_led: green_pwm_led { + pwms = <&pwm3 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button { + label = "User"; + gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &green_led_2; + pwm-led0 = &green_pwm_led; + sw0 = &user_button; + watchdog0 = &iwdg; + volt-sensor0 = &vref; + }; +}; + +&clk_csi { + status = "okay"; +}; + +&clk_hsi { + status = "okay"; +}; + +&clk_hse { + clock-frequency = ; + status = "okay"; +}; + +&pll { + div-m = <2>; + mul-n = <40>; + div-p = <2>; + div-q = <2>; + div-r = <2>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb3-prescaler = <1>; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pb14 &usart1_rx_pb15>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&usart2 { + pinctrl-0 = <&usart2_tx_pa2 &usart2_rx_pa3>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&iwdg { + status = "okay"; +}; + +&timers3 { + st,prescaler = <1000>; + status = "okay"; + + pwm3: pwm { + pinctrl-0 = <&tim3_ch3_pb0>; + pinctrl-names = "default"; + status = "okay"; + }; +}; + +&vref { + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +&clk_lse { + status = "okay"; +}; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; diff --git a/boards/st/nucleo_h533re/nucleo_h533re.yaml b/boards/st/nucleo_h533re/nucleo_h533re.yaml new file mode 100644 index 0000000000000..8262b95a84379 --- /dev/null +++ b/boards/st/nucleo_h533re/nucleo_h533re.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2024 +# SPDX-License-Identifier: Apache-2.0 + +identifier: nucleo_h533re +name: ST Nucleo H533RE +type: mcu +arch: arm +toolchain: + - zephyr +ram: 272 +flash: 512 +supported: + - gpio + - watchdog + - pwm + - rtc +vendor: st diff --git a/boards/st/nucleo_h533re/nucleo_h533re_defconfig b/boards/st/nucleo_h533re/nucleo_h533re_defconfig new file mode 100644 index 0000000000000..5b88c80b24fec --- /dev/null +++ b/boards/st/nucleo_h533re/nucleo_h533re_defconfig @@ -0,0 +1,16 @@ +# SPDX-License-Identifier: Apache-2.0 + +# enable uart driver +CONFIG_SERIAL=y + +# console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable clock +CONFIG_CLOCK_CONTROL=y + +# enable GPIO +CONFIG_GPIO=y +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/nucleo_h533re/st_morpho_connector.dtsi b/boards/st/nucleo_h533re/st_morpho_connector.dtsi new file mode 100644 index 0000000000000..ce3d7c8401738 --- /dev/null +++ b/boards/st/nucleo_h533re/st_morpho_connector.dtsi @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + st_morpho_header: st-morpho-header { + compatible = "st-morpho-header"; + #gpio-cells = <2>; + gpio-map-mask = ; + gpio-map-pass-thru = <0x0 GPIO_DT_FLAGS_MASK>; + gpio-map = , + , + , + , + , /* SB40=ON, SB41=ON */ + , /* SB40=ON, SB41=ON */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + + , + , + , + , + , + , + , /* SB13=ON, SB17=ON */ + , + , /* SB13=ON, SB17=ON */ + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + , + ; + }; +}; diff --git a/boards/st/nucleo_h563zi/doc/index.rst b/boards/st/nucleo_h563zi/doc/index.rst index e707e81fefa55..ecb3266526110 100644 --- a/boards/st/nucleo_h563zi/doc/index.rst +++ b/boards/st/nucleo_h563zi/doc/index.rst @@ -150,6 +150,8 @@ The Zephyr nucleo_h563zi board configuration supports the following hardware fea +===========+============+=====================================+ | ADC | on-chip | ADC Controller | +-----------+------------+-------------------------------------+ +| CAN/CANFD | on-chip | CAN | ++-----------+------------+-------------------------------------+ | CLOCK | on-chip | reset and clock control | +-----------+------------+-------------------------------------+ | DAC | on-chip | DAC Controller | @@ -216,6 +218,7 @@ Default Zephyr Peripheral Mapping: - ADC1 channel 3 input: PA6 - ADC1 channel 15 input: PA3 - DAC1 channel 2 output: PA5 +- CAN/CANFD TX/RX: PD1/PD0 - LD1 (green): PB0 - LD2 (yellow): PF4 - LD3 (red): PG4 diff --git a/boards/st/nucleo_h563zi/nucleo_h563zi-common.dtsi b/boards/st/nucleo_h563zi/nucleo_h563zi-common.dtsi index 4d37501620885..030bab86a0cb2 100644 --- a/boards/st/nucleo_h563zi/nucleo_h563zi-common.dtsi +++ b/boards/st/nucleo_h563zi/nucleo_h563zi-common.dtsi @@ -66,7 +66,7 @@ div-m = <2>; mul-n = <120>; div-p = <2>; - div-q = <2>; + div-q = <3>; div-r = <2>; clocks = <&clk_hse>; status = "okay"; @@ -152,6 +152,15 @@ status = "okay"; }; +&fdcan1 { + pinctrl-0 = <&fdcan1_rx_pd0 &fdcan1_tx_pd1>; + pinctrl-names = "default"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>, + <&rcc STM32_SRC_PLL1_Q FDCAN_SEL(1)>; + clk-divider = <2>; + status = "okay"; +}; + &flash0 { partitions { compatible = "fixed-partitions"; diff --git a/boards/st/nucleo_h563zi/nucleo_h563zi.dts b/boards/st/nucleo_h563zi/nucleo_h563zi.dts index 915a0ddee6046..8acb70d0e6c42 100644 --- a/boards/st/nucleo_h563zi/nucleo_h563zi.dts +++ b/boards/st/nucleo_h563zi/nucleo_h563zi.dts @@ -22,6 +22,7 @@ zephyr,sram = &sram1; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,canbus = &fdcan1; }; aliases { diff --git a/boards/st/nucleo_h563zi/nucleo_h563zi.yaml b/boards/st/nucleo_h563zi/nucleo_h563zi.yaml index 0130798df9dd0..2b7c314c97643 100644 --- a/boards/st/nucleo_h563zi/nucleo_h563zi.yaml +++ b/boards/st/nucleo_h563zi/nucleo_h563zi.yaml @@ -11,12 +11,14 @@ supported: - gpio - arduino_serial - arduino_spi + - can - gpio - uart - entropy - adc - dac - pwm + - netif:eth - counter - spi - usb_device diff --git a/boards/st/nucleo_h723zg/doc/index.rst b/boards/st/nucleo_h723zg/doc/index.rst index 0c24a47992095..93574531dae21 100644 --- a/boards/st/nucleo_h723zg/doc/index.rst +++ b/boards/st/nucleo_h723zg/doc/index.rst @@ -115,6 +115,8 @@ features: +-------------+------------+-------------------------------------+ | Backup SRAM | on-chip | Backup SRAM | +-------------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-------------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_h723zg/nucleo_h723zg.yaml b/boards/st/nucleo_h723zg/nucleo_h723zg.yaml index 622c268eceafa..698fb32a091b9 100644 --- a/boards/st/nucleo_h723zg/nucleo_h723zg.yaml +++ b/boards/st/nucleo_h723zg/nucleo_h723zg.yaml @@ -21,4 +21,5 @@ supported: - netif:eth - backup_sram - usb_device + - rtc vendor: st diff --git a/boards/st/nucleo_h743zi/doc/index.rst b/boards/st/nucleo_h743zi/doc/index.rst index d5d1ee596b62a..66e75e574bbcd 100644 --- a/boards/st/nucleo_h743zi/doc/index.rst +++ b/boards/st/nucleo_h743zi/doc/index.rst @@ -129,6 +129,8 @@ features: +-------------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-------------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-------------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_h743zi/nucleo_h743zi.dts b/boards/st/nucleo_h743zi/nucleo_h743zi.dts index fd1a5a8b29ff8..6e5a80b459310 100644 --- a/boards/st/nucleo_h743zi/nucleo_h743zi.dts +++ b/boards/st/nucleo_h743zi/nucleo_h743zi.dts @@ -80,10 +80,10 @@ }; &pll { - div-m = <1>; - mul-n = <24>; + div-m = <2>; + mul-n = <240>; div-p = <2>; - div-q = <4>; + div-q = <2>; div-r = <2>; clocks = <&clk_hse>; status = "okay"; @@ -91,13 +91,13 @@ &rcc { clocks = <&pll>; - clock-frequency = ; + clock-frequency = ; d1cpre = <1>; - hpre = <1>; - d1ppre = <1>; - d2ppre1 = <1>; - d2ppre2 = <1>; - d3ppre = <1>; + hpre = <2>; + d1ppre = <2>; + d2ppre1 = <2>; + d2ppre2 = <2>; + d3ppre = <2>; }; &usart3 { @@ -172,8 +172,6 @@ zephyr_udc0: &usbotg_fs { pinctrl-names = "default"; clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL1_Q FDCAN_SEL(1)>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/nucleo_h743zi/nucleo_h743zi.yaml b/boards/st/nucleo_h743zi/nucleo_h743zi.yaml index e67e8d0e54e7f..b283964820abf 100644 --- a/boards/st/nucleo_h743zi/nucleo_h743zi.yaml +++ b/boards/st/nucleo_h743zi/nucleo_h743zi.yaml @@ -25,4 +25,5 @@ supported: - can - dac - dma + - rtc vendor: st diff --git a/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.yaml b/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.yaml index 904e740e5edf4..06d192a68326b 100644 --- a/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.yaml +++ b/boards/st/nucleo_h745zi_q/nucleo_h745zi_q_stm32h745xx_m7.yaml @@ -17,6 +17,5 @@ supported: - i2c - pwm - netif:eth - - usb_cdc - usb_device vendor: st diff --git a/boards/st/nucleo_h753zi/nucleo_h753zi.dts b/boards/st/nucleo_h753zi/nucleo_h753zi.dts index d8cc922acada2..2a2d68b400156 100644 --- a/boards/st/nucleo_h753zi/nucleo_h753zi.dts +++ b/boards/st/nucleo_h753zi/nucleo_h753zi.dts @@ -77,10 +77,10 @@ }; &pll { - div-m = <1>; - mul-n = <24>; + div-m = <2>; + mul-n = <240>; div-p = <2>; - div-q = <4>; + div-q = <2>; div-r = <2>; clocks = <&clk_hse>; status = "okay"; @@ -88,13 +88,13 @@ &rcc { clocks = <&pll>; - clock-frequency = ; + clock-frequency = ; d1cpre = <1>; - hpre = <1>; - d1ppre = <1>; - d2ppre1 = <1>; - d2ppre2 = <1>; - d3ppre = <1>; + hpre = <2>; + d1ppre = <2>; + d2ppre1 = <2>; + d2ppre2 = <2>; + d3ppre = <2>; }; &usart3 { @@ -149,8 +149,6 @@ zephyr_udc0: &usbotg_fs { &fdcan1 { pinctrl-0 = <&fdcan1_rx_pd0 &fdcan1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/nucleo_l073rz/doc/index.rst b/boards/st/nucleo_l073rz/doc/index.rst index 4c4ca788ddd0b..991a3710d08d2 100644 --- a/boards/st/nucleo_l073rz/doc/index.rst +++ b/boards/st/nucleo_l073rz/doc/index.rst @@ -104,6 +104,8 @@ The Zephyr nucleo_l073rz board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_l073rz/nucleo_l073rz.dts b/boards/st/nucleo_l073rz/nucleo_l073rz.dts index 93571670b7dba..eefd8d428e7e2 100644 --- a/boards/st/nucleo_l073rz/nucleo_l073rz.dts +++ b/boards/st/nucleo_l073rz/nucleo_l073rz.dts @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Ilya Tagunov + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -165,6 +166,12 @@ stm32_lp_tick_source: &lptim1 { }; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>, + <&rcc STM32_SRC_LSI RTC_SEL(2)>; + status = "okay"; +}; + &rng { status = "okay"; }; diff --git a/boards/st/nucleo_l073rz/nucleo_l073rz.yaml b/boards/st/nucleo_l073rz/nucleo_l073rz.yaml index f97973c48542d..2a2ffde92bd78 100644 --- a/boards/st/nucleo_l073rz/nucleo_l073rz.yaml +++ b/boards/st/nucleo_l073rz/nucleo_l073rz.yaml @@ -22,4 +22,5 @@ supported: - counter - rng - eeprom + - rtc vendor: st diff --git a/boards/st/nucleo_l152re/doc/index.rst b/boards/st/nucleo_l152re/doc/index.rst index 9d8e31a6a6e3a..e0e92e5c16843 100644 --- a/boards/st/nucleo_l152re/doc/index.rst +++ b/boards/st/nucleo_l152re/doc/index.rst @@ -100,6 +100,8 @@ The Zephyr nucleo_l152re board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/nucleo_l152re/nucleo_l152re.yaml b/boards/st/nucleo_l152re/nucleo_l152re.yaml index cc550b993c9c5..2713e735fa5a3 100644 --- a/boards/st/nucleo_l152re/nucleo_l152re.yaml +++ b/boards/st/nucleo_l152re/nucleo_l152re.yaml @@ -23,4 +23,5 @@ supported: - pwm - dma - nvs + - rtc vendor: st diff --git a/boards/st/nucleo_l432kc/nucleo_l432kc.dts b/boards/st/nucleo_l432kc/nucleo_l432kc.dts index 370cfe3a0d87b..f6a3d56891399 100644 --- a/boards/st/nucleo_l432kc/nucleo_l432kc.dts +++ b/boards/st/nucleo_l432kc/nucleo_l432kc.dts @@ -99,7 +99,6 @@ &can1 { pinctrl-0 = <&can1_rx_pa11 &can1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_l433rc_p/nucleo_l433rc_p.dts b/boards/st/nucleo_l433rc_p/nucleo_l433rc_p.dts index 3c58b14302df2..4e483b55f002b 100644 --- a/boards/st/nucleo_l433rc_p/nucleo_l433rc_p.dts +++ b/boards/st/nucleo_l433rc_p/nucleo_l433rc_p.dts @@ -118,7 +118,6 @@ &can1 { pinctrl-0 = <&can1_rx_pa11 &can1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_l452re/nucleo_l452re_common.dtsi b/boards/st/nucleo_l452re/nucleo_l452re_common.dtsi index 3da0ae94b9993..8f0d76d9a8651 100644 --- a/boards/st/nucleo_l452re/nucleo_l452re_common.dtsi +++ b/boards/st/nucleo_l452re/nucleo_l452re_common.dtsi @@ -102,7 +102,6 @@ &can1 { pinctrl-0 = <&can1_rx_pa11 &can1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/nucleo_l4r5zi/doc/index.rst b/boards/st/nucleo_l4r5zi/doc/index.rst index f449c985a8360..5fd6156e1ba96 100644 --- a/boards/st/nucleo_l4r5zi/doc/index.rst +++ b/boards/st/nucleo_l4r5zi/doc/index.rst @@ -141,6 +141,8 @@ hardware features: +-----------+------------+-------------------------------------+ | ADC | on-chip | adc | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_l4r5zi/nucleo_l4r5zi.yaml b/boards/st/nucleo_l4r5zi/nucleo_l4r5zi.yaml index ee4115fc1e6d3..5be0e1f69bed5 100644 --- a/boards/st/nucleo_l4r5zi/nucleo_l4r5zi.yaml +++ b/boards/st/nucleo_l4r5zi/nucleo_l4r5zi.yaml @@ -18,6 +18,7 @@ supported: - nvs - counter - adc + - rtc ram: 640 flash: 2048 vendor: st diff --git a/boards/st/nucleo_u575zi_q/doc/index.rst b/boards/st/nucleo_u575zi_q/doc/index.rst index 5786fa21b0702..d69bbe3f28d2a 100644 --- a/boards/st/nucleo_u575zi_q/doc/index.rst +++ b/boards/st/nucleo_u575zi_q/doc/index.rst @@ -167,10 +167,14 @@ The Zephyr nucleo_u575zi_q board configuration supports the following hardware f +-----------+------------+-------------------------------------+ | WATCHDOG | on-chip | independent watchdog | +-----------+------------+-------------------------------------+ +| USB FS | on-chip | USB Full Speed device | ++-----------+------------+-------------------------------------+ | BKP SRAM | on-chip | Backup SRAM | +-----------+------------+-------------------------------------+ | RNG | on-chip | True Random number generator | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi index 92e438d03a8cc..bd8dc8453e091 100644 --- a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi +++ b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q-common.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2021 Linaro Limited + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -171,13 +172,23 @@ status = "okay"; }; +zephyr_udc0: &usbotg_fs { + pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; +}; + &fdcan1 { clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000200>, <&rcc STM32_SRC_PLL1_Q FDCAN1_SEL(1)>; pinctrl-0 = <&fdcan1_rx_pd0 &fdcan1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; + status = "okay"; +}; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; status = "okay"; }; diff --git a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q.yaml b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q.yaml index 0c65b8361ff6c..a8a38453cb6f3 100644 --- a/boards/st/nucleo_u575zi_q/nucleo_u575zi_q.yaml +++ b/boards/st/nucleo_u575zi_q/nucleo_u575zi_q.yaml @@ -20,6 +20,7 @@ supported: - watchdog - backup_sram - dma + - rtc ram: 786 flash: 2048 vendor: st diff --git a/boards/st/nucleo_u5a5zj_q/doc/index.rst b/boards/st/nucleo_u5a5zj_q/doc/index.rst index 521997ca26614..9245300e816ba 100644 --- a/boards/st/nucleo_u5a5zj_q/doc/index.rst +++ b/boards/st/nucleo_u5a5zj_q/doc/index.rst @@ -205,6 +205,8 @@ The Zephyr nucleo_u5a5zj_q board configuration supports the following hardware f +-----------+------------+-------------------------------------+ | RNG | on-chip | True Random number generator | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi index d0ba893c87300..a08d7b47ce2a4 100644 --- a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi +++ b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q-common.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -175,8 +175,12 @@ <&rcc STM32_SRC_PLL1_Q FDCAN1_SEL(1)>; pinctrl-0 = <&fdcan1_rx_pd0 &fdcan1_tx_pd1>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; + status = "okay"; +}; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; status = "okay"; }; diff --git a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml index 4d74f6a13b8b0..cd93708041410 100644 --- a/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml +++ b/boards/st/nucleo_u5a5zj_q/nucleo_u5a5zj_q.yaml @@ -20,5 +20,6 @@ supported: - watchdog - backup_sram - dma + - rtc ram: 2450 flash: 4096 diff --git a/boards/st/nucleo_wb55rg/Kconfig.defconfig b/boards/st/nucleo_wb55rg/Kconfig.defconfig index a482290173980..cd63e8d080e01 100644 --- a/boards/st/nucleo_wb55rg/Kconfig.defconfig +++ b/boards/st/nucleo_wb55rg/Kconfig.defconfig @@ -5,9 +5,8 @@ if BOARD_NUCLEO_WB55RG -choice BT_HCI_BUS_TYPE - default BT_STM32_IPM +config BT_STM32_IPM + default y depends on BT -endchoice endif diff --git a/boards/st/nucleo_wb55rg/doc/nucleo_wb55rg.rst b/boards/st/nucleo_wb55rg/doc/nucleo_wb55rg.rst index 04bdc9d45ec71..6be25936050be 100644 --- a/boards/st/nucleo_wb55rg/doc/nucleo_wb55rg.rst +++ b/boards/st/nucleo_wb55rg/doc/nucleo_wb55rg.rst @@ -173,6 +173,8 @@ The Zephyr nucleo_wb55rg board configuration supports the following hardware fea +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_wb55rg/nucleo_wb55rg.yaml b/boards/st/nucleo_wb55rg/nucleo_wb55rg.yaml index f455356048c47..a2b42575b1b54 100644 --- a/boards/st/nucleo_wb55rg/nucleo_wb55rg.yaml +++ b/boards/st/nucleo_wb55rg/nucleo_wb55rg.yaml @@ -22,4 +22,5 @@ supported: - arduino_spi - usb_device - nvs + - rtc vendor: st diff --git a/boards/st/nucleo_wba55cg/doc/nucleo_wba55cg.rst b/boards/st/nucleo_wba55cg/doc/nucleo_wba55cg.rst index 2423d6bc36a66..70b08b6b0566b 100644 --- a/boards/st/nucleo_wba55cg/doc/nucleo_wba55cg.rst +++ b/boards/st/nucleo_wba55cg/doc/nucleo_wba55cg.rst @@ -177,6 +177,8 @@ The Zephyr nucleo_wba55cg board configuration supports the following hardware fe +-----------+------------+-------------------------------------+ | RADIO | on-chip | Bluetooth Low Energy | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts b/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts index 88dd4083209f4..f3ba9c494e29a 100644 --- a/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts +++ b/boards/st/nucleo_wba55cg/nucleo_wba55cg.dts @@ -19,6 +19,7 @@ #size-cells = <1>; chosen { + zephyr,bt-c2h-uart = &usart1; zephyr,console = &usart1; zephyr,shell-uart = &usart1; zephyr,sram = &sram0; @@ -28,24 +29,48 @@ leds: leds { compatible = "gpio-leds"; - blue_led_1: led_1 { + blue_led_1: led_0 { gpios = <&gpiob 4 GPIO_ACTIVE_LOW>; label = "User LD1"; }; + green_led_2: led_1 { + gpios = <&gpioa 9 GPIO_ACTIVE_LOW>; + label = "User LD2"; + }; + red_led_3: led_2 { + gpios = <&gpiob 8 GPIO_ACTIVE_LOW>; + label = "User LD3"; + }; }; gpio_keys { compatible = "gpio-keys"; - user_button: button { - label = "User"; - gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; + user_button_1: button_0 { + label = "User B1"; + gpios = <&gpioc 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; zephyr,code = ; }; + user_button_2: button_1 { + label = "User B2"; + gpios = <&gpiob 6 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; + }; + user_button_3: button_2 { + label = "User B3"; + gpios = <&gpiob 7 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>; + zephyr,code = ; + }; }; aliases { led0 = &blue_led_1; - sw0 = &user_button; + led1 = &green_led_2; + led2 = &red_led_3; + sw0 = &user_button_1; + sw1 = &user_button_2; + sw2 = &user_button_3; + mcuboot-led0 = &blue_led_1; + mcuboot-button0 = &user_button_1; }; }; diff --git a/boards/st/nucleo_wba55cg/nucleo_wba55cg.yaml b/boards/st/nucleo_wba55cg/nucleo_wba55cg.yaml index 0f435e29c75e0..947549a697cf4 100644 --- a/boards/st/nucleo_wba55cg/nucleo_wba55cg.yaml +++ b/boards/st/nucleo_wba55cg/nucleo_wba55cg.yaml @@ -16,6 +16,7 @@ supported: - arduino_i2c - arduino_spi - counter + - rtc ram: 128 flash: 1024 vendor: st diff --git a/boards/st/nucleo_wl55jc/doc/nucleo_wl55jc.rst b/boards/st/nucleo_wl55jc/doc/nucleo_wl55jc.rst index df32bbc07c071..50f7c63d9e02c 100644 --- a/boards/st/nucleo_wl55jc/doc/nucleo_wl55jc.rst +++ b/boards/st/nucleo_wl55jc/doc/nucleo_wl55jc.rst @@ -208,6 +208,8 @@ features: +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/nucleo_wl55jc/nucleo_wl55jc.dts b/boards/st/nucleo_wl55jc/nucleo_wl55jc.dts index e83f45452ddd8..6e37b1c148533 100644 --- a/boards/st/nucleo_wl55jc/nucleo_wl55jc.dts +++ b/boards/st/nucleo_wl55jc/nucleo_wl55jc.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 STMicroelectronics + * Copyright (c) 2020-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -85,6 +85,10 @@ stm32_lp_tick_source: &lptim1 { status = "okay"; }; +&clk_lse { + status = "okay"; +}; + &pll { div-m = <1>; mul-n = <6>; @@ -216,6 +220,12 @@ stm32_lp_tick_source: &lptim1 { }; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &vref { status = "okay"; }; diff --git a/boards/st/nucleo_wl55jc/nucleo_wl55jc.yaml b/boards/st/nucleo_wl55jc/nucleo_wl55jc.yaml index b741d37280550..4eb53ef3324fb 100644 --- a/boards/st/nucleo_wl55jc/nucleo_wl55jc.yaml +++ b/boards/st/nucleo_wl55jc/nucleo_wl55jc.yaml @@ -23,4 +23,5 @@ supported: - watchdog - nvs - lora + - rtc vendor: st diff --git a/boards/st/sensortile_box/Kconfig.defconfig b/boards/st/sensortile_box/Kconfig.defconfig index 29aa7598ef81b..faa5dc0864c4d 100644 --- a/boards/st/sensortile_box/Kconfig.defconfig +++ b/boards/st/sensortile_box/Kconfig.defconfig @@ -10,16 +10,15 @@ if BT config SPI default y -choice BT_HCI_BUS_TYPE - default BT_SPI -endchoice +config BT_SPI + default y config BT_BLUENRG_ACI default y # Disable Flow control config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/boards/st/sensortile_box/sensortile_box.dts b/boards/st/sensortile_box/sensortile_box.dts index 102dbb6a73a73..70a0b4f900701 100644 --- a/boards/st/sensortile_box/sensortile_box.dts +++ b/boards/st/sensortile_box/sensortile_box.dts @@ -19,6 +19,7 @@ zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,bt-c2h-uart = &usart1; + zephyr,bt-hci = &spbtle_1s_sensortile_box; }; leds { diff --git a/boards/st/sensortile_box_pro/CMakeLists.txt b/boards/st/sensortile_box_pro/CMakeLists.txt deleted file mode 100644 index f2a184ea87fe5..0000000000000 --- a/boards/st/sensortile_box_pro/CMakeLists.txt +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -zephyr_library_sources(board.c) diff --git a/boards/st/sensortile_box_pro/Kconfig b/boards/st/sensortile_box_pro/Kconfig new file mode 100644 index 0000000000000..d8dc05c44f6a6 --- /dev/null +++ b/boards/st/sensortile_box_pro/Kconfig @@ -0,0 +1,12 @@ +# SENSORTILE_BOX_PRO board configuration + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_SENSORTILE_BOX_PRO + +config BOARD_SERIAL_BACKEND_CDC_ACM + bool "Use USB CDC as serial console backend" + default y + +endif # BOARD_SENSORTILE_BOX_PRO diff --git a/boards/st/sensortile_box_pro/Kconfig.defconfig b/boards/st/sensortile_box_pro/Kconfig.defconfig index f0271728a9a3e..fb701bd426546 100644 --- a/boards/st/sensortile_box_pro/Kconfig.defconfig +++ b/boards/st/sensortile_box_pro/Kconfig.defconfig @@ -10,9 +10,8 @@ if BT config SPI default y -choice BT_HCI_BUS_TYPE - default BT_SPI -endchoice +config BT_SPI + default y config BT_BLUENRG_ACI default y @@ -27,6 +26,36 @@ config SPI_STM32_INTERRUPT default y depends on SPI +if BOARD_SERIAL_BACKEND_CDC_ACM + +config USB_DEVICE_STACK + default y + +config USB_CDC_ACM + default SERIAL + +config USB_DEVICE_INITIALIZE_AT_BOOT + default y if CONSOLE + +config SHELL_BACKEND_SERIAL_CHECK_DTR + default SHELL + depends on UART_LINE_CTRL + +config UART_LINE_CTRL + default SHELL + +config USB_DEVICE_REMOTE_WAKEUP + default n + +config USB_DEVICE_VID + default 0x0483 + +config USB_DEVICE_PID + default 0x5740 + +config USB_DEVICE_PRODUCT + default "Zephyr CDC SensorTile.box PRO" + if LOG # Logger cannot use itself to log @@ -36,4 +65,11 @@ endchoice endif # LOG +endif # BOARD_SERIAL_BACKEND_CDC_ACM + +DT_CHOSEN_ZEPHYR_CONSOLE := zephyr,console + +config UART_CONSOLE + default y if $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_CONSOLE)) && CONSOLE + endif # BOARD_SENSORTILE_BOX_PRO diff --git a/boards/st/sensortile_box_pro/board.c b/boards/st/sensortile_box_pro/board.c deleted file mode 100644 index b66edf23be48d..0000000000000 --- a/boards/st/sensortile_box_pro/board.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2023 STMicroelectronics - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CONSOLE) && defined(CONFIG_UART_CONSOLE) -#if DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart) -/* - * Enable console on USB CDC_ACM - */ -static int sensortile_box_pro_usb_console_init(void) -{ - const struct device *const dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); - - if (!device_is_ready(dev) || usb_enable(NULL)) { - return -1; - } - - return 0; -} - -/* needs to be done at Application */ -SYS_INIT(sensortile_box_pro_usb_console_init, APPLICATION, - CONFIG_KERNEL_INIT_PRIORITY_DEVICE); -#endif /* DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart) */ -#endif /* defined(CONFIG_CONSOLE) && defined (CONFIG_UART_CONSOLE) */ diff --git a/boards/st/sensortile_box_pro/doc/index.rst b/boards/st/sensortile_box_pro/doc/index.rst index e98ddace1bbf8..0d824aa9543e1 100644 --- a/boards/st/sensortile_box_pro/doc/index.rst +++ b/boards/st/sensortile_box_pro/doc/index.rst @@ -219,61 +219,44 @@ Console There are two possible options for Zephyr console output: -- through UART4 which is available on SWD connector (JP2). In this case a JTAG adapter - can be used to connect SensorTile.box PRO and have both SWD and console lines available. - - To enable console and shell over UART - - - switch the console lines from cdc_acm to uart4 - (:file:`boards/st/sensortile_box_pro/sensortile_box_pro.dts`) - - - comment out the USB configuration macros - (:file:`boards/st/sensortile_box_pro/sensortile_box_pro_defconfig`) +- through USB as USB CDC/ACM class. This is the default case present in the board dts file + and is enabled by :kconfig:option:`CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM`. .. code-block:: dts :caption: boards/st/sensortile_box_pro/sensortile_box_pro.dts / { chosen { - zephyr,console = &uart4; - zephyr,shell-uart = &uart4; - //zephyr,console = &cdc_acm_uart0; - //zephyr,shell-uart = &cdc_acm_uart0; + zephyr,console = &cdc_acm_uart0; + }; + }; + + &zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; }; }; -.. code-block:: Kconfig - :caption: boards/st/sensortile_box_pro/sensortile_box_pro_defconfig - # Comment out following USB config lines when - # switching console to UART - #CONFIG_USB_DEVICE_STACK=y - #CONFIG_USB_DEVICE_VID=0x0483 - #CONFIG_USB_DEVICE_PID=0x1235 - #CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC SensorTile.box PRO" - #CONFIG_USB_CDC_ACM_LOG_LEVEL_OFF=y - #CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n +- through UART4 which is available on SWD connector (JP2). In this case a JTAG adapter + can be used to connect SensorTile.box PRO and have both SWD and console lines available. + To enable console and shell over UART: -- through USB as USB CDC/ACM class. This is the default case present in the board dts file. + - in your prj.conf, override the board's default configuration by setting :code:`CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n` + + - add an overlay file named ``.overlay``: .. code-block:: dts - :caption: boards/st/sensortile_box_pro/sensortile_box_pro.dts / { chosen { - zephyr,console = &cdc_acm_uart0; - }; - }; - - &zephyr_udc0 { - cdc_acm_uart0: cdc_acm_uart0 { - compatible = "zephyr,cdc-acm-uart"; + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; }; }; - Console default settings are 115200 8N1. Programming and Debugging diff --git a/boards/st/sensortile_box_pro/sensortile_box_pro.dts b/boards/st/sensortile_box_pro/sensortile_box_pro.dts index 8bd870151a574..1d942fe83aeef 100644 --- a/boards/st/sensortile_box_pro/sensortile_box_pro.dts +++ b/boards/st/sensortile_box_pro/sensortile_box_pro.dts @@ -14,21 +14,13 @@ compatible = "st,sensortile-box-pro"; chosen { - /* - * By default, Zephyr console and shell are assigned to - * USB CDC/ACM. To enable console and shell over UART, - * uncomment following lines and set the correct config - * in sensortile_box_pro_defconfig. - * - * zephyr,console = &uart4; - * zephyr,shell-uart = &uart4; - */ zephyr,console = &cdc_acm_uart0; zephyr,shell-uart = &cdc_acm_uart0; zephyr,bt-c2h-uart = &cdc_acm_uart0; zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &hci_spi; }; leds { @@ -163,7 +155,7 @@ stm32_lp_tick_source: &lptim1 { cs-gpios = <&gpioa 2 GPIO_ACTIVE_LOW>; status = "okay"; - bluenrg-lp@0 { + hci_spi: bluenrg-lp@0 { compatible = "st,hci-spi-v2"; reg = <0>; irq-gpios = <&gpiod 1 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; diff --git a/boards/st/sensortile_box_pro/sensortile_box_pro_defconfig b/boards/st/sensortile_box_pro/sensortile_box_pro_defconfig index a47f372d78471..ea12679af4817 100644 --- a/boards/st/sensortile_box_pro/sensortile_box_pro_defconfig +++ b/boards/st/sensortile_box_pro/sensortile_box_pro_defconfig @@ -12,20 +12,9 @@ CONFIG_GPIO=y # Enable Clocks CONFIG_CLOCK_CONTROL=y -# config USB and USB console +# Enable console CONFIG_SERIAL=y CONFIG_CONSOLE=y -CONFIG_UART_CONSOLE=y -CONFIG_UART_LINE_CTRL=y -CONFIG_UART_INTERRUPT_DRIVEN=y - -# Comment out following USB config lines when -# switching console to UART -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_VID=0x0483 -CONFIG_USB_DEVICE_PID=0x1235 -CONFIG_USB_DEVICE_PRODUCT="Zephyr CDC SensorTile.box PRO" -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n # enable pin controller CONFIG_PINCTRL=y diff --git a/boards/st/st25dv_mb1283_disco/support/openocd.cfg b/boards/st/st25dv_mb1283_disco/support/openocd.cfg index 72b4cd7492a21..5d6a3772c5cf6 100644 --- a/boards/st/st25dv_mb1283_disco/support/openocd.cfg +++ b/boards/st/st25dv_mb1283_disco/support/openocd.cfg @@ -4,7 +4,7 @@ transport select hla_swd source [find target/stm32f4x.cfg] -adapter_khz 1000 +adapter speed 1000 reset_config srst_only diff --git a/boards/st/steval_stwinbx1/Kconfig b/boards/st/steval_stwinbx1/Kconfig new file mode 100644 index 0000000000000..520aea81d168a --- /dev/null +++ b/boards/st/steval_stwinbx1/Kconfig @@ -0,0 +1,12 @@ +# STEVAL_STWINBX1 Development kit board configuration + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_STEVAL_STWINBX1 + +config BOARD_SERIAL_BACKEND_CDC_ACM + bool "Use USB CDC as serial console backend" + default y + +endif # BOARD_STEVAL_STWINBX1 diff --git a/boards/st/steval_stwinbx1/Kconfig.defconfig b/boards/st/steval_stwinbx1/Kconfig.defconfig new file mode 100644 index 0000000000000..657170dd30344 --- /dev/null +++ b/boards/st/steval_stwinbx1/Kconfig.defconfig @@ -0,0 +1,75 @@ +# STEVAL_STWINBX1 Development kit board configuration + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_STEVAL_STWINBX1 + +if BT + +config SPI + default y + +config BT_SPI + default y + +config BT_BLUENRG_ACI + default y + +# Disable Flow control +config BT_HCI_ACL_FLOW_CONTROL + default n + +endif # BT + +config SPI_STM32_INTERRUPT + default y + depends on SPI + +if BOARD_SERIAL_BACKEND_CDC_ACM + +config USB_DEVICE_STACK + default y + +config USB_CDC_ACM + default SERIAL + +config USB_DEVICE_INITIALIZE_AT_BOOT + default y if CONSOLE + +config SHELL_BACKEND_SERIAL_CHECK_DTR + default SHELL + depends on UART_LINE_CTRL + +config UART_LINE_CTRL + default SHELL + +config USB_DEVICE_REMOTE_WAKEUP + default n + +config USB_DEVICE_VID + default 0x0483 + +config USB_DEVICE_PID + default 0x5740 + +config USB_DEVICE_PRODUCT + default "Zephyr CDC STEval-STWinbx1" + +if LOG + +# Logger cannot use itself to log +choice USB_CDC_ACM_LOG_LEVEL_CHOICE + default USB_CDC_ACM_LOG_LEVEL_OFF +endchoice + +endif # LOG + +endif # BOARD_SERIAL_BACKEND_CDC_ACM + +DT_CHOSEN_ZEPHYR_CONSOLE := zephyr,console + +config UART_CONSOLE + default y if $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_CONSOLE)) && CONSOLE + +endif # BOARD_STEVAL_STWINBX1 diff --git a/boards/st/steval_stwinbx1/Kconfig.steval_stwinbx1 b/boards/st/steval_stwinbx1/Kconfig.steval_stwinbx1 new file mode 100644 index 0000000000000..aae01c61ac776 --- /dev/null +++ b/boards/st/steval_stwinbx1/Kconfig.steval_stwinbx1 @@ -0,0 +1,5 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STEVAL_STWINBX1 + select SOC_STM32U585XX diff --git a/boards/st/steval_stwinbx1/board.cmake b/boards/st/steval_stwinbx1/board.cmake new file mode 100644 index 0000000000000..7b41b6115ca78 --- /dev/null +++ b/boards/st/steval_stwinbx1/board.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +# By default stm32cubeprogrammer configured to use DFU upload method. +# Comment below line and uncomment the second line to use SWD upoad method. +board_runner_args(stm32cubeprogrammer "--port=usb1") +# board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") + +# Even if flash and start work, dfu-util return error 74. It can be ignored. +board_runner_args(dfu-util "--pid=0483:df11" "--alt=0" "--dfuse") + +board_runner_args(openocd "--tcl-port=6666") +board_runner_args(openocd --cmd-pre-init "gdb_report_data_abort enable") +board_runner_args(openocd "--no-halt") + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/dfu-util.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/st/steval_stwinbx1/board.yml b/boards/st/steval_stwinbx1/board.yml new file mode 100644 index 0000000000000..6431922325371 --- /dev/null +++ b/boards/st/steval_stwinbx1/board.yml @@ -0,0 +1,5 @@ +board: + name: steval_stwinbx1 + vendor: st + socs: + - name: stm32u585xx diff --git a/boards/st/steval_stwinbx1/doc/img/steval_stwinbx1.jpg b/boards/st/steval_stwinbx1/doc/img/steval_stwinbx1.jpg new file mode 100644 index 0000000000000..ed0b01c815889 Binary files /dev/null and b/boards/st/steval_stwinbx1/doc/img/steval_stwinbx1.jpg differ diff --git a/boards/st/steval_stwinbx1/doc/index.rst b/boards/st/steval_stwinbx1/doc/index.rst new file mode 100644 index 0000000000000..9027db10e5e82 --- /dev/null +++ b/boards/st/steval_stwinbx1/doc/index.rst @@ -0,0 +1,427 @@ +.. _steval_stwinbx1_board: + +STEVAL STWINBX1 Development kit +############################### + +Overview +******** + +The STWIN.box (STEVAL-STWINBX1) is a development kit that features an Arm|reg| Cortex|reg|-M33 based STM32U585AI MCU +and is a reference design that simplifies prototyping and testing of advanced industrial sensing applications in +IoT contexts such as condition monitoring and predictive maintenance. + +The STEVAL-STWINBX1 kit consists of an STWIN.box core system, a 480mAh LiPo battery, an adapter for the ST-LINK debugger, +a plastic case, an adapter board for DIL 24 sensors and a flexible cable. + +.. image:: img/steval_stwinbx1.jpg + :align: center + :alt: STEVAL-STWINBX1 Development kit + +More information about the board can be found at the `STEVAL-STWINBX1 Development kit website`_. + + +Supported Features +****************** + +The STEVAL-STWINBX1 provides motion, environmental, and audio +sensor data through either the built-in RS485 transceiver, BLE, Wi-Fi, and +NFC or USB protocols to a host application running on a smartphone/PC to implement applications such as: + +- Multisensing wireless platform for vibration monitoring and ultrasound detection +- Baby crying detection with Cloud AI learning +- Barometer / environmental monitoring +- Vehicle / goods tracking +- Vibration monitoring +- Compass and inclinometer +- Sensor data logger + +(see `Sensing`_ section for the complete lists of available +sensors on board) + +Hardware +******** + +The STM32U585xx devices are an ultra-low-power microcontrollers family (STM32U5 +Series) based on the high-performance Arm|reg| Cortex|reg|-M33 32-bit RISC core. +They operate at a frequency of up to 160 MHz. + +- Ultra-low-power with FlexPowerControl (down to 300 nA Standby mode and 19.5 uA/MHz run mode) +- Core: ARM |reg| 32-bit Cortex |reg| -M33 CPU with TrustZone |reg| and FPU. +- Performance benchmark: + + - 1.5 DMPIS/MHz (Drystone 2.1) + - 651 CoreMark |reg| (4.07 CoreMark |reg| /MHZ) + +- Security and cryptography + + - Arm |reg| TrustZone |reg| and securable I/Os memories and peripherals + - Flexible life cycle scheme with RDP (readout protection) and password protected debug + - Root of trust thanks to unique boot entry and secure hide protection area (HDP) + - Secure Firmware Installation thanks to embedded Root Secure Services + - Secure data storage with hardware unique key (HUK) + - Secure Firmware Update support with TF-M + - 2 AES coprocessors including one with DPA resistance + - Public key accelerator, DPA resistant + - On-the-fly decryption of Octo-SPI external memories + - HASH hardware accelerator + - Active tampers + - True Random Number Generator NIST SP800-90B compliant + - 96-bit unique ID + - 512-byte One-Time Programmable for user data + - Active tampers + +- Clock management: + + - 4 to 50 MHz crystal oscillator + - 32 kHz crystal oscillator for RTC (LSE) + - Internal 16 MHz factory-trimmed RC ( |plusminus| 1%) + - Internal low-power 32 kHz RC ( |plusminus| 5%) + - 2 internal multispeed 100 kHz to 48 MHz oscillators, including one auto-trimmed by + LSE (better than |plusminus| 0.25 % accuracy) + - 3 PLLs for system clock, USB, audio, ADC + - Internal 48 MHz with clock recovery + +- Power management + + - Embedded regulator (LDO) + - Embedded SMPS step-down converter supporting switch on-the-fly and voltage scaling + +- RTC with HW calendar and calibration +- Up to 136 fast I/Os, most 5 V-tolerant, up to 14 I/Os with independent supply down to 1.08 V +- Up to 24 capacitive sensing channels: support touchkey, linear and rotary touch sensors +- Up to 17 timers and 2 watchdogs + + - 2x 16-bit advanced motor-control + - 2x 32-bit and 5 x 16-bit general purpose + - 4x low-power 16-bit timers (available in Stop mode) + - 2x watchdogs + - 2x SysTick timer + +- ART accelerator + + - 8-Kbyte instruction cache allowing 0-wait-state execution from Flash and + external memories: up to 160 MHz, MPU, 240 DMIPS and DSP + - 4-Kbyte data cache for external memories + +- Memories + + - 2-Mbyte Flash memory with ECC, 2 banks read-while-write, including 512 Kbytes with 100 kcycles + - 786-Kbyte SRAM with ECC OFF or 722-Kbyte SRAM including up to 322-Kbyte SRAM with ECC ON + - External memory interface supporting SRAM, PSRAM, NOR, NAND and FRAM memories + - 2 Octo-SPI memory interfaces + +- Rich analog peripherals (independent supply) + + - 14-bit ADC 2.5-Msps, resolution up to 16 bits with hardware oversampling + - 12-bit ADC 2.5-Msps, with hardware oversampling, autonomous in Stop 2 mode + - 12-bit DAC, low-power sample and hold + - 2 operational amplifiers with built-in PGA + - 2 ultra-low-power comparators + +- Up to 22 communication interfaces + + - USB Type-C / USB power delivery controller + - USB OTG 2.0 full-speed controller + - 2x SAIs (serial audio interface) + - 4x I2C FM+(1 Mbit/s), SMBus/PMBus + - 6x USARTs (ISO 7816, LIN, IrDA, modem) + - 3x SPIs (5x SPIs with dual OCTOSPI in SPI mode) + - 1x FDCAN + - 2x SDMMC interface + - 16- and 4-channel DMA controllers, functional in Stop mode + - 1 multi-function digital filter (6 filters)+ 1 audio digital filter with + sound-activity detection + +- CRC calculation unit +- Development support: serial wire debug (SWD), JTAG, Embedded Trace Macrocell |trade| +- True Random Number Generator (RNG) + +- Graphic features + + - Chrom-ART Accelerator (DMA2D) for enhanced graphic content creation + - 1 digital camera interface + +- Mathematical co-processor + + - CORDIC for trigonometric functions acceleration + - FMAC (filter mathematical accelerator) + + +More information about STM32U585AI can be found here: + +- `STM32U585 on www.st.com`_ +- `STM32U585 reference manual`_ + +Connectivity +************ + + - **BlueNRG-M2SA** Bluetooth|reg| low energy v5.2 wireless technology module + (`BlueNRG-M2 datasheet`_) + - **MXCHIP EMW3080** (802.11 b/g/n compliant Wi-Fi module) + - **ST25DV64K** dynamic NFC/RFID tag IC with 64-Kbit EEPROM + (`st25dv64k datasheet`_) + - USB Type-C|trade| connector (power supply and data) + - STDC14 programming connector for **STLINK-V3MINI** + (`stlink-v3mini`_) + - microSD card socket + +Sensing +******* + + - **ILPS22QS** MEMS pressure sensor + (`ilps22qs datasheet`_) + - **STTS22H** Digital temperature sensor + (`stts22hh datasheet`_) + - **TSV912** wide-bandwidth (8 MHz) rail-to-rail I/O op-amp + (`tsv912 datasheet`_) + - **ISM330DHCX** iNEMO IMU, 3D accelerometer and 3D gyroscope with Machine Learning Core and Finite State Machine + (`ism330dhcx datasheet`_) + - **IIS3DWB** wide bandwidth accelerometer + (`iis3dwb datasheet`_) + - **IIS2DLPC** high-performance ultra-low-power 3-axis accelerometer for industrial applications + (`iis2dlpc datasheet`_) + - **IIS2MDC** 3-axis magnetometer + (`iis2mdc datasheet`_) + - **IIS2ICLX** high-accuracy, high-resolution, low-power, 2-axis digital inclinometer with Machine Learning Core + (`iis2iclx datasheet`_) + - **IMP23ABSU** analog MEMS microphone + (`imp23absu datasheet`_) + - **IMP34DT05** digital MEMS microphone + (`imp34dt05 datasheet`_) + +Connections and IOs +******************* + +- 2x user LEDs + + - **led0** (Green) + - **led1** (Orange) + +- 4x buttons/switch + + - **User** / **boot0** button, available to user application + but useful to let the SensorTile.box PRO enter DFU mode + if found pressed after h/w reset (see **rst** button and + `Programming and Debugging`_ section) + - **RESET** button, used to reset the board + - **PWR** button, used to Power on/off the board + + +For more details please refer to `STEVAL-STWINBX1 board User Manual`_. + +System Clock +------------ + +STEVAL-STWINBX1 System Clock could be driven by an internal or external oscillator, +as well as the main PLL clock. By default the System clock is driven by the PLL clock at 160MHz, +driven by 16MHz high speed external oscillator. +The internal AHB/APB1/APB2/APB3 AMBA buses are all clocked at 160MHz. + +Serial Port +----------- + +The USART2 is connected to JTAG/SWD connector +and may be used as console. + +USB interface +------------- + +STEVAL-STWINBX1 can be connected as a USB device to a PC host through its USB-C connector. +The final application may use it to declare STEVAL-STWINBX1 device as belonging to a +certain standard or vendor class, e.g. a CDC, a mass storage or a composite device with both +functions. + +Console +------- + +There are two possible options for Zephyr console output: + + +- through USB as USB CDC/ACM class. This is the default case present in the board dts file + and is enabled by :kconfig:option:`CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM`. + +.. code-block:: dts + :caption: boards/st/steval_stwinbx1/steval_stwinbx1.dts + + / { + chosen { + zephyr,console = &cdc_acm_uart0; + }; + }; + + &zephyr_udc0 { + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; + }; + +- through USART2 which is available on SWD connector (CN4). In this case a JTAG adapter + can be used to connect STEVAL-STWINBX1 and have both SWD and console lines available. + + To enable console and shell over UART: + + - in your prj.conf, override the board's default configuration by setting :code:`CONFIG_BOARD_SERIAL_BACKEND_CDC_ACM=n` + + - add an overlay file named ``.overlay``: + +.. code-block:: dts + + / { + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + }; + }; + + +Console default settings are 115200 8N1. + +Programming and Debugging +------------------------- + +There are two alternative methods of flashing ST Sensortile.box Pro board: + +1. Using DFU software tools + + This method requires to enter STM32U585 ROM bootloader DFU mode + by powering up (or reset) the board while keeping the USER (BOOT0) button pressed. + No additional hardware is required except a USB-C cable. This method is fully + supported by :ref:`flash-debug-host-tools`. + You can read more about how to enable and use the ROM bootloader by checking + the application note `AN2606`_ (STM32U585xx section). + +2. Using SWD hardware tools + + The STEVAL-STWINBX1 does not include a on-board debug probe. + It requires to connect additional hardware, like a ST-LINK/V3 + embedded debug tool, to the board STDC14 connector (CN4) labeled ``MCU-/SWD``. + + +Install dfu-util +---------------- + +.. note:: + Required only to use dfu-util runner. + +It is recommended to use at least v0.9 of dfu-util. The package available in +Debian and Ubuntu can be quite old, so you might have to build dfu-util from source. +Information about how to get the source code and how to build it can be found +at the `DFU-UTIL website`_ + +Install STM32CubeProgrammer +--------------------------- + +.. note:: + Required to program over DFU (default) or SWD. + +It is recommended to use the latest version of `STM32CubeProgrammer`_ + + +Flash an Application to STEVAL-STWINBX1 +------------------------------------------ + +There are two ways to enter DFU mode: + +1. USB-C cable not connected + + While pressing the USER button, connect the USB-C cable to the USB OTG STEVAL-STWINBX1 + port and to your computer. + +2. USB-C cable connected + + While pressing the USER button, press the RESET button and release it. + +With both methods, the board should be forced to enter DFU mode. + +Check that the board is indeed in DFU mode: + +.. code-block:: console + + $ sudo dfu-util -l + dfu-util 0.9 + + Copyright 2005-2009 Weston Schmidt, Harald Welte and OpenMoko Inc. + Copyright 2010-2019 Tormod Volden and Stefan Schmidt + This program is Free Software and has ABSOLUTELY NO WARRANTY + Please report bugs to http://sourceforge.net/p/dfu-util/tickets/ + + Found DFU: [0483:df11] ver=0200, devnum=58, cfg=1, intf=0, path="3-1", alt=2, name="@OTP Memory /0x0BFA0000/01*512 e", serial="207136863530" + Found DFU: [0483:df11] ver=0200, devnum=58, cfg=1, intf=0, path="3-1", alt=1, name="@Option Bytes /0x40022040/01*64 e", serial="207136863530" + Found DFU: [0483:df11] ver=0200, devnum=58, cfg=1, intf=0, path="3-1", alt=0, name="@Internal Flash /0x08000000/256*08Kg", serial="207136863530" + +You should see the following confirmation on your Linux host: + +.. code-block:: console + + $ dmesg + usb 3-1: new full-speed USB device number 16 using xhci_hcd + usb 3-1: New USB device found, idVendor=0483, idProduct=df11, bcdDevice= 2.00 + usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3 + usb 3-1: Product: DFU in FS Mode + usb 3-1: Manufacturer: STMicroelectronics + usb 3-1: SerialNumber: 207136863530 + +.. You can build and flash the provided sample application +.. (:ref:`sensortile_box_pro_sample_sensors`) that reads sensors data and outputs +.. values on the console. + + +.. _STEVAL-STWINBX1 Development kit website: + https://www.st.com/en/evaluation-tools/steval-stwinbx1.html + +.. _STEVAL-STWINBX1 board User Manual: + https://www.st.com/resource/en/user_manual/um2965-getting-started-with-the-stevalstwinbx1-sensortile-wireless-industrial-node-development-kit-stmicroelectronics.pdf + +.. _STM32U585 on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32u575-585.html + +.. _STM32U585 reference manual: + https://www.st.com/resource/en/reference_manual/rm0456-stm32u575585-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html + +.. _DFU-UTIL website: + http://dfu-util.sourceforge.net/ + +.. _AN2606: + http://www.st.com/content/ccc/resource/technical/document/application_note/b9/9b/16/3a/12/1e/40/0c/CD00167594.pdf/files/CD00167594.pdf/jcr:content/translations/en.CD00167594.pdf + +.. _BlueNRG-M2 datasheet: + https://www.st.com/en/product/BlueNRG-M2 + +.. _st25dv64k datasheet: + https://www.st.com/en/nfc/st25dv64k.html + +.. _stlink-v3mini: + https://www.st.com/en/development-tools/stlink-v3mini.html + +.. _ilps22qs datasheet: + https://www.st.com/en/mems-and-sensors/ilps22qs.html + +.. _stts22hh datasheet: + https://www.st.com/en/mems-and-sensors/stts22h.html + +.. _tsv912 datasheet: + https://www.st.com/en/automotive-analog-and-power/tsv912.html + +.. _ism330dhcx datasheet: + https://www.st.com/en/mems-and-sensors/ism330dhcx.html + +.. _iis3dwb datasheet: + https://www.st.com/en/mems-and-sensors/iis3dwb.html + +.. _iis2dlpc datasheet: + https://www.st.com/en/mems-and-sensors/iis2dlpc.html + +.. _iis2mdc datasheet: + https://www.st.com/en/mems-and-sensors/iis2mdc.html + +.. _iis2iclx datasheet: + https://www.st.com/en/mems-and-sensors/iis2iclx.html + +.. _imp23absu datasheet: + https://www.st.com/en/mems-and-sensors/imp23absu.html + +.. _imp34dt05 datasheet: + https://www.st.com/en/mems-and-sensors/imp34dt05.html diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1.dts b/boards/st/steval_stwinbx1/steval_stwinbx1.dts new file mode 100644 index 0000000000000..d8c3586320db9 --- /dev/null +++ b/boards/st/steval_stwinbx1/steval_stwinbx1.dts @@ -0,0 +1,295 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + #include + #include + #include + +/ { + model = "STMicroelectronics STEVAL-STWINBX1 Development kit"; + compatible = "st,steval_stwinbx1"; + + chosen { + zephyr,console = &cdc_acm_uart0; + zephyr,shell-uart = &cdc_acm_uart0; + + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,code-partition = &slot0_partition; + + zephyr,bt-hci = &hci_spi; + }; + + leds { + compatible = "gpio-leds"; + green_led: led_1 { + gpios = <&gpioh 12 GPIO_ACTIVE_HIGH>; + label = "LED_1"; + }; + orange_led: led_2 { + gpios = <&gpioh 10 GPIO_ACTIVE_HIGH>; + label = "LED_2"; + }; + }; + + pwmleds { + compatible = "pwm-leds"; + + green_pwm_led: green_pwm_led { + pwms = <&pwm5 3 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + label = "LED_1 - PWM5"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button { + label = "User"; + gpios = <&gpioe 0 GPIO_ACTIVE_HIGH>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &green_led; + led1 = &orange_led; + pwm-led0 = &green_pwm_led; + sw0 = &user_button; + mcuboot-led0 = &green_led; + mcuboot-button0 = &user_button; + watchdog0 = &iwdg; + die-temp0 = &die_temp; + volt-sensor0 = &vref1; + volt-sensor1 = &vbat4; + }; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_hse { + clock-frequency = ; + status = "okay"; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_msis { + status = "okay"; + msi-range = <4>; + msi-pll-mode; +}; + +&pll1 { + div-m = <1>; + mul-n = <10>; + div-q = <2>; + div-r = <1>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&pll2 { + div-m = <2>; + mul-n = <48>; + div-p = <2>; + div-q = <7>; + div-r = <25>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&pll3 { + div-m = <2>; + mul-n = <48>; + div-p = <2>; + div-q = <25>; + div-r = <2>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll1>; + clock-frequency = ; + ahb-prescaler = <1>; + apb1-prescaler = <1>; + apb2-prescaler = <1>; + apb3-prescaler = <1>; +}; + +&gpioe { + status = "okay"; + + /* Enable 2.7V Analog LDO */ + ldo-enable-gpios { + gpio-hog; + gpios = <15 GPIO_ACTIVE_HIGH>; + output-high; + }; +}; + +stm32_lp_tick_source: &lptim1 { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00000800>, + <&rcc STM32_SRC_LSE LPTIM1_SEL(3)>; + status = "okay"; +}; + +&usart2 { + pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&spi3 { + pinctrl-0 = <&spi3_sck_pg9 &spi3_miso_pb4 &spi3_mosi_pb5>; + pinctrl-names = "default"; + status = "okay"; + cs-gpios = <&gpioe 1 GPIO_ACTIVE_LOW>; + hci_spi: bluenrg-2@0 { + compatible = "st,hci-spi-v2"; + reg = <0>; + reset-gpios = <&gpiod 13 GPIO_ACTIVE_LOW>; + irq-gpios = <&gpiof 14 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; + spi-cpha; /* CPHA=1 */ + spi-hold-cs; + spi-max-frequency = ; + reset-assert-duration-ms = <6>; + }; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_scl_ph4 &i2c2_sda_pf0>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; + + stts22h@3f { + compatible = "st,stts22h"; + reg = <0x3f>; + int-gpios = <&gpiof 5 GPIO_ACTIVE_HIGH>; + status = "okay"; + }; +}; + +&timers5 { + st,prescaler = <10000>; + status = "okay"; + + pwm5: pwm { + status = "okay"; + pinctrl-0 = <&tim5_ch3_ph12>; + pinctrl-names = "default"; + }; +}; + + +&aes { + status = "okay"; +}; + +&rng { + status = "okay"; +}; + +zephyr_udc0: &usbotg_fs { + pinctrl-0 = <&usb_otg_fs_dm_pa11 &usb_otg_fs_dp_pa12>; + pinctrl-names = "default"; + status = "okay"; + + cdc_acm_uart0: cdc_acm_uart0 { + compatible = "zephyr,cdc-acm-uart"; + }; +}; + +&adc1 { + pinctrl-0 = <&adc1_in1_pc0>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + vref-mv = <2750>; + status = "okay"; +}; + +&adc4 { + pinctrl-0 = <&adc4_in3_pc2>; + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + vref-mv = <2750>; + status = "okay"; +}; + +&die_temp { + status = "okay"; +}; + +&iwdg { + status = "okay"; +}; + +&vref1 { + status = "okay"; +}; + +&vbat4 { + status = "okay"; +}; + +&sdmmc1 { + status = "okay"; + pinctrl-0 = <&sdmmc1_d0_pc8 &sdmmc1_d1_pc9 + &sdmmc1_d2_pc10 &sdmmc1_d3_pc11 + &sdmmc1_ck_pc12 &sdmmc1_cmd_pd2>; + pinctrl-names = "default"; + cd-gpios = <&gpiog 1 GPIO_ACTIVE_LOW>; + bus-width = <4>; + clk-div = <4>; +}; + +&flash0 { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* + * Following flash partition is dedicated to the use of steval_stwinbx1 + * with TZEN=0 (so w/o TFM). + * Set the partitions with first MB to make use of the whole Bank1 + */ + boot_partition: partition@0 { + label = "mcuboot"; + reg = <0x00000000 DT_SIZE_K(64)>; + }; + slot0_partition: partition@10000 { + label = "image-0"; + reg = <0x00010000 DT_SIZE_K(416)>; + }; + slot1_partition: partition@78000 { + label = "image-1"; + reg = <0x00078000 DT_SIZE_K(416)>; + }; + scratch_partition: partition@e0000 { + label = "image-scratch"; + reg = <0x000e0000 DT_SIZE_K(64)>; + }; + storage_partition: partition@f0000 { + label = "storage"; + reg = <0x000f0000 DT_SIZE_K(64)>; + }; + + }; +}; + +&gpdma1 { + status = "okay"; +}; diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1.yaml b/boards/st/steval_stwinbx1/steval_stwinbx1.yaml new file mode 100644 index 0000000000000..f08afe0d21d13 --- /dev/null +++ b/boards/st/steval_stwinbx1/steval_stwinbx1.yaml @@ -0,0 +1,16 @@ +identifier: steval_stwinbx1 +name: STEVAL STWINBX1 Development kit +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 786 +flash: 2048 +supported: + - counter + - gpio + - pwm + - watchdog + - ble +vendor: st diff --git a/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig b/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig new file mode 100644 index 0000000000000..a078754cd5d9e --- /dev/null +++ b/boards/st/steval_stwinbx1/steval_stwinbx1_defconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable hardware stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable GPIO +CONFIG_GPIO=y +CONFIG_GPIO_HOGS=y + +# Enable Clocks +CONFIG_CLOCK_CONTROL=y + +# Enable console +CONFIG_SERIAL=y +CONFIG_CONSOLE=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/steval_stwinbx1/support/openocd.cfg b/boards/st/steval_stwinbx1/support/openocd.cfg new file mode 100644 index 0000000000000..31f15356db715 --- /dev/null +++ b/boards/st/steval_stwinbx1/support/openocd.cfg @@ -0,0 +1,44 @@ +source [find interface/stlink-dap.cfg] + +set WORKAREASIZE 0x8000 + +transport select "dapdirect_swd" + +set CHIPNAME STM32U585AIIxQ +set BOARDNAME STEVAL-STWINBX1 + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# STlink Debug clock frequency +set CLOCK_FREQ 8000 + +# Reset configuration +# use hardware reset, connect under reset +# connect_assert_srst needed if low power mode application running (WFI...) +reset_config srst_only srst_nogate connect_assert_srst +set CONNECT_UNDER_RESET 1 +set CORE_RESET 0 + +# ACCESS PORT NUMBER +set AP_NUM 0 +# GDB PORT +set GDB_PORT 3333 + +# BCTM CPU variables + +source [find target/stm32u5x.cfg] + +$_TARGETNAME configure -event gdb-attach { + echo "Debugger attaching: halting execution" + reset halt + gdb_breakpoint_override hard +} + +$_TARGETNAME configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} diff --git a/boards/st/stm32c0116_dk/stm32c0116_dk.dts b/boards/st/stm32c0116_dk/stm32c0116_dk.dts index f9791268886a9..79b4db1fa2583 100644 --- a/boards/st/stm32c0116_dk/stm32c0116_dk.dts +++ b/boards/st/stm32c0116_dk/stm32c0116_dk.dts @@ -53,7 +53,7 @@ select_key { press-thresholds-mv = <0>; - zephyr,code = ; + zephyr,code = ; }; left_key { diff --git a/boards/st/stm32f072b_disco/stm32f072b_disco.dts b/boards/st/stm32f072b_disco/stm32f072b_disco.dts index 363e5a565c565..de73e11af6f99 100644 --- a/boards/st/stm32f072b_disco/stm32f072b_disco.dts +++ b/boards/st/stm32f072b_disco/stm32f072b_disco.dts @@ -118,7 +118,6 @@ &can1 { pinctrl-0 = <&can_rx_pb8 &can_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/stm32f103_mini/doc/index.rst b/boards/st/stm32f103_mini/doc/index.rst index 63d2199e4d03f..c6938020f99ef 100644 --- a/boards/st/stm32f103_mini/doc/index.rst +++ b/boards/st/stm32f103_mini/doc/index.rst @@ -75,8 +75,6 @@ The Zephyr stm32f103_mini board configuration supports the following hardware fe +-----------+------------+-------------------------------------+ | COUNTER | on-chip | rtc | +-----------+------------+-------------------------------------+ -| RTC | on-chip | rtc | -+-----------+------------+-------------------------------------+ Other hardware features are not yet supported in this Zephyr port. diff --git a/boards/st/stm32f3_disco/doc/index.rst b/boards/st/stm32f3_disco/doc/index.rst index 8862d754fbbd1..d4a629a489592 100644 --- a/boards/st/stm32f3_disco/doc/index.rst +++ b/boards/st/stm32f3_disco/doc/index.rst @@ -109,6 +109,8 @@ features: +-----------+------------+-------------------------------------+ | die-temp | on-chip | die temperature sensor | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on Zephyr porting. diff --git a/boards/st/stm32f3_disco/stm32f3_disco.dts b/boards/st/stm32f3_disco/stm32f3_disco.dts index f90c10cf71cc1..44a66f038be73 100644 --- a/boards/st/stm32f3_disco/stm32f3_disco.dts +++ b/boards/st/stm32f3_disco/stm32f3_disco.dts @@ -185,7 +185,6 @@ zephyr_udc0: &usb { pinctrl-0 = <&can_rx_pd0 &can_tx_pd1>; pinctrl-names = "default"; status = "okay"; - bus-speed = <125000>; }; &flash0 { diff --git a/boards/st/stm32f3_disco/stm32f3_disco_B.yaml b/boards/st/stm32f3_disco/stm32f3_disco_B.yaml index 1c87cb7fd36bf..ebdbe230d20dc 100644 --- a/boards/st/stm32f3_disco/stm32f3_disco_B.yaml +++ b/boards/st/stm32f3_disco/stm32f3_disco_B.yaml @@ -21,4 +21,5 @@ supported: - adc - dac - dma + - rtc vendor: st diff --git a/boards/st/stm32f3_disco/stm32f3_disco_stm32f303xc_E.yaml b/boards/st/stm32f3_disco/stm32f3_disco_stm32f303xc_E.yaml index 13e6b0bf1431f..bc17f1c2d684d 100644 --- a/boards/st/stm32f3_disco/stm32f3_disco_stm32f303xc_E.yaml +++ b/boards/st/stm32f3_disco/stm32f3_disco_stm32f303xc_E.yaml @@ -20,4 +20,5 @@ supported: - pwm - adc - dac + - rtc vendor: st diff --git a/boards/st/stm32f411e_disco/stm32f411e_disco_stm32f411xe_B.yaml b/boards/st/stm32f411e_disco/stm32f411e_disco_stm32f411xe_B.yaml index 05f3c979f7f0c..480b81537b678 100644 --- a/boards/st/stm32f411e_disco/stm32f411e_disco_stm32f411xe_B.yaml +++ b/boards/st/stm32f411e_disco/stm32f411e_disco_stm32f411xe_B.yaml @@ -1,5 +1,5 @@ identifier: stm32f411e_disco@B -name: ST STM32F411E Discovery +name: ST STM32F411E Discovery (rev. B) type: mcu arch: arm toolchain: diff --git a/boards/st/stm32f4_disco/stm32f4_disco.dts b/boards/st/stm32f4_disco/stm32f4_disco.dts index 2847c2fcfdb15..163612aaf0759 100644 --- a/boards/st/stm32f4_disco/stm32f4_disco.dts +++ b/boards/st/stm32f4_disco/stm32f4_disco.dts @@ -129,13 +129,11 @@ zephyr_udc0: &usbotg_fs { &can1 { pinctrl-0 = <&can1_rx_pb8 &can1_tx_pb9>; pinctrl-names = "default"; - bus-speed = <125000>; status = "disabled"; }; &can2 { pinctrl-0 = <&can2_rx_pb5 &can2_tx_pb13>; pinctrl-names = "default"; - bus-speed = <125000>; status = "okay"; }; diff --git a/boards/st/stm32f723e_disco/stm32f723e_disco.dts b/boards/st/stm32f723e_disco/stm32f723e_disco.dts index 4c6641c7f2c75..a9ca03675df18 100644 --- a/boards/st/stm32f723e_disco/stm32f723e_disco.dts +++ b/boards/st/stm32f723e_disco/stm32f723e_disco.dts @@ -52,7 +52,6 @@ led1 = &red_led; led2 = &green_led; sw0 = &user_button; - spi-flash0 = &mx25r512; }; }; diff --git a/boards/st/stm32f723e_disco/stm32f723e_disco.yaml b/boards/st/stm32f723e_disco/stm32f723e_disco.yaml index d8f5b1a14a7f4..1908ae26279a7 100644 --- a/boards/st/stm32f723e_disco/stm32f723e_disco.yaml +++ b/boards/st/stm32f723e_disco/stm32f723e_disco.yaml @@ -16,4 +16,5 @@ supported: - spi - arduino_spi - usb_device + - usbd vendor: st diff --git a/boards/st/stm32f746g_disco/stm32f746g_disco.dts b/boards/st/stm32f746g_disco/stm32f746g_disco.dts index 6250c4e8e80d8..2c31fef1c92c4 100644 --- a/boards/st/stm32f746g_disco/stm32f746g_disco.dts +++ b/boards/st/stm32f746g_disco/stm32f746g_disco.dts @@ -59,7 +59,6 @@ aliases { led0 = &green_led_1; sw0 = &user_button; - spi-flash0 = &n25q128a1; }; }; diff --git a/boards/st/stm32f746g_disco/stm32f746g_disco.yaml b/boards/st/stm32f746g_disco/stm32f746g_disco.yaml index f3ef45a79062e..5442db5bb6737 100644 --- a/boards/st/stm32f746g_disco/stm32f746g_disco.yaml +++ b/boards/st/stm32f746g_disco/stm32f746g_disco.yaml @@ -16,7 +16,6 @@ supported: - gpio - pwm - counter - - sdhc - usb_device - display - memc diff --git a/boards/st/stm32f7508_dk/stm32f7508_dk.dts b/boards/st/stm32f7508_dk/stm32f7508_dk.dts index b98cf5aeed9e4..100fd6e661d9b 100644 --- a/boards/st/stm32f7508_dk/stm32f7508_dk.dts +++ b/boards/st/stm32f7508_dk/stm32f7508_dk.dts @@ -59,7 +59,6 @@ aliases { led0 = &green_led_1; sw0 = &user_button; - spi-flash0 = &n25q128a1; }; }; diff --git a/boards/st/stm32f7508_dk/stm32f7508_dk.yaml b/boards/st/stm32f7508_dk/stm32f7508_dk.yaml index b474319510dda..9415c4660d1c7 100644 --- a/boards/st/stm32f7508_dk/stm32f7508_dk.yaml +++ b/boards/st/stm32f7508_dk/stm32f7508_dk.yaml @@ -19,7 +19,6 @@ supported: - gpio - pwm - counter - - sdhc - usb_device - display - memc diff --git a/boards/st/stm32f769i_disco/stm32f769i_disco.dts b/boards/st/stm32f769i_disco/stm32f769i_disco.dts index feb0f2f11a285..9ad4f4ef3bc57 100644 --- a/boards/st/stm32f769i_disco/stm32f769i_disco.dts +++ b/boards/st/stm32f769i_disco/stm32f769i_disco.dts @@ -32,6 +32,11 @@ zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; + otghs_ulpi_phy: otghs_ulpis_phy { + compatible = "usb-ulpi-phy"; + #phy-cells = <0>; + }; + leds { compatible = "gpio-leds"; red_led_1:led_1 { @@ -72,7 +77,13 @@ led2 = &green_led_3; led3 = &red_led_4; sw0 = &user_button; - spi-flash0 = &mx25l51245g; + }; + + quadspi_memory_avail: memory-avail@90000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x90000000 DT_SIZE_M(64)>; + zephyr,memory-region = "QSPI_AVAIL"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; }; }; @@ -175,7 +186,7 @@ arduino_serial: &usart6 {}; mx25l51245g: qspi-nor-flash@90000000 { compatible = "st,stm32-qspi-nor"; reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ - qspi-max-frequency = <72000000>; + qspi-max-frequency = ; status = "okay"; partitions { @@ -238,3 +249,22 @@ arduino_serial: &usart6 {}; }; }; }; + +zephyr_udc0: &usbotg_hs { + pinctrl-0 = <&usb_otg_hs_ulpi_ck_pa5 + &usb_otg_hs_ulpi_d0_pa3 + &usb_otg_hs_ulpi_d1_pb0 + &usb_otg_hs_ulpi_d2_pb1 + &usb_otg_hs_ulpi_d3_pb10 + &usb_otg_hs_ulpi_d4_pb11 + &usb_otg_hs_ulpi_d5_pb12 + &usb_otg_hs_ulpi_d6_pb13 + &usb_otg_hs_ulpi_d7_pb5 + &usb_otg_hs_ulpi_stp_pc0 + &usb_otg_hs_ulpi_dir_pi11 + &usb_otg_hs_ulpi_nxt_ph4>; + pinctrl-names = "default"; + maximum-speed = "high-speed"; + phys = <&otghs_ulpi_phy>; + status = "okay"; +}; diff --git a/boards/st/stm32f769i_disco/support/openocd.cfg b/boards/st/stm32f769i_disco/support/openocd.cfg index 1c964a0e64384..8896666bc6d22 100644 --- a/boards/st/stm32f769i_disco/support/openocd.cfg +++ b/boards/st/stm32f769i_disco/support/openocd.cfg @@ -2,7 +2,7 @@ source [find board/stm32f769i-disco.cfg] $_TARGETNAME configure -event gdb-attach { echo "Debugger attaching: halting execution" - reset halt + reset init gdb_breakpoint_override hard } diff --git a/boards/st/stm32h573i_dk/doc/index.rst b/boards/st/stm32h573i_dk/doc/index.rst index bdc29c5dc751f..72fba315ace50 100644 --- a/boards/st/stm32h573i_dk/doc/index.rst +++ b/boards/st/stm32h573i_dk/doc/index.rst @@ -197,6 +197,8 @@ hardware features: +-----------+------------+-------------------------------------+ | USB | on-chip | USB full-speed host/device bus | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. diff --git a/boards/st/stm32h573i_dk/stm32h573i_dk.dts b/boards/st/stm32h573i_dk/stm32h573i_dk.dts index e27445c2ac3bf..a02d042e25d4c 100644 --- a/boards/st/stm32h573i_dk/stm32h573i_dk.dts +++ b/boards/st/stm32h573i_dk/stm32h573i_dk.dts @@ -56,7 +56,6 @@ led0 = &blue_led_0; sw0 = &user_button; watchdog0 = &iwdg; - spi-flash0 = &mx25lm51245; die-temp0 = &die_temp; volt-sensor0 = &vref; volt-sensor1 = &vbat; @@ -247,12 +246,10 @@ <&rcc STM32_SRC_PLL1_Q FDCAN_SEL(1)>; pinctrl-0 = <&fdcan1_rx_pa11 &fdcan1_tx_pa12>; pinctrl-names = "default"; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; -&octospi1 { +&xspi1 { pinctrl-0 = <&octospi1_io0_pb1 &octospi1_io1_pd12 &octospi1_io2_pc2 &octospi1_io3_pd13 &octospi1_io4_ph2 &octospi1_io5_ph3 @@ -264,11 +261,11 @@ status = "okay"; mx25lm51245: ospi-nor-flash@90000000 { - compatible = "st,stm32-ospi-nor"; + compatible = "st,stm32-xspi-nor"; reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ ospi-max-frequency = ; - spi-bus-width = ; - data-rate = ; + spi-bus-width = ; + data-rate = ; four-byte-opcodes; status = "okay"; diff --git a/boards/st/stm32h573i_dk/stm32h573i_dk.yaml b/boards/st/stm32h573i_dk/stm32h573i_dk.yaml index ac963c5756f43..f6d5f12b17330 100644 --- a/boards/st/stm32h573i_dk/stm32h573i_dk.yaml +++ b/boards/st/stm32h573i_dk/stm32h573i_dk.yaml @@ -24,5 +24,5 @@ supported: - usb_device - usb - i2c - - sdhc + - rtc vendor: st diff --git a/boards/st/stm32h735g_disco/stm32h735g_disco.dts b/boards/st/stm32h735g_disco/stm32h735g_disco.dts index 4843e98a709d2..41e67e551c2c2 100644 --- a/boards/st/stm32h735g_disco/stm32h735g_disco.dts +++ b/boards/st/stm32h735g_disco/stm32h735g_disco.dts @@ -216,8 +216,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <8000000>; @@ -230,8 +228,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; status = "okay"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <8000000>; @@ -245,8 +241,6 @@ <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; /* Solder bridges SB29 and SB30 need to be closed for this to work */ status = "disabled"; - bus-speed = <125000>; - bus-speed-data = <1000000>; can-transceiver { max-bitrate = <8000000>; diff --git a/boards/st/stm32h745i_disco/Kconfig.defconfig b/boards/st/stm32h745i_disco/Kconfig.defconfig new file mode 100644 index 0000000000000..b6242139bfdfe --- /dev/null +++ b/boards/st/stm32h745i_disco/Kconfig.defconfig @@ -0,0 +1,23 @@ +# STM32H745XI DISCOVERY board configuration + +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_STM32H745I_DISCO + +if NETWORKING + +config NET_L2_ETHERNET + default y + +config ETH_STM32_HAL_MII + default y + +endif # NETWORKING + +config MEMC + default y if DISPLAY + + +endif # BOARD_STM32H745I_DISCO diff --git a/boards/st/stm32h745i_disco/Kconfig.stm32h745i_disco b/boards/st/stm32h745i_disco/Kconfig.stm32h745i_disco new file mode 100644 index 0000000000000..7dacd75eb4bae --- /dev/null +++ b/boards/st/stm32h745i_disco/Kconfig.stm32h745i_disco @@ -0,0 +1,9 @@ +# STM32H745XI DISCOVERY board configuration + +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_STM32H745I_DISCO + select SOC_STM32H745XX_M7 if BOARD_STM32H745I_DISCO_STM32H745XX_M7 + select SOC_STM32H745XX_M4 if BOARD_STM32H745I_DISCO_STM32H745XX_M4 diff --git a/boards/st/stm32h745i_disco/arduino_r3_connector.dtsi b/boards/st/stm32h745i_disco/arduino_r3_connector.dtsi new file mode 100644 index 0000000000000..1d24b1ecb74cb --- /dev/null +++ b/boards/st/stm32h745i_disco/arduino_r3_connector.dtsi @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020 Alexander Kozhinov + * Copyright (c) 2024 Tomas Jurena + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpioc 0 0>, /* A0 */ + <1 0 &gpiof 8 0>, /* A1 */ + <2 0 &gpioa 0 0>, /* A2 */ + <3 0 &gpioa 1 0>, /* A3 */ + <4 0 &gpioc 2 0>, /* A4 */ + <5 0 &gpioc 3 0>, /* A5 */ + <6 0 &gpiob 7 0>, /* D0 */ + <7 0 &gpiob 6 0>, /* D1 */ + <8 0 &gpiog 3 0>, /* D2 */ + <9 0 &gpioa 6 0>, /* D3 */ + <10 0 &gpiok 1 0>, /* D4 */ + <11 0 &gpioa 8 0>, /* D5 */ + <12 0 &gpioe 6 0>, /* D6 */ + <13 0 &gpioi 6 0>, /* D7 */ + <14 0 &gpioe 3 0>, /* D8 */ + <15 0 &gpioh 15 0>, /* D9 */ + <16 0 &gpiob 4 0>, /* D10 */ + <17 0 &gpiob 15 0>, /* D11 */ + <18 0 &gpioi 2 0>, /* D12 */ + <19 0 &gpiod 3 0>, /* D13 */ + <20 0 &gpiod 13 0>, /* D14 */ + <21 0 &gpiod 12 0>; /* D15 */ + }; +}; + + +arduino_i2c: &i2c4 {}; +arduino_spi: &spi2 {}; +arduino_serial: &usart1 {}; diff --git a/boards/st/stm32h745i_disco/board.cmake b/boards/st/stm32h745i_disco/board.cmake new file mode 100644 index 0000000000000..d52fff882b734 --- /dev/null +++ b/boards/st/stm32h745i_disco/board.cmake @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena + +board_runner_args(jlink "--device=STM32H745XI" "--speed=4000") +if(CONFIG_BOARD_STM32H745I_DISCO_STM32H745XX_M7) +board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) +elseif(CONFIG_BOARD_STM32H745I_DISCO_STM32H745XX_M4) +board_runner_args(openocd --target-handle=_CHIPNAME.cpu1) +endif() + +if(CONFIG_STM32_MEMMAP) +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +board_runner_args(stm32cubeprogrammer "--extload=MT25TL01G_STM32H745I-DISCO.stldr") +else() +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +endif() + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/st/stm32h745i_disco/board.yml b/boards/st/stm32h745i_disco/board.yml new file mode 100644 index 0000000000000..e1da9c4b2f44e --- /dev/null +++ b/boards/st/stm32h745i_disco/board.yml @@ -0,0 +1,5 @@ +board: + name: stm32h745i_disco + vendor: st + socs: + - name: stm32h745xx diff --git a/boards/st/stm32h745i_disco/doc/img/stm32h745i-disco.jpg b/boards/st/stm32h745i_disco/doc/img/stm32h745i-disco.jpg new file mode 100644 index 0000000000000..c2e5d12d5c511 Binary files /dev/null and b/boards/st/stm32h745i_disco/doc/img/stm32h745i-disco.jpg differ diff --git a/boards/st/stm32h745i_disco/doc/index.rst b/boards/st/stm32h745i_disco/doc/index.rst new file mode 100644 index 0000000000000..4a17b24f16f2a --- /dev/null +++ b/boards/st/stm32h745i_disco/doc/index.rst @@ -0,0 +1,272 @@ +.. _stm32h745i_disco_board: + +ST STM32H745I Discovery +####################### + +Overview +******** + +The STM32H745I-DISCO Discovery kit is a complete demonstration and development +platform for STMicroelectronics Arm |reg| Cortex |reg|‑M7 and Cortex |reg|‑M4 core-based STM32H745XI microcontroller. + +The full range of hardware features available on the board helps users enhance their application +development by an evaluation of almost all peripherals (such as USB OTG FS, Ethernet 10/100Mb/s, +eMMC, USART, SAI audio DAC stereo with audio jack input and output, MEMS digital microphone, SDRAM, +Quad-SPI flash memory, and RGB interface LCD with capacitive multi-touch panel). ARDUINO |reg| Uno V3 +connectors provide easy connection to extension shields or daughterboards for specific applications. + +STLINK-V3E is integrated into the board, as an embedded in-circuit debugger and programmer for the +STM32 MCU and the USB Virtual COM port bridge + +Key Features + +- Arm |reg| Cortex |reg| core-based microcontroller with 2 Mbytes of flash memory and 1 Mbyte of RAM, in a TFBGA240+25 package +- 4.3” RGB interface LCD with touch panel connector +- Ethernet compliant with IEEE-802.3-2002, and PoE +- USB OTG FS +- SAI audio codec +- One ST-MEMS digital microphone +- 2× 512-Mbit Quad-SPI NOR flash memory +- 128-Mbit SDRAM +- 4-Gbyte on-board eMMC +- 1 user and reset push-button +- Fanout daughterboard +- 2× CAN FDs +- Board connectors: + + - USB FS Micro-AB connectors + - ST-LINK Micro-B USB connector + - USB power Micro-B connector + - Ethernet RJ45 + - Stereo headset jack including analog microphone input + - Audio header for external speakers + - Tag‑Connect |trade| (TAG) 10-pin footprint + - Arm |reg| Cortex |reg| 10-pin 1.27 mm pitch debug connector over STDC14 footprint + - ARDUINO |reg| Uno V3 expansion connectors + - STMod+ + +- Flexible power-supply options: + + - STLINK-V3E USB connector, USB FS connector + - 5 V delivered by RJ45 (Power over Ethernet) + - 5 V delivered by ARDUINO |reg| or external connector + - USB charger + - USB power + +.. image:: img/stm32h745i-disco.jpg + :align: center + :alt: STM32H745I-DISCO + +More information about the board can be found at the `STM32H745I-DISCO website`_. +More information about STM32H747XIH6 can be found here: + +- `STM32H745XI on www.st.com`_ +- `STM32H745xx reference manual`_ +- `STM32H745xx datasheet`_ + +Supported Features +================== + +The current Zephyr stm32h745i_disco board configuration supports the following hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| RTC | on-chip | counter | ++-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ +| PWM | on-chip | pwm | ++-----------+------------+-------------------------------------+ +| ETHERNET | on-chip | ethernet | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi | ++-----------+------------+-------------------------------------+ +| QSPI NOR | on-chip | off-chip flash | ++-----------+------------+-------------------------------------+ +| FDCAN | on-chip | fdcan | ++-----------+------------+-------------------------------------+ +| FMC | on-chip | memc (SDRAM) | ++-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration per core can be found in the defconfig files: +:zephyr_file:`boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7_defconfig` and +:zephyr_file:`boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4_defconfig` + +For more details please refer to `STM32H745-Disco UM`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- USART_3 TX/RX : PB10/PB11 (ST-Link Virtual Port Com) +- USART_1 TX/RX : PB6/PB7 (Arduino Serial) +- SPI_2 NSS/SCK/MISO/MOSI : PB4/PD3/PI2/PB15 (Arduino SPI) +- I2C_4 SCL/SDA: PD12, PD13 (Arduino I2C) +- USER_PB : PC13 +- LD1 : PI13 +- LD2 : PJ2 +- LD3 : PD3 + +System Clock +------------ + +STM32H745I-DISCO System Clock could be driven by an internal or external +oscillator, as well as the main PLL clock. By default, the System clock is +driven by the PLL clock at 480MHz, driven by an 25MHz high-speed external clock. + +Serial Port +----------- + +STM32H745I-DISCO board has 4 UARTs and 4 USARTs. The Zephyr console output is +assigned to UART3. Default settings are 115200 8N1. + +Resources sharing +----------------- + +The dual core nature of STM32H745 SoC requires sharing HW resources between the +two cores. This is done in 3 ways: + +- **Compilation**: Clock configuration is only accessible to M7 core. M4 core only + has access to bus clock activation and deactivation. +- **Static pre-compilation assignment**: Peripherals such as a UART are assigned in + devicetree before compilation. The user must ensure peripherals are not assigned + to both cores at the same time. +- **Run time protection**: Interrupt-controller and GPIO configurations could be + accessed by both cores at run time. Accesses are protected by a hardware semaphore + to avoid potential concurrent access issues. + +Programming and Debugging +************************* + +Applications for the ``stm32h745i_disco`` board should be built per core target, +using either ``stm32h745i_disco/stm32h745xx/m7`` or ``stm32h745i_disco/stm32h745xx/m4`` as the target +(see :ref:`build_an_application` and :ref:`application_run` for more details). + +.. note:: + + Check if the on-board ST-LINK V3 has the latest firmware version. It can be done with either `STM32CubeIDE`_ or `STM32CubeProgrammer`_ + +Flashing +======== + +STM32H745I-DISCO board includes an ST-LINK/V3 embedded debug tool interface. + +Flashing operation will depend on the target and the SoC +option bytes configuration. + +By default: + + - CPU0 (Cortex-M7) boot address is set to 0x80000000 (OB: BOOT_CM7_ADD0) + - CPU1 (Cortex-M4) boot address is set to 0x81000000 (OB: BOOT_CM4_ADD0) + +Also, the out of the box default board configuration enables CM7 and CM4 boot when +board is powered (Option bytes BCM7 and BCM4 are checked). +In that configuration, Kconfig boot option ``STM32H7_BOOT_CM4_CM7`` should be selected. +Zephyr flash configuration has been set to meet these default settings. + +Alternatively, west `STM32CubeProgrammer`_ runner can be used, after installing +it, to flash applications for both cores. The target core is detected automatically. + +.. code-block:: console + + $ west flash --runner stm32cubeprogrammer + +Flashing an application to STM32H745XI M7 Core +---------------------------------------------- +First, connect the STM32H745I-DISCO to your host computer using +the USB port to prepare it for flashing. Then build and flash your application. + +Here is an example for the :ref:`hello_world` application. + +Run a serial host program to connect with your STM32H745I-DISCO board. + +.. code-block:: console + + $ minicom -b 115200 -D /dev/ttyACM0 + +or use screen: + +.. code-block:: console + + $ screen /dev/ttyACM0 115200 + +Build and flash the application: + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: stm32h745i_disco/stm32h745xx/m7 + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + $ Hello World! stm32h745i_disco + +.. note:: + Sometimes, flashing does not work properly. It is necessary to erase the flash + (with STM32CubeProgrammer for example) to make it work again. + +Similarly, you can build and flash samples on the M4 target. For this, please +take care of the resource sharing (UART port used for console for instance). + +Here is an example for the :zephyr:code-sample:`blinky` application on M4 core. + +.. zephyr-app-commands:: + :zephyr-app: samples/basic/blinky + :board: stm32h745i_disco/stm32h745xx/m7 + :goals: build flash + +.. note:: + + Flashing both M4 and M7 and pushing RESTART button on the board leads + to LD1 and LD2 flashing simultaneously. + +Debugging +========= + +You can debug an application in the usual way. Here is an example for the +:ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: stm32h745i_disco/stm32h745xx/m7 + :maybe-skip-config: + :goals: debug + +Debugging with west is currently not available on Cortex M4 side. +In order to debug a Zephyr application on Cortex M4 side, you can use +`STM32CubeIDE`_. + +.. _STM32H745I-DISCO website: + https://www.st.com/en/evaluation-tools/stm32h745i-disco.html + +.. _STM32H745XI on www.st.com: + https://www.st.com/en/microcontrollers-microprocessors/stm32h745xi.html + +.. _STM32H745xx reference manual: + https://www.st.com/resource/en/reference_manual/rm0399-stm32h745755-and-stm32h747757-advanced-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32H745xx datasheet: + https://www.st.com/resource/en/datasheet/stm32h745xi.pdf + +.. _STM32H745-Disco UM: + https://www.st.com/resource/en/user_manual/um2488-discovery-kits-with-stm32h745xi-and-stm32h750xb-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html + +.. _STM32CubeIDE: + https://www.st.com/en/development-tools/stm32cubeide.html diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco.dtsi b/boards/st/stm32h745i_disco/stm32h745i_disco.dtsi new file mode 100644 index 0000000000000..c196018316c28 --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco.dtsi @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2020 Alexander Kozhinov + * Copyright (c) 2024 Tomas Jurena + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "arduino_r3_connector.dtsi" +#include + +/ { + leds: leds { + compatible = "gpio-leds"; + green_led: led_1 { + gpios = <&gpioj 2 GPIO_ACTIVE_HIGH>; + label = "User LD7"; + }; + red_led: led_2 { + gpios = <&gpioi 13 GPIO_ACTIVE_HIGH>; + label = "User LD6"; + }; + green_led_2: led_3 { + gpios = <&gpiod 3 GPIO_ACTIVE_HIGH>; + label = "User LD8"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button_0 { + gpios = <&gpioc 13 GPIO_ACTIVE_HIGH>; + label = "User SB1"; + zephyr,code = ; + }; + }; +}; + +&rcc { + d1cpre = <1>; + hpre = <2>; + d1ppre = <2>; + d2ppre1 = <2>; + d2ppre2 = <2>; + d3ppre = <2>; +}; + +&mailbox { + status = "okay"; +}; diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.dts b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.dts new file mode 100644 index 0000000000000..fe16637e5efc6 --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.dts @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 Alexander Kozhinov + * Copyright (c) 2024 Tomas Jurena + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "stm32h745i_disco.dtsi" + +/ { + model = "STMicroelectronics STM32H745I-DISCO board"; + compatible = "st,stm32h745i-disco"; + + /* HW resources belonging to CM4 */ + chosen { + zephyr,console = &usart2; + zephyr,shell-uart = &usart2; + zephyr,sram = &sram1; + zephyr,flash = &flash1; + }; + + aliases { + led0 = &green_led; + }; +}; + +&usart2 { + pinctrl-0 = <&usart2_tx_pd5 &usart2_rx_pd6>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&rcc { + clock-frequency = ; +}; diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.yaml b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.yaml new file mode 100644 index 0000000000000..c54a159929890 --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4.yaml @@ -0,0 +1,17 @@ +identifier: stm32h745i_disco/stm32h745xx/m4 +name: STM32H745XI Discovery (M4) +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 288 +flash: 1024 +supported: + - arduino_gpio + - gpio +testing: + ignore_tags: + - mpu + - nfc +vendor: st diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4_defconfig b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4_defconfig new file mode 100644 index 0000000000000..03e689742d93b --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m4_defconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena + +# Enable GPIO +CONFIG_GPIO=y + +# Enable clock +CONFIG_CLOCK_CONTROL=y + +# By default SERIAL peripherals are assigned to m7 + +# Enable uart driver +#CONFIG_SERIAL=y + +# Console +#CONFIG_CONSOLE=y +#CONFIG_UART_CONSOLE=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts new file mode 100644 index 0000000000000..09b8177b7c449 --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.dts @@ -0,0 +1,282 @@ +/* + * Copyright (c) 2020 Alexander Kozhinov + * Copyright (c) 2024 Tomas Jurena + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include "stm32h745i_disco.dtsi" + +/ { + model = "STMicroelectronics STM32H745I-DISCO board"; + compatible = "st,stm32h745i-disco"; + + /* HW resources belonging to CM7 */ + chosen { + zephyr,console = &usart3; + zephyr,shell-uart = &usart3; + zephyr,dtcm = &dtcm; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,flash-controller = &mt25ql512ab1; + zephyr,canbus = &fdcan1; + }; + + pwmleds { + compatible = "pwm-leds"; + + green_pwm_led: green_pwm_led { + pwms = <&pwm11 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + label = "User LD8 - PWM11"; + }; + }; + + /* RM0455 - 23.6 External device address mapping */ + sdram2: sdram@d0000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + device_type = "memory"; + reg = <0xd0000000 DT_SIZE_M(16)>; /* 128Mbit */ + zephyr,memory-region = "SDRAM2"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; + }; + + ext_memory: memory@90000000 { + compatible = "zephyr,memory-region"; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ + zephyr,memory-region = "EXTMEM"; + /* The ATTR_MPU_EXTMEM attribut causing a MPU FAULT */ + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; + + aliases { + led0 = &green_led; + pwm-led0 = &green_pwm_led; + sw0 = &user_button; + spi-flash0 = &mt25ql512ab1; + }; +}; + +&clk_lsi { + status = "okay"; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_hse { + clock-frequency = ; /* X1: 25MHz */ + status = "okay"; +}; + +&pll { + div-m = <5>; + mul-n = <192>; + div-p = <2>; + div-q = <15>; + div-r = <4>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&pll2 { + div-m = <5>; + mul-n = <192>; + div-p = <2>; + div-q = <12>; + div-r = <4>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; +}; + +&usart1 { + pinctrl-0 = <&usart1_tx_pb6 &usart1_rx_pb7>; + pinctrl-names = "default"; + current-speed = <57600>; + status = "okay"; +}; + +&usart3 { + pinctrl-0 = <&usart3_tx_pb10 &usart3_rx_pb11>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00010000>, + <&rcc STM32_SRC_LSI RTC_SEL(2)>; + status = "okay"; +}; + +&timers1 { + st,prescaler = <10000>; + status = "okay"; + + pwm11: pwm { + status = "okay"; + pinctrl-0 = <&tim1_ch1_pa8>; + pinctrl-names = "default"; + }; +}; + +&mac { + status = "okay"; + /* MII */ + pinctrl-0 = <ð_ref_clk_pa1 + ð_crs_dv_pa7 + ð_rxd2_pb0 + ð_rxd3_pb1 + ð_txd2_pc2 + ð_tx_clk_pc3 + ð_rxd0_pc4 + ð_rxd1_pc5 + ð_txd3_pe2 + ð_tx_en_pg11 + ð_txd1_pg12 + ð_txd0_pg13 + ð_rx_er_pi10>; + pinctrl-names = "default"; +}; + +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; + +&rng { + status = "okay"; +}; + +&quadspi { + pinctrl-names = "default"; + pinctrl-0 = < + &quadspi_bk1_io0_pd11 + &quadspi_bk1_io3_pf6 + &quadspi_bk1_io2_pf7 + &quadspi_bk1_io1_pf9 + &quadspi_clk_pf10 + &quadspi_bk1_ncs_pg6 + &quadspi_bk2_io2_pg9 + &quadspi_bk2_io3_pg14 + &quadspi_bk2_io0_ph2 + &quadspi_bk2_io1_ph3 + >; + dual-flash; + status = "okay"; + + mt25ql512ab1: qspi-nor-flash-1@90000000 { + compatible = "st,stm32-qspi-nor"; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ + qspi-max-frequency = <72000000>; + spi-bus-width = <4>; + status = "okay"; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + storage_partition: partition@0 { + reg = <0x0 DT_SIZE_M(64)>; + }; + }; + }; + + mt25ql512ab2: qspi-nor-flash-2@90000000 { + compatible = "st,stm32-qspi-nor"; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ + qspi-max-frequency = <72000000>; + status = "okay"; + }; +}; + +&i2c4 { + status = "okay"; + pinctrl-0 = <&i2c4_scl_pd12 &i2c4_sda_pd13>; + pinctrl-names = "default"; +}; + +&spi2 { + status = "okay"; + pinctrl-0 = <&spi2_nss_pb4 &spi2_mosi_pb15 &spi2_miso_pi2 &spi2_sck_pd3>; + pinctrl-names = "default"; +}; + +&fdcan1 { + status = "okay"; + pinctrl-0 = <&fdcan1_tx_ph13 &fdcan1_rx_ph14>; + pinctrl-names = "default"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, + <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; + sample-point = <875>; + sample-point-data = <875>; + + can-transceiver { + max-bitrate = <5000000>; + }; +}; + +&fdcan2 { + status = "okay"; + pinctrl-0 = <&fdcan2_tx_pb13 &fdcan2_rx_pb5>; + pinctrl-names = "default"; + clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, + <&rcc STM32_SRC_PLL2_Q FDCAN_SEL(2)>; + sample-point = <875>; + sample-point-data = <875>; + + can-transceiver { + max-bitrate = <5000000>; + }; +}; + +&fmc { + pinctrl-0 = <&fmc_nbl0_pe0 &fmc_nbl1_pe1 + &fmc_sdclk_pg8 &fmc_sdnwe_ph5 &fmc_sdcke1_ph7 + &fmc_sdne1_ph6 &fmc_sdnras_pf11 &fmc_sdncas_pg15 + &fmc_a0_pf0 &fmc_a1_pf1 &fmc_a2_pf2 &fmc_a3_pf3 &fmc_a4_pf4 + &fmc_a5_pf5 &fmc_a6_pf12 &fmc_a7_pf13 &fmc_a8_pf14 + &fmc_a9_pf15 &fmc_a10_pg0 &fmc_a11_pg1 + &fmc_a14_pg4 &fmc_a15_pg5 &fmc_d0_pd14 &fmc_d1_pd15 + &fmc_d2_pd0 &fmc_d3_pd1 &fmc_d4_pe7 &fmc_d5_pe8 &fmc_d6_pe9 + &fmc_d7_pe10 &fmc_d8_pe11 &fmc_d9_pe12 &fmc_d10_pe13 + &fmc_d11_pe14 &fmc_d12_pe15 &fmc_d13_pd8 &fmc_d14_pd9 + &fmc_d15_pd10>; + pinctrl-names = "default"; + status = "okay"; + + sdram { + status = "okay"; + power-up-delay = <100>; + num-auto-refresh = <8>; + mode-register = <0x220>; + refresh-rate = <0x603>; + bank@1 { + reg = <1>; + st,sdram-control = ; + st,sdram-timing = <2 7 4 7 2 2 2>; + }; + }; +}; diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml new file mode 100644 index 0000000000000..ba7f0e8d9400a --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7.yaml @@ -0,0 +1,24 @@ +identifier: stm32h745i_disco/stm32h745xx/m7 +name: STM32H745XI Discovery (M7) +type: mcu +arch: arm +toolchain: + - zephyr + - gnuarmemb +ram: 512 +flash: 1024 +supported: + - arduino_gpio + - arduino_i2c + - uart + - gpio + - counter + - i2c + - pwm + - netif:eth + - qspi + - memc + - spi + - rtc + - can +vendor: st diff --git a/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7_defconfig b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7_defconfig new file mode 100644 index 0000000000000..f3ba3ad3b2a93 --- /dev/null +++ b/boards/st/stm32h745i_disco/stm32h745i_disco_stm32h745xx_m7_defconfig @@ -0,0 +1,28 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena + +# Enable the internal SMPS regulator +CONFIG_POWER_SUPPLY_DIRECT_SMPS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# Enable UART ( disable to assign to M4 core) +CONFIG_SERIAL=y + +# Console ( disable to assign to M4 core) +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# Enable GPIO +CONFIG_GPIO=y + +# Enable Clock +CONFIG_CLOCK_CONTROL=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/stm32h745i_disco/support/openocd.cfg b/boards/st/stm32h745i_disco/support/openocd.cfg new file mode 100644 index 0000000000000..cd2f2e5753b93 --- /dev/null +++ b/boards/st/stm32h745i_disco/support/openocd.cfg @@ -0,0 +1,30 @@ +# STM32H745XI DISCOVERY board OpenOCD ST-LINK V3 configuration +# +# Copyright (c) 2020 Alexander Kozhinov +# Copyright (c) 2024 Tomas Jurena +# SPDX-License-Identifier: Apache-2.0 +# + +source [find board/stm32h745i-disco.cfg] + +# Use connect_assert_srst here to be able to program +# even when core is in sleep mode +reset_config srst_only srst_nogate connect_assert_srst + +$_CHIPNAME.cpu0 configure -event gdb-attach { + echo "Debugger attaching: halting execution" + gdb_breakpoint_override hard +} + +$_CHIPNAME.cpu0 configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} + +# Due to the use of connect_assert_srst, running gdb requires +# to reset halt just after openocd init. +rename init old_init +proc init {} { + old_init + reset halt +} diff --git a/boards/st/stm32h747i_disco/board.cmake b/boards/st/stm32h747i_disco/board.cmake index 93b40d3634d37..cffd0a071e9ba 100644 --- a/boards/st/stm32h747i_disco/board.cmake +++ b/boards/st/stm32h747i_disco/board.cmake @@ -10,8 +10,14 @@ elseif(CONFIG_BOARD_STM32H747I_DISCO_STM32H747XX_M4) board_runner_args(openocd "--config=${BOARD_DIR}/support/openocd_stm32h747i_disco_m4.cfg") board_runner_args(openocd --target-handle=_CHIPNAME.cpu1) endif() + +if(CONFIG_STM32_MEMMAP) +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +board_runner_args(stm32cubeprogrammer "--extload=MT25TL01G_STM32H747I-DISCO.stldr") +else() board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +endif() -include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts index 8f27eb0f8365d..f1de8789781d6 100644 --- a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts +++ b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.dts @@ -31,6 +31,14 @@ zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; + ext_memory: memory@90000000 { + compatible = "zephyr,memory-region"; + reg = <0x90000000 DT_SIZE_M(64)>; /* 512 Mbits */ + zephyr,memory-region = "EXTMEM"; + /* The ATTR_MPU_EXTMEM attribut causing a MPU FAULT */ + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; + leds { green_led_1:led_1 { status = "okay"; @@ -55,7 +63,6 @@ led0 = &green_led_1; led1 = &orange_led_2; sw0 = &wake_up; - spi-flash0 = &mt25ql512ab1; }; }; @@ -130,9 +137,7 @@ */ status = "okay"; pinctrl-0 = <ð_ref_clk_pa1 - ð_mdio_pa2 ð_crs_dv_pa7 - ð_mdc_pc1 ð_rxd0_pc4 ð_rxd1_pc5 ð_tx_en_pg11 @@ -141,6 +146,18 @@ pinctrl-names = "default"; }; +&mdio { + status = "okay"; + pinctrl-0 = <ð_mdio_pa2 ð_mdc_pc1>; + pinctrl-names = "default"; + + ethernet-phy@0 { + compatible = "ethernet-phy"; + reg = <0x00>; + status = "okay"; + }; +}; + &rng { status = "okay"; }; @@ -230,6 +247,7 @@ zephyr_udc0: &usbotg_hs { &quadspi_bk2_io0_ph2 &quadspi_bk2_io1_ph3 &quadspi_bk2_io2_pg9 &quadspi_bk2_io3_pg14>; pinctrl-names = "default"; + dual-flash; status = "okay"; mt25ql512ab1: qspi-nor-flash-1@90000000 { diff --git a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.yaml b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.yaml index e4b7d1b33345a..d566de9a4cad7 100644 --- a/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.yaml +++ b/boards/st/stm32h747i_disco/stm32h747i_disco_stm32h747xx_m7.yaml @@ -16,6 +16,5 @@ supported: - netif:eth - qspi - memc - - usb_cdc - usb_device vendor: st diff --git a/boards/st/stm32h750b_dk/board.cmake b/boards/st/stm32h750b_dk/board.cmake index 6500e7b1a4a91..c38a92dfacc7d 100644 --- a/boards/st/stm32h750b_dk/board.cmake +++ b/boards/st/stm32h750b_dk/board.cmake @@ -3,5 +3,13 @@ board_runner_args(jlink "--device=STM32H735IG" "--speed=4000") board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) +if(CONFIG_STM32_MEMMAP) +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +board_runner_args(stm32cubeprogrammer "--extload=MT25TL01G_STM32H750B-DISCO.stldr") +else() +board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw" ) +endif() + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/st/stm32h750b_dk/doc/index.rst b/boards/st/stm32h750b_dk/doc/index.rst index f295947a33445..e450488ed4d39 100644 --- a/boards/st/stm32h750b_dk/doc/index.rst +++ b/boards/st/stm32h750b_dk/doc/index.rst @@ -55,6 +55,10 @@ The current Zephyr stm32h750b_dk board configuration supports the following hard +-----------+------------+-------------------------------------+ | GPIO | on-chip | gpio | +-----------+------------+-------------------------------------+ +| QSPI NOR | on-chip | off-chip flash | ++-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on Zephyr porting. diff --git a/boards/st/stm32h750b_dk/stm32h750b_dk.dts b/boards/st/stm32h750b_dk/stm32h750b_dk.dts index 7cd328e90dbde..ad0ecf065f3a4 100644 --- a/boards/st/stm32h750b_dk/stm32h750b_dk.dts +++ b/boards/st/stm32h750b_dk/stm32h750b_dk.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -29,6 +29,14 @@ zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; }; + ext_memory: memory@90000000 { + compatible = "zephyr,memory-region"; + reg = <0x90000000 DT_SIZE_M(256)>; /* max addressable area */ + zephyr,memory-region = "EXTMEM"; + /* The ATTR_MPU_EXTMEM attribut causing a MPU FAULT */ + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; + leds { compatible = "gpio-leds"; red_led: led_1 { @@ -54,7 +62,6 @@ led0 = &green_led; led1 = &red_led; sw0 = &user_button; - spi-flash0 = &mt25ql512ab1; }; }; @@ -64,6 +71,10 @@ status = "okay"; }; +&clk_lse { + status = "okay"; +}; + &pll { div-m = <5>; mul-n = <192>; @@ -99,7 +110,7 @@ &quadspi_bk1_io2_pf7 &quadspi_bk1_io3_pf6 &quadspi_bk2_io0_ph2 &quadspi_bk2_io1_ph3 &quadspi_bk2_io2_pg9 &quadspi_bk2_io3_pg14>; - flash-id = <1>; + dual-flash; status = "okay"; mt25ql512ab1: qspi-nor-flash-1@90000000 { @@ -163,3 +174,9 @@ }; }; }; + +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00010000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; diff --git a/boards/st/stm32h750b_dk/stm32h750b_dk.yaml b/boards/st/stm32h750b_dk/stm32h750b_dk.yaml index 126376b1464ed..ddca938bb51e6 100644 --- a/boards/st/stm32h750b_dk/stm32h750b_dk.yaml +++ b/boards/st/stm32h750b_dk/stm32h750b_dk.yaml @@ -12,4 +12,6 @@ supported: - arduino_gpio - gpio - dma + - flash + - rtc vendor: st diff --git a/boards/st/stm32h7b3i_dk/board.cmake b/boards/st/stm32h7b3i_dk/board.cmake index d13c9c0e976b1..027413fd66cf2 100644 --- a/boards/st/stm32h7b3i_dk/board.cmake +++ b/boards/st/stm32h7b3i_dk/board.cmake @@ -4,5 +4,13 @@ board_runner_args(jlink "--device=STM32H7B3LI" "--speed=4000") board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) +if(CONFIG_STM32_MEMMAP) +board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw") +board_runner_args(stm32cubeprogrammer "--extload=MX25LM51245G_STM32H7B3I-DISCO.stldr") +else() +board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw" ) +endif() + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) diff --git a/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts b/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts index 1567585b2fd53..95325e254b557 100644 --- a/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts +++ b/boards/st/stm32h7b3i_dk/stm32h7b3i_dk.dts @@ -59,6 +59,14 @@ zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; }; + octo_nor: memory@90000000 { + compatible = "zephyr,memory-region"; + reg = <0x90000000 DT_SIZE_M(64)>; + zephyr,memory-region = "EXTMEM"; + /* The ATTR_MPU_EXTMEM attribut causing a MPU FAULT */ + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; + }; + transceiver0: can-phy0 { compatible = "microchip,mcp2562fd", "can-transceiver-gpio"; standby-gpios = <&gpioh 8 GPIO_ACTIVE_HIGH>; @@ -70,7 +78,6 @@ led0 = &blue_led; led1 = &red_led; sw0 = &user_button; - spi-flash0 = &mx25lm51245; }; }; @@ -156,8 +163,6 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1_2 0x00000100>, <&rcc STM32_SRC_PLL1_Q FDCAN_SEL(1)>; phys = <&transceiver0>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; }; diff --git a/boards/st/stm32h7s78_dk/Kconfig.defconfig b/boards/st/stm32h7s78_dk/Kconfig.defconfig new file mode 100644 index 0000000000000..d8a0c6ecdcd50 --- /dev/null +++ b/boards/st/stm32h7s78_dk/Kconfig.defconfig @@ -0,0 +1,17 @@ +# STM32H7S78 DISCOVERY KIT board configuration +# +# Copyright (c) 2024 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# + +if BOARD_STM32H7S78_DK + +if NETWORKING + +config NET_L2_ETHERNET + default y + +endif # NETWORKING + +endif # BOARD_STM32H7S78_DK diff --git a/boards/st/stm32h7s78_dk/Kconfig.stm32h7s78_dk b/boards/st/stm32h7s78_dk/Kconfig.stm32h7s78_dk new file mode 100644 index 0000000000000..d3c5737a28933 --- /dev/null +++ b/boards/st/stm32h7s78_dk/Kconfig.stm32h7s78_dk @@ -0,0 +1,9 @@ +# STM32H7S78-DK Discovery kit board configuration +# +# Copyright (c) 2024 STMicroelectronics +# +# SPDX-License-Identifier: Apache-2.0 +# + +config BOARD_STM32H7S78_DK + select SOC_STM32H7S7XX diff --git a/boards/st/stm32h7s78_dk/arduino_r3_connector.dtsi b/boards/st/stm32h7s78_dk/arduino_r3_connector.dtsi new file mode 100644 index 0000000000000..c1d06e17bc13e --- /dev/null +++ b/boards/st/stm32h7s78_dk/arduino_r3_connector.dtsi @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + arduino_header: connector { + compatible = "arduino-header-r3"; + #gpio-cells = <2>; + gpio-map-mask = <0xffffffff 0xffffffc0>; + gpio-map-pass-thru = <0 0x3f>; + gpio-map = <0 0 &gpioc 0 0>, /* A0 */ + <1 0 &gpioc 2 0>, /* A1 */ + <2 0 &gpioc 3 0>, /* A2 */ + <3 0 &gpiof 12 0>, /* A3 */ + <4 0 &gpiof 13 0>, /* A4 */ + <5 0 &gpioc 1 0>, /* A5 */ + <6 0 &gpioe 7 0>, /* D0 */ + <7 0 &gpioe 8 0>, /* D1 */ + <8 0 &gpiof 1 0>, /* D2 */ + <9 0 &gpiod 12 0>, /* D3 */ + <10 0 &gpiof 2 0>, /* D4 */ + <11 0 &gpiod 13 0>, /* D5 */ + <12 0 &gpiod 15 0>, /* D6 */ + <13 0 &gpiof 3 0>, /* D7 */ + <14 0 &gpiof 4 0>, /* D8 */ + <15 0 &gpiof 6 0>, /* D9 */ + <16 0 &gpiof 8 0>, /* D10 */ + <17 0 &gpioe 14 0>, /* D11 */ + <18 0 &gpioe 13 0>, /* D12 */ + <19 0 &gpioe 12 0>, /* D13 */ + <20 0 &gpiob 9 0>, /* D14 */ + <21 0 &gpiob 6 0>; /* D15 */ + }; +}; + +arduino_spi: &spi4 {}; +arduino_i2c: &i2c1 {}; diff --git a/boards/st/stm32h7s78_dk/board.cmake b/boards/st/stm32h7s78_dk/board.cmake new file mode 100644 index 0000000000000..04b6ed24de460 --- /dev/null +++ b/boards/st/stm32h7s78_dk/board.cmake @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(stm32cubeprogrammer "--erase" "--port=swd" "--reset-mode=hw") +board_runner_args(openocd --target-handle=_CHIPNAME.cpu0) + +include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake) +# FIXME: openocd runner not yet available. +include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) diff --git a/boards/st/stm32h7s78_dk/board.yml b/boards/st/stm32h7s78_dk/board.yml new file mode 100644 index 0000000000000..c17be71480c2d --- /dev/null +++ b/boards/st/stm32h7s78_dk/board.yml @@ -0,0 +1,5 @@ +board: + name: stm32h7s78_dk + vendor: st + socs: + - name: stm32h7s7xx diff --git a/boards/st/stm32h7s78_dk/doc/img/stm32h7s78_dk.jpg b/boards/st/stm32h7s78_dk/doc/img/stm32h7s78_dk.jpg new file mode 100644 index 0000000000000..523ff89970c71 Binary files /dev/null and b/boards/st/stm32h7s78_dk/doc/img/stm32h7s78_dk.jpg differ diff --git a/boards/st/stm32h7s78_dk/doc/index.rst b/boards/st/stm32h7s78_dk/doc/index.rst new file mode 100644 index 0000000000000..8951ba16fdcd8 --- /dev/null +++ b/boards/st/stm32h7s78_dk/doc/index.rst @@ -0,0 +1,306 @@ +.. _stm32h7s78_dk_board: + +ST STM32H7S78-DK Discovery +########################## + +Overview +******** + +The STM32H7S78-DK Discovery kit is designed as a complete demonstration and +development platform for STMicroelectronics Arm |reg| Cortex |reg|-M7 core-based +STM32H7S7L8H6H microcontroller with TrustZone |reg|. Here are some highlights of +the STM32H7S78-DK Discovery board: + + +- STM32H7S7L8H6H microcontroller featuring 64Kbytes of Flash memory and 620 Kbytes of SRAM in 225-pin TFBGA package +- USB Type-C |trade| Host and device with USB power-delivery controller +- SAI Audio DAC stereo with one audio jacks for input/output, +- ST MEMS digital microphone with PDM interface +- Octo-SPI interface connected to 512Mbit Octo-SPI NORFlash memory device (MX66UW1G45GXD100 from MACRONIX) +- 10/100-Mbit Ethernet, + +- Board connectors + + - STMod+ expansion connector with fan-out expansion board for Wi‑Fi |reg|, Grove and mikroBUS |trade| compatible connectors + - Pmod |trade| expansion connector + - Audio MEMS daughterboard expansion connector + - ARDUINO |reg| Uno V3 expansion connector + +- Flexible power-supply options + + - ST-LINK + - USB VBUS + - external sources + +- On-board STLINK-V3E debugger/programmer with USB re-enumeration capability: + + - mass storage + - Virtual COM port + - debug port + +- 4 user LEDs +- User and reset push-buttons + +.. image:: img/stm32h7s78_dk.jpg + :align: center + :alt: STM32H7S78-DK Discovery + +More information about the board can be found at the `STM32H7S78-DK Discovery website`_. + +Hardware +******** + +The STM32H7S7xx devices are a high-performance microcontrollers family (STM32H7 +Series) based on the high-performance Arm |reg| Cortex |reg|-M7 32-bit RISC core. +They operate at a frequency of up to 500 MHz. + +- Core: ARM |reg| 32-bit Cortex |reg| -M7 CPU with TrustZone |reg| and FPU. +- Performance benchmark: + + - 1284 DMPIS/MHz (Dhrystone 2.1) + +- Security + + - Arm |reg| TrustZone |reg| with ARMv8-M mainline security extension + - Up to 8 configurable SAU regions + - TrustZone |reg| aware and securable peripherals + - Flexible lifecycle scheme with secure debug authentication + - Preconfigured immutable root of trust (ST-iROT) + - SFI (secure firmware installation) + - Secure data storage with hardware unique key (HUK) + - Secure firmware upgrade support with TF-M + - 2x AES coprocessors including one with DPA resistance + - Public key accelerator, DPA resistant + - On-the-fly decryption of Octo-SPI external memories + - HASH hardware accelerator + - True random number generator, NIST SP800-90B compliant + - 96-bit unique ID + - Active tampers + - True Random Number Generator (RNG) NIST SP800-90B compliant + +- Clock management: + + - 24 MHz crystal oscillator (HSE) + - 32768 Hz crystal oscillator for RTC (LSE) + - Internal 64 MHz (HSI) trimmable by software + - Internal low-power 32 kHz RC (LSI)( |plusminus| 5%) + - Internal 4 MHz oscillator (CSI), trimmable by software + - Internal 48 MHz (HSI48) with recovery system + - 3 PLLs for system clock, USB, audio, ADC + +- Power management + + - Embedded regulator (LDO) with three configurable range output to supply the digital circuitry + - Embedded SMPS step-down converter + +- RTC with HW calendar, alarms and calibration +- Up to 152 fast I/Os, most 5 V-tolerant, up to 10 I/Os with independent supply down to 1.08 V +- Up to 16 timers and 2 watchdogs + + - 16x 16-bit + - 4x 32-bit timers with up to 4 IC/OC/PWM or pulse counter and quadrature (incremental) encoder input + - 5x 16-bit low-power 16-bit timers (available in Stop mode) + - 2x watchdogs + - 1x SysTick timer + +- Memories + + - Up to 64KB Flash, 2 banks read-while-write + - 1 Kbyte OTP (one-time programmable) + - 640 KB of SRAM including 64 KB with hardware parity check and 320 Kbytes with flexible ECC + - 4 Kbytes of backup SRAM available in the lowest power modes + - Flexible external memory controller with up to 16-bit data bus: SRAM, PSRAM, FRAM, SDRAM/LPSDR SDRAM, NOR/NAND memories + - 2x OCTOSPI memory interface with on-the-fly decryption and support for serial PSRAM/NAND/NOR, Hyper RAM/Flash frame formats + - 1x HEXASPI memory interface with on-the-fly decryption and support for serial PSRAM/NAND/NOR, Hyper RAM/Flash frame formats + - 2x SD/SDIO/MMC interfaces + +- Rich analog peripherals (independent supply) + + - 2x 12-bit ADC with up to 5 MSPS in 12-bit + - 1x Digital temperature sensor + +- 35x communication interfaces + + - 1x USB Type-C / USB power-delivery controller + - 1x USB OTG full-speed with PHY + - 1x USB OTG high-speed with PHY + - 3x I2C FM+ interfaces (SMBus/PMBus) + - 1x I3C interface + - 7x U(S)ARTS (ISO7816 interface, LIN, IrDA, modem control) + - 2x LP UART + - 6x SPIs including 3 muxed with full-duplex I2S + - 2x SAI + - 2x FDCAN + - 2x SD/SDIO/MMC interface + - 2x 16 channel DMA controllers + - 1x 8- to 16- bit camera interface + - 1x HDMI-CEC + - 1x Ethernel MAC interface with DMA controller + - 1x 16-bit parallel slave synchronous-interface + - 1x SPDIF-IN interface + - 1x MDIO slave interface + +- CORDIC for trigonometric functions acceleration +- FMAC (filter mathematical accelerator) +- CRC calculation unit +- Development support: serial wire debug (SWD), JTAG, Embedded Trace Macrocell |trade| + + +More information about STM32H7S7 can be found here: + +- `STM32H7Sx on www.st.com`_ +- `STM32H7Sx reference manual`_ + +Supported Features +================== + +The Zephyr STM32H7S78_DK board configuration supports the following +hardware features: + ++-----------+------------+-------------------------------------+ +| Interface | Controller | Driver/Component | ++===========+============+=====================================+ +| CLOCK | on-chip | reset and clock control | ++-----------+------------+-------------------------------------+ +| GPIO | on-chip | gpio | ++-----------+------------+-------------------------------------+ +| NVIC | on-chip | nested vector interrupt controller | ++-----------+------------+-------------------------------------+ +| PINMUX | on-chip | pinmux | ++-----------+------------+-------------------------------------+ +| RNG | on-chip | True Random number generator | ++-----------+------------+-------------------------------------+ +| UART | on-chip | serial port-polling; | +| | | serial port-interrupt | ++-----------+------------+-------------------------------------+ +| WATCHDOG | on-chip | independent watchdog | ++-----------+------------+-------------------------------------+ +| ADC | on-chip | ADC Controller | ++-----------+------------+-------------------------------------+ +| SPI | on-chip | spi bus | ++-----------+------------+-------------------------------------+ + +Other hardware features are not yet supported on this Zephyr port. + +The default configuration can be found in the defconfig and dts files: + +- Secure target: + + - :zephyr_file:`boards/st/stm32h7s78_dk/stm32h7s78_dk_defconfig` + - :zephyr_file:`boards/st/stm32h7s78_dk/stm32h7s78_dk.dts` + +Zephyr board options +==================== + +The STM32HS7 is a SoC with Cortex-M7 architecture. Zephyr provides support +for building for Secure firmware. + +The BOARD options are summarized below: + ++----------------------+-----------------------------------------------+ +| BOARD | Description | ++======================+===============================================+ +| stm32h7s78_dk | For building Secure firmware | ++----------------------+-----------------------------------------------+ + +Connections and IOs +=================== + +STM32H7S78-DK Discovery Board has 12 GPIO controllers. These controllers are responsible for pin muxing, +input/output, pull-up, etc. + +For more details please refer to `STM32H7S78-DK Discovery board User Manual`_. + +Default Zephyr Peripheral Mapping: +---------------------------------- + +- USART_4 TX/RX : PD1/PD0 (VCP) +- USART_7 TX/RX : PE8/PE7 (Arduino USART7) +- USER_PB : PC13 +- LD1 (green) : PO1 +- LD2 (orange) : PO5 +- LD3 (red) : PM2 +- LD4 (blue) : PM3 +- ADC1 channel 6 input : PF12 + +System Clock +------------ + +STM32H7S78-DK System Clock could be driven by internal or external oscillator, +as well as main PLL clock. By default System clock is driven by PLL clock at +500MHz, driven by 24MHz external oscillator (HSE). + +Serial Port +----------- + +STM32H7S78-DK Discovery board has 2 U(S)ARTs. The Zephyr console output is +assigned to USART4. Default settings are 115200 8N1. + + +Programming and Debugging +************************* + +Applications for the ``stm32h7s78_dk`` board configuration can be built and +flashed in the usual way (see :ref:`build_an_application` and +:ref:`application_run` for more details). + +Flashing +======== + +STM32H7S78-DK Discovery board includes an ST-LINK/V3E embedded debug tool +interface. Support is available on STM32CubeProgrammer V2.13.0. + +Alternatively, this interface will be supported by a next openocd version. + +Flashing an application to STM32H7S78-DK Discovery +-------------------------------------------------- + +Connect the STM32H7S78-DK Discovery to your host computer using the USB port. +Then build and flash an application. Here is an example for the +:ref:`hello_world` application. + +Run a serial host program to connect with your Nucleo board: + +.. code-block:: console + + $ minicom -D /dev/ttyACM0 + +Then build and flash the application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: stm32h7s78_dk + :goals: build flash + +You should see the following message on the console: + +.. code-block:: console + + Hello World! stm32h7s78_dk + +Debugging +========= + +You can debug an application in the usual way. Here is an example for the +:ref:`hello_world` application. + +.. zephyr-app-commands:: + :zephyr-app: samples/hello_world + :board: stm32h7s78_dk + :maybe-skip-config: + :goals: debug + +.. _STM32H7S78-DK Discovery website: + https://www.st.com/en/evaluation-tools/stm32h7s78-dk.html + +.. _STM32H7S78-DK Discovery board User Manual: + https://www.st.com/en/evaluation-tools/stm32h7s78-dk.html + +.. _STM32H7Sx on www.st.com: + https://www.st.com/en/evaluation-tools/stm32h7s78-dk.html + +.. _STM32H7Sx reference manual: + https://www.st.com/resource/en/reference_manual/rm0477-stm32h7rx7sx-armbased-32bit-mcus-stmicroelectronics.pdf + +.. _STM32CubeProgrammer: + https://www.st.com/en/development-tools/stm32cubeprog.html diff --git a/boards/st/stm32h7s78_dk/stm32h7s78_dk.dts b/boards/st/stm32h7s78_dk/stm32h7s78_dk.dts new file mode 100644 index 0000000000000..6cd70cbe60d07 --- /dev/null +++ b/boards/st/stm32h7s78_dk/stm32h7s78_dk.dts @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include +#include +#include "arduino_r3_connector.dtsi" +#include + +/ { + model = "STMicroelectronics STM32H7S78 DISCOVERY KIT board"; + compatible = "st,stm32h7s78-dk"; + + chosen { + zephyr,console = &uart4; + zephyr,shell-uart = &uart4; + zephyr,flash = &flash0; + zephyr,sram = &sram0; + }; + + leds { + compatible = "gpio-leds"; + green_led: led_1 { + gpios = <&gpioo 1 GPIO_ACTIVE_LOW>; + label = "User LD1"; + }; + orange_led: led_2 { + gpios = <&gpioo 5 GPIO_ACTIVE_LOW>; + label = "User LD2"; + }; + red_led: led_3 { + gpios = <&gpiom 2 GPIO_ACTIVE_LOW>; + label = "User LD3"; + }; + blue_led: led_4 { + gpios = <&gpiom 3 GPIO_ACTIVE_LOW>; + label = "User LD4"; + }; + }; + + gpio_keys { + compatible = "gpio-keys"; + user_button: button { + label = "User"; + gpios = <&gpioc 13 GPIO_ACTIVE_LOW>; + zephyr,code = ; + }; + }; + + aliases { + led0 = &blue_led; + sw0 = &user_button; + watchdog0 = &iwdg; + die-temp0 = &die_temp; + volt-sensor0 = &vref; + volt-sensor1 = &vbat; + }; +}; + +&clk_hsi48 { + status = "okay"; +}; + +&clk_lse { + status = "okay"; +}; + +&clk_hse { + clock-frequency = ; + hse-bypass; /* X3 is a 24MHz oscillator on PH0 */ + status = "okay"; +}; + +&pll { + div-m = <12>; + mul-n = <250>; + div-p = <2>; + div-q = <2>; + div-r = <2>; + div-s = <2>; + div-t = <2>; + clocks = <&clk_hse>; + status = "okay"; +}; + +&rcc { + clocks = <&pll>; + clock-frequency = ; + dcpre = <1>; + hpre = <1>; + ppre1 = <2>; + ppre2 = <2>; + ppre4 = <2>; + ppre5 = <2>; +}; + +&uart4 { + pinctrl-0 = <&uart4_tx_pd1 &uart4_rx_pd0>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&uart7 { + pinctrl-0 = <&uart7_tx_pe8 &uart7_rx_pe7>; + pinctrl-names = "default"; + current-speed = <115200>; + status = "okay"; +}; + +&timers2 { + st,prescaler = <10000>; + status = "okay"; + + pwm2: pwm { + status = "okay"; + pinctrl-0 = <&tim2_ch4_pa3>; + pinctrl-names = "default"; + }; +}; + +&timers3 { + st,prescaler = <10000>; + status = "okay"; + + pwm3: pwm { + status = "okay"; + pinctrl-0 = <&tim3_ch2_pb5>; + pinctrl-names = "default"; + }; +}; + +&rng { + status = "okay"; +}; + +&iwdg { + status = "okay"; +}; + +&wwdg { + status = "okay"; +}; + +&adc1 { + pinctrl-0 = <&adc1_inp6_pf12>; /* Arduino A3 */ + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + status = "okay"; +}; + +&adc2 { + pinctrl-0 = <&adc2_inp2_pf13>; /* Arduino A4 */ + pinctrl-names = "default"; + st,adc-clock-source = ; + st,adc-prescaler = <4>; + status = "okay"; +}; + +&spi4 { + pinctrl-0 = <&spi4_nss_pe4 &spi4_sck_pe12 + &spi4_miso_pe13 &spi4_mosi_pe14>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c1 { + pinctrl-0 = <&i2c1_scl_pb6 &i2c1_sda_pb9>; + pinctrl-names = "default"; +}; + +&die_temp { + status = "okay"; +}; + +&vref { + status = "okay"; +}; + +&vbat { + status = "okay"; +}; diff --git a/boards/st/stm32h7s78_dk/stm32h7s78_dk.yaml b/boards/st/stm32h7s78_dk/stm32h7s78_dk.yaml new file mode 100644 index 0000000000000..e48895cbce1bb --- /dev/null +++ b/boards/st/stm32h7s78_dk/stm32h7s78_dk.yaml @@ -0,0 +1,16 @@ +identifier: stm32h7s78_dk +name: ST STM32H7S78 Discovery Kit +type: mcu +arch: arm +toolchain: + - zephyr +ram: 640 +flash: 64 +supported: + - arduino_gpio + - gpio + - uart + - watchdog + - entropy + - adc +vendor: st diff --git a/boards/st/stm32h7s78_dk/stm32h7s78_dk_defconfig b/boards/st/stm32h7s78_dk/stm32h7s78_dk_defconfig new file mode 100644 index 0000000000000..d8caa7276387a --- /dev/null +++ b/boards/st/stm32h7s78_dk/stm32h7s78_dk_defconfig @@ -0,0 +1,26 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +# Enable SMPS +CONFIG_POWER_SUPPLY_DIRECT_SMPS=y + +# Enable MPU +CONFIG_ARM_MPU=y + +# Enable HW stack protection +CONFIG_HW_STACK_PROTECTION=y + +# enable uart driver +CONFIG_SERIAL=y +# enable console +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y + +# enable GPIO +CONFIG_GPIO=y + +# Enable Clocks +CONFIG_CLOCK_CONTROL=y + +# enable pin controller +CONFIG_PINCTRL=y diff --git a/boards/st/stm32h7s78_dk/support/openocd.cfg b/boards/st/stm32h7s78_dk/support/openocd.cfg new file mode 100644 index 0000000000000..b32c9f26c2ca2 --- /dev/null +++ b/boards/st/stm32h7s78_dk/support/openocd.cfg @@ -0,0 +1,41 @@ +source [find interface/stlink-dap.cfg] +transport select "dapdirect_swd" + +set WORKAREASIZE 0x8000 +set CHIPNAME STM32H7S7XX +set BOARDNAME STM32H7S78_DK + +# Enable debug when in low power modes +set ENABLE_LOW_POWER 1 + +# Stop Watchdog counters when halt +set STOP_WATCHDOG 1 + +# Reset configuration +# use hardware reset, connect under reset +# connect_assert_srst needed if low power mode application running (WFI...) +# reset_config srst_only srst_nogate connect_assert_srst + +#set CONNECT_UNDER_RESET 1 +#set CORE_RESET 0 + +source [find target/stm32h7rx.cfg] + + +$_CHIPNAME.cpu0 configure -event gdb-attach { + echo "Debugger attaching: halting execution" + gdb_breakpoint_override hard +} + +$_CHIPNAME.cpu0 configure -event gdb-detach { + echo "Debugger detaching: resuming execution" + resume +} + +# Due to the use of connect_assert_srst, running gdb requires +# to reset halt just after openocd init. +rename init old_init +proc init {} { + old_init + reset halt +} diff --git a/boards/st/stm32l496g_disco/stm32l496g_disco.dts b/boards/st/stm32l496g_disco/stm32l496g_disco.dts index e2a70f6163d52..a6d1e876f4e81 100644 --- a/boards/st/stm32l496g_disco/stm32l496g_disco.dts +++ b/boards/st/stm32l496g_disco/stm32l496g_disco.dts @@ -68,7 +68,6 @@ sw4 = &joy_left; volt-sensor0 = &vref; volt-sensor1 = &vbat; - spi-flash0 = &mx25r6435; }; }; diff --git a/boards/st/stm32l496g_disco/stm32l496g_disco.yaml b/boards/st/stm32l496g_disco/stm32l496g_disco.yaml index 3544d15980c3b..15301e002c717 100644 --- a/boards/st/stm32l496g_disco/stm32l496g_disco.yaml +++ b/boards/st/stm32l496g_disco/stm32l496g_disco.yaml @@ -15,7 +15,6 @@ supported: - spi - gpio - counter - - sdhc - adc - qspi vendor: st diff --git a/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.dts b/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.dts index 3d54fbc3cdf62..49737c68c8f56 100644 --- a/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.dts +++ b/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.dts @@ -44,7 +44,6 @@ die-temp0 = &die_temp; volt-sensor0 = &vref; volt-sensor1 = &vbat; - spi-flash0 = &mx25lm51245; }; }; diff --git a/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.yaml b/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.yaml index 89ab98c92b108..81d844caf75df 100644 --- a/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.yaml +++ b/boards/st/stm32l4r9i_disco/stm32l4r9i_disco.yaml @@ -18,7 +18,6 @@ supported: - i2c - pwm - rtc - - sdhc - spi - uart - usb diff --git a/boards/st/stm32l562e_dk/Kconfig.defconfig b/boards/st/stm32l562e_dk/Kconfig.defconfig index 3f15027bb35d6..ed9a04edc17a4 100644 --- a/boards/st/stm32l562e_dk/Kconfig.defconfig +++ b/boards/st/stm32l562e_dk/Kconfig.defconfig @@ -10,9 +10,8 @@ if BT config SPI default y -choice BT_HCI_BUS_TYPE - default BT_SPI -endchoice +config BT_SPI + default y config BT_BLUENRG_ACI default y @@ -21,7 +20,7 @@ config BT_BLUENRG_ACI config BT_HCI_ACL_FLOW_CONTROL default n -config BT_HCI_VS_EXT +config BT_HCI_VS default n endif # BT diff --git a/boards/st/stm32l562e_dk/stm32l562e_dk.yaml b/boards/st/stm32l562e_dk/stm32l562e_dk.yaml index dcbe7539d6482..c2acb4cb09823 100644 --- a/boards/st/stm32l562e_dk/stm32l562e_dk.yaml +++ b/boards/st/stm32l562e_dk/stm32l562e_dk.yaml @@ -19,7 +19,6 @@ supported: - dma - usart - arduino_spi - - sdhc - usb - usb_device - nvs diff --git a/boards/st/stm32l562e_dk/stm32l562e_dk_common.dtsi b/boards/st/stm32l562e_dk/stm32l562e_dk_common.dtsi index ccd74b46ece55..6922b6be83fa9 100644 --- a/boards/st/stm32l562e_dk/stm32l562e_dk_common.dtsi +++ b/boards/st/stm32l562e_dk/stm32l562e_dk_common.dtsi @@ -32,11 +32,14 @@ }; aliases { - spi-flash0 = &mx25lm51245; die-temp0 = &die_temp; volt-sensor0 = &vref; volt-sensor1 = &vbat; }; + + chosen { + zephyr,bt-hci = &hci_spi; + }; }; &clk_hsi48 { @@ -114,7 +117,7 @@ stm32_lp_tick_source: &lptim1 { cs-gpios = <&gpiog 5 GPIO_ACTIVE_LOW>; status = "okay"; - spbtle-rf@0 { + hci_spi: spbtle-rf@0 { compatible = "st,hci-spi-v1"; reg = <0>; irq-gpios = <&gpiog 6 (GPIO_ACTIVE_HIGH | GPIO_PULL_DOWN)>; diff --git a/boards/st/stm32l562e_dk/stm32l562e_dk_stm32l562xx_ns.yaml b/boards/st/stm32l562e_dk/stm32l562e_dk_stm32l562xx_ns.yaml index c092f8da95d82..50d239c805beb 100644 --- a/boards/st/stm32l562e_dk/stm32l562e_dk_stm32l562xx_ns.yaml +++ b/boards/st/stm32l562e_dk/stm32l562e_dk_stm32l562xx_ns.yaml @@ -13,7 +13,6 @@ supported: - dac - spi - arduino_spi - - sdhc - usb - usb_device ram: 192 diff --git a/boards/st/stm32u5a9j_dk/doc/index.rst b/boards/st/stm32u5a9j_dk/doc/index.rst index 29e4e02cdebd1..7e3d638fa3ead 100644 --- a/boards/st/stm32u5a9j_dk/doc/index.rst +++ b/boards/st/stm32u5a9j_dk/doc/index.rst @@ -85,6 +85,8 @@ hardware features: +-----------+------------+-------------------------------------+ | TIMER | on-chip | counter | +-----------+------------+-------------------------------------+ +| RTC | on-chip | rtc | ++-----------+------------+-------------------------------------+ Other hardware features have not been enabled yet for this board. diff --git a/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.dts b/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.dts index 66859c3daabcb..05bdfdd34ebf3 100644 --- a/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.dts +++ b/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.dts @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -89,6 +89,10 @@ msi-pll-mode; }; +&clk_lse { + status = "okay"; +}; + &pll1 { div-m = <1>; mul-n = <80>; @@ -271,6 +275,12 @@ uart0: &usart3 { }; }; +&rtc { + clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>, + <&rcc STM32_SRC_LSE RTC_SEL(1)>; + status = "okay"; +}; + &iwdg { status = "okay"; }; diff --git a/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.yaml b/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.yaml index 7205a3954d46c..792eda8a7b76f 100644 --- a/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.yaml +++ b/boards/st/stm32u5a9j_dk/stm32u5a9j_dk.yaml @@ -20,6 +20,7 @@ supported: - sdmmc - timer - rng + - rtc ram: 2496 flash: 4096 vendor: st diff --git a/boards/st/stm32wb5mm_dk/Kconfig.defconfig b/boards/st/stm32wb5mm_dk/Kconfig.defconfig index 37be19b4d1c65..b75d5bdb31d8f 100644 --- a/boards/st/stm32wb5mm_dk/Kconfig.defconfig +++ b/boards/st/stm32wb5mm_dk/Kconfig.defconfig @@ -5,9 +5,8 @@ if BOARD_STM32WB5MM_DK -choice BT_HCI_BUS_TYPE - default BT_STM32_IPM +config BT_STM32_IPM + default y depends on BT -endchoice endif diff --git a/boards/st/stm32wb5mm_dk/doc/stm32wb5mm_dk.rst b/boards/st/stm32wb5mm_dk/doc/stm32wb5mm_dk.rst index a149ea79a3679..84322f1bc7173 100644 --- a/boards/st/stm32wb5mm_dk/doc/stm32wb5mm_dk.rst +++ b/boards/st/stm32wb5mm_dk/doc/stm32wb5mm_dk.rst @@ -121,6 +121,8 @@ The Zephyr STM32WB5MM-DK board configuration supports the following hardware fea | UART | on-chip | serial port-polling; | | | | serial port-interrupt | +-----------+------------+-------------------------------------+ +| I2C | on-chip | i2c | ++-----------+------------+-------------------------------------+ Other hardware features are not yet supported on this Zephyr port. @@ -157,6 +159,7 @@ Default Zephyr Peripheral Mapping: - LPUART_1 TX/RX : PA3/PA2 - USB : PA11/PA12 - SWD : PA13/PA14 +- I2C3: SDA/SCL PB11/PB13 (Sensor I2C bus) System Clock ------------ @@ -170,6 +173,18 @@ Serial Port STM32WB5MM-DK board has 2 (LP)U(S)ARTs. The Zephyr console output is assigned to USART1. Default settings are ``115200 8N1``. +LEDs +---- +STM32WB5MM-DK has two types of LEDs, The resources coming from STM32WB5MMG are +shared between the RGB and IR LEDs. It is not possible to use them +simultaneously. The selection is done by JP4 and JP5 jumpers. +To use the RGB LED, JP5 must be ON and JP4 OFF. In this configuration, +GPIO_SELECT2 (PH1) is the chip select for this RGB device on SPI1. + +Buttons +------- +STM32WB5MM-DK has two user buttons. The first button is mapped to PC12, +and the second to PC13. They have the aliases sw0 and sw1 respectively. Programming and Debugging ************************* diff --git a/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.dts b/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.dts index 4f4fb99cea013..e11ec3f0f20bd 100644 --- a/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.dts +++ b/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.dts @@ -8,6 +8,8 @@ #include #include #include +#include +#include / { model = "STMicroelectronics STM32WB5MM Discovery Development Kit"; @@ -22,11 +24,40 @@ zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; }; + + rgb_led_strip: rgb_strip { + compatible = "ti,tlc59731"; + gpios = <&gpioa 7 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>; + chain-length = <1>; + color-mapping = ; + status = "disabled"; + }; + + buttons { + compatible = "gpio-keys"; + button0: button_0 { + gpios = <&gpioc 12 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 1"; + zephyr,code = ; + }; + button1: button_1 { + gpios = <&gpioc 13 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + label = "Push button 2"; + zephyr,code = ; + }; + }; + aliases { watchdog0 = &iwdg; die-temp0 = &die_temp; volt-sensor0 = &vref; volt-sensor1 = &vbat; + led-strip = &rgb_led_strip; + sw0 = &button0; + sw1 = &button1; + accel0 = &ism330dhcx; }; }; @@ -136,6 +167,36 @@ zephyr_udc0: &usb { }; }; +&gpioh { + rgb_cs: rgb_cs { + gpios = <1 GPIO_ACTIVE_HIGH>; + gpio-hog; + output-high; + status = "disabled"; + }; +}; + +&i2c3 { + pinctrl-0 = <&i2c3_scl_pb13 &i2c3_sda_pb11>; + pinctrl-names = "default"; + status = "okay"; + clock-frequency = ; + + vl53l0x@29 { + compatible = "st,vl53l0x"; + reg = <0x29>; + xshut-gpios = <&gpioc 6 GPIO_ACTIVE_LOW>; + }; + + ism330dhcx: ism330dhcx@6b { + compatible = "st,ism330dhcx"; + reg = <0x6b>; + drdy-gpios = <&gpiod 2 GPIO_ACTIVE_HIGH>; + accel-odr= ; + gyro-odr= ; + }; +}; + &vref { status = "okay"; }; diff --git a/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.yaml b/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.yaml index 63c75d4473fb1..a90491d13aa88 100644 --- a/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.yaml +++ b/boards/st/stm32wb5mm_dk/stm32wb5mm_dk.yaml @@ -7,8 +7,11 @@ toolchain: - gnuarmemb - xtools ram: 256 -flash: 1024 +flash: 876 supported: - gpio - uart + - i2c + - vl53l0x + - ism330dhcx vendor: st diff --git a/boards/st/stm32wb5mmg/Kconfig.defconfig b/boards/st/stm32wb5mmg/Kconfig.defconfig index e63531f897bac..e07cc7210b21c 100644 --- a/boards/st/stm32wb5mmg/Kconfig.defconfig +++ b/boards/st/stm32wb5mmg/Kconfig.defconfig @@ -5,9 +5,8 @@ if BOARD_STM32WB5MMG -choice BT_HCI_BUS_TYPE - default BT_STM32_IPM +config BT_STM32_IPM + default y depends on BT -endchoice endif diff --git a/boards/technexion/pico_pi/Kconfig.defconfig b/boards/technexion/pico_pi/Kconfig.defconfig deleted file mode 100644 index aebd510fe618d..0000000000000 --- a/boards/technexion/pico_pi/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# Pico-Pi iMX7D M4 board - -# Copyright (c) 2019, Joris Offouga -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_PICO_PI - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_PICO_PI diff --git a/boards/telink/tlsr9518adk80d/Kconfig.defconfig b/boards/telink/tlsr9518adk80d/Kconfig.defconfig index 001ad28758607..a1dc3d5f5825b 100644 --- a/boards/telink/tlsr9518adk80d/Kconfig.defconfig +++ b/boards/telink/tlsr9518adk80d/Kconfig.defconfig @@ -6,22 +6,6 @@ if BOARD_TLSR9518ADK80D config SOC_FLASH_TELINK_B91 default y if FLASH -if BT - -# BLE Controller SDK from hal_telink requires -# Telink's toolchain with FPU support -config FPU - default y if "$(ZEPHYR_TOOLCHAIN_VARIANT)" != "zephyr" - -config BT_HCI_ACL_FLOW_CONTROL - default n - -choice BT_HCI_BUS_TYPE - default BT_B91 -endchoice - -endif # BT - # Workaround for not being able to have commas in macro arguments DT_CHOSEN_Z_CODE_PARTITION := zephyr,code-partition diff --git a/boards/ti/cc1352r_sensortag/support/openocd.cfg b/boards/ti/cc1352r_sensortag/support/openocd.cfg index 16a135a531a07..beec0517534db 100644 --- a/boards/ti/cc1352r_sensortag/support/openocd.cfg +++ b/boards/ti/cc1352r_sensortag/support/openocd.cfg @@ -1,4 +1,4 @@ source [find board/ti_cc13x2_launchpad.cfg] # Workaround for #21372. This allows OpenOCD to flash correctly # with newer 3.x XDS firmware -adapter_khz 1500 +adapter speed 1500 diff --git a/boards/ti/sk_am62/board.cmake b/boards/ti/sk_am62/board.cmake new file mode 100644 index 0000000000000..d148f687c293a --- /dev/null +++ b/boards/ti/sk_am62/board.cmake @@ -0,0 +1,10 @@ +# Texas Instruments Sitara AM62x-SK-M4 EVM +# +# Copyright (c) 2024, PHYTEC Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_SOC_AM6234_M4) + board_runner_args(openocd "--no-init" "--no-halt" "--no-targets" "--gdb-client-port=3339") + include(${ZEPHYR_BASE}/boards/common/openocd.board.cmake) +endif() diff --git a/boards/ti/sk_am62/doc/index.rst b/boards/ti/sk_am62/doc/index.rst index 0a93edd1367a0..3dd92386321b2 100644 --- a/boards/ti/sk_am62/doc/index.rst +++ b/boards/ti/sk_am62/doc/index.rst @@ -119,6 +119,21 @@ To allow the board to boot using the SD card, set the boot pins to the SD Card b After changing the boot mode, the board should go through the boot sequence on powering up. The binary will run and print Hello world to the MCU_UART0 port. +Debugging +********* + +The board is equipped with an XDS110 JTAG debugger. To debug a binary, utilize the `debug` build target: + +.. zephyr-app-commands:: + :zephyr-app: + :board: sk_am62/am6234/m4 + :maybe-skip-config: + :goals: debug + +.. hint:: + To utilize this feature, you'll need OpenOCD version 0.12 or higher. Due to the possibility of + older versions being available in package feeds, it's advisable to `build OpenOCD from source`_. + References ********** @@ -136,3 +151,6 @@ AM62x SK EVM TRM: .. _EVM Setup Page: https://software-dl.ti.com/mcu-plus-sdk/esd/AM62X/08_06_00_18/exports/docs/api_guide_am62x/EVM_SETUP_PAGE.html + +.. _build OpenOCD from source: + https://docs.u-boot.org/en/latest/board/ti/k3.html#building-openocd-from-source diff --git a/boards/ti/sk_am62/support/openocd.cfg b/boards/ti/sk_am62/support/openocd.cfg new file mode 100644 index 0000000000000..2b09fb7345a84 --- /dev/null +++ b/boards/ti/sk_am62/support/openocd.cfg @@ -0,0 +1,7 @@ +# Texas Instruments Sitara AM62x-SK-M4 EVM +# +# Copyright (c) 2024, PHYTEC Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +source [find board/ti_am625evm.cfg] diff --git a/boards/toradex/colibri_imx7d/Kconfig.defconfig b/boards/toradex/colibri_imx7d/Kconfig.defconfig deleted file mode 100644 index 4f108737fd2aa..0000000000000 --- a/boards/toradex/colibri_imx7d/Kconfig.defconfig +++ /dev/null @@ -1,16 +0,0 @@ -# Colibri iMX7D M4 board - -# Copyright 2017,2024 NXP -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_COLIBRI_IMX7D_MCIMX7D_M4 - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - - -endif # BOARD_COLIBRI_IMX7D_MCIMX7D_M4 diff --git a/boards/toradex/colibri_imx7d/doc/index.rst b/boards/toradex/colibri_imx7d/doc/index.rst index 22b356fc1c625..dd13a140b3c82 100644 --- a/boards/toradex/colibri_imx7d/doc/index.rst +++ b/boards/toradex/colibri_imx7d/doc/index.rst @@ -221,6 +221,195 @@ configured in the Zephyr compilation: setenv bootm4ddr 'run m4ddr && run bootm4' run bootm4ddr +M4<->Linux IPC using RPMSG +************************** + +The IMX7D soc supports the subsys/ipc/openamp_rsc_table sample to demonstrate the +usage of rpmsg_tty as an inter processor communication. + +The board configuration is provided for the colibri_imx7d board. +The boot process of the M4 core is handled solely by the Linux kernel using the RPROC +framework. + +The sample was tested with Toradex's LTS BSP 6.6.0 Minimal Open Embedded image with +upstream Linux kernel 6.1.83. + +Required kernel modules must be loaded for RPMSG to work: + +- imx_rproc +- virtio_rpmsg_bus +- rpmsg_tty (requiring rpmsg_core) + +You need to modify your Linux device tree to add the M4 definitions: + +- Enable MU_A +- Reserve memory areas for the M4 so Linux won't touch them. +- Define the M4 remoteproc node for the drivers. + +If you have not downloaded the BSP sources, you can modify the board's device tree +from its currently loaded dtb file. + + +.. code-block:: none + + #Check the which fdtfile is loaded for your board in U-boot + printenv + #For a Colibri_imx7d on Viola Carrier on BSP 6.6.0 + fdtfile = imx7d-colibri-emmc-eval-v3.dtb + + #Copy this file to your Linux PC through SSH from /boot + #Convert the dtb into a dts + dtc -I dtb -O dts -f imx7d-colibri-emmc-eval-v3.dtb -o imx7d-colibri-emmc-eval-v3.dts + + #You need to find the following phandle numbers: + # reset-controller + # mailbox@30aa0000 + + #Note down the phandle value (0xbd) + grep -A10 "mailbox@30aa0000 {" imx7d-colibri-emmc-eval-v3.dts + # outputs your DTS's mailbox definition + # mailbox@30aa0000 { + # compatible = "fsl,imx7s-mu\0fsl,imx6sx-mu"; + # reg = <0x30aa0000 0x10000>; + # interrupts = <0x00 0x58 0x04>; + # clocks = <0x01 0x1b1>; + # #mbox-cells = <0x02>; + # status = "disabled"; + # phandle = <0xbd>; + # }; + + #Note down the phandle value (0x32) + grep -A8 "reset-controller@30390000 {" imx7d-colibri-emmc-eval-v3.dts + # outputs your DTS's reset-controller definition + # reset-controller@30390000 { + # compatible = "fsl,imx7d-src\0syscon"; + # reg = <0x30390000 0x10000>; + # interrupts = <0x00 0x59 0x04>; + # #reset-cells = <0x01>; + # phandle = <0x32>; + # }; + + #Node down the biggest phandle value + grep "phandle = <" imx7d-colibri-emmc-eval-v3.dts | sort -r | head -1 + # outputs your DTS's largest phandle definition + # phandle = <0xca>; + + #Now we can add our nodes to the .dts file: + cp imx7d-colibri-emmc-eval-v3.dts imx7d-m4.dts + nano imx7d-m4.dts + + #Modify MU_A node to enable it + mailbox@30aa0000 { + compatible = "fsl,imx7s-mu\0fsl,imx6sx-mu"; + reg = <0x30aa0000 0x10000>; + interrupts = <0x00 0x58 0x04>; + clocks = <0x01 0x1b1>; + #mbox-cells = <0x02>; + status = "okay"; + phandle = <0xbd>; + }; + + #Add these definitions under / { } just before the __symbols__ + #Disgard the comments with #--> + reserved-memory { + #address-cells = <0x01>; + #size-cells = <0x01>; + ranges; + + vdev0buffer0@90002000 { + compatible = "shared-dma-pool"; + reg = <0x90002000 0x8000>; + no-map; + phandle = <0xcb>; #--> biggest phandle +1 + }; + + vdev0vring0@90000000 { + compatible = "shared-dma-pool"; + reg = <0x90000000 0x1000>; + no-map; + phandle = <0xcc>; #--> biggest phandle +2 + }; + + vdev0vring1@90001000 { + compatible = "shared-dma-pool"; + reg = <0x90001000 0x1000>; + no-map; + phandle = <0xcd>; #--> biggest phandle +3 + }; + + cm4tcmcode@7f8000 { + compatible = "shared-dma-pool"; + reg = <0x7f8000 0x8000>; + no-map; + phandle = <0xce>; #--> biggest phandle +4 + }; + + cm4sramcode@900000 { + compatible = "shared-dma-pool"; + reg = <0x900000 0x40000>; + no-map; + phandle = <0xcf>; #--> biggest phandle +5 + }; + + cm4reserved@8ff00000 { + compatible = "shared-dma-pool"; + reg = <0x8ff00000 0x100000>; + no-map; + phandle = <0xd0>; #--> biggest phandle +6 + }; + }; + + imx7d-cm4 { + compatible = "fsl,imx7d-cm4"; + mbox-names = "tx\0rx\0rxdb"; + mboxes = <0xbd 0x00 0x00 0xbd 0x01 0x00 0xbd 0x03 0x00>; #--> MU_A phandle (0xbd) + memory-region = <0xcb 0xcc 0xcd 0xce 0xcf 0xd0>; #--> All the previously defined phandles + syscon = <0x32>; #--> phandle for the reset-controller + clocks = <0x01 0x42>; + }; + + #Recompile the dts into a dtb + dtc -I dts -O dtb -f imx7d-m4.dts -o imx7d-m4.dtb + + #Copy the new dtb to /boot on the Colibri IMX7 board + #Start in U-boot and update the device-tree + setenv fdtfile imx7d-m4.dtb + saveenv + boot + +When the OS has finished booting with your new device tree you can enable +the drivers and start the M4 core. + +.. code-block:: console + + #Copy zephyr_openamp_rsc_table.elf to /lib/firmware on your board + $ modprobe imx_rproc + $ modprobe virtio_rpmsg_bus + $ modprobe rpmsg_tty + + #Request RPROC to load the M4 image + $ echo stop > /sys/class/remoteproc/remoteproc0/state + $ echo zephyr_openamp_rsc_table.elf > /sys/class/remoteproc/remoteproc0/firmware + $ echo start > /sys/class/remoteproc/remoteproc0/state + + #dmesg will detail the boot process: + $ dmesg + [ 497.120499] remoteproc remoteproc0: stopped remote processor imx-rproc + [ 497.138938] remoteproc remoteproc0: powering up imx-rproc + [ 497.168735] remoteproc remoteproc0: Booting fw image zephyr_openamp_rsc_table.elf, size 1267076 + [ 497.184826] rproc-virtio rproc-virtio.1.auto: assigned reserved memory node vdev0buffer0@90002000 + [ 497.221395] virtio_rpmsg_bus virtio0: rpmsg host is online + [ 497.233806] virtio_rpmsg_bus virtio0: creating channel rpmsg-tty addr 0x400 + [ 497.236666] rproc-virtio rproc-virtio.1.auto: registered virtio0 (type 7) + [ 497.259822] remoteproc remoteproc0: remote processor imx-rproc is now up + [ 497.293913] virtio_rpmsg_bus virtio0: creating channel rpmsg-client-sample addr 0x401 + [ 497.308388] rpmsg_client_sample virtio0.rpmsg-client-sample.-1.1025: new channel: 0x401 -> 0x401! + [ 497.337969] virtio_rpmsg_bus virtio0: creating channel rpmsg-tty addr 0x402 + + $ ls /dev | grep ttyRPMSG + ttyRPMSG0 -> used for zephyr shell interface + ttyRPMSG1 -> used for sample interface + Debugging ========= diff --git a/boards/toradex/verdin_imx8mp/Kconfig.defconfig b/boards/toradex/verdin_imx8mp/Kconfig.defconfig deleted file mode 100644 index 76903f1d2e1cc..0000000000000 --- a/boards/toradex/verdin_imx8mp/Kconfig.defconfig +++ /dev/null @@ -1,15 +0,0 @@ -# VERDIN_IMX8MP board defconfig - -# Copyright (c) 2023 Toradex -# SPDX-License-Identifier: Apache-2.0 - -if BOARD_VERDIN_IMX8MP - -if !XIP -config FLASH_SIZE - default 0 -config FLASH_BASE_ADDRESS - default 0 -endif - -endif # BOARD_VERDIN_IMX8MP diff --git a/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.dts b/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.dts index d06986a8afa29..070730c69d2c5 100644 --- a/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.dts +++ b/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.dts @@ -129,7 +129,6 @@ sw2 = &button2; sw3 = &button3; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.yaml b/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.yaml index be6ccd190a803..eeca79d1e5e43 100644 --- a/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.yaml +++ b/boards/u-blox/ubx_bmd340eval/ubx_bmd340eval_nrf52840.yaml @@ -20,7 +20,6 @@ supported: - pwm - spi - qspi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.dts b/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.dts index ef145eabe5408..68b3755123b28 100644 --- a/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.dts +++ b/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.dts @@ -141,7 +141,6 @@ mcuboot-button0 = &button0; mcuboot-led0 = &led0; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.yaml b/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.yaml index fa53f794f09fa..f79940dbbbdf0 100644 --- a/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.yaml +++ b/boards/u-blox/ubx_bmd345eval/ubx_bmd345eval_nrf52840.yaml @@ -19,7 +19,6 @@ supported: - pwm - spi - qspi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.dts b/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.dts index 404678ad95299..d7a21c98b444e 100644 --- a/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.dts +++ b/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.dts @@ -90,7 +90,6 @@ sw2 = &button2; sw3 = &button3; watchdog0 = &wdt0; - spi-flash0 = &mx25r64; }; }; diff --git a/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.yaml b/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.yaml index 15bb236585d4e..a794a4cac05ec 100644 --- a/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.yaml +++ b/boards/u-blox/ubx_bmd380eval/ubx_bmd380eval_nrf52840.yaml @@ -17,7 +17,6 @@ supported: - pwm - spi - qspi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/u-blox/ubx_evkninab3/ubx_evkninab3_nrf52840.yaml b/boards/u-blox/ubx_evkninab3/ubx_evkninab3_nrf52840.yaml index 90d292bc049e8..6e01ef035e8ee 100644 --- a/boards/u-blox/ubx_evkninab3/ubx_evkninab3_nrf52840.yaml +++ b/boards/u-blox/ubx_evkninab3/ubx_evkninab3_nrf52840.yaml @@ -18,7 +18,6 @@ supported: - i2c - pwm - spi - - usb_cdc - usb_device - watchdog - netif:openthread diff --git a/boards/up-bridge-the-gap/up_squared/Kconfig.defconfig b/boards/up-bridge-the-gap/up_squared/Kconfig.defconfig index 78d041976f1ab..9c721cfcc320b 100644 --- a/boards/up-bridge-the-gap/up_squared/Kconfig.defconfig +++ b/boards/up-bridge-the-gap/up_squared/Kconfig.defconfig @@ -18,6 +18,8 @@ config SYS_CLOCK_HW_CYCLES_PER_SEC if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/boards/up-bridge-the-gap/up_squared/up_squared.dts b/boards/up-bridge-the-gap/up_squared/up_squared.dts index beb83af8b1996..2e8e763115f60 100644 --- a/boards/up-bridge-the-gap/up_squared/up_squared.dts +++ b/boards/up-bridge-the-gap/up_squared/up_squared.dts @@ -25,7 +25,7 @@ zephyr,sram = &dram0; zephyr,console = &uart0; zephyr,shell-uart = &uart0; - zephyr,bt-uart = &uart1; + zephyr,bt-hci = &bt_hci_uart; zephyr,uart-pipe = &uart1; zephyr,bt-mon-uart = &uart1; }; @@ -49,3 +49,10 @@ }; }; }; + +&uart1 { + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; + }; +}; diff --git a/boards/up-bridge-the-gap/up_squared_pro_7000/Kconfig.defconfig b/boards/up-bridge-the-gap/up_squared_pro_7000/Kconfig.defconfig index 84744a7ea3af4..e7c98f9eddf5d 100644 --- a/boards/up-bridge-the-gap/up_squared_pro_7000/Kconfig.defconfig +++ b/boards/up-bridge-the-gap/up_squared_pro_7000/Kconfig.defconfig @@ -19,6 +19,8 @@ if APIC_TIMER config APIC_TIMER_IRQ default 24 +endif +if APIC_TIMER_TSC config APIC_TIMER_TSC_M default 3 config APIC_TIMER_TSC_N diff --git a/boards/vcc-gnd/yd_esp32/Kconfig.defconfig b/boards/vcc-gnd/yd_esp32/Kconfig.defconfig index 9b7b408dbef2d..2ca1ba1903658 100644 --- a/boards/vcc-gnd/yd_esp32/Kconfig.defconfig +++ b/boards/vcc-gnd/yd_esp32/Kconfig.defconfig @@ -12,10 +12,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_YD_ESP32_ESP32_PROCPU if BOARD_YD_ESP32_ESP32_APPCPU diff --git a/boards/vcc-gnd/yd_esp32/doc/index.rst b/boards/vcc-gnd/yd_esp32/doc/index.rst index 433c1ac0c30ba..236d076dfcb3a 100644 --- a/boards/vcc-gnd/yd_esp32/doc/index.rst +++ b/boards/vcc-gnd/yd_esp32/doc/index.rst @@ -61,7 +61,6 @@ Current Zephyr's YD-ESP32 board supports the following features: +------------+------------+-------------------------------------+ | Interface | Controller | Driver/Component | +============+============+=====================================+ -+------------+------------+-------------------------------------+ | UART | on-chip | serial port | +------------+------------+-------------------------------------+ | GPIO | on-chip | gpio | diff --git a/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.dts b/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.dts index 6bed6d3840294..8501714220d48 100644 --- a/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.dts +++ b/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.dts @@ -18,14 +18,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &ipm0 { status = "okay"; }; diff --git a/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.yaml b/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.yaml index 018b3c2b72732..20e2f1a74c6f8 100644 --- a/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.yaml +++ b/boards/vcc-gnd/yd_esp32/yd_esp32_appcpu.yaml @@ -1,5 +1,5 @@ identifier: yd_esp32/esp32/appcpu -name: ESP32 DEVKITC WROVER APPCPU +name: YD-ESP32 APPCPU type: mcu arch: xtensa toolchain: diff --git a/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.dts b/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.dts index 2e748af71b98d..a409ed6e90962 100644 --- a/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.dts +++ b/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.dts @@ -35,6 +35,7 @@ zephyr,shell-uart = &uart0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; + zephyr,bt-hci = &esp32_bt_hci; }; }; @@ -47,15 +48,6 @@ }; }; -&cpu0 { - clock-frequency = ; - cpu-power-states = <&light_sleep &deep_sleep>; -}; - -&cpu1 { - clock-frequency = ; -}; - &uart0 { status = "okay"; current-speed = <115200>; @@ -182,3 +174,7 @@ }; }; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.yaml b/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.yaml index b3fc0cdf97d1a..7e8e17cf71f08 100644 --- a/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.yaml +++ b/boards/vcc-gnd/yd_esp32/yd_esp32_procpu.yaml @@ -1,5 +1,5 @@ identifier: yd_esp32/esp32/procpu -name: YD-ESP32 +name: YD-ESP32 PROCPU type: mcu arch: xtensa toolchain: diff --git a/boards/waveshare/esp32s3_touch_lcd_1_28/Kconfig.defconfig b/boards/waveshare/esp32s3_touch_lcd_1_28/Kconfig.defconfig index 33296a8e529bb..06c61c850aa11 100644 --- a/boards/waveshare/esp32s3_touch_lcd_1_28/Kconfig.defconfig +++ b/boards/waveshare/esp32s3_touch_lcd_1_28/Kconfig.defconfig @@ -10,10 +10,6 @@ config HEAP_MEM_POOL_ADD_SIZE_BOARD default 40960 if BT default 4096 -choice BT_HCI_BUS_TYPE - default BT_ESP32 if BT -endchoice - endif # BOARD_ESP32S3_TOUCH_LCD_1_28_ESP32S3_PROCPU if BOARD_ESP32S3_TOUCH_LCD_1_28_ESP32S3_APPCPU diff --git a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.dts b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.dts index 50301f22c2088..9b345338aa41c 100644 --- a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.dts +++ b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.dts @@ -15,14 +15,6 @@ }; }; -&cpu0 { - clock-frequency = ; -}; - -&cpu1 { - clock-frequency = ; -}; - &flash0 { status = "okay"; reg = <0x0 DT_SIZE_M(16)>; diff --git a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.yaml b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.yaml index bd677cef701c1..c42258133ae27 100644 --- a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.yaml +++ b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_appcpu.yaml @@ -5,18 +5,23 @@ arch: xtensa toolchain: - zephyr supported: - - gpio - - i2c - - spi - - watchdog - - regulator - uart - - pwm - - pinmux - - nvs - - display testing: ignore_tags: - net - bluetooth + - flash + - cpp + - posix + - watchdog + - logging + - kernel + - pm + - gpio + - crypto + - eeprom + - heap + - cmsis_rtos + - jwt + - zdsp vendor: waveshare diff --git a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts index 346c522142f66..cb4bd891f611f 100644 --- a/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts +++ b/boards/waveshare/esp32s3_touch_lcd_1_28/esp32s3_touch_lcd_1_28_esp32s3_procpu.dts @@ -30,6 +30,7 @@ zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; zephyr,display = &gc9a01; + zephyr,bt-hci = &esp32_bt_hci; }; /* Buttons */ @@ -55,14 +56,28 @@ pwms = <&ledc0 0 PWM_HZ(250) PWM_POLARITY_NORMAL>; }; }; -}; - -&cpu0 { - clock-frequency = ; -}; -&cpu1 { - clock-frequency = ; + /* MIPI DBI */ + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi2>; + dc-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + write-only; + #address-cells = <1>; + #size-cells = <0>; + + gc9a01: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + mipi-max-frequency = <100000000>; + pixel-format = ; + display-inversion; + width = <240>; + height = <240>; + }; + }; }; &flash0 { @@ -153,19 +168,6 @@ pinctrl-0 = <&spim2_default>; pinctrl-names = "default"; cs-gpios = <&gpio0 9 GPIO_ACTIVE_LOW>; - - gc9a01: gc9a01@0 { - status = "okay"; - compatible = "galaxycore,gc9x01x"; - reg = <0>; - spi-max-frequency = <100000000>; - cmd-data-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; - reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; - pixel-format = ; - display-inversion; - width = <240>; - height = <240>; - }; }; &trng0 { @@ -182,3 +184,7 @@ &wdt0 { status = "okay"; }; + +&esp32_bt_hci { + status = "okay"; +}; diff --git a/boards/waveshare/open103z/waveshare_open103z.dts b/boards/waveshare/open103z/waveshare_open103z.dts index 6d2e47595488c..72dd744c4c21b 100644 --- a/boards/waveshare/open103z/waveshare_open103z.dts +++ b/boards/waveshare/open103z/waveshare_open103z.dts @@ -156,7 +156,6 @@ * reference: RM0008 rev20 page 205 */ status = "disabled"; - bus-speed = <125000>; }; zephyr_udc0: &usb { diff --git a/boards/weact/mini_stm32h743/mini_stm32h743.dts b/boards/weact/mini_stm32h743/mini_stm32h743.dts index 9aa6dcffc1b1e..9968b82d7d7b4 100644 --- a/boards/weact/mini_stm32h743/mini_stm32h743.dts +++ b/boards/weact/mini_stm32h743/mini_stm32h743.dts @@ -8,6 +8,7 @@ #include #include #include +#include / { model = "WeAct Studio MiniSTM32H743 Core Board"; @@ -18,7 +19,7 @@ zephyr,shell-uart = &usb_cdc_acm_uart; zephyr,sram = &sram0; zephyr,flash = &flash0; - zephyr,display = &st7735r_tft; + zephyr,display = &st7735r_160x80; }; leds { @@ -38,10 +39,47 @@ }; }; + mipi_dbi_st7735r_160x80 { + compatible = "zephyr,mipi-dbi-spi"; + spi-dev = <&spi4>; + dc-gpios = <&gpioe 13 GPIO_ACTIVE_HIGH>; + #address-cells = <1>; + #size-cells = <0>; + + st7735r_160x80: st7735r@0 { + compatible = "sitronix,st7735r"; + mipi-max-frequency = <20000000>; + mipi-mode = ; + reg = <0>; + width = <160>; + height = <80>; + inversion-on; + rgb-is-inverted; + x-offset = <1>; + y-offset = <26>; + pwctr1 = [A2 02 84]; + pwctr2 = [C5]; + pwctr3 = [0A 00]; + pwctr4 = [8A 2A]; + pwctr5 = [8A EE]; + invctr = <7>; + frmctr1 = [01 2C 2D]; + frmctr2 = [01 2C 2D]; + frmctr3 = [01 2C 2D 01 2C 2D]; + vmctr1 = <14>; + gamctrp1 = [02 1C 07 12 37 32 29 2D 29 25 2B 39 00 01 03 10]; + gamctrn1 = [03 1D 07 06 2E 2C 29 2D 2E 2E 37 3F 00 00 02 10]; + colmod = <5>; + /* Set D3 (RGB) bit to 1. LV_COLOR_16_SWAP is enabled by default */ + madctl = <120>; /* Set to <184> to rotate the image 180 degrees. */ + caset = [00 01 00 a0]; + raset = [00 1a 00 69]; + }; + }; + aliases { led0 = &user_led; sw0 = &user_button; - spi-flash0 = &w25q64_spi; watchdog0 = &iwdg; sdhc0 = &sdmmc1; }; @@ -154,42 +192,21 @@ zephyr_udc0: &usbotg_fs { }; }; +&gpioe { + status = "okay"; + + lcd_led { + gpio-hog; + gpios = <10 GPIO_ACTIVE_LOW>; + output-high; + }; +}; + &spi4 { pinctrl-0 = <&spi4_sck_pe12 &spi4_mosi_pe14>; cs-gpios = <&gpioe 11 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; status = "okay"; - - st7735r_tft: st7735r@0 { - compatible = "sitronix,st7735r"; - spi-max-frequency = <20000000>; - reg = <0>; - cmd-data-gpios = <&gpioe 13 GPIO_ACTIVE_LOW>; - reset-gpios = <&gpioe 10 GPIO_ACTIVE_HIGH>; - width = <160>; - height = <80>; - inversion-on; - rgb-is-inverted; - x-offset = <1>; - y-offset = <26>; - pwctr1 = [A2 02 84]; - pwctr2 = [C5]; - pwctr3 = [0A 00]; - pwctr4 = [8A 2A]; - pwctr5 = [8A EE]; - invctr = <7>; - frmctr1 = [01 2C 2D]; - frmctr2 = [01 2C 2D]; - frmctr3 = [01 2C 2D 01 2C 2D]; - vmctr1 = <14>; - gamctrp1 = [02 1C 07 12 37 32 29 2D 29 25 2B 39 00 01 03 10]; - gamctrn1 = [03 1D 07 06 2E 2C 29 2D 2E 2E 37 3F 00 00 02 10]; - colmod = <5>; - /* Set D3 (RGB) bit to 1. LV_COLOR_16_SWAP is enabled by default in Kconfig */ - madctl = <120>; /* Set to <184> to rotate the image 180 degrees. */ - caset = [00 01 00 a0]; - raset = [00 1a 00 69]; - }; }; &rng { diff --git a/boards/weact/mini_stm32h743/mini_stm32h743.yaml b/boards/weact/mini_stm32h743/mini_stm32h743.yaml index 0ce1024b6d08b..b92c045ee2359 100644 --- a/boards/weact/mini_stm32h743/mini_stm32h743.yaml +++ b/boards/weact/mini_stm32h743/mini_stm32h743.yaml @@ -15,6 +15,5 @@ supported: - backup_sram - watchdog - usb - - sdhc - qspi vendor: weact diff --git a/boards/wemos/esp32s2_lolin_mini/esp32s2_lolin_mini.dts b/boards/wemos/esp32s2_lolin_mini/esp32s2_lolin_mini.dts index 53a598ad0ded6..14d6fd4b1d807 100644 --- a/boards/wemos/esp32s2_lolin_mini/esp32s2_lolin_mini.dts +++ b/boards/wemos/esp32s2_lolin_mini/esp32s2_lolin_mini.dts @@ -46,11 +46,6 @@ }; }; -&cpu0 { - clock-frequency = ; - cpu-power-states = <&deep_sleep &light_sleep>; -}; - &uart0 { status = "okay"; current-speed = <115200>; diff --git a/cmake/bintools/bintools_template.cmake b/cmake/bintools/bintools_template.cmake index 4b48ffe005ad1..6fa63080dd921 100644 --- a/cmake/bintools/bintools_template.cmake +++ b/cmake/bintools/bintools_template.cmake @@ -66,6 +66,7 @@ # elfconvert_flag_final : Flags that must always be applied last at the elfconvert command # elfconvert_flag_strip_all : Flag that is used for stripping all symbols when converting # elfconvert_flag_strip_debug : Flag that is used to strip debug symbols when converting +# elfconvert_flag_compress_debug_sections: Flag that is used to compress debug sections when converting # elfconvert_flag_intarget : Flag for specifying target used for infile # elfconvert_flag_outtarget : Flag for specifying target to use for converted file. # Target value must be one of those listed described by: elfconvert_formats @@ -141,6 +142,7 @@ set_property(TARGET bintools PROPERTY elfconvert_command ${CMAKE_COMMAND} -E ech set_property(TARGET bintools PROPERTY elfconvert_formats "") set_property(TARGET bintools PROPERTY elfconvert_flag "") set_property(TARGET bintools PROPERTY elfconvert_flag_final "") +set_property(TARGET bintools PROPERTY elfconvert_flag_compress_debug_sections "") set_property(TARGET bintools PROPERTY elfconvert_flag_outtarget "") set_property(TARGET bintools PROPERTY elfconvert_flag_section_remove "") set_property(TARGET bintools PROPERTY elfconvert_flag_gapfill "") diff --git a/cmake/bintools/gnu/target_bintools.cmake b/cmake/bintools/gnu/target_bintools.cmake index 8aac55b0400cd..f61860b31da55 100644 --- a/cmake/bintools/gnu/target_bintools.cmake +++ b/cmake/bintools/gnu/target_bintools.cmake @@ -7,6 +7,7 @@ # elfconvert_flag_final : empty # elfconvert_flag_strip_all : -S # elfconvert_flag_strip_debug : -g +# elfconvert_flag_compress_debug_sections: --compress-debug-sections # elfconvert_flag_intarget : --input-target= # elfconvert_flag_outtarget : --output-target= # elfconvert_flag_section_remove: --remove-section= @@ -34,6 +35,8 @@ set_property(TARGET bintools PROPERTY elfconvert_flag_final "") set_property(TARGET bintools PROPERTY elfconvert_flag_strip_all "-S") set_property(TARGET bintools PROPERTY elfconvert_flag_strip_debug "-g") +set_property(TARGET bintools PROPERTY elfconvert_flag_compress_debug_sections "--compress-debug-sections") + set_property(TARGET bintools PROPERTY elfconvert_flag_intarget "--input-target=") set_property(TARGET bintools PROPERTY elfconvert_flag_outtarget "--output-target=") diff --git a/cmake/bintools/llvm/target_bintools.cmake b/cmake/bintools/llvm/target_bintools.cmake index 3a3e04e4388c1..cd3d55342b5d8 100644 --- a/cmake/bintools/llvm/target_bintools.cmake +++ b/cmake/bintools/llvm/target_bintools.cmake @@ -7,6 +7,7 @@ # elfconvert_flag_final : empty # elfconvert_flag_strip_all : -S # elfconvert_flag_strip_debug : -g +# elfconvert_flag_compress_debug_sections: --compress-debug-sections # elfconvert_flag_intarget : --input-target= # elfconvert_flag_outtarget : --output-target= # elfconvert_flag_section_remove: --remove-section= @@ -34,6 +35,8 @@ set_property(TARGET bintools PROPERTY elfconvert_flag_final "") set_property(TARGET bintools PROPERTY elfconvert_flag_strip_all "-S") set_property(TARGET bintools PROPERTY elfconvert_flag_strip_debug "-g") +set_property(TARGET bintools PROPERTY elfconvert_flag_compress_debug_sections "--compress-debug-sections") + set_property(TARGET bintools PROPERTY elfconvert_flag_intarget "--input-target=") set_property(TARGET bintools PROPERTY elfconvert_flag_outtarget "--output-target=") diff --git a/cmake/compiler/clang/target.cmake b/cmake/compiler/clang/target.cmake index d258cdadcf457..ae92664394c75 100644 --- a/cmake/compiler/clang/target.cmake +++ b/cmake/compiler/clang/target.cmake @@ -31,6 +31,8 @@ if(NOT "${ARCH}" STREQUAL "posix") ) include(${ZEPHYR_BASE}/cmake/compiler/clang/target_arm.cmake) + elseif("${ARCH}" STREQUAL "arm64") + include(${ZEPHYR_BASE}/cmake/compiler/clang/target_arm64.cmake) elseif("${ARCH}" STREQUAL "riscv") include(${ZEPHYR_BASE}/cmake/compiler/gcc/target_riscv.cmake) endif() diff --git a/cmake/compiler/clang/target_arm64.cmake b/cmake/compiler/clang/target_arm64.cmake new file mode 100644 index 0000000000000..44933802d0c49 --- /dev/null +++ b/cmake/compiler/clang/target_arm64.cmake @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 +if(DEFINED GCC_M_CPU) + list(APPEND TOOLCHAIN_C_FLAGS -mcpu=${GCC_M_CPU}) + list(APPEND TOOLCHAIN_LD_FLAGS -mcpu=${GCC_M_CPU}) +endif() + +if(DEFINED GCC_M_ARCH) + list(APPEND TOOLCHAIN_C_FLAGS -march=${GCC_M_ARCH}) + list(APPEND TOOLCHAIN_LD_FLAGS -march=${GCC_M_ARCH}) +endif() + +if(DEFINED GCC_M_TUNE) + list(APPEND TOOLCHAIN_C_FLAGS -mtune=${GCC_M_TUNE}) + list(APPEND TOOLCHAIN_LD_FLAGS -mtune=${GCC_M_TUNE}) +endif() diff --git a/cmake/compiler/gcc/target_arm.cmake b/cmake/compiler/gcc/target_arm.cmake index 77a718cc7259f..78e5fc9455034 100644 --- a/cmake/compiler/gcc/target_arm.cmake +++ b/cmake/compiler/gcc/target_arm.cmake @@ -58,3 +58,12 @@ set(LLEXT_APPEND_FLAGS -mlong-calls -mthumb ) + +list(APPEND LLEXT_EDK_REMOVE_FLAGS + --sysroot=.* + -fmacro-prefix-map=.* + ) + +list(APPEND LLEXT_EDK_APPEND_FLAGS + -nodefaultlibs + ) diff --git a/cmake/compiler/host-gcc/target.cmake b/cmake/compiler/host-gcc/target.cmake index 41e36b99a27ab..9bc1d46505749 100644 --- a/cmake/compiler/host-gcc/target.cmake +++ b/cmake/compiler/host-gcc/target.cmake @@ -36,3 +36,12 @@ foreach(file_name include/stddef.h) list(APPEND NOSTDINC ${_OUTPUT}) endforeach() + +list(APPEND LLEXT_EDK_REMOVE_FLAGS + --sysroot=.* + -fmacro-prefix-map=.* + ) + +list(APPEND LLEXT_EDK_APPEND_FLAGS + -nodefaultlibs + ) diff --git a/cmake/compiler/xt-clang/target.cmake b/cmake/compiler/xt-clang/target.cmake index 33b3be758daec..41a72aa782e90 100644 --- a/cmake/compiler/xt-clang/target.cmake +++ b/cmake/compiler/xt-clang/target.cmake @@ -1,3 +1,22 @@ # SPDX-License-Identifier: Apache-2.0 include(${ZEPHYR_BASE}/cmake/compiler/xcc/target.cmake) + +# Flags not supported by llext linker +# (regexps are supported and match whole word) +set(LLEXT_REMOVE_FLAGS + -fno-pic + -fno-pie + -ffunction-sections + -fdata-sections + -g.* + -Os + -mcpu=.* +) + +# Flags to be added to llext code compilation +set(LLEXT_APPEND_FLAGS + -fPIC + -nostdlib + -nodefaultlibs +) diff --git a/cmake/emu/nsim.cmake b/cmake/emu/nsim.cmake index a187cdad03e6f..323593fc1d829 100644 --- a/cmake/emu/nsim.cmake +++ b/cmake/emu/nsim.cmake @@ -13,14 +13,13 @@ if(CONFIG_MP_MAX_NUM_CPUS GREATER 1) set(MULTIFILES ${MDB} -multifiles=) foreach(val RANGE ${CONFIG_MP_MAX_NUM_CPUS}) if(val LESS CONFIG_MP_MAX_NUM_CPUS) - MATH(EXPR PSET_NUM "${CONFIG_MP_MAX_NUM_CPUS}-${val}") - MATH(EXPR CORE_NUM "${CONFIG_MP_MAX_NUM_CPUS}-${val}-1") - if(PSET_NUM GREATER 0) - list(APPEND MDB_OPTIONS &&) - endif() - list(APPEND MDB_OPTIONS ${MDB} -pset=${PSET_NUM} -psetname=core${CORE_NUM}) + MATH(EXPR PSET_NUM "${val}+1") + set(CORE_NUM ${val}) + list(APPEND MDB_OPTIONS && ${MDB} -pset=${PSET_NUM} -psetname=core${CORE_NUM}) if(PSET_NUM GREATER 1) list(APPEND MDB_OPTIONS -prop=download=2) + endif() + if(PSET_NUM LESS ${CONFIG_MP_MAX_NUM_CPUS}) set(MULTIFILES ${MULTIFILES}core${CORE_NUM},) else() set(MULTIFILES ${MULTIFILES}core${CORE_NUM}) diff --git a/cmake/emu/qemu.cmake b/cmake/emu/qemu.cmake index 6103fc1cefc15..0fd445f3c5939 100644 --- a/cmake/emu/qemu.cmake +++ b/cmake/emu/qemu.cmake @@ -100,7 +100,7 @@ endif() # Add a BT serial device when building for bluetooth, unless the # application explicitly opts out with NO_QEMU_SERIAL_BT_SERVER. if(CONFIG_BT) - if(CONFIG_BT_NO_DRIVER) + if(NOT CONFIG_BT_UART) set(NO_QEMU_SERIAL_BT_SERVER 1) endif() if(NOT NO_QEMU_SERIAL_BT_SERVER) diff --git a/cmake/emu/renode.cmake b/cmake/emu/renode.cmake index ab26cfeaf809c..fa99da0f8fd6e 100644 --- a/cmake/emu/renode.cmake +++ b/cmake/emu/renode.cmake @@ -22,40 +22,7 @@ add_custom_target(run_renode COMMAND ${RENODE} ${RENODE_FLAGS} - -e '$$bin=@${APPLICATION_BINARY_DIR}/zephyr/${KERNEL_ELF_NAME}\; include @${RENODE_SCRIPT}\; ${RENODE_OVERLAY} s' - WORKING_DIRECTORY ${APPLICATION_BINARY_DIR} - DEPENDS ${logical_target_for_zephyr_elf} - USES_TERMINAL - ) - -find_program( - RENODE_TEST - renode-test - ) - -set(RENODE_TEST_FLAGS - --variable ELF:@${APPLICATION_BINARY_DIR}/zephyr/${KERNEL_ELF_NAME} - --variable RESC:@${RENODE_SCRIPT} - --variable UART:${RENODE_UART} - --variable KEYWORDS:${ZEPHYR_BASE}/tests/robot/common.robot - --results-dir ${APPLICATION_BINARY_DIR} - ) - -add_custom_target(run_renode_test - COMMAND /bin/sh -c "\ - if [ -z $$ROBOT_FILES ] \;\ - then\ - echo ''\;\ - echo '--- Error: Robot file path is required to run Robot tests in Renode. To provide the path please set the ROBOT_FILES variable.'\;\ - echo '--- To rerun the test with west execute:'\;\ - echo '--- ROBOT_FILES=\\ west build -p -b \\ -s \\ -t run_renode_test'\;\ - echo ''\;\ - exit 1\;\ - fi\;" - COMMAND - ${RENODE_TEST} - ${RENODE_TEST_FLAGS} - ${APPLICATION_SOURCE_DIR}/$$ROBOT_FILES + -e '$$elf=@${PROJECT_BINARY_DIR}/${KERNEL_ELF_NAME}\; include @${RENODE_SCRIPT}\; ${RENODE_OVERLAY} s' WORKING_DIRECTORY ${APPLICATION_BINARY_DIR} DEPENDS ${logical_target_for_zephyr_elf} USES_TERMINAL diff --git a/cmake/flash/CMakeLists.txt b/cmake/flash/CMakeLists.txt index 392274891f196..9c2b18b6e898d 100644 --- a/cmake/flash/CMakeLists.txt +++ b/cmake/flash/CMakeLists.txt @@ -97,6 +97,14 @@ function(create_runners_yaml) runners_yaml_append("\n# Default debug runner if --runner is not given.") runners_yaml_append("debug-runner: ${BOARD_DEBUG_RUNNER}") endif() + if(DEFINED BOARD_SIM_RUNNER) + runners_yaml_append("\n# Default simulation runner if --runner is not given.") + runners_yaml_append("sim-runner: ${BOARD_SIM_RUNNER}") + endif() + if(DEFINED BOARD_ROBOT_RUNNER) + runners_yaml_append("\n# Default test runner if --runner is not given.") + runners_yaml_append("robot-runner: ${BOARD_ROBOT_RUNNER}") + endif() # Sets up common runner configuration values. runners_yaml_append_config() diff --git a/cmake/ide/eclipse_cdt4_generator_amendment.cmake b/cmake/ide/eclipse_cdt4_generator_amendment.cmake index 1bad729118e37..36eca028335d5 100644 --- a/cmake/ide/eclipse_cdt4_generator_amendment.cmake +++ b/cmake/ide/eclipse_cdt4_generator_amendment.cmake @@ -9,7 +9,7 @@ # # Solution: # The amendment function generates a macro header file -# ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h +# ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/cmake_intdef.h # based on INTERFACE_COMPILE_DEFINITIONS and appends the # defines from the file to # CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS. @@ -46,7 +46,7 @@ # CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS. # #3. The amendment function appends the defines from -# ${CMAKE_BINARY_DIR}/zephyr/include/generated/autoconf.h to +# ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/autoconf.h to # CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS. # function(eclipse_cdt4_generator_amendment _param_defs) @@ -88,7 +88,7 @@ else(${_param_defs} EQUAL 1) message(" ${_work_mode}") endif(${_param_defs} EQUAL 1) -set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h) +set(OUTPUT_FILE ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/cmake_intdef.h) file(WRITE ${OUTPUT_FILE} "/* Generated by eclipse_cd4_generator_amendment.cmake */\n") file(APPEND ${OUTPUT_FILE} "/* The header contains the defines collected from the */\n") file(APPEND ${OUTPUT_FILE} "/* INTERFACE_COMPILE_DEFINITIONS target property */\n") @@ -104,7 +104,7 @@ if (${_work_mode} STREQUAL "C and CXX includes, defines in Eclipse with project message(" -------------------------------------------------------------------------") message(" Add the following two command line parameters:") message("") - message(" -imacros ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h") + message(" -imacros ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/cmake_intdef.h") message(" -imacros ${AUTOCONF_H}") message("") message(" to 'CDT cross GCC Built-in Compiler Settings' provider command definition") @@ -125,7 +125,7 @@ if ( (${_work_mode} STREQUAL "C and CXX includes, defines in .settings - [EXPERI file(APPEND ${OUTPUT_FILE} "\t\t\t\n") file(APPEND ${OUTPUT_FILE} "\t\t\t\n") if (${_work_mode} STREQUAL "C and CXX includes, defines in .settings with project defines - [EXPERIMENTAL]") - file(APPEND ${OUTPUT_FILE} "\t\t\t\n") + file(APPEND ${OUTPUT_FILE} "\t\t\t\n") else () file(APPEND ${OUTPUT_FILE} "\t\t\t\n") endif () @@ -167,7 +167,7 @@ if ( (${_work_mode} STREQUAL "C and CXX includes, defines in .cproject without _ endif() - file(STRINGS ${CMAKE_BINARY_DIR}/zephyr/include/generated/cmake_intdef.h _int_comp_def) + file(STRINGS ${CMAKE_BINARY_DIR}/zephyr/include/generated/zephyr/cmake_intdef.h _int_comp_def) set (_resultDefines "${CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS}") foreach( d ${_int_comp_def} ) string(REGEX MATCH "^#define +([A-Za-z_][A-Za-z0-9_]*) *(.*) *$" _dummy "${d}") diff --git a/cmake/kobj.cmake b/cmake/kobj.cmake index dc693509b119d..22fa36ae44af4 100644 --- a/cmake/kobj.cmake +++ b/cmake/kobj.cmake @@ -2,9 +2,9 @@ function(gen_kobj gen_dir_out) if (PROJECT_BINARY_DIR) - set(gen_dir ${PROJECT_BINARY_DIR}/include/generated) + set(gen_dir ${PROJECT_BINARY_DIR}/include/generated/zephyr) else () - set(gen_dir ${CMAKE_BINARY_DIR}/include/generated) + set(gen_dir ${CMAKE_BINARY_DIR}/include/generated/zephyr) endif () set(KOBJ_TYPES ${gen_dir}/kobj-types-enum.h) @@ -30,6 +30,7 @@ function(gen_kobj gen_dir_out) ) add_custom_target(${KOBJ_TYPES_H_TARGET} DEPENDS ${KOBJ_TYPES} ${KOBJ_OTYPE}) + cmake_path(GET gen_dir PARENT_PATH gen_dir) set(${gen_dir_out} ${gen_dir} PARENT_SCOPE) endfunction () diff --git a/cmake/linker/xt-ld/linker_flags.cmake b/cmake/linker/xt-ld/linker_flags.cmake new file mode 100644 index 0000000000000..040b10fe46f20 --- /dev/null +++ b/cmake/linker/xt-ld/linker_flags.cmake @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +set_property(TARGET linker PROPERTY partial_linking "-r") diff --git a/cmake/linker_script/common/common-ram.cmake b/cmake/linker_script/common/common-ram.cmake index 04f6637a9e16a..4e160b58ea6a0 100644 --- a/cmake/linker_script/common/common-ram.cmake +++ b/cmake/linker_script/common/common-ram.cmake @@ -58,10 +58,6 @@ if(CONFIG_SENSING) zephyr_iterable_section(NAME sensing_sensor GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() -if(CONFIG_UART_MUX) - zephyr_iterable_section(NAME uart_mux GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) -endif() - if(CONFIG_USB_DEVICE_STACK) zephyr_linker_section(NAME usb_descriptor GROUP DATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT} SUBALIGN 1) zephyr_linker_section_configure(SECTION usb_descriptor @@ -120,7 +116,7 @@ endif() if(CONFIG_USB_DEVICE_STACK OR CONFIG_USB_DEVICE_STACK_NEXT) zephyr_iterable_section(NAME usb_cfg_data GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) - zephyr_iterable_section(NAME usbd_contex GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) + zephyr_iterable_section(NAME usbd_context GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) zephyr_iterable_section(NAME usbd_class_fs GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) zephyr_iterable_section(NAME usbd_class_hs GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() diff --git a/cmake/linker_script/common/common-rom.cmake b/cmake/linker_script/common/common-rom.cmake index dfd5ba8b9e348..2fd4fcedb4709 100644 --- a/cmake/linker_script/common/common-rom.cmake +++ b/cmake/linker_script/common/common-rom.cmake @@ -8,6 +8,9 @@ zephyr_linker_section_obj_level(SECTION init LEVEL POST_KERNEL) zephyr_linker_section_obj_level(SECTION init LEVEL APPLICATION) zephyr_linker_section_obj_level(SECTION init LEVEL SMP) +zephyr_linker_section(NAME deferred_init_list KVMA RAM_REGION GROUP RODATA_REGION) +zephyr_linker_section_configure(SECTION deferred_init_list INPUT ".z_deferred_init*" KEEP SORT NAME) + zephyr_iterable_section(NAME device NUMERIC KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) if(CONFIG_GEN_SW_ISR_TABLE AND NOT CONFIG_DYNAMIC_INTERRUPTS) @@ -185,6 +188,11 @@ zephyr_iterable_section(NAME tracing_backend KVMA RAM_REGION GROUP RODATA_REGION zephyr_linker_section(NAME zephyr_dbg_info KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT}) zephyr_linker_section_configure(SECTION zephyr_dbg_info INPUT ".zephyr_dbg_info" KEEP) +if(CONFIG_SYMTAB) + zephyr_linker_section(NAME symtab KVMA FLASH GROUP RODATA_REGION SUBALIGN 4 NOINPUT) + zephyr_linker_section_configure(SECTION symtab INPUT ".gnu.linkonce.symtab*") +endif() + if (CONFIG_DEVICE_DEPS) zephyr_linker_section(NAME device_deps KVMA RAM_REGION GROUP RODATA_REGION NOINPUT ${XIP_ALIGN_WITH_INPUT} ENDALIGN 16) zephyr_linker_section_configure(SECTION device_deps INPUT .__device_deps_pass1* KEEP SORT NAME PASS LINKER_DEVICE_DEPS_PASS1) @@ -202,10 +210,22 @@ if (CONFIG_LOG) zephyr_iterable_section(NAME log_backend KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() +if (CONFIG_MULTI_LEVEL_INTERRUPTS) + zephyr_iterable_section(NAME intc_table KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN 4) +endif() + if (CONFIG_HTTP_SERVER) zephyr_iterable_section(NAME http_service_desc KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() +if (CONFIG_COAP_SERVER) + zephyr_iterable_section(NAME coap_service KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +endif() + +if (CONFIG_NET_MGMT) + zephyr_iterable_section(NAME net_mgmt_event_static_handler KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) +endif() + if(CONFIG_INPUT) zephyr_iterable_section(NAME input_callback KVMA RAM_REGION GROUP RODATA_REGION SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) endif() diff --git a/cmake/llext-edk.cmake b/cmake/llext-edk.cmake new file mode 100644 index 0000000000000..73692b8b380b8 --- /dev/null +++ b/cmake/llext-edk.cmake @@ -0,0 +1,198 @@ +# Copyright (c) 2024 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +# This script generates a tarball containing all headers and flags necessary to +# build an llext extension. It does so by copying all headers accessible from +# INTERFACE_INCLUDE_DIRECTORIES and generating a Makefile.cflags file (and a +# cmake.cflags one) with all flags necessary to build the extension. +# +# The tarball can be extracted and used in the extension build system to include +# all necessary headers and flags. File paths are made relative to a few key +# directories (build/zephyr, zephyr base, west top dir and application source +# dir), to avoid leaking any information about the host system. +# +# The following arguments are expected: +# - llext_edk_name: Name of the extension, used to name the tarball and the +# install directory variable for Makefile. +# - INTERFACE_INCLUDE_DIRECTORIES: List of include directories to copy headers +# from. It should simply be the INTERFACE_INCLUDE_DIRECTORIES property of the +# zephyr_interface target. +# - llext_edk_file: Output file name for the tarball. +# - llext_cflags: Additional flags to be added to the generated flags. +# - ZEPHYR_BASE: Path to the zephyr base directory. +# - WEST_TOPDIR: Path to the west top directory. +# - APPLICATION_SOURCE_DIR: Path to the application source directory. +# - PROJECT_BINARY_DIR: Path to the project binary build directory. +# - CONFIG_LLEXT_EDK_USERSPACE_ONLY: Whether to copy syscall headers from the +# edk directory. This is necessary when building an extension that only +# supports userspace, as the syscall headers are regenerated in the edk +# directory. + +cmake_minimum_required(VERSION 3.20.0) + +if (CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) + message(FATAL_ERROR + "The LLEXT EDK is not compatible with CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID.") +endif() + +set(llext_edk ${PROJECT_BINARY_DIR}/${llext_edk_name}) +set(llext_edk_inc ${llext_edk}/include) + +# Usage: +# relative_dir( ) +# +# Helper function to generate relative paths to a few key directories +# (PROJECT_BINARY_DIR, ZEPHYR_BASE, WEST_TOPDIR and APPLICATION_SOURCE_DIR). +# The generated path is relative to the key directory, and the bindir_out +# output variable is set to TRUE if the path is relative to PROJECT_BINARY_DIR. +# +function(relative_dir dir relative_out bindir_out) + cmake_path(IS_PREFIX PROJECT_BINARY_DIR ${dir} NORMALIZE to_prj_bindir) + cmake_path(IS_PREFIX ZEPHYR_BASE ${dir} NORMALIZE to_zephyr_base) + if("${WEST_TOPDIR}" STREQUAL "") + set(to_west_topdir FALSE) + else() + cmake_path(IS_PREFIX WEST_TOPDIR ${dir} NORMALIZE to_west_topdir) + endif() + cmake_path(IS_PREFIX APPLICATION_SOURCE_DIR ${dir} NORMALIZE to_app_srcdir) + + # Overall idea is to place included files in the destination dir based on the source: + # files coming from build/zephyr/generated will end up at + # /include/zephyr/include/generated, files coming from zephyr base at + # /include/zephyr/include, files from west top dir (for instance, hal modules), + # at /include and application ones at /include/. + # Finally, everything else (such as external libs not at any of those places) will end up + # at /include/, so we avoid any external lib + # stepping at any other lib toes. + if(to_prj_bindir) + cmake_path(RELATIVE_PATH dir BASE_DIRECTORY ${PROJECT_BINARY_DIR} OUTPUT_VARIABLE dir_tmp) + set(dest ${llext_edk_inc}/zephyr/${dir_tmp}) + elseif(to_zephyr_base) + cmake_path(RELATIVE_PATH dir BASE_DIRECTORY ${ZEPHYR_BASE} OUTPUT_VARIABLE dir_tmp) + set(dest ${llext_edk_inc}/zephyr/${dir_tmp}) + elseif(to_west_topdir) + cmake_path(RELATIVE_PATH dir BASE_DIRECTORY ${WEST_TOPDIR} OUTPUT_VARIABLE dir_tmp) + set(dest ${llext_edk_inc}/${dir_tmp}) + elseif(to_app_srcdir) + cmake_path(GET APPLICATION_SOURCE_DIR FILENAME app_dir) + cmake_path(RELATIVE_PATH dir BASE_DIRECTORY ${APPLICATION_SOURCE_DIR} OUTPUT_VARIABLE dir_tmp) + set(dest ${llext_edk_inc}/${app_dir}/${dir_tmp}) + else() + set(dest ${llext_edk_inc}/${dir}) + endif() + + set(${relative_out} ${dest} PARENT_SCOPE) + if(to_prj_bindir) + set(${bindir_out} TRUE PARENT_SCOPE) + else() + set(${bindir_out} FALSE PARENT_SCOPE) + endif() +endfunction() + +string(REGEX REPLACE "[^a-zA-Z0-9]" "_" llext_edk_name_sane ${llext_edk_name}) +string(TOUPPER ${llext_edk_name_sane} llext_edk_name_sane) +set(install_dir_var "${llext_edk_name_sane}_INSTALL_DIR") + +separate_arguments(llext_cflags NATIVE_COMMAND ${llext_cflags}) + +set(make_relative FALSE) +foreach(flag ${llext_cflags}) + if (flag STREQUAL "-imacros") + set(make_relative TRUE) + elseif (make_relative) + set(make_relative FALSE) + cmake_path(GET flag PARENT_PATH parent) + cmake_path(GET flag FILENAME name) + relative_dir(${parent} dest bindir) + cmake_path(RELATIVE_PATH dest BASE_DIRECTORY ${llext_edk} OUTPUT_VARIABLE dest_rel) + if(bindir) + list(APPEND imacros_gen_make "-imacros\$(${install_dir_var})/${dest_rel}/${name}") + list(APPEND imacros_gen_cmake "-imacros\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}/${name}") + else() + list(APPEND imacros_make "-imacros\$(${install_dir_var})/${dest_rel}/${name}") + list(APPEND imacros_cmake "-imacros\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}/${name}") + endif() + else() + list(APPEND new_cflags ${flag}) + endif() +endforeach() +set(llext_cflags ${new_cflags}) + + +list(APPEND base_flags_make ${llext_cflags} ${imacros_make}) +list(APPEND base_flags_cmake ${llext_cflags} ${imacros_cmake}) + +separate_arguments(include_dirs NATIVE_COMMAND ${INTERFACE_INCLUDE_DIRECTORIES}) +file(MAKE_DIRECTORY ${llext_edk_inc}) +foreach(dir ${include_dirs}) + if (NOT EXISTS ${dir}) + continue() + endif() + + relative_dir(${dir} dest bindir) + # Use destination parent, as the last part of the source directory is copied as well + cmake_path(GET dest PARENT_PATH dest_p) + + file(MAKE_DIRECTORY ${dest_p}) + file(COPY ${dir} DESTINATION ${dest_p} FILES_MATCHING PATTERN "*.h") + + cmake_path(RELATIVE_PATH dest BASE_DIRECTORY ${llext_edk} OUTPUT_VARIABLE dest_rel) + if(bindir) + list(APPEND inc_gen_flags_make "-I\$(${install_dir_var})/${dest_rel}") + list(APPEND inc_gen_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") + else() + list(APPEND inc_flags_make "-I\$(${install_dir_var})/${dest_rel}") + list(APPEND inc_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") + endif() + list(APPEND all_inc_flags_make "-I\$(${install_dir_var})/${dest_rel}") + list(APPEND all_inc_flags_cmake "-I\${CMAKE_CURRENT_LIST_DIR}/${dest_rel}") +endforeach() + +if(CONFIG_LLEXT_EDK_USERSPACE_ONLY) + # Copy syscall headers from edk directory, as they were regenerated there. + file(COPY ${PROJECT_BINARY_DIR}/edk/include/generated/ DESTINATION ${llext_edk_inc}/zephyr/include/generated) +endif() + +# Generate flags for Makefile +list(APPEND all_flags_make ${base_flags_make} ${imacros_gen_make} ${all_inc_flags_make}) +list(JOIN all_flags_make " " all_flags_str) +file(WRITE ${llext_edk}/Makefile.cflags "LLEXT_CFLAGS = ${all_flags_str}") + +list(JOIN all_inc_flags_make " " all_inc_flags_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_ALL_INCLUDE_CFLAGS = ${all_inc_flags_str}") + +list(JOIN inc_flags_make " " inc_flags_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_INCLUDE_CFLAGS = ${inc_flags_str}") + +list(JOIN inc_gen_flags_make " " inc_gen_flags_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_GENERATED_INCLUDE_CFLAGS = ${inc_gen_flags_str}") + +list(JOIN base_flags_make " " base_flags_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_BASE_CFLAGS = ${base_flags_str}") + +list(JOIN imacros_gen_make " " imacros_gen_str) +file(APPEND ${llext_edk}/Makefile.cflags "\n\nLLEXT_GENERATED_IMACROS_CFLAGS = ${imacros_gen_str}") + +# Generate flags for CMake +list(APPEND all_flags_cmake ${base_flags_cmake} ${imacros_gen_cmake} ${all_inc_flags_cmake}) +file(WRITE ${llext_edk}/cmake.cflags "set(LLEXT_CFLAGS ${all_flags_cmake})") + +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_ALL_INCLUDE_CFLAGS ${all_inc_flags_cmake})") + +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_INCLUDE_CFLAGS ${inc_flags_cmake})") + +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_GENERATED_INCLUDE_CFLAGS ${inc_gen_flags_cmake})") + +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_BASE_CFLAGS ${base_flags_cmake})") + +file(APPEND ${llext_edk}/cmake.cflags "\n\nset(LLEXT_GENERATED_IMACROS_CFLAGS ${imacros_gen_cmake})") + +# Generate the tarball +file(ARCHIVE_CREATE + OUTPUT ${llext_edk_file} + PATHS ${llext_edk} + FORMAT gnutar + COMPRESSION XZ +) + +file(REMOVE_RECURSE ${llext_edk}) diff --git a/cmake/modules/basic_settings.cmake b/cmake/modules/basic_settings.cmake index 54bbffe79390a..ed947a4fb090b 100644 --- a/cmake/modules/basic_settings.cmake +++ b/cmake/modules/basic_settings.cmake @@ -23,7 +23,7 @@ include_guard(GLOBAL) if(SYSBUILD) add_custom_target(sysbuild_cache) - file(STRINGS "${SYSBUILD_CACHE}" sysbuild_cache_strings) + file(STRINGS "${SYSBUILD_CACHE}" sysbuild_cache_strings ENCODING UTF-8) foreach(str ${sysbuild_cache_strings}) # Using a regex for matching whole 'VAR_NAME:TYPE=VALUE' will strip semi-colons # thus resulting in lists to become strings. diff --git a/cmake/modules/boards.cmake b/cmake/modules/boards.cmake index ec9b6579146c0..d2c0666f2c576 100644 --- a/cmake/modules/boards.cmake +++ b/cmake/modules/boards.cmake @@ -136,7 +136,7 @@ foreach(root ${BOARD_ROOT}) message(WARNING "BOARD_ROOT element without a 'boards' subdirectory: ${root} Hints: - - if your board directory is '/foo/bar/boards//my_board' then add '/foo/bar' to BOARD_ROOT, not the entire board directory + - if your board directory is '/foo/bar/boards/my_board' then add '/foo/bar' to BOARD_ROOT, not the entire board directory - if in doubt, use absolute paths") endif() endforeach() diff --git a/cmake/modules/configuration_files.cmake b/cmake/modules/configuration_files.cmake index 2bd843a0d8da4..84af8c5b6353e 100644 --- a/cmake/modules/configuration_files.cmake +++ b/cmake/modules/configuration_files.cmake @@ -30,17 +30,10 @@ include(extensions) # Merge in variables from other sources (e.g. sysbuild) zephyr_get(FILE_SUFFIX SYSBUILD GLOBAL) -zephyr_get(APPLICATION_CONFIG_DIR) -if(DEFINED APPLICATION_CONFIG_DIR) - string(CONFIGURE ${APPLICATION_CONFIG_DIR} APPLICATION_CONFIG_DIR) - if(NOT IS_ABSOLUTE ${APPLICATION_CONFIG_DIR}) - get_filename_component(APPLICATION_CONFIG_DIR ${APPLICATION_CONFIG_DIR} ABSOLUTE) - endif() -else() - # Application config dir is not set, so we default to the application - # source directory as configuration directory. - set(APPLICATION_CONFIG_DIR ${APPLICATION_SOURCE_DIR}) -endif() +zephyr_get(APPLICATION_CONFIG_DIR SYSBUILD GLOBAL) +zephyr_file(APPLICATION_ROOT APPLICATION_CONFIG_DIR) +set_ifndef(APPLICATION_CONFIG_DIR ${APPLICATION_SOURCE_DIR}) +string(CONFIGURE ${APPLICATION_CONFIG_DIR} APPLICATION_CONFIG_DIR) zephyr_get(CONF_FILE SYSBUILD LOCAL) if(NOT DEFINED CONF_FILE) @@ -63,7 +56,7 @@ else() endif() endif() -set(APPLICATION_CONFIG_DIR ${APPLICATION_CONFIG_DIR} CACHE INTERNAL "The application configuration folder" FORCE) +set(APPLICATION_CONFIG_DIR ${APPLICATION_CONFIG_DIR} CACHE PATH "The application configuration folder" FORCE) set(CONF_FILE ${CONF_FILE} CACHE STRING "If desired, you can build the application using\ the configuration settings specified in an alternate .conf file using this parameter. \ These settings will override the settings in the application’s .config file or its default .conf file.\ diff --git a/cmake/modules/dts.cmake b/cmake/modules/dts.cmake index d1ff4df9bcd62..1cd531b7f3c57 100644 --- a/cmake/modules/dts.cmake +++ b/cmake/modules/dts.cmake @@ -57,8 +57,9 @@ find_package(Dtc 1.4.6) # - ${PROJECT_BINARY_DIR}/zephyr.dts exists # - ${PROJECT_BINARY_DIR}/edt.pickle exists # - ${KCONFIG_BINARY_DIR}/Kconfig.dts exists -# - the build system will be regenerated if any devicetree files -# used in this build change, including transitive includes +# - DTS_INCLUDE_FILES is set to a ;-list of all devicetree files +# used in this build, including transitive includes (the build +# system will be regenerated if any of those files change) # - the devicetree extensions in the extensions.cmake module # will be ready for use in other CMake list files that run # after this module @@ -257,14 +258,14 @@ zephyr_dt_preprocess( # Parse the generated dependency file to find the DT sources that # were included, including any transitive includes. toolchain_parse_make_rule(${DTS_DEPS} - include_files # Output parameter + DTS_INCLUDE_FILES # Output parameter ) # Add the results to the list of files that, when change, force the # build system to re-run CMake. set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS - ${include_files} + ${DTS_INCLUDE_FILES} ${GEN_DEFINES_SCRIPT} ${GEN_DRIVER_KCONFIG_SCRIPT} ${GEN_DTS_CMAKE_SCRIPT} diff --git a/cmake/modules/extensions.cmake b/cmake/modules/extensions.cmake index 35ab0e246b250..ade63dcded718 100644 --- a/cmake/modules/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -37,6 +37,7 @@ include(CheckCXXCompilerFlag) # 7 Linkable loadable extensions (llext) # 7.1 llext_* configuration functions # 7.2 add_llext_* build control functions +# 7.3 llext helper functions ######################################################## # 1. Zephyr-aware extensions @@ -704,9 +705,10 @@ endfunction() # This section provides glue between CMake and the Python code that # manages the runners. +set(TYPES "FLASH" "DEBUG" "SIM" "ROBOT") function(_board_check_runner_type type) # private helper - if (NOT (("${type}" STREQUAL "FLASH") OR ("${type}" STREQUAL "DEBUG"))) - message(FATAL_ERROR "invalid type ${type}; should be FLASH or DEBUG") + if (NOT "${type}" IN_LIST TYPES) + message(FATAL_ERROR "invalid type ${type}; should be one of: ${TYPES}") endif() endfunction() @@ -722,8 +724,8 @@ endfunction() # # This would set the board's flash runner to "pyocd". # -# In general, "type" is FLASH or DEBUG, and "runner" is the name of a -# runner. +# In general, "type" is FLASH, DEBUG, SIM or ROBOT and "runner" is +# the name of a runner. function(board_set_runner type runner) _board_check_runner_type(${type}) if (DEFINED BOARD_${type}_RUNNER) @@ -764,6 +766,16 @@ macro(board_set_debugger_ifnset runner) board_set_runner_ifnset(DEBUG ${runner}) endmacro() +# A convenience macro for board_set_runner_ifnset(ROBOT ${runner}). +macro(board_set_robot_runner_ifnset runner) + board_set_runner_ifnset(ROBOT ${runner}) +endmacro() + +# A convenience macro for board_set_runner_ifnset(SIM ${runner}). +macro(board_set_sim_runner_ifnset runner) + board_set_runner_ifnset(SIM ${runner}) +endmacro() + # This function is intended for board.cmake files and application # CMakeLists.txt files. # @@ -1759,9 +1771,11 @@ function(zephyr_blobs_verify) message(VERBOSE "Verifying blob \"${path}\"") - # Each path that has a correct sha256 is prefixed with an A - if(NOT "A ${path}" IN_LIST BLOBS_LIST) - message(${msg_lvl} "Blob for path \"${path}\" isn't valid.") + if(NOT EXISTS "${path}") + message(${msg_lvl} "Blob for path \"${path}\" missing. Update with: west blobs fetch") + elseif(NOT "A ${path}" IN_LIST BLOBS_LIST) + # Each path that has a correct sha256 is prefixed with an A + message(${msg_lvl} "Blob for path \"${path}\" isn't valid. Update with: west blobs fetch") endif() endforeach() else() @@ -1772,7 +1786,9 @@ function(zephyr_blobs_verify) message(VERBOSE "Verifying blob \"${path}\"") - if(NOT "${status}" STREQUAL "A") + if(NOT EXISTS "${path}") + message(${msg_lvl} "Blob for path \"${path}\" missing. Update with: west blobs fetch ${BLOBS_VERIFY_MODULE}") + elseif(NOT "${status}" STREQUAL "A") message(${msg_lvl} "Blob for path \"${path}\" isn't valid. Update with: west blobs fetch ${BLOBS_VERIFY_MODULE}") endif() endforeach() @@ -2533,6 +2549,8 @@ endfunction() # to absolute path, relative from `APPLICATION_SOURCE_DIR` # Issue an error for any relative path not specified # by user with `-D` +# BASE_DIR : convert paths relative to +# instead of `APPLICATION_SOURCE_DIR` # # returns an updated list of absolute paths # @@ -2586,7 +2604,7 @@ Please provide one of following: APPLICATION_ROOT, CONF_FILES") endif() if(${ARGV0} STREQUAL APPLICATION_ROOT) - set(single_args APPLICATION_ROOT) + set(single_args APPLICATION_ROOT BASE_DIR) elseif(${ARGV0} STREQUAL CONF_FILES) set(options QUALIFIERS REQUIRED) set(single_args BOARD BOARD_REVISION BOARD_QUALIFIERS DTS KCONF DEFCONFIG BUILD SUFFIX) @@ -2599,6 +2617,10 @@ Please provide one of following: APPLICATION_ROOT, CONF_FILES") endif() if(ZFILE_APPLICATION_ROOT) + if(NOT DEFINED ZFILE_BASE_DIR) + set(ZFILE_BASE_DIR ${APPLICATION_SOURCE_DIR}) + endif() + # Note: user can do: `-D=` and app can at same # time specify `list(APPEND )` # Thus need to check and update only CACHED variables (-D). @@ -2608,11 +2630,11 @@ Please provide one of following: APPLICATION_ROOT, CONF_FILES") # `set( CACHE)`, so let's update current scope variable to absolute # path from `APPLICATION_SOURCE_DIR`. if(NOT IS_ABSOLUTE ${path}) - set(abs_path ${APPLICATION_SOURCE_DIR}/${path}) list(FIND ${ZFILE_APPLICATION_ROOT} ${path} index) + cmake_path(ABSOLUTE_PATH path BASE_DIRECTORY ${ZFILE_BASE_DIR} NORMALIZE) if(NOT ${index} LESS 0) list(REMOVE_AT ${ZFILE_APPLICATION_ROOT} ${index}) - list(INSERT ${ZFILE_APPLICATION_ROOT} ${index} ${abs_path}) + list(INSERT ${ZFILE_APPLICATION_ROOT} ${index} ${path}) endif() endif() endforeach() @@ -2629,6 +2651,7 @@ Relative paths are only allowed with `-D${ARGV1}=`") endif() endforeach() + list(REMOVE_DUPLICATES ${ZFILE_APPLICATION_ROOT}) # This updates the provided argument in parent scope (callers scope) set(${ZFILE_APPLICATION_ROOT} ${${ZFILE_APPLICATION_ROOT}} PARENT_SCOPE) endif() @@ -5320,24 +5343,11 @@ function(add_llext_target target_name) set(llext_pkg_output ${LLEXT_OUTPUT}) set(source_files ${LLEXT_SOURCES}) - # Convert the LLEXT_REMOVE_FLAGS list to a regular expression, and use it to - # filter out these flags from the Zephyr target settings - list(TRANSFORM LLEXT_REMOVE_FLAGS - REPLACE "(.+)" "^\\1$" - OUTPUT_VARIABLE llext_remove_flags_regexp - ) - string(REPLACE ";" "|" llext_remove_flags_regexp "${llext_remove_flags_regexp}") - if ("${llext_remove_flags_regexp}" STREQUAL "") - # an empty regexp would match anything, we actually need the opposite - # so set it to match empty strings - set(llext_remove_flags_regexp "^$") - endif() set(zephyr_flags "$" ) - set(zephyr_filtered_flags - "$" - ) + llext_filter_zephyr_flags(LLEXT_REMOVE_FLAGS ${zephyr_flags} + zephyr_filtered_flags) # Compile the source file using current Zephyr settings but a different # set of flags to obtain the desired llext object type. @@ -5384,6 +5394,7 @@ function(add_llext_target target_name) target_compile_definitions(${llext_lib_target} PRIVATE $ + LL_EXTENSION_BUILD ) target_compile_options(${llext_lib_target} PRIVATE ${zephyr_filtered_flags} @@ -5421,6 +5432,23 @@ function(add_llext_target target_name) COMMAND_EXPAND_LISTS ) + # LLEXT ELF processing for importing via SLID + # + # This command must be executed as last step of the packaging process, + # to ensure that the ELF processed for binary generation contains SLIDs. + # If executed too early, it is possible that some tools executed to modify + # the ELF file (e.g., strip) undo the work performed here. + if (CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) + set(slid_inject_cmd + ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/build/llext_inject_slids.py + --elf-file ${llext_pkg_output} + -vvv + ) + else() + set(slid_inject_cmd ${CMAKE_COMMAND} -E true) + endif() + # Type-specific packaging of the built binary file into an .llext file if(CONFIG_LLEXT_TYPE_ELF_OBJECT) @@ -5428,6 +5456,7 @@ function(add_llext_target target_name) add_custom_command( OUTPUT ${llext_pkg_output} COMMAND ${CMAKE_COMMAND} -E copy ${llext_pkg_input} ${llext_pkg_output} + COMMAND ${slid_inject_cmd} DEPENDS ${llext_proc_target} ${llext_pkg_input} ) @@ -5443,6 +5472,7 @@ function(add_llext_target target_name) $${llext_pkg_input} $${llext_pkg_output} $ + COMMAND ${slid_inject_cmd} DEPENDS ${llext_proc_target} ${llext_pkg_input} ) @@ -5457,6 +5487,7 @@ function(add_llext_target target_name) $${llext_pkg_input} $${llext_pkg_output} $ + COMMAND ${slid_inject_cmd} DEPENDS ${llext_proc_target} ${llext_pkg_input} ) @@ -5557,3 +5588,35 @@ function(add_llext_command) COMMAND_EXPAND_LISTS ) endfunction() + +# 7.3 llext helper functions + +# Usage: +# llext_filter_zephyr_flags( ) +# +# Filter out flags from a list of flags. The filter is a list of regular +# expressions that will be used to exclude flags from the input list. +# +# The resulting generator expression will be stored in the variable . +# +# Example: +# llext_filter_zephyr_flags(LLEXT_REMOVE_FLAGS zephyr_flags zephyr_filtered_flags) +# +function(llext_filter_zephyr_flags filter flags outvar) + list(TRANSFORM ${filter} + REPLACE "(.+)" "^\\1$" + OUTPUT_VARIABLE llext_remove_flags_regexp + ) + list(JOIN llext_remove_flags_regexp "|" llext_remove_flags_regexp) + if ("${llext_remove_flags_regexp}" STREQUAL "") + # an empty regexp would match anything, we actually need the opposite + # so set it to match empty strings + set(llext_remove_flags_regexp "^$") + endif() + + set(zephyr_filtered_flags + "$" + ) + + set(${outvar} ${zephyr_filtered_flags} PARENT_SCOPE) +endfunction() diff --git a/cmake/modules/generated_file_directories.cmake b/cmake/modules/generated_file_directories.cmake index 9b18e1794de03..9865296879635 100644 --- a/cmake/modules/generated_file_directories.cmake +++ b/cmake/modules/generated_file_directories.cmake @@ -7,7 +7,7 @@ include_guard(GLOBAL) # # Outcome: # - BINARY_DIR_INCLUDE is set to ${PROJECT_BINARY_DIR}/include -# - BINARY_DIR_INCLUDE_GENERATED is set to ${BINARY_DIR_INCLUDE}/generated +# - BINARY_DIR_INCLUDE_GENERATED is set to ${BINARY_DIR_INCLUDE}/generated/zephyr # - BINARY_DIR_INCLUDE_GENERATED is a directory # # Required variables: @@ -20,5 +20,5 @@ include_guard(GLOBAL) # None set(BINARY_DIR_INCLUDE ${PROJECT_BINARY_DIR}/include) -set(BINARY_DIR_INCLUDE_GENERATED ${BINARY_DIR_INCLUDE}/generated) +set(BINARY_DIR_INCLUDE_GENERATED ${BINARY_DIR_INCLUDE}/generated/zephyr) file(MAKE_DIRECTORY ${BINARY_DIR_INCLUDE_GENERATED}) diff --git a/cmake/modules/kconfig.cmake b/cmake/modules/kconfig.cmake index 01fbdf73f3c06..3f374db5aea1d 100644 --- a/cmake/modules/kconfig.cmake +++ b/cmake/modules/kconfig.cmake @@ -5,10 +5,11 @@ include_guard(GLOBAL) include(extensions) include(python) -# autoconf.h is generated by Kconfig and placed in /zephyr/include/generated/autoconf.h. +# autoconf.h is generated by Kconfig and placed in +# /zephyr/include/generated/autoconf.h. # A project may request a custom location by setting AUTOCONF_H explicitly before # calling 'find_package(Zephyr)' or loading this module. -set_ifndef(AUTOCONF_H ${PROJECT_BINARY_DIR}/include/generated/autoconf.h) +set_ifndef(AUTOCONF_H ${PROJECT_BINARY_DIR}/include/generated/zephyr/autoconf.h) # Re-configure (Re-execute all CMakeLists.txt code) when autoconf.h changes set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${AUTOCONF_H}) @@ -25,13 +26,10 @@ file(MAKE_DIRECTORY ${KCONFIG_BINARY_DIR}) if(HWMv1) # Support multiple SOC_ROOT file(MAKE_DIRECTORY ${KCONFIG_BINARY_DIR}/soc) - set(kconfig_soc_root ${BOARD_ROOT}) + set(kconfig_soc_root ${SOC_ROOT}) list(REMOVE_ITEM kconfig_soc_root ${ZEPHYR_BASE}) set(soc_defconfig_file ${KCONFIG_BINARY_DIR}/soc/Kconfig.defconfig) - # This loads Zephyr base SoC root defconfigs - file(WRITE ${soc_defconfig_file} "osource \"soc/soc_legacy/$(ARCH)/*/Kconfig.defconfig\"\n") - set(OPERATION WRITE) foreach(root ${kconfig_soc_root}) file(APPEND ${soc_defconfig_file} @@ -400,7 +398,7 @@ if(CREATE_NEW_DOTCONFIG) endif() # Read out the list of 'Kconfig' sources that were used by the engine. -file(STRINGS ${PARSED_KCONFIG_SOURCES_TXT} PARSED_KCONFIG_SOURCES_LIST) +file(STRINGS ${PARSED_KCONFIG_SOURCES_TXT} PARSED_KCONFIG_SOURCES_LIST ENCODING UTF-8) # Force CMAKE configure when the Kconfig sources or configuration files changes. foreach(kconfig_input diff --git a/cmake/modules/python.cmake b/cmake/modules/python.cmake index 6fc765f8f58f8..2464bb1517cb3 100644 --- a/cmake/modules/python.cmake +++ b/cmake/modules/python.cmake @@ -25,7 +25,7 @@ if(NOT Python3_EXECUTABLE) # cause just using find_program directly could result in a python2.7 as python, # and not finding a valid python3. foreach(candidate "python" "python3") - find_program(Python3_EXECUTABLE ${candidate}) + find_program(Python3_EXECUTABLE ${candidate} PATHS ENV VIRTUAL_ENV NO_CMAKE_PATH) if(Python3_EXECUTABLE) execute_process (COMMAND "${Python3_EXECUTABLE}" -c "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))" diff --git a/cmake/modules/root.cmake b/cmake/modules/root.cmake index 0f4d5e1437baf..e14b853831f29 100644 --- a/cmake/modules/root.cmake +++ b/cmake/modules/root.cmake @@ -12,6 +12,7 @@ # - SOC_ROOT: CMake list of SoC roots containing SoC implementations # - BOARD_ROOT: CMake list of board roots containing board and shield implementations # - MODULE_EXT_ROOT: CMake list of module external roots containing module glue code +# - SCA_ROOT: CMake list of SCA roots containing static code analysis integration code # # If a root is defined it will check the list of paths in the root and convert # any relative path to absolute path and update the root list. diff --git a/cmake/modules/soc_v1.cmake b/cmake/modules/soc_v1.cmake index 1bba9536c0c21..e2004f322550d 100644 --- a/cmake/modules/soc_v1.cmake +++ b/cmake/modules/soc_v1.cmake @@ -60,9 +60,6 @@ if(HWMv1) if(EXISTS ${root}/soc/${ARCH}/${SOC_PATH}) set(SOC_DIR ${root}/soc) break() - elseif(EXISTS ${root}/soc/soc_legacy/${ARCH}/${SOC_PATH}) - set(SOC_DIR ${root}/soc/soc_legacy) - break() endif() endforeach() diff --git a/cmake/modules/unittest.cmake b/cmake/modules/unittest.cmake index 79e6c269c7ce6..de5b0f3eeb618 100644 --- a/cmake/modules/unittest.cmake +++ b/cmake/modules/unittest.cmake @@ -58,8 +58,30 @@ include(${ZEPHYR_BASE}/cmake/kobj.cmake) add_dependencies(test_interface ${KOBJ_TYPES_H_TARGET}) gen_kobj(KOBJ_GEN_DIR) +# Generates empty header files to build +set(INCL_GENERATED_DIR ${APPLICATION_BINARY_DIR}/zephyr/include/generated/zephyr) +set(INCL_GENERATED_SYSCALL_DIR ${INCL_GENERATED_DIR}/syscalls) +list(APPEND INCL_GENERATED_HEADERS + ${INCL_GENERATED_DIR}/devicetree_generated.h + ${INCL_GENERATED_DIR}/offsets.h + ${INCL_GENERATED_DIR}/syscall_list.h + ${INCL_GENERATED_DIR}/syscall_macros.h + ${INCL_GENERATED_SYSCALL_DIR}/kernel.h + ${INCL_GENERATED_SYSCALL_DIR}/kobject.h + ${INCL_GENERATED_SYSCALL_DIR}/log_core.h + ${INCL_GENERATED_SYSCALL_DIR}/log_ctrl.h + ${INCL_GENERATED_SYSCALL_DIR}/log_msg.h + ${INCL_GENERATED_SYSCALL_DIR}/sys_clock.h +) + +file(MAKE_DIRECTORY ${INCL_GENERATED_SYSCALL_DIR}) +foreach(header ${INCL_GENERATED_HEADERS}) + file(TOUCH ${header}) +endforeach() + list(APPEND INCLUDE subsys/testsuite/ztest/include/zephyr + subsys/testsuite/ztest/unittest/include subsys/testsuite/include/zephyr subsys/testsuite/ztest/include subsys/testsuite/include diff --git a/cmake/toolchain/arcmwdt/Kconfig.defconfig b/cmake/toolchain/arcmwdt/Kconfig.defconfig new file mode 100644 index 0000000000000..78164376629e6 --- /dev/null +++ b/cmake/toolchain/arcmwdt/Kconfig.defconfig @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Synopsys +# SPDX-License-Identifier: Apache-2.0 + +config PICOLIBC_SUPPORTED + default n diff --git a/cmake/toolchain/armclang/Kconfig b/cmake/toolchain/armclang/Kconfig index 27be295057ca9..70b9b2bd15203 100644 --- a/cmake/toolchain/armclang/Kconfig +++ b/cmake/toolchain/armclang/Kconfig @@ -16,7 +16,7 @@ choice LIBC_IMPLEMENTATION config ARMCLANG_STD_LIBC bool "ARM Compiler C library" select COMMON_LIBC_STRNLEN - select COMMON_LIBC_TIME if POSIX_CLOCK + select COMMON_LIBC_TIME if POSIX_TIMERS help Use the full Arm Compiler runtime libraries. A reduced Zephyr minimal libc will be used for library functionality diff --git a/cmake/toolchain/llvm/Kconfig b/cmake/toolchain/llvm/Kconfig index 1886f50cfe51d..00ef90d7da363 100644 --- a/cmake/toolchain/llvm/Kconfig +++ b/cmake/toolchain/llvm/Kconfig @@ -19,7 +19,7 @@ config LLVM_USE_LLD endchoice config TOOLCHAIN_LLVM_SUPPORTS_THREAD_LOCAL_STORAGE - depends on RISCV + depends on RISCV || ARM || ARM64 def_bool y select TOOLCHAIN_SUPPORTS_THREAD_LOCAL_STORAGE diff --git a/cmake/toolchain/llvm/target.cmake b/cmake/toolchain/llvm/target.cmake index 8446e22ced8fb..58c3b8ebbfc4d 100644 --- a/cmake/toolchain/llvm/target.cmake +++ b/cmake/toolchain/llvm/target.cmake @@ -25,6 +25,8 @@ if("${ARCH}" STREQUAL "arm") # Default ARM target supported by all processors. set(triple arm-none-eabi) endif() +elseif("${ARCH}" STREQUAL "arm64") + set(triple aarch64-none-elf) elseif("${ARCH}" STREQUAL "x86") if(CONFIG_64BIT) set(triple x86_64-pc-none-elf) diff --git a/cmake/usage/usage.cmake b/cmake/usage/usage.cmake index 2f4b0b76ddd3b..8ff24025954a1 100644 --- a/cmake/usage/usage.cmake +++ b/cmake/usage/usage.cmake @@ -31,6 +31,7 @@ message(" initlevels - Display the initialization sequence") message(" boards - Display supported boards") message(" shields - Display supported shields") message(" usage - Display this text") +message(" llext-edk - Build the Linkable Loadable Extension (LLEXT) Extension Development Kit (EDK)") message(" help - Display all build system targets") message("") message("Build flags:") diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index 5cfce578a4a9e..e72b7ac229861 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -174,7 +174,7 @@ add_doc_target( -d ${DOCS_DOCTREE_DIR} -w ${DOCS_BUILD_DIR}/latex.log -t ${DOC_TAG} - -t svgconvert + -t convertimages ${SPHINXOPTS} ${SPHINXOPTS_EXTRA} ${DOCS_SRC_DIR} diff --git a/doc/_doxygen/groups.dox b/doc/_doxygen/groups.dox index c0c5ab1a7bec1..69a3b892637b7 100644 --- a/doc/_doxygen/groups.dox +++ b/doc/_doxygen/groups.dox @@ -73,4 +73,9 @@ @{ @} +@brief Memory Management APIs +@defgroup mem_mgmt Memory Management APIs +@{ +@} + */ diff --git a/doc/_scripts/gen_devicetree_rest.py b/doc/_scripts/gen_devicetree_rest.py index dbd6227d972cb..4637aca7ae9d1 100644 --- a/doc/_scripts/gen_devicetree_rest.py +++ b/doc/_scripts/gen_devicetree_rest.py @@ -163,7 +163,7 @@ def init_vnd2ref_target(self): def main(): args = parse_args() setup_logging(args.verbose) - bindings = load_bindings(args.dts_roots) + bindings = load_bindings(args.dts_roots, args.dts_folders) base_binding = load_base_binding() vnd_lookup = VndLookup(args.vendor_prefixes, bindings) dump_content(bindings, base_binding, vnd_lookup, args.out_dir, @@ -180,6 +180,8 @@ def parse_args(): parser.add_argument('--dts-root', dest='dts_roots', action='append', help='''additional DTS root directory as it would be set in DTS_ROOTS''') + parser.add_argument('--dts-folder', dest='dts_folders', action='append', default=[], + help='additional DTS folders containing binding files') parser.add_argument('--turbo-mode', action='store_true', help='Enable turbo mode (dummy references)') parser.add_argument('out_dir', help='output files are generated here') @@ -196,7 +198,7 @@ def setup_logging(verbose): logging.basicConfig(format='%(filename)s:%(levelname)s: %(message)s', level=log_level) -def load_bindings(dts_roots): +def load_bindings(dts_roots, dts_folders): # Get a list of edtlib.Binding objects from searching 'dts_roots'. if not dts_roots: @@ -208,6 +210,9 @@ def load_bindings(dts_roots): recursive=True)) binding_files.extend(glob.glob(f'{dts_root}/dts/bindings/**/*.yaml', recursive=True)) + for folders in dts_folders: + binding_files.extend(glob.glob(f'{folders}/*.yml', recursive=False)) + binding_files.extend(glob.glob(f'{folders}/*.yaml', recursive=False)) bindings = edtlib.bindings_from_paths(binding_files, ignore_errors=True) @@ -322,7 +327,9 @@ def write_bindings_rst(vnd_lookup, out_dir): .. rst-class:: rst-columns ''', string_io) - for vnd in vnd_lookup.vnd2bindings: + for vnd, bindings in vnd_lookup.vnd2bindings.items(): + if len(bindings) == 0: + continue print(f'- :ref:`{vnd_lookup.target(vnd)}`', file=string_io) print_block('''\ @@ -358,6 +365,9 @@ def write_bindings_rst(vnd_lookup, out_dir): title += f' ({vnd})' underline = '=' * len(title) + if len(bindings) == 0: + continue + print_block(f'''\ .. _{vnd_lookup.target(vnd)}: diff --git a/doc/_scripts/redirects.py b/doc/_scripts/redirects.py index bf4f9262749a2..8b2d5e65626d2 100644 --- a/doc/_scripts/redirects.py +++ b/doc/_scripts/redirects.py @@ -143,6 +143,7 @@ ('guides/west/workspaces', 'develop/west/workspaces'), ('guides/west/zephyr-cmds', 'develop/west/zephyr-cmds'), ('guides/zephyr_cmake_package', 'build/zephyr_cmake_package'), + ('hardware/peripherals/sensor', 'hardware/peripherals/sensor/index'), ('reference/api/api_lifecycle', 'develop/api/api_lifecycle'), ('reference/api/index', 'develop/api/index'), ('reference/api/overview', 'develop/api/overview'), @@ -199,6 +200,14 @@ ('reference/usermode/overview', 'kernel/usermode/overview'), ('reference/usermode/syscalls', 'kernel/usermode/syscalls'), ('reference/util/index', 'kernel/util/index'), + ('samples/application_development/with_mcuboot/README', 'samples/sysbuild/with_mcuboot/README'), + ('samples/bluetooth/broadcast_audio_assistant/README', 'samples/bluetooth/bap_broadcast_assistant/README'), + ('samples/bluetooth/broadcast_audio_sink/README', 'samples/bluetooth/bap_broadcast_sink/README'), + ('samples/bluetooth/broadcast_audio_source/README', 'samples/bluetooth/bap_broadcast_source/README'), + ('samples/bluetooth/public_broadcast_sink/README', 'samples/bluetooth/pbp_public_broadcast_sink/README'), + ('samples/bluetooth/public_broadcast_source/README', 'samples/bluetooth/pbp_public_broadcast_source/README'), + ('samples/bluetooth/unicast_audio_client/README', 'samples/bluetooth/bap_unicast_client/README'), + ('samples/bluetooth/unicast_audio_server/README', 'samples/bluetooth/bap_unicast_server/README'), ('samples/drivers/adc/README', 'samples/drivers/adc/adc_dt/README'), ('samples/drivers/kscan_touch', 'samples/subsys/input/input'), ('samples/drivers/led_apa102/README', 'samples/drivers/led_strip/README'), diff --git a/doc/build/cmake/index.rst b/doc/build/cmake/index.rst index 534c3ff34e106..ee9bde7206ff8 100644 --- a/doc/build/cmake/index.rst +++ b/doc/build/cmake/index.rst @@ -88,7 +88,7 @@ Devicetree The preprocessed devicetree sources are parsed by :zephyr_file:`gen_defines.py ` to generate a - :file:`build/zephyr/include/generated/devicetree_generated.h` header with + :file:`build/zephyr/include/generated/zephyr/devicetree_generated.h` header with preprocessor macros. Source code should access preprocessor macros generated from devicetree by diff --git a/doc/build/dts/api/api.rst b/doc/build/dts/api/api.rst index 44b87653cc3fe..e76ad997fb519 100644 --- a/doc/build/dts/api/api.rst +++ b/doc/build/dts/api/api.rst @@ -386,8 +386,8 @@ device. :ref:`bluetooth-hci-uart-sample` * - zephyr,bt-mon-uart - Sets UART device used for the Bluetooth monitor logging - * - zephyr,bt-uart - - Sets UART device used by Bluetooth + * - zephyr,bt-hci + - Selects the HCI device used by the Bluetooth host stack * - zephyr,canbus - Sets the default CAN controller * - zephyr,ccm diff --git a/doc/build/dts/howtos.rst b/doc/build/dts/howtos.rst index c6ee5a80d3024..8875e9cfc4259 100644 --- a/doc/build/dts/howtos.rst +++ b/doc/build/dts/howtos.rst @@ -42,7 +42,7 @@ CMake prints the input and output file locations like this: -- Found BOARD.dts: .../zephyr/boards/arm/qemu_cortex_m3/qemu_cortex_m3.dts -- Generated zephyr.dts: .../zephyr/build/zephyr/zephyr.dts - -- Generated devicetree_generated.h: .../zephyr/build/zephyr/include/generated/devicetree_generated.h + -- Generated devicetree_generated.h: .../zephyr/build/zephyr/include/generated/zephyr/devicetree_generated.h The :file:`zephyr.dts` file is the final devicetree in DTS format. diff --git a/doc/build/dts/intro-input-output.rst b/doc/build/dts/intro-input-output.rst index 698012d5821fa..d069ae4660c9a 100644 --- a/doc/build/dts/intro-input-output.rst +++ b/doc/build/dts/intro-input-output.rst @@ -129,7 +129,7 @@ These are created in your application's build directory. input to :file:`gen_defines.py` and used to create :file:`zephyr.dts` and :file:`devicetree_generated.h`. -:file:`/zephyr/include/generated/devicetree_generated.h` +:file:`/zephyr/include/generated/zephyr/devicetree_generated.h` The generated macros and additional comments describing the devicetree. Included by ``devicetree.h``. diff --git a/doc/build/dts/macros.bnf b/doc/build/dts/macros.bnf index f42f483887749..f5e676f8f44a3 100644 --- a/doc/build/dts/macros.bnf +++ b/doc/build/dts/macros.bnf @@ -35,6 +35,7 @@ node-macro =/ %s"DT_N" path-id %s"_REG_IDX_" DIGIT %s"_VAL_" ( %s"ADDRESS" / %s"SIZE") node-macro =/ %s"DT_N" path-id %s"_REG_NAME_" dt-name %s"_VAL_" ( %s"ADDRESS" / %s"SIZE") +node-macro =/ %s"DT_N" path-id %s"_REG_NAME_" dt-name "_EXISTS" ; The interrupts property is also special. node-macro =/ %s"DT_N" path-id %s"_IRQ_NUM" node-macro =/ %s"DT_N" path-id %s"_IRQ_LEVEL" @@ -73,6 +74,9 @@ node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM" node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM_SEP" node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM_VARGS" node-macro =/ %s"DT_N" path-id %s"_P_" prop-id %s"_FOREACH_PROP_ELEM_SEP_VARGS" +; These are used by DT_CHILD_NUM and DT_CHILD_NUM_STATUS_OKAY macros +node-macro =/ %s"DT_N" path-id %s"_CHILD_NUM" +node-macro =/ %s"DT_N" path-id %s"_CHILD_NUM_STATUS_OKAY" ; These are used internally by DT_FOREACH_CHILD, which iterates over ; each child node. node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD" @@ -85,6 +89,11 @@ node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD_STATUS_OKAY" node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD_STATUS_OKAY_SEP" node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD_STATUS_OKAY_VARGS" node-macro =/ %s"DT_N" path-id %s"_FOREACH_CHILD_STATUS_OKAY_SEP_VARGS" +; These are used internally by DT_FOREACH_NODELABEL and +; DT_FOREACH_NODELABEL_VARGS, which iterate over a node's node labels. +node-macro =/ %s"DT_N" path-id %s"_FOREACH_NODELABEL" [ %s"_VARGS" ] +; These are used internally by DT_NUM_NODELABELS +node-macro =/ %s"DT_N" path-id %s"_NODELABEL_NUM" ; The node's zero-based index in the list of it's parent's child nodes. node-macro =/ %s"DT_N" path-id %s"_CHILD_IDX" ; The node's status macro; dt-name in this case is something like "okay" diff --git a/doc/build/dts/troubleshooting.rst b/doc/build/dts/troubleshooting.rst index 54169b3ab4252..71521a3026bcb 100644 --- a/doc/build/dts/troubleshooting.rst +++ b/doc/build/dts/troubleshooting.rst @@ -66,7 +66,7 @@ Below, ```` means your build directory. To find the devicetree node you need to check, use the number ```` from the linker error. Look for this number in the list of nodes at the top of -:file:`/zephyr/include/generated/devicetree_generated.h`. For example, if +:file:`/zephyr/include/generated/zephyr/devicetree_generated.h`. For example, if ```` is 15, and your :file:`devicetree_generated.h` file looks like this, the node you are interested in is ``/soc/i2c@deadbeef``: diff --git a/doc/build/dts/zephyr_dt_inputs_outputs.svg b/doc/build/dts/zephyr_dt_inputs_outputs.svg index 833353aa654c8..3aace1d0fb8fe 100644 --- a/doc/build/dts/zephyr_dt_inputs_outputs.svg +++ b/doc/build/dts/zephyr_dt_inputs_outputs.svg @@ -1,4 +1,4 @@ -
FILE_1.overlay
...
FILE_n.overlay
FILE_1.overlay...
Devicetree overlays:
optional DTS format files
which override <BOARD>.dts.
Devi...
In board directory.
The "base" devicetree.
Includes SoC .dtsi file,
may include other files.
In...
<BOARD>.dts
<BOARD>.dts
BINDING_1.yaml
...
BINDING_n.yaml
BINDING_1.yaml...
Devicetree bindings:
contain rules for devicetree's
contents.
Devi...
Devicetree scripts in scripts/dts/
Devicetree scri...
Intermediate output in build/zephyr/. C preprocessor output of including <BOARD>.dts and overlays.
Intermediate output in bu...
Generated C header files, in
build/zephyr/include/generated/.

Access these via <devicetree.h>
Gene...
Generated C headers
Generated C headers
zephyr.dts.pre
zephyr.dts.pre
zephyr.dts
zephyr.dts
Final merged devicetree in
build/zephyr/. Useful for debugging. Passed to dtc if it is installed.
Final merged devicetree i...
dtc (optional, just for errors/warnings)
dtc (optional, just...
Viewer does not support full SVG 1.1
\ No newline at end of file +
FILE_1.overlay
...
FILE_n.overlay
FILE_1.overlay...
Devicetree overlays:
optional DTS format files
which override <BOARD>.dts.
Devi...
In board directory.
The "base" devicetree.
Includes SoC .dtsi file,
may include other files.
In...
<BOARD>.dts
<BOARD>.dts
BINDING_1.yaml
...
BINDING_n.yaml
BINDING_1.yaml...
Devicetree bindings:
contain rules for devicetree's
contents.
Devi...
Devicetree scripts in scripts/dts/
Devicetree scri...
Intermediate output in build/zephyr/. C preprocessor output of including <BOARD>.dts and overlays.
Intermediate output in bu...
Generated C header files, in
build/zephyr/include/generated/zephyr/.

Access these via <devicetree.h>
Gene...
Generated C headers
Generated C headers
zephyr.dts.pre
zephyr.dts.pre
zephyr.dts
zephyr.dts
Final merged devicetree in
build/zephyr/. Useful for debugging. Passed to dtc if it is installed.
Final merged devicetree i...
dtc (optional, just for errors/warnings)
dtc (optional, just...
Viewer does not support full SVG 1.1
diff --git a/doc/build/kconfig/setting.rst b/doc/build/kconfig/setting.rst index b938e233f975b..05308589d53f6 100644 --- a/doc/build/kconfig/setting.rst +++ b/doc/build/kconfig/setting.rst @@ -198,6 +198,55 @@ configuration that gets modified when making changes in the :ref:`interactive configuration interfaces `. +Tracking Kconfig symbols +************************ + +It is possible to create Kconfig symbols which takes the default value of +another Kconfig symbol. + +This is valuable when you want a symbol specific to an application or subsystem +but do not want to rely directly on the common symbol. For example, you might +want to decouple the settings so they can be independently configured, or to +ensure you always have a locally named setting, even if the external setting name changes. +is later changed. + +For example, consider the common ``FOO_STRING`` setting where a subsystem wants +to have a ``SUB_FOO_STRING`` but still allow for customization. + +This can be done like this: + +.. code-block:: kconfig + + config FOO_STRING + string "Foo" + default "foo" + + config SUB_FOO_STRING + string "Sub-foo" + default FOO_STRING + +This ensures that the default value of ``SUB_FOO_STRING`` is identical to +``FOO_STRING`` while still allows users to configure both settings +independently. + +It is also possible to make ``SUB_FOO_STRING`` invisible and thereby keep the +two symbols in sync, unless the value of the tracking symbol is changed in a +:file:`defconfig` file. + +.. code-block:: kconfig + + config FOO_STRING + string "Foo" + default "foo" + + config SUB_FOO_STRING + string + default FOO_STRING + help + Hidden symbol which follows FOO_STRING + Can be changed through *.defconfig files. + + Configuring invisible Kconfig symbols ************************************* diff --git a/doc/build/sysbuild/index.rst b/doc/build/sysbuild/index.rst index 295b7767555de..5166e1d44827a 100644 --- a/doc/build/sysbuild/index.rst +++ b/doc/build/sysbuild/index.rst @@ -588,6 +588,8 @@ a Kconfig option, which would make ``my_sample`` conditionally build-only. ``west flash --domain my_sample``. As such, the ``BUILD_ONLY`` option only controls the default behavior of ``west flash``. +.. _sysbuild_application_configuration: + Zephyr application configuration ================================ diff --git a/doc/conf.py b/doc/conf.py index ff54dd2cc490f..a86f09b054234 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -99,9 +99,13 @@ "zephyr.api_overview", ] -# Only use SVG converter when it is really needed, e.g. LaTeX. -if tags.has("svgconvert"): # pylint: disable=undefined-variable +# Only use image conversion when it is really needed, e.g. LaTeX build. +# Ensure "sphinxcontrib.rsvgconverter" is added before "sphinx.ext.imgconverter" +# as it's better at converting SVG with extended features (like the ones from +# draw.io) to PDF format). +if tags.has("convertimages"): # pylint: disable=undefined-variable extensions.append("sphinxcontrib.rsvgconverter") + extensions.append("sphinx.ext.imgconverter") templates_path = ["_templates"] diff --git a/doc/connectivity/bluetooth/api/audio/shell/bap.rst b/doc/connectivity/bluetooth/api/audio/shell/bap.rst index 8d01943eb3b6d..77a44dbd5d7cc 100644 --- a/doc/connectivity/bluetooth/api/audio/shell/bap.rst +++ b/doc/connectivity/bluetooth/api/audio/shell/bap.rst @@ -34,6 +34,7 @@ Commands stream_qos : interval [framing] [latency] [pd] [sdu] [phy] [rtn] qos : Send QoS configure for Unicast Group enable : [context] + connect : Connect the CIS of the stream stop list print_ase_info : Print ASE info for default connection @@ -53,7 +54,7 @@ Commands [pref_ctx ] [stream_ctx ] [program_info ] - [stream_lang ] + [lang ] [ccid_list ] [parental_rating ] [program_info_uri ] @@ -62,10 +63,8 @@ Commands [extended ] [vendor ]] send : Send to Audio Stream [data] - start_sine : Start sending a LC3 encoded sine wave [all] - stop_sine : Stop sending a LC3 encoded sine wave [all] - recv_stats : Sets or gets the receive statistics reporting interval - in # of packets + bap_stats : Sets or gets the statistics reporting interval in # of + packets set_location : set_context : @@ -80,19 +79,19 @@ Commands "config","discover","idle/codec-configured/qos-configured","codec-configured" "qos","config","codec-configured/qos-configured","qos-configured" "enable","qos","qos-configured","enabling" - "[start]","enable","enabling","streaming" + "connect","qos/enable","qos-configured/enabling","qos-configured/enabling" + "[start]","enable/connect","enabling","streaming" "disable","enable", "enabling/streaming","disabling" "[stop]","disable","disabling","qos-configure/idle" "release","config","any","releasing/codec-configure/idle" "list","none","any","none" "select_unicast","none","any","none" - "connect","discover","idle/codec-configured/qos-configured","codec-configured" "send","enable","streaming","none" Example Central *************** -Connect and establish a stream: +Connect and establish a sink stream: .. code-block:: console @@ -104,8 +103,9 @@ Connect and establish a stream: uart:~$ bap config sink 0 uart:~$ bap qos uart:~$ bap enable + uart:~$ bap connect -Or using connect command: +Connect and establish a source stream: .. code-block:: console @@ -113,8 +113,12 @@ Or using connect command: uart:~$ bap init uart:~$ bt connect
uart:~$ gatt exchange-mtu - uart:~$ bap discover sink - uart:~$ bap connect sink 0 + uart:~$ bap discover source + uart:~$ bap config source 0 + uart:~$ bap qos + uart:~$ bap enable + uart:~$ bap connect + uart:~$ bap start Disconnect and release: @@ -332,7 +336,7 @@ any stream previously configured. [pref_ctx ] [stream_ctx ] [program_info ] - [stream_lang ] + [lang ] [ccid_list ] [parental_rating ] [program_info_uri ] @@ -411,7 +415,7 @@ assigned numbers values. 00000000: 08 00 |.. | QoS: interval 10000 framing 0x00 phy 0x02 sdu 80 rtn 2 latency 10 pd 40000 - uart:~$ bap preset sink 32_2_1 config freq 10 meta stream_lang "eng" stream_ctx 4 + uart:~$ bap preset sink 32_2_1 config freq 10 meta lang "eng" stream_ctx 4 32_2_1 codec cfg id 0x06 cid 0x0000 vid 0x0000 count 16 data #0: type 0x01 value_len 1 @@ -479,8 +483,7 @@ parameters. Enable ****** -The :code:`enable` command attempts to enable the stream previously configured, -if the remote peer accepts then the ISO connection procedure is also initiated. +The :code:`enable` command attempts to enable the stream previously configured. .. csv-table:: State Machine Transitions :header: "Depends", "Allowed States", "Next States" @@ -493,17 +496,33 @@ if the remote peer accepts then the ISO connection procedure is also initiated. uart:~$ bap enable [context] uart:~$ bap enable Media +Connect +******* + +The :code:`connect` command attempts to connect the stream previously configured. +Sink streams will have to be started by the unicast server, and source streams will have to be +started by the unicast client. + +.. csv-table:: State Machine Transitions + :header: "Depends", "Allowed States", "Next States" + :widths: auto + + "qos/enable","qos-configured/enabling","qos-configured/enabling" + +.. code-block:: console + + uart:~$ bap connect + Start ***** -The :code:`start` command is only necessary when acting as a sink as it -indicates to the source the stack is ready to start receiving data. +The :code:`start` command is only necessary when starting a source stream. .. csv-table:: State Machine Transitions :header: "Depends", "Allowed States", "Next States" :widths: auto - "enable","enabling","streaming" + "enable/connect","enabling","streaming" .. code-block:: console diff --git a/doc/connectivity/bluetooth/api/audio/shell/cap.rst b/doc/connectivity/bluetooth/api/audio/shell/cap.rst index 0cb65d87f79f0..57dc7e19d83c2 100644 --- a/doc/connectivity/bluetooth/api/audio/shell/cap.rst +++ b/doc/connectivity/bluetooth/api/audio/shell/cap.rst @@ -27,9 +27,9 @@ register callbacks. [rank ] [not-lockable] [sirk ] lock :Lock the set release :Release the set [force] - set_sirk :Set the currently used SIRK + sirk :Set the currently used SIRK get_sirk :Get the currently used SIRK - set_sirk_rsp :Set the response used in SIRK requests Besides initializing the CAS and the CSIS, there are also commands to lock and release the CSIS @@ -45,8 +45,8 @@ clients. .. code-block:: console - uart:~$ cap_acceptor set_sirk 00112233445566778899aabbccddeeff - Set SIRK updated + uart:~$ cap_acceptor sirk 00112233445566778899aabbccddeeff + SIRK updated Getting the current SIRK ------------------------ @@ -56,7 +56,7 @@ This command can get the currently used SIRK. .. code-block:: console uart:~$ cap_acceptor get_sirk - Set SIRK + SIRK 36 04 9a dc 66 3a a1 a1 |6...f:.. 1d 9a 2f 41 01 73 3e 01 |../A.s>. @@ -86,7 +86,7 @@ The CAP initiator also supports broadcast audio as a source. (default 1)] [conns ( | all) (default 1)] unicast_list : Unicast list streams unicast_update : Unicast Update - unicast_stop :Unicast stop streams [stream [stream [stream...]]] (all by default) + unicast_stop : Unicast stop streams [stream [stream [stream...]]] (all by default) unicast_cancel : Unicast cancel current procedure ac_1 : Unicast audio configuration 1 ac_2 : Unicast audio configuration 2 @@ -436,3 +436,18 @@ and index 1 gets the second offset, etc.: AICS inst 0x20014188 state gain 15, mute 0, mode 0 Gain set for inst 0x20014188 Microphone gain change completed + +Starting a broadcast reception +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: console + + uart:~$ bt connect + Connected: + uart:~$ bap_init + uart:~$ cap_commander discover + discovery completed with CSIS + uart:~$ bap_broadcast_assistant discover + BASS discover done with 1 recv states + uart:~$ cap_commander broadcast_reception_start 0 4 + Starting broadcast reception on 1 connection(s) diff --git a/doc/connectivity/bluetooth/api/audio/shell/csip.rst b/doc/connectivity/bluetooth/api/audio/shell/csip.rst index 307eade3999ff..84a11d75081bf 100644 --- a/doc/connectivity/bluetooth/api/audio/shell/csip.rst +++ b/doc/connectivity/bluetooth/api/audio/shell/csip.rst @@ -80,7 +80,7 @@ Discovering sets on a device: bt_csip_set_coordinator.discover_func: Setup complete for 1 / 1 Found 1 sets on device uart:~$ csip_set_coordinator discover_sets - bt_csip_set_coordinator.Set SIRK + bt_csip_set_coordinator.SIRK 36 04 9a dc 66 3a a1 a1 |6...f:.. 1d 9a 2f 41 01 73 3e 01 |../A.s>. bt_csip_set_coordinator.csip_set_coordinator_discover_sets_read_set_size_cb: 2 @@ -109,7 +109,7 @@ Lock set members: bt_csip_set_coordinator.csip_set_coordinator_connected: Connected to 34:02:86:03:86:c0 (public) bt_csip_set_coordinator.discover_func: Setup complete for 1 / 1 bt_csip_set_coordinator.csip_set_coordinator_lock_set_init_cb: - bt_csip_set_coordinator.Set SIRK + bt_csip_set_coordinator.SIRK 36 04 9a dc 66 3a a1 a1 |6...f:.. 1d 9a 2f 41 01 73 3e 01 |../A.s>. bt_csip_set_coordinator.csip_set_coordinator_discover_sets_read_set_size_cb: 2 @@ -149,9 +149,9 @@ Using the Set Member [rank ] [not-lockable] [sirk ] lock :Lock the set release :Release the set [force] - set_sirk :Set the currently used SIRK + sirk :Set the currently used SIRK get_sirk :Get the currently used SIRK - set_sirk_rsp :Set the response used in SIRK requests Example Usage @@ -176,8 +176,8 @@ clients. .. code-block:: console - uart:~$ csip_set_member set_sirk 00112233445566778899aabbccddeeff - Set SIRK updated + uart:~$ csip_set_member sirk 00112233445566778899aabbccddeeff + SIRK updated Getting the current SIRK ------------------------ @@ -187,6 +187,6 @@ This command can get the currently used SIRK. .. code-block:: console uart:~$ csip_set_member get_sirk - Set SIRK + SIRK 36 04 9a dc 66 3a a1 a1 |6...f:.. 1d 9a 2f 41 01 73 3e 01 |../A.s>. diff --git a/doc/connectivity/bluetooth/api/mesh/blob_cli.rst b/doc/connectivity/bluetooth/api/mesh/blob_cli.rst index b4193d5033472..0d533109830ad 100644 --- a/doc/connectivity/bluetooth/api/mesh/blob_cli.rst +++ b/doc/connectivity/bluetooth/api/mesh/blob_cli.rst @@ -33,7 +33,7 @@ Transfer context ================ Both the transfer capabilities retrieval procedure and the BLOB transfer uses an instance of a -:c:type:`bt_mesh_blob_cli_inputs` to determine how to perform the transfer. The BLOB Transfer Client +:c:struct:`bt_mesh_blob_cli_inputs` to determine how to perform the transfer. The BLOB Transfer Client Inputs structure must at least be initialized with a list of targets, an application key and a time to live (TTL) value before it is used in a procedure: diff --git a/doc/connectivity/bluetooth/api/mesh/dfu.rst b/doc/connectivity/bluetooth/api/mesh/dfu.rst index c83377aef85ca..5140d2ae36d65 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu.rst @@ -201,17 +201,17 @@ DFU. Depending on the availability of the Remote Provisioning Server model on th the device may either boot up unprovisioned after applying the new firmware or require to be re-provisioned. The complete list of available options is defined in :c:enum:`bt_mesh_dfu_effect`: -:c:enum:`BT_MESH_DFU_EFFECT_NONE` +:c:enumerator:`BT_MESH_DFU_EFFECT_NONE` The device stays provisioned after the new firmware is programmed. This effect is chosen if the composition data of the new firmware doesn't change. -:c:enum:`BT_MESH_DFU_EFFECT_COMP_CHANGE_NO_RPR` +:c:enumerator:`BT_MESH_DFU_EFFECT_COMP_CHANGE_NO_RPR` This effect is chosen when the composition data changes and the device doesn't support the remote provisioning. The new composition data takes place only after re-provisioning. -:c:enum:`BT_MESH_DFU_EFFECT_COMP_CHANGE` +:c:enumerator:`BT_MESH_DFU_EFFECT_COMP_CHANGE` This effect is chosen when the composition data changes and the device supports the remote provisioning. In this case, the device stays provisioned and the new composition data takes place after re-provisioning using the Remote Provisioning models. -:c:enum:`BT_MESH_DFU_EFFECT_UNPROV` +:c:enumerator:`BT_MESH_DFU_EFFECT_UNPROV` This effect is chosen if the composition data in the new firmware changes, the device doesn't support the remote provisioning, and the new composition data takes effect after applying the firmware. @@ -219,7 +219,7 @@ re-provisioned. The complete list of available options is defined in :c:enum:`bt When the Target node receives the Firmware Update Firmware Metadata Check message, the Firmware Update Server model calls the :c:member:`bt_mesh_dfu_srv_cb.check` callback, the application can then process the metadata and provide the effect value. If the effect is -:c:enum:`BT_MESH_DFU_EFFECT_COMP_CHANGE`, the application must call functions +:c:enumerator:`BT_MESH_DFU_EFFECT_COMP_CHANGE`, the application must call functions :c:func:`bt_mesh_comp_change_prepare` and :c:func:`bt_mesh_models_metadata_change_prepare` to prepare the Composition Data Page and Models Metadata Page contents before applying the new firmware image. See :ref:`bluetooth_mesh_dfu_srv_comp_data_and_models_metadata` for more diff --git a/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst b/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst index 105bdecb86cce..fdccbba639cce 100644 --- a/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst +++ b/doc/connectivity/bluetooth/api/mesh/dfu_srv.rst @@ -45,7 +45,7 @@ firmware image metadata. The Firmware Update Server performs the transfer check :c:member:`check ` callback. The result of the transfer check is a pass/fail status return and the expected -:c:type:`bt_mesh_dfu_effect`. The DFU effect return parameter will be communicated back to the +:c:enum:`bt_mesh_dfu_effect`. The DFU effect return parameter will be communicated back to the Distributor, and should indicate what effect the firmware update will have on the mesh state of the device. diff --git a/doc/connectivity/bluetooth/bluetooth-shell.rst b/doc/connectivity/bluetooth/bluetooth-shell.rst index 0e54ab627c97c..80ae3c35b4335 100644 --- a/doc/connectivity/bluetooth/bluetooth-shell.rst +++ b/doc/connectivity/bluetooth/bluetooth-shell.rst @@ -445,6 +445,95 @@ On device A, you should have received the data: Incoming data channel 0x20000210 len 14 00000000: ff ff ff ff ff ff ff ff ff ff ff ff ff ff |........ ...... | +A2DP +***** +The :code:`a2dp` command exposes parts of the A2DP API. + +The following examples assume that you have two devices already connected. + +Here is a example connecting two devices: + * Source and Sink sides register a2dp callbacks. using :code:`a2dp register_cb`. + * Source and Sink sides register stream endpoints. using :code:`a2dp register_ep source sbc` and :code:`a2dp register_ep sink sbc`. + * Source establish A2dp connection. It will create the AVDTP Signaling and Media L2CAP channels. using :code:`a2dp connect`. + * Source and Sink side can discover remote device's stream endpoints. using :code:`a2dp discover_peer_eps` + * Source or Sink configure the stream to create the stream after discover remote's endpoints. using :code:`a2dp configure`. + * Source or Sink establish the stream. using :code:`a2dp establish`. + * Source or Sink start the media. using :code:`a2dp start`. + * Source test the media sending. using :code:`a2dp send_media` to send one test packet data. + +.. tabs:: + + .. group-tab:: Device A (Audio Source Side) + + .. code-block:: console + + uart:~$ a2dp register_cb + success + uart:~$ a2dp register_ep source sbc + SBC source endpoint is registered + uart:~$ a2dp connect + Bonded with XX:XX:XX:XX:XX:XX + Security changed: XX:XX:XX:XX:XX:XX level 2 + a2dp connected + uart:~$ a2dp discover_peer_eps + endpoint id: 1, (sink), (idle): + codec type: SBC + sample frequency: + 44100 + 48000 + channel mode: + Mono + Stereo + Joint-Stereo + Block Length: + 16 + Subbands: + 8 + Allocation Method: + Loudness + Bitpool Range: 18 - 35 + uart:~$ a2dp configure + success to configure + stream configured + uart:~$ a2dp establish + success to establish + stream established + uart:~$ a2dp start + success to start + stream started + uart:~$ a2dp send_media + frames num: 1, data length: 160 + data: 1, 2, 3, 4, 5, 6 ...... + + .. group-tab:: Device B (Audio Sink Side) + + .. code-block:: console + + uart:~$ a2dp register_cb + success + uart:~$ a2dp register_ep sink sbc + SBC sink endpoint is registered + + Connected: XX:XX:XX:XX:XX:XX + Bonded with XX:XX:XX:XX:XX:XX + Security changed: XX:XX:XX:XX:XX:XX level 2 + a2dp connected + + receive requesting config and accept + SBC configure success + sample rate 44100Hz + stream configured + + receive requesting establishment and accept + stream established + + receive requesting start and accept + stream started + + received, num of frames: 1, data length: 160 + data: 1, 2, 3, 4, 5, 6 ...... + ... + Logging ******* diff --git a/doc/connectivity/networking/api/dhcpv4.rst b/doc/connectivity/networking/api/dhcpv4.rst index e06bcd9182a23..8ded72e0e206c 100644 --- a/doc/connectivity/networking/api/dhcpv4.rst +++ b/doc/connectivity/networking/api/dhcpv4.rst @@ -18,7 +18,7 @@ See this `DHCP Wikipedia article `_ for a detailed overview of how DHCP works. -Note that Zephyr only supports DHCP client functionality. +Note that Zephyr supports both DHCPv4 client and server functionality. Sample usage ************ diff --git a/doc/connectivity/networking/api/dhcpv6.rst b/doc/connectivity/networking/api/dhcpv6.rst new file mode 100644 index 0000000000000..ae6d0c21cd668 --- /dev/null +++ b/doc/connectivity/networking/api/dhcpv6.rst @@ -0,0 +1,26 @@ +.. _dhcpv6_interface: + +DHCPv6 +###### + +.. contents:: + :local: + :depth: 2 + +Overview +******** + +The Dynamic Host Configuration Protocol (DHCP) for IPv6 is a network management protocol +used on IPv6 based networks. A DHCPv6 server dynamically assigns an IPv6 address +and other network configuration parameters to each device on a network so they +can communicate with other IP networks. +See this +`DHCPv6 Wikipedia article `_ +for a detailed overview of how DHCPv6 works. + +Note that Zephyr only supports DHCPv6 client functionality. + +API Reference +************* + +.. doxygengroup:: dhcpv6 diff --git a/doc/connectivity/networking/api/gsm_modem.rst b/doc/connectivity/networking/api/gsm_modem.rst deleted file mode 100644 index cf15e4297968a..0000000000000 --- a/doc/connectivity/networking/api/gsm_modem.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. _gsm_modem: - -Generic GSM Modem -################# - -Overview -******** - -The generic GSM modem driver allows the user to connect Zephyr to a GSM modem -which provides a data connection to cellular operator's network. -The Zephyr uses :ref:`PPP (Point-to-Point Protocol) ` to connect -to the GSM modem using UART. Note that some cellular modems have proprietary -offloading support using AT commands, but usually those modems also support -3GPP standards and provide PPP connection to them. -See :zephyr:code-sample:`GSM modem sample application ` how to setup Zephyr -to use the GSM modem. - -The GSM muxing, that is defined in -`GSM 07.10 `__, -and which allows mixing of AT commands and PPP traffic, is also supported in -this version of Zephyr. One needs to enable :kconfig:option:`CONFIG_GSM_MUX` and -:kconfig:option:`CONFIG_UART_MUX` configuration options to enable muxing. diff --git a/doc/connectivity/networking/api/http.rst b/doc/connectivity/networking/api/http.rst deleted file mode 100644 index d32748e77fae5..0000000000000 --- a/doc/connectivity/networking/api/http.rst +++ /dev/null @@ -1,78 +0,0 @@ -.. _http_interface: - -HTTP client -########### - -.. contents:: - :local: - :depth: 2 - -Overview -******** - -The HTTP client library allows you to send HTTP requests and -parse HTTP responses. The library communicates over the sockets -API but it does not create sockets on its own. -It can be enabled with :kconfig:option:`CONFIG_HTTP_CLIENT` Kconfig option. - -The application must be responsible for creating a socket and passing it to the library. -Therefore, depending on the application's needs, the library can communicate over -either a plain TCP socket (HTTP) or a TLS socket (HTTPS). - -Sample Usage -************ - -The API of the HTTP client library has a single function. - -The following is an example of a request structure created correctly: - -.. code-block:: c - - struct http_request req = { 0 }; - static uint8_t recv_buf[512]; - - req.method = HTTP_GET; - req.url = "/"; - req.host = "localhost"; - req.protocol = "HTTP/1.1"; - req.response = response_cb; - req.recv_buf = recv_buf; - req.recv_buf_len = sizeof(recv_buf); - - /* sock is a file descriptor referencing a socket that has been connected - * to the HTTP server. - */ - ret = http_client_req(sock, &req, 5000, NULL); - -If the server responds to the request, the library provides the response to the -application through the response callback registered in the request structure. -As the library can provide the response in chunks, the application must be able -to process these. - -Together with the structure containing the response data, the callback function -also provides information about whether the library expects to receive more data. - -The following is an example of a very simple response handling function: - -.. code-block:: c - - static void response_cb(struct http_response *rsp, - enum http_final_call final_data, - void *user_data) - { - if (final_data == HTTP_DATA_MORE) { - LOG_INF("Partial data received (%zd bytes)", rsp->data_len); - } else if (final_data == HTTP_DATA_FINAL) { - LOG_INF("All the data received (%zd bytes)", rsp->data_len); - } - - LOG_INF("Response status %s", rsp->http_status); - } - -See :zephyr:code-sample:`HTTP client sample application ` for -more information about the library usage. - -API Reference -************* - -.. doxygengroup:: http_client diff --git a/doc/connectivity/networking/api/http_client.rst b/doc/connectivity/networking/api/http_client.rst new file mode 100644 index 0000000000000..fa7876d841115 --- /dev/null +++ b/doc/connectivity/networking/api/http_client.rst @@ -0,0 +1,78 @@ +.. _http_client_interface: + +HTTP Client +########### + +.. contents:: + :local: + :depth: 2 + +Overview +******** + +The HTTP client library allows you to send HTTP requests and +parse HTTP responses. The library communicates over the sockets +API but it does not create sockets on its own. +It can be enabled with :kconfig:option:`CONFIG_HTTP_CLIENT` Kconfig option. + +The application must be responsible for creating a socket and passing it to the library. +Therefore, depending on the application's needs, the library can communicate over +either a plain TCP socket (HTTP) or a TLS socket (HTTPS). + +Sample Usage +************ + +The API of the HTTP client library has a single function. + +The following is an example of a request structure created correctly: + +.. code-block:: c + + struct http_request req = { 0 }; + static uint8_t recv_buf[512]; + + req.method = HTTP_GET; + req.url = "/"; + req.host = "localhost"; + req.protocol = "HTTP/1.1"; + req.response = response_cb; + req.recv_buf = recv_buf; + req.recv_buf_len = sizeof(recv_buf); + + /* sock is a file descriptor referencing a socket that has been connected + * to the HTTP server. + */ + ret = http_client_req(sock, &req, 5000, NULL); + +If the server responds to the request, the library provides the response to the +application through the response callback registered in the request structure. +As the library can provide the response in chunks, the application must be able +to process these. + +Together with the structure containing the response data, the callback function +also provides information about whether the library expects to receive more data. + +The following is an example of a very simple response handling function: + +.. code-block:: c + + static void response_cb(struct http_response *rsp, + enum http_final_call final_data, + void *user_data) + { + if (final_data == HTTP_DATA_MORE) { + LOG_INF("Partial data received (%zd bytes)", rsp->data_len); + } else if (final_data == HTTP_DATA_FINAL) { + LOG_INF("All the data received (%zd bytes)", rsp->data_len); + } + + LOG_INF("Response status %s", rsp->http_status); + } + +See :zephyr:code-sample:`HTTP client sample application ` for +more information about the library usage. + +API Reference +************* + +.. doxygengroup:: http_client diff --git a/doc/connectivity/networking/api/http_server.rst b/doc/connectivity/networking/api/http_server.rst new file mode 100644 index 0000000000000..11a0ca2080761 --- /dev/null +++ b/doc/connectivity/networking/api/http_server.rst @@ -0,0 +1,321 @@ +.. _http_server_interface: + +HTTP Server +########### + +.. contents:: + :local: + :depth: 2 + +Overview +******** + +Zephyr provides an HTTP server library, which allows to register HTTP services +and HTTP resources associated with those services. The server creates a listening +socket for every registered service, and handles incoming client connections. +It's possible to communicate over a plain TCP socket (HTTP) or a TLS socket (HTTPS). +Both, HTTP/1.1 (RFC 2616) and HTTP/2 (RFC 9113) protocol versions are supported. + +The server operation is generally transparent for the application, running in a +background thread. The application can control the server activity with +respective API functions. + +Certain resource types (for example dynamic resource) provide resource-specific +application callbacks, allowing the server to interact with the application (for +instance provide resource content, or process request payload). + +Currently, the following resource types are supported: + +* Static resources - content defined compile-time, cannot be modified at runtime + (:c:enumerator:`HTTP_RESOURCE_TYPE_STATIC`). + +* Dynamic resources - content provided at runtime by respective application + callback (:c:enumerator:`HTTP_RESOURCE_TYPE_DYNAMIC`). + +* Websocket resources - allowing to establish Websocket connections with the + server (:c:enumerator:`HTTP_RESOURCE_TYPE_WEBSOCKET`). + +Zephyr provides a sample demonstrating HTTP(s) server operation and various +resource types usage. See :zephyr:code-sample:`sockets-http-server` for more +information. + +Server Setup +************ + +A few prerequisites are needed in order to enable HTTP server functionality in +the application. + +First of all, the HTTP server has to be enabled in applications configuration file +with :kconfig:option:`CONFIG_HTTP_SERVER` Kconfig option: + +.. code-block:: cfg + :caption: ``prj.conf`` + + CONFIG_HTTP_SERVER=y + +All HTTP services and HTTP resources are placed in a dedicated linker section. +The linker section for services is predefined locally, however the application +is responsible for defining linker sections for resources associated with +respective services. Linker section names for resources should be prefixed with +``http_resource_desc_``, appended with the service name. + +Linker sections for resources should be defined in a linker file. For example, +for a service named ``my_service``, the linker section shall be defined as follows: + +.. code-block:: c + :caption: ``sections-rom.ld`` + + #include + + ITERABLE_SECTION_ROM(http_resource_desc_my_service, Z_LINK_ITERABLE_SUBALIGN) + +Finally, the linker file and linker section have to be added to your application +using CMake: + +.. code-block:: cmake + :caption: ``CMakeLists.txt`` + + zephyr_linker_sources(SECTIONS sections-rom.ld) + zephyr_linker_section(NAME http_resource_desc_my_service + KVMA RAM_REGION GROUP RODATA_REGION + SUBALIGN Z_LINK_ITERABLE_SUBALIGN) + +.. note:: + + You need to define a separate linker section for each HTTP service + registered in the system. + +Sample Usage +************ + +Services +======== + +The application needs to define an HTTP service (or multiple services), with +the same name as used for the linker section with :c:macro:`HTTP_SERVICE_DEFINE` +macro: + +.. code-block:: c + + #include + + static uint16_t http_service_port = 80; + + HTTP_SERVICE_DEFINE(my_service, "0.0.0.0", &http_service_port, 1, 10, NULL); + +Alternatively, an HTTPS service can be defined with with +:c:macro:`HTTPS_SERVICE_DEFINE`: + +.. code-block:: c + + #include + #include + + #define HTTP_SERVER_CERTIFICATE_TAG 1 + + static uint16_t https_service_port = 443; + static const sec_tag_t sec_tag_list[] = { + HTTP_SERVER_CERTIFICATE_TAG, + }; + + HTTPS_SERVICE_DEFINE(my_service, "0.0.0.0", &https_service_port, 1, 10, + NULL, sec_tag_list, sizeof(sec_tag_list)); + +.. note:: + + HTTPS services rely on TLS credentials being registered in the system. + See :ref:`sockets_tls_credentials_subsys` for information on how to + configure TLS credentials in the system. + +Once HTTP(s) service is defined, resources can be registered for it with +:c:macro:`HTTP_RESOURCE_DEFINE` macro. + +Application can enable resource wildcard support by enabling +:kconfig:option:`CONFIG_HTTP_SERVER_RESOURCE_WILDCARD` option. When this +option is set, then it is possible to match several incoming HTTP requests +with just one resource handler. The `fnmatch() +`__ +POSIX API function is used to match the pattern in the URL paths. + +Example: + +.. code-block:: c + + HTTP_RESOURCE_DEFINE(my_resource, my_service, "/foo*", &resource_detail); + +This would match all URLs that start with a string ``foo``. See +`POSIX.2 chapter 2.13 +`__ +for pattern matching syntax description. + +Static resources +================ + +Static resource content is defined build-time and is immutable. The following +example shows how gzip compressed webpage can be defined as a static resource +in the application: + +.. code-block:: c + + static const uint8_t index_html_gz[] = { + #include "index.html.gz.inc" + }; + + struct http_resource_detail_static index_html_gz_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_STATIC, + .bitmask_of_supported_http_methods = BIT(HTTP_GET), + .content_encoding = "gzip", + }, + .static_data = index_html_gz, + .static_data_len = sizeof(index_html_gz), + }; + + HTTP_RESOURCE_DEFINE(index_html_gz_resource, my_service, "/", + &index_html_gz_resource_detail); + +The resource content and content encoding is application specific. For the above +example, a gzip compressed webpage can be generated during build, by adding the +following code to the application's ``CMakeLists.txt`` file: + +.. code-block:: cmake + :caption: ``CMakeLists.txt`` + + set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/) + set(source_file_index src/index.html) + generate_inc_file_for_target(app ${source_file_index} ${gen_dir}/index.html.gz.inc --gzip) + +where ``src/index.html`` is the location of the webpage to be compressed. + +Dynamic resources +================= + +For dynamic resource, a resource callback is registered to exchange data between +the server and the application. The application defines a resource buffer used +to pass the request payload data from the server, and to provide response payload +to the server. The following example code shows how to register a dynamic resource +with a simple resource handler, which echoes received data back to the client: + +.. code-block:: c + + static uint8_t recv_buffer[1024]; + + static int dyn_handler(struct http_client_ctx *client, + enum http_data_status status, uint8_t *buffer, + size_t len, void *user_data) + { + #define MAX_TEMP_PRINT_LEN 32 + static char print_str[MAX_TEMP_PRINT_LEN]; + enum http_method method = client->method; + static size_t processed; + + __ASSERT_NO_MSG(buffer != NULL); + + if (status == HTTP_SERVER_DATA_ABORTED) { + LOG_DBG("Transaction aborted after %zd bytes.", processed); + processed = 0; + return 0; + } + + processed += len; + + snprintf(print_str, sizeof(print_str), "%s received (%zd bytes)", + http_method_str(method), len); + LOG_HEXDUMP_DBG(buffer, len, print_str); + + if (status == HTTP_SERVER_DATA_FINAL) { + LOG_DBG("All data received (%zd bytes).", processed); + processed = 0; + } + + /* This will echo data back to client as the buffer and recv_buffer + * point to same area. + */ + return len; + } + + struct http_resource_detail_dynamic dyn_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_DYNAMIC, + .bitmask_of_supported_http_methods = + BIT(HTTP_GET) | BIT(HTTP_POST), + }, + .cb = dyn_handler, + .data_buffer = recv_buffer, + .data_buffer_len = sizeof(recv_buffer), + .user_data = NULL, + }; + + HTTP_RESOURCE_DEFINE(dyn_resource, my_service, "/dynamic", + &dyn_resource_detail); + + +The resource callback may be called multiple times for a single request, hence +the application should be able to keep track of the received data progress. + +The ``status`` field informs the application about the progress in passing +request payload from the server to the application. As long as the status +reports :c:enumerator:`HTTP_SERVER_DATA_MORE`, the application should expect +more data to be provided in a consecutive callback calls. +Once all request payload has been passed to the application, the server reports +:c:enumerator:`HTTP_SERVER_DATA_FINAL` status. In case of communication errors +during request processing (for example client closed the connection before +complete payload has been received), the server reports +:c:enumerator:`HTTP_SERVER_DATA_ABORTED`. Either of the two events indicate that +the application shall reset any progress recorded for the resource, and await +a new request to come. The server guarantees that the resource can only be +accessed by single client at a time. + +The resource callback returns the number of bytes to be replied in the response +payload to the server (provided in the resource data buffer). In case there is +no more data to be included in the response, the callback should return 0. + +The server will call the resource callback until it provided all request data +to the application, and the application reports there is no more data to include +in the reply. + +Websocket resources +=================== + +Websocket resources register an application callback, which is is called when a +Websocket connection upgrade takes place. The callback is provided with a socket +descriptor corresponding to the underlying TCP/TLS connection. Once called, +the application takes full control over the socket, i. e. is responsible to +release it when done. + +.. code-block:: c + + static int ws_socket; + static uint8_t ws_recv_buffer[1024]; + + int ws_setup(int sock, void *user_data) + { + ws_socket = sock; + return 0; + } + + struct http_resource_detail_websocket ws_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_WEBSOCKET, + /* We need HTTP/1.1 Get method for upgrading */ + .bitmask_of_supported_http_methods = BIT(HTTP_GET), + }, + .cb = ws_setup, + .data_buffer = ws_recv_buffer, + .data_buffer_len = sizeof(ws_recv_buffer), + .user_data = NULL, /* Fill this for any user specific data */ + }; + + HTTP_RESOURCE_DEFINE(ws_resource, my_service, "/", &ws_resource_detail); + +The above minimalistic example shows how to register a Websocket resource with +a simple callback, used only to store the socket descriptor provided. Further +processing of the Websocket connection is application-specific, hence outside +of scope of this guide. See :zephyr:code-sample:`sockets-http-server` for an +example Websocket-based echo service implementation. + +API Reference +************* + +.. doxygengroup:: http_service +.. doxygengroup:: http_server diff --git a/doc/connectivity/networking/api/index.rst b/doc/connectivity/networking/api/index.rst index 1264ff2aafb9d..fd362492b3c2f 100644 --- a/doc/connectivity/networking/api/index.rst +++ b/doc/connectivity/networking/api/index.rst @@ -23,5 +23,4 @@ libraries for the application to use. See the list below for details. protocols.rst system_mgmt.rst tsn.rst - gsm_modem.rst zperf.rst diff --git a/doc/connectivity/networking/api/lwm2m.rst b/doc/connectivity/networking/api/lwm2m.rst index 8aab68e54caa5..b340166fbff86 100644 --- a/doc/connectivity/networking/api/lwm2m.rst +++ b/doc/connectivity/networking/api/lwm2m.rst @@ -521,7 +521,7 @@ engine. Data caches depends on one of the SenML data formats :kconfig:option:`CONFIG_LWM2M_RW_SENML_CBOR_SUPPORT` or -:kconfig:option:`CONFIG_LWM2M_RW_SENML_JSON_SUPPORT` and needs :kconfig:option:`CONFIG_POSIX_CLOCK` +:kconfig:option:`CONFIG_LWM2M_RW_SENML_JSON_SUPPORT` and needs :kconfig:option:`CONFIG_POSIX_TIMERS` so it can request a timestamp from the system and :kconfig:option:`CONFIG_RING_BUFFER` for ring buffer. diff --git a/doc/connectivity/networking/api/protocols.rst b/doc/connectivity/networking/api/protocols.rst index aea485b74aa6d..f4f3b1f88c1af 100644 --- a/doc/connectivity/networking/api/protocols.rst +++ b/doc/connectivity/networking/api/protocols.rst @@ -10,8 +10,10 @@ Protocols coap coap_client coap_server - http + http_client + http_server lwm2m mqtt mqtt_sn + ptp tftp diff --git a/doc/connectivity/networking/api/ptp.rst b/doc/connectivity/networking/api/ptp.rst new file mode 100644 index 0000000000000..8b0d8384393a7 --- /dev/null +++ b/doc/connectivity/networking/api/ptp.rst @@ -0,0 +1,140 @@ +.. _ptp_interface: + +Precision Time Protocol (PTP) +############################# + +.. contents:: + :local: + :depth: 2 + +Overview +******** + +PTP is a network protocol implemented in the application layer, used to synchronize +clocks in a computer network. It's accurate up to less than a microsecond. +The stack supports the protocol and procedures as defined in the `IEEE 1588-2019 standard`_ +(IEEE Standard for a Precision Clock Synchronization Protocol +for Networked Measurement and Control Systems). It has multiple profiles, +and can be implemented on top of L2 (Ethernet) or L3 (UDP/IPv4 or UDP/IPv6). +Its accuracy is achieved by using hardware timestamping of the protocol packets. + +Zephyr's implementation of PTP stack consist following items: + +* PTP stack thread that handles incoming messages and events +* Integration with ptp_clock driver +* PTP stack initialization executed during system init + +The implementation automatically creates PTP Ports (each PTP Port coresponds to unique interface). + +Supported features +****************** + +Implementation of the stack doesn't support all features specified in the standard. +In the table below all supported features are listed. + +.. csv-table:: Supported features + :header: Feature, Supported + :widths: 50,10 + + Ordinary Clock, yes + Boundary Clock, yes + Transparent Clock, + Management Node, + End to end delay mechanism, yes + Peer to peer delay mechanism, + Multicast operation mode, + Hybrid operation mode, + Unicast operation mode, + Non-volatile storage, + UDP IPv4 transport protocol, yes + UDP IPv6 transport protocol, yes + IEEE 802.3 (Ethernet) transport protocol, + Hardware timestamping, yes + Software timestamping, + TIME_RECEIVER_ONLY PTP Instance, yes + TIME_TRANSMITTER_ONLY PTP Instance, + +Supported Management messages +***************************** + +Based on Table 59 from section 15.5.2.3 of the IEEE 1588-2019 following management TLVs +are supported: + +.. csv-table:: Supported management message's IDs + :header: Management_ID, Management_ID name, Allowed acctions + :widths: 10,40,25 + + 0x0000, NULL_PTP_MANAGEMENT, GET SET COMMAND + 0x0001, CLOCK_DESCRIPTION, GET + 0x0002, USER_DESCRIPTION, GET + 0x0003, SAVE_IN_NON_VOLATILE_STORAGE, - + 0x0004, RESET_NON_VOLATILE_STORAGE, - + 0x0005, INITIALIZE, - + 0x0006, FAULT_LOG, - + 0x0007, FAULT_LOG_RESET, - + 0x2000, DEFAULT_DATA_SET, GET + 0x2001, CURRENT_DATA_SET, GET + 0x2002, PARENT_DATA_SET, GET + 0x2003, TIME_PROPERTIES_DATA_SET, GET + 0x2004, PORT_DATA_SET, GET + 0x2005, PRIORITY1, GET SET + 0x2006, PRIORITY2, GET SET + 0x2007, DOMAIN, GET SET + 0x2008, TIME_RECEIVER_ONLY, GET SET + 0x2009, LOG_ANNOUNCE_INTERVAL, GET SET + 0x200A, ANNOUNCE_RECEIPT_TIMEOUT, GET SET + 0x200B, LOG_SYNC_INTERVAL, GET SET + 0x200C, VERSION_NUMBER, GET SET + 0x200D, ENABLE_PORT, COMMAND + 0x200E, DISABLE_PORT, COMMAND + 0x200F, TIME, GET SET + 0x2010, CLOCK_ACCURACY, GET SET + 0x2011, UTC_PROPERTIES, GET SET + 0x2012, TRACEBILITY_PROPERTIES, GET SET + 0x2013, TIMESCALE_PROPERTIES, GET SET + 0x2014, UNICAST_NEGOTIATION_ENABLE, - + 0x2015, PATH_TRACE_LIST, - + 0x2016, PATH_TRACE_ENABLE, - + 0x2017, GRANDMASTER_CLUSTER_TABLE, - + 0x2018, UNICAST_TIME_TRANSMITTER_TABLE, - + 0x2019, UNICAST_TIME_TRANSMITTER_MAX_TABLE_SIZE, - + 0x201A, ACCEPTABLE_TIME_TRANSMITTER_TABLE, - + 0x201B, ACCEPTABLE_TIME_TRANSMITTER_TABLE_ENABLED, - + 0x201C, ACCEPTABLE_TIME_TRANSMITTER_MAX_TABLE_SIZE, - + 0x201D, ALTERNATE_TIME_TRANSMITTER, - + 0x201E, ALTERNATE_TIME_OFFSET_ENABLE, - + 0x201F, ALTERNATE_TIME_OFFSET_NAME, - + 0x2020, ALTERNATE_TIME_OFFSET_MAX_KEY, - + 0x2021, ALTERNATE_TIME_OFFSET_PROPERTIES, - + 0x3000, EXTERNAL_PORT_CONFIGURATION_ENABLED, + 0x3001, TIME_TRANSMITTER_ONLY, - + 0x3002, HOLDOVER_UPGRADE_ENABLE, - + 0x3003, EXT_PORT_CONFIG_PORT_DATA_SET, - + 0x4000, TRANSPARENT_CLOCK_DEFAULT_DATA_SET, - + 0x4001, TRANSPARENT_CLOCK_PORT_DATA_SET, - + 0x4002, PRIMARY_DOMAIN, - + 0x6000, DELAY_MECHANISM, GET + 0x6001, LOG_MIN_PDELAY_REQ_INTERVAL, GET SET + +Enabling the stack +****************** + +The following configuration option must me enabled in :file:`prj.conf` file. + +- :kconfig:option:`CONFIG_PTP` + +Testing +******* + +The stack has been informally tested using the +`Linux ptp4l `_ daemons. +The :zephyr:code-sample:`PTP sample application ` from the Zephyr +source distribution can be used for testing. + +.. _IEEE 1588-2019 standard: + https://standards.ieee.org/ieee/1588/6825/ + +API Reference +************* + +.. doxygengroup:: ptp diff --git a/doc/connectivity/networking/api/system_mgmt.rst b/doc/connectivity/networking/api/system_mgmt.rst index a09ed2b2787f2..97f2f559bd781 100644 --- a/doc/connectivity/networking/api/system_mgmt.rst +++ b/doc/connectivity/networking/api/system_mgmt.rst @@ -8,6 +8,7 @@ Network System Management net_config.rst dhcpv4.rst + dhcpv6.rst net_hostname.rst net_core.rst net_if.rst diff --git a/doc/connectivity/networking/api/tsn.rst b/doc/connectivity/networking/api/tsn.rst index c9d00cfcc5ce6..276be30e230e1 100644 --- a/doc/connectivity/networking/api/tsn.rst +++ b/doc/connectivity/networking/api/tsn.rst @@ -9,3 +9,4 @@ Time Sensitive Networking gptp.rst net_time.rst ptp_time.rst + ptp.rst diff --git a/doc/connectivity/networking/conn_mgr/main.rst b/doc/connectivity/networking/conn_mgr/main.rst index fd7a8bf87eec5..8788da9ceb82b 100644 --- a/doc/connectivity/networking/conn_mgr/main.rst +++ b/doc/connectivity/networking/conn_mgr/main.rst @@ -73,6 +73,17 @@ Afterwards, ifaces can become ready or unready without firing additional events, When there are no longer any ready ifaces left, the :c:macro:`NET_EVENT_L4_DISCONNECTED` :ref:`network management ` event is triggered, and IP connectivity is said to be unready. +.. note:: + + Connection Manager also fires the following more specific ``CONNECTED`` / ``DISCONNECTED`` events: + + - :c:macro:`NET_EVENT_L4_IPV4_CONNECTED` + - :c:macro:`NET_EVENT_L4_IPV4_DISCONNECTED` + - :c:macro:`NET_EVENT_L4_IPV6_CONNECTED` + - :c:macro:`NET_EVENT_L4_IPV6_DISCONNECTED` + + These are similar to :c:macro:`NET_EVENT_L4_CONNECTED` and :c:macro:`NET_EVENT_L4_DISCONNECTED`, but specifically track whether IPv4- and IPv6-capable ifaces are ready. + .. _conn_mgr_monitoring_usage: Usage diff --git a/doc/connectivity/networking/net_config_guide.rst b/doc/connectivity/networking/net_config_guide.rst index 177ff434e8ae1..fd4f0ff402f18 100644 --- a/doc/connectivity/networking/net_config_guide.rst +++ b/doc/connectivity/networking/net_config_guide.rst @@ -87,7 +87,7 @@ Socket Options Maximum number of supported poll() entries. One needs to select proper value here depending on how many BSD sockets are polled in the system. -:kconfig:option:`CONFIG_POSIX_MAX_FDS` +:kconfig:option:`CONFIG_ZVFS_OPEN_MAX` Maximum number of open file descriptors, this includes files, sockets, special devices, etc. One needs to select proper value here depending on how many BSD sockets are created in the system. diff --git a/doc/connectivity/networking/overview.rst b/doc/connectivity/networking/overview.rst index fdcc73753a280..73876449c88fa 100644 --- a/doc/connectivity/networking/overview.rst +++ b/doc/connectivity/networking/overview.rst @@ -84,6 +84,13 @@ can be disabled if not needed. supported in similar manner when enabled with a Kconfig option. :zephyr:code-sample:`lwm2m-client` sample implements the library as an example. +* **HTTP** Hypertext Transfer Protocol client and server are supported. + :ref:`http_client_interface` library supports HTTP/1.1 (`RFC 2616`_). + :ref:`http_server_interface` library supports HTTP/1.1 (`RFC 2616`_) and + HTTP/2 (`RFC 9113`_). + :zephyr:code-sample:`sockets-http-client` and + :zephyr:code-sample:`sockets-http-server` samples are provided. + * **DNS** Domain Name Service (`RFC 1035 `_) client functionality is supported. @@ -177,3 +184,9 @@ The networking stack source code tree is organized as follows: .. _LwM2M specification 1.1.1: http://openmobilealliance.org/release/LightweightM2M/V1_1_1-20190617-A/ + +.. _RFC 2616: + https://tools.ietf.org/html/rfc2616 + +.. _RFC 9113: + https://tools.ietf.org/html/rfc9113 diff --git a/doc/connectivity/usb/device/usb_device.rst b/doc/connectivity/usb/device/usb_device.rst index 1e5950d2bf88c..acdd07a3a1b57 100644 --- a/doc/connectivity/usb/device/usb_device.rst +++ b/doc/connectivity/usb/device/usb_device.rst @@ -110,7 +110,7 @@ and looks like this: }; }; -Samples :zephyr:code-sample:`usb-cdc-acm` and :zephyr:code-sample:`usb-hid-cdc` have similar overlay files. +Sample :zephyr:code-sample:`usb-cdc-acm` has similar overlay files. And since no special properties are present, it may seem overkill to use devicetree to describe CDC ACM UART. The motivation behind using devicetree is the easy interchangeability of a real UART controller and CDC ACM UART @@ -579,7 +579,7 @@ The following Product IDs are currently used: +----------------------------------------------------+--------+ | :zephyr:code-sample:`usb-cdc-acm-composite` | 0x0002 | +----------------------------------------------------+--------+ -| :zephyr:code-sample:`usb-hid-cdc` | 0x0003 | +| Reserved (previously: usb-hid-cdc) | 0x0003 | +----------------------------------------------------+--------+ | :zephyr:code-sample:`usb-cdc-acm-console` | 0x0004 | +----------------------------------------------------+--------+ diff --git a/doc/connectivity/usb/device_next/api/index.rst b/doc/connectivity/usb/device_next/api/index.rst index bbc5bfc47a967..d0ba69763221d 100644 --- a/doc/connectivity/usb/device_next/api/index.rst +++ b/doc/connectivity/usb/device_next/api/index.rst @@ -8,3 +8,5 @@ New USB device support APIs udc.rst usbd.rst + usbd_hid_device.rst + uac2_device.rst diff --git a/doc/connectivity/usb/device_next/api/uac2_device.rst b/doc/connectivity/usb/device_next/api/uac2_device.rst new file mode 100644 index 0000000000000..bbe1fd0758b17 --- /dev/null +++ b/doc/connectivity/usb/device_next/api/uac2_device.rst @@ -0,0 +1,11 @@ +.. _uac2_device: + +Audio Class 2 device API +######################## + +USB Audio Class 2 device specific API defined in :zephyr_file:`include/zephyr/usb/class/usbd_uac2.h`. + +API Reference +************* + +.. doxygengroup:: uac2_device diff --git a/doc/connectivity/usb/device_next/api/usbd_hid_device.rst b/doc/connectivity/usb/device_next/api/usbd_hid_device.rst new file mode 100644 index 0000000000000..51a499a20503f --- /dev/null +++ b/doc/connectivity/usb/device_next/api/usbd_hid_device.rst @@ -0,0 +1,11 @@ +.. _usbd_hid_device: + +HID device API +############## + +HID device specific API defined in :zephyr_file:`include/zephyr/usb/class/usbd_hid.h`. + +API Reference +************* + +.. doxygengroup:: usbd_hid_device diff --git a/doc/connectivity/usb/device_next/usb_device.rst b/doc/connectivity/usb/device_next/usb_device.rst index a9009d54e2b1f..852da003cef06 100644 --- a/doc/connectivity/usb/device_next/usb_device.rst +++ b/doc/connectivity/usb/device_next/usb_device.rst @@ -1,57 +1,187 @@ .. _usb_device_stack_next: -New experimental USB device support -################################### +New USB device support +###################### Overview ******** -The new USB device support is experimental. It consists of :ref:`udc_api` -and :ref:`usbd_api`. The new device stack brings support for multiple device -controllers, support for multiple configurations, and dynamic registration of -class instances to a configuration at runtime. The stack also provides a specific -class API that should be used to implement the functions (classes). -It will replace :ref:`usb_device_stack`. +USB device support consists of the USB device controller (UDC) drivers +, :ref:`udc_api`, and USB device stack, :ref:`usbd_api`. +The :ref:`udc_api` provides a generic and vendor independent interface to USB +device controllers, and although, there a is clear separation between these +layers, the purpose of :ref:`udc_api` is to serve new Zephyr's USB device stack +exclusively. -If you would like to play around with the new device support, or the new USB -support in general, please try :zephyr:code-sample:`usb-shell` sample. The sample is mainly to help -test the capabilities of the stack and correct implementation of the USB controller -drivers. +The new device stack supports multiple device controllers, meaning that if a +SoC has multiple controllers, they can be used simultaneously. Full and +high-speed device controllers are supported. It also provides support for +registering multiple function or class instances to a configuration at runtime, +or changing the configuration later. It has built-in support for several USB +classes and provides an API to implement custom USB functions. -Supported USB classes -********************* +The new USB device support is considered experimental and will replace +:ref:`usb_device_stack`. -Bluetooth HCI USB transport layer -================================= +Built-in functions +================== + +The USB device stack has built-in USB functions. Some can be used directly in +the user application through a special API, such as HID or Audio class devices, +while others use a general Zephyr RTOS driver API, such as MSC and CDC class +implementations. The *Identification string* identifies a class or function +instance (n) and is used as an argument to the :c:func:`usbd_register_class`. -See :ref:`bluetooth-hci-usb-sample` sample for reference. -To build the sample for the new device support, set the configuration -``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. ++-----------------------------------+-------------------------+-------------------------+ +| Class or function | User API (if any) | Identification string | ++===================================+=========================+=========================+ +| USB Audio 2 class | :ref:`uac2_device` | uac2_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| USB CDC ACM class | :ref:`uart_api` | cdc_acm_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| USB CDC ECM class | Ethernet device | cdc_ecm_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| USB Mass Storage Class (MSC) | :ref:`disk_access_api` | msc_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| USB Human Interface Devices (HID) | :ref:`usbd_hid_device` | hid_(n) | ++-----------------------------------+-------------------------+-------------------------+ +| Bluetooth HCI USB transport layer | :ref:`bt_hci_raw` | bt_hci_(n) | ++-----------------------------------+-------------------------+-------------------------+ -CDC ACM +Samples ======= -CDC ACM implementation has support for multiple instances. -Description from :ref:`usb_device_cdc_acm` also applies to the new implementation. -See :zephyr:code-sample:`usb-cdc-acm` sample for reference. -To build the sample for the new device support, set the configuration -``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. +* :zephyr:code-sample:`usb-hid-keyboard` -Mass Storage Class -================== +* :zephyr:code-sample:`uac2-explicit-feedback` + +Samples ported to new USB device support +---------------------------------------- + +To build a sample that supports both the old and new USB device stack, set the +configuration ``-DCONF_FILE=usbd_next_prj.conf`` either directly or via +``west``. + +* :ref:`bluetooth-hci-usb-sample` + +* :zephyr:code-sample:`usb-cdc-acm` + +* :zephyr:code-sample:`usb-cdc-acm-console` + +* :zephyr:code-sample:`usb-mass` + +* :zephyr:code-sample:`usb-hid-mouse` + +* :zephyr:code-sample:`zperf` To build the sample for the new device support, + set the configuration overlay file + ``-DDEXTRA_CONF_FILE=overlay-usbd_next_ecm.conf`` and devicetree overlay file + ``-DDTC_OVERLAY_FILE="usbd_next_ecm.overlay`` either directly or via ``west``. + +How to configure and enable USB device support +********************************************** + +For the USB device support samples in the Zephyr project repository, we have a +common file for instantiation, configuration and initialization, +:zephyr_file:`samples/subsys/usb/common/sample_usbd_init.c`. The following code +snippets from this file are used as examples. USB Samples Kconfig options used +in the USB samples and prefixed with ``SAMPLE_USBD_`` have default values +specific to the Zephyr project and the scope is limited to the project samples. +In the examples below, you will need to replace these Kconfig options and other +defaults with values appropriate for your application or hardware. + +The USB device stack requires a context structure to manage its properties and +runtime data. The preferred way to define a device context is to use the +:c:macro:`USBD_DEVICE_DEFINE` macro. This creates a static +:c:struct:`usbd_context` variable with a given name. Any number of contexts may +be instantiated. A USB controller device can be assigned to multiple contexts, +but only one context can be initialized and used at a time. Context properties +must not be directly accessed or manipulated by the application. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc device instantiation start + :end-before: doc device instantiation end + +Your USB device may have manufacturer, product, and serial number string +descriptors. To instantiate these string descriptors, the application should +use the appropriate :c:macro:`USBD_DESC_MANUFACTURER_DEFINE`, +:c:macro:`USBD_DESC_PRODUCT_DEFINE`, and +:c:macro:`USBD_DESC_SERIAL_NUMBER_DEFINE` macros. String descriptors also +require a single instantiation of the language descriptor using the +:c:macro:`USBD_DESC_LANG_DEFINE` macro. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc string instantiation start + :end-before: doc string instantiation end + +String descriptors must be added to the device context at runtime before +initializing the USB device with :c:func:`usbd_add_descriptor`. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc add string descriptor start + :end-before: doc add string descriptor end + +USB device requires at least one configuration instance per supported speed. +The application should use :c:macro:`USBD_CONFIGURATION_DEFINE` to instantiate +a configuration. Later, USB device functions are assigned to a configuration. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc configuration instantiation start + :end-before: doc configuration instantiation end + +Each configuration instance for a specific speed must be added to the device +context at runtime before the USB device is initialized using +:c:func:`usbd_add_configuration`. Note :c:enumerator:`USBD_SPEED_FS` and +:c:enumerator:`USBD_SPEED_HS`. The first full-speed or high-speed +configuration will get ``bConfigurationValue`` one, and then further upward. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc configuration register start + :end-before: doc configuration register end + + +Although we have already done a lot, this USB device has no function. A device +can have multiple configurations with different set of functions at different +speeds. A function or class can be registered on a USB device before +it is initialized using :c:func:`usbd_register_class`. The desired +configuration is specified using :c:enumerator:`USBD_SPEED_FS` or +:c:enumerator:`USBD_SPEED_HS` and the configuration number. For simple cases, +:c:func:`usbd_register_all_classes` can be used to register all available +instances. + +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc functions register start + :end-before: doc functions register end + +The last step in the preparation is to initialize the device with +:c:func:`usbd_init`. After this, the configuration of the device cannot be +changed. A device can be deinitialized with :c:func:`usbd_shutdown` and all +instances can be reused, but the previous steps must be repeated. So it is +possible to shutdown a device, register another type of configuration or +function, and initialize it again. At the USB controller level, +:c:func:`usbd_init` does only what is necessary to detect VBUS changes. There +are controller types where the next step is only possible if a VBUS signal is +present. -See :zephyr:code-sample:`usb-mass` sample for reference. -To build the sample for the new device support, set the configuration -``-DCONF_FILE=usbd_next_prj.conf`` either directly or via ``west``. +A function or class implementation may require its own specific configuration +steps, which should be performed prior to initializing the USB device. -Networking -========== +.. literalinclude:: ../../../../samples/subsys/usb/common/sample_usbd_init.c + :language: c + :start-after: doc device init start + :end-before: doc device init end -At the moment only CDC ECM class is implemented and has support for multiple instances. -It provides a virtual Ethernet connection between the remote (USB host) and -Zephyr network support. +The final step to enable the USB device is :c:func:`usbd_enable`, after that, +if the USB device is connected to a USB host controller, the host can start +enumerating the device. The application can disable the USB device using +:c:func:`usbd_disable`. -See :zephyr:code-sample:`zperf` for reference. -To build the sample for the new device support, set the configuration overlay file -``-DDEXTRA_CONF_FILE=overlay-usbd_next_ecm.conf`` and devicetree overlay file -``-DDTC_OVERLAY_FILE="usbd_next_ecm.overlay`` either directly or via ``west``. +.. literalinclude:: ../../../../samples/subsys/usb/hid-keyboard/src/main.c + :language: c + :start-after: doc device enable start + :end-before: doc device enable end diff --git a/doc/contribute/contributor_expectations.rst b/doc/contribute/contributor_expectations.rst index cba1627a1b9be..88fe625c00525 100644 --- a/doc/contribute/contributor_expectations.rst +++ b/doc/contribute/contributor_expectations.rst @@ -276,6 +276,9 @@ Reviewer Expectations #. PRs assigned to the reviewer as the area maintainer. #. All other PRs. +- Reviewers shall strive to advance the PR to a mergeable state with their + feedback and engagement with the PR author. + - Try to provide feedback on the entire PR in one shot. This provides the contributor an opportunity to address all comments in the next PR update. @@ -305,6 +308,11 @@ Reviewer Expectations the PR in question and following the contribution and style guidelines of the project. +- Reviewers shall not close a PR due to technical or structural disagreement. + If requested changes cannot be resolved within the review process, the + :ref:`pr_technical_escalation` path shall be used for any potential resolution + path, which may include closing the PR. + .. _Code of Conduct: https://github.com/zephyrproject-rtos/zephyr/blob/main/CODE_OF_CONDUCT.md .. _Zephyr Release Plan: https://github.com/orgs/zephyrproject-rtos/projects/13 diff --git a/doc/contribute/documentation/generation.rst b/doc/contribute/documentation/generation.rst index 87a00357c8938..f51eb59e44e49 100644 --- a/doc/contribute/documentation/generation.rst +++ b/doc/contribute/documentation/generation.rst @@ -98,34 +98,34 @@ as described below: .. code-block:: console - pip install -r ~/zephyrproject/zephyr/doc/requirements.txt + pip install -U -r ~/zephyrproject/zephyr/doc/requirements.txt On Ubuntu Linux: .. code-block:: console sudo apt-get install --no-install-recommends doxygen graphviz librsvg2-bin \ - texlive-latex-base texlive-latex-extra latexmk texlive-fonts-recommended + texlive-latex-base texlive-latex-extra latexmk texlive-fonts-recommended imagemagick On Fedora Linux: .. code-block:: console sudo dnf install doxygen graphviz texlive-latex latexmk \ - texlive-collection-fontsrecommended librsvg2-tools + texlive-collection-fontsrecommended librsvg2-tools ImageMagick On Clear Linux: .. code-block:: console - sudo swupd bundle-add texlive graphviz + sudo swupd bundle-add texlive graphviz ImageMagick On Arch Linux: .. code-block:: console sudo pacman -S graphviz doxygen librsvg texlive-core texlive-bin \ - texlive-latexextra texlive-fontsextra + texlive-latexextra texlive-fontsextra imagemagick .. group-tab:: macOS @@ -133,13 +133,13 @@ as described below: .. code-block:: console - pip install -r ~/zephyrproject/zephyr/doc/requirements.txt + pip install -U -r ~/zephyrproject/zephyr/doc/requirements.txt Use ``brew`` and ``tlmgr`` to install the tools: .. code-block:: console - brew install doxygen graphviz mactex librsvg + brew install doxygen graphviz mactex librsvg imagemagick tlmgr install latexmk tlmgr install collection-fontsrecommended @@ -149,13 +149,13 @@ as described below: .. code-block:: console - pip install -r %HOMEPATH$\zephyrproject\zephyr\doc\requirements.txt + pip install -U -r %HOMEPATH$\zephyrproject\zephyr\doc\requirements.txt Open a ``cmd.exe`` window as **Administrator** and run the following command: .. code-block:: console - choco install doxygen.install graphviz strawberryperl miktex rsvg-convert + choco install doxygen.install graphviz strawberryperl miktex rsvg-convert imagemagick .. note:: On Windows, the Sphinx executable ``sphinx-build.exe`` is placed in diff --git a/doc/contribute/external.rst b/doc/contribute/external.rst index c154bc3a698a8..312c3d2f416fb 100644 --- a/doc/contribute/external.rst +++ b/doc/contribute/external.rst @@ -39,7 +39,7 @@ have not been approved by the `Open Source Initiative (OSI)`_. See the https://www.zephyrproject.org/governance/ .. _Zephyr project charter: - https://www.zephyrproject.org/wp-content/uploads/sites/38/2020/09/CLEAN-LF-Zephyr-Charter-20200624-effective-20200901.pdf + https://www.zephyrproject.org/wp-content/uploads/sites/38/2023/08/LF-Zephyr-Charter-2023.08.21.pdf .. _Open Source Initiative (OSI): https://opensource.org/licenses/alphabetical diff --git a/doc/contribute/guidelines.rst b/doc/contribute/guidelines.rst index 564deb0741896..5f31f6422e166 100644 --- a/doc/contribute/guidelines.rst +++ b/doc/contribute/guidelines.rst @@ -148,6 +148,8 @@ For your commits, replace: You can automatically add the Signed-off-by: line to your commit body using ``git commit -s``. Use other commits in the zephyr git history as examples. +See :ref:`git_setup` for instructions on configuring user and email settings +in Git. Additional requirements: @@ -331,16 +333,10 @@ business days. You can find all `open pull requests`_ on GitHub and open `Zephyr Project Issues`_ in Github issues. - .. _Continuous Integration: +.. _git_setup: - -Tools and Git Setup -******************* - -.. _git-name-and-email: - -Name and email -============== +Git Setup +********* We need to know who you are, and how to contact you. To add this information to your Git installation, set the Git configuration @@ -355,93 +351,181 @@ address is ``z.developer@example.com``: git config --global user.name "Zephyr Developer" git config --global user.email "z.developer@example.com" -gitlint -========= -When you submit a pull request to the project, a series of checks are -performed to verify your commit messages meet the requirements. The same step -done during the CI process can be performed locally using the ``gitlint`` -command. +Pull Request Guidelines +*********************** +When opening a new Pull Request, adhere to the following guidelines to ensure +compliance with Zephyr standards and facilitate the review process. -Run ``gitlint`` locally in your tree and branch where your patches have been -committed: +If in doubt, it's advisible to explore existing Pull Requests within the Zephyr +repository. Use the search filters and labels to locate PRs related to changes +similar to the ones you are proposing. -.. code-block:: console +.. _commit-guidelines: - gitlint +Commit Message Guidelines +========================= -Note, gitlint only checks HEAD (the most recent commit), so you should run it -after each commit, or use the ``--commits`` option to specify a commit range -covering all the development patches to be submitted. +Changes are submitted as Git commits. Each commit has a *commit +message* describing the change. Acceptable commit messages look like +this: -twister -======= +.. code-block:: none -.. note:: - twister support on windows is limited and execution of tests is not - supported, only building. + [area]: [summary of change] -To verify that your changes did not break any tests or samples, please run the -``twister`` script locally before submitting your pull request to GitHub. + [Commit message body (must be non-empty)] -Twister allows limiting the scope of the tests built and run by pointing it to -the tests related to the code or the platform you have modified. For example, to -limit tests to a single platform and an area in the kernel:: + Signed-off-by: [Your Full Name] <[your.email@address]> - source zephyr-env.sh - west twister -p qemu_x86 -T tests/kernel/sched +You need to change text in square brackets (``[like this]``) above to +fit your commit. -Running tests on connected devices is also supported using the -``--device-testing`` options. Please consult with the :ref:`Twister -` documentation for more details. +Examples and more details follow. -To run the same tests the CI system runs, follow these steps from within your -local Zephyr source working directory: +Example +------- -.. code-block:: console +Here is an example of a good commit message. - source zephyr-env.sh - west twister --integration +.. code-block:: none -The above will execute the basic twister script, which will run various -tests using the QEMU emulator and other simulators supported in Zephyr. -It will also do some build tests on various samples with advanced features that -can't run in a simulator or QEMU. + drivers: sensor: abcd1234: fix bus I/O error handling -We highly recommend you run these tests locally to avoid any CI failures -However, note that building and executing tests using twister requires -significant computing resources. When running locally and to get results in a -reasonable time, limit the scope to the areas and platforms you have modified. -In case of major changes to the kernel, build or configuration infrastructures -of Zephyr, it is advised to use twister for verifying majority the changes -before handing over to the dedicated CI resources provided by the Zephyr -project. + The abcd1234 sensor driver is failing to check the flags field in + the response packet from the device which signals that an error + occurred. This can lead to reading invalid data from the response + buffer. Fix it by checking the flag and adding an error path. -clang-format -============ + Signed-off-by: Zephyr Developer -The `clang-format tool `_ can -be helpful to quickly reformat large amounts of new source code to our -`Coding Style`_ standards together with the ``.clang-format`` configuration file -provided in the repository. ``clang-format`` is well integrated into most -editors, but you can also run it manually like this: +[area]: [summary of change] +--------------------------- -.. code-block:: bash +This line is called the commit's *title*. Titles must be: - clang-format -i my_source_file.c +* one line +* less than 72 characters long +* followed by a completely blank line -``clang-format`` is part of LLVM, which can be downloaded from the project -`releases page `. Note that if -you are a Linux user, ``clang-format`` will likely be available as a package in -your distribution repositories. +[area] + The ``[area]`` prefix usually identifies the area of code + being changed. It can also identify the change's wider + context if multiple areas are affected. + + Here are some examples: + + * ``doc: ...`` for documentation changes + * ``drivers: foo:`` for ``foo`` driver changes + * ``Bluetooth: Shell:`` for changes to the Bluetooth shell + * ``net: ethernet:`` for Ethernet-related networking changes + * ``dts:`` for treewide devicetree changes + * ``style:`` for code style changes + + If you're not sure what to use, try running ``git log FILE``, where + ``FILE`` is a file you are changing, and using previous commits that + changed the same file as inspiration. + +[summary of change] + The ``[summary of change]`` part should be a quick description of + what you've done. Here are some examples: + + * ``doc: update wiki references to new site`` + * ``drivers: sensor: sensor_shell: fix channel name collision`` + +Commit Message Body +------------------- + +.. warning:: + + An empty commit message body is not permitted. Even for trivial + changes, please include a descriptive commit message body. Your + pull request will fail CI checks if you do not. + +This part of the commit should explain what your change does, and why +it's needed. Be specific. A body that says ``"Fixes stuff"`` will be +rejected. Be sure to include the following as relevant: + +* **what** the change does, +* **why** you chose that approach, +* **what** assumptions were made, and +* **how** you know it works -- for example, which tests you ran. + +Each line in your commit message should usually be 75 characters or +less. Use newlines to wrap longer lines. Exceptions include lines +with long URLs, email addresses, etc. + +For examples of accepted commit messages, you can refer to the Zephyr GitHub +`changelog `__. + + +Signed-off-by: ... +------------------ + +.. tip:: + + You should have set your :ref:`git_setup` + already. Create your commit with ``git commit -s`` to add the + Signed-off-by: line automatically using this information. + +For open source licensing reasons, your commit must include a +Signed-off-by: line that looks like this: + +.. code-block:: none + + Signed-off-by: [Your Full Name] <[your.email@address]> + +For example, if your full name is ``Zephyr Developer`` and your email +address is ``z.developer@example.com``: + +.. code-block:: none + + Signed-off-by: Zephyr Developer + +This means that you have personally made sure your change complies +with the :ref:`DCO`. For this reason, you must use your legal name. +Pseudonyms or "hacker aliases" are not permitted. + +Your name and the email address you use must match the name and email +in the Git commit's ``Author:`` field. + +See the :ref:`contributor-expectations` for a more complete discussion of +contributor and reviewer expectations. + +Adding links +------------ + +.. _GitHub references: + https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/autolinked-references-and-urls + +Do not include `GitHub references`_ in the commit message directly, as it can +lose meaning in case the repository is forked, for example. Instead, if the +change addresses a specific GitHub issue, include in the Pull Request message a +line of the form: + +.. code-block:: none + + Fixes #[issue number] + +Where ``[issue number]`` is the relevant GitHub issue's number. For +example: + +.. code-block:: none + + Fixes: #1234 + +You can point to other relevant information that can be found on the web using +:code:`Link:` tags. This includes, for example: GitHub issues, datasheets, +reference manuals, etc. + +.. code-block:: none + + Link: https://github.com/zephyrproject-rtos/zephyr/issues/ .. _coding_style: Coding Style -************ - -Use these coding guidelines to ensure that your development complies with the -project's style and naming conventions. +============ .. _Linux kernel coding style: https://kernel.org/doc/html/latest/process/coding-style.html @@ -462,8 +546,8 @@ exceptions: * Avoid using non-ASCII symbols in code, unless it significantly improves clarity, avoid emojis in any case. -When there are differences between the guidelines above and the formatting -generated by code formatting tools, the guidelines above take precedence. +Use these coding guidelines to ensure that your development complies with the +project's style and naming conventions. The Linux kernel GPL-licensed tool ``checkpatch`` is used to check coding style conformity. @@ -506,8 +590,102 @@ before pushing on zephyr repo. To do this, make the file If you want to override checkpatch verdict and push you branch despite reported issues, you can add option --no-verify to the git push command. -A more complete alternative to this is using check_compliance.py script from -ci-tools repo. +A more complete alternative to this is using :ref:`check_compliance_py` script. + +clang-format +------------ + +The `clang-format tool `_ can +be helpful to quickly reformat large amounts of new source code to our +`Coding Style`_ standards together with the ``.clang-format`` configuration file +provided in the repository. ``clang-format`` is well integrated into most +editors, but you can also run it manually like this: + +.. code-block:: bash + + clang-format -i my_source_file.c + +``clang-format`` is part of LLVM, which can be downloaded from the project +`releases page `_. Note that if +you are a Linux user, ``clang-format`` will likely be available as a package in +your distribution repositories. + +When there are differences between the `Coding Style`_ guidelines and the +formatting generated by code formatting tools, the `Coding Style`_ guidelines +take precedence. If there is ambiguity between formatting tools and the +guidelines, maintainers may decide which style should be adopted. + +.. _Continuous Integration: + +Continuous Integration (CI) +=========================== + +The Zephyr Project operates a Continuous Integration (CI) system that runs on +every Pull Request (PR) in order to verify several aspects of the PR: + +* Git commit formatting +* Coding Style +* Twister builds for multiple architectures and boards +* Documentation build to verify any doc changes + +CI is run on Github Actions and it uses the same tools described in the +`CI Tests`_ section. The CI results must be green indicating "All +checks have passed" before the Pull Request can be merged. CI is run when the +PR is created, and again every time the PR is modified with a commit. + +The current status of the CI run can always be found at the bottom of the +GitHub PR page, below the review status. Depending on the success or failure +of the run you will see: + +* "All checks have passed" +* "All checks have failed" + +In case of failure you can click on the "Details" link presented below the +failure message in order to navigate to ``Github Actions`` and inspect the +results. +Once you click on the link you will be taken to the ``Github actions`` summary +results page where a table with all the different builds will be shown. To see +what build or test failed click on the row that contains the failed (i.e. +non-green) build. + +.. _CI Tests: + +Running CI Tests Locally +======================== + +.. _check_compliance_py: + +check_compliance.py +------------------- + +The ``check_compliance.py`` script serves as a valuable tool for assessing code +compliance with Zephyr's established guidelines and best practices. The script +acts as wrapper for a suite of tools that performs various checks, including +linters and formatters. + +Developers are encouraged to run the script locally to validate their changes +before opening a new Pull Request: + +.. code-block:: bash + + ./scripts/ci/check_compliance.py -c upstream/main.. + +twister +------- + +.. note:: + twister is only fully supported on Linux; on Windows and MacOS the execution + of tests is not supported, only building. + +If you think your change may break some test, you can submit your PR as a draft +and let the project CI automatically run the :ref:`twister_script` for you. + +If a test fails, you can check from the CI run logs how to rerun it locally, +for example: + +.. code-block:: bash + + west twister -p native_sim -s tests/drivers/build_all/sensor/sensors.generic_test .. _static_analysis: @@ -560,8 +738,6 @@ it after completing the steps above on scan service website. Any issues closed without a fix or without ignoring the entry in the scan service will be automatically reopened if the issue continues to be present in the code. -.. _Contribution Tools: - .. _Contribution workflow: Contribution Workflow @@ -687,13 +863,7 @@ workflow here: and use the same process described above to work on this new topic branch. #. If reviewers do request changes to your patch, you can interactively rebase - commit(s) to fix review issues. In your development repo:: - - git fetch --all - git rebase --ignore-whitespace upstream/main - - The ``--ignore-whitespace`` option stops ``git apply`` (called by rebase) - from changing any whitespace. Continuing:: + commit(s) to fix review issues. In your development repo:: git rebase -i ^ @@ -715,6 +885,17 @@ workflow here: By force pushing your update, your original pull request will be updated with your changes so you won't need to resubmit the pull request. +#. After pushing the requested change, check on the PR page if there is a + merge conflict. If so, rebase your local branch:: + + git fetch --all + git rebase --ignore-whitespace upstream/main + + The ``--ignore-whitespace`` option stops ``git apply`` (called by rebase) + from changing any whitespace. Resolve the conflicts and push again:: + + git push --force origin fix_comment_typo + .. note:: While amending commits and force pushing is a common review model outside GitHub, and the one recommended by Zephyr, it's not the main model supported by GitHub. Forced pushes can cause unexpected behavior, @@ -729,151 +910,41 @@ workflow here: Additional information about the CI system can be found in `Continuous Integration`_. -.. _commit-guidelines: - -Commit Message Guidelines -************************* - -Changes are submitted as Git commits. Each commit has a *commit -message* describing the change. Acceptable commit messages look like -this: - -.. code-block:: none - - [area]: [summary of change] - - [Commit message body (must be non-empty)] - - Signed-off-by: [Your Full Name] <[your.email@address]> - -You need to change text in square brackets (``[like this]``) above to -fit your commit. - -Examples and more details follow. - -Example -======= - -Here is an example of a good commit message. - -.. code-block:: none - - drivers: sensor: abcd1234: fix bus I/O error handling - - The abcd1234 sensor driver is failing to check the flags field in - the response packet from the device which signals that an error - occurred. This can lead to reading invalid data from the response - buffer. Fix it by checking the flag and adding an error path. +.. _contribution_tips: - Signed-off-by: Zephyr Developer +Contribution Tips +================= -[area]: [summary of change] -=========================== +The following is a list of tips to improve and accelerate the review process of +Pull Requests. If you follow them, chances are your pull request will get the +attention needed and it will be ready for merge sooner than later: -This line is called the commit's *title*. Titles must be: +.. _git-rebase: + https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---keep-base -* one line -* less than 72 characters long -* followed by a completely blank line +#. When pushing follow-up changes, use the ``--keep-base`` option of + `git-rebase`_ -[area] - The ``[area]`` prefix usually identifies the area of code - being changed. It can also identify the change's wider - context if multiple areas are affected. +#. On the PR page, check if the change can still be merged with no merge + conflicts - Here are some examples: +#. Make sure title of PR explains what is being fixed or added - * ``doc: ...`` for documentation changes - * ``drivers: foo:`` for ``foo`` driver changes - * ``Bluetooth: Shell:`` for changes to the Bluetooth shell - * ``net: ethernet:`` for Ethernet-related networking changes - * ``dts:`` for treewide devicetree changes - * ``style:`` for code style changes +#. Make sure your PR has a body with more details about the content of your + submission - If you're not sure what to use, try running ``git log FILE``, where - ``FILE`` is a file you are changing, and using previous commits that - changed the same file as inspiration. +#. Make sure you reference the issue you are fixing in the body of the PR -[summary of change] - The ``[summary of change]`` part should be a quick description of - what you've done. Here are some examples: +#. Watch early CI results immediately after submissions and fix issues as they + are discovered - * ``doc: update wiki references to new site`` - * ``drivers: sensor: sensor_shell: fix channel name collision`` +#. Revisit PR after 1-2 hours to see the status of all CI checks, make sure all + is green -Commit Message Body -=================== +#. If you get request for changes and submit a change to address them, make + sure you click the "Re-request review" button on the GitHub UI to notify + those who asked for the changes -.. warning:: - - An empty commit message body is not permitted. Even for trivial - changes, please include a descriptive commit message body. Your - pull request will fail CI checks if you do not. - -This part of the commit should explain what your change does, and why -it's needed. Be specific. A body that says ``"Fixes stuff"`` will be -rejected. Be sure to include the following as relevant: - -* **what** the change does, -* **why** you chose that approach, -* **what** assumptions were made, and -* **how** you know it works -- for example, which tests you ran. - -Each line in your commit message should usually be 75 characters or -less. Use newlines to wrap longer lines. Exceptions include lines -with long URLs, email addresses, etc. - -For examples of accepted commit messages, you can refer to the Zephyr GitHub -`changelog `__. - -If the change addresses a GitHub issue, include a line of the form: - -.. code-block:: none - - Fixes #[issue number] - -Where ``[issue number]`` is the relevant GitHub issue's number. For -example: - -.. code-block:: none - - Fixes: #1234 - -Signed-off-by: ... -================== - -.. tip:: - - You should have set your :ref:`git-name-and-email` - already. Create your commit with ``git commit -s`` to add the - Signed-off-by: line automatically using this information. - -For open source licensing reasons, your commit must include a -Signed-off-by: line that looks like this: - -.. code-block:: none - - Signed-off-by: [Your Full Name] <[your.email@address]> - -For example, if your full name is ``Zephyr Developer`` and your email -address is ``z.developer@example.com``: - -.. code-block:: none - - Signed-off-by: Zephyr Developer - -This means that you have personally made sure your change complies -with the :ref:`DCO`. For this reason, you must use your legal name. -Pseudonyms or "hacker aliases" are not permitted. - -Your name and the email address you use must match the name and email -in the Git commit's ``Author:`` field. - -Other Commit Expectations -========================= - -See the :ref:`contributor-expectations` for a more complete discussion of -contributor and reviewer expectations. Submitting Proposals ==================== @@ -930,38 +1001,6 @@ For example, a copy of an externally maintained import in a module repository:: commit: 08ded7f21529c39e5133688ffb93a9d0c94e5c6e Purpose: Introduction of TinyCrypt - -Continuous Integration (CI) -*************************** - -The Zephyr Project operates a Continuous Integration (CI) system that runs on -every Pull Request (PR) in order to verify several aspects of the PR: - -* Git commit formatting -* Coding Style -* Twister builds for multiple architectures and boards -* Documentation build to verify any doc changes - -CI is run on Github Actions and it uses the same tools described in the -`Contribution Tools`_ section. The CI results must be green indicating "All -checks have passed" before the Pull Request can be merged. CI is run when the -PR is created, and again every time the PR is modified with a commit. - -The current status of the CI run can always be found at the bottom of the -GitHub PR page, below the review status. Depending on the success or failure -of the run you will see: - -* "All checks have passed" -* "All checks have failed" - -In case of failure you can click on the "Details" link presented below the -failure message in order to navigate to ``Github Actions`` and inspect the -results. -Once you click on the link you will be taken to the ``Github actions`` summary -results page where a table with all the different builds will be shown. To see -what build or test failed click on the row that contains the failed (i.e. -non-green) build. - Contributions to External Modules ********************************** diff --git a/doc/develop/api/terminology.rst b/doc/develop/api/terminology.rst index dacf937727237..593ce5929f45b 100644 --- a/doc/develop/api/terminology.rst +++ b/doc/develop/api/terminology.rst @@ -184,7 +184,7 @@ Explanation Be aware that **async** is orthogonal to context-switching. Some APIs may provide completion information through a callback, but may suspend while waiting for the resource necessary to initiate the operation; an -example is :c:func:`spi_transceive_async`. +example is :c:func:`spi_transceive_signal`. If a function is both **no-wait** and **async** then selecting the no-wait path only guarantees that the function will not sleep. It does diff --git a/doc/develop/flash_debug/probes.rst b/doc/develop/flash_debug/probes.rst index 0e237a6fcf63f..652db3be5ea28 100644 --- a/doc/develop/flash_debug/probes.rst +++ b/doc/develop/flash_debug/probes.rst @@ -23,33 +23,42 @@ flash programmer. This eliminates the need to purchase an external debug probe and provides a variety of debug host tool options. Several hardware vendors have their own branded onboard debug probe -implementations: NXP LPC boards have `LPC-Link2 <#lpclink2-jlink-onboard-debug-probe>`_, -NXP Kinetis (former Freescale) boards have `OpenSDA <#opensda-daplink-onboard-debug-probe>`_, -and ST boards have `ST-LINK <#stlink-v21-onboard-debug-probe>`_. Each onboard debug probe -microcontroller can support one or more types of firmware that communicate with -their respective debug host tools. For example, an OpenSDA microcontroller can -be programmed with DAPLink firmware to communicate with pyOCD or OpenOCD debug -host tools, or with J-Link firmware to communicate with J-Link debug host -tools. - - -+------------------------------------------+------------------------------------------------------------------------------------+ -|| *Debug Probes & Host Tools* | Host Tools | -+| *Compatibility Chart* +--------------------+--------------------+---------------------+--------------------+ -| | **J-Link Debug** | **OpenOCD** | **pyOCD** | **NXP S32DS** | -+----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+ -| | **LPC-Link2 J-Link** | ✓ | | | | -| +-------------------------+--------------------+--------------------+---------------------+--------------------+ -| | **OpenSDA DAPLink** | | ✓ | ✓ | | -| +-------------------------+--------------------+--------------------+---------------------+--------------------+ -| Debug Probes | **OpenSDA J-Link** | ✓ | | | | -| +-------------------------+--------------------+--------------------+---------------------+--------------------+ -| | **J-Link External** | ✓ | ✓ | | | -| +-------------------------+--------------------+--------------------+---------------------+--------------------+ -| | **ST-LINK/V2-1** | ✓ | ✓ | *some STM32 boards* | | -| +-------------------------+--------------------+--------------------+---------------------+--------------------+ -| | **NXP S32 Debug Probe** | | | | ✓ | -+----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+ +implementations: NXP boards may use +`OpenSDA <#opensda-daplink-onboard-debug-probe>`_, +`LPC-Link2 <#lpclink2-jlink-onboard-debug-probe>`_, or +`MCU-Link <#mcu-link-cmsis-onboard-debug-probe>`_, probes depending on +the microcontroller the debug probe firmware runs on. +ST boards have the `ST-LINK probe <#stlink-v21-onboard-debug-probe>`_. Each +onboard debug probe microcontroller can support one or more types of firmware +that communicate with their respective debug host tools. For example, an +OpenSDA microcontroller can be programmed with DAPLink firmware to communicate +with pyOCD or OpenOCD debug host tools, or with J-Link firmware to communicate +with J-Link debug host tools. + + ++------------------------------------------+---------------------------------------------------------------------------------------------------------+ +|| *Debug Probes & Host Tools* | Host Tools | ++| *Compatibility Chart* +--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **J-Link Debug** | **OpenOCD** | **pyOCD** | **NXP S32DS** | **NXP LinkServer** | ++----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **J-Link External** | ✓ | ✓ | | | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **LPC-Link2 CMSIS-DAP** | | | | | ✓ | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **LPC-Link2 J-Link** | ✓ | | | | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **MCU-Link CMSIS-DAP** | | | | | ✓ | +| Debug Probes +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **MCU-Link J-Link** | ✓ | | | | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **NXP S32 Debug Probe** | | | | ✓ | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **OpenSDA DAPLink** | | ✓ | ✓ | | ✓ | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **OpenSDA J-Link** | ✓ | | | | | +| +-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ +| | **ST-LINK/V2-1** | ✓ | ✓ | *some STM32 boards* | | | ++----------------+-------------------------+--------------------+--------------------+---------------------+--------------------+--------------------+ Some supported boards in Zephyr do not include an onboard debug probe and @@ -60,15 +69,49 @@ onboard debug probe may have limitations, such as lack of support for advanced debuggers or high-speed tracing. You may need to adjust jumpers to prevent the onboard debug probe from interfering with the external debug probe. +.. _nxp-onboard-debug-probes: + +NXP Onboard Debug Probes +************************ + +NXP boards may have one of several onboard debug probes. These probes include +the :ref:`mcu-link-onboard-debug-probe`, :ref:`lpc-link2-onboard-debug-probe` +and :ref:`opensda-onboard-debug-probe`. Each of these probes is implemented +as a secondary microcontroller present on the evaluation board. The specific +debug probe type present on a given board can be determined based on the +debug microcontroller SOC: + +- LPC55S69: :ref:`mcu-link-onboard-debug-probe` +- LPC4322: :ref:`lpc-link2-onboard-debug-probe` +- MK20: :ref:`opensda-onboard-debug-probe` + +For example, the :ref:`frdm_k64f` board has an MK20 debug microcontroller, +so this board uses the :ref:`opensda-onboard-debug-probe`. + +.. _mcu-link-onboard-debug-probe: + +MCU-Link Onboard Debug Probe +**************************** + +The MCU-Link onboard debug probe uses an LPC55S69 SOC. This probe supports +the following firmwares: + +- :ref:`mcu-link-cmsis-onboard-debug-probe` (default firmware) +- :ref:`mcu-link-jlink-onboard-debug-probe` + +This probe is programmed using the MCU-Link host tools, which are installed +with the :ref:`linkserver-debug-host-tools`. NXP recommends using NXP's +`MCUXpresso Installer`_ to install the Linkserver tools. + .. _mcu-link-cmsis-onboard-debug-probe: MCU-Link CMSIS-DAP Onboard Debug Probe -*************************************** +====================================== -The CMSIS-DAP debug probes allow debugging from any compatible toolchain, -including IAR EWARM, Keil MDK, NXP’s MCUXpresso IDE and -MCUXpresso extension for VS Code. In addition to debug probe functionality, the -MCU-Link probes may also provide: +This is the default firmware installed on MCU-Link debug probes. The CMSIS-DAP +debug probes allow debugging from any compatible toolchain, including IAR +EWARM, Keil MDK, NXP’s MCUXpresso IDE and MCUXpresso extension for VS Code. In +addition to debug probe functionality, the MCU-Link probes may also provide: 1. SWO trace end point: this virtual device is used by MCUXpresso to retrieve SWO trace data. See the MCUXpresso IDE documentation for more information. @@ -81,13 +124,13 @@ This debug probe is compatible with the following debug host tools: - :ref:`linkserver-debug-host-tools` -This probe is realized by programming the MCU-Link microcontroller with the -CMSIS-DAP MCU-Link firmware, which is already installed by default. NXP -recommends using NXP's `MCUXpresso Installer`_, which installs both the MCU-Link -host tools plus the :ref:`linkserver-debug-host-tools`. +Once the MCU-Link host tools are installed, the following steps are +required to program the CMSIS-DAP firmware: 1. Put the MCU-Link microcontroller into DFU boot mode by attaching the DFU - jumper, then powering up the board. + jumper then connecting to the USB debug port on the board. This jumper may + also be referred to as the ISP jumper, and will be connected to ``PIO0_5`` + on the LPC55S69. #. Run the ``program_CMSIS`` script, found in the installed MCU-Link ``scripts`` folder. @@ -97,31 +140,48 @@ host tools plus the :ref:`linkserver-debug-host-tools`. .. _mcu-link-jlink-onboard-debug-probe: MCU-Link JLink Onboard Debug Probe -************************************ - -The MCU-Link J-Link is an onboard debug probe and usb-to-serial adapter -supported on many NXP development boards. +================================== -This debug probe is compatible with the following debug host tools: +This debug probe firmware provides a JLink compatible debug interface, +as well as a USB-Serial adapter. It is compatible with the following debug host +tools: - :ref:`jlink-debug-host-tools` These probes do not have JLink firmware installed by default, and must be -updated. NXP recommends using NXP's `MCUXpresso Installer`_, which installs both -the :ref:`jlink-debug-host-tools` plus the MCU-Link host tools. +updated. Once the MCU-Link host tools are installed, the following steps are +required to program the JLink firmware: 1. Put the MCU-Link microcontroller into DFU boot mode by attaching the DFU - jumper, then powering up the board. + jumper then connecting to the USB debug port on the board. This jumper may + also be referred to as the ISP jumper, and will be connected to ``PIO0_5`` + on the LPC55S69. #. Run the ``program_JLINK`` script, found in the installed MCU-Link ``scripts`` folder. #. Remove the DFU jumper and power cycle the board. +.. _lpc-link2-onboard-debug-probe: + +LPC-LINK2 Onboard Debug Probe +***************************** + +The LPC-LINK2 onboard debug probe uses an LPC4322 SOC. This probe supports +the following firmwares: + +- :ref:`lpclink2-cmsis-onboard-debug-probe` +- :ref:`lpclink2-jlink-onboard-debug-probe` +- :ref:`lpclink2-daplink-onboard-debug-probe` (default firmware) + +This probe is programmed using the LPCScrypt host tools, which are installed +with the :ref:`linkserver-debug-host-tools`. NXP recommends using NXP's +`MCUXpresso Installer`_ to install the Linkserver tools. + .. _lpclink2-cmsis-onboard-debug-probe: LPC-LINK2 CMSIS DAP Onboard Debug Probe -*************************************** +======================================= The CMSIS-DAP debug probes allow debugging from any compatible toolchain, including IAR EWARM, Keil MDK, as well as NXP’s MCUXpresso IDE and @@ -134,57 +194,83 @@ provide: 2. Virtual COM (VCOM) port / UART bridge connected to the target processor 3. LPCSIO bridge that provides communication to I2C and SPI slave devices -This probe is realized by programming the LPC-Link2 microcontroller with the CMSIS-DAP -LPC-Link2 firmware. Download and install `LPCScrypt`_ to get the firmware and -programming scripts. +This debug probe firmware is compatible with the following debug host tools: -.. note:: Verify the firmware supports your board by visiting `Firmware for LPCXpresso`_ +- :ref:`linkserver-debug-host-tools` + +After installing the LPCScrypt host tools, the firmware may be updated to +use CMSIS-DAP firmware with the following steps: 1. Put the LPC-Link2 microcontroller into DFU boot mode by attaching the DFU - jumper, then powering up the board. + jumper, then then connecting to the USB debug port on the board. This + jumper is connected to ``P2_6`` on the LPC4322 SOC. -#. Run the ``program_CMSIS`` script. +#. Run the ``program_CMSIS`` script, found in the installed LPCScrypt ``scripts`` + folder. #. Remove the DFU jumper and power cycle the board. .. _lpclink2-jlink-onboard-debug-probe: LPC-Link2 J-Link Onboard Debug Probe -************************************ +==================================== -The LPC-Link2 J-Link is an onboard debug probe and usb-to-serial adapter -supported on many NXP LPC and i.MX RT development boards. +.. note:: On some boards, the J-Link probe firmware will no longer power the + board via the USB debug port. On these boards, an alternative method + of powering the board must be used when this firmware is programmed. -This debug probe is compatible with the following debug host tools: +This debug probe firmware provides a JLink compatible debug interface, +as well as a USB-Serial adapter. It is compatible with the following debug host +tools: - :ref:`jlink-debug-host-tools` -This probe is realized by programming the LPC-Link2 microcontroller with J-Link -LPC-Link2 firmware. Download and install `LPCScrypt`_ to get the firmware and -programming scripts. +After installing the LPCScrypt host tools, the firmware may be updated to +use CMSIS-DAP firmware with the following steps: .. note:: Verify the firmware supports your board by visiting `Firmware for LPCXpresso`_ 1. Put the LPC-Link2 microcontroller into DFU boot mode by attaching the DFU - jumper, then powering up the board. + jumper, then then connecting to the USB debug port on the board. This + jumper is connected to ``P2_6`` on the LPC4322 SOC. -#. Run the ``program_JLINK`` script. +#. Run the ``program_JLINK`` script, found in the installed LPCScrypt ``scripts`` + folder. #. Remove the DFU jumper and power cycle the board. +.. _lpclink2-daplink-onboard-debug-probe: + +LPC-Link2 DAPLink Onboard Debug Probe +===================================== + +The LPC-Link2 DAPLink firmware is the default firmware shipped on LPC-Link2 +based boards, but is not the recommended firmware. Users should update to +the :ref:`lpclink2-cmsis-onboard-debug-probe` firmware following the +instructions provided above. For details on programming the DAPLink firmware, +see `NXP AN13206`_. + +.. _opensda-onboard-debug-probe: + +OpenSDA Onboard Debug Probe +*************************** + +The OpenSDA onboard debug probe is based on the NXP MK20 SOC. It features +drag and drop programming supports, and supports the following debug firmwares: + +- :ref:`opensda-daplink-onboard-debug-probe` (default firmware) +- :ref:`opensda-jlink-onboard-debug-probe` + .. _opensda-daplink-onboard-debug-probe: OpenSDA DAPLink Onboard Debug Probe -*********************************** - -The OpenSDA DAPLink is an onboard debug probe and usb-to-serial adapter -supported on many NXP Kinetis and i.MX RT development boards. It also includes -drag-and-drop flash programming support. +=================================== -This debug probe is compatible with the following debug host tools: +This debug probe firmware is compatible with the following debug host tools: - :ref:`pyocd-debug-host-tools` - :ref:`openocd-debug-host-tools` +- :ref:`linkserver-debug-host-tools` This probe is realized by programming the OpenSDA microcontroller with DAPLink OpenSDA firmware. NXP provides `OpenSDA DAPLink Board-Specific Firmwares`_. @@ -199,7 +285,10 @@ As with all OpenSDA debug probes, the steps for programming the firmware are: microcontroller of your Zephyr application. #. After you power on the board, release the reset button. A USB mass storage - device called **BOOTLOADER** or **MAINTENANCE** will enumerate. + device called **BOOTLOADER** or **MAINTENANCE** will enumerate. If the + enumerated device is named **BOOTLOADER**, please first update the booloader + to the latest revision by following the instructions for a + `DAPLink Bootloader Update`_. #. Copy the OpenSDA firmware binary to the USB mass storage device. @@ -211,10 +300,7 @@ As with all OpenSDA debug probes, the steps for programming the firmware are: .. _opensda-jlink-onboard-debug-probe: OpenSDA J-Link Onboard Debug Probe -********************************** - -The OpenSDA J-Link is an onboard debug probe and usb-to-serial adapter -supported on many NXP Kinetis and i.MX RT development boards. +================================== This debug probe is compatible with the following debug host tools: @@ -232,12 +318,15 @@ Install the debug host tools before you program the firmware. As with all OpenSDA debug probes, the steps for programming the firmware are: 1. Put the OpenSDA microcontroller into bootloader mode by holding the reset - button while you power on the board. Note that "bootloader mode" in this - context applies to the OpenSDA microcontroller itself, not the target - microcontroller of your Zephyr application. + button while you plug a USB into the board's USB debug port. Note that + "bootloader mode" in this context applies to the OpenSDA microcontroller + itself, not the target microcontroller of your Zephyr application. #. After you power on the board, release the reset button. A USB mass storage - device called **BOOTLOADER** or **MAINTENANCE** will enumerate. + device called **BOOTLOADER** or **MAINTENANCE** will enumerate. If the + enumerated device is named **BOOTLOADER**, please first update the booloader + to the latest revision by following the instructions for a + `DAPLink Bootloader Update`_. #. Copy the OpenSDA firmware binary to the USB mass storage device. @@ -421,3 +510,9 @@ the firmware. .. _NXP S32 Debug Probe: https://www.nxp.com/design/software/automotive-software-and-tools/s32-debug-probe:S32-DP + +.. _NXP AN13206: + https://www.nxp.com/docs/en/application-note/AN13206.pdf + +.. _DAPLink Bootloader Update: + https://os.mbed.com/blog/entry/DAPLink-bootloader-update/ diff --git a/doc/develop/languages/cpp/index.rst b/doc/develop/languages/cpp/index.rst index 492872d7e9ca4..d075a47319b29 100644 --- a/doc/develop/languages/cpp/index.rst +++ b/doc/develop/languages/cpp/index.rst @@ -121,5 +121,133 @@ library can select, from its config, compatible C++ standard library unless the Kconfig symbol for a specific C++ standard library is selected. +Header files and incompatibilities between C and C++ +**************************************************** + +To interact with each other, C and C++ must share code through header +files: data structures, macros, static functions,... While C and C++ +have a large overlap, they're different languages with `known +incompatibilities`_. C is not just a C++ subset. Standard levels (e.g.: +"C+11") add another level of complexity as new features are often +inspired by and copied from the other language but many years later and +with subtle differences. Making things more complex, compilers often +offer early prototypes of features before they become +standardized. Standards can have ambiguities interpreted differently by +different compilers. Compilers can have bugs and these may need +workarounds. To help with this, many projects restrict themselves to a +limited number of toolchains. Zephyr does not. + +These compatibility issues affect header files dis-proportionally. Not +just because they have to be compatible between C and C++, but also +because they end up being compiled in a surprisingly high number of other +source files due to *indirect* inclusion and the `lack of structure and +headers organization`_ that is typical in real-world projects. So, header +files are exposed to a much larger variety of toolchains and project +configurations. +Adding more constraints, the Zephyr project has demanding policies +with respect to code style, compiler warnings, static analyzers and +standard compliance (e.g.: MISRA). + +Put together, all these constraints can make writing header files very +challenging. The purpose of this section is to document some best "header +practices" and lessons learned in a Zephyr-specific context. While a lot +of the information here is not Zephyr-specific, this section is not a +substitute for knowledge of C/C++ standards, textbooks and other +references. + +Testing +------- + +Fortunately, the Zephyr project has an extensive test and CI +infrastructure that provides coverage baselines, catches issues early, +enforces policies and maintains such combinatorial explosions under some +control. The ``tests/lib/cpp/cxx/`` are very useful in this context +because their ``testcase.yaml`` configuration lets ``twister`` iterate +quickly over a range of ``-std`` parameters: ``-std=c++98``, +``-std=c++11``, etc. + +Keep in mind unused macros are not compiled. + +Designated initializers +----------------------- + +Initialization macros are common in header files as they help reduce +boilerplate code. C99 added initialization of ``struct`` and ``union`` +types by "designated" member names instead of a list of *bare* +expressions. Some GCC versions support designated initializers even in +their C90 mode. + +When used at a simple level, designated initializers are less +error-prone, more readable and more flexible. On the other hand, C99 +allowed a surprisingly large and lax set of possibilities: designated +initializers can be out of order, duplicated, "nested" (``.a.x =``), +various other braces can be omitted, designated initializers and not can +be mixed, etc. + +Twenty years later, C++20 added designated initializers to C++ but in +much more restricted way; partly because a C++ ``struct`` is actually a +``class``. As described in the C++ proposal number P0329 (which compares +with C) or in any complete C++ reference, a mix is not allowed and +initializers must be in order (gaps are allowed). + +Interestingly, the new restrictions in C++20 can cause ``gcc -std=c++20`` +to fail to compile code that successfully compiles with +``gcc -std=c++17``. For example, ``gcc -std=c++17`` and older allow the +C-style mix of initializers and bare expressions. This fails to compile +with using ``gcc -std=c++20`` *with the same GCC version*. + +Recommendation: to maximize compatibility across different C and C++ +toolchains and standards, designated initializers in Zephyr header files +should follow all C++20 rules and restrictions. Non-designated, pre-C99 +initialization offers more compatibility and is also allowed but +designated initialization is the more readable and preferred code +style. In any case, both styles must never be mixed in the same +initializer. + +Warning: successful compilation is not the end of the incompatibility +story. For instance, the *evaluation order* of initializer expressions is +unspecified in C99! It is the (expected) left-to-right order in +C++20. Other standard revisions may vary. In doubt, do not rely on +evaluation order (here and elsewhere). + +Anonymous unions +---------------- + +Anonymous unions (a.k.a. "unnamed" unions) seem to have been part of C++ +from its very beginning. They were not officially added to C until C11. +As usual, there are differences between C and C++. For instance, C +supports anonymous unions only as a member of an enclosing ``struct`` or +``union``, empty lists ``{ }`` have always been allowed in C++ but they +require C23, etc. + +When initializing anonymous members, the expression can be enclosed in +braces or not. It can be either designated or bare. For maximum +portability, when initializing *anonymous unions*: + +- Do *not* enclose *designated* initializers with braces. This is + required by C++20 and above which perceive such braces as mixing bare + expressions with (other) designated initializers and fails to compile. + +- Do enclose *bare* expressions with braces. This is required by C. + Maybe because C is laxer and allows many initialization possibilities + and variations, so it may need such braces to disambiguate? Note C + does allow omitting most braces in initializer expressions - but not + in this particular case of initializing anonymous unions with bare + expressions. + +Some pre-C11 GCC versions support some form of anonymous unions. They +unfortunately require enclosing their designated initializers with +braces which conflicts with this recommendation. This can be solved +with an ``#ifdef __STDC_VERSION__`` as demonstrated in Zephyr commit +`c15f029a7108 +`_ and +the corresponding code review. + + .. _`C++ Standard Library`: https://en.wikipedia.org/wiki/C%2B%2B_Standard_Library .. _`Standard Template Library (STL)`: https://en.wikipedia.org/wiki/Standard_Template_Library +.. _`known incompatibilities`: https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B +.. _`lack of structure and headers organization`: + https://github.com/zephyrproject-rtos/zephyr/issues/41543 +.. _`gcc commit [C++ PATCH] P0329R4: Designated Initialization`: + https://gcc.gnu.org/pipermail/gcc-patches/2017-November/487584.html diff --git a/doc/develop/optimizations/tools.rst b/doc/develop/optimizations/tools.rst index f892209250960..630696c9f1b42 100644 --- a/doc/develop/optimizations/tools.rst +++ b/doc/develop/optimizations/tools.rst @@ -229,32 +229,32 @@ as in the following example. Pahole will generate something similar to the output below in the console:: - /* Used at: zephyr/isr_tables.c */ - /* <80> ../include/sw_isr_table.h:30 */ - struct _isr_table_entry { - void * arg; /* 0 4 */ - void (*isr)(void *); /* 4 4 */ + /* Used at: [...]/build/zephyr/kobject_hash.c */ + /* <375> [...]/zephyr/include/zephyr/sys/dlist.h:37 */ + union { + struct _dnode * head; /* 0 4 */ + struct _dnode * next; /* 0 4 */ + }; + /* Used at: [...]/build/zephyr/kobject_hash.c */ + /* <397> [...]/zephyr/include/zephyr/sys/dlist.h:36 */ + struct _dnode { + union { + struct _dnode * head; /* 0 4 */ + struct _dnode * next; /* 0 4 */ + }; /* 0 4 */ + union { + struct _dnode * tail; /* 4 4 */ + struct _dnode * prev; /* 4 4 */ + }; /* 4 4 */ /* size: 8, cachelines: 1, members: 2 */ /* last cacheline: 8 bytes */ }; - /* Used at: zephyr/isr_tables.c */ - /* ../include/arch/arm/aarch32/cortex_m/mpu/arm_mpu_v7m.h:134 */ - struct arm_mpu_region_attr { - uint32_t rasr; /* 0 4 */ - - /* size: 4, cachelines: 1, members: 1 */ - /* last cacheline: 4 bytes */ - }; - /* Used at: zephyr/isr_tables.c */ - /* <112> ../include/arch/arm/aarch32/cortex_m/mpu/arm_mpu.h:24 */ - struct arm_mpu_region { - uint32_t base; /* 0 4 */ - const char * name; /* 4 4 */ - arm_mpu_region_attr_t attr; /* 8 4 */ - - /* size: 12, cachelines: 1, members: 3 */ - /* last cacheline: 12 bytes */ + /* Used at: [...]/build/zephyr/kobject_hash.c */ + /* <3b7> [...]/zephyr/include/zephyr/sys/dlist.h:41 */ + union { + struct _dnode * tail; /* 0 4 */ + struct _dnode * prev; /* 0 4 */ }; ... ... diff --git a/doc/develop/test/bsim.rst b/doc/develop/test/bsim.rst index d2f98295dc76a..0bdc7d0fecc19 100644 --- a/doc/develop/test/bsim.rst +++ b/doc/develop/test/bsim.rst @@ -21,7 +21,8 @@ to simulate the radio channel. In the BabbleSim documentation you can find more information on how to `get `_ and `build `_ the simulator. -In the :ref:`nrf52_bsim` and :ref:`nrf5340bsim` boards documentation +In the :ref:`nrf52_bsim`, :ref:`nrf5340bsim`, +and :ref:`nrf54l15bsim` boards documentation you can find more information about how to build Zephyr targeting these particular boards, and a few examples. @@ -67,8 +68,9 @@ found in the :ref:`bsim boards tests section`. Test coverage and BabbleSim *************************** -As the :ref:`nrf52_bsim` and :ref:`nrf5340bsim` boards are based on the -POSIX architecture, you can easily collect test coverage information. +As the :ref:`nrf52_bsim` and :ref:`nrf5340bsim`, and +:ref:`nrf54l15bsim` boards are based on the POSIX architecture, you can easily collect +test coverage information. You can use the script :zephyr_file:`tests/bsim/generate_coverage_report.sh` to generate an html coverage report from tests. diff --git a/doc/develop/test/twister.rst b/doc/develop/test/twister.rst index 4f0169ecec69b..99a4e546e62f9 100644 --- a/doc/develop/test/twister.rst +++ b/doc/develop/test/twister.rst @@ -504,16 +504,55 @@ harness_config: The regular expression with named subgroups to match data fields at the test's output lines where the test provides some custom data for further analysis. These records will be written into the build - directory 'recording.csv' file as well as 'recording' property - of the test suite object in 'twister.json'. + directory ``recording.csv`` file as well as ``recording`` property + of the test suite object in ``twister.json``. - For example, to extract three data fields 'metric', 'cycles', 'nanoseconds': + For example, to extract three data fields ``metric``, ``cycles``, + ``nanoseconds``: .. code-block:: yaml record: regex: "(?P.*):(?P.*) cycles, (?P.*) ns" + as_json: (optional) + Data fields, extracted by the regular expression into named subgroups, + which will be additionally parsed as JSON encoded strings and written + into ``twister.json`` as nested ``recording`` object properties. + The corresponding ``recording.csv`` columns will contain strings as-is. + + Using this option, a test log can convey layered data structures + passed from the test image for further analysis with summary results, + traces, statistics, etc. + + For example, this configuration: + + .. code-block:: yaml + + record: + regex: "RECORD:(?P.*):DATA:(?P.*)" + as_json: [metrics] + + when matched to a test log string: + + .. code-block:: none + + RECORD:jitter_drift:DATA:{"rollovers":0, "mean_us":1000.0} + + will be reported in ``twister.json`` as: + + .. code-block:: json + + "recording":[ + { + "type":"jitter_drift", + "metrics":{ + "rollovers":0, + "mean_us":1000.0 + } + } + ] + fixture: Specify a test case dependency on an external device(e.g., sensor), and identify setups that fulfill this dependency. It depends on @@ -1082,6 +1121,10 @@ can be used multiple times and all given fixtures will be appended as a list. An given fixtures will be assigned to all boards, this means that all boards set by current twister command can run those testcases which request the same fixtures. +Some fixtures allow for configuration strings to be appended, separated from the +fixture name by a ``:``. Only the fixture name is matched against the fixtures +requested by testcases. + Notes +++++ @@ -1347,12 +1390,6 @@ To execute a Robot test suite with twister, run the following command: python .\scripts\twister --platform hifive1 --test samples/subsys/shell/shell_module/sample.shell.shell_module.robot -It's also possible to run it by `west` directly, with: - -.. code-block:: bash - - $ ROBOT_FILES=shell_module.robot west build -p -b hifive1 -s samples/subsys/shell/shell_module -t run_renode_test - Writing Robot tests =================== diff --git a/doc/develop/test/ztest.rst b/doc/develop/test/ztest.rst index 124fd415c2306..e8bf8f43f0715 100644 --- a/doc/develop/test/ztest.rst +++ b/doc/develop/test/ztest.rst @@ -351,6 +351,20 @@ efforts into the specific module in question. This will speed up testing since only the module will have to be compiled in, and the tested functions will be called directly. +Examples of unit tests can be found in the :zephyr_file:`tests/unit/` folder. +In order to declare the unit tests present in a source folder, you need to add +the relevant source files to the ``testbinary`` target from the CMake +:zephyr_file:`unittest ` component. See a minimal +example below: + +.. code-block:: cmake + + cmake_minimum_required(VERSION 3.20.0) + + project(app) + find_package(Zephyr COMPONENTS unittest REQUIRED HINTS $ENV{ZEPHYR_BASE}) + target_sources(testbinary PRIVATE main.c) + Since you won't be including basic kernel data structures that most code depends on, you have to provide function stubs in the test. Ztest provides some helpers for mocking functions, as demonstrated below. @@ -361,7 +375,7 @@ interaction with an object occurred, and if required, to assert the order of that interaction. Best practices for declaring the test suite -=========================================== +******************************************* *twister* and other validation tools need to obtain the list of subcases that a Zephyr *ztest* test image will expose. @@ -443,9 +457,9 @@ Configuration Static configuration of Ztress contains: - - :c:macro:`ZTRESS_MAX_THREADS` - number of supported threads. - - :c:macro:`ZTRESS_STACK_SIZE` - Stack size of created threads. - - :c:macro:`ZTRESS_REPORT_PROGRESS_MS` - Test progress report interval. + - :kconfig:option:`CONFIG_ZTRESS_MAX_THREADS` - number of supported threads. + - :kconfig:option:`CONFIG_ZTRESS_STACK_SIZE` - Stack size of created threads. + - :kconfig:option:`CONFIG_ZTRESS_REPORT_PROGRESS_MS` - Test progress report interval. API reference ************* diff --git a/doc/develop/toolchains/designware_arc_mwdt.rst b/doc/develop/toolchains/designware_arc_mwdt.rst index 24d5d53dc1b22..f41976c8c9800 100644 --- a/doc/develop/toolchains/designware_arc_mwdt.rst +++ b/doc/develop/toolchains/designware_arc_mwdt.rst @@ -13,6 +13,9 @@ DesignWare ARC MetaWare Development Toolkit (MWDT) Even though ARC MWDT toolchain is used for Zephyr RTOS build, still the GNU preprocessor & GNU objcopy might be used for some steps like device tree preprocessing and ``.bin`` file generation. We used Zephyr SDK as a source of these ARC GNU tools as well. + To setup ARC GNU toolchain please use SDK Bundle (Full or Minimal) instead of manual installation + of separate tarballs. It installs and registers toolchain and host tools in the system, + that allows you to avoid toolchain related issues while building Zephyr. #. :ref:`Set these environment variables `: diff --git a/doc/develop/tools/clion.rst b/doc/develop/tools/clion.rst index d72e2ed28d6a2..2bb5cb56995bc 100644 --- a/doc/develop/tools/clion.rst +++ b/doc/develop/tools/clion.rst @@ -58,10 +58,12 @@ not happen, go to :menuselection:`Settings --> Build, Execution, Deployment --> #. Click :menuselection:`Add environment --> From file` and select ``..\.venv\Scripts\activate.bat``. - .. figure:: img/clion_toolchain_mingw.webp - :width: 600px - :align: center - :alt: MinGW toolchain with environment script + .. only:: html + + .. figure:: img/clion_toolchain_mingw.webp + :width: 600px + :align: center + :alt: MinGW toolchain with environment script Click :guilabel:`Apply` to save the changes. @@ -72,10 +74,12 @@ not happen, go to :menuselection:`Settings --> Build, Execution, Deployment --> -DBOARD=nrf52840dk/nrf52840 - .. figure:: img/clion_cmakeprofile.webp - :width: 600px - :align: center - :alt: CMake profile + .. only:: html + + .. figure:: img/clion_cmakeprofile.webp + :width: 600px + :align: center + :alt: CMake profile #. Click :guilabel:`Apply` to save the changes. @@ -166,17 +170,21 @@ your setup is different, make sure to adjust the configuration settings accordin * - :guilabel:`TCP/IP port` - Auto - .. figure:: img/clion_gdbserverconfig.webp - :width: 500px - :align: center - :alt: Embedded GDB server configuration + .. only:: html + + .. figure:: img/clion_gdbserverconfig.webp + :width: 500px + :align: center + :alt: Embedded GDB server configuration #. Click :guilabel:`Next` to set the Segger J-Link parameters. - .. figure:: img/clion_segger_settings.webp - :width: 500px - :align: center - :alt: Segger J-Link parameters + .. only:: html + + .. figure:: img/clion_segger_settings.webp + :width: 500px + :align: center + :alt: Segger J-Link parameters #. Click :guilabel:`Create` when ready. @@ -193,10 +201,12 @@ Start debugging Zephyr tasks are listed in the :guilabel:`Threads & Variables` pane. You can switch between them and inspect the variables for each task. - .. figure:: img/clion_debug_threads.webp - :width: 800px - :align: center - :alt: Viewing Zephyr tasks during a debug session + .. only:: html + + .. figure:: img/clion_debug_threads.webp + :width: 800px + :align: center + :alt: Viewing Zephyr tasks during a debug session Refer to `CLion web help`_ for detailed description of the IDE debug capabilities. diff --git a/doc/develop/west/build-flash-debug.rst b/doc/develop/west/build-flash-debug.rst index 8356d95cade64..75db9a8a90b6d 100644 --- a/doc/develop/west/build-flash-debug.rst +++ b/doc/develop/west/build-flash-debug.rst @@ -698,6 +698,87 @@ determined by the imported subclasses of ``ZephyrBinaryRunner``. runner implementations are in other submodules, such as ``runners.nrfjprog``, ``runners.openocd``, etc. +Running Robot Framework tests: ``west robot`` +********************************************* + +.. tip:: Run ``west robot -h`` for additional help. + +Basics +====== + +Currently the command supports only one runner which is using ``renode-test``, +(essentially a wrapper for running Robot tests in Renode), but can be +easily extended by adding other runners. + +From a Zephyr build directory, to run a Robot test suite:: + + west robot --runner=renode-robot --testsuite path/to/testsuite.robot + +This will run all tests from testsuite.robot and print output provided +by Robot Framework. + +To pass additional parameters to Renode use ``--renode-robot-args`` switch. +For example to show Renode logs in addition to Robot Framework's output: + + west robot --runner=renode-robot --testsuite path/to/testsuite.robot --renode-robot-arg="--show-log" + +Runner-Specific Overrides +========================= + +To view all of the available options for the Robot runners your board +supports, as well as their usage information, use ``--context`` (or +``-H``):: + + west robot --runner=renode-robot --context + + +To view all available options "renode-test" runner supports, use:: + + west robot --runner=renode-robot --renode-robot-help + +Simulating a board with: ``west simulate`` +****************************************** + +Basics +====== + +Currently the command supports only one runner which is using Renode, +but can be easily extended by adding other runners. + +From a Zephyr build directory, to run the built binary:: + + west simulate --runner=renode + +This will start Renode and configure simulation based on a default ``.resc`` script +for the current platform with the zephyr.elf file loaded by default. The simulation +then can be started by typing "start" or "s" in Renode's Monitor. This can also be +done by passing a command to Renode, using an argument provided by the runner: + + west simulate --runner=renode --renode-command start + +To pass an argument to Renode itself, for example to start Renode in console mode +intead of a separate window: + + west simulate --runner=renode --renode-arg="--console" + +From that point on Renode can be used normally in both console and window modes. +For details on using Renode see `Renode - documentation`_. + +.. _Renode - documentation: + http://docs.renode.io + +Runner-Specific Overrides +========================= + +To view all of the available options supported by the runners, as well +as their usage information, use ``--context`` (or``-H``):: + + west simulate --runner=renode --context + +To view all available options Renode supports, use:: + + west simulate --runner=renode --renode-help + Hacking ******* diff --git a/doc/glossary.rst b/doc/glossary.rst index 240727d9e2438..e9e892320c44f 100644 --- a/doc/glossary.rst +++ b/doc/glossary.rst @@ -140,6 +140,10 @@ Glossary of Terms A number of different :term:`SoCs ` that share similar characteristics and features, and that the vendor typically names and markets together. + subsystem + A subsystem refers to a logically distinct part of the operating system + that handles specific functionality or provides certain services. + system power state System power states describe the power consumption of the system as a whole. System power states are represented by :c:enum:`pm_state`. diff --git a/doc/hardware/arch/arm_cortex_m.rst b/doc/hardware/arch/arm_cortex_m.rst index eac559d238deb..d0c9fcec71345 100644 --- a/doc/hardware/arch/arm_cortex_m.rst +++ b/doc/hardware/arch/arm_cortex_m.rst @@ -169,7 +169,7 @@ PendSV exception return sequence restores the new thread's caller-saved register return address, as part of unstacking the exception stack frame. The implementation of the context-switch mechanism is present in -:file:`arch/arm/core/swap_helper.S`. +:file:`arch/arm/core/cortex_m/swap_helper.S`. Stack limit checking (Arm v8-M) ------------------------------- @@ -262,7 +262,7 @@ interrupt. If the ZLI feature is enabled in Mainline Cortex-M builds (see * Regular HW interrupts are assigned priority levels lower than SVC. The priority level configuration in Cortex-M is implemented in -:file:`include/arch/arm/exception.h`. +:file:`include/zephyr/arch/arm/cortex_m/exception.h`. Locking and unlocking IRQs -------------------------- @@ -337,7 +337,7 @@ CPU Idling The Cortex-M architecture port implements both k_cpu_idle() and k_cpu_atomic_idle(). The implementation is present in -:file:`arch/arm/core/cpu_idle.S`. +:file:`arch/arm/core/cortex_m/cpu_idle.c`. In both implementations, the processor will attempt to put the core to low power mode. @@ -444,7 +444,7 @@ are programmed during system boot. ``zephyr,memory-attr`` defining the MPU permissions for the memory region. See the next section for more details. -The above MPU regions are defined in :file:`soc/arm/common/cortex_m/arm_mpu_regions.c`. +The above MPU regions are defined in :file:`arch/arm/core/mpu/arm_mpu_regions.c`. Alternative MPU configurations are allowed by enabling :kconfig:option:`CONFIG_CPU_HAS_CUSTOM_FIXED_SOC_MPU_REGIONS`. When enabled, this option signifies that the Cortex-M SoC will define and configure its own fixed MPU regions in the SoC definition. @@ -618,7 +618,7 @@ Linking Cortex-M applications ***************************** Most Cortex-M platforms make use of the default Cortex-M -GCC linker script in :file:`include/arch/arm/cortex-m/scripts/linked.ld`, +GCC linker script in :file:`include/zephyr/arch/arm/cortex_m/scripts/linker.ld`, although it is possible for platforms to use a custom linker script as well. diff --git a/doc/hardware/peripherals/can/shell.rst b/doc/hardware/peripherals/can/shell.rst index d10759ac30246..0457203438d7e 100644 --- a/doc/hardware/peripherals/can/shell.rst +++ b/doc/hardware/peripherals/can/shell.rst @@ -101,7 +101,7 @@ stopping the processing of CAN frames. .. note:: The CAN controller mode and timing can only be changed while the CAN controller is stopped, which is the initial setting upon boot-up. The initial CAN controller mode is set to ``normal`` and the - initial timing is set according to the ``bus-speed``, ``sample-point``, ``bus-speed-data``, and + initial timing is set according to the ``bitrate``, ``sample-point``, ``bitrate-data``, and ``sample-point-data`` :ref:`devicetree` properties. Timing @@ -186,16 +186,20 @@ Received CAN frames matching the added filter(s) are printed to the shell. A few .. code-block:: console - # Flags ID Size Data bytes - -- 010 [8] 01 02 03 04 05 06 07 08 - B- 010 [08] 01 02 03 04 05 06 07 08 - BP 010 [03] 01 aa bb - -- 00000010 [0] - -- 010 [1] 20 - -- 010 [8] remote transmission request + # Dev Flags ID Size Data bytes + can0 -- 010 [8] 01 02 03 04 05 06 07 08 + can0 B- 010 [08] 01 02 03 04 05 06 07 08 + can0 BP 010 [03] 01 aa bb + can0 -- 00000010 [0] + can0 -- 010 [1] 20 + can0 -- 010 [8] remote transmission request The columns have the following meaning: +* Dev + + * Name of the device receiving the frame. + * Flags * ``B``: The frame has the CAN FD Baud Rate Switch (BRS) flag set. diff --git a/doc/hardware/peripherals/charger.rst b/doc/hardware/peripherals/charger.rst index 0198fe11f6567..e0285d036d0e1 100644 --- a/doc/hardware/peripherals/charger.rst +++ b/doc/hardware/peripherals/charger.rst @@ -5,6 +5,18 @@ Chargers The charger subsystem exposes an API to uniformly access battery charger devices. +A charger device, or charger peripheral, is a device used to take external power provided to the +system as an input and provide power as an output downstream to the battery pack(s) and system. +The charger device can exist as a module, an integrated circuit, or as a functional block in a power +management integrated circuit (PMIC). + +The action of charging a battery pack is referred to as a charge cycle. When the charge cycle is +executed the battery pack is charged according to the charge profile configured on the charger +device. The charge profile is defined in the battery pack's specification that is provided by the +manufacturer. On charger devices with a control port, the charge profile can be configured by the +host controller by setting the relevant properties, and can be adjusted at runtime to respond to +environmental changes. + Basic Operation *************** diff --git a/doc/hardware/peripherals/index.rst b/doc/hardware/peripherals/index.rst index cd75fee037105..9889ca9ac2cb4 100644 --- a/doc/hardware/peripherals/index.rst +++ b/doc/hardware/peripherals/index.rst @@ -51,7 +51,7 @@ Peripherals reset.rst retained_mem.rst sdhc.rst - sensor.rst + sensor/index.rst spi.rst smbus.rst uart.rst diff --git a/doc/hardware/peripherals/sensor.rst b/doc/hardware/peripherals/sensor.rst deleted file mode 100644 index 5c7817b627bbb..0000000000000 --- a/doc/hardware/peripherals/sensor.rst +++ /dev/null @@ -1,231 +0,0 @@ -.. _sensor_api: - -Sensors -####### - -The sensor subsystem exposes an API to uniformly access sensor devices. -Common operations are: reading data and executing code when specific -conditions are met. - -Basic Operation -*************** - -Channels -======== - -Fundamentally, a channel is a quantity that a sensor device can measure. - -Sensors can have multiple channels, either to represent different axes of -the same physical property (e.g. acceleration); or because they can measure -different properties altogether (ambient temperature, pressure and -humidity). Complex sensors cover both cases, so a single device can expose -three acceleration channels and a temperature one. - -It is imperative that all sensors that support a given channel express -results in the same unit of measurement. Consult the -:ref:`sensor_api_reference` for all supported channels, along with their -description and units of measurement: - -Values -====== - -Sensor stable APIs return results as :c:struct:`sensor_value`. This -representation avoids use of floating point values as they may not be -supported on certain setups. - -A newer experimental (may change) API that can interpret raw sensor data is -available in parallel. This new API exposes raw encoded sensor data to the -application and provides a separate decoder to convert the data to a Q31 format -which is compatible with the Zephyr :ref:`zdsp_api`. The values represented are -in the range of (-1.0, 1.0) and require a shift operation in order to scale -them to their SI unit values. See :ref:`Async Read` for more information. - -Fetching Values -=============== - -Getting a reading from a sensor requires two operations. First, an -application instructs the driver to fetch a sample of all its channels. -Then, individual channels may be read. In the case of channels with -multiple axes, they can be read in a single operation by supplying -the corresponding :literal:`_XYZ` channel type and a buffer of 3 -:c:struct:`sensor_value` objects. This approach ensures consistency -of channels between reads and efficiency of communication by issuing a -single transaction on the underlying bus. - -Below is an example illustrating the usage of the BME280 sensor, which -measures ambient temperature and atmospheric pressure. Note that -:c:func:`sensor_sample_fetch` is only called once, as it reads and -compensates data for both channels. - -.. literalinclude:: ../../../samples/sensor/bme280/src/main.c - :language: c - :lines: 12- - :linenos: - -.. _Async Read: - -Async Read -========== - -To enable the async APIs, use :kconfig:option:`CONFIG_SENSOR_ASYNC_API`. - -Reading the sensors leverages the :ref:`rtio_api` subsystem. Applications -gain control of the data processing thread and even memory management. In order -to get started with reading the sensors, an IODev must be created via the -:c:macro:`SENSOR_DT_READ_IODEV`. Next, an RTIO context must be created. It is -strongly suggested that this context is created with a memory pool via -:c:macro:`RTIO_DEFINE_WITH_MEMPOOL`. - -.. code-block:: C - - #include - #include - #include - - static const struct device *lid_accel = DEVICE_DT_GET(DT_ALIAS(lid_accel)); - SENSOR_DT_READ_IODEV(lid_accel_iodev, DT_ALIAS(lid_accel), SENSOR_CHAN_ACCEL_XYZ); - - RTIO_DEFINE_WITH_MEMPOOL(sensors_rtio, - 4, /* submission queue size */ - 4, /* completion queue size */ - 16, /* number of memory blocks */ - 32, /* size of each memory block */ - 4 /* memory alignment */ - ); - -To trigger a read, the application simply needs to call :c:func:`sensor_read` -and pass the relevant IODev and RTIO context. Getting the result is done like -any other RTIO operation, by waiting on a completion queue event (CQE). In -order to help reduce some boilerplate code, the helper function -:c:func:`sensor_processing_with_callback` is provided. When called, the -function will block until a CQE becomes available from the provided RTIO -context. The appropriate buffers are extracted and the callback is called. -Once the callback is done, the memory is reclaimed by the memorypool. This -looks like: - -.. code-block:: C - - static void sensor_processing_callback(int result, uint8_t *buf, - uint32_t buf_len, void *userdata) { - // Process the data... - } - - static void sensor_processing_thread(void *, void *, void *) { - while (true) { - sensor_processing_with_callback(&sensors_rtio, sensor_processing_callback); - } - } - K_THREAD_DEFINE(sensor_processing_tid, 1024, sensor_processing_thread, - NULL, NULL, NULL, 0, 0, 0); - -.. note:: - Helper functions to create custom length IODev nodes and ones that don't - have static bindings will be added soon. - -Processing the Data -=================== - -Once data collection completes and the processing callback was called, -processing the data is done via the :c:struct:`sensor_decoder_api`. The API -provides a means for applications to control *when* to process the data and how -many resources to dedicate to the processing. The API is entirely self -contained and requires no system calls (even when -:kconfig:option:`CONFIG_USERSPACE` is enabled). - -.. code-block:: C - - static struct sensor_decoder_api *lid_accel_decoder = SENSOR_DECODER_DT_GET(DT_ALIAS(lid_accel)); - - static void sensor_processing_callback(int result, uint8_t *buf, - uint32_t buf_len, void *userdata) { - uint64_t timestamp; - sensor_frame_iterator_t fit = {0}; - sensor_channel_iterator_t cit = {0}; - enum sensor_channel channels[3]; - q31_t values[3]; - int8_t shift[3]; - - lid_accel_decoder->get_timestamp(buf, ×tamp); - lid_accel_decoder->decode(buf, &fit, &cit, channels, values, 3); - - /* Values are now in q31_t format, we're going to convert them to micro-units */ - - /* First, we need to know by how much to shift the values */ - lid_accel_decoder->get_shift(buf, channels[0], &shift[0]); - lid_accel_decoder->get_shift(buf, channels[1], &shift[1]); - lid_accel_decoder->get_shift(buf, channels[2], &shift[2]); - - /* Shift the values to get the SI units */ - int64_t scaled_values[] = { - (int64_t)values[0] << shift[0], - (int64_t)values[1] << shift[1], - (int64_t)values[2] << shift[2], - }; - - /* - * FIELD_GET(GENMASK64(63, 31), scaled_values[]) - will give the integer value - * FIELD_GET(GENMASK64(30, 0), scaled_values[]) / INT32_MAX - is the decimal value - */ - } - -Configuration and Attributes -**************************** - -Setting the communication bus and address is considered the most basic -configuration for sensor devices. This setting is done at compile time, via -the configuration menu. If the sensor supports interrupts, the interrupt -lines and triggering parameters described below are also configured at -compile time. - -Alongside these communication parameters, sensor chips typically expose -multiple parameters that control the accuracy and frequency of measurement. -In compliance with Zephyr's design goals, most of these values are -statically configured at compile time. - -However, certain parameters could require runtime configuration, for -example, threshold values for interrupts. These values are configured via -attributes. The example in the following section showcases a sensor with an -interrupt line that is triggered when the temperature crosses a threshold. -The threshold is configured at runtime using an attribute. - -Triggers -******** - -:dfn:`Triggers` in Zephyr refer to the interrupt lines of the sensor chips. -Many sensor chips support one or more triggers. Some examples of triggers -include: new data is ready for reading, a channel value has crossed a -threshold, or the device has sensed motion. - -To configure a trigger, an application needs to supply a -:c:struct:`sensor_trigger` and a handler function. The structure contains the -trigger type and the channel on which the trigger must be configured. - -Because most sensors are connected via SPI or I2C buses, it is not possible -to communicate with them from the interrupt execution context. The -execution of the trigger handler is deferred to a thread, so that data -fetching operations are possible. A driver can spawn its own thread to fetch -data, thus ensuring minimum latency. Alternatively, multiple sensor drivers -can share a system-wide thread. The shared thread approach increases the -latency of handling interrupts but uses less memory. You can configure which -approach to follow for each driver. Most drivers can entirely disable -triggers resulting in a smaller footprint. - -The following example contains a trigger fired whenever temperature crosses -the 26 degree Celsius threshold. It also samples the temperature every -second. A real application would ideally disable periodic sampling in the -interest of saving power. Since the application has direct access to the -kernel config symbols, no trigger is registered when triggering was disabled -by the driver's configuration. - -.. literalinclude:: ../../../samples/sensor/mcp9808/src/main.c - :language: c - :lines: 12- - :linenos: - -.. _sensor_api_reference: - -API Reference -************** - -.. doxygengroup:: sensor_interface -.. doxygengroup:: sensor_emulator_backend diff --git a/doc/hardware/peripherals/sensor/index.rst b/doc/hardware/peripherals/sensor/index.rst new file mode 100644 index 0000000000000..ec3cf2028faa9 --- /dev/null +++ b/doc/hardware/peripherals/sensor/index.rst @@ -0,0 +1,231 @@ +.. _sensor_api: + +Sensors +####### + +The sensor subsystem exposes an API to uniformly access sensor devices. +Common operations are: reading data and executing code when specific +conditions are met. + +Basic Operation +*************** + +Channels +======== + +Fundamentally, a channel is a quantity that a sensor device can measure. + +Sensors can have multiple channels, either to represent different axes of +the same physical property (e.g. acceleration); or because they can measure +different properties altogether (ambient temperature, pressure and +humidity). Complex sensors cover both cases, so a single device can expose +three acceleration channels and a temperature one. + +It is imperative that all sensors that support a given channel express +results in the same unit of measurement. Consult the +:ref:`sensor_api_reference` for all supported channels, along with their +description and units of measurement: + +Values +====== + +Sensor stable APIs return results as :c:struct:`sensor_value`. This +representation avoids use of floating point values as they may not be +supported on certain setups. + +A newer experimental (may change) API that can interpret raw sensor data is +available in parallel. This new API exposes raw encoded sensor data to the +application and provides a separate decoder to convert the data to a Q31 format +which is compatible with the Zephyr :ref:`zdsp_api`. The values represented are +in the range of (-1.0, 1.0) and require a shift operation in order to scale +them to their SI unit values. See :ref:`Async Read` for more information. + +Fetching Values +=============== + +Getting a reading from a sensor requires two operations. First, an +application instructs the driver to fetch a sample of all its channels. +Then, individual channels may be read. In the case of channels with +multiple axes, they can be read in a single operation by supplying +the corresponding :literal:`_XYZ` channel type and a buffer of 3 +:c:struct:`sensor_value` objects. This approach ensures consistency +of channels between reads and efficiency of communication by issuing a +single transaction on the underlying bus. + +Below is an example illustrating the usage of the BME280 sensor, which +measures ambient temperature and atmospheric pressure. Note that +:c:func:`sensor_sample_fetch` is only called once, as it reads and +compensates data for both channels. + +.. literalinclude:: ../../../../samples/sensor/bme280/src/main.c + :language: c + :lines: 12- + :linenos: + +.. _Async Read: + +Async Read +========== + +To enable the async APIs, use :kconfig:option:`CONFIG_SENSOR_ASYNC_API`. + +Reading the sensors leverages the :ref:`rtio_api` subsystem. Applications +gain control of the data processing thread and even memory management. In order +to get started with reading the sensors, an IODev must be created via the +:c:macro:`SENSOR_DT_READ_IODEV`. Next, an RTIO context must be created. It is +strongly suggested that this context is created with a memory pool via +:c:macro:`RTIO_DEFINE_WITH_MEMPOOL`. + +.. code-block:: C + + #include + #include + #include + + static const struct device *lid_accel = DEVICE_DT_GET(DT_ALIAS(lid_accel)); + SENSOR_DT_READ_IODEV(lid_accel_iodev, DT_ALIAS(lid_accel), SENSOR_CHAN_ACCEL_XYZ); + + RTIO_DEFINE_WITH_MEMPOOL(sensors_rtio, + 4, /* submission queue size */ + 4, /* completion queue size */ + 16, /* number of memory blocks */ + 32, /* size of each memory block */ + 4 /* memory alignment */ + ); + +To trigger a read, the application simply needs to call :c:func:`sensor_read` +and pass the relevant IODev and RTIO context. Getting the result is done like +any other RTIO operation, by waiting on a completion queue event (CQE). In +order to help reduce some boilerplate code, the helper function +:c:func:`sensor_processing_with_callback` is provided. When called, the +function will block until a CQE becomes available from the provided RTIO +context. The appropriate buffers are extracted and the callback is called. +Once the callback is done, the memory is reclaimed by the memorypool. This +looks like: + +.. code-block:: C + + static void sensor_processing_callback(int result, uint8_t *buf, + uint32_t buf_len, void *userdata) { + // Process the data... + } + + static void sensor_processing_thread(void *, void *, void *) { + while (true) { + sensor_processing_with_callback(&sensors_rtio, sensor_processing_callback); + } + } + K_THREAD_DEFINE(sensor_processing_tid, 1024, sensor_processing_thread, + NULL, NULL, NULL, 0, 0, 0); + +.. note:: + Helper functions to create custom length IODev nodes and ones that don't + have static bindings will be added soon. + +Processing the Data +=================== + +Once data collection completes and the processing callback was called, +processing the data is done via the :c:struct:`sensor_decoder_api`. The API +provides a means for applications to control *when* to process the data and how +many resources to dedicate to the processing. The API is entirely self +contained and requires no system calls (even when +:kconfig:option:`CONFIG_USERSPACE` is enabled). + +.. code-block:: C + + static struct sensor_decoder_api *lid_accel_decoder = SENSOR_DECODER_DT_GET(DT_ALIAS(lid_accel)); + + static void sensor_processing_callback(int result, uint8_t *buf, + uint32_t buf_len, void *userdata) { + uint64_t timestamp; + sensor_frame_iterator_t fit = {0}; + sensor_channel_iterator_t cit = {0}; + enum sensor_channel channels[3]; + q31_t values[3]; + int8_t shift[3]; + + lid_accel_decoder->get_timestamp(buf, ×tamp); + lid_accel_decoder->decode(buf, &fit, &cit, channels, values, 3); + + /* Values are now in q31_t format, we're going to convert them to micro-units */ + + /* First, we need to know by how much to shift the values */ + lid_accel_decoder->get_shift(buf, channels[0], &shift[0]); + lid_accel_decoder->get_shift(buf, channels[1], &shift[1]); + lid_accel_decoder->get_shift(buf, channels[2], &shift[2]); + + /* Shift the values to get the SI units */ + int64_t scaled_values[] = { + (int64_t)values[0] << shift[0], + (int64_t)values[1] << shift[1], + (int64_t)values[2] << shift[2], + }; + + /* + * FIELD_GET(GENMASK64(63, 31), scaled_values[]) - will give the integer value + * FIELD_GET(GENMASK64(30, 0), scaled_values[]) / INT32_MAX - is the decimal value + */ + } + +Configuration and Attributes +**************************** + +Setting the communication bus and address is considered the most basic +configuration for sensor devices. This setting is done at compile time, via +the configuration menu. If the sensor supports interrupts, the interrupt +lines and triggering parameters described below are also configured at +compile time. + +Alongside these communication parameters, sensor chips typically expose +multiple parameters that control the accuracy and frequency of measurement. +In compliance with Zephyr's design goals, most of these values are +statically configured at compile time. + +However, certain parameters could require runtime configuration, for +example, threshold values for interrupts. These values are configured via +attributes. The example in the following section showcases a sensor with an +interrupt line that is triggered when the temperature crosses a threshold. +The threshold is configured at runtime using an attribute. + +Triggers +******** + +:dfn:`Triggers` in Zephyr refer to the interrupt lines of the sensor chips. +Many sensor chips support one or more triggers. Some examples of triggers +include: new data is ready for reading, a channel value has crossed a +threshold, or the device has sensed motion. + +To configure a trigger, an application needs to supply a +:c:struct:`sensor_trigger` and a handler function. The structure contains the +trigger type and the channel on which the trigger must be configured. + +Because most sensors are connected via SPI or I2C buses, it is not possible +to communicate with them from the interrupt execution context. The +execution of the trigger handler is deferred to a thread, so that data +fetching operations are possible. A driver can spawn its own thread to fetch +data, thus ensuring minimum latency. Alternatively, multiple sensor drivers +can share a system-wide thread. The shared thread approach increases the +latency of handling interrupts but uses less memory. You can configure which +approach to follow for each driver. Most drivers can entirely disable +triggers resulting in a smaller footprint. + +The following example contains a trigger fired whenever temperature crosses +the 26 degree Celsius threshold. It also samples the temperature every +second. A real application would ideally disable periodic sampling in the +interest of saving power. Since the application has direct access to the +kernel config symbols, no trigger is registered when triggering was disabled +by the driver's configuration. + +.. literalinclude:: ../../../../samples/sensor/mcp9808/src/main.c + :language: c + :lines: 12- + :linenos: + +.. _sensor_api_reference: + +API Reference +************** + +.. doxygengroup:: sensor_interface +.. doxygengroup:: sensor_emulator_backend diff --git a/doc/hardware/porting/board_porting.rst b/doc/hardware/porting/board_porting.rst index 7543e062ada3f..a2b7796ebfae5 100644 --- a/doc/hardware/porting/board_porting.rst +++ b/doc/hardware/porting/board_porting.rst @@ -488,7 +488,6 @@ controller and sets the bus speed: &can0 { status = "okay"; - bus-speed = <125000>; }; The ``&can0 { ... };`` syntax adds/overrides properties on the node with label diff --git a/doc/hardware/porting/index.rst b/doc/hardware/porting/index.rst index e6453a5ba48ac..91dc8b6ef38fd 100644 --- a/doc/hardware/porting/index.rst +++ b/doc/hardware/porting/index.rst @@ -9,5 +9,6 @@ These pages document how to port Zephyr to new hardware. :maxdepth: 1 arch.rst + soc_porting.rst board_porting.rst shields.rst diff --git a/doc/hardware/porting/soc_porting.rst b/doc/hardware/porting/soc_porting.rst new file mode 100644 index 0000000000000..5f97065734b36 --- /dev/null +++ b/doc/hardware/porting/soc_porting.rst @@ -0,0 +1,304 @@ +.. _soc_porting_guide: + +SoC Porting Guide +################### + +To add Zephyr support for a new :term:`SoC`, you need a *SoC directory* with +various files in it, and a SoC :file:`.dtsi` in +:zephyr_file:`dts//` is required. + +SoC Definitions +*************** + +It is expected that you are familiar with the board concept in Zephyr. +A high level overview of the hardware support hierarchy and terms used in the +Zephyr documentation can be seen in :ref:`hw_support_hierarchy`. + +For SoC porting, the most important terms are: + +- SoC: the exact system on a chip the board's CPU is part of. +- SoC series: a group of tightly related SoCs. +- SoC family: a wider group of SoCs with similar characteristics. +- CPU Cluster: a cluster of one or more CPU cores. +- CPU core: a particular CPU instance of a given architecture. +- Architecture: an instruction set architecture. + +Architecture +============ + +See :ref:`architecture_porting_guide`. + + +Create your SoC directory +************************* + +Each SoC must have a unique name. Use the official name given by the SoC vendor +and check that it's not already in use. In some cases someone else may have +contributed a SoC with identical name. If the SoC name is already in use, then +you should probably improve the existing SoC instead of creating a new one. +The script ``list_hardware`` can be used to retrieve a list of all SoCs known +in Zephyr, for example ``./scripts/list_hardware.py --soc-root=. --socs`` from +the Zephyr base directory for a list of names that are already in use. + +Start by creating the directory ``zephyr/soc//soc1``, where +```` is your vendor subdirectory. + +.. note:: + A ```` subdirectory is mandatory if contributing your SoC + to Zephyr, but if your SoC is placed in a local repo, then any folder + structure under ``/soc`` is permitted. + The ```` subdirectory must match a vendor defined in the list in + :zephyr_file:`dts/bindings/vendor-prefixes.txt`. If the SoC vendor does not + have a prefix in that list, then one must be created. + +.. note:: + + The SoC directory name does not need to match the name of the SoC. + Multiple SoCs can even be defined in one directory. In Zephyr, SoCs are often + organized in sub-folders in a common SoC Family or SoC Series tree. + +Your SoC directory should look like this: + +.. code-block:: none + + soc// + ├── soc.yml + ├── soc.h + ├── CMakeLists.txt + ├── Kconfig + ├── Kconfig.soc + └── Kconfig.defconfig + +Replace ```` with your SoC's name. + + +The mandatory files are: + +#. :file:`soc.yml`: a YAML file describing the high-level meta data of the + SoC such as: + - SoC name: the name of the SoC + - CPU clusters: CPU clusters if the SoC contains one or more clusters + - SoC series: the SoC series to which the SoC belong + - SoC family: the SoC family to which the series belong + +#. :file:`soc.h`: a header file which can be used to describe or provide + configuration macros for the SoC. The :file:`soc.h` will often be included in + drivers, sub-systems, boards, and other source code found in Zephyr. + +#. :file:`Kconfig.soc`: the base SoC configuration which defines a Kconfig SoC + symbol in the form of ``config SOC_`` and provides the SoC name to + the Kconfig ``SOC`` setting. + If the ``soc.yml`` describes a SoC family and series, then those must also + be defined in this file. Kconfig settings outside of the SoC tree must not be + selected. To select general Zephyr Kconfig settings the :file:`Kconfig` file + must be used. + +#. :file:`CMakeLists.txt`: CMake file loaded by the Zephyr build system. This + CMake file can define additional include paths and/or source files to be used + when a build targets the SoC. Also the base line linker script to use must be + defined. + +The optional files are: + +- :file:`Kconfig`, :file:`Kconfig.defconfig` software configuration in + :ref:`kconfig` format. These select the architecture and peripherals + available. + +Write your SoC YAML +********************* + +The SoC YAML file describes the SoC family, SoC series, and SoC at a high level. + +Detailed configurations, such as hardware description and configuration are done +in devicetree and Kconfig. + +The skeleton of a simple SoC YAML file containing just one SoC is: + +.. code-block:: yaml + + socs: + - name: + +It is possible to have multiple SoC located in the SoC folder. +For example if they belong to a common family or series it is recommended to +locate such SoC in a common tree. +Multiple SoCs and SoC series in a common folder can be described in the +:file:`soc.yml` file as: + +.. code-block:: yaml + + family: + name: + series: + - name: + socs: + - name: + cpucluster: + - name: + - name: + ... + - name: + - name: + ... + + +Write your SoC devicetree +************************* + +SoC devicetree include files are located in the :file:`/dts` folder +under a corresponding :file:`/`. + +The SoC :file:`dts///.dtsi` describes your SoC hardware in +the Devicetree Source (DTS) format and must be included by any boards which use +the SoC. + +If a highlevel :file:`.dtsi` file exists, then a good starting point is to +include this file in your :file:`.dtsi`. + +In general, :file:`.dtsi` should look like this: + +.. code-block:: devicetree + + #include /.dtsi + + / { + chosen { + /* common chosen settings for your SoC */ + }; + + cpus { + #address-cells = ; + #size-cells = ; + + cpu@0 { + device_type = "cpu"; + compatible = ""; + /* ... your CPU definitions ... */ + }; + + soc { + /* Your SoC definitions and peripherals */ + /* such as ram, clock, buses, peripherals. */ + }; + }; + +.. hint:: + It is possible to structure multiple :file:`/.dtsi` files in + sub-directories for a cleaner file system structure. For example organized + pre SoC series, like this: :file:`//.dtsi`. + + +Multiple CPU clusters +===================== + +Devicetree reflects the hardware. The memory space and peripherals available to +one CPU cluster can be very different from another CPU cluster, therefore each +CPU cluster will often have its own :file:`.dtsi` file. + +CPU cluster :file:`.dtsi` files should follow the naming scheme +:file:`_.dtsi`. A :file:`_.dtsi` file will look +similar to a SoC :file:`.dtsi` without CPU clusters. + +Write Kconfig files +******************* + +Zephyr uses the Kconfig language to configure software features. Your SoC +needs to provide some Kconfig settings before you can compile a Zephyr +application for it. + +Setting Kconfig configuration values is documented in detail in +:ref:`setting_configuration_values`. + +There is one mandatory Kconfig file in the SoC directory, and two optional +files for a SoC: + +.. code-block:: none + + soc// + ├── Kconfig.soc + ├── Kconfig + └── Kconfig.defconfig + +:file:`Kconfig.soc` + A shared Kconfig file which can be sourced both in Zephyr Kconfig and sysbuild + Kconfig trees. + + This file selects the SoC family and series in the Kconfig tree and potential + other SoC related Kconfig settings. In some cases a SOC_PART_NUMBER. + This file must not select anything outside the re-usable Kconfig SoC tree. + + A :file:`Kconfig.soc` may look like this: + + .. code-block:: kconfig + + config SOC_ + bool + + config SOC_ + bool + select SOC_SERIES_ + + config SOC + default "SoC name" if SOC_ + + Notice that ``SOC_NAME`` is a pure upper case version of the SoC name. + + The Kconfig ``SOC`` setting is globally defined as a string and therefore the + :file:`Kconfig.soc` file shall only define the default string value and not + the type. Notice that the string value must match the SoC name used in the + :file:`soc.yml` file. + +:file:`Kconfig` + Included by :zephyr_file:`soc/Kconfig`. + + This file can add Kconfig settings which are specific to the current SoC. + + The :file:`Kconfig` will often indicate given hardware support using a setting + of the form ``HAS_``. + + .. code-block:: kconfig + + config SOC_ + select ARM + select CPU_HAS_FPU + + If the setting name is identical to an existing Kconfig setting in Zephyr and + only modifies the default value of said setting, then + :file:`Kconfig.defconfig` should be used instead. + +:file:`Kconfig.defconfig` + SoC specific default values for Kconfig options. + + Not all SoCs have a :file:`Kconfig.defconfig` file. + + The entire file should be inside a pair of ``if SOC_`` / ``endif`` + or ``if SOC_SERIES_`` / ``endif``, like this: + + .. code-block:: kconfig + + if SOC_ + + config NUM_IRQS + default 32 + + endif # SOC_ + +Multiple CPU clusters +===================== + +CPU clusters must provide additional Kconfig settings in the :file:`Kconfig.soc` +file. This will usually be in the form of ``SOC__`` so for +a given ``soc1`` with two clusters ``clusterA`` and ``clusterB``, then this +will look like: + +SoC's When a SoC defines CPU cluster + + .. code-block:: kconfig + + config SOC_SOC1_CLUSTERA + bool + select SOC_SOC1 + + config SOC_SOC1_CLUSTERB + bool + select SOC_SOC1 diff --git a/doc/introduction/index.rst b/doc/introduction/index.rst index f8b841ae30022..af67331aa2991 100644 --- a/doc/introduction/index.rst +++ b/doc/introduction/index.rst @@ -23,6 +23,14 @@ The Zephyr kernel supports multiple architectures, including: The full list of supported boards based on these architectures can be found :ref:`here `. +In the context of the Zephyr OS, a :term:`subsystem` refers to a logically distinct +part of the operating system that handles specific functionality or provides +certain services. Subsystems can include components such as networking, +file systems, device driver classes, power management, and communication protocols, +among others. Each subsystem is designed to be modular and can be configured, +customized, and extended to meet the requirements of different embedded +applications. + Licensing ********* diff --git a/doc/kernel/data_structures/dlist.rst b/doc/kernel/data_structures/dlist.rst index f045c939193e2..7366d37f4f9b7 100644 --- a/doc/kernel/data_structures/dlist.rst +++ b/doc/kernel/data_structures/dlist.rst @@ -11,9 +11,9 @@ the head, tail or any internal node). To do this, the list stores two pointers per node, and thus has somewhat higher runtime code and memory space needs. -A :c:struct:`sys_dlist_t` struct may be instantiated by the user in any +A :c:type:`sys_dlist_t` struct may be instantiated by the user in any accessible memory. It must be initialized with :c:func:`sys_dlist_init` -or :c:macro:`SYS_DLIST_STATIC_INIT` before use. The :c:struct:`sys_dnode_t` struct +or :c:macro:`SYS_DLIST_STATIC_INIT` before use. The :c:type:`sys_dnode_t` struct is expected to be provided by the user for any nodes added to the list (typically embedded within the struct to be tracked, as described above). It must be initialized in zeroed/bss memory or with @@ -50,8 +50,8 @@ implementation that has zero overhead vs. the normal list processing). Double-linked List Internals ---------------------------- -Internally, the dlist implementation is minimal: the :c:struct:`sys_dlist_t` -struct contains "head" and "tail" pointer fields, the :c:struct:`sys_dnode_t` +Internally, the dlist implementation is minimal: the :c:type:`sys_dlist_t` +struct contains "head" and "tail" pointer fields, the :c:type:`sys_dnode_t` contains "prev" and "next" pointers, and no other data is stored. But in practice the two structs are internally identical, and the list struct is inserted as a node into the list itself. This allows for a diff --git a/doc/kernel/data_structures/index.rst b/doc/kernel/data_structures/index.rst index ccdc2349225fe..f7e7c5ad35422 100644 --- a/doc/kernel/data_structures/index.rst +++ b/doc/kernel/data_structures/index.rst @@ -34,3 +34,5 @@ needed will be provided by the user. spsc_pbuf.rst rbtree.rst ring_buffers.rst + mpsc_lockfree.rst + spsc_lockfree.rst diff --git a/doc/kernel/data_structures/mpsc_lockfree.rst b/doc/kernel/data_structures/mpsc_lockfree.rst new file mode 100644 index 0000000000000..6b919125166b3 --- /dev/null +++ b/doc/kernel/data_structures/mpsc_lockfree.rst @@ -0,0 +1,14 @@ +.. _mpsc_lockfree: + +Multi Producer Single Consumer Lock Free Queue +============================================== + +A :dfn:`Multi Producer Single Consumer Lock Free Queue (MPSC)` is an lockfree +intrusive queue based on atomic pointer swaps as described by Dmitry Vyukov +at `1024cores `_. + + +API Reference +************* + +.. doxygengroup:: mpsc_lockfree diff --git a/doc/kernel/data_structures/ring_buffers.rst b/doc/kernel/data_structures/ring_buffers.rst index d077cf1f21fb7..409b1c2bdc624 100644 --- a/doc/kernel/data_structures/ring_buffers.rst +++ b/doc/kernel/data_structures/ring_buffers.rst @@ -198,7 +198,7 @@ Implementation Defining a Ring Buffer ====================== -A ring buffer is defined using a variable of type :c:type:`ring_buf`. +A ring buffer is defined using a variable of type :c:struct:`ring_buf`. It must then be initialized by calling :c:func:`ring_buf_init` or :c:func:`ring_buf_item_init`. diff --git a/doc/kernel/data_structures/slist.rst b/doc/kernel/data_structures/slist.rst index c1eb062ff83df..cfffe802895ee 100644 --- a/doc/kernel/data_structures/slist.rst +++ b/doc/kernel/data_structures/slist.rst @@ -3,7 +3,7 @@ Single-linked List ================== -Zephyr provides a :c:struct:`sys_slist_t` type for storing simple +Zephyr provides a :c:type:`sys_slist_t` type for storing simple singly-linked list data (i.e. data where each list element stores a pointer to the next element, but not the previous one). This supports constant-time access to the first (head) and last (tail) elements of @@ -12,7 +12,7 @@ constant time removal of the head. Removal of subsequent nodes requires access to the "previous" pointer and thus can only be performed in linear time by searching the list. -The :c:struct:`sys_slist_t` struct may be instantiated by the user in any +The :c:type:`sys_slist_t` struct may be instantiated by the user in any accessible memory. It should be initialized with either :c:func:`sys_slist_init` or by static assignment from SYS_SLIST_STATIC_INIT before use. Its interior fields are opaque and should not be accessed @@ -21,15 +21,15 @@ by user code. The end nodes of a list may be retrieved with :c:func:`sys_slist_peek_head` and :c:func:`sys_slist_peek_tail`, which will return NULL if the list is empty, otherwise a pointer to a -:c:struct:`sys_snode_t` struct. +:c:type:`sys_snode_t` struct. -The :c:struct:`sys_snode_t` struct represents the data to be inserted. In +The :c:type:`sys_snode_t` struct represents the data to be inserted. In general, it is expected to be allocated/controlled by the user, usually embedded within a struct which is to be added to the list. The container struct pointer may be retrieved from a list node using :c:macro:`SYS_SLIST_CONTAINER`, passing it the struct name of the containing struct and the field name of the node. Internally, the -:c:struct:`sys_snode_t` struct contains only a next pointer, which may be +:c:type:`sys_snode_t` struct contains only a next pointer, which may be accessed with :c:func:`sys_slist_peek_next`. Lists may be modified by adding a single node at the head or tail with @@ -66,8 +66,8 @@ Single-linked List Internals ---------------------------- The slist code is designed to be minimal and conventional. -Internally, a :c:struct:`sys_slist_t` struct is nothing more than a pair of -"head" and "tail" pointer fields. And a :c:struct:`sys_snode_t` stores only a +Internally, a :c:type:`sys_slist_t` struct is nothing more than a pair of +"head" and "tail" pointer fields. And a :c:type:`sys_snode_t` stores only a single "next" pointer. .. figure:: slist.png @@ -101,7 +101,7 @@ Only one such variant, sflist, exists in Zephyr at the moment. Flagged List ------------ -The :c:struct:`sys_sflist_t` is implemented using the described genlist +The :c:type:`sys_sflist_t` is implemented using the described genlist template API. With the exception of symbol naming ("sflist" instead of "slist") and the additional API described next, it operates in all ways identically to the slist API. diff --git a/doc/kernel/data_structures/spsc_lockfree.rst b/doc/kernel/data_structures/spsc_lockfree.rst new file mode 100644 index 0000000000000..dcd9939112c38 --- /dev/null +++ b/doc/kernel/data_structures/spsc_lockfree.rst @@ -0,0 +1,12 @@ +.. _spsc_lockfree: + +Single Producer Single Consumer Lock Free Queue +=============================================== + +A :dfn:`Single Producer Single Consumer Lock Free Queue (MPSC)` is a lock free +atomic ring buffer based queue. + +API Reference +************* + +.. doxygengroup:: spsc_lockfree diff --git a/doc/kernel/drivers/index.rst b/doc/kernel/drivers/index.rst index 51b31de006f72..96574e0899538 100644 --- a/doc/kernel/drivers/index.rst +++ b/doc/kernel/drivers/index.rst @@ -203,7 +203,7 @@ A device-specific API definition typically looks like this: __syscall int specific_from_user(const struct device *dev, int bar); /* Only needed when extensions include syscalls */ - #include + #include A driver implementing extensions to the subsystem will define the real implementation of both the subsystem API and the specific APIs: @@ -243,7 +243,7 @@ implementation of both the subsystem API and the specific APIs: return z_impl_specific_do_that(dev, bar) } - #include + #include #endif /* CONFIG_USERSPACE */ @@ -373,6 +373,24 @@ Drivers and other system utilities can determine whether startup is still in pre-kernel states by using the :c:func:`k_is_pre_kernel` function. +Deferred initialization +*********************** + +Initialization of devices can also be deferred to a later time. In this case, +the device is not automatically initialized by Zephyr at boot time. Instead, +the device is initialized when the application calls :c:func:`device_init`. +To defer a device driver initialization, add the property ``zephyr,deferred-init`` +to the associated device node in the DTS file. For example: + +.. code-block:: devicetree + + / { + a-driver@40000000 { + reg = <0x40000000 0x1000>; + zephyr,deferred-init; + }; + }; + System Drivers ************** diff --git a/doc/kernel/memory_management/demand_paging.rst b/doc/kernel/memory_management/demand_paging.rst index 13a04cd283327..54eb12baac0a7 100644 --- a/doc/kernel/memory_management/demand_paging.rst +++ b/doc/kernel/memory_management/demand_paging.rst @@ -50,28 +50,32 @@ Page Frame A page frame is a page-sized physical memory region in RAM. It is a container where a data page may be placed. It is always referred to by physical address. Zephyr has a convention of using ``uintptr_t`` for physical - addresses. For every page frame, a ``struct z_page_frame`` is instantiated to + addresses. For every page frame, a ``struct k_mem_page_frame`` is instantiated to store metadata. Flags for each page frame: - * ``Z_PAGE_FRAME_PINNED`` indicates a page frame is pinned in memory + * ``K_MEM_PAGE_FRAME_FREE`` indicates a page frame is unused and on the list of + free page frames. When this flag is set, none of the other flags are + meaningful and they must not be modified. + + * ``K_MEM_PAGE_FRAME_PINNED`` indicates a page frame is pinned in memory and should never be paged out. - * ``Z_PAGE_FRAME_RESERVED`` indicates a physical page reserved by hardware + * ``K_MEM_PAGE_FRAME_RESERVED`` indicates a physical page reserved by hardware and should not be used at all. - * ``Z_PAGE_FRAME_MAPPED`` is set when a physical page is mapped to + * ``K_MEM_PAGE_FRAME_MAPPED`` is set when a physical page is mapped to virtual memory address. - * ``Z_PAGE_FRAME_BUSY`` indicates a page frame is currently involved in + * ``K_MEM_PAGE_FRAME_BUSY`` indicates a page frame is currently involved in a page-in/out operation. - * ``Z_PAGE_FRAME_BACKED`` indicates a page frame has a clean copy + * ``K_MEM_PAGE_FRAME_BACKED`` indicates a page frame has a clean copy in the backing store. -Z_SCRATCH_PAGE +K_MEM_SCRATCH_PAGE The virtual address of a special page provided to the backing store to: - * Copy a data page from ``Z_SCRATCH_PAGE`` to the specified location; or, - * Copy a data page from the provided location to ``Z_SCRATCH_PAGE``. + * Copy a data page from ``k_MEM_SCRATCH_PAGE`` to the specified location; or, + * Copy a data page from the provided location to ``K_MEM_SCRATCH_PAGE``. This is used as an intermediate page for page in/out operations. This scratch needs to be mapped read/write for backing store code to access. However the data page itself may only be mapped as read-only in virtual @@ -159,10 +163,10 @@ which must be implemented: * :c:func:`k_mem_paging_backing_store_page_in()` copies a data page from the backing store location associated with the provided - ``location`` token to the page pointed by ``Z_SCRATCH_PAGE``. + ``location`` token to the page pointed by ``K_MEM_SCRATCH_PAGE``. * :c:func:`k_mem_paging_backing_store_page_out()` copies a data page - from ``Z_SCRATCH_PAGE`` to the backing store location associated + from ``K_MEM_SCRATCH_PAGE`` to the backing store location associated with the provided ``location`` token. * :c:func:`k_mem_paging_backing_store_page_finalize()` is invoked after diff --git a/doc/kernel/memory_management/shared_multi_heap.rst b/doc/kernel/memory_management/shared_multi_heap.rst index 89458ecb927c6..cc5101ae1fbfe 100644 --- a/doc/kernel/memory_management/shared_multi_heap.rst +++ b/doc/kernel/memory_management/shared_multi_heap.rst @@ -18,7 +18,7 @@ This framework is commonly used as follow: the pool with :c:func:`shared_multi_heap_add()`, possibly gathering the needed information for the regions from the DT. -2. Each memory region encoded in a :c:type:`shared_multi_heap_region` +2. Each memory region encoded in a :c:struct:`shared_multi_heap_region` structure. This structure is also carrying an opaque and user-defined integer value that is used to define the region capabilities (for example: cacheability, cpu affinity, etc...) @@ -76,7 +76,7 @@ Adding new attributes ********************* The API does not enforce any attributes, but at least it defines the two most -common ones: :c:enum:`SMH_REG_ATTR_CACHEABLE` and :c:enum:`SMH_REG_ATTR_NON_CACHEABLE` +common ones: :c:enumerator:`SMH_REG_ATTR_CACHEABLE` and :c:enumerator:`SMH_REG_ATTR_NON_CACHEABLE`. .. doxygengroup:: shared_multi_heap :project: Zephyr diff --git a/doc/kernel/memory_management/virtual_memory.rst b/doc/kernel/memory_management/virtual_memory.rst index dbc95fb7b5279..4e2f11e90c7b3 100644 --- a/doc/kernel/memory_management/virtual_memory.rst +++ b/doc/kernel/memory_management/virtual_memory.rst @@ -73,15 +73,15 @@ below. .. code-block:: none :emphasize-lines: 1, 3, 9, 22, 24 - +--------------+ <- Z_VIRT_RAM_START + +--------------+ <- K_MEM_VIRT_RAM_START | Undefined VM | <- architecture specific reserved area - +--------------+ <- Z_KERNEL_VIRT_START + +--------------+ <- K_MEM_KERNEL_VIRT_START | Mapping for | | main kernel | | image | | | | | - +--------------+ <- Z_FREE_VM_START + +--------------+ <- K_MEM_VM_FREE_START | | | Unused, | | Available VM | @@ -95,27 +95,27 @@ below. +--------------+ | Mapping | +--------------+ <- memory mappings start here - | Reserved | <- special purpose virtual page(s) of size Z_VM_RESERVED - +--------------+ <- Z_VIRT_RAM_END + | Reserved | <- special purpose virtual page(s) of size K_MEM_VM_RESERVED + +--------------+ <- K_MEM_VIRT_RAM_END -* ``Z_VIRT_RAM_START`` is the beginning of the virtual memory address space. +* ``K_MEM_VIRT_RAM_START`` is the beginning of the virtual memory address space. This needs to be page aligned. Currently, it is the same as :kconfig:option:`CONFIG_KERNEL_VM_BASE`. -* ``Z_VIRT_RAM_SIZE`` is the size of the virtual memory address space. +* ``K_MEM_VIRT_RAM_SIZE`` is the size of the virtual memory address space. This needs to be page aligned. Currently, it is the same as :kconfig:option:`CONFIG_KERNEL_VM_SIZE`. -* ``Z_VIRT_RAM_END`` is simply (``Z_VIRT_RAM_START`` + ``Z_VIRT_RAM_SIZE``). +* ``K_MEM_VIRT_RAM_END`` is simply (``K_MEM_VIRT_RAM_START`` + ``K_MEM_VIRT_RAM_SIZE``). -* ``Z_KERNEL_VIRT_START`` is the same as ``z_mapped_start`` specified in the linker +* ``K_MEM_KERNEL_VIRT_START`` is the same as ``z_mapped_start`` specified in the linker script. This is the virtual address of the beginning of the kernel image at boot time. -* ``Z_KERNEL_VIRT_END`` is the same as ``z_mapped_end`` specified in the linker +* ``K_MEM_KERNEL_VIRT_END`` is the same as ``z_mapped_end`` specified in the linker script. This is the virtual address of the end of the kernel image at boot time. -* ``Z_FREE_VM_START`` is the beginning of the virtual address space where addresses +* ``K_MEM_VM_FREE_START`` is the beginning of the virtual address space where addresses can be allocated for memory mapping. This depends on whether :kconfig:option:`CONFIG_ARCH_MAPS_ALL_RAM` is enabled. @@ -123,10 +123,10 @@ below. memory address space, and it is the same as (:kconfig:option:`CONFIG_SRAM_BASE_ADDRESS` + :kconfig:option:`CONFIG_SRAM_SIZE`). - * If it is disabled, ``Z_FREE_VM_START`` is the same ``Z_KERNEL_VIRT_END`` which + * If it is disabled, ``K_MEM_VM_FREE_START`` is the same ``K_MEM_KERNEL_VIRT_END`` which is the end of the kernel image. -* ``Z_VM_RESERVED`` is an area reserved to support kernel functions. For example, +* ``K_MEM_VM_RESERVED`` is an area reserved to support kernel functions. For example, some addresses are reserved to support demand paging. @@ -176,7 +176,7 @@ mappings must be aligned on page size and have finer access control. * The requested size must be multiple of page size. * The address returned is inside the virtual address space between - ``Z_FREE_VM_START`` and ``Z_VIRT_RAM_END``. + ``K_MEM_VM_FREE_START`` and ``K_MEM_VIRT_RAM_END``. * The mapped region is not guaranteed to be physically contiguous in memory. diff --git a/doc/kernel/services/data_passing/pipes.rst b/doc/kernel/services/data_passing/pipes.rst index bdeec48f0117b..c4cb571fc07ee 100644 --- a/doc/kernel/services/data_passing/pipes.rst +++ b/doc/kernel/services/data_passing/pipes.rst @@ -231,7 +231,7 @@ Configuration Options Related configuration options: -* CONFIG_PIPES +* :kconfig:option:`CONFIG_PIPES` API Reference ************* diff --git a/doc/kernel/services/polling.rst b/doc/kernel/services/polling.rst index 46e586badb6e9..b1d08e35d0d1a 100644 --- a/doc/kernel/services/polling.rst +++ b/doc/kernel/services/polling.rst @@ -78,14 +78,15 @@ Poll events can be initialized using either the runtime initializers :c:macro:`K_POLL_EVENT_INITIALIZER()` or :c:func:`k_poll_event_init`, or the static initializer :c:macro:`K_POLL_EVENT_STATIC_INITIALIZER()`. An object that matches the **type** specified must be passed to the initializers. The -**mode** *must* be set to :c:macro:`K_POLL_MODE_NOTIFY_ONLY`. The state *must* -be set to :c:macro:`K_POLL_STATE_NOT_READY` (the initializers take care of -this). The user **tag** is optional and completely opaque to the API: it is +**mode** *must* be set to :c:enumerator:`K_POLL_MODE_NOTIFY_ONLY`. The state +*must* be set to :c:macro:`K_POLL_STATE_NOT_READY` (the initializers take care +of this). The user **tag** is optional and completely opaque to the API: it is there to help a user to group similar events together. Being optional, it is passed to the static initializer, but not the runtime ones for performance reasons. If using runtime initializers, the user must set it separately in the :c:struct:`k_poll_event` data structure. If an event in the array is to be -ignored, most likely temporarily, its type can be set to K_POLL_TYPE_IGNORE. +ignored, most likely temporarily, its type can be set to +:c:macro:`K_POLL_TYPE_IGNORE`. .. code-block:: c @@ -195,6 +196,7 @@ to :c:macro:`K_POLL_STATE_NOT_READY` by the user. } else if (events[3].state == K_POLL_STATE_PIPE_DATA_AVAILABLE) { ret = k_pipe_get(events[3].pipe, buf, bytes_to_read, &bytes_read, min_xfer, K_NO_WAIT); // handle data + } events[0].state = K_POLL_STATE_NOT_READY; events[1].state = K_POLL_STATE_NOT_READY; events[2].state = K_POLL_STATE_NOT_READY; diff --git a/doc/kernel/services/smp/smp.rst b/doc/kernel/services/smp/smp.rst index ca1e0149ad55e..4b178432bd559 100644 --- a/doc/kernel/services/smp/smp.rst +++ b/doc/kernel/services/smp/smp.rst @@ -180,13 +180,17 @@ handle the newly-runnable load. So where possible, Zephyr SMP architectures should implement an interprocessor interrupt. The current framework is very simple: the -architecture provides a :c:func:`arch_sched_ipi` call, which when invoked -will flag an interrupt on all CPUs (except the current one, though -that is allowed behavior) which will then invoke the :c:func:`z_sched_ipi` -function implemented in the scheduler. The expectation is that these -APIs will evolve over time to encompass more functionality -(e.g. cross-CPU calls), and that the scheduler-specific calls here -will be implemented in terms of a more general framework. +architecture provides at least a :c:func:`arch_sched_broadcast_ipi` call, +which when invoked will flag an interrupt on all CPUs (except the current one, +though that is allowed behavior). If the architecture supports directed IPIs +(see :kconfig:option:`CONFIG_ARCH_HAS_DIRECTED_IPIS`), then the +architecture also provides a :c:func:`arch_sched_directed_ipi` call, which +when invoked will flag an interrupt on the specified CPUs. When an interrupt is +flagged on the CPUs, the :c:func:`z_sched_ipi` function implmented in the +scheduler will get invoked on those CPUs. The expectation is that these +APIs will evolve over time to encompass more functionality (e.g. cross-CPU +calls), and that the scheduler-specific calls here will be implemented in +terms of a more general framework. Note that not all SMP architectures will have a usable IPI mechanism (either missing, or just undocumented/unimplemented). In those cases diff --git a/doc/kernel/services/threads/workqueue.rst b/doc/kernel/services/threads/workqueue.rst index b221e1163b7cd..18c1cf0e31a63 100644 --- a/doc/kernel/services/threads/workqueue.rst +++ b/doc/kernel/services/threads/workqueue.rst @@ -71,7 +71,7 @@ itself. The work item also maintains information about its status. A work item must be initialized before it can be used. This records the work item's handler function and marks it as not pending. -A work item may be **queued** (:c:macro:`K_WORK_QUEUED`) by submitting it to a +A work item may be **queued** (:c:enumerator:`K_WORK_QUEUED`) by submitting it to a workqueue by an ISR or a thread. Submitting a work item appends the work item to the workqueue's queue. Once the workqueue's thread has processed all of the preceding work items in its queue the thread will remove the next work @@ -80,11 +80,11 @@ the scheduling priority of the workqueue's thread, and the work required by other items in the queue, a queued work item may be processed quickly or it may remain in the queue for an extended period of time. -A delayable work item may be **scheduled** (:c:macro:`K_WORK_DELAYED`) to a +A delayable work item may be **scheduled** (:c:enumerator:`K_WORK_DELAYED`) to a workqueue; see `Delayable Work`_. -A work item will be **running** (:c:macro:`K_WORK_RUNNING`) when it is running -on a work queue, and may also be **canceling** (:c:macro:`K_WORK_CANCELING`) +A work item will be **running** (:c:enumerator:`K_WORK_RUNNING`) when it is running +on a work queue, and may also be **canceling** (:c:enumerator:`K_WORK_CANCELING`) if it started running before a thread has requested that it be cancelled. A work item can be in multiple states; for example it can be: @@ -248,7 +248,7 @@ The following code defines and initializes a workqueue: In addition the queue identity and certain behavior related to thread rescheduling can be controlled by the optional final parameter; see -:c:struct:`k_work_queue_start()` for details. +:c:func:`k_work_queue_start()` for details. The following API can be used to interact with a workqueue: @@ -416,7 +416,7 @@ be a flag indicating that work needs to be done, or a shared object that is filled by an ISR or thread and read by the work handler. For simple flags :ref:`atomic_v2` may be sufficient. In other cases spin -locks (:c:struct:`k_spinlock_t`) or thread-aware locks (:c:struct:`k_sem`, +locks (:c:struct:`k_spinlock`) or thread-aware locks (:c:struct:`k_sem`, :c:struct:`k_mutex` , ...) may be used to ensure data races don't occur. If the selected lock mechanism can :ref:`api_term_sleep` then allowing the diff --git a/doc/kernel/services/timing/clocks.rst b/doc/kernel/services/timing/clocks.rst index 0517d601f2767..4d88606938ee8 100644 --- a/doc/kernel/services/timing/clocks.rst +++ b/doc/kernel/services/timing/clocks.rst @@ -98,7 +98,7 @@ For example: * The kernel :c:struct:`k_work_delayable` API provides a timeout parameter indicating when a work queue item will be added to the system queue. -All these values are specified using a :c:struct:`k_timeout_t` value. This is +All these values are specified using a :c:type:`k_timeout_t` value. This is an opaque struct type that must be initialized using one of a family of kernel timeout macros. The most common, :c:macro:`K_MSEC`, defines a time in milliseconds after the current time. @@ -123,7 +123,7 @@ described above: :c:macro:`K_NSEC()`, :c:macro:`K_USEC`, :c:macro:`K_TICKS` and :c:macro:`K_CYC()` specify timeout values that will expire after specified numbers of nanoseconds, microseconds, ticks and cycles, respectively. -Precision of :c:struct:`k_timeout_t` values is configurable, with the default +Precision of :c:type:`k_timeout_t` values is configurable, with the default being 32 bits. Large uptime counts in non-tick units will experience complicated rollover semantics, so it is expected that timing-sensitive applications with long uptimes will be configured to @@ -141,16 +141,16 @@ Timing Internals Timeout Queue ------------- -All Zephyr :c:struct:`k_timeout_t` events specified using the API above are +All Zephyr :c:type:`k_timeout_t` events specified using the API above are managed in a single, global queue of events. Each event is stored in a double-linked list, with an attendant delta count in ticks from the previous event. The action to take on an event is specified as a callback function pointer provided by the subsystem requesting the event, along with a :c:struct:`_timeout` tracking struct that is expected to be embedded within subsystem-defined data structures (for -example: a :c:struct:`wait_q` struct, or a :c:struct:`k_tid_t` thread struct). +example: a :c:struct:`wait_q` struct, or a :c:type:`k_tid_t` thread struct). -Note that all variant units passed via a :c:struct:`k_timeout_t` are converted +Note that all variant units passed via a :c:type:`k_timeout_t` are converted to ticks once on insertion into the list. There no multiple-conversion steps internal to the kernel, so precision is guaranteed at the tick level no matter how many events exist or how diff --git a/doc/kernel/services/timing/timers.rst b/doc/kernel/services/timing/timers.rst index 9b1e424921de4..7fd3e2e46010d 100644 --- a/doc/kernel/services/timing/timers.rst +++ b/doc/kernel/services/timing/timers.rst @@ -22,11 +22,11 @@ is referenced by its memory address. A timer has the following key properties: * A **duration** specifying the time interval before the timer - expires for the first time. This is a ``k_timeout_t`` value that + expires for the first time. This is a :c:type:`k_timeout_t` value that may be initialized via different units. * A **period** specifying the time interval between all timer - expirations after the first one, also a ``k_timeout_t``. It must be + expirations after the first one, also a :c:type:`k_timeout_t`. It must be non-negative. A period of ``K_NO_WAIT`` (i.e. zero) or ``K_FOREVER`` means that the timer is a one-shot timer that stops after a single expiration. (For example then, if a timer is started diff --git a/doc/kernel/usermode/memory_domain.rst b/doc/kernel/usermode/memory_domain.rst index a1ddcd395e98a..f830cc981b91b 100644 --- a/doc/kernel/usermode/memory_domain.rst +++ b/doc/kernel/usermode/memory_domain.rst @@ -74,10 +74,24 @@ Thread Stack ************ Any thread running in user mode will need access to its own stack buffer. -On context switch into a user mode thread, a dedicated MPU region will be -programmed with the bounds of the stack buffer. A thread exceeding its stack -buffer will start pushing data onto memory it doesn't have access to and a -memory access violation exception will be generated. +On context switch into a user mode thread, a dedicated MPU region or MMU +page table entries will be programmed with the bounds of the stack buffer. +A thread exceeding its stack buffer will start pushing data onto memory +it doesn't have access to and a memory access violation exception will be +generated. + +Note that user threads have access to the stacks of other user threads in +the same memory domain. This is the minimum required for architectures to +support memory domains. Architecture can further restrict access to stacks +so each user thread only has access to its own stack if such architecture +advertises this capability via +:kconfig:option:`CONFIG_ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS`. +This behavior is enabled by default if supported and can be selectively +disabled via :kconfig:option:`CONFIG_MEM_DOMAIN_ISOLATED_STACKS` if +architecture supports both operating modes. However, some architectures +may decide to enable this all the time, and thus this option cannot be +disabled. Regardless of these kconfigs, user threads cannot access +the stacks of other user threads outside of their memory domains. Thread Resource Pools ********************* diff --git a/doc/kernel/usermode/syscalls.rst b/doc/kernel/usermode/syscalls.rst index f751697d9a307..dd9838629d9b9 100644 --- a/doc/kernel/usermode/syscalls.rst +++ b/doc/kernel/usermode/syscalls.rst @@ -87,7 +87,7 @@ bottom of ``include/sensor.h``: .. code-block:: c - #include + #include C prototype functions must be declared in one of the directories listed in the CMake variable ``SYSCALL_INCLUDE_DIRS``. This list @@ -143,11 +143,11 @@ C and header files by the :ref:`gen_syscalls.py` script, all of which can be fou the project out directory under ``include/generated/``: * The system call is added to the enumerated type of system call IDs, - which is expressed in ``include/generated/syscall_list.h``. It is the name + which is expressed in ``include/generated/zephyr/syscall_list.h``. It is the name of the API in uppercase, prefixed with ``K_SYSCALL_``. * An entry for the system call is created in the dispatch table - ``_k_syscall_table``, expressed in ``include/generated/syscall_dispatch.c`` + ``_k_syscall_table``, expressed in ``include/generated/zephyr/syscall_dispatch.c`` * This table only contains syscalls where their corresponding prototypes are declared in header files when @@ -172,7 +172,7 @@ The body of the API is created in the generated system header. Using the example of :c:func:`k_sem_init()`, this API is declared in ``include/kernel.h``. At the bottom of ``include/kernel.h`` is:: - #include + #include Inside this header is the body of :c:func:`k_sem_init()`:: @@ -335,6 +335,8 @@ If any check fails, the macros will return a nonzero value. The macro calling thread. This is done instead of returning some error condition to keep the APIs the same when calling from supervisor mode. +.. _syscall_verification: + Verifier Definition =================== @@ -360,7 +362,7 @@ For example: K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); return z_impl_k_sem_take(sem, timeout); } - #include + #include Verification Memory Access Policies diff --git a/doc/project/index.rst b/doc/project/index.rst index 372e4816ddc29..dda70ca575f22 100644 --- a/doc/project/index.rst +++ b/doc/project/index.rst @@ -7,7 +7,9 @@ Project and Governance .. toctree:: :maxdepth: 1 + tsc project_roles.rst + working_groups release_process proposals code_flow diff --git a/doc/project/project_roles.rst b/doc/project/project_roles.rst index a57a7b46def4b..3e106e888f223 100644 --- a/doc/project/project_roles.rst +++ b/doc/project/project_roles.rst @@ -3,8 +3,8 @@ TSC Project Roles ***************** -Main Roles -########## +Project Roles +############# TSC projects generally will involve *Maintainers*, *Collaborators*, and *Contributors*: @@ -159,6 +159,7 @@ Assignees are set either automatically based on the code being changed or set by the other Maintainers, the Release Engineering team can set an assignee when the latter is not possible. +* Responsibility to drive the pull request to a mergeable state * Right to dismiss stale and unrelated reviews or reviews not following :ref:`expectations ` from reviewers and seek reviews from additional maintainers, developers and contributors @@ -166,7 +167,6 @@ the latter is not possible. requested are addressed * Responsibility to re-assign a pull request if they are the original submitter of the code -* Responsibility to drive the pull request to a mergeable state * Solicit approvals from maintainers of the subsystems affected * Responsibility to drive the :ref:`pr_technical_escalation` process diff --git a/doc/project/tsc.rst b/doc/project/tsc.rst new file mode 100644 index 0000000000000..f183bde9f060c --- /dev/null +++ b/doc/project/tsc.rst @@ -0,0 +1,242 @@ +Technical Steering Committee (TSC) +********************************** + +TSC Member Role +############### + +The TSC role and its responsibilities is defined in the `Zephyr project charter`_. + +Membership +++++++++++ + +A TSC member plays a pivotal role in shaping the technical direction of the +Zephyr Project. TSC members work collaboratively with other TSC members, +contributors, and stakeholders to ensure the project's success and +sustainability. + +By fulfilling the rights and responsibilities below, TSC members contribute to +the overall success and growth of the Zephyr Project, ensuring that it remains a +vibrant and thriving open-source community for years to come. + + +Rights +------ + +Decision Making + Participate in key decisions related to the project's technical direction, + including architectural changes, feature additions, and release planning. + +Voting + Exercise voting rights on important matters discussed within the TSC, + including feature proposals, code contributions, and community initiatives. + +Access + Gain access to relevant project repositories, documentation, and communication + channels to stay informed and contribute effectively. + +Leadership + Take on leadership roles within working groups or subcommittees dedicated to + specific technical areas or initiatives. + +Representation + Act as a representative of the broader Zephyr community, advocating for the + interests of contributors, users, and stakeholders. + +Responsibilities +---------------- +TSC members are expected to fulfill the following responsibilities, though it is +not mandatory to fulfill all: + +Technical Oversight + Provide guidance and oversight on technical matters, ensuring alignment with + project goals, standards, and best practices through active participation as + core members in working groups and committees. + +Code Review + Participate in code reviews to maintain code quality, consistency, and + compatibility with project standards. + +Community Engagement + Engage with the community through forums, mailing lists, conferences, and + other channels to foster collaboration, address concerns, and gather feedback. + +Documentation + Contribute to the development and maintenance of project documentation, + including technical guides, API references, and best practices. + +Release Management + Collaborate with the release manager and other stakeholders to plan and + coordinate project releases, ensuring timely delivery and quality assurance. + +Contributor Support + Support and mentor new contributors, helping them navigate the project's + codebase, processes, and community norms. + +Issue Triage + Assist in triaging and prioritizing issues reported by users and contributors, + facilitating timely resolution and communication. + +Compliance and Licensing + Ensure compliance with project licensing requirements and open-source best + practices, addressing any licensing-related issues that may arise. + +Conflict Resolution + Facilitate constructive discussions and resolution of technical disagreements + or conflicts within the community, promoting a healthy and inclusive + environment. + +Continuous Improvement + Continuously seek opportunities to improve project governance, processes, and + infrastructure, driving innovation and sustainability. + + +Appointed TSC Members ++++++++++++++++++++++ + +See `Zephyr project charter`_ for more details. + +- Appointed TSC members have no term limits besides the term of their employment + at the organization they represent or their organization's membership in the + Zephyr Project. +- Appointed TSC members can select an Alternate from the same organization. + +Elected TSC Members ++++++++++++++++++++ + +Per the `Zephyr project charter`_, TSC members can nominate representatives from +the technical community at the rate of no more than one per quarter. + +- Majority vote is required to confirm a candidate. +- Once elected, a TSC member serves for 2 years. +- Elected TSC members do not have the right to appoint an Alternate. +- To ensure continuity of the TSC, at the end of the 2 year term, the TSC is + required to reconfirm the membership of elected members. If the elected member + declines a new term or if the TSC fails to reconfirm the term, the seat will + be open for new nominations. +- If an elected TSC member resigns before the end of the 2 year term, their spot + will be open for new members outside of the quarterly nomination limit. The + elected member will serve a 2 year term. +- The TSC has the right to terminate elected members who become inactive and are + not fulfilling the responsibilities of TSC members as described in this + document. +- The number of elected members shall not exceed 20% of the total of appointed + members. +- Existing TSC members who were elected before May 2024 shall be re-confirmed + after completing the 2 year term since they were first elected. + +Suspensions ++++++++++++ + +As noted under Section 8b of the Project Charter, voting rights for a +representative who misses three consecutive meetings are subject to suspension +and suspended representatives do not count towards the quorum requirement. + +A representative’s suspension will end and voting rights be restored at the start +of the next attended meeting. The TSC enforces the suspension policy for voting +members who miss three consecutive TSC weekly meetings. + +Multi-day meetings (F2F events) are counted as "one" meeting. The TSC voted on +February 16, 2022 to discontinue default enforcement of the suspension policy. +The TSC voted on January 18, 2023 to re-enact default enforcement of the +suspension policy. + +Notice of suspension will be sent to representatives who miss three consecutive +meetings, noting that rights will be restored upon next attendance of a TSC +meeting. + +.. note:: + + As per Section 4b of the Project Charter, Platinum and Silver + Members may choose to opt out of a voting seat on the TSC. + + Members who opt out and then wish to reclaim their seat later will have their + voting rights restored at the start of the second consecutive meeting + attended following notification to the TSC Chair. + + +Voting +++++++ + +Voting in the Zephyr Project is defined under Section 8 of the Project Charter. + +Additional points of clarity / TSC interpretation have been added below. The +Governing Board may opt to update the Charter to include the below +refinements. Until then, additional clarifications (if/where needed) will be +discussed in the Process Working Group, and approved in the TSC. + +- TSC In-Meeting Voting For items requesting an in-meeting vote of the Zephyr + Technical Steering Committee (TSC), assuming quorum requirements have been + met, the default voting mechanism will be a verbal motion to determine if + there is general consensus. +- If there are no objections to a motion being brought forward, general + consensus is assumed and the motion passes. +- Should there be any objections raised, the vote will move to email, and be + executed using the Voting Guidelines outlined in Section 8 of the Project + Charter. +- Should a motion be deemed urgent by the TSC Chair, and assuming quorum + requirements have been met, the Chair may call for a roll call vote + in-meeting. + +Voting Options +-------------- + +- Voting Options are: + + - "Yes", + - "No" or + - "Abstain" + +Abstention +---------- + +Abstentions do not count in tallying the vote negatively or positively; when +members abstain, they are in effect attending only to contribute to a quorum. + +Abstentions do not impact the number of votes needed to decide a vote. + +Quorum +------ + +Quorum for TSC meetings shall require 60% of the voting representatives... (ref +8b of the Charter) + +Decisions +--------- + +Decisions by vote shall be based on a majority vote, provided that at least +sixty percent (60%) of the **TSC** representatives must be either +present or participating electronically or by written action in order to +conduct a valid vote. (ref 8c of the Charter) + +Example A: + + 40 eligible TSC voters. 3 abstain from a vote on a motion. 12 vote Yes. 11 vote + No. + + Quorum reached: 26 votes cast (quorum = 60% of 40 = 24) + Majority vote: 12 Yes vs. 11 No. Yes wins. + Motion adopted. + +Example B: + + 40 eligible TSC voters. 5 abstain from a vote on a motion. 12 vote Yes. 6 + vote No. Quorum reached? 23 votes cast (quorum = 60% of 40 = 24) + + Vote is not valid. Quorum not reached. + +Example C: + + 40 eligible TSC voters. 21 abstain from a vote on a motion. 2 vote Yes. 1 votes + No. Quorum reached? 24 votes cast (quorum = 60% of 40 = 24) + + Majority vote: 2 Yes vs. 1 No. Yes wins. + +Immutable Votes ++++++++++++++++ + +Votes are considered immutable once cast. A voter may not change their vote, +once cast, between the time a Motion is brought forth and the time at which +results are announced. + +.. _Zephyr project charter: + https://www.zephyrproject.org/wp-content/uploads/sites/38/2023/08/LF-Zephyr-Charter-2023.08.21.pdf diff --git a/doc/project/working_groups.rst b/doc/project/working_groups.rst new file mode 100644 index 0000000000000..900f287738477 --- /dev/null +++ b/doc/project/working_groups.rst @@ -0,0 +1,118 @@ +TSC Working Groups +****************** + +Overview +######## + +The TSC, at its discretion, may establish working groups or subcommittees to +serve as focused teams dedicated to specific technical areas, initiatives, or +tasks. + +Membership +########## + +Working Group Membership Eligibility +++++++++++++++++++++++++++++++++++++ + +- Each Working group (WG) shall determine its own membership eligibility, in + consultation with the TSC. +- Each working group shall have a team of members who are actively involved + in its activities and decision-making processes. +- It is expected that WG membership shall be **open to all Zephyr project + Contributors**; however, working groups may impose restrictions such as the + number of participants from a single company. +- All TSC members are eligible to join a working group as members, part of + the responsibilities being a TSC member. +- The minimal number of members may vary depending on the complexity of the + tasks and the breadth of expertise required to address them effectively. +- A working group should aim to have at least five to seven members to + ensure diversity of perspectives, collaboration, and continuity. +- The structure of each working group within the Zephyr Project should be + designed to ensure effectiveness, productivity, and inclusivity. While the + optimal size of a working group can vary depending on the specific context and + scope of its activities. +- Participation in WG meetings and discussions is open to all project contributors. + +Working Group Chair / Co-chair +++++++++++++++++++++++++++++++ + +Each working group may elect a Chair and optionally a Co-Chair who is +responsible for leading meetings and representing the working group to the TSC. + +Working Group Chair / Co-Chair Elections +++++++++++++++++++++++++++++++++++++++++ + +- The Chair and Co-Chair shall be elected by the members of the working group +- Any member of the working group has the right to nominate themselves for the + chair/co-chair positions. +- The term for the chair/co-chair is one year +- If a chair/co-chair resigns from the position before the end of the term, a + vote is to be held to elect a new chair/co-chair. + +Working Group Voter Eligibility ++++++++++++++++++++++++++++++++ + +- Voting for a Chair or Co-Chair is open to the members of the working group. +- Only 1 working group member from each company may vote in the election. +- The Chair and Co-Chair shall be members of the working group. + +Working Group Election Confirmation +++++++++++++++++++++++++++++++++++++ + +- The elected Chair (and/or Co-Chair) is submitted to the TSC for confirmation. +- The TSC decides to accept the outcome or requests a new voting. + +Advisory role +############# + +- Working Groups are advisory in nature. They provide advice to the projects and + to the TSC. +- Working groups operate on a rough consensus basis. If the working group is + unable to reach consensus on what advice to offer, the working group Chair + shall raise the issue with the TSC or the relevant committee (Safety and + Security), where a formal vote can be taken, or advise the project that the + working group cannot reach consensus. +- Working groups shall keep track of discussions and record any votes, + decisions, or recommendations made and share results with the community and + the TSC. +- Working group meetings and offline discussions shall be captured in a + standalone document with all supporting details such as attendance, quorum, + actions to be taken, and next steps. +- Decisions made within a working group are non-binding and are only considered + ratified after communicating decisions and outcomes to the TSC. +- Lacking any objections from the TSC within 1 week after the communication or + report of any results, decisions of a working group are considered confirmed + and ratified. + +TSC Working Group Lifecycle +########################### + +Creation of a TSC working group ++++++++++++++++++++++++++++++++ + +In order to create a TSC working group, a TSC member shall make a proposal to +the TSC (via TSC email list) that shall cover at least the following: + +- TSC working group name. +- TSC working group purpose +- TSC working group expected deliverables +- TSC working group starting participants with at least one TSC member acting as + a sponsor. +- Optionally TSC working group definition of done + +Update of a TSC working group ++++++++++++++++++++++++++++++ + +The TSC can modify a TSC working group via a TSC decision. To request such a +modification, a request is made to the TSC email list. + +Conclusion of a TSC working group ++++++++++++++++++++++++++++++++++ + +The TSC decides the termination of the TSC working group in accordance with the +TSC decision procedure. The submission of a request to terminate the TSC working +group should cover: + +- TSC working group name +- TSC working group deliveries +- Motivation for termination of the TSC working group diff --git a/doc/releases/index.rst b/doc/releases/index.rst index 544f721994bf3..fc483fa606d4d 100644 --- a/doc/releases/index.rst +++ b/doc/releases/index.rst @@ -15,6 +15,8 @@ The technical documentation for current and past releases is available at https://docs.zephyrproject.org/ (use the version selector to select your release of interest). +.. _zephyr_release_cycle: + Release Life Cycle and Maintenance ********************************** @@ -103,6 +105,10 @@ in the migration guide. This includes: - Anything else that can affect the compilation or runtime behavior of an existing application +Each entry in the migration guide must include a brief explanation of the change +as well as refer to the Pull Request that introduced it, in order for the user +to be able to understand the context of the change. + .. toctree:: :maxdepth: 1 :glob: diff --git a/doc/releases/migration-guide-3.7.rst b/doc/releases/migration-guide-3.7.rst index 07d2585fa1687..835ad1afa1de4 100644 --- a/doc/releases/migration-guide-3.7.rst +++ b/doc/releases/migration-guide-3.7.rst @@ -20,28 +20,110 @@ Build System * Completely overhauled the way SoCs and boards are defined. This requires all out-of-tree SoCs and boards to be ported to the new model. See the - :ref:`hw_model_v2` for more detailed information. + :ref:`hw_model_v2` for more detailed information. (:github:`69607`) + +* The following build-time generated headers: + + .. list-table:: + :header-rows: 1 + + * - Affected header files + * - ``app_version.h`` + * - ``autoconf.h`` + * - ``cmake_intdef.h`` + * - ``core-isa-dM.h`` + * - ``devicetree_generated.h`` + * - ``driver-validation.h`` + * - ``kobj-types-enum.h`` + * - ``linker-kobject-prebuilt-data.h`` + * - ``linker-kobject-prebuilt-priv-stacks.h`` + * - ``linker-kobject-prebuilt-rodata.h`` + * - ``mcuboot_version.h`` + * - ``offsets.h`` + * - ``otype-to-size.h`` + * - ``otype-to-str.h`` + * - ``strerror_table.h`` + * - ``strsignal_table.h`` + * - ``syscall_list.h`` + * - ``version.h`` + * - ``zsr.h`` + + as well as syscall headers & sources are now namespaced into the ``zephyr/`` folder. The change is largely + automated, and the script can be found in :github:`63973`. + For the time being, the compatibility Kconfig (:kconfig:option:`CONFIG_LEGACY_GENERATED_INCLUDE_PATH`) + is enabled by default so that downstream applications will continue to compile, a warning message + will be generated during CMake configuration time. + This Kconfig will be deprecated and eventually removed in the future, developers are advised to + update the include paths of these affected headers as soon as possible. Kernel ****** +* All architectures are now required to define the new ``struct arch_esf``, which describes the members + of a stack frame. This new struct replaces the named struct ``z_arch_esf_t``. (:github:`73593`) + +* The named struct ``z_arch_esf_t`` is now deprecated. Use ``struct arch_esf`` instead. (:github:`73593`) + Boards ****** * Reordered D1 and D0 in the `pro_micro` connector gpio-map for SparkFun Pro Micro RP2040 to match - original Pro Micro definition. Out-of-tree shields must be updated to reflect this change. + original Pro Micro definition. Out-of-tree shields must be updated to reflect this change. (:github:`69994`) * ITE: Rename all SoC variant Kconfig options, e.g., ``CONFIG_SOC_IT82202_AX`` is renamed to ``CONFIG_SOC_IT82202AX``. All symbols are renamed as follows: ``SOC_IT81202BX``, ``SOC_IT81202CX``, ``SOC_IT81302BX``, ``SOC_IT81302CX``, ``SOC_IT82002AW``, ``SOC_IT82202AX``, ``SOC_IT82302AX``. - And, rename the ``SOC_SERIES_ITE_IT8XXX2`` to ``SOC_SERIES_IT8XXX2``. + And, rename the ``SOC_SERIES_ITE_IT8XXX2`` to ``SOC_SERIES_IT8XXX2``. (:github:`71680`) +* For native_sim/posix: :kconfig:option:`CONFIG_EMUL` is no longer enabled by default when + :kconfig:option:`CONFIG_I2C` is set. Users who need this setting enabled should set it in + their project config file. (:github:`73067`) + +* LiteX: Renamed the ``compatible`` of the LiteX VexRiscV interrupt controller node from + ``vexriscv-intc0`` to :dtcompatible:`litex,vexriscv-intc0`. (:github:`73211`) + +* `lairdconnect` boards are now `ezurio` boards. Laird Connectivity has rebranded to `Ezurio `_. Modules ******* +Mbed TLS +======== + +* TLS 1.2, RSA, AES, DES, and all the hash algorithms except SHA-256 + (SHA-224, SHA-384, SHA-512, MD5 and SHA-1) are not enabled by default anymore. + Their respective Kconfig options now need to be explicitly enabled to be able to use them. + (:github:`72078`) +* The Kconfig options previously named ``CONFIG_MBEDTLS_MAC_*_ENABLED`` have been renamed. + The ``_MAC`` and ``_ENABLED`` parts have been removed from their names. (:github:`73267`) +* The :kconfig:option:`CONFIG_MBEDTLS_HASH_ALL_ENABLED` Kconfig option has been fixed to actually + enable all the available hash algorithms. Previously, it used to only enable the SHA-2 ones. + (:github:`73267`) +* The ``CONFIG_MBEDTLS_HASH_SHA*_ENABLED`` Kconfig options have been removed. They were duplicates + of other Kconfig options which are now named ``CONFIG_MBEDTLS_SHA*``. (:github:`73267`) +* The ``CONFIG_MBEDTLS_MAC_ALL_ENABLED`` Kconfig option has been removed. Its equivalent is the + combination of :kconfig:option:`CONFIG_MBEDTLS_HASH_ALL_ENABLED` and :kconfig:option:`CONFIG_MBEDTLS_CMAC`. + (:github:`73267`) +* The Kconfig options ``CONFIG_MBEDTLS_MAC_MD4_ENABLED``, ``CONFIG_MBEDTLS_CIPHER_ARC4_ENABLED`` + and ``CONFIG_MBEDTLS_CIPHER_BLOWFISH_ENABLED`` were removed because they are no more supported + in Mbed TLS. (:github:`73222`) +* When there is any PSA crypto provider available in the system + (i.e. :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT` is set), desired PSA crypto + features must be explicitly enabled using proper ``CONFIG_PSA_WANT_*``. (:github:`72243`) +* TLS/X509/PK/MD modules will use PSA crypto APIs instead of legacy ones as soon + as there is any PSA crypto provider available in the system + (i.e. :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT` is set). (:github:`72243`) + MCUboot ======= +Trusted Firmware-M +================== + +* The default MCUboot signature type has been changed from RSA-3072 to EC-P256. + This affects builds that have MCUboot enabled in TF-M (:kconfig:option:`CONFIG_TFM_BL2`). + If you wish to keep using RSA-3072, you need to set :kconfig:option:`CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE` + to `"RSA-3072"`. Otherwise, make sure to have your own signing keys of the signature type in use. + zcbor ===== @@ -54,7 +136,7 @@ Device Drivers and Devicetree compatible :dtcompatible:`nxp,pit-channel` and configure as below. The :kconfig:option:`CONFIG_COUNTER_MCUX_PIT` has also been renamed to :kconfig:option:`CONFIG_COUNTER_NXP_PIT` with regards to the renaming - of the binding for the pit. + of the binding for the pit. (:github:`66336`) example: .. code-block:: devicetree @@ -81,8 +163,8 @@ Device Drivers and Devicetree in DT, which also comes with a different version driver. Alternatively, the Ethernet node can be deleted and redefined as the old binding to use the deprecated legacy driver. The primary advantage of the new binding - is to be able to abstract an arbitrary phy through the mdio API. Example - of a basic board level ENET DT definition: + is to be able to abstract an arbitrary phy through the mdio API. (:github:`70400`) + Example of a basic board level ENET DT definition: .. code-block:: devicetree @@ -106,7 +188,11 @@ Device Drivers and Devicetree }; }; -* Some of the driver API structs have been rename to have the required ``_driver_api`` suffix. +* The :dtcompatible:`nxp,kinetis-lptmr` compatible string has been changed to + :dtcompatible:`nxp,lptmr`. The old string will be usable for a short time, but + should be replaced for it will be removed in the future. + +* Some of the driver API structs have been rename to have the required ``_driver_api`` suffix. (:github:`72182`) The following types have been renamed: * ``emul_sensor_backend_api`` to :c:struct:`emul_sensor_driver_api` @@ -114,8 +200,8 @@ Device Drivers and Devicetree * ``usbc_ppc_drv`` to :c:struct:`usbc_ppc_driver_api` * The driver for :dtcompatible:`maxim,max31790` got split up into a MFD and an - actual PWM driver. Previously, an instance of this device could have been - defined like this: + actual PWM driver. (:github:`68433`) + Previously, an instance of this device could have been defined like this: .. code-block:: devicetree @@ -150,21 +236,46 @@ Analog-to-Digital Converter (ADC) Bluetooth HCI ============= + * A new HCI driver API was introduced (:github:`72323`) and the old one deprecated. The new API + follows the normal Zephyr driver model, with devicetree nodes, etc. The host now + selects which driver instance to use as the controller by looking for a ``zephyr,bt-hci`` + chosen property. The devicetree bindings for all HCI drivers derive from a common + ``bt-hci.yaml`` base binding. + + * As part of the new HCI driver API, the ``zephyr,bt-uart`` chosen property is no longer used, + rather the UART HCI drivers select their UART by looking for the parent devicetree node of the + HCI driver instance node. + * As part of the new HCI driver API, the ``zephyr,bt-hci-ipc`` chosen property is only used for + the controller side, whereas the HCI driver now relies on nodes with the compatible string + ``zephyr,bt-hci-ipc``. + * The ``BT_NO_DRIVER`` Kconfig option was removed. HCI drivers are no-longer behind a Kconfig + choice, rather they can now be enabled and disabled independently, mostly based on their + respective devicetree node being enabled or not. + * The ``BT_HCI_VS_EXT`` Kconfig option was deleted and the feature is now included in the + :kconfig:option:`BT_HCI_VS` Kconfig option. + * The ``BT_HCI_VS_EVT`` Kconfig option was removed, since vendor event support is implicit if + the :kconfig:option:`BT_HCI_VS` option is enabled. + * The bt_read_static_addr() API was removed. This wasn't really a completely public API, but + since it was exposed by the public hci_driver.h header file the removal is mentioned here. + Enable the :kconfig:option:`BT_HCI_VS` Kconfig option instead, and use vendor specific HCI + commands API to get the Controller's Bluetooth static address when available. + Charger ======= * Dropped ``constant-charge-current-max-microamp`` property in ``charger_max20335`` driver because - it did not reflect real chip functionality. + it did not reflect real chip functionality. (:github:`69910`) * Added enum key to ``constant-charge-voltage-max-microvolt`` property in ``maxim,max20335-charger`` - binding to indicate invalid devicetree values at build time. + binding to indicate invalid devicetree values at build time. (:github:`69910`) Controller Area Network (CAN) ============================= * Removed the following deprecated CAN controller devicetree properties. Out-of-tree boards using - these properties need to switch to using the ``bus-speed``, ``sample-point``, ``bus-speed-data``, - and ``sample-point-data`` devicetree properties for specifying the initial CAN bitrate: + these properties can switch to using the ``bitrate``, ``sample-point``, ``bitrate-data``, and + ``sample-point-data`` devicetree properties (or rely on :kconfig:option:`CAN_DEFAULT_BITRATE` and + :kconfig:option:`CAN_DEFAULT_BITRATE_DATA`) for specifying the initial CAN bitrate: * ``sjw`` * ``prop-seg`` @@ -175,7 +286,12 @@ Controller Area Network (CAN) * ``phase-seg1-data`` * ``phase-seg1-data`` -* Support for manual bus-off recovery was reworked: + The ``bus-speed`` and ``bus-speed-data`` CAN controller devicetree properties have been + deprecated. + + (:github:`68714`) + +* Support for manual bus-off recovery was reworked (:github:`69460`): * Automatic bus recovery will always be enabled upon driver initialization regardless of Kconfig options. Since CAN controllers are initialized in "stopped" state, no unwanted bus-off recovery @@ -196,16 +312,230 @@ Controller Area Network (CAN) Display ======= +* GC9X01 based displays now use the MIPI DBI driver class. These displays + must now be declared within a MIPI DBI driver wrapper device, which will + manage interfacing with the display. (:github:`73686`) + For an example, see below: + + .. code-block:: devicetree + + /* Legacy GC9X01 display definition */ + &spi0 { + gc9a01: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + spi-max-frequency = <100000000>; + cmd-data-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + ... + }; + }; + + /* New display definition with MIPI DBI device */ + + #include + + ... + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + dc-gpios = <&gpio0 8 GPIO_ACTIVE_HIGH>; + reset-gpios = <&gpio0 14 GPIO_ACTIVE_LOW>; + spi-dev = <&spi0>; + #address-cells = <1>; + #size-cells = <0>; + + gc9a01: gc9a01@0 { + status = "okay"; + compatible = "galaxycore,gc9x01x"; + reg = <0>; + mipi-max-frequency = <100000000>; + ... + }; + }; + + +* ST7735R based displays now use the MIPI DBI driver class. These displays + must now be declared within a MIPI DBI driver wrapper device, which will + manage interfacing with the display. Note that the `cmd-data-gpios` pin has + changed polarity with this update, to align better with the new + `dc-gpios` name. For an example, see below: + + .. code-block:: devicetree + + /* Legacy ST7735R display definition */ + &spi0 { + st7735r: st7735r@0 { + compatible = "sitronix,st7735r"; + reg = <0>; + spi-max-frequency = <32000000>; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + cmd-data-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + ... + }; + }; + + /* New display definition with MIPI DBI device */ + + #include + + ... + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + spi-dev = <&spi0>; + #address-cells = <1>; + #size-cells = <0>; + + st7735r: st7735r@0 { + compatible = "sitronix,st7735r"; + reg = <0>; + mipi-max-frequency = <32000000>; + mipi-mode = ; + ... + }; + }; + +* UC81XX based displays now use the MIPI DBI driver class. These displays must + now be declared within a MIPI DBI driver wrapper device, which will manage + interfacing with the display. (:github:`73812`) Note that the ``dc-gpios`` + pin has changed polarity with this update, for an example, see below: + + .. code-block:: devicetree + + /* Legacy UC81XX display definition */ + &spi0 { + uc8179: uc8179@0 { + compatible = "ultrachip,uc8179"; + reg = <0>; + spi-max-frequency = <4000000>; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + ... + }; + }; + + /* New display definition with MIPI DBI device */ + + #include + + ... + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + spi-dev = <&spi0>; + #address-cells = <1>; + #size-cells = <0>; + uc8179: uc8179@0 { + compatible = "ultrachip,uc8179"; + reg = <0>; + mipi-max-frequency = <4000000>; + ... + }; + }; + +* ST7789V based displays now use the MIPI DBI driver class. These displays + must now be declared within a MIPI DBI driver wrapper device, which will + manage interfacing with the display. (:github:`73750`) Note that the + ``cmd-data-gpios`` pin has changed polarity with this update, to align better + with the new ``dc-gpios`` name. For an example, see below: + + .. code-block:: devicetree + + /* Legacy ST7789V display definition */ + &spi0 { + st7789: st7789@0 { + compatible = "sitronix,st7789v"; + reg = <0>; + spi-max-frequency = <32000000>; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + cmd-data-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + ... + }; + }; + + /* New display definition with MIPI DBI device */ + + #include + + ... + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + spi-dev = <&spi0>; + #address-cells = <1>; + #size-cells = <0>; + + st7789: st7789@0 { + compatible = "sitronix,st7789v"; + reg = <0>; + mipi-max-frequency = <32000000>; + mipi-mode = ; + ... + }; + }; + +* SSD16XX based displays now use the MIPI DBI driver class (:github:`73946`). + These displays must now be declared within a MIPI DBI driver wrapper device, + which will manage interfacing with the display. Note that the ``dc-gpios`` + pin has changed polarity with this update. For an example, see below: + + .. code-block:: devicetree + + /* Legacy SSD16XX display definition */ + &spi0 { + ssd1680: ssd1680@0 { + compatible = "solomon,ssd1680"; + reg = <0>; + spi-max-frequency = <4000000>; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>; + ... + }; + }; + + /* New display definition with MIPI DBI device */ + + #include + + ... + + mipi_dbi { + compatible = "zephyr,mipi-dbi-spi"; + reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>; + dc-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>; + spi-dev = <&spi0>; + #address-cells = <1>; + #size-cells = <0>; + + ssd1680: ssd1680@0 { + compatible = "solomon,ssd1680"; + reg = <0>; + mipi-max-frequency = <4000000>; + ... + }; + }; + Enhanced Serial Peripheral Interface (eSPI) =========================================== - * The macros ``ESPI_SLAVE_TO_MASTER`` and ``ESPI_MASTER_TO_SLAVE`` were renamed to - ``ESPI_TARGET_TO_CONTROLLER`` and ``ESPI_CONTROLLER_TO_TARGET`` respectively to reflect - the new terminology in eSPI 1.5 specification. - * The enum values ``ESPI_VWIRE_SIGNAL_SLV_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE`` and - all ``ESPI_VWIRE_SIGNAL_SLV_GPIO_`` signals were renamed to - ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE`` and - ``ESPI_VWIRE_SIGNAL_TARGET_GPIO_`` respectively to reflect the new terminology - in eSPI 1.5 specification. + +* The macros ``ESPI_SLAVE_TO_MASTER`` and ``ESPI_MASTER_TO_SLAVE`` were renamed to + ``ESPI_TARGET_TO_CONTROLLER`` and ``ESPI_CONTROLLER_TO_TARGET`` respectively to reflect + the new terminology in eSPI 1.5 specification. + The enum values ``ESPI_VWIRE_SIGNAL_SLV_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_SLV_BOOT_DONE`` and + all ``ESPI_VWIRE_SIGNAL_SLV_GPIO_`` signals were renamed to + ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_STS``, ``ESPI_VWIRE_SIGNAL_TARGET_BOOT_DONE`` and + ``ESPI_VWIRE_SIGNAL_TARGET_GPIO_`` respectively to reflect the new terminology + in eSPI 1.5 specification. (:github:`68492`) + The KConfig ``CONFIG_ESPI_SLAVE`` was renamed to ``CONFIG_ESPI_TARGET``, similarly + ``CONFIG_ESPI_SAF`` was renamed as ``CONFIG_ESPI_TAF`` (:github:`73887`) Flash ===== @@ -219,7 +549,7 @@ GNSS * Basic power management support has been added to the ``gnss-nmea-generic`` driver. If ``CONFIG_PM_DEVICE=y`` the driver is now initialized in suspended mode and the application needs to call :c:func:`pm_device_action_run` with :c:macro:`PM_DEVICE_ACTION_RESUME` - to start up the driver. + to start up the driver. (:github:`71774`) Input ===== @@ -228,30 +558,87 @@ Input relative to the raw ADC values, similarly to min and max. The data structures and properties have been renamed to reflect that (from ``out-deadzone`` to ``in-deadzone``) and when migrating to the new definition the value should be - scaled accordingly. + scaled accordingly. (:github:`70377`) * The ``holtek,ht16k33-keyscan`` driver has been converted to use the :ref:`input` subsystem, callbacks have to be migrated to use the input APIs, - :dtcompatible:`zephyr,kscan-input` can be used for backward compatibility. + :dtcompatible:`zephyr,kscan-input` can be used for backward compatibility. (:github:`69875`) Interrupt Controller ==================== +* The static auto-generation of the multilevel interrupt controller lookup table has been + deprecated, and will be compiled only when the new compatibility Kconfig: + :kconfig:option:`CONFIG_LEGACY_MULTI_LEVEL_TABLE_GENERATION` is enabled, which will eventually + be removed in the coming releases. + + Multi-level interrupt controller drivers should be updated to use the newly created + ``IRQ_PARENT_ENTRY_DEFINE`` macro to register itself with the new multi-level interrupt + architecture. To make the macro easier to use, ``INTC_INST_ISR_TBL_OFFSET`` macro is made to + deduce the software ISR table offset for a given driver instance, for pseudo interrupt controller + child, use the ``INTC_CHILD_ISR_TBL_OFFSET`` macro instead. New devicetree macros + (``DT_INTC_GET_AGGREGATOR_LEVEL`` & ``DT_INST_INTC_GET_AGGREGATOR_LEVEL``) have been added + for an interrupt controller driver instance to pass its aggregator level into the + ``IRQ_PARENT_ENTRY_DEFINE`` macro. + LED Strip ========= * The property ``in-gpios`` defined in :dtcompatible:`worldsemi,ws2812-gpio` has been - renamed to ``gpios``. + renamed to ``gpios``. (:github:`68514`) + +* The ``chain-length`` and ``color-mapping`` properties have been added to all LED strip bindings + and are now mandatory. + +* Added a new mandatory ``length`` function which returns the length (number of pixels) of an LED + strip device. + +* Made ``update_channels`` function optional and removed unimplemented functions. Sensors ======= +* The ``chip`` devicetree property from the :dtcompatible:`sensirion,shtcx` sensor driver has been + removed. Chip variants are now selected using the matching compatible property (:github:`74033`). + For an example of the new shtc3 configuration, see below: + + .. code-block:: devicetree + + &i2c0 { + status = "okay"; + + shtc3: shtc3@70 { + compatible = "sensirion,shtc3", "sensirion,shtcx"; + reg = <0x70>; + measure-mode = "normal"; + clock-stretching; + }; + }; + Serial ====== Timer ===== +regulator +========= + +* The :dtcompatible:`nxp,vref` driver no longer supports the ground selection function, + as this setting should not be modified by the user. The DT property ``nxp,ground-select`` + has been removed, users should remove this property from their devicetree if it is present. + (:github:`70642`) + +Watchdog +======== + +* The ``nuvoton,npcx-watchdog`` driver has been changed to extend the max timeout period. + The time of one watchdog count varies with the different pre-scalar settings. + Removed :kconfig:option:`CONFIG_WDT_NPCX_DELAY_CYCLES` because it is no longer suitable to + set the leading warning time. + Instead, added the :kconfig:option:`CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS` to set + the leading warning time in milliseconds. + Bluetooth ********* @@ -266,19 +653,67 @@ Bluetooth Mesh * The model metadata pointer declaration of :c:struct:`bt_mesh_model` has been changed to a single ``const *`` and redundant metadata pointer from :c:struct:`bt_mesh_health_srv` is removed. Consequently, :code:`BT_MESH_MODEL_HEALTH_SRV` definition is changed - to use variable argument notation. (:github:`71281`). Now, when your implementation + to use variable argument notation. Now, when your implementation supports :kconfig:option:`CONFIG_BT_MESH_LARGE_COMP_DATA_SRV` and when you need to specify metadata for Health Server model, simply pass metadata as the last argument - to the :code:`BT_MESH_MODEL_HEALTH_SRV` macro, otherwise omit the last argument. + to the :code:`BT_MESH_MODEL_HEALTH_SRV` macro, otherwise omit the last argument. (:github:`71281`) Bluetooth Audio =============== * :kconfig:option:`CONFIG_BT_ASCS`, :kconfig:option:`CONFIG_BT_PERIPHERAL` and - :kconfig:option:`CONFIG_BT_ISO_PERIPHERAL` are not longer `select`ed automatically when + :kconfig:option:`CONFIG_BT_ISO_PERIPHERAL` are no longer enabled automatically when enabling :kconfig:option:`CONFIG_BT_BAP_UNICAST_SERVER`, and these must now be set explicitly in the project configuration file. (:github:`71993`) +* The discover callback functions :code:`bt_cap_initiator_cb.unicast_discovery_complete` and + :code:`bt_cap_commander_cb.discovery_complete` for CAP now contain an additional parameter for + the set member. + This needs to be added to all instances of CAP discovery callback functions defined. + (:github:`72797`) + +* :c:func:`bt_bap_stream_start` no longer connects the CIS. To connect the CIS, + the :c:func:`bt_bap_stream_connect` shall now be called before :c:func:`bt_bap_stream_start`. + (:github:`73032`) + +* Renamed ``stream_lang`` to just ``lang`` to better fit with the assigned numbers document. + This affects the ``BT_AUDIO_METADATA_TYPE_LANG`` macro and the following functions: + + * :c:func:`bt_audio_codec_cap_meta_set_lang` + * :c:func:`bt_audio_codec_cap_meta_get_lang` + * :c:func:`bt_audio_codec_cfg_meta_set_lang` + * :c:func:`bt_audio_codec_cfg_meta_get_lang` + + (:github:`72584`) + +* Changed ``lang`` from ``uint32_t`` to ``uint8_t [3]``. This modifies the following functions: + + * :c:func:`bt_audio_codec_cap_meta_set_lang` + * :c:func:`bt_audio_codec_cap_meta_get_lang` + * :c:func:`bt_audio_codec_cfg_meta_set_lang` + * :c:func:`bt_audio_codec_cfg_meta_get_lang` + + The result of this is that string values such as ``"eng"`` and ``"deu"`` can now be used to set + new values, and to prevent unnecessary copies of data when getting the values. (:github:`72584`) + +* All occurrences of ``set_sirk`` have been changed to just ``sirk`` as the ``s`` in ``sirk`` stands + for set. (:github:`73413`) + +* Added ``fallback_to_default`` parameter to :c:func:`bt_audio_codec_cfg_get_chan_allocation`. + To maintain existing behavior set the parameter to ``false``. (:github:`72090`) + +* Added ``fallback_to_default`` parameter to + :c:func:`bt_audio_codec_cap_get_supported_audio_chan_counts`. + To maintain existing behavior set the parameter to ``false``. (:github:`72090`) + +* Added ``fallback_to_default`` parameter to + :c:func:`bt_audio_codec_cap_get_max_codec_frames_per_sdu`. + To maintain existing behavior set the parameter to ``false``. (:github:`72090`) + +* Added ``fallback_to_default`` parameter to + :c:func:`bt_audio_codec_cfg_meta_get_pref_context`. + To maintain existing behavior set the parameter to ``false``. (:github:`72090`) + Bluetooth Classic ================= @@ -301,6 +736,18 @@ Bluetooth Host (:github:`71686`) +* The field :code:`init_credits` in :c:type:`bt_l2cap_le_endpoint` has been removed as it was no + longer used in Zephyr 3.4.0 and later. Any references to this field should be removed. No further + action is needed. + +Bluetooth Crypto +================ + +* :kconfig:option:`CONFIG_BT_USE_PSA_API` was added to explicitly request use + of PSA APIs instead of TinyCrypt for crypto operations. Of course, this is + possible only a PSA crypto provider available in the system, i.e. + :kconfig:option:`CONFIG_PSA_CRYPTO_CLIENT` is set. (:github:`73378`) + Networking ********** @@ -318,8 +765,7 @@ Networking * The zperf zperf_results struct is changed to support 64 bits transferred bytes (total_len) and test duration (time_in_us and client_time_in_us), instead of 32 bits. This will make - the long-duration zperf test show with correct throughput result. - (:github:`69500`) + the long-duration zperf test show with correct throughput result. (:github:`69500`) * Each IPv4 address assigned to a network interface has an IPv4 netmask tied to it instead of being set for the whole interface. @@ -353,16 +799,49 @@ Networking ``CONFIG_NET_TCP_RETRY_COUNT`` instead to control the total timeout at the TCP level. (:github:`70731`) +* In LwM2M API, the callback type :c:type:`lwm2m_engine_set_data_cb_t` has now an additional + parameter ``offset``. This parameter is used to indicate the offset of the data + during a Coap Block-wise transfer. Any post write, validate or some firmware callbacks + should be updated to include this parameter. (:github:`72590`) + +* The DNS resolver and mDNS/LLMNR responders are converted to use socket service API. + This means that the number of pollable sockets in the system might need to be increased. + Please check that the values of :kconfig:option:`CONFIG_NET_SOCKETS_POLL_MAX` and + :kconfig:option:`CONFIG_POSIX_MAX_FDS` are high enough. Unfortunately no exact values + for these can be given as it depends on application needs and usage. (:github:`72834`) + +* The packet socket (type ``AF_PACKET``) protocol field in ``socket`` API call has changed. + The protocol field should be in network byte order so that we are compatible with Linux + socket calls. Linux expects the protocol field to be ``htons(ETH_P_ALL)`` if it is desired + to receive all the network packets. See details in + https://www.man7.org/linux/man-pages/man7/packet.7.html documentation. (:github:`73338`) + +* TCP now uses SHA-256 instead of MD5 for ISN generation. The crypto support for + this hash computation was also changed from Mbed TLS to PSA APIs. This was achieved + by making :kconfig:option:`CONFIG_NET_TCP_ISN_RFC6528` depend on + :kconfig:option:`PSA_WANT_ALG_SHA_256` instead of legacy ``CONFIG_MBEDTLS_*`` + features. (:github:`71827`) + Other Subsystems **************** +Flash map +========= + +* The crypto backend for the flash check functions (:kconfig:option:`CONFIG_FLASH_AREA_CHECK_INTEGRITY_BACKEND`), + previously provided through either TinyCrypt or Mbed TLS, is now provided through either PSA or Mbed TLS. + The updated Mbed TLS implementation has a slightly smaller footprint than the previous TinyCrypt one, + and the PSA implementation offers an even greater footprint reduction for devices built with TF-M. + PSA is the supported way forward, however as of now you may still use Mbed TLS if you cannot afford the + one-time cost of enabling the PSA API (:kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_C` for devices without TF-M). + :github:`73511` + hawkBit ======= - * :kconfig:option:`CONFIG_HAWKBIT_PORT` is now an int instead of a string. - - * :kconfig:option:`CONFIG_SETTINGS` needs to be enabled to use hawkBit, as it now uses the - settings subsystem to store the hawkBit configuration. +* :kconfig:option:`CONFIG_HAWKBIT_PORT` is now an int instead of a string. + :kconfig:option:`CONFIG_SETTINGS` needs to be enabled to use hawkBit, as it now uses the + settings subsystem to store the hawkBit configuration. (:github:`68806`) LoRaWAN ======= @@ -370,11 +849,30 @@ LoRaWAN MCUmgr ====== +* The support for SHA-256 (when using checksum/hash functions), previously provided + by either TinyCrypt or Mbed TLS, is now provided by either PSA or Mbed TLS. + PSA is the recommended API going forward, however, if it is not already enabled + (:kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT`) and you have tight code size + constraints, you may be able to save 1.3 KB by using Mbed TLS instead. + Modem ===== * The ``CONFIG_MODEM_CHAT_LOG_BUFFER`` Kconfig option was - renamed to :kconfig:option:`MODEM_CHAT_LOG_BUFFER_SIZE`. + renamed to :kconfig:option:`CONFIG_MODEM_CHAT_LOG_BUFFER_SIZE`. (:github:`70405`) + +.. _zephyr_3.7_posix_api_migration: + +POSIX API +========= + +* The :ref:`POSIX API Kconfig deprecations ` may require + changes to Kconfig files (``prj.conf``, etc), as outlined in the release notes. A more automated + approach is available via the provided migration script. Simply run the following: + + .. code-block:: bash + + $ python ${ZEPHYR_BASE}/scripts/utils/migrate_posix_kconfigs.py -r root_path Shell ===== @@ -386,6 +884,23 @@ State Machine Framework now independent of the values of :kconfig:option:`CONFIG_SMF_ANCESTOR_SUPPORT` and :kconfig:option:`CONFIG_SMF_INITIAL_TRANSITION`. If the additional arguments are not used, they have to be set to ``NULL``. (:github:`71250`) +* SMF now follows a more UML-like transition flow when the transition source is a parent of the + state called by :c:func:`smf_run_state`. Exit actions up to (but not including) the Least Common + Ancestor of the transition source and target state will be executed, as will entry actions from + (but not including) the LCA down to the target state. (:github:`71675`) +* Previously, calling :c:func:`smf_set_state` with a ``new_state`` set to NULL would execute all + exit actions from the current state to the topmost parent, with the expectation the topmost exit + action would terminate the state machine. Passing ``NULL`` is now not allowed. Instead create a + 'terminate' state at the top level, and call :c:func:`smf_set_terminate` from its entry action. + +UpdateHub +========= + +* The SHA-256 implementation used to perform integrity checks is not chosen with + :kconfig:option:`CONFIG_FLASH_AREA_CHECK_INTEGRITY_BACKEND` anymore. Instead, the implementation + used (now either Mbed TLS or PSA) is chosen based on :kconfig:option:`CONFIG_PSA_CRYPTO_CLIENT`. + It still defaults to using Mbed TLS (with a smaller footprint than previously) unless the + board is built with TF-M or :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_C` is enabled. (:github:`73511`) ZBus ==== @@ -396,19 +911,22 @@ Userspace Architectures ************* -* Function :c:func:`arch_start_cpu` has been renamed to :c:func:`arch_cpu_start`. +* Function :c:func:`arch_start_cpu` has been renamed to :c:func:`arch_cpu_start`. (:github:`64987`) + +* ``CONFIG_ARM64_ENABLE_FRAME_POINTER`` is deprecated. Use :kconfig:option:`CONFIG_FRAME_POINTER` + instead. (:github:`72646`) * x86 * Kconfigs ``CONFIG_DISABLE_SSBD`` and ``CONFIG_ENABLE_EXTENDED_IBRS`` are deprecated. Use :kconfig:option:`CONFIG_X86_DISABLE_SSBD` and - :kconfig:option:`CONFIG_X86_ENABLE_EXTENDED_IBRS` instead. + :kconfig:option:`CONFIG_X86_ENABLE_EXTENDED_IBRS` instead. (:github:`69690`) * POSIX arch: * LLVM fuzzing support has been refactored. A test application now needs to provide its own ``LLVMFuzzerTestOneInput()`` hook instead of relying on a board provided one. Check - ``samples/subsys/debug/fuzz/`` for an example. + ``samples/subsys/debug/fuzz/`` for an example. (:github:`71378`) Xtensa ====== diff --git a/doc/releases/release-notes-3.7.rst b/doc/releases/release-notes-3.7.rst index bc60d8f3d2c40..84c783055d543 100644 --- a/doc/releases/release-notes-3.7.rst +++ b/doc/releases/release-notes-3.7.rst @@ -13,6 +13,8 @@ Major enhancements with this release include: the way both SoCs and boards are named, defined and constructed in Zephyr. Additional information can be found in the :ref:`board_porting_guide`. * Zephyr now requires Python 3.10 or higher +* Trusted Firmware-M (TF-M) 2.1.0 and Mbed TLS 3.6.0 have been integrated into Zephyr. + Both of these versions are LTS releases. An overview of the changes required or recommended when migrating your application from Zephyr v3.6.0 to Zephyr v3.7.0 can be found in the separate :ref:`migration guide`. @@ -29,6 +31,14 @@ https://docs.zephyrproject.org/latest/security/vulnerabilities.html * CVE-2024-3077 `Zephyr project bug tracker GHSA-gmfv-4vfh-2mh8 `_ +* CVE-2024-3332 Under embargo until 2024-07-01 + +* CVE-2024-4785: Under embargo until 2024-08-07 + +* CVE-2024-5754: Under embargo until 2024-09-04 + +* CVE-2024-5931: Under embargo until 2024-09-10 + API Changes *********** @@ -38,6 +48,8 @@ Removed APIs in this release * The Bluetooth subsystem specific debug symbols are removed. They have been replaced with the Zephyr logging ones. + * Removed deprecated ``pcie_probe`` and ``pcie_bdf_lookup`` functions from the PCIe APIs. + Deprecated in this release ========================== @@ -56,6 +68,62 @@ Deprecated in this release Application developer will now need to set the advertised name themselves by updating the advertising data or the scan response data. +.. _zephyr_3.7_posix_api_deprecations: + + * POSIX API + + * Deprecated :c:macro:`PTHREAD_BARRIER_DEFINE` has been removed. + * Deprecated :c:macro:`EFD_IN_USE` and :c:macro:`EFD_FLAGS_SET` have been removed. + + * In efforts to use Kconfig options that map directly to the Options and Option Groups in + IEEE 1003.1-2017, the following Kconfig options have been deprecated (replaced by): + + * :kconfig:option:`CONFIG_EVENTFD_MAX` (:kconfig:option:`CONFIG_ZVFS_EVENTFD_MAX`) + * :kconfig:option:`CONFIG_FNMATCH` (:kconfig:option:`CONFIG_POSIX_C_LIB_EXT`) + * :kconfig:option:`CONFIG_GETENTROPY` (:kconfig:option:`CONFIG_POSIX_C_LIB_EXT`) + * :kconfig:option:`CONFIG_GETOPT` (:kconfig:option:`CONFIG_POSIX_C_LIB_EXT`) +  * :kconfig:option:`CONFIG_MAX_PTHREAD_COUNT` (:kconfig:option:`CONFIG_POSIX_THREAD_THREADS_MAX`) + * :kconfig:option:`CONFIG_MAX_PTHREAD_KEY_COUNT` (:kconfig:option:`CONFIG_POSIX_THREAD_KEYS_MAX`) + * :kconfig:option:`CONFIG_MAX_TIMER_COUNT` (:kconfig:option:`CONFIG_POSIX_TIMER_MAX`) + * :kconfig:option:`CONFIG_POSIX_LIMITS_RTSIG_MAX` (:kconfig:option:`CONFIG_POSIX_RTSIG_MAX`) + * :kconfig:option:`CONFIG_POSIX_CLOCK` (:kconfig:option:`CONFIG_POSIX_CLOCK_SELECTION`, + :kconfig:option:`CONFIG_POSIX_CPUTIME`, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK`, + :kconfig:option:`CONFIG_POSIX_TIMERS`, and :kconfig:option:`CONFIG_POSIX_TIMEOUTS`) + * :kconfig:option:`CONFIG_POSIX_CONFSTR` (:kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS`) + * :kconfig:option:`CONFIG_POSIX_ENV` (:kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS`) + * :kconfig:option:`CONFIG_POSIX_FS` (:kconfig:option:`CONFIG_POSIX_FILE_SYSTEM`) + * :kconfig:option:`CONFIG_POSIX_MAX_FDS` (:kconfig:option:`CONFIG_POSIX_OPEN_MAX` and + :kconfig:option:`CONFIG_ZVFS_OPEN_MAX`) + * :kconfig:option:`CONFIG_POSIX_MAX_OPEN_FILES` (:kconfig:option:`CONFIG_POSIX_OPEN_MAX` and + :kconfig:option:`CONFIG_ZVFS_OPEN_MAX`) + * :kconfig:option:`CONFIG_POSIX_MQUEUE` (:kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING`) + * :kconfig:option:`CONFIG_POSIX_PUTMSG` (:kconfig:option:`CONFIG_XOPEN_STREAMS`) + * :kconfig:option:`CONFIG_POSIX_SIGNAL` (:kconfig:option:`CONFIG_POSIX_SIGNALS`) + * :kconfig:option:`CONFIG_POSIX_SYSCONF` (:kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS`) + * :kconfig:option:`CONFIG_POSIX_SYSLOG` (:kconfig:option:`CONFIG_XSI_SYSTEM_LOGGING`) + * :kconfig:option:`CONFIG_POSIX_UNAME` (:kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS`) + * :kconfig:option:`CONFIG_PTHREAD` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_BARRIER` (:kconfig:option:`CONFIG_POSIX_BARRIERS`) + * :kconfig:option:`CONFIG_PTHREAD_COND` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_IPC` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_KEY` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_MUTEX` (:kconfig:option:`CONFIG_POSIX_THREADS`) + * :kconfig:option:`CONFIG_PTHREAD_RWLOCK` (:kconfig:option:`CONFIG_POSIX_READER_WRITER_LOCKS`) + * :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` (:kconfig:option:`CONFIG_POSIX_SPIN_LOCKS`) + * :kconfig:option:`CONFIG_SEM_NAMELEN_MAX` (:kconfig:option:`CONFIG_POSIX_SEM_NAMELEN_MAX`) + * :kconfig:option:`CONFIG_SEM_VALUE_MAX` (:kconfig:option:`CONFIG_POSIX_SEM_VALUE_MAX`) + * :kconfig:option:`CONFIG_TIMER` (:kconfig:option:`CONFIG_POSIX_TIMERS`) + * :kconfig:option:`CONFIG_TIMER_DELAYTIMER_MAX` (:kconfig:option:`CONFIG_POSIX_DELAYTIMER_MAX`) + + Please see the :ref:`POSIX API migration guide `. + + * SPI + + * Deprecated :c:func:`spi_is_ready` API function has been removed. + * Deprecated :c:func:`spi_transceive_async` API function has been removed. + * Deprecated :c:func:`spi_read_async` API function has been removed. + * Deprecated :c:func:`spi_write_async` API function has been removed. + Architectures ************* @@ -63,32 +131,88 @@ Architectures * ARM -* RISC-V +* ARM64 - * Implemented frame-pointer based stack unwinding. + * Implemented symbol names in the backtraces, enable by selecting :kconfig:option:`CONFIG_SYMTAB` + +* RISC-V * The fatal error message triggered from a fault now contains the callee-saved-registers states. + * Implemented stack unwinding + + * Frame-pointer can be selected to enable precise stack traces at the expense of slightly + increased size and decreased speed. + + * Symbol names can be enabled by selecting :kconfig:option:`CONFIG_EXCEPTION_STACK_TRACE_SYMTAB` + * Xtensa +Kernel +****** + + * Added :c:func:`k_uptime_seconds` function to simplify `k_uptime_get() / 1000` usage. + + * Added :c:func:`k_realloc`, that uses kernel heap to implement traditional :c:func:`realloc` + semantics. + Bluetooth ********* +* Audio + + * Removed ``err`` from :c:struct:`bt_bap_broadcast_assistant_cb.recv_state_removed` as it was + redundant. + + * The broadcast_audio_assistant sample has been renamed to bap_broadcast_assistant. + The broadcast_audio_sink sample has been renamed to bap_broadcast_sink. + The broadcast_audio_source sample has been renamed to bap_broadcast_source. + The unicast_audio_client sample has been renamed to bap_unicast_client. + The unicast_audio_server sample has been renamed to bap_unicast_server. + The public_broadcast_sink sample has been renamed to pbp_public_broadcast_sink. + The public_broadcast_source sample has been renamed to pbp_public_broadcast_source. + + * The CAP Commander and CAP Initiator now no longer require CAS to be discovered for + :code:`BT_CAP_SET_TYPE_AD_HOC` sets. This allows applications to use these APIs on e.g. + BAP Unicast Servers that do not implement the CAP Acceptor role. + +* Host * Added Nordic UART Service (NUS), enabled by the :kconfig:option:`CONFIG_BT_ZEPHYR_NUS`. This Service exposes the ability to declare multiple instances of the GATT service, allowing multiple serial endpoints to be used for different purposes. + * Implemented Hands-free Audio Gateway (AG), enabled by the :kconfig:option:`CONFIG_BT_HFP_AG`. + It works as a device that is the gateway of the audio. Typical device acting as Audio + Gateway is cellular phone. It controls the device (Hands-free Unit), that is the remote + audio input and output mechanism. + + * Implemented Advanced Audio Distribution Profile (A2DP) and Audio/Video Distribution Transport + Protocol (AVDTP), A2DP is enabled by :kconfig:option:`CONFIG_BT_A2DP`, AVDTP is enabled + by :kconfig:option:`CONFIG_BT_AVDTP`. They implement the protocols and procedures that + realize distribution of audio content of high quality in mono, stereo, or multi-channel modes. + A typical use case is the streaming of music content from a stereo music player to headphones + or speakers. The audio data is compressed in a proper format for efficient use of the limited + bandwidth. + +* HCI Driver + + * Added support for Ambiq Apollo3 Blue series. + Boards & SoC Support ******************** * Added support for these SoC series: + * Added support for Ambiq Apollo3 Blue and Apollo3 Blue Plus SoC series. + * Made these changes in other SoC series: * ITE: Rename the Kconfig symbol for all ITE SoC variants. * Added support for these ARM boards: + * Added support for Ambiq Apollo3 boards: ``apollo3_evb``, ``apollo3p_evb``. + * Added support for these Xtensa boards: * Made these changes for ARM boards: @@ -97,6 +221,8 @@ Boards & SoC Support * Made these changes for native/POSIX boards: + * Introduced the simulated :ref:`nrf54l15bsim` target. + * LLVM fuzzing support has been refactored while adding support for it in native_sim. * Added support for these following shields: @@ -116,6 +242,8 @@ Build system and Infrastructure choice to select the C Standard version. Additionally subsystems can select a minimum required C Standard version, with for example :kconfig:option:`CONFIG_REQUIRES_STD_C11`. + * Fixed issue with passing UTF-8 configs to applications using sysbuild. + Drivers and Sensors ******************* @@ -154,6 +282,8 @@ Drivers and Sensors * Updated the CAN timing functions to take the minimum supported bitrate into consideration when validating the bitrate. * Made the ``sample-point`` and ``sample-point-data`` devicetree properties optional. + * Renamed the ``bus_speed`` and ``bus_speed_data`` fields of :c:struct:`can_driver_config` to + ``bitrate`` and ``bitrate_data``. * Charger @@ -166,6 +296,8 @@ Drivers and Sensors * Counter + * Added support for Ambiq Apollo3 series. + * Crypto * Display @@ -176,8 +308,8 @@ Drivers and Sensors * eSPI - * Renamed eSPI virtual wire direction macros and enum values to match the new terminology in - eSPI 1.5 specification. + * Renamed eSPI virtual wire direction macros, enum values and KConfig to match the new + terminology in eSPI 1.5 specification. * Ethernet @@ -188,12 +320,18 @@ Drivers and Sensors * Flash + * Added support for Ambiq Apollo3 series. + * GNSS * GPIO + * Added support for Ambiq Apollo3 series. + * I2C + * Added support for Ambiq Apollo3 series. + * I2S * I3C @@ -202,10 +340,32 @@ Drivers and Sensors * Input +* LED Strip + + * The ``chain-length`` and ``color-mapping`` properties have been added to all LED strip + bindings. + + +* LoRa + + * Added driver for Reyax LoRa module + * MDIO * MFD +* Modem + + * Removed deprecated ``GSM_PPP`` driver along with its dts compatible ``zephyr,gsm-ppp``. + + * Removed deprecated ``UART_MUX`` and ``GSM_MUX`` previously used by ``GSM_PPP``. + + * Removed support for dts compatible ``zephyr,gsm-ppp`` from ``MODEM_CELLULAR`` driver. + + * Removed integration with ``UART_MUX`` from ``MODEM_IFACE_UART_INTERRUPT`` module. + + * Removed integration with ``UART_MUX`` from ``MODEM_SHELL`` module. + * PCIE * MEMC @@ -229,6 +389,7 @@ Drivers and Sensors * Sensor * Added TMP114 driver + * Added DS18S20 1-wire temperature sensor driver. * Serial @@ -238,15 +399,37 @@ Drivers and Sensors * SPI + * Added support for Ambiq Apollo3 series general IOM based SPI. + * Added support for Ambiq Apollo3 BLEIF based SPI, which is specific for internal HCI. + * USB * W1 +* Watchdog + + * Added :kconfig:option:`CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS` to set the leading warning time + in milliseconds. Removed no longer used :kconfig:option:`CONFIG_WDT_NPCX_DELAY_CYCLES`. + * Added support for Ambiq Apollo3 series. + * Wi-Fi * Added support for configuring RTS threshold. With this, users can set the RTS threshold value or disable the RTS mechanism. + * Added support for configuring AP parameters. With this, users can set AP parameters at + build and run time. + + * Added support to configure "max_inactivity" BSS parameter. Users can set this both build and runtime + duration to control the maximum time duration after which AP may disconnect a STA due to inactivity + from STA. + + * Added support to configure "inactivity_poll" BSS parameter. Users can set build only AP parameter + to control whether AP may poll the STA before throwing away STA due to inactivity. + + * Added support to configure "max_num_sta" BSS parameter. Users can set this both build and run time + parameter to control the maximum numuber of STA entries. + Networking ********** @@ -270,10 +453,18 @@ Networking * :c:func:`lwm2m_set_bulk` + * Added new ``offset`` parameter to :c:type:`lwm2m_engine_set_data_cb_t` callback type. + This affects post write and validate callbacks as well as some firmware callbacks. + * IPSP: * Removed IPSP support. ``CONFIG_NET_L2_BT`` does not exist anymore. +* TCP: + + * ISN generation now uses SHA-256 instead of MD5. Moreover it now relies on PSA APIs + instead of legacy Mbed TLS functions for hash computation. + USB *** @@ -283,6 +474,13 @@ Devicetree Libraries / Subsystems ********************** +* Debug + + * symtab + + * By enabling :kconfig:option:`CONFIG_SYMTAB`, the symbol table will be + generated with Zephyr link stage executable on supported architectures. + * Management * hawkBit @@ -306,6 +504,11 @@ Libraries / Subsystems registered to set the device attributes that are sent to the hawkBit server. Use the :c:func:`hawkbit_set_custom_data_cb` function to register the callback. + * MCUmgr + + * Instructions for the deprecated mcumgr go tool have been removed, a list of alternative, + supported clients can be found on :ref:`mcumgr_tools_libraries`. + * Logging * By enabling :kconfig:option:`CONFIG_LOG_BACKEND_NET_USE_DHCPV4_OPTION`, the IP address of the @@ -319,6 +522,20 @@ Libraries / Subsystems * Crypto + * Mbed TLS was updated to 3.6.0. Release notes can be found at: + https://github.com/Mbed-TLS/mbedtls/releases/tag/v3.6.0 + * When any PSA crypto provider is available in the system + (:kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT` is enabled), desired PSA features + must now be explicitly selected through ``CONFIG_PSA_WANT_xxx`` symbols. + * Choice symbols :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_LEGACY_RNG` and + :kconfig:option:`CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG` were added in order + to allow the user to specify how Mbed TLS PSA crypto core should generate random numbers. + The former option, which is the default, relies on legacy entropy and CTR_DRBG/HMAC_DRBG + modules, while the latter relies on CSPRNG drivers. + * :kconfig:option:`CONFIG_MBEDTLS_PSA_P256M_DRIVER_ENABLED` enables support + for the Mbed TLS's p256-m driver PSA crypto library. This is a Cortex-M SW + optimized implementation of secp256r1 curve. + * Random * Besides the existing :c:func:`sys_rand32_get` function, :c:func:`sys_rand8_get`, @@ -332,6 +549,9 @@ Libraries / Subsystems * State Machine Framework * The :c:macro:`SMF_CREATE_STATE` macro now always takes 5 arguments. + * Transition sources that are parents of the state that was run now choose the correct Least + Common Ancestor for executing Exit and Entry Actions. + * Passing ``NULL`` to :c:func:`smf_set_state` is now not allowed. * Storage @@ -340,6 +560,9 @@ Libraries / Subsystems :kconfig:option:`CONFIG_FS_FATFS_MKFS` Kconfig option. This option is enabled by default if :kconfig:option:`CONFIG_FILE_SYSTEM_MKFS` is set. + * FS: It is now possible to truncate a file while opening using :c:func:`fs_open` + and by passing ``FS_O_TRUNC`` flag. + * POSIX API * LoRa/LoRaWAN @@ -354,6 +577,16 @@ HALs MCUboot ******* +Trusted Firmware-M +****************** + +* TF-M was updated to 2.1.0. Release notes can be found at: + https://tf-m-user-guide.trustedfirmware.org/releases/2.1.0.html + +* Support for MCUboot signature types other than RSA-3072 has been added. + The type can be chosen with the :kconfig:option:`CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE` Kconfig option. + Using EC-P256, the new default, reduces flash usage by several KBs compared to RSA. + zcbor ***** @@ -367,3 +600,12 @@ Tests and Samples ``west build``. This snippet sets the :kconfig:option:`CONFIG_BT_ZEPHYR_NUS_AUTO_START_BLUETOOTH` which allows non-Bluetooth samples that use the UART APIs to run without modifications (e.g: Console and Logging examples). + + * Removed ``GSM_PPP`` specific configuration overlays from samples ``net/cloud/tagoio`` and + ``net/mgmt/updatehub``. The ``GSM_PPP`` device driver has been deprecated and removed. The new + ``MODEM_CELLULAR`` device driver which replaces it uses the native networking stack and ``PM`` + subsystem, which like ethernet, requires no application specific actions to set up networking. + + * Removed ``net/gsm_modem`` sample as the ``GSM_PPP`` device driver it depended on has been + deprecated and removed. The sample has been replaced by the sample ``net/cellular_modem`` + based on the ``MODEM_CELLULAR`` device driver. diff --git a/doc/requirements.txt b/doc/requirements.txt index bb12e241930e5..55cf8de629759 100644 --- a/doc/requirements.txt +++ b/doc/requirements.txt @@ -15,8 +15,9 @@ sphinx-sitemap PyYAML>=6.0 pykwalify -# Used by pytest-twister-harness plugin +# Used by pytest-twister-harness plugin (imported by autodoc) pytest +pyserial # Doxygen doxmlparser doxmlparser diff --git a/doc/safety/index.rst b/doc/safety/index.rst index 1eb55d12a325e..734f9a19ac4ae 100644 --- a/doc/safety/index.rst +++ b/doc/safety/index.rst @@ -11,3 +11,4 @@ for ensuring safety is addressed within the Zephyr project. :glob: safety_overview.rst + safety_requirements.rst diff --git a/doc/safety/safety_overview.rst b/doc/safety/safety_overview.rst index 9a17434e6d0fb..39a9da169df8e 100644 --- a/doc/safety/safety_overview.rst +++ b/doc/safety/safety_overview.rst @@ -99,7 +99,7 @@ which need to be reached to achieve an auditable code base: 1. Basic software quality standards a. :ref:`coding_guidelines` (including: static code analysis, coding style, etc.) - b. Requirements and requirements tracing + b. :ref:`safety_requirements` and requirements tracing c. Test coverage 2. Software architecture design principles diff --git a/doc/safety/safety_requirements.rst b/doc/safety/safety_requirements.rst new file mode 100644 index 0000000000000..097c9063b4977 --- /dev/null +++ b/doc/safety/safety_requirements.rst @@ -0,0 +1,120 @@ +.. _safety_requirements: + +Safety Requirements +################### + +Introduction +************ + +The safety committee leads the effort to gather requirements that reflect the **actual** state of +the implementation, following the `route 3s `_ +approach of the project's safety effort. The goal is **NOT** to create new requirements to request +additional features for the project. + +The requirements are gathered in the separate repository: +`Requirement repository +`__ + +Guidelines +********** + +Below are the guidelines for the requirements repository and the expectations of the safety +committee when adding requirements to the repository. + +Scope +===== + +The scope of the requirements covers the KERNEL functionalities. + +Consistency +=========== + +Maintain consistency across all requirements. The language and choice of words shall be consistent. +(See: `Syntax`_) + +Levels of requirements in the repository +======================================== + +System Requirements + System requirements describe the behaviour of the Zephyr RTOS (= the system here). + They describe the functionality of the Zephyr RTOS from a very high-level perspective, + without going into details of the functionality itself. + The purpose of the system requirements is to get an overview of the currently implemented features + of the Zephyr RTOS. + In other words a person writing these requirements usually has some knowledge of the Zephyr RTOS + Project as the requirements are specific to an RTOS. + +Software Requirements + Software requirements refine the system-level requirements at a more granular level so + that each requirement can be tested. + These requirements define the specific actions the feature shall be able to execute and the + behavior of the feature. + +Requirement UID (Unique identifier) Handling +============================================ + +The tool used to manage requirements, `strictDoc `_, is +responsible for handling the Unique Identifier (UID) associated with each requirement. To manage +UIDs, follow these steps: + +#. Don't add a requirement UID and UID field for new requirements +#. After completing work on the new requirements execute: ``strictDoc manage auto-uid .`` +#. Establish links between the requirements with the new attributed UIDs if needed + +After doing this, the requirements are ready and a pull request can be created. +The CI in the PR will check if the requirements UIDs are valid or if there are duplicates in it. +If there are duplicates in the PR, these need to be resolved by rebasing and re-executing +the steps above. + +Requirement Types +================= + +* Functional +* Non-Functional + +Requirement title convention +============================ + +Use short and succinct requirement titles. + +Pull Request requirement repository +=================================== + +* Adhere to the :ref:`contribute_guidelines` of the Zephyr Project. + + * As long as they are applicable to the requirements repository. + +* Avoid creating large commits that contain both trivial and non-trivial changes. + +* Avoid moving and changing requirements in the same commit. + +Characteristics of a good requirement +===================================== + +* Unambiguous +* Verifiable (e.g. testable for functional requirements) +* Clear (concise, succinct, simple, precise) +* Correct +* Understandable +* Feasible (realistic, possible) +* Independent +* Atomic +* Necessary +* Implementation-free (abstract) + +Characteristics of a set of requirements +======================================== + +* Complete +* Consistent +* Non redundant + +Syntax +====== + +* Use of a recognized Requirements Syntax is recommended. + + * `EARS `_ is a good reference. Particularly if you are + unfamiliar with requirements writing. + + * Other formats are accepted as long as the characteristics of a requirement from above are met. diff --git a/doc/security/index.rst b/doc/security/index.rst index 2ae92f7f57224..f05691c014e7e 100644 --- a/doc/security/index.rst +++ b/doc/security/index.rst @@ -16,3 +16,4 @@ for ensuring security is addressed within the Zephyr project. sensor-threat.rst hardening-tool.rst vulnerabilities.rst + standards/index.rst diff --git a/doc/security/reporting.rst b/doc/security/reporting.rst index 376237fe938ce..946e502fa54ab 100644 --- a/doc/security/reporting.rst +++ b/doc/security/reporting.rst @@ -101,6 +101,8 @@ and 2. Exploitability of the issue. Issues that the subcommittee decides do not need an embargo will be reproduced in the regular Zephyr project bug tracking system. +.. _vulnerability_timeline: + Security sensitive vulnerabilities shall be made public after an embargo period of at most 90 days. The intent is to allow 30 days within the Zephyr project to fix the issues, and 60 days for external diff --git a/doc/security/security-overview.rst b/doc/security/security-overview.rst index 6ed15fa55ba89..53c956cbe53b5 100644 --- a/doc/security/security-overview.rst +++ b/doc/security/security-overview.rst @@ -122,14 +122,12 @@ Security Functionality The security functionality in Zephyr hinges mainly on the inclusion of cryptographic algorithms, and on its monolithic system design. -The cryptographic features are provided through a set of cryptographic -libraries. Applications can choose TinyCrypt2 or Mbed TLS based on their -needs. TinyCrypt2 supports key cryptographic algorithms required by the -connectivity stacks. TinyCrypt2, however, only provides a limited set of -algorithms. Mbed TLS supports a wider range of algorithms, but at the -cost of additional requirements such as malloc support. Applications can -choose the solution that matches their individual requirements. Future -work may include APIs to abstract the underlying crypto library choice. +The cryptographic features are provided through PSA Crypto, with +mbedTLS as the underlying implementation. Applications leverage PSA +Crypto APIs, ensuring a standardized and secure approach to +cryptographic operations. mbedTLS, as the implementation of PSA +Crypto, supports a wide range of cryptographic algorithms, making it +suitable for various application requirements. APIs for vendor specific cryptographic IPs in both hardware and software are planned, including secure key storage in the form of secure access diff --git a/doc/security/standards/etsi-303645.rst b/doc/security/standards/etsi-303645.rst new file mode 100644 index 0000000000000..ce78c96ab676e --- /dev/null +++ b/doc/security/standards/etsi-303645.rst @@ -0,0 +1,739 @@ +.. _etsi_303645: + +ETSI 303-645 +############ + + +`ETSI EN 303 645`, also known as "Cyber Security for Consumer Internet +of Things: Baseline Requirements," is a standard developed by the +European Telecommunications Standards Institute (ETSI). + +The standard includes provisions for secure software updates, data +protection, secure communication, and the minimization of exposed +attack surfaces, among other things. It is part of a broader effort to +address the challenges and risks associated with IoT devices. + +Full version of the standard can be found `here `_. + + +Terminology +*********** + +.. list-table:: ETSI 303645 terminology + :widths: 17 43 + + * - administrator + - user who has the highest-privilege level possible for a user of the device, + which can mean they are able to change any configuration related to the intended + functionality. + + * - associated services + - digital services that, together with the device, are part of the overall consumer + IoT product and that are typically required to provide the product's intended + functionality. + + * - authentication mechanism + - method used to prove the authenticity of an entity. + + * - authentication value + - individual value of an attribute used by an authentication mechanism. + + * - best practice cryptography + - cryptography that is suitable for the corresponding use case and has no + indications of a feasible attack with current readily available techniques. + + * - constrained device + - device which has physical limitations in either the ability to process data, the + ability to communicate data, the ability to store data or the ability to interact + with the user, due to restrictions that arise from its intended use. + + * - consumer + - natural person who is acting for purposes that are outside her/his trade, + business, craft or profession. + + * - consumer IoT device + - network-connected (and network-connectable) device that has relationships to + associated services and are used by the consumer typically in the home or as + electronic wearables. + + * - critical security parameter + - security-related secret information whose disclosure or modification can compromise + the security of a security module. + + * - debug interface + - physical interface used by the manufacturer to communicate with the device during + development or to perform triage of issues with the device and that is not used as part + of the consumer-facing functionality + + * - defined support period + - minimum length of time, expressed as a period or by an end-date, for which a + manufacturer will provide security updates. + + * - device manufacturer + - entity that creates an assembled final consumer IoT product, which is likely to contain + the products and components of many other suppliers. + + * - factory default + - state of the device after factory reset or after final production/assembly. + + * - initialization + - process that activates the network connectivity of the device for operation and + optionally sets authentication features for a user or for network access. + + * - initialized state + - state of the device after initialization. + + * - IoT product + - consumer IoT device and its associated services. + + * - isolable + - able to be removed from the network it is connected to, where any functionality loss + caused is related only to that connectivity and not to its main function; alternatively, + able to be placed in a self-contained environment with other devices if and only if the + integrity of devices within that environment can be ensured + + * - logical interface + - software implementation that utilizes a network interface to communicate over the network + via channels or ports. + + * - manufacturer + - relevant economic operator in the supply chain (including the device manufacturer). + + * - network interface + - physical interface that can be used to access the functionality of consumer IoT via a network. + + * - owner + - user who owns or who purchased the device. + + * - personal data + - Any information relating to an identified or identifiable natural person. + + * - physical interface + - physical port or air interface (such as radio, audio or optical) used to communicate with the + device at the physical layer. + + * - public security parameter + - security related public information whose modification can compromise the security of a + security module. + + * - remotely accessible + - intended to be accessible from outside the local network. + + * - security module + - set of hardware, software, and/or firmware that implements security functions. + + * - security update + - software update that addresses security vulnerabilities either discovered by or reported + to the manufacturer. + + * - sensitive security parameters + - critical security parameters and public security parameters. + + * - software service + - software component of a device that is used to support functionality. + + * - telemetry + - data from a device that can provide information to help the manufacturer identify issues + or information related to device usage. + + * - unique per device + - unique for each individual device of a given product class or type. + + * - user + - natural person or organization. + +Provisions Assessment +********************* + + The following table is a self-assessment using Table B.1 from ETSI EN + 303 645, specifically focusing on the Zephyr RTOS as a component + within IoT products. + + According with ETSI 303 645, table B.1 provides a mechanism to give information + about the implementation of the provisions presented in the standard. Zephyr has + adopted the following notations used in the standard: + +.. list-table:: ETSI 303645 Table B.1 notations + :widths: 17 43 + + * - M + - the provision is a mandatory requirement + + * - R + - the provision is a recommendation + + * - M C + - the provision is a mandatory requirement and conditional + + * - R C + - the provision is a recommendation and conditional + + * - Y + - The provision is supported by Zephyr + + * - N + - The provision is not supported by Zephyr + + * - N/A + - The provision is not applicable to Zephyr or it is product makers responsibility + +.. raw:: latex + + \begin{landscape} + +.. list-table:: ETSI 303645 provisions assessment using table B.1 + :header-rows: 1 + :widths: 25 80 15 15 60 + + * - Provision + - Description + - Status + - Support + - Detail + + .. _ETSI_Provision_5_1_1: + * - Provision 5.1-1 + - Where passwords are used and in any state other than the + factory default, all consumer IoT device passwords shall be + unique per device or defined by the user. + - M C + - N/A + - + + .. _ETSI_Provision_5_1_2: + * - Provision 5.1-2 + - Where pre-installed unique per device passwords are used, + these shall be generated with a mechanism that reduces the + risk of automated attacks against a class or type of device. + - M C + - N/A + - + + .. _ETSI_Provision_5_1_3: + * - Provision 5.1-3 + - Authentication mechanisms used to authenticate users against a + device shall use best practice cryptography, appropriate to + the properties of the technology, risk and usage. + - M + - N/A + - + + .. _ETSI_Provision_5_1_4: + * - Provision 5.1-4 + - Where a user can authenticate against a device, the device + shall provide to the user or an administrator a simple + mechanism to change the authentication value used. + - M C + - N/A + - + + .. _ETSI_Provision_5_1_5: + * - Provision 5.1-5 + - When the device is not a constrained device, it shall have a + mechanism available which makes brute-force attacks on + authentication mechanisms via network interfaces + impracticable. + - M C + - N + - **TODO** + + .. _ETSI_Provision_5_2_1: + * - Provision 5.2-1 + - The manufacture shall make a vulnerability disclosure policy publicly + available. + - M + - Y + - :ref:`Vulnerability Management ` + + .. _ETSI_Provision_5_2_2: + * - Provision 5.2-2 + - Disclosed vulnerabilities should be acted on in a timely manner. + - R + - Y + - :ref:`Vulnerability Timeline ` + + .. _ETSI_Provision_5_2_3: + * - Provision 5.2-3 + - Manufacturers should continually monitor for, identify and rectify security + vulnerabilities within products and services they sell, produce, have produced + and services they operate during the defined support period. + - R + - Y + - `Modules `_ are covered + + .. _ETSI_Provision_5_3_1: + * - Provision 5.3-1 + - All software components in consumer IoT devices should be securely updatable. + - R + - Y + - :ref:`Device firwmware upgrade ` + + .. _ETSI_Provision_5_3_2: + * - Provision 5.3-2 + - When the device is not a constrained device, it shall have an update mechanism + for the secure installation of updates. + - M C + - Y + - :ref:`Device firwmware upgrade ` + + .. _ETSI_Provision_5_3_3: + * - Provision 5.3-3 + - An update shall be simple for the user to apply. + - M C + - N/A + - + + .. _ETSI_Provision_5_3_4: + * - Provision 5.3-4 + - Automatic mechanisms should be used for software updates. + - R C + - N/A + - + + .. _ETSI_Provision_5_3_5: + * - Provision 5.3-5 + - The device should check after initialization, and then periodically, whether + security updates are available. + - R C + - N/A + - + + .. _ETSI_Provision_5_3_6: + * - Provision 5.3-6 + - If the device supports automatic updates and/or update notifications, these + should be enabled in the initialized state and configurable so that the user + can enable, disable, or postpone installation of security updates and/or + update notifications. + - R C + - N/A + - + + .. _ETSI_Provision_5_3_7: + * - Provision 5.3-7 + - The device shall use best practice cryptography to facilitate secure update mechanisms. + - M C + - Y + - :ref:`West Sign ` + + .. _ETSI_Provision_5_3_8: + * - Provision 5.3-8 + - Security updates shall be timely. + - M C + - N/A + - + + .. _ETSI_Provision_5_3_9: + * - Provision 5.3-9 + - The device should verify the authenticity and integrity of software updates. + - R C + - Y + - Functionality provided by `MCUboot `. Also see :ref:`Device Firwmware Upgrade ` + + .. _ETSI_Provision_5_3_10: + * - Provision 5.3-10 + - Where updates are delivered over a network interface, the device shall verify + the authenticity and integrity of each update via a trust relationship. + - M + - N/A + - + + .. _ETSI_Provision_5_3_11: + * - Provision 5.3-11 + - The manufacturer should inform the user in a recognizable and apparent manner + that a security update is required together with information on the risks + mitigated by that update. + - R C + - N/A + - + + .. _ETSI_Provision_5_3_12: + * - Provision 5.3-12 + - The device should notify the user when the application of a software update + will disrupt the basic functioning of the device. + - R C + - N/A + - Zephyr provides this information for its updates. Anyone using Zephyr in their products must check if they are affected + + .. _ETSI_Provision_5_3_13: + * - Provision 5.3-13 + - The manufacturer shall publish, in an accessible way that is clear and + transparent to the user, the defined support period. + - M + - Y + - :ref:`Release Life Cycle and Maintenance ` + + .. _ETSI_Provision_5_3_14: + * - Provision 5.3-14 + - For constrained devices that cannot have their software updated, the rationale + for the absence of software updates, the period and method of hardware replacement + support and a defined support period should be published by the manufacturer in an + accessible way that is clear and transparent to the user. + - R C + - N/A + - + + .. _ETSI_Provision_5_3_15: + * - Provision 5.3-15 + - For constrained devices that cannot have their software updated, the product + should be isolable and the hardware replaceable. + - R C + - N/A + - + + .. _ETSI_Provision_5_3_16: + * - Provision 5.3-16 + - The model designation of the consumer IoT device shall be clearly recognizable, + either by labelling on the device or via a physical interface. + - M + - N/A + - + + .. _ETSI_Provision_5_4_1: + * - Provision 5.4-1 + - Sensitive security parameters in persistent storage shall be stored securely by the device. + - M + - N + - There is not secure storage within Zephyr + + .. _ETSI_Provision_5_4_2: + * - Provision 5.4-2 + - Where a hard-coded unique per device identity is used in a device for security purposes, + it shall be implemented in such a way that it resists tampering by means such as physical, + electrical or software. + - M C + - N/A + - + + .. _ETSI_Provision_5_4_3: + * - Provision 5.4-3 + - Hard-coded critical security parameters in device software source code shall not be used. + - M + - Y + - :ref:`Hardening Tool ` + + .. _ETSI_Provision_5_4_4: + * - Provision 5.4-4 + - Any critical security parameters used for integrity and authenticity checks of software + updates and for protection of communication with associated services in device software + shall be unique per device and shall be produced with a mechanism that reduces the risk + of automated attacks against classes of devices. + - M + - N/A + - + + .. _ETSI_Provision_5_5_1: + * - Provision 5.5-1 + - The consumer IoT device shall use best practice cryptography to communicate securely. + - M + - Y + - + + .. _ETSI_Provision_5_5_2: + * - Provision 5.5-2 + - The consumer IoT device should use reviewed or evaluated implementations to deliver + network and security functionalities, particularly in the field of cryptography. + - R + - Y + - + + .. _ETSI_Provision_5_5_3: + * - Provision 5.5-3 + - Cryptographic algorithms and primitives should be updatable. + - R + - N + - The whole image must be updated + + .. _ETSI_Provision_5_5_4: + * - Provision 5.5-4 + - Access to device functionality via a network interface in the initialized state should + only be possible after authentication on that interface. + - R + - N/A + - + + .. _ETSI_Provision_5_5_5: + * - Provision 5.5-5 + - Device functionality that allows security-relevant changes in configuration via a + network interface shall only be accessible after authentication. The exception is for + network service protocols that are relied upon by the device and where the manufacturer + cannot guarantee what configuration will be required for the device to operate. + - M + - N/A + - + + .. _ETSI_Provision_5_5_6: + * - Provision 5.5-6 + - Critical security parameters should be encrypted in transit, with such encryption + appropriate to the properties of the technology, risk and usage. + - R + - Y + - + + .. _ETSI_Provision_5_5_7: + * - Provision 5.5-7 + - The consumer IoT device shall protect the confidentiality of critical security + parameters that are communicated via remotely accessible network interfaces. + - M + - Y + - + + .. _ETSI_Provision_5_5_8: + * - Provision 5.5-8 + - The manufacturer shall follow secure management processes for critical security + parameters that relate to the device. + - M + - N/A + - + + .. _ETSI_Provision_5_6_1: + * - Provision 5.6-1 + - All unused network and logical interfaces shall be disabled. + - M + - Y + - :ref:`Kconfig ` + + .. _ETSI_Provision_5_6_2: + * - Provision 5.6-2 + - In the initialized state, the network interfaces of the device shall minimize the + unauthenticated disclosure of security-relevant information. + - M + - Y + - + + .. _ETSI_Provision_5_6_3: + * - Provision 5.6-3 + - Device hardware should not unnecessarily expose physical interfaces to attack. + - R + - Y + - :ref:`Kconfig ` and :ref:`Hardening Tool ` + + .. _ETSI_Provision_5_6_4: + * - Provision 5.6-4 + - Where a debug interface is physically accessible, it shall be disabled in software. + - M C + - Y + - :ref:`Hardening Tool ` + + .. _ETSI_Provision_5_6_5: + * - Provision 5.6-5 + - The manufacturer should only enable software services that are used or required for + the intended use or operation of the device. + - R + - Y + - :ref:`Kconfig ` and :ref:`Hardening Tool ` + + .. _ETSI_Provision_5_6_6: + * - Provision 5.6-6 + - Code should be minimized to the functionality necessary for the service/device to operate. + - R + - Y + - :ref:`Kconfig ` + + .. _ETSI_Provision_5_6_7: + * - Provision 5.6-7 + - Software should run with least necessary privileges, taking account of both security + and functionality. + - R + - Y + - :ref:`Security Overview ` + + .. _ETSI_Provision_5_6_8: + * - Provision 5.6-8 + - The device should include a hardware-level access control mechanism for memory. + - R + - Y + - :ref:`Memory protection ` + + .. _ETSI_Provision_5_6_9: + * - Provision 5.6-9 + - The manufacturer should follow secure development processes for software deployed on + the device. + - R + - Y + - :ref:`Security Overview ` and :ref:`Coding guidelines ` + + .. _ETSI_Provision_5_7_1: + * - Provision 5.7-1 + - The consumer IoT device should verify its software using secure boot mechanisms. + - R + - Y + - Functionality provided by `MCUboot `. Also see :ref:`Security Overview ` + + .. _ETSI_Provision_5_7_2: + * - Provision 5.7-2 + - If an unauthorized change is detected to the software, the device should alert the + user and/or administrator to the issue and should not connect to wider networks than + those necessary to perform the alerting function. + - R + - N + - Zephyr does not provide runtime detection / notification. + + .. _ETSI_Provision_5_8_1: + * - Provision 5.8-1 + - The confidentiality of personal data transiting between a device and a service, + especially associated services, should be protected, with best practice cryptography. + - R + - Y + - + + .. _ETSI_Provision_5_8_2: + * - Provision 5.8-2 + - The confidentiality of sensitive personal data communicated between the device and + associated services shall be protected, with cryptography appropriate to the + properties of the technology and usage. + - M + - Y + - + + .. _ETSI_Provision_5_8_3: + * - Provision 5.8-3 + - All external sensing capabilities of the device shall be documented in an accessible + way that is clear and transparent for the user. + - M + - Y + - :ref:`Sensing Subsystem ` + + .. _ETSI_Provision_5_9_1: + * - Provision 5.9-1 + - Resilience should be built in to consumer IoT devices and services, taking into + account the possibility of outages of data networks and power. + - R + - Y + - + + .. _ETSI_Provision_5_9_2: + * - Provision 5.9-2 + - Consumer IoT devices should remain operating and locally functional in the case of a + loss of network access and should recover cleanly in the case of restoration of a + loss of power. + - R + - Y + - + + .. _ETSI_Provision_5_9_3: + * - Provision 5.9-3 + - The consumer IoT device should connect to networks in an expected, operational and + stable state and in an orderly fashion, taking the capability of the infrastructure + into consideration. + - R + - Y + - + + .. _ETSI_Provision_5_10_1: + * - Provision 5.10-1 + - If telemetry data is collected from consumer IoT devices and services, such as usage + and measurement data, it should be examined for security anomalies. + - R C + - N/A + - + + .. _ETSI_Provision_5_11_1: + * - Provision 5.11-1 + - The user shall be provided with functionality such that user data can be erased from + the device in a simple manner. + - M + - N/A + - + + .. _ETSI_Provision_5_11_2: + * - Provision 5.11-2 + - The consumer should be provided with functionality on the device such that personal + data can be removed from associated services in a simple manner. + - R + - N/A + - + + .. _ETSI_Provision_5_11_3: + * - Provision 5.11-3 + - Users should be given clear instructions on how to delete their personal data. + - R + - N/A + - + + .. _ETSI_Provision_5_11_4: + * - Provision 5.11-4 + - Users should be provided with clear confirmation that personal data has been deleted + from services, devices and applications. + - R + - N/A + - + + .. _ETSI_Provision_5_12_1: + * - Provision 5.12-1 + - Installation and maintenance of consumer IoT should involve minimal decisions by the + user and should follow security best practice on usability. + - R + - N/A + - + + .. _ETSI_Provision_5_12_2: + * - Provision 5.12-2 + - The manufacturer should provide users with guidance on how to securely set up their device. + - R + - N/A + - + + .. _ETSI_Provision_5_12_3: + * - Provision 5.12-3 + - The manufacturer should provide users with guidance on how to check whether their + device is securely set up. + - R + - N/A + - + + .. _ETSI_Provision_5_13_1: + * - Provision 5.13-1 + - The consumer IoT device software shall validate data input via user interfaces or + transferred via Application Programming Interfaces (APIs) or between networks in + services and devices. + - M + - Y + - :ref:`Syscall verification ` and :ref:`Coding guidelines ` + + .. _ETSI_Provision_6_1_1: + * - Provision 6.1-1 + - The manufacturer shall provide consumers with clear and transparent information about + what personal data is processed, how it is being used, by whom, and for what purposes, + for each device and service. This also applies to third parties that can be involved, + including advertisers. + - M + - N/A + - + + .. _ETSI_Provision_6_1_2: + * - Provision 6.1-2 + - Where personal data is processed on the basis of consumers' consent, this consent + shall be obtained in a valid way. + - M C + - N/A + - + + .. _ETSI_Provision_6_1_3: + * - Provision 6.1-3 + - Consumers who gave consent for the processing of their personal data shall have + the capability to withdraw it at any time. + - M + - N/A + - + + .. _ETSI_Provision_6_1_4: + * - Provision 6.1-4 + - If telemetry data is collected from consumer IoT devices and services, the + processing of personal data should be kept to the minimum necessary for the + intended functionality. + - R C + - N/A + - + + .. _ETSI_Provision_6_1_5: + * - Provision 6.1-5 + - If telemetry data is collected from consumer IoT devices and services, consumers + shall be provided with information on what telemetry data is collected, how it is + being used, by whom, and for what purposes. + - M C + - N/A + - + +.. raw:: latex + + \end{landscape} diff --git a/doc/security/standards/index.rst b/doc/security/standards/index.rst new file mode 100644 index 0000000000000..39b9a0c8db03a --- /dev/null +++ b/doc/security/standards/index.rst @@ -0,0 +1,22 @@ +.. _security_standards: + +Security standards and Zephyr +############################# + +For a long period organizations were, more or less, left responsible to deal +with cyber security on their own. This included how to assess the scale and impact +of the problem and who to properly respond it. + +Now, governments started looking how to regulate it and several regulations +and enforcements are rapidly emerging, and consequently, security standards. These +standards provide guidelines and outline requirements that products have to follow +to achieve compliance. + +This section aims to identify and assess which Zephyr project components are impacted +by security standards requirements and provide the right information to enable +organizations developing certifiable products using Zephyr project. + +.. toctree:: + :maxdepth: 1 + + etsi-303645.rst diff --git a/doc/security/vulnerabilities.rst b/doc/security/vulnerabilities.rst index 468098fa0cc06..f087886de3494 100644 --- a/doc/security/vulnerabilities.rst +++ b/doc/security/vulnerabilities.rst @@ -1687,6 +1687,9 @@ This has been fixed in main for v3.6.0 - `PR 66887 fix for 2.7 `_ +CVE-2024 +======== + CVE-2024-1638 ------------- @@ -1713,3 +1716,23 @@ This has been fixed in main for v3.7.0 - `PR 69396 fix for main `_ + +CVE-2024-3332 +------------- + +Under embargo until 2024-07-01 + +CVE-2024-4785 +------------- + +Under embargo until 2024-08-07 + +CVE-2024-5754 +------------- + +Under embargo until 2024-09-04 + +CVE-2024-5931 +------------- + +Under embargo until 2024-09-10 diff --git a/doc/services/crypto/index.rst b/doc/services/crypto/index.rst index 988366c2e62f9..2ac0f534208c1 100644 --- a/doc/services/crypto/index.rst +++ b/doc/services/crypto/index.rst @@ -13,6 +13,6 @@ The following crypto libraries have been included: .. toctree:: :maxdepth: 1 - tinycrypt.rst + psa_crypto.rst random/index.rst api/index.rst diff --git a/doc/services/crypto/psa_crypto.rst b/doc/services/crypto/psa_crypto.rst new file mode 100644 index 0000000000000..fe5360e996718 --- /dev/null +++ b/doc/services/crypto/psa_crypto.rst @@ -0,0 +1,181 @@ +.. _psa_crypto: + +PSA Crypto +########## + +Overview +******** + +The PSA (Platform Security Architecture) Crypto API offers a portable +programming interface for cryptographic operations and key storage +across a wide range of hardware. It is designed to be user-friendly +while still providing access to the low-level primitives essential for +modern cryptography. + +It is created and maintained by Arm. Arm developed the PSA as a +comprehensive security framework to address the increasing security +needs of connected devices. + +In Zephyr, the PSA Crypto API is implemented using Mbed TLS, an +open-source cryptographic library that provides the underlying +cryptographic functions. + +Design Goals +************ + +The interface is suitable for a vast range of devices: from +special-purpose cryptographic processors that process data with a +built-in key, to constrained devices running custom application code, +such as microcontrollers, and multi-application devices, such as +servers. It follows the principle of cryptographic agility. + +Algorithm Flexibility + The PSA Crypto API supports a wide range of cryptographic algorithms, + allowing developers to switch between different cryptographic + methods as needed. This flexibility is crucial for maintaining + security as new algorithms emerge and existing ones become obsolete. + +Key Management + The PSA Crypto API includes robust key management features that + support the creation, storage, and use of cryptographic keys in a + secure and flexible manner. It uses opaque key identifiers, which + allows for easy key replacement and updates without exposing key + material. + +Implementation Independence + The PSA Crypto API abstracts the underlying cryptographic library, + meaning that the specific implementation can be changed without + affecting the application code. This abstraction supports + cryptographic agility by enabling the use of different cryptographic + libraries or hardware accelerators as needed. + +Future-Proofing + By adhering to cryptographic agility, PSA Crypto ensures that + applications can quickly adapt to new cryptographic standards and + practices, enhancing long-term security and compliance. + +Examples of Applications +************************ + +Network Security (TLS) + The API provides all of the cryptographic primitives needed to establish TLS connections. + +Secure Storage + The API provides all primitives related to storage encryption, block + or file-based, with master encryption keys stored inside a key store. + +Network Credentials + The API provides network credential management inside a key store, + for example, for X.509-based authentication or pre-shared keys on + enterprise networks. + +Device Pairing + The API provides support for key agreement protocols that are often + used for secure pairing of devices over wireless channels. For + example, the pairing of an NFC token or a Bluetooth device might use + key agreement protocols upon first use. + +Secure Boot + The API provides primitives for use during firmware integrity and + authenticity validation, during a secure or trusted boot process. + +Attestation + The API provides primitives used in attestation + activities. Attestation is the ability for a device to sign an array + of bytes with a device private key and return the result to the + caller. There are several use cases; ranging from attestation of the + device state, to the ability to generate a key pair and prove that it + has been generated inside a secure key store. The API provides access + to the algorithms commonly used for attestation. + +Factory Provisioning + Most IoT devices receive a unique identity during the factory + provisioning process, or once they have been deployed to the + field. This API provides the APIs necessary for populating a device + with keys that represent that identity. + +Usage considerations +******************** + +Always check for errors + Most functions in the PSA Crypto API can return errors. All functions + that can fail have the return type ``psa_status_t``. A few functions + cannot fail, and thus, return void or some other type. + + If an error occurs, unless otherwise specified, the content of the + output parameters is undefined and must not be used. + + Some common causes of errors include: + + * In implementations where the keys are stored and processed in a + separate environment from the application, all functions that need + to access the cryptography processing environment might fail due + to an error in the communication between the two environments. + + * If an algorithm is implemented with a hardware accelerator, which + is logically separate from the application processor, the + accelerator might fail, even when the application processor keeps + running normally. + + * Most functions might fail due to a lack of resources. However, + some implementations guarantee that certain functions always have + sufficient memory. + + * All functions that access persistent keys might fail due to a + storage failure. + + * All functions that require randomness might fail due to a lack of + entropy. Implementations are encouraged to seed the random + generator with sufficient entropy during the execution of + ``psa_crypto_init()``. However, some security standards require + periodic reseeding from a hardware random generator, which can + fail. + +Shared memory and concurrency + Some environments allow applications to be multithreaded, while + others do not. In some environments, applications can share memory + with a different security context. In environments with + multithreaded applications or shared memory, applications must be + written carefully to avoid data corruption or leakage. This + specification requires the application to obey certain constraints. + + In general, the PSA Crypto API allows either one writer or any number of + simultaneous readers, on any given object. In other words, if two or + more calls access the same object concurrently, then the behavior is + only well-defined if all the calls are only reading from the object + and do not modify it. Read accesses include reading memory by input + parameters and reading keystore content by using a key. For more + details, refer to `Concurrent calls + `_ + + If an application shares memory with another security context, it + can pass shared memory blocks as input buffers or output buffers, + but not as non-buffer parameters. For more details, refer to + `Stability of parameters `_. + +Cleaning up after use + To minimize impact if the system is compromised, it is recommended + that applications wipe all sensitive data from memory when it is no + longer used. That way, only data that is currently in use can be + leaked, and past data is not compromised. + + Wiping sensitive data includes: + + * Clearing temporary buffers in the stack or on the heap. + + * Aborting operations if they will not be finished. + + * Destroying keys that are no longer used. + +References +********** + +* `PSA Crypto`_ + +.. _PSA Crypto: + https://arm-software.github.io/psa-api/crypto/ + +* `Mbed TLS`_ + +.. _Mbed TLS: + https://www.trustedfirmware.org/projects/mbed-tls/ diff --git a/doc/services/crypto/tinycrypt.rst b/doc/services/crypto/tinycrypt.rst deleted file mode 100644 index 1757ac350e7f5..0000000000000 --- a/doc/services/crypto/tinycrypt.rst +++ /dev/null @@ -1,325 +0,0 @@ -.. _tinycrypt: - -TinyCrypt Cryptographic Library -############################### - -Overview -******** -The TinyCrypt Library provides an implementation for targeting constrained devices -with a minimal set of standard cryptography primitives, as listed below. To better -serve applications targeting constrained devices, TinyCrypt implementations differ -from the standard specifications (see the Important Remarks section for some -important differences). Certain cryptographic primitives depend on other -primitives, as mentioned in the list below. - -Aside from the Important Remarks section below, valuable information on the usage, -security and technicalities of each cryptographic primitive are found in the -corresponding header file. - -* SHA-256: - - * Type of primitive: Hash function. - * Standard Specification: NIST FIPS PUB 180-4. - * Requires: -- - -* HMAC-SHA256: - - * Type of primitive: Message authentication code. - * Standard Specification: RFC 2104. - * Requires: SHA-256 - -* HMAC-PRNG: - - * Type of primitive: Pseudo-random number generator. - * Standard Specification: NIST SP 800-90A. - * Requires: SHA-256 and HMAC-SHA256. - -* AES-128: - - * Type of primitive: Block cipher. - * Standard Specification: NIST FIPS PUB 197. - * Requires: -- - -* AES-CBC mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CTR mode: - - * Type of primitive: Encryption mode of operation. - * Standard Specification: NIST SP 800-38A. - * Requires: AES-128. - -* AES-CMAC mode: - - * Type of primitive: Message authentication code. - * Standard Specification: NIST SP 800-38B. - * Requires: AES-128. - -* AES-CCM mode: - - * Type of primitive: Authenticated encryption. - * Standard Specification: NIST SP 800-38C. - * Requires: AES-128. - -* ECC-DH: - - * Type of primitive: Key exchange. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -* ECC-DSA: - - * Type of primitive: Digital signature. - * Standard Specification: RFC 6090. - * Requires: ECC auxiliary functions (ecc.h/c). - -Design Goals -************ - -* Minimize the code size of each cryptographic primitive. This means minimize - the size of a board-independent implementation, as presented in TinyCrypt. - Note that various applications may require further features, optimizations with - respect to other metrics and countermeasures for particular threats. These - peculiarities would increase the code size and thus are not considered here. - -* Minimize the dependencies among the cryptographic primitives. This means - that it is unnecessary to build and allocate object code for more primitives - than the ones strictly required by the intended application. In other words, - one can select and compile only the primitives required by the application. - - -Important Remarks -***************** - -The cryptographic implementations in TinyCrypt library have some limitations. -Some of these limitations are inherent to the cryptographic primitives -themselves, while others are specific to TinyCrypt. Some of these limitations -are discussed in-depth below. - -General Remarks -*************** - -* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the - variety of side-channel attacks, many of them making certain boards - vulnerable. In this sense, instead of penalizing all library users with - side-channel countermeasures such as increasing the overall code size, - TinyCrypt only implements certain generic timing-attack countermeasures. - -Specific Remarks -**************** - -* SHA-256: - - * The number of bits_hashed in the state is not checked for overflow. Note - however that this will only be a problem if you intend to hash more than - 2^64 bits, which is an extremely large window. - -* HMAC: - - * The HMAC verification process is assumed to be performed by the application. - This compares the computed tag with some given tag. - Note that conventional memory-comparison methods (such as memcmp function) - might be vulnerable to timing attacks; thus be sure to use a constant-time - memory comparison function (such as compare_constant_time - function provided in lib/utils.c). - -* HMAC-PRNG: - - * Before using HMAC-PRNG, you *must* find an entropy source to produce a seed. - PRNGs only stretch the seed into a seemingly random output of arbitrary - length. The security of the output is exactly equal to the - unpredictability of the seed. - - * NIST SP 800-90A requires three items as seed material in the initialization - step: entropy seed, personalization and a nonce (which is not implemented). - TinyCrypt requires the personalization byte array and automatically creates - the entropy seed using a mandatory call to the re-seed function. - -* AES-128: - - * The current implementation does not support other key-lengths (such as 256 - bits). Note that if you need AES-256, it doesn't sound as though your - application is running in a constrained environment. AES-256 requires keys - twice the size as for AES-128, and the key schedule is 40% larger. - -* CTR mode: - - * The AES-CTR mode limits the size of a data message they encrypt to 2^32 - blocks. If you need to encrypt larger data sets, your application would - need to replace the key after 2^32 block encryptions. - -* CBC mode: - - * TinyCrypt CBC decryption assumes that the iv and the ciphertext are - contiguous (as produced by TinyCrypt CBC encryption). This allows for a - very efficient decryption algorithm that would not otherwise be possible. - -* CMAC mode: - - * AES128-CMAC mode of operation offers 64 bits of security against collision - attacks. Note however that an external attacker cannot generate the tags - him/herself without knowing the MAC key. In this sense, to attack the - collision property of AES128-CMAC, an external attacker would need the - cooperation of the legal user to produce an exponentially high number of - tags (e.g. 2^64) to finally be able to look for collisions and benefit - from them. As an extra precaution, the current implementation allows to at - most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup - (allowing a new key to be set), as suggested in Appendix B of SP 800-38B. - -* CCM mode: - - * There are a few tradeoffs for the selection of the parameters of CCM mode. - In special, there is a tradeoff between the maximum number of invocations - of CCM under a given key and the maximum payload length for those - invocations. Both things are related to the parameter 'q' of CCM mode. The - maximum number of invocations of CCM under a given key is determined by - the nonce size, which is: 15-q bytes. The maximum payload length for those - invocations is defined as 2^(8q) bytes. - - To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2, - which is a quite reasonable choice for constrained applications. The - implications of this choice are: - - The nonce size is: 13 bytes. - - The maximum payload length is: 2^16 bytes = 65 KB. - - The mac size parameter is an important parameter to estimate the security - against collision attacks (that aim at finding different messages that - produce the same authentication tag). TinyCrypt CCM implementation - accepts any even integer between 4 and 16, as suggested in SP 800-38C. - - * TinyCrypt CCM implementation accepts associated data of any length between - 0 and (2^16 - 2^8) = 65280 bytes. - - * TinyCrypt CCM implementation accepts: - - * Both non-empty payload and associated data (it encrypts and - authenticates the payload and only authenticates the associated data); - - * Non-empty payload and empty associated data (it encrypts and - authenticates the payload); - - * Non-empty associated data and empty payload (it degenerates to an - authentication-only mode on the associated data). - - * RFC-3610, which also specifies CCM, presents a few relevant security - suggestions, such as: it is recommended for most applications to use a - mac size greater than 8. Besides, it is emphasized that the usage of the - same nonce for two different messages which are encrypted with the same - key obviously destroys the security properties of CCM mode. - -* ECC-DH and ECC-DSA: - - * TinyCrypt ECC implementation is based on nano-ecc (see - https://github.com/iSECPartners/nano-ecc) which in turn is based on - micro-ecc (see https://github.com/kmackay/micro-ecc). In the original - nano and micro-ecc documentation, there is an important remark about the - way integers are represented: - - "Integer representation: To reduce code size, all large integers are - represented using little-endian words - so the least significant word is - first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()' - functions to convert between the native integer representation and the - standardized octet representation." - -Examples of Applications -************************ -It is possible to do useful cryptography with only the given small set of -primitives. With this list of primitives it becomes feasible to support a range -of cryptography usages: - - * Measurement of code, data structures, and other digital artifacts (SHA256); - - * Generate commitments (SHA256); - - * Construct keys (HMAC-SHA256); - - * Extract entropy from strings containing some randomness (HMAC-SHA256); - - * Construct random mappings (HMAC-SHA256); - - * Construct nonces and challenges (HMAC-PRNG); - - * Authenticate using a shared secret (HMAC-SHA256); - - * Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG); - - * Authenticated encryption (AES-128 + AES-CCM); - - * Key-exchange (EC-DH); - - * Digital signature (EC-DSA); - -Test Vectors -************ - -The library provides a test program for each cryptographic primitive (see 'test' -folder). Besides illustrating how to use the primitives, these tests evaluate -the correctness of the implementations by checking the results against -well-known publicly validated test vectors. - -For the case of the HMAC-PRNG, due to the necessity of performing an extensive -battery test to produce meaningful conclusions, we suggest the user to evaluate -the unpredictability of the implementation by using the NIST Statistical Test -Suite (see References). - -For the case of the EC-DH and EC-DSA implementations, most of the test vectors -were obtained from the site of the NIST Cryptographic Algorithm Validation -Program (CAVP), see References. - -References -********** - -* `NIST FIPS PUB 180-4 (SHA-256)`_ - -.. _NIST FIPS PUB 180-4 (SHA-256): - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf - -* `NIST FIPS PUB 197 (AES-128)`_ - -.. _NIST FIPS PUB 197 (AES-128): - http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - -* `NIST SP800-90A (HMAC-PRNG)`_ - -.. _NIST SP800-90A (HMAC-PRNG): - http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf - -* `NIST SP 800-38A (AES-CBC and AES-CTR)`_ - -.. _NIST SP 800-38A (AES-CBC and AES-CTR): - http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - -* `NIST SP 800-38B (AES-CMAC)`_ - -.. _NIST SP 800-38B (AES-CMAC): - http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf - -* `NIST SP 800-38C (AES-CCM)`_ - -.. _NIST SP 800-38C (AES-CCM): - http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf - -* `NIST Statistical Test Suite`_ - -.. _NIST Statistical Test Suite: - http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html - -* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_ - -.. _NIST Cryptographic Algorithm Validation Program (CAVP) site: - http://csrc.nist.gov/groups/STM/cavp/ - -* `RFC 2104 (HMAC-SHA256)`_ - -.. _RFC 2104 (HMAC-SHA256): - https://www.ietf.org/rfc/rfc2104.txt - -* `RFC 6090 (ECC-DH and ECC-DSA)`_ - -.. _RFC 6090 (ECC-DH and ECC-DSA): - https://www.ietf.org/rfc/rfc6090.txt diff --git a/doc/services/debugging/index.rst b/doc/services/debugging/index.rst index c1a455f5b1cae..cbc566bdbf0fb 100644 --- a/doc/services/debugging/index.rst +++ b/doc/services/debugging/index.rst @@ -10,3 +10,5 @@ Debugging coredump.rst gdbstub.rst debugmon.rst + mipi_stp_decoder.rst + symtab.rst diff --git a/doc/services/debugging/mipi_stp_decoder.rst b/doc/services/debugging/mipi_stp_decoder.rst new file mode 100644 index 0000000000000..9edf1e4d94e00 --- /dev/null +++ b/doc/services/debugging/mipi_stp_decoder.rst @@ -0,0 +1,43 @@ +.. _mipi_stp_decoder: + +MIPI STP Decoder +################ + +The MIPI System Trace Protocol (MIPI STP) was developed as a generic base protocol that can +be shared by multiple application-specific trace protocols. It serves as a wrapper protocol +that merges disparate streams that typically contain different trace protocols from different +trace sources. Stream consists of opcode (shortest is 4 bit long) followed by optional data and +optional timestamp. There are opcodes for data (8, 16, 32, 64 bit data marked/not marked, with or +without timestamp), stream recognition (master and channel), synchronization (ASYNC opcode) and +others. + +One example where protocol is used is ARM Coresight STM (System Trace Macrocell) where data +written to Stimulus Port registers maps directly to STP stream. + +This module can be used to perform on-chip decoding of the data stream. STP v2 is used. + +Usage +***** + +Decoder is initialized with a callback. A callback is called on each decoded opcode. +Decoder has internal state since there are dependency between opcodes (e.g. timestamp can be +relative). Decoder can be in synchronization or not. Initial state is configurable. +If decoder is not synchronized to the stream then it decodes each nibble in search for ASYNC opcode. +Loss of synchronization can be indicated to the decoder by calling +:c:func:`mipi_stp_decoder_sync_loss`. :c:func:`mipi_stp_decoder_decode` is used to decode the data. + +Limitations +*********** + +There are following limitations: + +* Decoder supports only little endian architectures. +* When decoding nibbles, it is more efficient when core supports unaligned memory access. + Implementation supports optimized version with unaligned memory access and generic one. + Optimized version is used for ARM Cortex-M (expect for M0). +* Limited set of the most common opcodes is implemented. + +API documentation +***************** + +.. doxygengroup:: mipi_stp_decoder_apis diff --git a/doc/services/debugging/symtab.rst b/doc/services/debugging/symtab.rst new file mode 100644 index 0000000000000..a85bdbb10e248 --- /dev/null +++ b/doc/services/debugging/symtab.rst @@ -0,0 +1,31 @@ +.. _symtab: + +Symbol Table (Symtab) +##################### + +The Symtab module, when enabled, will generate full symbol table during the Zephyr linking +stage that keep tracks of the information about the functions' name and address, for advanced application +with a lot of functions, this is expected to consume a sizable amount of ROM. + +Currently, this is being used to look up the function names during a stack trace in supported architectures. + + +Usage +***** + +Application can gain access to the symbol table data structure by including the :file:`symtab.h` header +file and call :c:func:`symtab_get`. For now, we only provide :c:func:`symtab_find_symbol_name` +function to look-up the symbol name and offset of an address. More advanced functionalities and be +achieved by directly accessing the members of the data structure. + +Configuration +************* + +Configure this module using the following options. + +* :kconfig:option:`CONFIG_SYMTAB`: enable the generation of the symbol table. + +API documentation +***************** + +.. doxygengroup:: symtab_apis diff --git a/doc/services/device_mgmt/mcumgr.rst b/doc/services/device_mgmt/mcumgr.rst index 905307ab424ae..0f4f57e7954ee 100644 --- a/doc/services/device_mgmt/mcumgr.rst +++ b/doc/services/device_mgmt/mcumgr.rst @@ -113,203 +113,6 @@ project. Note that a tick for a particular group indicates basic support for that group in the code, it is possible that not all commands/features of a group are supported by the implementation. -.. _mcumgr_cli: - -Command-line Tool -***************** - -MCUmgr provides a command-line tool, :file:`mcumgr`, for managing remote devices. -The tool is written in the Go programming language. - -.. note:: - This tool is provided for evaluation use only and is not recommended for - use in a production environment. It has known issues and will not respect - the MCUmgr protocol properly e.g. when an error is received, instead of - aborting will, in some circumstances, sit in an endless loop of sending the - same command over and over again. A universal replacement for this tool is - currently in development and once released, support for the go tool will be - dropped entirely. It is recommended that usage of tools listed above in the - :ref:`mcumgr_tools_libraries` section are used instead of the go client. - -To install the tool: - -.. tabs:: - - .. group-tab:: go version < 1.18 - - .. code-block:: console - - go get github.com/apache/mynewt-mcumgr-cli/mcumgr - - .. group-tab:: go version >= 1.18 - - .. code-block:: console - - go install github.com/apache/mynewt-mcumgr-cli/mcumgr@latest - -Configuring the transport -************************* - -There are two command-line options that are responsible for setting and configuring -the transport layer to use when communicating with managed device: - -* ``--conntype`` is used to choose the transport used, and -* ``--connstring`` is used to pass a comma separated list of options in the - ``key=value`` format, where each valid ``key`` depends on the particular - ``conntype``. - -Valid transports for ``--conntype`` are ``serial``, ``ble`` and ``udp``. Each -transport expects a different set of key/value options: - -.. tabs:: - - .. group-tab:: serial - - ``--connstring`` accepts the following ``key`` values: - - .. list-table:: - :width: 100% - :widths: 10 60 - - * - ``dev`` - - the device name for the OS ``mcumgr`` is running on (eg, ``/dev/ttyUSB0``, ``/dev/tty.usbserial``, ``COM1``, etc). - * - ``baud`` - - the communication speed; must match the baudrate of the server. - * - ``mtu`` - - aka Maximum Transmission Unit, the maximum protocol packet size. - - .. group-tab:: ble - - ``--connstring`` accepts the following ``key`` values: - - .. list-table:: - :width: 100% - :widths: 10 60 - - * - ``ctlr_name`` - - an OS specific string for the controller name. - * - ``own_addr_type`` - - can be one of ``public``, ``random``, ``rpa_pub``, ``rpa_rnd``, where ``random`` is the default. - * - ``peer_name`` - - the name the peer BLE device advertises, this should match the configuration specified with :kconfig:option:`CONFIG_BT_DEVICE_NAME`. - * - ``peer_id`` - - the peer BLE device address or UUID. Only required when ``peer_name`` was not given. The format depends on the OS where ``mcumgr`` is run, it is a 6 bytes hexadecimal string separated by colons on Linux, or a 128-bit UUID on macOS. - * - ``conn_timeout`` - - a float number representing the connection timeout in seconds. - - .. group-tab:: udp - - ``--connstring`` takes the form ``[addr]:port`` where: - - .. list-table:: - :width: 100% - :widths: 10 60 - - * - ``addr`` - - can be a DNS name (if it can be resolved to the device IP), IPv4 addr (app must be - built with :kconfig:option:`CONFIG_MCUMGR_TRANSPORT_UDP_IPV4`), or IPv6 addr (app must be built with :kconfig:option:`CONFIG_MCUMGR_TRANSPORT_UDP_IPV6`) - * - ``port`` - - any valid UDP port. - -Saving the connection config -**************************** - -The transport configuration can be managed with the ``conn`` sub-command and -later used with ``--conn`` (or ``-c``) parameter to skip typing both ``--conntype`` -and ``--connstring``. For example a new config for a serial device that would -require typing ``mcumgr --conntype serial --connstring dev=/dev/ttyACM0,baud=115200,mtu=512`` -can be saved with:: - - mcumgr conn add acm0 type="serial" connstring="dev=/dev/ttyACM0,baud=115200,mtu=512" - -Accessing this port can now be done with:: - - mcumgr -c acm0 - -.. _general_options: - -General options -*************** - -Some options work for every ``mcumgr`` command and might be helpful to debug and fix -issues with the communication, among them the following deserve special mention: - -.. list-table:: - :width: 100% - :widths: 10 60 - - * - ``-l `` - - Configures the log level, which can be one of ``critical``, ``error``, - ``warn``, ``info`` or ``debug``, from less to most verbose. When there are - communication issues, ``-lDEBUG`` might be useful to dump the packets for - later inspection. - * - ``-t `` - - Changes the timeout waiting for a response from the default of 10s to a - given value. Some commands might take a long time of processing, eg, the - erase before an image upload, and might need incrementing the timeout to - a larger value. - * - ``-r `` - - Changes the number of retries on timeout from the default of 1 to a given - value. - -List of Commands -**************** - -Not all commands defined by ``mcumgr`` (and SMP protocol) are currently supported -on Zephyr. The ones that are supported are described in the following table: - -.. tip:: Running ``mcumgr`` with no parameters, or ``-h`` will display the list - of commands. - -.. list-table:: - :widths: 10 30 - :header-rows: 1 - - * - Command - - Description - * - ``echo`` - - Send data to a device and display the echoed back data. This command is - part of the ``OS`` group, which must be enabled by setting - :kconfig:option:`CONFIG_MCUMGR_GRP_OS`. The ``echo`` command itself can be - enabled by setting :kconfig:option:`CONFIG_MCUMGR_GRP_OS_ECHO`. - * - ``fs`` - - Access files on a device. More info in :ref:`fs_mgmt`. - * - ``image`` - - Manage images on a device. More info in :ref:`image_mgmt`. - * - ``reset`` - - Perform a soft reset of a device. This command is part of the ``OS`` - group, which must be enabled by setting :kconfig:option:`CONFIG_MCUMGR_GRP_OS`. - The ``reset`` command itself is always enabled and the time taken for a - reset to happen can be set with :kconfig:option:`CONFIG_MCUMGR_GRP_OS_RESET_MS` (in ms). - * - ``shell`` - - Execute a command in the remote shell. This option is disabled by default - and can be enabled with :kconfig:option:`CONFIG_MCUMGR_GRP_SHELL` = ``y``. - To know more about the shell in Zephyr check :ref:`shell_api`. - * - ``stat`` - - Read statistics from a device. More info in :ref:`stats_mgmt`. - * - ``taskstat`` - - Read task statistics from a device. This command is part of the ``OS`` - group, which must be enabled by setting :kconfig:option:`CONFIG_MCUMGR_GRP_OS`. - The ``taskstat`` command itself can be enabled by setting - :kconfig:option:`CONFIG_MCUMGR_GRP_OS_TASKSTAT`. :kconfig:option:`CONFIG_THREAD_MONITOR` also - needs to be enabled otherwise a ``-8`` (``MGMT_ERR_ENOTSUP``) will be - returned. - -.. tip:: - - ``taskstat`` has a few options that might require tweaking. The - :kconfig:option:`CONFIG_THREAD_NAME` must be set to display the task names, otherwise - the priority is displayed. Since the ``taskstat`` packets are large, they - might need increasing the :kconfig:option:`CONFIG_MCUMGR_TRANSPORT_NETBUF_SIZE` option. - -.. warning:: - - To display the correct stack size in the ``taskstat`` command, the - :kconfig:option:`CONFIG_THREAD_STACK_INFO` option must be set. - To display the correct stack usage in the ``taskstat`` command, both - :kconfig:option:`CONFIG_THREAD_STACK_INFO` and :kconfig:option:`CONFIG_INIT_STACKS` options - must be set. - .. _mcumgr_jlink_ob_virtual_msd: J-Link Virtual MSD Interaction Note @@ -325,343 +128,6 @@ management commands for updating firmware). This issue can be resolved by disabling MSD functionality on the J-Link device, follow the instructions on :ref:`nordic_segger_msd` to disable MSD support. -.. _image_mgmt: - -Image Management -**************** - -The image management provided by ``mcumgr`` is based on the image format defined -by MCUboot. For more details on the internals see `MCUboot design`_ and :ref:`west-sign`. - -To list available images in a device:: - - mcumgr image list - -This should result in an output similar to this:: - - $ mcumgr -c acm0 image list - Images: - image=0 slot=0 - version: 1.0.0 - bootable: true - flags: active confirmed - hash: 86dca73a3439112b310b5e033d811ec2df728d2264265f2046fced5a9ed00cc7 - Split status: N/A (0) - -Where ``image`` is the number of the image pair in a multi-image system, and slot -is the number of the slot where the image is stored, ``0`` for primary and ``1`` for -secondary. This image being ``active`` and ``confirmed`` means it will run again on -next reset. Also relevant is the ``hash``, which is used by other commands to -refer to this specific image when performing operations. - -An image can be manually erased using:: - - mcumgr image erase - -The behavior of ``erase`` is defined by the server (``MCUmgr`` in the device). -The current implementation is limited to erasing the image in the secondary -partition. - -To upload a new image:: - - mcumgr image upload [-n] [-e] [-u] [-w] - -* ``-n``: This option allows uploading a new image to a specific set of images - in a multi-image system, and is currently only supported by MCUboot when the - CONFIG\ _MCUBOOT_SERIAL option is enabled. - -* ``-e``: This option avoids performing a full erase of the partition before - starting a new upload. - -.. tip:: - - The ``-e`` option should always be passed in because the ``upload`` command - already checks if an erase is required, respecting the - :kconfig:option:`CONFIG_IMG_ERASE_PROGRESSIVELY` setting. - -.. tip:: - - If the ``upload`` command times out while waiting for a response from the - device, ``-t`` might be used to increase the wait time to something larger - than the default of 10s. See general_options_. - -.. warning:: - - ``mcumgr`` does not understand .hex files, when uploading a new image always - use the .bin file. - -* ``-u``: This option allows upgrading only to newer image version. - -* ``-w``: This option allows setting the maximum size for the window of outstanding chunks in transit. - It is set to 5 by default. - - .. tip:: - - If the option is set to a value lower than the default one, for example ``-w 1``, less chunks are transmitted on the window, - resulting in lower risk of errors. Conversely, setting a value higher than 5 increases risk of errors and may impact performance. - -After an image upload is finished, a new ``image list`` would now have an output -like this:: - - $ mcumgr -c acm0 image upload -e build/zephyr/zephyr.signed.bin - 35.69 KiB / 92.92 KiB [==========>---------------] 38.41% 2.97 KiB/s 00m19 - -Now listing the images again:: - - $ mcumgr -c acm0 image list - Images: - image=0 slot=0 - version: 1.0.0 - bootable: true - flags: active confirmed - hash: 86dca73a3439112b310b5e033d811ec2df728d2264265f2046fced5a9ed00cc7 - image=0 slot=1 - version: 1.1.0 - bootable: true - flags: - hash: e8cf0dcef3ec8addee07e8c4d5dc89e64ba3fae46a2c5267fc4efbea4ca0e9f4 - Split status: N/A (0) - -To test a new upgrade image the ``test`` command is used:: - - mcumgr image test - -This command should mark a ``test`` upgrade, which means that after the next -reboot the bootloader will execute the upgrade and jump into the new image. If no -other image operations are executed on the newly running image, it will ``revert`` -back to the image that was previously running on the device on the subsequent reset. -When a ``test`` is requested, ``flags`` will be updated with ``pending`` to inform -that a new image will be run after a reset:: - - $ mcumgr -c acm0 image test e8cf0dcef3ec8addee07e8c4d5dc89e64ba3fae46a2c5267fc4efbea4ca0e9f4 - Images: - image=0 slot=0 - version: 1.0.0 - bootable: true - flags: active confirmed - hash: 86dca73a3439112b310b5e033d811ec2df728d2264265f2046fced5a9ed00cc7 - image=0 slot=1 - version: 1.1.0 - bootable: true - flags: pending - hash: e8cf0dcef3ec8addee07e8c4d5dc89e64ba3fae46a2c5267fc4efbea4ca0e9f4 - Split status: N/A (0) - -After a reset the output with change to:: - - $ mcumgr -c acm0 image list - Images: - image=0 slot=0 - version: 1.1.0 - bootable: true - flags: active - hash: e8cf0dcef3ec8addee07e8c4d5dc89e64ba3fae46a2c5267fc4efbea4ca0e9f4 - image=0 slot=1 - version: 1.0.0 - bootable: true - flags: confirmed - hash: 86dca73a3439112b310b5e033d811ec2df728d2264265f2046fced5a9ed00cc7 - Split status: N/A (0) - -.. tip:: - - It's important to mention that an upgrade only ever happens if the image is - valid. The first thing MCUboot does when an upgrade is requested is to - validate the image, using the SHA-256 and/or the signature (depending on - the configuration). So before uploading an image, one way to be sure it is - valid is to run ``imgtool verify -k ``, - where ``-k image confirm "" - -The ``confirm`` command can also be run passing in a ``hash`` so that instead of -doing a ``test``/``revert`` procedure, the image in the secondary partition is -directly upgraded to, eg:: - - mcumgr image confirm - -.. tip:: - - The whole ``test``/``revert`` cycle does not need to be done using only the - ``mcumgr`` command-line tool. A better alternative is to perform a ``test`` - and allow the new running image to self-confirm after any checks by calling - :c:func:`boot_write_img_confirmed`. - -.. tip:: - - Building with :kconfig:option:`CONFIG_MCUMGR_GRP_IMG_VERBOSE_ERR` enables better error - messages when failures happen (but increases the application size). - -.. _stats_mgmt: - -Statistics Management -********************* - -Statistics are used for troubleshooting, maintenance, and usage monitoring; it -consists basically of user-defined counters which are tightly connected to -``mcumgr`` and can be used to track any information for easy retrieval. The -available sub-commands are:: - - mcumgr stat list - mcumgr stat - -Statistics are organized in sections (also called groups), and each section can -be individually queried. Defining new statistics sections is done by using macros -available under :file:`zephyr/stats/stats.h`. Each section consists of multiple -variables (or counters), all with the same size (16, 32 or 64 bits). - -To create a new section ``my_stats``:: - - STATS_SECT_START(my_stats) - STATS_SECT_ENTRY(my_stat_counter1) - STATS_SECT_ENTRY(my_stat_counter2) - STATS_SECT_ENTRY(my_stat_counter3) - STATS_SECT_END; - - STATS_SECT_DECL(my_stats) my_stats; - -Each entry can be declared with :c:macro:`STATS_SECT_ENTRY` (or the equivalent -:c:macro:`STATS_SECT_ENTRY32`), :c:macro:`STATS_SECT_ENTRY16` or -:c:macro:`STATS_SECT_ENTRY64`. -All statistics in a section must be declared with the same size. - -The statistics counters can either have names or not, depending on the setting -of the :kconfig:option:`CONFIG_STATS_NAMES` option. Using names requires an extra -declaration step:: - - STATS_NAME_START(my_stats) - STATS_NAME(my_stats, my_stat_counter1) - STATS_NAME(my_stats, my_stat_counter2) - STATS_NAME(my_stats, my_stat_counter3) - STATS_NAME_END(my_stats); - -.. tip:: - - Disabling :kconfig:option:`CONFIG_STATS_NAMES` will free resources. When this option - is disabled the ``STATS_NAME*`` macros output nothing, so adding them in the - code does not increase the binary size. - -.. tip:: - - :kconfig:option:`CONFIG_MCUMGR_GRP_STAT_MAX_NAME_LEN` sets the maximum length of a section - name that can can be accepted as parameter for showing the section data, and - might require tweaking for long section names. - -The final steps to use a statistics section is to initialize and register it:: - - rc = STATS_INIT_AND_REG(my_stats, STATS_SIZE_32, "my_stats"); - assert (rc == 0); - -In the running code a statistics counter can be incremented by 1 using -:c:macro:`STATS_INC`, by N using :c:macro:`STATS_INCN` or reset with -:c:macro:`STATS_CLEAR`. - -Let's suppose we want to increment those counters by ``1``, ``2`` and ``3`` -every second. To get a list of stats:: - - $ mcumgr --conn acm0 stat list - stat groups: - my_stats - -To get the current value of the counters in ``my_stats``:: - - $ mcumgr --conn acm0 stat my_stats - stat group: my_stats - 13 my_stat_counter1 - 26 my_stat_counter2 - 39 my_stat_counter3 - - $ mcumgr --conn acm0 stat my_stats - stat group: my_stats - 16 my_stat_counter1 - 32 my_stat_counter2 - 48 my_stat_counter3 - -When :kconfig:option:`CONFIG_STATS_NAMES` is disabled the output will look like this:: - - $ mcumgr --conn acm0 stat my_stats - stat group: my_stats - 8 s0 - 16 s1 - 24 s2 - -.. _fs_mgmt: - -Filesystem Management -********************* - -The filesystem module is disabled by default due to security concerns: -because of a lack of access control by default, every file in the FS will be -accessible, including secrets, etc. To enable it -:kconfig:option:`CONFIG_MCUMGR_GRP_FS` must be set (``y``). Once enabled the -following sub-commands can be used:: - - mcumgr fs download - mcumgr fs upload - -Using the ``fs`` command, requires :kconfig:option:`CONFIG_FILE_SYSTEM` to be enabled, -and that some particular filesystem is enabled and properly mounted by the running -application, eg for littlefs this would mean enabling -:kconfig:option:`CONFIG_FILE_SYSTEM_LITTLEFS`, defining a storage partition :ref:`flash_map_api` -and mounting the filesystem in the startup (:c:func:`fs_mount`). - -Uploading a new file to a littlefs storage, mounted under ``/lfs``, can be done with:: - - $ mcumgr -c acm0 fs upload foo.txt /lfs/foo.txt - 25 - Done - -Where ``25`` is the size of the file. - -For downloading a file, let's first use the ``fs`` command -(:kconfig:option:`CONFIG_FILE_SYSTEM_SHELL` must be enabled) in a remote shell to create -a new file:: - - uart:~$ fs write /lfs/bar.txt 41 42 43 44 31 32 33 34 0a - uart:~$ fs read /lfs/bar.txt - File size: 9 - 00000000 41 42 43 44 31 32 33 34 0A ABCD1234. - -Now it can be downloaded using:: - - $ mcumgr -c acm0 fs download /lfs/bar.txt bar.txt - 0 - 9 - Done - $ cat bar.txt - ABCD1234 - -Where ``0`` is the return code, and ``9`` is the size of the file. - -.. warning:: - - The commands might exhaust the system workqueue, if its size is not large - enough, so increasing :kconfig:option:`CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE` might be - required for correct behavior. - -The size of the stack allocated buffer used to store the blocks, while transferring -a file can be adjusted with :kconfig:option:`CONFIG_MCUMGR_GRP_FS_DL_CHUNK_SIZE`; this allows -saving RAM resources. - -.. tip:: - - :kconfig:option:`CONFIG_MCUMGR_GRP_FS_PATH_LEN` sets the maximum PATH accepted for a file - name. It might require tweaking for longer file names. - -.. note:: - To add security to the filesystem management group, callbacks for MCUmgr - hooks can be registered by a user application when the upload/download - functions are ran which allows the application to control if access to a - file is allowed or denied. See the :ref:`mcumgr_callbacks` section for - details. - Bootloader Integration ********************** diff --git a/doc/services/device_mgmt/mcumgr_callbacks.rst b/doc/services/device_mgmt/mcumgr_callbacks.rst index 7333f273f2b0b..0ed8b580c757c 100644 --- a/doc/services/device_mgmt/mcumgr_callbacks.rst +++ b/doc/services/device_mgmt/mcumgr_callbacks.rst @@ -192,7 +192,7 @@ the file should be allowed or not, note that this requires that :kconfig:option:`CONFIG_MCUMGR_GRP_FS_FILE_ACCESS_HOOK` be enabled to receive this callback. Two types of errors can be returned, the ``rc`` parameter can be set to an -:c:enumerator:`mcumgr_err_t` error code and :c:enumerator:`MGMT_CB_ERROR_RC` +:c:enum:`mcumgr_err_t` error code and :c:enumerator:`MGMT_CB_ERROR_RC` can be returned, or a group error code (introduced with version 2 of the MCUmgr protocol) can be set by setting the ``group`` value to the group and ``rc`` value to the group error code and returning :c:enumerator:`MGMT_CB_ERROR_ERR`. @@ -330,4 +330,3 @@ API Reference ************* .. doxygengroup:: mcumgr_callback_api - :inner: diff --git a/doc/services/device_mgmt/mcumgr_handlers.rst b/doc/services/device_mgmt/mcumgr_handlers.rst index e189ea887d473..18fc5e65366cb 100644 --- a/doc/services/device_mgmt/mcumgr_handlers.rst +++ b/doc/services/device_mgmt/mcumgr_handlers.rst @@ -52,8 +52,8 @@ responses (which have unique error codes per group as opposed to the legacy SMP responses that return a :c:enum:`mcumgr_err_t` - there should always be an OK error code with the value 0 and an unknown error code with the value 1. The above example then adds an error code of ``not wanted`` with value 2. In addition, the group ID is set to be -:c:enum:`MGMT_GROUP_ID_PERUSER`, which is the start group ID for user-defined groups, note that -group IDs need to be unique so other custom groups should use different values, a central index +:c:enumerator:`MGMT_GROUP_ID_PERUSER`, which is the start group ID for user-defined groups, note +that group IDs need to be unique so other custom groups should use different values, a central index header file (as upstream Zephyr has) can be used to distribute group IDs more easily. Initial header _mgmt_callbacks.h @@ -70,7 +70,7 @@ file would look similar to: This sets up a single event which application (or module) code can register for to receive a callback when the function handler is executed, which allows the flow of the handler to be changed (i.e. to return an error instead of continuing). The event group ID is set to -:c:enum:`MGMT_EVT_GRP_USER_CUSTOM_START`, which is the start event ID for user-defined groups, +:c:enumerator:`MGMT_EVT_GRP_USER_CUSTOM_START`, which is the start event ID for user-defined groups, note that event IDs need to be unique so other custom groups should use different values, a central index header file (as upstream Zephyr has) can be used to distribute event IDs more easily. diff --git a/doc/services/device_mgmt/smp_groups/smp_group_0.rst b/doc/services/device_mgmt/smp_groups/smp_group_0.rst index 7fb91463e336f..eb3b90b3a1d7f 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_0.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_0.rst @@ -563,7 +563,7 @@ System reset request header fields: +--------+--------------+----------------+ Normally the command sends an empty CBOR map as data, but if a previous reset -attempt has responded with "rc" equal to :c:enum:`MGMT_ERR_EBUSY` then the +attempt has responded with "rc" equal to :c:enumerator:`MGMT_ERR_EBUSY` then the following map may be sent to force a reset: .. code-block:: none diff --git a/doc/services/device_mgmt/smp_groups/smp_group_1.rst b/doc/services/device_mgmt/smp_groups/smp_group_1.rst index 2a1d1f2708632..744835fad25b1 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_1.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_1.rst @@ -204,7 +204,7 @@ where: | | using SMP version 1 or for SMP errors when using SMP version 2. | +------------------+-------------------------------------------------------------------------+ | "rsn" | optional string that clarifies reason for an error; specifically useful | - | | when ``rc`` is :c:enum:`MGMT_ERR_EUNKNOWN`. | + | | when ``rc`` is :c:enumerator:`MGMT_ERR_EUNKNOWN`. | +------------------+-------------------------------------------------------------------------+ .. note:: @@ -407,7 +407,7 @@ where: | | using SMP version 1 or for SMP errors when using SMP version 2. | +------------------+-------------------------------------------------------------------------+ | "rsn" | optional string that clarifies reason for an error; specifically useful | - | | when ``rc`` is :c:enum:`MGMT_ERR_EUNKNOWN`. | + | | when ``rc`` is :c:enumerator:`MGMT_ERR_EUNKNOWN`. | +------------------+-------------------------------------------------------------------------+ The "off" field is only included in responses to successfully processed requests; @@ -509,10 +509,10 @@ where: | | using SMP version 1 or for SMP errors when using SMP version 2. | +------------------+-------------------------------------------------------------------------+ | "rsn" | optional string that clarifies reason for an error; specifically useful | - | | when ``rc`` is :c:enum:`MGMT_ERR_EUNKNOWN`. | + | | when ``rc`` is :c:enumerator:`MGMT_ERR_EUNKNOWN`. | +------------------+-------------------------------------------------------------------------+ .. note:: Response from Zephyr running device may have "rc" value of - :c:enum:`MGMT_ERR_EBADSTATE`, which means that the secondary + :c:enumerator:`MGMT_ERR_EBADSTATE`, which means that the secondary image has been marked for next boot already and may not be erased. diff --git a/doc/services/device_mgmt/smp_groups/smp_group_3.rst b/doc/services/device_mgmt/smp_groups/smp_group_3.rst index 0636e72e3f649..b5fd66d3d6033 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_3.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_3.rst @@ -542,5 +542,5 @@ There is a settings access MCUmgr callback available (see :ref:`mcumgr_callbacks callbacks) which allows for applications/modules to know when settings management commands are used and, optionally, block access (for example through the use of a security mechanism). This callback can be enabled with :kconfig:option:`CONFIG_MCUMGR_GRP_SETTINGS_ACCESS_HOOK`, registered -with the event :c:enum:`MGMT_EVT_OP_SETTINGS_MGMT_ACCESS`, whereby the supplied callback data is -:c:struct:`settings_mgmt_access`. +with the event :c:enumerator:`MGMT_EVT_OP_SETTINGS_MGMT_ACCESS`, whereby the supplied callback data +is :c:struct:`settings_mgmt_access`. diff --git a/doc/services/device_mgmt/smp_groups/smp_group_8.rst b/doc/services/device_mgmt/smp_groups/smp_group_8.rst index 502a575716904..7a50ebf3d7c89 100644 --- a/doc/services/device_mgmt/smp_groups/smp_group_8.rst +++ b/doc/services/device_mgmt/smp_groups/smp_group_8.rst @@ -47,7 +47,7 @@ requests or even be removed. However, if the Kconfig option :kconfig:option:`CONFIG_MCUMGR_GRP_FS_FILE_ACCESS_HOOK` is enabled, then an application can register a callback handler for - :c:enum:`MGMT_EVT_OP_FS_MGMT_FILE_ACCESS` (see + :c:enumerator:`MGMT_EVT_OP_FS_MGMT_FILE_ACCESS` (see :ref:`MCUmgr callbacks `), which allows for allowing or declining access to reading/writing a particular file, or for rewriting the path supplied by the client. @@ -185,7 +185,7 @@ change between requests or even be removed. However, if the Kconfig option :kconfig:option:`CONFIG_MCUMGR_GRP_FS_FILE_ACCESS_HOOK` is enabled, then an application can register a callback handler for - :c:enum:`MGMT_EVT_OP_FS_MGMT_FILE_ACCESS` (see + :c:enumerator:`MGMT_EVT_OP_FS_MGMT_FILE_ACCESS` (see :ref:`MCUmgr callbacks `), which allows for allowing or declining access to reading/writing a particular file, or for rewriting the path supplied by the client. diff --git a/doc/services/llext/index.rst b/doc/services/llext/index.rst index d742f198530d3..899936cda61ab 100644 --- a/doc/services/llext/index.rst +++ b/doc/services/llext/index.rst @@ -18,6 +18,66 @@ needed by the :c:func:`llext_load` function. An implementation over a buffer containing an ELF in addressable memory in memory is available as :c:struct:`llext_buf_loader`. +LLEXT Extension Development Kit +******************************* + +To build the extensions to be loaded by the llext subsystem, it's necessary to +have access to the headers and compiler flags used by the main Zephyr +application. While building an extension as part of the Zephyr application +is straightforward, it can be more complex as a standalone project. + +The LLEXT Extension Development Kit (EDK) provides a set of headers and compile +flags that can be used to build extensions as standalone projects. The EDK +can be generated by the Zephyr build system by running the following command +which uses the ``llext-edk`` target to generate the EDK: + +.. code-block:: shell + + west build -t llext-edk + +The generated EDK can be found in the build directory under the ``zephyr`` +directory. It's a tarball that contains the headers and compile flags needed +to build extensions. The extension developer can then include the headers +and use the compile flags in their build system to build the extension. + +Compile flags +------------- + +Convenience files ``cmake.cflags`` (for CMake based projects) and +``Makefile.cflags`` are provided by the EDK containing the needed compile flags. +The main flag is ``LLEXT_CFLAGS`` which contains the flags needed to build an +extension. Also provided is a granular set of flags that can be used in support +of different use cases, such as when building mocks for unit tests. The provided +flags are: + +- ``LLEXT_CFLAGS``: Flags needed to build an extension. +- ``LLEXT_ALL_INCLUDE_CFLAGS``: Include flags needed to include all headers. +- ``LLEXT_INCLUDE_CFLAGS``: Include flags for non build generated headers. +- ``LLEXT_GENERATED_INCLUDE_CFLAGS``: Include flags for build generated headers. +- ``LLEXT_BASE_CFLAGS``: All other flags needed to build an extension, + excluding the include flags. +- ``LLEXT_GENERATED_IMACROS_CFLAGS``: Include only ``-imacros`` flags for build + generated headers. + +LLEXT EDK Kconfig options +------------------------- + +The LLEXT EDK can be configured using the following Kconfig options: + +:kconfig:option:`CONFIG_LLEXT_EDK_NAME` + The name of the generated EDK tarball. + +:kconfig:option:`CONFIG_LLEXT_EDK_USERSPACE_ONLY` + If set, the EDK will include headers that do not contain code to route + syscalls to the kernel. This is useful when building extensions that will + run exclusively in user mode. + +EDK Sample +---------- + +Refer to :zephyr:code-sample:`llext-edk` for an example of how to use the +LLEXT EDK. + API Reference ************* diff --git a/doc/services/logging/index.rst b/doc/services/logging/index.rst index 9e54f8d4da8d0..1193bc6ce7ab9 100644 --- a/doc/services/logging/index.rst +++ b/doc/services/logging/index.rst @@ -53,7 +53,7 @@ For each level the following set of macros are available: - ``LOG_INST_X`` for standard printf-like message associated with the particular instance, e.g. :c:macro:`LOG_INST_INF`. - ``LOG_INST_HEXDUMP_X`` for dumping data associated with the particular - instance, e.g. :c:macro:`LOG_HEXDUMP_INST_DBG` + instance, e.g. :c:macro:`LOG_INST_HEXDUMP_DBG` The warning level also exposes the following additional macro: diff --git a/doc/services/pm/device.rst b/doc/services/pm/device.rst index 055591c5f2c0b..379ebfbef74fb 100644 --- a/doc/services/pm/device.rst +++ b/doc/services/pm/device.rst @@ -72,16 +72,46 @@ For more information, see :ref:`pm-device-runtime`. System-Managed Device Power Management ====================================== +The system managed device power management (PM) framework is a method where +devices are suspended along with the system entering a CPU (or SoC) power state. +It can be enabled by setting :kconfig:option:`CONFIG_PM_DEVICE_SYSTEM_MANAGED`. When using this method, device power management is mostly done inside -:c:func:`pm_system_suspend()` along with entering a CPU or SOC power state. +:c:func:`pm_system_suspend()`. If a decision to enter a CPU lower power state is made, the power management -subsystem will suspend devices before changing state. The subsystem takes care -of suspending devices following their initialization order, ensuring that +subsystem will check if the selected low power state triggers device power +management and then suspend devices before changing state. The subsystem takes +care of suspending devices following their initialization order, ensuring that possible dependencies between them are satisfied. As soon as the CPU wakes up from a sleep state, devices are resumed in the opposite order that they were suspended. +The decision about suspending devices when entering a low power state is done based on the +state and if it has set the property ``zephyr,pm-device-disabled``. Here is +an example of a target with two low power states with only one triggering device power +management: + +.. code-block:: devicetree + + /* Node in a DTS file */ + cpus { + power-states { + state0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <5000>; + exit-latency-us = <240>; + zephyr,pm-device-disabled; + }; + state1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + min-residency-us = <8000>; + exit-latency-us = <360>; + }; + }; + }; + .. note:: When using :ref:`pm-system`, device transitions can be run from the idle thread. @@ -114,12 +144,6 @@ It is important to emphasize that this method has drawbacks (see above) and :kconfig:option:`CONFIG_PM_NEED_ALL_DEVICES_IDLE` is set and a device is marked as busy. -.. note:: - - This method of device power management is disabled when - :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE` is set to ``y`` (that is - the default value when :kconfig:option:`CONFIG_PM_DEVICE_RUNTIME` is enabled) - .. note:: Devices are suspended only when the last active core is entering a low power @@ -283,6 +307,96 @@ the system will not do power management on it. After the device is no longer doing an operation and can be suspended, it should call :c:func:`pm_device_busy_clear`. +.. _pm-device-constraint: + +Device Power Management X System Power Management +************************************************* + +When managing power in embedded systems, it's crucial to understand +the interplay between device power state and the overall system power +state. Some devices may have dependencies on the system power +state. For example, certain low-power states of the SoC might not +supply power to peripheral devices, leading to problems if the device +is in the middle of an operation. Proper coordination is essential to +maintain system stability and data integrity. + +To avoid this sort of problem, devices must :ref:`get and release lock ` +power states that cause power loss during an operation. + +Zephyr provides a mechanism for devices to declare which power states cause power +loss and an API that automatically get and put lock on them. This feature is +enabled setting :kconfig:option:`CONFIG_PM_POLICY_DEVICE_CONSTRAINTS` to ``y``. + +Once this feature is enabled, devices must declare in devicetree which +states cause power loss. In the following example, device ``test_dev`` +says that power states ``state1`` and ``state2`` cause power loss. + +.. code-block:: devicetree + + power-states { + state0: state0 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <10000>; + exit-latency-us = <100>; + }; + + state1: state1 { + compatible = "zephyr,power-state"; + power-state-name = "standby"; + min-residency-us = <20000>; + exit-latency-us = <200>; + }; + + state2: state2 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + min-residency-us = <50000>; + exit-latency-us = <500>; + }; + + state3: state3 { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + status = "disabled"; + }; + }; + + test_dev: test_dev { + compatible = "test-device-pm"; + status = "okay"; + zephyr,disabling-power-states = <&state1 &state2>; + }; + +After that devices can lock these state calling +:c:func:`pm_policy_device_power_lock_get` and release with +:c:func:`pm_policy_device_power_lock_put`. For example: + +.. code-block:: C + + static void timer_expire_cb(struct k_timer *timer) + { + struct test_driver_data *data = k_timer_user_data_get(timer); + + data->ongoing = false; + k_timer_stop(timer); + pm_policy_device_power_lock_put(data->self); + } + + void test_driver_async_operation(const struct device *dev) + { + struct test_driver_data *data = dev->data; + + data->ongoing = true; + pm_policy_device_power_lock_get(dev); + + /** Lets set a timer big enough to ensure that any deep + * sleep state would be suitable but constraints will + * make only state0 (suspend-to-idle) will be used. + */ + k_timer_start(&data->timer, K_MSEC(500), K_NO_WAIT); + } + Wakeup capability ***************** diff --git a/doc/services/pm/power_domain.rst b/doc/services/pm/power_domain.rst index feab6998c6ee3..faa677b796a1b 100644 --- a/doc/services/pm/power_domain.rst +++ b/doc/services/pm/power_domain.rst @@ -184,5 +184,5 @@ Examples Some helpful examples showing power domain features: -* :zephyr_file:`samples/subsys/pm/device_power_domains/` -* :zephyr_file:`samples/subsys/pm/power_domain/` +* :zephyr_file:`tests/subsys/pm/device_power_domains/` +* :zephyr_file:`tests/subsys/pm/power_domain/` diff --git a/doc/services/pm/system.rst b/doc/services/pm/system.rst index d6ec306a20013..49ba81e935731 100644 --- a/doc/services/pm/system.rst +++ b/doc/services/pm/system.rst @@ -122,6 +122,8 @@ remaining time until the next scheduled timeout. An example of an application that defines its own policy can be found in :zephyr_file:`tests/subsys/pm/power_mgmt/`. +.. _pm-policy-power-states: + Policy and Power States ------------------------ diff --git a/doc/services/portability/posix/aep/index.rst b/doc/services/portability/posix/aep/index.rst index a8f214ef2aacb..aeb591f2ab0a4 100644 --- a/doc/services/portability/posix/aep/index.rst +++ b/doc/services/portability/posix/aep/index.rst @@ -42,7 +42,7 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :header: Symbol, Support, Remarks :widths: 50, 10, 50 - _POSIX_AEP_REALTIME_MINIMAL, -1, + _POSIX_AEP_REALTIME_MINIMAL, -1, :kconfig:option:`CONFIG_POSIX_AEP_REALTIME_MINIMAL` .. csv-table:: PSE51 Option Groups :header: Symbol, Support, Remarks @@ -50,28 +50,27 @@ The *Minimal Realtime System Profile* (PSE51) includes all of the :ref:`POSIX_C_LANG_JUMP `, yes, :ref:`POSIX_C_LANG_SUPPORT `, yes, - :ref:`POSIX_DEVICE_IO `,, - :ref:`POSIX_SIGNALS `,, - :ref:`POSIX_SINGLE_PROCESS `, yes, - :ref:`POSIX_THREADS_BASE `, yes, - :ref:`XSI_THREADS_EXT `, yes, + :ref:`POSIX_DEVICE_IO `,, :kconfig:option:`CONFIG_POSIX_DEVICE_IO` + :ref:`POSIX_SIGNALS `,, :kconfig:option:`CONFIG_POSIX_SIGNALS` + :ref:`POSIX_SINGLE_PROCESS `, yes, :kconfig:option:`CONFIG_POSIX_SINGLE_PROCESS` + :ref:`XSI_THREADS_EXT `, yes, :kconfig:option:`CONFIG_XSI_THREADS_EXT` .. csv-table:: PSE51 Option Requirements :header: Symbol, Support, Remarks :widths: 50, 10, 50 :ref:`_POSIX_FSYNC `, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` - :ref:`_POSIX_MEMLOCK `, -1, - :ref:`_POSIX_MEMLOCK_RANGE `, -1, - :ref:`_POSIX_MONOTONIC_CLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` - :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, -1, - :ref:`_POSIX_SYNCHRONIZED_IO `, -1, - :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` - :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` - :ref:`_POSIX_THREAD_CPUTIME `, -1, - _POSIX_THREAD_PRIO_INHERIT, 200809L, :kconfig:option:`CONFIG_PTHREAD_MUTEX` - _POSIX_THREAD_PRIO_PROTECT, -1, - :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` + :ref:`_POSIX_MEMLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK` :ref:`†` + :ref:`_POSIX_MEMLOCK_RANGE `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK_RANGE` + :ref:`_POSIX_MONOTONIC_CLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` + :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, 200809L, :kconfig:option:`CONFIG_POSIX_SHARED_MEMORY_OBJECTS` + :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` + :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKADDR` + :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKSIZE` + :ref:`_POSIX_THREAD_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` + :ref:`_POSIX_THREAD_PRIO_INHERIT `, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_PRIO_INHERIT` + :ref:`_POSIX_THREAD_PRIO_PROTECT `, -1, :kconfig:option:`CONFIG_POSIX_THREAD_PRIO_PROTECT` + :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING `, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_PRIORITY_SCHEDULING` _POSIX_THREAD_SPORADIC_SERVER, -1, .. _posix_aep_pse52: @@ -95,21 +94,21 @@ The *Realtime Controller System Profile* (PSE52) includes all features from PSE5 :header: Symbol, Support, Remarks :widths: 50, 10, 50 - _POSIX_AEP_REALTIME_CONTROLLER, -1, + _POSIX_AEP_REALTIME_CONTROLLER, -1, :kconfig:option:`CONFIG_POSIX_AEP_REALTIME_CONTROLLER` .. csv-table:: PSE52 Option Groups :header: Symbol, Support, Remarks :widths: 50, 10, 50 :ref:`POSIX_C_LANG_MATH `, yes, - :ref:`POSIX_FD_MGMT `,, - :ref:`POSIX_FILE_SYSTEM `,, + :ref:`POSIX_FD_MGMT `,, :kconfig:option:`CONFIG_POSIX_FD_MGMT` + :ref:`POSIX_FILE_SYSTEM `,, :kconfig:option:`CONFIG_POSIX_FILE_SYSTEM` .. csv-table:: PSE52 Option Requirements :header: Symbol, Support, Remarks :widths: 50, 10, 50 - :ref:`_POSIX_MESSAGE_PASSING `, 200809L, :kconfig:option:`CONFIG_POSIX_MQUEUE` + :ref:`_POSIX_MESSAGE_PASSING `, 200809L, :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` _POSIX_TRACE, -1, _POSIX_TRACE_EVENT_FILTER, -1, _POSIX_TRACE_LOG, -1, @@ -135,14 +134,14 @@ The *Dedicated Realtime System Profile* (PSE53) includes all features from PSE52 :header: Symbol, Support, Remarks :widths: 50, 10, 50 - _POSIX_AEP_REALTIME_DEDICATED, -1, + _POSIX_AEP_REALTIME_DEDICATED, -1, :kconfig:option:`CONFIG_POSIX_AEP_REALTIME_DEDICATED` .. csv-table:: PSE53 Option Groups :header: Symbol, Support, Remarks :widths: 50, 10, 50 - POSIX_MULTI_PROCESS,, :ref:`†` - :ref:`POSIX_NETWORKING `, yes, + :ref:`POSIX_MULTI_PROCESS`,, :kconfig:option:`CONFIG_POSIX_MULTI_PROCESS`:ref:`†` + :ref:`POSIX_NETWORKING `, yes, :kconfig:option:`CONFIG_POSIX_NETWORKING` :ref:`POSIX_PIPE `,, :ref:`POSIX_SIGNAL_JUMP `,, @@ -150,10 +149,10 @@ The *Dedicated Realtime System Profile* (PSE53) includes all features from PSE52 :header: Symbol, Support, Remarks :widths: 50, 10, 50 - _POSIX_CPUTIME, -1, + :ref:`_POSIX_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING `, -1, - _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS_PACKET` + :ref:`_POSIX_RAW_SOCKETS `, 200809L, :kconfig:option:`CONFIG_POSIX_RAW_SOCKETS` _POSIX_SPAWN, -1, :ref:`†` _POSIX_SPORADIC_SERVER, -1, :ref:`†` diff --git a/doc/services/portability/posix/conformance/index.rst b/doc/services/portability/posix/conformance/index.rst index 69e77eed89c35..4cd8687ebf4fa 100644 --- a/doc/services/portability/posix/conformance/index.rst +++ b/doc/services/portability/posix/conformance/index.rst @@ -5,22 +5,6 @@ POSIX Conformance As per `IEEE 1003.1-2017`, this section details Zephyr's POSIX conformance. -.. _posix_undefined_behaviour: - -.. note:: - As per POSIX 1003.13, single process mode is supported directly by both PSE51 and PSE52 - profiles. While Zephyr includes support for many features found in PSE53, PSE53 itself requires - supporting multiple processes. Since supporting multiple processes is beyond the scope of - Zephyr's current design, some features requiring multi-process capabilities may exhibit - undefined behaviour, which we denote with the † (obelus) symbol. - -.. _posix_libc_provided: - -.. note:: - Features listed in various POSIX Options or Option Groups may be provided in whole or in part - by a conformant C library implementation. This includes (but is not limited to) POSIX - Extensions to the ISO C Standard (`CX`_). - .. _posix_system_interfaces: POSIX System Interfaces @@ -34,19 +18,7 @@ POSIX System Interfaces _POSIX_CHOWN_RESTRICTED, 0, _POSIX_NO_TRUNC, 0, - _POSIX_VDISABLE, 0, - -.. The following should be valued greater than zero in Zephyr, in order to be strictly conformant - with the POSIX specification. - -.. csv-table:: POSIX System Interfaces - :header: Symbol, Support, Remarks - :widths: 50, 10, 50 - - _POSIX_JOB_CONTROL, -1, :ref:`†` - _POSIX_REGEXP, -1, :ref:`†` - _POSIX_SAVED_IDS, -1, :ref:`†` - _POSIX_SHELL, -1, :ref:`†` + _POSIX_VDISABLE, ``'\0'``, .. TODO: POSIX_ASYNCHRONOUS_IO, and other interfaces below, are mandatory. That means that a strictly conforming application need not be modified in order to compile against Zephyr. @@ -61,46 +33,58 @@ POSIX System Interfaces :widths: 50, 10, 50 _POSIX_VERSION, 200809L, - :ref:`_POSIX_ASYNCHRONOUS_IO`, 200809L, :ref:`†` - :ref:`_POSIX_BARRIERS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_BARRIER` - :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` - _POSIX_MAPPED_FILES, -1, :ref:`†` - _POSIX_MEMORY_PROTECTION, -1, :ref:`†` - :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` - :ref:`_POSIX_REALTIME_SIGNALS`, -1, - :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` - :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` - :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, - :ref:`_POSIX_THREADS`, -1, :kconfig:option:`CONFIG_PTHREAD_IPC` - :ref:`_POSIX_TIMEOUTS`, 200809L, :kconfig:option:`CONFIG_PTHREAD_IPC` - :ref:`_POSIX_TIMERS`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + :ref:`_POSIX_ASYNCHRONOUS_IO`, 200809L, :kconfig:option:`CONFIG_POSIX_ASYNCHRONOUS_IO`:ref:`†` + :ref:`_POSIX_BARRIERS`, 200809L, :kconfig:option:`CONFIG_POSIX_BARRIERS` + :ref:`_POSIX_CLOCK_SELECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK_SELECTION` + :ref:`_POSIX_MAPPED_FILES`, 200809L, :kconfig:option:`CONFIG_POSIX_MAPPED_FILES` + :ref:`_POSIX_MEMORY_PROTECTION`, 200809L, :kconfig:option:`CONFIG_POSIX_MEMORY_PROTECTION` :ref:`†` + :ref:`_POSIX_READER_WRITER_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_READER_WRITER_LOCKS` + :ref:`_POSIX_REALTIME_SIGNALS`, -1, :kconfig:option:`CONFIG_POSIX_REALTIME_SIGNALS` + :ref:`_POSIX_SEMAPHORES`, 200809L, :kconfig:option:`CONFIG_POSIX_SEMAPHORES` + :ref:`_POSIX_SPIN_LOCKS`, 200809L, :kconfig:option:`CONFIG_POSIX_SPIN_LOCKS` + :ref:`_POSIX_THREAD_SAFE_FUNCTIONS`, -1, :kconfig:option:`CONFIG_POSIX_THREAD_SAFE_FUNCTIONS` + :ref:`_POSIX_THREADS`, -1, :kconfig:option:`CONFIG_POSIX_THREADS` + :ref:`_POSIX_TIMEOUTS`, 200809L, :kconfig:option:`CONFIG_POSIX_TIMEOUTS` + :ref:`_POSIX_TIMERS`, 200809L, :kconfig:option:`CONFIG_POSIX_TIMERS` _POSIX2_C_BIND, 200809L, +.. The following should be valued greater than zero in Zephyr, in order to be strictly conformant + with the POSIX specification. + +.. csv-table:: POSIX System Interfaces (Unsupported) + :header: Symbol, Support, Remarks + :widths: 50, 10, 50 + + _POSIX_JOB_CONTROL, -1, :ref:`†` + _POSIX_REGEXP, -1, :ref:`†` + _POSIX_SAVED_IDS, -1, :ref:`†` + _POSIX_SHELL, -1, :ref:`†` + .. csv-table:: POSIX System Interfaces (Optional) :header: Symbol, Support, Remarks :widths: 50, 10, 50 _POSIX_ADVISORY_INFO, -1, - _POSIX_CPUTIME, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + :ref:`_POSIX_CPUTIME`, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` :ref:`_POSIX_FSYNC`, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` - _POSIX_IPV6, 200809L, :kconfig:option:`CONFIG_NET_IPV6` - _POSIX_MEMLOCK, -1, - _POSIX_MEMLOCK_RANGE, -1, - :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MQUEUE` - :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_CLOCK` + :ref:`_POSIX_IPV6`, 200809L, :kconfig:option:`CONFIG_POSIX_IPV6` + :ref:`_POSIX_MEMLOCK `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK` :ref:`†` + :ref:`_POSIX_MEMLOCK_RANGE `, 200809L, :kconfig:option:`CONFIG_POSIX_MEMLOCK_RANGE` + :ref:`_POSIX_MESSAGE_PASSING`, 200809L, :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` + :ref:`_POSIX_MONOTONIC_CLOCK`, 200809L, :kconfig:option:`CONFIG_POSIX_MONOTONIC_CLOCK` _POSIX_PRIORITIZED_IO, -1, :ref:`_POSIX_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_POSIX_PRIORITY_SCHEDULING` - _POSIX_RAW_SOCKETS, 200809L, :kconfig:option:`CONFIG_NET_SOCKETS_PACKET` - _POSIX_SHARED_MEMORY_OBJECTS, -1, + :ref:`_POSIX_RAW_SOCKETS`, 200809L, :kconfig:option:`CONFIG_POSIX_RAW_SOCKETS` + :ref:`_POSIX_SHARED_MEMORY_OBJECTS `, 200809L, :kconfig:option:`CONFIG_POSIX_SHARED_MEMORY_OBJECTS` _POSIX_SPAWN, -1, :ref:`†` _POSIX_SPORADIC_SERVER, -1, :ref:`†` - _POSIX_SYNCHRONIZED_IO, -1, - :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` - :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` - _POSIX_THREAD_CPUTIME, -1, - _POSIX_THREAD_PRIO_INHERIT, 200809L, :kconfig:option:`CONFIG_PTHREAD_MUTEX` - _POSIX_THREAD_PRIO_PROTECT, -1, - :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + :ref:`_POSIX_SYNCHRONIZED_IO `, -1, :kconfig:option:`CONFIG_POSIX_SYNCHRONIZED_IO` + :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKADDR` + :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKSIZE` + :ref:`_POSIX_THREAD_CPUTIME `, 200809L, :kconfig:option:`CONFIG_POSIX_CPUTIME` + :ref:`_POSIX_THREAD_PRIO_INHERIT `, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_PRIO_INHERIT` + :ref:`_POSIX_THREAD_PRIO_PROTECT `, -1, :kconfig:option:`CONFIG_POSIX_THREAD_PRIO_PROTECT` + :ref:`_POSIX_THREAD_PRIORITY_SCHEDULING `, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_PRIORITY_SCHEDULING` _POSIX_THREAD_PROCESS_SHARED, -1, _POSIX_THREAD_SPORADIC_SERVER, -1, _POSIX_TRACE, -1, @@ -111,9 +95,10 @@ POSIX System Interfaces _XOPEN_CRYPT, -1, _XOPEN_REALTIME, -1, _XOPEN_REALTIME_THREADS, -1, - :ref:`_XOPEN_STREAMS`, -1, :ref:`†` + :ref:`_XOPEN_STREAMS`, 200809L, :kconfig:option:`CONFIG_XOPEN_STREAMS` _XOPEN_UNIX, -1, + POSIX Shell and Utilities ========================= @@ -141,16 +126,32 @@ Zephyr does not support a POSIX shell or utilities at this time. XSI Conformance ############### -XSI System Interfaces -===================== +X/Open System Interfaces +======================== -.. csv-table:: XSI System Interfaces +.. csv-table:: X/Open System Interfaces :header: Symbol, Support, Remarks :widths: 50, 10, 50 :ref:`_POSIX_FSYNC`, 200809L, :kconfig:option:`CONFIG_POSIX_FSYNC` - :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_PTHREAD` - :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_PTHREAD` + :ref:`_POSIX_THREAD_ATTR_STACKADDR`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKADDR` + :ref:`_POSIX_THREAD_ATTR_STACKSIZE`, 200809L, :kconfig:option:`CONFIG_POSIX_THREAD_ATTR_STACKSIZE` _POSIX_THREAD_PROCESS_SHARED, -1, +.. _posix_undefined_behaviour: + +.. note:: + Some features may exhibit undefined behaviour as they fall beyond the scope of Zephyr's current + design and capabilities. For example, multi-processing, ad-hoc memory-mapping, multiple users, + or regular expressions are features that are uncommon in low-footprint embedded systems. + Such undefined behaviour is denoted with the † (obelus) symbol. Additional details + :ref:`here `. + +.. _posix_libc_provided: + +.. note:: + Features listed in various POSIX Options or Option Groups may be provided in whole or in part + by a conformant C library implementation. This includes (but is not limited to) POSIX + Extensions to the ISO C Standard (`CX`_). + .. _CX: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap01.html diff --git a/doc/services/portability/posix/kconfig/index.rst b/doc/services/portability/posix/kconfig/index.rst index 059c0c1affe50..7c7055326df2c 100644 --- a/doc/services/portability/posix/kconfig/index.rst +++ b/doc/services/portability/posix/kconfig/index.rst @@ -1,50 +1,40 @@ .. _posix_kconfig_options: -Configuration Options -********************* +Additional Configuration Options +******************************** -This is a non-exhaustive list of specific :ref:`kconfig` options relating to Zephyr's +Below is a non-exhaustive list of additional :ref:`kconfig` options relating to Zephyr's implementation of the POSIX API. +* :kconfig:option:`CONFIG_DYNAMIC_THREAD` +* :kconfig:option:`CONFIG_DYNAMIC_THREAD_POOL_SIZE` * :kconfig:option:`CONFIG_EVENTFD` -* :kconfig:option:`CONFIG_EVENTFD_MAX` * :kconfig:option:`CONFIG_FDTABLE` -* :kconfig:option:`CONFIG_FNMATCH` -* :kconfig:option:`CONFIG_GETOPT` * :kconfig:option:`CONFIG_GETOPT_LONG` -* :kconfig:option:`CONFIG_MAX_PTHREAD_BARRIER_COUNT` -* :kconfig:option:`CONFIG_MAX_PTHREAD_COUNT` -* :kconfig:option:`CONFIG_MAX_PTHREAD_KEY_COUNT` -* :kconfig:option:`CONFIG_MAX_PTHREAD_MUTEX_COUNT` * :kconfig:option:`CONFIG_MAX_PTHREAD_SPINLOCK_COUNT` -* :kconfig:option:`CONFIG_MAX_TIMER_COUNT` * :kconfig:option:`CONFIG_MQUEUE_NAMELEN_MAX` -* :kconfig:option:`CONFIG_MSG_COUNT_MAX` +* :kconfig:option:`CONFIG_POSIX_MQ_OPEN_MAX` * :kconfig:option:`CONFIG_MSG_SIZE_MAX` * :kconfig:option:`CONFIG_NET_SOCKETPAIR` * :kconfig:option:`CONFIG_NET_SOCKETS` * :kconfig:option:`CONFIG_NET_SOCKETS_POLL_MAX` +* :kconfig:option:`CONFIG_ZVFS_OPEN_MAX` * :kconfig:option:`CONFIG_POSIX_API` -* :kconfig:option:`CONFIG_POSIX_CLOCK` -* :kconfig:option:`CONFIG_POSIX_FS` -* :kconfig:option:`CONFIG_POSIX_LIMITS_RTSIG_MAX` -* :kconfig:option:`CONFIG_POSIX_MAX_FDS` -* :kconfig:option:`CONFIG_POSIX_MAX_OPEN_FILES` -* :kconfig:option:`CONFIG_POSIX_MQUEUE` +* :kconfig:option:`CONFIG_POSIX_OPEN_MAX` +* :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_BITS` +* :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT` +* :kconfig:option:`CONFIG_POSIX_PTHREAD_ATTR_STACKSIZE_BITS` * :kconfig:option:`CONFIG_POSIX_RTSIG_MAX` -* :kconfig:option:`CONFIG_POSIX_SIGNAL` * :kconfig:option:`CONFIG_POSIX_SIGNAL_STRING_DESC` -* :kconfig:option:`CONFIG_POSIX_UNAME` +* :kconfig:option:`CONFIG_POSIX_THREAD_KEYS_MAX` +* :kconfig:option:`CONFIG_POSIX_THREAD_THREADS_MAX` * :kconfig:option:`CONFIG_POSIX_UNAME_NODENAME_LEN` * :kconfig:option:`CONFIG_POSIX_UNAME_VERSION_LEN` -* :kconfig:option:`CONFIG_PTHREAD` -* :kconfig:option:`CONFIG_PTHREAD_BARRIER` -* :kconfig:option:`CONFIG_PTHREAD_COND` * :kconfig:option:`CONFIG_PTHREAD_CREATE_BARRIER` -* :kconfig:option:`CONFIG_PTHREAD_IPC` -* :kconfig:option:`CONFIG_PTHREAD_KEY` -* :kconfig:option:`CONFIG_PTHREAD_MUTEX` * :kconfig:option:`CONFIG_PTHREAD_RECYCLER_DELAY_MS` -* :kconfig:option:`CONFIG_PTHREAD_SPINLOCK` -* :kconfig:option:`CONFIG_SEM_VALUE_MAX` -* :kconfig:option:`CONFIG_TIMER` +* :kconfig:option:`CONFIG_POSIX_SEM_NAMELEN_MAX` +* :kconfig:option:`CONFIG_POSIX_SEM_NSEMS_MAX` +* :kconfig:option:`CONFIG_POSIX_SEM_VALUE_MAX` +* :kconfig:option:`CONFIG_TIMER_CREATE_WAIT` +* :kconfig:option:`CONFIG_THREAD_STACK_INFO` +* :kconfig:option:`CONFIG_ZVFS_EVENTFD_MAX` diff --git a/doc/services/portability/posix/option_groups/index.rst b/doc/services/portability/posix/option_groups/index.rst index e284af76d0254..8339e200e05c1 100644 --- a/doc/services/portability/posix/option_groups/index.rst +++ b/doc/services/portability/posix/option_groups/index.rst @@ -102,6 +102,20 @@ This table lists service support status in Zephyr: pthread_getconcurrency(),yes pthread_setconcurrency(),yes +.. _posix_option_group_xsi_system_logging: + +XSI_SYSTEM_LOGGING +================== + +.. csv-table:: XSI_SYSTEM_LOGGING + :header: API, Supported + :widths: 50,10 + + closelog(),yes + openlog(),yes + setlogmask(),yes + syslog(),yes + .. _posix_option_group_c_lang_jump: POSIX_C_LANG_JUMP @@ -151,6 +165,31 @@ Group. For more information on developing Zephyr applications in the C programming language, please refer to :ref:`details`. +.. _posix_option_group_c_lib_ext: + +POSIX_C_LIB_EXT +=============== + +.. csv-table:: POSIX_C_LIB_EXT + :header: API, Supported + :widths: 50,10 + + fnmatch(), yes + getopt(), yes + getsubopt(), + optarg, yes + opterr, yes + optind, yes + optopt, yes + stpcpy(), + stpncpy(), + strcasecmp(), + strdup(), + strfmon(), + strncasecmp(), yes + strndup(), + strnlen(), yes + .. _posix_option_group_realtime_signals: POSIX_REALTIME_SIGNALS @@ -329,7 +368,7 @@ POSIX_FILE_SYSTEM creat(), fchdir(), fpathconf(), - fstat(), + fstat(), yes fstatvfs(), getcwd(), link(), @@ -350,6 +389,19 @@ POSIX_FILE_SYSTEM unlink(), yes utime(), +.. _posix_option_group_mapped_files: + +POSIX_MAPPED_FILES +================== + +.. csv-table:: POSIX_MAPPED_FILES + :header: API, Supported + :widths: 50,10 + + mmap(),yes + msync(),yes + munmap(),yes + .. _posix_option_group_networking: POSIX_NETWORKING @@ -520,6 +572,51 @@ This table lists service support status in Zephyr for `POSIX_FD_MGMT`: putc_unlocked(), putchar_unlocked(), +.. _posix_option_group_memory_protection: + +POSIX_MEMORY_PROTECTION +======================= + +.. csv-table:: POSIX_MEMORY_PROTECTION + :header: API, Supported + :widths: 50,10 + + mprotect(), yes :ref:`†` + +.. _posix_option_group_multi_process: + +POSIX_MULTI_PROCESS +=================== + +.. csv-table:: POSIX_MULTI_PROCESS + :header: API, Supported + :widths: 50,10 + + _Exit(), yes + _exit(), yes + assert(), yes + atexit(),:ref:`†` + clock(), + execl(),:ref:`†` + execle(),:ref:`†` + execlp(),:ref:`†` + execv(),:ref:`†` + execve(),:ref:`†` + execvp(),:ref:`†` + exit(), yes + fork(),:ref:`†` + getpgrp(),:ref:`†` + getpgid(),:ref:`†` + getpid(), yes :ref:`†` + getppid(),:ref:`†` + getsid(),:ref:`†` + setsid(),:ref:`†` + sleep(),yes + times(), + wait(),:ref:`†` + waitid(),:ref:`†` + waitpid(),:ref:`†` + .. _posix_options: Additional POSIX Options @@ -543,6 +640,17 @@ _POSIX_ASYNCHRONOUS_IO aio_write(),yes (will fail with ``ENOSYS``:ref:`†`) lio_listio(),yes (will fail with ``ENOSYS``:ref:`†`) +.. _posix_option_cputime: + +_POSIX_CPUTIME +++++++++++++++ + +.. csv-table:: _POSIX_CPUTIME + :header: API, Supported + :widths: 50,10 + + CLOCK_PROCESS_CPUTIME_ID,yes + .. _posix_option_fsync: _POSIX_FSYNC @@ -554,17 +662,30 @@ _POSIX_FSYNC fsync(),yes +.. _posix_option_ipv6: + +_POSIX_IPV6 ++++++++++++ + +Internet Protocol Version 6 is supported. + +For more information, please refer to :ref:`Networking `. + .. _posix_option_memlock: _POSIX_MEMLOCK ++++++++++++++ +Zephyr's :ref:`Demand Paging API ` does not yet support +pinning or unpinning all virtual memory regions. The functions below are expected to fail and +set ``errno`` to ``ENOSYS`` :ref:`†`. + .. csv-table:: _POSIX_MEMLOCK :header: API, Supported :widths: 50,10 - mlockall(), - munlockall(), + mlockall(), yes + munlockall(), yes .. _posix_option_memlock_range: @@ -575,8 +696,8 @@ _POSIX_MEMLOCK_RANGE :header: API, Supported :widths: 50,10 - mlock(), - munlock(), + mlock(), yes + munlock(), yes .. _posix_option_message_passing: @@ -625,6 +746,15 @@ _POSIX_PRIORITY_SCHEDULING sched_setscheduler(),yes (will fail with ``ENOSYS``:ref:`†`) sched_yield(),yes +.. _posix_option_raw_sockets: + +_POSIX_RAW_SOCKETS +++++++++++++++++++ + +Raw sockets are supported. + +For more information, please refer to :kconfig:option:`CONFIG_NET_SOCKETS_PACKET`. + .. _posix_option_reader_writer_locks: _POSIX_READER_WRITER_LOCKS @@ -655,10 +785,10 @@ _POSIX_SHARED_MEMORY_OBJECTS :header: API, Supported :widths: 50,10 - mmap(), - munmap(), - shm_open(), - shm_unlink(), + mmap(), yes + munmap(), yes + shm_open(), yes + shm_unlink(), yes .. _posix_option_synchronized_io: @@ -728,6 +858,34 @@ _POSIX_THREAD_PRIORITY_SCHEDULING pthread_setschedparam(),yes pthread_setschedprio(),yes +.. _posix_option_thread_prio_inherit: + +_POSIX_THREAD_PRIO_INHERIT +++++++++++++++++++++++++++ + +.. csv-table:: _POSIX_THREAD_PRIO_INHERIT + :header: API, Supported + :widths: 50,10 + + pthread_mutexattr_getprotocol(),yes + pthread_mutexattr_setprotocol(),yes + +.. _posix_option_thread_prio_protect: + +_POSIX_THREAD_PRIO_PROTECT +++++++++++++++++++++++++++ + +.. csv-table:: _POSIX_THREAD_PRIO_PROTECT + :header: API, Supported + :widths: 50,10 + + pthread_mutex_getprioceiling(), + pthread_mutex_setprioceiling(), + pthread_mutexattr_getprioceiling(), + pthread_mutexattr_getprotocol(),yes + pthread_mutexattr_setprioceiling(), + pthread_mutexattr_setprotocol(),yes + .. _posix_thread_safe_functions: _POSIX_THREAD_SAFE_FUNCTIONS @@ -779,18 +937,23 @@ _POSIX_TIMEOUTS _XOPEN_STREAMS ++++++++++++++ +With the exception of ``ioctl()``, functions in the ``_XOPEN_STREAMS`` option group are not +implemented in Zephyr but are provided so that conformant applications can still link. +Unimplemented functions in this option group will fail, setting ``errno`` to ``ENOSYS`` +:ref:`†`. + .. csv-table:: _XOPEN_STREAMS :header: API, Supported :widths: 50,10 - fattach(),yes (will fail with ``ENOSYS``:ref:`†`) - fdetach(),yes (will fail with ``ENOSYS``:ref:`†`) - getmsg(), yes (will fail with ``ENOSYS``:ref:`†`) - getpmsg(), yes (will fail with ``ENOSYS``:ref:`†`) - ioctl(),yes - isastream(),yes (will fail with ``ENOSYS``:ref:`†`) - putmsg(), yes (will fail with ``ENOSYS``:ref:`†`) - putpmsg(), + fattach(), yes :ref:`†` + fdetach(), yes :ref:`†` + getmsg(), yes :ref:`†` + getpmsg(), yes :ref:`†` + ioctl(), yes + isastream(), yes :ref:`†` + putmsg(), yes :ref:`†` + putpmsg(), yes :ref:`†` .. _Subprofiling Considerations: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html diff --git a/doc/services/portability/posix/overview/index.rst b/doc/services/portability/posix/overview/index.rst index cd00b68b1a721..6c352cf245433 100644 --- a/doc/services/portability/posix/overview/index.rst +++ b/doc/services/portability/posix/overview/index.rst @@ -122,23 +122,43 @@ Configuration Like most features in Zephyr, POSIX features are :ref:`highly configurable` but disabled by default. Users must -explicitly choose to enable POSIX options via :ref:`Kconfig` selection. Indeed, there are -:ref:`many Kconfig options in Zephyr` for the POSIX API to allow for -feature selection at various levels of granularity. +explicitly choose to enable POSIX options via :ref:`Kconfig` selection. -Alternatively, users may enable one of the Kconfig options below as a shortcut to enable multiple -:ref:`Option Groups`. +Subprofiles ++++++++++++ + +Enable one of the Kconfig options below to quickly configure a pre-defined +:ref:`POSIX subprofile `. + +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_BASE` (:ref:`Base `) +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_PSE51` (:ref:`PSE51 `) +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_PSE52` (:ref:`PSE52 `) +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_PSE53` (:ref:`PSE53 `) + +Additional POSIX :ref:`Options and Option Groups ` may be enabled as needed +via Kconfig (e.g. ``CONFIG_POSIX_C_LIB_EXT=y``). Further fine-tuning may be accomplished via +:ref:`additional POSIX-related Kconfig options `. + +Subprofiles, Options, and Option Groups should be considered the preferred way to configure POSIX +in Zephyr going forward. + +Legacy +++++++ + +Historically, Zephyr used :kconfig:option:`CONFIG_POSIX_API` to configure a set of POSIX features +that was overloaded and always increasing in size. * :kconfig:option:`CONFIG_POSIX_API` -* :kconfig:option:`CONFIG_PTHREAD_IPC` -.. note:: - Since the POSIX environment in Zephyr is fully configurable via :ref:`Kconfig`, - configurations that require modifying features should not be made if strict compliance is - required (POSIX-1.2017, section 2.1.3.1). +The option is now frozen, and can be considered equivalent to the following: + +* :kconfig:option:`CONFIG_POSIX_AEP_CHOICE_PSE51` +* :kconfig:option:`CONFIG_POSIX_FD_MGMT` +* :kconfig:option:`CONFIG_POSIX_MESSAGE_PASSING` +* :kconfig:option:`CONFIG_POSIX_NETWORKING` -.. - TODO: create Kconfig shortcuts for PSE51, PSE52, and PSE53 +However, :kconfig:option:`CONFIG_POSIX_API` should be considered legacy and should not be used for +new Zephyr applications. .. _IEEE: https://www.ieee.org/ .. _IEEE Computer Society: https://www.computer.org/ diff --git a/doc/services/retention/blinfo.rst b/doc/services/retention/blinfo.rst index 6f34b0f9a3564..6d18b1d8688d4 100644 --- a/doc/services/retention/blinfo.rst +++ b/doc/services/retention/blinfo.rst @@ -122,7 +122,7 @@ this mode: #include #include - #include + #include #include API Reference diff --git a/doc/services/rtio/index.rst b/doc/services/rtio/index.rst index df6e75d7702c8..cb33a3ffbeb6a 100644 --- a/doc/services/rtio/index.rst +++ b/doc/services/rtio/index.rst @@ -216,13 +216,3 @@ API Reference ************* .. doxygengroup:: rtio - -MPSC Lock-free Queue API -======================== - -.. doxygengroup:: rtio_mpsc - -SPSC Lock-free Queue API -======================== - -.. doxygengroup:: rtio_spsc diff --git a/doc/services/shell/index.rst b/doc/services/shell/index.rst index 504bef139fe01..8327031e197df 100644 --- a/doc/services/shell/index.rst +++ b/doc/services/shell/index.rst @@ -40,6 +40,11 @@ interaction is required. This module is a Unix-like shell with these features: enable :kconfig:option:`CONFIG_SHELL_MINIMAL` and selectively enable just the features you want. +.. _backends: + +Backends +******** + The module can be connected to any transport for command input and output. At this point, the following transport layers are implemented: @@ -49,10 +54,76 @@ At this point, the following transport layers are implemented: * Telnet * UART * USB +* Bluetooth LE (NUS) +* RPMSG * DUMMY - not a physical transport layer. +Telnet +====== + +Enabling :kconfig:option:`CONFIG_SHELL_BACKEND_TELNET` will allow users to use telnet +as a shell backend. Connecting to it can be done using PuTTY or any ``telnet`` client. +For example: + +.. code-block:: none + + telnet + +By default the telnet client won't handle telnet commands and configuration. Although +command support can be enabled with :kconfig:option:`CONFIG_SHELL_TELNET_SUPPORT_COMMAND`. +This will give the telnet client access to a very limited set of supported commands but +still can be turned on if needed. One of the command options it supports is the ``ECHO`` +option. This will allow the client to be in character mode (character at a time), +similar to a UART backend in that regard. This will make the client send a character +as soon as it is typed having the effect of increasing the network traffic +considerably. For that cost, it will enable the line editing, +`tab completion `_, and `history `_ +features of the shell. + +USB CDC ACM +=========== + +To configure Shell USB CDC ACM backend, simply add the snippet ``cdc-acm-console`` +to your build: + +.. code-block:: console + + west build -S cdc-acm-console [...] + +Details on the configuration settings are captured in the following files: + +- :zephyr_file:`snippets/cdc-acm-console/cdc-acm-console.conf`. +- :zephyr_file:`snippets/cdc-acm-console/cdc-acm-console.overlay`. + +Bluetooth LE (NUS) +================== + +To configure Bluetooth LE (NUS) backend, simply add the snippet ``nus-console`` +to your build: + +.. code-block:: console + + west build -S nus-console [...] + +Details on the configuration settings are captured in the following files: + +- :zephyr_file:`snippets/nus-console/nus-console.conf`. +- :zephyr_file:`snippets/nus-console/nus-console.overlay`. + +Segget RTT +========== + +To configure Segger RTT backend, add the following configurations to your build: + +- :kconfig:option:`CONFIG_USE_SEGGER_RTT` +- :kconfig:option:`CONFIG_SHELL_BACKEND_RTT` +- :kconfig:option:`CONFIG_SHELL_BACKEND_SERIAL` + +Details on additional configuration settings are captured in: +:zephyr_file:`samples/subsys/shell/shell_module/prj_minimal_rtt.conf`. + Connecting to Segger RTT via TCP (on macOS, for example) -======================================================== +-------------------------------------------------------- On macOS JLinkRTTClient won't let you enter input. Instead, please use following procedure: @@ -74,30 +145,6 @@ procedure: * Now you should have a network connection to RTT that will let you enter input to the shell. - -Telnet Backend -============== - -Enabling :kconfig:option:`CONFIG_SHELL_BACKEND_TELNET` will allow users to use telnet -as a shell backend. Connecting to it can be done using PuTTY or any ``telnet`` client. -For example: - -.. code-block:: none - - telnet - -By default the telnet client won't handle telnet commands and configuration. Although -command support can be enabled with :kconfig:option:`CONFIG_SHELL_TELNET_SUPPORT_COMMAND`. -This will give the telnet client access to a very limited set of supported commands but -still can be turned on if needed. One of the command options it supports is the ``ECHO`` -option. This will allow the client to be in character mode (character at a time), -similar to a UART backend in that regard. This will make the client send a character -as soon as it is typed having the effect of increasing the network traffic -considerably. For that cost, it will enable the line editing, -`tab completion `_, and `history `_ -features of the shell. - - Commands ******** @@ -112,6 +159,41 @@ types: during compile time. Created in the software module. +Commonly-used command groups +============================ + +The following list is a set of useful command groups and how to enable them: + +GPIO +---- + +- :kconfig:option:`CONFIG_GPIO` +- :kconfig:option:`CONFIG_GPIO_SHELL` + +I2C +--- + +- :kconfig:option:`CONFIG_I2C` +- :kconfig:option:`CONFIG_I2C_SHELL` + +Sensor +------ + +- :kconfig:option:`CONFIG_SENSOR` +- :kconfig:option:`CONFIG_SENSOR_SHELL` + +Flash +----- + +- :kconfig:option:`CONFIG_FLASH` +- :kconfig:option:`CONFIG_FLASH_SHELL` + +File-System +----------- + +- :kconfig:option:`CONFIG_FILE_SYSTEM` +- :kconfig:option:`CONFIG_FILE_SYSTEM_SHELL` + Creating commands ================= @@ -556,7 +638,7 @@ is accomplished by the ``getopt`` family functions. For this purpose shell supports the getopt and getopt_long libraries available in the FreeBSD project. This feature is activated by: -:kconfig:option:`CONFIG_GETOPT` set to ``y`` and :kconfig:option:`CONFIG_GETOPT_LONG` +:kconfig:option:`CONFIG_POSIX_C_LIB_EXT` set to ``y`` and :kconfig:option:`CONFIG_GETOPT_LONG` set to ``y``. This feature can be used in thread safe as well as non thread safe manner. @@ -671,18 +753,11 @@ while a script interfaces over channel 1. This allows interactive use of the shell through JLinkRTTViewer, while the log is written to file. -.. warning:: - Regardless of the channel selection, the RTT log backend must be explicitly - enabled using :kconfig:option:`CONFIG_LOG_BACKEND_RTT` set to ``y``, because it - defaults to ``n`` when the Shell RTT backend is also enabled using - :kconfig:option:`CONFIG_SHELL_BACKEND_RTT` being set to ``y``. +See `shell backends `_ for details on how to enable RTT as a Shell backend. Usage ***** -To create a new shell instance user needs to activate requested -backend using ``menuconfig``. - The following code shows a simple use case of this library: .. code-block:: c diff --git a/doc/services/smf/index.rst b/doc/services/smf/index.rst index 169ee507ec4b4..9b5ee62af7642 100644 --- a/doc/services/smf/index.rst +++ b/doc/services/smf/index.rst @@ -39,7 +39,7 @@ By default, a state can have no ancestor states, resulting in a flat state machine. But to enable the creation of a hierarchical state machine, the :kconfig:option:`CONFIG_SMF_ANCESTOR_SUPPORT` option must be enabled. -By default, the hierarchical state machine does not support initial transitions +By default, the hierarchical state machines do not support initial transitions to child states on entering a superstate. To enable them the :kconfig:option:`CONFIG_SMF_INITIAL_TRANSITION` option must be enabled. @@ -87,31 +87,29 @@ from parent state S0 to child state S2:: }; To set the initial state, the :c:func:`smf_set_initial` function should be -called. It has the following prototype: -``void smf_set_initial(smf_ctx *ctx, smf_state *state)`` +called. To transition from one state to another, the :c:func:`smf_set_state` -function is used and it has the following prototype: -``void smf_set_state(smf_ctx *ctx, smf_state *state)`` +function is used. .. note:: If :kconfig:option:`CONFIG_SMF_INITIAL_TRANSITION` is not set, :c:func:`smf_set_initial` and :c:func:`smf_set_state` function should not be passed a parent state as the parent state does not know which child state to transition to. Transitioning to a parent state is OK if an initial transition to a child state is defined. A well-formed - HSM will have initial transitions defined for all parent states. + HSM should have initial transitions defined for all parent states. -.. note:: While the state machine is running, smf_set_state should only be - called from the Entry and Run functions. Calling smf_set_state from the - Exit functions doesn't make sense and will generate a warning. +.. note:: While the state machine is running, :c:func:`smf_set_state` should + only be called from the Entry or Run function. Calling + :c:func:`smf_set_state` from Exit functions will generate a warning in the + log and no transition will occur. State Machine Execution ======================= To run the state machine, the :c:func:`smf_run_state` function should be called in some application dependent way. An application should cease calling -smf_run_state if it returns a non-zero value. The function has the following -prototype: ``int32_t smf_run_state(smf_ctx *ctx)`` +smf_run_state if it returns a non-zero value. Preventing Parent Run Actions ============================= @@ -124,13 +122,38 @@ State Machine Termination ========================= To terminate the state machine, the :c:func:`smf_set_terminate` function -should be called. It can be called from the entry, run, or exit action. The -function takes a non-zero user defined value that's returned by the -:c:func:`smf_run_state` function. The function has the following prototype: -``void smf_set_terminate(smf_ctx *ctx, int32_t val)`` +should be called. It can be called from the entry, run, or exit actions. The +function takes a non-zero user defined value that will be returned by the +:c:func:`smf_run_state` function. + +UML State Machines +================== + +SMF follows UML hierarchical state machine rules for transitions i.e., the +entry and exit actions of the least common ancestor are not executed on +transition, unless said transition is a transition to self. + +The UML Specification for StateMachines may be found in chapter 14 of the UML +specification available here: https://www.omg.org/spec/UML/ + +SMF breaks from UML rules in: + +1. Executing the actions associated with the transition within the context + of the source state, rather than after the exit actions are performed. +2. Only allowing external transitions to self, not to sub-states. A transition + from a superstate to a child state is treated as a local transition. +3. Prohibiting transitions using :c:func:`smf_set_state` in exit actions. + +SMF also does not provide any pseudostates except the Initial Pseudostate. +Terminate pseudostates can be modelled by calling :c:func:`smf_set_terminate` +from the entry action of a 'terminate' state. Orthogonal regions are modelled +by calling :c:func:`smf_run_state` for each region. + +State Machine Examples +====================== Flat State Machine Example -========================== +************************** This example turns the following state diagram into code using the SMF, where the initial state is S0. @@ -232,7 +255,7 @@ Code:: } Hierarchical State Machine Example -================================== +********************************** This example turns the following state diagram into code using the SMF, where S0 and S1 share a parent state and S0 is the initial state. @@ -342,17 +365,14 @@ When designing hierarchical state machines, the following should be considered: re-execute the ancestor\'s entry action or execute the exit action. For example, the parent_entry function is not called when transitioning from S0 to S1, nor is the parent_exit function called. - - Ancestor exit actions are executed after the sibling exit actions. For - example, the s1_exit function is called before the parent_exit function - is called. + - Ancestor exit actions are executed after the exit action of the current + state. For example, the s1_exit function is called before the parent_exit + function is called. - The parent_run function only executes if the child_run function does not call either :c:func:`smf_set_state` or :c:func:`smf_set_handled`. - - Transitions to self in super-states containing sub-states are not supported. - Transitions to self from the most-nested child state are supported and will - call the exit and entry function of the child state correctly. Event Driven State Machine Example -================================== +********************************** Events are not explicitly part of the State Machine Framework but an event driven state machine can be implemented using Zephyr :ref:`events`. @@ -499,47 +519,55 @@ Code:: } } -Hierarchical State Machine Example With Initial Transitions -=========================================================== +State Machine Example With Initial Transitions And Transition To Self +********************************************************************* + +:zephyr_file:`tests/lib/smf/src/test_lib_self_transition_smf.c` defines a state +machine for testing the initial transitions and transitions to self in a parent +state. The statechart for this test is below. -:zephyr_file:`tests/lib/smf/src/test_lib_initial_transitions_smf.c` defines -a state machine for testing initial transitions and :c:func:`smf_set_handled`. -The statechart for this test is below. .. graphviz:: - :caption: Test state machine for initial transitions and ``smf_set_handled`` + :caption: Test state machine for UML State Transitions digraph smf_hierarchical_initial { compound=true; node [style = rounded]; - smf_set_initial [shape=plaintext]; + "smf_set_initial()" [shape=plaintext fontname=Courier]; ab_init_state [shape = point]; STATE_A [shape = box]; STATE_B [shape = box]; STATE_C [shape = box]; STATE_D [shape = box]; + DC[shape=point height=0 width=0 label=<>] - subgraph cluster_ab { - label = "PARENT_AB"; + subgraph cluster_root { + label = "ROOT"; style = rounded; - ab_init_state -> STATE_A; - STATE_A -> STATE_B; - } - subgraph cluster_c { - label = "PARENT_C"; - style = rounded; - STATE_C -> STATE_C + subgraph cluster_ab { + label = "PARENT_AB"; + style = rounded; + ab_init_state -> STATE_A; + STATE_A -> STATE_B; + } + + subgraph cluster_c { + label = "PARENT_C"; + style = rounded; + STATE_B -> STATE_C [ltail=cluster_ab] + } + + STATE_C -> DC [ltail=cluster_c, dir=none]; + DC -> STATE_C [lhead=cluster_c]; + STATE_C -> STATE_D } - smf_set_initial -> STATE_A [lhead=cluster_ab] - STATE_B -> STATE_C - STATE_C -> STATE_D + "smf_set_initial()" -> STATE_A [lhead=cluster_ab] } - API Reference -************* +============= .. doxygengroup:: smf diff --git a/doc/services/storage/disk/access.rst b/doc/services/storage/disk/access.rst index db06e87e5c07e..7cc5fe12f5419 100644 --- a/doc/services/storage/disk/access.rst +++ b/doc/services/storage/disk/access.rst @@ -8,6 +8,35 @@ Overview The disk access API provides access to storage devices. +Initializing Disks +****************** + +Since many disk devices (such as SD cards) are hotpluggable, the disk access +API provides IOCTLs to initialize and de-initialize the disk. They are +as follows: + +* :c:macro:`DISK_IOCTL_CTRL_INIT`: Initialize the disk. Must be called before + additional I/O operations can be run on the disk device. Equivalent to + calling the legacy function :c:func:`disk_access_init`. + +* :c:macro:`DISK_IOCTL_CTRL_DEINIT`: De-initialize the disk. Once this IOCTL + is issued, the :c:macro:`DISK_IOCTL_CTRL_INIT` must be issued before + the disk can be used for addition I/O operations. + +Init/deinit IOCTL calls are balanced, so a disk will not de-initialize until +an equal number of deinit IOCTLs have been issued as init IOCTLs. + +It is also possible to force a disk de-initialization by passing a +pointer to a boolean set to ``true`` as a parameter to the +:c:macro:`DISK_IOCTL_CTRL_DEINIT` IOCTL. This is an unsafe operation which +each disk driver may handle differently, but it will always return +a value indicating success. + +Note that de-initializing a disk is a low level operation- typically the +de-initialization and initialization calls should be left to the filesystem +implementation, and the user application should not need to manually +de-initialize the disk and can instead call :c:func:`fs_unmount` + SD Card support *************** @@ -16,12 +45,9 @@ SD cards via SPI. These drivers use disk driver interface and a file system can access the SD cards via disk access API. Both standard and high-capacity SD cards are supported. -.. note:: The system does not support inserting or removing cards while the - system is running. The cards must be present at boot and must not be - removed. This may be fixed in future releases. - - FAT filesystems are not power safe so the filesystem may become - corrupted if power is lost or if the card is removed. +.. note:: FAT filesystems are not power safe so the filesystem may become + corrupted if power is lost or if the card is removed without unmounting + the filesystem SD Memory Card subsystem ======================== diff --git a/doc/services/storage/nvs/nvs.rst b/doc/services/storage/nvs/nvs.rst index 8278e49bf7128..c41f6ad83edd1 100644 --- a/doc/services/storage/nvs/nvs.rst +++ b/doc/services/storage/nvs/nvs.rst @@ -19,11 +19,16 @@ combination of these. Each element is stored in flash as metadata (8 byte) and data. The metadata is written in a table starting from the end of a nvs sector, the data is written one after the other from the start of the sector. The metadata consists -of: id, data offset in sector, data length, part (unused), and a CRC. The CRC is +of: id, data offset in sector, data length, part (unused), and a CRC. This CRC is only calculated over the metadata and only ensures that a write has been -completed. The actual data of the element is not protected by a CRC. It is -encouraged to include a CRC as part of the data and to take appropriate -corrective actions when the data CRC does not match its expected value. +completed. The actual data of the element can be protected by a different (and optional) +CRC-32. Use the :kconfig:option:`CONFIG_NVS_DATA_CRC` configuration item to enable +the data part CRC. +**Note:** the data CRC is checked only when the whole data of the element is read. +The data CRC is not checked for a partial read, as it is stored at the end of the +element data area. +**Note 2:** enabling the data CRC feature on a previously existing NVS content without +data CRC will make all existing data invalid. A write of data to nvs always starts with writing the data, followed by a write of the metadata. Data that is written in flash without metadata is ignored diff --git a/doc/services/tfm/overview.rst b/doc/services/tfm/overview.rst index ef71b53a113a0..8ecbd5946d864 100644 --- a/doc/services/tfm/overview.rst +++ b/doc/services/tfm/overview.rst @@ -8,7 +8,7 @@ It defines and implements an architecture and a set of software components that aim to address some of the main security concerns in IoT products. Zephyr RTOS has been PSA Certified since Zephyr 2.0.0 with TF-M 1.0, and -is currently integrated with TF-M 2.0.0. +is currently integrated with TF-M 2.1.0. What Does TF-M Offer? ********************* diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt index e1dbab7e1a201..7332e1e354181 100644 --- a/drivers/CMakeLists.txt +++ b/drivers/CMakeLists.txt @@ -31,6 +31,7 @@ add_subdirectory_ifdef(CONFIG_DAC dac) add_subdirectory_ifdef(CONFIG_DAI dai) add_subdirectory_ifdef(CONFIG_DISPLAY display) add_subdirectory_ifdef(CONFIG_DMA dma) +add_subdirectory_ifdef(CONFIG_DP_DRIVER dp) add_subdirectory_ifdef(CONFIG_EDAC edac) add_subdirectory_ifdef(CONFIG_EEPROM eeprom) add_subdirectory_ifdef(CONFIG_ENTROPY_GENERATOR entropy) diff --git a/drivers/Kconfig b/drivers/Kconfig index ac07add3c1f5c..b1aec9de129fe 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -24,6 +24,7 @@ source "drivers/dai/Kconfig" source "drivers/disk/Kconfig" source "drivers/display/Kconfig" source "drivers/dma/Kconfig" +source "drivers/dp/Kconfig" source "drivers/edac/Kconfig" source "drivers/eeprom/Kconfig" source "drivers/entropy/Kconfig" diff --git a/drivers/adc/CMakeLists.txt b/drivers/adc/CMakeLists.txt index ae0ebcb5b54cc..cd4006bccd77e 100644 --- a/drivers/adc/CMakeLists.txt +++ b/drivers/adc/CMakeLists.txt @@ -50,3 +50,4 @@ zephyr_library_sources_ifdef(CONFIG_ADC_AD559X adc_ad559x.c) zephyr_library_sources_ifdef(CONFIG_ADC_LTC2451 adc_ltc2451.c) zephyr_library_sources_ifdef(CONFIG_ADC_NUMAKER adc_numaker.c) zephyr_library_sources_ifdef(CONFIG_ADC_ENE_KB1200 adc_ene_kb1200.c) +zephyr_library_sources_ifdef(CONFIG_ADC_MCUX_GAU adc_mcux_gau_adc.c) diff --git a/drivers/adc/Kconfig.ad559x b/drivers/adc/Kconfig.ad559x index 7c5f65bb74558..70cb0474a0274 100644 --- a/drivers/adc/Kconfig.ad559x +++ b/drivers/adc/Kconfig.ad559x @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config ADC_AD559X bool "AD559x ADC driver" diff --git a/drivers/adc/Kconfig.esp32 b/drivers/adc/Kconfig.esp32 index 8fc8c9cabce07..604d0ad49edbe 100644 --- a/drivers/adc/Kconfig.esp32 +++ b/drivers/adc/Kconfig.esp32 @@ -8,3 +8,15 @@ config ADC_ESP32 depends on DT_HAS_ESPRESSIF_ESP32_ADC_ENABLED help Enable the driver implementation for the ESP32 ADC + +if ADC_ESP32 + +config ADC_ESP32_DMA + bool "ESP32 ADC DMA Support" + default n + depends on DT_HAS_ESPRESSIF_ESP32_GDMA_ENABLED + help + Enable the ADC DMA mode for ADC instances + that enable dma channels in their device tree node. + +endif diff --git a/drivers/adc/Kconfig.mcux b/drivers/adc/Kconfig.mcux index 725ec32c2c892..a61e7068e886c 100644 --- a/drivers/adc/Kconfig.mcux +++ b/drivers/adc/Kconfig.mcux @@ -41,6 +41,14 @@ config ADC_MCUX_ETC help Enable the MCUX ADC ETC driver. +config ADC_MCUX_GAU + bool "MCUX GAU ADC driver" + default y + depends on DT_HAS_NXP_GAU_ADC_ENABLED + select ADC_CONFIGURABLE_INPUTS + help + Enable the GAU ADC driver + if ADC_MCUX_ADC16 choice diff --git a/drivers/adc/adc_ad559x.c b/drivers/adc/adc_ad559x.c index 21ee1e62e18de..b0e7bb9581087 100644 --- a/drivers/adc/adc_ad559x.c +++ b/drivers/adc/adc_ad559x.c @@ -130,9 +130,6 @@ static int adc_ad559x_read_channel(const struct device *dev, uint8_t channel, ui if (ret < 0) { return ret; } - - *result = sys_get_be16((uint8_t *)&val); - } else { /* * Invalid data: @@ -145,31 +142,31 @@ static int adc_ad559x_read_channel(const struct device *dev, uint8_t channel, ui if (ret < 0) { return ret; } + } - val = sys_be16_to_cpu(val); + val = sys_be16_to_cpu(val); - /* - * Invalid data: - * See "ADC section" in "Theory of operation" chapter. - * Valid ADC result has MSB bit set to 0. - */ - if ((val & AD559X_ADC_RES_IND_BIT) != 0) { - return -EAGAIN; - } - - /* - * Invalid channel converted: - * See "ADC section" in "Theory of operation" chapter. - * Conversion result contains channel number which should match requested channel. - */ - conv_channel = FIELD_GET(AD559X_ADC_RES_CHAN_MASK, val); - if (conv_channel != channel) { - return -EIO; - } + /* + * Invalid data: + * See AD5592 "ADC section" in "Theory of operation" chapter. + * Valid ADC result has MSB bit set to 0. + */ + if ((val & AD559X_ADC_RES_IND_BIT) != 0) { + return -EAGAIN; + } - *result = val & AD559X_ADC_RES_VAL_MASK; + /* + * Invalid channel converted: + * See AD5592 "ADC section" in "Theory of operation" chapter. + * Conversion result contains channel number which should match requested channel. + */ + conv_channel = FIELD_GET(AD559X_ADC_RES_CHAN_MASK, val); + if (conv_channel != channel) { + return -EIO; } + *result = val & AD559X_ADC_RES_VAL_MASK; + return 0; } diff --git a/drivers/adc/adc_esp32.c b/drivers/adc/adc_esp32.c index 9b47fdf6bd723..4e45a3ea22e54 100644 --- a/drivers/adc/adc_esp32.c +++ b/drivers/adc/adc_esp32.c @@ -9,12 +9,25 @@ #include #include #include +#include #include +#include #include +#include +#include + +#if defined(CONFIG_ADC_ESP32_DMA) +#if !SOC_GDMA_SUPPORTED +#error "SoCs without GDMA peripheral are not supported!" +#endif +#include +#include +#endif #include #include #include +#include #include LOG_MODULE_REGISTER(adc_esp32, CONFIG_ADC_LOG_LEVEL); @@ -43,9 +56,16 @@ LOG_MODULE_REGISTER(adc_esp32, CONFIG_ADC_LOG_LEVEL); /* Default internal reference voltage */ #define ADC_ESP32_DEFAULT_VREF_INTERNAL (1100) +#define ADC_DMA_BUFFER_SIZE DMA_DESCRIPTOR_BUFFER_MAX_SIZE_4B_ALIGNED + struct adc_esp32_conf { adc_unit_t unit; uint8_t channel_count; +#if defined(CONFIG_ADC_ESP32_DMA) + const struct device *gpio_port; + const struct device *dma_dev; + uint8_t dma_channel; +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ }; struct adc_esp32_data { @@ -54,8 +74,12 @@ struct adc_esp32_data { esp_adc_cal_characteristics_t chars[SOC_ADC_MAX_CHANNEL_NUM]; uint16_t meas_ref_internal; uint16_t *buffer; - uint16_t *buffer_repeat; bool calibrate; +#if defined(CONFIG_ADC_ESP32_DMA) + adc_hal_dma_ctx_t adc_hal_dma_ctx; + uint8_t *dma_buffer; + struct k_sem dma_conv_wait_lock; +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ }; /* Convert zephyr,gain property to the ESP32 attenuation */ @@ -80,6 +104,7 @@ static inline int gain_to_atten(enum adc_gain gain, adc_atten_t *atten) return 0; } +#if !defined(CONFIG_ADC_ESP32_DMA) /* Convert voltage by inverted attenuation to support zephyr gain values */ static void atten_to_gain(adc_atten_t atten, uint32_t *val_mv) { @@ -101,6 +126,7 @@ static void atten_to_gain(adc_atten_t atten, uint32_t *val_mv) break; } } +#endif /* !defined(CONFIG_ADC_ESP32_DMA) */ static bool adc_calibration_init(const struct device *dev) { @@ -120,9 +146,229 @@ static bool adc_calibration_init(const struct device *dev) LOG_ERR("Invalid arg"); break; } + return false; } +#if defined(CONFIG_ADC_ESP32_DMA) + +static void IRAM_ATTR adc_esp32_dma_conv_done(const struct device *dma_dev, void *user_data, + uint32_t channel, int status) +{ + ARG_UNUSED(dma_dev); + ARG_UNUSED(status); + + const struct device *dev = user_data; + struct adc_esp32_data *data = dev->data; + + k_sem_give(&data->dma_conv_wait_lock); +} + +static int adc_esp32_dma_start(const struct device *dev, uint8_t *buf, size_t len) +{ + const struct adc_esp32_conf *conf = dev->config; + struct adc_esp32_data *data = dev->data; + + int err = 0; + struct dma_config dma_cfg = {0}; + struct dma_status dma_status = {0}; + struct dma_block_config dma_blk = {0}; + + err = dma_get_status(conf->dma_dev, conf->dma_channel, &dma_status); + if (err) { + LOG_ERR("Unable to get dma channel[%u] status (%d)", + (unsigned int)conf->dma_channel, err); + return -EINVAL; + } + + if (dma_status.busy) { + LOG_ERR("dma channel[%u] is busy!", (unsigned int)conf->dma_channel); + return -EBUSY; + } + + unsigned int key = irq_lock(); + + dma_cfg.channel_direction = PERIPHERAL_TO_MEMORY; + dma_cfg.dma_callback = adc_esp32_dma_conv_done; + dma_cfg.user_data = (void *)dev; + dma_cfg.dma_slot = ESP_GDMA_TRIG_PERIPH_ADC0; + dma_cfg.block_count = 1; + dma_cfg.head_block = &dma_blk; + dma_blk.block_size = len; + dma_blk.dest_address = (uint32_t)buf; + + err = dma_config(conf->dma_dev, conf->dma_channel, &dma_cfg); + if (err) { + LOG_ERR("Error configuring dma (%d)", err); + goto unlock; + } + + err = dma_start(conf->dma_dev, conf->dma_channel); + if (err) { + LOG_ERR("Error starting dma (%d)", err); + goto unlock; + } + +unlock: + irq_unlock(key); + return err; +} + +static int adc_esp32_dma_stop(const struct device *dev) +{ + const struct adc_esp32_conf *conf = dev->config; + unsigned int key = irq_lock(); + int err = 0; + + err = dma_stop(conf->dma_dev, conf->dma_channel); + if (err) { + LOG_ERR("Error stopping dma (%d)", err); + } + + irq_unlock(key); + return err; +} + +static int adc_esp32_fill_digi_pattern(const struct device *dev, const struct adc_sequence *seq, + void *pattern_config, uint32_t *pattern_len, uint32_t *unit_attenuation) +{ + const struct adc_esp32_conf *conf = dev->config; + struct adc_esp32_data *data = dev->data; + + adc_digi_pattern_config_t *adc_digi_pattern_config = + (adc_digi_pattern_config_t *)pattern_config; + const uint32_t unit_atten_uninit = 999; + uint32_t channel_mask = 1, channels_copy = seq->channels; + + *pattern_len = 0; + *unit_attenuation = unit_atten_uninit; + for (uint8_t channel_id = 0; channel_id < conf->channel_count; channel_id++) { + if (channels_copy & channel_mask) { + if (*unit_attenuation == unit_atten_uninit) { + *unit_attenuation = data->attenuation[channel_id]; + } else if (*unit_attenuation != data->attenuation[channel_id]) { + LOG_ERR("Channel[%u] attenuation different of unit[%u] attenuation", + (unsigned int)channel_id, (unsigned int)conf->unit); + return -EINVAL; + } + + adc_digi_pattern_config->atten = data->attenuation[channel_id]; + adc_digi_pattern_config->channel = channel_id; + adc_digi_pattern_config->unit = conf->unit; + adc_digi_pattern_config->bit_width = seq->resolution; + adc_digi_pattern_config++; + + *pattern_len += 1; + if (*pattern_len > SOC_ADC_PATT_LEN_MAX) { + LOG_ERR("Max pattern len is %d", SOC_ADC_PATT_LEN_MAX); + return -EINVAL; + } + + channels_copy &= ~channel_mask; + if (!channels_copy) { + break; + } + } + channel_mask <<= 1; + } + + return 0; +} + +static void adc_esp32_digi_start(const struct device *dev, void *pattern_config, + uint32_t pattern_len, uint32_t number_of_samplings, + uint32_t sample_freq_hz, uint32_t unit_attenuation) +{ + const struct adc_esp32_conf *conf = dev->config; + struct adc_esp32_data *data = dev->data; + + sar_periph_ctrl_adc_continuous_power_acquire(); + adc_lock_acquire(conf->unit); + +#if SOC_ADC_CALIBRATION_V1_SUPPORTED + adc_set_hw_calibration_code(conf->unit, unit_attenuation); +#endif /* SOC_ADC_CALIBRATION_V1_SUPPORTED */ + +#if SOC_ADC_ARBITER_SUPPORTED + if (conf->unit == ADC_UNIT_2) { + adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT(); + + adc_hal_arbiter_config(&config); + } +#endif /* SOC_ADC_ARBITER_SUPPORTED */ + + adc_hal_digi_ctrlr_cfg_t adc_hal_digi_ctrlr_cfg; + soc_module_clk_t clk_src = ADC_DIGI_CLK_SRC_DEFAULT; + uint32_t clk_src_freq_hz = 0; + + esp_clk_tree_src_get_freq_hz(clk_src, ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, + &clk_src_freq_hz); + + adc_hal_digi_ctrlr_cfg.conv_mode = + (conf->unit == ADC_UNIT_1)?ADC_CONV_SINGLE_UNIT_1:ADC_CONV_SINGLE_UNIT_2; + adc_hal_digi_ctrlr_cfg.clk_src = clk_src; + adc_hal_digi_ctrlr_cfg.clk_src_freq_hz = clk_src_freq_hz; + adc_hal_digi_ctrlr_cfg.sample_freq_hz = sample_freq_hz; + adc_hal_digi_ctrlr_cfg.adc_pattern = (adc_digi_pattern_config_t *)pattern_config; + adc_hal_digi_ctrlr_cfg.adc_pattern_len = pattern_len; + + uint32_t number_of_adc_digi_samples = number_of_samplings * pattern_len; + + adc_hal_dma_config_t adc_hal_dma_config = { + .dev = (void *)GDMA_LL_GET_HW(0), + .eof_desc_num = 1, + .eof_step = 1, + .dma_chan = conf->dma_channel, + .eof_num = number_of_adc_digi_samples, + }; + + adc_hal_dma_ctx_config(&data->adc_hal_dma_ctx, &adc_hal_dma_config); + + adc_hal_set_controller(conf->unit, ADC_HAL_CONTINUOUS_READ_MODE); + adc_hal_digi_init(&data->adc_hal_dma_ctx); + adc_hal_digi_controller_config(&data->adc_hal_dma_ctx, &adc_hal_digi_ctrlr_cfg); + adc_hal_digi_start(&data->adc_hal_dma_ctx, data->dma_buffer); +} + +static void adc_esp32_digi_stop(const struct device *dev) +{ + const struct adc_esp32_conf *conf = dev->config; + struct adc_esp32_data *data = dev->data; + + adc_hal_digi_dis_intr(&data->adc_hal_dma_ctx, ADC_HAL_DMA_INTR_MASK); + adc_hal_digi_clr_intr(&data->adc_hal_dma_ctx, ADC_HAL_DMA_INTR_MASK); + adc_hal_digi_stop(&data->adc_hal_dma_ctx); + adc_hal_digi_deinit(&data->adc_hal_dma_ctx); + adc_lock_release(conf->unit); + sar_periph_ctrl_adc_continuous_power_release(); +} + +static void adc_esp32_fill_seq_buffer(const void *seq_buffer, const void *dma_buffer, + uint32_t number_of_samples) +{ + uint16_t *sample = (uint16_t *)seq_buffer; + adc_digi_output_data_t *digi_data = (adc_digi_output_data_t *)dma_buffer; + + for (uint32_t k = 0; k < number_of_samples; k++) { + *sample++ = (uint16_t)(digi_data++)->type2.data; + } +} + +static int adc_esp32_wait_for_dma_conv_done(const struct device *dev) +{ + struct adc_esp32_data *data = dev->data; + int err = 0; + + err = k_sem_take(&data->dma_conv_wait_lock, K_FOREVER); + if (err) { + LOG_ERR("Error taking dma_conv_wait_lock (%d)", err); + } + + return err; +} + +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ + static int adc_esp32_read(const struct device *dev, const struct adc_sequence *seq) { const struct adc_esp32_conf *conf = dev->config; @@ -137,10 +383,12 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s return -ENOMEM; } +#if !defined(CONFIG_ADC_ESP32_DMA) if (seq->channels > BIT(channel_id)) { LOG_ERR("Multi-channel readings not supported"); return -ENOTSUP; } +#endif /* !defined(CONFIG_ADC_ESP32_DMA) */ if (seq->options) { if (seq->options->extra_samplings) { @@ -148,10 +396,12 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s return -ENOTSUP; } +#if !defined(CONFIG_ADC_ESP32_DMA) if (seq->options->interval_us) { LOG_ERR("Interval between samplings not supported"); return -ENOTSUP; } +#endif /* !defined(CONFIG_ADC_ESP32_DMA) */ } if (INVALID_RESOLUTION(seq->resolution)) { @@ -176,6 +426,7 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s adc_set_data_width(conf->unit, WIDTH_MASK(data->resolution[channel_id])); #endif /* CONFIG_SOC_SERIES_ESP32C3 */ +#if !defined(CONFIG_ADC_ESP32_DMA) /* Read raw value */ if (conf->unit == ADC_UNIT_1) { reading = adc1_get_raw(channel_id); @@ -216,6 +467,74 @@ static int adc_esp32_read(const struct device *dev, const struct adc_sequence *s data->buffer = (uint16_t *) seq->buffer; data->buffer[0] = cal; +#else /* !defined(CONFIG_ADC_ESP32_DMA) */ + + int err = 0; + uint32_t adc_pattern_len, unit_attenuation; + adc_digi_pattern_config_t adc_digi_pattern_config[SOC_ADC_MAX_CHANNEL_NUM]; + + err = adc_esp32_fill_digi_pattern(dev, seq, &adc_digi_pattern_config, + &adc_pattern_len, &unit_attenuation); + if (err || adc_pattern_len == 0) { + return -EINVAL; + } + + const struct adc_sequence_options *options = seq->options; + uint32_t sample_freq_hz = SOC_ADC_SAMPLE_FREQ_THRES_HIGH, + number_of_samplings = 1; + + if (options != NULL) { + number_of_samplings = seq->buffer_size / (adc_pattern_len * sizeof(uint16_t)); + + if (options->interval_us) { + sample_freq_hz = MHZ(1) / options->interval_us; + } + } + + if (!number_of_samplings) { + LOG_ERR("buffer_size insufficient to store at least one set of samples!"); + return -EINVAL; + } + + if (sample_freq_hz < SOC_ADC_SAMPLE_FREQ_THRES_LOW || + sample_freq_hz > SOC_ADC_SAMPLE_FREQ_THRES_HIGH) { + LOG_ERR("ADC sampling frequency out of range: %uHz", sample_freq_hz); + return -EINVAL; + } + + uint32_t number_of_adc_samples = number_of_samplings * adc_pattern_len; + uint32_t number_of_adc_dma_data_bytes = + number_of_adc_samples * SOC_ADC_DIGI_DATA_BYTES_PER_CONV; + + if (number_of_adc_dma_data_bytes > ADC_DMA_BUFFER_SIZE) { + LOG_ERR("dma buffer size insufficient to store a complete sequence!"); + return -EINVAL; + } + + err = adc_esp32_dma_start(dev, data->dma_buffer, number_of_adc_dma_data_bytes); + if (err) { + return err; + } + + adc_esp32_digi_start(dev, &adc_digi_pattern_config, adc_pattern_len, number_of_samplings, + sample_freq_hz, unit_attenuation); + + err = adc_esp32_wait_for_dma_conv_done(dev); + if (err) { + return err; + } + + adc_esp32_digi_stop(dev); + + err = adc_esp32_dma_stop(dev); + if (err) { + return err; + } + + adc_esp32_fill_seq_buffer(seq->buffer, data->dma_buffer, number_of_adc_samples); + +#endif /* !defined(CONFIG_ADC_ESP32_DMA) */ + return 0; } @@ -284,6 +603,34 @@ static int adc_esp32_channel_setup(const struct device *dev, const struct adc_ch LOG_DBG("Using ADC calibration method %d", cal); } +#if defined(CONFIG_ADC_ESP32_DMA) + + if (!SOC_ADC_DIG_SUPPORTED_UNIT(conf->unit)) { + LOG_ERR("ADC2 dma mode is no longer supported, please use ADC1!"); + return -EINVAL; + } + + int io_num = adc_channel_io_map[conf->unit][cfg->channel_id]; + + if (io_num < 0) { + LOG_ERR("Channel %u not supported!", cfg->channel_id); + return -ENOTSUP; + } + + struct gpio_dt_spec gpio = { + .port = conf->gpio_port, + .dt_flags = 0, + .pin = io_num, + }; + + err = gpio_pin_configure_dt(&gpio, GPIO_DISCONNECTED); + if (err) { + LOG_ERR("Error disconnecting io (%d)", io_num); + return err; + } + +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ + return 0; } @@ -291,9 +638,41 @@ static int adc_esp32_init(const struct device *dev) { struct adc_esp32_data *data = (struct adc_esp32_data *) dev->data; +#if defined(CONFIG_ADC_ESP32_DMA) + struct adc_esp32_conf *conf = (struct adc_esp32_conf *) dev->config; + + if (!device_is_ready(conf->gpio_port)) { + LOG_ERR("gpio0 port not ready"); + return -ENODEV; + } + + if (k_sem_init(&data->dma_conv_wait_lock, 0, 1)) { + LOG_ERR("dma_conv_wait_lock initialization failed!"); + return -EINVAL; + } + + data->adc_hal_dma_ctx.rx_desc = k_aligned_alloc(sizeof(uint32_t), + sizeof(dma_descriptor_t)); + if (!data->adc_hal_dma_ctx.rx_desc) { + LOG_ERR("rx_desc allocation failed!"); + return -ENOMEM; + } + LOG_DBG("rx_desc = 0x%08X", (unsigned int)data->adc_hal_dma_ctx.rx_desc); + + data->dma_buffer = k_aligned_alloc(sizeof(uint32_t), ADC_DMA_BUFFER_SIZE); + if (!data->dma_buffer) { + LOG_ERR("dma buffer allocation failed!"); + k_free(data->adc_hal_dma_ctx.rx_desc); + return -ENOMEM; + } + LOG_DBG("data->dma_buffer = 0x%08X", (unsigned int)data->dma_buffer); + +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ + for (uint8_t i = 0; i < ARRAY_SIZE(data->resolution); i++) { data->resolution[i] = ADC_RESOLUTION_MAX; } + for (uint8_t i = 0; i < ARRAY_SIZE(data->attenuation); i++) { data->attenuation[i] = ADC_ATTEN_DB_0; } @@ -316,11 +695,30 @@ static const struct adc_driver_api api_esp32_driver_api = { .ref_internal = ADC_ESP32_DEFAULT_VREF_INTERNAL, }; +#if defined(CONFIG_ADC_ESP32_DMA) + +#define ADC_ESP32_CONF_GPIO_PORT_INIT .gpio_port = DEVICE_DT_GET(DT_NODELABEL(gpio0)), + +#define ADC_ESP32_CONF_DMA_INIT(n) .dma_dev = COND_CODE_1(DT_INST_NODE_HAS_PROP(n, dmas), \ + (DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_IDX(n, 0))), \ + (NULL)), \ + .dma_channel = COND_CODE_1(DT_INST_NODE_HAS_PROP(n, dmas), \ + (DT_INST_DMAS_CELL_BY_IDX(n, 0, channel)), \ + (0xff)), +#else + +#define ADC_ESP32_CONF_GPIO_PORT_INIT +#define ADC_ESP32_CONF_DMA_INIT(inst) + +#endif /* defined(CONFIG_ADC_ESP32_DMA) */ + #define ESP32_ADC_INIT(inst) \ \ static const struct adc_esp32_conf adc_esp32_conf_##inst = { \ .unit = DT_PROP(DT_DRV_INST(inst), unit) - 1, \ .channel_count = DT_PROP(DT_DRV_INST(inst), channel_count), \ + ADC_ESP32_CONF_GPIO_PORT_INIT \ + ADC_ESP32_CONF_DMA_INIT(inst) \ }; \ \ static struct adc_esp32_data adc_esp32_data_##inst = { \ diff --git a/drivers/adc/adc_handlers.c b/drivers/adc/adc_handlers.c index 2b00c2d95a9fc..c2f0fd4aef2fc 100644 --- a/drivers/adc/adc_handlers.c +++ b/drivers/adc/adc_handlers.c @@ -21,7 +21,7 @@ static inline int z_vrfy_adc_channel_setup(const struct device *dev, return z_impl_adc_channel_setup((const struct device *)dev, &channel_cfg); } -#include +#include static bool copy_sequence(struct adc_sequence *dst, struct adc_sequence_options *options, @@ -66,7 +66,7 @@ static inline int z_vrfy_adc_read(const struct device *dev, return z_impl_adc_read((const struct device *)dev, &sequence); } -#include +#include #ifdef CONFIG_ADC_ASYNC static inline int z_vrfy_adc_read_async(const struct device *dev, @@ -89,5 +89,5 @@ static inline int z_vrfy_adc_read_async(const struct device *dev, return z_impl_adc_read_async((const struct device *)dev, &sequence, (struct k_poll_signal *)async); } -#include +#include #endif /* CONFIG_ADC_ASYNC */ diff --git a/drivers/adc/adc_mcux_gau_adc.c b/drivers/adc/adc_mcux_gau_adc.c new file mode 100644 index 0000000000000..137c33feeaf47 --- /dev/null +++ b/drivers/adc/adc_mcux_gau_adc.c @@ -0,0 +1,392 @@ +/* + * Copyright 2022-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_gau_adc + +#include +#include +#include +#include + +LOG_MODULE_REGISTER(adc_mcux_gau_adc, CONFIG_ADC_LOG_LEVEL); + +#define ADC_CONTEXT_USES_KERNEL_TIMER +#include "adc_context.h" + +#include + +#define NUM_ADC_CHANNELS 16 + +struct mcux_gau_adc_config { + ADC_Type *base; + void (*irq_config_func)(const struct device *dev); + adc_clock_divider_t clock_div; + adc_analog_portion_power_mode_t power_mode; + bool input_gain_buffer; + adc_calibration_ref_t cal_volt; +}; + +struct mcux_gau_adc_data { + const struct device *dev; + struct adc_context ctx; + adc_channel_source_t channel_sources[NUM_ADC_CHANNELS]; + uint8_t scan_length; + uint16_t *results; + size_t results_length; + uint16_t *repeat; + struct k_work read_samples_work; +}; + +static int mcux_gau_adc_channel_setup(const struct device *dev, + const struct adc_channel_cfg *channel_cfg) +{ + const struct mcux_gau_adc_config *config = dev->config; + struct mcux_gau_adc_data *data = dev->data; + ADC_Type *base = config->base; + uint8_t channel_id = channel_cfg->channel_id; + uint8_t source_channel = channel_cfg->input_positive; + uint32_t tmp_reg; + + if (channel_cfg->differential) { + LOG_ERR("Differential channels not yet supported"); + return -ENOTSUP; + } + + if (channel_id >= NUM_ADC_CHANNELS) { + LOG_ERR("ADC does not support more than %d channels", NUM_ADC_CHANNELS); + return -ENOTSUP; + } + + if (source_channel > 12 && source_channel != 15) { + LOG_ERR("Invalid source channel"); + return -EINVAL; + } + + /* Set Acquisition/Warmup time */ + tmp_reg = base->ADC_REG_INTERVAL; + base->ADC_REG_INTERVAL &= ~ADC_ADC_REG_INTERVAL_WARMUP_TIME_MASK; + base->ADC_REG_INTERVAL &= ~ADC_ADC_REG_INTERVAL_BYPASS_WARMUP_MASK; + if (channel_cfg->acquisition_time == 0) { + base->ADC_REG_INTERVAL |= ADC_ADC_REG_INTERVAL_BYPASS_WARMUP_MASK; + } else if (channel_cfg->acquisition_time <= 32) { + base->ADC_REG_INTERVAL |= + ADC_ADC_REG_INTERVAL_WARMUP_TIME(channel_cfg->acquisition_time - 1); + } else { + LOG_ERR("Invalid acquisition time requested of ADC"); + return -EINVAL; + } + /* If user changed the warmup time, warn */ + if (base->ADC_REG_INTERVAL != tmp_reg) { + LOG_WRN("Acquisition/Warmup time is global to entire ADC peripheral, " + "i.e. channel_setup will override this property for all previous channels."); + } + + /* Set Input Gain */ + tmp_reg = base->ADC_REG_ANA; + base->ADC_REG_ANA &= ~ADC_ADC_REG_ANA_INBUF_GAIN_MASK; + if (channel_cfg->gain == ADC_GAIN_1) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_INBUF_GAIN(kADC_InputGain1); + } else if (channel_cfg->gain == ADC_GAIN_1_2) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_INBUF_GAIN(kADC_InputGain0P5); + } else if (channel_cfg->gain == ADC_GAIN_2) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_INBUF_GAIN(kADC_InputGain2); + } else { + LOG_ERR("Invalid gain"); + return -EINVAL; + } + /* If user changed the gain, warn */ + if (base->ADC_REG_ANA != tmp_reg) { + LOG_WRN("Input gain is global to entire ADC peripheral, " + "i.e. channel_setup will override this property for all previous channels."); + } + + /* Set Reference voltage of ADC */ + tmp_reg = base->ADC_REG_ANA; + base->ADC_REG_ANA &= ~ADC_ADC_REG_ANA_VREF_SEL_MASK; + if (channel_cfg->reference == ADC_REF_INTERNAL) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_VREF_SEL(kADC_Vref1P2V); + } else if (channel_cfg->reference == ADC_REF_EXTERNAL0) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_VREF_SEL(kADC_VrefExternal); + } else if (channel_cfg->reference == ADC_REF_VDD_1) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_VREF_SEL(kADC_Vref1P8V); + } else { + LOG_ERR("Vref not supported"); + return -ENOTSUP; + } + /* if user changed the reference voltage, warn */ + if (base->ADC_REG_ANA != tmp_reg) { + LOG_WRN("Reference voltage is global to entire ADC peripheral, " + "i.e. channel_setup will override this property for all previous channels."); + } + + data->channel_sources[channel_id] = source_channel; + + return 0; +} + +static void mcux_gau_adc_read_samples(struct k_work *work) +{ + struct mcux_gau_adc_data *data = + CONTAINER_OF(work, struct mcux_gau_adc_data, + read_samples_work); + const struct device *dev = data->dev; + const struct mcux_gau_adc_config *config = dev->config; + ADC_Type *base = config->base; + + /* using this variable to prevent buffer overflow */ + size_t length = data->results_length; + + while ((ADC_GetFifoDataCount(base) > 0) && (--length > 0)) { + *(data->results++) = (uint16_t)ADC_GetConversionResult(base); + } + + adc_context_on_sampling_done(&data->ctx, dev); +} + + +static void mcux_gau_adc_isr(const struct device *dev) +{ + const struct mcux_gau_adc_config *config = dev->config; + struct mcux_gau_adc_data *data = dev->data; + ADC_Type *base = config->base; + + if (ADC_GetStatusFlags(base) & kADC_DataReadyInterruptFlag) { + /* Clear flag to avoid infinite interrupt */ + ADC_ClearStatusFlags(base, kADC_DataReadyInterruptFlag); + + /* offload and do not block during irq */ + k_work_submit(&data->read_samples_work); + } else { + LOG_ERR("ADC received unimplemented interrupt"); + } +} + +static void adc_context_start_sampling(struct adc_context *ctx) +{ + struct mcux_gau_adc_data *data = + CONTAINER_OF(ctx, struct mcux_gau_adc_data, ctx); + const struct mcux_gau_adc_config *config = data->dev->config; + ADC_Type *base = config->base; + + ADC_StopConversion(base); + ADC_DoSoftwareTrigger(base); +} + +static void adc_context_update_buffer_pointer(struct adc_context *ctx, + bool repeat_sampling) +{ + struct mcux_gau_adc_data *data = + CONTAINER_OF(ctx, struct mcux_gau_adc_data, ctx); + + if (repeat_sampling) { + data->results = data->repeat; + } +} + +static int mcux_gau_adc_do_read(const struct device *dev, + const struct adc_sequence *sequence) +{ + const struct mcux_gau_adc_config *config = dev->config; + ADC_Type *base = config->base; + struct mcux_gau_adc_data *data = dev->data; + uint8_t num_channels = 0; + + /* if user selected channel >= NUM_ADC_CHANNELS that is invalid */ + if (sequence->channels & (0xFFFF << NUM_ADC_CHANNELS)) { + LOG_ERR("Invalid channels selected for sequence"); + return -EINVAL; + } + + /* Count channels */ + for (int i = 0; i < NUM_ADC_CHANNELS; i++) { + num_channels += ((sequence->channels & (0x1 << i)) ? 1 : 0); + } + + /* Buffer must hold (number of samples per channel) * (number of channels) samples */ + if ((sequence->options != NULL && sequence->buffer_size < + ((1 + sequence->options->extra_samplings) * num_channels)) || + (sequence->options == NULL && sequence->buffer_size < num_channels)) { + LOG_ERR("Buffer size too small"); + return -ENOMEM; + } + + /* Set scan length in data struct for isr to understand & set scan length register */ + base->ADC_REG_CONFIG &= ~ADC_ADC_REG_CONFIG_SCAN_LENGTH_MASK; + data->scan_length = num_channels; + /* Register Value is 1 less than what it represents */ + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_SCAN_LENGTH(data->scan_length - 1); + + /* Set up scan channels */ + for (int channel = 0; channel < NUM_ADC_CHANNELS; channel++) { + if (sequence->channels & (0x1 << channel)) { + ADC_SetScanChannel(base, + data->scan_length - num_channels--, + data->channel_sources[channel]); + } + } + + /* Set resolution of ADC */ + base->ADC_REG_ANA &= ~ADC_ADC_REG_ANA_RES_SEL_MASK; + /* odd numbers are for differential channels */ + if (sequence->resolution == 12 || sequence->resolution == 11) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_RES_SEL(kADC_Resolution12Bit); + } else if (sequence->resolution == 14 || sequence->resolution == 13) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_RES_SEL(kADC_Resolution14Bit); + } else if (sequence->resolution == 16 || sequence->resolution == 15) { + base->ADC_REG_ANA |= ADC_ADC_REG_ANA_RES_SEL(kADC_Resolution16Bit); + } else { + LOG_ERR("Invalid resolution"); + return -EINVAL; + } + + /* Set oversampling */ + base->ADC_REG_CONFIG &= ~ADC_ADC_REG_CONFIG_AVG_SEL_MASK; + if (sequence->oversampling == 0) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_AverageNone); + } else if (sequence->oversampling == 1) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_Average2); + } else if (sequence->oversampling == 2) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_Average4); + } else if (sequence->oversampling == 3) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_Average8); + } else if (sequence->oversampling == 4) { + base->ADC_REG_CONFIG |= ADC_ADC_REG_CONFIG_AVG_SEL(kADC_Average16); + } else { + LOG_ERR("Invalid oversampling setting"); + return -EINVAL; + } + + /* Calibrate if requested */ + if (sequence->calibrate) { + if (ADC_DoAutoCalibration(base, config->cal_volt)) { + LOG_WRN("Calibration of ADC failed!"); + } + } + + data->results = sequence->buffer; + data->results_length = sequence->buffer_size; + data->repeat = sequence->buffer; + + adc_context_start_read(&data->ctx, sequence); + + return adc_context_wait_for_completion(&data->ctx); +} + +static int mcux_gau_adc_read(const struct device *dev, + const struct adc_sequence *sequence) +{ + struct mcux_gau_adc_data *data = dev->data; + int error; + + adc_context_lock(&data->ctx, false, NULL); + error = mcux_gau_adc_do_read(dev, sequence); + adc_context_release(&data->ctx, error); + return error; +} + +#ifdef CONFIG_ADC_ASYNC +static int mcux_gau_adc_read_async(const struct device *dev, + const struct adc_sequence *sequence, + struct k_poll_signal *async) +{ + struct mcux_gau_adc_data *data = dev->data; + int error; + + adc_context_lock(&data->ctx, true, async); + error = mcux_gau_adc_do_read(dev, sequence); + adc_context_release(&data->ctx, error); + return error; +} +#endif + + +static int mcux_gau_adc_init(const struct device *dev) +{ + const struct mcux_gau_adc_config *config = dev->config; + struct mcux_gau_adc_data *data = dev->data; + ADC_Type *base = config->base; + adc_config_t adc_config; + + data->dev = dev; + + LOG_DBG("Initializing ADC"); + + ADC_GetDefaultConfig(&adc_config); + + /* DT configs */ + adc_config.clockDivider = config->clock_div; + adc_config.powerMode = config->power_mode; + adc_config.enableInputGainBuffer = config->input_gain_buffer; + adc_config.triggerSource = kADC_TriggerSourceSoftware; + + adc_config.inputMode = kADC_InputSingleEnded; + /* One shot meets the needs of the current zephyr adc context/api */ + adc_config.conversionMode = kADC_ConversionOneShot; + /* since using one shot mode, just interrupt on one sample (agnostic to # channels) */ + adc_config.fifoThreshold = kADC_FifoThresholdData1; + /* 32 bit width not supported in this driver; zephyr seems to use 16 bit */ + adc_config.resultWidth = kADC_ResultWidth16; + adc_config.enableDMA = false; + adc_config.enableADC = true; + + ADC_Init(base, &adc_config); + + if (ADC_DoAutoCalibration(base, config->cal_volt)) { + LOG_WRN("Calibration of ADC failed!"); + } + + ADC_ClearStatusFlags(base, kADC_DataReadyInterruptFlag); + + config->irq_config_func(dev); + ADC_EnableInterrupts(base, kADC_DataReadyInterruptEnable); + + k_work_init(&data->read_samples_work, &mcux_gau_adc_read_samples); + + adc_context_init(&data->ctx); + adc_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static const struct adc_driver_api mcux_gau_adc_driver_api = { + .channel_setup = mcux_gau_adc_channel_setup, + .read = mcux_gau_adc_read, +#ifdef CONFIG_ADC_ASYNC + .read_async = mcux_gau_adc_read_async, +#endif + .ref_internal = 1200, +}; + + +#define GAU_ADC_MCUX_INIT(n) \ + \ + static void mcux_gau_adc_config_func_##n(const struct device *dev); \ + \ + static const struct mcux_gau_adc_config mcux_gau_adc_config_##n = { \ + .base = (ADC_Type *)DT_INST_REG_ADDR(n), \ + .irq_config_func = mcux_gau_adc_config_func_##n, \ + /* Minus one because DT starts at 1, HAL enum starts at 0 */ \ + .clock_div = DT_INST_PROP(n, nxp_clock_divider) - 1, \ + .power_mode = DT_INST_ENUM_IDX(n, nxp_power_mode), \ + .input_gain_buffer = DT_INST_PROP(n, nxp_input_buffer), \ + .cal_volt = DT_INST_ENUM_IDX(n, nxp_calibration_voltage), \ + }; \ + \ + static struct mcux_gau_adc_data mcux_gau_adc_data_##n = {0}; \ + \ + DEVICE_DT_INST_DEFINE(n, &mcux_gau_adc_init, NULL, \ + &mcux_gau_adc_data_##n, &mcux_gau_adc_config_##n, \ + POST_KERNEL, CONFIG_ADC_INIT_PRIORITY, \ + &mcux_gau_adc_driver_api); \ + \ + static void mcux_gau_adc_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ + mcux_gau_adc_isr, DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } + +DT_INST_FOREACH_STATUS_OKAY(GAU_ADC_MCUX_INIT) diff --git a/drivers/adc/adc_mcux_lpadc.c b/drivers/adc/adc_mcux_lpadc.c index 1f47328496f7c..02c6e7ac648ee 100644 --- a/drivers/adc/adc_mcux_lpadc.c +++ b/drivers/adc/adc_mcux_lpadc.c @@ -122,10 +122,15 @@ static int mcux_lpadc_acquisition_time_setup(const struct device *dev, uint16_t static int mcux_lpadc_channel_setup(const struct device *dev, const struct adc_channel_cfg *channel_cfg) { + const struct mcux_lpadc_config *config = dev->config; + const struct device **regulator = config->ref_supplies; + uint16_t vref_mv = CONTAINER_OF(channel_cfg, struct adc_dt_spec, channel_cfg)->vref_mv; + int32_t vref_uv = (int32_t)((uint32_t)vref_mv * 1000); struct mcux_lpadc_data *data = dev->data; lpadc_conv_command_config_t *cmd; uint8_t channel_side; uint8_t channel_num; + int err; /* User may configure maximum number of active channels */ if (channel_cfg->channel_id >= CONFIG_LPADC_CHANNEL_COUNT) { @@ -200,8 +205,25 @@ static int mcux_lpadc_channel_setup(const struct device *dev, } #endif - if (channel_cfg->reference != ADC_REF_EXTERNAL0) { - LOG_ERR("Invalid channel reference"); + /* + * ADC_REF_EXTERNAL1: Use SoC internal regulator as LPADC reference voltage. + * ADC_REF_EXTERNAL0: Use other voltage source (maybe also within the SoCs) + * as LPADC reference voltage, like VREFH, VDDA, etc. + */ + if (channel_cfg->reference == ADC_REF_EXTERNAL1) { + LOG_DBG("ref external1"); + if (*regulator != NULL) { + err = regulator_set_voltage(*regulator, vref_uv, vref_uv); + if (err < 0) { + return err; + } + } else { + return -EINVAL; + } + } else if (channel_cfg->reference == ADC_REF_EXTERNAL0) { + LOG_DBG("ref external0"); + } else { + LOG_DBG("ref not support"); return -EINVAL; } diff --git a/drivers/adc/adc_nrfx_saadc.c b/drivers/adc/adc_nrfx_saadc.c index 6d1973ca0aae9..ba22a05325d38 100644 --- a/drivers/adc/adc_nrfx_saadc.c +++ b/drivers/adc/adc_nrfx_saadc.c @@ -6,8 +6,9 @@ #define ADC_CONTEXT_USES_KERNEL_TIMER #include "adc_context.h" -#include +#include #include +#include #define LOG_LEVEL CONFIG_ADC_LOG_LEVEL #include @@ -16,6 +17,33 @@ LOG_MODULE_REGISTER(adc_nrfx_saadc); #define DT_DRV_COMPAT nordic_nrf_saadc +#if (NRF_SAADC_HAS_AIN_AS_PIN) + +#if defined(CONFIG_SOC_NRF54H20) +static const uint8_t saadc_psels[NRF_SAADC_AIN7 + 1] = { + [NRF_SAADC_AIN0] = NRF_PIN_PORT_TO_PIN_NUMBER(0U, 1), + [NRF_SAADC_AIN1] = NRF_PIN_PORT_TO_PIN_NUMBER(1U, 1), + [NRF_SAADC_AIN2] = NRF_PIN_PORT_TO_PIN_NUMBER(2U, 1), + [NRF_SAADC_AIN3] = NRF_PIN_PORT_TO_PIN_NUMBER(3U, 1), + [NRF_SAADC_AIN4] = NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1), + [NRF_SAADC_AIN5] = NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1), + [NRF_SAADC_AIN6] = NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1), + [NRF_SAADC_AIN7] = NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), +}; +#elif defined(CONFIG_SOC_NRF54L15) +static const uint8_t saadc_psels[NRF_SAADC_AIN7 + 1] = { + [NRF_SAADC_AIN0] = NRF_PIN_PORT_TO_PIN_NUMBER(4U, 1), + [NRF_SAADC_AIN1] = NRF_PIN_PORT_TO_PIN_NUMBER(5U, 1), + [NRF_SAADC_AIN2] = NRF_PIN_PORT_TO_PIN_NUMBER(6U, 1), + [NRF_SAADC_AIN3] = NRF_PIN_PORT_TO_PIN_NUMBER(7U, 1), + [NRF_SAADC_AIN4] = NRF_PIN_PORT_TO_PIN_NUMBER(11U, 1), + [NRF_SAADC_AIN5] = NRF_PIN_PORT_TO_PIN_NUMBER(12U, 1), + [NRF_SAADC_AIN6] = NRF_PIN_PORT_TO_PIN_NUMBER(13U, 1), + [NRF_SAADC_AIN7] = NRF_PIN_PORT_TO_PIN_NUMBER(14U, 1), +}; +#endif + +#else BUILD_ASSERT((NRF_SAADC_AIN0 == NRF_SAADC_INPUT_AIN0) && (NRF_SAADC_AIN1 == NRF_SAADC_INPUT_AIN1) && (NRF_SAADC_AIN2 == NRF_SAADC_INPUT_AIN2) && @@ -24,104 +52,207 @@ BUILD_ASSERT((NRF_SAADC_AIN0 == NRF_SAADC_INPUT_AIN0) && (NRF_SAADC_AIN5 == NRF_SAADC_INPUT_AIN5) && (NRF_SAADC_AIN6 == NRF_SAADC_INPUT_AIN6) && (NRF_SAADC_AIN7 == NRF_SAADC_INPUT_AIN7) && - (NRF_SAADC_AIN7 == NRF_SAADC_INPUT_AIN7) && #if defined(SAADC_CH_PSELP_PSELP_VDDHDIV5) (NRF_SAADC_VDDHDIV5 == NRF_SAADC_INPUT_VDDHDIV5) && #endif - (NRF_SAADC_VDD == NRF_SAADC_INPUT_VDD), +#if defined(SAADC_CH_PSELP_PSELP_VDD) + (NRF_SAADC_VDD == NRF_SAADC_INPUT_VDD) && +#endif + 1, "Definitions from nrf-adc.h do not match those from nrf_saadc.h"); +#endif + +#ifdef CONFIG_SOC_NRF54H20 + +/* nRF54H20 always uses bounce buffers in RAM */ + +#define SAADC_MEMORY_SECTION \ + COND_CODE_1(DT_NODE_HAS_PROP(DT_NODELABEL(adc), memory_regions), \ + (__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \ + DT_PHANDLE(DT_NODELABEL(adc), memory_regions)))))), \ + ()) + +static uint16_t adc_samples_buffer[SAADC_CH_NUM] SAADC_MEMORY_SECTION; + +#define ADC_BUFFER_IN_RAM + +#endif /* CONFIG_SOC_NRF54H20 */ struct driver_data { struct adc_context ctx; uint8_t positive_inputs[SAADC_CH_NUM]; + +#if defined(ADC_BUFFER_IN_RAM) + void *samples_buffer; + void *user_buffer; + uint8_t active_channels; +#endif }; static struct driver_data m_data = { ADC_CONTEXT_INIT_TIMER(m_data, ctx), ADC_CONTEXT_INIT_LOCK(m_data, ctx), ADC_CONTEXT_INIT_SYNC(m_data, ctx), +#if defined(ADC_BUFFER_IN_RAM) + .samples_buffer = adc_samples_buffer, + .user_buffer = NULL, + .active_channels = 0, +#endif }; +/* Helper function to convert number of samples to the byte representation. */ +static uint32_t samples_to_bytes(const struct adc_sequence *sequence, uint16_t number_of_samples) +{ + if (NRF_SAADC_8BIT_SAMPLE_WIDTH == 8 && sequence->resolution == 8) { + return number_of_samples; + } + + return number_of_samples * 2; +} + +/* Helper function to convert acquisition time to register TACQ value. */ +static int adc_convert_acq_time(uint16_t acquisition_time, nrf_saadc_acqtime_t *p_tacq_val) +{ + int result = 0; + +#if NRF_SAADC_HAS_ACQTIME_ENUM + switch (acquisition_time) { + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 3): + *p_tacq_val = NRF_SAADC_ACQTIME_3US; + break; + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 5): + *p_tacq_val = NRF_SAADC_ACQTIME_5US; + break; + case ADC_ACQ_TIME_DEFAULT: + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10): + *p_tacq_val = NRF_SAADC_ACQTIME_10US; + break; + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 15): + *p_tacq_val = NRF_SAADC_ACQTIME_15US; + break; + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 20): + *p_tacq_val = NRF_SAADC_ACQTIME_20US; + break; + case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40): + *p_tacq_val = NRF_SAADC_ACQTIME_40US; + break; + default: + result = -EINVAL; + } +#else +#define MINIMUM_ACQ_TIME_IN_NS 125 +#define DEFAULT_ACQ_TIME_IN_NS 10000 + + nrf_saadc_acqtime_t tacq = 0; + uint16_t acq_time = + (acquisition_time == ADC_ACQ_TIME_DEFAULT + ? DEFAULT_ACQ_TIME_IN_NS + : (ADC_ACQ_TIME_VALUE(acquisition_time) * + (ADC_ACQ_TIME_UNIT(acquisition_time) == ADC_ACQ_TIME_MICROSECONDS + ? 1000 + : 1))); + + tacq = (nrf_saadc_acqtime_t)(acq_time / MINIMUM_ACQ_TIME_IN_NS) - 1; + if ((tacq > NRF_SAADC_ACQTIME_MAX) || (acq_time < MINIMUM_ACQ_TIME_IN_NS)) { + result = -EINVAL; + } else { + *p_tacq_val = tacq; + } +#endif + + return result; +} /* Implementation of the ADC driver API function: adc_channel_setup. */ static int adc_nrfx_channel_setup(const struct device *dev, const struct adc_channel_cfg *channel_cfg) { nrf_saadc_channel_config_t config = { - .resistor_p = NRF_SAADC_RESISTOR_DISABLED, - .resistor_n = NRF_SAADC_RESISTOR_DISABLED, - .burst = NRF_SAADC_BURST_DISABLED, +#if NRF_SAADC_HAS_CH_CONFIG_RES + .resistor_p = NRF_SAADC_RESISTOR_DISABLED, + .resistor_n = NRF_SAADC_RESISTOR_DISABLED, +#endif + .burst = NRF_SAADC_BURST_DISABLED, }; uint8_t channel_id = channel_cfg->channel_id; + uint32_t input_negative = channel_cfg->input_negative; if (channel_id >= SAADC_CH_NUM) { return -EINVAL; } switch (channel_cfg->gain) { +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_6) case ADC_GAIN_1_6: config.gain = NRF_SAADC_GAIN1_6; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_5) case ADC_GAIN_1_5: config.gain = NRF_SAADC_GAIN1_5; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_4) case ADC_GAIN_1_4: config.gain = NRF_SAADC_GAIN1_4; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_3) case ADC_GAIN_1_3: config.gain = NRF_SAADC_GAIN1_3; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain1_2) case ADC_GAIN_1_2: config.gain = NRF_SAADC_GAIN1_2; break; +#endif +#if defined(SAADC_CH_CONFIG_GAIN_Gain2_3) + case ADC_GAIN_2_3: + config.gain = NRF_SAADC_GAIN2_3; + break; +#endif case ADC_GAIN_1: config.gain = NRF_SAADC_GAIN1; break; case ADC_GAIN_2: config.gain = NRF_SAADC_GAIN2; break; +#if defined(SAADC_CH_CONFIG_GAIN_Gain4) case ADC_GAIN_4: config.gain = NRF_SAADC_GAIN4; break; +#endif default: LOG_ERR("Selected ADC gain is not valid"); return -EINVAL; } switch (channel_cfg->reference) { +#if defined(SAADC_CH_CONFIG_REFSEL_Internal) case ADC_REF_INTERNAL: config.reference = NRF_SAADC_REFERENCE_INTERNAL; break; +#endif +#if defined(SAADC_CH_CONFIG_REFSEL_VDD1_4) case ADC_REF_VDD_1_4: config.reference = NRF_SAADC_REFERENCE_VDD4; break; +#endif +#if defined(SAADC_CH_CONFIG_REFSEL_External) + case ADC_REF_EXTERNAL0: + config.reference = NRF_SAADC_REFERENCE_EXTERNAL; + break; +#endif default: LOG_ERR("Selected ADC reference is not valid"); return -EINVAL; } - switch (channel_cfg->acquisition_time) { - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 3): - config.acq_time = NRF_SAADC_ACQTIME_3US; - break; - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 5): - config.acq_time = NRF_SAADC_ACQTIME_5US; - break; - case ADC_ACQ_TIME_DEFAULT: - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 10): - config.acq_time = NRF_SAADC_ACQTIME_10US; - break; - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 15): - config.acq_time = NRF_SAADC_ACQTIME_15US; - break; - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 20): - config.acq_time = NRF_SAADC_ACQTIME_20US; - break; - case ADC_ACQ_TIME(ADC_ACQ_TIME_MICROSECONDS, 40): - config.acq_time = NRF_SAADC_ACQTIME_40US; - break; - default: + int ret = adc_convert_acq_time(channel_cfg->acquisition_time, &config.acq_time); + + if (ret) { LOG_ERR("Selected ADC acquisition time is not valid"); return -EINVAL; } @@ -134,17 +265,37 @@ static int adc_nrfx_channel_setup(const struct device *dev, * in a sampling sequence. */ - nrf_saadc_channel_init(NRF_SAADC, channel_id, &config); - nrf_saadc_channel_input_set(NRF_SAADC, - channel_id, - NRF_SAADC_INPUT_DISABLED, - channel_cfg->input_negative); +#if (NRF_SAADC_HAS_AIN_AS_PIN) + if ((channel_cfg->input_positive > NRF_SAADC_AIN7) || + (channel_cfg->input_positive < NRF_SAADC_AIN0)) { + return -EINVAL; + } + + if (config.mode == NRF_SAADC_MODE_DIFFERENTIAL) { + if (input_negative > NRF_SAADC_AIN7 || + input_negative < NRF_SAADC_AIN0) { + return -EINVAL; + } + + input_negative = saadc_psels[input_negative]; + } else { + input_negative = NRF_SAADC_INPUT_DISABLED; + } /* Store the positive input selection in a dedicated array, * to get it later when the channel is selected for a sampling * and to mark the channel as configured (ready to be selected). */ + m_data.positive_inputs[channel_id] = saadc_psels[channel_cfg->input_positive]; +#else m_data.positive_inputs[channel_id] = channel_cfg->input_positive; +#endif + + nrf_saadc_channel_init(NRF_SAADC, channel_id, &config); + nrf_saadc_channel_input_set(NRF_SAADC, + channel_id, + NRF_SAADC_INPUT_DISABLED, + input_negative); return 0; } @@ -168,10 +319,15 @@ static void adc_context_update_buffer_pointer(struct adc_context *ctx, ARG_UNUSED(ctx); if (!repeat) { - nrf_saadc_buffer_pointer_set( - NRF_SAADC, - (uint16_t *)nrf_saadc_buffer_pointer_get(NRF_SAADC) + - nrf_saadc_amount_get(NRF_SAADC)); +#if defined(ADC_BUFFER_IN_RAM) + m_data.user_buffer = (uint8_t *)m_data.user_buffer + + samples_to_bytes(&ctx->sequence, nrfy_saadc_amount_get(NRF_SAADC)); +#else + nrf_saadc_value_t *buffer = + (uint8_t *)nrf_saadc_buffer_pointer_get(NRF_SAADC) + + samples_to_bytes(&ctx->sequence, nrfy_saadc_amount_get(NRF_SAADC)); + nrfy_saadc_buffer_pointer_set(NRF_SAADC, buffer); +#endif } } @@ -256,7 +412,8 @@ static int check_buffer_size(const struct adc_sequence *sequence, { size_t needed_buffer_size; - needed_buffer_size = active_channels * sizeof(uint16_t); + needed_buffer_size = samples_to_bytes(sequence, active_channels); + if (sequence->options) { needed_buffer_size *= (1 + sequence->options->extra_samplings); } @@ -344,13 +501,23 @@ static int start_read(const struct device *dev, return error; } +#if defined(ADC_BUFFER_IN_RAM) + m_data.user_buffer = sequence->buffer; + m_data.active_channels = active_channels; + + nrf_saadc_buffer_init(NRF_SAADC, + (nrf_saadc_value_t *)m_data.samples_buffer, + active_channels); +#else nrf_saadc_buffer_init(NRF_SAADC, (nrf_saadc_value_t *)sequence->buffer, active_channels); +#endif adc_context_start_read(&m_data.ctx, sequence); error = adc_context_wait_for_completion(&m_data.ctx); + return error; } @@ -391,6 +558,11 @@ static void saadc_irq_handler(const struct device *dev) nrf_saadc_task_trigger(NRF_SAADC, NRF_SAADC_TASK_STOP); nrf_saadc_disable(NRF_SAADC); +#if defined(ADC_BUFFER_IN_RAM) + memcpy(m_data.user_buffer, m_data.samples_buffer, + samples_to_bytes(&m_data.ctx.sequence, m_data.active_channels)); +#endif + adc_context_on_sampling_done(&m_data.ctx, dev); } else if (nrf_saadc_event_check(NRF_SAADC, NRF_SAADC_EVENT_CALIBRATEDONE)) { @@ -429,7 +601,13 @@ static const struct adc_driver_api adc_nrfx_driver_api = { #ifdef CONFIG_ADC_ASYNC .read_async = adc_nrfx_read_async, #endif +#if defined(CONFIG_SOC_NRF54L15) + .ref_internal = 900, +#elif defined(CONFIG_SOC_NRF54H20) + .ref_internal = 1024, +#else .ref_internal = 600, +#endif }; /* diff --git a/drivers/adc/adc_smartbond_gpadc.c b/drivers/adc/adc_smartbond_gpadc.c index 49854372a5aab..367d32110ea2f 100644 --- a/drivers/adc/adc_smartbond_gpadc.c +++ b/drivers/adc/adc_smartbond_gpadc.c @@ -8,6 +8,7 @@ #define ADC_CONTEXT_USES_KERNEL_TIMER #include +#include #include "adc_context.h" #include @@ -15,7 +16,13 @@ #include #include #include +#include +#include +#include #include +#include +#include +#include LOG_MODULE_REGISTER(adc_smartbond_adc); @@ -34,6 +41,10 @@ struct adc_smartbond_data { uint8_t sequence_channel_count; /* Index in buffer to store current value to */ uint8_t result_index; +#if defined(CONFIG_PM_DEVICE) + /* Flag to prevent sleep */ + ATOMIC_DEFINE(pm_policy_state_flag, 1); +#endif }; #define SMARTBOND_ADC_CHANNEL_COUNT 8 @@ -101,6 +112,42 @@ static int adc_smartbond_channel_setup(const struct device *dev, return 0; } +static inline void gpadc_smartbond_pm_policy_state_lock_get(const struct device *dev, + struct adc_smartbond_data *data) +{ + +#if defined(CONFIG_PM_DEVICE) +#if defined(CONFIG_PM_DEVICE_RUNTIME) + pm_device_runtime_get(dev); +#endif + + if (!atomic_test_and_set_bit(data->pm_policy_state_flag, 0)) { + /* + * Prevent the SoC from entering the normal sleep state. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } + +#endif +} + +static inline void gpadc_smartbond_pm_policy_state_lock_put(const struct device *dev, + struct adc_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) +#if defined(CONFIG_PM_DEVICE_RUNTIME) + pm_device_runtime_put(dev); +#endif + + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0)) { + /* + * Allow the SoC to enter the normal sleep state once GPADC is done. + */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + #define PER_CHANNEL_ADC_CONFIG_MASK (GPADC_GP_ADC_CTRL_REG_GP_ADC_SEL_Msk | \ GPADC_GP_ADC_CTRL_REG_GP_ADC_SE_Msk) @@ -213,6 +260,7 @@ static void adc_smartbond_isr(const struct device *dev) if (data->channel_read_mask == 0) { adc_context_on_sampling_done(&data->ctx, dev); + gpadc_smartbond_pm_policy_state_lock_put(dev, data); } else { adc_context_start_sampling(&data->ctx); } @@ -227,6 +275,7 @@ static int adc_smartbond_read(const struct device *dev, int error; struct adc_smartbond_data *data = dev->data; + gpadc_smartbond_pm_policy_state_lock_get(dev, data); adc_context_lock(&data->ctx, false, NULL); error = start_read(dev, sequence); adc_context_release(&data->ctx, error); @@ -243,6 +292,7 @@ static int adc_smartbond_read_async(const struct device *dev, struct adc_smartbond_data *data = dev->data; int error; + gpadc_smartbond_pm_policy_state_lock_get(dev, data); adc_context_lock(&data->ctx, true, async); error = start_read(dev, sequence); adc_context_release(&data->ctx, error); @@ -251,26 +301,99 @@ static int adc_smartbond_read_async(const struct device *dev, } #endif /* CONFIG_ADC_ASYNC */ -static int adc_smartbond_init(const struct device *dev) +static int gpadc_smartbond_resume(const struct device *dev) { - int err; - struct adc_smartbond_data *data = dev->data; + int ret, rate; const struct adc_smartbond_cfg *config = dev->config; + const struct device *clock_dev = DEVICE_DT_GET(DT_NODELABEL(osc)); + + da1469x_pd_acquire(MCU_PD_DOMAIN_PER); + + /* Get current clock to determine GP_ADC_EN_DEL */ + clock_control_get_rate(clock_dev, (clock_control_subsys_t)SMARTBOND_CLK_SYS_CLK, &rate); + GPADC->GP_ADC_CTRL3_REG = (rate/1600000)&0xff; GPADC->GP_ADC_CTRL_REG = GPADC_GP_ADC_CTRL_REG_GP_ADC_EN_Msk; - GPADC->GP_ADC_CTRL2_REG = 0; - GPADC->GP_ADC_CTRL3_REG = 0x40; - GPADC->GP_ADC_CLEAR_INT_REG = 0x0; /* * Configure dt provided device signals when available. * pinctrl is optional so ENOENT is not setup failure. */ - err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (err < 0 && err != -ENOENT) { - LOG_ERR("ADC pinctrl setup failed (%d)", err); - return err; + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0 && ret != -ENOENT) { + /* Disable the GPADC LDO */ + GPADC->GP_ADC_CTRL_REG = 0; + + /* Release the peripheral domain */ + da1469x_pd_release(MCU_PD_DOMAIN_PER); + + LOG_ERR("ADC pinctrl setup failed (%d)", ret); + return ret; + } + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static int gpadc_smartbond_suspend(const struct device *dev) +{ + int ret; + const struct adc_smartbond_cfg *config = dev->config; + + /* Disable the GPADC LDO */ + GPADC->GP_ADC_CTRL_REG = 0; + + /* Release the peripheral domain */ + da1469x_pd_release(MCU_PD_DOMAIN_PER); + + /* + * Configure dt provided device signals for sleep. + * pinctrl is optional so ENOENT is not setup failure. + */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0 && ret != -ENOENT) { + LOG_WRN("Failed to configure the GPADC pins to inactive state"); + return ret; } + + return 0; +} + +static int gpadc_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = gpadc_smartbond_resume(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = gpadc_smartbond_suspend(dev); + break; + default: + return -ENOTSUP; + } + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + +static int adc_smartbond_init(const struct device *dev) +{ + int ret; + struct adc_smartbond_data *data = dev->data; + +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); + +#else + ret = gpadc_smartbond_resume(dev); + +#endif + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), adc_smartbond_isr, DEVICE_DT_INST_GET(0), 0); @@ -279,7 +402,7 @@ static int adc_smartbond_init(const struct device *dev) adc_context_unlock_unconditionally(&data->ctx); - return 0; + return ret; } static const struct adc_driver_api adc_smartbond_driver_api = { @@ -312,8 +435,10 @@ static const struct adc_driver_api adc_smartbond_driver_api = { ADC_CONTEXT_INIT_LOCK(adc_smartbond_data_##inst, ctx), \ ADC_CONTEXT_INIT_SYNC(adc_smartbond_data_##inst, ctx), \ }; \ - DEVICE_DT_INST_DEFINE(0, \ - adc_smartbond_init, NULL, \ + PM_DEVICE_DT_INST_DEFINE(inst, gpadc_smartbond_pm_action); \ + DEVICE_DT_INST_DEFINE(inst, \ + adc_smartbond_init, \ + PM_DEVICE_DT_INST_GET(inst), \ &adc_smartbond_data_##inst, \ &adc_smartbond_cfg_##inst, \ POST_KERNEL, \ diff --git a/drivers/adc/adc_smartbond_sdadc.c b/drivers/adc/adc_smartbond_sdadc.c index 7ac435f786034..5576a65bed159 100644 --- a/drivers/adc/adc_smartbond_sdadc.c +++ b/drivers/adc/adc_smartbond_sdadc.c @@ -8,6 +8,7 @@ #define ADC_CONTEXT_USES_KERNEL_TIMER #include +#include #include "adc_context.h" #include @@ -16,6 +17,9 @@ #include #include #include +#include +#include +#include LOG_MODULE_REGISTER(adc_smartbond_sdadc); @@ -36,6 +40,10 @@ struct sdadc_smartbond_data { uint8_t sequence_channel_count; /* Index in buffer to store current value to */ uint8_t result_index; +#if defined(CONFIG_PM_DEVICE) + /* Flag to prevent sleep */ + ATOMIC_DEFINE(pm_policy_state_flag, 1); +#endif }; #define SMARTBOND_SDADC_CHANNEL_COUNT 8 @@ -107,6 +115,41 @@ static int sdadc_smartbond_channel_setup(const struct device *dev, SDADC_SDADC_CTRL_REG_SDADC_SE_Msk \ ) +static inline void sdadc_smartbond_pm_policy_state_lock_get(const struct device *dev, + struct sdadc_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) +#if defined(CONFIG_PM_DEVICE_RUNTIME) + pm_device_runtime_get(dev); +#endif + + if (!atomic_test_and_set_bit(data->pm_policy_state_flag, 0)) { + /* + * Prevent the SoC from entering the normal sleep state. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void sdadc_smartbond_pm_policy_state_lock_put(const struct device *dev, + struct sdadc_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) +#if defined(CONFIG_PM_DEVICE_RUNTIME) + pm_device_runtime_put(dev); +#endif + + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0)) { + /* + * Allow the SoC to enter the normal sleep state once sdadc is done. + */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + + static int pop_count(uint32_t n) { return __builtin_popcount(n); @@ -120,6 +163,10 @@ static void adc_context_start_sampling(struct adc_context *ctx) /* Extract lower channel from sequence mask */ int current_channel = u32_count_trailing_zeros(data->channel_read_mask); + /* Wait until the SDADC LDO stabilizes */ + while (!(SDADC->SDADC_CTRL_REG & SDADC_SDADC_CTRL_REG_SDADC_LDO_OK_Msk)) + __NOP(); + if (ctx->sequence.calibrate) { /* TODO: Add calibration code */ } else { @@ -216,6 +263,7 @@ static void sdadc_smartbond_isr(const struct device *dev) if (data->channel_read_mask == 0) { adc_context_on_sampling_done(&data->ctx, dev); + sdadc_smartbond_pm_policy_state_lock_put(dev, data); } else { adc_context_start_sampling(&data->ctx); } @@ -230,6 +278,7 @@ static int sdadc_smartbond_read(const struct device *dev, int error; struct sdadc_smartbond_data *data = dev->data; + sdadc_smartbond_pm_policy_state_lock_get(dev, data); adc_context_lock(&data->ctx, false, NULL); error = start_read(dev, sequence); adc_context_release(&data->ctx, error); @@ -246,6 +295,7 @@ static int sdadc_smartbond_read_async(const struct device *dev, struct sdadc_smartbond_data *data = dev->data; int error; + sdadc_smartbond_pm_policy_state_lock_get(dev, data); adc_context_lock(&data->ctx, true, async); error = start_read(dev, sequence); adc_context_release(&data->ctx, error); @@ -254,26 +304,97 @@ static int sdadc_smartbond_read_async(const struct device *dev, } #endif /* CONFIG_ADC_ASYNC */ -static int sdadc_smartbond_init(const struct device *dev) +static int sdadc_smartbond_resume(const struct device *dev) { - int err; - struct sdadc_smartbond_data *data = dev->data; + int ret; const struct sdadc_smartbond_cfg *config = dev->config; - SDADC->SDADC_CTRL_REG = SDADC_SDADC_CTRL_REG_SDADC_EN_Msk; - SDADC->SDADC_CLEAR_INT_REG = 0x0; + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + SDADC->SDADC_TEST_REG = (SDADC->SDADC_TEST_REG & ~SDADC_SDADC_TEST_REG_SDADC_CLK_FREQ_Msk) | (config->sdadc_clk_freq) << SDADC_SDADC_TEST_REG_SDADC_CLK_FREQ_Pos; + + SDADC->SDADC_CTRL_REG = SDADC_SDADC_CTRL_REG_SDADC_EN_Msk; + /* * Configure dt provided device signals when available. * pinctrl is optional so ENOENT is not setup failure. */ - err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (err < 0 && err != -ENOENT) { - LOG_ERR("ADC pinctrl setup failed (%d)", err); - return err; + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0 && ret != -ENOENT) { + SDADC->SDADC_CTRL_REG = 0; + + /* Release the comms domain */ + da1469x_pd_release(MCU_PD_DOMAIN_COM); + + LOG_ERR("ADC pinctrl setup failed (%d)", ret); + return ret; } + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static int sdadc_smartbond_suspend(const struct device *dev) +{ + int ret; + const struct sdadc_smartbond_cfg *config = dev->config; + + /* Disable the sdadc LDO */ + SDADC->SDADC_CTRL_REG = 0; + + /* Release the comms domain */ + da1469x_pd_release(MCU_PD_DOMAIN_COM); + + /* + * Configure dt provided device signals for sleep. + * pinctrl is optional so ENOENT is not setup failure. + */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0 && ret != -ENOENT) { + LOG_WRN("Failed to configure the sdadc pins to inactive state"); + return ret; + } + + return 0; +} + +static int sdadc_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = sdadc_smartbond_resume(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = sdadc_smartbond_suspend(dev); + break; + default: + return -ENOTSUP; + } + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + +static int sdadc_smartbond_init(const struct device *dev) +{ + int ret; + struct sdadc_smartbond_data *data = dev->data; + +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); + +#else + ret = sdadc_smartbond_resume(dev); + +#endif + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), sdadc_smartbond_isr, DEVICE_DT_INST_GET(0), 0); @@ -282,7 +403,7 @@ static int sdadc_smartbond_init(const struct device *dev) adc_context_unlock_unconditionally(&data->ctx); - return 0; + return ret; } static const struct adc_driver_api sdadc_smartbond_driver_api = { @@ -316,8 +437,10 @@ static const struct adc_driver_api sdadc_smartbond_driver_api = { ADC_CONTEXT_INIT_LOCK(sdadc_smartbond_data_##inst, ctx), \ ADC_CONTEXT_INIT_SYNC(sdadc_smartbond_data_##inst, ctx), \ }; \ - DEVICE_DT_INST_DEFINE(0, \ - sdadc_smartbond_init, NULL, \ + PM_DEVICE_DT_INST_DEFINE(inst, sdadc_smartbond_pm_action); \ + DEVICE_DT_INST_DEFINE(inst, \ + sdadc_smartbond_init, \ + PM_DEVICE_DT_INST_GET(inst), \ &sdadc_smartbond_data_##inst, \ &sdadc_smartbond_cfg_##inst, \ POST_KERNEL, \ diff --git a/drivers/adc/adc_stm32.c b/drivers/adc/adc_stm32.c index 1ed8db1c54abc..3e5c67ad4586d 100644 --- a/drivers/adc/adc_stm32.c +++ b/drivers/adc/adc_stm32.c @@ -46,7 +46,7 @@ LOG_MODULE_REGISTER(adc_stm32); #include #include -#ifdef CONFIG_SOC_SERIES_STM32H7X +#if defined(CONFIG_SOC_SERIES_STM32H7X) || defined(CONFIG_SOC_SERIES_STM32H7RSX) #include #endif @@ -522,6 +522,7 @@ static void adc_stm32_calibration_start(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32L4X) || \ defined(CONFIG_SOC_SERIES_STM32L5X) || \ defined(CONFIG_SOC_SERIES_STM32H5X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32WBX) || \ defined(CONFIG_SOC_SERIES_STM32G4X) LL_ADC_StartCalibration(adc, LL_ADC_SINGLE_ENDED); @@ -556,6 +557,7 @@ static int adc_stm32_calibrate(const struct device *dev) #if defined(CONFIG_SOC_SERIES_STM32C0X) || \ defined(CONFIG_SOC_SERIES_STM32F0X) || \ defined(CONFIG_SOC_SERIES_STM32G0X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32L0X) || \ defined(CONFIG_SOC_SERIES_STM32WBAX) || \ defined(CONFIG_SOC_SERIES_STM32WLX) @@ -606,6 +608,7 @@ static int adc_stm32_calibrate(const struct device *dev) linear_calib_buffer = *(uint32_t *)( ADC_LINEAR_CALIB_REG_1_ADDR + channel_offset + count ); + LL_ADC_SetCalibrationLinearFactor( adc, LL_ADC_CALIB_LINEARITY_WORD1 << count, linear_calib_buffer @@ -1425,6 +1428,7 @@ static int adc_stm32_init(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32G4X) || \ defined(CONFIG_SOC_SERIES_STM32H5X) || \ defined(CONFIG_SOC_SERIES_STM32H7X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32U5X) /* * L4, WB, G4, H5, H7 and U5 series STM32 needs to be awaken from deep sleep @@ -1485,6 +1489,7 @@ static int adc_stm32_suspend_setup(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32G4X) || \ defined(CONFIG_SOC_SERIES_STM32H5X) || \ defined(CONFIG_SOC_SERIES_STM32H7X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32U5X) /* * L4, WB, G4, H5, H7 and U5 series STM32 needs to be put into diff --git a/drivers/auxdisplay/auxdisplay_handlers.c b/drivers/auxdisplay/auxdisplay_handlers.c index 5c88e7afa09bc..45b22303ec3ad 100644 --- a/drivers/auxdisplay/auxdisplay_handlers.c +++ b/drivers/auxdisplay/auxdisplay_handlers.c @@ -12,21 +12,21 @@ static inline int z_vrfy_auxdisplay_display_on(const struct device *dev) K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_on(dev); } -#include +#include static inline int z_vrfy_auxdisplay_display_off(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_off(dev); } -#include +#include static inline int z_vrfy_auxdisplay_cursor_set_enabled(const struct device *dev, bool enabled) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_set_enabled(dev, enabled); } -#include +#include static inline int z_vrfy_auxdisplay_position_blinking_set_enabled(const struct device *dev, bool enabled) @@ -34,7 +34,7 @@ static inline int z_vrfy_auxdisplay_position_blinking_set_enabled(const struct d K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_position_blinking_set_enabled(dev, enabled); } -#include +#include static inline int z_vrfy_auxdisplay_cursor_shift_set(const struct device *dev, uint8_t direction, bool display_shift) @@ -42,7 +42,7 @@ static inline int z_vrfy_auxdisplay_cursor_shift_set(const struct device *dev, u K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_shift_set(dev, direction, display_shift); } -#include +#include static inline int z_vrfy_auxdisplay_cursor_position_set(const struct device *dev, enum auxdisplay_position type, @@ -51,7 +51,7 @@ static inline int z_vrfy_auxdisplay_cursor_position_set(const struct device *dev K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_position_set(dev, type, x, y); } -#include +#include static inline int z_vrfy_auxdisplay_cursor_position_get(const struct device *dev, int16_t *x, int16_t *y) @@ -59,7 +59,7 @@ static inline int z_vrfy_auxdisplay_cursor_position_get(const struct device *dev K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_cursor_position_get(dev, x, y); } -#include +#include static inline int z_vrfy_auxdisplay_display_position_set(const struct device *dev, enum auxdisplay_position type, @@ -68,7 +68,7 @@ static inline int z_vrfy_auxdisplay_display_position_set(const struct device *de K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_position_set(dev, type, x, y); } -#include +#include static inline int z_vrfy_auxdisplay_display_position_get(const struct device *dev, int16_t *x, int16_t *y) @@ -76,7 +76,7 @@ static inline int z_vrfy_auxdisplay_display_position_get(const struct device *de K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_display_position_get(dev, x, y); } -#include +#include static inline int z_vrfy_auxdisplay_capabilities_get(const struct device *dev, struct auxdisplay_capabilities *capabilities) @@ -84,14 +84,14 @@ static inline int z_vrfy_auxdisplay_capabilities_get(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_capabilities_get(dev, capabilities); } -#include +#include static inline int z_vrfy_auxdisplay_clear(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_clear(dev); } -#include +#include static inline int z_vrfy_auxdisplay_brightness_get(const struct device *dev, uint8_t *brightness) @@ -99,7 +99,7 @@ static inline int z_vrfy_auxdisplay_brightness_get(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_brightness_get(dev, brightness); } -#include +#include static inline int z_vrfy_auxdisplay_brightness_set(const struct device *dev, uint8_t brightness) @@ -107,7 +107,7 @@ static inline int z_vrfy_auxdisplay_brightness_set(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_brightness_set(dev, brightness); } -#include +#include static inline int z_vrfy_auxdisplay_backlight_get(const struct device *dev, uint8_t *backlight) @@ -115,7 +115,7 @@ static inline int z_vrfy_auxdisplay_backlight_get(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_backlight_get(dev, backlight); } -#include +#include static inline int z_vrfy_auxdisplay_backlight_set(const struct device *dev, uint8_t backlight) @@ -123,14 +123,14 @@ static inline int z_vrfy_auxdisplay_backlight_set(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_backlight_set(dev, backlight); } -#include +#include static inline int z_vrfy_auxdisplay_is_busy(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_is_busy(dev); } -#include +#include static inline int z_vrfy_auxdisplay_custom_character_set(const struct device *dev, struct auxdisplay_character *character) @@ -138,7 +138,7 @@ static inline int z_vrfy_auxdisplay_custom_character_set(const struct device *de K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_custom_character_set(dev, character); } -#include +#include static inline int z_vrfy_auxdisplay_write(const struct device *dev, const uint8_t *data, uint16_t len) @@ -146,7 +146,7 @@ static inline int z_vrfy_auxdisplay_write(const struct device *dev, const uint8_ K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_write(dev, data, len); } -#include +#include static inline int z_vrfy_auxdisplay_custom_command(const struct device *dev, struct auxdisplay_custom_data *data) @@ -154,4 +154,4 @@ static inline int z_vrfy_auxdisplay_custom_command(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_AUXDISPLAY)); return z_impl_auxdisplay_custom_command(dev, data); } -#include +#include diff --git a/drivers/bbram/bbram_handlers.c b/drivers/bbram/bbram_handlers.c index 14e4abe21b35d..2fc26954014a2 100644 --- a/drivers/bbram/bbram_handlers.c +++ b/drivers/bbram/bbram_handlers.c @@ -12,21 +12,21 @@ static inline int z_vrfy_bbram_check_invalid(const struct device *dev) K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); return z_impl_bbram_check_invalid(dev); } -#include +#include static inline int z_vrfy_bbram_check_standby_power(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); return z_impl_bbram_check_standby_power(dev); } -#include +#include static inline int z_vrfy_bbram_check_power(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_BBRAM)); return z_impl_bbram_check_power(dev); } -#include +#include static inline int z_vrfy_bbram_get_size(const struct device *dev, size_t *size) { @@ -34,7 +34,7 @@ static inline int z_vrfy_bbram_get_size(const struct device *dev, size_t *size) K_OOPS(K_SYSCALL_MEMORY_WRITE(size, sizeof(size_t))); return z_impl_bbram_get_size(dev, size); } -#include +#include static inline int z_vrfy_bbram_read(const struct device *dev, size_t offset, size_t size, uint8_t *data) @@ -43,7 +43,7 @@ static inline int z_vrfy_bbram_read(const struct device *dev, size_t offset, K_OOPS(K_SYSCALL_MEMORY_WRITE(data, size)); return z_impl_bbram_read(dev, offset, size, data); } -#include +#include static inline int z_vrfy_bbram_write(const struct device *dev, size_t offset, size_t size, const uint8_t *data) @@ -52,4 +52,4 @@ static inline int z_vrfy_bbram_write(const struct device *dev, size_t offset, K_OOPS(K_SYSCALL_MEMORY_READ(data, size)); return z_impl_bbram_write(dev, offset, size, data); } -#include +#include diff --git a/drivers/bbram/bbram_stm32.c b/drivers/bbram/bbram_stm32.c index 8412153bc76c4..26acf001a9aed 100644 --- a/drivers/bbram/bbram_stm32.c +++ b/drivers/bbram/bbram_stm32.c @@ -11,6 +11,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(bbram, CONFIG_BBRAM_LOG_LEVEL); @@ -65,6 +66,10 @@ static int bbram_stm32_write(const struct device *dev, size_t offset, size_t siz return -EFAULT; } +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) + LL_PWR_EnableBkUpAccess(); +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPCR_DBP || PWR_DBPR_DBP */ + for (size_t written = 0; written < size; written += to_copy) { reg = STM32_BKP_REG(STM32_BKP_REG_INDEX(offset + written)); begin = STM32_BKP_REG_BYTE_INDEX(offset + written); @@ -73,6 +78,10 @@ static int bbram_stm32_write(const struct device *dev, size_t offset, size_t siz STM32_BKP_REG(STM32_BKP_REG_INDEX(offset + written)) = reg; } +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) + LL_PWR_DisableBkUpAccess(); +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPCR_DBP || PWR_DBPR_DBP */ + return 0; } diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index 46bf62bb1a7ff..a1680af6583d0 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -12,7 +12,7 @@ menuconfig BT_DRIVERS bool "Bluetooth drivers" default y - depends on BT && !BT_CTLR + depends on BT if BT_DRIVERS diff --git a/drivers/bluetooth/hci/CMakeLists.txt b/drivers/bluetooth/hci/CMakeLists.txt index adda6ea0e2ab0..14d81d7458d5b 100644 --- a/drivers/bluetooth/hci/CMakeLists.txt +++ b/drivers/bluetooth/hci/CMakeLists.txt @@ -13,8 +13,6 @@ if(CONFIG_BT_HCI_IPC) endif() endif() -zephyr_library_sources_ifdef(CONFIG_BT_B91 hci_b91.c) -zephyr_library_sources_ifdef(CONFIG_BT_AIROC cyw43xxx.c) zephyr_library_sources_ifdef(CONFIG_BT_ESP32 hci_esp32.c) zephyr_library_sources_ifdef(CONFIG_BT_H4 h4.c) zephyr_library_sources_ifdef(CONFIG_BT_H5 h5.c) @@ -26,10 +24,16 @@ if(CONFIG_BT_SPI) zephyr_library_sources(spi.c) endif() endif() +zephyr_library_sources_ifdef(CONFIG_BT_CYW43XX h4_ifx_cyw43xxx.c) +zephyr_library_sources_ifdef(CONFIG_BT_CYW208XX hci_ifx_cyw208xx.c) + zephyr_library_sources_ifdef(CONFIG_BT_STM32_IPM ipm_stm32wb.c) zephyr_library_sources_ifdef(CONFIG_BT_STM32WBA hci_stm32wba.c) zephyr_library_sources_ifdef(CONFIG_BT_USERCHAN userchan.c) zephyr_library_sources_ifdef(CONFIG_BT_SILABS_HCI slz_hci.c) -zephyr_library_sources_ifdef(CONFIG_BT_PSOC6_BLESS hci_psoc6_bless.c) +zephyr_library_sources_ifdef(CONFIG_BT_PSOC6_BLESS hci_ifx_psoc6_bless.c) zephyr_library_sources_ifdef(CONFIG_SOC_NRF5340_CPUAPP nrf53_support.c) zephyr_library_sources_ifdef(CONFIG_BT_AMBIQ_HCI hci_ambiq.c apollox_blue.c) +zephyr_library_sources_ifdef(CONFIG_BT_DA1469X hci_da1469x.c) +zephyr_library_sources_ifdef(CONFIG_BT_NXP hci_nxp.c) +zephyr_library_sources_ifdef(CONFIG_BT_H4_NXP_CTLR hci_nxp_setup.c) diff --git a/drivers/bluetooth/hci/Kconfig b/drivers/bluetooth/hci/Kconfig index ad1d9da2df2a6..c311fc185eecb 100644 --- a/drivers/bluetooth/hci/Kconfig +++ b/drivers/bluetooth/hci/Kconfig @@ -10,13 +10,11 @@ config BT_UART select SERIAL select UART_INTERRUPT_DRIVEN - -choice BT_HCI_BUS_TYPE - prompt "Bluetooth HCI driver" - config BT_H4 bool "H:4 UART" select BT_UART + default y + depends on DT_HAS_ZEPHYR_BT_HCI_UART_ENABLED help Bluetooth H:4 UART driver. Requires hardware flow control lines to be available. @@ -25,6 +23,8 @@ config BT_H5 bool "H:5 UART [EXPERIMENTAL]" select BT_UART select EXPERIMENTAL + default y + depends on DT_HAS_ZEPHYR_BT_HCI_3WIRE_UART_ENABLED help Bluetooth three-wire (H:5) UART driver. Implementation of HCI Three-Wire UART Transport Layer. @@ -38,6 +38,8 @@ config BT_RPMSG config BT_HCI_IPC bool "HCI using the IPC subsystem" + default y + depends on DT_HAS_ZEPHYR_BT_HCI_IPC_ENABLED select BT_HAS_HCI_VS select IPC_SERVICE select MBOX @@ -57,6 +59,8 @@ config BT_SPI config BT_STM32_IPM bool "IPM HCI" + default y + depends on DT_HAS_ST_STM32WB_RF_ENABLED select USE_STM32_HAL_CORTEX select HAS_STM32LIB help @@ -64,13 +68,16 @@ config BT_STM32_IPM config BT_STM32WBA bool "STM32WBA HCI driver" + default y + depends on DT_HAS_ST_HCI_STM32WBA_ENABLED select HAS_STM32LIB help ST STM32WBA HCI Bluetooth interface config BT_SILABS_HCI bool "Silicon Labs Bluetooth interface" - depends on SOC_SERIES_EFR32BG22 || SOC_SERIES_EFR32MG24 || SOC_SERIES_EFR32BG27 + default y + depends on DT_HAS_SILABS_BT_HCI_ENABLED depends on !PM || SOC_GECKO_PM_BACKEND_PMGR select SOC_GECKO_USE_RAIL select ENTROPY_GENERATOR @@ -85,6 +92,8 @@ config BT_SILABS_HCI config BT_USERCHAN bool "HCI User Channel based driver" depends on BOARD_NATIVE_POSIX + default y + depends on DT_HAS_ZEPHYR_BT_HCI_USERCHAN_ENABLED help This driver provides access to the local Linux host's Bluetooth adapter using a User Channel HCI socket to the Linux kernel. It @@ -94,39 +103,55 @@ config BT_USERCHAN config BT_ESP32 bool "ESP32 HCI driver" + default y + depends on DT_HAS_ESPRESSIF_ESP32_BT_HCI_ENABLED help Espressif HCI bluetooth interface -config BT_B91 - bool "Telink B91 HCI driver" - help - Telink B91 HCI bluetooth interface - config BT_PSOC6_BLESS bool "PSOC6 BLESS driver" + default y + depends on DT_HAS_INFINEON_CAT1_BLESS_HCI_ENABLED select BT_HCI_SETUP help PSOC6 BLESS driver with BLE Controller which operates in Single CPU mode. -config BT_NO_DRIVER - bool "No default HCI driver" - select BT_HAS_HCI_VS +config BT_DA1469X + bool "DA1469x HCI driver" + default y + depends on DT_HAS_RENESAS_BT_HCI_DA1469X_ENABLED help - This is intended for unit tests where no internal driver - should be selected. + Bluetooth HCI driver for communication with CMAC core + on DA1469x MCU. + +config BT_NXP + bool "NXP HCI driver" + default y + depends on DT_HAS_NXP_HCI_BLE_ENABLED + select BT_HCI_SETUP + help + NXP HCI bluetooth interface + +config BT_CYW208XX + bool "CYW208XX BLE driver" + default y + depends on DT_HAS_INFINEON_CYW208XX_HCI_ENABLED + help + Infineon CYW208XX HCI bluetooth interface config BT_AMBIQ_HCI bool "AMBIQ BT HCI driver" + default y + depends on DT_HAS_AMBIQ_BT_HCI_SPI_ENABLED select SPI - select GPIO - select CLOCK_CONTROL + select GPIO if SOC_SERIES_APOLLO4X + select CLOCK_CONTROL if SOC_SERIES_APOLLO4X select BT_HCI_SETUP help Supports Ambiq Bluetooth SoC using SPI as the communication protocol. HCI packets are sent and received as single Byte transfers. -endchoice if BT_SPI @@ -143,16 +168,12 @@ config BT_BLUENRG_ACI endif # BT_SPI -if BT_AMBIQ_HCI - config BT_HCI_INIT_PRIORITY int "BT HCI init priority" - default 75 + default 75 if BT_AMBIQ_HCI + default KERNEL_INIT_PRIORITY_DEVICE help - The priority of BT HCI driver initialization needs to be lower than - the SPI, GPIO, clock controller drivers initialization priorities. - -endif # BT_AMBIQ_HCI + The priority of BT HCI driver initialization. config BT_STM32_IPM_RX_STACK_SIZE int "STM32 IPM stack size for RX thread" @@ -162,16 +183,19 @@ config BT_STM32_IPM_RX_STACK_SIZE menuconfig BT_AIROC bool "AIROC BT connectivity" default y + select GPIO if BT_H4 + select UART if BT_H4 + select UART_USE_RUNTIME_CONFIGURE if BT_H4 select BT_HCI_SETUP - select UART_USE_RUNTIME_CONFIGURE - depends on GPIO - depends on DT_HAS_INFINEON_CYW43XXX_BT_HCI_ENABLED - depends on BT_H4 + select USE_INFINEON_ABSTRACTION_RTOS if BT_CYW208XX + select EVENTS if BT_CYW208XX + depends on DT_HAS_INFINEON_CYW43XXX_BT_HCI_ENABLED || DT_HAS_INFINEON_CYW208XX_HCI_ENABLED help Infineon's AIROC™ Wi-Fi & combos portfolio integrates IEEE 802.11a/b/g/n/ac/ax Wi-Fi and Bluetooth® 5.2 in a single-chip solution to enable small-form-factor IoT designs. source "drivers/bluetooth/hci/Kconfig.infineon" +source "drivers/bluetooth/hci/Kconfig.nxp" config BT_DRIVER_QUIRK_NO_AUTO_DLE bool "Host auto-initiated Data Length Update quirk" @@ -234,3 +258,33 @@ config BT_SILABS_HCI_BUFFER_MEMORY help Select the size of allocated memory buffer for the Silicon Labs Bluetooth Library. + +config BT_H4_NXP_CTLR + bool "NXP Bluetooth Controller" + select GPIO + depends on BT_H4 + select CRC + default y + depends on DT_HAS_NXP_BT_HCI_UART_ENABLED + help + Enables support for NXP Bluetooth Controller. + More inforamtion about NXP Bluetooth profuct could be found on + https://www.nxp.com/products/wireless-connectivity/wi-fi-plus-bluetooth-plus-802-15-4:WIFI-BLUETOOTH + +if BT_H4_NXP_CTLR + +config BT_H4_NXP_CTLR_WAIT_HDR_SIG_TIMEOUT + int "Timeout for waiting HDR Signure" + range 1000 60000 + default 2500 + help + Timeout for waiting HDR Signure. Unit is millisecond. + +config BT_H4_NXP_CTLR_WAIT_TIME_AFTER_UPLOAD + int "Waiting time after firmware is uploaded" + range 1000 5000 + default 1000 + help + Waiting time after firmware is uploaded. Unit is millisecond. + +endif #BT_H4_NXP_CTLR diff --git a/drivers/bluetooth/hci/Kconfig.infineon b/drivers/bluetooth/hci/Kconfig.infineon index 6204ed4f8a2fd..3e9138eb50054 100644 --- a/drivers/bluetooth/hci/Kconfig.infineon +++ b/drivers/bluetooth/hci/Kconfig.infineon @@ -4,11 +4,16 @@ if BT_AIROC +config BT_CYW43XX + bool + default y if BT_AIROC && BT_H4 + choice AIROC_PART prompt "Select AIROC part" config CYW4343W bool "CYW4343W" + depends on BT_H4 help Enable Infineon CYW4343W BLE connectivity, More information about CYW4343W device you can find on @@ -16,6 +21,7 @@ config CYW4343W config CYW4373 bool "CYW4373" + depends on BT_H4 help Enable Infineon CYW4373 BLE connectivity, More information about CYW4373 device you can find on @@ -23,6 +29,7 @@ config CYW4373 config CYW43012 bool "CYW43012" + depends on BT_H4 help Enable Infineon CYW43012 BLE connectivity, More information about CYW43012 device you can find on @@ -30,6 +37,7 @@ config CYW43012 config CYW43438 bool "CYW43438" + depends on BT_H4 help Enable Infineon CYW43438 BLE connectivity, More information about CYW43438 device you can find on @@ -37,11 +45,20 @@ config CYW43438 config CYW43439 bool "CYW43439" + depends on BT_H4 help Enable Infineon CYW43439 BLE connectivity, More information about CYW43439 device you can find on https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-wi-fi-plus-bluetooth-combos/cyw43439/ +config CYW20829 + bool "CYW20829" + depends on BT_CYW208XX + help + Enable Infineon CYW20829 BLE connectivity, + More information about CYW20829 device you can find on + https://www.infineon.com/cms/en/product/wireless-connectivity/airoc-bluetooth-le-bluetooth-multiprotocol/airoc-bluetooth-le/cyw20829/ + config BT_AIROC_CUSTOM bool "Custom AIROC device/module" help @@ -92,11 +109,11 @@ choice CYW4373_MODULE config CYW4373_STERLING_LWB5PLUS bool "STERLING-LWB5plus" help - Laird Sterling LWB5+ 802.11ac / Bluetooth 5.0 M.2 Carrier Board + Ezurio Sterling LWB5+ 802.11ac / Bluetooth 5.0 M.2 Carrier Board (E-Type Key w/ SDIO/UART) Detailed information about Type Sterling LWB5+ module you can find on - https://www.lairdconnect.com/wireless-modules/wifi-modules-bluetooth/sterling-lwb5-plus-wifi-5-bluetooth-5-module + https://www.ezurio.com/wireless-modules/wifi-modules-bluetooth/sterling-lwb5-plus-wifi-5-bluetooth-5-module endchoice @@ -117,6 +134,61 @@ config CYW43439_MURATA_1YN endchoice +if CYW20829 + +config CYW20829_BT_FW_TX10DBM_POWER + bool "CYW20829_BT_FW_TX10DBM_POWER" + help + Enable 10dBm TX Power variant of CYW20829 FW patch. + +choice CYW20829_BT_FW + prompt "Select variant of default CYW20829 BT FW" + default CYW20829_BT_FW_ISOC_TX10 if BT_ISO && CYW20829_BT_FW_TX10DBM_POWER + default CYW20829_BT_FW_ISOC_TX0 if BT_ISO && !CYW20829_BT_FW_TX10DBM_POWER + default CYW20829_BT_FW_PAWR_TX10 if BT_PER_ADV_RSP && CYW20829_BT_FW_TX10DBM_POWER + default CYW20829_BT_FW_PAWR_TX0 if BT_PER_ADV_RSP && !CYW20829_BT_FW_TX10DBM_POWER + default CYW20829_BT_FW_TX10 if CYW20829_BT_FW_TX10DBM_POWER + default CYW20829_BT_FW_TX0 + +config CYW20829_BT_FW_TX0 + bool "CYW20829_BT_FW_TX0" + help + Enable CYW20829 FW patch for 0dBm TX Power. + This configuration should be used with non-PAWR and non-ISOC applications. + +config CYW20829_BT_FW_TX10 + bool "CYW20829_BT_FW_TX10" + help + Enable CYW20829 FW patch for 10dBm TX Power. + This configuration should be used with non-PAwR and non-ISOC applications. + +config CYW20829_BT_FW_PAWR_TX0 + bool "CYW20829_BT_FW_PAWR_TX0" + help + Enable CYW20829 FW patch with PAwR support for 0dBm TX Power. + This configuration should be used with PAwR applications. + +config CYW20829_BT_FW_PAWR_TX10 + bool "CYW20829_BT_FW_PAWR_TX10" + help + Enable CYW20829 FW patch for 10dBm TX Power. + This configuration should be used with PAwR applications. + +config CYW20829_BT_FW_ISOC_TX0 + bool "CYW20829_BT_FW_ISOC_TX0" + help + Enable CYW20829 FW patch for 0dBm TX Power. + This configuration should be used with ISOC applications. + +config CYW20829_BT_FW_ISOC_TX10 + bool "CYW20829_BT_FW_ISOC_TX10" + help + Enable CYW20829 FW patch for 10dBm TX Power. + This configuration should be used with ISOC applications. + +endchoice +endif # CYW20829 + config AIROC_CUSTOM_FIRMWARE_HCD_BLOB depends on BT_AIROC_CUSTOM string "Path to user BT firmware HCD file" diff --git a/drivers/bluetooth/hci/Kconfig.nxp b/drivers/bluetooth/hci/Kconfig.nxp new file mode 100644 index 0000000000000..65bbc3067e76d --- /dev/null +++ b/drivers/bluetooth/hci/Kconfig.nxp @@ -0,0 +1,40 @@ +# +# Copyright 2023-2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +config HCI_NXP_ENABLE_AUTO_SLEEP + bool "BLE Controller auto sleep mode" + help + If enabled, the Controller auto sleep mode will be configured and enabled during HCI init. + Auto sleep mode means the Controller will handle its low power state automatically. + Enabling this feature will allow to save power at the cost of some latency when sending a HCI + message to the Controller as the Host will need to wake it up. + +config HCI_NXP_SET_CAL_DATA + bool "BLE Controller calibration data" + help + If enabled, the Host will send calibration data to the BLE Controller during HCI init. + +config HCI_NXP_SET_CAL_DATA_ANNEX100 + bool "BLE Controller calibration data annex 100" + help + If enabled, the Host will send calibration data annex 100 to the BLE Controller during HCI + init. + +if BT_H4_NXP_CTLR + +config BT_NXP_NW612 + bool "NXP IW612 Chipset" + help + NXP IW612 Chipset supports Wi-Fi? 802.11a/b/g/n/ac/ax + Bluetooth? 5.3 + BR/EDR/LE + IEEE802.1.5.4 up to 601 Mbps data rate on Wi-Fi? and 2Mbps + data rate on Bluetooth?. 4-wire UART@3M baud is supported. PCM for + audio is also supported. + Details of the module could be fond on https://www.nxp.com/products/ + wireless-connectivity/wi-fi-plus-bluetooth-plus-802-15-4/2-4-5-ghz- + dual-band-1x1-wi-fi-6-802-11ax-plus-bluetooth-5-4-plus-802-15-4-tri- + radio-solution:IW612. + +endif # BT_H4_NXP_CTLR diff --git a/drivers/bluetooth/hci/apollox_blue.c b/drivers/bluetooth/hci/apollox_blue.c index eff8d8fbd8125..7994069a5a2a4 100644 --- a/drivers/bluetooth/hci/apollox_blue.c +++ b/drivers/bluetooth/hci/apollox_blue.c @@ -14,7 +14,7 @@ #include #include #include -#include +#include #include #include @@ -25,8 +25,13 @@ LOG_MODULE_REGISTER(bt_apollox_driver); #include #include +#include #include "apollox_blue.h" +#if (CONFIG_SOC_SERIES_APOLLO4X) #include "am_devices_cooper.h" +#elif (CONFIG_SOC_SERIES_APOLLO3X) +#include "am_apollo3_bt_support.h" +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ #define HCI_SPI_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(ambiq_bt_hci_spi) #define SPI_DEV_NODE DT_BUS(HCI_SPI_NODE) @@ -44,6 +49,7 @@ LOG_MODULE_REGISTER(bt_apollox_driver); #define SPI_MAX_RX_MSG_LEN 258 +#if (CONFIG_SOC_SERIES_APOLLO4X) static const struct gpio_dt_spec irq_gpio = GPIO_DT_SPEC_GET(HCI_SPI_NODE, irq_gpios); static const struct gpio_dt_spec rst_gpio = GPIO_DT_SPEC_GET(HCI_SPI_NODE, reset_gpios); static const struct gpio_dt_spec cs_gpio = GPIO_DT_SPEC_GET(SPI_DEV_NODE, cs_gpios); @@ -54,10 +60,19 @@ static struct gpio_callback clkreq_gpio_cb; static const struct device *clk32m_dev = DEVICE_DT_GET(CLK_32M_NODE); static const struct device *clk32k_dev = DEVICE_DT_GET(CLK_32K_NODE); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ extern void bt_packet_irq_isr(const struct device *unused1, struct gpio_callback *unused2, uint32_t unused3); +void bt_apollo_rcv_isr_preprocess(void) +{ +#if (CONFIG_SOC_SERIES_APOLLO3X) + am_apollo3_bt_isr_pre(); +#endif /* CONFIG_SOC_SERIES_APOLLO3X */ +} + +#if (CONFIG_SOC_SERIES_APOLLO4X) static bool irq_pin_state(void) { int pin_state; @@ -117,10 +132,13 @@ static void bt_apollo_controller_reset(void) /* Give the controller some time to boot */ k_sleep(K_MSEC(500)); } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ int bt_apollo_spi_send(uint8_t *data, uint16_t len, bt_spi_transceive_fun transceive) { - int ret; + int ret = -ENOTSUP; + +#if (CONFIG_SOC_SERIES_APOLLO4X) uint8_t command[1] = {SPI_WRITE}; uint8_t response[2] = {0, 0}; uint16_t fail_count = 0; @@ -139,18 +157,24 @@ int bt_apollo_spi_send(uint8_t *data, uint16_t len, bt_spi_transceive_fun transc break; } } while (fail_count++ < SPI_WRITE_TIMEOUT); +#elif (CONFIG_SOC_SERIES_APOLLO3X) + ret = transceive(data, len, NULL, 0); + if ((ret) && (ret != AM_HAL_BLE_STATUS_SPI_NOT_READY)) { + LOG_ERR("SPI write error %d", ret); + } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ return ret; } int bt_apollo_spi_rcv(uint8_t *data, uint16_t *len, bt_spi_transceive_fun transceive) { - int ret; - uint8_t command[1] = {SPI_READ}; + int ret = -ENOTSUP; uint8_t response[2] = {0, 0}; uint16_t read_size = 0; do { +#if (CONFIG_SOC_SERIES_APOLLO4X) /* Skip if the IRQ pin is not in high state */ if (!irq_pin_state()) { ret = -1; @@ -158,10 +182,26 @@ int bt_apollo_spi_rcv(uint8_t *data, uint16_t *len, bt_spi_transceive_fun transc } /* Check the available packet bytes */ + uint8_t command[1] = {SPI_READ}; ret = transceive(command, 1, response, 2); if (ret) { break; } +#elif (CONFIG_SOC_SERIES_APOLLO3X) + /* Skip if the IRQ bit is not set */ + if (!BLEIFn(0)->BSTATUS_b.BLEIRQ) { + ret = -1; + break; + } + + /* Check the available packet bytes */ + ret = transceive(NULL, 0, response, 2); + if (ret) { + break; + } +#else + break; +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ /* Check if the read size is acceptable */ read_size = (uint16_t)(response[0] | response[1] << 8); @@ -186,6 +226,7 @@ int bt_apollo_spi_rcv(uint8_t *data, uint16_t *len, bt_spi_transceive_fun transc bool bt_apollo_vnd_rcv_ongoing(uint8_t *data, uint16_t len) { +#if (CONFIG_SOC_SERIES_APOLLO4X) /* The vendor specific handshake command/response is incompatible with * standard Bluetooth HCI format, need to handle the received packets * specifically. @@ -196,14 +237,18 @@ bool bt_apollo_vnd_rcv_ongoing(uint8_t *data, uint16_t len) } else { return false; } +#else + return false; +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ } int bt_hci_transport_setup(const struct device *dev) { ARG_UNUSED(dev); - int ret; + int ret = 0; +#if (CONFIG_SOC_SERIES_APOLLO4X) /* Configure the XO32MHz and XO32kHz clocks.*/ clock_control_configure(clk32k_dev, NULL, NULL); clock_control_configure(clk32m_dev, NULL, NULL); @@ -256,13 +301,18 @@ int bt_hci_transport_setup(const struct device *dev) /* Configure the interrupt edge for IRQ pin */ gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_RISING); +#elif (CONFIG_SOC_SERIES_APOLLO3X) + IRQ_CONNECT(DT_IRQN(SPI_DEV_NODE), DT_IRQ(SPI_DEV_NODE, priority), bt_packet_irq_isr, 0, 0); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ - return 0; + return ret; } int bt_apollo_controller_init(spi_transmit_fun transmit) { - int ret; + int ret = 0; + +#if (CONFIG_SOC_SERIES_APOLLO4X) am_devices_cooper_callback_t cb = { .write = transmit, .reset = bt_apollo_controller_reset, @@ -277,10 +327,21 @@ int bt_apollo_controller_init(spi_transmit_fun transmit) am_devices_cooper_set_initialize_state(AM_DEVICES_COOPER_STATE_INITIALIZE_FAIL); LOG_ERR("BT controller initialization fail"); } +#elif (CONFIG_SOC_SERIES_APOLLO3X) + ret = am_apollo3_bt_controller_init(); + if (ret == AM_HAL_STATUS_SUCCESS) { + LOG_INF("BT controller initialized"); + } else { + LOG_ERR("BT controller initialization fail"); + } + + irq_enable(DT_IRQN(SPI_DEV_NODE)); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ return ret; } +#if (CONFIG_SOC_SERIES_APOLLO4X) static int bt_apollo_set_nvds(void) { int ret; @@ -334,19 +395,23 @@ static int bt_apollo_set_nvds(void) return ret; } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ int bt_apollo_vnd_setup(void) { - int ret; + int ret = 0; +#if (CONFIG_SOC_SERIES_APOLLO4X) /* Set the NVDS parameters to BLE controller */ ret = bt_apollo_set_nvds(); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ return ret; } int bt_apollo_dev_init(void) { +#if (CONFIG_SOC_SERIES_APOLLO4X) if (!gpio_is_ready_dt(&irq_gpio)) { LOG_ERR("IRQ GPIO device not ready"); return -ENODEV; @@ -361,6 +426,7 @@ int bt_apollo_dev_init(void) LOG_ERR("CLKREQ GPIO device not ready"); return -ENODEV; } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ return 0; } diff --git a/drivers/bluetooth/hci/apollox_blue.h b/drivers/bluetooth/hci/apollox_blue.h index a05238657e5a5..85e586d790856 100644 --- a/drivers/bluetooth/hci/apollox_blue.h +++ b/drivers/bluetooth/hci/apollox_blue.h @@ -98,6 +98,12 @@ int bt_apollo_vnd_setup(void); */ bool bt_apollo_vnd_rcv_ongoing(uint8_t *data, uint16_t len); +/** + * @brief Do the specific preprocessing in HCI packet receiving ISR if needed, + * for example, clear the interrupt status. + */ +void bt_apollo_rcv_isr_preprocess(void); + #ifdef __cplusplus } #endif diff --git a/drivers/bluetooth/hci/cyw43xxx.c b/drivers/bluetooth/hci/cyw43xxx.c deleted file mode 100644 index 8da6192610dbe..0000000000000 --- a/drivers/bluetooth/hci/cyw43xxx.c +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or - * an affiliate of Cypress Semiconductor Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @brief CYW43xxx HCI extension driver. - */ - -#include -#include - -#include -#include -#include -#include -#include -#include - -#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL -#include -LOG_MODULE_REGISTER(cyw43xxx_driver); - -#include - -BUILD_ASSERT(DT_PROP(DT_CHOSEN(zephyr_bt_uart), hw_flow_control) == 1, - "hw_flow_control must be enabled for HCI H4 UART"); - -#define DT_DRV_COMPAT infineon_cyw43xxx_bt_hci - -/* BT settling time after power on */ -#define BT_POWER_ON_SETTLING_TIME_MS (500u) - -/* Stabilization delay after FW loading */ -#define BT_STABILIZATION_DELAY_MS (250u) - -/* HCI Command packet from Host to Controller */ -#define HCI_COMMAND_PACKET (0x01) - -/* Length of UPDATE BAUD RATE command */ -#define HCI_VSC_UPDATE_BAUD_RATE_LENGTH (6u) - -/* Default BAUDRATE */ -#define HCI_UART_DEFAULT_BAUDRATE (115200) - -/* Externs for CY43xxx controller FW */ -extern const uint8_t brcm_patchram_buf[]; -extern const int brcm_patch_ram_length; - -enum { - BT_HCI_VND_OP_DOWNLOAD_MINIDRIVER = 0xFC2E, - BT_HCI_VND_OP_WRITE_RAM = 0xFC4C, - BT_HCI_VND_OP_LAUNCH_RAM = 0xFC4E, - BT_HCI_VND_OP_UPDATE_BAUDRATE = 0xFC18, -}; - -/* bt_h4_vnd_setup function. - * This function executes vendor-specific commands sequence to - * initialize BT Controller before BT Host executes Reset sequence. - * bt_h4_vnd_setup function must be implemented in vendor-specific HCI - * extansion module if CONFIG_BT_HCI_SETUP is enabled. - */ -int bt_h4_vnd_setup(const struct device *dev); - -static int bt_hci_uart_set_baudrate(const struct device *bt_uart_dev, uint32_t baudrate) -{ - struct uart_config uart_cfg; - int err; - - /* Get current UART configuration */ - err = uart_config_get(bt_uart_dev, &uart_cfg); - if (err) { - return err; - } - - if (uart_cfg.baudrate != baudrate) { - /* Re-configure UART */ - uart_cfg.baudrate = baudrate; - err = uart_configure(bt_uart_dev, &uart_cfg); - if (err) { - return err; - } - - /* Revert Interrupt options */ - uart_irq_rx_enable(bt_uart_dev); - } - return 0; -} - -static int bt_update_controller_baudrate(const struct device *bt_uart_dev, uint32_t baudrate) -{ - /* - * NOTE from datasheet for update baudrate: - * - To speed up application downloading, the MCU host commands the CYWxxx device - * to communicate at a new, higher rate by issuing the following Vendor Specific - * UPDATE_BAUDRATE command: - * 01 18 FC 06 00 00 xx xx xx xx - * In the above command, the xx xx xx xx bytes specify the 32-bit little-endian - * value of the new rate in bits per second. For example, - * 115200 is represented as 00 C2 01 00. - * The following response to the UPDATE_BAUDRATE command is expected within 100 ms: - * 04 0E 04 01 18 FC 00 - * - The host switches to the new baud rate after receiving the response at the old - * baud rate. - */ - struct net_buf *buf; - int err; - uint8_t hci_data[HCI_VSC_UPDATE_BAUD_RATE_LENGTH]; - - /* Baudrate is loaded LittleEndian */ - hci_data[0] = 0; - hci_data[1] = 0; - hci_data[2] = (uint8_t)(baudrate & 0xFFUL); - hci_data[3] = (uint8_t)((baudrate >> 8) & 0xFFUL); - hci_data[4] = (uint8_t)((baudrate >> 16) & 0xFFUL); - hci_data[5] = (uint8_t)((baudrate >> 24) & 0xFFUL); - - /* Allocate buffer for update uart baudrate command. - * It will be BT_HCI_OP_RESET with extra parameters. - */ - buf = bt_hci_cmd_create(BT_HCI_VND_OP_UPDATE_BAUDRATE, - HCI_VSC_UPDATE_BAUD_RATE_LENGTH); - if (buf == NULL) { - LOG_ERR("Unable to allocate command buffer"); - return -ENOMEM; - } - - /* Add data part of packet */ - net_buf_add_mem(buf, &hci_data, HCI_VSC_UPDATE_BAUD_RATE_LENGTH); - - /* Send update uart baudrate command. */ - err = bt_hci_cmd_send_sync(BT_HCI_VND_OP_UPDATE_BAUDRATE, buf, NULL); - if (err) { - return err; - } - - /* Re-configure Uart baudrate */ - err = bt_hci_uart_set_baudrate(bt_uart_dev, baudrate); - if (err) { - return err; - } - - return 0; -} - -static int bt_firmware_download(const uint8_t *firmware_image, uint32_t size) -{ - uint8_t *data = (uint8_t *)firmware_image; - volatile uint32_t remaining_length = size; - struct net_buf *buf; - int err; - - LOG_DBG("Executing Fw downloading for CYW43xx device"); - - /* Send hci_download_minidriver command */ - err = bt_hci_cmd_send_sync(BT_HCI_VND_OP_DOWNLOAD_MINIDRIVER, NULL, NULL); - if (err) { - return err; - } - - /* The firmware image (.hcd format) contains a collection of hci_write_ram - * command + a block of the image, followed by a hci_write_ram image at the end. - * Parse and send each individual command and wait for the response. This is to - * ensure the integrity of the firmware image sent to the bluetooth chip. - */ - while (remaining_length) { - size_t data_length = data[2]; /* data length from firmware image block */ - uint16_t op_code = *(uint16_t *)data; - - /* Allocate buffer for hci_write_ram/hci_launch_ram command. */ - buf = bt_hci_cmd_create(op_code, data_length); - if (buf == NULL) { - LOG_ERR("Unable to allocate command buffer"); - return err; - } - - /* Add data part of packet */ - net_buf_add_mem(buf, &data[3], data_length); - - /* Send hci_write_ram command. */ - err = bt_hci_cmd_send_sync(op_code, buf, NULL); - if (err) { - return err; - } - - switch (op_code) { - case BT_HCI_VND_OP_WRITE_RAM: - /* Update remaining length and data pointer: - * content of data length + 2 bytes of opcode and 1 byte of data length. - */ - data += data_length + 3; - remaining_length -= data_length + 3; - break; - - case BT_HCI_VND_OP_LAUNCH_RAM: - remaining_length = 0; - break; - - default: - return -ENOMEM; - } - } - - LOG_DBG("Fw downloading complete"); - return 0; -} - -int bt_h4_vnd_setup(const struct device *dev) -{ - int err; - uint32_t default_uart_speed = DT_PROP(DT_INST_BUS(0), current_speed); - uint32_t hci_operation_speed = DT_INST_PROP_OR(0, hci_operation_speed, default_uart_speed); - uint32_t fw_download_speed = DT_INST_PROP_OR(0, fw_download_speed, default_uart_speed); - - /* Check BT Uart instance */ - if (!device_is_ready(dev)) { - return -EINVAL; - } - -#if DT_INST_NODE_HAS_PROP(0, bt_reg_on_gpios) - struct gpio_dt_spec bt_reg_on = GPIO_DT_SPEC_GET(DT_DRV_INST(0), bt_reg_on_gpios); - - /* Check BT REG_ON gpio instance */ - if (!gpio_is_ready_dt(&bt_reg_on)) { - LOG_ERR("Error: failed to configure bt_reg_on %s pin %d", - bt_reg_on.port->name, bt_reg_on.pin); - return -EIO; - } - - /* Configure bt_reg_on as output */ - err = gpio_pin_configure_dt(&bt_reg_on, GPIO_OUTPUT); - if (err) { - LOG_ERR("Error %d: failed to configure bt_reg_on %s pin %d", - err, bt_reg_on.port->name, bt_reg_on.pin); - return err; - } - err = gpio_pin_set_dt(&bt_reg_on, 1); - if (err) { - return err; - } -#endif /* DT_INST_NODE_HAS_PROP(0, bt_reg_on_gpios) */ - - /* BT settling time after power on */ - (void)k_msleep(BT_POWER_ON_SETTLING_TIME_MS); - - /* Send HCI_RESET */ - err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, NULL); - if (err) { - return err; - } - - /* Re-configure baudrate for BT Controller */ - if (fw_download_speed != default_uart_speed) { - err = bt_update_controller_baudrate(dev, fw_download_speed); - if (err) { - return err; - } - } - - /* BT firmware download */ - err = bt_firmware_download(brcm_patchram_buf, (uint32_t) brcm_patch_ram_length); - if (err) { - return err; - } - - /* Stabilization delay */ - (void)k_msleep(BT_STABILIZATION_DELAY_MS); - - /* When FW launched, HCI UART baudrate should be configured to default */ - if (fw_download_speed != default_uart_speed) { - err = bt_hci_uart_set_baudrate(dev, default_uart_speed); - if (err) { - return err; - } - } - - /* Send HCI_RESET */ - err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, NULL); - if (err) { - return err; - } - - /* Set host controller functionality to user defined baudrate - * after fw downloading. - */ - if (hci_operation_speed != default_uart_speed) { - err = bt_update_controller_baudrate(dev, hci_operation_speed); - if (err) { - return err; - } - } - - return 0; -} diff --git a/drivers/bluetooth/hci/h4.c b/drivers/bluetooth/hci/h4.c index 16b28b52586a3..412214c7f3224 100644 --- a/drivers/bluetooth/hci/h4.c +++ b/drivers/bluetooth/hci/h4.c @@ -20,7 +20,7 @@ #include #include -#include +#include #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL #include @@ -30,168 +30,183 @@ LOG_MODULE_REGISTER(bt_driver); #include "../util.h" -static K_KERNEL_STACK_DEFINE(rx_thread_stack, CONFIG_BT_DRV_RX_STACK_SIZE); -static struct k_thread rx_thread_data; +#define DT_DRV_COMPAT zephyr_bt_hci_uart -static struct { - struct net_buf *buf; - struct k_fifo fifo; +struct h4_data { + struct { + struct net_buf *buf; + struct k_fifo fifo; - uint16_t remaining; - uint16_t discard; + uint16_t remaining; + uint16_t discard; - bool have_hdr; - bool discardable; + bool have_hdr; + bool discardable; - uint8_t hdr_len; + uint8_t hdr_len; - uint8_t type; - union { - struct bt_hci_evt_hdr evt; - struct bt_hci_acl_hdr acl; - struct bt_hci_iso_hdr iso; - uint8_t hdr[4]; - }; -} rx = { - .fifo = Z_FIFO_INITIALIZER(rx.fifo), -}; + uint8_t type; + union { + struct bt_hci_evt_hdr evt; + struct bt_hci_acl_hdr acl; + struct bt_hci_iso_hdr iso; + uint8_t hdr[4]; + }; + } rx; -static struct { - uint8_t type; - struct net_buf *buf; - struct k_fifo fifo; -} tx = { - .fifo = Z_FIFO_INITIALIZER(tx.fifo), + struct { + uint8_t type; + struct net_buf *buf; + struct k_fifo fifo; + } tx; + + bt_hci_recv_t recv; }; -static const struct device *const h4_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_uart)); +struct h4_config { + const struct device *uart; + k_thread_stack_t *rx_thread_stack; + size_t rx_thread_stack_size; + struct k_thread *rx_thread; +}; -static inline void h4_get_type(void) +static inline void h4_get_type(const struct device *dev) { + const struct h4_config *cfg = dev->config; + struct h4_data *h4 = dev->data; + /* Get packet type */ - if (uart_fifo_read(h4_dev, &rx.type, 1) != 1) { + if (uart_fifo_read(cfg->uart, &h4->rx.type, 1) != 1) { LOG_WRN("Unable to read H:4 packet type"); - rx.type = BT_HCI_H4_NONE; + h4->rx.type = BT_HCI_H4_NONE; return; } - switch (rx.type) { + switch (h4->rx.type) { case BT_HCI_H4_EVT: - rx.remaining = sizeof(rx.evt); - rx.hdr_len = rx.remaining; + h4->rx.remaining = sizeof(h4->rx.evt); + h4->rx.hdr_len = h4->rx.remaining; break; case BT_HCI_H4_ACL: - rx.remaining = sizeof(rx.acl); - rx.hdr_len = rx.remaining; + h4->rx.remaining = sizeof(h4->rx.acl); + h4->rx.hdr_len = h4->rx.remaining; break; case BT_HCI_H4_ISO: if (IS_ENABLED(CONFIG_BT_ISO)) { - rx.remaining = sizeof(rx.iso); - rx.hdr_len = rx.remaining; + h4->rx.remaining = sizeof(h4->rx.iso); + h4->rx.hdr_len = h4->rx.remaining; break; } __fallthrough; default: - LOG_ERR("Unknown H:4 type 0x%02x", rx.type); - rx.type = BT_HCI_H4_NONE; + LOG_ERR("Unknown H:4 type 0x%02x", h4->rx.type); + h4->rx.type = BT_HCI_H4_NONE; } } -static void h4_read_hdr(void) +static void h4_read_hdr(const struct device *dev) { - int bytes_read = rx.hdr_len - rx.remaining; + const struct h4_config *cfg = dev->config; + struct h4_data *h4 = dev->data; + int bytes_read = h4->rx.hdr_len - h4->rx.remaining; int ret; - ret = uart_fifo_read(h4_dev, rx.hdr + bytes_read, rx.remaining); + ret = uart_fifo_read(cfg->uart, h4->rx.hdr + bytes_read, h4->rx.remaining); if (unlikely(ret < 0)) { LOG_ERR("Unable to read from UART (ret %d)", ret); } else { - rx.remaining -= ret; + h4->rx.remaining -= ret; } } -static inline void get_acl_hdr(void) +static inline void get_acl_hdr(const struct device *dev) { - h4_read_hdr(); + struct h4_data *h4 = dev->data; - if (!rx.remaining) { - struct bt_hci_acl_hdr *hdr = &rx.acl; + h4_read_hdr(dev); - rx.remaining = sys_le16_to_cpu(hdr->len); - LOG_DBG("Got ACL header. Payload %u bytes", rx.remaining); - rx.have_hdr = true; + if (!h4->rx.remaining) { + struct bt_hci_acl_hdr *hdr = &h4->rx.acl; + + h4->rx.remaining = sys_le16_to_cpu(hdr->len); + LOG_DBG("Got ACL header. Payload %u bytes", h4->rx.remaining); + h4->rx.have_hdr = true; } } -static inline void get_iso_hdr(void) +static inline void get_iso_hdr(const struct device *dev) { - h4_read_hdr(); + struct h4_data *h4 = dev->data; + + h4_read_hdr(dev); - if (!rx.remaining) { - struct bt_hci_iso_hdr *hdr = &rx.iso; + if (!h4->rx.remaining) { + struct bt_hci_iso_hdr *hdr = &h4->rx.iso; - rx.remaining = bt_iso_hdr_len(sys_le16_to_cpu(hdr->len)); - LOG_DBG("Got ISO header. Payload %u bytes", rx.remaining); - rx.have_hdr = true; + h4->rx.remaining = bt_iso_hdr_len(sys_le16_to_cpu(hdr->len)); + LOG_DBG("Got ISO header. Payload %u bytes", h4->rx.remaining); + h4->rx.have_hdr = true; } } -static inline void get_evt_hdr(void) +static inline void get_evt_hdr(const struct device *dev) { - struct bt_hci_evt_hdr *hdr = &rx.evt; + struct h4_data *h4 = dev->data; + + struct bt_hci_evt_hdr *hdr = &h4->rx.evt; - h4_read_hdr(); + h4_read_hdr(dev); - if (rx.hdr_len == sizeof(*hdr) && rx.remaining < sizeof(*hdr)) { - switch (rx.evt.evt) { + if (h4->rx.hdr_len == sizeof(*hdr) && h4->rx.remaining < sizeof(*hdr)) { + switch (h4->rx.evt.evt) { case BT_HCI_EVT_LE_META_EVENT: - rx.remaining++; - rx.hdr_len++; + h4->rx.remaining++; + h4->rx.hdr_len++; break; #if defined(CONFIG_BT_CLASSIC) case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI: case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT: - rx.discardable = true; + h4->rx.discardable = true; break; #endif } } - if (!rx.remaining) { - if (rx.evt.evt == BT_HCI_EVT_LE_META_EVENT && - (rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { + if (!h4->rx.remaining) { + if (h4->rx.evt.evt == BT_HCI_EVT_LE_META_EVENT && + (h4->rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { LOG_DBG("Marking adv report as discardable"); - rx.discardable = true; + h4->rx.discardable = true; } - rx.remaining = hdr->len - (rx.hdr_len - sizeof(*hdr)); + h4->rx.remaining = hdr->len - (h4->rx.hdr_len - sizeof(*hdr)); LOG_DBG("Got event header. Payload %u bytes", hdr->len); - rx.have_hdr = true; + h4->rx.have_hdr = true; } } -static inline void copy_hdr(struct net_buf *buf) +static inline void copy_hdr(struct h4_data *h4) { - net_buf_add_mem(buf, rx.hdr, rx.hdr_len); + net_buf_add_mem(h4->rx.buf, h4->rx.hdr, h4->rx.hdr_len); } -static void reset_rx(void) +static void reset_rx(struct h4_data *h4) { - rx.type = BT_HCI_H4_NONE; - rx.remaining = 0U; - rx.have_hdr = false; - rx.hdr_len = 0U; - rx.discardable = false; + h4->rx.type = BT_HCI_H4_NONE; + h4->rx.remaining = 0U; + h4->rx.have_hdr = false; + h4->rx.hdr_len = 0U; + h4->rx.discardable = false; } -static struct net_buf *get_rx(k_timeout_t timeout) +static struct net_buf *get_rx(struct h4_data *h4, k_timeout_t timeout) { - LOG_DBG("type 0x%02x, evt 0x%02x", rx.type, rx.evt.evt); + LOG_DBG("type 0x%02x, evt 0x%02x", h4->rx.type, h4->rx.evt.evt); - switch (rx.type) { + switch (h4->rx.type) { case BT_HCI_H4_EVT: - return bt_buf_get_evt(rx.evt.evt, rx.discardable, timeout); + return bt_buf_get_evt(h4->rx.evt.evt, h4->rx.discardable, timeout); case BT_HCI_H4_ACL: return bt_buf_get_rx(BT_BUF_ACL_IN, timeout); case BT_HCI_H4_ISO: @@ -205,42 +220,44 @@ static struct net_buf *get_rx(k_timeout_t timeout) static void rx_thread(void *p1, void *p2, void *p3) { + const struct device *dev = p1; + const struct h4_config *cfg = dev->config; + struct h4_data *h4 = dev->data; struct net_buf *buf; - ARG_UNUSED(p1); ARG_UNUSED(p2); ARG_UNUSED(p3); LOG_DBG("started"); while (1) { - LOG_DBG("rx.buf %p", rx.buf); + LOG_DBG("rx.buf %p", h4->rx.buf); /* We can only do the allocation if we know the initial * header, since Command Complete/Status events must use the * original command buffer (if available). */ - if (rx.have_hdr && !rx.buf) { - rx.buf = get_rx(K_FOREVER); - LOG_DBG("Got rx.buf %p", rx.buf); - if (rx.remaining > net_buf_tailroom(rx.buf)) { + if (h4->rx.have_hdr && !h4->rx.buf) { + h4->rx.buf = get_rx(h4, K_FOREVER); + LOG_DBG("Got rx.buf %p", h4->rx.buf); + if (h4->rx.remaining > net_buf_tailroom(h4->rx.buf)) { LOG_ERR("Not enough space in buffer"); - rx.discard = rx.remaining; - reset_rx(); + h4->rx.discard = h4->rx.remaining; + reset_rx(h4); } else { - copy_hdr(rx.buf); + copy_hdr(h4); } } /* Let the ISR continue receiving new packets */ - uart_irq_rx_enable(h4_dev); + uart_irq_rx_enable(cfg->uart); - buf = net_buf_get(&rx.fifo, K_FOREVER); + buf = net_buf_get(&h4->rx.fifo, K_FOREVER); do { - uart_irq_rx_enable(h4_dev); + uart_irq_rx_enable(cfg->uart); LOG_DBG("Calling bt_recv(%p)", buf); - bt_recv(buf); + h4->recv(dev, buf); /* Give other threads a chance to run if the ISR * is receiving data so fast that rx.fifo never @@ -248,8 +265,8 @@ static void rx_thread(void *p1, void *p2, void *p3) */ k_yield(); - uart_irq_rx_disable(h4_dev); - buf = net_buf_get(&rx.fifo, K_NO_WAIT); + uart_irq_rx_disable(cfg->uart); + buf = net_buf_get(&h4->rx.fifo, K_NO_WAIT); } while (buf); } } @@ -268,87 +285,93 @@ static size_t h4_discard(const struct device *uart, size_t len) return err; } -static inline void read_payload(void) +static inline void read_payload(const struct device *dev) { + const struct h4_config *cfg = dev->config; + struct h4_data *h4 = dev->data; struct net_buf *buf; int read; - if (!rx.buf) { + if (!h4->rx.buf) { size_t buf_tailroom; - rx.buf = get_rx(K_NO_WAIT); - if (!rx.buf) { - if (rx.discardable) { - LOG_WRN("Discarding event 0x%02x", rx.evt.evt); - rx.discard = rx.remaining; - reset_rx(); + h4->rx.buf = get_rx(h4, K_NO_WAIT); + if (!h4->rx.buf) { + if (h4->rx.discardable) { + LOG_WRN("Discarding event 0x%02x", h4->rx.evt.evt); + h4->rx.discard = h4->rx.remaining; + reset_rx(h4); return; } LOG_WRN("Failed to allocate, deferring to rx_thread"); - uart_irq_rx_disable(h4_dev); + uart_irq_rx_disable(cfg->uart); return; } - LOG_DBG("Allocated rx.buf %p", rx.buf); + LOG_DBG("Allocated rx.buf %p", h4->rx.buf); - buf_tailroom = net_buf_tailroom(rx.buf); - if (buf_tailroom < rx.remaining) { - LOG_ERR("Not enough space in buffer %u/%zu", rx.remaining, buf_tailroom); - rx.discard = rx.remaining; - reset_rx(); + buf_tailroom = net_buf_tailroom(h4->rx.buf); + if (buf_tailroom < h4->rx.remaining) { + LOG_ERR("Not enough space in buffer %u/%zu", h4->rx.remaining, + buf_tailroom); + h4->rx.discard = h4->rx.remaining; + reset_rx(h4); return; } - copy_hdr(rx.buf); + copy_hdr(h4); } - read = uart_fifo_read(h4_dev, net_buf_tail(rx.buf), rx.remaining); + read = uart_fifo_read(cfg->uart, net_buf_tail(h4->rx.buf), h4->rx.remaining); if (unlikely(read < 0)) { LOG_ERR("Failed to read UART (err %d)", read); return; } - net_buf_add(rx.buf, read); - rx.remaining -= read; + net_buf_add(h4->rx.buf, read); + h4->rx.remaining -= read; - LOG_DBG("got %d bytes, remaining %u", read, rx.remaining); - LOG_DBG("Payload (len %u): %s", rx.buf->len, bt_hex(rx.buf->data, rx.buf->len)); + LOG_DBG("got %d bytes, remaining %u", read, h4->rx.remaining); + LOG_DBG("Payload (len %u): %s", h4->rx.buf->len, + bt_hex(h4->rx.buf->data, h4->rx.buf->len)); - if (rx.remaining) { + if (h4->rx.remaining) { return; } - buf = rx.buf; - rx.buf = NULL; + buf = h4->rx.buf; + h4->rx.buf = NULL; - if (rx.type == BT_HCI_H4_EVT) { + if (h4->rx.type == BT_HCI_H4_EVT) { bt_buf_set_type(buf, BT_BUF_EVT); } else { bt_buf_set_type(buf, BT_BUF_ACL_IN); } - reset_rx(); + reset_rx(h4); LOG_DBG("Putting buf %p to rx fifo", buf); - net_buf_put(&rx.fifo, buf); + net_buf_put(&h4->rx.fifo, buf); } -static inline void read_header(void) +static inline void read_header(const struct device *dev) { - switch (rx.type) { + struct h4_data *h4 = dev->data; + + switch (h4->rx.type) { case BT_HCI_H4_NONE: - h4_get_type(); + h4_get_type(dev); return; case BT_HCI_H4_EVT: - get_evt_hdr(); + get_evt_hdr(dev); break; case BT_HCI_H4_ACL: - get_acl_hdr(); + get_acl_hdr(dev); break; case BT_HCI_H4_ISO: if (IS_ENABLED(CONFIG_BT_ISO)) { - get_iso_hdr(); + get_iso_hdr(dev); break; } __fallthrough; @@ -357,41 +380,43 @@ static inline void read_header(void) return; } - if (rx.have_hdr && rx.buf) { - if (rx.remaining > net_buf_tailroom(rx.buf)) { + if (h4->rx.have_hdr && h4->rx.buf) { + if (h4->rx.remaining > net_buf_tailroom(h4->rx.buf)) { LOG_ERR("Not enough space in buffer"); - rx.discard = rx.remaining; - reset_rx(); + h4->rx.discard = h4->rx.remaining; + reset_rx(h4); } else { - copy_hdr(rx.buf); + copy_hdr(h4); } } } -static inline void process_tx(void) +static inline void process_tx(const struct device *dev) { + const struct h4_config *cfg = dev->config; + struct h4_data *h4 = dev->data; int bytes; - if (!tx.buf) { - tx.buf = net_buf_get(&tx.fifo, K_NO_WAIT); - if (!tx.buf) { + if (!h4->tx.buf) { + h4->tx.buf = net_buf_get(&h4->tx.fifo, K_NO_WAIT); + if (!h4->tx.buf) { LOG_ERR("TX interrupt but no pending buffer!"); - uart_irq_tx_disable(h4_dev); + uart_irq_tx_disable(cfg->uart); return; } } - if (!tx.type) { - switch (bt_buf_get_type(tx.buf)) { + if (!h4->tx.type) { + switch (bt_buf_get_type(h4->tx.buf)) { case BT_BUF_ACL_OUT: - tx.type = BT_HCI_H4_ACL; + h4->tx.type = BT_HCI_H4_ACL; break; case BT_BUF_CMD: - tx.type = BT_HCI_H4_CMD; + h4->tx.type = BT_HCI_H4_CMD; break; case BT_BUF_ISO_OUT: if (IS_ENABLED(CONFIG_BT_ISO)) { - tx.type = BT_HCI_H4_ISO; + h4->tx.type = BT_HCI_H4_ISO; break; } __fallthrough; @@ -400,73 +425,79 @@ static inline void process_tx(void) goto done; } - bytes = uart_fifo_fill(h4_dev, &tx.type, 1); + bytes = uart_fifo_fill(cfg->uart, &h4->tx.type, 1); if (bytes != 1) { LOG_WRN("Unable to send H:4 type"); - tx.type = BT_HCI_H4_NONE; + h4->tx.type = BT_HCI_H4_NONE; return; } } - bytes = uart_fifo_fill(h4_dev, tx.buf->data, tx.buf->len); + bytes = uart_fifo_fill(cfg->uart, h4->tx.buf->data, h4->tx.buf->len); if (unlikely(bytes < 0)) { LOG_ERR("Unable to write to UART (err %d)", bytes); } else { - net_buf_pull(tx.buf, bytes); + net_buf_pull(h4->tx.buf, bytes); } - if (tx.buf->len) { + if (h4->tx.buf->len) { return; } done: - tx.type = BT_HCI_H4_NONE; - net_buf_unref(tx.buf); - tx.buf = net_buf_get(&tx.fifo, K_NO_WAIT); - if (!tx.buf) { - uart_irq_tx_disable(h4_dev); + h4->tx.type = BT_HCI_H4_NONE; + net_buf_unref(h4->tx.buf); + h4->tx.buf = net_buf_get(&h4->tx.fifo, K_NO_WAIT); + if (!h4->tx.buf) { + uart_irq_tx_disable(cfg->uart); } } -static inline void process_rx(void) +static inline void process_rx(const struct device *dev) { - LOG_DBG("remaining %u discard %u have_hdr %u rx.buf %p len %u", rx.remaining, rx.discard, - rx.have_hdr, rx.buf, rx.buf ? rx.buf->len : 0); + const struct h4_config *cfg = dev->config; + struct h4_data *h4 = dev->data; + + LOG_DBG("remaining %u discard %u have_hdr %u rx.buf %p len %u", + h4->rx.remaining, h4->rx.discard, h4->rx.have_hdr, h4->rx.buf, + h4->rx.buf ? h4->rx.buf->len : 0); - if (rx.discard) { - rx.discard -= h4_discard(h4_dev, rx.discard); + if (h4->rx.discard) { + h4->rx.discard -= h4_discard(cfg->uart, h4->rx.discard); return; } - if (rx.have_hdr) { - read_payload(); + if (h4->rx.have_hdr) { + read_payload(dev); } else { - read_header(); + read_header(dev); } } -static void bt_uart_isr(const struct device *unused, void *user_data) +static void bt_uart_isr(const struct device *uart, void *user_data) { - ARG_UNUSED(unused); - ARG_UNUSED(user_data); + struct device *dev = user_data; - while (uart_irq_update(h4_dev) && uart_irq_is_pending(h4_dev)) { - if (uart_irq_tx_ready(h4_dev)) { - process_tx(); + while (uart_irq_update(uart) && uart_irq_is_pending(uart)) { + if (uart_irq_tx_ready(uart)) { + process_tx(dev); } - if (uart_irq_rx_ready(h4_dev)) { - process_rx(); + if (uart_irq_rx_ready(uart)) { + process_rx(dev); } } } -static int h4_send(struct net_buf *buf) +static int h4_send(const struct device *dev, struct net_buf *buf) { + const struct h4_config *cfg = dev->config; + struct h4_data *h4 = dev->data; + LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); - net_buf_put(&tx.fifo, buf); - uart_irq_tx_enable(h4_dev); + net_buf_put(&h4->tx.fifo, buf); + uart_irq_tx_enable(cfg->uart); return 0; } @@ -477,32 +508,36 @@ static int h4_send(struct net_buf *buf) * * @return 0 on success, negative error value on failure */ -int __weak bt_hci_transport_setup(const struct device *dev) +int __weak bt_hci_transport_setup(const struct device *uart) { - h4_discard(h4_dev, 32); + h4_discard(uart, 32); return 0; } -static int h4_open(void) +static int h4_open(const struct device *dev, bt_hci_recv_t recv) { + const struct h4_config *cfg = dev->config; + struct h4_data *h4 = dev->data; int ret; k_tid_t tid; LOG_DBG(""); - uart_irq_rx_disable(h4_dev); - uart_irq_tx_disable(h4_dev); + uart_irq_rx_disable(cfg->uart); + uart_irq_tx_disable(cfg->uart); - ret = bt_hci_transport_setup(h4_dev); + ret = bt_hci_transport_setup(cfg->uart); if (ret < 0) { return -EIO; } - uart_irq_callback_set(h4_dev, bt_uart_isr); + h4->recv = recv; + + uart_irq_callback_user_data_set(cfg->uart, bt_uart_isr, (void *)dev); - tid = k_thread_create(&rx_thread_data, rx_thread_stack, - K_KERNEL_STACK_SIZEOF(rx_thread_stack), - rx_thread, NULL, NULL, NULL, + tid = k_thread_create(cfg->rx_thread, cfg->rx_thread_stack, + cfg->rx_thread_stack_size, + rx_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_BT_RX_PRIO), 0, K_NO_WAIT); k_thread_name_set(tid, "bt_rx_thread"); @@ -511,8 +546,10 @@ static int h4_open(void) } #if defined(CONFIG_BT_HCI_SETUP) -static int h4_setup(const struct bt_hci_setup_params *params) +static int h4_setup(const struct device *dev, const struct bt_hci_setup_params *params) { + const struct h4_config *cfg = dev->config; + ARG_UNUSED(params); /* Extern bt_h4_vnd_setup function. @@ -523,30 +560,36 @@ static int h4_setup(const struct bt_hci_setup_params *params) */ extern int bt_h4_vnd_setup(const struct device *dev); - return bt_h4_vnd_setup(h4_dev); + return bt_h4_vnd_setup(cfg->uart); } #endif -static const struct bt_hci_driver drv = { - .name = "H:4", - .bus = BT_HCI_DRIVER_BUS_UART, - .open = h4_open, - .send = h4_send, +static const struct bt_hci_driver_api h4_driver_api = { + .open = h4_open, + .send = h4_send, #if defined(CONFIG_BT_HCI_SETUP) - .setup = h4_setup + .setup = h4_setup, #endif }; -static int bt_uart_init(void) -{ - - if (!device_is_ready(h4_dev)) { - return -ENODEV; - } - - bt_hci_driver_register(&drv); - - return 0; -} - -SYS_INIT(bt_uart_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +#define BT_UART_DEVICE_INIT(inst) \ + static K_KERNEL_STACK_DEFINE(rx_thread_stack_##inst, CONFIG_BT_DRV_RX_STACK_SIZE); \ + static struct k_thread rx_thread_##inst; \ + static const struct h4_config h4_config_##inst = { \ + .uart = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .rx_thread_stack = rx_thread_stack_##inst, \ + .rx_thread_stack_size = K_KERNEL_STACK_SIZEOF(rx_thread_stack_##inst), \ + .rx_thread = &rx_thread_##inst, \ + }; \ + static struct h4_data h4_data_##inst = { \ + .rx = { \ + .fifo = Z_FIFO_INITIALIZER(h4_data_##inst.rx.fifo), \ + }, \ + .tx = { \ + .fifo = Z_FIFO_INITIALIZER(h4_data_##inst.tx.fifo), \ + }, \ + }; \ + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &h4_data_##inst, &h4_config_##inst, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &h4_driver_api) + +DT_INST_FOREACH_STATUS_OKAY(BT_UART_DEVICE_INIT) diff --git a/drivers/bluetooth/hci/h4_ifx_cyw43xxx.c b/drivers/bluetooth/hci/h4_ifx_cyw43xxx.c new file mode 100644 index 0000000000000..252b40129d7ad --- /dev/null +++ b/drivers/bluetooth/hci/h4_ifx_cyw43xxx.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief CYW43xxx HCI extension driver. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include +LOG_MODULE_REGISTER(cyw43xxx_driver); + +#include + +#define DT_DRV_COMPAT infineon_cyw43xxx_bt_hci + +BUILD_ASSERT(DT_PROP(DT_INST_GPARENT(0), hw_flow_control) == 1, + "hw_flow_control must be enabled for HCI H4 UART"); + +/* BT settling time after power on */ +#define BT_POWER_ON_SETTLING_TIME_MS (500u) + +/* Stabilization delay after FW loading */ +#define BT_STABILIZATION_DELAY_MS (250u) + +/* HCI Command packet from Host to Controller */ +#define HCI_COMMAND_PACKET (0x01) + +/* Length of UPDATE BAUD RATE command */ +#define HCI_VSC_UPDATE_BAUD_RATE_LENGTH (6u) + +/* Default BAUDRATE */ +#define HCI_UART_DEFAULT_BAUDRATE (115200) + +/* Externs for CY43xxx controller FW */ +extern const uint8_t brcm_patchram_buf[]; +extern const int brcm_patch_ram_length; + +enum { + BT_HCI_VND_OP_DOWNLOAD_MINIDRIVER = 0xFC2E, + BT_HCI_VND_OP_WRITE_RAM = 0xFC4C, + BT_HCI_VND_OP_LAUNCH_RAM = 0xFC4E, + BT_HCI_VND_OP_UPDATE_BAUDRATE = 0xFC18, +}; + +/* bt_h4_vnd_setup function. + * This function executes vendor-specific commands sequence to + * initialize BT Controller before BT Host executes Reset sequence. + * bt_h4_vnd_setup function must be implemented in vendor-specific HCI + * extansion module if CONFIG_BT_HCI_SETUP is enabled. + */ +int bt_h4_vnd_setup(const struct device *dev); + +static int bt_hci_uart_set_baudrate(const struct device *bt_uart_dev, uint32_t baudrate) +{ + struct uart_config uart_cfg; + int err; + + /* Get current UART configuration */ + err = uart_config_get(bt_uart_dev, &uart_cfg); + if (err) { + return err; + } + + if (uart_cfg.baudrate != baudrate) { + /* Re-configure UART */ + uart_cfg.baudrate = baudrate; + err = uart_configure(bt_uart_dev, &uart_cfg); + if (err) { + return err; + } + + /* Revert Interrupt options */ + uart_irq_rx_enable(bt_uart_dev); + } + return 0; +} + +static int bt_update_controller_baudrate(const struct device *bt_uart_dev, uint32_t baudrate) +{ + /* + * NOTE from datasheet for update baudrate: + * - To speed up application downloading, the MCU host commands the CYWxxx device + * to communicate at a new, higher rate by issuing the following Vendor Specific + * UPDATE_BAUDRATE command: + * 01 18 FC 06 00 00 xx xx xx xx + * In the above command, the xx xx xx xx bytes specify the 32-bit little-endian + * value of the new rate in bits per second. For example, + * 115200 is represented as 00 C2 01 00. + * The following response to the UPDATE_BAUDRATE command is expected within 100 ms: + * 04 0E 04 01 18 FC 00 + * - The host switches to the new baud rate after receiving the response at the old + * baud rate. + */ + struct net_buf *buf; + int err; + uint8_t hci_data[HCI_VSC_UPDATE_BAUD_RATE_LENGTH]; + + /* Baudrate is loaded LittleEndian */ + hci_data[0] = 0; + hci_data[1] = 0; + hci_data[2] = (uint8_t)(baudrate & 0xFFUL); + hci_data[3] = (uint8_t)((baudrate >> 8) & 0xFFUL); + hci_data[4] = (uint8_t)((baudrate >> 16) & 0xFFUL); + hci_data[5] = (uint8_t)((baudrate >> 24) & 0xFFUL); + + /* Allocate buffer for update uart baudrate command. + * It will be BT_HCI_OP_RESET with extra parameters. + */ + buf = bt_hci_cmd_create(BT_HCI_VND_OP_UPDATE_BAUDRATE, + HCI_VSC_UPDATE_BAUD_RATE_LENGTH); + if (buf == NULL) { + LOG_ERR("Unable to allocate command buffer"); + return -ENOMEM; + } + + /* Add data part of packet */ + net_buf_add_mem(buf, &hci_data, HCI_VSC_UPDATE_BAUD_RATE_LENGTH); + + /* Send update uart baudrate command. */ + err = bt_hci_cmd_send_sync(BT_HCI_VND_OP_UPDATE_BAUDRATE, buf, NULL); + if (err) { + return err; + } + + /* Re-configure Uart baudrate */ + err = bt_hci_uart_set_baudrate(bt_uart_dev, baudrate); + if (err) { + return err; + } + + return 0; +} + +static int bt_firmware_download(const uint8_t *firmware_image, uint32_t size) +{ + uint8_t *data = (uint8_t *)firmware_image; + volatile uint32_t remaining_length = size; + struct net_buf *buf; + int err; + + LOG_DBG("Executing Fw downloading for CYW43xx device"); + + /* Send hci_download_minidriver command */ + err = bt_hci_cmd_send_sync(BT_HCI_VND_OP_DOWNLOAD_MINIDRIVER, NULL, NULL); + if (err) { + return err; + } + + /* The firmware image (.hcd format) contains a collection of hci_write_ram + * command + a block of the image, followed by a hci_write_ram image at the end. + * Parse and send each individual command and wait for the response. This is to + * ensure the integrity of the firmware image sent to the bluetooth chip. + */ + while (remaining_length) { + size_t data_length = data[2]; /* data length from firmware image block */ + uint16_t op_code = *(uint16_t *)data; + + /* Allocate buffer for hci_write_ram/hci_launch_ram command. */ + buf = bt_hci_cmd_create(op_code, data_length); + if (buf == NULL) { + LOG_ERR("Unable to allocate command buffer"); + return err; + } + + /* Add data part of packet */ + net_buf_add_mem(buf, &data[3], data_length); + + /* Send hci_write_ram command. */ + err = bt_hci_cmd_send_sync(op_code, buf, NULL); + if (err) { + return err; + } + + switch (op_code) { + case BT_HCI_VND_OP_WRITE_RAM: + /* Update remaining length and data pointer: + * content of data length + 2 bytes of opcode and 1 byte of data length. + */ + data += data_length + 3; + remaining_length -= data_length + 3; + break; + + case BT_HCI_VND_OP_LAUNCH_RAM: + remaining_length = 0; + break; + + default: + return -ENOMEM; + } + } + + LOG_DBG("Fw downloading complete"); + return 0; +} + +int bt_h4_vnd_setup(const struct device *dev) +{ + int err; + uint32_t default_uart_speed = DT_PROP(DT_INST_BUS(0), current_speed); + uint32_t hci_operation_speed = DT_INST_PROP_OR(0, hci_operation_speed, default_uart_speed); + uint32_t fw_download_speed = DT_INST_PROP_OR(0, fw_download_speed, default_uart_speed); + + /* Check BT Uart instance */ + if (!device_is_ready(dev)) { + return -EINVAL; + } + +#if DT_INST_NODE_HAS_PROP(0, bt_reg_on_gpios) + struct gpio_dt_spec bt_reg_on = GPIO_DT_SPEC_GET(DT_DRV_INST(0), bt_reg_on_gpios); + + /* Check BT REG_ON gpio instance */ + if (!gpio_is_ready_dt(&bt_reg_on)) { + LOG_ERR("Error: failed to configure bt_reg_on %s pin %d", + bt_reg_on.port->name, bt_reg_on.pin); + return -EIO; + } + + /* Configure bt_reg_on as output */ + err = gpio_pin_configure_dt(&bt_reg_on, GPIO_OUTPUT); + if (err) { + LOG_ERR("Error %d: failed to configure bt_reg_on %s pin %d", + err, bt_reg_on.port->name, bt_reg_on.pin); + return err; + } + err = gpio_pin_set_dt(&bt_reg_on, 1); + if (err) { + return err; + } +#endif /* DT_INST_NODE_HAS_PROP(0, bt_reg_on_gpios) */ + + /* BT settling time after power on */ + (void)k_msleep(BT_POWER_ON_SETTLING_TIME_MS); + + /* Send HCI_RESET */ + err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, NULL); + if (err) { + return err; + } + + /* Re-configure baudrate for BT Controller */ + if (fw_download_speed != default_uart_speed) { + err = bt_update_controller_baudrate(dev, fw_download_speed); + if (err) { + return err; + } + } + + /* BT firmware download */ + err = bt_firmware_download(brcm_patchram_buf, (uint32_t) brcm_patch_ram_length); + if (err) { + return err; + } + + /* Stabilization delay */ + (void)k_msleep(BT_STABILIZATION_DELAY_MS); + + /* When FW launched, HCI UART baudrate should be configured to default */ + if (fw_download_speed != default_uart_speed) { + err = bt_hci_uart_set_baudrate(dev, default_uart_speed); + if (err) { + return err; + } + } + + /* Send HCI_RESET */ + err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, NULL); + if (err) { + return err; + } + + /* Set host controller functionality to user defined baudrate + * after fw downloading. + */ + if (hci_operation_speed != default_uart_speed) { + err = bt_update_controller_baudrate(dev, hci_operation_speed); + if (err) { + return err; + } + } + + return 0; +} diff --git a/drivers/bluetooth/hci/h5.c b/drivers/bluetooth/hci/h5.c index 25a3b3e28f622..0be22f61f888f 100644 --- a/drivers/bluetooth/hci/h5.c +++ b/drivers/bluetooth/hci/h5.c @@ -17,11 +17,13 @@ #include #include #include +#include +#include #include #include #include -#include +#include #include "../util.h" @@ -29,14 +31,7 @@ #include LOG_MODULE_REGISTER(bt_driver); -static K_KERNEL_STACK_DEFINE(tx_stack, CONFIG_BT_DRV_TX_STACK_SIZE); -static K_KERNEL_STACK_DEFINE(rx_stack, CONFIG_BT_DRV_RX_STACK_SIZE); - -static struct k_thread tx_thread_data; -static struct k_thread rx_thread_data; - -static struct k_work_delayable ack_work; -static struct k_work_delayable retx_work; +#define DT_DRV_COMPAT zephyr_bt_hci_3wire_uart #define HCI_3WIRE_ACK_PKT 0x00 #define HCI_COMMAND_PKT 0x01 @@ -86,13 +81,21 @@ static bool reliable_packet(uint8_t type) #define H5_SET_LEN(hdr, len) (((hdr)[1] |= ((len) & 0x0f) << 4), \ ((hdr)[2] |= (len) >> 4)) -static struct h5 { +struct h5_data { + /* Needed for delayed work callbacks */ + const struct device *dev; + + bt_hci_recv_t recv; + struct net_buf *rx_buf; struct k_fifo tx_queue; struct k_fifo rx_queue; struct k_fifo unack_queue; + struct k_work_delayable ack_work; + struct k_work_delayable retx_work; + uint8_t tx_win; uint8_t tx_ack; uint8_t tx_seq; @@ -111,9 +114,21 @@ static struct h5 { PAYLOAD, END, } rx_state; -} h5; -static uint8_t unack_queue_len; + uint8_t unack_queue_len; +}; + +struct h5_config { + const struct device *uart; + + k_thread_stack_t *rx_stack; + size_t rx_stack_size; + struct k_thread *rx_thread; + + k_thread_stack_t *tx_stack; + size_t tx_stack_size; + struct k_thread *tx_thread; +}; static const uint8_t sync_req[] = { 0x01, 0x7e }; static const uint8_t sync_rsp[] = { 0x02, 0x7d }; @@ -123,23 +138,21 @@ static const uint8_t conf_rsp[] = { 0x04, 0x7b }; /* H5 signal buffers pool */ #define MAX_SIG_LEN 3 -#define SIGNAL_COUNT 2 +#define SIGNAL_COUNT (2 * DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)) #define SIG_BUF_SIZE (BT_BUF_RESERVE + MAX_SIG_LEN) NET_BUF_POOL_DEFINE(h5_pool, SIGNAL_COUNT, SIG_BUF_SIZE, 0, NULL); -static const struct device *const h5_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_uart)); - -static void h5_reset_rx(void) +static void h5_reset_rx(struct h5_data *h5) { - if (h5.rx_buf) { - net_buf_unref(h5.rx_buf); - h5.rx_buf = NULL; + if (h5->rx_buf) { + net_buf_unref(h5->rx_buf); + h5->rx_buf = NULL; } - h5.rx_state = START; + h5->rx_state = START; } -static int h5_unslip_byte(uint8_t *byte) +static int h5_unslip_byte(const struct device *uart, uint8_t *byte) { int count; @@ -148,7 +161,7 @@ static int h5_unslip_byte(uint8_t *byte) } do { - count = uart_fifo_read(h5_dev, byte, sizeof(*byte)); + count = uart_fifo_read(uart, byte, sizeof(*byte)); } while (!count); switch (*byte) { @@ -166,20 +179,20 @@ static int h5_unslip_byte(uint8_t *byte) return 0; } -static void process_unack(void) +static void process_unack(struct h5_data *h5) { - uint8_t next_seq = h5.tx_seq; - uint8_t number_removed = unack_queue_len; + uint8_t next_seq = h5->tx_seq; + uint8_t number_removed = h5->unack_queue_len; - if (!unack_queue_len) { + if (!h5->unack_queue_len) { return; } - LOG_DBG("rx_ack %u tx_ack %u tx_seq %u unack_queue_len %u", h5.rx_ack, h5.tx_ack, h5.tx_seq, - unack_queue_len); + LOG_DBG("rx_ack %u tx_ack %u tx_seq %u unack_queue_len %u", h5->rx_ack, h5->tx_ack, + h5->tx_seq, h5->unack_queue_len); - while (unack_queue_len > 0) { - if (next_seq == h5.rx_ack) { + while (h5->unack_queue_len > 0) { + if (next_seq == h5->rx_ack) { /* Next sequence number is the same as last received * ack number */ @@ -191,15 +204,15 @@ static void process_unack(void) next_seq = (next_seq - 1) & 0x07; } - if (next_seq != h5.rx_ack) { - LOG_ERR("Wrong sequence: rx_ack %u tx_seq %u next_seq %u", h5.rx_ack, h5.tx_seq, - next_seq); + if (next_seq != h5->rx_ack) { + LOG_ERR("Wrong sequence: rx_ack %u tx_seq %u next_seq %u", h5->rx_ack, + h5->tx_seq, next_seq); } LOG_DBG("Need to remove %u packet from the queue", number_removed); while (number_removed) { - struct net_buf *buf = net_buf_get(&h5.unack_queue, K_NO_WAIT); + struct net_buf *buf = net_buf_get(&h5->unack_queue, K_NO_WAIT); if (!buf) { LOG_ERR("Unack queue is empty"); @@ -210,7 +223,7 @@ static void process_unack(void) LOG_DBG("Remove buf from the unack_queue"); net_buf_unref(buf); - unack_queue_len--; + h5->unack_queue_len--; number_removed--; } } @@ -261,25 +274,27 @@ static void hexdump(const char *str, const uint8_t *packet, size_t length) #define hexdump(str, packet, length) #endif -static uint8_t h5_slip_byte(uint8_t byte) +static uint8_t h5_slip_byte(const struct device *uart, uint8_t byte) { switch (byte) { case SLIP_DELIMITER: - uart_poll_out(h5_dev, SLIP_ESC); - uart_poll_out(h5_dev, SLIP_ESC_DELIM); + uart_poll_out(uart, SLIP_ESC); + uart_poll_out(uart, SLIP_ESC_DELIM); return 2; case SLIP_ESC: - uart_poll_out(h5_dev, SLIP_ESC); - uart_poll_out(h5_dev, SLIP_ESC_ESC); + uart_poll_out(uart, SLIP_ESC); + uart_poll_out(uart, SLIP_ESC_ESC); return 2; default: - uart_poll_out(h5_dev, byte); + uart_poll_out(uart, byte); return 1; } } -static void h5_send(const uint8_t *payload, uint8_t type, int len) +static void h5_send(const struct device *dev, const uint8_t *payload, uint8_t type, int len) { + const struct h5_config *cfg = dev->config; + struct h5_data *h5 = dev->data; uint8_t hdr[4]; int i; @@ -288,14 +303,14 @@ static void h5_send(const uint8_t *payload, uint8_t type, int len) (void)memset(hdr, 0, sizeof(hdr)); /* Set ACK for outgoing packet and stop delayed work */ - H5_SET_ACK(hdr, h5.tx_ack); + H5_SET_ACK(hdr, h5->tx_ack); /* If cancel fails we may ack the same seq number twice, this is OK. */ - (void)k_work_cancel_delayable(&ack_work); + (void)k_work_cancel_delayable(&h5->ack_work); if (reliable_packet(type)) { H5_SET_RELIABLE(hdr); - H5_SET_SEQ(hdr, h5.tx_seq); - h5.tx_seq = (h5.tx_seq + 1) % 8; + H5_SET_SEQ(hdr, h5->tx_seq); + h5->tx_seq = (h5->tx_seq + 1) % 8; } H5_SET_TYPE(hdr, type); @@ -306,97 +321,100 @@ static void h5_send(const uint8_t *payload, uint8_t type, int len) h5_print_header(hdr, "TX: <"); - uart_poll_out(h5_dev, SLIP_DELIMITER); + uart_poll_out(cfg->uart, SLIP_DELIMITER); for (i = 0; i < 4; i++) { - h5_slip_byte(hdr[i]); + h5_slip_byte(cfg->uart, hdr[i]); } for (i = 0; i < len; i++) { - h5_slip_byte(payload[i]); + h5_slip_byte(cfg->uart, payload[i]); } - uart_poll_out(h5_dev, SLIP_DELIMITER); + uart_poll_out(cfg->uart, SLIP_DELIMITER); } /* Delayed work taking care about retransmitting packets */ static void retx_timeout(struct k_work *work) { - ARG_UNUSED(work); + struct k_work_delayable *delayable = k_work_delayable_from_work(work); + struct h5_data *h5 = CONTAINER_OF(delayable, struct h5_data, retx_work); - LOG_DBG("unack_queue_len %u", unack_queue_len); + LOG_DBG("unack_queue_len %u", h5->unack_queue_len); - if (unack_queue_len) { + if (h5->unack_queue_len) { struct k_fifo tmp_queue; struct net_buf *buf; k_fifo_init(&tmp_queue); /* Queue to temporary queue */ - while ((buf = net_buf_get(&h5.tx_queue, K_NO_WAIT))) { + while ((buf = net_buf_get(&h5->tx_queue, K_NO_WAIT))) { net_buf_put(&tmp_queue, buf); } /* Queue unack packets to the beginning of the queue */ - while ((buf = net_buf_get(&h5.unack_queue, K_NO_WAIT))) { + while ((buf = net_buf_get(&h5->unack_queue, K_NO_WAIT))) { /* include also packet type */ net_buf_push(buf, sizeof(uint8_t)); - net_buf_put(&h5.tx_queue, buf); - h5.tx_seq = (h5.tx_seq - 1) & 0x07; - unack_queue_len--; + net_buf_put(&h5->tx_queue, buf); + h5->tx_seq = (h5->tx_seq - 1) & 0x07; + h5->unack_queue_len--; } /* Queue saved packets from temp queue */ while ((buf = net_buf_get(&tmp_queue, K_NO_WAIT))) { - net_buf_put(&h5.tx_queue, buf); + net_buf_put(&h5->tx_queue, buf); } } } static void ack_timeout(struct k_work *work) { - ARG_UNUSED(work); + struct k_work_delayable *delayable = k_work_delayable_from_work(work); + struct h5_data *h5 = CONTAINER_OF(delayable, struct h5_data, ack_work); LOG_DBG(""); - h5_send(NULL, HCI_3WIRE_ACK_PKT, 0); + h5_send(h5->dev, NULL, HCI_3WIRE_ACK_PKT, 0); } -static void h5_process_complete_packet(uint8_t *hdr) +static void h5_process_complete_packet(const struct device *dev, uint8_t *hdr) { + struct h5_data *h5 = dev->data; struct net_buf *buf; LOG_DBG(""); /* rx_ack should be in every packet */ - h5.rx_ack = H5_HDR_ACK(hdr); + h5->rx_ack = H5_HDR_ACK(hdr); if (reliable_packet(H5_HDR_PKT_TYPE(hdr))) { /* For reliable packet increment next transmit ack number */ - h5.tx_ack = (h5.tx_ack + 1) % 8; + h5->tx_ack = (h5->tx_ack + 1) % 8; /* Submit delayed work to ack the packet */ - k_work_reschedule(&ack_work, H5_RX_ACK_TIMEOUT); + k_work_reschedule(&h5->ack_work, H5_RX_ACK_TIMEOUT); } h5_print_header(hdr, "RX: >"); - process_unack(); + process_unack(h5); - buf = h5.rx_buf; - h5.rx_buf = NULL; + buf = h5->rx_buf; + h5->rx_buf = NULL; switch (H5_HDR_PKT_TYPE(hdr)) { case HCI_3WIRE_ACK_PKT: net_buf_unref(buf); break; case HCI_3WIRE_LINK_PKT: - net_buf_put(&h5.rx_queue, buf); + net_buf_put(&h5->rx_queue, buf); break; case HCI_EVENT_PKT: case HCI_ACLDATA_PKT: case HCI_ISODATA_PKT: hexdump("=> ", buf->data, buf->len); - bt_recv(buf); + h5->recv(dev, buf); break; } } @@ -406,22 +424,21 @@ static inline struct net_buf *get_evt_buf(uint8_t evt) return bt_buf_get_evt(evt, false, K_NO_WAIT); } -static void bt_uart_isr(const struct device *unused, void *user_data) +static void bt_uart_isr(const struct device *uart, void *user_data) { + const struct device *dev = user_data; + struct h5_data *h5 = dev->data; static int remaining; uint8_t byte; int ret; static uint8_t hdr[4]; size_t buf_tailroom; - ARG_UNUSED(unused); - ARG_UNUSED(user_data); - - while (uart_irq_update(h5_dev) && - uart_irq_is_pending(h5_dev)) { + while (uart_irq_update(uart) && + uart_irq_is_pending(uart)) { - if (!uart_irq_rx_ready(h5_dev)) { - if (uart_irq_tx_ready(h5_dev)) { + if (!uart_irq_rx_ready(uart)) { + if (uart_irq_tx_ready(uart)) { LOG_DBG("transmit ready"); } else { LOG_DBG("spurious interrupt"); @@ -430,15 +447,15 @@ static void bt_uart_isr(const struct device *unused, void *user_data) break; } - ret = uart_fifo_read(h5_dev, &byte, sizeof(byte)); + ret = uart_fifo_read(uart, &byte, sizeof(byte)); if (!ret) { continue; } - switch (h5.rx_state) { + switch (h5->rx_state) { case START: if (byte == SLIP_DELIMITER) { - h5.rx_state = HEADER; + h5->rx_state = HEADER; remaining = sizeof(hdr); } break; @@ -451,8 +468,8 @@ static void bt_uart_isr(const struct device *unused, void *user_data) continue; } - if (h5_unslip_byte(&byte) < 0) { - h5_reset_rx(); + if (h5_unslip_byte(uart, &byte) < 0) { + h5_reset_rx(h5); continue; } @@ -470,86 +487,85 @@ static void bt_uart_isr(const struct device *unused, void *user_data) /* The buffer is allocated only once we know * the exact event type. */ - h5.rx_state = PAYLOAD; + h5->rx_state = PAYLOAD; break; case HCI_ACLDATA_PKT: - h5.rx_buf = bt_buf_get_rx(BT_BUF_ACL_IN, - K_NO_WAIT); - if (!h5.rx_buf) { + h5->rx_buf = bt_buf_get_rx(BT_BUF_ACL_IN, + K_NO_WAIT); + if (!h5->rx_buf) { LOG_WRN("No available data buffers"); - h5_reset_rx(); + h5_reset_rx(h5); continue; } - h5.rx_state = PAYLOAD; + h5->rx_state = PAYLOAD; break; case HCI_ISODATA_PKT: - h5.rx_buf = bt_buf_get_rx(BT_BUF_ISO_IN, - K_NO_WAIT); - if (!h5.rx_buf) { + h5->rx_buf = bt_buf_get_rx(BT_BUF_ISO_IN, K_NO_WAIT); + if (!h5->rx_buf) { LOG_WRN("No available data buffers"); - h5_reset_rx(); + h5_reset_rx(h5); continue; } - h5.rx_state = PAYLOAD; + h5->rx_state = PAYLOAD; break; case HCI_3WIRE_LINK_PKT: case HCI_3WIRE_ACK_PKT: - h5.rx_buf = net_buf_alloc(&h5_pool, K_NO_WAIT); - if (!h5.rx_buf) { + h5->rx_buf = net_buf_alloc(&h5_pool, K_NO_WAIT); + if (!h5->rx_buf) { LOG_WRN("No available signal buffers"); - h5_reset_rx(); + h5_reset_rx(h5); continue; } - h5.rx_state = PAYLOAD; + h5->rx_state = PAYLOAD; break; default: LOG_ERR("Wrong packet type %u", H5_HDR_PKT_TYPE(hdr)); - h5.rx_state = END; + h5->rx_state = END; break; } if (!remaining) { - h5.rx_state = END; + h5->rx_state = END; } break; case PAYLOAD: - if (h5_unslip_byte(&byte) < 0) { - h5_reset_rx(); + if (h5_unslip_byte(uart, &byte) < 0) { + h5_reset_rx(h5); continue; } /* Allocate HCI event buffer now that we know the * exact event type. */ - if (!h5.rx_buf) { - h5.rx_buf = get_evt_buf(byte); - if (!h5.rx_buf) { + if (!h5->rx_buf) { + h5->rx_buf = get_evt_buf(byte); + if (!h5->rx_buf) { LOG_WRN("No available event buffers"); - h5_reset_rx(); + h5_reset_rx(h5); continue; } } - buf_tailroom = net_buf_tailroom(h5.rx_buf); + buf_tailroom = net_buf_tailroom(h5->rx_buf); if (buf_tailroom < sizeof(byte)) { LOG_ERR("Not enough space in buffer %zu/%zu", sizeof(byte), buf_tailroom); - h5_reset_rx(); + h5_reset_rx(h5); break; } - net_buf_add_mem(h5.rx_buf, &byte, sizeof(byte)); + net_buf_add_mem(h5->rx_buf, &byte, sizeof(byte)); remaining--; if (!remaining) { - h5.rx_state = END; + h5->rx_state = END; } break; case END: if (byte != SLIP_DELIMITER) { LOG_ERR("Missing ending SLIP_DELIMITER"); - h5_reset_rx(); + h5_reset_rx(h5); break; } @@ -560,15 +576,15 @@ static void bt_uart_isr(const struct device *unused, void *user_data) * full packet anyway to clear UART. */ if (H5_HDR_RELIABLE(hdr) && - H5_HDR_SEQ(hdr) != h5.tx_ack) { - LOG_ERR("Seq expected %u got %u. Drop packet", h5.tx_ack, + H5_HDR_SEQ(hdr) != h5->tx_ack) { + LOG_ERR("Seq expected %u got %u. Drop packet", h5->tx_ack, H5_HDR_SEQ(hdr)); - h5_reset_rx(); + h5_reset_rx(h5); break; } - h5_process_complete_packet(hdr); - h5.rx_state = START; + h5_process_complete_packet(dev, hdr); + h5->rx_state = START; break; } } @@ -579,8 +595,9 @@ static uint8_t h5_get_type(struct net_buf *buf) return net_buf_pull_u8(buf); } -static int h5_queue(struct net_buf *buf) +static int h5_queue(const struct device *dev, struct net_buf *buf) { + struct h5_data *h5 = dev->data; uint8_t type; LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); @@ -602,29 +619,31 @@ static int h5_queue(struct net_buf *buf) memcpy(net_buf_push(buf, sizeof(type)), &type, sizeof(type)); - net_buf_put(&h5.tx_queue, buf); + net_buf_put(&h5->tx_queue, buf); return 0; } static void tx_thread(void *p1, void *p2, void *p3) { - ARG_UNUSED(p1); + const struct device *dev = p1; + struct h5_data *h5 = dev->data; + ARG_UNUSED(p2); ARG_UNUSED(p3); LOG_DBG(""); /* FIXME: make periodic sending */ - h5_send(sync_req, HCI_3WIRE_LINK_PKT, sizeof(sync_req)); + h5_send(dev, sync_req, HCI_3WIRE_LINK_PKT, sizeof(sync_req)); while (true) { struct net_buf *buf; uint8_t type; - LOG_DBG("link_state %u", h5.link_state); + LOG_DBG("link_state %u", h5->link_state); - switch (h5.link_state) { + switch (h5->link_state) { case UNINIT: /* FIXME: send sync */ k_sleep(K_MSEC(100)); @@ -634,32 +653,34 @@ static void tx_thread(void *p1, void *p2, void *p3) k_sleep(K_MSEC(100)); break; case ACTIVE: - buf = net_buf_get(&h5.tx_queue, K_FOREVER); + buf = net_buf_get(&h5->tx_queue, K_FOREVER); type = h5_get_type(buf); - h5_send(buf->data, type, buf->len); + h5_send(dev, buf->data, type, buf->len); /* buf is dequeued from tx_queue and queued to unack * queue. */ - net_buf_put(&h5.unack_queue, buf); - unack_queue_len++; + net_buf_put(&h5->unack_queue, buf); + h5->unack_queue_len++; - k_work_reschedule(&retx_work, H5_TX_ACK_TIMEOUT); + k_work_reschedule(&h5->retx_work, H5_TX_ACK_TIMEOUT); break; } } } -static void h5_set_txwin(uint8_t *conf) +static void h5_set_txwin(struct h5_data *h5, uint8_t *conf) { - conf[2] = h5.tx_win & 0x07; + conf[2] = h5->tx_win & 0x07; } static void rx_thread(void *p1, void *p2, void *p3) { - ARG_UNUSED(p1); + const struct device *dev = p1; + struct h5_data *h5 = dev->data; + ARG_UNUSED(p2); ARG_UNUSED(p3); @@ -668,42 +689,42 @@ static void rx_thread(void *p1, void *p2, void *p3) while (true) { struct net_buf *buf; - buf = net_buf_get(&h5.rx_queue, K_FOREVER); + buf = net_buf_get(&h5->rx_queue, K_FOREVER); hexdump("=> ", buf->data, buf->len); if (!memcmp(buf->data, sync_req, sizeof(sync_req))) { - if (h5.link_state == ACTIVE) { + if (h5->link_state == ACTIVE) { /* TODO Reset H5 */ } - h5_send(sync_rsp, HCI_3WIRE_LINK_PKT, sizeof(sync_rsp)); + h5_send(dev, sync_rsp, HCI_3WIRE_LINK_PKT, sizeof(sync_rsp)); } else if (!memcmp(buf->data, sync_rsp, sizeof(sync_rsp))) { - if (h5.link_state == ACTIVE) { + if (h5->link_state == ACTIVE) { /* TODO Reset H5 */ } - h5.link_state = INIT; - h5_set_txwin(conf_req); - h5_send(conf_req, HCI_3WIRE_LINK_PKT, sizeof(conf_req)); + h5->link_state = INIT; + h5_set_txwin(h5, conf_req); + h5_send(dev, conf_req, HCI_3WIRE_LINK_PKT, sizeof(conf_req)); } else if (!memcmp(buf->data, conf_req, 2)) { /* * The Host sends Config Response messages without a * Configuration Field. */ - h5_send(conf_rsp, HCI_3WIRE_LINK_PKT, sizeof(conf_rsp)); + h5_send(dev, conf_rsp, HCI_3WIRE_LINK_PKT, sizeof(conf_rsp)); /* Then send Config Request with Configuration Field */ - h5_set_txwin(conf_req); - h5_send(conf_req, HCI_3WIRE_LINK_PKT, sizeof(conf_req)); + h5_set_txwin(h5, conf_req); + h5_send(dev, conf_req, HCI_3WIRE_LINK_PKT, sizeof(conf_req)); } else if (!memcmp(buf->data, conf_rsp, 2)) { - h5.link_state = ACTIVE; + h5->link_state = ACTIVE; if (buf->len > 2) { /* Configuration field present */ - h5.tx_win = (buf->data[2] & 0x07); + h5->tx_win = (buf->data[2] & 0x07); } - LOG_DBG("Finished H5 configuration, tx_win %u", h5.tx_win); + LOG_DBG("Finished H5 configuration, tx_win %u", h5->tx_win); } else { LOG_ERR("Not handled yet %x %x", buf->data[0], buf->data[1]); } @@ -717,74 +738,91 @@ static void rx_thread(void *p1, void *p2, void *p3) } } -static void h5_init(void) +static void h5_init(const struct device *dev) { + const struct h5_config *cfg = dev->config; + struct h5_data *h5 = dev->data; + k_tid_t tid; + LOG_DBG(""); - h5.link_state = UNINIT; - h5.rx_state = START; - h5.tx_win = 4U; + h5->link_state = UNINIT; + h5->rx_state = START; + h5->tx_win = 4U; /* TX thread */ - k_fifo_init(&h5.tx_queue); - k_thread_create(&tx_thread_data, tx_stack, - K_KERNEL_STACK_SIZEOF(tx_stack), - tx_thread, NULL, NULL, NULL, - K_PRIO_COOP(CONFIG_BT_HCI_TX_PRIO), - 0, K_NO_WAIT); - k_thread_name_set(&tx_thread_data, "tx_thread"); - - k_fifo_init(&h5.rx_queue); - k_thread_create(&rx_thread_data, rx_stack, - K_KERNEL_STACK_SIZEOF(rx_stack), - rx_thread, NULL, NULL, NULL, - K_PRIO_COOP(CONFIG_BT_RX_PRIO), - 0, K_NO_WAIT); - k_thread_name_set(&rx_thread_data, "rx_thread"); + k_fifo_init(&h5->tx_queue); + tid = k_thread_create(cfg->tx_thread, cfg->tx_stack, cfg->tx_stack_size, + tx_thread, (void *)dev, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_HCI_TX_PRIO), + 0, K_NO_WAIT); + k_thread_name_set(tid, "tx_thread"); + + k_fifo_init(&h5->rx_queue); + tid = k_thread_create(cfg->rx_thread, cfg->rx_stack, cfg->rx_stack_size, + rx_thread, (void *)dev, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_RX_PRIO), + 0, K_NO_WAIT); + k_thread_name_set(tid, "rx_thread"); /* Unack queue */ - k_fifo_init(&h5.unack_queue); + k_fifo_init(&h5->unack_queue); /* Init delayed work */ - k_work_init_delayable(&ack_work, ack_timeout); - k_work_init_delayable(&retx_work, retx_timeout); + k_work_init_delayable(&h5->ack_work, ack_timeout); + k_work_init_delayable(&h5->retx_work, retx_timeout); } -static int h5_open(void) +static int h5_open(const struct device *dev, bt_hci_recv_t recv) { + const struct h5_config *cfg = dev->config; + struct h5_data *h5 = dev->data; + LOG_DBG(""); - uart_irq_rx_disable(h5_dev); - uart_irq_tx_disable(h5_dev); + /* This is needed so that we can access the device struct from within the + * delayed work callbacks. + */ + h5->dev = dev; - bt_uart_drain(h5_dev); + h5->recv = recv; - uart_irq_callback_set(h5_dev, bt_uart_isr); + uart_irq_rx_disable(cfg->uart); + uart_irq_tx_disable(cfg->uart); - h5_init(); + bt_uart_drain(cfg->uart); - uart_irq_rx_enable(h5_dev); + uart_irq_callback_user_data_set(cfg->uart, bt_uart_isr, (void *)dev); - return 0; -} + h5_init(dev); -static const struct bt_hci_driver drv = { - .name = "H:5", - .bus = BT_HCI_DRIVER_BUS_UART, - .open = h5_open, - .send = h5_queue, -}; - -static int bt_uart_init(void) -{ - - if (!device_is_ready(h5_dev)) { - return -ENODEV; - } - - bt_hci_driver_register(&drv); + uart_irq_rx_enable(cfg->uart); return 0; } -SYS_INIT(bt_uart_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +static const struct bt_hci_driver_api h5_driver_api = { + .open = h5_open, + .send = h5_queue, +}; + +#define BT_UART_DEVICE_INIT(inst) \ + static K_KERNEL_STACK_DEFINE(rx_thread_stack_##inst, CONFIG_BT_DRV_RX_STACK_SIZE); \ + static struct k_thread rx_thread_##inst; \ + static K_KERNEL_STACK_DEFINE(tx_thread_stack_##inst, CONFIG_BT_DRV_TX_STACK_SIZE); \ + static struct k_thread tx_thread_##inst; \ + static const struct h5_config h5_config_##inst = { \ + .uart = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .rx_stack = rx_thread_stack_##inst, \ + .rx_stack_size = K_KERNEL_STACK_SIZEOF(rx_thread_stack_##inst), \ + .rx_thread = &rx_thread_##inst, \ + .tx_stack = tx_thread_stack_##inst, \ + .tx_stack_size = K_KERNEL_STACK_SIZEOF(tx_thread_stack_##inst), \ + .tx_thread = &tx_thread_##inst, \ + }; \ + static struct h5_data h5_##inst; \ + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &h5_##inst, &h5_config_##inst, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &h5_driver_api) + + +DT_INST_FOREACH_STATUS_OKAY(BT_UART_DEVICE_INIT) diff --git a/drivers/bluetooth/hci/hci_ambiq.c b/drivers/bluetooth/hci/hci_ambiq.c index ec3a0b944fe46..34a2360a2c21f 100644 --- a/drivers/bluetooth/hci/hci_ambiq.c +++ b/drivers/bluetooth/hci/hci_ambiq.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL @@ -29,17 +29,18 @@ LOG_MODULE_REGISTER(bt_hci_driver); #define PACKET_TYPE 0 #define PACKET_TYPE_SIZE 1 #define EVT_HEADER_TYPE 0 -#define EVT_HEADER_EVENT 1 -#define EVT_HEADER_SIZE 2 -#define EVT_VENDOR_CODE_LSB 3 -#define EVT_VENDOR_CODE_MSB 4 -#define CMD_OGF 1 -#define CMD_OCF 2 +#define EVT_CMD_COMP_OP_LSB 3 +#define EVT_CMD_COMP_OP_MSB 4 +#define EVT_CMD_COMP_DATA 5 #define EVT_OK 0 #define EVT_DISCARD 1 #define EVT_NOP 2 +#define BT_FEAT_SET_BIT(feat, octet, bit) (feat[octet] |= BIT(bit)) +#define BT_FEAT_SET_NO_BREDR(feat) BT_FEAT_SET_BIT(feat, 4, 5) +#define BT_FEAT_SET_LE(feat) BT_FEAT_SET_BIT(feat, 4, 6) + /* Max SPI buffer length for transceive operations. * The maximum TX packet number is 512 bytes data + 12 bytes header. * The maximum RX packet number is 255 bytes data + 3 header. @@ -47,6 +48,13 @@ LOG_MODULE_REGISTER(bt_hci_driver); #define SPI_MAX_TX_MSG_LEN 524 #define SPI_MAX_RX_MSG_LEN 258 +/* The controller may be unavailable to receive packets because it is busy + * on processing something or have packets to send to host. Need to free the + * SPI bus and wait some moment to try again. + */ +#define SPI_BUSY_WAIT_INTERVAL_MS 25 +#define SPI_BUSY_TX_ATTEMPTS 200 + static uint8_t __noinit rxmsg[SPI_MAX_RX_MSG_LEN]; static const struct device *spi_dev = DEVICE_DT_GET(SPI_DEV_NODE); static struct spi_config spi_cfg = { @@ -64,9 +72,14 @@ static const struct spi_buf_set spi_rx = {.buffers = &spi_rx_buf, .count = 1}; static K_SEM_DEFINE(sem_irq, 0, 1); static K_SEM_DEFINE(sem_spi_available, 1, 1); +struct bt_apollo_data { + bt_hci_recv_t recv; +}; + void bt_packet_irq_isr(const struct device *unused1, struct gpio_callback *unused2, uint32_t unused3) { + bt_apollo_rcv_isr_preprocess(); k_sem_give(&sem_irq); } @@ -76,21 +89,45 @@ static inline int bt_spi_transceive(void *tx, uint32_t tx_len, void *rx, uint32_ spi_tx_buf.len = (size_t)tx_len; spi_rx_buf.buf = rx; spi_rx_buf.len = (size_t)rx_len; + + /* Before sending packet to controller the host needs to poll the status of + * controller to know it's ready, or before reading packets from controller + * the host needs to get the payload size of coming packets by sending specific + * command and putting the status or size to the rx buffer, the CS should be + * held at this moment to continue to send or receive packets. + */ + if (tx_len && rx_len) { + spi_cfg.operation |= SPI_HOLD_ON_CS; + } else { + spi_cfg.operation &= ~SPI_HOLD_ON_CS; + } return spi_transceive(spi_dev, &spi_cfg, &spi_tx, &spi_rx); } static int spi_send_packet(uint8_t *data, uint16_t len) { int ret; + uint16_t fail_count = 0; - /* Wait for SPI bus to be available */ - k_sem_take(&sem_spi_available, K_FOREVER); + do { + /* Wait for SPI bus to be available */ + k_sem_take(&sem_spi_available, K_FOREVER); - /* Send the SPI packet to controller */ - ret = bt_apollo_spi_send(data, len, bt_spi_transceive); + /* Send the SPI packet to controller */ + ret = bt_apollo_spi_send(data, len, bt_spi_transceive); - /* Free the SPI bus */ - k_sem_give(&sem_spi_available); + /* Free the SPI bus */ + k_sem_give(&sem_spi_available); + + if (ret) { + /* Give some chance to controller to complete the processing or + * packets sending. + */ + k_sleep(K_MSEC(SPI_BUSY_WAIT_INTERVAL_MS)); + } else { + break; + } + } while (fail_count++ < SPI_BUSY_TX_ATTEMPTS); return ret; } @@ -113,7 +150,7 @@ static int spi_receive_packet(uint8_t *data, uint16_t *len) static int hci_event_filter(const uint8_t *evt_data) { - uint8_t evt_type = evt_data[0]; + uint8_t evt_type = evt_data[EVT_HEADER_TYPE]; switch (evt_type) { case BT_HCI_EVT_LE_META_EVENT: { @@ -127,11 +164,26 @@ static int hci_event_filter(const uint8_t *evt_data) } } case BT_HCI_EVT_CMD_COMPLETE: { - uint16_t opcode = (uint16_t)(evt_data[3] + (evt_data[4] << 8)); + uint16_t opcode = (uint16_t)(evt_data[EVT_CMD_COMP_OP_LSB] + + (evt_data[EVT_CMD_COMP_OP_MSB] << 8)); switch (opcode) { case BT_OP_NOP: return EVT_NOP; + case BT_HCI_OP_READ_LOCAL_FEATURES: { + /* The BLE controller of some Ambiq Apollox Blue SOC may have issue to + * report the expected supported features bitmask successfully, thought the + * features are actually supportive. Need to correct them before going to + * the host stack. + */ + struct bt_hci_rp_read_local_features *rp = + (void *)&evt_data[EVT_CMD_COMP_DATA]; + if (rp->status == 0) { + BT_FEAT_SET_NO_BREDR(rp->features); + BT_FEAT_SET_LE(rp->features); + } + return EVT_OK; + } default: return EVT_OK; } @@ -240,7 +292,9 @@ static struct net_buf *bt_hci_acl_recv(uint8_t *data, size_t len) static void bt_spi_rx_thread(void *p1, void *p2, void *p3) { - ARG_UNUSED(p1); + const struct device *dev = p1; + struct bt_apollo_data *hci = dev->data; + ARG_UNUSED(p2); ARG_UNUSED(p3); @@ -283,13 +337,13 @@ static void bt_spi_rx_thread(void *p1, void *p2, void *p3) /* Post the RX message to host stack to process */ if (buf) { - bt_recv(buf); + hci->recv(dev, buf); } } while (0); } } -static int bt_hci_send(struct net_buf *buf) +static int bt_apollo_send(const struct device *dev, struct net_buf *buf) { int ret = 0; @@ -320,8 +374,9 @@ static int bt_hci_send(struct net_buf *buf) return ret; } -static int bt_hci_open(void) +static int bt_apollo_open(const struct device *dev, bt_hci_recv_t recv) { + struct bt_apollo_data *hci = dev->data; int ret; ret = bt_hci_transport_setup(spi_dev); @@ -331,15 +386,18 @@ static int bt_hci_open(void) /* Start RX thread */ k_thread_create(&spi_rx_thread_data, spi_rx_stack, K_KERNEL_STACK_SIZEOF(spi_rx_stack), - (k_thread_entry_t)bt_spi_rx_thread, NULL, NULL, NULL, + (k_thread_entry_t)bt_spi_rx_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); ret = bt_apollo_controller_init(spi_send_packet); + if (ret == 0) { + hci->recv = recv; + } return ret; } -static int bt_spi_setup(const struct bt_hci_setup_params *params) +static int bt_apollo_setup(const struct device *dev, const struct bt_hci_setup_params *params) { ARG_UNUSED(params); @@ -350,18 +408,18 @@ static int bt_spi_setup(const struct bt_hci_setup_params *params) return ret; } -static const struct bt_hci_driver drv = { - .name = "ambiq hci", - .bus = BT_HCI_DRIVER_BUS_SPI, - .open = bt_hci_open, - .send = bt_hci_send, - .setup = bt_spi_setup, +static const struct bt_hci_driver_api drv = { + .open = bt_apollo_open, + .send = bt_apollo_send, + .setup = bt_apollo_setup, }; -static int bt_hci_init(void) +static int bt_apollo_init(const struct device *dev) { int ret; + ARG_UNUSED(dev); + if (!device_is_ready(spi_dev)) { LOG_ERR("SPI device not ready"); return -ENODEV; @@ -372,11 +430,16 @@ static int bt_hci_init(void) return ret; } - bt_hci_driver_register(&drv); - LOG_DBG("BT HCI initialized"); return 0; } -SYS_INIT(bt_hci_init, POST_KERNEL, CONFIG_BT_HCI_INIT_PRIORITY); +#define HCI_DEVICE_INIT(inst) \ + static struct bt_apollo_data hci_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, bt_apollo_init, NULL, &hci_data_##inst, NULL, \ + POST_KERNEL, CONFIG_BT_HCI_INIT_PRIORITY, &drv) + +/* Only one instance supported right now */ +HCI_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/hci_b91.c b/drivers/bluetooth/hci/hci_b91.c deleted file mode 100644 index 9909718e94be6..0000000000000 --- a/drivers/bluetooth/hci/hci_b91.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2022, Telink Semiconductor (Shanghai) Co., Ltd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -#include -#include - -#include - -#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL -#include -LOG_MODULE_REGISTER(bt_hci_driver_b91); - -#define HCI_BT_B91_TIMEOUT K_MSEC(2000) - -static K_SEM_DEFINE(hci_send_sem, 1, 1); - -static bool is_hci_event_discardable(const uint8_t *evt_data) -{ - uint8_t evt_type = evt_data[0]; - - switch (evt_type) { -#if defined(CONFIG_BT_CLASSIC) - case BT_HCI_EVT_INQUIRY_RESULT_WITH_RSSI: - case BT_HCI_EVT_EXTENDED_INQUIRY_RESULT: - return true; -#endif - case BT_HCI_EVT_LE_META_EVENT: { - uint8_t subevt_type = evt_data[sizeof(struct bt_hci_evt_hdr)]; - - switch (subevt_type) { - case BT_HCI_EVT_LE_ADVERTISING_REPORT: - return true; - default: - return false; - } - } - default: - return false; - } -} - -static struct net_buf *bt_b91_evt_recv(uint8_t *data, size_t len) -{ - bool discardable; - struct bt_hci_evt_hdr hdr; - struct net_buf *buf; - size_t buf_tailroom; - - if (len < sizeof(hdr)) { - LOG_ERR("Not enough data for event header"); - return NULL; - } - - discardable = is_hci_event_discardable(data); - - memcpy((void *)&hdr, data, sizeof(hdr)); - data += sizeof(hdr); - len -= sizeof(hdr); - - if (len != hdr.len) { - LOG_ERR("Event payload length is not correct"); - return NULL; - } - LOG_DBG("len %u", hdr.len); - - buf = bt_buf_get_evt(hdr.evt, discardable, K_NO_WAIT); - if (!buf) { - if (discardable) { - LOG_DBG("Discardable buffer pool full, ignoring event"); - } else { - LOG_ERR("No available event buffers!"); - } - return buf; - } - - net_buf_add_mem(buf, &hdr, sizeof(hdr)); - - buf_tailroom = net_buf_tailroom(buf); - if (buf_tailroom < len) { - LOG_ERR("Not enough space in buffer %zu/%zu", len, buf_tailroom); - net_buf_unref(buf); - return NULL; - } - - net_buf_add_mem(buf, data, len); - - return buf; -} - -static struct net_buf *bt_b91_acl_recv(uint8_t *data, size_t len) -{ - struct bt_hci_acl_hdr hdr; - struct net_buf *buf; - size_t buf_tailroom; - - if (len < sizeof(hdr)) { - LOG_ERR("Not enough data for ACL header"); - return NULL; - } - - buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT); - if (buf) { - memcpy((void *)&hdr, data, sizeof(hdr)); - data += sizeof(hdr); - len -= sizeof(hdr); - } else { - LOG_ERR("No available ACL buffers!"); - return NULL; - } - - if (len != sys_le16_to_cpu(hdr.len)) { - LOG_ERR("ACL payload length is not correct"); - net_buf_unref(buf); - return NULL; - } - - net_buf_add_mem(buf, &hdr, sizeof(hdr)); - buf_tailroom = net_buf_tailroom(buf); - if (buf_tailroom < len) { - LOG_ERR("Not enough space in buffer %zu/%zu", len, buf_tailroom); - net_buf_unref(buf); - return NULL; - } - - LOG_DBG("len %u", len); - net_buf_add_mem(buf, data, len); - - return buf; -} - -static void hci_b91_host_rcv_pkt(uint8_t *data, uint16_t len) -{ - uint8_t pkt_indicator; - struct net_buf *buf; - - LOG_HEXDUMP_DBG(data, len, "host packet data:"); - - pkt_indicator = *data++; - len -= sizeof(pkt_indicator); - - switch (pkt_indicator) { - case BT_HCI_H4_EVT: - buf = bt_b91_evt_recv(data, len); - break; - - case BT_HCI_H4_ACL: - buf = bt_b91_acl_recv(data, len); - break; - - default: - buf = NULL; - LOG_ERR("Unknown HCI type %u", pkt_indicator); - } - - if (buf) { - LOG_DBG("Calling bt_recv(%p)", buf); - bt_recv(buf); - } -} - -static void hci_b91_controller_rcv_pkt_ready(void) -{ - k_sem_give(&hci_send_sem); -} - -static b91_bt_host_callback_t vhci_host_cb = { - .host_send_available = hci_b91_controller_rcv_pkt_ready, - .host_read_packet = hci_b91_host_rcv_pkt -}; - -static int bt_b91_send(struct net_buf *buf) -{ - int err = 0; - uint8_t type; - - LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); - - switch (bt_buf_get_type(buf)) { - case BT_BUF_ACL_OUT: - type = BT_HCI_H4_ACL; - break; - - case BT_BUF_CMD: - type = BT_HCI_H4_CMD; - break; - - default: - LOG_ERR("Unknown type %u", bt_buf_get_type(buf)); - goto done; - } - - LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:"); - - if (k_sem_take(&hci_send_sem, HCI_BT_B91_TIMEOUT) == 0) { - b91_bt_host_send_packet(type, buf->data, buf->len); - } else { - LOG_ERR("Send packet timeout error"); - err = -ETIMEDOUT; - } - -done: - net_buf_unref(buf); - k_sem_give(&hci_send_sem); - - return err; -} - -static int hci_b91_open(void) -{ - int status; - - status = b91_bt_controller_init(); - if (status) { - LOG_ERR("Bluetooth controller init failed %d", status); - return status; - } - - b91_bt_host_callback_register(&vhci_host_cb); - - LOG_DBG("B91 BT started"); - - return 0; -} - -static const struct bt_hci_driver drv = { - .name = "BT B91", - .open = hci_b91_open, - .send = bt_b91_send, - .bus = BT_HCI_DRIVER_BUS_IPM, -#if defined(CONFIG_BT_DRIVER_QUIRK_NO_AUTO_DLE) - .quirks = BT_QUIRK_NO_AUTO_DLE, -#endif -}; - -static int bt_b91_init(void) -{ - - bt_hci_driver_register(&drv); - - return 0; -} - -SYS_INIT(bt_b91_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/drivers/bluetooth/hci/hci_da1469x.c b/drivers/bluetooth/hci/hci_da1469x.c new file mode 100644 index 0000000000000..18733d8444cdb --- /dev/null +++ b/drivers/bluetooth/hci/hci_da1469x.c @@ -0,0 +1,525 @@ +/* hci_da1469x.c - DA1469x CMAC IPC Bluetooth driver */ + +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include + +LOG_MODULE_REGISTER(hci_da1469x); + +#define DT_DRV_COMPAT renesas_bt_hci_da1469x + +struct hci_data { + bt_hci_recv_t recv; +}; + +static K_KERNEL_STACK_DEFINE(rng_thread_stack, CONFIG_BT_RX_STACK_SIZE); +static struct k_thread rng_thread_data; +struct k_sem rng_sem; + +static K_KERNEL_STACK_DEFINE(rx_thread_stack, CONFIG_BT_RX_STACK_SIZE); +static struct k_thread rx_thread_data; + +static struct { + struct net_buf *buf; + struct k_fifo fifo; + + uint16_t remaining; + uint16_t discard; + + bool have_hdr; + bool discardable; + bool deferred; + + uint8_t hdr_len; + + uint8_t type; + union { + struct bt_hci_evt_hdr evt; + struct bt_hci_acl_hdr acl; + struct bt_hci_iso_hdr iso; + uint8_t hdr[4]; + }; +} rx = { + .fifo = Z_FIFO_INITIALIZER(rx.fifo), +}; + +static void h4_get_type(void) +{ + /* Get packet type */ + if (cmac_mbox_read(&rx.type, 1) != 1) { + LOG_WRN("Unable to read H:4 packet type"); + rx.type = BT_HCI_H4_NONE; + return; + } + + switch (rx.type) { + case BT_HCI_H4_EVT: + rx.remaining = sizeof(rx.evt); + rx.hdr_len = rx.remaining; + break; + case BT_HCI_H4_ACL: + rx.remaining = sizeof(rx.acl); + rx.hdr_len = rx.remaining; + break; + case BT_HCI_H4_ISO: + if (IS_ENABLED(CONFIG_BT_ISO)) { + rx.remaining = sizeof(rx.iso); + rx.hdr_len = rx.remaining; + break; + } + __fallthrough; + default: + LOG_ERR("Unknown H:4 type 0x%02x", rx.type); + rx.type = BT_HCI_H4_NONE; + } +} + +static void h4_read_hdr(void) +{ + int bytes_read = rx.hdr_len - rx.remaining; + int ret; + + ret = cmac_mbox_read(rx.hdr + bytes_read, rx.remaining); + if (unlikely(ret < 0)) { + LOG_ERR("Unable to read from mailbox (ret %d)", ret); + } else { + rx.remaining -= ret; + } +} + +static inline void get_acl_hdr(void) +{ + h4_read_hdr(); + + if (!rx.remaining) { + struct bt_hci_acl_hdr *hdr = &rx.acl; + + rx.remaining = sys_le16_to_cpu(hdr->len); + LOG_DBG("Got ACL header. Payload %u bytes", rx.remaining); + rx.have_hdr = true; + } +} + +static inline void get_iso_hdr(void) +{ + h4_read_hdr(); + + if (!rx.remaining) { + struct bt_hci_iso_hdr *hdr = &rx.iso; + + rx.remaining = bt_iso_hdr_len(sys_le16_to_cpu(hdr->len)); + LOG_DBG("Got ISO header. Payload %u bytes", rx.remaining); + rx.have_hdr = true; + } +} + +static inline void get_evt_hdr(void) +{ + struct bt_hci_evt_hdr *hdr = &rx.evt; + + h4_read_hdr(); + + if (rx.hdr_len == sizeof(*hdr) && rx.remaining < sizeof(*hdr)) { + switch (rx.evt.evt) { + case BT_HCI_EVT_LE_META_EVENT: + rx.remaining++; + rx.hdr_len++; + break; + } + } + + if (!rx.remaining) { + if (rx.evt.evt == BT_HCI_EVT_LE_META_EVENT && + (rx.hdr[sizeof(*hdr)] == BT_HCI_EVT_LE_ADVERTISING_REPORT)) { + LOG_DBG("Marking adv report as discardable"); + rx.discardable = true; + } + + rx.remaining = hdr->len - (rx.hdr_len - sizeof(*hdr)); + LOG_DBG("Got event header. Payload %u bytes", hdr->len); + rx.have_hdr = true; + } +} + + +static inline void copy_hdr(struct net_buf *buf) +{ + net_buf_add_mem(buf, rx.hdr, rx.hdr_len); +} + +static void reset_rx(void) +{ + rx.type = BT_HCI_H4_NONE; + rx.remaining = 0U; + rx.have_hdr = false; + rx.hdr_len = 0U; + rx.discardable = false; +} + +static struct net_buf *get_rx(k_timeout_t timeout) +{ + LOG_DBG("type 0x%02x, evt 0x%02x", rx.type, rx.evt.evt); + + switch (rx.type) { + case BT_HCI_H4_EVT: + return bt_buf_get_evt(rx.evt.evt, rx.discardable, timeout); + case BT_HCI_H4_ACL: + return bt_buf_get_rx(BT_BUF_ACL_IN, timeout); + case BT_HCI_H4_ISO: + if (IS_ENABLED(CONFIG_BT_ISO)) { + return bt_buf_get_rx(BT_BUF_ISO_IN, timeout); + } + } + + return NULL; +} + +static void rx_isr_start(void) +{ + if (rx.deferred) { + rx.deferred = false; + NVIC_SetPendingIRQ(CMAC2SYS_IRQn); + } + + irq_enable(CMAC2SYS_IRQn); +} + +static void rx_isr_stop(void) +{ + irq_disable(CMAC2SYS_IRQn); +} + +static void rx_thread(void *p1, void *p2, void *p3) +{ + const struct device *dev = p1; + struct hci_data *hci = dev->data; + struct net_buf *buf; + + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + LOG_DBG("started"); + + while (1) { + LOG_DBG("rx.buf %p", rx.buf); + + /* We can only do the allocation if we know the initial + * header, since Command Complete/Status events must use the + * original command buffer (if available). + */ + if (rx.have_hdr && !rx.buf) { + rx.buf = get_rx(K_FOREVER); + LOG_DBG("Got rx.buf %p", rx.buf); + if (rx.remaining > net_buf_tailroom(rx.buf)) { + LOG_ERR("Not enough space in buffer"); + rx.discard = rx.remaining; + reset_rx(); + } else { + copy_hdr(rx.buf); + } + } + + /* Let the ISR continue receiving new packets */ + rx_isr_start(); + + buf = net_buf_get(&rx.fifo, K_FOREVER); + do { + rx_isr_start(); + + LOG_DBG("Calling bt_recv(%p)", buf); + hci->recv(dev, buf); + + /* Give other threads a chance to run if the ISR + * is receiving data so fast that rx.fifo never + * or very rarely goes empty. + */ + k_yield(); + + rx_isr_stop(); + + buf = net_buf_get(&rx.fifo, K_NO_WAIT); + } while (buf); + } +} + +static size_t h4_discard(size_t len) +{ + uint8_t buf[33]; + int err; + + err = cmac_mbox_read(buf, MIN(len, sizeof(buf))); + if (unlikely(err < 0)) { + LOG_ERR("Unable to read from mailbox (err %d)", err); + return 0; + } + + return err; +} + +static inline void read_payload(void) +{ + struct net_buf *buf; + int read; + + if (!rx.buf) { + size_t buf_tailroom; + + rx.buf = get_rx(K_NO_WAIT); + if (!rx.buf) { + if (rx.discardable) { + LOG_WRN("Discarding event 0x%02x", rx.evt.evt); + rx.discard = rx.remaining; + reset_rx(); + return; + } + + LOG_WRN("Failed to allocate, deferring to rx_thread"); + rx.deferred = true; + return; + } + + LOG_DBG("Allocated rx.buf %p", rx.buf); + + buf_tailroom = net_buf_tailroom(rx.buf); + if (buf_tailroom < rx.remaining) { + LOG_ERR("Not enough space in buffer %u/%zu", rx.remaining, buf_tailroom); + rx.discard = rx.remaining; + reset_rx(); + return; + } + + copy_hdr(rx.buf); + } + + read = cmac_mbox_read(net_buf_tail(rx.buf), rx.remaining); + if (unlikely(read < 0)) { + LOG_ERR("Failed to read mailbox (err %d)", read); + return; + } + + net_buf_add(rx.buf, read); + rx.remaining -= read; + + LOG_DBG("got %d bytes, remaining %u", read, rx.remaining); + LOG_DBG("Payload (len %u): %s", rx.buf->len, bt_hex(rx.buf->data, rx.buf->len)); + + if (rx.remaining) { + return; + } + + buf = rx.buf; + rx.buf = NULL; + + if (rx.type == BT_HCI_H4_EVT) { + bt_buf_set_type(buf, BT_BUF_EVT); + } else { + bt_buf_set_type(buf, BT_BUF_ACL_IN); + } + + reset_rx(); + + LOG_DBG("Putting buf %p to rx fifo", buf); + net_buf_put(&rx.fifo, buf); +} + +static inline void read_header(void) +{ + switch (rx.type) { + case BT_HCI_H4_NONE: + h4_get_type(); + return; + case BT_HCI_H4_EVT: + get_evt_hdr(); + break; + case BT_HCI_H4_ACL: + get_acl_hdr(); + break; + case BT_HCI_H4_ISO: + if (IS_ENABLED(CONFIG_BT_ISO)) { + get_iso_hdr(); + break; + } + __fallthrough; + default: + CODE_UNREACHABLE; + return; + } + + if (rx.have_hdr && rx.buf) { + if (rx.remaining > net_buf_tailroom(rx.buf)) { + LOG_ERR("Not enough space in buffer"); + rx.discard = rx.remaining; + reset_rx(); + } else { + copy_hdr(rx.buf); + } + } +} + +static inline void process_rx(void) +{ + LOG_DBG("remaining %u discard %u have_hdr %u rx.buf %p len %u", rx.remaining, rx.discard, + rx.have_hdr, rx.buf, rx.buf ? rx.buf->len : 0); + + if (rx.discard) { + rx.discard -= h4_discard(rx.discard); + return; + } + + if (rx.have_hdr) { + read_payload(); + } else { + read_header(); + } +} + +/* Called by HAL when data in CMAC mailbox is available to read */ +void cmac_read_req(void) +{ + while (!rx.deferred && cmac_mbox_has_data()) { + process_rx(); + } +} + +/* Called by HAL when CMAC requests host to put more data in rng buffer */ +void cmac_rng_req(void) +{ + k_sem_give(&rng_sem); +} + +static void rng_thread(void *p1, void *p2, void *p3) +{ + uint32_t word; + + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + while (1) { + k_sem_take(&rng_sem, K_FOREVER); + + while (cmac_rand_needs_data()) { + word = sys_rand32_get(); + cmac_rand_fill(&word, 1); + } + + cmac_signal(); + } +} + +static int bt_da1469x_open(const struct device *dev, bt_hci_recv_t recv) +{ + struct hci_data *hci = dev->data; + k_tid_t tid; + + tid = k_thread_create(&rx_thread_data, rx_thread_stack, + K_KERNEL_STACK_SIZEOF(rx_thread_stack), + rx_thread, (void *)dev, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_RX_PRIO), + 0, K_NO_WAIT); + k_thread_name_set(tid, "bt_rx_thread"); + + k_sem_init(&rng_sem, 0, 1); + + tid = k_thread_create(&rng_thread_data, rng_thread_stack, + K_KERNEL_STACK_SIZEOF(rng_thread_stack), + rng_thread, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_RX_PRIO), + 0, K_NO_WAIT); + k_thread_name_set(tid, "bt_rng_thread"); + + hci->recv = recv; + + cmac_enable(); + irq_enable(CMAC2SYS_IRQn); + + return 0; +} + +#ifdef CONFIG_BT_HCI_HOST +static int bt_da1469x_close(const struct device *dev) +{ + struct hci_data *hci = dev->data; + + irq_disable(CMAC2SYS_IRQn); + cmac_disable(); + + hci->recv = NULL; + + return 0; +} +#endif /* CONFIG_BT_HCI_HOST */ + +static int bt_da1469x_send(const struct device *dev, struct net_buf *buf) +{ + ARG_UNUSED(dev); + + switch (bt_buf_get_type(buf)) { + case BT_BUF_ACL_OUT: + LOG_DBG("ACL: buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + net_buf_push_u8(buf, BT_HCI_H4_ACL); + break; + case BT_BUF_CMD: + LOG_DBG("CMD: buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + net_buf_push_u8(buf, BT_HCI_H4_CMD); + break; + default: + LOG_ERR("Unsupported type"); + return -EINVAL; + } + + cmac_mbox_write(buf->data, buf->len); + + net_buf_unref(buf); + + return 0; +} + +static const struct bt_hci_driver_api drv = { + .open = bt_da1469x_open, + .close = bt_da1469x_close, + .send = bt_da1469x_send, +}; + +static int bt_da1469x_init(const struct device *dev) +{ + irq_disable(CMAC2SYS_IRQn); + + cmac_disable(); + cmac_load_image(); + cmac_configure_pdc(); + cmac_configure_shm(); + + IRQ_CONNECT(CMAC2SYS_IRQn, 0, cmac_cmac2sys_isr, NULL, 0); + + return 0; +} + +#define HCI_DEVICE_INIT(inst) \ + static struct hci_data hci_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, bt_da1469x_init, NULL, &hci_data_##inst, NULL, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) + +/* Only one instance supported right now */ +HCI_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/hci_esp32.c b/drivers/bluetooth/hci/hci_esp32.c index 311dddf916c32..7536e9f7622e9 100644 --- a/drivers/bluetooth/hci/hci_esp32.c +++ b/drivers/bluetooth/hci/hci_esp32.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include @@ -17,8 +17,14 @@ #include LOG_MODULE_REGISTER(bt_hci_driver_esp32); +#define DT_DRV_COMPAT espressif_esp32_bt_hci + #define HCI_BT_ESP32_TIMEOUT K_MSEC(2000) +struct bt_esp32_data { + bt_hci_recv_t recv; +}; + static K_SEM_DEFINE(hci_send_sem, 1, 1); static bool is_hci_event_discardable(const uint8_t *evt_data) @@ -180,6 +186,8 @@ static struct net_buf *bt_esp_iso_recv(uint8_t *data, size_t remaining) static int hci_esp_host_rcv_pkt(uint8_t *data, uint16_t len) { + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); + struct bt_esp32_data *hci = dev->data; uint8_t pkt_indicator; struct net_buf *buf = NULL; size_t remaining = len; @@ -210,7 +218,7 @@ static int hci_esp_host_rcv_pkt(uint8_t *data, uint16_t len) if (buf) { LOG_DBG("Calling bt_recv(%p)", buf); - bt_recv(buf); + hci->recv(dev, buf); } return 0; @@ -226,7 +234,7 @@ static esp_vhci_host_callback_t vhci_host_cb = { hci_esp_host_rcv_pkt }; -static int bt_esp32_send(struct net_buf *buf) +static int bt_esp32_send(const struct device *dev, struct net_buf *buf) { int err = 0; uint8_t pkt_indicator; @@ -316,8 +324,9 @@ static int bt_esp32_ble_deinit(void) return 0; } -static int bt_esp32_open(void) +static int bt_esp32_open(const struct device *dev, bt_hci_recv_t recv) { + struct bt_esp32_data *hci = dev->data; int err; err = bt_esp32_ble_init(); @@ -325,13 +334,16 @@ static int bt_esp32_open(void) return err; } + hci->recv = recv; + LOG_DBG("ESP32 BT started"); return 0; } -static int bt_esp32_close(void) +static int bt_esp32_close(const struct device *dev) { + struct bt_esp32_data *hci = dev->data; int err; err = bt_esp32_ble_deinit(); @@ -339,27 +351,24 @@ static int bt_esp32_close(void) return err; } + hci->recv = NULL; + LOG_DBG("ESP32 BT stopped"); return 0; } -static const struct bt_hci_driver drv = { - .name = "BT ESP32", +static const struct bt_hci_driver_api drv = { .open = bt_esp32_open, .send = bt_esp32_send, .close = bt_esp32_close, - .bus = BT_HCI_DRIVER_BUS_IPM, -#if defined(CONFIG_BT_DRIVER_QUIRK_NO_AUTO_DLE) - .quirks = BT_QUIRK_NO_AUTO_DLE, -#endif }; -static int bt_esp32_init(void) -{ - bt_hci_driver_register(&drv); - - return 0; -} +#define BT_ESP32_DEVICE_INIT(inst) \ + static struct bt_esp32_data bt_esp32_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &bt_esp32_data_##inst, NULL, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) -SYS_INIT(bt_esp32_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +/* Only one instance supported */ +BT_ESP32_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/hci_ifx_cyw208xx.c b/drivers/bluetooth/hci/hci_ifx_cyw208xx.c new file mode 100644 index 0000000000000..0590b4c55755a --- /dev/null +++ b/drivers/bluetooth/hci/hci_ifx_cyw208xx.c @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + + /** + * @brief Zephyr CYW20829 driver. + * + * This driver uses btstack-integration asset as hosts platform adaptation layer + * (porting layer) for CYW20829. btstack-integration layer implements/ + * invokes the interfaces defined by BTSTACK to to enable communication + * with the BT controller by using IPC_BTSS (IPC Bluetooth sub-system interface). + * Zephyr CYW20829 driver implements wiced_bt_**** functions requreds for + * btstack-integration asset and Zephyr Bluetooth driver interface + * (defined in struct bt_hci_driver). + * + * CM33 (application core) + * |=========================================| + * | |-------------------------| | + * | | Zephyr application | | + * | |-------------------------| | + * | | | + * | |------------| | + * | | Zephyr | | + * | | Bluetooth | | + * CM33 (BTSS core) | | Host | | + * |=====================| | |------------| | + * | | | | | + * | |---------------| | | |--------------| | -----------| | + * | | Bluetooth | | IPC_BTSS | | btstack- | | Zephyr | | + * | | Controller FW | | <--------|-> | integration | ---- | CYW20829 | | + * | |---------------| | | | asset | | driver | | + * | | | |--------------| |------------| | + * |=====================| | | + * | |=========================================| + * |====================| + * | CYW20829 | + * | Bluetooth | + * |====================| + * + * NOTE: + * cyw920829 requires fetch binary files of Bluetooth controller firmware. + * To fetch Binary Blobs: west blobs fetch hal_infineon + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include +LOG_MODULE_REGISTER(cyw208xx); + +#define DT_DRV_COMPAT infineon_cyw208xx_hci + +struct cyw208xx_data { + bt_hci_recv_t recv; +}; + +enum { + BT_HCI_VND_OP_DOWNLOAD_MINIDRIVER = 0xFC2E, + BT_HCI_VND_OP_WRITE_RAM = 0xFC4C, + BT_HCI_VND_OP_LAUNCH_RAM = 0xFC4E, + BT_HCI_VND_OP_UPDATE_BAUDRATE = 0xFC18, +}; + +/* Externs for CY43xxx controller FW */ +extern const uint8_t brcm_patchram_buf[]; +extern const int brcm_patch_ram_length; + +#define CYBSP_BT_PLATFORM_CFG_SLEEP_MODE_LP_ENABLED (1) + +static K_SEM_DEFINE(hci_sem, 1, 1); +static K_SEM_DEFINE(cybt_platform_task_init_sem, 0, 1); + + +/****************************************************************************** + * Function Declarations + ******************************************************************************/ +extern void host_stack_platform_interface_init(void); +extern void cybt_platform_hci_wait_for_boot_fully_up(bool is_from_isr); +extern uint8_t *host_stack_get_acl_to_lower_buffer(wiced_bt_transport_t transport, uint32_t size); +extern wiced_result_t host_stack_send_acl_to_lower(wiced_bt_transport_t transport, + uint8_t *data, uint16_t len); +extern wiced_result_t host_stack_send_cmd_to_lower(uint8_t *cmd, uint16_t cmd_len); +extern wiced_result_t host_stack_send_iso_to_lower(uint8_t *data, uint16_t len); +extern cybt_result_t cybt_platform_msg_to_bt_task(const uint16_t msg, bool is_from_isr); +extern void cybt_bttask_deinit(void); + +static int cyw208xx_bt_firmware_download(const uint8_t *firmware_image, uint32_t size) +{ + uint8_t *data = (uint8_t *)firmware_image; + volatile uint32_t remaining_length = size; + struct net_buf *buf; + int err; + + LOG_DBG("Executing Fw downloading for CYW208xx device"); + + /* The firmware image (.hcd format) contains a collection of hci_write_ram + * command + a block of the image, followed by a hci_write_ram image at the end. + * Parse and send each individual command and wait for the response. This is to + * ensure the integrity of the firmware image sent to the bluetooth chip. + */ + while (remaining_length) { + size_t data_length = data[2]; /* data length from firmware image block */ + uint16_t op_code = *(uint16_t *)data; + + /* Allocate buffer for hci_write_ram/hci_launch_ram command. */ + buf = bt_hci_cmd_create(op_code, data_length); + if (buf == NULL) { + LOG_ERR("Unable to allocate command buffer"); + return err; + } + + /* Add data part of packet */ + net_buf_add_mem(buf, &data[3], data_length); + + /* Send hci_write_ram command. */ + err = bt_hci_cmd_send_sync(op_code, buf, NULL); + if (err) { + return err; + } + + switch (op_code) { + case BT_HCI_VND_OP_WRITE_RAM: + /* Update remaining length and data pointer: + * content of data length + 2 bytes of opcode and 1 byte of data length. + */ + data += data_length + 3; + remaining_length -= data_length + 3; + break; + + case BT_HCI_VND_OP_LAUNCH_RAM: + remaining_length = 0; + break; + + default: + return -ENOMEM; + } + } + + LOG_DBG("Fw downloading complete"); + return 0; +} + +static int cyw208xx_setup(const struct device *dev, const struct bt_hci_setup_params *params) +{ + ARG_UNUSED(dev); + ARG_UNUSED(params); + int err; + + /* Send HCI_RESET */ + err = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, NULL); + if (err) { + return err; + } + + /* BT firmware download */ + err = cyw208xx_bt_firmware_download(brcm_patchram_buf, (uint32_t)brcm_patch_ram_length); + if (err) { + return err; + } + + /* Waiting when BLE up after firmware launch */ + cybt_platform_hci_wait_for_boot_fully_up(false); + return 0; +} + +static int cyw208xx_open(const struct device *dev, bt_hci_recv_t recv) +{ + int err; + struct cyw208xx_data *hci = dev->data; + + hci->recv = recv; + + /* Initialize Bluetooth platform related OS tasks. */ + err = cybt_platform_task_init((void *)NULL); + if (err) { + return err; + } + + /* Wait until cybt platform task starts */ + k_sem_take(&cybt_platform_task_init_sem, K_FOREVER); + + return 0; +} + +static int cyw208xx_close(const struct device *dev) +{ + struct cyw208xx_data *hci = dev->data; + + /* Send SHUTDOWN event, BT task will release resources and tervinate task */ + cybt_platform_msg_to_bt_task(BT_EVT_TASK_SHUTDOWN, false); + + cybt_bttask_deinit(); + + k_sem_reset(&cybt_platform_task_init_sem); + hci->recv = NULL; + + return 0; +} + +static int cyw208xx_send(const struct device *dev, struct net_buf *buf) +{ + ARG_UNUSED(dev); + + int ret = 0; + + k_sem_take(&hci_sem, K_FOREVER); + + LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + + switch (bt_buf_get_type(buf)) { + case BT_BUF_ACL_OUT: + uint8_t *bt_msg = host_stack_get_acl_to_lower_buffer(BT_TRANSPORT_LE, buf->len); + + memcpy(bt_msg, buf->data, buf->len); + ret = host_stack_send_acl_to_lower(BT_TRANSPORT_LE, bt_msg, buf->len); + break; + + case BT_BUF_CMD: + ret = host_stack_send_cmd_to_lower(buf->data, buf->len); + break; + + case BT_BUF_ISO_OUT: + ret = host_stack_send_iso_to_lower(buf->data, buf->len); + break; + + default: + LOG_ERR("Unknown type %u", bt_buf_get_type(buf)); + ret = EIO; + goto done; + } + + LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:"); + + if (ret) { + LOG_ERR("SPI write error %d", ret); + } + +done: + k_sem_give(&hci_sem); + net_buf_unref(buf); + return ret ? -EIO : 0; +} + +static const struct bt_hci_driver_api drv = { + .open = cyw208xx_open, + .close = cyw208xx_close, + .send = cyw208xx_send, + .setup = cyw208xx_setup +}; + +static int cyw208xx_hci_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + const cybt_platform_config_t cybsp_bt_platform_cfg = { + .hci_config = { + .hci_transport = CYBT_HCI_IPC, + }, + + .controller_config = { + .sleep_mode = { + .sleep_mode_enabled = CYBSP_BT_PLATFORM_CFG_SLEEP_MODE_LP_ENABLED, + }, + } + }; + + /* Configure platform specific settings for the BT device */ + cybt_platform_config_init(&cybsp_bt_platform_cfg); + + return 0; +} + +/* Implements wiced_bt_**** functions requreds for the btstack-integration asset */ + +wiced_result_t wiced_bt_dev_vendor_specific_command(uint16_t opcode, uint8_t param_len, + uint8_t *param_buf, wiced_bt_dev_vendor_specific_command_complete_cback_t cback) + +{ + /* + * This function is using only by btstack-integration asset + * for enable LPM. + */ + struct net_buf *buf = NULL; + + /* Allocate a HCI command buffer */ + buf = bt_hci_cmd_create(opcode, param_len); + if (!buf) { + LOG_ERR("Unable to allocate buffer"); + return WICED_NO_MEMORY; + } + + /* Add data part of packet */ + net_buf_add_mem(buf, param_buf, param_len); + bt_hci_cmd_send(opcode, buf); + + return WICED_BT_SUCCESS; +} + +void wiced_bt_process_hci(hci_packet_type_t pti, uint8_t *data, uint32_t length) +{ + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); + struct cyw208xx_data *hci = dev->data; + struct net_buf *buf = NULL; + size_t buf_tailroom = 0; + + switch (pti) { + case HCI_PACKET_TYPE_EVENT: + buf = bt_buf_get_evt(data[0], 0, K_NO_WAIT); + if (!buf) { + LOG_ERR("Failed to allocate the buffer for RX: EVENT "); + return; + } + break; + + case HCI_PACKET_TYPE_ACL: + buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT); + if (!buf) { + LOG_ERR("Failed to allocate the buffer for RX: ACL "); + return; + } + bt_buf_set_type(buf, BT_BUF_ACL_IN); + break; + + case HCI_PACKET_TYPE_SCO: + /* NA */ + break; + + case HCI_PACKET_TYPE_ISO: + buf = bt_buf_get_rx(BT_BUF_ISO_IN, K_NO_WAIT); + if (!buf) { + LOG_ERR("Failed to allocate the buffer for RX: ISO "); + return; + } + break; + + default: + return; + + } + + buf_tailroom = net_buf_tailroom(buf); + if (buf_tailroom < length) { + LOG_WRN("Not enough space for rx data"); + return; + } + net_buf_add_mem(buf, data, length); + + /* Provide the buffer to the host */ + hci->recv(dev, buf); +} + +void wiced_bt_process_hci_events(uint8_t *data, uint32_t length) +{ + wiced_bt_process_hci(HCI_PACKET_TYPE_EVENT, data, length); +} + +void wiced_bt_process_acl_data(uint8_t *data, uint32_t length) +{ + wiced_bt_process_hci(HCI_PACKET_TYPE_ACL, data, length); +} + +void wiced_bt_process_isoc_data(uint8_t *data, uint32_t length) +{ + wiced_bt_process_hci(HCI_PACKET_TYPE_ISO, data, length); +} + +void wiced_bt_stack_init_internal(wiced_bt_management_cback_t mgmt_cback, + wiced_bt_internal_post_stack_init_cb post_stack_cb, + wiced_bt_internal_stack_evt_handler_cb evt_handler_cb) +{ + k_sem_give(&cybt_platform_task_init_sem); +} + +/* Keep below empty functions, used in the btstack_integration assets for Wiced BT stack. */ +void wiced_bt_stack_indicate_lower_tx_complete(void) +{ + /* NA for Zephyr */ +} + +void wiced_bt_stack_shutdown(void) +{ + /* NA for Zephyr */ +} + +void wiced_bt_process_timer(void) +{ + /* NA for Zephyr */ +} + +#define CYW208XX_DEVICE_INIT(inst) \ + static struct cyw208xx_data cyw208xx_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, cyw208xx_hci_init, NULL, &cyw208xx_data_##inst, NULL, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) + +/* Only one instance supported */ +CYW208XX_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/hci_ifx_psoc6_bless.c b/drivers/bluetooth/hci/hci_ifx_psoc6_bless.c new file mode 100644 index 0000000000000..5f4d1fdd13ddd --- /dev/null +++ b/drivers/bluetooth/hci/hci_ifx_psoc6_bless.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief PSoC 6 BLE (BLESS) driver. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include +LOG_MODULE_REGISTER(psoc6_bless); + +#include "cy_ble_stack_pvt.h" +#include "cycfg_ble.h" + +#define DT_DRV_COMPAT infineon_cat1_bless_hci + +struct psoc6_bless_data { + bt_hci_recv_t recv; +}; + +#define BLE_LOCK_TMOUT_MS (1000) +#define BLE_THREAD_SEM_TMOUT_MS (1000) + +#define CYBLE_STACK_SIZE (CY_BLE_STACK_RAM_SIZE + 4096) + +#define PSOC6_BLESS_OP_SET_PUBLIC_ADDR BT_OP(BT_OGF_VS, 0x1a0) + +static K_SEM_DEFINE(psoc6_bless_rx_sem, 0, 1); +static K_SEM_DEFINE(psoc6_bless_operation_sem, 1, 1); +static K_KERNEL_STACK_DEFINE(psoc6_bless_rx_thread_stack, CONFIG_BT_RX_STACK_SIZE); +static struct k_thread psoc6_bless_rx_thread_data; +static cy_stc_ble_hci_tx_packet_info_t hci_tx_pkt; + +extern void Cy_BLE_EnableLowPowerMode(void); + +CY_ALIGN(sizeof(uint32_t)) CY_NOINIT uint8_t psoc6_bless_stack_memory[CYBLE_STACK_SIZE]; + +/** BLE Stack parameters */ +static cy_stc_ble_stack_params_t psoc6_bless_stack_param = { + .memoryHeapPtr = psoc6_bless_stack_memory, + .totalHeapSz = CYBLE_STACK_SIZE, + .dleMaxTxCapability = CONFIG_BT_PSOC6_BLESS_MAX_TX_PAYLOAD, + .dleMaxRxCapability = CONFIG_BT_PSOC6_BLESS_MAX_RX_PAYLOAD, + .featureMask = (CY_BLE_DLE_FEATURE | CY_BLE_LL_PRIVACY_FEATURE | + CY_BLE_SECURE_CONN_FEATURE | CY_BLE_PHY_UPDATE_FEATURE | + CY_BLE_STORE_BONDLIST_FEATURE | CY_BLE_STORE_RESOLVING_LIST_FEATURE | + CY_BLE_STORE_WHITELIST_FEATURE | CY_BLE_TX_POWER_CALIBRATION_FEATURE), + .maxConnCount = CY_BLE_CONN_COUNT, + .tx5dbmModeEn = CY_BLE_ENABLE_TX_5DBM, +}; + +static const cy_stc_sysint_t psoc6_bless_isr_cfg = { + .intrSrc = DT_INST_IRQN(0), + .intrPriority = DT_INST_IRQ(0, priority), +}; + +static cy_stc_ble_hw_config_t psoc6_bless_hw_config = { + .blessIsrConfig = &psoc6_bless_isr_cfg, +}; + +static const cy_stc_ble_config_t psoc6_bless_config = { + .stackParam = &psoc6_bless_stack_param, + .hw = &psoc6_bless_hw_config, +}; + +static void psoc6_bless_rx_thread(void *, void *, void *) +{ + while (true) { + k_sem_take(&psoc6_bless_rx_sem, K_MSEC(BLE_THREAD_SEM_TMOUT_MS)); + Cy_BLE_ProcessEvents(); + } +} + +static void psoc6_bless_isr_handler(const struct device *dev) +{ + if (Cy_BLE_HAL_BlessInterruptHandler()) { + k_sem_give(&psoc6_bless_rx_sem); + } +} + +static void psoc6_bless_events_handler(uint32_t eventCode, void *eventParam) +{ + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); + struct psoc6_bless_data *hci = dev->data; + cy_stc_ble_hci_tx_packet_info_t *hci_rx = NULL; + struct net_buf *buf = NULL; + size_t buf_tailroom = 0; + + if (eventCode != CY_BLE_EVT_HCI_PKT_RCVD) { + LOG_DBG("Other EVENT 0x%X", eventCode); + return; + } + + hci_rx = eventParam; + + switch (hci_rx->packetType) { + case BT_HCI_H4_EVT: + buf = bt_buf_get_evt(hci_rx->data[0], 0, K_NO_WAIT); + if (!buf) { + LOG_ERR("Failed to allocate the buffer for RX: EVENT "); + return; + } + + break; + case BT_HCI_H4_ACL: + buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT); + if (!buf) { + LOG_ERR("Failed to allocate the buffer for RX: ACL "); + return; + } + bt_buf_set_type(buf, BT_BUF_ACL_IN); + + break; + + default: + LOG_WRN("Unsupported HCI Packet Received"); + return; + } + + buf_tailroom = net_buf_tailroom(buf); + if (buf_tailroom < hci_rx->dataLength) { + LOG_WRN("Not enough space for rx data"); + return; + } + net_buf_add_mem(buf, hci_rx->data, hci_rx->dataLength); + hci->recv(dev, buf); +} + +static int psoc6_bless_open(const struct device *dev, bt_hci_recv_t recv) +{ + struct psoc6_bless_data *hci = dev->data; + k_tid_t tid; + + hci->recv = recv; + + tid = k_thread_create(&psoc6_bless_rx_thread_data, psoc6_bless_rx_thread_stack, + K_KERNEL_STACK_SIZEOF(psoc6_bless_rx_thread_stack), + psoc6_bless_rx_thread, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_RX_PRIO), 0, K_NO_WAIT); + k_thread_name_set(tid, "psoc6_bless_rx_thread"); + + return 0; +} + +static int psoc6_bless_send(const struct device *dev, struct net_buf *buf) +{ + cy_en_ble_api_result_t result; + + ARG_UNUSED(dev); + + memset(&hci_tx_pkt, 0, sizeof(cy_stc_ble_hci_tx_packet_info_t)); + + hci_tx_pkt.dataLength = buf->len; + hci_tx_pkt.data = buf->data; + + switch (bt_buf_get_type(buf)) { + case BT_BUF_ACL_OUT: + hci_tx_pkt.packetType = BT_HCI_H4_ACL; + break; + case BT_BUF_CMD: + hci_tx_pkt.packetType = BT_HCI_H4_CMD; + break; + default: + net_buf_unref(buf); + return -ENOTSUP; + } + + if (k_sem_take(&psoc6_bless_operation_sem, K_MSEC(BLE_LOCK_TMOUT_MS)) != 0) { + LOG_ERR("Failed to acquire BLE DRV Semaphore"); + net_buf_unref(buf); + return -EIO; + } + + result = Cy_BLE_SoftHciSendAppPkt(&hci_tx_pkt); + if (result != CY_BLE_SUCCESS) { + LOG_ERR("Error in sending packet reason %d\r\n", result); + } + + k_sem_give(&psoc6_bless_operation_sem); + + net_buf_unref(buf); + + return 0; +} + +static int psoc6_bless_setup(const struct device *dev, const struct bt_hci_setup_params *params) +{ + ARG_UNUSED(dev); + ARG_UNUSED(params); + struct net_buf *buf; + int err; + uint8_t *addr = (uint8_t *)&SFLASH_BLE_DEVICE_ADDRESS[0]; + uint8_t hci_data[] = { + addr[5], addr[4], addr[3], addr[2], addr[1], addr[0], BT_ADDR_LE_PUBLIC, + }; + + buf = bt_hci_cmd_create(PSOC6_BLESS_OP_SET_PUBLIC_ADDR, sizeof(hci_data)); + if (buf == NULL) { + LOG_ERR("Unable to allocate command buffer"); + return -ENOMEM; + } + + /* Add data part of packet */ + net_buf_add_mem(buf, hci_data, sizeof(hci_data)); + + err = bt_hci_cmd_send_sync(PSOC6_BLESS_OP_SET_PUBLIC_ADDR, buf, NULL); + if (err) { + return err; + } + + return 0; +} + +static int psoc6_bless_hci_init(const struct device *dev) +{ + cy_en_ble_api_result_t result; + + ARG_UNUSED(dev); + + /* Connect BLE interrupt to ISR */ + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), psoc6_bless_isr_handler, 0, 0); + + /* Registers the generic callback functions. */ + Cy_BLE_RegisterEventCallback(psoc6_bless_events_handler); + + /* Initializes the PSoC 6 BLESS Controller. */ + result = Cy_BLE_InitController(&psoc6_bless_config); + if (result != CY_BLE_SUCCESS) { + LOG_ERR("Failed to init the BLE Controller"); + return -EIO; + } + + /* Enables the BLESS controller in HCI only mode. */ + result = Cy_BLE_EnableHCIModeController(); + if (result != CY_BLE_SUCCESS) { + LOG_ERR("Failed to enable the BLE Controller in hci mode"); + return -EIO; + } + + /* Enables BLE Low-power mode (LPM)*/ + Cy_BLE_EnableLowPowerMode(); + + return 0; +} + +static const struct bt_hci_driver_api drv = { + .open = psoc6_bless_open, + .send = psoc6_bless_send, + .setup = psoc6_bless_setup, +}; + +#define PSOC6_BLESS_DEVICE_INIT(inst) \ + static struct psoc6_bless_data psoc6_bless_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, psoc6_bless_hci_init, NULL, &psoc6_bless_data_##inst, NULL, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) + +/* Only one instance supported */ +PSOC6_BLESS_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/hci_nxp.c b/drivers/bluetooth/hci/hci_nxp.c new file mode 100644 index 0000000000000..ff9d9628c1607 --- /dev/null +++ b/drivers/bluetooth/hci/hci_nxp.c @@ -0,0 +1,444 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* -------------------------------------------------------------------------- */ +/* Includes */ +/* -------------------------------------------------------------------------- */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* -------------------------------------------------------------------------- */ +/* Definitions */ +/* -------------------------------------------------------------------------- */ + +#define DT_DRV_COMPAT nxp_hci_ble + +struct bt_nxp_data { + bt_hci_recv_t recv; +}; + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +LOG_MODULE_REGISTER(bt_driver); + +#define HCI_IRQ_N DT_INST_IRQ_BY_NAME(0, hci_int, irq) +#define HCI_IRQ_P DT_INST_IRQ_BY_NAME(0, hci_int, priority) +#define HCI_WAKEUP_IRQ_N DT_INST_IRQ_BY_NAME(0, wakeup_int, irq) +#define HCI_WAKEUP_IRQ_P DT_INST_IRQ_BY_NAME(0, wakeup_int, priority) + +/* Vendor specific commands */ +#define HCI_CMD_STORE_BT_CAL_DATA_OCF 0x61U +#define HCI_CMD_STORE_BT_CAL_DATA_PARAM_LENGTH 32U +#define HCI_CMD_STORE_BT_CAL_DATA_ANNEX100_OCF 0xFFU +#define HCI_CMD_STORE_BT_CAL_DATA_PARAM_ANNEX100_LENGTH 16U +#define HCI_CMD_SET_BT_SLEEP_MODE_OCF 0x23U +#define HCI_CMD_SET_BT_SLEEP_MODE_PARAM_LENGTH 3U +#define HCI_CMD_BT_HOST_SLEEP_CONFIG_OCF 0x59U +#define HCI_CMD_BT_HOST_SLEEP_CONFIG_PARAM_LENGTH 2U + +/* -------------------------------------------------------------------------- */ +/* Public prototypes */ +/* -------------------------------------------------------------------------- */ + +extern int32_t ble_hci_handler(void); +extern int32_t ble_wakeup_done_handler(void); + +/* -------------------------------------------------------------------------- */ +/* Private functions */ +/* -------------------------------------------------------------------------- */ + +#if CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP || CONFIG_HCI_NXP_SET_CAL_DATA +static int nxp_bt_send_vs_command(uint16_t opcode, const uint8_t *params, uint8_t params_len) +{ +#if CONFIG_BT_HCI_HOST + struct net_buf *buf; + + /* Allocate buffer for the hci command */ + buf = bt_hci_cmd_create(opcode, params_len); + if (buf == NULL) { + LOG_ERR("Unable to allocate command buffer"); + return -ENOMEM; + } + + /* Add data part of packet */ + net_buf_add_mem(buf, params, params_len); + + /* Send the command */ + return bt_hci_cmd_send_sync(opcode, buf, NULL); +#else + return 0; +#endif +} +#endif /* CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP || CONFIG_HCI_NXP_SET_CAL_DATA */ + +#if CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP +static int nxp_bt_enable_controller_autosleep(void) +{ + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_SET_BT_SLEEP_MODE_OCF); + const uint8_t params[HCI_CMD_SET_BT_SLEEP_MODE_PARAM_LENGTH] = { + 0x02U, /* Auto sleep enable */ + 0x00U, /* Idle timeout LSB */ + 0x00U /* Idle timeout MSB */ + }; + + /* Send the command */ + return nxp_bt_send_vs_command(opcode, params, HCI_CMD_SET_BT_SLEEP_MODE_PARAM_LENGTH); +} + +static int nxp_bt_set_host_sleep_config(void) +{ + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_BT_HOST_SLEEP_CONFIG_OCF); + const uint8_t params[HCI_CMD_BT_HOST_SLEEP_CONFIG_PARAM_LENGTH] = { + 0xFFU, /* BT_HIU_WAKEUP_INBAND */ + 0xFFU, /* BT_HIU_WAKE_GAP_WAIT_FOR_IRQ */ + }; + + /* Send the command */ + return nxp_bt_send_vs_command(opcode, params, HCI_CMD_BT_HOST_SLEEP_CONFIG_PARAM_LENGTH); +} +#endif /* CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP */ + +#if CONFIG_HCI_NXP_SET_CAL_DATA +static int bt_nxp_set_calibration_data(void) +{ + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_STORE_BT_CAL_DATA_OCF); + extern const uint8_t hci_cal_data_params[HCI_CMD_STORE_BT_CAL_DATA_PARAM_LENGTH]; + + /* Send the command */ + return nxp_bt_send_vs_command(opcode, hci_cal_data_params, + HCI_CMD_STORE_BT_CAL_DATA_PARAM_LENGTH); +} + +#if CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100 +static int bt_nxp_set_calibration_data_annex100(void) +{ + uint16_t opcode = BT_OP(BT_OGF_VS, HCI_CMD_STORE_BT_CAL_DATA_ANNEX100_OCF); + + extern const uint8_t + hci_cal_data_annex100_params[HCI_CMD_STORE_BT_CAL_DATA_PARAM_ANNEX100_LENGTH]; + + /* Send the command */ + return nxp_bt_send_vs_command(opcode, hci_cal_data_annex100_params, + HCI_CMD_STORE_BT_CAL_DATA_PARAM_ANNEX100_LENGTH); +} +#endif /* CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100 */ + +#endif /* CONFIG_HCI_NXP_SET_CAL_DATA */ + +static bool is_hci_event_discardable(const uint8_t *evt_data) +{ + bool ret = false; + uint8_t evt_type = evt_data[0]; + + switch (evt_type) { + case BT_HCI_EVT_LE_META_EVENT: { + uint8_t subevt_type = evt_data[sizeof(struct bt_hci_evt_hdr)]; + + switch (subevt_type) { + case BT_HCI_EVT_LE_ADVERTISING_REPORT: + case BT_HCI_EVT_LE_EXT_ADVERTISING_REPORT: + ret = true; + break; + default: + break; + } + } break; + + default: + break; + } + + return ret; +} + +static struct net_buf *bt_evt_recv(uint8_t *data, size_t len) +{ + struct net_buf *buf; + uint8_t payload_len; + uint8_t evt_hdr; + bool discardable_evt; + size_t space_in_buffer; + + payload_len = data[1]; + evt_hdr = data[0]; + discardable_evt = false; + + /* Data Check */ + if (len < BT_HCI_EVT_HDR_SIZE) { + LOG_ERR("Event header is missing"); + return NULL; + } + if ((len - BT_HCI_EVT_HDR_SIZE) != payload_len) { + LOG_ERR("Event payload length is incorrect"); + return NULL; + } + + discardable_evt = is_hci_event_discardable(data); + + /* Allocate a buffer for the HCI Event */ + buf = bt_buf_get_evt(evt_hdr, discardable_evt, (discardable_evt ? K_NO_WAIT : K_FOREVER)); + + if (buf) { + space_in_buffer = net_buf_tailroom(buf); + if (len > space_in_buffer) { + LOG_ERR("Buffer size error,INFO : evt_hdr=%d, data_len=%zu, buf_size=%zu", + evt_hdr, len, space_in_buffer); + net_buf_unref(buf); + return NULL; + } + /* Copy the data to the buffer */ + net_buf_add_mem(buf, data, len); + } else { + if (discardable_evt) { + LOG_DBG("Discardable buffer pool full, ignoring event"); + } else { + LOG_ERR("No available event buffers!"); + } + return NULL; + } + + return buf; +} + +static struct net_buf *bt_acl_recv(uint8_t *data, size_t len) +{ + struct net_buf *buf; + uint16_t payload_len; + + /* Data Check */ + if (len < BT_HCI_ACL_HDR_SIZE) { + LOG_ERR("ACL header is missing"); + return NULL; + } + memcpy((void *)&payload_len, (void *)&data[2], 2); + if ((len - BT_HCI_ACL_HDR_SIZE) != payload_len) { + LOG_ERR("ACL payload length is incorrect"); + return NULL; + } + /* Allocate a buffer for the received data */ + buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT); + + if (buf) { + if (len > net_buf_tailroom(buf)) { + LOG_ERR("Buffer doesn't have enough space to store the data"); + net_buf_unref(buf); + return NULL; + } + /* Copy the data to the buffer */ + net_buf_add_mem(buf, data, len); + } else { + LOG_ERR("ACL buffer is empty"); + return NULL; + } + + return buf; +} + +static void hci_rx_cb(uint8_t packetType, uint8_t *data, uint16_t len) +{ + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); + struct bt_nxp_data *hci = dev->data; + struct net_buf *buf; + + switch (packetType) { + case BT_HCI_H4_EVT: + /* create a buffer and fill it out with event data */ + buf = bt_evt_recv(data, len); + break; + case BT_HCI_H4_ACL: + /* create a buffer and fill it out with ACL data */ + buf = bt_acl_recv(data, len); + break; + default: + buf = NULL; + LOG_ERR("Unknown HCI type"); + } + + if (buf) { + /* Provide the buffer to the host */ + hci->recv(dev, buf); + } +} + +static int bt_nxp_send(const struct device *dev, struct net_buf *buf) +{ + uint8_t packetType; + + ARG_UNUSED(dev); + + switch (bt_buf_get_type(buf)) { + case BT_BUF_CMD: + packetType = BT_HCI_H4_CMD; + break; + case BT_BUF_ACL_OUT: + packetType = BT_HCI_H4_ACL; + break; + default: + LOG_ERR("Not supported type"); + return -1; + } + + net_buf_push_u8(buf, packetType); + PLATFORM_SendHciMessage(buf->data, buf->len); + + net_buf_unref(buf); + + return 0; +} + +static int bt_nxp_open(const struct device *dev, bt_hci_recv_t recv) +{ + struct bt_nxp_data *hci = dev->data; + int ret = 0; + + do { + ret = PLATFORM_InitBle(); + if (ret < 0) { + LOG_ERR("Failed to initialize BLE controller"); + break; + } + + ret = PLATFORM_SetHciRxCallback(hci_rx_cb); + if (ret < 0) { + LOG_ERR("BLE HCI RX callback registration failed"); + break; + } + + ret = PLATFORM_StartHci(); + if (ret < 0) { + LOG_ERR("HCI open failed"); + break; + } + + hci->recv = recv; + } while (false); + + return ret; +} + +int bt_nxp_setup(const struct device *dev, const struct bt_hci_setup_params *params) +{ + ARG_UNUSED(dev); + ARG_UNUSED(params); + + int ret; + + do { +#if CONFIG_HCI_NXP_SET_CAL_DATA + ret = bt_nxp_set_calibration_data(); + if (ret < 0) { + LOG_ERR("Failed to set calibration data"); + break; + } +#if CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100 + /* After send annex55 to CPU2, CPU2 need reset, + * a delay of at least 20ms is required to continue sending annex100 + */ + k_sleep(Z_TIMEOUT_MS(20)); + + ret = bt_nxp_set_calibration_data_annex100(); + if (ret < 0) { + LOG_ERR("Failed to set calibration data"); + break; + } +#endif /* CONFIG_HCI_NXP_SET_CAL_DATA_ANNEX100 */ +#endif /* CONFIG_HCI_NXP_SET_CAL_DATA */ + +#if CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP + ret = nxp_bt_set_host_sleep_config(); + if (ret < 0) { + LOG_ERR("Failed to set host sleep config"); + break; + } + + ret = nxp_bt_enable_controller_autosleep(); + if (ret < 0) { + LOG_ERR("Failed to configure controller autosleep"); + break; + } +#endif /* CONFIG_HCI_NXP_ENABLE_AUTO_SLEEP */ + } while (false); + + return ret; +} + +static int bt_nxp_close(const struct device *dev) +{ + struct bt_nxp_data *hci = dev->data; + int ret = 0; + /* Reset the Controller */ +#if CONFIG_BT_HCI_HOST + ret = bt_hci_cmd_send_sync(BT_HCI_OP_RESET, NULL, NULL); + if (ret) { + LOG_ERR("Failed to reset BLE controller"); + } + k_sleep(K_SECONDS(1)); + + ret = PLATFORM_TerminateBle(); + if (ret < 0) { + LOG_ERR("Failed to shutdown BLE controller"); + } +#endif + hci->recv = NULL; + + return ret; +} + +static const struct bt_hci_driver_api drv = { + .open = bt_nxp_open, + .setup = bt_nxp_setup, + .close = bt_nxp_close, + .send = bt_nxp_send, +}; + +static int bt_nxp_init(const struct device *dev) +{ + int status; + int ret = 0; + + ARG_UNUSED(dev); + + /* HCI Interrupt */ + IRQ_CONNECT(HCI_IRQ_N, HCI_IRQ_P, ble_hci_handler, 0, 0); + irq_enable(HCI_IRQ_N); + + /* Wake up done interrupt */ + IRQ_CONNECT(HCI_WAKEUP_IRQ_N, HCI_WAKEUP_IRQ_P, ble_wakeup_done_handler, 0, 0); + irq_enable(HCI_WAKEUP_IRQ_N); + +#if (DT_INST_PROP(0, wakeup_source)) && CONFIG_PM + EnableDeepSleepIRQ(HCI_IRQ_N); +#endif + + do { + status = PLATFORM_InitBle(); + if (status < 0) { + LOG_ERR("BLE Controller initialization failed"); + ret = status; + break; + } + } while (0); + + return ret; +} + +#define HCI_DEVICE_INIT(inst) \ + static struct bt_nxp_data hci_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, bt_nxp_init, NULL, &hci_data_##inst, NULL, \ + POST_KERNEL, CONFIG_BT_HCI_INIT_PRIORITY, &drv) + +/* Only one instance supported right now */ +HCI_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/hci_nxp_setup.c b/drivers/bluetooth/hci/hci_nxp_setup.c new file mode 100644 index 0000000000000..b3cc0e18c6f2c --- /dev/null +++ b/drivers/bluetooth/hci/hci_nxp_setup.c @@ -0,0 +1,1177 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL +#include +LOG_MODULE_REGISTER(bt_nxp_ctlr); + +#include "common/bt_str.h" + +#include "bt_nxp_ctlr_fw.h" + +#define DT_DRV_COMPAT nxp_bt_hci_uart + +#define FW_UPLOAD_CHANGE_TIMEOUT_RETRY_COUNT 6 + +static const struct device *uart_dev = DEVICE_DT_GET(DT_INST_GPARENT(0)); + +#if DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) +struct gpio_dt_spec sdio_reset = GPIO_DT_SPEC_GET(DT_DRV_INST(0), sdio_reset_gpios); +#endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) */ +#if DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) +struct gpio_dt_spec w_disable = GPIO_DT_SPEC_GET(DT_DRV_INST(0), w_disable_gpios); +#endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) */ + +struct nxp_ctlr_dev_data { + uint32_t primary_speed; + bool primary_flowcontrol; + uint32_t secondary_speed; + bool secondary_flowcontrol; +}; + +static struct nxp_ctlr_dev_data uart_dev_data; + +#define DI 0x07U +#define POLYNOMIAL 0x04c11db7UL + +#define CRC32_LEN 4 + +static unsigned long crc_table[256U]; +static bool made_table; + +static void fw_upload_gen_crc32_table(void) +{ + int i, j; + unsigned long crc_accum; + + for (i = 0; i < 256; i++) { + crc_accum = ((unsigned long)i << 24); + for (j = 0; j < 8; j++) { + if (crc_accum & 0x80000000L) { + crc_accum = (crc_accum << 1) ^ POLYNOMIAL; + } else { + crc_accum = (crc_accum << 1); + } + } + crc_table[i] = crc_accum; + } +} + +static unsigned char fw_upload_crc8(unsigned char *array, unsigned char len) +{ + unsigned char crc_8 = 0xff; + + crc_8 = crc8(array, len, DI, crc_8, false); + + return crc_8; +} + +static unsigned long fw_upload_update_crc32(unsigned long crc_accum, char *data_blk_ptr, + int data_blk_size) +{ + unsigned int i, j; + + for (j = 0; j < data_blk_size; j++) { + i = ((unsigned int)(crc_accum >> 24) ^ *data_blk_ptr++) & 0xff; + crc_accum = (crc_accum << 8) ^ crc_table[i]; + } + return crc_accum; +} + +#define CMD4 0x4U +#define CMD6 0x6U +#define CMD7 0x7U + +#define V1_HEADER_DATA_REQ 0xa5U +#define V1_START_INDICATION 0xaaU +#define V1_REQUEST_ACK 0x5aU + +#define V3_START_INDICATION 0xabU +#define V3_HEADER_DATA_REQ 0xa7U +#define V3_REQUEST_ACK 0x7aU +#define V3_TIMEOUT_ACK 0x7bU +#define V3_CRC_ERROR 0x7cU + +#define REQ_HEADER_LEN 1U +#define A6REQ_PAYLOAD_LEN 8U +#define AbREQ_PAYLOAD_LEN 3U + +#define CRC_ERR_BIT BIT(0) +#define NAK_REC_BIT BIT(1) +#define TIMEOUT_REC_ACK_BIT BIT(2) +#define TIMEOUT_REC_HEAD_BIT BIT(3) +#define TIMEOUT_REC_DATA_BIT BIT(4) +#define INVALID_CMD_REC_BIT BIT(5) +#define WIFI_MIC_FAIL_BIT BIT(6) +#define BT_MIC_FAIL_BIT BIT(7) + +#define CMD_HDR_LEN 16 + +/* CMD5 Header to change bootloader baud rate */ +static uint8_t cmd5_hdrData[CMD_HDR_LEN] = {0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2c, 0x00, 0x00, 0x00, 0x77, 0xdb, 0xfd, 0xe0}; +/* CMD7 Header to change timeout of bootloader */ +static uint8_t cmd7_hdrData[CMD_HDR_LEN] = {0x07, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5b, 0x88, 0xf8, 0xba}; + +enum bt_nxp_ctlr_version { + VER1 = 1, + VER2, + VER3, +}; + +struct change_speed_config { + uint32_t clk_div_addr; + uint32_t clk_div_val; + uint32_t uart_clk_div_addr; + uint32_t uart_clk_div_val; + uint32_t mcr_addr; + uint32_t mcr_val; + uint32_t reinit_addr; + uint32_t reinit_val; + uint32_t icr_addr; + uint32_t icr_val; + uint32_t fcr_addr; + uint32_t fcr_val; +}; + +#define SEND_BUFFER_MAX_LENGTH 0xFFFFU /* Maximum 2 byte value */ +#define RECV_RING_BUFFER_LENGTH 1024 + +struct nxp_ctlr_fw_upload_state { + uint8_t version; + uint8_t hdr_sig; + + uint8_t buffer[A6REQ_PAYLOAD_LEN + REQ_HEADER_LEN + 1]; + + uint8_t send_buffer[SEND_BUFFER_MAX_LENGTH + 1]; + + struct { + uint8_t buffer[RECV_RING_BUFFER_LENGTH]; + uint32_t head; + uint32_t tail; + struct k_sem sem; + } rx; + + uint16_t length; + uint32_t offset; + uint16_t error; + uint8_t crc8; + + uint32_t last_offset; + uint8_t change_speed_buffer[sizeof(struct change_speed_config) + CRC32_LEN]; + + uint32_t fw_length; + uint32_t current_length; + const uint8_t *fw; + + uint32_t cmd7_change_timeout_len; + uint32_t change_speed_buffer_len; + + bool wait_hdr_sig; + + bool is_hdr_data; + bool is_error_case; + bool is_cmd7_req; + bool is_entry_point_req; + + uint8_t last_5bytes_buffer[6]; +}; + +static struct nxp_ctlr_fw_upload_state fw_upload; + +static int fw_upload_read_data(uint8_t *buffer, uint32_t len) +{ + int err; + + while (len > 0) { + err = k_sem_take(&fw_upload.rx.sem, + K_MSEC(CONFIG_BT_H4_NXP_CTLR_WAIT_HDR_SIG_TIMEOUT)); + if (err < 0) { + LOG_ERR("Fail to read data"); + return err; + } + *buffer = fw_upload.rx.buffer[fw_upload.rx.tail]; + buffer++; + fw_upload.rx.tail++; + fw_upload.rx.tail = fw_upload.rx.tail % sizeof(fw_upload.rx.buffer); + len--; + } + return 0; +} + +static void fw_upload_read_to_clear(void) +{ + uint32_t key; + + key = irq_lock(); + k_sem_reset(&fw_upload.rx.sem); + fw_upload.rx.head = 0; + fw_upload.rx.tail = 0; + irq_unlock(key); +} + +static int fw_upload_wait_for_hdr_sig(void) +{ + int err; + int64_t end; + char c; + + end = k_uptime_get() + CONFIG_BT_H4_NXP_CTLR_WAIT_HDR_SIG_TIMEOUT; + fw_upload.hdr_sig = 0xFF; + + while (k_uptime_get() < end) { + err = fw_upload_read_data(&c, 1); + if (err < 0) { + k_msleep(1); + continue; + } + if ((c == V1_HEADER_DATA_REQ) || (c == V1_START_INDICATION) || + (c == V3_START_INDICATION) || (c == V3_HEADER_DATA_REQ)) { + LOG_DBG("HDR SIG found 0x%02X", c); + fw_upload.hdr_sig = c; + if (fw_upload.version == 0) { + if ((c == V3_START_INDICATION) || (c == V3_HEADER_DATA_REQ)) { + fw_upload.version = VER3; + } else { + fw_upload.version = VER1; + } + } + return 0; + } + } + LOG_ERR("HDR SIG not found"); + return -EIO; +} + +static void fw_upload_write_data(const uint8_t *buffer, uint32_t len) +{ + for (int i = 0; i < len; i++) { + uart_poll_out(uart_dev, buffer[i]); + } +} + +static int fw_upload_request_check_crc(uint8_t *buffer, uint8_t request) +{ + uint8_t crc; + + if (request == V3_HEADER_DATA_REQ) { + crc = fw_upload_crc8(buffer, A6REQ_PAYLOAD_LEN + REQ_HEADER_LEN); + if (crc != buffer[A6REQ_PAYLOAD_LEN + REQ_HEADER_LEN]) { + LOG_ERR("Request %d, CRC check failed", request); + return -EINVAL; + } + } else if (request == V3_START_INDICATION) { + crc = fw_upload_crc8(buffer, AbREQ_PAYLOAD_LEN + REQ_HEADER_LEN); + if (crc != buffer[AbREQ_PAYLOAD_LEN + REQ_HEADER_LEN]) { + LOG_ERR("Request %d, CRC check failed", request); + return -EINVAL; + } + } else { + LOG_ERR("Invalid request %d", request); + } + + return 0; +} + +static void fw_upload_send_ack(uint8_t ack) +{ + if ((ack == V3_REQUEST_ACK) || (ack == V3_CRC_ERROR)) { + /* prepare crc for 0x7A or 0x7C */ + fw_upload.buffer[0] = ack; + fw_upload.buffer[1] = fw_upload_crc8(fw_upload.buffer, 1); + fw_upload_write_data(fw_upload.buffer, 2); + LOG_DBG("ACK = %x, CRC = %x", ack, fw_upload.buffer[1]); + } else if (ack == V3_TIMEOUT_ACK) { + /* prepare crc for 0x7B */ + fw_upload.buffer[0] = ack; + sys_put_le32(fw_upload.offset, &fw_upload.buffer[1]); + fw_upload.buffer[5] = fw_upload_crc8(fw_upload.buffer, 5); + fw_upload_write_data(fw_upload.buffer, 6); + LOG_DBG("ACK = %x, CRC = %x", ack, fw_upload.buffer[5]); + } else { + LOG_ERR("Invalid ack"); + } +} + +static int fw_upload_wait_req(bool secondary_speed) +{ + int err; + uint32_t len; + uint8_t buffer[10]; + + buffer[0] = fw_upload.hdr_sig; + if (fw_upload.hdr_sig == V3_HEADER_DATA_REQ) { + /* CMD LINE: 0xA7 */ + len = A6REQ_PAYLOAD_LEN + 1; + } else if (fw_upload.hdr_sig == V3_START_INDICATION) { + /* CMD LINE: 0xAB */ + len = AbREQ_PAYLOAD_LEN + 1; + } else { + return -EINVAL; + } + + err = fw_upload_read_data(&buffer[1], len); + if (err < 0) { + LOG_ERR("Fail to read req"); + return err; + } + + err = fw_upload_request_check_crc(buffer, fw_upload.hdr_sig); + if (err != 0) { + LOG_ERR("Fail to check CRC"); + fw_upload_send_ack(V3_CRC_ERROR); + return err; + } + + if (fw_upload.hdr_sig == V3_HEADER_DATA_REQ) { + fw_upload.length = sys_get_le16(&buffer[1]); + fw_upload.offset = sys_get_le32(&buffer[3]); + fw_upload.error = sys_get_le16(&buffer[7]); + fw_upload.crc8 = buffer[9]; + LOG_DBG("Req: %hhd, %hd, %d, %hd, %hhd", fw_upload.hdr_sig, fw_upload.length, + fw_upload.offset, fw_upload.error, fw_upload.crc8); + } else if (fw_upload.hdr_sig == V3_START_INDICATION) { + uint16_t chip_id; + + fw_upload_send_ack(V3_REQUEST_ACK); + chip_id = sys_get_le16(&buffer[1]); + LOG_DBG("Indicate: %hhd, %hd, %hhd, %hhd", fw_upload.hdr_sig, chip_id, buffer[3], + buffer[4]); + + if (!secondary_speed) { + return -EINVAL; + } + } + + return 0; +} + +static int fw_upload_change_timeout(void) +{ + int err = 0; + bool first = true; + uint8_t retry = FW_UPLOAD_CHANGE_TIMEOUT_RETRY_COUNT; + + LOG_DBG(""); + + fw_upload_gen_crc32_table(); + + while (true) { + err = fw_upload_wait_for_hdr_sig(); + if (err) { + continue; + } + + if (fw_upload.version == VER1) { + return 0; + } else if (fw_upload.version == VER3) { + err = fw_upload_wait_req(true); + if (err) { + continue; + } + + if (fw_upload.length == 0) { + continue; + } + + if (fw_upload.error == 0) { + if (first || (fw_upload.last_offset == fw_upload.offset)) { + fw_upload_send_ack(V3_REQUEST_ACK); + fw_upload_write_data(cmd7_hdrData, + fw_upload.length > CMD_HDR_LEN + ? CMD_HDR_LEN + : fw_upload.length); + fw_upload.last_offset = fw_upload.offset; + first = false; + } else { + fw_upload.cmd7_change_timeout_len = CMD_HDR_LEN; + fw_upload.wait_hdr_sig = false; + return 0; + } + } else { + if (retry > 0) { + retry--; + fw_upload_send_ack(V3_TIMEOUT_ACK); + } else { + LOG_ERR("Fail to change timeout with response err %d", + fw_upload.error); + return -ENOTSUP; + } + } + } else { + LOG_ERR("Unsupported version %d", fw_upload.version); + return -ENOTSUP; + } + } + + return -EINVAL; +} + +typedef struct { + uint32_t uartBaudRate; + uint32_t uartDivisio; + uint32_t uartClkDivisor; +} uart_baudrate_clkDiv_map_t; + +static const uart_baudrate_clkDiv_map_t clk_div_map[] = { + {115200U, 16U, 0x0075F6FDU}, + {1000000U, 2U, 0x00800000U}, + {3000000U, 1U, 0x00C00000U}, +}; + +static int fw_upload_change_speed_config(struct change_speed_config *config, uint32_t speed) +{ + config->clk_div_addr = 0x7f00008fU; + config->uart_clk_div_addr = 0x7f000090U; + config->mcr_addr = 0x7f000091U; + config->reinit_addr = 0x7f000092U; + config->icr_addr = 0x7f000093U; + config->fcr_addr = 0x7f000094U; + + config->mcr_val = 0x00000022U; + config->reinit_val = 0x00000001U; + config->icr_val = 0x000000c7U; + config->fcr_val = 0x000000c7U; + + for (int i = 0; i < ARRAY_SIZE(clk_div_map); i++) { + if (speed == clk_div_map[i].uartBaudRate) { + config->clk_div_val = clk_div_map[i].uartClkDivisor; + config->uart_clk_div_val = clk_div_map[i].uartDivisio; + return 0; + } + } + return -ENOTSUP; +} + +static uint16_t fw_upload_wait_length(uint8_t flag) +{ + uint8_t buffer[4]; + uint16_t len; + uint16_t len_comp; + int err; + uint8_t ack; + + err = fw_upload_read_data(buffer, sizeof(buffer)); + if (err < 0) { + return 0; + } + + len = sys_get_le16(buffer); + len_comp = sys_get_le16(buffer); + + if ((len ^ len_comp) == 0xFFFF) { + LOG_DBG("remote asks for %d bytes", len); + + /* Successful. Send back the ack. */ + if ((fw_upload.hdr_sig == V1_HEADER_DATA_REQ) || + (fw_upload.hdr_sig == V1_START_INDICATION)) { + ack = V1_REQUEST_ACK; + fw_upload_write_data(&ack, 1); + if (fw_upload.hdr_sig == V1_START_INDICATION) { + /* Eliminated longjmp(resync, 1); returning restart status */ + return (uint16_t)V1_START_INDICATION; + } + } + } else { + LOG_ERR("remote asks len %d bytes", len); + LOG_ERR("remote asks len_comp %d bytes", len_comp); + /* Failure due to mismatch. */ + ack = 0xbf; + fw_upload_write_data(&ack, 1); + /* Start all over again. */ + if (flag) { + /* Eliminated longjmp(resync, 1); returning restart status */ + return (uint16_t)V1_START_INDICATION; + } + len = 0; + } + return len; +} + +static uint32_t fw_upload_get_payload_length(uint8_t *cmd) +{ + uint32_t len; + + len = sys_get_le32(&cmd[8]); + + return len; +} + +static void fw_upload_get_hdr_start(uint8_t *buffer) +{ + int err; + bool done = false; + uint32_t count = 0; + + while (!done) { + err = fw_upload_read_data(&fw_upload.hdr_sig, 1); + if (err >= 0) { + if (fw_upload.hdr_sig == V1_HEADER_DATA_REQ) { + buffer[count++] = fw_upload.hdr_sig; + done = true; + LOG_DBG("Found header %x", fw_upload.hdr_sig); + } + } else { + LOG_ERR("Fail to read HDR sig %d", err); + return; + } + } + err = fw_upload_read_data(&buffer[count], 4); + if (err < 0) { + LOG_ERR("Fail to read HDR payload %d", err); + } +} + +static int fw_upload_len_valid(uint8_t *buffer, uint16_t *length) +{ + uint16_t len; + uint16_t len_comp; + + len = sys_get_le16(&buffer[1]); + len_comp = sys_get_le16(&buffer[3]); + + if ((len ^ len_comp) == 0xFFFFU) { + *length = len; + return 0; + } else { + return -EINVAL; + } +} + +static int fw_upload_get_last_5bytes(uint8_t *buffer) +{ + int err; + uint32_t payload_len; + uint16_t len = 0; + + memset(fw_upload.last_5bytes_buffer, 0, sizeof(fw_upload.last_5bytes_buffer)); + + fw_upload_get_hdr_start(fw_upload.last_5bytes_buffer); + err = fw_upload_len_valid(fw_upload.last_5bytes_buffer, &len); + if (err >= 0) { + LOG_DBG("Valid len %d", len); + } else { + LOG_ERR("Invalid HDR"); + return err; + } + + payload_len = fw_upload_get_payload_length(buffer); + + if ((len == CMD_HDR_LEN) || ((uint32_t)len == payload_len)) { + LOG_DBG("Len valid"); + fw_upload.is_error_case = false; + return 0; + } + + LOG_DBG("Len invalid"); + fw_upload.is_error_case = true; + + return -EINVAL; +} + +static void fw_upload_update_result(uint32_t payload_len, uint16_t *sending_len, + bool *first_chunk_sent) +{ + if (fw_upload.is_cmd7_req || fw_upload.is_entry_point_req) { + *sending_len = CMD_HDR_LEN; + *first_chunk_sent = true; + } else { + *sending_len = payload_len; + *first_chunk_sent = false; + if (*sending_len == CMD_HDR_LEN) { + fw_upload.is_hdr_data = true; + } + } +} + +static int fw_upload_write_hdr_and_payload(uint16_t len_to_send, uint8_t *buffer, bool new_speed) +{ + int err; + uint32_t payload_len; + bool send_done = false; + uint16_t sending_len = CMD_HDR_LEN; + bool first_chunk_sent = false; + + LOG_DBG(""); + + payload_len = fw_upload_get_payload_length(buffer); + + while (!send_done) { + if (sending_len == len_to_send) { + if ((sending_len == CMD_HDR_LEN) && (!fw_upload.is_hdr_data)) { + if ((first_chunk_sent == false) || + (first_chunk_sent && fw_upload.is_error_case)) { + LOG_DBG("Send first chunk: len %d", sending_len); + fw_upload_write_data(buffer, sending_len); + fw_upload_update_result(payload_len, &sending_len, + &first_chunk_sent); + } else { + send_done = true; + break; + } + } else { + LOG_DBG("Send data: len %d", sending_len); + if (sending_len) { + fw_upload_write_data(&buffer[CMD_HDR_LEN], sending_len); + first_chunk_sent = true; + sending_len = CMD_HDR_LEN; + fw_upload.is_hdr_data = false; + if (new_speed) { + return 0; + } + } else { + LOG_DBG("Download Complete"); + return 0; + } + } + } else { + if ((len_to_send & 0x01) == 0x01) { + if (len_to_send == (CMD_HDR_LEN + 1)) { + LOG_DBG("Resending first chunk..."); + fw_upload_write_data(buffer, len_to_send - 1); + sending_len = payload_len; + first_chunk_sent = false; + } else if (len_to_send == (payload_len + 1)) { + LOG_DBG("Resending second chunk..."); + fw_upload_write_data(&buffer[CMD_HDR_LEN], len_to_send - 1); + sending_len = CMD_HDR_LEN; + first_chunk_sent = true; + } + } else if (len_to_send == CMD_HDR_LEN) { + LOG_DBG("Resending send buffer..."); + fw_upload_write_data(buffer, len_to_send); + sending_len = payload_len; + first_chunk_sent = false; + } else if (len_to_send == payload_len) { + LOG_DBG("Resending second chunk..."); + fw_upload_write_data(&buffer[CMD_HDR_LEN], len_to_send); + sending_len = CMD_HDR_LEN; + first_chunk_sent = true; + } + } + + err = fw_upload_get_last_5bytes(buffer); + if (err < 0) { + LOG_ERR("Fail to get response"); + return err; + } + + if (fw_upload_len_valid(fw_upload.last_5bytes_buffer, &len_to_send) == 0) { + fw_upload_send_ack(V1_REQUEST_ACK); + LOG_DBG("BOOT_HEADER_ACK 0x5a sent"); + } + } + return len_to_send; +} + +static int fw_upload_uart_reconfig(uint32_t speed, bool flow_control) +{ + struct uart_config config; + int err; + + config.baudrate = speed; + config.data_bits = UART_CFG_DATA_BITS_8; + config.flow_ctrl = flow_control ? UART_CFG_FLOW_CTRL_RTS_CTS : UART_CFG_FLOW_CTRL_NONE; + config.parity = UART_CFG_PARITY_NONE; + config.stop_bits = UART_CFG_STOP_BITS_1; + + uart_irq_rx_disable(uart_dev); + uart_irq_tx_disable(uart_dev); + fw_upload_read_to_clear(); + err = uart_configure(uart_dev, &config); + uart_irq_rx_enable(uart_dev); + + return err; +} + +static int fw_upload_change_speed(uint8_t hdr) +{ + int err; + uint32_t hdr_len; + bool load_payload = false; + bool recovery = false; + uint16_t len_to_send; + uint32_t crc; + + err = fw_upload_change_speed_config( + (struct change_speed_config *)fw_upload.change_speed_buffer, + uart_dev_data.secondary_speed); + if (err) { + return err; + } + + hdr_len = sizeof(fw_upload.change_speed_buffer); + + fw_upload_gen_crc32_table(); + crc = sys_cpu_to_le32(hdr_len); + memcpy(cmd5_hdrData + 8, &crc, 4); + crc = fw_upload_update_crc32(0, (char *)cmd5_hdrData, 12); + crc = sys_cpu_to_be32(crc); + memcpy(cmd5_hdrData + 12, &crc, CRC32_LEN); + crc = fw_upload_update_crc32(0, (char *)fw_upload.change_speed_buffer, + (int)sizeof(struct change_speed_config)); + crc = sys_cpu_to_be32(crc); + memcpy(&fw_upload.change_speed_buffer[sizeof(struct change_speed_config)], &crc, CRC32_LEN); + + while (true) { + err = fw_upload_wait_for_hdr_sig(); + + if (hdr && (err == 0)) { + if (load_payload) { + if (fw_upload.version == VER3) { + fw_upload.change_speed_buffer_len = + CMD_HDR_LEN + fw_upload.length; + } + return 0; + } + } else { + if (recovery) { + return -ETIME; + } + + if (load_payload) { + LOG_ERR("HDR cannot be received by using second speed. receovery " + "speed"); + + err = fw_upload_uart_reconfig(uart_dev_data.primary_speed, + uart_dev_data.primary_flowcontrol); + if (err) { + return err; + } + + load_payload = false; + recovery = true; + continue; + } + } + + if (fw_upload.version == VER1) { + len_to_send = fw_upload_wait_length(0); + if (len_to_send == V1_START_INDICATION) { + return -EINVAL; + } else if (len_to_send == 0) { + continue; + } else if (len_to_send == CMD_HDR_LEN) { + memcpy(fw_upload.send_buffer, cmd5_hdrData, CMD_HDR_LEN); + memcpy(&fw_upload.send_buffer[CMD_HDR_LEN], + fw_upload.change_speed_buffer, hdr_len); + + err = fw_upload_write_hdr_and_payload(len_to_send, + fw_upload.send_buffer, true); + if (err < 0) { + return err; + } + + LOG_DBG("Change speed to %d", uart_dev_data.secondary_speed); + + err = fw_upload_uart_reconfig(uart_dev_data.secondary_speed, + uart_dev_data.secondary_flowcontrol); + if (err) { + return err; + } + load_payload = true; + } else { + fw_upload_write_data(fw_upload.change_speed_buffer, hdr_len); + + LOG_DBG("Change speed to %d", uart_dev_data.secondary_speed); + + err = fw_upload_uart_reconfig(uart_dev_data.secondary_speed, + uart_dev_data.secondary_flowcontrol); + if (err) { + return err; + } + load_payload = true; + } + } else if (fw_upload.version == VER3) { + err = fw_upload_wait_req(true); + if (!(!hdr || (err == 0))) { + continue; + } + if (fw_upload.length && (fw_upload.hdr_sig == V3_HEADER_DATA_REQ)) { + if (fw_upload.error != 0) { + fw_upload_send_ack(V3_TIMEOUT_ACK); + continue; + } + + fw_upload_send_ack(V3_REQUEST_ACK); + hdr = true; + + if (fw_upload.length == CMD_HDR_LEN) { + LOG_DBG("Send CMD5"); + fw_upload_write_data(cmd5_hdrData, fw_upload.length); + fw_upload.last_offset = fw_upload.offset; + } else { + LOG_DBG("Send UA RT config"); + fw_upload_write_data(fw_upload.change_speed_buffer, + fw_upload.length); + + LOG_DBG("Change speed to %d", + uart_dev_data.secondary_speed); + + err = fw_upload_uart_reconfig( + uart_dev_data.secondary_speed, + uart_dev_data.secondary_flowcontrol); + if (err) { + return err; + } + load_payload = true; + } + } + } + } + + return 0; +} + +static int fw_upload_v1_send_data(uint16_t len) +{ + uint32_t cmd; + uint32_t data_len; + int ret_len; + + memset(fw_upload.send_buffer, 0, sizeof(fw_upload.send_buffer)); + + fw_upload.is_cmd7_req = false; + fw_upload.is_entry_point_req = false; + + if ((fw_upload.fw_length - fw_upload.current_length) < len) { + len = fw_upload.fw_length - fw_upload.current_length; + } + + memcpy(fw_upload.send_buffer, fw_upload.fw + fw_upload.current_length, len); + fw_upload.current_length += len; + cmd = sys_get_le32(fw_upload.send_buffer); + if (cmd == CMD7) { + fw_upload.is_cmd7_req = true; + data_len = 0; + } else { + data_len = fw_upload_get_payload_length(fw_upload.send_buffer); + if ((data_len > (sizeof(fw_upload.send_buffer) - len)) || + ((data_len + fw_upload.current_length) > fw_upload.fw_length)) { + LOG_ERR("Invalid FW at %d/%d", fw_upload.current_length, + fw_upload.fw_length); + return -EINVAL; + } + memcpy(&fw_upload.send_buffer[len], fw_upload.fw + fw_upload.current_length, + data_len); + fw_upload.current_length += data_len; + if ((fw_upload.current_length < fw_upload.fw_length) && + ((cmd == CMD6) || (cmd == CMD4))) { + fw_upload.is_entry_point_req = true; + } + } + + ret_len = fw_upload_write_hdr_and_payload(len, fw_upload.send_buffer, false); + LOG_DBG("FW upload %d/%d", fw_upload.current_length, fw_upload.fw_length); + + return ret_len; +} + +static int fw_upload_v3_send_data(void) +{ + uint32_t start; + + LOG_DBG("Sending offset %d", fw_upload.offset); + if (fw_upload.offset == fw_upload.last_offset) { + LOG_WRN("Resending offset %d ...", fw_upload.offset); + fw_upload_write_data(fw_upload.send_buffer, fw_upload.length); + return fw_upload.length; + } + memset(fw_upload.send_buffer, 0, sizeof(fw_upload.send_buffer)); + start = fw_upload.offset - fw_upload.cmd7_change_timeout_len - + fw_upload.change_speed_buffer_len; + if (start >= fw_upload.fw_length) { + LOG_ERR("Invalid fw offset"); + return -EINVAL; + } + + if ((fw_upload.length + start) > fw_upload.fw_length) { + fw_upload.length = fw_upload.fw_length - start; + } + memcpy(fw_upload.send_buffer, fw_upload.fw + start, fw_upload.length); + fw_upload.current_length = start + fw_upload.length; + + fw_upload_write_data(fw_upload.send_buffer, fw_upload.length); + fw_upload.last_offset = fw_upload.offset; + + return fw_upload.length; +} + +static int fw_uploading(const uint8_t *fw, uint32_t fw_length) +{ + int err; + bool secondary_speed = false; + uint16_t len_to_send; + + fw_upload.wait_hdr_sig = true; + fw_upload.is_hdr_data = false; + fw_upload.is_error_case = false; + fw_upload.is_cmd7_req = false; + fw_upload.is_entry_point_req = false; + fw_upload.last_offset = 0xFFFFU; + + err = fw_upload_change_timeout(); + LOG_DBG("Change timeout hdr flag %d (err %d)", fw_upload.wait_hdr_sig, err); + if (err) { + return err; + } + + fw_upload_read_to_clear(); + + if (uart_dev_data.secondary_speed && + (uart_dev_data.secondary_speed != uart_dev_data.primary_speed)) { + LOG_DBG("Change speed to %d", uart_dev_data.secondary_speed); + err = fw_upload_change_speed(fw_upload.wait_hdr_sig); + if (err != 0) { + LOG_ERR("Fail to change speed"); + return err; + } + secondary_speed = true; + } + + fw_upload.fw_length = fw_length; + fw_upload.current_length = 0; + fw_upload.fw = fw; + + while (true) { + err = fw_upload_wait_for_hdr_sig(); + if (secondary_speed && (err != 0)) { + return -ETIME; + } + + secondary_speed = false; + + if (fw_upload.version == VER1) { + len_to_send = fw_upload_wait_length(true); + + if (len_to_send == V1_START_INDICATION) { + continue; + } + while (len_to_send > 0) { + len_to_send = fw_upload_v1_send_data(len_to_send); + } + if (fw_upload.current_length >= fw_upload.fw_length) { + LOG_DBG("FW download done"); + return 0; + } + LOG_ERR("FW download failed"); + return len_to_send; + } else if (fw_upload.version == VER3) { + if (fw_upload.hdr_sig == V3_START_INDICATION) { + fw_upload_wait_req(false); + continue; + } + err = fw_upload_wait_req(false); + if (err) { + LOG_ERR("Fail to wait req"); + return err; + } + if (fw_upload.length) { + if (fw_upload.error == 0) { + fw_upload_send_ack(V3_REQUEST_ACK); + err = fw_upload_v3_send_data(); + if (err < 0) { + LOG_ERR("FW download failed"); + return err; + } + } else { + LOG_ERR("Error occurs %d", fw_upload.error); + fw_upload_send_ack(V3_TIMEOUT_ACK); + if (fw_upload.error & BT_MIC_FAIL_BIT) { + fw_upload.change_speed_buffer_len = 0; + fw_upload.current_length = 0; + fw_upload.last_offset = 0; + } + } + } else { + if (fw_upload.error == 0) { + fw_upload_send_ack(V3_REQUEST_ACK); + LOG_DBG("FW download done"); + return 0; + } + LOG_ERR("Error occurs %d", fw_upload.error); + fw_upload_send_ack(V3_TIMEOUT_ACK); + if (fw_upload.error & BT_MIC_FAIL_BIT) { + fw_upload.change_speed_buffer_len = 0; + fw_upload.current_length = 0; + fw_upload.last_offset = 0; + } + } + } else { + return -ENOTSUP; + } + } + return -EINVAL; +} + +static void bt_nxp_ctlr_uart_isr(const struct device *unused, void *user_data) +{ + int err = 0; + int count = 0; + + ARG_UNUSED(unused); + ARG_UNUSED(user_data); + + while (uart_irq_update(uart_dev) && uart_irq_is_pending(uart_dev)) { + err = uart_poll_in(uart_dev, &fw_upload.rx.buffer[fw_upload.rx.head]); + if (err >= 0) { + fw_upload.rx.head++; + fw_upload.rx.head = fw_upload.rx.head % sizeof(fw_upload.rx.buffer); + count++; + } + } + + while (count > 0) { + k_sem_give(&fw_upload.rx.sem); + count--; + } +} + +static int bt_nxp_ctlr_init(void) +{ + int err; + uint32_t speed; + bool flowcontrol_of_hci; + + if (!device_is_ready(uart_dev)) { + return -ENODEV; + } + + speed = DT_PROP(DT_INST_GPARENT(0), current_speed); + speed = DT_PROP_OR(DT_DRV_INST(0), hci_operation_speed, speed); + uart_dev_data.primary_speed = DT_PROP_OR(DT_DRV_INST(0), fw_download_primary_speed, speed); + uart_dev_data.secondary_speed = + DT_PROP_OR(DT_DRV_INST(0), fw_download_secondary_speed, speed); + + flowcontrol_of_hci = (bool)DT_PROP_OR(DT_DRV_INST(0), hw_flow_control, false); + uart_dev_data.primary_flowcontrol = + (bool)DT_PROP_OR(DT_DRV_INST(0), fw_download_primary_flowcontrol, false); + uart_dev_data.secondary_flowcontrol = + (bool)DT_PROP_OR(DT_DRV_INST(0), fw_download_secondary_flowcontrol, false); + +#if DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) || \ + DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) +#if DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) + /* Check BT REG_ON gpio instance */ + if (!gpio_is_ready_dt(&sdio_reset)) { + LOG_ERR("Error: failed to configure sdio_reset %s pin %d", sdio_reset.port->name, + sdio_reset.pin); + return -EIO; + } + + /* Configure sdio_reset as output */ + err = gpio_pin_configure_dt(&sdio_reset, GPIO_OUTPUT); + if (err) { + LOG_ERR("Error %d: failed to configure sdio_reset %s pin %d", err, + sdio_reset.port->name, sdio_reset.pin); + return err; + } + err = gpio_pin_set_dt(&sdio_reset, 0); + if (err) { + return err; + } +#endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) */ + +#if DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) + /* Check BT REG_ON gpio instance */ + if (!gpio_is_ready_dt(&w_disable)) { + LOG_ERR("Error: failed to configure w_disable %s pin %d", w_disable.port->name, + w_disable.pin); + return -EIO; + } + + /* Configure w_disable as output */ + err = gpio_pin_configure_dt(&w_disable, GPIO_OUTPUT); + if (err) { + LOG_ERR("Error %d: failed to configure w_disable %s pin %d", err, + w_disable.port->name, w_disable.pin); + return err; + } + err = gpio_pin_set_dt(&w_disable, 0); + if (err) { + return err; + } +#endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) */ + + /* wait for reset done */ + k_sleep(K_MSEC(100)); + +#if DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) + err = gpio_pin_set_dt(&sdio_reset, 1); + if (err) { + return err; + } +#endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), sdio_reset_gpios) */ + +#if DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) + err = gpio_pin_set_dt(&w_disable, 1); + if (err) { + return err; + } +#endif /* DT_NODE_HAS_PROP(DT_DRV_INST(0), w_disable_gpios) */ +#endif + + uart_irq_rx_disable(uart_dev); + uart_irq_tx_disable(uart_dev); + + fw_upload.rx.head = 0; + fw_upload.rx.tail = 0; + + k_sem_init(&fw_upload.rx.sem, 0, sizeof(fw_upload.rx.buffer)); + + uart_irq_callback_set(uart_dev, bt_nxp_ctlr_uart_isr); + + made_table = false; + + err = fw_upload_uart_reconfig(uart_dev_data.primary_speed, + uart_dev_data.primary_flowcontrol); + if (err) { + LOG_ERR("Fail to config uart"); + return err; + } + + uart_irq_rx_enable(uart_dev); + + err = fw_uploading(bt_fw_bin, bt_fw_bin_len); + + if (err) { + LOG_ERR("Fail to upload firmware"); + return err; + } + + (void)fw_upload_uart_reconfig(speed, flowcontrol_of_hci); + + uart_irq_rx_disable(uart_dev); + uart_irq_tx_disable(uart_dev); + + k_sleep(K_MSEC(CONFIG_BT_H4_NXP_CTLR_WAIT_TIME_AFTER_UPLOAD)); + + return 0; +} + +int bt_hci_transport_setup(const struct device *dev) +{ + if (dev != uart_dev) { + return -EINVAL; + } + + return bt_nxp_ctlr_init(); +} diff --git a/drivers/bluetooth/hci/hci_psoc6_bless.c b/drivers/bluetooth/hci/hci_psoc6_bless.c deleted file mode 100644 index af6804f2f1759..0000000000000 --- a/drivers/bluetooth/hci/hci_psoc6_bless.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or - * an affiliate of Cypress Semiconductor Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @brief PSoC 6 BLE (BLESS) driver. - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL -#include -LOG_MODULE_REGISTER(psoc6_bless); - -#include "cy_ble_stack_pvt.h" -#include "cycfg_ble.h" - -#define DT_DRV_COMPAT infineon_cat1_bless_hci - -#define BLE_LOCK_TMOUT_MS (1000) -#define BLE_THREAD_SEM_TMOUT_MS (1000) - -#define CYBLE_STACK_SIZE (CY_BLE_STACK_RAM_SIZE + 4096) - -#define PSOC6_BLESS_OP_SET_PUBLIC_ADDR BT_OP(BT_OGF_VS, 0x1a0) - -static K_SEM_DEFINE(psoc6_bless_rx_sem, 0, 1); -static K_SEM_DEFINE(psoc6_bless_operation_sem, 1, 1); -static K_KERNEL_STACK_DEFINE(psoc6_bless_rx_thread_stack, CONFIG_BT_RX_STACK_SIZE); -static struct k_thread psoc6_bless_rx_thread_data; -static cy_stc_ble_hci_tx_packet_info_t hci_tx_pkt; - -extern void Cy_BLE_EnableLowPowerMode(void); - -CY_ALIGN(sizeof(uint32_t)) CY_NOINIT uint8_t psoc6_bless_stack_memory[CYBLE_STACK_SIZE]; - -/** BLE Stack parameters */ -static cy_stc_ble_stack_params_t psoc6_bless_stack_param = { - .memoryHeapPtr = psoc6_bless_stack_memory, - .totalHeapSz = CYBLE_STACK_SIZE, - .dleMaxTxCapability = CONFIG_BT_PSOC6_BLESS_MAX_TX_PAYLOAD, - .dleMaxRxCapability = CONFIG_BT_PSOC6_BLESS_MAX_RX_PAYLOAD, - .featureMask = (CY_BLE_DLE_FEATURE | CY_BLE_LL_PRIVACY_FEATURE | - CY_BLE_SECURE_CONN_FEATURE | CY_BLE_PHY_UPDATE_FEATURE | - CY_BLE_STORE_BONDLIST_FEATURE | CY_BLE_STORE_RESOLVING_LIST_FEATURE | - CY_BLE_STORE_WHITELIST_FEATURE | CY_BLE_TX_POWER_CALIBRATION_FEATURE), - .maxConnCount = CY_BLE_CONN_COUNT, - .tx5dbmModeEn = CY_BLE_ENABLE_TX_5DBM, -}; - -static const cy_stc_sysint_t psoc6_bless_isr_cfg = { - .intrSrc = DT_INST_IRQN(0), - .intrPriority = DT_INST_IRQ(0, priority), -}; - -static cy_stc_ble_hw_config_t psoc6_bless_hw_config = { - .blessIsrConfig = &psoc6_bless_isr_cfg, -}; - -static const cy_stc_ble_config_t psoc6_bless_config = { - .stackParam = &psoc6_bless_stack_param, - .hw = &psoc6_bless_hw_config, -}; - -static void psoc6_bless_rx_thread(void *, void *, void *) -{ - while (true) { - k_sem_take(&psoc6_bless_rx_sem, K_MSEC(BLE_THREAD_SEM_TMOUT_MS)); - Cy_BLE_ProcessEvents(); - } -} - -static void psoc6_bless_isr_handler(const struct device *dev) -{ - if (Cy_BLE_HAL_BlessInterruptHandler()) { - k_sem_give(&psoc6_bless_rx_sem); - } -} - -static void psoc6_bless_events_handler(uint32_t eventCode, void *eventParam) -{ - cy_stc_ble_hci_tx_packet_info_t *hci_rx = NULL; - struct net_buf *buf = NULL; - size_t buf_tailroom = 0; - - if (eventCode != CY_BLE_EVT_HCI_PKT_RCVD) { - LOG_DBG("Other EVENT 0x%X", eventCode); - return; - } - - hci_rx = eventParam; - - switch (hci_rx->packetType) { - case BT_HCI_H4_EVT: - buf = bt_buf_get_evt(hci_rx->data[0], 0, K_NO_WAIT); - if (!buf) { - LOG_ERR("Failed to allocate the buffer for RX: EVENT "); - return; - } - - break; - case BT_HCI_H4_ACL: - buf = bt_buf_get_rx(BT_BUF_ACL_IN, K_NO_WAIT); - if (!buf) { - LOG_ERR("Failed to allocate the buffer for RX: ACL "); - return; - } - bt_buf_set_type(buf, BT_BUF_ACL_IN); - - break; - - default: - LOG_WRN("Unsupported HCI Packet Received"); - return; - } - - buf_tailroom = net_buf_tailroom(buf); - if (buf_tailroom < hci_rx->dataLength) { - LOG_WRN("Not enough space for rx data"); - return; - } - net_buf_add_mem(buf, hci_rx->data, hci_rx->dataLength); - bt_recv(buf); -} - -static int psoc6_bless_open(void) -{ - k_tid_t tid; - - tid = k_thread_create(&psoc6_bless_rx_thread_data, psoc6_bless_rx_thread_stack, - K_KERNEL_STACK_SIZEOF(psoc6_bless_rx_thread_stack), - psoc6_bless_rx_thread, NULL, NULL, NULL, - K_PRIO_COOP(CONFIG_BT_RX_PRIO), 0, K_NO_WAIT); - k_thread_name_set(tid, "psoc6_bless_rx_thread"); - - return 0; -} - -static int psoc6_bless_send(struct net_buf *buf) -{ - cy_en_ble_api_result_t result; - - memset(&hci_tx_pkt, 0, sizeof(cy_stc_ble_hci_tx_packet_info_t)); - - hci_tx_pkt.dataLength = buf->len; - hci_tx_pkt.data = buf->data; - - switch (bt_buf_get_type(buf)) { - case BT_BUF_ACL_OUT: - hci_tx_pkt.packetType = BT_HCI_H4_ACL; - break; - case BT_BUF_CMD: - hci_tx_pkt.packetType = BT_HCI_H4_CMD; - break; - default: - net_buf_unref(buf); - return -ENOTSUP; - } - - if (k_sem_take(&psoc6_bless_operation_sem, K_MSEC(BLE_LOCK_TMOUT_MS)) != 0) { - LOG_ERR("Failed to acquire BLE DRV Semaphore"); - net_buf_unref(buf); - return -EIO; - } - - result = Cy_BLE_SoftHciSendAppPkt(&hci_tx_pkt); - if (result != CY_BLE_SUCCESS) { - LOG_ERR("Error in sending packet reason %d\r\n", result); - } - - k_sem_give(&psoc6_bless_operation_sem); - - net_buf_unref(buf); - - return 0; -} - -static int psoc6_bless_setup(const struct bt_hci_setup_params *params) -{ - ARG_UNUSED(params); - struct net_buf *buf; - int err; - uint8_t *addr = (uint8_t *)&SFLASH_BLE_DEVICE_ADDRESS[0]; - uint8_t hci_data[] = { - addr[5], addr[4], addr[3], addr[2], addr[1], addr[0], BT_ADDR_LE_PUBLIC, - }; - - buf = bt_hci_cmd_create(PSOC6_BLESS_OP_SET_PUBLIC_ADDR, sizeof(hci_data)); - if (buf == NULL) { - LOG_ERR("Unable to allocate command buffer"); - return -ENOMEM; - } - - /* Add data part of packet */ - net_buf_add_mem(buf, hci_data, sizeof(hci_data)); - - err = bt_hci_cmd_send_sync(PSOC6_BLESS_OP_SET_PUBLIC_ADDR, buf, NULL); - if (err) { - return err; - } - - return 0; -} - -static int psoc6_bless_hci_init(void) -{ - cy_en_ble_api_result_t result; - static const struct bt_hci_driver drv = { - .name = "PSoC 6 BLESS", - .bus = BT_HCI_DRIVER_BUS_VIRTUAL, - .quirks = BT_QUIRK_NO_RESET, - .open = psoc6_bless_open, - .send = psoc6_bless_send, - .setup = psoc6_bless_setup, - }; - - /* Connect BLE interrupt to ISR */ - IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), psoc6_bless_isr_handler, 0, 0); - - /* Registers the generic callback functions. */ - Cy_BLE_RegisterEventCallback(psoc6_bless_events_handler); - - /* Initializes the PSoC 6 BLESS Controller. */ - result = Cy_BLE_InitController(&psoc6_bless_config); - if (result != CY_BLE_SUCCESS) { - LOG_ERR("Failed to init the BLE Controller"); - return -EIO; - } - - /* Enables the BLESS controller in HCI only mode. */ - result = Cy_BLE_EnableHCIModeController(); - if (result != CY_BLE_SUCCESS) { - LOG_ERR("Failed to enable the BLE Controller in hci mode"); - return -EIO; - } - - /* Enables BLE Low-power mode (LPM)*/ - Cy_BLE_EnableLowPowerMode(); - - /* Register a BLESS HCI driver to the Bluetooth stack. */ - bt_hci_driver_register(&drv); - - return 0; -} - -SYS_INIT(psoc6_bless_hci_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/drivers/bluetooth/hci/hci_spi_st.c b/drivers/bluetooth/hci/hci_spi_st.c index 8da9936888eef..fcfe2f4b75024 100644 --- a/drivers/bluetooth/hci/hci_spi_st.c +++ b/drivers/bluetooth/hci/hci_spi_st.c @@ -22,7 +22,7 @@ #include #include -#include +#include #include #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL @@ -38,7 +38,7 @@ LOG_MODULE_REGISTER(bt_driver); #define READY_NOW 0x02 #define EVT_BLUE_INITIALIZED 0x01 - +#define FW_STARTED_PROPERLY 0X01 /* Offsets */ #define STATUS_HEADER_READY 0 #define STATUS_HEADER_TOREAD 3 @@ -51,6 +51,7 @@ LOG_MODULE_REGISTER(bt_driver); #define EVT_LE_META_SUBEVENT 3 #define EVT_VENDOR_CODE_LSB 3 #define EVT_VENDOR_CODE_MSB 4 +#define REASON_CODE 5 #define CMD_OGF 1 #define CMD_OCF 2 @@ -89,7 +90,9 @@ static struct k_thread spi_rx_thread_data; #define BLUENRG_CONFIG_LL_ONLY_OFFSET 0x2C #define BLUENRG_CONFIG_LL_ONLY_LEN 0x01 -static int bt_spi_send_aci_config(uint8_t offset, const uint8_t *value, size_t value_len); +struct bt_spi_data { + bt_hci_recv_t recv; +}; static const struct spi_dt_spec bus = SPI_DT_SPEC_INST_GET( 0, SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8) | SPI_LOCK_ON, 0); @@ -110,6 +113,43 @@ struct bt_hci_ext_evt_hdr { uint16_t len; } __packed; +int bluenrg_bt_reset(bool updater_mode) +{ + int err = 0; + /* Assert reset */ + if (!updater_mode) { + gpio_pin_set_dt(&rst_gpio, 1); + k_sleep(K_MSEC(DT_INST_PROP_OR(0, reset_assert_duration_ms, 0))); + gpio_pin_set_dt(&rst_gpio, 0); + } else { +#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) + return -ENOTSUP; +#else /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) */ + gpio_pin_set_dt(&rst_gpio, 1); + gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_DISABLE); + /* Configure IRQ pin as output and force it high */ + err = gpio_pin_configure_dt(&irq_gpio, GPIO_OUTPUT_ACTIVE); + if (err) { + return err; + } + /* Add reset delay and release reset */ + k_sleep(K_MSEC(DT_INST_PROP_OR(0, reset_assert_duration_ms, 0))); + gpio_pin_set_dt(&rst_gpio, 0); + /* Give firmware some time to read the IRQ high */ + k_sleep(K_MSEC(5)); + gpio_pin_interrupt_configure_dt(&irq_gpio, GPIO_INT_EDGE_TO_ACTIVE); + /* Reconfigure IRQ pin as input */ + err = gpio_pin_configure_dt(&irq_gpio, GPIO_INPUT); + if (err) { + return err; + } + /* Emulate possibly missed rising edge IRQ by signaling the IRQ semaphore */ + k_sem_give(&sem_request); +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) */ + } + return err; +} + static inline int bt_spi_transceive(void *tx, uint32_t tx_len, void *rx, uint32_t rx_len) { @@ -142,13 +182,17 @@ static void bt_spi_isr(const struct device *unused1, static bool bt_spi_handle_vendor_evt(uint8_t *msg) { bool handled = false; + uint8_t reset_reason; switch (bt_spi_get_evt(msg)) { case EVT_BLUE_INITIALIZED: { - k_sem_give(&sem_initialised); + reset_reason = msg[REASON_CODE]; + if (reset_reason == FW_STARTED_PROPERLY) { + k_sem_give(&sem_initialised); #if defined(CONFIG_BT_BLUENRG_ACI) - handled = true; + handled = true; #endif + } } default: break; @@ -311,7 +355,8 @@ static int bt_spi_send_aci_config(uint8_t offset, const uint8_t *value, size_t v } #if !defined(CONFIG_BT_HCI_RAW) -static int bt_spi_bluenrg_setup(const struct bt_hci_setup_params *params) +static int bt_spi_bluenrg_setup(const struct device *dev, + const struct bt_hci_setup_params *params) { int ret; const bt_addr_t *addr = ¶ms->public_addr; @@ -435,12 +480,12 @@ static int bt_spi_rx_buf_construct(uint8_t *msg, struct net_buf **bufp, uint16_t len = sizeof(iso_hdr) + bt_iso_hdr_len(sys_le16_to_cpu(iso_hdr.len)); } else { LOG_ERR("No available ISO buffers!"); - return NULL; + return -ENOMEM; } if (len > net_buf_tailroom(buf)) { LOG_ERR("ISO too long: %d", len); net_buf_unref(buf); - return NULL; + return -ENOMEM; } net_buf_add_mem(buf, &msg[1], len); break; @@ -456,7 +501,9 @@ static int bt_spi_rx_buf_construct(uint8_t *msg, struct net_buf **bufp, uint16_t static void bt_spi_rx_thread(void *p1, void *p2, void *p3) { - ARG_UNUSED(p1); + const struct device *dev = p1; + struct bt_spi_data *hci = dev->data; + ARG_UNUSED(p2); ARG_UNUSED(p3); @@ -499,14 +546,14 @@ static void bt_spi_rx_thread(void *p1, void *p2, void *p3) ret = bt_spi_rx_buf_construct(rxmsg, &buf, size); if (!ret) { /* Handle the received HCI data */ - bt_recv(buf); + hci->recv(dev, buf); buf = NULL; } } while (READ_CONDITION); } } -static int bt_spi_send(struct net_buf *buf) +static int bt_spi_send(const struct device *dev, struct net_buf *buf) { uint16_t size; uint8_t rx_first[1]; @@ -592,8 +639,9 @@ static int bt_spi_send(struct net_buf *buf) return ret; } -static int bt_spi_open(void) +static int bt_spi_open(const struct device *dev, bt_hci_recv_t recv) { + struct bt_spi_data *hci = dev->data; int err; /* Configure RST pin and hold BLE in Reset */ @@ -620,6 +668,8 @@ static int bt_spi_open(void) return err; } + hci->recv = recv; + /* Take BLE out of reset */ k_sleep(K_MSEC(DT_INST_PROP_OR(0, reset_assert_duration_ms, 0))); gpio_pin_set_dt(&rst_gpio, 0); @@ -627,7 +677,7 @@ static int bt_spi_open(void) /* Start RX thread */ k_thread_create(&spi_rx_thread_data, spi_rx_stack, K_KERNEL_STACK_SIZEOF(spi_rx_stack), - bt_spi_rx_thread, NULL, NULL, NULL, + bt_spi_rx_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); @@ -643,10 +693,7 @@ static int bt_spi_open(void) return 0; } -static const struct bt_hci_driver drv = { - .name = DEVICE_DT_NAME(DT_DRV_INST(0)), - .bus = BT_HCI_DRIVER_BUS_SPI, - .quirks = BT_QUIRK_NO_RESET, +static const struct bt_hci_driver_api drv = { #if defined(CONFIG_BT_BLUENRG_ACI) && !defined(CONFIG_BT_HCI_RAW) .setup = bt_spi_bluenrg_setup, #endif /* CONFIG_BT_BLUENRG_ACI && !CONFIG_BT_HCI_RAW */ @@ -654,7 +701,7 @@ static const struct bt_hci_driver drv = { .send = bt_spi_send, }; -static int bt_spi_init(void) +static int bt_spi_init(const struct device *dev) { if (!spi_is_ready_dt(&bus)) { @@ -672,12 +719,16 @@ static int bt_spi_init(void) return -ENODEV; } - bt_hci_driver_register(&drv); - - LOG_DBG("BT SPI initialized"); return 0; } -SYS_INIT(bt_spi_init, POST_KERNEL, CONFIG_BT_SPI_INIT_PRIORITY); +#define HCI_DEVICE_INIT(inst) \ + static struct bt_spi_data hci_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, bt_spi_init, NULL, &hci_data_##inst, NULL, \ + POST_KERNEL, CONFIG_BT_SPI_INIT_PRIORITY, &drv) + +/* Only one instance supported right now */ +HCI_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/hci_stm32wba.c b/drivers/bluetooth/hci/hci_stm32wba.c index 67b87a5aa25dd..34e2385b2414d 100644 --- a/drivers/bluetooth/hci/hci_stm32wba.c +++ b/drivers/bluetooth/hci/hci_stm32wba.c @@ -7,11 +7,10 @@ * SPDX-License-Identifier: Apache-2.0 */ - #include #include #include -#include +#include #include #include #include @@ -27,6 +26,12 @@ #include LOG_MODULE_REGISTER(hci_wba); +#define DT_DRV_COMPAT st_hci_stm32wba + +struct hci_data { + bt_hci_recv_t recv; +}; + static K_SEM_DEFINE(hci_sem, 1, 1); #define BLE_CTRLR_STACK_BUFFER_SIZE 300 @@ -39,9 +44,16 @@ static K_SEM_DEFINE(hci_sem, 1, 1); #define BLE_DYN_ALLOC_SIZE \ (BLE_TOTAL_BUFFER_SIZE(CFG_BLE_NUM_LINK, MBLOCK_COUNT)) +/* GATT buffer size (in bytes)*/ +#define BLE_GATT_BUF_SIZE \ + BLE_TOTAL_BUFFER_SIZE_GATT(CFG_BLE_NUM_GATT_ATTRIBUTES, \ + CFG_BLE_NUM_GATT_SERVICES, \ + CFG_BLE_ATT_VALUE_ARRAY_SIZE) + #define DIVC(x, y) (((x)+(y)-1)/(y)) static uint32_t __noinit buffer[DIVC(BLE_DYN_ALLOC_SIZE, 4)]; +static uint32_t __noinit gatt_buffer[DIVC(BLE_GATT_BUF_SIZE, 4)]; extern uint8_t ll_state_busy; @@ -205,9 +217,10 @@ static struct net_buf *treat_iso(const uint8_t *data, size_t len, return buf; } -static int receive_data(const uint8_t *data, size_t len, +static int receive_data(const struct device *dev, const uint8_t *data, size_t len, const uint8_t *ext_data, size_t ext_len) { + struct hci_data *hci = dev->data; uint8_t pkt_indicator; struct net_buf *buf; int err = 0; @@ -235,7 +248,7 @@ static int receive_data(const uint8_t *data, size_t len, } if (buf) { - bt_recv(buf); + hci->recv(dev, buf); } else { err = -ENOMEM; ll_state_busy = 1; @@ -247,6 +260,7 @@ static int receive_data(const uint8_t *data, size_t len, uint8_t BLECB_Indication(const uint8_t *data, uint16_t length, const uint8_t *ext_data, uint16_t ext_length) { + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); int ret = 0; int err; @@ -257,7 +271,7 @@ uint8_t BLECB_Indication(const uint8_t *data, uint16_t length, k_sem_take(&hci_sem, K_FOREVER); - err = receive_data(data, (size_t)length - 1, + err = receive_data(dev, data, (size_t)length - 1, ext_data, (size_t)ext_length); k_sem_give(&hci_sem); @@ -271,12 +285,14 @@ uint8_t BLECB_Indication(const uint8_t *data, uint16_t length, return ret; } -static int bt_hci_stm32wba_send(struct net_buf *buf) +static int bt_hci_stm32wba_send(const struct device *dev, struct net_buf *buf) { uint16_t event_length; uint8_t pkt_indicator; uint8_t tx_buffer[BLE_CTRLR_STACK_BUFFER_SIZE]; + ARG_UNUSED(dev); + k_sem_take(&hci_sem, K_FOREVER); LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); @@ -304,7 +320,7 @@ static int bt_hci_stm32wba_send(struct net_buf *buf) LOG_DBG("event_length: %u", event_length); if (event_length) { - receive_data((uint8_t *)&tx_buffer, (size_t)event_length, NULL, 0); + receive_data(dev, (uint8_t *)&tx_buffer, (size_t)event_length, NULL, 0); } k_sem_give(&hci_sem); @@ -330,8 +346,8 @@ static int bt_ble_ctlr_init(void) init_params_p.mblockCount = CFG_BLE_MBLOCK_COUNT; init_params_p.bleStartRamAddress = (uint8_t *)buffer; init_params_p.total_buffer_size = BLE_DYN_ALLOC_SIZE; - init_params_p.bleStartRamAddress_GATT = NULL; - init_params_p.total_buffer_size_GATT = 0; + init_params_p.bleStartRamAddress_GATT = (uint8_t *)gatt_buffer; + init_params_p.total_buffer_size_GATT = BLE_GATT_BUF_SIZE; init_params_p.options = CFG_BLE_OPTIONS; init_params_p.debug = 0U; @@ -342,8 +358,9 @@ static int bt_ble_ctlr_init(void) return 0; } -static int bt_hci_stm32wba_open(void) +static int bt_hci_stm32wba_open(const struct device *dev, bt_hci_recv_t recv) { + struct hci_data *data = dev->data; int ret = 0; link_layer_register_isr(); @@ -351,6 +368,9 @@ static int bt_hci_stm32wba_open(void) ll_sys_config_params(); ret = bt_ble_ctlr_init(); + if (ret == 0) { + data->recv = recv; + } /* TODO. Enable Flash manager once available */ if (IS_ENABLED(CONFIG_FLASH)) { @@ -360,18 +380,16 @@ static int bt_hci_stm32wba_open(void) return ret; } -static const struct bt_hci_driver drv = { - .name = "BT IPM", - .bus = BT_HCI_DRIVER_BUS_IPM, +static const struct bt_hci_driver_api drv = { .open = bt_hci_stm32wba_open, .send = bt_hci_stm32wba_send, }; -static int bt_stm32wba_hci_init(void) -{ - bt_hci_driver_register(&drv); - - return 0; -} +#define HCI_DEVICE_INIT(inst) \ + static struct hci_data hci_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &hci_data_##inst, NULL, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) -SYS_INIT(bt_stm32wba_hci_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +/* Only one instance supported */ +HCI_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/ipc.c b/drivers/bluetooth/hci/ipc.c index 54a8556d1384a..9d63d12ec3286 100644 --- a/drivers/bluetooth/hci/ipc.c +++ b/drivers/bluetooth/hci/ipc.c @@ -9,7 +9,7 @@ #include #include -#include +#include #include #include @@ -18,10 +18,17 @@ #include LOG_MODULE_REGISTER(bt_hci_driver); +#define DT_DRV_COMPAT zephyr_bt_hci_ipc + #define IPC_BOUND_TIMEOUT_IN_MS K_MSEC(1000) -static struct ipc_ept hci_ept; -static K_SEM_DEFINE(ipc_bound_sem, 0, 1); +struct ipc_data { + bt_hci_recv_t recv; + struct ipc_ept hci_ept; + struct ipc_ept_cfg hci_ept_cfg; + struct k_sem bound_sem; + const struct device *ipc; +}; static bool is_hci_event_discardable(const uint8_t *evt_data) { @@ -200,8 +207,9 @@ static struct net_buf *bt_ipc_iso_recv(const uint8_t *data, size_t remaining) return buf; } -static void bt_ipc_rx(const uint8_t *data, size_t len) +static void bt_ipc_rx(const struct device *dev, const uint8_t *data, size_t len) { + struct ipc_data *ipc = dev->data; uint8_t pkt_indicator; struct net_buf *buf = NULL; size_t remaining = len; @@ -231,14 +239,15 @@ static void bt_ipc_rx(const uint8_t *data, size_t len) if (buf) { LOG_DBG("Calling bt_recv(%p)", buf); - bt_recv(buf); + ipc->recv(dev, buf); LOG_HEXDUMP_DBG(buf->data, buf->len, "RX buf payload:"); } } -static int bt_ipc_send(struct net_buf *buf) +static int bt_ipc_send(const struct device *dev, struct net_buf *buf) { + struct ipc_data *data = dev->data; int err; uint8_t pkt_indicator; @@ -261,7 +270,7 @@ static int bt_ipc_send(struct net_buf *buf) net_buf_push_u8(buf, pkt_indicator); LOG_HEXDUMP_DBG(buf->data, buf->len, "Final HCI buffer:"); - err = ipc_service_send(&hci_ept, buf->data, buf->len); + err = ipc_service_send(&data->hci_ept, buf->data, buf->len); if (err < 0) { LOG_ERR("Failed to send (err %d)", err); } @@ -273,21 +282,18 @@ static int bt_ipc_send(struct net_buf *buf) static void hci_ept_bound(void *priv) { - k_sem_give(&ipc_bound_sem); + const struct device *dev = priv; + struct ipc_data *ipc = dev->data; + + k_sem_give(&ipc->bound_sem); } static void hci_ept_recv(const void *data, size_t len, void *priv) { - bt_ipc_rx(data, len); -} + const struct device *dev = priv; -static struct ipc_ept_cfg hci_ept_cfg = { - .name = "nrf_bt_hci", - .cb = { - .bound = hci_ept_bound, - .received = hci_ept_recv, - }, -}; + bt_ipc_rx(dev, data, len); +} int __weak bt_hci_transport_setup(const struct device *dev) { @@ -301,13 +307,11 @@ int __weak bt_hci_transport_teardown(const struct device *dev) return 0; } -static int bt_ipc_open(void) +static int bt_ipc_open(const struct device *dev, bt_hci_recv_t recv) { + struct ipc_data *ipc = dev->data; int err; - const struct device *hci_ipc_instance = - DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_hci_ipc)); - err = bt_hci_transport_setup(NULL); if (err) { LOG_ERR("HCI transport setup failed with: %d\n", err); @@ -316,29 +320,32 @@ static int bt_ipc_open(void) LOG_DBG(""); - err = ipc_service_open_instance(hci_ipc_instance); + err = ipc_service_open_instance(ipc->ipc); if (err && (err != -EALREADY)) { LOG_ERR("IPC service instance initialization failed: %d\n", err); return err; } - err = ipc_service_register_endpoint(hci_ipc_instance, &hci_ept, &hci_ept_cfg); + err = ipc_service_register_endpoint(ipc->ipc, &ipc->hci_ept, &ipc->hci_ept_cfg); if (err) { LOG_ERR("Registering endpoint failed with %d", err); return err; } - err = k_sem_take(&ipc_bound_sem, IPC_BOUND_TIMEOUT_IN_MS); + err = k_sem_take(&ipc->bound_sem, IPC_BOUND_TIMEOUT_IN_MS); if (err) { LOG_ERR("Endpoint binding failed with %d", err); return err; } + ipc->recv = recv; + return 0; } -static int bt_ipc_close(void) +static int bt_ipc_close(const struct device *dev) { + struct ipc_data *ipc = dev->data; int err; if (IS_ENABLED(CONFIG_BT_HCI_HOST)) { @@ -349,16 +356,13 @@ static int bt_ipc_close(void) } } - err = ipc_service_deregister_endpoint(&hci_ept); + err = ipc_service_deregister_endpoint(&ipc->hci_ept); if (err) { LOG_ERR("Deregistering HCI endpoint failed with: %d", err); return err; } - const struct device *hci_ipc_instance = - DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_hci_ipc)); - - err = ipc_service_close_instance(hci_ipc_instance); + err = ipc_service_close_instance(ipc->ipc); if (err) { LOG_ERR("Closing IPC service failed with: %d", err); return err; @@ -370,31 +374,31 @@ static int bt_ipc_close(void) return err; } + ipc->recv = NULL; + return 0; } -static const struct bt_hci_driver drv = { - .name = "IPC", +static const struct bt_hci_driver_api drv = { .open = bt_ipc_open, .close = bt_ipc_close, .send = bt_ipc_send, - .bus = BT_HCI_DRIVER_BUS_IPM, -#if defined(CONFIG_BT_DRIVER_QUIRK_NO_AUTO_DLE) - .quirks = BT_QUIRK_NO_AUTO_DLE, -#endif }; -static int bt_ipc_init(void) -{ - - int err; - - err = bt_hci_driver_register(&drv); - if (err < 0) { - LOG_ERR("Failed to register BT HIC driver (err %d)", err); - } - - return err; -} - -SYS_INIT(bt_ipc_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +#define IPC_DEVICE_INIT(inst) \ + static struct ipc_data ipc_data_##inst = { \ + .bound_sem = Z_SEM_INITIALIZER(ipc_data_##inst.bound_sem, 0, 1), \ + .hci_ept_cfg = { \ + .name = DT_INST_PROP(inst, bt_hci_ipc_name), \ + .cb = { \ + .bound = hci_ept_bound, \ + .received = hci_ept_recv, \ + }, \ + .priv = (void *)DEVICE_DT_INST_GET(inst), \ + }, \ + .ipc = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + }; \ + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &ipc_data_##inst, NULL, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) + +DT_INST_FOREACH_STATUS_OKAY(IPC_DEVICE_INIT) diff --git a/drivers/bluetooth/hci/ipm_stm32wb.c b/drivers/bluetooth/hci/ipm_stm32wb.c index 48c5dd0a99cae..df83ee36d54c9 100644 --- a/drivers/bluetooth/hci/ipm_stm32wb.c +++ b/drivers/bluetooth/hci/ipm_stm32wb.c @@ -11,7 +11,7 @@ #include #include #include -#include +#include #include #include #include @@ -21,7 +21,11 @@ #include "shci.h" #include "shci_tl.h" -static const struct stm32_pclken clk_cfg[] = STM32_DT_CLOCKS(DT_NODELABEL(ble_rf)); +struct hci_data { + bt_hci_recv_t recv; +}; + +static const struct stm32_pclken clk_cfg[] = STM32_DT_CLOCKS(DT_DRV_INST(0)); #define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH * 4 * \ DIVC((sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE), 4)) @@ -156,7 +160,9 @@ void TM_EvtReceivedCb(TL_EvtPacket_t *hcievt) static void bt_ipm_rx_thread(void *p1, void *p2, void *p3) { - ARG_UNUSED(p1); + const struct device *dev = p1; + struct hci_data *hci = dev->data; + ARG_UNUSED(p2); ARG_UNUSED(p3); @@ -245,7 +251,7 @@ static void bt_ipm_rx_thread(void *p1, void *p2, void *p3) TL_MM_EvtDone(hcievt); - bt_recv(buf); + hci->recv(dev, buf); end_loop: k_sem_give(&ipm_busy); } @@ -347,10 +353,12 @@ void transport_init(void) TL_Enable(); } -static int bt_ipm_send(struct net_buf *buf) +static int bt_ipm_send(const struct device *dev, struct net_buf *buf) { TL_CmdPacket_t *ble_cmd_buff = &BleCmdBuffer; + ARG_UNUSED(dev); + k_sem_take(&ipm_busy, K_FOREVER); switch (bt_buf_get_type(buf)) { @@ -534,8 +542,9 @@ static int c2_reset(void) return 0; } -static int bt_ipm_open(void) +static int bt_ipm_open(const struct device *dev, bt_hci_recv_t recv) { + struct hci_data *hci = dev->data; int err; if (!c2_started_flag) { @@ -553,7 +562,7 @@ static int bt_ipm_open(void) /* Start RX thread */ k_thread_create(&ipm_rx_thread_data, ipm_rx_stack, K_KERNEL_STACK_SIZEOF(ipm_rx_stack), - bt_ipm_rx_thread, NULL, NULL, NULL, + bt_ipm_rx_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); @@ -564,14 +573,17 @@ static int bt_ipm_open(void) } #endif /* CONFIG_BT_HCI_HOST */ + hci->recv = recv; + LOG_DBG("IPM Channel Open Completed"); return 0; } #ifdef CONFIG_BT_HCI_HOST -static int bt_ipm_close(void) +static int bt_ipm_close(const struct device *dev) { + struct hci_data *hci = dev->data; int err; struct net_buf *rsp; @@ -590,15 +602,15 @@ static int bt_ipm_close(void) k_thread_abort(&ipm_rx_thread_data); + hci->recv = NULL; + LOG_DBG("IPM Channel Close Completed"); return err; } #endif /* CONFIG_BT_HCI_HOST */ -static const struct bt_hci_driver drv = { - .name = "BT IPM", - .bus = BT_HCI_DRIVER_BUS_IPM, +static const struct bt_hci_driver_api drv = { .open = bt_ipm_open, #ifdef CONFIG_BT_HCI_HOST .close = bt_ipm_close, @@ -606,12 +618,11 @@ static const struct bt_hci_driver drv = { .send = bt_ipm_send, }; -static int _bt_ipm_init(void) +static int _bt_ipm_init(const struct device *dev) { int err; - - bt_hci_driver_register(&drv); + ARG_UNUSED(dev); err = c2_reset(); if (err) { @@ -621,4 +632,11 @@ static int _bt_ipm_init(void) return 0; } -SYS_INIT(_bt_ipm_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +#define HCI_DEVICE_INIT(inst) \ + static struct hci_data hci_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, _bt_ipm_init, NULL, &hci_data_##inst, NULL, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) + +/* Only one instance supported right now */ +HCI_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/slz_hci.c b/drivers/bluetooth/hci/slz_hci.c index a3daf33460711..1dcb0278fd7e0 100644 --- a/drivers/bluetooth/hci/slz_hci.c +++ b/drivers/bluetooth/hci/slz_hci.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include #include @@ -16,6 +16,12 @@ #include LOG_MODULE_REGISTER(bt_hci_driver_slz); +#define DT_DRV_COMPAT silabs_bt_hci + +struct hci_data { + bt_hci_recv_t recv; +}; + #define SL_BT_CONFIG_ACCEPT_LIST_SIZE 1 #define SL_BT_CONFIG_MAX_CONNECTIONS 1 #define SL_BT_CONFIG_USER_ADVERTISERS 1 @@ -53,6 +59,8 @@ void rail_isr_installer(void) */ uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len) { + const struct device *dev = DEVICE_DT_GET(DT_DRV_INST(0)); + struct hci_data *hci = dev->data; struct net_buf *buf; uint8_t packet_type = data[0]; uint8_t event_code; @@ -77,17 +85,19 @@ uint32_t hci_common_transport_transmit(uint8_t *data, int16_t len) } net_buf_add_mem(buf, data, len); - bt_recv(buf); + hci->recv(dev, buf); sl_btctrl_hci_transmit_complete(0); return 0; } -static int slz_bt_send(struct net_buf *buf) +static int slz_bt_send(const struct device *dev, struct net_buf *buf) { int rv = 0; + ARG_UNUSED(dev); + switch (bt_buf_get_type(buf)) { case BT_BUF_ACL_OUT: net_buf_push_u8(buf, h4_acl); @@ -119,8 +129,9 @@ static void slz_thread_func(void *p1, void *p2, void *p3) slz_ll_thread_func(); } -static int slz_bt_open(void) +static int slz_bt_open(const struct device *dev, bt_hci_recv_t recv) { + struct hci_data *hci = dev->data; int ret; /* Start RX thread */ @@ -185,6 +196,8 @@ static int slz_bt_open(void) } #endif + hci->recv = recv; + LOG_DBG("SiLabs BT HCI started"); return 0; @@ -193,24 +206,16 @@ static int slz_bt_open(void) return ret; } -static const struct bt_hci_driver drv = { - .name = "sl:bt", - .bus = BT_HCI_DRIVER_BUS_UART, +static const struct bt_hci_driver_api drv = { .open = slz_bt_open, .send = slz_bt_send, - .quirks = BT_QUIRK_NO_RESET }; -static int slz_bt_init(void) -{ - int ret; - - ret = bt_hci_driver_register(&drv); - if (ret) { - LOG_ERR("Failed to register SiLabs BT HCI %d", ret); - } - - return ret; -} +#define HCI_DEVICE_INIT(inst) \ + static struct hci_data hci_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &hci_data_##inst, NULL, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &drv) -SYS_INIT(slz_bt_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +/* Only one instance supported right now */ +HCI_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/spi.c b/drivers/bluetooth/hci/spi.c index 26d8f32afd0a7..05e46a1d182cf 100644 --- a/drivers/bluetooth/hci/spi.c +++ b/drivers/bluetooth/hci/spi.c @@ -15,7 +15,7 @@ #include #include -#include +#include #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL #include @@ -66,6 +66,10 @@ LOG_MODULE_REGISTER(bt_driver); be transmitted across this HCI link #endif /* CONFIG_BT_L2CAP_TX_MTU > MAX_MTU */ +struct bt_spi_data { + bt_hci_recv_t recv; +}; + static uint8_t __noinit rxmsg[SPI_MAX_MSG_LEN]; static uint8_t __noinit txmsg[SPI_MAX_MSG_LEN]; @@ -236,7 +240,9 @@ static struct net_buf *bt_spi_rx_buf_construct(uint8_t *msg) static void bt_spi_rx_thread(void *p1, void *p2, void *p3) { - ARG_UNUSED(p1); + const struct device *dev = p1; + struct bt_spi_data *hci = dev->data; + ARG_UNUSED(p2); ARG_UNUSED(p3); @@ -288,17 +294,19 @@ static void bt_spi_rx_thread(void *p1, void *p2, void *p3) buf = bt_spi_rx_buf_construct(rxmsg); if (buf) { /* Handle the received HCI data */ - bt_recv(buf); + hci->recv(dev, buf); } } } -static int bt_spi_send(struct net_buf *buf) +static int bt_spi_send(const struct device *dev, struct net_buf *buf) { uint16_t size; uint8_t rx_first[1]; int ret; + ARG_UNUSED(dev); + LOG_DBG(""); /* Buffer needs an additional byte for type */ @@ -364,8 +372,9 @@ static int bt_spi_send(struct net_buf *buf) return ret; } -static int bt_spi_open(void) +static int bt_spi_open(const struct device *dev, bt_hci_recv_t recv) { + struct bt_spi_data *hci = dev->data; int err; /* Configure RST pin and hold BLE in Reset */ @@ -392,6 +401,8 @@ static int bt_spi_open(void) return err; } + hci->recv = recv; + /* Take BLE out of reset */ k_sleep(K_MSEC(DT_INST_PROP_OR(0, reset_assert_duration_ms, 0))); gpio_pin_set_dt(&rst_gpio, 0); @@ -399,7 +410,7 @@ static int bt_spi_open(void) /* Start RX thread */ k_thread_create(&spi_rx_thread_data, spi_rx_stack, K_KERNEL_STACK_SIZEOF(spi_rx_stack), - bt_spi_rx_thread, NULL, NULL, NULL, + bt_spi_rx_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); @@ -409,15 +420,14 @@ static int bt_spi_open(void) return 0; } -static const struct bt_hci_driver drv = { - .name = DEVICE_DT_NAME(DT_DRV_INST(0)), - .bus = BT_HCI_DRIVER_BUS_SPI, +static const struct bt_hci_driver_api drv = { .open = bt_spi_open, .send = bt_spi_send, }; -static int bt_spi_init(void) +static int bt_spi_init(const struct device *dev) { + ARG_UNUSED(dev); if (!spi_is_ready_dt(&bus)) { LOG_ERR("SPI device not ready"); @@ -434,12 +444,16 @@ static int bt_spi_init(void) return -ENODEV; } - bt_hci_driver_register(&drv); - - LOG_DBG("BT SPI initialized"); return 0; } -SYS_INIT(bt_spi_init, POST_KERNEL, CONFIG_BT_SPI_INIT_PRIORITY); +#define HCI_DEVICE_INIT(inst) \ + static struct bt_spi_data hci_data_##inst = { \ + }; \ + DEVICE_DT_INST_DEFINE(inst, bt_spi_init, NULL, &hci_data_##inst, NULL, \ + POST_KERNEL, CONFIG_BT_SPI_INIT_PRIORITY, &drv) + +/* Only one instance supported right now */ +HCI_DEVICE_INIT(0) diff --git a/drivers/bluetooth/hci/userchan.c b/drivers/bluetooth/hci/userchan.c index 4c7b178fa6d83..a5f6810b82b7e 100644 --- a/drivers/bluetooth/hci/userchan.c +++ b/drivers/bluetooth/hci/userchan.c @@ -30,12 +30,20 @@ #include #include -#include +#include #define LOG_LEVEL CONFIG_BT_HCI_DRIVER_LOG_LEVEL #include LOG_MODULE_REGISTER(bt_driver); +#define DT_DRV_COMPAT zephyr_bt_hci_userchan + +struct uc_data { + int fd; + bt_hci_recv_t recv; + +}; + #define BTPROTO_HCI 1 struct sockaddr_hci { sa_family_t hci_family; @@ -50,8 +58,6 @@ static K_KERNEL_STACK_DEFINE(rx_thread_stack, CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE); static struct k_thread rx_thread_data; -static int uc_fd = -1; - static unsigned short bt_dev_index; #define TCP_ADDR_BUFF_SIZE 16 @@ -89,16 +95,18 @@ static struct net_buf *get_rx(const uint8_t *buf) } /** - * @brief Decode the length of an HCI H4 packet + * @brief Decode the length of an HCI H4 packet and check it's complete * @details Decodes packet length according to Bluetooth spec v5.4 Vol 4 Part E * @param buf Pointer to a HCI packet buffer - * @return Length of the HCI packet in bytes, zero if no valid packet found. + * @param buf_len Bytes available in the buffer + * @return Length of the complete HCI packet in bytes, -1 if cannot find an HCI + * packet, 0 if more data required. */ -static uint16_t packet_len(const uint8_t *buf) +static int32_t hci_packet_complete(const uint8_t *buf, uint16_t buf_len) { uint16_t payload_len = 0; - uint8_t header_len = 0; const uint8_t type = buf[0]; + uint8_t header_len = sizeof(type); const uint8_t *hdr = &buf[sizeof(type)]; switch (type) { @@ -107,7 +115,7 @@ static uint16_t packet_len(const uint8_t *buf) /* Parameter Total Length */ payload_len = cmd->param_len; - header_len = BT_HCI_CMD_HDR_SIZE; + header_len += BT_HCI_CMD_HDR_SIZE; break; } case BT_HCI_H4_ACL: { @@ -115,7 +123,7 @@ static uint16_t packet_len(const uint8_t *buf) /* Data Total Length */ payload_len = sys_le16_to_cpu(acl->len); - header_len = BT_HCI_ACL_HDR_SIZE; + header_len += BT_HCI_ACL_HDR_SIZE; break; } case BT_HCI_H4_SCO: { @@ -123,7 +131,7 @@ static uint16_t packet_len(const uint8_t *buf) /* Data_Total_Length */ payload_len = sco->len; - header_len = BT_HCI_SCO_HDR_SIZE; + header_len += BT_HCI_SCO_HDR_SIZE; break; } case BT_HCI_H4_EVT: { @@ -131,7 +139,7 @@ static uint16_t packet_len(const uint8_t *buf) /* Parameter Total Length */ payload_len = evt->len; - header_len = BT_HCI_EVT_HDR_SIZE; + header_len += BT_HCI_EVT_HDR_SIZE; break; } case BT_HCI_H4_ISO: { @@ -139,33 +147,42 @@ static uint16_t packet_len(const uint8_t *buf) /* ISO_Data_Load_Length parameter */ payload_len = bt_iso_hdr_len(sys_le16_to_cpu(iso->len)); - header_len = BT_HCI_ISO_HDR_SIZE; + header_len += BT_HCI_ISO_HDR_SIZE; break; } /* If no valid packet type found */ default: LOG_WRN("Unknown packet type 0x%02x", type); + return -1; + } + + /* Request more data */ + if (buf_len < header_len || buf_len - header_len < payload_len) { return 0; } - return sizeof(type) + header_len + payload_len; + return (int32_t)header_len + payload_len; } -static bool uc_ready(void) +static bool uc_ready(int fd) { - struct pollfd pollfd = { .fd = uc_fd, .events = POLLIN }; + struct pollfd pollfd = { .fd = fd, .events = POLLIN }; return (poll(&pollfd, 1, 0) == 1); } static void rx_thread(void *p1, void *p2, void *p3) { - ARG_UNUSED(p1); + const struct device *dev = p1; + struct uc_data *uc = dev->data; + ARG_UNUSED(p2); ARG_UNUSED(p3); LOG_DBG("started"); + uint16_t frame_size = 0; + while (1) { static uint8_t frame[512]; struct net_buf *buf; @@ -174,14 +191,14 @@ static void rx_thread(void *p1, void *p2, void *p3) ssize_t len; const uint8_t *frame_start = frame; - if (!uc_ready()) { + if (!uc_ready(uc->fd)) { k_sleep(K_MSEC(1)); continue; } LOG_DBG("calling read()"); - len = read(uc_fd, frame, sizeof(frame)); + len = read(uc->fd, frame + frame_size, sizeof(frame) - frame_size); if (len < 0) { if (errno == EINTR) { k_yield(); @@ -189,62 +206,78 @@ static void rx_thread(void *p1, void *p2, void *p3) } LOG_ERR("Reading socket failed, errno %d", errno); - close(uc_fd); - uc_fd = -1; + close(uc->fd); + uc->fd = -1; return; } - while (len > 0) { + frame_size += len; + while (frame_size > 0) { + const uint8_t *buf_add; const uint8_t packet_type = frame_start[0]; - const uint16_t decoded_len = packet_len(frame_start); + const int32_t decoded_len = hci_packet_complete(frame_start, frame_size); - if (decoded_len == 0) { + if (decoded_len == -1) { LOG_ERR("HCI Packet type is invalid, length could not be decoded"); + frame_size = 0; /* Drop buffer */ break; } - if (decoded_len > len) { - LOG_ERR("Decoded HCI packet length (%d bytes) is greater " - "than buffer length (%d bytes)", decoded_len, len); + if (decoded_len == 0) { + if (frame_size == sizeof(frame)) { + LOG_ERR("HCI Packet (%d bytes) is too big for frame (%d " + "bytes)", + decoded_len, sizeof(frame)); + frame_size = 0; /* Drop buffer */ + break; + } + if (frame_start != frame) { + memmove(frame, frame_start, frame_size); + } + /* Read more */ break; } + buf_add = frame_start + sizeof(packet_type); + buf_add_len = decoded_len - sizeof(packet_type); + buf = get_rx(frame_start); + + frame_size -= decoded_len; + frame_start += decoded_len; + if (!buf) { LOG_DBG("Discard adv report due to insufficient buf"); - goto next; + continue; } buf_tailroom = net_buf_tailroom(buf); - buf_add_len = decoded_len - sizeof(packet_type); if (buf_tailroom < buf_add_len) { LOG_ERR("Not enough space in buffer %zu/%zu", buf_add_len, buf_tailroom); net_buf_unref(buf); - goto next; + continue; } - net_buf_add_mem(buf, frame_start + sizeof(packet_type), buf_add_len); + net_buf_add_mem(buf, buf_add, buf_add_len); LOG_DBG("Calling bt_recv(%p)", buf); - bt_recv(buf); - -next: - len -= decoded_len; - frame_start += decoded_len; + uc->recv(dev, buf); } k_yield(); } } -static int uc_send(struct net_buf *buf) +static int uc_send(const struct device *dev, struct net_buf *buf) { + struct uc_data *uc = dev->data; + LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); - if (uc_fd < 0) { + if (uc->fd < 0) { LOG_ERR("User channel not open"); return -EIO; } @@ -267,7 +300,7 @@ static int uc_send(struct net_buf *buf) return -EINVAL; } - if (write(uc_fd, buf->data, buf->len) < 0) { + if (write(uc->fd, buf->data, buf->len) < 0) { return -errno; } @@ -327,25 +360,28 @@ static int user_chan_open(void) return fd; } -static int uc_open(void) +static int uc_open(const struct device *dev, bt_hci_recv_t recv) { + struct uc_data *uc = dev->data; + if (hci_socket) { LOG_DBG("hci%d", bt_dev_index); } else { LOG_DBG("hci %s:%d", ip_addr, port); } - - uc_fd = user_chan_open(); - if (uc_fd < 0) { - return uc_fd; + uc->fd = user_chan_open(); + if (uc->fd < 0) { + return uc->fd; } - LOG_DBG("User Channel opened as fd %d", uc_fd); + uc->recv = recv; + + LOG_DBG("User Channel opened as fd %d", uc->fd); k_thread_create(&rx_thread_data, rx_thread_stack, K_KERNEL_STACK_SIZEOF(rx_thread_stack), - rx_thread, NULL, NULL, NULL, + rx_thread, (void *)dev, NULL, NULL, K_PRIO_COOP(CONFIG_BT_DRIVER_RX_HIGH_PRIO), 0, K_NO_WAIT); @@ -354,22 +390,31 @@ static int uc_open(void) return 0; } -static const struct bt_hci_driver drv = { - .name = "HCI User Channel", - .bus = BT_HCI_DRIVER_BUS_UART, - .open = uc_open, - .send = uc_send, +static const struct bt_hci_driver_api uc_drv_api = { + .open = uc_open, + .send = uc_send, }; -static int bt_uc_init(void) +static int uc_init(const struct device *dev) { - - bt_hci_driver_register(&drv); + if (!arg_found) { + posix_print_warning("Warning: Bluetooth device missing.\n" + "Specify either a local hci interface --bt-dev=hciN\n" + "or a valid hci tcp server --bt-dev=ip_address:port\n"); + return -ENODEV; + } return 0; } -SYS_INIT(bt_uc_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); +#define UC_DEVICE_INIT(inst) \ + static struct uc_data uc_data_##inst = { \ + .fd = -1, \ + }; \ + DEVICE_DT_INST_DEFINE(inst, uc_init, NULL, &uc_data_##inst, NULL, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &uc_drv_api) + +DT_INST_FOREACH_STATUS_OKAY(UC_DEVICE_INIT) static void cmd_bt_dev_found(char *argv, int offset) { @@ -423,14 +468,4 @@ static void add_btuserchan_arg(void) native_add_command_line_opts(btuserchan_args); } -static void btuserchan_check_arg(void) -{ - if (!arg_found) { - posix_print_error_and_exit("Error: Bluetooth device missing.\n" - "Specify either a local hci interface --bt-dev=hciN\n" - "or a valid hci tcp server --bt-dev=ip_address:port\n"); - } -} - NATIVE_TASK(add_btuserchan_arg, PRE_BOOT_1, 10); -NATIVE_TASK(btuserchan_check_arg, PRE_BOOT_2, 10); diff --git a/drivers/cache/cache_handlers.c b/drivers/cache/cache_handlers.c index 2005124136f76..692ec1306d9c8 100644 --- a/drivers/cache/cache_handlers.c +++ b/drivers/cache/cache_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_sys_cache_data_flush_range(void *addr, size_t size) return z_impl_sys_cache_data_flush_range(addr, size); } -#include +#include static inline int z_vrfy_sys_cache_data_invd_range(void *addr, size_t size) { @@ -21,7 +21,7 @@ static inline int z_vrfy_sys_cache_data_invd_range(void *addr, size_t size) return z_impl_sys_cache_data_invd_range(addr, size); } -#include +#include static inline int z_vrfy_sys_cache_data_flush_and_invd_range(void *addr, size_t size) { @@ -29,4 +29,4 @@ static inline int z_vrfy_sys_cache_data_flush_and_invd_range(void *addr, size_t return z_impl_sys_cache_data_flush_and_invd_range(addr, size); } -#include +#include diff --git a/drivers/can/CMakeLists.txt b/drivers/can/CMakeLists.txt index f53cf7d2c1e65..caed52dc8fb8a 100644 --- a/drivers/can/CMakeLists.txt +++ b/drivers/can/CMakeLists.txt @@ -24,6 +24,7 @@ zephyr_library_sources_ifdef(CONFIG_CAN_XMC4XXX can_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_CAN_SJA1000 can_sja1000.c) zephyr_library_sources_ifdef(CONFIG_CAN_ESP32_TWAI can_esp32_twai.c) zephyr_library_sources_ifdef(CONFIG_CAN_KVASER_PCI can_kvaser_pci.c) +zephyr_library_sources_ifdef(CONFIG_CAN_NRF can_nrf.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE can_handlers.c) zephyr_library_sources_ifdef(CONFIG_CAN_SHELL can_shell.c) diff --git a/drivers/can/Kconfig b/drivers/can/Kconfig index 4f929ba32f83e..5aa956353dc21 100644 --- a/drivers/can/Kconfig +++ b/drivers/can/Kconfig @@ -23,6 +23,21 @@ config CAN_INIT_PRIORITY help CAN driver device initialization priority. +config CAN_DEFAULT_BITRATE + int "Default CAN bitrate" + default 125000 + help + Default initial CAN bitrate in bits/s. This can be overridden per CAN controller using the + "bitrate" devicetree property. + +config CAN_DEFAULT_BITRATE_DATA + int "Default CAN data phase bitrate" + default 1000000 + depends on CAN_FD_MODE + help + Default initial CAN data phase bitrate in bits/s. This can be overridden per CAN controller + using the "bitrate-data" devicetree property. + config CAN_SHELL bool "CAN shell" depends on SHELL @@ -46,6 +61,13 @@ config CAN_SHELL_RX_QUEUE_SIZE help Maximum number of CAN frames in the CAN shell receive queue. +config CAN_SHELL_SCRIPTING_FRIENDLY + bool "Produce scripting-friendly output" + help + Enable scripting-friendly/machine-readable output from the CAN shell. Enabling this + bypasses the shell when printing certain outputs to ensure the output is not interleaved + with the shell prompt. + endif # CAN_SHELL config CAN_STATS @@ -106,6 +128,7 @@ source "drivers/can/Kconfig.nxp_s32" source "drivers/can/Kconfig.tcan4x5x" source "drivers/can/Kconfig.mcp251xfd" source "drivers/can/Kconfig.xmc4xxx" +source "drivers/can/Kconfig.nrf" source "drivers/can/transceiver/Kconfig" diff --git a/drivers/can/Kconfig.mcux b/drivers/can/Kconfig.mcux index e995a19ab6f1a..a0e3e00fddab0 100644 --- a/drivers/can/Kconfig.mcux +++ b/drivers/can/Kconfig.mcux @@ -59,5 +59,6 @@ config CAN_MCUX_MCAN depends on CLOCK_CONTROL select CAN_MCAN select PINCTRL + select RESET help Enable support for mcux mcan driver. diff --git a/drivers/can/Kconfig.nrf b/drivers/can/Kconfig.nrf new file mode 100644 index 0000000000000..d21bb4e7ebe36 --- /dev/null +++ b/drivers/can/Kconfig.nrf @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config CAN_NRF + bool "nRF CAN driver" + default y + depends on DT_HAS_NORDIC_NRF_CAN_ENABLED + select CAN_MCAN + select CLOCK_CONTROL + help + Driver for nRF CAN. diff --git a/drivers/can/Kconfig.numaker b/drivers/can/Kconfig.numaker index 23de8ab50ecd8..f36feee6fb41e 100644 --- a/drivers/can/Kconfig.numaker +++ b/drivers/can/Kconfig.numaker @@ -8,6 +8,6 @@ config CAN_NUMAKER default y select CAN_MCAN depends on DT_HAS_NUVOTON_NUMAKER_CANFD_ENABLED - depends on SOC_SERIES_M46X + depends on SOC_SERIES_M46X || SOC_SERIES_M2L31X help Enables Nuvoton NuMaker CAN FD driver, using Bosch M_CAN diff --git a/drivers/can/can_handlers.c b/drivers/can/can_handlers.c index b762b80d9209c..c67ce015330d5 100644 --- a/drivers/can/can_handlers.c +++ b/drivers/can/can_handlers.c @@ -21,7 +21,7 @@ static int z_vrfy_can_calc_timing(const struct device *dev, struct can_timing *r return err; } -#include +#include static inline int z_vrfy_can_set_timing(const struct device *dev, const struct can_timing *timing) @@ -33,7 +33,7 @@ static inline int z_vrfy_can_set_timing(const struct device *dev, return z_impl_can_set_timing(dev, &timing_copy); } -#include +#include static inline int z_vrfy_can_get_core_clock(const struct device *dev, uint32_t *rate) @@ -43,7 +43,7 @@ static inline int z_vrfy_can_get_core_clock(const struct device *dev, return z_impl_can_get_core_clock(dev, rate); } -#include +#include static inline uint32_t z_vrfy_can_get_bitrate_min(const struct device *dev) { @@ -51,7 +51,7 @@ static inline uint32_t z_vrfy_can_get_bitrate_min(const struct device *dev) return z_impl_can_get_bitrate_min(dev); } -#include +#include static inline uint32_t z_vrfy_can_get_bitrate_max(const struct device *dev) { @@ -59,7 +59,7 @@ static inline uint32_t z_vrfy_can_get_bitrate_max(const struct device *dev) return z_impl_can_get_bitrate_max(dev); } -#include +#include static inline const struct can_timing *z_vrfy_can_get_timing_min(const struct device *dev) { @@ -67,7 +67,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_min(const struct de return z_impl_can_get_timing_min(dev); } -#include +#include static inline const struct can_timing *z_vrfy_can_get_timing_max(const struct device *dev) { @@ -75,7 +75,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_max(const struct de return z_impl_can_get_timing_max(dev); } -#include +#include #ifdef CONFIG_CAN_FD_MODE @@ -93,7 +93,7 @@ static int z_vrfy_can_calc_timing_data(const struct device *dev, struct can_timi return err; } -#include +#include static inline const struct can_timing *z_vrfy_can_get_timing_data_min(const struct device *dev) { @@ -101,7 +101,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_data_min(const stru return z_impl_can_get_timing_data_min(dev); } -#include +#include static inline const struct can_timing *z_vrfy_can_get_timing_data_max(const struct device *dev) { @@ -109,7 +109,7 @@ static inline const struct can_timing *z_vrfy_can_get_timing_data_max(const stru return z_impl_can_get_timing_data_max(dev); } -#include +#include static inline int z_vrfy_can_set_timing_data(const struct device *dev, const struct can_timing *timing_data) @@ -121,7 +121,7 @@ static inline int z_vrfy_can_set_timing_data(const struct device *dev, return z_impl_can_set_timing_data(dev, &timing_data_copy); } -#include +#include static inline int z_vrfy_can_set_bitrate_data(const struct device *dev, uint32_t bitrate_data) @@ -130,7 +130,7 @@ static inline int z_vrfy_can_set_bitrate_data(const struct device *dev, return z_impl_can_set_bitrate_data(dev, bitrate_data); } -#include +#include #endif /* CONFIG_CAN_FD_MODE */ @@ -141,7 +141,7 @@ static inline int z_vrfy_can_get_max_filters(const struct device *dev, bool ide) return z_impl_can_get_max_filters(dev, ide); } -#include +#include static inline int z_vrfy_can_get_capabilities(const struct device *dev, can_mode_t *cap) { @@ -150,7 +150,7 @@ static inline int z_vrfy_can_get_capabilities(const struct device *dev, can_mode return z_impl_can_get_capabilities(dev, cap); } -#include +#include static inline const struct device *z_vrfy_can_get_transceiver(const struct device *dev) { @@ -158,7 +158,7 @@ static inline const struct device *z_vrfy_can_get_transceiver(const struct devic return z_impl_can_get_transceiver(dev); } -#include +#include static inline int z_vrfy_can_start(const struct device *dev) { @@ -166,7 +166,7 @@ static inline int z_vrfy_can_start(const struct device *dev) return z_impl_can_start(dev); } -#include +#include static inline int z_vrfy_can_stop(const struct device *dev) { @@ -174,7 +174,7 @@ static inline int z_vrfy_can_stop(const struct device *dev) return z_impl_can_stop(dev); } -#include +#include static inline int z_vrfy_can_set_mode(const struct device *dev, can_mode_t mode) { @@ -182,7 +182,7 @@ static inline int z_vrfy_can_set_mode(const struct device *dev, can_mode_t mode) return z_impl_can_set_mode(dev, mode); } -#include +#include static inline can_mode_t z_vrfy_can_get_mode(const struct device *dev) { @@ -190,7 +190,7 @@ static inline can_mode_t z_vrfy_can_get_mode(const struct device *dev) return z_impl_can_get_mode(dev); } -#include +#include static inline int z_vrfy_can_set_bitrate(const struct device *dev, uint32_t bitrate) { @@ -198,7 +198,7 @@ static inline int z_vrfy_can_set_bitrate(const struct device *dev, uint32_t bitr return z_impl_can_set_bitrate(dev, bitrate); } -#include +#include static inline int z_vrfy_can_send(const struct device *dev, const struct can_frame *frame, @@ -214,7 +214,7 @@ static inline int z_vrfy_can_send(const struct device *dev, return z_impl_can_send(dev, &frame_copy, timeout, callback, user_data); } -#include +#include static inline int z_vrfy_can_add_rx_filter_msgq(const struct device *dev, struct k_msgq *msgq, @@ -228,7 +228,7 @@ static inline int z_vrfy_can_add_rx_filter_msgq(const struct device *dev, return z_impl_can_add_rx_filter_msgq(dev, msgq, &filter_copy); } -#include +#include static inline void z_vrfy_can_remove_rx_filter(const struct device *dev, int filter_id) { @@ -236,7 +236,7 @@ static inline void z_vrfy_can_remove_rx_filter(const struct device *dev, int fil z_impl_can_remove_rx_filter(dev, filter_id); } -#include +#include static inline int z_vrfy_can_get_state(const struct device *dev, enum can_state *state, struct can_bus_err_cnt *err_cnt) @@ -253,7 +253,7 @@ static inline int z_vrfy_can_get_state(const struct device *dev, enum can_state return z_impl_can_get_state(dev, state, err_cnt); } -#include +#include #ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE static inline int z_vrfy_can_recover(const struct device *dev, k_timeout_t timeout) @@ -263,7 +263,7 @@ static inline int z_vrfy_can_recover(const struct device *dev, k_timeout_t timeo return z_impl_can_recover(dev, timeout); } -#include +#include #endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */ #ifdef CONFIG_CAN_STATS @@ -274,7 +274,7 @@ static inline uint32_t z_vrfy_can_stats_get_bit_errors(const struct device *dev) return z_impl_can_stats_get_bit_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_bit0_errors(const struct device *dev) { @@ -282,7 +282,7 @@ static inline uint32_t z_vrfy_can_stats_get_bit0_errors(const struct device *dev return z_impl_can_stats_get_bit0_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_bit1_errors(const struct device *dev) { @@ -290,7 +290,7 @@ static inline uint32_t z_vrfy_can_stats_get_bit1_errors(const struct device *dev return z_impl_can_stats_get_bit1_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_stuff_errors(const struct device *dev) { @@ -298,7 +298,7 @@ static inline uint32_t z_vrfy_can_stats_get_stuff_errors(const struct device *de return z_impl_can_stats_get_stuff_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_crc_errors(const struct device *dev) { @@ -306,7 +306,7 @@ static inline uint32_t z_vrfy_can_stats_get_crc_errors(const struct device *dev) return z_impl_can_stats_get_crc_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_form_errors(const struct device *dev) { @@ -314,7 +314,7 @@ static inline uint32_t z_vrfy_can_stats_get_form_errors(const struct device *dev return z_impl_can_stats_get_form_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_ack_errors(const struct device *dev) { @@ -322,7 +322,7 @@ static inline uint32_t z_vrfy_can_stats_get_ack_errors(const struct device *dev) return z_impl_can_stats_get_ack_errors(dev); } -#include +#include static inline uint32_t z_vrfy_can_stats_get_rx_overruns(const struct device *dev) { @@ -330,6 +330,6 @@ static inline uint32_t z_vrfy_can_stats_get_rx_overruns(const struct device *dev return z_impl_can_stats_get_rx_overruns(dev); } -#include +#include #endif /* CONFIG_CAN_STATS */ diff --git a/drivers/can/can_mcan.c b/drivers/can/can_mcan.c index 9f3d41368b94c..c4a94d49cfaa4 100644 --- a/drivers/can/can_mcan.c +++ b/drivers/can/can_mcan.c @@ -743,7 +743,7 @@ static void can_mcan_get_message(const struct device *dev, uint16_t fifo_offset, data_length = can_dlc_to_bytes(frame.dlc); if (data_length <= sizeof(frame.data)) { - if ((frame.flags & CAN_FRAME_RTR) == 0U) { + if ((frame.flags & CAN_FRAME_RTR) == 0U && data_length != 0U) { err = can_mcan_read_mram(dev, fifo_offset + get_idx * sizeof(struct can_mcan_rx_fifo) + offsetof(struct can_mcan_rx_fifo, data_32), @@ -802,6 +802,14 @@ void can_mcan_line_1_isr(const struct device *dev) return; } + if ((ir & CAN_MCAN_IR_PEA) != 0U) { + LOG_DBG("Protocol error in arbitration phase: ir: 0x%x", ir); + } + + if ((ir & CAN_MCAN_IR_PED) != 0U) { + LOG_DBG("Protocol error in data phase: ir: 0x%x", ir); + } + while ((ir & events) != 0U) { err = can_mcan_write_reg(dev, CAN_MCAN_IR, events & ir); if (err != 0) { @@ -1006,7 +1014,7 @@ int can_mcan_send(const struct device *dev, const struct can_frame *frame, k_tim goto err_unlock; } - if ((frame->flags & CAN_FRAME_RTR) == 0U) { + if ((frame->flags & CAN_FRAME_RTR) == 0U && data_length != 0U) { err = can_mcan_write_mram(dev, config->mram_offsets[CAN_MCAN_MRAM_CFG_TX_BUFFER] + put_idx * sizeof(struct can_mcan_tx_buffer) + offsetof(struct can_mcan_tx_buffer, data_32), @@ -1458,7 +1466,7 @@ int can_mcan_init(const struct device *dev) return err; } - err = can_calc_timing(dev, &timing, config->common.bus_speed, + err = can_calc_timing(dev, &timing, config->common.bitrate, config->common.sample_point); if (err == -EINVAL) { LOG_ERR("Can't find timing for given param"); @@ -1469,7 +1477,7 @@ int can_mcan_init(const struct device *dev) timing.phase_seg2); LOG_DBG("Sample-point err : %d", err); #ifdef CONFIG_CAN_FD_MODE - err = can_calc_timing_data(dev, &timing_data, config->common.bus_speed_data, + err = can_calc_timing_data(dev, &timing_data, config->common.bitrate_data, config->common.sample_point_data); if (err == -EINVAL) { LOG_ERR("Can't find timing for given dataphase param"); diff --git a/drivers/can/can_mcp2515.c b/drivers/can/can_mcp2515.c index b7720a7ab47ae..791f548cec5b4 100644 --- a/drivers/can/can_mcp2515.c +++ b/drivers/can/can_mcp2515.c @@ -972,7 +972,7 @@ static int mcp2515_init(const struct device *dev) (void)memset(dev_data->filter, 0, sizeof(dev_data->filter)); dev_data->old_state = CAN_STATE_ERROR_ACTIVE; - ret = can_calc_timing(dev, &timing, dev_cfg->common.bus_speed, + ret = can_calc_timing(dev, &timing, dev_cfg->common.bitrate, dev_cfg->common.sample_point); if (ret == -EINVAL) { LOG_ERR("Can't find timing for given param"); diff --git a/drivers/can/can_mcp251xfd.c b/drivers/can/can_mcp251xfd.c index 8e1fef06168ee..ae347296eeb3a 100644 --- a/drivers/can/can_mcp251xfd.c +++ b/drivers/can/can_mcp251xfd.c @@ -1576,7 +1576,7 @@ static int mcp251xfd_init(const struct device *dev) goto done; } - ret = can_calc_timing(dev, &timing, dev_cfg->common.bus_speed, + ret = can_calc_timing(dev, &timing, dev_cfg->common.bitrate, dev_cfg->common.sample_point); if (ret < 0) { LOG_ERR("Can't find timing for given param"); @@ -1588,7 +1588,7 @@ static int mcp251xfd_init(const struct device *dev) LOG_DBG("Sample-point err : %d", ret); #if defined(CONFIG_CAN_FD_MODE) - ret = can_calc_timing_data(dev, &timing_data, dev_cfg->common.bus_speed_data, + ret = can_calc_timing_data(dev, &timing_data, dev_cfg->common.bitrate_data, dev_cfg->common.sample_point_data); if (ret < 0) { LOG_ERR("Can't find data timing for given param"); diff --git a/drivers/can/can_mcux_flexcan.c b/drivers/can/can_mcux_flexcan.c index c4109c89c610d..cc11dadf96247 100644 --- a/drivers/can/can_mcux_flexcan.c +++ b/drivers/can/can_mcux_flexcan.c @@ -305,6 +305,12 @@ static int mcux_flexcan_start(const struct device *dev) timing.fphaseSeg2 = data->timing_data.phase_seg2 - 1U; timing.fpropSeg = data->timing_data.prop_seg; FLEXCAN_SetFDTimingConfig(config->base, &timing); + + FLEXCAN_EnterFreezeMode(config->base); + config->base->FDCTRL &= ~(CAN_FDCTRL_TDCOFF_MASK); + config->base->FDCTRL |= FIELD_PREP(CAN_FDCTRL_TDCOFF_MASK, + CAN_CALC_TDCO((&data->timing_data), 1U, 31U)); + FLEXCAN_ExitFreezeMode(config->base); } #endif /* CONFIG_CAN_MCUX_FLEXCAN_FD */ @@ -1139,7 +1145,7 @@ static int mcux_flexcan_init(const struct device *dev) k_sem_init(&data->tx_allocs_sem, MCUX_FLEXCAN_MAX_TX, MCUX_FLEXCAN_MAX_TX); - err = can_calc_timing(dev, &data->timing, config->common.bus_speed, + err = can_calc_timing(dev, &data->timing, config->common.bitrate, config->common.sample_point); if (err == -EINVAL) { LOG_ERR("Can't find timing for given param"); @@ -1160,7 +1166,7 @@ static int mcux_flexcan_init(const struct device *dev) #ifdef CONFIG_CAN_MCUX_FLEXCAN_FD if (config->flexcan_fd) { err = can_calc_timing_data(dev, &data->timing_data, - config->common.bus_speed_data, + config->common.bitrate_data, config->common.sample_point_data); if (err == -EINVAL) { LOG_ERR("Can't find timing for given param"); diff --git a/drivers/can/can_mcux_mcan.c b/drivers/can/can_mcux_mcan.c index 2ca5d3e02771d..5a984279ae554 100644 --- a/drivers/can/can_mcux_mcan.c +++ b/drivers/can/can_mcux_mcan.c @@ -11,6 +11,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(can_mcux_mcan, CONFIG_CAN_LOG_LEVEL); @@ -27,6 +28,7 @@ struct mcux_mcan_config { clock_control_subsys_t clock_subsys; void (*irq_config_func)(const struct device *dev); const struct pinctrl_dev_config *pincfg; + const struct reset_dt_spec reset; }; static int mcux_mcan_read_reg(const struct device *dev, uint16_t reg, uint32_t *val) @@ -91,6 +93,16 @@ static int mcux_mcan_init(const struct device *dev) return -ENODEV; } + if (!device_is_ready(mcux_config->reset.dev)) { + LOG_ERR("Reset device not ready"); + return -ENODEV; + } + + err = reset_line_toggle(mcux_config->reset.dev, mcux_config->reset.id); + if (err) { + return err; + } + err = pinctrl_apply_state(mcux_config->pincfg, PINCTRL_STATE_DEFAULT); if (err) { return err; @@ -197,6 +209,7 @@ static const struct can_mcan_ops mcux_mcan_ops = { DT_INST_CLOCKS_CELL(n, name), \ .irq_config_func = mcux_mcan_irq_config_##n, \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .reset = RESET_DT_SPEC_INST_GET(n), \ }; \ \ static const struct can_mcan_config can_mcan_config_##n = \ diff --git a/drivers/can/can_nrf.c b/drivers/can/can_nrf.c new file mode 100644 index 0000000000000..553e115f8e239 --- /dev/null +++ b/drivers/can/can_nrf.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_nrf_can + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* nRF CAN wrapper offsets */ +#define CAN_TASKS_START offsetof(NRF_CAN_Type, TASKS_START) +#define CAN_EVENTS_CORE_0 offsetof(NRF_CAN_Type, EVENTS_CORE[0]) +#define CAN_EVENTS_CORE_1 offsetof(NRF_CAN_Type, EVENTS_CORE[1]) +#define CAN_INTEN offsetof(NRF_CAN_Type, INTEN) + +struct can_nrf_config { + uint32_t wrapper; + uint32_t mcan; + uint32_t mrba; + uint32_t mram; + const struct device *clock; + const struct pinctrl_dev_config *pcfg; + void (*irq_configure)(void); + uint16_t irq; +}; + +static void can_nrf_irq_handler(const struct device *dev) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_nrf_config *config = mcan_config->custom; + + if (sys_read32(config->wrapper + CAN_EVENTS_CORE_0) == 1U) { + sys_write32(0U, config->wrapper + CAN_EVENTS_CORE_0); + can_mcan_line_0_isr(dev); + } + + if (sys_read32(config->wrapper + CAN_EVENTS_CORE_1) == 1U) { + sys_write32(0U, config->wrapper + CAN_EVENTS_CORE_1); + can_mcan_line_1_isr(dev); + } +} + +static int can_nrf_get_core_clock(const struct device *dev, uint32_t *rate) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_nrf_config *config = mcan_config->custom; + + return clock_control_get_rate(config->clock, NULL, rate); +} + +static const struct can_driver_api can_nrf_api = { + .get_capabilities = can_mcan_get_capabilities, + .start = can_mcan_start, + .stop = can_mcan_stop, + .set_mode = can_mcan_set_mode, + .set_timing = can_mcan_set_timing, + .send = can_mcan_send, + .add_rx_filter = can_mcan_add_rx_filter, + .remove_rx_filter = can_mcan_remove_rx_filter, + .get_state = can_mcan_get_state, +#ifdef CONFIG_CAN_MANUAL_RECOVERY_MODE + .recover = can_mcan_recover, +#endif /* CONFIG_CAN_MANUAL_RECOVERY_MODE */ + .get_core_clock = can_nrf_get_core_clock, + .get_max_filters = can_mcan_get_max_filters, + .set_state_change_callback = can_mcan_set_state_change_callback, + .timing_min = CAN_MCAN_TIMING_MIN_INITIALIZER, + .timing_max = CAN_MCAN_TIMING_MAX_INITIALIZER, +#ifdef CONFIG_CAN_FD_MODE + .set_timing_data = can_mcan_set_timing_data, + .timing_data_min = CAN_MCAN_TIMING_DATA_MIN_INITIALIZER, + .timing_data_max = CAN_MCAN_TIMING_DATA_MAX_INITIALIZER, +#endif /* CONFIG_CAN_FD_MODE */ +}; + +static int can_nrf_read_reg(const struct device *dev, uint16_t reg, uint32_t *val) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_nrf_config *config = mcan_config->custom; + + return can_mcan_sys_read_reg(config->mcan, reg, val); +} + +static int can_nrf_write_reg(const struct device *dev, uint16_t reg, uint32_t val) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_nrf_config *config = mcan_config->custom; + + return can_mcan_sys_write_reg(config->mcan, reg, val); +} + +static int can_nrf_read_mram(const struct device *dev, uint16_t offset, void *dst, size_t len) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_nrf_config *config = mcan_config->custom; + + return can_mcan_sys_read_mram(config->mram, offset, dst, len); +} + +static int can_nrf_write_mram(const struct device *dev, uint16_t offset, const void *src, + size_t len) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_nrf_config *config = mcan_config->custom; + + return can_mcan_sys_write_mram(config->mram, offset, src, len); +} + +static int can_nrf_clear_mram(const struct device *dev, uint16_t offset, size_t len) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_nrf_config *config = mcan_config->custom; + + return can_mcan_sys_clear_mram(config->mram, offset, len); +} + +static const struct can_mcan_ops can_mcan_nrf_ops = { + .read_reg = can_nrf_read_reg, + .write_reg = can_nrf_write_reg, + .read_mram = can_nrf_read_mram, + .write_mram = can_nrf_write_mram, + .clear_mram = can_nrf_clear_mram, +}; + +static int can_nrf_init(const struct device *dev) +{ + const struct can_mcan_config *mcan_config = dev->config; + const struct can_nrf_config *config = mcan_config->custom; + int ret; + + if (!device_is_ready(config->clock)) { + return -ENODEV; + } + + ret = clock_control_on(config->clock, NULL); + if (ret < 0) { + return ret; + } + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + + sys_write32(0U, config->wrapper + CAN_EVENTS_CORE_0); + sys_write32(0U, config->wrapper + CAN_EVENTS_CORE_1); + sys_write32(CAN_INTEN_CORE0_Msk | CAN_INTEN_CORE1_Msk, config->wrapper + CAN_INTEN); + sys_write32(1U, config->wrapper + CAN_TASKS_START); + + config->irq_configure(); + + ret = can_mcan_configure_mram(dev, config->mrba, config->mram); + if (ret < 0) { + return ret; + } + + ret = can_mcan_init(dev); + if (ret < 0) { + return ret; + } + + return 0; +} + +#define CAN_NRF_DEFINE(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static inline void can_nrf_irq_configure##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), can_nrf_irq_handler, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct can_nrf_config can_nrf_config##n = { \ + .wrapper = DT_INST_REG_ADDR_BY_NAME(n, wrapper), \ + .mcan = CAN_MCAN_DT_INST_MCAN_ADDR(n), \ + .mrba = CAN_MCAN_DT_INST_MRBA(n), \ + .mram = CAN_MCAN_DT_INST_MRAM_ADDR(n), \ + .clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .irq = DT_INST_IRQN(n), \ + .irq_configure = can_nrf_irq_configure##n, \ + }; \ + \ + CAN_MCAN_DT_INST_CALLBACKS_DEFINE(n, can_mcan_nrf_cbs##n); \ + \ + static const struct can_mcan_config can_mcan_nrf_config##n = CAN_MCAN_DT_CONFIG_INST_GET( \ + n, &can_nrf_config##n, &can_mcan_nrf_ops, &can_mcan_nrf_cbs##n); \ + \ + static struct can_mcan_data can_mcan_nrf_data##n = CAN_MCAN_DATA_INITIALIZER(NULL); \ + \ + DEVICE_DT_INST_DEFINE(n, can_nrf_init, NULL, &can_mcan_nrf_data##n, \ + &can_mcan_nrf_config##n, POST_KERNEL, CONFIG_CAN_INIT_PRIORITY, \ + &can_nrf_api); + +DT_INST_FOREACH_STATUS_OKAY(CAN_NRF_DEFINE) diff --git a/drivers/can/can_nxp_s32_canxl.c b/drivers/can/can_nxp_s32_canxl.c index 9d1e2626ab010..010f291ce160b 100644 --- a/drivers/can/can_nxp_s32_canxl.c +++ b/drivers/can/can_nxp_s32_canxl.c @@ -43,6 +43,8 @@ #define CAN_NXP_S32_MAX_BITRATE 8000000 #define CAN_NXP_S32_DATA_LENGTH 64 +#define CAN_NXP_S32_TDCO_MAX FIELD_GET(CANXL_SIC_BTDCC_FTDCOFF_MASK, CANXL_SIC_BTDCC_FTDCOFF_MASK) + #ifdef CONFIG_CAN_NXP_S32_RX_FIFO /* RX FIFO depth is fixed to the maximum value */ #define CAN_NXP_S32_RX_FIFO_DEPTH 32 @@ -706,6 +708,9 @@ static int can_nxp_s32_set_timing_data(const struct device *dev, /* Set timing for CAN FD instance*/ CanXL_SetFDBaudRate(config->base_sic, &can_fd_time_segment); + Canexcel_Ip_SetTDCOffsetFD(config->instance, true, false, + CAN_CALC_TDCO((timing_data), 0U, CAN_NXP_S32_TDCO_MAX)); + return 0; } #endif @@ -931,7 +936,7 @@ static int can_nxp_s32_init(const struct device *dev) IP_MC_RGM->PRST_0[0].PRST_0 &= ~(MC_RGM_PRST_0_PERIPH_16_RST_MASK | MC_RGM_PRST_0_PERIPH_24_RST_MASK); - err = can_calc_timing(dev, &data->timing, config->common.bus_speed, + err = can_calc_timing(dev, &data->timing, config->common.bitrate, config->common.sample_point); if (err == -EINVAL) { LOG_ERR("Can't find timing for given param"); @@ -942,11 +947,11 @@ static int can_nxp_s32_init(const struct device *dev) LOG_WRN("Sample-point error : %d", err); } - LOG_DBG("Setting CAN bitrate %d:", config->common.bus_speed); + LOG_DBG("Setting CAN bitrate %d:", config->common.bitrate); nxp_s32_zcan_timing_to_canxl_timing(&data->timing, &config->can_cfg->bitrate); #ifdef CAN_NXP_S32_FD_MODE - err = can_calc_timing_data(dev, &data->timing_data, config->common.bus_speed_data, + err = can_calc_timing_data(dev, &data->timing_data, config->common.bitrate_data, config->common.sample_point_data); if (err == -EINVAL) { LOG_ERR("Can't find timing data for given param"); @@ -957,13 +962,18 @@ static int can_nxp_s32_init(const struct device *dev) LOG_WRN("Sample-point-data err : %d", err); } - LOG_DBG("Setting CAN FD bitrate %d:", config->common.bus_speed_data); + LOG_DBG("Setting CAN FD bitrate %d:", config->common.bitrate_data); nxp_s32_zcan_timing_to_canxl_timing(&data->timing_data, &config->can_cfg->Fd_bitrate); #endif /* Initialize CAN structure */ Canexcel_Ip_Init(config->instance, config->can_cfg, data->can_state); +#ifdef CAN_NXP_S32_FD_MODE + Canexcel_Ip_SetTDCOffsetFD(config->instance, true, false, + CAN_CALC_TDCO((&data->timing_data), 0U, CAN_NXP_S32_TDCO_MAX)); +#endif + /* Configure time stamp */ #ifdef CONFIG_CAN_RX_TIMESTAMP Canexcel_Ip_ConfigTimeStamp(config->instance, &time_stamp); diff --git a/drivers/can/can_rcar.c b/drivers/can/can_rcar.c index d1607a6797a93..23bd82896cbe8 100644 --- a/drivers/can/can_rcar.c +++ b/drivers/can/can_rcar.c @@ -1075,7 +1075,7 @@ static int can_rcar_init(const struct device *dev) return ret; } - ret = can_calc_timing(dev, &timing, config->common.bus_speed, + ret = can_calc_timing(dev, &timing, config->common.bitrate, config->common.sample_point); if (ret == -EINVAL) { LOG_ERR("Can't find timing for given param"); diff --git a/drivers/can/can_shell.c b/drivers/can/can_shell.c index 6c0744879aef0..1eadd6ac0bd0a 100644 --- a/drivers/can/can_shell.c +++ b/drivers/can/can_shell.c @@ -20,6 +20,11 @@ struct can_shell_tx_event { int error; }; +struct can_shell_rx_event { + struct can_frame frame; + const struct device *dev; +}; + struct can_shell_mode_mapping { const char *name; can_mode_t mode; @@ -49,7 +54,8 @@ static struct k_poll_event can_shell_tx_msgq_events[] = { &can_shell_tx_msgq, 0) }; -CAN_MSGQ_DEFINE(can_shell_rx_msgq, CONFIG_CAN_SHELL_RX_QUEUE_SIZE); +K_MSGQ_DEFINE(can_shell_rx_msgq, sizeof(struct can_shell_rx_event), + CONFIG_CAN_SHELL_RX_QUEUE_SIZE, 4); const struct shell *can_shell_rx_msgq_sh; static struct k_work_poll can_shell_rx_msgq_work; static struct k_poll_event can_shell_rx_msgq_events[] = { @@ -62,16 +68,33 @@ static struct k_poll_event can_shell_rx_msgq_events[] = { static void can_shell_tx_msgq_triggered_work_handler(struct k_work *work); static void can_shell_rx_msgq_triggered_work_handler(struct k_work *work); -static void can_shell_print_frame(const struct shell *sh, const struct can_frame *frame) +#ifdef CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY +static void can_shell_dummy_bypass_cb(const struct shell *sh, uint8_t *data, size_t len) +{ + ARG_UNUSED(sh); + ARG_UNUSED(data); + ARG_UNUSED(len); +} +#endif /* CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY */ + +static void can_shell_print_frame(const struct shell *sh, const struct device *dev, + const struct can_frame *frame) { uint8_t nbytes = can_dlc_to_bytes(frame->dlc); int i; +#ifdef CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY + /* Bypass the shell to avoid breaking up the line containing the frame */ + shell_set_bypass(sh, can_shell_dummy_bypass_cb); +#endif /* CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY */ + #ifdef CONFIG_CAN_RX_TIMESTAMP /* Timestamp */ shell_fprintf(sh, SHELL_NORMAL, "(%05d) ", frame->timestamp); #endif /* CONFIG_CAN_RX_TIMESTAMP */ + shell_fprintf(sh, SHELL_NORMAL, "%s ", dev->name); + #ifdef CONFIG_CAN_FD_MODE /* Flags */ shell_fprintf(sh, SHELL_NORMAL, "%c%c ", @@ -102,6 +125,10 @@ static void can_shell_print_frame(const struct shell *sh, const struct can_frame } shell_fprintf(sh, SHELL_NORMAL, "\n"); + +#ifdef CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY + shell_set_bypass(sh, NULL); +#endif /* CONFIG_CAN_SHELL_SCRIPTING_FRIENDLY */ } static int can_shell_tx_msgq_poll_submit(const struct shell *sh) @@ -156,6 +183,23 @@ static void can_shell_tx_callback(const struct device *dev, int error, void *use } } +static void can_shell_rx_callback(const struct device *dev, struct can_frame *frame, + void *user_data) +{ + struct can_shell_rx_event event; + int err; + + ARG_UNUSED(user_data); + + event.frame = *frame; + event.dev = dev; + + err = k_msgq_put(&can_shell_rx_msgq, &event, K_NO_WAIT); + if (err != 0) { + LOG_ERR("CAN shell rx event queue full"); + } +} + static int can_shell_rx_msgq_poll_submit(const struct shell *sh) { int err; @@ -177,10 +221,10 @@ static int can_shell_rx_msgq_poll_submit(const struct shell *sh) static void can_shell_rx_msgq_triggered_work_handler(struct k_work *work) { - struct can_frame frame; + struct can_shell_rx_event event; - while (k_msgq_get(&can_shell_rx_msgq, &frame, K_NO_WAIT) == 0) { - can_shell_print_frame(can_shell_rx_msgq_sh, &frame); + while (k_msgq_get(&can_shell_rx_msgq, &event, K_NO_WAIT) == 0) { + can_shell_print_frame(can_shell_rx_msgq_sh, event.dev, &event.frame); } (void)can_shell_rx_msgq_poll_submit(can_shell_rx_msgq_sh); @@ -674,7 +718,7 @@ static int cmd_can_send(const struct shell *sh, size_t argc, char **argv) const struct device *dev = device_get_binding(argv[1]); static unsigned int frame_counter; unsigned int frame_no; - struct can_frame frame; + struct can_frame frame = { 0 }; uint32_t id_mask; int argidx = 2; uint32_t val; @@ -779,7 +823,7 @@ static int cmd_can_send(const struct shell *sh, size_t argc, char **argv) (frame.flags & CAN_FRAME_RTR) != 0 ? 1 : 0, (frame.flags & CAN_FRAME_FDF) != 0 ? 1 : 0, (frame.flags & CAN_FRAME_BRS) != 0 ? 1 : 0, - can_dlc_to_bytes(frame.dlc)); + frame.dlc); err = can_send(dev, &frame, K_NO_WAIT, can_shell_tx_callback, UINT_TO_POINTER(frame_no)); if (err != 0) { @@ -879,7 +923,7 @@ static int cmd_can_filter_add(const struct shell *sh, size_t argc, char **argv) (filter.flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter.id, (filter.flags & CAN_FILTER_IDE) != 0 ? 8 : 3, filter.mask); - err = can_add_rx_filter_msgq(dev, &can_shell_rx_msgq, &filter); + err = can_add_rx_filter(dev, can_shell_rx_callback, NULL, &filter); if (err < 0) { shell_error(sh, "failed to add filter (err %d)", err); return err; diff --git a/drivers/can/can_sja1000.c b/drivers/can/can_sja1000.c index 871f0fdb00ddd..758715bb44303 100644 --- a/drivers/can/can_sja1000.c +++ b/drivers/can/can_sja1000.c @@ -781,7 +781,7 @@ int can_sja1000_init(const struct device *dev) can_sja1000_write_reg(dev, CAN_SJA1000_AMR2, 0xFF); can_sja1000_write_reg(dev, CAN_SJA1000_AMR3, 0xFF); - err = can_calc_timing(dev, &timing, config->common.bus_speed, + err = can_calc_timing(dev, &timing, config->common.bitrate, config->common.sample_point); if (err == -EINVAL) { LOG_ERR("bitrate/sample point cannot be met (err %d)", err); diff --git a/drivers/can/can_stm32_bxcan.c b/drivers/can/can_stm32_bxcan.c index c21099c04b3a0..5c3e44dfd0c3c 100644 --- a/drivers/can/can_stm32_bxcan.c +++ b/drivers/can/can_stm32_bxcan.c @@ -659,7 +659,7 @@ static int can_stm32_init(const struct device *dev) /* Enable automatic bus-off recovery */ can->MCR |= CAN_MCR_ABOM; - ret = can_calc_timing(dev, &timing, cfg->common.bus_speed, + ret = can_calc_timing(dev, &timing, cfg->common.bitrate, cfg->common.sample_point); if (ret == -EINVAL) { LOG_ERR("Can't find timing for given param"); diff --git a/drivers/can/can_xmc4xxx.c b/drivers/can/can_xmc4xxx.c index 8eddf05b96ea9..2704ef1b44edb 100644 --- a/drivers/can/can_xmc4xxx.c +++ b/drivers/can/can_xmc4xxx.c @@ -869,7 +869,7 @@ static int can_xmc4xxx_init(const struct device *dev) } #endif - ret = can_calc_timing(dev, &timing, dev_cfg->common.bus_speed, + ret = can_calc_timing(dev, &timing, dev_cfg->common.bitrate, dev_cfg->common.sample_point); if (ret < 0) { return ret; diff --git a/drivers/can/transceiver/can_transceiver_gpio.c b/drivers/can/transceiver/can_transceiver_gpio.c index e6aaacc8c34eb..3f7bbca688f07 100644 --- a/drivers/can/transceiver/can_transceiver_gpio.c +++ b/drivers/can/transceiver/can_transceiver_gpio.c @@ -120,6 +120,11 @@ static const struct can_transceiver_driver_api can_transceiver_gpio_driver_api = (.name##_gpio = GPIO_DT_SPEC_INST_GET(inst, name##_gpios),)) #define CAN_TRANSCEIVER_GPIO_INIT(inst) \ + BUILD_ASSERT(DT_INST_NODE_HAS_PROP(inst, enable_gpios) || \ + DT_INST_NODE_HAS_PROP(inst, standby_gpios), \ + "Missing GPIO property on " \ + DT_NODE_FULL_NAME(DT_DRV_INST(inst))); \ + \ static const struct can_transceiver_gpio_config can_transceiver_gpio_config_##inst = { \ CAN_TRANSCEIVER_GPIO_COND(inst, enable) \ CAN_TRANSCEIVER_GPIO_COND(inst, standby) \ diff --git a/drivers/charger/charger_handlers.c b/drivers/charger/charger_handlers.c index 4fdf6ca7140e5..44042b3fdd916 100644 --- a/drivers/charger/charger_handlers.c +++ b/drivers/charger/charger_handlers.c @@ -21,7 +21,7 @@ static inline int z_vrfy_charger_get_prop(const struct device *dev, const charge return ret; } -#include +#include static inline int z_vrfy_charger_set_prop(const struct device *dev, const charger_prop_t prop, const union charger_propval *val) @@ -35,7 +35,7 @@ static inline int z_vrfy_charger_set_prop(const struct device *dev, const charge return z_impl_charger_set_prop(dev, prop, &k_val); } -#include +#include static inline int z_vrfy_charger_charge_enable(const struct device *dev, const bool enable) { @@ -44,4 +44,4 @@ static inline int z_vrfy_charger_charge_enable(const struct device *dev, const b return z_impl_charger_charge_enable(dev, enable); } -#include +#include diff --git a/drivers/clock_control/CMakeLists.txt b/drivers/clock_control/CMakeLists.txt index 596b07676e035..43f86e8c7d38c 100644 --- a/drivers/clock_control/CMakeLists.txt +++ b/drivers/clock_control/CMakeLists.txt @@ -38,6 +38,8 @@ if(CONFIG_SOC_SERIES_STM32MP1X) zephyr_library_sources(clock_stm32_ll_mp1.c) elseif(CONFIG_SOC_SERIES_STM32H7X) zephyr_library_sources(clock_stm32_ll_h7.c) +elseif(CONFIG_SOC_SERIES_STM32H7RSX) + zephyr_library_sources(clock_stm32_ll_h7.c) elseif(CONFIG_SOC_SERIES_STM32H5X) zephyr_library_sources(clock_stm32_ll_h5.c) elseif(CONFIG_SOC_SERIES_STM32U5X) @@ -76,3 +78,5 @@ if(CONFIG_CLOCK_CONTROL_RCAR_CPG_MSSR) endif() zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_AST10X0 clock_control_ast10x0.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_MAX32 clock_control_max32.c) +zephyr_library_sources_ifdef(CONFIG_CLOCK_CONTROL_NRF_AUXPLL clock_control_nrf_auxpll.c) diff --git a/drivers/clock_control/Kconfig b/drivers/clock_control/Kconfig index b0c6cf8de48c7..558210560479f 100644 --- a/drivers/clock_control/Kconfig +++ b/drivers/clock_control/Kconfig @@ -82,10 +82,14 @@ source "drivers/clock_control/Kconfig.agilex5" source "drivers/clock_control/Kconfig.renesas_ra" +source "drivers/clock_control/Kconfig.max32" + source "drivers/clock_control/Kconfig.ambiq" source "drivers/clock_control/Kconfig.pwm" source "drivers/clock_control/Kconfig.rpi_pico" +source "drivers/clock_control/Kconfig.nrf_auxpll" + endif # CLOCK_CONTROL diff --git a/drivers/clock_control/Kconfig.max32 b/drivers/clock_control/Kconfig.max32 new file mode 100644 index 0000000000000..30f8d9fda7a34 --- /dev/null +++ b/drivers/clock_control/Kconfig.max32 @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_MAX32 + bool "MAX32 Clock Control Driver" + default y + depends on DT_HAS_ADI_MAX32_GCR_ENABLED + help + Enable clock control support for Analog Devices MAX32xxx/MAX78xxx SoC series. diff --git a/drivers/clock_control/Kconfig.nrf b/drivers/clock_control/Kconfig.nrf index 725a76949869f..37e09ce21a998 100644 --- a/drivers/clock_control/Kconfig.nrf +++ b/drivers/clock_control/Kconfig.nrf @@ -132,7 +132,7 @@ choice CLOCK_CONTROL_NRF_ACCURACY_PPM prompt "32KHz clock accuracy" default CLOCK_CONTROL_NRF_K32SRC_500PPM if CLOCK_CONTROL_NRF_K32SRC_RC && SOC_COMPATIBLE_NRF52X default CLOCK_CONTROL_NRF_K32SRC_250PPM if CLOCK_CONTROL_NRF_K32SRC_RC - default CLOCK_CONTROL_NRF_K32SRC_150PPM if CLOCK_CONTROL_NRF_K32SRC_XTAL && SOC_SERIES_NRF54LX + default CLOCK_CONTROL_NRF_K32SRC_150PPM if CLOCK_CONTROL_NRF_K32SRC_XTAL && SOC_COMPATIBLE_NRF54LX default CLOCK_CONTROL_NRF_K32SRC_50PPM config CLOCK_CONTROL_NRF_K32SRC_500PPM diff --git a/drivers/clock_control/Kconfig.nrf_auxpll b/drivers/clock_control/Kconfig.nrf_auxpll new file mode 100644 index 0000000000000..413452c1ac49a --- /dev/null +++ b/drivers/clock_control/Kconfig.nrf_auxpll @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config CLOCK_CONTROL_NRF_AUXPLL + bool "nRF Auxiliary PLL driver" + default y + depends on DT_HAS_NORDIC_NRF_AUXPLL_ENABLED + help + Driver for nRF Auxiliary PLL. diff --git a/drivers/clock_control/Kconfig.smartbond b/drivers/clock_control/Kconfig.smartbond index d20907c60018c..49ac7c7c660fa 100644 --- a/drivers/clock_control/Kconfig.smartbond +++ b/drivers/clock_control/Kconfig.smartbond @@ -8,3 +8,14 @@ config CLOCK_CONTROL_SMARTBOND depends on SOC_FAMILY_RENESAS_SMARTBOND help Enable driver for Clock Control subsystem found in SmartBond + +if CLOCK_CONTROL_SMARTBOND + +config SMARTBOND_LP_OSC_CALIBRATION_INTERVAL + int "Low-power oscillators calibration interval" + default 1 + range 1 10 + help + Time in seconds between calibration of low power clock RC32K and RCX. + +endif # CLOCK_CONTROL_SMARTBOND diff --git a/drivers/clock_control/Kconfig.stm32 b/drivers/clock_control/Kconfig.stm32 index c5f4f27364622..484b331db7c24 100644 --- a/drivers/clock_control/Kconfig.stm32 +++ b/drivers/clock_control/Kconfig.stm32 @@ -9,7 +9,7 @@ menuconfig CLOCK_CONTROL_STM32_CUBE depends on SOC_FAMILY_STM32 select USE_STM32_LL_UTILS select USE_STM32_LL_RCC if (SOC_SERIES_STM32MP1X || SOC_SERIES_STM32H7X || \ - SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X) + SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X) select RUNTIME_NMI if ($(dt_nodelabel_enabled,clk_hse) && \ $(dt_nodelabel_has_prop,clk_hse,css-enabled)) help @@ -69,6 +69,7 @@ config CLOCK_STM32_MCO1_SRC_LSE SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use LSE as source of MCO1 @@ -80,6 +81,7 @@ config CLOCK_STM32_MCO1_SRC_HSE SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSE as source of MCO1 @@ -102,6 +104,7 @@ config CLOCK_STM32_MCO1_SRC_HSI SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSI as source of MCO1 @@ -116,6 +119,7 @@ config CLOCK_STM32_MCO1_SRC_HSI48 bool "HSI48" depends on SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSI48 as source of MCO1 @@ -129,6 +133,7 @@ config CLOCK_STM32_MCO1_SRC_PLLCLK config CLOCK_STM32_MCO1_SRC_PLLQCLK bool "PLLQ" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use PLLQ as source of MCO1 @@ -171,11 +176,12 @@ config CLOCK_STM32_MCO1_DIV SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32L4X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X \ ) default 1 range 1 5 if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X - range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X + range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32H5X range 1 16 if SOC_SERIES_STM32L4X help Prescaler for MCO1 output clock @@ -194,6 +200,7 @@ config CLOCK_STM32_MCO2_SRC_SYSCLK depends on SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use SYSCLK as source of MCO2 @@ -209,6 +216,7 @@ config CLOCK_STM32_MCO2_SRC_HSE depends on SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use HSE as source of MCO2 @@ -216,6 +224,7 @@ config CLOCK_STM32_MCO2_SRC_HSE config CLOCK_STM32_MCO2_SRC_LSI bool "LSI" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use LSI as source of MCO2 @@ -223,6 +232,7 @@ config CLOCK_STM32_MCO2_SRC_LSI config CLOCK_STM32_MCO2_SRC_CSI bool "CSI" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use CSI as source of MCO2 @@ -236,6 +246,7 @@ config CLOCK_STM32_MCO2_SRC_PLLCLK config CLOCK_STM32_MCO2_SRC_PLLPCLK bool "PLLPCLK" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use PLLPCLK as source of MC02 @@ -243,6 +254,7 @@ config CLOCK_STM32_MCO2_SRC_PLLPCLK config CLOCK_STM32_MCO2_SRC_PLL2PCLK bool "PLL2PCLK" depends on SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX || \ SOC_SERIES_STM32H5X help Use PLL2PCLK as source of MC02 @@ -254,11 +266,12 @@ config CLOCK_STM32_MCO2_DIV SOC_SERIES_STM32F4X || \ SOC_SERIES_STM32F7X || \ SOC_SERIES_STM32H5X || \ - SOC_SERIES_STM32H7X \ + SOC_SERIES_STM32H7X || \ + SOC_SERIES_STM32H7RSX \ ) default 1 range 1 5 if SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X - range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X + range 1 15 if SOC_SERIES_STM32H7X || SOC_SERIES_STM32H7RSX || SOC_SERIES_STM32H5X help Prescaler for MCO2 output clock diff --git a/drivers/clock_control/clock_control_esp32.c b/drivers/clock_control/clock_control_esp32.c index 7aec123785d35..02cf64d52b5a9 100644 --- a/drivers/clock_control/clock_control_esp32.c +++ b/drivers/clock_control/clock_control_esp32.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2020 Mohamed ElShahawi. - * Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd. + * Copyright (c) 2021-2024 Espressif Systems (Shanghai) Co., Ltd. * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,19 +10,21 @@ #define CPU_RESET_REASON RTC_SW_CPU_RESET #if defined(CONFIG_SOC_SERIES_ESP32) -#define DT_CPU_COMPAT cdns_tensilica_xtensa_lx6 +#define DT_CPU_COMPAT espressif_xtensa_lx6 #undef CPU_RESET_REASON #define CPU_RESET_REASON SW_CPU_RESET #include #include #include +#include #elif defined(CONFIG_SOC_SERIES_ESP32S2) -#define DT_CPU_COMPAT cdns_tensilica_xtensa_lx7 +#define DT_CPU_COMPAT espressif_xtensa_lx7 #include #include #include +#include #elif defined(CONFIG_SOC_SERIES_ESP32S3) -#define DT_CPU_COMPAT cdns_tensilica_xtensa_lx7 +#define DT_CPU_COMPAT espressif_xtensa_lx7 #include #include #include @@ -30,122 +32,157 @@ #define DT_CPU_COMPAT espressif_riscv #include #include -#include -#include -#include +#elif CONFIG_SOC_SERIES_ESP32C6 +#define DT_CPU_COMPAT espressif_riscv +#include +#include +#include +#include +#include +#include +#include #endif /* CONFIG_SOC_SERIES_ESP32xx */ +#include +#include + #include #include #include +#include #include -#include -#include -#include #include -#include -#include #include #include #include -#include +#include +#include +#include -struct esp32_clock_config { - int clk_src_sel; - uint32_t cpu_freq; - uint32_t xtal_freq_sel; - int xtal_div; -}; +#include +LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL); -static int clock_control_esp32_on(const struct device *dev, - clock_control_subsys_t sys) +static bool reset_reason_is_cpu_reset(void) { - ARG_UNUSED(dev); - periph_module_enable((periph_module_t)sys); - return 0; -} - -static int clock_control_esp32_off(const struct device *dev, - clock_control_subsys_t sys) -{ - ARG_UNUSED(dev); - periph_module_disable((periph_module_t)sys); - return 0; -} - -static int clock_control_esp32_async_on(const struct device *dev, - clock_control_subsys_t sys, - clock_control_cb_t cb, - void *user_data) -{ - ARG_UNUSED(dev); - ARG_UNUSED(sys); - ARG_UNUSED(cb); - ARG_UNUSED(user_data); - return -ENOTSUP; -} - -static enum clock_control_status clock_control_esp32_get_status(const struct device *dev, - clock_control_subsys_t sys) -{ - ARG_UNUSED(dev); - uint32_t clk_en_reg = periph_ll_get_clk_en_reg((periph_module_t)sys); - uint32_t clk_en_mask = periph_ll_get_clk_en_mask((periph_module_t)sys); + soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); - if (DPORT_GET_PERI_REG_MASK(clk_en_reg, clk_en_mask)) { - return CLOCK_CONTROL_STATUS_ON; + if ((rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW || + rst_reason == RESET_REASON_CPU0_RTC_WDT +#if !defined(CONFIG_SOC_SERIES_ESP32) + || rst_reason == RESET_REASON_CPU0_MWDT1 +#endif + )) { + return true; } - return CLOCK_CONTROL_STATUS_OFF; + return false; } -static int clock_control_esp32_get_rate(const struct device *dev, - clock_control_subsys_t sub_system, - uint32_t *rate) +#if defined(CONFIG_SOC_SERIES_ESP32C6) +static void esp32_clock_perip_init(void) { - ARG_UNUSED(sub_system); - - rtc_cpu_freq_config_t config; - - rtc_clk_cpu_freq_get_config(&config); - - *rate = config.freq_mhz; + soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); - return 0; + if ((rst_reason != RESET_REASON_CPU0_MWDT0) && (rst_reason != RESET_REASON_CPU0_MWDT1) && + (rst_reason != RESET_REASON_CPU0_SW) && (rst_reason != RESET_REASON_CPU0_RTC_WDT)) { + + periph_ll_disable_clk_set_rst(PERIPH_UART1_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_I2C0_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_RMT_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_LEDC_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_TIMG1_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_TWAI0_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_TWAI1_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_I2S1_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_PCNT_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_ETM_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_MCPWM0_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_PARLIO_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_GDMA_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_SPI2_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_TEMPSENSOR_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_UHCI0_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_SARADC_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_SDIO_SLAVE_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_RSA_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_AES_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_SHA_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_ECC_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_HMAC_MODULE); + periph_ll_disable_clk_set_rst(PERIPH_DS_MODULE); + + REG_CLR_BIT(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE); + REG_CLR_BIT(PCR_TRACE_CONF_REG, PCR_TRACE_CLK_EN); + REG_CLR_BIT(PCR_RETENTION_CONF_REG, PCR_RETENTION_CLK_EN); + REG_CLR_BIT(PCR_MEM_MONITOR_CONF_REG, PCR_MEM_MONITOR_CLK_EN); + REG_CLR_BIT(PCR_PVT_MONITOR_CONF_REG, PCR_PVT_MONITOR_CLK_EN); + REG_CLR_BIT(PCR_PVT_MONITOR_FUNC_CLK_CONF_REG, PCR_PVT_MONITOR_FUNC_CLK_EN); + WRITE_PERI_REG(PCR_CTRL_CLK_OUT_EN_REG, 0); + } } - -#if defined(CONFIG_SOC_SERIES_ESP32) +#else static void esp32_clock_perip_init(void) { uint32_t common_perip_clk; uint32_t hwcrypto_perip_clk; uint32_t wifi_bt_sdio_clk; - -#if !CONFIG_SMP - soc_reset_reason_t rst_reas[1]; -#else - soc_reset_reason_t rst_reas[2]; -#endif - - rst_reas[0] = esp_rom_get_reset_reason(0); -#if CONFIG_SMP - rst_reas[1] = esp_rom_get_reset_reason(1); +#if !defined(CONFIG_SOC_SERIES_ESP32) + uint32_t common_perip_clk1; #endif /* For reason that only reset CPU, do not disable the clocks * that have been enabled before reset. */ - if ((rst_reas[0] == RESET_REASON_CPU0_MWDT0 || rst_reas[0] == RESET_REASON_CPU0_SW || - rst_reas[0] == RESET_REASON_CPU0_RTC_WDT) -#if CONFIG_SMP - || (rst_reas[1] == RESET_REASON_CPU1_MWDT1 || rst_reas[1] == RESET_REASON_CPU1_SW || - rst_reas[1] == RESET_REASON_CPU1_RTC_WDT) -#endif - ) { + if (reset_reason_is_cpu_reset()) { +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) + common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG); + hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG); + wifi_bt_sdio_clk = ~READ_PERI_REG(SYSTEM_WIFI_CLK_EN_REG); +#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */ common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG); hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERI_CLK_EN_REG); wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG); +#endif + +#if defined(CONFIG_SOC_SERIES_ESP32S2) + hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN1_REG); +#endif } else { - common_perip_clk = DPORT_WDG_CLK_EN | + common_perip_clk = +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) + SYSTEM_WDG_CLK_EN | + SYSTEM_I2S0_CLK_EN | +#if ESP_CONSOLE_UART_NUM != 0 + SYSTEM_UART_CLK_EN | +#endif +#if ESP_CONSOLE_UART_NUM != 1 + SYSTEM_UART1_CLK_EN | +#endif +#if defined(CONFIG_SOC_SERIES_ESP32S3) +#if ESP_CONSOLE_UART_NUM != 2 + SYSTEM_UART2_CLK_EN | +#endif + SYSTEM_USB_CLK_EN | + SYSTEM_PCNT_CLK_EN | + SYSTEM_LEDC_CLK_EN | + SYSTEM_PWM0_CLK_EN | + SYSTEM_PWM1_CLK_EN | + SYSTEM_PWM2_CLK_EN | + SYSTEM_PWM3_CLK_EN | +#endif /* CONFIG_SOC_SERIES_ESP32S3 */ + SYSTEM_SPI2_CLK_EN | + SYSTEM_I2C_EXT0_CLK_EN | + SYSTEM_UHCI0_CLK_EN | + SYSTEM_RMT_CLK_EN | + SYSTEM_LEDC_CLK_EN | + SYSTEM_TIMERGROUP1_CLK_EN | + SYSTEM_SPI3_CLK_EN | + SYSTEM_SPI4_CLK_EN | + SYSTEM_TWAI_CLK_EN | + SYSTEM_I2S1_CLK_EN | + SYSTEM_SPI2_DMA_CLK_EN | + SYSTEM_SPI3_DMA_CLK_EN; +#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */ + DPORT_WDG_CLK_EN | DPORT_PCNT_CLK_EN | DPORT_LEDC_CLK_EN | DPORT_TIMERGROUP1_CLK_EN | @@ -153,228 +190,77 @@ static void esp32_clock_perip_init(void) DPORT_TWAI_CLK_EN | DPORT_PWM1_CLK_EN | DPORT_PWM2_CLK_EN | - DPORT_PWM3_CLK_EN; - - hwcrypto_perip_clk = DPORT_PERI_EN_AES | - DPORT_PERI_EN_SHA | - DPORT_PERI_EN_RSA | - DPORT_PERI_EN_SECUREBOOT; - - wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN | - DPORT_WIFI_CLK_BT_EN_M | - DPORT_WIFI_CLK_UNUSED_BIT5 | - DPORT_WIFI_CLK_UNUSED_BIT12 | - DPORT_WIFI_CLK_SDIOSLAVE_EN | - DPORT_WIFI_CLK_SDIO_HOST_EN | - DPORT_WIFI_CLK_EMAC_EN; - } - - /* Reset peripherals like I2C, SPI, UART, I2S and bring them to known state */ - common_perip_clk |= DPORT_I2S0_CLK_EN | - DPORT_UART_CLK_EN | - DPORT_SPI2_CLK_EN | - DPORT_I2C_EXT0_CLK_EN | - DPORT_UHCI0_CLK_EN | - DPORT_RMT_CLK_EN | - DPORT_UHCI1_CLK_EN | - DPORT_SPI3_CLK_EN | - DPORT_I2C_EXT1_CLK_EN | - DPORT_I2S1_CLK_EN | - DPORT_SPI_DMA_CLK_EN; - - common_perip_clk &= ~DPORT_SPI01_CLK_EN; - common_perip_clk &= ~DPORT_SPI2_CLK_EN; - common_perip_clk &= ~DPORT_SPI3_CLK_EN; - - /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock, - * the current is not reduced when disable I2S clock. - */ - DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(0), I2S_CLKA_ENA); - DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(1), I2S_CLKA_ENA); - - /* Disable some peripheral clocks. */ - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk); - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk); - - /* Disable hardware crypto clocks. */ - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERI_CLK_EN_REG, hwcrypto_perip_clk); - DPORT_SET_PERI_REG_MASK(DPORT_PERI_RST_EN_REG, hwcrypto_perip_clk); - - /* Disable WiFi/BT/SDIO clocks. */ - DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk); - - /* Enable RNG clock. */ - periph_module_enable(PERIPH_RNG_MODULE); -} -#endif /* CONFIG_SOC_SERIES_ESP32 */ - #if defined(CONFIG_SOC_SERIES_ESP32S2) -static void esp32_clock_perip_init(void) -{ - uint32_t common_perip_clk; - uint32_t hwcrypto_perip_clk; - uint32_t wifi_bt_sdio_clk; - uint32_t common_perip_clk1; - - soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); - - /* For reason that only reset CPU, do not disable the clocks - * that have been enabled before reset. - */ - if (rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW || - rst_reason == RESET_REASON_CPU0_RTC_WDT || rst_reason == RESET_REASON_CPU0_MWDT1) { - common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG); - hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN1_REG); - wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG); - } else { - common_perip_clk = DPORT_WDG_CLK_EN | DPORT_I2S0_CLK_EN | - DPORT_UART1_CLK_EN | DPORT_SPI2_CLK_EN | DPORT_I2C_EXT0_CLK_EN | DPORT_UHCI0_CLK_EN | DPORT_RMT_CLK_EN | - DPORT_PCNT_CLK_EN | - DPORT_LEDC_CLK_EN | - DPORT_TIMERGROUP1_CLK_EN | DPORT_SPI3_CLK_EN | - DPORT_PWM0_CLK_EN | - DPORT_TWAI_CLK_EN | - DPORT_PWM1_CLK_EN | DPORT_I2S1_CLK_EN | DPORT_SPI2_DMA_CLK_EN | DPORT_SPI3_DMA_CLK_EN | - DPORT_PWM2_CLK_EN | +#endif /* CONFIG_SOC_SERIES_ESP32S2 */ DPORT_PWM3_CLK_EN; +#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */ +#if !defined(CONFIG_SOC_SERIES_ESP32) common_perip_clk1 = 0; - - hwcrypto_perip_clk = DPORT_CRYPTO_AES_CLK_EN | - DPORT_CRYPTO_SHA_CLK_EN | - DPORT_CRYPTO_RSA_CLK_EN; - - wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN | +#endif + hwcrypto_perip_clk = +#if defined(CONFIG_SOC_SERIES_ESP32) + DPORT_PERI_EN_AES | + DPORT_PERI_EN_SHA | + DPORT_PERI_EN_RSA | + DPORT_PERI_EN_SECUREBOOT; +#endif /* CONFIG_SOC_SERIES_ESP32 */ +#if defined(CONFIG_SOC_SERIES_ESP32S2) + DPORT_CRYPTO_AES_CLK_EN | + DPORT_CRYPTO_SHA_CLK_EN | + DPORT_CRYPTO_RSA_CLK_EN; +#endif /* CONFIG_SOC_SERIES_ESP32S2 */ +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) + SYSTEM_CRYPTO_AES_CLK_EN | + SYSTEM_CRYPTO_SHA_CLK_EN | + SYSTEM_CRYPTO_RSA_CLK_EN; +#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */ + + wifi_bt_sdio_clk = +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) + SYSTEM_WIFI_CLK_WIFI_EN | + SYSTEM_WIFI_CLK_BT_EN_M | + SYSTEM_WIFI_CLK_I2C_CLK_EN | +#if defined(CONFIG_SOC_SERIES_ESP32S3) + SYSTEM_WIFI_CLK_SDIO_HOST_EN | +#endif /* CONFIG_SOC_SERIES_ESP32S3 */ + SYSTEM_WIFI_CLK_UNUSED_BIT12; +#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */ + DPORT_WIFI_CLK_WIFI_EN | DPORT_WIFI_CLK_BT_EN_M | DPORT_WIFI_CLK_UNUSED_BIT5 | DPORT_WIFI_CLK_UNUSED_BIT12 | DPORT_WIFI_CLK_SDIOSLAVE_EN | DPORT_WIFI_CLK_SDIO_HOST_EN | DPORT_WIFI_CLK_EMAC_EN; +#endif /* CONFIG_SOC_SERIES_ESP32C3 */ } /* Reset peripherals like I2C, SPI, UART, I2S and bring them to known state */ - common_perip_clk |= DPORT_I2S0_CLK_EN | - DPORT_UART1_CLK_EN | - DPORT_USB_CLK_EN | - DPORT_SPI2_CLK_EN | - DPORT_I2C_EXT0_CLK_EN | - DPORT_UHCI0_CLK_EN | - DPORT_RMT_CLK_EN | - DPORT_UHCI1_CLK_EN | - DPORT_SPI3_CLK_EN | - DPORT_I2C_EXT1_CLK_EN | - DPORT_I2S1_CLK_EN | - DPORT_SPI2_DMA_CLK_EN | - DPORT_SPI3_DMA_CLK_EN; - - common_perip_clk1 = 0; - - /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock, - * the current is not reduced when disable I2S clock. - */ - REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); - REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); - - /* Disable some peripheral clocks. */ - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk); - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk); - - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, common_perip_clk1); - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, common_perip_clk1); - - /* Disable hardware crypto clocks. */ - DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, hwcrypto_perip_clk); - DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, hwcrypto_perip_clk); - - /* Disable WiFi/BT/SDIO clocks. */ - DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk); - - /* Enable WiFi MAC and POWER clocks */ - DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_WIFI_EN); - - /* Set WiFi light sleep clock source to RTC slow clock */ - DPORT_REG_SET_FIELD(DPORT_BT_LPCK_DIV_INT_REG, DPORT_BT_LPCK_DIV_NUM, 0); - DPORT_CLEAR_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_8M); - DPORT_SET_PERI_REG_MASK(DPORT_BT_LPCK_DIV_FRAC_REG, DPORT_LPCLK_SEL_RTC_SLOW); - - /* Enable RNG clock. */ - periph_module_enable(PERIPH_RNG_MODULE); -} -#endif /* CONFIG_SOC_SERIES_ESP32S2 */ - -#if defined(CONFIG_SOC_SERIES_ESP32S3) -static void esp32_clock_perip_init(void) -{ -#if defined(CONFIG_SOC_ESP32S3_APPCPU) - /* skip APPCPU configuration */ - return; -#endif - - uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; - uint32_t common_perip_clk1 = 0; - - soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); - - /* For reason that only reset CPU, do not disable the clocks - * that have been enabled before reset. - */ - if (rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW || - rst_reason == RESET_REASON_CPU0_RTC_WDT || rst_reason == RESET_REASON_CPU0_MWDT1) { - common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG); - hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG); - wifi_bt_sdio_clk = ~READ_PERI_REG(SYSTEM_WIFI_CLK_EN_REG); - } else { - common_perip_clk = SYSTEM_WDG_CLK_EN | + common_perip_clk |= +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) SYSTEM_I2S0_CLK_EN | +#if ESP_CONSOLE_UART_NUM != 0 + SYSTEM_UART_CLK_EN | +#endif +#if ESP_CONSOLE_UART_NUM != 1 SYSTEM_UART1_CLK_EN | +#endif +#if defined(CONFIG_SOC_SERIES_ESP32S3) +#if ESP_CONSOLE_UART_NUM != 2 SYSTEM_UART2_CLK_EN | +#endif SYSTEM_USB_CLK_EN | - SYSTEM_SPI2_CLK_EN | - SYSTEM_I2C_EXT0_CLK_EN | - SYSTEM_UHCI0_CLK_EN | - SYSTEM_RMT_CLK_EN | - SYSTEM_PCNT_CLK_EN | - SYSTEM_LEDC_CLK_EN | - SYSTEM_TIMERGROUP1_CLK_EN | - SYSTEM_SPI3_CLK_EN | - SYSTEM_SPI4_CLK_EN | - SYSTEM_PWM0_CLK_EN | - SYSTEM_TWAI_CLK_EN | - SYSTEM_PWM1_CLK_EN | - SYSTEM_I2S1_CLK_EN | - SYSTEM_SPI2_DMA_CLK_EN | - SYSTEM_SPI3_DMA_CLK_EN | - SYSTEM_PWM2_CLK_EN | - SYSTEM_PWM3_CLK_EN; - - common_perip_clk1 = 0; - - hwcrypto_perip_clk = SYSTEM_CRYPTO_AES_CLK_EN | - SYSTEM_CRYPTO_SHA_CLK_EN | - SYSTEM_CRYPTO_RSA_CLK_EN; - - wifi_bt_sdio_clk = SYSTEM_WIFI_CLK_WIFI_EN | - SYSTEM_WIFI_CLK_BT_EN_M | - SYSTEM_WIFI_CLK_I2C_CLK_EN | - SYSTEM_WIFI_CLK_UNUSED_BIT12 | - SYSTEM_WIFI_CLK_SDIO_HOST_EN; - } - - /* Reset peripherals like I2C, SPI, UART, I2S and bring them to known state */ - common_perip_clk |= SYSTEM_I2S0_CLK_EN | - SYSTEM_UART1_CLK_EN | - SYSTEM_UART2_CLK_EN | - SYSTEM_USB_CLK_EN | +#endif SYSTEM_SPI2_CLK_EN | SYSTEM_I2C_EXT0_CLK_EN | SYSTEM_UHCI0_CLK_EN | @@ -386,214 +272,427 @@ static void esp32_clock_perip_init(void) SYSTEM_I2S1_CLK_EN | SYSTEM_SPI2_DMA_CLK_EN | SYSTEM_SPI3_DMA_CLK_EN; +#else + DPORT_I2S0_CLK_EN | + DPORT_SPI2_CLK_EN | + DPORT_I2C_EXT0_CLK_EN | + DPORT_UHCI0_CLK_EN | + DPORT_RMT_CLK_EN | + DPORT_UHCI1_CLK_EN | + DPORT_SPI3_CLK_EN | + DPORT_I2C_EXT1_CLK_EN | +#if ESP_CONSOLE_UART_NUM != 0 + DPORT_UART_CLK_EN | +#endif +#if ESP_CONSOLE_UART_NUM != 1 + DPORT_UART1_CLK_EN | +#endif +#if defined(CONFIG_SOC_SERIES_ESP32) + DPORT_SPI_DMA_CLK_EN | +#if ESP_CONSOLE_UART_NUM != 2 + DPORT_UART2_CLK_EN | +#endif +#endif /* CONFIG_SOC_SERIES_ESP32 */ +#if defined(CONFIG_SOC_SERIES_ESP32S2) + DPORT_USB_CLK_EN | + DPORT_SPI2_DMA_CLK_EN | + DPORT_SPI3_DMA_CLK_EN | +#endif /* CONFIG_SOC_SERIES_ESP32S2 */ + DPORT_I2S1_CLK_EN; +#endif /* CONFIG_SOC_SERIES_ESP32C3 */ +#if !defined(CONFIG_SOC_SERIES_ESP32) common_perip_clk1 = 0; +#endif + +#if defined(CONFIG_SOC_SERIES_ESP32) + common_perip_clk &= ~DPORT_SPI01_CLK_EN; +#if defined(CONFIG_SPIRAM_SPEED_80M) + /* + * 80MHz SPIRAM uses SPI2/SPI3 as well; it's initialized before this is called. Because it + * is used in a weird mode where clock to the peripheral is disabled but reset is also + * disabled, it 'hangs' in a state where it outputs a continuous 80MHz signal. Mask its bit + * here because we should not modify that state, regardless of what we calculated earlier. + */ + common_perip_clk &= ~DPORT_SPI2_CLK_EN; + common_perip_clk &= ~DPORT_SPI3_CLK_EN; +#endif +#endif /* CONFIG_SOC_SERIES_ESP32 */ + + /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock, + * the current is not reduced when disable I2S clock. + */ +#if defined(CONFIG_SOC_SERIES_ESP32) + DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(0), I2S_CLKA_ENA); + DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(1), I2S_CLKA_ENA); +#endif /* CONFIG_SOC_SERIES_ESP32 */ +#if defined(CONFIG_SOC_SERIES_ESP32S2) + REG_SET_FIELD(I2S_CLKM_CONF_REG(0), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); + REG_SET_FIELD(I2S_CLKM_CONF_REG(1), I2S_CLK_SEL, I2S_CLK_AUDIO_PLL); +#endif /* CONFIG_SOC_SERIES_ESP32S2 */ /* Disable some peripheral clocks. */ +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk); SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, common_perip_clk); CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, common_perip_clk1); SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, common_perip_clk1); +#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */ + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk); + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk); +#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */ /* Disable hardware crypto clocks. */ +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, hwcrypto_perip_clk); SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, hwcrypto_perip_clk); +#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */ + DPORT_CLEAR_PERI_REG_MASK(DPORT_PERI_CLK_EN_REG, hwcrypto_perip_clk); + DPORT_SET_PERI_REG_MASK(DPORT_PERI_RST_EN_REG, hwcrypto_perip_clk); +#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */ + +#if defined(CONFIG_SOC_SERIES_ESP32S3) + /* Force clear backup dma reset signal. This is a fix to the backup dma + * implementation in the ROM, the reset signal was not cleared when the + * backup dma was started, which caused the backup dma operation to fail. + */ + CLEAR_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_PERI_BACKUP_RST); +#endif /* CONFIG_SOC_SERIES_ESP32S3 */ /* Disable WiFi/BT/SDIO clocks. */ +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, wifi_bt_sdio_clk); SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_EN); +#else /* CONFIG_SOC_SERIES_ESP32 || CONFIG_SOC_SERIES_ESP32S2 */ + DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk); +#endif /* CONFIG_SOC_SERIES_ESP32C3 || CONFIG_SOC_SERIES_ESP32S3 */ +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) /* Set WiFi light sleep clock source to RTC slow clock */ REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0); CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M); SET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_RTC_SLOW); +#endif /* Enable RNG clock. */ periph_module_enable(PERIPH_RNG_MODULE); - /* Enable TimerGroup 0 clock to ensure its reference counter will never - * be decremented to 0 during normal operation and preventing it from - * being disabled. - * If the TimerGroup 0 clock is disabled and then reenabled, the watchdog - * registers (Flashboot protection included) will be reenabled, and some - * seconds later, will trigger an unintended reset. - */ +#if (defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32S3)) periph_module_enable(PERIPH_TIMG0_MODULE); +#endif } -#endif /* CONFIG_SOC_SERIES_ESP32S3 */ +#endif -#if defined(CONFIG_SOC_SERIES_ESP32C3) -static void esp32_clock_perip_init(void) +static enum clock_control_status clock_control_esp32_get_status(const struct device *dev, + clock_control_subsys_t sys) { - uint32_t common_perip_clk; - uint32_t hwcrypto_perip_clk; - uint32_t wifi_bt_sdio_clk; - uint32_t common_perip_clk1; + ARG_UNUSED(dev); + uint32_t clk_en_reg = periph_ll_get_clk_en_reg((periph_module_t)sys); + uint32_t clk_en_mask = periph_ll_get_clk_en_mask((periph_module_t)sys); - soc_reset_reason_t rst_reason = esp_rom_get_reset_reason(0); + if (DPORT_GET_PERI_REG_MASK(clk_en_reg, clk_en_mask)) { + return CLOCK_CONTROL_STATUS_ON; + } + return CLOCK_CONTROL_STATUS_OFF; +} - /* For reason that only reset CPU, do not disable the clocks - * that have been enabled before reset. - */ - if (rst_reason == RESET_REASON_CPU0_MWDT0 || rst_reason == RESET_REASON_CPU0_SW || - rst_reason == RESET_REASON_CPU0_RTC_WDT || rst_reason == RESET_REASON_CPU0_MWDT1) { - common_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN0_REG); - hwcrypto_perip_clk = ~READ_PERI_REG(SYSTEM_PERIP_CLK_EN1_REG); - wifi_bt_sdio_clk = ~READ_PERI_REG(SYSTEM_WIFI_CLK_EN_REG); - } else { - common_perip_clk = SYSTEM_WDG_CLK_EN | - SYSTEM_I2S0_CLK_EN | - SYSTEM_UART1_CLK_EN | - SYSTEM_SPI2_CLK_EN | - SYSTEM_I2C_EXT0_CLK_EN | - SYSTEM_UHCI0_CLK_EN | - SYSTEM_RMT_CLK_EN | - SYSTEM_LEDC_CLK_EN | - SYSTEM_TIMERGROUP1_CLK_EN | - SYSTEM_SPI3_CLK_EN | - SYSTEM_SPI4_CLK_EN | - SYSTEM_TWAI_CLK_EN | - SYSTEM_I2S1_CLK_EN | - SYSTEM_SPI2_DMA_CLK_EN | - SYSTEM_SPI3_DMA_CLK_EN; +static int clock_control_esp32_on(const struct device *dev, clock_control_subsys_t sys) +{ + enum clock_control_status status = clock_control_esp32_get_status(dev, sys); - common_perip_clk1 = 0; + if (status == CLOCK_CONTROL_STATUS_ON && !reset_reason_is_cpu_reset()) { + return -EALREADY; + } + + periph_module_enable((periph_module_t)sys); - hwcrypto_perip_clk = SYSTEM_CRYPTO_AES_CLK_EN | - SYSTEM_CRYPTO_SHA_CLK_EN | - SYSTEM_CRYPTO_RSA_CLK_EN; + return 0; +} - wifi_bt_sdio_clk = SYSTEM_WIFI_CLK_WIFI_EN | - SYSTEM_WIFI_CLK_BT_EN_M | - SYSTEM_WIFI_CLK_I2C_CLK_EN | - SYSTEM_WIFI_CLK_UNUSED_BIT12; +static int clock_control_esp32_off(const struct device *dev, clock_control_subsys_t sys) +{ + enum clock_control_status status = clock_control_esp32_get_status(dev, sys); + + if (status == CLOCK_CONTROL_STATUS_ON) { + periph_module_disable((periph_module_t)sys); } - /* Reset peripherals like I2C, SPI, UART, I2S and bring them to known state */ - common_perip_clk |= SYSTEM_I2S0_CLK_EN | - SYSTEM_UART1_CLK_EN | - SYSTEM_SPI2_CLK_EN | - SYSTEM_I2C_EXT0_CLK_EN | - SYSTEM_UHCI0_CLK_EN | - SYSTEM_RMT_CLK_EN | - SYSTEM_UHCI1_CLK_EN | - SYSTEM_SPI3_CLK_EN | - SYSTEM_SPI4_CLK_EN | - SYSTEM_I2C_EXT1_CLK_EN | - SYSTEM_I2S1_CLK_EN | - SYSTEM_SPI2_DMA_CLK_EN | - SYSTEM_SPI3_DMA_CLK_EN; + return 0; +} - common_perip_clk1 = 0; +static int clock_control_esp32_get_rate(const struct device *dev, clock_control_subsys_t sys, + uint32_t *rate) +{ + ARG_UNUSED(dev); - /* Disable some peripheral clocks. */ - CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, common_perip_clk); - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, common_perip_clk); + switch ((int)sys) { + case ESP32_CLOCK_CONTROL_SUBSYS_RTC_FAST: + *rate = esp_clk_tree_lp_fast_get_freq_hz(ESP_CLK_TREE_SRC_FREQ_PRECISION_APPROX); + break; + case ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW: + *rate = clk_hal_lp_slow_get_freq_hz(); + break; + default: + *rate = clk_hal_cpu_get_freq_hz(); + } - CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, common_perip_clk1); - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, common_perip_clk1); + return 0; +} - /* Disable hardware crypto clocks. */ - CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN1_REG, hwcrypto_perip_clk); - SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, hwcrypto_perip_clk); +static int esp32_select_rtc_slow_clk(uint8_t slow_clk) +{ +#if !defined(CONFIG_SOC_SERIES_ESP32C6) + soc_rtc_slow_clk_src_t rtc_slow_clk_src = slow_clk & RTC_CNTL_ANA_CLK_RTC_SEL_V; +#else + soc_rtc_slow_clk_src_t rtc_slow_clk_src = slow_clk; +#endif + uint32_t cal_val = 0; + /* number of times to repeat 32k XTAL calibration + * before giving up and switching to the internal RC + */ + int retry_32k_xtal = 3; + + do { + if (rtc_slow_clk_src == ESP32_RTC_SLOW_CLK_SRC_XTAL32K) { + /* 32k XTAL oscillator needs to be enabled and running before it can + * be used. Hardware doesn't have a direct way of checking if the + * oscillator is running. Here we use rtc_clk_cal function to count + * the number of main XTAL cycles in the given number of 32k XTAL + * oscillator cycles. If the 32k XTAL has not started up, calibration + * will time out, returning 0. + */ + LOG_DBG("waiting for 32k oscillator to start up"); + if (slow_clk == ESP32_RTC_SLOW_CLK_SRC_XTAL32K) { + rtc_clk_32k_enable(true); + } else if (slow_clk == ESP32_RTC_SLOW_CLK_32K_EXT_OSC) { + rtc_clk_32k_enable_external(); + } + /* When CONFIG_RTC_CLK_CAL_CYCLES is set to 0, clock calibration will not be + * performed at startup. + */ + if (CONFIG_RTC_CLK_CAL_CYCLES > 0) { + cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, CONFIG_RTC_CLK_CAL_CYCLES); + if (cal_val == 0) { + if (retry_32k_xtal-- > 0) { + continue; + } + LOG_ERR("32 kHz XTAL not found"); + return -ENODEV; + } + } +#if defined(CONFIG_SOC_SERIES_ESP32C6) + } else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) { + rtc_clk_rc32k_enable(true); + } +#else + } else if (rtc_slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_FAST_D256) { + rtc_clk_8m_enable(true, true); + } +#endif + rtc_clk_slow_src_set(rtc_slow_clk_src); - /* Disable WiFi/BT/SDIO clocks. */ - CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, wifi_bt_sdio_clk); - SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_EN); + if (CONFIG_RTC_CLK_CAL_CYCLES > 0) { + cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, CONFIG_RTC_CLK_CAL_CYCLES); + } else { + const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL; - /* Set WiFi light sleep clock source to RTC slow clock */ - REG_SET_FIELD(SYSTEM_BT_LPCK_DIV_INT_REG, SYSTEM_BT_LPCK_DIV_NUM, 0); - CLEAR_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_8M); - SET_PERI_REG_MASK(SYSTEM_BT_LPCK_DIV_FRAC_REG, SYSTEM_LPCLK_SEL_RTC_SLOW); + cal_val = (uint32_t)(cal_dividend / rtc_clk_slow_freq_get_hz()); + } + } while (cal_val == 0); - /* Enable RNG clock. */ - periph_module_enable(PERIPH_RNG_MODULE); + LOG_DBG("RTC_SLOW_CLK calibration value: %d", cal_val); + + esp_clk_slowclk_cal_set(cal_val); + + return 0; } -#endif /* CONFIG_SOC_SERIES_ESP32C3 */ -static int clock_control_esp32_init(const struct device *dev) +static int esp32_cpu_clock_configure(const struct esp32_cpu_clock_config *cpu_cfg) { - const struct esp32_clock_config *cfg = dev->config; rtc_cpu_freq_config_t old_config; rtc_cpu_freq_config_t new_config; - bool res; + rtc_clk_config_t rtc_clk_cfg = RTC_CLK_CONFIG_DEFAULT(); + uint32_t uart_clock_src_hz; + bool ret; + + rtc_clk_cfg.xtal_freq = cpu_cfg->xtal_freq; + rtc_clk_cfg.cpu_freq_mhz = cpu_cfg->cpu_freq; - /* wait uart output to be cleared */ esp_rom_uart_tx_wait_idle(ESP_CONSOLE_UART_NUM); - /* reset default config to use dts config */ - if (rtc_clk_apb_freq_get() < APB_CLK_FREQ || rtc_get_reset_reason(0) != CPU_RESET_REASON) { - rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT(); +#if defined(CONFIG_SOC_SERIES_ESP32C6) + rtc_clk_modem_clock_domain_active_state_icg_map_preinit(); - clk_cfg.xtal_freq = cfg->xtal_freq_sel; - clk_cfg.cpu_freq_mhz = cfg->cpu_freq; - clk_cfg.slow_clk_src = rtc_clk_slow_freq_get(); - clk_cfg.fast_clk_src = rtc_clk_fast_freq_get(); - rtc_clk_init(clk_cfg); - } + REG_SET_FIELD(LP_CLKRST_FOSC_CNTL_REG, LP_CLKRST_FOSC_DFREQ, rtc_clk_cfg.clk_8m_dfreq); + REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_SCK_DCAP, rtc_clk_cfg.slow_clk_dcap); + REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, rtc_clk_cfg.rc32k_dfreq); +#else + REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, rtc_clk_cfg.slow_clk_dcap); + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, rtc_clk_cfg.clk_8m_dfreq); +#endif - rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M); +#if defined(CONFIG_SOC_SERIES_ESP32) + REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, rtc_clk_cfg.clk_8m_div - 1); +#elif defined(CONFIG_SOC_SERIES_ESP32C6) + clk_ll_rc_fast_tick_conf(); +#else + /* Configure 150k clock division */ + rtc_clk_divider_set(rtc_clk_cfg.clk_rtc_clk_div); - rtc_clk_cpu_freq_get_config(&old_config); + /* Configure 8M clock division */ + rtc_clk_8m_divider_set(rtc_clk_cfg.clk_8m_clk_div); +#endif - const uint32_t old_freq_mhz = old_config.freq_mhz; - const uint32_t new_freq_mhz = cfg->cpu_freq; +#if !defined(CONFIG_SOC_SERIES_ESP32C6) + /* Reset (disable) i2c internal bus for all regi2c registers */ + regi2c_ctrl_ll_i2c_reset(); + /* Enable the internal bus used to configure BBPLL */ + regi2c_ctrl_ll_i2c_bbpll_enable(); +#endif - res = rtc_clk_cpu_freq_mhz_to_config(cfg->cpu_freq, &new_config); - if (!res) { - return -ENOTSUP; - } +#if defined(CONFIG_SOC_SERIES_ESP32S2) || defined(CONFIG_SOC_SERIES_ESP32) + regi2c_ctrl_ll_i2c_apll_enable(); +#endif - if (cfg->xtal_div >= 0) { - new_config.div = cfg->xtal_div; - } +#if !defined(CONFIG_SOC_SERIES_ESP32S2) + rtc_clk_xtal_freq_update(rtc_clk_cfg.xtal_freq); +#endif +#if defined(CONFIG_SOC_SERIES_ESP32C6) + /* On ESP32C6, MSPI source clock's default HS divider leads to 120MHz, + * which is unusable before calibration. Therefore, before switching + * SOC_ROOT_CLK to HS, we need to set MSPI source clock HS divider + * to make it run at 80MHz after the switch. PLL = 480MHz, so divider is 6. + */ + clk_ll_mspi_fast_set_hs_divider(6); +#else + rtc_clk_apb_freq_update(rtc_clk_cfg.xtal_freq * MHZ(1)); +#endif + + /* Set CPU frequency */ + rtc_clk_cpu_freq_get_config(&old_config); - if (cfg->clk_src_sel >= 0) { - new_config.source = cfg->clk_src_sel; + ret = rtc_clk_cpu_freq_mhz_to_config(rtc_clk_cfg.cpu_freq_mhz, &new_config); + if (!ret || (new_config.source != cpu_cfg->clk_src)) { + LOG_ERR("invalid CPU frequency value"); + return -EINVAL; } - /* set new configuration */ rtc_clk_cpu_freq_set_config(&new_config); - /* Re-calculate the ccount to make time calculation correct */ - esp_cpu_set_cycle_count((uint64_t)esp_cpu_get_cycle_count() * new_freq_mhz / old_freq_mhz); + /* Re-calculate the ccount to make time calculation correct. */ + esp_cpu_set_cycle_count((uint64_t)esp_cpu_get_cycle_count() * rtc_clk_cfg.cpu_freq_mhz / + old_config.freq_mhz); - esp32_clock_perip_init(); - - uint32_t clock_hz = esp_clk_apb_freq(); +#if !defined(CONFIG_SOC_SERIES_ESP32C6) #if ESP_ROM_UART_CLK_IS_XTAL - clock_hz = esp_clk_xtal_freq(); + uart_clock_src_hz = (uint32_t)rtc_clk_xtal_freq_get() * MHZ(1); +#else + uart_clock_src_hz = esp_clk_apb_freq(); #endif #if !defined(ESP_CONSOLE_UART_NONE) - esp_rom_uart_set_clock_baudrate(ESP_CONSOLE_UART_NUM, - clock_hz, ESP_CONSOLE_UART_BAUDRATE); + esp_rom_uart_set_clock_baudrate(ESP_CONSOLE_UART_NUM, uart_clock_src_hz, + ESP_CONSOLE_UART_BAUDRATE); #endif +#endif + return 0; +} + +static int clock_control_esp32_configure(const struct device *dev, clock_control_subsys_t sys, + void *data) +{ + + const struct esp32_clock_config *cfg = dev->config; + struct esp32_clock_config *new_cfg = data; + int ret = 0; + + switch ((int)sys) { + case ESP32_CLOCK_CONTROL_SUBSYS_RTC_FAST: + rtc_clk_fast_src_set(new_cfg->rtc.rtc_fast_clock_src); + break; + case ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW: + ret = esp32_select_rtc_slow_clk(new_cfg->rtc.rtc_slow_clock_src); + break; + case ESP32_CLOCK_CONTROL_SUBSYS_CPU: + /* Normalize frequency */ + new_cfg->cpu.xtal_freq = new_cfg->cpu.xtal_freq > MHZ(1) + ? new_cfg->cpu.xtal_freq / MHZ(1) + : new_cfg->cpu.xtal_freq; + new_cfg->cpu.cpu_freq = new_cfg->cpu.cpu_freq > MHZ(1) + ? new_cfg->cpu.cpu_freq / MHZ(1) + : new_cfg->cpu.cpu_freq; + ret = esp32_cpu_clock_configure(&new_cfg->cpu); + break; + default: + LOG_ERR("Unsupported subsystem %d", (int)sys); + return -EINVAL; + } + return ret; +} + +static int clock_control_esp32_init(const struct device *dev) +{ + const struct esp32_clock_config *cfg = dev->config; + bool ret; +#if !defined(CONFIG_SOC_SERIES_ESP32C6) + soc_reset_reason_t rst_reas; + rtc_config_t rtc_cfg = RTC_CONFIG_DEFAULT(); + + rst_reas = esp_rom_get_reset_reason(0); +#if !defined(CONFIG_SOC_SERIES_ESP32) + if (rst_reas == RESET_REASON_CHIP_POWER_ON +#if SOC_EFUSE_HAS_EFUSE_RST_BUG + || rst_reas == RESET_REASON_CORE_EFUSE_CRC +#endif + ) { + rtc_cfg.cali_ocode = 1; + } +#endif + rtc_init(rtc_cfg); +#endif + + ret = esp32_cpu_clock_configure(&cfg->cpu); + if (ret) { + LOG_ERR("Failed to configure CPU clock"); + return ret; + } + + rtc_clk_fast_src_set(cfg->rtc.rtc_fast_clock_src); + + ret = esp32_select_rtc_slow_clk(cfg->rtc.rtc_slow_clock_src); + if (ret) { + LOG_ERR("Failed to configure RTC clock"); + return ret; + } + + esp32_clock_perip_init(); + return 0; } static const struct clock_control_driver_api clock_control_esp32_api = { .on = clock_control_esp32_on, .off = clock_control_esp32_off, - .async_on = clock_control_esp32_async_on, .get_rate = clock_control_esp32_get_rate, .get_status = clock_control_esp32_get_status, + .configure = clock_control_esp32_configure, }; -#define ESP32_CLOCK_SOURCE \ - COND_CODE_1(DT_NODE_HAS_PROP(DT_INST(0, DT_CPU_COMPAT), clock_source), \ - (DT_PROP(DT_INST(0, DT_CPU_COMPAT), clock_source)), (-1)) +static const struct esp32_cpu_clock_config esp32_cpu_clock_config0 = { + .clk_src = DT_PROP(DT_INST(0, DT_CPU_COMPAT), clock_source), + .cpu_freq = (DT_PROP(DT_INST(0, DT_CPU_COMPAT), clock_frequency) / MHZ(1)), + .xtal_freq = ((DT_PROP(DT_INST(0, DT_CPU_COMPAT), xtal_freq)) / MHZ(1)), +}; -#define ESP32_CLOCK_XTAL_DIV \ - COND_CODE_1(DT_NODE_HAS_PROP(0, xtal_div), \ - (DT_INST_PROP(0, xtal_div)), (-1)) +static const struct esp32_rtc_clock_config esp32_rtc_clock_config0 = { + .rtc_fast_clock_src = DT_PROP(DT_INST(0, espressif_esp32_rtc), fast_clk_src), + .rtc_slow_clock_src = DT_PROP(DT_INST(0, espressif_esp32_rtc), slow_clk_src), +}; static const struct esp32_clock_config esp32_clock_config0 = { - .clk_src_sel = ESP32_CLOCK_SOURCE, - .cpu_freq = DT_PROP(DT_INST(0, DT_CPU_COMPAT), clock_frequency) / 1000000, - .xtal_freq_sel = DT_INST_PROP(0, xtal_freq), - .xtal_div = ESP32_CLOCK_XTAL_DIV + .cpu = esp32_cpu_clock_config0, + .rtc = esp32_rtc_clock_config0 }; DEVICE_DT_DEFINE(DT_NODELABEL(rtc), diff --git a/drivers/clock_control/clock_control_gd32.c b/drivers/clock_control/clock_control_gd32.c index e7f1f739a8be3..1a20d5e4ab210 100644 --- a/drivers/clock_control/clock_control_gd32.c +++ b/drivers/clock_control/clock_control_gd32.c @@ -198,7 +198,7 @@ clock_control_gd32_get_status(const struct device *dev, return CLOCK_CONTROL_STATUS_OFF; } -static struct clock_control_driver_api clock_control_gd32_api = { +static const struct clock_control_driver_api clock_control_gd32_api = { .on = clock_control_gd32_on, .off = clock_control_gd32_off, .get_rate = clock_control_gd32_get_rate, diff --git a/drivers/clock_control/clock_control_ifx_cat1.c b/drivers/clock_control/clock_control_ifx_cat1.c index 7e17b94951434..4d8f4603b44e3 100644 --- a/drivers/clock_control/clock_control_ifx_cat1.c +++ b/drivers/clock_control/clock_control_ifx_cat1.c @@ -18,7 +18,13 @@ /* Enumeration of enabled in device tree Clock, uses for indexing clock info table */ enum { +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_imo), okay) INFINEON_CAT1_CLOCK_IMO, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) + INFINEON_CAT1_CLOCK_IHO, +#endif #if DT_NODE_HAS_STATUS(DT_NODELABEL(path_mux0), okay) INFINEON_CAT1_CLOCK_PATHMUX0, @@ -60,6 +66,42 @@ enum { INFINEON_CAT1_CLOCK_HF4, #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf5), okay) + INFINEON_CAT1_CLOCK_HF5, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf6), okay) + INFINEON_CAT1_CLOCK_HF6, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf7), okay) + INFINEON_CAT1_CLOCK_HF7, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf8), okay) + INFINEON_CAT1_CLOCK_HF8, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf9), okay) + INFINEON_CAT1_CLOCK_HF9, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf10), okay) + INFINEON_CAT1_CLOCK_HF10, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf11), okay) + INFINEON_CAT1_CLOCK_HF11, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf12), okay) + INFINEON_CAT1_CLOCK_HF12, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf13), okay) + INFINEON_CAT1_CLOCK_HF13, +#endif + #if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_fast), okay) INFINEON_CAT1_CLOCK_FAST, #endif @@ -100,7 +142,13 @@ struct infineon_cat1_clock_info_t { static struct infineon_cat1_clock_info_t clock_info_table[INFINEON_CAT1_ENABLED_CLOCK_COUNT] = { /* We always have IMO */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_imo), okay) [INFINEON_CAT1_CLOCK_IMO] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_imo)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) + [INFINEON_CAT1_CLOCK_IHO] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_iho)) }, +#endif #if DT_NODE_HAS_STATUS(DT_NODELABEL(path_mux0), okay) [INFINEON_CAT1_CLOCK_PATHMUX0] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(path_mux0)) }, @@ -142,6 +190,42 @@ static struct infineon_cat1_clock_info_t [INFINEON_CAT1_CLOCK_HF4] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf4)) }, #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf5), okay) + [INFINEON_CAT1_CLOCK_HF5] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf5)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf6), okay) + [INFINEON_CAT1_CLOCK_HF6] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf6)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf7), okay) + [INFINEON_CAT1_CLOCK_HF7] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf7)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf8), okay) + [INFINEON_CAT1_CLOCK_HF8] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf8)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf9), okay) + [INFINEON_CAT1_CLOCK_HF9] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf9)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf10), okay) + [INFINEON_CAT1_CLOCK_HF10] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf10)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf11), okay) + [INFINEON_CAT1_CLOCK_HF11] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf11)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf12), okay) + [INFINEON_CAT1_CLOCK_HF12] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf12)) }, +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf13), okay) + [INFINEON_CAT1_CLOCK_HF13] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_hf13)) }, +#endif + #if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_fast), okay) [INFINEON_CAT1_CLOCK_FAST] = { .dt_ord = DT_DEP_ORD(DT_NODELABEL(clk_fast)) }, #endif @@ -242,13 +326,67 @@ static cyhal_clock_t *_get_hal_obj_from_ord(uint32_t dt_ord) return ret_obj; } +#if DT_NODE_HAS_STATUS(DT_NODELABEL(dpll_hp), okay) +__WEAK void cycfg_ClockStartupError(uint32_t error) +{ + (void)error; /* Suppress the compiler warning */ + while (1) { + } +} + +void Cy_SysClk_Dpll_Hp0_Init(void) +{ +#define CY_CFG_SYSCLK_PLL_ERROR 3 + + static cy_stc_dpll_hp_config_t srss_0_clock_0_pll500m_0_hp_pllConfig = { + .pDiv = 0, + .nDiv = 15, + .kDiv = 1, + .nDivFract = 0, + .freqModeSel = CY_SYSCLK_DPLL_HP_CLK50MHZ_1US_CNT_VAL, + .ivrTrim = 0x8U, + .clkrSel = 0x1U, + .alphaCoarse = 0xCU, + .betaCoarse = 0x5U, + .flockThresh = 0x3U, + .flockWait = 0x6U, + .flockLkThres = 0x7U, + .flockLkWait = 0x4U, + .alphaExt = 0x14U, + .betaExt = 0x14U, + .lfEn = 0x1U, + .dcEn = 0x1U, + .outputMode = CY_SYSCLK_FLLPLL_OUTPUT_AUTO, + }; + static cy_stc_pll_manual_config_t srss_0_clock_0_pll500m_0_pllConfig = { + .hpPllCfg = &srss_0_clock_0_pll500m_0_hp_pllConfig, + }; + +#if !defined(CY_PDL_TZ_ENABLED) + if (Cy_SysClk_PllIsEnabled(SRSS_DPLL_HP_0_PATH_NUM)) { + return; + } +#endif + Cy_SysClk_PllDisable(SRSS_DPLL_HP_0_PATH_NUM); + if (CY_SYSCLK_SUCCESS != + Cy_SysClk_PllManualConfigure(SRSS_DPLL_HP_0_PATH_NUM, + &srss_0_clock_0_pll500m_0_pllConfig)) { + cycfg_ClockStartupError(CY_CFG_SYSCLK_PLL_ERROR); + } + if (CY_SYSCLK_SUCCESS != Cy_SysClk_PllEnable(SRSS_DPLL_HP_0_PATH_NUM, 10000u)) { + cycfg_ClockStartupError(CY_CFG_SYSCLK_PLL_ERROR); + } +} +#endif + static int clock_control_infineon_cat1_init(const struct device *dev) { ARG_UNUSED(dev); cy_rslt_t rslt; cyhal_clock_t *clock_obj = NULL; cyhal_clock_t *clock_source_obj = NULL; - uint32 frequency; + + __attribute__((unused)) uint32 frequency; uint32 clock_div; /* Configure IMO */ @@ -257,8 +395,16 @@ static int clock_control_infineon_cat1_init(const struct device *dev) if (cyhal_clock_get(clock_obj, &CYHAL_CLOCK_RSC_IMO)) { return -EIO; } -#else - #error "IMO clock must be enabled" +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_IHO].obj; + if (cyhal_clock_get(clock_obj, &CYHAL_CLOCK_RSC_IHO)) { + return -EIO; + } +#endif +#if !DT_NODE_HAS_STATUS(DT_NODELABEL(clk_imo), okay) && \ + !DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) + #error "IMO clock or IHO clock must be enabled" #endif /* Configure the PathMux[0] to source defined in tree device 'path_mux0' node */ @@ -403,6 +549,105 @@ static int clock_control_infineon_cat1_init(const struct device *dev) } #endif + /* Configure the HF[5] to source defined in tree device 'clk_hf5' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf5), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF5].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf5)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf5), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[5], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[6] to source defined in tree device 'clk_hf6' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf6), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF6].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf6)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf6), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[6], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[7] to source defined in tree device 'clk_hf7' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf7), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF7].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf7)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf7), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[7], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[8] to source defined in tree device 'clk_hf8' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf8), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF8].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf8)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf8), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[8], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[9] to source defined in tree device 'clk_hf9' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf9), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF9].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf9)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf9), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[9], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[10] to source defined in tree device 'clk_hf10' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf10), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF10].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf10)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf10), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[10], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[11] to source defined in tree device 'clk_hf11' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf11), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF11].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf11)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf11), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[11], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[12] to source defined in tree device 'clk_hf12' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf12), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF12].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf12)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf12), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[12], clock_div)) { + return -EIO; + } +#endif + + /* Configure the HF[13] to source defined in tree device 'clk_hf13' node */ +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_hf13), okay) + clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_HF13].obj; + clock_source_obj = _get_hal_obj_from_ord(GET_CLK_SOURCE_ORD(clk_hf13)); + clock_div = DT_PROP(DT_NODELABEL(clk_hf13), clock_div); + + if (_configure_clk_hf(clock_obj, clock_source_obj, &CYHAL_CLOCK_HF[13], clock_div)) { + return -EIO; + } +#endif + /* Configure the clock fast to source defined in tree device 'clk_fast' node */ #if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_fast), okay) clock_obj = &clock_info_table[INFINEON_CAT1_CLOCK_FAST].obj; @@ -445,6 +690,11 @@ static int clock_control_infineon_cat1_init(const struct device *dev) } #endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(dpll_hp), okay) + Cy_SysClk_Dpll_Hp0_Init(); + SystemCoreClockUpdate(); +#endif + return (int) rslt; } @@ -463,6 +713,7 @@ static const struct clock_control_driver_api clock_control_infineon_cat1_api = { .off = clock_control_infineon_cat_on_off }; +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_imo), okay) DEVICE_DT_DEFINE(DT_NODELABEL(clk_imo), &clock_control_infineon_cat1_init, NULL, @@ -471,3 +722,14 @@ DEVICE_DT_DEFINE(DT_NODELABEL(clk_imo), PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &clock_control_infineon_cat1_api); +#endif +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iho), okay) +DEVICE_DT_DEFINE(DT_NODELABEL(clk_iho), + &clock_control_infineon_cat1_init, + NULL, + NULL, + NULL, + PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, + &clock_control_infineon_cat1_api); +#endif diff --git a/drivers/clock_control/clock_control_litex.c b/drivers/clock_control/clock_control_litex.c index 2eb0c6b358981..06d3d1264baaa 100644 --- a/drivers/clock_control/clock_control_litex.c +++ b/drivers/clock_control/clock_control_litex.c @@ -26,7 +26,7 @@ static struct litex_clk_device *ldev; /* global struct for whole driver */ static struct litex_clk_clkout *clkouts;/* clkout array for whole driver */ /* All DRP regs addresses and sizes */ -static struct litex_drp_reg drp[] = { +static const struct litex_drp_reg drp[] = { {DRP_ADDR_RESET, 1}, {DRP_ADDR_LOCKED, 1}, {DRP_ADDR_READ, 1}, @@ -905,11 +905,15 @@ static int litex_clk_calc_duty_normal(struct litex_clk_clkout *lcko, uint32_t ht_aprox, synth_duty, min_d; uint8_t high_time_it, edge_it, high_duty, divider = lcko->config.div; + int err; if (calc_new) { duty = lcko->ts_config.duty; } else { - litex_clk_get_duty_cycle(lcko, &duty); + err = litex_clk_get_duty_cycle(lcko, &duty); + if (err != 0) { + return err; + } } high_duty = litex_clk_calc_duty_percent(&duty); @@ -1127,9 +1131,13 @@ int litex_clk_get_phase(struct litex_clk_clkout *lcko) uint32_t divider = 0, fract_cnt, post_glob_div_f, pm, global_period, clkout_period, period; uint8_t phase_mux = 0, delay_time = 0; + int err = 0; litex_clk_get_phase_data(lcko, &phase_mux, &delay_time); - litex_clk_get_clkout_divider(lcko, ÷r, &fract_cnt); + err = litex_clk_get_clkout_divider(lcko, ÷r, &fract_cnt); + if (err != 0) { + return err; + } post_glob_div_f = (uint32_t)litex_clk_get_real_global_frequency(); period_buff = PICOS_IN_SEC; diff --git a/drivers/clock_control/clock_control_max32.c b/drivers/clock_control/clock_control_max32.c new file mode 100644 index 0000000000000..2cbed41bd23a8 --- /dev/null +++ b/drivers/clock_control/clock_control_max32.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#define DT_DRV_COMPAT adi_max32_gcr + +static inline int api_on(const struct device *dev, clock_control_subsys_t clkcfg) +{ + ARG_UNUSED(dev); + struct max32_perclk *perclk = (struct max32_perclk *)(clkcfg); + + switch (perclk->bus) { + case ADI_MAX32_CLOCK_BUS0: + MXC_SYS_ClockEnable((mxc_sys_periph_clock_t)perclk->bit); + break; + case ADI_MAX32_CLOCK_BUS1: + MXC_SYS_ClockEnable((mxc_sys_periph_clock_t)(perclk->bit + 32)); + break; + case ADI_MAX32_CLOCK_BUS2: + MXC_SYS_ClockEnable((mxc_sys_periph_clock_t)(perclk->bit + 64)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static inline int api_off(const struct device *dev, clock_control_subsys_t clkcfg) +{ + ARG_UNUSED(dev); + struct max32_perclk *perclk = (struct max32_perclk *)(clkcfg); + + switch (perclk->bus) { + case ADI_MAX32_CLOCK_BUS0: + MXC_SYS_ClockDisable((mxc_sys_periph_clock_t)perclk->bit); + break; + case ADI_MAX32_CLOCK_BUS1: + MXC_SYS_ClockDisable((mxc_sys_periph_clock_t)(perclk->bit + 32)); + break; + case ADI_MAX32_CLOCK_BUS2: + MXC_SYS_ClockDisable((mxc_sys_periph_clock_t)(perclk->bit + 64)); + break; + default: + return -EINVAL; + } + + return 0; +} + +static int api_get_rate(const struct device *dev, clock_control_subsys_t clkcfg, uint32_t *rate) +{ + ARG_UNUSED(dev); + struct max32_perclk *perclk = (struct max32_perclk *)(clkcfg); + + switch (perclk->clk_src) { + case ADI_MAX32_PRPH_CLK_SRC_PCLK: + *rate = ADI_MAX32_PCLK_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_EXTCLK: + *rate = ADI_MAX32_CLK_EXTCLK_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_IBRO: + *rate = ADI_MAX32_CLK_IBRO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_ERFO: + *rate = ADI_MAX32_CLK_ERFO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_ERTCO: + *rate = ADI_MAX32_CLK_ERTCO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_INRO: + *rate = ADI_MAX32_CLK_INRO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_ISO: + *rate = ADI_MAX32_CLK_ISO_FREQ; + break; + case ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8: + *rate = ADI_MAX32_CLK_IBRO_FREQ / 8; + break; + default: + *rate = 0U; + /* Invalid parameters */ + return -EINVAL; + } + + return 0; +} + +static const struct clock_control_driver_api max32_clkctrl_api = { + .on = api_on, + .off = api_off, + .get_rate = api_get_rate, +}; + +static void setup_fixed_clocks(void) +{ +#if DT_NODE_HAS_COMPAT(DT_NODELABEL(clk_extclk), fixed_clock) + MXC_SYS_ClockSourceDisable(ADI_MAX32_CLK_EXTCLK); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_ipo), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_IPO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_erfo), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_ERFO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_ibro), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_IBRO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_iso), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_ISO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_inro), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_INRO); +#endif + +#if DT_NODE_HAS_STATUS(DT_NODELABEL(clk_ertco), okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_ERTCO); +#endif + +/* Some device does not support external clock */ +#if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(clk_extclk), fixed_clock, okay) + MXC_SYS_ClockSourceEnable(ADI_MAX32_CLK_EXTCLK); +#endif +} + +static int max32_clkctrl_init(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Setup fixed clocks if enabled */ + setup_fixed_clocks(); + + /* Setup device clock source */ + MXC_SYS_Clock_Select(ADI_MAX32_SYSCLK_SRC); + +#if DT_NODE_HAS_PROP(DT_NODELABEL(gcr), sysclk_prescaler) + /* Setup divider */ + Wrap_MXC_SYS_SetClockDiv(sysclk_prescaler(ADI_MAX32_SYSCLK_PRESCALER)); +#endif + + return 0; +} + +DEVICE_DT_INST_DEFINE(0, max32_clkctrl_init, NULL, NULL, NULL, PRE_KERNEL_1, + CONFIG_CLOCK_CONTROL_INIT_PRIORITY, &max32_clkctrl_api); diff --git a/drivers/clock_control/clock_control_mchp_xec.c b/drivers/clock_control/clock_control_mchp_xec.c index 11b0b54ac41fc..c3ff0bbb78f2c 100644 --- a/drivers/clock_control/clock_control_mchp_xec.c +++ b/drivers/clock_control/clock_control_mchp_xec.c @@ -1014,7 +1014,7 @@ void mchp_xec_clk_ctrl_sys_sleep_disable(void) #endif /* Clock controller driver registration */ -static struct clock_control_driver_api xec_clock_control_api = { +static const struct clock_control_driver_api xec_clock_control_api = { .on = xec_clock_control_on, .off = xec_clock_control_off, .get_rate = xec_clock_control_get_subsys_rate, diff --git a/drivers/clock_control/clock_control_mcux_ccm.c b/drivers/clock_control/clock_control_mcux_ccm.c index c9fd6229bab5e..72f1afaae398d 100644 --- a/drivers/clock_control/clock_control_mcux_ccm.c +++ b/drivers/clock_control/clock_control_mcux_ccm.c @@ -108,8 +108,13 @@ static int mcux_ccm_on(const struct device *dev, #endif #if defined(CONFIG_ETH_NXP_ENET) +#ifdef CONFIG_SOC_SERIES_IMX8M +#define ENET_CLOCK kCLOCK_Enet1 +#else +#define ENET_CLOCK kCLOCK_Enet +#endif case IMX_CCM_ENET_CLK: - CLOCK_EnableClock(kCLOCK_Enet); + CLOCK_EnableClock(ENET_CLOCK); return 0; #endif default: @@ -239,9 +244,14 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, #ifdef CONFIG_ETH_NXP_ENET case IMX_CCM_ENET_CLK: +#ifdef CONFIG_SOC_SERIES_IMX8M + *rate = CLOCK_GetFreq(kCLOCK_EnetIpgClk); +#else *rate = CLOCK_GetIpgFreq(); - break; #endif +#endif + break; + #ifdef CONFIG_PTP_CLOCK_NXP_ENET case IMX_CCM_ENET_PLL: *rate = CLOCK_GetPllFreq(kCLOCK_PllEnet); diff --git a/drivers/clock_control/clock_control_mcux_ccm_rev2.c b/drivers/clock_control/clock_control_mcux_ccm_rev2.c index f3e7c59aea36c..188fe976df4f9 100644 --- a/drivers/clock_control/clock_control_mcux_ccm_rev2.c +++ b/drivers/clock_control/clock_control_mcux_ccm_rev2.c @@ -20,6 +20,10 @@ static int mcux_ccm_on(const struct device *dev, #ifdef CONFIG_ETH_NXP_ENET if ((uint32_t)sub_system == IMX_CCM_ENET_CLK) { CLOCK_EnableClock(kCLOCK_Enet); +#ifdef CONFIG_ETH_NXP_ENET_1G + } else if ((uint32_t)sub_system == IMX_CCM_ENET1G_CLK) { + CLOCK_EnableClock(kCLOCK_Enet_1g); +#endif } #endif return 0; @@ -111,6 +115,7 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, #ifdef CONFIG_ETH_NXP_ENET case IMX_CCM_ENET_CLK: + case IMX_CCM_ENET1G_CLK: clock_root = kCLOCK_Root_Bus; break; #endif @@ -139,6 +144,15 @@ static int mcux_ccm_get_subsys_rate(const struct device *dev, break; #endif +#ifdef CONFIG_PWM_MCUX_QTMR + case IMX_CCM_QTMR1_CLK: + case IMX_CCM_QTMR2_CLK: + case IMX_CCM_QTMR3_CLK: + case IMX_CCM_QTMR4_CLK: + clock_root = kCLOCK_Root_Bus; + break; +#endif + #ifdef CONFIG_MEMC_MCUX_FLEXSPI case IMX_CCM_FLEXSPI_CLK: clock_root = kCLOCK_Root_Flexspi1; diff --git a/drivers/clock_control/clock_control_mcux_scg.c b/drivers/clock_control/clock_control_mcux_scg.c index 690c133dd16a8..2898766e452cd 100644 --- a/drivers/clock_control/clock_control_mcux_scg.c +++ b/drivers/clock_control/clock_control_mcux_scg.c @@ -1,8 +1,9 @@ /* * Copyright (c) 2019-2021 Vestas Wind Systems A/S + * Copyright 2024 NXP * * Based on clock_control_mcux_sim.c, which is: - * Copyright (c) 2017, NXP + * Copyright (c) 2017, 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -45,9 +46,11 @@ static int mcux_scg_get_rate(const struct device *dev, case KINETIS_SCG_BUS_CLK: clock_name = kCLOCK_BusClk; break; +#if !(defined(CONFIG_SOC_MKE17Z7) || defined(CONFIG_SOC_MKE17Z9)) case KINETIS_SCG_FLEXBUS_CLK: clock_name = kCLOCK_FlexBusClk; break; +#endif case KINETIS_SCG_FLASH_CLK: clock_name = kCLOCK_FlashClk; break; @@ -60,33 +63,57 @@ static int mcux_scg_get_rate(const struct device *dev, case KINETIS_SCG_FIRC_CLK: clock_name = kCLOCK_ScgFircClk; break; +#if (defined(FSL_FEATURE_SCG_HAS_SPLL) && FSL_FEATURE_SCG_HAS_SPLL) case KINETIS_SCG_SPLL_CLK: clock_name = kCLOCK_ScgSysPllClk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SPLL) && FSL_FEATURE_SCG_HAS_SPLL) */ +#if (defined(FSL_FEATURE_SCG_HAS_LPFLL) && FSL_FEATURE_SCG_HAS_LPFLL) + case KINETIS_SCG_SPLL_CLK: + clock_name = kCLOCK_ScgLpFllClk; + break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_LPFLL) && FSL_FEATURE_SCG_HAS_LPFLL) */ +#if (defined(FSL_FEATURE_SCG_HAS_SOSCDIV1) && FSL_FEATURE_SCG_HAS_SOSCDIV1) case KINETIS_SCG_SOSC_ASYNC_DIV1_CLK: clock_name = kCLOCK_ScgSysOscAsyncDiv1Clk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SOSCDIV1) && FSL_FEATURE_SCG_HAS_SOSCDIV1) */ case KINETIS_SCG_SOSC_ASYNC_DIV2_CLK: clock_name = kCLOCK_ScgSysOscAsyncDiv2Clk; break; +#if (defined(FSL_FEATURE_SCG_HAS_SIRCDIV1) && FSL_FEATURE_SCG_HAS_SIRCDIV1) case KINETIS_SCG_SIRC_ASYNC_DIV1_CLK: clock_name = kCLOCK_ScgSircAsyncDiv1Clk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SIRCDIV1) && FSL_FEATURE_SCG_HAS_SIRCDIV1) */ case KINETIS_SCG_SIRC_ASYNC_DIV2_CLK: clock_name = kCLOCK_ScgSircAsyncDiv2Clk; break; +#if (defined(FSL_FEATURE_FSL_FEATURE_SCG_HAS_FIRCDIV1) && FSL_FEATURE_SCG_HAS_FIRCDIV1) case KINETIS_SCG_FIRC_ASYNC_DIV1_CLK: clock_name = kCLOCK_ScgFircAsyncDiv1Clk; break; +#endif /* (defined(FSL_FEATURE_FSL_FEATURE_SCG_HAS_FIRCDIV1) && FSL_FEATURE_SCG_HAS_FIRCDIV1) */ case KINETIS_SCG_FIRC_ASYNC_DIV2_CLK: clock_name = kCLOCK_ScgFircAsyncDiv2Clk; break; +#if (defined(FSL_FEATURE_SCG_HAS_SPLLDIV1) && FSL_FEATURE_SCG_HAS_SPLLDIV1) case KINETIS_SCG_SPLL_ASYNC_DIV1_CLK: clock_name = kCLOCK_ScgSysPllAsyncDiv1Clk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SPLLDIV1) && FSL_FEATURE_SCG_HAS_SPLLDIV1) */ +#if (defined(FSL_FEATURE_SCG_HAS_SPLL) && FSL_FEATURE_SCG_HAS_SPLL) case KINETIS_SCG_SPLL_ASYNC_DIV2_CLK: clock_name = kCLOCK_ScgSysPllAsyncDiv2Clk; break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_SPLL) && FSL_FEATURE_SCG_HAS_SPLL) */ +#if (defined(FSL_FEATURE_SCG_HAS_FLLDIV1) && FSL_FEATURE_SCG_HAS_FLLDIV1) + case KINETIS_SCG_LPFLL_ASYNC_DIV2_CLK: + clock_name = kCLOCK_ScgSysLPFllAsyncDiv2Clk; + break; +#endif /* (defined(FSL_FEATURE_SCG_HAS_FLLDIV1) && FSL_FEATURE_SCG_HAS_FLLDIV1) */ + + default: LOG_ERR("Unsupported clock name"); return -EINVAL; diff --git a/drivers/clock_control/clock_control_mcux_syscon.c b/drivers/clock_control/clock_control_mcux_syscon.c index 93a9f1db4ac71..b7a39b11d1116 100644 --- a/drivers/clock_control/clock_control_mcux_syscon.c +++ b/drivers/clock_control/clock_control_mcux_syscon.c @@ -71,6 +71,29 @@ static int mcux_lpc_syscon_clock_control_on(const struct device *dev, } #endif +#if defined(CONFIG_CAN_MCUX_FLEXCAN) + switch ((uint32_t)sub_system) { + case MCUX_FLEXCAN0_CLK: + CLOCK_EnableClock(kCLOCK_Flexcan0); + break; + case MCUX_FLEXCAN1_CLK: + CLOCK_EnableClock(kCLOCK_Flexcan1); + break; + default: + break; + } +#endif /* defined(CONFIG_CAN_MCUX_MCAN) */ + +#ifdef CONFIG_ETH_NXP_ENET + if ((uint32_t)sub_system == MCUX_ENET_CLK) { +#ifdef CONFIG_SOC_SERIES_RW6XX + CLOCK_EnableClock(kCLOCK_TddrMciEnetClk); + CLOCK_EnableClock(kCLOCK_EnetIpg); + CLOCK_EnableClock(kCLOCK_EnetIpgS); +#endif + } +#endif + return 0; } @@ -292,6 +315,14 @@ static int mcux_lpc_syscon_clock_control_get_subsys_rate( break; #endif +#ifdef CONFIG_ETH_NXP_ENET + case MCUX_ENET_CLK: +#ifdef CONFIG_SOC_SERIES_RW6XX + *rate = CLOCK_GetTddrMciEnetClkFreq(); +#endif + break; +#endif + #if defined(CONFIG_MIPI_DBI_NXP_LCDIC) case MCUX_LCDIC_CLK: *rate = CLOCK_GetLcdClkFreq(); @@ -312,6 +343,21 @@ static int mcux_lpc_syscon_clock_control_get_subsys_rate( break; #endif #endif /* CONFIG_ADC_MCUX_LPADC */ + +#if defined(CONFIG_CAN_MCUX_FLEXCAN) + case MCUX_FLEXCAN0_CLK: + *rate = CLOCK_GetFlexcanClkFreq(0); + break; + case MCUX_FLEXCAN1_CLK: + *rate = CLOCK_GetFlexcanClkFreq(1); + break; +#endif /* defined(CONFIG_CAN_MCUX_FLEXCAN) */ + +#if defined(CONFIG_MCUX_FLEXIO) + case MCUX_FLEXIO0_CLK: + *rate = CLOCK_GetFlexioClkFreq(); + break; +#endif /* defined(CONFIG_MCUX_FLEXIO) */ } return 0; diff --git a/drivers/clock_control/clock_control_npcx.c b/drivers/clock_control/clock_control_npcx.c index eec3604aa7713..3875b28da7059 100644 --- a/drivers/clock_control/clock_control_npcx.c +++ b/drivers/clock_control/clock_control_npcx.c @@ -147,7 +147,7 @@ void npcx_clock_control_turn_off_system_sleep(void) #endif /* CONFIG_PM */ /* Clock controller driver registration */ -static struct clock_control_driver_api npcx_clock_control_api = { +static const struct clock_control_driver_api npcx_clock_control_api = { .on = npcx_clock_control_on, .off = npcx_clock_control_off, .get_rate = npcx_clock_control_get_subsys_rate, diff --git a/drivers/clock_control/clock_control_nrf_auxpll.c b/drivers/clock_control/clock_control_nrf_auxpll.c new file mode 100644 index 0000000000000..e313b5c056046 --- /dev/null +++ b/drivers/clock_control/clock_control_nrf_auxpll.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_nrf_auxpll + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* maximum lock time in ms, >10x time observed experimentally */ +#define AUXPLL_LOCK_TIME_MAX_MS 20 +/* lock wait step in ms*/ +#define AUXPLL_LOCK_WAIT_STEP_MS 1 + +struct clock_control_nrf_auxpll_config { + NRF_AUXPLL_Type *auxpll; + uint32_t ref_clk_hz; + uint32_t ficr_ctune; + nrf_auxpll_config_t cfg; + uint16_t frequency; + nrf_auxpll_ctrl_outsel_t out_div; +}; + +static int clock_control_nrf_auxpll_on(const struct device *dev, clock_control_subsys_t sys) +{ + const struct clock_control_nrf_auxpll_config *config = dev->config; + bool locked; + unsigned int wait = 0U; + + ARG_UNUSED(sys); + + nrf_auxpll_task_trigger(config->auxpll, NRF_AUXPLL_TASK_START); + + do { + locked = nrf_auxpll_mode_locked_check(config->auxpll); + if (!locked) { + k_msleep(AUXPLL_LOCK_WAIT_STEP_MS); + wait += AUXPLL_LOCK_WAIT_STEP_MS; + } + } while (wait < AUXPLL_LOCK_TIME_MAX_MS && !locked); + + return locked ? 0 : -ETIMEDOUT; +} + +static int clock_control_nrf_auxpll_off(const struct device *dev, clock_control_subsys_t sys) +{ + const struct clock_control_nrf_auxpll_config *config = dev->config; + + ARG_UNUSED(sys); + + nrf_auxpll_task_trigger(config->auxpll, NRF_AUXPLL_TASK_STOP); + + while (nrf_auxpll_running_check(config->auxpll)) { + } + + return 0; +} + +static int clock_control_nrf_auxpll_get_rate(const struct device *dev, clock_control_subsys_t sys, + uint32_t *rate) +{ + const struct clock_control_nrf_auxpll_config *config = dev->config; + uint8_t ratio; + + ARG_UNUSED(sys); + + ratio = nrf_auxpll_static_ratio_get(config->auxpll); + + *rate = (ratio * config->ref_clk_hz + + (config->ref_clk_hz * (uint64_t)config->frequency) / + (AUXPLL_AUXPLLCTRL_FREQUENCY_FREQUENCY_MaximumDiv + 1U)) / + config->out_div; + + return 0; +} + +static enum clock_control_status clock_control_nrf_auxpll_get_status(const struct device *dev, + clock_control_subsys_t sys) +{ + const struct clock_control_nrf_auxpll_config *config = dev->config; + + ARG_UNUSED(sys); + + if (nrf_auxpll_mode_locked_check(config->auxpll)) { + return CLOCK_CONTROL_STATUS_ON; + } + + return CLOCK_CONTROL_STATUS_OFF; +} + +static const struct clock_control_driver_api clock_control_nrf_auxpll_api = { + .on = clock_control_nrf_auxpll_on, + .off = clock_control_nrf_auxpll_off, + .get_rate = clock_control_nrf_auxpll_get_rate, + .get_status = clock_control_nrf_auxpll_get_status, +}; + +static int clock_control_nrf_auxpll_init(const struct device *dev) +{ + const struct clock_control_nrf_auxpll_config *config = dev->config; + + nrf_auxpll_ctrl_frequency_set(config->auxpll, config->frequency); + + nrf_auxpll_lock(config->auxpll); + nrf_auxpll_trim_ctune_set(config->auxpll, sys_read8(config->ficr_ctune)); + nrf_auxpll_config_set(config->auxpll, &config->cfg); + nrf_auxpll_ctrl_outsel_set(config->auxpll, config->out_div); + nrf_auxpll_unlock(config->auxpll); + + nrf_auxpll_ctrl_mode_set(config->auxpll, NRF_AUXPLL_CTRL_MODE_LOCKED); + + return 0; +} + +#define CLOCK_CONTROL_NRF_AUXPLL_DEFINE(n) \ + static const struct clock_control_nrf_auxpll_config config##n = { \ + .auxpll = (NRF_AUXPLL_Type *)DT_INST_REG_ADDR(n), \ + .ref_clk_hz = DT_PROP(DT_INST_CLOCKS_CTLR(n), clock_frequency), \ + .ficr_ctune = DT_REG_ADDR(DT_INST_PHANDLE(n, nordic_ficrs)) + \ + DT_INST_PHA(n, nordic_ficrs, offset), \ + .cfg = \ + { \ + .outdrive = DT_INST_PROP(n, nordic_out_drive), \ + .current_tune = DT_INST_PROP(n, nordic_current_tune), \ + .sdm_off = DT_INST_PROP(n, nordic_sdm_disable), \ + .dither_off = DT_INST_PROP(n, nordic_dither_disable), \ + .range = DT_INST_ENUM_IDX(n, nordic_range), \ + }, \ + .frequency = DT_INST_PROP(n, nordic_frequency), \ + .out_div = DT_INST_PROP(n, nordic_out_div), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, clock_control_nrf_auxpll_init, NULL, NULL, &config##n, \ + PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, \ + &clock_control_nrf_auxpll_api); + +DT_INST_FOREACH_STATUS_OKAY(CLOCK_CONTROL_NRF_AUXPLL_DEFINE) diff --git a/drivers/clock_control/clock_control_numaker_scc.c b/drivers/clock_control/clock_control_numaker_scc.c index f33d2da120a86..af36931e00dc2 100644 --- a/drivers/clock_control/clock_control_numaker_scc.c +++ b/drivers/clock_control/clock_control_numaker_scc.c @@ -95,7 +95,7 @@ static inline int numaker_scc_configure(const struct device *dev, clock_control_ } /* System clock controller driver registration */ -static struct clock_control_driver_api numaker_scc_api = { +static const struct clock_control_driver_api numaker_scc_api = { .on = numaker_scc_on, .off = numaker_scc_off, .get_rate = numaker_scc_get_rate, diff --git a/drivers/clock_control/clock_control_pwm.c b/drivers/clock_control/clock_control_pwm.c index 1936e3ab6cce2..92bcd31c91fe2 100644 --- a/drivers/clock_control/clock_control_pwm.c +++ b/drivers/clock_control/clock_control_pwm.c @@ -129,7 +129,7 @@ static int clock_control_pwm_init(const struct device *dev) return 0; } -static struct clock_control_driver_api clock_control_pwm_api = { +static const struct clock_control_driver_api clock_control_pwm_api = { .on = clock_control_pwm_on, .get_rate = clock_control_pwm_get_rate, .set_rate = clock_control_pwm_set_rate, diff --git a/drivers/clock_control/clock_control_rv32m1_pcc.c b/drivers/clock_control/clock_control_rv32m1_pcc.c index e7ea06986aae7..9d22b9efae0d7 100644 --- a/drivers/clock_control/clock_control_rv32m1_pcc.c +++ b/drivers/clock_control/clock_control_rv32m1_pcc.c @@ -58,7 +58,7 @@ static const struct clock_control_driver_api rv32m1_pcc_api = { }; #define RV32M1_PCC_INIT(inst) \ - static struct rv32m1_pcc_config rv32m1_pcc##inst##_config = { \ + static const struct rv32m1_pcc_config rv32m1_pcc##inst##_config = { \ .base_address = DT_INST_REG_ADDR(inst) \ }; \ \ diff --git a/drivers/clock_control/clock_control_sam_pmc.c b/drivers/clock_control/clock_control_sam_pmc.c index 801f5c37e8731..6c43e142a9cf6 100644 --- a/drivers/clock_control/clock_control_sam_pmc.c +++ b/drivers/clock_control/clock_control_sam_pmc.c @@ -129,7 +129,7 @@ atmel_sam_clock_control_get_status(const struct device *dev, return status; } -static struct clock_control_driver_api atmel_sam_clock_control_api = { +static const struct clock_control_driver_api atmel_sam_clock_control_api = { .on = atmel_sam_clock_control_on, .off = atmel_sam_clock_control_off, .get_rate = atmel_sam_clock_control_get_rate, diff --git a/drivers/clock_control/clock_control_smartbond.c b/drivers/clock_control/clock_control_smartbond.c index 60c98f8668a0f..536b83b414d34 100644 --- a/drivers/clock_control/clock_control_smartbond.c +++ b/drivers/clock_control/clock_control_smartbond.c @@ -10,7 +10,13 @@ #include #include #include +#include #include +#include +#if defined(CONFIG_BT_DA1469X) +#include +#endif +#include LOG_MODULE_REGISTER(clock_control, CONFIG_CLOCK_CONTROL_LOG_LEVEL); @@ -30,12 +36,15 @@ struct lpc_clock_state { .rc32k_freq = DT_PROP(DT_NODELABEL(rc32k), clock_frequency), }; -#define CALIBRATION_INTERVAL (DT_NODE_HAS_STATUS(DT_NODELABEL(rcx), okay) ? \ - DT_PROP(DT_NODELABEL(rcx), calibration_interval) : \ - DT_PROP(DT_NODELABEL(rc32k), calibration_interval)) +#define CALIBRATION_INTERVAL CONFIG_SMARTBOND_LP_OSC_CALIBRATION_INTERVAL + +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME +extern int z_clock_hw_cycles_per_sec; +#endif static void calibration_work_cb(struct k_work *work); static void xtal32k_settle_work_cb(struct k_work *work); +static enum smartbond_clock smartbond_source_clock(enum smartbond_clock clk); static K_WORK_DELAYABLE_DEFINE(calibration_work, calibration_work_cb); static K_WORK_DELAYABLE_DEFINE(xtal32k_settle_work, xtal32k_settle_work_cb); @@ -46,19 +55,38 @@ static void calibration_work_cb(struct k_work *work) da1469x_clock_lp_rcx_calibrate(); lpc_clock_state.rcx_ready = true; lpc_clock_state.rcx_freq = da1469x_clock_lp_rcx_freq_get(); - k_work_schedule(&calibration_work, - K_MSEC(1000 * CALIBRATION_INTERVAL)); LOG_DBG("RCX calibration done, RCX freq: %d", (int)lpc_clock_state.rcx_freq); - } else if (lpc_clock_state.rc32k_started) { + +#if defined(CONFIG_BT_DA1469X) + /* Update CMAC sleep clock with calculated frequency if RCX is set as lp_clk */ + if ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) == + (1 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos)) { + cmac_request_lp_clock_freq_set(lpc_clock_state.rcx_freq); + } +#endif + } + if (lpc_clock_state.rc32k_started) { da1469x_clock_lp_rc32k_calibrate(); lpc_clock_state.rc32k_ready = true; lpc_clock_state.rc32k_freq = da1469x_clock_lp_rc32k_freq_get(); - k_work_schedule(&calibration_work, - K_MSEC(1000 * CALIBRATION_INTERVAL)); LOG_DBG("RC32K calibration done, RC32K freq: %d", (int)lpc_clock_state.rc32k_freq); } + k_work_schedule(&calibration_work, + K_MSEC(1000 * CALIBRATION_INTERVAL)); +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + switch (smartbond_source_clock(SMARTBOND_CLK_LP_CLK)) { + case SMARTBOND_CLK_RCX: + z_clock_hw_cycles_per_sec = lpc_clock_state.rcx_freq; + break; + case SMARTBOND_CLK_RC32K: + z_clock_hw_cycles_per_sec = lpc_clock_state.rc32k_freq; + break; + default: + break; + } +#endif } static void xtal32k_settle_work_cb(struct k_work *work) @@ -66,6 +94,14 @@ static void xtal32k_settle_work_cb(struct k_work *work) if (lpc_clock_state.xtal32k_started && !lpc_clock_state.xtal32k_ready) { LOG_DBG("XTAL32K settled."); lpc_clock_state.xtal32k_ready = true; + +#if defined(CONFIG_BT_DA1469X) + /* Update CMAC sleep clock if XTAL32K is set as lp_clk */ + if ((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) == + (2 << CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos)) { + cmac_request_lp_clock_freq_set(32768); + } +#endif } } @@ -75,7 +111,7 @@ static void smartbond_start_rc32k(void) CRG_TOP->CLK_RC32K_REG |= CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk; } lpc_clock_state.rc32k_started = true; - if (!lpc_clock_state.rc32k_ready && (CALIBRATION_INTERVAL > 0)) { + if (!lpc_clock_state.rc32k_ready) { if (!k_work_is_pending(&calibration_work.work)) { k_work_schedule(&calibration_work, K_MSEC(1000 * CALIBRATION_INTERVAL)); @@ -90,7 +126,7 @@ static void smartbond_start_rcx(void) da1469x_clock_lp_rcx_enable(); lpc_clock_state.rcx_started = true; } - if (!lpc_clock_state.rcx_ready && (CALIBRATION_INTERVAL > 0)) { + if (!lpc_clock_state.rcx_ready) { if (!k_work_is_pending(&calibration_work.work)) { k_work_schedule(&calibration_work, K_MSEC(1000 * CALIBRATION_INTERVAL)); @@ -110,10 +146,59 @@ static void smartbond_start_xtal32k(void) } } +#ifdef CONFIG_REGULATOR +/* + * Should be used to control PLL when the regulator driver is available. + * If the latter is available, then the VDD level should be changed when + * switching to/from PLL. Otherwise, the VDD level is considered to + * be fixed @1.2V which should support both XTAL32M and PLL system clocks. + */ +static int smartbond_clock_set_pll_status(bool status) +{ + const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(vdd)); + int ret; + + if (!device_is_ready(dev)) { + LOG_ERR("Regulator device is not ready"); + return -ENODEV; + } + + if (status) { + /* Enabling PLL requires that VDD be raised to 1.2V */ + if (regulator_set_voltage(dev, 1200000, 1200000) == 0) { + da1469x_clock_sys_pll_enable(); + + /* QSPIC read pipe delay should be updated when switching to PLL */ + } else { + LOG_ERR("Failed to set VDD_LEVEL to 1.2V"); + return -EIO; + } + } else { + /* Disable PLL and switch back to XTAL32M */ + da1469x_clock_sys_pll_disable(); + + /* VDD level can now be switched back to 0.9V */ + ret = regulator_set_voltage(dev, 900000, 900000); + if (ret < 0) { + LOG_WRN("Failed to set VDD_LEVEL to 0.9V"); + } else { + /* + * System clock should be switched to XTAL32M and VDD should be set to 0.9. + * The QSPIC read pipe delay should be updated. + */ + da1469x_qspi_set_read_pipe_delay(QSPIC_ID, 2); + } + } + + return 0; +} +#endif + static inline int smartbond_clock_control_on(const struct device *dev, clock_control_subsys_t sub_system) { enum smartbond_clock clk = (enum smartbond_clock)(sub_system); + int ret = 0; ARG_UNUSED(dev); @@ -142,31 +227,34 @@ static inline int smartbond_clock_control_on(const struct device *dev, da1469x_clock_sys_xtal32m_enable(); da1469x_clock_sys_xtal32m_wait_to_settle(); } +#if CONFIG_REGULATOR + ret = smartbond_clock_set_pll_status(true); +#else da1469x_clock_sys_pll_enable(); +#endif } break; default: return -ENOTSUP; } - return 0; + return ret; } static inline int smartbond_clock_control_off(const struct device *dev, clock_control_subsys_t sub_system) { enum smartbond_clock clk = (enum smartbond_clock)(sub_system); + int ret = 0; ARG_UNUSED(dev); switch (clk) { case SMARTBOND_CLK_RC32K: - if (((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >> - CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Pos) != 0) { - CRG_TOP->CLK_RC32K_REG &= ~CRG_TOP_CLK_RC32K_REG_RC32K_ENABLE_Msk; - lpc_clock_state.rc32k_ready = false; - lpc_clock_state.rc32k_started = false; - } + /* RC32K is used by POWERUP and WAKEUP HW FSM */ + BUILD_ASSERT(DT_NODE_HAS_STATUS(DT_NODELABEL(rc32k), okay), + "RC32K is not allowed to be turned off"); + ret = -EPERM; break; case SMARTBOND_CLK_RCX: if (((CRG_TOP->CLK_CTRL_REG & CRG_TOP_CLK_CTRL_REG_LP_CLK_SEL_Msk) >> @@ -195,13 +283,27 @@ static inline int smartbond_clock_control_off(const struct device *dev, da1469x_clock_sys_xtal32m_enable(); break; case SMARTBOND_CLK_PLL96M: - da1469x_clock_sys_pll_disable(); + /* + * PLL must not be disabled as long as a peripheral e.g. LCDC is enabled + * and clocked by PLL. It's critical that PLL be not turned off if USB + * is active, as the latter is clocked by PLL/2 to generate the required + * clock for the full speed mode. + */ + if (!da1469x_clock_check_device_div1_clock()) { +#if CONFIG_REGULATOR + ret = smartbond_clock_set_pll_status(false); +#else + da1469x_clock_sys_pll_disable(); +#endif + } else { + ret = -EPERM; + } break; default: return -ENOTSUP; } - return 0; + return ret; } static enum smartbond_clock smartbond_source_clock(enum smartbond_clock clk) @@ -305,30 +407,6 @@ static void smartbond_clock_control_off_by_ord(const struct device *dev, smartbond_clock_control_off(dev, (clock_control_subsys_rate_t)clk); } -static void -qspi_set_read_pipe_delay(uint8_t delay) -{ - QSPIC->QSPIC_CTRLMODE_REG = - (QSPIC->QSPIC_CTRLMODE_REG & ~QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Msk) | - (delay << QSPIC_QSPIC_CTRLMODE_REG_QSPIC_PCLK_MD_Pos) | - QSPIC_QSPIC_CTRLMODE_REG_QSPIC_RPIPE_EN_Msk; -} - -static void -qspi_set_cs_delay(uint32_t sys_clock_freq, uint32_t read_delay_ns, uint32_t erase_delay_ns) -{ - sys_clock_freq /= 100000; - uint32_t read_delay_cyc = ((read_delay_ns * sys_clock_freq) + 9999) / 10000; - uint32_t erase_delay_cyc = ((erase_delay_ns * sys_clock_freq) + 9999) / 10000; - - QSPIC->QSPIC_BURSTCMDB_REG = - (QSPIC->QSPIC_BURSTCMDB_REG & ~QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Msk) | - read_delay_cyc << QSPIC_QSPIC_BURSTCMDB_REG_QSPIC_CS_HIGH_MIN_Pos; - QSPIC->QSPIC_ERASECMDB_REG = - (QSPIC->QSPIC_ERASECMDB_REG & ~QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Msk) | - (erase_delay_cyc << QSPIC_QSPIC_ERASECMDB_REG_QSPIC_ERS_CS_HI_Pos); -} - int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk) { int rc = 0; @@ -350,18 +428,58 @@ int z_smartbond_select_lp_clk(enum smartbond_clock lp_clk) } if (rc == 0) { +#ifdef CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME + switch (lp_clk) { + case SMARTBOND_CLK_RCX: + z_clock_hw_cycles_per_sec = lpc_clock_state.rcx_freq; + break; + case SMARTBOND_CLK_RC32K: + z_clock_hw_cycles_per_sec = lpc_clock_state.rc32k_freq; + break; + default: + z_clock_hw_cycles_per_sec = 32768; + break; + } +#endif CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG & ~clk_sel_msk) | clk_sel; } return rc; } +static void smartbond_clock_control_update_memory_settings(uint32_t sys_clock_freq) +{ + if (sys_clock_freq > 32000000) { + da1469x_qspi_set_read_pipe_delay(QSPIC_ID, 7); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + da1469x_qspi_set_read_pipe_delay(QSPIC2_ID, 7); +#endif + } else { + da1469x_qspi_set_read_pipe_delay(QSPIC_ID, 2); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + da1469x_qspi_set_read_pipe_delay(QSPIC2_ID, 2); +#endif + } + + da1469x_qspi_set_cs_delay(QSPIC_ID, SystemCoreClock, + DT_PROP(DT_NODELABEL(flash_controller), read_cs_idle_delay), + DT_PROP(DT_NODELABEL(flash_controller), erase_cs_idle_delay)); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + da1469x_qspi_set_cs_delay(QSPIC2_ID, SystemCoreClock, + DT_PROP(DT_NODELABEL(memc), read_cs_idle_min_ns), + DT_PROP_OR(DT_NODELABEL(memc), erase_cs_idle_min_ns, 0)); +#if DT_PROP(DT_NODELABEL(memc), is_ram) + da1469x_qspi_set_tcem(SystemCoreClock, DT_PROP(DT_NODELABEL(memc), tcem_max_us)); +#endif +#endif +} + int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk) { uint32_t sys_clock_freq; uint32_t clk_sel; uint32_t clk_sel_msk = CRG_TOP_CLK_CTRL_REG_SYS_CLK_SEL_Msk; - int res; + int res = 0; res = smartbond_clock_get_rate(sys_clk, &sys_clock_freq); if (res != 0) { @@ -370,12 +488,7 @@ int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk) /* When PLL is selected as system clock qspi read pipe delay must be set to 7 */ if (sys_clock_freq > 32000000) { - qspi_set_read_pipe_delay(7); - qspi_set_cs_delay(SystemCoreClock, - DT_PROP(DT_NODELABEL(flash_controller), - read_cs_idle_delay), - DT_PROP(DT_NODELABEL(flash_controller), - erase_cs_idle_delay)); + smartbond_clock_control_update_memory_settings(sys_clock_freq); } if (sys_clk == SMARTBOND_CLK_RC32M) { @@ -383,23 +496,34 @@ int z_smartbond_select_sys_clk(enum smartbond_clock sys_clk) CRG_TOP->CLK_CTRL_REG = (CRG_TOP->CLK_CTRL_REG & ~clk_sel_msk) | clk_sel; SystemCoreClock = sys_clock_freq; } else if (sys_clk == SMARTBOND_CLK_PLL96M) { - da1469x_clock_pll_wait_to_lock(); + /* Check that PLL is already enabled, otherwise enable it. */ + if (!da1469x_clock_sys_pll_is_enabled()) { +#if CONFIG_REGULATOR + res = smartbond_clock_set_pll_status(true); + if (res != 0) { + return -EIO; + } +#else + da1469x_clock_sys_pll_enable(); +#endif + } da1469x_clock_sys_pll_switch(); } else if (sys_clk == SMARTBOND_CLK_XTAL32M) { + /* + * XTAL32M should be enabled eitherway as it's not allowed + * to be turned off by application. + */ da1469x_clock_sys_xtal32m_switch_safe(); + } else { + return -EINVAL; } /* When switching back from PLL to 32MHz read pipe delay may be set to 2 */ if (SystemCoreClock <= 32000000) { - qspi_set_read_pipe_delay(2); - qspi_set_cs_delay(SystemCoreClock, - DT_PROP(DT_NODELABEL(flash_controller), - read_cs_idle_delay), - DT_PROP(DT_NODELABEL(flash_controller), - erase_cs_idle_delay)); + smartbond_clock_control_update_memory_settings(SystemCoreClock); } - return 0; + return res; } /** @@ -420,6 +544,11 @@ int smartbond_clocks_init(const struct device *dev) ARG_UNUSED(dev); +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + /* Make sure QSPIC2 is enabled */ + da1469x_clock_amba_enable(CRG_TOP_CLK_AMBA_REG_QSPI2_ENABLE_Msk); +#endif + #define ENABLE_OSC(clock) smartbond_clock_control_on_by_ord(dev, DT_DEP_ORD(clock)) #define DISABLE_OSC(clock) if (DT_NODE_HAS_STATUS(clock, disabled)) { \ smartbond_clock_control_off_by_ord(dev, DT_DEP_ORD(clock)); \ @@ -453,15 +582,42 @@ int smartbond_clocks_init(const struct device *dev) return 0; } -static struct clock_control_driver_api smartbond_clock_control_api = { +static const struct clock_control_driver_api smartbond_clock_control_api = { .on = smartbond_clock_control_on, .off = smartbond_clock_control_off, .get_rate = smartbond_clock_control_get_rate, }; +#if CONFIG_PM_DEVICE +static int smartbond_clocks_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + break; + case PM_DEVICE_ACTION_RESUME: +#if DT_NODE_HAS_STATUS(DT_NODELABEL(memc), okay) + /* Make sure QSPIC2 is enabled */ + da1469x_clock_amba_enable(CRG_TOP_CLK_AMBA_REG_QSPI2_ENABLE_Msk); +#endif + /* + * Make sure the flash controller has correct settings as clock restoration + * might have been performed upon waking up. + */ + smartbond_clock_control_update_memory_settings(SystemCoreClock); + break; + default: + return -ENOTSUP; + } + + return 0; +} +#endif + +PM_DEVICE_DT_DEFINE(DT_NODELABEL(osc), smartbond_clocks_pm_action); + DEVICE_DT_DEFINE(DT_NODELABEL(osc), &smartbond_clocks_init, - NULL, + PM_DEVICE_DT_GET(DT_NODELABEL(osc)), NULL, NULL, PRE_KERNEL_1, CONFIG_CLOCK_CONTROL_INIT_PRIORITY, diff --git a/drivers/clock_control/clock_stm32_ll_common.c b/drivers/clock_control/clock_stm32_ll_common.c index 024e336561673..be4c30a5aba0a 100644 --- a/drivers/clock_control/clock_stm32_ll_common.c +++ b/drivers/clock_control/clock_stm32_ll_common.c @@ -35,6 +35,28 @@ #define apb2_prescaler(v) fn_apb2_prescaler(v) #endif +#if defined(RCC_CFGR_ADCPRE) +#define z_adc12_prescaler(v) LL_RCC_ADC_CLKSRC_PCLK2_DIV_ ## v +#define adc12_prescaler(v) z_adc12_prescaler(v) +#elif defined(RCC_CFGR2_ADC1PRES) +#define z_adc12_prescaler(v) \ + COND_CODE_1(IS_EQ(v, 0), \ + LL_RCC_ADC1_CLKSRC_HCLK, \ + LL_RCC_ADC1_CLKSRC_PLL_DIV_ ## v) +#define adc12_prescaler(v) z_adc12_prescaler(v) +#else +#define z_adc12_prescaler(v) \ + COND_CODE_1(IS_EQ(v, 0), \ + (LL_RCC_ADC12_CLKSRC_HCLK), \ + (LL_RCC_ADC12_CLKSRC_PLL_DIV_ ## v)) +#define adc12_prescaler(v) z_adc12_prescaler(v) +#define z_adc34_prescaler(v) \ + COND_CODE_1(IS_EQ(v, 0), \ + (LL_RCC_ADC34_CLKSRC_HCLK), \ + (LL_RCC_ADC34_CLKSRC_PLL_DIV_ ## v)) +#define adc34_prescaler(v) z_adc34_prescaler(v) +#endif + #if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), ahb4_prescaler) #define RCC_CALC_FLASH_FREQ __LL_RCC_CALC_HCLK4_FREQ #define GET_CURRENT_FLASH_PRESCALER LL_RCC_GetAHB4Prescaler @@ -205,7 +227,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to change a wrong periph clock bit */ + /* Attempt to change a wrong periph clock bit */ return -ENOTSUP; } @@ -228,7 +250,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -451,7 +473,7 @@ static enum clock_control_status stm32_clock_control_get_status(const struct dev } } -static struct clock_control_driver_api stm32_clock_control_api = { +static const struct clock_control_driver_api stm32_clock_control_api = { .on = stm32_clock_control_on, .off = stm32_clock_control_off, .get_rate = stm32_clock_control_get_subsys_rate, @@ -733,6 +755,7 @@ int stm32_clock_control_init(const struct device *dev) /* Some clocks would be activated by default */ config_enable_default_clocks(); + config_regulator_voltage(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC); #if defined(FLASH_ACR_LATENCY) uint32_t old_flash_freq; @@ -750,7 +773,7 @@ int stm32_clock_control_init(const struct device *dev) } #endif /* FLASH_ACR_LATENCY */ - /* Set up indiviual enabled clocks */ + /* Set up individual enabled clocks */ set_up_fixed_clock_sources(); /* Set up PLLs */ @@ -813,13 +836,13 @@ int stm32_clock_control_init(const struct device *dev) LL_RCC_SetAHB4Prescaler(ahb_prescaler(STM32_AHB4_PRESCALER)); #endif #if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), adc_prescaler) - LL_RCC_SetADCClockSource(adc_prescaler(STM32_ADC_PRESCALER)); + LL_RCC_SetADCClockSource(adc12_prescaler(STM32_ADC_PRESCALER)); #endif #if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), adc12_prescaler) - LL_RCC_SetADCClockSource(adc_prescaler(STM32_ADC12_PRESCALER)); + LL_RCC_SetADCClockSource(adc12_prescaler(STM32_ADC12_PRESCALER)); #endif #if DT_NODE_HAS_PROP(DT_NODELABEL(rcc), adc34_prescaler) - LL_RCC_SetADCClockSource(adc_prescaler(STM32_ADC34_PRESCALER)); + LL_RCC_SetADCClockSource(adc34_prescaler(STM32_ADC34_PRESCALER)); #endif /* configure MCO1/MCO2 based on Kconfig */ @@ -838,6 +861,7 @@ void HAL_RCC_CSSCallback(void) } #endif +void __weak config_regulator_voltage(uint32_t hclk_freq) {} /** * @brief RCC device, note that priority is intentionally set to 1 so * that the device init runs just after SOC init diff --git a/drivers/clock_control/clock_stm32_ll_common.h b/drivers/clock_control/clock_stm32_ll_common.h index 5bab50d2e0dfa..a97d01337acac 100644 --- a/drivers/clock_control/clock_stm32_ll_common.h +++ b/drivers/clock_control/clock_stm32_ll_common.h @@ -49,9 +49,11 @@ void config_pll2(void); void config_plli2s(void); #endif void config_enable_default_clocks(void); +void config_regulator_voltage(uint32_t hclk_freq); -/* function exported to the soc power.c */ +/* functions exported to the soc power.c */ int stm32_clock_control_init(const struct device *dev); +void stm32_clock_control_standby_exit(void); #ifdef __cplusplus } diff --git a/drivers/clock_control/clock_stm32_ll_h5.c b/drivers/clock_control/clock_stm32_ll_h5.c index 28e2dd3e0092f..5f9ffdcc5b8dd 100644 --- a/drivers/clock_control/clock_stm32_ll_h5.c +++ b/drivers/clock_control/clock_stm32_ll_h5.c @@ -150,7 +150,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -171,7 +171,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -338,7 +338,7 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev, return 0; } -static struct clock_control_driver_api stm32_clock_control_api = { +static const struct clock_control_driver_api stm32_clock_control_api = { .on = stm32_clock_control_on, .off = stm32_clock_control_off, .get_rate = stm32_clock_control_get_subsys_rate, @@ -696,8 +696,8 @@ static void set_up_fixed_clock_sources(void) int stm32_clock_control_init(const struct device *dev) { - uint32_t old_hclk_freq = 0; - int r = 0; + uint32_t old_hclk_freq; + int r; ARG_UNUSED(dev); @@ -722,7 +722,7 @@ int stm32_clock_control_init(const struct device *dev) return r; } - /* Set peripheral busses prescalers */ + /* Set peripheral buses prescalers */ LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_AHB_PRESCALER)); LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_APB1_PRESCALER)); LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_APB2_PRESCALER)); diff --git a/drivers/clock_control/clock_stm32_ll_h7.c b/drivers/clock_control/clock_stm32_ll_h7.c index e4d78e5ce6032..bdbdf860e227f 100644 --- a/drivers/clock_control/clock_stm32_ll_h7.c +++ b/drivers/clock_control/clock_stm32_ll_h7.c @@ -21,7 +21,11 @@ /* Macros to fill up prescaler values */ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define z_hsi_divider(v) LL_RCC_HSI_DIV_ ## v +#else #define z_hsi_divider(v) LL_RCC_HSI_DIV ## v +#endif #define hsi_divider(v) z_hsi_divider(v) #define z_sysclk_prescaler(v) LL_RCC_SYSCLK_DIV_ ## v @@ -42,6 +46,9 @@ #define z_apb4_prescaler(v) LL_RCC_APB4_DIV_ ## v #define apb4_prescaler(v) z_apb4_prescaler(v) +#define z_apb5_prescaler(v) LL_RCC_APB5_DIV_ ## v +#define apb5_prescaler(v) z_apb5_prescaler(v) + /* Macro to check for clock feasibility */ /* It is Cortex M7's responsibility to setup clock tree */ /* This check should only be performed for the M7 core code */ @@ -81,12 +88,21 @@ #endif /* ARM Sys CPU Clock before HPRE prescaler */ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define SYSCLK_FREQ ((SYSCLKSRC_FREQ)/(STM32_D1CPRE)) +#define AHB_FREQ ((SYSCLK_FREQ)/(STM32_HPRE)) +#define APB1_FREQ ((AHB_FREQ)/(STM32_PPRE1)) +#define APB2_FREQ ((AHB_FREQ)/(STM32_PPRE2)) +#define APB4_FREQ ((AHB_FREQ)/(STM32_PPRE4)) +#define APB5_FREQ ((AHB_FREQ)/(STM32_PPRE5)) +#else #define SYSCLK_FREQ ((SYSCLKSRC_FREQ)/(STM32_D1CPRE)) #define AHB_FREQ ((SYSCLK_FREQ)/(STM32_HPRE)) #define APB1_FREQ ((AHB_FREQ)/(STM32_D2PPRE1)) #define APB2_FREQ ((AHB_FREQ)/(STM32_D2PPRE2)) #define APB3_FREQ ((AHB_FREQ)/(STM32_D1PPRE)) #define APB4_FREQ ((AHB_FREQ)/(STM32_D3PPRE)) +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ /* Datasheet maximum frequency definitions */ #if defined(CONFIG_SOC_STM32H743XX) ||\ @@ -112,6 +128,11 @@ #define SYSCLK_FREQ_MAX 280000000UL #define AHB_FREQ_MAX 280000000UL #define APBx_FREQ_MAX 140000000UL +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) +/* All h7RS SoC with maximum 500MHz SYSCLK (refer to Datasheet DS14359 rev 1) */ +#define SYSCLK_FREQ_MAX 500000000UL +#define AHB_FREQ_MAX 250000000UL +#define APBx_FREQ_MAX 125000000UL #else /* Default: All h7 SoC with maximum 280MHz SYSCLK */ #define SYSCLK_FREQ_MAX 280000000UL @@ -142,7 +163,7 @@ #error "SYS clock frequency for M7 core doesn't match CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC" #endif -/* end of clock feasability check */ +/* end of clock feasibility check */ #endif /* CONFIG_CPU_CORTEX_M7 */ @@ -154,7 +175,7 @@ * So, changing this prescaler is not allowed until it is made possible to * use them independently in zephyr clock subsystem. */ -#error "D1CPRE presacler can't be higher than 1" +#error "D1CPRE prescaler can't be higher than 1" #endif #endif /* CONFIG_CPU_CORTEX_M7 */ @@ -255,7 +276,11 @@ static int32_t prepare_regulator_voltage_scale(void) /* Make sure to put the CPU in highest Voltage scale during clock configuration */ /* Highest voltage is SCALE0 */ LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0); +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + while (LL_PWR_IsActiveFlag_VOSRDY() == 0) { +#else while (LL_PWR_IsActiveFlag_VOS() == 0) { +#endif } return 0; } @@ -290,8 +315,12 @@ static int32_t optimize_regulator_voltage_scale(uint32_t sysclk_freq) LL_PWR_ConfigSupply(LL_PWR_LDO_SUPPLY); #endif LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE0); +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + while (LL_PWR_IsActiveFlag_VOSRDY() == 0) { +#else while (LL_PWR_IsActiveFlag_VOS() == 0) { - } +#endif + }; return 0; } @@ -329,7 +358,7 @@ static uint32_t get_vco_output_range(uint32_t vco_input_range) #endif /* ! CONFIG_CPU_CORTEX_M4 */ -/** @brief Verifies clock is part of actve clock configuration */ +/** @brief Verifies clock is part of active clock configuration */ static int enabled_clock(uint32_t src_clk) { @@ -365,7 +394,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -391,7 +420,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -416,7 +445,7 @@ static inline int stm32_clock_control_configure(const struct device *dev, err = enabled_clock(pclken->bus); if (err < 0) { - /* Attemp to configure a src clock not available or not valid */ + /* Attempt to configure a src clock not available or not valid */ return err; } @@ -448,10 +477,17 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, #else uint32_t ahb_clock = get_bus_clock(SystemCoreClock, STM32_HPRE); #endif +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_PPRE1); + uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_PPRE2); + uint32_t apb4_clock = get_bus_clock(ahb_clock, STM32_PPRE4); + uint32_t apb5_clock = get_bus_clock(ahb_clock, STM32_PPRE5); +#else uint32_t apb1_clock = get_bus_clock(ahb_clock, STM32_D2PPRE1); uint32_t apb2_clock = get_bus_clock(ahb_clock, STM32_D2PPRE2); uint32_t apb3_clock = get_bus_clock(ahb_clock, STM32_D1PPRE); uint32_t apb4_clock = get_bus_clock(ahb_clock, STM32_D3PPRE); +#endif ARG_UNUSED(clock); @@ -469,12 +505,22 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, case STM32_CLOCK_BUS_APB2: *rate = apb2_clock; break; +#if !defined(CONFIG_SOC_SERIES_STM32H7RSX) case STM32_CLOCK_BUS_APB3: *rate = apb3_clock; break; +#endif /* !CONFIG_SOC_SERIES_STM32H7RSX */ case STM32_CLOCK_BUS_APB4: *rate = apb4_clock; break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_CLOCK_BUS_APB5: + *rate = apb5_clock; + break; + case STM32_CLOCK_BUS_AHB5: + *rate = ahb_clock; + break; +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ case STM32_SRC_SYSCLK: *rate = get_hclk_frequency(); break; @@ -522,6 +568,15 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, STM32_PLL_N_MULTIPLIER, STM32_PLL_R_DIVISOR); break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_SRC_PLL1_S: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL_M_DIVISOR, + STM32_PLL_N_MULTIPLIER, + STM32_PLL_S_DIVISOR); + break; + /* PLL 1 has no T-divider */ +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #endif /* STM32_PLL_ENABLED */ #if defined(STM32_PLL2_ENABLED) case STM32_SRC_PLL2_P: @@ -542,6 +597,20 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, STM32_PLL2_N_MULTIPLIER, STM32_PLL2_R_DIVISOR); break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_SRC_PLL2_S: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL2_M_DIVISOR, + STM32_PLL2_N_MULTIPLIER, + STM32_PLL2_S_DIVISOR); + break; + case STM32_SRC_PLL2_T: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL2_M_DIVISOR, + STM32_PLL2_N_MULTIPLIER, + STM32_PLL2_T_DIVISOR); + break; +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #endif /* STM32_PLL2_ENABLED */ #if defined(STM32_PLL3_ENABLED) case STM32_SRC_PLL3_P: @@ -562,6 +631,15 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, STM32_PLL3_N_MULTIPLIER, STM32_PLL3_R_DIVISOR); break; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + case STM32_SRC_PLL3_S: + *rate = get_pllout_frequency(get_pllsrc_frequency(), + STM32_PLL3_M_DIVISOR, + STM32_PLL3_N_MULTIPLIER, + STM32_PLL3_S_DIVISOR); + break; + /* PLL 3 has no T-divider */ +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #endif /* STM32_PLL3_ENABLED */ default: return -ENOTSUP; @@ -570,7 +648,7 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, return 0; } -static struct clock_control_driver_api stm32_clock_control_api = { +static const struct clock_control_driver_api stm32_clock_control_api = { .on = stm32_clock_control_on, .off = stm32_clock_control_off, .get_rate = stm32_clock_control_get_subsys_rate, @@ -739,6 +817,12 @@ static int set_up_plls(void) LL_RCC_PLL1R_Enable(); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + if (IS_ENABLED(STM32_PLL_S_ENABLED)) { + LL_RCC_PLL1_SetS(STM32_PLL_S_DIVISOR); + LL_RCC_PLL1S_Enable(); + } +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ LL_RCC_PLL1_Enable(); while (LL_RCC_PLL1_IsReady() != 1U) { } @@ -777,6 +861,18 @@ static int set_up_plls(void) LL_RCC_PLL2R_Enable(); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + if (IS_ENABLED(STM32_PLL2_S_ENABLED)) { + LL_RCC_PLL2_SetS(STM32_PLL2_S_DIVISOR); + LL_RCC_PLL2S_Enable(); + } + + if (IS_ENABLED(STM32_PLL2_T_ENABLED)) { + LL_RCC_PLL2_SetT(STM32_PLL2_T_DIVISOR); + LL_RCC_PLL2T_Enable(); + } + +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ LL_RCC_PLL2_Enable(); while (LL_RCC_PLL2_IsReady() != 1U) { } @@ -815,6 +911,13 @@ static int set_up_plls(void) LL_RCC_PLL3R_Enable(); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + if (IS_ENABLED(STM32_PLL3_S_ENABLED)) { + LL_RCC_PLL3_SetS(STM32_PLL3_S_DIVISOR); + LL_RCC_PLL3S_Enable(); + } + +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ LL_RCC_PLL3_Enable(); while (LL_RCC_PLL3_IsReady() != 1U) { } @@ -830,29 +933,114 @@ static int set_up_plls(void) return 0; } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +/* adapted from the stm32cube SystemCoreClockUpdate*/ +void stm32_system_clock_update(void) +{ + uint32_t sysclk, hsivalue, pllsource, pllm, pllp, core_presc; + float_t pllfracn, pllvco; + + /* Get SYSCLK source */ + switch (RCC->CFGR & RCC_CFGR_SWS) { + case 0x00: /* HSI used as system clock source (default after reset) */ + sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) + >> RCC_CR_HSIDIV_Pos)); + break; + + case 0x08: /* CSI used as system clock source */ + sysclk = CSI_VALUE; + break; + + case 0x10: /* HSE used as system clock source */ + sysclk = HSE_VALUE; + break; + + case 0x18: /* PLL1 used as system clock source */ + /* + * PLL1_VCO = (HSE_VALUE or HSI_VALUE or CSI_VALUE/ PLLM) * PLLN + * SYSCLK = PLL1_VCO / PLL1R + */ + pllsource = (RCC->PLLCKSELR & RCC_PLLCKSELR_PLLSRC); + pllm = ((RCC->PLLCKSELR & RCC_PLLCKSELR_DIVM1) >> RCC_PLLCKSELR_DIVM1_Pos); + + if ((RCC->PLLCFGR & RCC_PLLCFGR_PLL1FRACEN) != 0U) { + pllfracn = (float_t)(uint32_t)(((RCC->PLL1FRACR & RCC_PLL1FRACR_FRACN) + >> RCC_PLL1FRACR_FRACN_Pos)); + } else { + pllfracn = (float_t)0U; + } + + if (pllm != 0U) { + switch (pllsource) { + case 0x02: /* HSE used as PLL1 clock source */ + pllvco = ((float_t)HSE_VALUE / (float_t)pllm) * + ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + + (pllfracn/(float_t)0x2000) + (float_t)1); + break; + + case 0x01: /* CSI used as PLL1 clock source */ + pllvco = ((float_t)CSI_VALUE / (float_t)pllm) * + ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + + (pllfracn/(float_t)0x2000) + (float_t)1); + break; + + case 0x00: /* HSI used as PLL1 clock source */ + default: + hsivalue = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> + RCC_CR_HSIDIV_Pos)); + pllvco = ((float_t)hsivalue / (float_t)pllm) * + ((float_t)(uint32_t)(RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVN) + + (pllfracn/(float_t)0x2000) + (float_t)1); + break; + } + + pllp = (((RCC->PLL1DIVR1 & RCC_PLL1DIVR1_DIVP) >> + RCC_PLL1DIVR1_DIVP_Pos) + 1U); + sysclk = (uint32_t)(float_t)(pllvco/(float_t)pllp); + } else { + sysclk = 0U; + } + break; + + default: /* Unexpected, default to HSI used as system clk source (default after reset) */ + sysclk = (HSI_VALUE >> ((RCC->CR & RCC_CR_HSIDIV) >> RCC_CR_HSIDIV_Pos)); + break; + } + + /* system clock frequency : CM7 CPU frequency */ + core_presc = (RCC->CDCFGR & RCC_CDCFGR_CPRE); + + if (core_presc >= 8U) { + SystemCoreClock = (sysclk >> (core_presc - RCC_CDCFGR_CPRE_3 + 1U)); + } else { + SystemCoreClock = sysclk; + } +} +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ + int stm32_clock_control_init(const struct device *dev) { int r = 0; #if defined(CONFIG_CPU_CORTEX_M7) - uint32_t old_hclk_freq = 0; - uint32_t new_hclk_freq = 0; + uint32_t old_hclk_freq; + uint32_t new_hclk_freq; /* HW semaphore Clock enable */ #if defined(CONFIG_SOC_STM32H7A3XX) || defined(CONFIG_SOC_STM32H7A3XXQ) || \ defined(CONFIG_SOC_STM32H7B0XX) || defined(CONFIG_SOC_STM32H7B0XXQ) || \ defined(CONFIG_SOC_STM32H7B3XX) || defined(CONFIG_SOC_STM32H7B3XXQ) LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_HSEM); -#else +#elif !defined(CONFIG_SOC_SERIES_STM32H7RSX) + /* The stm32h7RS serie has no HSEM peripheral */ LL_AHB4_GRP1_EnableClock(LL_AHB4_GRP1_PERIPH_HSEM); #endif - z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); /* Configure MCO1/MCO2 based on Kconfig */ stm32_clock_control_mco_init(); - /* Set up indiviual enabled clocks */ + /* Set up individual enabled clocks */ set_up_fixed_clock_sources(); /* Set up PLLs */ @@ -871,22 +1059,38 @@ int stm32_clock_control_init(const struct device *dev) STM32_HPRE); /* Set flash latency */ + /* AHB/AXI/HCLK clock is SYSCLK / HPRE */ /* If freq increases, set flash latency before any clock setting */ if (new_hclk_freq > old_hclk_freq) { LL_SetFlashLatency(new_hclk_freq); } +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + /* + * The default Flash latency is 3 WS which is not enough, + * set higher and correct later if needed + */ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_6); +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ - /* Preset the prescalers prior to chosing SYSCLK */ + /* Preset the prescalers prior to choosing SYSCLK */ /* Prevents APB clock to go over limits */ /* Set buses (Sys,AHB, APB1, APB2 & APB4) prescalers */ LL_RCC_SetSysPrescaler(sysclk_prescaler(STM32_D1CPRE)); LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_HPRE)); +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_PPRE1)); + LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_PPRE2)); + LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_PPRE4)); + LL_RCC_SetAPB5Prescaler(apb5_prescaler(STM32_PPRE5)); + +#else LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_D2PPRE1)); LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_D2PPRE2)); LL_RCC_SetAPB3Prescaler(apb3_prescaler(STM32_D1PPRE)); LL_RCC_SetAPB4Prescaler(apb4_prescaler(STM32_D3PPRE)); +#endif /* Set up sys clock */ if (IS_ENABLED(STM32_SYSCLK_SRC_PLL)) { /* Set PLL1 as System Clock Source */ diff --git a/drivers/clock_control/clock_stm32_ll_mco.h b/drivers/clock_control/clock_stm32_ll_mco.h index d98c4a116e8e1..b526f13a1b22d 100644 --- a/drivers/clock_control/clock_stm32_ll_mco.h +++ b/drivers/clock_control/clock_stm32_ll_mco.h @@ -33,7 +33,8 @@ #elif CONFIG_CLOCK_STM32_MCO1_SRC_PLLQCLK #if (CONFIG_SOC_SERIES_STM32G0X || CONFIG_SOC_SERIES_STM32WLX) #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLLQCLK - #elif (CONFIG_SOC_SERIES_STM32H5X || CONFIG_SOC_SERIES_STM32H7X) + #elif (CONFIG_SOC_SERIES_STM32H5X || \ + CONFIG_SOC_SERIES_STM32H7X || CONFIG_SOC_SERIES_STM32H7RSX) #define MCO1_SOURCE LL_RCC_MCO1SOURCE_PLL1QCLK #else #error "PLLQCLK is not a valid clock source on your SOC" diff --git a/drivers/clock_control/clock_stm32_ll_mp1.c b/drivers/clock_control/clock_stm32_ll_mp1.c index 6a8e1978f84f5..e0ffedda3a86a 100644 --- a/drivers/clock_control/clock_stm32_ll_mp1.c +++ b/drivers/clock_control/clock_stm32_ll_mp1.c @@ -393,7 +393,7 @@ static int stm32_clock_control_get_subsys_rate(const struct device *clock, return 0; } -static struct clock_control_driver_api stm32_clock_control_api = { +static const struct clock_control_driver_api stm32_clock_control_api = { .on = stm32_clock_control_on, .off = stm32_clock_control_off, .get_rate = stm32_clock_control_get_subsys_rate, diff --git a/drivers/clock_control/clock_stm32_ll_u5.c b/drivers/clock_control/clock_stm32_ll_u5.c index ec4d11546f3d4..2c7e12f287255 100644 --- a/drivers/clock_control/clock_stm32_ll_u5.c +++ b/drivers/clock_control/clock_stm32_ll_u5.c @@ -125,7 +125,7 @@ static int enabled_clock(uint32_t src_clk) if ((src_clk == STM32_SRC_SYSCLK) || ((src_clk == STM32_SRC_HSE) && IS_ENABLED(STM32_HSE_ENABLED)) || ((src_clk == STM32_SRC_HSI16) && IS_ENABLED(STM32_HSI_ENABLED)) || -+ ((src_clk == STM32_SRC_HSI48) && IS_ENABLED(STM32_HSI48_ENABLED)) || + ((src_clk == STM32_SRC_HSI48) && IS_ENABLED(STM32_HSI48_ENABLED)) || ((src_clk == STM32_SRC_LSE) && IS_ENABLED(STM32_LSE_ENABLED)) || ((src_clk == STM32_SRC_LSI) && IS_ENABLED(STM32_LSI_ENABLED)) || ((src_clk == STM32_SRC_MSIS) && IS_ENABLED(STM32_MSIS_ENABLED)) || @@ -154,7 +154,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -175,7 +175,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -351,10 +351,36 @@ static int stm32_clock_control_get_subsys_rate(const struct device *dev, return 0; } -static struct clock_control_driver_api stm32_clock_control_api = { +static enum clock_control_status stm32_clock_control_get_status(const struct device *dev, + clock_control_subsys_t sub_system) +{ + struct stm32_pclken *pclken = (struct stm32_pclken *)sub_system; + + ARG_UNUSED(dev); + + if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == true) { + /* Gated clocks */ + if ((sys_read32(DT_REG_ADDR(DT_NODELABEL(rcc)) + pclken->bus) & pclken->enr) + == pclken->enr) { + return CLOCK_CONTROL_STATUS_ON; + } else { + return CLOCK_CONTROL_STATUS_OFF; + } + } else { + /* Domain clock sources */ + if (enabled_clock(pclken->bus) == 0) { + return CLOCK_CONTROL_STATUS_ON; + } else { + return CLOCK_CONTROL_STATUS_OFF; + } + } +} + +static const struct clock_control_driver_api stm32_clock_control_api = { .on = stm32_clock_control_on, .off = stm32_clock_control_off, .get_rate = stm32_clock_control_get_subsys_rate, + .get_status = stm32_clock_control_get_status, .configure = stm32_clock_control_configure, }; @@ -715,7 +741,7 @@ static void set_up_fixed_clock_sources(void) while (!LL_RCC_LSE_IsReady()) { } - /* Enable LSESYS additionnally */ + /* Enable LSESYS additionally */ LL_RCC_LSE_EnablePropagation(); /* Wait till LSESYS is ready */ while (!LL_RCC_LSESYS_IsReady()) { @@ -804,8 +830,8 @@ static void set_up_fixed_clock_sources(void) int stm32_clock_control_init(const struct device *dev) { - uint32_t old_hclk_freq = 0; - int r = 0; + uint32_t old_hclk_freq; + int r; ARG_UNUSED(dev); @@ -830,7 +856,7 @@ int stm32_clock_control_init(const struct device *dev) return r; } - /* Set peripheral busses prescalers */ + /* Set peripheral buses prescalers */ LL_RCC_SetAHBPrescaler(ahb_prescaler(STM32_AHB_PRESCALER)); LL_RCC_SetAPB1Prescaler(apb1_prescaler(STM32_APB1_PRESCALER)); LL_RCC_SetAPB2Prescaler(apb2_prescaler(STM32_APB2_PRESCALER)); diff --git a/drivers/clock_control/clock_stm32_ll_wba.c b/drivers/clock_control/clock_stm32_ll_wba.c index 17857c0e7ca74..ceb528ccd702e 100644 --- a/drivers/clock_control/clock_stm32_ll_wba.c +++ b/drivers/clock_control/clock_stm32_ll_wba.c @@ -67,7 +67,7 @@ static inline int stm32_clock_control_on(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -88,7 +88,7 @@ static inline int stm32_clock_control_off(const struct device *dev, ARG_UNUSED(dev); if (IN_RANGE(pclken->bus, STM32_PERIPH_BUS_MIN, STM32_PERIPH_BUS_MAX) == 0) { - /* Attemp to toggle a wrong periph clock bit */ + /* Attempt to toggle a wrong periph clock bit */ return -ENOTSUP; } @@ -290,7 +290,7 @@ static enum clock_control_status stm32_clock_control_get_status(const struct dev } } -static struct clock_control_driver_api stm32_clock_control_api = { +static const struct clock_control_driver_api stm32_clock_control_api = { .on = stm32_clock_control_on, .off = stm32_clock_control_off, .get_rate = stm32_clock_control_get_subsys_rate, @@ -487,7 +487,7 @@ static void set_up_fixed_clock_sources(void) /* Wait for LSE ready */ } - /* Enable LSESYS additionnally */ + /* Enable LSESYS additionally */ LL_RCC_LSE_EnablePropagation(); /* Wait till LSESYS is ready */ while (!LL_RCC_LSE_IsPropagationReady()) { @@ -510,7 +510,7 @@ static void set_up_fixed_clock_sources(void) int stm32_clock_control_init(const struct device *dev) { uint32_t old_flash_freq; - int r = 0; + int r; ARG_UNUSED(dev); diff --git a/drivers/clock_control/clock_stm32f0_f3.c b/drivers/clock_control/clock_stm32f0_f3.c index a4843782dfdcb..2557355a6f419 100644 --- a/drivers/clock_control/clock_stm32f0_f3.c +++ b/drivers/clock_control/clock_stm32f0_f3.c @@ -15,28 +15,6 @@ #include #include "clock_stm32_ll_common.h" -#if defined(RCC_CFGR_ADCPRE) -#define z_adc_prescaler(v) LL_RCC_ADC_CLKSRC_PCLK2_DIV_ ## v -#define adc_prescaler(v) z_adc_prescaler(v) -#elif defined(RCC_CFGR2_ADC1PRES) -#define z_adc12_prescaler(v) \ - COND_CODE_1(IS_EQ(v, 0), \ - LL_RCC_ADC1_CLKSRC_HCLK, \ - LL_RCC_ADC1_CLKSRC_PLL_DIV_ ## v) -#define adc12_prescaler(v) z_adc12_prescaler(v) -#else -#define z_adc12_prescaler(v) \ - COND_CODE_1(IS_EQ(v, 0), \ - LL_RCC_ADC12_CLKSRC_HCLK, \ - LL_RCC_ADC12_CLKSRC_PLL_DIV_ ## v) -#define adc12_prescaler(v) z_adc12_prescaler(v) -#define z_adc34_prescaler(v) \ - COND_CODE_1(IS_EQ(v, 0), \ - LL_RCC_ADC34_CLKSRC_HCLK, \ - LL_RCC_ADC34_CLKSRC_PLL_DIV_ ## v) -#define adc34_prescaler(v) z_adc34_prescaler(v) -#endif - #if defined(STM32_PLL_ENABLED) /** diff --git a/drivers/clock_control/clock_stm32f1.c b/drivers/clock_control/clock_stm32f1.c index c882fcc40df72..760e417eaab0e 100644 --- a/drivers/clock_control/clock_stm32f1.c +++ b/drivers/clock_control/clock_stm32f1.c @@ -21,9 +21,6 @@ #define STM32_USB_PRE_ENABLED RCC_CFGR_OTGFSPRE #endif -#define z_adc_prescaler(v) LL_RCC_ADC_CLKSRC_PCLK2_DIV_ ## v -#define adc_prescaler(v) z_adc_prescaler(v) - #if defined(STM32_PLL_ENABLED) /* diff --git a/drivers/clock_control/clock_stm32l0_l1.c b/drivers/clock_control/clock_stm32l0_l1.c index 8099993d8660c..d378b12852561 100644 --- a/drivers/clock_control/clock_stm32l0_l1.c +++ b/drivers/clock_control/clock_stm32l0_l1.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -81,6 +82,22 @@ uint32_t get_pllout_frequency(void) #endif /* defined(STM32_PLL_ENABLED) */ +/** + * @brief Set up voltage regulator voltage + */ +void config_regulator_voltage(uint32_t hclk_freq) +{ + if (hclk_freq <= MHZ(4.2)) { + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE3); + } else if (hclk_freq <= MHZ(16)) { + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE2); + } else { + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + } + while (LL_PWR_IsActiveFlag_VOS() == 1) { + } +} + /** * @brief Activate default clocks */ @@ -92,4 +109,5 @@ void config_enable_default_clocks(void) /* Enable System Configuration Controller clock. */ LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG); #endif + LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR); } diff --git a/drivers/console/CMakeLists.txt b/drivers/console/CMakeLists.txt index 8e5e26aaabc9b..b31486dee4242 100644 --- a/drivers/console/CMakeLists.txt +++ b/drivers/console/CMakeLists.txt @@ -1,13 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 -zephyr_syscall_header_ifdef( - CONFIG_UART_MUX - ${ZEPHYR_BASE}/include/zephyr/drivers/console/uart_mux.h -) - zephyr_library() -zephyr_library_sources_ifdef(CONFIG_GSM_MUX gsm_mux.c) zephyr_library_sources_ifdef(CONFIG_IPM_CONSOLE_RECEIVER ipm_console_receiver.c) zephyr_library_sources_ifdef(CONFIG_IPM_CONSOLE_SENDER ipm_console_sender.c) zephyr_library_sources_ifdef(CONFIG_IPM_CONSOLE ipm_console.c) @@ -18,7 +12,6 @@ zephyr_library_sources_ifdef(CONFIG_RTT_CONSOLE rtt_console.c) zephyr_library_sources_ifdef(CONFIG_SEMIHOST_CONSOLE semihost_console.c) zephyr_library_sources_ifdef(CONFIG_UART_CONSOLE uart_console.c) zephyr_library_sources_ifdef(CONFIG_UART_MCUMGR uart_mcumgr.c) -zephyr_library_sources_ifdef(CONFIG_UART_MUX uart_mux.c) zephyr_library_sources_ifdef(CONFIG_XTENSA_SIM_CONSOLE xtensa_sim_console.c) zephyr_library_sources_ifdef(CONFIG_EFI_CONSOLE efi_console.c) zephyr_library_sources_ifdef(CONFIG_WINSTREAM_CONSOLE winstream_console.c) diff --git a/drivers/console/Kconfig b/drivers/console/Kconfig index 28dcf9fbc16ba..2fd0111a9dd52 100644 --- a/drivers/console/Kconfig +++ b/drivers/console/Kconfig @@ -34,7 +34,6 @@ config CONSOLE_HANDLER config CONSOLE_INIT_PRIORITY int "Console init priority" - default 95 if UART_MUX default 60 if UART_CONSOLE || XTENSA_SIM_CONSOLE default KERNEL_INIT_PRIORITY_DEFAULT help @@ -96,21 +95,37 @@ config JAILHOUSE_DEBUG_CONSOLE Useful in board bring-up if there aren't any working serial drivers. +# Workaround for not being able to have commas in macro arguments +DT_CHOSEN_Z_RAM_CONSOLE := zephyr,ram-console + config RAM_CONSOLE bool "Use RAM console" select CONSOLE_HAS_DRIVER + select RAM_CONSOLE_BUFFER_SECTION if $(dt_chosen_enabled,$(DT_CHOSEN_Z_RAM_CONSOLE)) help Emit console messages to a RAM buffer "ram_console" which can be examined at runtime with a debugger. Useful in board bring-up if there aren't any working serial drivers. +config RAM_CONSOLE_BUFFER_SECTION + bool "Use dedicated section as RAM console buffer" + depends on RAM_CONSOLE && $(dt_chosen_enabled,$(DT_CHOSEN_Z_RAM_CONSOLE)) + select KERNEL_DIRECT_MAP if MMU + help + Use a dedicated section as the RAM console buffer, whose address is + known before build so that the console output messages can be easily + examined by a debugger or software tool from a parallel-running OS. + config RAM_CONSOLE_BUFFER_SIZE int "Ram Console buffer size" + default $(dt_chosen_reg_size_int,$(DT_CHOSEN_Z_RAM_CONSOLE)) if RAM_CONSOLE_BUFFER_SECTION default 1024 depends on RAM_CONSOLE help - Size of the RAM console buffer. Messages will wrap around if the - length is exceeded. + Total size of the RAM console buffer, to ensure it's always + NULL-terminated leave one byte unused, the actual length is + one byte less. Messages will wrap around if the actual length + is exceeded. config RTT_CONSOLE bool "Use RTT console" @@ -254,84 +269,6 @@ module = UART_CONSOLE module-str = UART console source "subsys/logging/Kconfig.template.log_config" -source "drivers/console/Kconfig.gsm_mux" - -config UART_MUX - bool "[DEPRECATED] UART muxing (GSM 07.10) support [EXPERIMENTAL]" - depends on SERIAL_SUPPORT_INTERRUPT && GSM_MUX - select UART_INTERRUPT_DRIVEN - select EXPERIMENTAL - select DEPRECATED - help - Enable this option to create UART muxer that run over a physical - UART. The GSM 07.10 muxing protocol is used to separate the data - between these muxed UARTs. - -if UART_MUX - -config UART_MUX_DEVICE_NAME - string "UART mux device name template" - default "GSM" - help - Device name template for the UART mux Devices. First device would - have name $(UART_MUX_DEVICE_NAME)_0, etc. User will access muxed - UART using this name. - -config UART_MUX_RINGBUF_SIZE - int "UART mux ring buffer size" - default 256 - help - UART mux ring buffer size when passing data from RX ISR to worker - thread that will do the unmuxing. - -config UART_MUX_TEMP_BUF_SIZE - int "Size of the temp buffer when reading data from real UART" - default 32 - help - Size of the temporary RX buffer in receiving ISR. - -config UART_MUX_DEVICE_COUNT - int "Number of UART mux devices (DLCIs)" - default GSM_MUX_DLCI_MAX - range 1 64 - help - Number of instances of UART muxes. Default value is set by - maximum number of DLCIs (Data Link Connection Identifiers) - configured in the system. - -config UART_MUX_REAL_DEVICE_COUNT - int "Number of real UART devices" - default 1 - help - Tells how many real UART devices there are. Typically there is - only one UART and the muxed UARTs are run on top of that. If you have - two modems for example, then you would need to increase this to two. - -config UART_MUX_RX_STACK_SIZE - int "Size of the stack allocated for receiving data from UART" - default 512 - help - Sets the stack size which will be used by the PPP RX workqueue. - -config UART_MUX_RX_PRIORITY - int "RX workqueue thread priority" - default 7 - help - Sets the priority of the RX workqueue thread. - -module = UART_MUX -module-str = UART mux -source "subsys/logging/Kconfig.template.log_config" - -endif # UART_MUX - -config UART_MUX_VERBOSE_DEBUG - bool "Print hexdump of sent and received packets" - depends on UART_MUX_LOG_LEVEL_DBG - help - As there might be lot of debug output printed, only enable - this if really needed. - config EFI_CONSOLE bool "Use EFI console for console output" select CONSOLE_HAS_DRIVER diff --git a/drivers/console/Kconfig.gsm_mux b/drivers/console/Kconfig.gsm_mux deleted file mode 100644 index 100b5d54303b5..0000000000000 --- a/drivers/console/Kconfig.gsm_mux +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright (c) 2020 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -config GSM_MUX - bool "[DEPRECATED] GSM 07.10 muxing protocol" - select CRC - select DEPRECATED - help - Enable GSM 07.10 muxing protocol defined in - https://www.etsi.org/deliver/etsi_ts/101300_101399/101369/07.01.00_60/ts_101369v070100p.pdf - The muxing protocol allows GSM modem to share the same UART for both - the PPP data and AT commands. - -config GSM_MUX_MAX - int "Max number of GSM mux instances" - default 1 - depends on GSM_MUX - help - Usually we only need one GSM mux instance. You need to increase - this if you have more than one GSM modems. - -config GSM_MUX_DLCI_MAX - int "Max number of GSM data link connection (DLC) instances" - default 3 - range 1 64 - depends on GSM_MUX - help - For our purposes we will manage with 3 DLCI (control, ppp, and AT - commands) so making it the default value. If GSM modem also provides - GNSS (location) services and you want to create a DLCI for it, then - you need to increase this to 4. - -config GSM_MUX_DLCI_AT - int "DLCI id of the AT commands channel" - default 2 if MODEM_GSM_SIMCOM - default 1 - range 1 63 - depends on GSM_MUX - help - Channel number for the AT commands to the modem. - -config GSM_MUX_DLCI_PPP - int "DLCI id of the PPP connection channel" - default 1 if MODEM_GSM_SIMCOM - default 2 - range 1 63 - depends on GSM_MUX - help - Channel number for the PPP connection to the modem. - SIMCOM modem has 16kb buffer for DLCI 1 so the manual recommends - it for PPP traffic. For other DLCIs in that modem, the buffer size - is only 1kb. - -config GSM_MUX_PENDING_CMD_MAX - int "Max number of pending GSM mux commands" - default 2 - range 1 8 - depends on GSM_MUX - help - How many pending GSM mux commands can exists. - -config GSM_MUX_MRU_DEFAULT_LEN - int "Default size of received user data (MRU)" - default 127 if MODEM_GSM_SIMCOM - default 127 if MODEM_GSM_QUECTEL - default 31 - range 1 1509 - depends on GSM_MUX - help - Default MRU (Maximum Receive Unit) data size. The default - value for Basic mode is 31 bytes. The 1509 limit comes from - ublox-sara modem and it means we can transfer full Ethernet sized - frame and muxing headers. - -config GSM_MUX_MRU_MAX_LEN - int "Max size of received user data (MRU)" - default 255 if MODEM_GSM_SIMCOM - default 128 - range 1 1509 - depends on GSM_MUX - help - Max MRU (Maximum Receive Unit) data size. The default max - value for Basic mode is 128 bytes. - -config GSM_MUX_INITIATOR - bool "Are we the initiator of the connection" - default y - depends on GSM_MUX - help - Default value when deciding whether we are the initiator of the - connection attempt. Normally this should be enabled. - -config GSM_MUX_T1_TIMEOUT - int "T1 timeout in ms" - default 0 - range 0 5000 - depends on GSM_MUX - help - T1 timeout is initial command timeout when establishing - the connection. The value is in milliseconds. Zero value - means that default (100 ms) specified in the code is used. - -if GSM_MUX - -module = GSM_MUX -module-dep = LOG -module-str = Log level for GSM 07.10 Mux driver -module-help = Sets log level for GSM 07.10 Mux Device Driver. -source "subsys/net/Kconfig.template.log_config.net" - -config GSM_MUX_VERBOSE_DEBUG - bool "Print hexdump of sent and received packets" - depends on GSM_MUX_LOG_LEVEL_DBG - help - As there might be lot of debug output printed, only enable - this if really needed. - -endif diff --git a/drivers/console/gsm_mux.c b/drivers/console/gsm_mux.c deleted file mode 100644 index c7e8793b6ae79..0000000000000 --- a/drivers/console/gsm_mux.c +++ /dev/null @@ -1,1535 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -LOG_MODULE_REGISTER(gsm_mux, CONFIG_GSM_MUX_LOG_LEVEL); - -#include -#include -#include -#include -#include - -#include "uart_mux_internal.h" -#include "gsm_mux.h" - -/* Default values are from the specification 07.10 */ -#define T1_MSEC 100 /* 100 ms */ -#define T2_MSEC 340 /* 333 ms */ - -#define N1 256 /* default I frame size, GSM 07.10 ch 6.2.2.1 */ -#define N2 3 /* retry 3 times */ - -/* CRC8 is the reflected CRC8/ROHC algorithm */ -#define FCS_POLYNOMIAL 0xe0 /* reversed crc8 */ -#define FCS_INIT_VALUE 0xFF -#define FCS_GOOD_VALUE 0xCF - -#define GSM_EA 0x01 /* Extension bit */ -#define GSM_CR 0x02 /* Command / Response */ -#define GSM_PF 0x10 /* Poll / Final */ - -/* Frame types */ -#define FT_RR 0x01 /* Receive Ready */ -#define FT_UI 0x03 /* Unnumbered Information */ -#define FT_RNR 0x05 /* Receive Not Ready */ -#define FT_REJ 0x09 /* Reject */ -#define FT_DM 0x0F /* Disconnected Mode */ -#define FT_SABM 0x2F /* Set Asynchronous Balanced Mode */ -#define FT_DISC 0x43 /* Disconnect */ -#define FT_UA 0x63 /* Unnumbered Acknowledgement */ -#define FT_UIH 0xEF /* Unnumbered Information with Header check */ - -/* Control channel commands */ -#define CMD_NSC 0x08 /* Non Supported Command Response */ -#define CMD_TEST 0x10 /* Test Command */ -#define CMD_PSC 0x20 /* Power Saving Control */ -#define CMD_RLS 0x28 /* Remote Line Status Command */ -#define CMD_FCOFF 0x30 /* Flow Control Off Command */ -#define CMD_PN 0x40 /* DLC parameter negotiation */ -#define CMD_RPN 0x48 /* Remote Port Negotiation Command */ -#define CMD_FCON 0x50 /* Flow Control On Command */ -#define CMD_CLD 0x60 /* Multiplexer close down */ -#define CMD_SNC 0x68 /* Service Negotiation Command */ -#define CMD_MSC 0x70 /* Modem Status Command */ - -/* Flag sequence field between messages (start of frame) */ -#define SOF_MARKER 0xF9 - -/* Mux parsing states */ -enum gsm_mux_state { - GSM_MUX_SOF, /* Start of frame */ - GSM_MUX_ADDRESS, /* Address field */ - GSM_MUX_CONTROL, /* Control field */ - GSM_MUX_LEN_0, /* First length byte */ - GSM_MUX_LEN_1, /* Second length byte */ - GSM_MUX_DATA, /* Data */ - GSM_MUX_FCS, /* Frame Check Sequence */ - GSM_MUX_EOF /* End of frame */ -}; - -struct gsm_mux { - /* UART device to use. This device is the real UART, not the - * muxed one. - */ - const struct device *uart; - - /* Buf to use when TX mux packet (hdr + data). For RX it only contains - * the data (not hdr). - */ - struct net_buf *buf; - int mru; - - enum gsm_mux_state state; - - /* Control DLCI is not included in this list so -1 here */ - uint8_t dlci_to_create[CONFIG_GSM_MUX_DLCI_MAX - 1]; - - uint16_t msg_len; /* message length */ - uint16_t received; /* bytes so far received */ - - struct k_work_delayable t2_timer; - sys_slist_t pending_ctrls; - - uint16_t t1_timeout_value; /* T1 default value */ - uint16_t t2_timeout_value; /* T2 default value */ - - /* Information from currently read packet */ - uint8_t address; /* dlci address (only one byte address supported) */ - uint8_t control; /* type of the frame */ - uint8_t fcs; /* calculated frame check sequence */ - uint8_t received_fcs; /* packet fcs */ - uint8_t retries; /* N2 counter */ - - bool in_use : 1; - bool is_initiator : 1; /* Did we initiate the connection attempt */ - bool refuse_service : 1; /* Do not try to talk to this modem */ -}; - -/* DLCI states */ -enum gsm_dlci_state { - GSM_DLCI_CLOSED, - GSM_DLCI_OPENING, - GSM_DLCI_OPEN, - GSM_DLCI_CLOSING -}; - -enum gsm_dlci_mode { - GSM_DLCI_MODE_ABM = 0, /* Normal Asynchronous Balanced Mode */ - GSM_DLCI_MODE_ADM = 1, /* Asynchronous Disconnected Mode */ -}; - -typedef int (*dlci_process_msg_t)(struct gsm_dlci *dlci, bool cmd, - struct net_buf *buf); -typedef void (*dlci_command_cb_t)(struct gsm_dlci *dlci, bool connected); - -struct gsm_dlci { - sys_snode_t node; - struct k_sem disconnect_sem; - struct gsm_mux *mux; - dlci_process_msg_t handler; - dlci_command_cb_t command_cb; - gsm_mux_dlci_created_cb_t dlci_created_cb; - void *user_data; - const struct device *uart; - enum gsm_dlci_state state; - enum gsm_dlci_mode mode; - int num; - uint32_t req_start; - uint8_t retries; - bool refuse_service : 1; /* Do not try to talk to this channel */ - bool in_use : 1; -}; - -struct gsm_control_msg { - sys_snode_t node; - struct net_buf *buf; - uint32_t req_start; - uint8_t cmd; - bool finished : 1; -}; - -/* From 07.10, Maximum Frame Size [1 - 128] in Basic mode */ -#define MAX_MRU CONFIG_GSM_MUX_MRU_MAX_LEN - -/* Assume that there are 3 network buffers (one for RX and one for TX, and one - * extra when parsing data) going on at the same time. - */ -#define MIN_BUF_COUNT (CONFIG_GSM_MUX_MAX * 3) - -NET_BUF_POOL_DEFINE(gsm_mux_pool, MIN_BUF_COUNT, MAX_MRU, 0, NULL); - -#define BUF_ALLOC_TIMEOUT K_MSEC(50) - -static struct gsm_mux muxes[CONFIG_GSM_MUX_MAX]; - -static struct gsm_dlci dlcis[CONFIG_GSM_MUX_DLCI_MAX]; -static sys_slist_t dlci_free_entries; -static sys_slist_t dlci_active_t1_timers; -static struct k_work_delayable t1_timer; - -static struct gsm_control_msg ctrls[CONFIG_GSM_MUX_PENDING_CMD_MAX]; -static sys_slist_t ctrls_free_entries; - -static bool gsm_mux_init_done; - -static const char *get_frame_type_str(uint8_t frame_type) -{ - switch (frame_type) { - case FT_RR: - return "RR"; - case FT_UI: - return "UI"; - case FT_RNR: - return "RNR"; - case FT_REJ: - return "REJ"; - case FT_DM: - return "DM"; - case FT_SABM: - return "SABM"; - case FT_DISC: - return "DISC"; - case FT_UA: - return "UA"; - case FT_UIH: - return "UIH"; - } - - return NULL; -} - -static void hexdump_packet(const char *header, uint8_t address, bool cmd_rsp, - uint8_t control, const uint8_t *data, size_t len) -{ - const char *frame_type; - char out[128]; - int ret; - - if (!IS_ENABLED(CONFIG_GSM_MUX_LOG_LEVEL_DBG)) { - return; - } - - memset(out, 0, sizeof(out)); - - ret = snprintk(out, sizeof(out), "%s: DLCI %d %s ", - header, address, cmd_rsp ? "cmd" : "resp"); - if (ret >= sizeof(out)) { - LOG_DBG("%d: Too long msg (%ld)", __LINE__, (long)(ret - sizeof(out))); - goto print; - } - - frame_type = get_frame_type_str(control & ~GSM_PF); - if (frame_type) { - ret += snprintk(out + ret, sizeof(out) - ret, "%s ", - frame_type); - } else if (!(control & 0x01)) { - ret += snprintk(out + ret, sizeof(out) - ret, - "I N(S)%d N(R)%d ", - (control & 0x0E) >> 1, - (control & 0xE0) >> 5); - } else { - frame_type = get_frame_type_str(control & 0x0F); - if (frame_type) { - ret += snprintk(out + ret, sizeof(out) - ret, - "%s(%d) ", frame_type, - (control & 0xE0) >> 5); - } else { - ret += snprintk(out + ret, sizeof(out) - ret, - "[%02X] ", control); - } - } - - if (ret >= sizeof(out)) { - LOG_DBG("%d: Too long msg (%ld)", __LINE__, (long)(ret - sizeof(out))); - goto print; - } - - ret += snprintk(out + ret, sizeof(out) - ret, "%s", (control & GSM_PF) ? "(P)" : "(F)"); - if (ret >= sizeof(out)) { - LOG_DBG("%d: Too long msg (%ld)", __LINE__, (long)(ret - sizeof(out))); - goto print; - } - -print: - if (IS_ENABLED(CONFIG_GSM_MUX_VERBOSE_DEBUG)) { - if (len > 0) { - LOG_HEXDUMP_DBG(data, len, out); - } else { - LOG_DBG("%s", out); - } - } else { - LOG_DBG("%s", out); - } -} - -static uint8_t gsm_mux_fcs_add_buf(uint8_t fcs, const uint8_t *buf, size_t len) -{ - return crc8(buf, len, FCS_POLYNOMIAL, fcs, true); -} - -static uint8_t gsm_mux_fcs_add(uint8_t fcs, uint8_t recv_byte) -{ - return gsm_mux_fcs_add_buf(fcs, &recv_byte, 1); -} - -static bool gsm_mux_read_ea(int *value, uint8_t recv_byte) -{ - /* As the value can be larger than one byte, collect the read - * bytes to given variable. - */ - *value <<= 7; - *value |= recv_byte >> 1; - - /* When the address has been read fully, the EA bit is 1 */ - return recv_byte & GSM_EA; -} - -static bool gsm_mux_read_msg_len(struct gsm_mux *mux, uint8_t recv_byte) -{ - int value = mux->msg_len; - bool ret; - - ret = gsm_mux_read_ea(&value, recv_byte); - - mux->msg_len = value; - - return ret; -} - -static struct net_buf *gsm_mux_alloc_buf(k_timeout_t timeout, void *user_data) -{ - struct net_buf *buf; - - ARG_UNUSED(user_data); - - buf = net_buf_alloc(&gsm_mux_pool, timeout); - if (!buf) { - LOG_ERR("Cannot allocate buffer"); - } - - return buf; -} - -static void hexdump_buf(const char *header, struct net_buf *buf) -{ - if (IS_ENABLED(CONFIG_GSM_MUX_VERBOSE_DEBUG)) { - while (buf) { - LOG_HEXDUMP_DBG(buf->data, buf->len, header); - buf = buf->frags; - } - } -} - -static int gsm_dlci_process_data(struct gsm_dlci *dlci, bool cmd, - struct net_buf *buf) -{ - int len = 0; - - LOG_DBG("[%p] DLCI %d data %s", dlci->mux, dlci->num, - cmd ? "request" : "response"); - hexdump_buf("buf", buf); - - while (buf) { - uart_mux_recv(dlci->uart, dlci, buf->data, buf->len); - len += buf->len; - buf = buf->frags; - } - - return len; -} - -static struct gsm_dlci *gsm_dlci_get(struct gsm_mux *mux, uint8_t dlci_address) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(dlcis); i++) { - if (dlcis[i].in_use && - dlcis[i].mux == mux && - dlcis[i].num == dlci_address) { - return &dlcis[i]; - } - } - - return NULL; -} - -static int gsm_mux_modem_send(struct gsm_mux *mux, const uint8_t *buf, size_t size) -{ - if (mux->uart == NULL) { - return -ENOENT; - } - - if (size == 0) { - return 0; - } - - return uart_mux_send(mux->uart, buf, size); -} - -static int gsm_mux_send_data_msg(struct gsm_mux *mux, bool cmd, - struct gsm_dlci *dlci, uint8_t frame_type, - const uint8_t *buf, size_t size) -{ - uint8_t hdr[7]; - int pos; - int ret; - - hdr[0] = SOF_MARKER; - hdr[1] = (dlci->num << 2) | ((uint8_t)cmd << 1) | GSM_EA; - hdr[2] = frame_type; - - if (size < 128) { - hdr[3] = (size << 1) | GSM_EA; - pos = 4; - } else { - hdr[3] = (size & 127) << 1; - hdr[4] = (size >> 7); - pos = 5; - } - - /* Write the header and data in smaller chunks in order to avoid - * allocating a big buffer. - */ - (void)gsm_mux_modem_send(mux, &hdr[0], pos); - - if (size > 0) { - (void)gsm_mux_modem_send(mux, buf, size); - } - - /* FSC is calculated only for address, type and length fields - * for UIH frames - */ - hdr[pos] = 0xFF - gsm_mux_fcs_add_buf(FCS_INIT_VALUE, &hdr[1], - pos - 1); - if ((frame_type & ~GSM_PF) != FT_UIH) { - hdr[pos] = gsm_mux_fcs_add_buf(hdr[pos], buf, size); - } - - hdr[pos + 1] = SOF_MARKER; - - ret = gsm_mux_modem_send(mux, &hdr[pos], 2); - - hexdump_packet("Sending", dlci->num, cmd, frame_type, - buf, size); - return ret; -} - -static int gsm_mux_send_control_msg(struct gsm_mux *mux, bool cmd, - uint8_t dlci_address, uint8_t frame_type) -{ - uint8_t buf[6]; - - buf[0] = SOF_MARKER; - buf[1] = (dlci_address << 2) | ((uint8_t)cmd << 1) | GSM_EA; - buf[2] = frame_type; - buf[3] = GSM_EA; - buf[4] = 0xFF - gsm_mux_fcs_add_buf(FCS_INIT_VALUE, buf + 1, 3); - buf[5] = SOF_MARKER; - - hexdump_packet("Sending", dlci_address, cmd, frame_type, - buf, sizeof(buf)); - - return gsm_mux_modem_send(mux, buf, sizeof(buf)); -} - -static int gsm_mux_send_command(struct gsm_mux *mux, uint8_t dlci_address, - uint8_t frame_type) -{ - return gsm_mux_send_control_msg(mux, true, dlci_address, frame_type); -} - -static int gsm_mux_send_response(struct gsm_mux *mux, uint8_t dlci_address, - uint8_t frame_type) -{ - return gsm_mux_send_control_msg(mux, false, dlci_address, frame_type); -} - -static void dlci_run_timer(uint32_t current_time) -{ - struct gsm_dlci *dlci, *next; - uint32_t new_timer = UINT_MAX; - - (void)k_work_cancel_delayable(&t1_timer); - - SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&dlci_active_t1_timers, - dlci, next, node) { - uint32_t current_timer = dlci->req_start + - dlci->mux->t1_timeout_value - current_time; - - new_timer = MIN(current_timer, new_timer); - } - - if (new_timer != UINT_MAX) { - k_work_reschedule(&t1_timer, K_MSEC(new_timer)); - } -} - -static void gsm_dlci_open(struct gsm_dlci *dlci) -{ - LOG_DBG("[%p/%d] DLCI id %d open", dlci, dlci->num, dlci->num); - dlci->state = GSM_DLCI_OPEN; - - /* Remove this DLCI from pending T1 timers */ - sys_slist_remove(&dlci_active_t1_timers, NULL, &dlci->node); - dlci_run_timer(k_uptime_get_32()); - - if (dlci->command_cb) { - dlci->command_cb(dlci, true); - } -} - -static void gsm_dlci_close(struct gsm_dlci *dlci) -{ - LOG_DBG("[%p/%d] DLCI id %d closed", dlci, dlci->num, dlci->num); - dlci->state = GSM_DLCI_CLOSED; - - k_sem_give(&dlci->disconnect_sem); - - /* Remove this DLCI from pending T1 timers */ - sys_slist_remove(&dlci_active_t1_timers, NULL, &dlci->node); - dlci_run_timer(k_uptime_get_32()); - - if (dlci->command_cb) { - dlci->command_cb(dlci, false); - } - - if (dlci->num == 0) { - dlci->mux->refuse_service = true; - } -} - -/* Return true if we need to retry, false otherwise */ -static bool handle_t1_timeout(struct gsm_dlci *dlci) -{ - LOG_DBG("[%p/%d] T1 timeout", dlci, dlci->num); - - if (dlci->state == GSM_DLCI_OPENING) { - dlci->retries--; - if (dlci->retries) { - dlci->req_start = k_uptime_get_32(); - (void)gsm_mux_send_command(dlci->mux, dlci->num, FT_SABM | GSM_PF); - return true; - } - - if (dlci->command_cb) { - dlci->command_cb(dlci, false); - } - - if (dlci->num == 0 && dlci->mux->control == (FT_DM | GSM_PF)) { - LOG_DBG("DLCI %d -> ADM mode", dlci->num); - dlci->mode = GSM_DLCI_MODE_ADM; - gsm_dlci_open(dlci); - } else { - gsm_dlci_close(dlci); - } - } else if (dlci->state == GSM_DLCI_CLOSING) { - dlci->retries--; - if (dlci->retries) { - (void)gsm_mux_send_command(dlci->mux, dlci->num, FT_DISC | GSM_PF); - return true; - } - - gsm_dlci_close(dlci); - } - - return false; -} - -static void dlci_t1_timeout(struct k_work *work) -{ - uint32_t current_time = k_uptime_get_32(); - struct gsm_dlci *entry, *next; - sys_snode_t *prev_node = NULL; - - ARG_UNUSED(work); - - SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&dlci_active_t1_timers, - entry, next, node) { - if ((int32_t)(entry->req_start + - entry->mux->t1_timeout_value - current_time) > 0) { - prev_node = &entry->node; - break; - } - - if (!handle_t1_timeout(entry)) { - sys_slist_remove(&dlci_active_t1_timers, prev_node, - &entry->node); - } - } - - dlci_run_timer(current_time); -} - -static struct gsm_control_msg *gsm_ctrl_msg_get_free(void) -{ - sys_snode_t *node; - - node = sys_slist_peek_head(&ctrls_free_entries); - if (!node) { - return NULL; - } - - sys_slist_remove(&ctrls_free_entries, NULL, node); - - return CONTAINER_OF(node, struct gsm_control_msg, node); -} - -static struct gsm_control_msg *gsm_mux_alloc_control_msg(struct net_buf *buf, - uint8_t cmd) -{ - struct gsm_control_msg *msg; - - msg = gsm_ctrl_msg_get_free(); - if (!msg) { - return NULL; - } - - msg->buf = buf; - msg->cmd = cmd; - - return msg; -} - -static void ctrl_msg_cleanup(struct gsm_control_msg *entry, bool pending) -{ - if (pending) { - LOG_DBG("Releasing pending buf %p (ref %d)", - entry->buf, entry->buf->ref - 1); - net_buf_unref(entry->buf); - entry->buf = NULL; - } -} - -/* T2 timeout is for control message retransmits */ -static void gsm_mux_t2_timeout(struct k_work *work) -{ - struct k_work_delayable *dwork = k_work_delayable_from_work(work); - struct gsm_mux *mux = CONTAINER_OF(dwork, struct gsm_mux, t2_timer); - uint32_t current_time = k_uptime_get_32(); - struct gsm_control_msg *entry, *next; - - SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&mux->pending_ctrls, entry, next, - node) { - if ((int32_t)(entry->req_start + T2_MSEC - current_time) > 0) { - break; - } - - ctrl_msg_cleanup(entry, true); - - sys_slist_remove(&mux->pending_ctrls, NULL, &entry->node); - sys_slist_append(&ctrls_free_entries, &entry->node); - - entry = NULL; - } - - if (entry) { - k_work_reschedule( - &mux->t2_timer, - K_MSEC(entry->req_start + T2_MSEC - current_time)); - } -} - -static int gsm_mux_send_control_message(struct gsm_mux *mux, uint8_t dlci_address, - int cmd, uint8_t *data, size_t data_len) -{ - struct gsm_control_msg *ctrl; - struct net_buf *buf; - - /* We create a net_buf for the control message so that we can - * resend it easily if needed. - */ - buf = gsm_mux_alloc_buf(BUF_ALLOC_TIMEOUT, NULL); - if (!buf) { - LOG_ERR("[%p] Cannot allocate header", mux); - return -ENOMEM; - } - - if (data && data_len > 0) { - size_t added; - - added = net_buf_append_bytes(buf, data_len, data, - BUF_ALLOC_TIMEOUT, - gsm_mux_alloc_buf, NULL); - if (added != data_len) { - net_buf_unref(buf); - return -ENOMEM; - } - } - - ctrl = gsm_mux_alloc_control_msg(buf, cmd); - if (!ctrl) { - net_buf_unref(buf); - return -ENOMEM; - } - - sys_slist_append(&mux->pending_ctrls, &ctrl->node); - ctrl->req_start = k_uptime_get_32(); - - /* Let's start the timer if necessary */ - if (!k_work_delayable_remaining_get(&mux->t2_timer)) { - k_work_reschedule(&mux->t2_timer, K_MSEC(T2_MSEC)); - } - - return gsm_mux_modem_send(mux, buf->data, buf->len); -} - -static int gsm_dlci_opening_or_closing(struct gsm_dlci *dlci, - enum gsm_dlci_state state, - int command, - dlci_command_cb_t cb) -{ - dlci->retries = dlci->mux->retries; - dlci->req_start = k_uptime_get_32(); - dlci->state = state; - dlci->command_cb = cb; - - /* Let's start the timer if necessary */ - if (!k_work_delayable_remaining_get(&t1_timer)) { - k_work_reschedule(&t1_timer, - K_MSEC(dlci->mux->t1_timeout_value)); - } - - sys_slist_append(&dlci_active_t1_timers, &dlci->node); - - return gsm_mux_send_command(dlci->mux, dlci->num, command | GSM_PF); -} - -static int gsm_dlci_closing(struct gsm_dlci *dlci, dlci_command_cb_t cb) -{ - if (dlci->state == GSM_DLCI_CLOSED || - dlci->state == GSM_DLCI_CLOSING) { - return -EALREADY; - } - - LOG_DBG("[%p] DLCI %d closing", dlci, dlci->num); - - return gsm_dlci_opening_or_closing(dlci, GSM_DLCI_CLOSING, FT_DISC, - cb); -} - -static int gsm_dlci_opening(struct gsm_dlci *dlci, dlci_command_cb_t cb) -{ - if (dlci->state == GSM_DLCI_OPEN || dlci->state == GSM_DLCI_OPENING) { - return -EALREADY; - } - - LOG_DBG("[%p] DLCI %d opening", dlci, dlci->num); - - return gsm_dlci_opening_or_closing(dlci, GSM_DLCI_OPENING, FT_SABM, - cb); -} - -int gsm_mux_disconnect(struct gsm_mux *mux, k_timeout_t timeout) -{ - struct gsm_dlci *dlci; - - dlci = gsm_dlci_get(mux, 0); - if (dlci == NULL) { - return -ENOENT; - } - - (void)gsm_mux_send_control_message(dlci->mux, dlci->num, - CMD_CLD, NULL, 0); - - (void)k_work_cancel_delayable(&mux->t2_timer); - - (void)gsm_dlci_closing(dlci, NULL); - - return k_sem_take(&dlci->disconnect_sem, timeout); -} - -static int gsm_mux_control_reply(struct gsm_dlci *dlci, bool sub_cr, - uint8_t sub_cmd, const uint8_t *buf, size_t len) -{ - /* As this is a reply to received command, set the value according - * to initiator status. See GSM 07.10 page 17. - */ - bool cmd = !dlci->mux->is_initiator; - - return gsm_mux_send_data_msg(dlci->mux, cmd, dlci, FT_UIH | GSM_PF, buf, len); -} - -static bool get_field(struct net_buf *buf, int *ret_value) -{ - int value = 0; - uint8_t recv_byte; - - while (buf->len) { - recv_byte = net_buf_pull_u8(buf); - - if (gsm_mux_read_ea(&value, recv_byte)) { - *ret_value = value; - return true; - } - - if (buf->len == 0) { - buf = net_buf_frag_del(NULL, buf); - if (buf == NULL) { - break; - } - } - } - - return false; -} - -static int gsm_mux_msc_reply(struct gsm_dlci *dlci, bool cmd, - struct net_buf *buf, size_t len) -{ - uint32_t modem_sig = 0, break_sig = 0; - int ret; - - ret = get_field(buf, &modem_sig); - if (!ret) { - LOG_DBG("[%p] Malformed data", dlci->mux); - return -EINVAL; - } - - if (buf->len > 0) { - ret = get_field(buf, &break_sig); - if (!ret) { - LOG_DBG("[%p] Malformed data", dlci->mux); - return -EINVAL; - } - } - - LOG_DBG("Modem signal 0x%02x break signal 0x%02x", modem_sig, - break_sig); - - /* FIXME to return proper status back */ - - return gsm_mux_control_reply(dlci, cmd, CMD_MSC, buf->data, len); -} - -static int gsm_mux_control_message(struct gsm_dlci *dlci, struct net_buf *buf) -{ - uint32_t command = 0, len = 0; - int ret = 0; - bool cr; - - __ASSERT_NO_MSG(dlci != NULL); - - /* Remove the C/R bit from sub-command */ - cr = buf->data[0] & GSM_CR; - buf->data[0] &= ~GSM_CR; - - ret = get_field(buf, &command); - if (!ret) { - LOG_DBG("[%p] Malformed data", dlci->mux); - return -EINVAL; - } - - ret = get_field(buf, &len); - if (!ret) { - LOG_DBG("[%p] Malformed data", dlci->mux); - return -EINVAL; - } - - LOG_DBG("[%p] DLCI %d %s 0x%02x len %u", dlci->mux, dlci->num, - cr ? "cmd" : "rsp", command, len); - - /* buf->data should now point to start of dlci command data */ - - switch (command) { - case CMD_CLD: - /* Modem closing down */ - dlci->mux->refuse_service = true; - dlci->refuse_service = true; - gsm_dlci_closing(dlci, NULL); - break; - - case CMD_FCOFF: - /* Do not accept data */ - ret = gsm_mux_control_reply(dlci, cr, CMD_FCOFF, NULL, 0); - break; - - case CMD_FCON: - /* Accepting data */ - ret = gsm_mux_control_reply(dlci, cr, CMD_FCON, NULL, 0); - break; - - case CMD_MSC: - /* Modem status information */ - /* FIXME: WIP: MSC reply does not work */ - if (0) { - ret = gsm_mux_msc_reply(dlci, cr, buf, len); - } - - break; - - case CMD_PSC: - /* Modem wants to enter power saving state */ - ret = gsm_mux_control_reply(dlci, cr, CMD_PSC, NULL, len); - break; - - case CMD_RLS: - /* Out of band error reception for a DLCI */ - break; - - case CMD_TEST: - /* Send test message back */ - ret = gsm_mux_control_reply(dlci, cr, CMD_TEST, - buf->data, len); - break; - - /* Optional and currently unsupported commands */ - case CMD_PN: /* Parameter negotiation */ - case CMD_RPN: /* Remote port negotiation */ - case CMD_SNC: /* Service negotiation command */ - default: - /* Reply to bad commands with an NSC */ - buf->data[0] = command | (cr ? GSM_CR : 0); - buf->len = 1; - ret = gsm_mux_control_reply(dlci, cr, CMD_NSC, buf->data, len); - break; - } - - return ret; -} - -/* Handle a response to our control message */ -static int gsm_mux_control_response(struct gsm_dlci *dlci, struct net_buf *buf) -{ - struct gsm_control_msg *entry, *next; - - SYS_SLIST_FOR_EACH_CONTAINER_SAFE(&dlci->mux->pending_ctrls, - entry, next, node) { - if (dlci->mux->control == entry->cmd) { - sys_slist_remove(&dlci->mux->pending_ctrls, NULL, - &entry->node); - sys_slist_append(&ctrls_free_entries, &entry->node); - entry->finished = true; - - if (dlci->command_cb) { - dlci->command_cb(dlci, true); - } - - break; - } - } - - return 0; -} - -static int gsm_dlci_process_command(struct gsm_dlci *dlci, bool cmd, - struct net_buf *buf) -{ - int ret; - - LOG_DBG("[%p] DLCI %d control %s", dlci->mux, dlci->num, - cmd ? "request" : "response"); - hexdump_buf("buf", buf); - - if (cmd) { - ret = gsm_mux_control_message(dlci, buf); - } else { - ret = gsm_mux_control_response(dlci, buf); - } - - return ret; -} - -static void gsm_dlci_free(struct gsm_mux *mux, uint8_t address) -{ - struct gsm_dlci *dlci; - int i; - - for (i = 0; i < ARRAY_SIZE(dlcis); i++) { - if (!dlcis[i].in_use) { - continue; - } - - dlci = &dlcis[i]; - - if (dlci->mux == mux && dlci->num == address) { - dlci->in_use = false; - - sys_slist_prepend(&dlci_free_entries, &dlci->node); - } - - break; - } -} - -static struct gsm_dlci *gsm_dlci_get_free(void) -{ - sys_snode_t *node; - - node = sys_slist_peek_head(&dlci_free_entries); - if (!node) { - return NULL; - } - - sys_slist_remove(&dlci_free_entries, NULL, node); - - return CONTAINER_OF(node, struct gsm_dlci, node); -} - -static struct gsm_dlci *gsm_dlci_alloc(struct gsm_mux *mux, uint8_t address, - const struct device *uart, - gsm_mux_dlci_created_cb_t dlci_created_cb, - void *user_data) -{ - struct gsm_dlci *dlci; - - dlci = gsm_dlci_get_free(); - if (!dlci) { - return NULL; - } - - k_sem_init(&dlci->disconnect_sem, 1, 1); - - dlci->mux = mux; - dlci->num = address; - dlci->in_use = true; - dlci->retries = mux->retries; - dlci->state = GSM_DLCI_CLOSED; - dlci->uart = uart; - dlci->user_data = user_data; - dlci->dlci_created_cb = dlci_created_cb; - - /* Command channel (0) handling is separated from data */ - if (dlci->num) { - dlci->handler = gsm_dlci_process_data; - } else { - dlci->handler = gsm_dlci_process_command; - } - - return dlci; -} - -static int gsm_mux_process_pkt(struct gsm_mux *mux) -{ - uint8_t dlci_address = mux->address >> 2; - int ret = 0; - bool cmd; /* C/R bit, command (true) / response (false) */ - struct gsm_dlci *dlci; - - /* This function is only called for received packets so if the - * command is set, then it means a response if we are initiator. - */ - cmd = (mux->address >> 1) & 0x01; - - if (mux->is_initiator) { - cmd = !cmd; - } - - hexdump_packet("Received", dlci_address, cmd, mux->control, - mux->buf ? mux->buf->data : NULL, - mux->buf ? mux->buf->len : 0); - - dlci = gsm_dlci_get(mux, dlci_address); - - /* What to do next */ - switch (mux->control) { - case FT_SABM | GSM_PF: - if (cmd == false) { - ret = -ENOENT; - goto fail; - } - - if (dlci == NULL) { - const struct device *uart; - - uart = uart_mux_find(dlci_address); - if (uart == NULL) { - ret = -ENOENT; - goto fail; - } - - dlci = gsm_dlci_alloc(mux, dlci_address, uart, NULL, - NULL); - if (dlci == NULL) { - ret = -ENOENT; - goto fail; - } - } - - if (dlci->refuse_service) { - ret = gsm_mux_send_response(mux, dlci_address, FT_DM); - } else { - ret = gsm_mux_send_response(mux, dlci_address, FT_UA); - gsm_dlci_open(dlci); - } - - break; - - case FT_DISC | GSM_PF: - if (cmd == false) { - ret = -ENOENT; - goto fail; - } - - if (dlci == NULL || dlci->state == GSM_DLCI_CLOSED) { - (void)gsm_mux_send_response(mux, dlci_address, FT_DM); - ret = -ENOENT; - goto out; - } - - ret = gsm_mux_send_command(mux, dlci_address, FT_UA); - gsm_dlci_close(dlci); - break; - - case FT_UA | GSM_PF: - case FT_UA: - if (cmd == true || dlci == NULL) { - ret = -ENOENT; - goto out; - } - - switch (dlci->state) { - case GSM_DLCI_CLOSING: - gsm_dlci_close(dlci); - break; - case GSM_DLCI_OPENING: - gsm_dlci_open(dlci); - break; - default: - break; - } - - break; - - case FT_DM | GSM_PF: - case FT_DM: - if (cmd == true || dlci == NULL) { - ret = -ENOENT; - goto fail; - } - - gsm_dlci_close(dlci); - break; - - case FT_UI | GSM_PF: - case FT_UI: - case FT_UIH | GSM_PF: - case FT_UIH: - if (dlci == NULL || dlci->state != GSM_DLCI_OPEN) { - (void)gsm_mux_send_command(mux, dlci_address, FT_DM | GSM_PF); - ret = -ENOENT; - goto out; - } - - ret = dlci->handler(dlci, cmd, mux->buf); - - if (mux->buf) { - net_buf_unref(mux->buf); - mux->buf = NULL; - } - - break; - - default: - ret = -EINVAL; - goto fail; - } - -out: - return ret; - -fail: - LOG_ERR("Cannot handle command (0x%02x) (%d)", mux->control, ret); - return ret; -} - -static bool is_UI(struct gsm_mux *mux) -{ - return (mux->control & ~GSM_PF) == FT_UI; -} - -static const char *gsm_mux_state_str(enum gsm_mux_state state) -{ -#if (CONFIG_GSM_MUX_LOG_LEVEL >= LOG_LEVEL_DBG) || defined(CONFIG_NET_SHELL) - switch (state) { - case GSM_MUX_SOF: - return "Start-Of-Frame"; - case GSM_MUX_ADDRESS: - return "Address"; - case GSM_MUX_CONTROL: - return "Control"; - case GSM_MUX_LEN_0: - return "Len0"; - case GSM_MUX_LEN_1: - return "Len1"; - case GSM_MUX_DATA: - return "Data"; - case GSM_MUX_FCS: - return "FCS"; - case GSM_MUX_EOF: - return "End-Of-Frame"; - } -#else - ARG_UNUSED(state); -#endif - - return ""; -} - -#if CONFIG_GSM_MUX_LOG_LEVEL >= LOG_LEVEL_DBG -static void validate_state_transition(enum gsm_mux_state current, - enum gsm_mux_state new) -{ - static const uint8_t valid_transitions[] = { - [GSM_MUX_SOF] = 1 << GSM_MUX_ADDRESS, - [GSM_MUX_ADDRESS] = 1 << GSM_MUX_CONTROL, - [GSM_MUX_CONTROL] = 1 << GSM_MUX_LEN_0, - [GSM_MUX_LEN_0] = 1 << GSM_MUX_LEN_1 | - 1 << GSM_MUX_DATA | - 1 << GSM_MUX_FCS | - 1 << GSM_MUX_SOF, - [GSM_MUX_LEN_1] = 1 << GSM_MUX_DATA | - 1 << GSM_MUX_FCS | - 1 << GSM_MUX_SOF, - [GSM_MUX_DATA] = 1 << GSM_MUX_FCS | - 1 << GSM_MUX_SOF, - [GSM_MUX_FCS] = 1 << GSM_MUX_EOF, - [GSM_MUX_EOF] = 1 << GSM_MUX_SOF - }; - - if (!(valid_transitions[current] & 1 << new)) { - LOG_DBG("Invalid state transition: %s (%d) => %s (%d)", - gsm_mux_state_str(current), current, - gsm_mux_state_str(new), new); - } -} -#else -static inline void validate_state_transition(enum gsm_mux_state current, - enum gsm_mux_state new) -{ - ARG_UNUSED(current); - ARG_UNUSED(new); -} -#endif - -static inline enum gsm_mux_state gsm_mux_get_state(const struct gsm_mux *mux) -{ - return (enum gsm_mux_state)mux->state; -} - -void gsm_mux_change_state(struct gsm_mux *mux, enum gsm_mux_state new_state) -{ - __ASSERT_NO_MSG(mux); - - if (gsm_mux_get_state(mux) == new_state) { - return; - } - - LOG_DBG("[%p] state %s (%d) => %s (%d)", - mux, gsm_mux_state_str(mux->state), mux->state, - gsm_mux_state_str(new_state), new_state); - - validate_state_transition(mux->state, new_state); - - mux->state = new_state; -} - -static void gsm_mux_process_data(struct gsm_mux *mux, uint8_t recv_byte) -{ - size_t bytes_added; - - switch (mux->state) { - case GSM_MUX_SOF: - /* This is the initial state where we look for SOF char */ - if (recv_byte == SOF_MARKER) { - gsm_mux_change_state(mux, GSM_MUX_ADDRESS); - mux->fcs = FCS_INIT_VALUE; - mux->received = 0; - - /* Avoid memory leak by freeing all the allocated - * buffers at start. - */ - if (mux->buf) { - net_buf_unref(mux->buf); - mux->buf = NULL; - } - } - - break; - - case GSM_MUX_ADDRESS: - /* DLCI (Data Link Connection Identifier) address we want to - * talk. This address field also contains C/R bit. - * Currently we only support one byte addresses. - */ - mux->address = recv_byte; - LOG_DBG("[%p] recv %d address %d C/R %d", mux, recv_byte, - mux->address >> 2, !!(mux->address & GSM_CR)); - gsm_mux_change_state(mux, GSM_MUX_CONTROL); - mux->fcs = gsm_mux_fcs_add(mux->fcs, recv_byte); - break; - - case GSM_MUX_CONTROL: - mux->control = recv_byte; - LOG_DBG("[%p] recv %s (0x%02x) control 0x%02x P/F %d", mux, - get_frame_type_str(recv_byte & ~GSM_PF), recv_byte, - mux->control & ~GSM_PF, !!(mux->control & GSM_PF)); - gsm_mux_change_state(mux, GSM_MUX_LEN_0); - mux->fcs = gsm_mux_fcs_add(mux->fcs, recv_byte); - break; - - case GSM_MUX_LEN_0: - mux->fcs = gsm_mux_fcs_add(mux->fcs, recv_byte); - mux->msg_len = 0; - - if (gsm_mux_read_msg_len(mux, recv_byte)) { - if (mux->msg_len > mux->mru) { - gsm_mux_change_state(mux, GSM_MUX_SOF); - } else if (mux->msg_len == 0) { - gsm_mux_change_state(mux, GSM_MUX_FCS); - } else { - gsm_mux_change_state(mux, GSM_MUX_DATA); - - LOG_DBG("[%p] data len %d", mux, mux->msg_len); - } - } else { - gsm_mux_change_state(mux, GSM_MUX_LEN_1); - } - - break; - - case GSM_MUX_LEN_1: - mux->fcs = gsm_mux_fcs_add(mux->fcs, recv_byte); - - mux->msg_len |= recv_byte << 7; - if (mux->msg_len > mux->mru) { - gsm_mux_change_state(mux, GSM_MUX_SOF); - } else if (mux->msg_len == 0) { - gsm_mux_change_state(mux, GSM_MUX_FCS); - } else { - gsm_mux_change_state(mux, GSM_MUX_DATA); - - LOG_DBG("[%p] data len %d", mux, mux->msg_len); - } - - break; - - case GSM_MUX_DATA: - if (mux->buf == NULL) { - mux->buf = net_buf_alloc(&gsm_mux_pool, - BUF_ALLOC_TIMEOUT); - if (mux->buf == NULL) { - LOG_ERR("[%p] Can't allocate RX data! " - "Skipping data!", mux); - gsm_mux_change_state(mux, GSM_MUX_SOF); - break; - } - } - - bytes_added = net_buf_append_bytes(mux->buf, 1, - (void *)&recv_byte, - BUF_ALLOC_TIMEOUT, - gsm_mux_alloc_buf, - &gsm_mux_pool); - if (bytes_added != 1) { - gsm_mux_change_state(mux, GSM_MUX_SOF); - } else if (++mux->received == mux->msg_len) { - gsm_mux_change_state(mux, GSM_MUX_FCS); - } - - break; - - case GSM_MUX_FCS: - mux->received_fcs = recv_byte; - - /* Update the FCS for Unnumbered Information field (UI) */ - if (is_UI(mux)) { - struct net_buf *buf = mux->buf; - - while (buf) { - mux->fcs = gsm_mux_fcs_add_buf(mux->fcs, - buf->data, - buf->len); - buf = buf->frags; - } - } - - mux->fcs = gsm_mux_fcs_add(mux->fcs, mux->received_fcs); - if (mux->fcs == FCS_GOOD_VALUE) { - int ret = gsm_mux_process_pkt(mux); - - if (ret < 0) { - LOG_DBG("[%p] Cannot process pkt (%d)", mux, - ret); - } - } - - gsm_mux_change_state(mux, GSM_MUX_EOF); - break; - - case GSM_MUX_EOF: - if (recv_byte == SOF_MARKER) { - gsm_mux_change_state(mux, GSM_MUX_SOF); - } - - break; - } -} - -void gsm_mux_recv_buf(struct gsm_mux *mux, uint8_t *buf, int len) -{ - int i = 0; - - LOG_DBG("Received %d bytes", len); - - while (i < len) { - gsm_mux_process_data(mux, buf[i++]); - } -} - -static void dlci_done(struct gsm_dlci *dlci, bool connected) -{ - LOG_DBG("[%p] DLCI id %d %screated", dlci, dlci->num, - connected == false ? "not " : ""); - - /* Let the UART mux to continue */ - if (dlci->dlci_created_cb) { - dlci->dlci_created_cb(dlci, connected, dlci->user_data); - } -} - -int gsm_dlci_create(struct gsm_mux *mux, - const struct device *uart, - int dlci_address, - gsm_mux_dlci_created_cb_t dlci_created_cb, - void *user_data, - struct gsm_dlci **dlci) -{ - int ret; - - *dlci = gsm_dlci_alloc(mux, dlci_address, uart, dlci_created_cb, - user_data); - if (!*dlci) { - LOG_ERR("[%p] Cannot allocate DLCI %d", mux, dlci_address); - ret = -ENOMEM; - goto fail; - } - - ret = gsm_dlci_opening(*dlci, dlci_done); - if (ret < 0 && ret != -EALREADY) { - LOG_ERR("[%p] Cannot open DLCI %d", mux, dlci_address); - gsm_dlci_free(mux, dlci_address); - *dlci = NULL; - } else { - ret = 0; - } - -fail: - return ret; -} - -int gsm_dlci_send(struct gsm_dlci *dlci, const uint8_t *buf, size_t size) -{ - /* Mux the data and send to UART */ - return gsm_mux_send_data_msg(dlci->mux, true, dlci, FT_UIH, buf, size); -} - -int gsm_dlci_id(struct gsm_dlci *dlci) -{ - return dlci->num; -} - -struct gsm_mux *gsm_mux_create(const struct device *uart) -{ - struct gsm_mux *mux = NULL; - int i; - - if (!gsm_mux_init_done) { - LOG_ERR("GSM mux not initialized!"); - return NULL; - } - - for (i = 0; i < ARRAY_SIZE(muxes); i++) { - if (muxes[i].in_use) { - /* If the mux was already created, return it */ - if (uart && muxes[i].uart == uart) { - return &muxes[i]; - } - - continue; - } - - mux = &muxes[i]; - - memset(mux, 0, sizeof(*mux)); - - mux->in_use = true; - mux->uart = uart; - mux->mru = CONFIG_GSM_MUX_MRU_DEFAULT_LEN; - mux->retries = N2; - mux->t1_timeout_value = CONFIG_GSM_MUX_T1_TIMEOUT ? - CONFIG_GSM_MUX_T1_TIMEOUT : T1_MSEC; - mux->t2_timeout_value = T2_MSEC; - mux->is_initiator = CONFIG_GSM_MUX_INITIATOR; - mux->state = GSM_MUX_SOF; - mux->buf = NULL; - - k_work_init_delayable(&mux->t2_timer, gsm_mux_t2_timeout); - sys_slist_init(&mux->pending_ctrls); - - /* The system will continue after the control DLCI is - * created or timeout occurs. - */ - break; - } - - return mux; -} - -int gsm_mux_send(struct gsm_mux *mux, uint8_t dlci_address, - const uint8_t *buf, size_t size) -{ - struct gsm_dlci *dlci; - - dlci = gsm_dlci_get(mux, dlci_address); - if (!dlci) { - return -ENOENT; - } - - /* Mux the data and send to UART */ - return gsm_mux_send_data_msg(mux, true, dlci, FT_UIH, buf, size); -} - -void gsm_mux_detach(struct gsm_mux *mux) -{ - struct gsm_dlci *dlci; - - for (int i = 0; i < ARRAY_SIZE(dlcis); i++) { - dlci = &dlcis[i]; - - if (mux != dlci->mux || !dlci->in_use) { - continue; - } - - dlci->in_use = false; - sys_slist_prepend(&dlci_free_entries, &dlci->node); - } -} - -void gsm_mux_init(void) -{ - int i; - - if (gsm_mux_init_done) { - return; - } - - gsm_mux_init_done = true; - - sys_slist_init(&ctrls_free_entries); - - for (i = 0; i < ARRAY_SIZE(ctrls); i++) { - sys_slist_prepend(&ctrls_free_entries, &ctrls[i].node); - } - - sys_slist_init(&dlci_free_entries); - - for (i = 0; i < ARRAY_SIZE(dlcis); i++) { - sys_slist_prepend(&dlci_free_entries, &dlcis[i].node); - } - - k_work_init_delayable(&t1_timer, dlci_t1_timeout); -} diff --git a/drivers/console/gsm_mux.h b/drivers/console/gsm_mux.h deleted file mode 100644 index fce8a104bd77b..0000000000000 --- a/drivers/console/gsm_mux.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DLCI_CONTROL 0 - -#if defined(CONFIG_GSM_MUX) -#define DLCI_AT CONFIG_GSM_MUX_DLCI_AT -#define DLCI_PPP CONFIG_GSM_MUX_DLCI_PPP -#else -#define DLCI_AT -1 -#define DLCI_PPP -1 -#endif - -struct gsm_mux; -struct gsm_dlci; - -void gsm_mux_recv_buf(struct gsm_mux *mux, uint8_t *buf, int len); -int gsm_mux_send(struct gsm_mux *mux, uint8_t dlci_address, - const uint8_t *buf, size_t size); -struct gsm_mux *gsm_mux_create(const struct device *uart); -int gsm_mux_disconnect(struct gsm_mux *mux, k_timeout_t timeout); -void gsm_mux_init(void); - -typedef void (*gsm_mux_dlci_created_cb_t)(struct gsm_dlci *dlci, - bool connected, - void *user_data); - -int gsm_dlci_create(struct gsm_mux *mux, - const struct device *uart, - int dlci_address, - gsm_mux_dlci_created_cb_t dlci_created_cb, - void *user_data, - struct gsm_dlci **dlci); -int gsm_dlci_send(struct gsm_dlci *dlci, const uint8_t *buf, size_t size); -int gsm_dlci_id(struct gsm_dlci *dlci); -void gsm_mux_detach(struct gsm_mux *mux); diff --git a/drivers/console/ram_console.c b/drivers/console/ram_console.c index 4ace56f963043..fdb71b8bda0a7 100644 --- a/drivers/console/ram_console.c +++ b/drivers/console/ram_console.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2015 Intel Corporation + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -11,23 +12,47 @@ #include #include #include +#include + +#ifdef CONFIG_RAM_CONSOLE_BUFFER_SECTION +#if !DT_HAS_CHOSEN(zephyr_ram_console) +#error "Lack of chosen property zephyr,ram_console!" +#elif (CONFIG_RAM_CONSOLE_BUFFER_SIZE > DT_REG_SIZE(DT_CHOSEN(zephyr_ram_console))) +#error "Custom RAM console buffer exceeds the section size!" +#endif + +#define RAM_CONSOLE_BUF_ATTR \ + __attribute__((__section__(LINKER_DT_NODE_REGION_NAME(DT_CHOSEN(zephyr_ram_console))))) +#else +#define RAM_CONSOLE_BUF_ATTR +#endif extern void __printk_hook_install(int (*fn)(int)); extern void __stdout_hook_install(int (*fn)(int)); -/* Extra byte to ensure we're always NULL-terminated */ -char ram_console[CONFIG_RAM_CONSOLE_BUFFER_SIZE + 1]; +char ram_console_buf[CONFIG_RAM_CONSOLE_BUFFER_SIZE] RAM_CONSOLE_BUF_ATTR; +char *ram_console; static int pos; static int ram_console_out(int character) { ram_console[pos] = (char)character; - pos = (pos + 1) % CONFIG_RAM_CONSOLE_BUFFER_SIZE; + /* Leave one byte to ensure we're always NULL-terminated */ + pos = (pos + 1) % (CONFIG_RAM_CONSOLE_BUFFER_SIZE - 1); return character; } static int ram_console_init(void) { +#ifdef CONFIG_RAM_CONSOLE_BUFFER_SECTION + mm_reg_t ram_console_va; + + device_map((mm_reg_t *)&ram_console_va, DT_REG_ADDR(DT_CHOSEN(zephyr_ram_console)), + CONFIG_RAM_CONSOLE_BUFFER_SIZE, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + ram_console = (char *)ram_console_va, +#else + ram_console = ram_console_buf, +#endif __printk_hook_install(ram_console_out); __stdout_hook_install(ram_console_out); diff --git a/drivers/console/uart_mux.c b/drivers/console/uart_mux.c deleted file mode 100644 index 8ade93ef0bbaa..0000000000000 --- a/drivers/console/uart_mux.c +++ /dev/null @@ -1,890 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -LOG_MODULE_REGISTER(uart_mux, CONFIG_UART_MUX_LOG_LEVEL); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "gsm_mux.h" - -#if CONFIG_UART_MUX_DEVICE_COUNT == 0 -#error "CONFIG_UART_MUX_DEVICE_COUNT tells number of DLCIs to create " \ - "and must be >0" -#endif - -#define UART_MUX_WORKQ_PRIORITY CONFIG_UART_MUX_RX_PRIORITY -#define UART_MUX_WORKQ_STACK_SIZE CONFIG_UART_MUX_RX_STACK_SIZE - -/* All the RX/TX data is passed via own workqueue. This is done like this - * as the GSM modem uses global workqueue which causes difficulties if we do - * the same here. This workqueue is shared between all the DLCI channels. - */ -K_KERNEL_STACK_DEFINE(uart_mux_stack, UART_MUX_WORKQ_STACK_SIZE); -static struct k_work_q uart_mux_workq; - -/* The UART mux contains information about the real UART. It will synchronize - * the access to the real UART and pass data between it and GSM muxing API. - * Usually there is only one instance of these in the system, if we have only - * one UART connected to modem device. - */ -struct uart_mux { - /* The real UART device that is shared between muxed UARTs */ - const struct device *uart; - - /* GSM mux related to this UART */ - struct gsm_mux *mux; - - /* Received data is routed from ISR to MUX API via ring buffer */ - struct ring_buf *rx_ringbuf; - - /* RX worker that passes data from RX ISR to GSM mux API */ - struct k_work rx_work; - - /* Mutex for accessing the real UART */ - struct k_mutex lock; - - /* Flag that tells whether this instance is initialized or not */ - atomic_t init_done; - - /* Temporary buffer when reading data in ISR */ - uint8_t rx_buf[CONFIG_UART_MUX_TEMP_BUF_SIZE]; -}; - -#define DEFINE_UART_MUX(x, _) \ - RING_BUF_DECLARE(uart_rx_ringbuf_##x, \ - CONFIG_UART_MUX_RINGBUF_SIZE); \ - STRUCT_SECTION_ITERABLE(uart_mux, uart_mux_##x) = { \ - .rx_ringbuf = &uart_rx_ringbuf_##x, \ - } - -LISTIFY(CONFIG_UART_MUX_REAL_DEVICE_COUNT, DEFINE_UART_MUX, (;), _); - -STRUCT_SECTION_START_EXTERN(uart_mux); -STRUCT_SECTION_END_EXTERN(uart_mux); - -/* UART Mux Driver Status Codes */ -enum uart_mux_status_code { - UART_MUX_UNKNOWN, /* Initial connection status */ - UART_MUX_CONFIGURED, /* UART mux configuration done */ - UART_MUX_CONNECTED, /* UART mux connected */ - UART_MUX_DISCONNECTED, /* UART mux connection lost */ -}; - -struct uart_mux_config { -}; - -struct uart_mux_dev_data { - sys_snode_t node; - - /* Configuration data */ - struct uart_mux_config cfg; - - /* This UART mux device */ - const struct device *dev; - - /* The UART device where we are running on top of */ - struct uart_mux *real_uart; - - /* TX worker that will mux the transmitted data */ - struct k_work tx_work; - - /* ISR function callback worker */ - struct k_work cb_work; - - /* ISR function callback */ - uart_irq_callback_user_data_t cb; - void *cb_user_data; - - /* Attach callback */ - uart_mux_attach_cb_t attach_cb; - void *attach_user_data; - - /* TX data from application is handled via ring buffer */ - struct ring_buf *tx_ringbuf; - - /* Received data is routed from RX worker to application via ring - * buffer. - */ - struct ring_buf *rx_ringbuf; - - /* Muxing status */ - enum uart_mux_status_code status; - - /* DLCI (muxing virtual channel) linked to this muxed UART */ - struct gsm_dlci *dlci; - - /* Status (enabled / disabled) for RX and TX */ - bool rx_enabled : 1; - bool tx_enabled : 1; - bool rx_ready : 1; - bool tx_ready : 1; - bool in_use : 1; -}; - -struct uart_mux_cfg_data { -}; - -static sys_slist_t uart_mux_data_devlist; - -static void uart_mux_cb_work(struct k_work *work) -{ - struct uart_mux_dev_data *dev_data = - CONTAINER_OF(work, struct uart_mux_dev_data, cb_work); - - dev_data->cb(dev_data->dev, dev_data->cb_user_data); -} - -static int uart_mux_consume_ringbuf(struct uart_mux *uart_mux) -{ - uint8_t *data; - size_t len; - int ret; - - len = ring_buf_get_claim(uart_mux->rx_ringbuf, &data, - CONFIG_UART_MUX_RINGBUF_SIZE); - if (len == 0) { - LOG_DBG("Ringbuf %p is empty!", uart_mux->rx_ringbuf); - return 0; - } - - /* We have now received muxed data. Push that through GSM mux API which - * will parse it and call proper functions to get the data to the user. - */ - - if (IS_ENABLED(CONFIG_UART_MUX_VERBOSE_DEBUG)) { - char tmp[sizeof("RECV muxed ") + 10]; - - snprintk(tmp, sizeof(tmp), "RECV muxed %s", - uart_mux->uart->name); - LOG_HEXDUMP_DBG(data, len, tmp); - } - - gsm_mux_recv_buf(uart_mux->mux, data, len); - - ret = ring_buf_get_finish(uart_mux->rx_ringbuf, len); - if (ret < 0) { - LOG_DBG("Cannot flush ring buffer (%d)", ret); - } - - return -EAGAIN; -} - -static void uart_mux_rx_work(struct k_work *work) -{ - struct uart_mux *uart_mux = - CONTAINER_OF(work, struct uart_mux, rx_work);; - int ret; - - do { - ret = uart_mux_consume_ringbuf(uart_mux); - } while (ret == -EAGAIN); -} - -static void uart_mux_tx_work(struct k_work *work) -{ - struct uart_mux_dev_data *dev_data = - CONTAINER_OF(work, struct uart_mux_dev_data, tx_work); - uint8_t *data; - size_t len; - - len = ring_buf_get_claim(dev_data->tx_ringbuf, &data, - CONFIG_UART_MUX_RINGBUF_SIZE); - if (!len) { - LOG_DBG("Ringbuf %p empty!", dev_data->tx_ringbuf); - return; - } - - LOG_DBG("Got %ld bytes from ringbuffer send to uart %p", (unsigned long)len, - dev_data->dev); - - if (IS_ENABLED(CONFIG_UART_MUX_VERBOSE_DEBUG)) { - char tmp[sizeof("SEND _x") + - sizeof(CONFIG_UART_MUX_DEVICE_NAME)]; - - snprintk(tmp, sizeof(tmp), "SEND %s", - dev_data->dev->name); - LOG_HEXDUMP_DBG(data, len, tmp); - } - - (void)gsm_dlci_send(dev_data->dlci, data, len); - - ring_buf_get_finish(dev_data->tx_ringbuf, len); -} - -static int uart_mux_init(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - gsm_mux_init(); - - dev_data->dev = dev; - dev_data->real_uart = NULL; /* will be set when user attach to it */ - - sys_slist_find_and_remove(&uart_mux_data_devlist, &dev_data->node); - sys_slist_prepend(&uart_mux_data_devlist, &dev_data->node); - - k_work_init(&dev_data->tx_work, uart_mux_tx_work); - k_work_init(&dev_data->cb_work, uart_mux_cb_work); - - LOG_DBG("Device %s dev %p dev_data %p cfg %p created", - dev->name, dev, dev_data, dev->config); - - return 0; -} - -/* This IRQ handler is shared between muxing UARTs. After we have received - * data from it in uart_mux_rx_work(), we push the data to GSM mux API which - * will call proper callbacks to pass data to correct recipient. - */ -static void uart_mux_isr(const struct device *uart, void *user_data) -{ - struct uart_mux *real_uart = user_data; - int rx = 0; - size_t wrote = 0; - - /* Read all data off UART, and send to RX worker for unmuxing */ - while (uart_irq_update(uart) && - uart_irq_rx_ready(uart)) { - rx = uart_fifo_read(uart, real_uart->rx_buf, - sizeof(real_uart->rx_buf)); - if (rx <= 0) { - continue; - } - - wrote = ring_buf_put(real_uart->rx_ringbuf, - real_uart->rx_buf, rx); - if (wrote < rx) { - LOG_ERR("Ring buffer full, drop %ld bytes", (long)(rx - wrote)); - } - - k_work_submit_to_queue(&uart_mux_workq, &real_uart->rx_work); - } -} - -static void uart_mux_flush_isr(const struct device *dev) -{ - uint8_t c; - - while (uart_fifo_read(dev, &c, 1) > 0) { - continue; - } -} - -void uart_mux_disable(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - const struct device *uart = dev_data->real_uart->uart; - - uart_irq_rx_disable(uart); - uart_irq_tx_disable(uart); - uart_mux_flush_isr(uart); - - gsm_mux_detach(dev_data->real_uart->mux); -} - -void uart_mux_enable(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - struct uart_mux *real_uart = dev_data->real_uart; - - LOG_DBG("Claiming uart for uart_mux"); - - uart_irq_rx_disable(real_uart->uart); - uart_irq_tx_disable(real_uart->uart); - uart_mux_flush_isr(real_uart->uart); - uart_irq_callback_user_data_set( - real_uart->uart, uart_mux_isr, - real_uart); - - uart_irq_rx_enable(real_uart->uart); -} - -static void dlci_created_cb(struct gsm_dlci *dlci, bool connected, - void *user_data) -{ - struct uart_mux_dev_data *dev_data = user_data; - - if (connected) { - dev_data->status = UART_MUX_CONNECTED; - } else { - dev_data->status = UART_MUX_DISCONNECTED; - } - - LOG_DBG("%s %s", dev_data->dev->name, - dev_data->status == UART_MUX_CONNECTED ? "connected" : - "disconnected"); - - if (dev_data->attach_cb) { - dev_data->attach_cb(dev_data->dev, - dlci ? gsm_dlci_id(dlci) : -1, - connected, - dev_data->attach_user_data); - } -} - -static int init_real_uart(const struct device *mux, const struct device *uart, - struct uart_mux **mux_uart) -{ - bool found = false; - struct uart_mux *real_uart; - - for (real_uart = TYPE_SECTION_START(uart_mux); - real_uart != TYPE_SECTION_END(uart_mux); - real_uart++) { - if (real_uart->uart == uart) { - found = true; - break; - } - } - - if (found == false) { - for (real_uart = TYPE_SECTION_START(uart_mux); - real_uart != TYPE_SECTION_END(uart_mux); - real_uart++) { - if (real_uart->uart == NULL) { - real_uart->uart = uart; - found = true; - break; - } - } - - if (found == false) { - return -ENOENT; - } - } - - /* Init the real UART only once */ - if (atomic_cas(&real_uart->init_done, false, true)) { - real_uart->mux = gsm_mux_create(mux); - - LOG_DBG("Initializing UART %s and GSM mux %p", - real_uart->uart->name, (void *)real_uart->mux); - - if (!real_uart->mux) { - real_uart->uart = NULL; - atomic_clear(&real_uart->init_done); - return -ENOMEM; - } - - k_work_init(&real_uart->rx_work, uart_mux_rx_work); - k_mutex_init(&real_uart->lock); - - uart_irq_rx_disable(real_uart->uart); - uart_irq_tx_disable(real_uart->uart); - uart_mux_flush_isr(real_uart->uart); - uart_irq_callback_user_data_set( - real_uart->uart, uart_mux_isr, - real_uart); - - uart_irq_rx_enable(real_uart->uart); - } - - __ASSERT(real_uart->uart, "Real UART not set"); - - *mux_uart = real_uart; - - return 0; -} - -/* This will bind the physical (real) UART to this muxed UART */ -static int attach(const struct device *mux_uart, const struct device *uart, - int dlci_address, uart_mux_attach_cb_t cb, - void *user_data) -{ - sys_snode_t *sn, *sns; - - if (mux_uart == NULL || uart == NULL) { - return -EINVAL; - } - - LOG_DBG("Attach DLCI %d (%s) to %s", dlci_address, - mux_uart->name, uart->name); - - SYS_SLIST_FOR_EACH_NODE_SAFE(&uart_mux_data_devlist, sn, sns) { - struct uart_mux_dev_data *dev_data = - CONTAINER_OF(sn, struct uart_mux_dev_data, node); - - if (dev_data->dev == mux_uart) { - struct uart_mux *real_uart; - int ret; - - ret = init_real_uart(mux_uart, uart, &real_uart); - if (ret < 0) { - return ret; - } - - dev_data->real_uart = real_uart; - dev_data->tx_ready = true; - dev_data->tx_enabled = true; - dev_data->rx_enabled = true; - dev_data->attach_cb = cb; - dev_data->attach_user_data = user_data; - dev_data->status = UART_MUX_CONFIGURED; - - ret = gsm_dlci_create(real_uart->mux, - mux_uart, - dlci_address, - dlci_created_cb, - dev_data, - &dev_data->dlci); - if (ret < 0) { - LOG_DBG("Cannot create DLCI %d (%d)", - dlci_address, ret); - return ret; - } - - return 0; - } - } - - return -ENOENT; -} - -static int uart_mux_poll_in(const struct device *dev, unsigned char *p_char) -{ - ARG_UNUSED(dev); - ARG_UNUSED(p_char); - - return -ENOTSUP; -} - -static void uart_mux_poll_out(const struct device *dev, - unsigned char out_char) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - if (dev_data->dev == NULL) { - return; - } - - (void)gsm_dlci_send(dev_data->dlci, &out_char, 1); -} - -static int uart_mux_err_check(const struct device *dev) -{ - ARG_UNUSED(dev); - - return -ENOTSUP; -} - -static int uart_mux_fifo_fill(const struct device *dev, - const uint8_t *tx_data, int len) -{ - struct uart_mux_dev_data *dev_data; - size_t wrote; - - if (dev == NULL) { - return -EINVAL; - } - - dev_data = dev->data; - if (dev_data->dev == NULL) { - return -ENOENT; - } - - /* If we're not in ISR context, do the xfer synchronously. This - * effectively let's applications use this implementation of fifo_fill - * as a multi-byte poll_out which prevents each byte getting wrapped by - * mux headers. - */ - if (!k_is_in_isr() && dev_data->dlci) { - return gsm_dlci_send(dev_data->dlci, tx_data, len); - } - - LOG_DBG("dev_data %p len %d tx_ringbuf space %u", - dev_data, len, ring_buf_space_get(dev_data->tx_ringbuf)); - - if (dev_data->status != UART_MUX_CONNECTED) { - LOG_WRN("UART mux not connected, drop %d bytes", len); - return 0; - } - - dev_data->tx_ready = false; - - wrote = ring_buf_put(dev_data->tx_ringbuf, tx_data, len); - if (wrote < len) { - LOG_WRN("Ring buffer full, drop %ld bytes", (long)(len - wrote)); - } - - k_work_submit_to_queue(&uart_mux_workq, &dev_data->tx_work); - - return wrote; -} - -static int uart_mux_fifo_read(const struct device *dev, uint8_t *rx_data, - const int size) -{ - struct uart_mux_dev_data *dev_data; - uint32_t len; - - if (dev == NULL) { - return -EINVAL; - } - - dev_data = dev->data; - if (dev_data->dev == NULL) { - return -ENOENT; - } - - LOG_DBG("%s size %d rx_ringbuf space %u", - dev->name, size, - ring_buf_space_get(dev_data->rx_ringbuf)); - - len = ring_buf_get(dev_data->rx_ringbuf, rx_data, size); - - if (ring_buf_is_empty(dev_data->rx_ringbuf)) { - dev_data->rx_ready = false; - } - - return len; -} - -static void uart_mux_irq_tx_enable(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - if (dev_data == NULL || dev_data->dev == NULL) { - return; - } - - dev_data->tx_enabled = true; - - if (dev_data->cb && dev_data->tx_ready) { - k_work_submit_to_queue(&uart_mux_workq, &dev_data->cb_work); - } -} - -static void uart_mux_irq_tx_disable(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - if (dev_data == NULL || dev_data->dev == NULL) { - return; - } - - dev_data->tx_enabled = false; -} - -static int uart_mux_irq_tx_ready(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - if (dev_data == NULL) { - return -EINVAL; - } - - if (dev_data->dev == NULL) { - return -ENOENT; - } - - return dev_data->tx_ready; -} - -static void uart_mux_irq_rx_enable(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - if (dev_data == NULL || dev_data->dev == NULL) { - return; - } - - dev_data->rx_enabled = true; - - if (dev_data->cb && dev_data->rx_ready) { - k_work_submit_to_queue(&uart_mux_workq, &dev_data->cb_work); - } -} - -static void uart_mux_irq_rx_disable(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - if (dev_data == NULL || dev_data->dev == NULL) { - return; - } - - dev_data->rx_enabled = false; -} - -static int uart_mux_irq_tx_complete(const struct device *dev) -{ - ARG_UNUSED(dev); - - return -ENOTSUP; -} - -static int uart_mux_irq_rx_ready(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - if (dev_data == NULL) { - return -EINVAL; - } - - if (dev_data->dev == NULL) { - return -ENOENT; - } - - return dev_data->rx_ready; -} - -static void uart_mux_irq_err_enable(const struct device *dev) -{ - ARG_UNUSED(dev); -} - -static void uart_mux_irq_err_disable(const struct device *dev) -{ - ARG_UNUSED(dev); -} - -static int uart_mux_irq_is_pending(const struct device *dev) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - if (dev_data == NULL || dev_data->dev == NULL) { - return 0; - } - - if (dev_data->tx_ready && dev_data->tx_enabled) { - return 1; - } - - if (dev_data->rx_ready && dev_data->rx_enabled) { - return 1; - } - - return 0; -} - -static int uart_mux_irq_update(const struct device *dev) -{ - ARG_UNUSED(dev); - - return 1; -} - -static void uart_mux_irq_callback_set(const struct device *dev, - uart_irq_callback_user_data_t cb, - void *user_data) -{ - struct uart_mux_dev_data *dev_data = dev->data; - - if (dev_data == NULL) { - return; - } - - dev_data->cb = cb; - dev_data->cb_user_data = user_data; -} - -static struct uart_mux_driver_api uart_mux_driver_api = { - .uart_api.poll_in = uart_mux_poll_in, - .uart_api.poll_out = uart_mux_poll_out, - .uart_api.err_check = uart_mux_err_check, - .uart_api.fifo_fill = uart_mux_fifo_fill, - .uart_api.fifo_read = uart_mux_fifo_read, - .uart_api.irq_tx_enable = uart_mux_irq_tx_enable, - .uart_api.irq_tx_disable = uart_mux_irq_tx_disable, - .uart_api.irq_tx_ready = uart_mux_irq_tx_ready, - .uart_api.irq_rx_enable = uart_mux_irq_rx_enable, - .uart_api.irq_rx_disable = uart_mux_irq_rx_disable, - .uart_api.irq_tx_complete = uart_mux_irq_tx_complete, - .uart_api.irq_rx_ready = uart_mux_irq_rx_ready, - .uart_api.irq_err_enable = uart_mux_irq_err_enable, - .uart_api.irq_err_disable = uart_mux_irq_err_disable, - .uart_api.irq_is_pending = uart_mux_irq_is_pending, - .uart_api.irq_update = uart_mux_irq_update, - .uart_api.irq_callback_set = uart_mux_irq_callback_set, - - .attach = attach, -}; - -const struct device *uart_mux_alloc(void) -{ - sys_snode_t *sn, *sns; - - SYS_SLIST_FOR_EACH_NODE_SAFE(&uart_mux_data_devlist, sn, sns) { - struct uart_mux_dev_data *dev_data = - CONTAINER_OF(sn, struct uart_mux_dev_data, node); - - if (dev_data->in_use) { - continue; - } - - dev_data->in_use = true; - - return dev_data->dev; - } - - return NULL; -} - -#ifdef CONFIG_USERSPACE -static inline const struct device *z_vrfy_uart_mux_find(int dlci_address) -{ - return z_impl_uart_mux_find(dlci_address); -} -#include -#endif /* CONFIG_USERSPACE */ - -const struct device *z_impl_uart_mux_find(int dlci_address) -{ - sys_snode_t *sn, *sns; - - SYS_SLIST_FOR_EACH_NODE_SAFE(&uart_mux_data_devlist, sn, sns) { - struct uart_mux_dev_data *dev_data = - CONTAINER_OF(sn, struct uart_mux_dev_data, node); - - if (!dev_data->in_use) { - continue; - } - - if (dev_data->dlci == NULL) { - continue; - } - - if (gsm_dlci_id(dev_data->dlci) == dlci_address) { - return dev_data->dev; - } - } - - return NULL; -} - -int uart_mux_send(const struct device *uart, const uint8_t *buf, size_t size) -{ - struct uart_mux_dev_data *dev_data = uart->data; - size_t remaining = size; - - if (size == 0) { - return 0; - } - - if (atomic_get(&dev_data->real_uart->init_done) == false) { - return -ENODEV; - } - - if (IS_ENABLED(CONFIG_UART_MUX_VERBOSE_DEBUG)) { - char tmp[sizeof("SEND muxed ") + 10]; - - snprintk(tmp, sizeof(tmp), "SEND muxed %s", - dev_data->real_uart->uart->name); - LOG_HEXDUMP_DBG(buf, size, tmp); - } - - k_mutex_lock(&dev_data->real_uart->lock, K_FOREVER); - - do { - uart_poll_out(dev_data->real_uart->uart, *buf++); - } while (--remaining); - - k_mutex_unlock(&dev_data->real_uart->lock); - - return size; -} - -int uart_mux_recv(const struct device *mux, struct gsm_dlci *dlci, - uint8_t *data, - size_t len) -{ - struct uart_mux_dev_data *dev_data = mux->data; - size_t wrote = 0; - - LOG_DBG("%s: dlci %p data %p len %zd", mux->name, (void *)dlci, - data, len); - - if (IS_ENABLED(CONFIG_UART_MUX_VERBOSE_DEBUG)) { - char tmp[sizeof("RECV _x") + - sizeof(CONFIG_UART_MUX_DEVICE_NAME)]; - - snprintk(tmp, sizeof(tmp), "RECV %s", - dev_data->dev->name); - LOG_HEXDUMP_DBG(data, len, tmp); - } - - wrote = ring_buf_put(dev_data->rx_ringbuf, data, len); - if (wrote < len) { - LOG_ERR("Ring buffer full, drop %ld bytes", (long)(len - wrote)); - } - - dev_data->rx_ready = true; - - if (dev_data->cb && dev_data->rx_enabled) { - k_work_submit_to_queue(&uart_mux_workq, &dev_data->cb_work); - } - - return wrote; -} - -void uart_mux_foreach(uart_mux_cb_t cb, void *user_data) -{ - sys_snode_t *sn, *sns; - - SYS_SLIST_FOR_EACH_NODE_SAFE(&uart_mux_data_devlist, sn, sns) { - struct uart_mux_dev_data *dev_data = - CONTAINER_OF(sn, struct uart_mux_dev_data, node); - - if (!dev_data->in_use) { - continue; - } - - cb(dev_data->real_uart->uart, dev_data->dev, - dev_data->dlci ? gsm_dlci_id(dev_data->dlci) : -1, - user_data); - } -} - -#define DEFINE_UART_MUX_CFG_DATA(x, _) \ - struct uart_mux_cfg_data uart_mux_config_##x = { \ - } - -#define DEFINE_UART_MUX_DEV_DATA(x, _) \ - RING_BUF_DECLARE(tx_ringbuf_##x, CONFIG_UART_MUX_RINGBUF_SIZE); \ - RING_BUF_DECLARE(rx_ringbuf_##x, CONFIG_UART_MUX_RINGBUF_SIZE); \ - static struct uart_mux_dev_data uart_mux_dev_data_##x = { \ - .tx_ringbuf = &tx_ringbuf_##x, \ - .rx_ringbuf = &rx_ringbuf_##x, \ - } - -#define DEFINE_UART_MUX_DEVICE(x, _) \ - DEVICE_DEFINE(uart_mux_##x, \ - CONFIG_UART_MUX_DEVICE_NAME "_" #x, \ - &uart_mux_init, \ - NULL, \ - &uart_mux_dev_data_##x, \ - &uart_mux_config_##x, \ - POST_KERNEL, \ - CONFIG_CONSOLE_INIT_PRIORITY, \ - &uart_mux_driver_api) - -LISTIFY(CONFIG_UART_MUX_DEVICE_COUNT, DEFINE_UART_MUX_CFG_DATA, (;), _); -LISTIFY(CONFIG_UART_MUX_DEVICE_COUNT, DEFINE_UART_MUX_DEV_DATA, (;), _); -LISTIFY(CONFIG_UART_MUX_DEVICE_COUNT, DEFINE_UART_MUX_DEVICE, (;), _); - -static int init_uart_mux(void) -{ - - k_work_queue_start(&uart_mux_workq, uart_mux_stack, - K_KERNEL_STACK_SIZEOF(uart_mux_stack), - K_PRIO_COOP(UART_MUX_WORKQ_PRIORITY), NULL); - k_thread_name_set(&uart_mux_workq.thread, "uart_mux_workq"); - - return 0; -} - -SYS_INIT(init_uart_mux, POST_KERNEL, CONFIG_CONSOLE_INIT_PRIORITY); diff --git a/drivers/console/uart_mux_internal.h b/drivers/console/uart_mux_internal.h deleted file mode 100644 index 79e0f3264bec0..0000000000000 --- a/drivers/console/uart_mux_internal.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Send data to real UART (the data should be muxed already) - * - * @param uart Muxed uart - * @param buf Data to send - * @param size Data length - * - * @return >=0 if data was sent (and number of bytes sent), <0 if error - */ -int uart_mux_send(const struct device *uart, const uint8_t *buf, size_t size); - -/** - * @brief Receive unmuxed data. - * - * @param mux UART mux device structure. - * @param dlci DLCI id for the muxing channel that should receive the data. - * @param data Received data (already unmuxed) - * @param len Length of the received data - * - * @retval >=0 No errors, number of bytes received - * @retval <0 Error - */ -int uart_mux_recv(const struct device *mux, struct gsm_dlci *dlci, - uint8_t *data, size_t len); - -#ifdef __cplusplus -} -#endif diff --git a/drivers/counter/Kconfig.esp32_tmr b/drivers/counter/Kconfig.esp32_tmr index 52f1c55c695bb..93f6e2503e2c3 100644 --- a/drivers/counter/Kconfig.esp32_tmr +++ b/drivers/counter/Kconfig.esp32_tmr @@ -10,3 +10,11 @@ config COUNTER_TMR_ESP32 help Enables the Counter driver API based on Espressif's General Purpose Timers for ESP32 series devices. + +config COUNTER_TMR_RTC_ESP32 + bool "ESP32 Counter Driver based on GP-Timers" + default y + depends on DT_HAS_ESPRESSIF_ESP32_RTC_TIMER_ENABLED + help + Enables the Counter driver API based on Espressif's General + Purpose Timers for ESP32 series devices. diff --git a/drivers/counter/Kconfig.mcux_lptmr b/drivers/counter/Kconfig.mcux_lptmr index 98bf35dec5caa..af961c790e1d4 100644 --- a/drivers/counter/Kconfig.mcux_lptmr +++ b/drivers/counter/Kconfig.mcux_lptmr @@ -6,6 +6,17 @@ config COUNTER_MCUX_LPTMR bool "MCUX LPTMR driver" default y - depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED + depends on DT_HAS_NXP_LPTMR_ENABLED || \ + COUNTER_MCUX_KINETIS_LPTMR help Enable support for the MCUX Low Power Timer (LPTMR). + +config COUNTER_MCUX_KINETIS_LPTMR + bool + default y + depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED + select DEPRECATED + help + The compatible string "nxp,kinetis-lptmr" should + be swiched to "nxp,lptmr" in DT. The former will + be removed eventually. diff --git a/drivers/counter/Kconfig.nxp_mrt b/drivers/counter/Kconfig.nxp_mrt index 6bd8c6dcd024e..cf3bb84558f19 100644 --- a/drivers/counter/Kconfig.nxp_mrt +++ b/drivers/counter/Kconfig.nxp_mrt @@ -6,5 +6,6 @@ config COUNTER_NXP_MRT default y depends on DT_HAS_NXP_MRT_CHANNEL_ENABLED && \ DT_HAS_NXP_MRT_ENABLED + select RESET help Enable driver for the NXP Multirate Timer (MRT). diff --git a/drivers/counter/counter_ambiq_timer.c b/drivers/counter/counter_ambiq_timer.c index 67df6c5647f69..2036102138dd1 100644 --- a/drivers/counter/counter_ambiq_timer.c +++ b/drivers/counter/counter_ambiq_timer.c @@ -18,10 +18,11 @@ LOG_MODULE_REGISTER(ambiq_counter, CONFIG_COUNTER_LOG_LEVEL); static void counter_ambiq_isr(void *arg); -#define TIMER_IRQ (DT_INST_IRQN(0)) - struct counter_ambiq_config { struct counter_config_info counter_info; + uint32_t instance; + uint32_t clk_src; + void (*irq_config_func)(void); }; struct counter_ambiq_data { @@ -31,33 +32,76 @@ struct counter_ambiq_data { static struct k_spinlock lock; -static int counter_ambiq_init(const struct device *dev) +#if defined(CONFIG_SOC_SERIES_APOLLO3X) +static void counter_irq_config_func(void) { - am_hal_timer_config_t tc; + /* Apollo3 counters share the same irq number, connect to counter0 once when init and handle + * different banks in counter_ambiq_isr + */ + static bool global_irq_init = true; + + if (!global_irq_init) { + return; + } + + global_irq_init = false; + + /* Shared irq config default to ctimer0. */ + NVIC_ClearPendingIRQ(CTIMER_IRQn); + IRQ_CONNECT(CTIMER_IRQn, DT_INST_IRQ(0, priority), counter_ambiq_isr, DEVICE_DT_INST_GET(0), + 0); + irq_enable(CTIMER_IRQn); +}; +#endif +static int counter_ambiq_init(const struct device *dev) +{ k_spinlock_key_t key = k_spin_lock(&lock); + const struct counter_ambiq_config *cfg = dev->config; + +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + /* Timer configuration */ + am_hal_ctimer_config_t sContTimer; + /* Create 32-bit timer */ + sContTimer.ui32Link = 1; + /* Set up TimerA. */ + sContTimer.ui32TimerAConfig = (AM_HAL_CTIMER_FN_REPEAT | AM_HAL_CTIMER_INT_ENABLE | + (cfg->clk_src << CTIMER_CTRL0_TMRA0CLK_Pos)); + /* Set up TimerB. */ + sContTimer.ui32TimerBConfig = 0; + + am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0); + + am_hal_ctimer_clear(cfg->instance, AM_HAL_CTIMER_BOTH); + am_hal_ctimer_config(cfg->instance, &sContTimer); + counter_irq_config_func(); +#else + am_hal_timer_config_t tc; am_hal_timer_default_config_set(&tc); - tc.eInputClock = AM_HAL_TIMER_CLOCK_HFRC_DIV16; + tc.eInputClock = cfg->clk_src; tc.eFunction = AM_HAL_TIMER_FN_UPCOUNT; tc.ui32PatternLimit = 0; - am_hal_timer_config(0, &tc); + am_hal_timer_config(cfg->instance, &tc); + cfg->irq_config_func(); +#endif k_spin_unlock(&lock, key); - NVIC_ClearPendingIRQ(TIMER_IRQ); - IRQ_CONNECT(TIMER_IRQ, 0, counter_ambiq_isr, DEVICE_DT_INST_GET(0), 0); - irq_enable(TIMER_IRQ); - return 0; } static int counter_ambiq_start(const struct device *dev) { + const struct counter_ambiq_config *cfg = dev->config; k_spinlock_key_t key = k_spin_lock(&lock); - am_hal_timer_start(0); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_ctimer_start(cfg->instance, AM_HAL_CTIMER_TIMERA); +#else + am_hal_timer_start(cfg->instance); +#endif k_spin_unlock(&lock, key); @@ -66,9 +110,15 @@ static int counter_ambiq_start(const struct device *dev) static int counter_ambiq_stop(const struct device *dev) { + const struct counter_ambiq_config *cfg = dev->config; + k_spinlock_key_t key = k_spin_lock(&lock); - am_hal_timer_stop(0); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_ctimer_stop(cfg->instance, AM_HAL_CTIMER_BOTH); +#else + am_hal_timer_stop(cfg->instance); +#endif k_spin_unlock(&lock, key); @@ -77,9 +127,16 @@ static int counter_ambiq_stop(const struct device *dev) static int counter_ambiq_get_value(const struct device *dev, uint32_t *ticks) { + const struct counter_ambiq_config *cfg = dev->config; + k_spinlock_key_t key = k_spin_lock(&lock); - *ticks = am_hal_timer_read(0); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + *ticks = (am_hal_ctimer_read(cfg->instance, AM_HAL_CTIMER_TIMERA)) | + (am_hal_ctimer_read(cfg->instance, AM_HAL_CTIMER_TIMERB) << 16); +#else + *ticks = am_hal_timer_read(cfg->instance); +#endif k_spin_unlock(&lock, key); @@ -91,21 +148,34 @@ static int counter_ambiq_set_alarm(const struct device *dev, uint8_t chan_id, { ARG_UNUSED(chan_id); struct counter_ambiq_data *data = dev->data; + const struct counter_ambiq_config *cfg = dev->config; uint32_t now; counter_ambiq_get_value(dev, &now); k_spinlock_key_t key = k_spin_lock(&lock); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_ctimer_int_clear(AM_HAL_CTIMER_INT_TIMERA0C0); + am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERA0C0); + + if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { + am_hal_ctimer_compare_set(cfg->instance, AM_HAL_CTIMER_BOTH, 0, + now + alarm_cfg->ticks); + } else { + am_hal_ctimer_compare_set(cfg->instance, AM_HAL_CTIMER_BOTH, 0, alarm_cfg->ticks); + } +#else /* Enable interrupt, due to counter_ambiq_cancel_alarm() disables it*/ - am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); - am_hal_timer_interrupt_enable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(cfg->instance, AM_HAL_TIMER_COMPARE1)); + am_hal_timer_interrupt_enable(AM_HAL_TIMER_MASK(cfg->instance, AM_HAL_TIMER_COMPARE1)); if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { - am_hal_timer_compare1_set(0, now + alarm_cfg->ticks); + am_hal_timer_compare1_set(cfg->instance, now + alarm_cfg->ticks); } else { - am_hal_timer_compare1_set(0, alarm_cfg->ticks); + am_hal_timer_compare1_set(cfg->instance, alarm_cfg->ticks); } +#endif data->user_data = alarm_cfg->user_data; data->callback = alarm_cfg->callback; @@ -118,12 +188,19 @@ static int counter_ambiq_set_alarm(const struct device *dev, uint8_t chan_id, static int counter_ambiq_cancel_alarm(const struct device *dev, uint8_t chan_id) { ARG_UNUSED(chan_id); - + const struct counter_ambiq_config *cfg = dev->config; k_spinlock_key_t key = k_spin_lock(&lock); - am_hal_timer_interrupt_disable(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_ctimer_int_disable(AM_HAL_CTIMER_INT_TIMERA0C0); /* Reset the compare register */ - am_hal_timer_compare1_set(0, 0); + am_hal_ctimer_compare_set(cfg->instance, AM_HAL_CTIMER_BOTH, 0, 0); +#else + am_hal_timer_interrupt_disable(AM_HAL_TIMER_MASK(cfg->instance, AM_HAL_TIMER_COMPARE1)); + /* Reset the compare register */ + am_hal_timer_compare1_set(cfg->instance, 0); +#endif + k_spin_unlock(&lock, key); return 0; @@ -163,33 +240,71 @@ static const struct counter_driver_api counter_api = { .get_top_value = counter_ambiq_get_top_value, }; +#define APOLLO3_HANDLE_SHARED_TIMER_IRQ(n) \ + static const struct device *const dev_##n = DEVICE_DT_INST_GET(n); \ + struct counter_ambiq_data *const data_##n = dev_##n->data; \ + uint32_t status_##n = CTIMERn(n)->INTSTAT; \ + status_##n &= CTIMERn(n)->INTEN; \ + if (status_##n) { \ + CTIMERn(n)->INTCLR = AM_HAL_CTIMER_INT_TIMERA0C0; \ + counter_ambiq_get_value(dev_##n, &now); \ + if (data_##n->callback) { \ + data_##n->callback(dev_##n, 0, now, data_##n->user_data); \ + } \ + } + static void counter_ambiq_isr(void *arg) { + uint32_t now = 0; + +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + ARG_UNUSED(arg); + + DT_INST_FOREACH_STATUS_OKAY(APOLLO3_HANDLE_SHARED_TIMER_IRQ) +#else const struct device *dev = (const struct device *)arg; struct counter_ambiq_data *data = dev->data; - uint32_t now = 0; + const struct counter_ambiq_config *cfg = dev->config; - am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(0, AM_HAL_TIMER_COMPARE1)); + am_hal_timer_interrupt_clear(AM_HAL_TIMER_MASK(cfg->instance, AM_HAL_TIMER_COMPARE1)); counter_ambiq_get_value(dev, &now); if (data->callback) { data->callback(dev, 0, now, data->user_data); } +#endif } +#if defined(CONFIG_SOC_SERIES_APOLLO3X) +/* Apollo3 counters share the same irq number, connect irq here will cause build error, so we + * leave this function blank here and do it in counter_irq_config_func + */ +#define AMBIQ_COUNTER_CONFIG_FUNC(idx) static void counter_irq_config_func_##idx(void){}; +#else +#define AMBIQ_COUNTER_CONFIG_FUNC(idx) \ + static void counter_irq_config_func_##idx(void) \ + { \ + NVIC_ClearPendingIRQ(DT_INST_IRQN(idx)); \ + IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority), counter_ambiq_isr, \ + DEVICE_DT_INST_GET(idx), 0); \ + irq_enable(DT_INST_IRQN(idx)); \ + }; +#endif + #define AMBIQ_COUNTER_INIT(idx) \ - \ + static void counter_irq_config_func_##idx(void); \ static struct counter_ambiq_data counter_data_##idx; \ - \ static const struct counter_ambiq_config counter_config_##idx = { \ + .instance = (DT_INST_REG_ADDR(idx) - DT_INST_REG_ADDR(0)) / DT_INST_REG_SIZE(idx), \ + .clk_src = DT_INST_PROP(idx, clk_source), \ .counter_info = {.max_top_value = UINT32_MAX, \ - .freq = 6000000, \ + .freq = DT_INST_PROP(idx, clock_frequency), \ .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ .channels = 1}, \ + .irq_config_func = counter_irq_config_func_##idx, \ }; \ - \ + AMBIQ_COUNTER_CONFIG_FUNC(idx) \ DEVICE_DT_INST_DEFINE(idx, counter_ambiq_init, NULL, &counter_data_##idx, \ &counter_config_##idx, PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \ &counter_api); - DT_INST_FOREACH_STATUS_OKAY(AMBIQ_COUNTER_INIT); diff --git a/drivers/counter/counter_andes_atcpit100.c b/drivers/counter/counter_andes_atcpit100.c index 5252c2c56cb3a..3fc69215f60cc 100644 --- a/drivers/counter/counter_andes_atcpit100.c +++ b/drivers/counter/counter_andes_atcpit100.c @@ -103,12 +103,6 @@ static void atcpit100_irq_handler(void *arg) if (int_status & TIMER0_CHANNEL(i)) { int_enable &= ~TIMER0_CHANNEL(i); ch_enable &= ~TIMER0_CHANNEL(i); - - cb = data->ch_data[i].alarm_callback; - data->ch_data[i].alarm_callback = NULL; - - cur_ticks = get_current_tick(dev, 3); - cb(dev, i, cur_ticks, data->ch_data[i].alarm_user_data); } } @@ -118,6 +112,17 @@ static void atcpit100_irq_handler(void *arg) /* Clear interrupt status */ sys_write32(int_status, PIT_ISTA(dev)); + + for (i = 0; i < CH_NUM_PER_COUNTER; i++) { + if (int_status & TIMER0_CHANNEL(i)) { + cur_ticks = get_current_tick(dev, 3); + cb = data->ch_data[i].alarm_callback; + data->ch_data[i].alarm_callback = NULL; + if (cb != NULL) { + cb(dev, i, cur_ticks, data->ch_data[i].alarm_user_data); + } + } + } } static int counter_atcpit100_init(const struct device *dev) @@ -494,7 +499,7 @@ static const struct counter_driver_api atcpit100_driver_api = { NULL, \ &atcpit100_data_##n, \ &atcpit100_config_##n, \ - POST_KERNEL, \ + PRE_KERNEL_1, \ CONFIG_KERNEL_INIT_PRIORITY_DEFAULT, \ &atcpit100_driver_api); \ \ diff --git a/drivers/counter/counter_esp32_rtc.c b/drivers/counter/counter_esp32_rtc.c index 0b7e8bbbb27cc..379a9f0e57b29 100644 --- a/drivers/counter/counter_esp32_rtc.c +++ b/drivers/counter/counter_esp32_rtc.c @@ -12,11 +12,15 @@ */ #include "soc/rtc_cntl_reg.h" #include "soc/rtc.h" +#include +#include #include #include #include #include +#include +#include #if defined(CONFIG_SOC_SERIES_ESP32C3) #include @@ -38,21 +42,25 @@ static void counter_esp32_isr(void *arg); struct counter_esp32_config { struct counter_config_info counter_info; int irq_source; + const struct device *clock_dev; }; struct counter_esp32_data { struct counter_alarm_cfg alarm_cfg; uint32_t ticks; + uint32_t clk_src_freq; }; static int counter_esp32_init(const struct device *dev) { const struct counter_esp32_config *cfg = dev->config; + struct counter_esp32_data *data = dev->data; - /* SLOW_CK is the default clk source */ - if (cfg->counter_info.freq != rtc_clk_slow_freq_get_hz()) { - return -EINVAL; - } + + /* RTC_SLOW_CLK is the default clk source */ + clock_control_get_rate(cfg->clock_dev, + (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW, + &data->clk_src_freq); esp_intr_alloc(cfg->irq_source, 0, @@ -80,22 +88,14 @@ static int counter_esp32_stop(const struct device *dev) * reset, will not stop or reset the RTC timer * ESP32 TRM v4.6 sec. 31.3.11 */ - return -ENOTSUP; + return 0; } static int counter_esp32_get_value(const struct device *dev, uint32_t *ticks) { ARG_UNUSED(dev); - SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE); -#if defined(CONFIG_SOC_SERIES_ESP32) - while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) { - /* might take 1 RTC slowclk period, don't flood RTC bus */ - k_sleep(K_USEC(1)); - } - SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR); -#endif - *ticks = (uint32_t) READ_PERI_REG(RTC_CNTL_TIME0_REG); + *ticks = (uint32_t) rtc_cntl_ll_get_rtc_time(); return 0; } @@ -106,26 +106,32 @@ static int counter_esp32_set_alarm(const struct device *dev, uint8_t chan_id, ARG_UNUSED(chan_id); struct counter_esp32_data *data = dev->data; uint32_t now; + uint32_t ticks = 0; + +#if defined(CONFIG_SOC_SERIES_ESP32) || defined(CONFIG_SOC_SERIES_ESP32C3) + /* In ESP32/C3 Series the min possible value is 30 us*/ + if (counter_ticks_to_us(dev, alarm_cfg->ticks) < 30) { + return -EINVAL; + } +#endif + data->alarm_cfg.callback = alarm_cfg->callback; + data->alarm_cfg.user_data = alarm_cfg->user_data; counter_esp32_get_value(dev, &now); - if ((alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) == 0) { - WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, (now + alarm_cfg->ticks)); - } else { - WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, alarm_cfg->ticks); - } + ticks = (alarm_cfg->flags & COUNTER_ALARM_CFG_ABSOLUTE) ? alarm_cfg->ticks + : now + alarm_cfg->ticks; + + rtc_cntl_ll_set_wakeup_timer(ticks); /* RTC main timer set alarm value */ CLEAR_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, 0xffffffff); - /* RTC main timer interrupt enable */ - SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_MAIN_TIMER_INT_ENA); - /* RTC main timer set alarm enable */ SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN); - data->alarm_cfg.callback = alarm_cfg->callback; - data->alarm_cfg.user_data = alarm_cfg->user_data; + /* RTC main timer interrupt enable */ + SET_PERI_REG_MASK(RTC_CNTL_INT_ENA_REG, RTC_CNTL_MAIN_TIMER_INT_ENA); return 0; } @@ -172,9 +178,16 @@ static uint32_t counter_esp32_get_pending_int(const struct device *dev) */ static uint32_t counter_esp32_get_top_value(const struct device *dev) { - const struct counter_config_info *info = dev->config; + const struct counter_esp32_config *cfg = dev->config; + + return cfg->counter_info.max_top_value; +} + +static uint32_t counter_esp32_get_freq(const struct device *dev) +{ + struct counter_esp32_data *data = dev->data; - return info->max_top_value; + return data->clk_src_freq; } static struct counter_esp32_data counter_data; @@ -182,10 +195,10 @@ static struct counter_esp32_data counter_data; static const struct counter_esp32_config counter_config = { .counter_info = { .max_top_value = UINT32_MAX, - .freq = DT_INST_PROP(0, slow_clk_freq), .flags = COUNTER_CONFIG_INFO_COUNT_UP, .channels = 1 }, + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)), .irq_source = DT_INST_IRQN(0), }; @@ -198,6 +211,7 @@ static const struct counter_driver_api rtc_timer_esp32_api = { .set_top_value = counter_esp32_set_top_value, .get_pending_int = counter_esp32_get_pending_int, .get_top_value = counter_esp32_get_top_value, + .get_freq = counter_esp32_get_freq, }; static void counter_esp32_isr(void *arg) @@ -222,6 +236,6 @@ DEVICE_DT_INST_DEFINE(0, NULL, &counter_data, &counter_config, - PRE_KERNEL_1, + POST_KERNEL, CONFIG_COUNTER_INIT_PRIORITY, &rtc_timer_esp32_api); diff --git a/drivers/counter/counter_handlers.c b/drivers/counter/counter_handlers.c index 15cd0cb588163..df2a20562a360 100644 --- a/drivers/counter/counter_handlers.c +++ b/drivers/counter/counter_handlers.c @@ -21,30 +21,30 @@ COUNTER_HANDLER(get_pending_int) COUNTER_HANDLER(stop) COUNTER_HANDLER(start) -#include -#include -#include +#include +#include +#include static inline bool z_vrfy_counter_is_counting_up(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_is_counting_up((const struct device *)dev); } -#include +#include static inline uint8_t z_vrfy_counter_get_num_of_channels(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_num_of_channels((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_counter_get_frequency(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_frequency((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_counter_us_to_ticks(const struct device *dev, uint64_t us) @@ -53,7 +53,7 @@ static inline uint32_t z_vrfy_counter_us_to_ticks(const struct device *dev, return z_impl_counter_us_to_ticks((const struct device *)dev, (uint64_t)us); } -#include +#include static inline uint64_t z_vrfy_counter_ticks_to_us(const struct device *dev, uint32_t ticks) @@ -62,7 +62,7 @@ static inline uint64_t z_vrfy_counter_ticks_to_us(const struct device *dev, return z_impl_counter_ticks_to_us((const struct device *)dev, (uint32_t)ticks); } -#include +#include static inline int z_vrfy_counter_get_value(const struct device *dev, uint32_t *ticks) @@ -80,7 +80,7 @@ static inline int z_vrfy_counter_get_value_64(const struct device *dev, return z_impl_counter_get_value_64((const struct device *)dev, ticks); } -#include +#include static inline int z_vrfy_counter_set_channel_alarm(const struct device *dev, uint8_t chan_id, @@ -97,7 +97,7 @@ static inline int z_vrfy_counter_set_channel_alarm(const struct device *dev, (const struct counter_alarm_cfg *)&cfg_copy); } -#include +#include static inline int z_vrfy_counter_cancel_channel_alarm(const struct device *dev, uint8_t chan_id) @@ -106,7 +106,7 @@ static inline int z_vrfy_counter_cancel_channel_alarm(const struct device *dev, return z_impl_counter_cancel_channel_alarm((const struct device *)dev, (uint8_t)chan_id); } -#include +#include static inline int z_vrfy_counter_set_top_value(const struct device *dev, const struct counter_top_cfg @@ -122,21 +122,21 @@ static inline int z_vrfy_counter_set_top_value(const struct device *dev, (const struct counter_top_cfg *) &cfg_copy); } -#include +#include static inline uint32_t z_vrfy_counter_get_top_value(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_COUNTER(dev, get_top_value)); return z_impl_counter_get_top_value((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_counter_get_max_top_value(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_COUNTER)); return z_impl_counter_get_max_top_value((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_counter_get_guard_period(const struct device *dev, uint32_t flags) @@ -145,7 +145,7 @@ static inline uint32_t z_vrfy_counter_get_guard_period(const struct device *dev, return z_impl_counter_get_guard_period((const struct device *)dev, flags); } -#include +#include static inline int z_vrfy_counter_set_guard_period(const struct device *dev, uint32_t ticks, uint32_t flags) @@ -155,4 +155,4 @@ static inline int z_vrfy_counter_set_guard_period(const struct device *dev, ticks, flags); } -#include +#include diff --git a/drivers/counter/counter_ll_stm32_rtc.c b/drivers/counter/counter_ll_stm32_rtc.c index 128586a4a0a43..cab26b1eeeab8 100644 --- a/drivers/counter/counter_ll_stm32_rtc.c +++ b/drivers/counter/counter_ll_stm32_rtc.c @@ -191,7 +191,7 @@ static int rtc_stm32_start(const struct device *dev) /* Enable RTC bus clock */ if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken[0]) != 0) { - LOG_ERR("clock op failed\n"); + LOG_ERR("RTC clock enabling failed\n"); return -EIO; } #else @@ -212,9 +212,9 @@ static int rtc_stm32_stop(const struct device *dev) const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); const struct rtc_stm32_config *cfg = dev->config; - /* Enable RTC bus clock */ - if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken[0]) != 0) { - LOG_ERR("clock op failed\n"); + /* Disable RTC bus clock */ + if (clock_control_off(clk, (clock_control_subsys_t) &cfg->pclken[0]) != 0) { + LOG_ERR("RTC clock disabling failed\n"); return -EIO; } #else diff --git a/drivers/counter/counter_ll_stm32_timer.c b/drivers/counter/counter_ll_stm32_timer.c index 869b31a31f7a0..8f6b1ffd1f43a 100644 --- a/drivers/counter/counter_ll_stm32_timer.c +++ b/drivers/counter/counter_ll_stm32_timer.c @@ -42,9 +42,7 @@ static void(*const set_timer_compare[TIMER_MAX_CH])(TIM_TypeDef *, }; /** Channel to compare get function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32F4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32MP1X) +#if !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t(*const get_timer_compare[TIMER_MAX_CH])(const TIM_TypeDef *) = { LL_TIM_OC_GetCompareCH1, LL_TIM_OC_GetCompareCH2, LL_TIM_OC_GetCompareCH3, LL_TIM_OC_GetCompareCH4, @@ -69,9 +67,7 @@ static void(*const disable_it[TIMER_MAX_CH])(TIM_TypeDef *) = { #ifdef CONFIG_ASSERT /** Channel to interrupt enable check function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32F4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32MP1X) +#if !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t(*const check_it_enabled[TIMER_MAX_CH])(const TIM_TypeDef *) = { LL_TIM_IsEnabledIT_CC1, LL_TIM_IsEnabledIT_CC2, LL_TIM_IsEnabledIT_CC3, LL_TIM_IsEnabledIT_CC4, diff --git a/drivers/counter/counter_mcux_lptmr.c b/drivers/counter/counter_mcux_lptmr.c index 4e1007d9b4927..878a14c196005 100644 --- a/drivers/counter/counter_mcux_lptmr.c +++ b/drivers/counter/counter_mcux_lptmr.c @@ -4,7 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#if DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_lptmr) #define DT_DRV_COMPAT nxp_kinetis_lptmr +#else +#define DT_DRV_COMPAT nxp_lptmr +#endif #include #include @@ -137,6 +142,8 @@ static int mcux_lptmr_init(const struct device *dev) LPTMR_Init(config->base, &lptmr_config); + LPTMR_SetTimerPeriod(config->base, config->info.max_top_value); + config->irq_config_func(dev); return 0; @@ -205,7 +212,8 @@ static void mcux_lptmr_irq_config_0(const struct device *dev); static struct mcux_lptmr_config mcux_lptmr_config_0 = { .info = { - .max_top_value = UINT16_MAX, + .max_top_value = ((DT_INST_PROP(0, resolution) == 32) + ? UINT32_MAX : UINT16_MAX), .freq = DT_INST_PROP(0, clock_frequency) / DT_INST_PROP(0, prescaler), .flags = COUNTER_CONFIG_INFO_COUNT_UP, diff --git a/drivers/counter/counter_nrfx_timer.c b/drivers/counter/counter_nrfx_timer.c index 1fe3a98f8d754..bd6af3c5d3c82 100644 --- a/drivers/counter/counter_nrfx_timer.c +++ b/drivers/counter/counter_nrfx_timer.c @@ -15,8 +15,6 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL); #define DT_DRV_COMPAT nordic_nrf_timer -#define TIMER_CLOCK(timer_instance) NRF_TIMER_BASE_FREQUENCY_GET(timer_instance) - #define CC_TO_ID(cc_num) (cc_num - 2) #define ID_TO_CC(idx) (nrf_timer_cc_channel_t)(idx + 2) @@ -419,6 +417,14 @@ static const struct counter_driver_api counter_nrfx_driver_api = { irq_handler, DEVICE_DT_INST_GET(idx), 0)) \ ) +#if !defined(CONFIG_SOC_SERIES_BSIM_NRFXX) +#define CHECK_MAX_FREQ(idx) \ + BUILD_ASSERT(DT_INST_PROP(idx, max_frequency) == \ + NRF_TIMER_BASE_FREQUENCY_GET((NRF_TIMER_Type *)DT_INST_REG_ADDR(idx))) +#else +#define CHECK_MAX_FREQ(idx) +#endif + #define COUNTER_NRFX_TIMER_DEVICE(idx) \ BUILD_ASSERT(DT_INST_PROP(idx, prescaler) <= \ TIMER_PRESCALER_PRESCALER_Msk, \ @@ -448,7 +454,7 @@ static const struct counter_driver_api counter_nrfx_driver_api = { static MAYBE_CONST_CONFIG struct counter_nrfx_config nrfx_counter_##idx##_config = { \ .info = { \ .max_top_value = (uint32_t)BIT64_MASK(DT_INST_PROP(idx, max_bit_width)),\ - .freq = TIMER_CLOCK((NRF_TIMER_Type *)DT_INST_REG_ADDR(idx)) / \ + .freq = DT_INST_PROP(idx, max_frequency) / \ BIT(DT_INST_PROP(idx, prescaler)), \ .flags = COUNTER_CONFIG_INFO_COUNT_UP, \ .channels = CC_TO_ID(DT_INST_PROP(idx, cc_num)), \ @@ -457,6 +463,7 @@ static const struct counter_driver_api counter_nrfx_driver_api = { .timer = (NRF_TIMER_Type *)DT_INST_REG_ADDR(idx), \ LOG_INSTANCE_PTR_INIT(log, LOG_MODULE_NAME, idx) \ }; \ + CHECK_MAX_FREQ(idx); \ DEVICE_DT_INST_DEFINE(idx, \ counter_##idx##_init, \ NULL, \ diff --git a/drivers/counter/counter_nxp_mrt.c b/drivers/counter/counter_nxp_mrt.c index 209d0314b3e14..2ad62385d8e37 100644 --- a/drivers/counter/counter_nxp_mrt.c +++ b/drivers/counter/counter_nxp_mrt.c @@ -21,6 +21,8 @@ #include #include #include +#include + #include #define LOG_MODULE_NAME counter_mrt @@ -55,6 +57,7 @@ struct nxp_mrt_config { void (*irq_config_func)(const struct device *dev); struct nxp_mrt_channel_data *const *data; const struct device *const *channels; + const struct reset_dt_spec reset; }; static int nxp_mrt_stop(const struct device *dev) @@ -210,6 +213,17 @@ static int nxp_mrt_init(const struct device *dev) const struct nxp_mrt_config *config = dev->config; MRT_Type *base = config->base; uint32_t num_channels = (base->MODCFG & MRT_MODCFG_NOC_MASK) >> MRT_MODCFG_NOC_SHIFT; + int ret = 0; + + if (!device_is_ready(config->reset.dev)) { + LOG_ERR("Reset device not ready"); + return -ENODEV; + } + + ret = reset_line_toggle(config->reset.dev, config->reset.id); + if (ret) { + return ret; + } clock_control_on(config->clock_dev, config->clock_subsys); @@ -331,6 +345,7 @@ struct counter_driver_api nxp_mrt_api = { .irq_config_func = nxp_mrt_##n##_irq_config_func, \ .data = nxp_mrt_##n##_channel_datas, \ .channels = nxp_mrt_##n##_channels, \ + .reset = RESET_DT_SPEC_INST_GET(n), \ }; \ \ /* Init parent device in order to handle ISR and init. */ \ diff --git a/drivers/counter/counter_nxp_pit.c b/drivers/counter/counter_nxp_pit.c index 5cf192a73c476..6640b1aa2f2ad 100644 --- a/drivers/counter/counter_nxp_pit.c +++ b/drivers/counter/counter_nxp_pit.c @@ -187,7 +187,9 @@ static void nxp_pit_isr(const struct device *dev) flags = PIT_GetStatusFlags(config->base, channel); if (flags) { PIT_ClearStatusFlags(config->base, channel, flags); - data->top_callback(dev, data->top_user_data); + if (data->top_callback) { + data->top_callback(dev, data->top_user_data); + } } } #endif /* DT_NODE_HAS_PROP(DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_pit), interrupts) */ diff --git a/drivers/counter/counter_smartbond_timer.c b/drivers/counter/counter_smartbond_timer.c index 0173373f1076c..c15bdfad86e05 100644 --- a/drivers/counter/counter_smartbond_timer.c +++ b/drivers/counter/counter_smartbond_timer.c @@ -10,9 +10,12 @@ #include #include #include - -#include +#include +#include +#include #include +#include +#include LOG_MODULE_REGISTER(counter_timer, CONFIG_COUNTER_LOG_LEVEL); @@ -22,11 +25,20 @@ LOG_MODULE_REGISTER(counter_timer, CONFIG_COUNTER_LOG_LEVEL); #define TIMER_TOP_VALUE 0xFFFFFF +#define COUNTER_DT_DEVICE(_idx) DEVICE_DT_GET_OR_NULL(DT_NODELABEL(timer##_idx)) + +#define PDC_XTAL_EN (DT_NODE_HAS_STATUS(DT_NODELABEL(xtal32m), okay) ? \ + MCU_PDC_EN_XTAL : MCU_PDC_EN_NONE) + struct counter_smartbond_data { counter_alarm_callback_t callback; void *user_data; uint32_t guard_period; uint32_t freq; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + ATOMIC_DEFINE(pm_policy_state_flag, 1); + uint8_t pdc_idx; +#endif }; struct counter_smartbond_ch_data { @@ -47,15 +59,109 @@ struct counter_smartbond_config { LOG_INSTANCE_PTR_DECLARE(log); }; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static void counter_smartbond_pm_policy_state_lock_get(struct counter_smartbond_data *data) +{ + if (!atomic_test_and_set_bit(data->pm_policy_state_flag, 0)) { + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +} + +static void counter_smartbond_pm_policy_state_lock_put(struct counter_smartbond_data *data) +{ + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0)) { + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +} + +/* + * Routine to check whether the device is allowed to enter the sleep state or not. + * Entering the standby mode should be allowed for TIMER1/2 that are clocked by LP + * clock. Although, TIMER1/2 are powered by a distinct power domain, + * namely PD_TMR which is always enabled (used to generate the sleep tick count), + * the DIVN path which reflects the main crystal, that is XTAL32M, is turned off + * during sleep by PDC. It's worth noting that during sleep the clock source of + * a timer block will automatically be switched from DIVN to LP and vice versa. + */ +static inline bool counter_smartbond_is_sleep_allowed(const struct device *dev) +{ + const struct counter_smartbond_config *config = dev->config; + + return (((dev == COUNTER_DT_DEVICE(1)) || + (dev == COUNTER_DT_DEVICE(2))) && !config->clock_src_divn); +} + +/* Get the PDC trigger associated with the requested counter device */ +static uint8_t counter_smartbond_pdc_trigger_get(const struct device *dev) +{ + const struct counter_smartbond_config *config = dev->config; + + switch ((uint32_t)config->timer) { + case (uint32_t)TIMER: + return MCU_PDC_TRIGGER_TIMER; + case (uint32_t)TIMER2: + return MCU_PDC_TRIGGER_TIMER2; + case (uint32_t)TIMER3: + return MCU_PDC_TRIGGER_TIMER3; + case (uint32_t)TIMER4: + return MCU_PDC_TRIGGER_TIMER4; + default: + return 0; + } +} + +/* + * Add PDC entry so that the application core, which should be turned off during sleep, + * can get notified upon counter events. This routine is called for counter instances + * that are powered by PD_TMR and can operate during sleep. + */ +static void counter_smartbond_pdc_add(const struct device *dev) +{ + struct counter_smartbond_data *data = dev->data; + uint8_t trigger = counter_smartbond_pdc_trigger_get(dev); + + if (!atomic_test_and_set_bit(data->pm_policy_state_flag, 0)) { + + data->pdc_idx = da1469x_pdc_add(trigger, MCU_PDC_MASTER_M33, PDC_XTAL_EN); + __ASSERT_NO_MSG(data->pdc_idx >= 0); + + da1469x_pdc_set(data->pdc_idx); + da1469x_pdc_ack(data->pdc_idx); + } +} + +static void counter_smartbond_pdc_del(const struct device *dev) +{ + struct counter_smartbond_data *data = dev->data; + + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0)) { + da1469x_pdc_del(data->pdc_idx); + } +} +#endif + static int counter_smartbond_start(const struct device *dev) { const struct counter_smartbond_config *config = dev->config; TIMER2_Type *timer = config->timer; - /* enable counter in free running mode */ - timer->TIMER2_CTRL_REG |= TIMER_TIMER_CTRL_REG_TIM_CLK_EN_Msk | - TIMER_TIMER_CTRL_REG_TIM_EN_Msk | - TIMER_TIMER_CTRL_REG_TIM_FREE_RUN_MODE_EN_Msk; + /* Enable counter in free running mode */ + timer->TIMER2_CTRL_REG |= (TIMER2_TIMER2_CTRL_REG_TIM_CLK_EN_Msk | + TIMER2_TIMER2_CTRL_REG_TIM_EN_Msk | + TIMER2_TIMER2_CTRL_REG_TIM_FREE_RUN_MODE_EN_Msk); + +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + if (!counter_smartbond_is_sleep_allowed(dev)) { + struct counter_smartbond_data *data = dev->data; + /* + * Power mode constraints should be applied as long as the device + * is up and running. + */ + counter_smartbond_pm_policy_state_lock_get(data); + } else { + counter_smartbond_pdc_add(dev); + } +#endif return 0; } @@ -68,9 +174,18 @@ static int counter_smartbond_stop(const struct device *dev) /* disable counter */ timer->TIMER2_CTRL_REG &= ~(TIMER2_TIMER2_CTRL_REG_TIM_EN_Msk | - TIMER2_TIMER2_CTRL_REG_TIM_IRQ_EN_Msk); + TIMER2_TIMER2_CTRL_REG_TIM_IRQ_EN_Msk | + TIMER2_TIMER2_CTRL_REG_TIM_CLK_EN_Msk); data->callback = NULL; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + if (!counter_smartbond_is_sleep_allowed(dev)) { + counter_smartbond_pm_policy_state_lock_put(data); + } else { + counter_smartbond_pdc_del(dev); + } +#endif + return 0; } @@ -229,7 +344,7 @@ static int counter_smartbond_init_timer(const struct device *dev) if (cfg->clock_src_divn) { /* Timer clock source is DIVn 32MHz */ - timer->TIMER2_CTRL_REG = TIMER_TIMER_CTRL_REG_TIM_SYS_CLK_EN_Msk; + timer->TIMER2_CTRL_REG = TIMER2_TIMER2_CTRL_REG_TIM_SYS_CLK_EN_Msk; data->freq = DT_PROP(DT_NODELABEL(divn_clk), clock_frequency) / (cfg->prescaler + 1); } else { @@ -268,6 +383,13 @@ static int counter_smartbond_init_timer(const struct device *dev) /* config/enable IRQ */ cfg->irq_config_func(dev); +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + return pm_device_runtime_enable(dev); +#endif + return 0; } @@ -299,6 +421,45 @@ static uint32_t counter_smartbond_get_freq(const struct device *dev) return data->freq; } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static void counter_smartbond_resume(const struct device *dev) +{ + const struct counter_smartbond_config *cfg = dev->config; + TIMER2_Type *timer = cfg->timer; + + /* + * Resume only for block instances that are powered by PD_SYS + * and so their register contents should reset after sleep. + */ + if (!counter_smartbond_is_sleep_allowed(dev)) { + if (cfg->clock_src_divn) { + timer->TIMER2_CTRL_REG = TIMER2_TIMER2_CTRL_REG_TIM_SYS_CLK_EN_Msk; + } else { + timer->TIMER2_CTRL_REG = 0; + } + timer->TIMER2_PRESCALER_REG = cfg->prescaler; + timer->TIMER2_RELOAD_REG = counter_get_max_top_value(dev); + } +} + +static int counter_smartbond_pm_action(const struct device *dev, enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + break; + case PM_DEVICE_ACTION_RESUME: + counter_smartbond_resume(dev); + break; + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif + static const struct counter_driver_api counter_smartbond_driver_api = { .start = counter_smartbond_start, .stop = counter_smartbond_stop, @@ -370,9 +531,10 @@ void counter_smartbond_irq_handler(const struct device *dev) .irqn = DT_IRQN(TIMERN(idx)), \ }; \ \ + PM_DEVICE_DT_INST_DEFINE(idx, counter_smartbond_pm_action); \ DEVICE_DT_INST_DEFINE(idx, \ counter_smartbond_init_timer, \ - NULL, \ + PM_DEVICE_DT_INST_GET(idx), \ &counter##idx##_data, \ &counter##idx##_config, \ PRE_KERNEL_1, CONFIG_COUNTER_INIT_PRIORITY, \ diff --git a/drivers/counter/maxim_ds3231.c b/drivers/counter/maxim_ds3231.c index c6b8e08b79c71..146be21762a75 100644 --- a/drivers/counter/maxim_ds3231.c +++ b/drivers/counter/maxim_ds3231.c @@ -1321,7 +1321,7 @@ int z_vrfy_maxim_ds3231_get_syncpoint(const struct device *dev, return rv; } -#include +#include int z_vrfy_maxim_ds3231_req_syncpoint(const struct device *dev, struct k_poll_signal *sig) @@ -1334,6 +1334,6 @@ int z_vrfy_maxim_ds3231_req_syncpoint(const struct device *dev, return z_impl_maxim_ds3231_req_syncpoint(dev, sig); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 451a524c810fc..61955697da87b 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -52,7 +52,8 @@ config CRYPTO_MBEDTLS_SHIM bool "MbedTLS shim driver [EXPERIMENTAL]" select MBEDTLS select MBEDTLS_ENABLE_HEAP - select MBEDTLS_MAC_SHA512_ENABLED + select MBEDTLS_SHA512 + select MBEDTLS_CIPHER_AES_ENABLED select EXPERIMENTAL help Enable mbedTLS shim layer compliant with crypto APIs. You will need diff --git a/drivers/crypto/crypto_it8xxx2_sha.c b/drivers/crypto/crypto_it8xxx2_sha.c index b144878de8f19..3fea42f217d28 100644 --- a/drivers/crypto/crypto_it8xxx2_sha.c +++ b/drivers/crypto/crypto_it8xxx2_sha.c @@ -215,7 +215,7 @@ static int it8xxx2_sha_init(const struct device *dev) return 0; } -static struct crypto_driver_api it8xxx2_crypto_api = { +static const struct crypto_driver_api it8xxx2_crypto_api = { .hash_begin_session = it8xxx2_hash_begin_session, .hash_free_session = it8xxx2_hash_session_free, .query_hw_caps = it8xxx2_query_hw_caps, diff --git a/drivers/crypto/crypto_it8xxx2_sha_v2.c b/drivers/crypto/crypto_it8xxx2_sha_v2.c index 48eae76c673c2..6da1cff4c2942 100644 --- a/drivers/crypto/crypto_it8xxx2_sha_v2.c +++ b/drivers/crypto/crypto_it8xxx2_sha_v2.c @@ -340,7 +340,7 @@ static int it8xxx2_sha_init(const struct device *dev) return 0; } -static struct crypto_driver_api it8xxx2_crypto_api = { +static const struct crypto_driver_api it8xxx2_crypto_api = { .hash_begin_session = it8xxx2_hash_begin_session, .hash_free_session = it8xxx2_hash_session_free, .query_hw_caps = it8xxx2_query_hw_caps, diff --git a/drivers/crypto/crypto_mchp_xec_symcr.c b/drivers/crypto/crypto_mchp_xec_symcr.c index 8f47e374d36e6..6bcf4f17c854a 100644 --- a/drivers/crypto/crypto_mchp_xec_symcr.c +++ b/drivers/crypto/crypto_mchp_xec_symcr.c @@ -514,7 +514,7 @@ static int xec_symcr_init(const struct device *dev) return ret; } -static struct crypto_driver_api xec_symcr_api = { +static const struct crypto_driver_api xec_symcr_api = { .query_hw_caps = xec_symcr_query_hw_caps, .hash_begin_session = xec_symcr_hash_session_begin, .hash_free_session = xec_symcr_hash_session_free, diff --git a/drivers/crypto/crypto_mcux_dcp.c b/drivers/crypto/crypto_mcux_dcp.c index 7419a340b0bfb..23232ed9b57cd 100644 --- a/drivers/crypto/crypto_mcux_dcp.c +++ b/drivers/crypto/crypto_mcux_dcp.c @@ -331,7 +331,7 @@ static int crypto_dcp_init(const struct device *dev) return 0; } -static struct crypto_driver_api crypto_dcp_api = { +static const struct crypto_driver_api crypto_dcp_api = { .query_hw_caps = crypto_dcp_query_hw_caps, .cipher_begin_session = crypto_dcp_cipher_begin_session, .cipher_free_session = crypto_dcp_cipher_free_session, diff --git a/drivers/crypto/crypto_npcx_sha.c b/drivers/crypto/crypto_npcx_sha.c index 8aa30846ae23f..20c817f1cf903 100644 --- a/drivers/crypto/crypto_npcx_sha.c +++ b/drivers/crypto/crypto_npcx_sha.c @@ -202,7 +202,7 @@ static int npcx_hash_init(const struct device *dev) return 0; } -static struct crypto_driver_api npcx_crypto_api = { +static const struct crypto_driver_api npcx_crypto_api = { .hash_begin_session = npcx_hash_session_setup, .hash_free_session = npcx_hash_session_free, .query_hw_caps = npcx_query_caps, diff --git a/drivers/crypto/crypto_smartbond.c b/drivers/crypto/crypto_smartbond.c index 5b003875b93f2..7b8e33799b52c 100644 --- a/drivers/crypto/crypto_smartbond.c +++ b/drivers/crypto/crypto_smartbond.c @@ -12,7 +12,11 @@ #include #include #include +#include #include +#include +#include +#include #include LOG_MODULE_REGISTER(crypto_smartbond_crypto, CONFIG_CRYPTO_LOG_LEVEL); @@ -28,7 +32,7 @@ LOG_MODULE_REGISTER(crypto_smartbond_crypto, CONFIG_CRYPTO_LOG_LEVEL); #define CRYPTO_HW_CAPS (CAP_RAW_KEY | CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS | CAP_NO_IV_PREFIX) #endif -#define SWAP32(_w) __builtin_bswap32(_w) +#define SWAP32(_w) __REV(_w) #define CRYPTO_CTRL_REG_SET(_field, _val) \ AES_HASH->CRYPTO_CTRL_REG = \ @@ -114,6 +118,21 @@ static void smartbond_crypto_isr(const void *arg) } } +static inline void crypto_smartbond_pm_policy_state_lock_get(const struct device *dev) +{ + /* + * Prevent the SoC from entering the normal sleep state as PDC does not support + * waking up the application core following AES/HASH events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); +} + +static inline void crypto_smartbond_pm_policy_state_lock_put(const struct device *dev) +{ + /* Allow the SoC to enter the normal sleep state once AES/HASH operations are done. */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); +} + static bool crypto_smartbond_lock_session(const struct device *dev) { bool lock = false; @@ -123,6 +142,9 @@ static bool crypto_smartbond_lock_session(const struct device *dev) if (!in_use) { in_use = true; + /* Prevent sleep as long as a cryptographic session is in place */ + da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); + crypto_smartbond_pm_policy_state_lock_get(dev); crypto_smartbond_set_status(true); lock = true; } @@ -141,6 +163,8 @@ static void crypto_smartbond_unlock_session(const struct device *dev) if (in_use) { in_use = false; crypto_smartbond_set_status(false); + crypto_smartbond_pm_policy_state_lock_put(dev); + da1469x_pd_release_nowait(MCU_PD_DOMAIN_SYS); } k_sem_give(&data->session_sem); @@ -257,9 +281,7 @@ static uint32_t crypto_smartbond_swap_word(uint8_t *data) { /* Check word boundaries of given address and if possible accellerate swapping */ if ((uint32_t)data & 0x3) { - sys_mem_swap(data, sizeof(uint32_t)); - - return (*(uint32_t *)data); + return SWAP32(sys_get_le32(data)); } else { return SWAP32(*(uint32_t *)data); } @@ -781,16 +803,17 @@ crypto_smartbond_cipher_begin_session(const struct device *dev, struct cipher_ct return -ENOSPC; } - ret = crypto_smartbond_cipher_key_load(ctx->key.bit_stream, ctx->keylen); + /* First check if the requested cryptographic algo is supported */ + ret = crypto_smartbond_cipher_set_mode(mode); if (ret < 0) { - LOG_ERR("Invalid key length or key cannot be accessed"); + LOG_ERR("Unsupported cipher mode"); crypto_smartbond_unlock_session(dev); return ret; } - ret = crypto_smartbond_cipher_set_mode(mode); + ret = crypto_smartbond_cipher_key_load((uint8_t *)ctx->key.bit_stream, ctx->keylen); if (ret < 0) { - LOG_ERR("Unsupported cipher mode"); + LOG_ERR("Invalid key length or key cannot be accessed"); crypto_smartbond_unlock_session(dev); return ret; } @@ -899,7 +922,7 @@ crypto_smartbond_hash_set_async_callback(const struct device *dev, hash_completi } #endif -static struct crypto_driver_api crypto_smartbond_driver_api = { +static const struct crypto_driver_api crypto_smartbond_driver_api = { .cipher_begin_session = crypto_smartbond_cipher_begin_session, .cipher_free_session = crypto_smartbond_cipher_free_session, #if defined(CONFIG_CRYPTO_ASYNC) @@ -913,6 +936,33 @@ static struct crypto_driver_api crypto_smartbond_driver_api = { .query_hw_caps = crypto_smartbond_query_hw_caps }; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static int crypto_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* + * No need to perform any actions here as the AES/HASH controller + * should already be turned off. + */ + break; + case PM_DEVICE_ACTION_RESUME: + /* + * No need to perform any actions here as the AES/HASH controller + * will be initialized upon acquiring a cryptographic session. + */ + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + static int crypto_smartbond_init(const struct device *dev) { struct crypto_smartbond_data *data = dev->data; @@ -931,9 +981,17 @@ static int crypto_smartbond_init(const struct device *dev) IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_crypto_isr, DEVICE_DT_INST_GET(0), 0); + /* Controller should be initialized once a crypyographic session is requested */ crypto_smartbond_set_status(false); +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + return pm_device_runtime_enable(dev); +#else return 0; +#endif } /* @@ -944,10 +1002,13 @@ static int crypto_smartbond_init(const struct device *dev) BUILD_ASSERT((inst) == 0, \ "multiple instances are not supported"); \ \ + PM_DEVICE_DT_INST_DEFINE(inst, crypto_smartbond_pm_action); \ + \ static struct crypto_smartbond_data crypto_smartbond_data_##inst; \ \ DEVICE_DT_INST_DEFINE(0, \ - crypto_smartbond_init, NULL, \ + crypto_smartbond_init, \ + PM_DEVICE_DT_INST_GET(inst), \ &crypto_smartbond_data_##inst, NULL, \ POST_KERNEL, \ CONFIG_CRYPTO_INIT_PRIORITY, \ diff --git a/drivers/crypto/crypto_stm32.c b/drivers/crypto/crypto_stm32.c index 680792bbb2c83..bb78d65894a5f 100644 --- a/drivers/crypto/crypto_stm32.c +++ b/drivers/crypto/crypto_stm32.c @@ -234,7 +234,7 @@ static int crypto_stm32_ctr_encrypt(struct cipher_ctx *ctx, { int ret; uint32_t ctr[BLOCK_LEN_WORDS] = {0}; - int ivlen = ctx->keylen - (ctx->mode_params.ctr_info.ctr_len >> 3); + int ivlen = BLOCK_LEN_BYTES - (ctx->mode_params.ctr_info.ctr_len >> 3); struct crypto_stm32_session *session = CRYPTO_STM32_SESSN(ctx); @@ -257,7 +257,7 @@ static int crypto_stm32_ctr_decrypt(struct cipher_ctx *ctx, { int ret; uint32_t ctr[BLOCK_LEN_WORDS] = {0}; - int ivlen = ctx->keylen - (ctx->mode_params.ctr_info.ctr_len >> 3); + int ivlen = BLOCK_LEN_BYTES - (ctx->mode_params.ctr_info.ctr_len >> 3); struct crypto_stm32_session *session = CRYPTO_STM32_SESSN(ctx); @@ -507,7 +507,7 @@ static struct crypto_stm32_data crypto_stm32_dev_data = { } }; -static struct crypto_stm32_config crypto_stm32_dev_config = { +static const struct crypto_stm32_config crypto_stm32_dev_config = { .pclken = { .enr = DT_INST_CLOCKS_CELL(0, bits), .bus = DT_INST_CLOCKS_CELL(0, bus) diff --git a/drivers/dac/CMakeLists.txt b/drivers/dac/CMakeLists.txt index 50cd660ac524e..d6869cc234a1c 100644 --- a/drivers/dac/CMakeLists.txt +++ b/drivers/dac/CMakeLists.txt @@ -23,3 +23,4 @@ zephyr_library_sources_ifdef(CONFIG_DAC_AD559X dac_ad559x.c) zephyr_library_sources_ifdef(CONFIG_DAC_AD56XX dac_ad56xx.c) zephyr_library_sources_ifdef(CONFIG_DAC_AD569X dac_ad569x.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE dac_handlers.c) +zephyr_library_sources_ifdef(CONFIG_DAC_MCUX_GAU dac_mcux_gau.c) diff --git a/drivers/dac/Kconfig.ad559x b/drivers/dac/Kconfig.ad559x index 5266680199f3f..7bfcccb492e81 100644 --- a/drivers/dac/Kconfig.ad559x +++ b/drivers/dac/Kconfig.ad559x @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config DAC_AD559X bool "AD559x DAC driver" diff --git a/drivers/dac/Kconfig.ad569x b/drivers/dac/Kconfig.ad569x index e40e8fc8e3beb..0b6b6ab2e108a 100644 --- a/drivers/dac/Kconfig.ad569x +++ b/drivers/dac/Kconfig.ad569x @@ -1,5 +1,5 @@ # Copyright (c) 2024 Jan Kubiznak -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config DAC_AD569X bool "Analog Devices AD5691 / AD5692 / AD5693 DAC driver" diff --git a/drivers/dac/Kconfig.mcux b/drivers/dac/Kconfig.mcux index 87869775d03c1..417e1b9be943a 100644 --- a/drivers/dac/Kconfig.mcux +++ b/drivers/dac/Kconfig.mcux @@ -31,3 +31,10 @@ config DAC_MCUX_DAC32_TESTOUT depends on DAC_MCUX_DAC32 help Enable the DAC test output. + +config DAC_MCUX_GAU + bool "NXP GAU DAC driver" + default y + depends on DT_HAS_NXP_GAU_DAC_ENABLED + help + Enable the driver for the NXP GAU DAC. diff --git a/drivers/dac/dac_handlers.c b/drivers/dac/dac_handlers.c index bd9ee0bc7e0d6..36557ad208e3d 100644 --- a/drivers/dac/dac_handlers.c +++ b/drivers/dac/dac_handlers.c @@ -21,7 +21,7 @@ static inline int z_vrfy_dac_channel_setup(const struct device *dev, return z_impl_dac_channel_setup((const struct device *)dev, &channel_cfg); } -#include +#include static inline int z_vrfy_dac_write_value(const struct device *dev, uint8_t channel, uint32_t value) @@ -31,4 +31,4 @@ static inline int z_vrfy_dac_write_value(const struct device *dev, return z_impl_dac_write_value((const struct device *)dev, channel, value); } -#include +#include diff --git a/drivers/dac/dac_mcux_gau.c b/drivers/dac/dac_mcux_gau.c new file mode 100644 index 0000000000000..ba4835b1c7046 --- /dev/null +++ b/drivers/dac/dac_mcux_gau.c @@ -0,0 +1,116 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_gau_dac + +#include + +#include + +#define LOG_LEVEL CONFIG_DAC_LOG_LEVEL +#include +#include +LOG_MODULE_REGISTER(nxp_gau_dac); + +struct nxp_gau_dac_config { + DAC_Type *base; + dac_conversion_rate_t conversion_rate : 2; + dac_reference_voltage_source_t voltage_ref : 1; + dac_output_voltage_range_t output_range : 2; +}; + +static inline dac_channel_id_t convert_channel_id(uint8_t channel_id) +{ + switch (channel_id) { + case 0: return kDAC_ChannelA; + case 1: return kDAC_ChannelB; + default: + LOG_ERR("Invalid DAC channel ID"); + return -EINVAL; + }; +} + +static int nxp_gau_dac_channel_setup(const struct device *dev, + const struct dac_channel_cfg *channel_cfg) +{ + const struct nxp_gau_dac_config *config = dev->config; + dac_channel_config_t dac_channel_config = {0}; + + if (channel_cfg->resolution != 10) { + LOG_ERR("DAC only support 10 bit resolution"); + return -EINVAL; + } + + if (channel_cfg->buffered) { + /* External and internal output are mutually exclusive */ + LOG_WRN("Note: buffering DAC output to pad disconnects internal output"); + } + + dac_channel_config.waveType = kDAC_WaveNormal; + dac_channel_config.outMode = channel_cfg->buffered ? + kDAC_ChannelOutputPAD : kDAC_ChannelOutputInternal; + dac_channel_config.timingMode = kDAC_NonTimingCorrelated; + dac_channel_config.enableTrigger = false; + dac_channel_config.enableDMA = false; + dac_channel_config.enableConversion = true; + + DAC_SetChannelConfig(config->base, + (uint32_t)convert_channel_id(channel_cfg->channel_id), + &dac_channel_config); + + return 0; +}; + +static int nxp_gau_dac_write_value(const struct device *dev, + uint8_t channel, uint32_t value) +{ + const struct nxp_gau_dac_config *config = dev->config; + + DAC_SetChannelData(config->base, + (uint32_t)convert_channel_id(channel), + (uint16_t)value); + return 0; +}; + +static const struct dac_driver_api nxp_gau_dac_driver_api = { + .channel_setup = nxp_gau_dac_channel_setup, + .write_value = nxp_gau_dac_write_value, +}; + +static int nxp_gau_dac_init(const struct device *dev) +{ + const struct nxp_gau_dac_config *config = dev->config; + dac_config_t dac_cfg; + + DAC_GetDefaultConfig(&dac_cfg); + + dac_cfg.conversionRate = config->conversion_rate; + dac_cfg.refSource = config->voltage_ref; + dac_cfg.rangeSelect = config->output_range; + + DAC_Init(config->base, &dac_cfg); + + return 0; +}; + +#define NXP_GAU_DAC_INIT(inst) \ + \ + const struct nxp_gau_dac_config nxp_gau_dac_##inst##_config = { \ + .base = (DAC_Type *) DT_INST_REG_ADDR(inst), \ + .voltage_ref = DT_INST_ENUM_IDX(inst, nxp_dac_reference), \ + .conversion_rate = DT_INST_ENUM_IDX(inst, nxp_conversion_rate), \ + .output_range = DT_INST_ENUM_IDX(inst, \ + nxp_output_voltage_range), \ + }; \ + \ + \ + DEVICE_DT_INST_DEFINE(inst, &nxp_gau_dac_init, NULL, \ + NULL, \ + &nxp_gau_dac_##inst##_config, \ + POST_KERNEL, CONFIG_DAC_INIT_PRIORITY, \ + &nxp_gau_dac_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(NXP_GAU_DAC_INIT) diff --git a/drivers/dai/intel/dmic/dmic.c b/drivers/dai/intel/dmic/dmic.c index f65c554cf989a..81a404a51208c 100644 --- a/drivers/dai/intel/dmic/dmic.c +++ b/drivers/dai/intel/dmic/dmic.c @@ -159,7 +159,7 @@ static inline void dai_dmic_release_ownership(const struct dai_intel_dmic *dmic) static inline uint32_t dai_dmic_base(const struct dai_intel_dmic *dmic) { -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) return dmic->hdamldmic_base; #else return dmic->shim_base; @@ -172,7 +172,7 @@ static inline void dai_dmic_set_sync_period(uint32_t period, const struct dai_in uint32_t val = CONFIG_DAI_DMIC_HW_IOCLK / period - 1; uint32_t base = dai_dmic_base(dmic); /* DMIC Change sync period */ -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) sys_write32(sys_read32(base + DMICSYNC_OFFSET) | FIELD_PREP(DMICSYNC_SYNCPRD, val), base + DMICSYNC_OFFSET); sys_write32(sys_read32(base + DMICSYNC_OFFSET) | DMICSYNC_SYNCPU, @@ -286,7 +286,7 @@ static void dai_dmic_irq_handler(const void *data) static inline void dai_dmic_dis_clk_gating(const struct dai_intel_dmic *dmic) { /* Disable DMIC clock gating */ -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if (CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL) sys_write32((sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET) | DMICLVSCTL_DCGD), dmic->vshim_base + DMICLVSCTL_OFFSET); #else @@ -298,10 +298,10 @@ static inline void dai_dmic_dis_clk_gating(const struct dai_intel_dmic *dmic) static inline void dai_dmic_en_clk_gating(const struct dai_intel_dmic *dmic) { /* Enable DMIC clock gating */ -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if (CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL) sys_write32((sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET) & ~DMICLVSCTL_DCGD), dmic->vshim_base + DMICLVSCTL_OFFSET); -#else +#else /* All other CAVS and ACE platforms */ sys_write32((sys_read32(dmic->shim_base + DMICLCTL_OFFSET) & ~DMICLCTL_DCGD), dmic->shim_base + DMICLCTL_OFFSET); #endif @@ -312,7 +312,7 @@ static inline void dai_dmic_program_channel_map(const struct dai_intel_dmic *dmi const struct dai_config *cfg, uint32_t index) { -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) uint16_t pcmsycm = cfg->link_config; uint32_t reg_add = dmic->shim_base + DMICXPCMSyCM_OFFSET + 0x0004*index; @@ -321,7 +321,7 @@ static inline void dai_dmic_program_channel_map(const struct dai_intel_dmic *dmi ARG_UNUSED(dmic); ARG_UNUSED(cfg); ARG_UNUSED(index); -#endif /* defined(CONFIG_SOC_INTEL_ACE20_LNL) */ +#endif /* defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) */ } static inline void dai_dmic_en_power(const struct dai_intel_dmic *dmic) @@ -331,7 +331,7 @@ static inline void dai_dmic_en_power(const struct dai_intel_dmic *dmic) sys_write32((sys_read32(base + DMICLCTL_OFFSET) | DMICLCTL_SPA), base + DMICLCTL_OFFSET); -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) while (!(sys_read32(base + DMICLCTL_OFFSET) & DMICLCTL_CPA)) { k_sleep(K_USEC(100)); } diff --git a/drivers/dai/intel/dmic/dmic.h b/drivers/dai/intel/dmic/dmic.h index e06ed80daed75..d690c0cd21a1c 100644 --- a/drivers/dai/intel/dmic/dmic.h +++ b/drivers/dai/intel/dmic/dmic.h @@ -173,7 +173,7 @@ struct dai_intel_dmic { /* hardware parameters */ uint32_t reg_base; uint32_t shim_base; -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) uint32_t hdamldmic_base; uint32_t vshim_base; #endif diff --git a/drivers/dai/intel/dmic/dmic_nhlt.c b/drivers/dai/intel/dmic/dmic_nhlt.c index c7fe48e1432da..5f150e6d0375c 100644 --- a/drivers/dai/intel/dmic/dmic_nhlt.c +++ b/drivers/dai/intel/dmic/dmic_nhlt.c @@ -279,7 +279,7 @@ static int dai_nhlt_dmic_dai_params_get(struct dai_intel_dmic *dmic, const int c static inline void dai_dmic_clock_select_set(const struct dai_intel_dmic *dmic, uint32_t source) { uint32_t val; -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) /* ACE 2.0,3.0 */ val = sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET); val &= ~DMICLVSCTL_MLCS; val |= FIELD_PREP(DMICLVSCTL_MLCS, source); @@ -300,7 +300,7 @@ static inline void dai_dmic_clock_select_set(const struct dai_intel_dmic *dmic, static inline uint32_t dai_dmic_clock_select_get(const struct dai_intel_dmic *dmic) { uint32_t val; -#ifdef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) /* ACE 2.0,3.0 */ val = sys_read32(dmic->vshim_base + DMICLVSCTL_OFFSET); return FIELD_GET(DMICLVSCTL_MLCS, val); #else @@ -322,7 +322,7 @@ static int dai_dmic_set_clock(const struct dai_intel_dmic *dmic, const uint8_t c return -ENOTSUP; } -#ifndef CONFIG_SOC_INTEL_ACE20_LNL /* Ace 2.0 */ +#if defined(CONFIG_SOC_INTEL_ACE15_MTPM) if (clock_source && !(sys_read32(dmic->shim_base + DMICLCAP_OFFSET) & DMICLCAP_MLCS)) { return -ENOTSUP; } diff --git a/drivers/dai/intel/ssp/dai-params-intel-ipc4.h b/drivers/dai/intel/ssp/dai-params-intel-ipc4.h index 057a45d2a1242..a92f06d6620ca 100644 --- a/drivers/dai/intel/ssp/dai-params-intel-ipc4.h +++ b/drivers/dai/intel/ssp/dai-params-intel-ipc4.h @@ -11,6 +11,9 @@ #define DAI_INTEL_I2S_TDM_MAX_SLOT_MAP_COUNT 8 +#define I2SIPCMC 8 +#define I2SOPCMC 8 + /**< Type of the gateway. */ enum dai_intel_ipc4_connector_node_id_type { /**< HD/A host output (-> DSP). */ @@ -228,12 +231,18 @@ struct dai_intel_ipc4_ssp_config { uint32_t ssc1; uint32_t sscto; uint32_t sspsp; +#ifndef CONFIG_SOC_INTEL_ACE30_PTL uint32_t sstsa; uint32_t ssrsa; +#endif uint32_t ssc2; uint32_t sspsp2; uint32_t ssc3; uint32_t ssioc; +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + uint64_t ssmidytsa[I2SIPCMC]; + uint64_t ssmodytsa[I2SOPCMC]; +#endif } __packed; struct dai_intel_ipc4_ssp_mclk_config { diff --git a/drivers/dai/intel/ssp/ssp.c b/drivers/dai/intel/ssp/ssp.c index 215f9912d5774..1c9488d3f0a54 100644 --- a/drivers/dai/intel/ssp/ssp.c +++ b/drivers/dai/intel/ssp/ssp.c @@ -74,11 +74,11 @@ static struct dai_intel_ssp_mn ssp_mn_divider = { .irq = DT_NUM_IRQS(node_id), \ .irq_name = irq_name_level5_z, \ .fifo[DAI_DIR_PLAYBACK].offset = \ - DT_REG_ADDR_BY_IDX(node_id, 0) + SSDR, \ + DT_REG_ADDR_BY_IDX(node_id, 0) + OUT_FIFO, \ .fifo[DAI_DIR_PLAYBACK].handshake = \ DT_DMAS_CELL_BY_NAME(node_id, tx, channel), \ .fifo[DAI_DIR_CAPTURE].offset = \ - DT_REG_ADDR_BY_IDX(node_id, 0) + SSDR, \ + DT_REG_ADDR_BY_IDX(node_id, 0) + IN_FIFO, \ .fifo[DAI_DIR_CAPTURE].handshake = \ DT_DMAS_CELL_BY_NAME(node_id, rx, channel), \ .mn_inst = &ssp_mn_divider, \ @@ -817,7 +817,7 @@ static void dai_ssp_pm_runtime_en_ssp_power(struct dai_intel_ssp *dp, uint32_t s ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET, I2SLCTL_CPA(ssp_index), I2SLCTL_CPA(ssp_index), DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); -#elif CONFIG_SOC_INTEL_ACE20_LNL +#elif CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL sys_write32(sys_read32(dai_hdamlssp_base(dp) + I2SLCTL_OFFSET) | I2SLCTL_SPA(ssp_index), dai_hdamlssp_base(dp) + I2SLCTL_OFFSET); @@ -851,7 +851,8 @@ static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t ret = dai_ssp_poll_for_register_delay(dai_ip_base(dp) + I2SLCTL_OFFSET, I2SLCTL_CPA(ssp_index), 0, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); -#elif CONFIG_SOC_INTEL_ACE20_LNL + +#elif CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL sys_write32(sys_read32(dai_hdamlssp_base(dp) + I2SLCTL_OFFSET) & (~I2SLCTL_SPA(ssp_index)), dai_hdamlssp_base(dp) + I2SLCTL_OFFSET); @@ -872,9 +873,10 @@ static void dai_ssp_pm_runtime_dis_ssp_power(struct dai_intel_ssp *dp, uint32_t } static void dai_ssp_program_channel_map(struct dai_intel_ssp *dp, - const struct dai_config *cfg, uint32_t ssp_index) + const struct dai_config *cfg, uint32_t ssp_index, const void *spec_config) { -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) + ARG_UNUSED(spec_config); uint16_t pcmsycm = cfg->link_config; /* Set upper slot number from configuration */ pcmsycm = pcmsycm | (dp->ssp_plat_data->params.tdm_slots - 1) << 4; @@ -888,10 +890,39 @@ static void dai_ssp_program_channel_map(struct dai_intel_ssp *dp, /* Program HDA input stream parameters */ sys_write16((pcmsycm & 0xffff), reg_add); } +#elif defined(CONFIG_SOC_INTEL_ACE30_PTL) + const struct dai_intel_ipc4_ssp_configuration_blob *blob = spec_config; + uint64_t time_slot_map = 0; + uint16_t pcmsycm = cfg->link_config; + uint8_t slot_count = 0; + + if (DAI_INTEL_SSP_IS_BIT_SET(cfg->link_config, 15)) { + time_slot_map = + blob->i2s_driver_config.i2s_config.ssmidytsa[cfg->tdm_slot_group]; + slot_count = POPCOUNT(time_slot_map >> 32) + POPCOUNT(time_slot_map & 0xFFFFFFFF); + pcmsycm = cfg->link_config | (slot_count - 1) << 4; + uint32_t reg_add = dai_ip_base(dp) + 0x1000 * ssp_index + + PCMSyCM_OFFSET(cfg->tdm_slot_group); + + /* Program HDA output stream parameters */ + sys_write16((pcmsycm & 0xffff), reg_add); + + } else { + time_slot_map = + blob->i2s_driver_config.i2s_config.ssmodytsa[cfg->tdm_slot_group]; + slot_count = POPCOUNT(time_slot_map >> 32) + POPCOUNT(time_slot_map & 0xFFFFFFFF); + pcmsycm = cfg->link_config | (slot_count - 1) << 4; + uint32_t reg_add = dai_ip_base(dp) + 0x1000 * ssp_index + + PCMSyCM_OFFSET(cfg->tdm_slot_group + I2SOPCMC); + + /* Program HDA input stream parameters */ + sys_write16((pcmsycm & 0xffff), reg_add); + } #else ARG_UNUSED(dp); ARG_UNUSED(cfg); ARG_UNUSED(ssp_index); + ARG_UNUSED(spec_config); #endif /* CONFIG_SOC_INTEL_ACE20_LNL */ } @@ -905,11 +936,22 @@ static void dai_ssp_empty_tx_fifo(struct dai_intel_ssp *dp) * SSSR_TNF is cleared when TX FIFO is empty or full, * so wait for set TNF then for TFL zero - order matter. */ +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + ret = dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(dp->tdm_slot_group), + SSMODyCS_TNF, SSMODyCS_TNF, + DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); + + ret |= dai_ssp_poll_for_register_delay(dai_base(dp) + SSMODyCS(dp->tdm_slot_group), + SSMODyCS_TFL, 0, + DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE * + (DAI_INTEL_SSP_FIFO_DEPTH - 1) / 2); +#else ret = dai_ssp_poll_for_register_delay(dai_base(dp) + SSSR, SSSR_TNF, SSSR_TNF, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE); ret |= dai_ssp_poll_for_register_delay(dai_base(dp) + SSCR3, SSCR3_TFL_MASK, 0, DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE * (DAI_INTEL_SSP_FIFO_DEPTH - 1) / 2); +#endif if (ret) { LOG_WRN("timeout"); @@ -923,6 +965,92 @@ static void dai_ssp_empty_tx_fifo(struct dai_intel_ssp *dp) } } +#ifdef CONFIG_SOC_INTEL_ACE30_PTL +static void ssp_empty_rx_fifo_on_start(struct dai_intel_ssp *dp) +{ + uint32_t retry = DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX; + uint32_t i, sssr; + + sssr = sys_read32(dai_base(dp) + SSSR); + + if (sssr & SSSR_ROR) { + /* The RX FIFO is in overflow condition, empty it */ + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + for (i = 0; i < DAI_INTEL_SSP_FIFO_DEPTH; i++) + sys_read32(dai_base(dp) + SSMIDyD(idx)); + } + + /* Clear the overflow status */ + dai_ssp_update_bits(dp, SSSR, SSSR_ROR, SSSR_ROR); + /* Re-read the SSSR register */ + sssr = sys_read32(dai_base(dp) + SSSR); + } + + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + while ((sys_read32(dai_base(dp) + SSMIDyCS(idx)) & SSMIDyCS_RNE) && retry--) { + uint32_t entries = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + + SSMIDyCS(idx))); + + /* Empty the RX FIFO (the DMA is not running at this point) */ + for (i = 0; i < entries + 1; i++) + sys_read32(dai_base(dp) + SSMIDyD(idx)); + + sssr = sys_read32(dai_base(dp) + SSSR); + } + } +} + +static void ssp_empty_rx_fifo_on_stop(struct dai_intel_ssp *dp) +{ + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + uint64_t sample_ticks = ssp_plat_data->params.fsync_rate ? + 1000000 / ssp_plat_data->params.fsync_rate : 0; + uint32_t retry = DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX; + uint32_t i, sssr, ssmidycs; + uint32_t entries[2]; + + if (ssp_is_acquired(dp->ssp_plat_data)) { + return; + } + + sssr = sys_read32(dai_base(dp) + SSSR); + + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + entries[0] = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(idx))); + + while ((sys_read32(dai_base(dp) + SSMIDyCS(idx)) & SSMIDyCS_RNE) && retry--) { + /* Wait one sample time */ + k_busy_wait(sample_ticks); + + entries[1] = SSMIDyCS_RFL_VAL(sys_read32(dai_base(dp) + SSMIDyCS(idx))); + sssr = sys_read32(dai_base(dp) + SSSR); + ssmidycs = sys_read32(dai_base(dp) + SSMIDyCS(idx)); + + if (entries[0] > entries[1]) { + /* + * The DMA is reading the FIFO, check the status in the + * next loop + */ + entries[0] = entries[1]; + } else if (!(ssmidycs & SSMIDyCS_RFS)) { + /* + * The DMA request is not asserted, read the FIFO + * directly, otherwise let the next loop iteration to + * check the status + */ + for (i = 0; i < entries[1] + 1; i++) + sys_read32(dai_base(dp) + SSMIDyD(idx)); + } + + sssr = sys_read32(dai_base(dp) + SSSR); + } + + } + /* Just in case clear the overflow status */ + dai_ssp_update_bits(dp, SSSR, SSSR_ROR, SSSR_ROR); +} + +#else static void ssp_empty_rx_fifo_on_start(struct dai_intel_ssp *dp) { uint32_t retry = DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX; @@ -994,21 +1122,20 @@ static void ssp_empty_rx_fifo_on_stop(struct dai_intel_ssp *dp) dai_ssp_update_bits(dp, SSSR, SSSR_ROR, SSSR_ROR); } +#endif + static int dai_ssp_mclk_prepare_enable(struct dai_intel_ssp *dp) { struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); - int ret = 0; + int ret; if (ssp_plat_data->clk_active & SSP_CLK_MCLK_ACTIVE) { return 0; } /* MCLK config */ - if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { - ret = dai_ssp_mn_set_mclk(dp, ssp_plat_data->params.mclk_id, - ssp_plat_data->params.mclk_rate); - } - + ret = dai_ssp_mn_set_mclk(dp, ssp_plat_data->params.mclk_id, + ssp_plat_data->params.mclk_rate); if (ret < 0) { LOG_ERR("invalid mclk_rate = %d for mclk_id = %d", ssp_plat_data->params.mclk_rate, ssp_plat_data->params.mclk_id); @@ -1027,9 +1154,7 @@ static void dai_ssp_mclk_disable_unprepare(struct dai_intel_ssp *dp) return; } - if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { - dai_ssp_mn_release_mclk(dp, ssp_plat_data->params.mclk_id); - } + dai_ssp_mn_release_mclk(dp, ssp_plat_data->params.mclk_id); ssp_plat_data->clk_active &= ~SSP_CLK_MCLK_ACTIVE; } @@ -1049,10 +1174,6 @@ static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) return 0; } - if (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_IS_NEEDED)) { - goto out; - } - sscr0 = sys_read32(dai_base(dp) + SSCR0); #if CONFIG_INTEL_MN @@ -1075,9 +1196,11 @@ static int dai_ssp_bclk_prepare_enable(struct dai_intel_ssp *dp) mdiv = ft[DAI_INTEL_SSP_DEFAULT_IDX].freq / ssp_plat_data->params.bclk_rate; #endif +#ifndef CONFIG_SOC_INTEL_ACE30_PTL if (need_ecs) { sscr0 |= SSCR0_ECS; } +#endif /* clock divisor is SCR + 1 */ mdiv -= 1; @@ -1112,9 +1235,7 @@ static void dai_ssp_bclk_disable_unprepare(struct dai_intel_ssp *dp) return; } #if CONFIG_INTEL_MN - if (ssp_plat_data->clk_active & SSP_CLK_BCLK_IS_NEEDED) { - dai_ssp_mn_release_bclk(dp, ssp_plat_data->ssp_index); - } + dai_ssp_mn_release_bclk(dp, ssp_plat_data->ssp_index); #endif ssp_plat_data->clk_active &= ~SSP_CLK_BCLK_ACTIVE; } @@ -1237,19 +1358,16 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR; break; case DAI_INTEL_IPC3_SSP_FMT_CBC_CFC: - ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED | SSP_CLK_BCLK_IS_NEEDED; sscr1 |= SSCR1_SCFR; cfs = true; break; case DAI_INTEL_IPC3_SSP_FMT_CBP_CFC: - ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED; sscr1 |= SSCR1_SCLKDIR; /* FIXME: this mode has not been tested */ cfs = true; break; case DAI_INTEL_IPC3_SSP_FMT_CBC_CFP: - ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED | SSP_CLK_BCLK_IS_NEEDED; sscr1 |= SSCR1_SCFR | SSCR1_SFRMDIR; /* FIXME: this mode has not been tested */ break; @@ -1611,8 +1729,18 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co sys_write32(sspsp2, dai_base(dp) + SSPSP2); sys_write32(ssioc, dai_base(dp) + SSIOC); sys_write32(ssto, dai_base(dp) + SSTO); +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + sys_write64(sstsa, dai_base(dp) + SSMODyTSA(idx)); + } + + for (uint32_t idx = 0; idx < I2SOPCMC; ++idx) { + sys_write64(ssrsa, dai_base(dp) + SSMIDyTSA(idx)); + } +#else sys_write32(sstsa, dai_base(dp) + SSTSA); sys_write32(ssrsa, dai_base(dp) + SSRSA); +#endif LOG_INF("sscr0 = 0x%08x, sscr1 = 0x%08x, ssto = 0x%08x, sspsp = 0x%0x", sscr0, sscr1, ssto, sspsp); @@ -1654,6 +1782,16 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co ssp_plat_data->clk_active |= SSP_CLK_BCLK_ES_REQ; if (enable_sse) { +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), + SSMIDyCS_RSRE, SSMIDyCS_RSRE); + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), + SSMODyCS_TSRE, SSMODyCS_TSRE); +#else + dai_ssp_update_bits(dp, SSCR1, + SSCR1_TSRE | SSCR1_RSRE, + SSCR1_TSRE | SSCR1_RSRE); +#endif /* enable port */ dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, SSCR0_SSE); @@ -1677,6 +1815,19 @@ static int dai_ssp_set_config_tplg(struct dai_intel_ssp *dp, const struct dai_co LOG_INF("hw_free stage: releasing BCLK clocks for SSP%d...", dp->dai_index); if (ssp_plat_data->clk_active & SSP_CLK_BCLK_ACTIVE) { +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + for (uint32_t idx = 0; idx < I2SOPCMC; ++idx) { + dai_ssp_update_bits(dp, SSMODyCS(idx), SSMODyCS_TSRE, 0); + } + + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + dai_ssp_update_bits(dp, SSMIDyCS(idx), SSMIDyCS_RSRE, 0); + } +#else + dai_ssp_update_bits(dp, SSCR1, + SSCR1_TSRE | SSCR1_RSRE, + 0); +#endif dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, 0); LOG_INF("SSE clear for SSP%d", dp->dai_index); } @@ -1825,7 +1976,7 @@ static int dai_ssp_parse_aux_data(struct dai_intel_ssp *dp, const void *spec_con sys_write32(sys_read32(dai_ip_base(dp) + I2SLCTL_OFFSET) | I2CLCTL_MLCS(link->clock_source), dai_ip_base(dp) + I2SLCTL_OFFSET); -#elif CONFIG_SOC_INTEL_ACE20_LNL +#elif CONFIG_SOC_INTEL_ACE20_LNL || CONFIG_SOC_INTEL_ACE30_PTL sys_write32(sys_read32(dai_i2svss_base(dp) + I2SLCTL_OFFSET) | I2CLCTL_MLCS(link->clock_source), dai_i2svss_base(dp) + I2SLCTL_OFFSET); @@ -1876,14 +2027,22 @@ static int dai_ssp_set_clock_control_ver_1(struct dai_intel_ssp *dp, static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_config *cfg, const struct dai_intel_ipc4_ssp_config *regs) { - uint32_t ssc0, sstsa, ssrsa, sscr1; + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + uint32_t sscr1 = 0; + uint32_t sstsa = 0; + uint32_t ssrsa = 0; + uint32_t ssc0 = regs->ssc0; - ssc0 = regs->ssc0; +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + sscr1 = regs->ssc1 & ~(SSCR1_RSVD21); +#else + sscr1 = regs->ssc1 & ~(SSCR1_RSRE | SSCR1_TSRE); sstsa = SSTSA_GET(regs->sstsa); ssrsa = SSRSA_GET(regs->ssrsa); - sscr1 = regs->ssc1 & ~(SSCR1_RSRE | SSCR1_TSRE); +#endif LOG_INF("SSP%d configuration:", dp->dai_index); +#ifndef CONFIG_SOC_INTEL_ACE30_PTL if (regs->sstsa & SSTSA_TXEN || regs->ssrsa & SSRSA_RXEN || regs->ssc1 & (SSCR1_RSRE | SSCR1_TSRE)) { LOG_INF(" Ignoring %s%s%s%sfrom blob", @@ -1892,19 +2051,32 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co regs->ssc1 & SSCR1_TSRE ? "SSCR1:TSRE " : "", regs->ssc1 & SSCR1_RSRE ? "SSCR1:RSRE " : ""); } +#endif sys_write32(ssc0, dai_base(dp) + SSCR0); sys_write32(regs->ssc2 & ~SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ sys_write32(sscr1, dai_base(dp) + SSCR1); sys_write32(regs->ssc2 | SSCR2_SFRMEN, dai_base(dp) + SSCR2); /* hardware specific flow */ sys_write32(regs->ssc2, dai_base(dp) + SSCR2); +#ifndef CONFIG_SOC_INTEL_ACE30_PTL sys_write32(regs->ssc3, dai_base(dp) + SSCR3); +#endif sys_write32(regs->sspsp, dai_base(dp) + SSPSP); sys_write32(regs->sspsp2, dai_base(dp) + SSPSP2); sys_write32(regs->ssioc, dai_base(dp) + SSIOC); sys_write32(regs->sscto, dai_base(dp) + SSTO); +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + for (uint32_t idx = 0; idx < I2SIPCMC; ++idx) { + sys_write64(regs->ssmidytsa[idx], dai_base(dp) + SSMIDyTSA(idx)); + } + + for (uint32_t idx = 0; idx < I2SOPCMC; ++idx) { + sys_write64(regs->ssmodytsa[idx], dai_base(dp) + SSMODyTSA(idx)); + } +#else sys_write32(sstsa, dai_base(dp) + SSTSA); sys_write32(ssrsa, dai_base(dp) + SSRSA); +#endif LOG_INF(" sscr0 = 0x%08x, sscr1 = 0x%08x, ssto = 0x%08x, sspsp = 0x%0x", ssc0, sscr1, regs->sscto, regs->sspsp); @@ -1913,25 +2085,19 @@ static void dai_ssp_set_reg_config(struct dai_intel_ssp *dp, const struct dai_co LOG_INF(" ssioc = 0x%08x, ssrsa = 0x%08x, sstsa = 0x%08x", regs->ssioc, ssrsa, sstsa); - dp->ssp_plat_data->params.sample_valid_bits = SSCR0_DSIZE_GET(ssc0); + ssp_plat_data->params.sample_valid_bits = SSCR0_DSIZE_GET(ssc0); if (ssc0 & SSCR0_EDSS) { - dp->ssp_plat_data->params.sample_valid_bits += 16; - } - - dp->ssp_plat_data->params.tdm_slots = SSCR0_FRDC_GET(ssc0); - dp->ssp_plat_data->params.tx_slots = SSTSA_GET(sstsa); - dp->ssp_plat_data->params.rx_slots = SSRSA_GET(ssrsa); - dp->ssp_plat_data->params.fsync_rate = cfg->rate; - - /* MCLK is needed if SSP is FS and/or BCLK provider */ - if (!(regs->ssc1 & (SSCR1_SCLKDIR | SSCR1_SFRMDIR))) { - dp->ssp_plat_data->clk_active |= SSP_CLK_MCLK_IS_NEEDED; - /* BCLK is only needed if SSP is BCLK provider */ - if (!(regs->ssc1 & SSCR1_SCLKDIR)) { - dp->ssp_plat_data->clk_active |= SSP_CLK_BCLK_IS_NEEDED; - } + ssp_plat_data->params.sample_valid_bits += 16; } - +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + ssp_plat_data->params.tx_slots = regs->ssmodytsa[dp->tdm_slot_group]; + ssp_plat_data->params.rx_slots = regs->ssmidytsa[dp->tdm_slot_group]; +#else + ssp_plat_data->params.tdm_slots = SSCR0_FRDC_GET(ssc0); + ssp_plat_data->params.tx_slots = SSTSA_GET(sstsa); + ssp_plat_data->params.rx_slots = SSRSA_GET(ssrsa); +#endif + ssp_plat_data->params.fsync_rate = cfg->rate; dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; } @@ -1944,6 +2110,10 @@ static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_co struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); int err; +#ifdef CONFIG_SOC_INTEL_ACE30_PTL + dp->tdm_slot_group = cfg->tdm_slot_group; +#endif + /* set config only once for playback or capture */ if (ssp_plat_data->is_initialized) { dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; @@ -1956,19 +2126,14 @@ static int dai_ssp_set_config_blob(struct dai_intel_ssp *dp, const struct dai_co if (err) return err; dai_ssp_set_reg_config(dp, cfg, &blob15->i2s_ssp_config); - if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { - err = dai_ssp_set_clock_control_ver_1_5(dp, &blob15->i2s_mclk_control); - if (err) - return err; - } + err = dai_ssp_set_clock_control_ver_1_5(dp, &blob15->i2s_mclk_control); + if (err) + return err; } else { dai_ssp_set_reg_config(dp, cfg, &blob->i2s_driver_config.i2s_config); - if (ssp_plat_data->clk_active & SSP_CLK_MCLK_IS_NEEDED) { - err = dai_ssp_set_clock_control_ver_1(dp, - &blob->i2s_driver_config.mclk_config); - if (err) - return err; - } + err = dai_ssp_set_clock_control_ver_1(dp, &blob->i2s_driver_config.mclk_config); + if (err) + return err; } ssp_plat_data->clk_active |= SSP_CLK_MCLK_ES_REQ; @@ -2070,6 +2235,19 @@ static void dai_ssp_start(struct dai_intel_ssp *dp, int direction) /* enable DMA */ +#if CONFIG_SOC_INTEL_ACE30_PTL + if (direction == DAI_DIR_PLAYBACK) { + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), + SSMODyCS_TSRE, SSMODyCS_TSRE); + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), + SSMODyCS_TXEN, SSMODyCS_TXEN); + } else { + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), + SSMIDyCS_RSRE, SSMIDyCS_RSRE); + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), + SSMIDyCS_RXEN, SSMIDyCS_RXEN); + } +#else if (direction == DAI_DIR_PLAYBACK) { LOG_INF("SSP%d TX", dp->dai_index); dai_ssp_update_bits(dp, SSCR1, SSCR1_TSRE, SSCR1_TSRE); @@ -2079,6 +2257,7 @@ static void dai_ssp_start(struct dai_intel_ssp *dp, int direction) dai_ssp_update_bits(dp, SSCR1, SSCR1_RSRE, SSCR1_RSRE); dai_ssp_update_bits(dp, SSRSA, SSRSA_RXEN, SSRSA_RXEN); } +#endif dp->state[direction] = DAI_STATE_RUNNING; ssp_acquire_port(dp->ssp_plat_data); @@ -2128,8 +2307,13 @@ static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) if (direction == DAI_DIR_CAPTURE && dp->state[DAI_DIR_CAPTURE] != DAI_STATE_PRE_RUNNING) { LOG_INF("SSP%d RX", dp->dai_index); +#if CONFIG_SOC_INTEL_ACE30_PTL + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), SSMIDyCS_RXEN, 0); + dai_ssp_update_bits(dp, SSMIDyCS(dp->tdm_slot_group), SSMIDyCS_RSRE, 0); +#else dai_ssp_update_bits(dp, SSRSA, SSRSA_RXEN, 0); dai_ssp_update_bits(dp, SSCR1, SSCR1_RSRE, 0); +#endif ssp_empty_rx_fifo_on_stop(dp); dp->state[DAI_DIR_CAPTURE] = DAI_STATE_PRE_RUNNING; ssp_release_port(ssp_plat_data); @@ -2139,9 +2323,15 @@ static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) if (direction == DAI_DIR_PLAYBACK && dp->state[DAI_DIR_PLAYBACK] != DAI_STATE_PRE_RUNNING) { LOG_INF("SSP%d TX", dp->dai_index); +#if CONFIG_SOC_INTEL_ACE30_PTL + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), SSMODyCS_TSRE, 0); + dai_ssp_empty_tx_fifo(dp); + dai_ssp_update_bits(dp, SSMODyCS(dp->tdm_slot_group), SSMODyCS_TXEN, 0); +#else dai_ssp_update_bits(dp, SSCR1, SSCR1_TSRE, 0); dai_ssp_empty_tx_fifo(dp); dai_ssp_update_bits(dp, SSTSA, SSTSA_TXEN, 0); +#endif dp->state[DAI_DIR_PLAYBACK] = DAI_STATE_PRE_RUNNING; ssp_release_port(ssp_plat_data); } @@ -2151,7 +2341,6 @@ static void dai_ssp_stop(struct dai_intel_ssp *dp, int direction) dp->state[DAI_DIR_PLAYBACK] == DAI_STATE_PRE_RUNNING && COND_CODE_1(CONFIG_INTEL_ADSP_CAVS, (!(ssp_plat_data->clk_active & SSP_CLK_BCLK_ES_REQ)), (true))) { - if (!ssp_is_acquired(ssp_plat_data)) { dai_ssp_update_bits(dp, SSCR0, SSCR0_SSE, 0); LOG_INF("%s SSE clear SSP%d", __func__, ssp_plat_data->ssp_index); @@ -2242,6 +2431,7 @@ static int dai_ssp_config_set(const struct device *dev, const struct dai_config const void *bespoke_cfg) { struct dai_intel_ssp *dp = (struct dai_intel_ssp *)dev->data; + struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); int ret; if (cfg->type == DAI_INTEL_SSP) { @@ -2249,7 +2439,8 @@ static int dai_ssp_config_set(const struct device *dev, const struct dai_config } else { ret = dai_ssp_set_config_blob(dp, cfg, bespoke_cfg); } - dai_ssp_program_channel_map(dp, cfg, dp->ssp_index); + dai_ssp_program_channel_map(dp, cfg, ssp_plat_data->ssp_index, bespoke_cfg); + return ret; } @@ -2321,6 +2512,12 @@ static int dai_ssp_remove(struct dai_intel_ssp *dp) { struct dai_intel_ssp_plat_data *ssp_plat_data = dai_get_plat_data(dp); + if (ssp_is_acquired(ssp_plat_data)) { + k_free(dai_get_drvdata(dp)); + dai_set_drvdata(dp, NULL); + return 0; + } + dai_ssp_pm_runtime_en_ssp_clk_gating(dp, ssp_plat_data->ssp_index); dai_ssp_mclk_disable_unprepare(dp); @@ -2402,6 +2599,7 @@ static struct dai_driver_api dai_intel_ssp_api_funcs = { static struct dai_intel_ssp dai_intel_ssp_data_##n = { \ .dai_index = DT_INST_REG_ADDR(n), \ .ssp_index = DT_PROP(DT_INST_PARENT(n), ssp_index), \ + .tdm_slot_group = 0, \ }; \ \ PM_DEVICE_DT_INST_DEFINE(n, ssp_pm_action); \ diff --git a/drivers/dai/intel/ssp/ssp.h b/drivers/dai/intel/ssp/ssp.h index 8c3e248a0d9b7..560b5d3df5f6e 100644 --- a/drivers/dai/intel/ssp/ssp.h +++ b/drivers/dai/intel/ssp/ssp.h @@ -48,234 +48,16 @@ #define DAI_INTEL_SSP_CLOCK_AUDIO_CARDINAL 0x1 #define DAI_INTEL_SSP_CLOCK_PLL_FIXED 0x2 -/* SSP register offsets */ -#define SSCR0 0x00 -#define SSCR1 0x04 -#define SSSR 0x08 -#define SSITR 0x0C -#define SSDR 0x10 -#define SSTO 0x28 -#define SSPSP 0x2C -#define SSTSA 0x30 -#define SSRSA 0x34 -#define SSTSS 0x38 -#define SSCR2 0x40 - -/* SSCR0 bits */ -#define SSCR0_DSIZE(x) DAI_INTEL_SSP_SET_BITS(3, 0, (x) - 1) -#define SSCR0_DSIZE_GET(x) (((x) & DAI_INTEL_SSP_MASK(3, 0)) + 1) -#define SSCR0_FRF DAI_INTEL_SSP_MASK(5, 4) -#define SSCR0_MOT DAI_INTEL_SSP_SET_BITS(5, 4, 0) -#define SSCR0_TI DAI_INTEL_SSP_SET_BITS(5, 4, 1) -#define SSCR0_NAT DAI_INTEL_SSP_SET_BITS(5, 4, 2) -#define SSCR0_PSP DAI_INTEL_SSP_SET_BITS(5, 4, 3) -#define SSCR0_ECS BIT(6) -#define SSCR0_SSE BIT(7) -#define SSCR0_SCR_MASK DAI_INTEL_SSP_MASK(19, 8) -#define SSCR0_SCR(x) DAI_INTEL_SSP_SET_BITS(19, 8, x) -#define SSCR0_EDSS BIT(20) -#define SSCR0_NCS BIT(21) -#define SSCR0_RIM BIT(22) -#define SSCR0_TIM BIT(23) -#define SSCR0_FRDC(x) DAI_INTEL_SSP_SET_BITS(26, 24, (x) - 1) -#define SSCR0_FRDC_GET(x) ((((x) & DAI_INTEL_SSP_MASK(26, 24)) >> 24) + 1) -#define SSCR0_ACS BIT(30) -#define SSCR0_MOD BIT(31) - -/* SSCR1 bits */ -#define SSCR1_RIE BIT(0) -#define SSCR1_TIE BIT(1) -#define SSCR1_LBM BIT(2) -#define SSCR1_SPO BIT(3) -#define SSCR1_SPH BIT(4) -#define SSCR1_MWDS BIT(5) -#define SSCR1_TFT_MASK DAI_INTEL_SSP_MASK(9, 6) -#define SSCR1_TFT(x) DAI_INTEL_SSP_SET_BITS(9, 6, (x) - 1) -#define SSCR1_RFT_MASK DAI_INTEL_SSP_MASK(13, 10) -#define SSCR1_RFT(x) DAI_INTEL_SSP_SET_BITS(13, 10, (x) - 1) -#define SSCR1_EFWR BIT(14) -#define SSCR1_STRF BIT(15) -#define SSCR1_IFS BIT(16) -#define SSCR1_PINTE BIT(18) -#define SSCR1_TINTE BIT(19) -#define SSCR1_RSRE BIT(20) -#define SSCR1_TSRE BIT(21) -#define SSCR1_TRAIL BIT(22) -#define SSCR1_RWOT BIT(23) -#define SSCR1_SFRMDIR BIT(24) -#define SSCR1_SCLKDIR BIT(25) -#define SSCR1_ECRB BIT(26) -#define SSCR1_ECRA BIT(27) -#define SSCR1_SCFR BIT(28) -#define SSCR1_EBCEI BIT(29) -#define SSCR1_TTE BIT(30) -#define SSCR1_TTELP BIT(31) - -#define SSCR2_TURM1 BIT(1) -#define SSCR2_PSPSRWFDFD BIT(3) -#define SSCR2_PSPSTWFDFD BIT(4) -#define SSCR2_SDFD BIT(14) -#define SSCR2_SDPM BIT(16) -#define SSCR2_LJDFD BIT(17) -#define SSCR2_MMRATF BIT(18) -#define SSCR2_SMTATF BIT(19) -#define SSCR2_SFRMEN BIT(20) -#define SSCR2_ACIOLBS BIT(21) - -/* SSR bits */ -#define SSSR_TNF BIT(2) -#define SSSR_RNE BIT(3) -#define SSSR_BSY BIT(4) -#define SSSR_TFS BIT(5) -#define SSSR_RFS BIT(6) -#define SSSR_ROR BIT(7) -#define SSSR_TUR BIT(21) - -/* SSPSP bits */ -#define SSPSP_SCMODE(x) DAI_INTEL_SSP_SET_BITS(1, 0, x) -#define SSPSP_SFRMP(x) DAI_INTEL_SSP_SET_BIT(2, x) -#define SSPSP_ETDS BIT(3) -#define SSPSP_STRTDLY(x) DAI_INTEL_SSP_SET_BITS(6, 4, x) -#define SSPSP_DMYSTRT(x) DAI_INTEL_SSP_SET_BITS(8, 7, x) -#define SSPSP_SFRMDLY(x) DAI_INTEL_SSP_SET_BITS(15, 9, x) -#define SSPSP_SFRMWDTH(x) DAI_INTEL_SSP_SET_BITS(21, 16, x) -#define SSPSP_DMYSTOP(x) DAI_INTEL_SSP_SET_BITS(24, 23, x) -#define SSPSP_DMYSTOP_BITS 2 -#define SSPSP_DMYSTOP_MASK DAI_INTEL_SSP_MASK(SSPSP_DMYSTOP_BITS - 1, 0) -#define SSPSP_FSRT BIT(25) -#define SSPSP_EDMYSTOP(x) DAI_INTEL_SSP_SET_BITS(28, 26, x) - -#define SSPSP2 0x44 -#define SSPSP2_FEP_MASK 0xff - -#define SSCR3 0x48 -#define SSIOC 0x4C -#define SSP_REG_MAX SSIOC - -/* SSTSA bits */ -#define SSTSA_SSTSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) -#define SSTSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) -#define SSTSA_TXEN BIT(8) - -/* SSRSA bits */ -#define SSRSA_SSRSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) -#define SSRSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) -#define SSRSA_RXEN BIT(8) - -/* SSCR3 bits */ -#define SSCR3_FRM_MST_EN BIT(0) -#define SSCR3_I2S_MODE_EN BIT(1) -#define SSCR3_I2S_FRM_POL(x) DAI_INTEL_SSP_SET_BIT(2, x) -#define SSCR3_I2S_TX_SS_FIX_EN BIT(3) -#define SSCR3_I2S_RX_SS_FIX_EN BIT(4) -#define SSCR3_I2S_TX_EN BIT(9) -#define SSCR3_I2S_RX_EN BIT(10) -#define SSCR3_CLK_EDGE_SEL BIT(12) -#define SSCR3_STRETCH_TX BIT(14) -#define SSCR3_STRETCH_RX BIT(15) -#define SSCR3_MST_CLK_EN BIT(16) -#define SSCR3_SYN_FIX_EN BIT(17) - -/* SSCR4 bits */ -#define SSCR4_TOT_FRM_PRD(x) ((x) << 7) - -/* SSCR5 bits */ -#define SSCR5_FRM_ASRT_CLOCKS(x) (((x) - 1) << 1) -#define SSCR5_FRM_POLARITY(x) DAI_INTEL_SSP_SET_BIT(0, x) - -/* SFIFOTT bits */ -#define SFIFOTT_TX(x) ((x) - 1) -#define SFIFOTT_RX(x) (((x) - 1) << 16) - -/* SFIFOL bits */ -#define SFIFOL_TFL(x) ((x) & 0xFFFF) -#define SFIFOL_RFL(x) ((x) >> 16) - -#define SSTSA_TSEN BIT(8) -#define SSRSA_RSEN BIT(8) - -#define SSCR3_TFL_MASK DAI_INTEL_SSP_MASK(5, 0) -#define SSCR3_RFL_MASK DAI_INTEL_SSP_MASK(13, 8) -#define SSCR3_TFL_VAL(scr3_val) (((scr3_val) >> 0) & DAI_INTEL_SSP_MASK(5, 0)) -#define SSCR3_RFL_VAL(scr3_val) (((scr3_val) >> 8) & DAI_INTEL_SSP_MASK(5, 0)) -#define SSCR3_TX(x) DAI_INTEL_SSP_SET_BITS(21, 16, (x) - 1) -#define SSCR3_RX(x) DAI_INTEL_SSP_SET_BITS(29, 24, (x) - 1) - -#define SSIOC_TXDPDEB BIT(1) -#define SSIOC_SFCR BIT(4) -#define SSIOC_SCOE BIT(5) - -/* For 8000 Hz rate one sample is transmitted within 125us */ -#define DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE 125 - -/* SSP flush retry counts maximum */ -#define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16 - -#define SSP_CLK_MCLK_IS_NEEDED BIT(0) -#define SSP_CLK_MCLK_ES_REQ BIT(1) -#define SSP_CLK_MCLK_ACTIVE BIT(2) -#define SSP_CLK_BCLK_IS_NEEDED BIT(3) -#define SSP_CLK_BCLK_ES_REQ BIT(4) -#define SSP_CLK_BCLK_ACTIVE BIT(5) - -#define I2SLCTL_OFFSET 0x04 - #if defined(CONFIG_SOC_INTEL_ACE15_MTPM) || defined(CONFIG_SOC_SERIES_INTEL_ADSP_CAVS) -#define I2SLCTL_SPA(x) BIT(0 + x) -#define I2SLCTL_CPA(x) BIT(8 + x) +#include "ssp_regs_v1.h" #elif defined(CONFIG_SOC_INTEL_ACE20_LNL) -#define I2SLCTL_OFLEN BIT(4) -#define I2SLCTL_SPA(x) BIT(16 + x) -#define I2SLCTL_CPA(x) BIT(23 + x) -#define PCMS0CM_OFFSET 0x16 -#define PCMS1CM_OFFSET 0x1A +#include "ssp_regs_v2.h" +#elif defined(CONFIG_SOC_INTEL_ACE30_PTL) +#include "ssp_regs_v3.h" #else #error "Missing ssp definitions" #endif -#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x) -#define SHIM_CLKCTL 0x78 -#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) -#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) - -#ifdef CONFIG_SOC_SERIES_INTEL_ADSP_ACE -/** \brief Offset of MCLK Divider Control Register. */ -#define MN_MDIVCTRL 0x100 - -/** \brief Offset of MCLK Divider x Ratio Register. */ -#define MN_MDIVR(x) (0x180 + (x) * 0x4) - -/** \brief Enables the output of MCLK Divider. - * On ACE+ there is a single divider for all MCLKs - */ -#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(0) - -#else -#define MN_MDIVCTRL 0x0 -#define MN_MDIVR(x) (0x80 + (x) * 0x4) - -/** \brief Enables the output of MCLK Divider. - * Each MCLK divider can be enabled separately. - */ -#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) - -#endif - -/** \brief Bits for setting MCLK source clock. */ -#define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x) - -/** \brief Offset of BCLK x M/N Divider M Value Register. */ -#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) - -/** \brief Offset of BCLK x M/N Divider N Value Register. */ -#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) - -/** \brief Bits for setting M/N source clock. */ -#define MNDSS(x) DAI_INTEL_SSP_SET_BITS(21, 20, x) - -/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ -#define MN_SOURCE_CLKS_MASK 0x3 - #if CONFIG_INTEL_MN /** \brief BCLKs can be driven by multiple sources - M/N or XTAL directly. * Even in the case of M/N, the actual clock source can be XTAL, @@ -334,7 +116,7 @@ struct dai_intel_ssp_plat_data { uint32_t base; uint32_t ip_base; uint32_t shim_base; -#ifdef CONFIG_SOC_INTEL_ACE20_LNL +#if defined(CONFIG_SOC_INTEL_ACE20_LNL) || defined(CONFIG_SOC_INTEL_ACE30_PTL) uint32_t hdamlssp_base; uint32_t i2svss_base; #endif @@ -360,6 +142,7 @@ struct dai_intel_ssp_pdata { struct dai_intel_ssp { uint32_t dai_index; uint32_t ssp_index; + uint32_t tdm_slot_group; uint32_t state[2]; struct k_spinlock lock; /**< locking mechanism */ int sref; /**< simple ref counter, guarded by lock */ diff --git a/drivers/dai/intel/ssp/ssp_regs_v1.h b/drivers/dai/intel/ssp/ssp_regs_v1.h new file mode 100644 index 0000000000000..a821ab8733a63 --- /dev/null +++ b/drivers/dai/intel/ssp/ssp_regs_v1.h @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2022 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INTEL_DAI_DRIVER_SSP_REGSV1_H__ +#define __INTEL_DAI_DRIVER_SSP_REGSV1_H__ + +/* SSP register offsets */ +#define SSCR0 0x00 +#define SSCR1 0x04 +#define SSSR 0x08 +#define SSITR 0x0C +#define SSTO 0x28 +#define SSPSP 0x2C +#define SSTSS 0x38 +#define SSCR2 0x40 +#define SSPSP2 0x44 +#define SSIOC 0x4C +#define SSGFS 0x50 +#define SSDR 0x10 /* Not PTL */ +#define SSTSA 0x30 /* Not PTL */ +#define SSRSA 0x34 /* Not PTL */ + +#define OUT_FIFO SSDR +#define IN_FIFO SSDR + +/* SSCR0 bits */ +#define SSCR0_DSIZE(x) DAI_INTEL_SSP_SET_BITS(3, 0, (x) - 1) +#define SSCR0_DSIZE_GET(x) (((x) & DAI_INTEL_SSP_MASK(3, 0)) + 1) +#define SSCR0_FRF DAI_INTEL_SSP_MASK(5, 4) +#define SSCR0_MOT DAI_INTEL_SSP_SET_BITS(5, 4, 0) +#define SSCR0_TI DAI_INTEL_SSP_SET_BITS(5, 4, 1) +#define SSCR0_NAT DAI_INTEL_SSP_SET_BITS(5, 4, 2) +#define SSCR0_PSP DAI_INTEL_SSP_SET_BITS(5, 4, 3) +#define SSCR0_ECS BIT(6) +#define SSCR0_SSE BIT(7) +#define SSCR0_SCR_MASK DAI_INTEL_SSP_MASK(19, 8) +#define SSCR0_SCR(x) DAI_INTEL_SSP_SET_BITS(19, 8, x) +#define SSCR0_EDSS BIT(20) +#define SSCR0_NCS BIT(21) +#define SSCR0_RIM BIT(22) +#define SSCR0_TIM BIT(23) +#define SSCR0_FRDC(x) DAI_INTEL_SSP_SET_BITS(26, 24, (x) - 1) +#define SSCR0_FRDC_GET(x) ((((x) & DAI_INTEL_SSP_MASK(26, 24)) >> 24) + 1) +#define SSCR0_ACS BIT(30) +#define SSCR0_MOD BIT(31) + +/* SSCR1 bits */ +#define SSCR1_RIE BIT(0) +#define SSCR1_TIE BIT(1) +#define SSCR1_LBM BIT(2) +#define SSCR1_SPO BIT(3) +#define SSCR1_SPH BIT(4) +#define SSCR1_MWDS BIT(5) +#define SSCR1_TFT_MASK DAI_INTEL_SSP_MASK(9, 6) +#define SSCR1_TFT(x) DAI_INTEL_SSP_SET_BITS(9, 6, (x) - 1) +#define SSCR1_RFT_MASK DAI_INTEL_SSP_MASK(13, 10) +#define SSCR1_RFT(x) DAI_INTEL_SSP_SET_BITS(13, 10, (x) - 1) +#define SSCR1_EFWR BIT(14) +#define SSCR1_STRF BIT(15) +#define SSCR1_IFS BIT(16) +#define SSCR1_PINTE BIT(18) +#define SSCR1_TINTE BIT(19) +#define SSCR1_RSRE BIT(20) +#define SSCR1_TSRE BIT(21) +#define SSCR1_TRAIL BIT(22) +#define SSCR1_RWOT BIT(23) +#define SSCR1_SFRMDIR BIT(24) +#define SSCR1_SCLKDIR BIT(25) +#define SSCR1_ECRB BIT(26) +#define SSCR1_ECRA BIT(27) +#define SSCR1_SCFR BIT(28) +#define SSCR1_EBCEI BIT(29) +#define SSCR1_TTE BIT(30) +#define SSCR1_TTELP BIT(31) + +#define SSCR2_TURM1 BIT(1) +#define SSCR2_PSPSRWFDFD BIT(3) +#define SSCR2_PSPSTWFDFD BIT(4) +#define SSCR2_SDFD BIT(14) +#define SSCR2_SDPM BIT(16) +#define SSCR2_LJDFD BIT(17) +#define SSCR2_MMRATF BIT(18) +#define SSCR2_SMTATF BIT(19) +#define SSCR2_SFRMEN BIT(20) +#define SSCR2_ACIOLBS BIT(21) + +/* SSR bits */ +#define SSSR_TNF BIT(2) +#define SSSR_RNE BIT(3) +#define SSSR_BSY BIT(4) +#define SSSR_TFS BIT(5) +#define SSSR_RFS BIT(6) +#define SSSR_ROR BIT(7) +#define SSSR_TUR BIT(21) + +/* SSPSP bits */ +#define SSPSP_SCMODE(x) DAI_INTEL_SSP_SET_BITS(1, 0, x) +#define SSPSP_SFRMP(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSPSP_ETDS BIT(3) +#define SSPSP_STRTDLY(x) DAI_INTEL_SSP_SET_BITS(6, 4, x) +#define SSPSP_DMYSTRT(x) DAI_INTEL_SSP_SET_BITS(8, 7, x) +#define SSPSP_SFRMDLY(x) DAI_INTEL_SSP_SET_BITS(15, 9, x) +#define SSPSP_SFRMWDTH(x) DAI_INTEL_SSP_SET_BITS(21, 16, x) +#define SSPSP_DMYSTOP(x) DAI_INTEL_SSP_SET_BITS(24, 23, x) +#define SSPSP_DMYSTOP_BITS 2 +#define SSPSP_DMYSTOP_MASK DAI_INTEL_SSP_MASK(SSPSP_DMYSTOP_BITS - 1, 0) +#define SSPSP_FSRT BIT(25) +#define SSPSP_EDMYSTOP(x) DAI_INTEL_SSP_SET_BITS(28, 26, x) + +#define SSPSP2 0x44 +#define SSPSP2_FEP_MASK 0xff + +#define SSCR3 0x48 +#define SSIOC 0x4C +#define SSP_REG_MAX SSIOC + +/* SSTSA bits */ +#define SSTSA_SSTSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSTSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSTSA_TXEN BIT(8) + +/* SSRSA bits */ +#define SSRSA_SSRSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSRSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSRSA_RXEN BIT(8) + +/* SSCR3 bits */ +#define SSCR3_FRM_MST_EN BIT(0) +#define SSCR3_I2S_MODE_EN BIT(1) +#define SSCR3_I2S_FRM_POL(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSCR3_I2S_TX_SS_FIX_EN BIT(3) +#define SSCR3_I2S_RX_SS_FIX_EN BIT(4) +#define SSCR3_I2S_TX_EN BIT(9) +#define SSCR3_I2S_RX_EN BIT(10) +#define SSCR3_CLK_EDGE_SEL BIT(12) +#define SSCR3_STRETCH_TX BIT(14) +#define SSCR3_STRETCH_RX BIT(15) +#define SSCR3_MST_CLK_EN BIT(16) +#define SSCR3_SYN_FIX_EN BIT(17) + +/* SSCR4 bits */ +#define SSCR4_TOT_FRM_PRD(x) ((x) << 7) + +/* SSCR5 bits */ +#define SSCR5_FRM_ASRT_CLOCKS(x) (((x) - 1) << 1) +#define SSCR5_FRM_POLARITY(x) DAI_INTEL_SSP_SET_BIT(0, x) + +/* SFIFOTT bits */ +#define SFIFOTT_TX(x) ((x) - 1) +#define SFIFOTT_RX(x) (((x) - 1) << 16) + +/* SFIFOL bits */ +#define SFIFOL_TFL(x) ((x) & 0xFFFF) +#define SFIFOL_RFL(x) ((x) >> 16) + +#define SSTSA_TSEN BIT(8) +#define SSRSA_RSEN BIT(8) + +#define SSCR3_TFL_MASK DAI_INTEL_SSP_MASK(5, 0) +#define SSCR3_RFL_MASK DAI_INTEL_SSP_MASK(13, 8) +#define SSCR3_TFL_VAL(scr3_val) (((scr3_val) >> 0) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_RFL_VAL(scr3_val) (((scr3_val) >> 8) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_TX(x) DAI_INTEL_SSP_SET_BITS(21, 16, (x) - 1) +#define SSCR3_RX(x) DAI_INTEL_SSP_SET_BITS(29, 24, (x) - 1) + +#define SSIOC_TXDPDEB BIT(1) +#define SSIOC_SFCR BIT(4) +#define SSIOC_SCOE BIT(5) + +/* SSMIDyCS */ +#define SSMIDyCS_RXEN BIT(0) +#define SSMIDyCS_RSRE BIT(1) +#define SSMIDyCS_RFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_RFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMIDyCS_RNE BIT(26) +#define SSMIDyCS_RFS BIT(27) +#define SSMIDyCS_ROR BIT(28) +#define SSMIDyCS_PINT BIT(29) +#define SSMIDyCS_TINT BIT(30) +#define SSMIDyCS_EOC BIT(31) + +/* SSMIDyTSA */ +#define SSMIDyTSA_RTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMIDyTSA_SRTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* SSMODyCS */ +#define SSMODyCS_TXEN BIT(0) +#define SSMODyCS_TSRE BIT(1) +#define SSMODyCS_TFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_TFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMODyCS_TNF BIT(26) +#define SSMODyCS_TFS BIT(27) +#define SSMODyCS_TUR BIT(28) + +/* SSMODyTSA */ +#define SSMODyTSA_TTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMODyTSA_STTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* For 8000 Hz rate one sample is transmitted within 125us */ +#define DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE 125 + +/* SSP flush retry counts maximum */ +#define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16 + +#define SSP_CLK_MCLK_ES_REQ BIT(0) +#define SSP_CLK_MCLK_ACTIVE BIT(1) +#define SSP_CLK_BCLK_ES_REQ BIT(2) +#define SSP_CLK_BCLK_ACTIVE BIT(3) + +#define I2SLCTL_OFFSET 0x04 + +#define I2SLCTL_SPA(x) BIT(0 + x) +#define I2SLCTL_CPA(x) BIT(8 + x) + +#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x) +#define SHIM_CLKCTL 0x78 +#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) +#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) + +#ifdef CONFIG_SOC_SERIES_INTEL_ADSP_ACE +/** \brief Offset of MCLK Divider Control Register. */ +#define MN_MDIVCTRL 0x100 + +/** \brief Offset of MCLK Divider x Ratio Register. */ +#define MN_MDIVR(x) (0x180 + (x) * 0x4) +#else +#define MN_MDIVCTRL 0x0 +#define MN_MDIVR(x) (0x80 + (x) * 0x4) +#endif + +/** \brief Enables the output of MCLK Divider. */ +#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) + +/** \brief Bits for setting MCLK source clock. */ +#define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x) + +/** \brief Offset of BCLK x M/N Divider M Value Register. */ +#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) + +/** \brief Offset of BCLK x M/N Divider N Value Register. */ +#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) + +/** \brief Bits for setting M/N source clock. */ +#define MNDSS(x) DAI_INTEL_SSP_SET_BITS(21, 20, x) + +/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ +#define MN_SOURCE_CLKS_MASK 0x3 + +#endif /* __INTEL_DAI_DRIVER_SSP_REGSV1_H__ */ diff --git a/drivers/dai/intel/ssp/ssp_regs_v2.h b/drivers/dai/intel/ssp/ssp_regs_v2.h new file mode 100644 index 0000000000000..e2d1c826d075c --- /dev/null +++ b/drivers/dai/intel/ssp/ssp_regs_v2.h @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2022 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INTEL_DAI_DRIVER_SSP_REGSV2_H__ +#define __INTEL_DAI_DRIVER_SSP_REGSV2_H__ + +/* SSP register offsets */ +#define SSCR0 0x00 +#define SSCR1 0x04 +#define SSSR 0x08 +#define SSITR 0x0C +#define SSTO 0x28 +#define SSPSP 0x2C +#define SSTSS 0x38 +#define SSCR2 0x40 +#define SSPSP2 0x44 + +#define SSIOC 0x4C +#define SSGFS 0x50 +#define SSDR 0x10 /* Not PTL */ +#define SSTSA 0x30 /* Not PTL */ +#define SSRSA 0x34 /* Not PTL */ + +#define OUT_FIFO SSDR +#define IN_FIFO SSDR + +/* SSCR0 bits */ +#define SSCR0_DSIZE(x) DAI_INTEL_SSP_SET_BITS(3, 0, (x) - 1) +#define SSCR0_DSIZE_GET(x) (((x) & DAI_INTEL_SSP_MASK(3, 0)) + 1) +#define SSCR0_FRF DAI_INTEL_SSP_MASK(5, 4) +#define SSCR0_MOT DAI_INTEL_SSP_SET_BITS(5, 4, 0) +#define SSCR0_TI DAI_INTEL_SSP_SET_BITS(5, 4, 1) +#define SSCR0_NAT DAI_INTEL_SSP_SET_BITS(5, 4, 2) +#define SSCR0_PSP DAI_INTEL_SSP_SET_BITS(5, 4, 3) +#define SSCR0_ECS BIT(6) +#define SSCR0_SSE BIT(7) +#define SSCR0_SCR_MASK DAI_INTEL_SSP_MASK(19, 8) +#define SSCR0_SCR(x) DAI_INTEL_SSP_SET_BITS(19, 8, x) +#define SSCR0_EDSS BIT(20) +#define SSCR0_NCS BIT(21) +#define SSCR0_RIM BIT(22) +#define SSCR0_TIM BIT(23) +#define SSCR0_FRDC(x) DAI_INTEL_SSP_SET_BITS(26, 24, (x) - 1) +#define SSCR0_FRDC_GET(x) ((((x) & DAI_INTEL_SSP_MASK(26, 24)) >> 24) + 1) +#define SSCR0_ACS BIT(30) +#define SSCR0_MOD BIT(31) + +/* SSCR1 bits */ +#define SSCR1_RIE BIT(0) +#define SSCR1_TIE BIT(1) +#define SSCR1_LBM BIT(2) +#define SSCR1_SPO BIT(3) +#define SSCR1_SPH BIT(4) +#define SSCR1_MWDS BIT(5) +#define SSCR1_TFT_MASK DAI_INTEL_SSP_MASK(9, 6) +#define SSCR1_TFT(x) DAI_INTEL_SSP_SET_BITS(9, 6, (x) - 1) +#define SSCR1_RFT_MASK DAI_INTEL_SSP_MASK(13, 10) +#define SSCR1_RFT(x) DAI_INTEL_SSP_SET_BITS(13, 10, (x) - 1) +#define SSCR1_EFWR BIT(14) +#define SSCR1_STRF BIT(15) +#define SSCR1_IFS BIT(16) +#define SSCR1_PINTE BIT(18) +#define SSCR1_TINTE BIT(19) +#define SSCR1_RSRE BIT(20) +#define SSCR1_TSRE BIT(21) +#define SSCR1_TRAIL BIT(22) +#define SSCR1_RWOT BIT(23) +#define SSCR1_SFRMDIR BIT(24) +#define SSCR1_SCLKDIR BIT(25) +#define SSCR1_ECRB BIT(26) +#define SSCR1_ECRA BIT(27) +#define SSCR1_SCFR BIT(28) +#define SSCR1_EBCEI BIT(29) +#define SSCR1_TTE BIT(30) +#define SSCR1_TTELP BIT(31) + +#define SSCR2_TURM1 BIT(1) +#define SSCR2_PSPSRWFDFD BIT(3) +#define SSCR2_PSPSTWFDFD BIT(4) +#define SSCR2_SDFD BIT(14) +#define SSCR2_SDPM BIT(16) +#define SSCR2_LJDFD BIT(17) +#define SSCR2_MMRATF BIT(18) +#define SSCR2_SMTATF BIT(19) +#define SSCR2_SFRMEN BIT(20) +#define SSCR2_ACIOLBS BIT(21) + +/* SSR bits */ +#define SSSR_TNF BIT(2) +#define SSSR_RNE BIT(3) +#define SSSR_BSY BIT(4) +#define SSSR_TFS BIT(5) +#define SSSR_RFS BIT(6) +#define SSSR_ROR BIT(7) +#define SSSR_TUR BIT(21) + +/* SSPSP bits */ +#define SSPSP_SCMODE(x) DAI_INTEL_SSP_SET_BITS(1, 0, x) +#define SSPSP_SFRMP(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSPSP_ETDS BIT(3) +#define SSPSP_STRTDLY(x) DAI_INTEL_SSP_SET_BITS(6, 4, x) +#define SSPSP_DMYSTRT(x) DAI_INTEL_SSP_SET_BITS(8, 7, x) +#define SSPSP_SFRMDLY(x) DAI_INTEL_SSP_SET_BITS(15, 9, x) +#define SSPSP_SFRMWDTH(x) DAI_INTEL_SSP_SET_BITS(21, 16, x) +#define SSPSP_DMYSTOP(x) DAI_INTEL_SSP_SET_BITS(24, 23, x) +#define SSPSP_DMYSTOP_BITS 2 +#define SSPSP_DMYSTOP_MASK DAI_INTEL_SSP_MASK(SSPSP_DMYSTOP_BITS - 1, 0) +#define SSPSP_FSRT BIT(25) +#define SSPSP_EDMYSTOP(x) DAI_INTEL_SSP_SET_BITS(28, 26, x) + +#define SSPSP2 0x44 +#define SSPSP2_FEP_MASK 0xff + +#define SSCR3 0x48 +#define SSIOC 0x4C +#define SSP_REG_MAX SSIOC + +/* SSTSA bits */ +#define SSTSA_SSTSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSTSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSTSA_TXEN BIT(8) + +/* SSRSA bits */ +#define SSRSA_SSRSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSRSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSRSA_RXEN BIT(8) + +/* SSCR3 bits */ +#define SSCR3_FRM_MST_EN BIT(0) +#define SSCR3_I2S_MODE_EN BIT(1) +#define SSCR3_I2S_FRM_POL(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSCR3_I2S_TX_SS_FIX_EN BIT(3) +#define SSCR3_I2S_RX_SS_FIX_EN BIT(4) +#define SSCR3_I2S_TX_EN BIT(9) +#define SSCR3_I2S_RX_EN BIT(10) +#define SSCR3_CLK_EDGE_SEL BIT(12) +#define SSCR3_STRETCH_TX BIT(14) +#define SSCR3_STRETCH_RX BIT(15) +#define SSCR3_MST_CLK_EN BIT(16) +#define SSCR3_SYN_FIX_EN BIT(17) + +/* SSCR4 bits */ +#define SSCR4_TOT_FRM_PRD(x) ((x) << 7) + +/* SSCR5 bits */ +#define SSCR5_FRM_ASRT_CLOCKS(x) (((x) - 1) << 1) +#define SSCR5_FRM_POLARITY(x) DAI_INTEL_SSP_SET_BIT(0, x) + +/* SFIFOTT bits */ +#define SFIFOTT_TX(x) ((x) - 1) +#define SFIFOTT_RX(x) (((x) - 1) << 16) + +/* SFIFOL bits */ +#define SFIFOL_TFL(x) ((x) & 0xFFFF) +#define SFIFOL_RFL(x) ((x) >> 16) + +#define SSTSA_TSEN BIT(8) +#define SSRSA_RSEN BIT(8) + +#define SSCR3_TFL_MASK DAI_INTEL_SSP_MASK(5, 0) +#define SSCR3_RFL_MASK DAI_INTEL_SSP_MASK(13, 8) +#define SSCR3_TFL_VAL(scr3_val) (((scr3_val) >> 0) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_RFL_VAL(scr3_val) (((scr3_val) >> 8) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_TX(x) DAI_INTEL_SSP_SET_BITS(21, 16, (x) - 1) +#define SSCR3_RX(x) DAI_INTEL_SSP_SET_BITS(29, 24, (x) - 1) + +#define SSIOC_TXDPDEB BIT(1) +#define SSIOC_SFCR BIT(4) +#define SSIOC_SCOE BIT(5) + +/* SSMIDyCS */ +#define SSMIDyCS_RXEN BIT(0) +#define SSMIDyCS_RSRE BIT(1) +#define SSMIDyCS_RFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_RFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMIDyCS_RNE BIT(26) +#define SSMIDyCS_RFS BIT(27) +#define SSMIDyCS_ROR BIT(28) +#define SSMIDyCS_PINT BIT(29) +#define SSMIDyCS_TINT BIT(30) +#define SSMIDyCS_EOC BIT(31) + +/* SSMIDyTSA */ +#define SSMIDyTSA_RTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMIDyTSA_SRTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* SSMODyCS */ +#define SSMODyCS_TXEN BIT(0) +#define SSMODyCS_TSRE BIT(1) +#define SSMODyCS_TFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_TFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMODyCS_TNF BIT(26) +#define SSMODyCS_TFS BIT(27) +#define SSMODyCS_TUR BIT(28) + +/* SSMODyTSA */ +#define SSMODyTSA_TTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMODyTSA_STTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* For 8000 Hz rate one sample is transmitted within 125us */ +#define DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE 125 + +/* SSP flush retry counts maximum */ +#define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16 + +#define SSP_CLK_MCLK_ES_REQ BIT(0) +#define SSP_CLK_MCLK_ACTIVE BIT(1) +#define SSP_CLK_BCLK_ES_REQ BIT(2) +#define SSP_CLK_BCLK_ACTIVE BIT(3) + +#define I2SLCTL_OFFSET 0x04 +#define I2SLCTL_OFLEN BIT(4) +#define I2SLCTL_SPA(x) BIT(16 + x) +#define I2SLCTL_CPA(x) BIT(23 + x) +#define PCMS0CM_OFFSET 0x16 +#define PCMS1CM_OFFSET 0x1A + +#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x) +#define SHIM_CLKCTL 0x78 +#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) +#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) + +/** \brief Offset of MCLK Divider Control Register. */ +#define MN_MDIVCTRL 0x100 + +/** \brief Offset of MCLK Divider x Ratio Register. */ +#define MN_MDIVR(x) (0x180 + (x) * 0x4) + +/** \brief Enables the output of MCLK Divider. */ +#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) + +/** \brief Bits for setting MCLK source clock. */ +#define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x) + +/** \brief Offset of BCLK x M/N Divider M Value Register. */ +#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) + +/** \brief Offset of BCLK x M/N Divider N Value Register. */ +#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) + +/** \brief Bits for setting M/N source clock. */ +#define MNDSS(x) DAI_INTEL_SSP_SET_BITS(21, 20, x) + +/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ +#define MN_SOURCE_CLKS_MASK 0x3 + +#endif /* __INTEL_DAI_DRIVER_SSP_REGSV2_H__ */ diff --git a/drivers/dai/intel/ssp/ssp_regs_v3.h b/drivers/dai/intel/ssp/ssp_regs_v3.h new file mode 100644 index 0000000000000..2141dc39d85b6 --- /dev/null +++ b/drivers/dai/intel/ssp/ssp_regs_v3.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2022 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __INTEL_DAI_DRIVER_SSP_REGSV3_H__ +#define __INTEL_DAI_DRIVER_SSP_REGSV3_H__ + +/* SSP register offsets */ +#define SSCR0 0x00 +#define SSCR1 0x04 +#define SSSR 0x08 +#define SSITR 0x0C +#define SSTO 0x28 +#define SSPSP 0x2C +#define SSTSS 0x38 +#define SSCR2 0x40 +#define SSPSP2 0x44 + +#define SSIOC 0x4C +#define SSGFS 0x50 + +#define I2SIPCMC 8 +#define SSMIDyCS(y) 0x60 + 0x10*y +#define SSMIDyD(y) 0x64 + 0x10*y +#define SSMIDyTSA(y) 0x68 + 0x10*y +#define SSMODyCS(y) 0x60 + 0x10*I2SIPCMC + 0x10*y +#define SSMODyD(y) 0x64 + 0x10*I2SIPCMC + 0x10*y +#define SSMODyTSA(y) 0x68 + 0x10*I2SIPCMC + 0x10*y + +#define PCMSyCM_OFFSET(x) 0x16 + 0x4*(x) + +#define OUT_FIFO SSMODyD(0) +#define IN_FIFO SSMIDyD(0) + +/* SSCR0 bits */ +#define SSCR0_DSIZE(x) DAI_INTEL_SSP_SET_BITS(3, 0, (x) - 1) +#define SSCR0_DSIZE_GET(x) (((x) & DAI_INTEL_SSP_MASK(3, 0)) + 1) +#define SSCR0_FRF DAI_INTEL_SSP_MASK(5, 4) +#define SSCR0_MOT DAI_INTEL_SSP_SET_BITS(5, 4, 0) +#define SSCR0_TI DAI_INTEL_SSP_SET_BITS(5, 4, 1) +#define SSCR0_NAT DAI_INTEL_SSP_SET_BITS(5, 4, 2) +#define SSCR0_PSP DAI_INTEL_SSP_SET_BITS(5, 4, 3) +#define SSCR0_RSVD1 BIT(6) +#define SSCR0_SSE BIT(7) +#define SSCR0_SCR_MASK DAI_INTEL_SSP_MASK(19, 8) +#define SSCR0_SCR(x) DAI_INTEL_SSP_SET_BITS(19, 8, x) +#define SSCR0_EDSS BIT(20) +#define SSCR0_RSVD2 BIT(21) +#define SSCR0_RIM BIT(22) +#define SSCR0_TIM BIT(23) +#define SSCR0_FRDC(x) DAI_INTEL_SSP_SET_BITS(26, 24, (x) - 1) +#define SSCR0_FRDC_GET(x) ((((x) & DAI_INTEL_SSP_MASK(26, 24)) >> 24) + 1) +#define SSCR0_EFRDC BIT(27) +#define SSCR0_EFRDC2 BIT(28) +#define SSCR0_DLE DAI_INTEL_SSP_SET_BITS(30, 29, 0) +#define SSCR0_MOD BIT(31) + +/* SSCR1 bits */ +#define SSCR1_RIE BIT(0) +#define SSCR1_TIE BIT(1) +#define SSCR1_LBM BIT(2) +#define SSCR1_RSVD1 DAI_INTEL_SSP_MASK(15, 3) +#define SSCR1_IFS BIT(16) +#define SSCR1_PINTE BIT(18) +#define SSCR1_TINTE BIT(19) +#define SSCR1_RSVD21 DAI_INTEL_SSP_MASK(21, 20) +#define SSCR1_TRAIL BIT(22) +#define SSCR1_RWOT BIT(23) +#define SSCR1_SFRMDIR BIT(24) +#define SSCR1_SCLKDIR BIT(25) +#define SSCR1_SCFR BIT(28) +#define SSCR1_EBCEI BIT(29) +#define SSCR1_TTE BIT(30) +#define SSCR1_TTELP BIT(31) + +#define SSCR2_TURM1 BIT(1) +#define SSCR2_PSPSRWFDFD BIT(3) +#define SSCR2_PSPSTWFDFD BIT(4) +#define SSCR2_SDFD BIT(14) +#define SSCR2_SDPM BIT(16) +#define SSCR2_LJDFD BIT(17) +#define SSCR2_MMRATF BIT(18) +#define SSCR2_SMTATF BIT(19) +#define SSCR2_SFRMEN BIT(20) +#define SSCR2_ACIOLBS BIT(21) + +/* SSR bits */ +#define SSSR_BSY BIT(4) +#define SSSR_ROR BIT(7) +#define SSSR_TUR BIT(21) + +/* SSPSP bits */ +#define SSPSP_SCMODE(x) DAI_INTEL_SSP_SET_BITS(1, 0, x) +#define SSPSP_SFRMP(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSPSP_STRTDLY(x) DAI_INTEL_SSP_SET_BITS(6, 4, x) +#define SSPSP_DMYSTRT(x) DAI_INTEL_SSP_SET_BITS(8, 7, x) +#define SSPSP_SFRMDLY(x) DAI_INTEL_SSP_SET_BITS(15, 9, x) +#define SSPSP_SFRMWDTH(x) DAI_INTEL_SSP_SET_BITS(21, 16, x) +#define SSPSP_DMYSTOP(x) DAI_INTEL_SSP_SET_BITS(24, 23, x) +#define SSPSP_DMYSTOP_BITS 2 +#define SSPSP_DMYSTOP_MASK DAI_INTEL_SSP_MASK(SSPSP_DMYSTOP_BITS - 1, 0) +#define SSPSP_FSRT BIT(25) +#define SSPSP_EDMYSTOP(x) DAI_INTEL_SSP_SET_BITS(28, 26, x) + +#define SSPSP2 0x44 +#define SSPSP2_FEP_MASK 0xff + +#define SSPSP2_RFAC DAI_INTEL_SSP_MASK(9, 8) +#define SSPSP2_TFAC DAI_INTEL_SSP_MASK(11, 10) +#define SSPSP2_EFEP DAI_INTEL_SSP_MASK(13, 12) +#define SSPSP2_ESFRMDW DAI_INTEL_SSP_MASK(15, 14) + + +#define SSCR3 0x48 +#define SSIOC 0x4C +#define SSP_REG_MAX SSIOC + +/* SSTSA bits */ +#define SSTSA_SSTSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSTSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) + +/* SSRSA bits */ +#define SSRSA_SSRSA(x) DAI_INTEL_SSP_SET_BITS(7, 0, x) +#define SSRSA_GET(x) ((x) & DAI_INTEL_SSP_MASK(7, 0)) + +/* SSCR3 bits */ +#define SSCR3_FRM_MST_EN BIT(0) +#define SSCR3_I2S_MODE_EN BIT(1) +#define SSCR3_I2S_FRM_POL(x) DAI_INTEL_SSP_SET_BIT(2, x) +#define SSCR3_I2S_TX_SS_FIX_EN BIT(3) +#define SSCR3_I2S_RX_SS_FIX_EN BIT(4) +#define SSCR3_I2S_TX_EN BIT(9) +#define SSCR3_I2S_RX_EN BIT(10) +#define SSCR3_CLK_EDGE_SEL BIT(12) +#define SSCR3_STRETCH_TX BIT(14) +#define SSCR3_STRETCH_RX BIT(15) +#define SSCR3_MST_CLK_EN BIT(16) +#define SSCR3_SYN_FIX_EN BIT(17) + +/* SSCR4 bits */ +#define SSCR4_TOT_FRM_PRD(x) ((x) << 7) + +/* SSCR5 bits */ +#define SSCR5_FRM_ASRT_CLOCKS(x) (((x) - 1) << 1) +#define SSCR5_FRM_POLARITY(x) DAI_INTEL_SSP_SET_BIT(0, x) + +/* SFIFOTT bits */ +#define SFIFOTT_TX(x) ((x) - 1) +#define SFIFOTT_RX(x) (((x) - 1) << 16) + +/* SFIFOL bits */ +#define SFIFOL_TFL(x) ((x) & 0xFFFF) +#define SFIFOL_RFL(x) ((x) >> 16) + +#define SSTSA_TSEN BIT(8) +#define SSRSA_RSEN BIT(8) + +#define SSCR3_TFL_MASK DAI_INTEL_SSP_MASK(5, 0) +#define SSCR3_RFL_MASK DAI_INTEL_SSP_MASK(13, 8) +#define SSCR3_TFL_VAL(scr3_val) (((scr3_val) >> 0) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_RFL_VAL(scr3_val) (((scr3_val) >> 8) & DAI_INTEL_SSP_MASK(5, 0)) +#define SSCR3_TX(x) DAI_INTEL_SSP_SET_BITS(21, 16, (x) - 1) +#define SSCR3_RX(x) DAI_INTEL_SSP_SET_BITS(29, 24, (x) - 1) + +#define SSIOC_TXDPDEB BIT(1) +#define SSIOC_SFCR BIT(4) +#define SSIOC_SCOE BIT(5) + +/* SSMIDyCS */ +#define SSMIDyCS_RXEN BIT(0) +#define SSMIDyCS_RSRE BIT(1) +#define SSMIDyCS_RFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_RFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMIDyCS_RNE BIT(26) +#define SSMIDyCS_RFS BIT(27) +#define SSMIDyCS_ROR BIT(28) +#define SSMIDyCS_PINT BIT(29) +#define SSMIDyCS_TINT BIT(30) +#define SSMIDyCS_EOC BIT(31) + +/* SSMIDyTSA */ +#define SSMIDyTSA_RTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMIDyTSA_SRTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* SSMODyCS */ +#define SSMODyCS_TXEN BIT(0) +#define SSMODyCS_TSRE BIT(1) +#define SSMODyCS_TFL DAI_INTEL_SSP_MASK(23, 16) +#define SSMIDyCS_TFL_VAL(rfl_val) (((rfl_val) >> 16) & DAI_INTEL_SSP_MASK(7, 0)) +#define SSMODyCS_TNF BIT(26) +#define SSMODyCS_TFS BIT(27) +#define SSMODyCS_TUR BIT(28) + +/* SSMODyTSA */ +#define SSMODyTSA_TTSA DAI_INTEL_SSP_MASK(63, 0) +#define SSMODyTSA_STTSA(x) DAI_INTEL_SSP_MASK(63, 0, x) + +/* For 8000 Hz rate one sample is transmitted within 125us */ +#define DAI_INTEL_SSP_MAX_SEND_TIME_PER_SAMPLE 125 + +/* SSP flush retry counts maximum */ +#define DAI_INTEL_SSP_RX_FLUSH_RETRY_MAX 16 + +#define SSP_CLK_MCLK_ES_REQ BIT(0) +#define SSP_CLK_MCLK_ACTIVE BIT(1) +#define SSP_CLK_BCLK_ES_REQ BIT(2) +#define SSP_CLK_BCLK_ACTIVE BIT(3) + +#define I2SLCTL_OFFSET 0x04 + +#define I2SLCTL_OFLEN BIT(4) +#define I2SLCTL_SPA(x) BIT(16 + x) +#define I2SLCTL_CPA(x) BIT(23 + x) + +#define I2CLCTL_MLCS(x) DAI_INTEL_SSP_SET_BITS(30, 27, x) +#define SHIM_CLKCTL 0x78 +#define SHIM_CLKCTL_I2SFDCGB(x) BIT(20 + x) +#define SHIM_CLKCTL_I2SEFDCGB(x) BIT(18 + x) + +/** \brief Offset of MCLK Divider Control Register. */ +#define MN_MDIVCTRL 0x100 + +/** \brief Offset of MCLK Divider x Ratio Register. */ +#define MN_MDIVR(x) (0x180 + (x) * 0x4) + +/** \brief Enables the output of MCLK Divider. */ +#define MN_MDIVCTRL_M_DIV_ENABLE(x) BIT(x) + +/** \brief Bits for setting MCLK source clock. */ +#define MCDSS(x) DAI_INTEL_SSP_SET_BITS(17, 16, x) + +/** \brief Offset of BCLK x M/N Divider M Value Register. */ +#define MN_MDIV_M_VAL(x) (0x100 + (x) * 0x8 + 0x0) + +/** \brief Offset of BCLK x M/N Divider N Value Register. */ +#define MN_MDIV_N_VAL(x) (0x100 + (x) * 0x8 + 0x4) + +/** \brief Bits for setting M/N source clock. */ +#define MNDSS(x) DAI_INTEL_SSP_SET_BITS(21, 20, x) + +/** \brief Mask for clearing mclk and bclk source in MN_MDIVCTRL */ +#define MN_SOURCE_CLKS_MASK 0x3 + +#endif /* __INTEL_DAI_DRIVER_SSP_REGSV1_H__ */ diff --git a/drivers/dai/nxp/sai/sai.c b/drivers/dai/nxp/sai/sai.c index c61e6115a807b..8deb17e06a19b 100644 --- a/drivers/dai/nxp/sai/sai.c +++ b/drivers/dai/nxp/sai/sai.c @@ -696,7 +696,7 @@ static int sai_trigger_start(const struct device *dev, struct sai_data *data; const struct sai_config *cfg; uint32_t old_state; - int ret; + int ret, i; data = dev->data; cfg = dev->config; @@ -733,7 +733,12 @@ static int sai_trigger_start(const struct device *dev, SAI_TX_RX_ENABLE_DISABLE_IRQ(dir, data->regmap, kSAI_FIFOErrorInterruptEnable, true); - /* TODO: is there a need to write some words to the FIFO to avoid starvation? */ + /* avoid initial underrun by writing a frame's worth of 0s */ + if (dir == DAI_DIR_TX) { + for (i = 0; i < data->cfg.channels; i++) { + SAI_WriteData(UINT_TO_I2S(data->regmap), cfg->tx_dline, 0x0); + } + } /* TODO: for now, only DMA mode is supported */ SAI_TX_RX_DMA_ENABLE_DISABLE(dir, data->regmap, true); diff --git a/drivers/disk/flashdisk.c b/drivers/disk/flashdisk.c index 6336ad4dfd03e..6b71ea993c21e 100644 --- a/drivers/disk/flashdisk.c +++ b/drivers/disk/flashdisk.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2016 Intel Corporation. - * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * Copyright (c) 2022-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,6 +19,11 @@ #include LOG_MODULE_REGISTER(flashdisk, CONFIG_FLASHDISK_LOG_LEVEL); +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && \ + defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) +#define DISK_ERASE_RUNTIME_CHECK +#endif + struct flashdisk_data { struct disk_info info; struct k_mutex lock; @@ -32,11 +37,43 @@ struct flashdisk_data { off_t cached_addr; bool cache_valid; bool cache_dirty; + bool erase_required; }; #define GET_SIZE_TO_BOUNDARY(start, block_size) \ (block_size - (start & (block_size - 1))) +/* + * The default block size is used for devices not requiring erase. + * It defaults to 512 as this is most widely used sector size + * on storage devices. + */ +#define DEFAULT_BLOCK_SIZE 512 + +static inline bool flashdisk_with_erase(const struct flashdisk_data *ctx) +{ + ARG_UNUSED(ctx); +#if CONFIG_FLASH_HAS_EXPLICIT_ERASE +#if CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE + return ctx->erase_required; +#else + return true; +#endif +#endif + return false; +} + +static inline void flashdisk_probe_erase(struct flashdisk_data *ctx) +{ +#if defined(DISK_ERASE_RUNTIME_CHECK) + ctx->erase_required = + flash_params_get_erase_cap(flash_get_parameters(ctx->info.dev)) & + FLASH_ERASE_C_EXPLICIT; +#else + ARG_UNUSED(ctx); +#endif +} + static int disk_flash_access_status(struct disk_info *disk) { LOG_DBG("status : %s", disk->dev ? "okay" : "no media"); @@ -54,13 +91,20 @@ static int flashdisk_init_runtime(struct flashdisk_data *ctx, struct flash_pages_info page; off_t offset; - rc = flash_get_page_info_by_offs(ctx->info.dev, ctx->offset, &page); - if (rc < 0) { - LOG_ERR("Error %d while getting page info", rc); - return rc; + flashdisk_probe_erase(ctx); + + if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT) && flashdisk_with_erase(ctx)) { + rc = flash_get_page_info_by_offs(ctx->info.dev, ctx->offset, &page); + if (rc < 0) { + LOG_ERR("Error %d while getting page info", rc); + return rc; + } + + ctx->page_size = page.size; + } else { + ctx->page_size = DEFAULT_BLOCK_SIZE; } - ctx->page_size = page.size; LOG_INF("Initialize device %s", ctx->info.name); LOG_INF("offset %lx, sector size %zu, page size %zu, volume size %zu", (long)ctx->offset, ctx->sector_size, ctx->page_size, ctx->size); @@ -71,7 +115,7 @@ static int flashdisk_init_runtime(struct flashdisk_data *ctx, return 0; } - if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT)) { + if (IS_ENABLED(CONFIG_FLASHDISK_VERIFY_PAGE_LAYOUT) && flashdisk_with_erase(ctx)) { if (ctx->offset != page.start_offset) { LOG_ERR("Disk %s does not start at page boundary", ctx->info.name); @@ -213,8 +257,10 @@ static int flashdisk_cache_commit(struct flashdisk_data *ctx) return 0; } - if (flash_erase(ctx->info.dev, ctx->cached_addr, ctx->page_size) < 0) { - return -EIO; + if (flashdisk_with_erase(ctx)) { + if (flash_erase(ctx->info.dev, ctx->cached_addr, ctx->page_size) < 0) { + return -EIO; + } } /* write data to flash */ @@ -389,6 +435,7 @@ static int disk_flash_access_ioctl(struct disk_info *disk, uint8_t cmd, void *bu ctx = CONTAINER_OF(disk, struct flashdisk_data, info); switch (cmd) { + case DISK_IOCTL_CTRL_DEINIT: case DISK_IOCTL_CTRL_SYNC: k_mutex_lock(&ctx->lock, K_FOREVER); rc = flashdisk_cache_commit(ctx); @@ -405,6 +452,8 @@ static int disk_flash_access_ioctl(struct disk_info *disk, uint8_t cmd, void *bu *(uint32_t *)buff = ctx->page_size / ctx->sector_size; k_mutex_unlock(&ctx->lock); return 0; + case DISK_IOCTL_CTRL_INIT: + return disk_flash_access_init(disk); default: break; } diff --git a/drivers/disk/loopback_disk.c b/drivers/disk/loopback_disk.c index 50b7beeaabc40..c7f587b0c1955 100644 --- a/drivers/disk/loopback_disk.c +++ b/drivers/disk/loopback_disk.c @@ -22,10 +22,6 @@ static inline struct loopback_disk_access *get_ctx(struct disk_info *info) return CONTAINER_OF(info, struct loopback_disk_access, info); } -static int loopback_disk_access_init(struct disk_info *disk) -{ - return 0; -} static int loopback_disk_access_status(struct disk_info *disk) { return DISK_STATUS_OK; @@ -111,12 +107,19 @@ static int loopback_disk_access_ioctl(struct disk_info *disk, uint8_t cmd, void *(uint32_t *)buff = LOOPBACK_SECTOR_SIZE; return 0; } + case DISK_IOCTL_CTRL_DEINIT: case DISK_IOCTL_CTRL_SYNC: return fs_sync(&ctx->file); + case DISK_IOCTL_CTRL_INIT: + return 0; default: return -ENOTSUP; } } +static int loopback_disk_access_init(struct disk_info *disk) +{ + return loopback_disk_access_ioctl(disk, DISK_IOCTL_CTRL_INIT, NULL); +} static const struct disk_operations loopback_disk_operations = { .init = loopback_disk_access_init, diff --git a/drivers/disk/mmc_subsys.c b/drivers/disk/mmc_subsys.c index 455d56818d3c1..c595c0edb8a7e 100644 --- a/drivers/disk/mmc_subsys.c +++ b/drivers/disk/mmc_subsys.c @@ -38,11 +38,6 @@ static int disk_mmc_access_init(struct disk_info *disk) struct mmc_data *data = dev->data; int ret; - if (data->status == SD_OK) { - /* Called twice, don't reinit */ - return 0; - } - ret = sd_init(cfg->host_controller, &data->card); if (ret) { data->status = SD_ERROR; @@ -87,7 +82,21 @@ static int disk_mmc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buf) const struct device *dev = disk->dev; struct mmc_data *data = dev->data; - return mmc_ioctl(&data->card, cmd, buf); + switch (cmd) { + case DISK_IOCTL_CTRL_INIT: + return disk_mmc_access_init(disk); + case DISK_IOCTL_CTRL_DEINIT: + mmc_ioctl(&data->card, DISK_IOCTL_CTRL_SYNC, NULL); + /* sd_init() will toggle power to MMC, so we can just mark + * disk as uninitialized + */ + data->status = SD_UNINIT; + return 0; + default: + return mmc_ioctl(&data->card, cmd, buf); + } + + return 0; } static const struct disk_operations mmc_disk_ops = { diff --git a/drivers/disk/nvme/nvme_disk.c b/drivers/disk/nvme/nvme_disk.c index 9b46e0270d7ac..5d1e18f6b7264 100644 --- a/drivers/disk/nvme/nvme_disk.c +++ b/drivers/disk/nvme/nvme_disk.c @@ -11,11 +11,6 @@ LOG_MODULE_DECLARE(nvme, CONFIG_NVME_LOG_LEVEL); #include "nvme.h" -static int nvme_disk_init(struct disk_info *disk) -{ - return 0; -} - static int nvme_disk_status(struct disk_info *disk) { return 0; @@ -183,9 +178,13 @@ static int nvme_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) *(uint32_t *)buff = nvme_namespace_get_sector_size(ns); break; + case DISK_IOCTL_CTRL_DEINIT: case DISK_IOCTL_CTRL_SYNC: ret = nvme_disk_flush(ns); break; + case DISK_IOCTL_CTRL_INIT: + ret = 0; + break; default: ret = -EINVAL; } @@ -194,6 +193,11 @@ static int nvme_disk_ioctl(struct disk_info *disk, uint8_t cmd, void *buff) return ret; } +static int nvme_disk_init(struct disk_info *disk) +{ + return nvme_disk_ioctl(disk, DISK_IOCTL_CTRL_INIT, NULL); +} + static const struct disk_operations nvme_disk_ops = { .init = nvme_disk_init, .status = nvme_disk_status, diff --git a/drivers/disk/ramdisk.c b/drivers/disk/ramdisk.c index 1d1fcc46a0d2f..d4da37ea9d9d4 100644 --- a/drivers/disk/ramdisk.c +++ b/drivers/disk/ramdisk.c @@ -41,11 +41,6 @@ static int disk_ram_access_status(struct disk_info *disk) return DISK_STATUS_OK; } -static int disk_ram_access_init(struct disk_info *disk) -{ - return 0; -} - static int disk_ram_access_read(struct disk_info *disk, uint8_t *buff, uint32_t sector, uint32_t count) { @@ -98,6 +93,9 @@ static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff case DISK_IOCTL_GET_ERASE_BLOCK_SZ: *(uint32_t *)buff = 1U; break; + case DISK_IOCTL_CTRL_INIT: + case DISK_IOCTL_CTRL_DEINIT: + break; default: return -EINVAL; } @@ -105,6 +103,11 @@ static int disk_ram_access_ioctl(struct disk_info *disk, uint8_t cmd, void *buff return 0; } +static int disk_ram_access_init(struct disk_info *disk) +{ + return disk_ram_access_ioctl(disk, DISK_IOCTL_CTRL_INIT, NULL); +} + static int disk_ram_init(const struct device *dev) { struct disk_info *info = dev->data; diff --git a/drivers/disk/sdmmc_stm32.c b/drivers/disk/sdmmc_stm32.c index a9cda286e3af6..a344bb9d19235 100644 --- a/drivers/disk/sdmmc_stm32.c +++ b/drivers/disk/sdmmc_stm32.c @@ -265,10 +265,6 @@ static int stm32_sdmmc_access_init(struct disk_info *disk) struct stm32_sdmmc_priv *priv = dev->data; int err; - if (priv->status == DISK_STATUS_OK) { - return 0; - } - if (priv->status == DISK_STATUS_NOMEDIA) { return -ENODEV; } @@ -311,14 +307,18 @@ static int stm32_sdmmc_access_init(struct disk_info *disk) return 0; } -#if !defined(CONFIG_SDMMC_STM32_EMMC) -static void stm32_sdmmc_access_deinit(struct stm32_sdmmc_priv *priv) +static int stm32_sdmmc_access_deinit(struct stm32_sdmmc_priv *priv) { +#if defined(CONFIG_SDMMC_STM32_EMMC) + HAL_MMC_DeInit(&priv->hsd); +#else HAL_SD_DeInit(&priv->hsd); stm32_sdmmc_clock_disable(priv); -} #endif + priv->status = DISK_STATUS_UNINIT; + return 0; +} static int stm32_sdmmc_access_status(struct disk_info *disk) { @@ -485,6 +485,10 @@ static int stm32_sdmmc_access_ioctl(struct disk_info *disk, uint8_t cmd, case DISK_IOCTL_CTRL_SYNC: /* we use a blocking API, so nothing to do for sync */ break; + case DISK_IOCTL_CTRL_INIT: + return stm32_sdmmc_access_init(disk); + case DISK_IOCTL_CTRL_DEINIT: + return stm32_sdmmc_access_deinit(priv); default: return -EINVAL; } diff --git a/drivers/disk/sdmmc_subsys.c b/drivers/disk/sdmmc_subsys.c index 863755841dad3..e2511d1b1007a 100644 --- a/drivers/disk/sdmmc_subsys.c +++ b/drivers/disk/sdmmc_subsys.c @@ -37,11 +37,6 @@ static int disk_sdmmc_access_init(struct disk_info *disk) struct sdmmc_data *data = dev->data; int ret; - if (data->status == SD_OK) { - /* Called twice, don't reinit */ - return 0; - } - if (!sd_is_card_present(cfg->host_controller)) { return DISK_STATUS_NOMEDIA; } @@ -94,7 +89,21 @@ static int disk_sdmmc_access_ioctl(struct disk_info *disk, uint8_t cmd, void *bu const struct device *dev = disk->dev; struct sdmmc_data *data = dev->data; - return sdmmc_ioctl(&data->card, cmd, buf); + switch (cmd) { + case DISK_IOCTL_CTRL_INIT: + return disk_sdmmc_access_init(disk); + case DISK_IOCTL_CTRL_DEINIT: + sdmmc_ioctl(&data->card, DISK_IOCTL_CTRL_SYNC, NULL); + /* sd_init() will toggle power to SDMMC, so we can just mark + * disk as uninitialized + */ + data->status = SD_UNINIT; + return 0; + default: + return sdmmc_ioctl(&data->card, cmd, buf); + } + + return 0; } static const struct disk_operations sdmmc_disk_ops = { diff --git a/drivers/display/Kconfig.gc9x01x b/drivers/display/Kconfig.gc9x01x index aba24c445f1ae..650b0de919155 100644 --- a/drivers/display/Kconfig.gc9x01x +++ b/drivers/display/Kconfig.gc9x01x @@ -5,6 +5,6 @@ config GC9X01X bool "GC9X01X display driver" default y depends on DT_HAS_GALAXYCORE_GC9X01X_ENABLED - select SPI + select MIPI_DBI help Enable driver for GC9X01X display driver. diff --git a/drivers/display/Kconfig.ili9xxx b/drivers/display/Kconfig.ili9xxx index ccd6778d04a01..d1710d176e918 100644 --- a/drivers/display/Kconfig.ili9xxx +++ b/drivers/display/Kconfig.ili9xxx @@ -10,6 +10,15 @@ config ILI9XXX help Hidden configuration entry for all ILI9XXX drivers. +config ILI9XXX_READ + bool "Allow display_read API with ILI9XXX" + help + Support display_read API with ILI9XXX controllers. This API is opt-in, + because it adds code overhead and is not very performant due to + the requirement to bitshift data read from the ILI9XXX. Note the + API only supports RGB565 mode. + + config ILI9340 bool "ILI9340 display driver" default y diff --git a/drivers/display/Kconfig.mcux_elcdif b/drivers/display/Kconfig.mcux_elcdif index 43f90374380a7..44510e4bc3006 100644 --- a/drivers/display/Kconfig.mcux_elcdif +++ b/drivers/display/Kconfig.mcux_elcdif @@ -53,6 +53,18 @@ config MCUX_ELCDIF_PXP display_write is called with a framebuffer equal in size to the display. +config MCUX_ELCDIF_LP + bool "ELCDIF low power" + help + This option, when enabled, will enable CUR_FRAME_DONE_IRQ at the display + write function and disable it at the interruption handler for each new frame. + Disabling the interrupt when no new frame needs to be sent gives the CPU the + possibility to enter low-power mode, thus saving energy. + This option, when disabled, CUR_FRAME_DONE_IRQ will be enabled only + once at initialization. This option should be disabled when the application's + frame rate is close to the display's refresh rate to avoid introducing + additional latency caused by frequently enabling and disabling CUR_FRAME_DONE_IRQ. + if MCUX_ELCDIF_PXP choice MCUX_ELCDIF_PXP_ROTATE_DIRECTION @@ -60,8 +72,13 @@ choice MCUX_ELCDIF_PXP_ROTATE_DIRECTION prompt "Rotation angle of PXP" help Set rotation angle of PXP. The ELCDIF cannot detect the correct - rotation angle based on the call to display_write, so the user - should configure it here. + rotation angle based on the call to display_write, so the user should + configure it here. In order for PXP rotation to work, calls to + display_write MUST supply a framebuffer equal in size to screen width + and height (without rotation applied). Note that the width and + height settings of the screen in devicetree should not be modified + from their values in the default screen orientation when using this + functionality. config MCUX_ELCDIF_PXP_ROTATE_0 bool "Rotate display by 0 degrees" @@ -72,17 +89,19 @@ config MCUX_ELCDIF_PXP_ROTATE_0 config MCUX_ELCDIF_PXP_ROTATE_90 bool "Rotate display by 90 degrees" help - Rotate display clockwise by 90 degrees + Rotate display counter-clockwise by 90 degrees. + For LVGL, this corresponds to a rotation of 270 degrees config MCUX_ELCDIF_PXP_ROTATE_180 bool "Rotate display by 180 degrees" help - Rotate display clockwise by 180 degrees + Rotate display counter-clockwise by 180 degrees config MCUX_ELCDIF_PXP_ROTATE_270 bool "Rotate display by 270 degrees" help - Rotate display clockwise by 270 degrees + Rotate display counter-clockwise by 270 degrees + For LVGL, this corresponds to a rotation of 90 degrees endchoice diff --git a/drivers/display/Kconfig.ssd16xx b/drivers/display/Kconfig.ssd16xx index 1149ff03692e1..097351fec5ea1 100644 --- a/drivers/display/Kconfig.ssd16xx +++ b/drivers/display/Kconfig.ssd16xx @@ -12,6 +12,6 @@ config SSD16XX DT_HAS_SOLOMON_SSD1675A_ENABLED || \ DT_HAS_SOLOMON_SSD1680_ENABLED || \ DT_HAS_SOLOMON_SSD1681_ENABLED - select SPI + select MIPI_DBI help Enable driver for SSD16XX compatible controller. diff --git a/drivers/display/Kconfig.st7735r b/drivers/display/Kconfig.st7735r index 94153eca5859b..387665ace45bb 100644 --- a/drivers/display/Kconfig.st7735r +++ b/drivers/display/Kconfig.st7735r @@ -7,6 +7,6 @@ config ST7735R bool "ST7735R/ST7735S display driver" default y depends on DT_HAS_SITRONIX_ST7735R_ENABLED - select SPI + select MIPI_DBI help Enable driver for ST7735R/ST7735S display driver. diff --git a/drivers/display/Kconfig.st7789v b/drivers/display/Kconfig.st7789v index 5a452732779af..61d9c5497fd35 100644 --- a/drivers/display/Kconfig.st7789v +++ b/drivers/display/Kconfig.st7789v @@ -7,7 +7,7 @@ menuconfig ST7789V bool "ST7789V display driver" default y depends on DT_HAS_SITRONIX_ST7789V_ENABLED - select SPI + select MIPI_DBI help Enable driver for ST7789V display driver. diff --git a/drivers/display/Kconfig.uc81xx b/drivers/display/Kconfig.uc81xx index 75678d2f66310..123b5b3ed6fda 100644 --- a/drivers/display/Kconfig.uc81xx +++ b/drivers/display/Kconfig.uc81xx @@ -7,6 +7,6 @@ config UC81XX bool "UltraChip UC81xx compatible display controller driver" default y depends on DT_HAS_ULTRACHIP_UC8175_ENABLED || DT_HAS_ULTRACHIP_UC8176_ENABLED || DT_HAS_ULTRACHIP_UC8179_ENABLED - select SPI + select MIPI_DBI help Enable driver for UC81xx compatible controller. diff --git a/drivers/display/display_gc9x01x.c b/drivers/display/display_gc9x01x.c index 1d432d3f3556b..963e0dbe7a69a 100644 --- a/drivers/display/display_gc9x01x.c +++ b/drivers/display/display_gc9x01x.c @@ -10,8 +10,7 @@ #include #include -#include -#include +#include #include #include #include @@ -19,12 +18,6 @@ #include LOG_MODULE_REGISTER(display_gc9x01x, CONFIG_DISPLAY_LOG_LEVEL); -/* Command/data GPIO level for commands. */ -#define GC9X01X_GPIO_LEVEL_CMD 0U - -/* Command/data GPIO level for data. */ -#define GC9X01X_GPIO_LEVEL_DATA 1U - /* Maximum number of default init registers */ #define GC9X01X_NUM_DEFAULT_INIT_REGS 12U @@ -37,9 +30,8 @@ struct gc9x01x_data { /* Configuration data struct.*/ struct gc9x01x_config { - struct spi_dt_spec spi; - struct gpio_dt_spec cmd_data; - struct gpio_dt_spec reset; + const struct device *mipi_dev; + struct mipi_dbi_config dbi_config; uint8_t pixel_format; uint16_t orientation; uint16_t x_resolution; @@ -229,35 +221,9 @@ static int gc9x01x_transmit(const struct device *dev, uint8_t cmd, const void *t size_t tx_len) { const struct gc9x01x_config *config = dev->config; - int ret; - struct spi_buf tx_buf = {.buf = &cmd, .len = 1U}; - struct spi_buf_set tx_bufs = {.buffers = &tx_buf, .count = 1U}; - - ret = gpio_pin_set_dt(&config->cmd_data, GC9X01X_GPIO_LEVEL_CMD); - if (ret < 0) { - return ret; - } - ret = spi_write_dt(&config->spi, &tx_bufs); - if (ret < 0) { - return ret; - } - - /* send data (if any) */ - if (tx_data != NULL) { - tx_buf.buf = (void *)tx_data; - tx_buf.len = tx_len; - - ret = gpio_pin_set_dt(&config->cmd_data, GC9X01X_GPIO_LEVEL_DATA); - if (ret < 0) { - return ret; - } - ret = spi_write_dt(&config->spi, &tx_bufs); - if (ret < 0) { - return ret; - } - } - return 0; + return mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, tx_data, tx_len); } static int gc9x01x_regs_init(const struct device *dev) @@ -266,6 +232,10 @@ static int gc9x01x_regs_init(const struct device *dev) const struct gc9x01x_regs *regs = config->regs; int ret; + if (!device_is_ready(config->mipi_dev)) { + return -ENODEV; + } + /* Enable inter-command mode */ ret = gc9x01x_transmit(dev, GC9X01X_CMD_INREGEN1, NULL, 0); if (ret < 0) { @@ -371,17 +341,15 @@ static int gc9x01x_enter_sleep(const struct device *dev) static int gc9x01x_hw_reset(const struct device *dev) { const struct gc9x01x_config *config = dev->config; + int ret; - if (config->reset.port == NULL) { - return -ENODEV; + ret = mipi_dbi_reset(config->mipi_dev, 100); + if (ret < 0) { + return ret; } - - gpio_pin_set_dt(&config->reset, 1U); - k_msleep(100); - gpio_pin_set_dt(&config->reset, 0U); k_msleep(10); - return 0; + return ret; } static int gc9x01x_display_blanking_off(const struct device *dev) @@ -492,38 +460,8 @@ static int gc9x01x_configure(const struct device *dev) static int gc9x01x_init(const struct device *dev) { - const struct gc9x01x_config *config = dev->config; int ret; - if (!spi_is_ready_dt(&config->spi)) { - LOG_ERR("SPI device is not ready"); - return -ENODEV; - } - - if (!gpio_is_ready_dt(&config->cmd_data)) { - LOG_ERR("Command/Data GPIO device not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->cmd_data, GPIO_OUTPUT); - if (ret < 0) { - LOG_ERR("Could not configure command/data GPIO (%d)", ret); - return ret; - } - - if (config->reset.port != NULL) { - if (!device_is_ready(config->reset.port)) { - LOG_ERR("Reset GPIO device not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_INACTIVE); - if (ret < 0) { - LOG_ERR("Could not configure reset GPIO (%d)", ret); - return ret; - } - } - gc9x01x_hw_reset(dev); gc9x01x_display_blanking_on(dev); @@ -573,8 +511,7 @@ static int gc9x01x_write(const struct device *dev, const uint16_t x, const uint1 struct gc9x01x_data *data = dev->data; int ret; const uint8_t *write_data_start = (const uint8_t *)buf; - struct spi_buf tx_buf; - struct spi_buf_set tx_bufs; + struct display_buffer_descriptor mipi_desc; uint16_t write_cnt; uint16_t nbr_of_writes; uint16_t write_h; @@ -592,26 +529,30 @@ static int gc9x01x_write(const struct device *dev, const uint16_t x, const uint1 if (desc->pitch > desc->width) { write_h = 1U; nbr_of_writes = desc->height; + mipi_desc.height = 1; + mipi_desc.buf_size = desc->pitch * data->bytes_per_pixel; } else { write_h = desc->height; + mipi_desc.height = desc->height; + mipi_desc.buf_size = desc->width * data->bytes_per_pixel * write_h; nbr_of_writes = 1U; } - ret = gc9x01x_transmit(dev, GC9X01X_CMD_MEMWR, write_data_start, - desc->width * data->bytes_per_pixel * write_h); + mipi_desc.width = desc->width; + /* Per MIPI API, pitch must always match width */ + mipi_desc.pitch = desc->width; + + ret = gc9x01x_transmit(dev, GC9X01X_CMD_MEMWR, NULL, 0); if (ret < 0) { return ret; } - tx_bufs.buffers = &tx_buf; - tx_bufs.count = 1U; - - write_data_start += desc->pitch * data->bytes_per_pixel; - for (write_cnt = 1U; write_cnt < nbr_of_writes; ++write_cnt) { - tx_buf.buf = (void *)write_data_start; - tx_buf.len = desc->width * data->bytes_per_pixel * write_h; - - ret = spi_write_dt(&config->spi, &tx_bufs); + for (write_cnt = 0U; write_cnt < nbr_of_writes; ++write_cnt) { + ret = mipi_dbi_write_display(config->mipi_dev, + &config->dbi_config, + write_data_start, + &mipi_desc, + data->pixel_format); if (ret < 0) { return ret; } @@ -679,9 +620,13 @@ static const struct display_driver_api gc9x01x_api = { #define GC9X01X_INIT(inst) \ GC9X01X_REGS_INIT(inst); \ static const struct gc9x01x_config gc9x01x_config_##inst = { \ - .spi = SPI_DT_SPEC_INST_GET(inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8), 0), \ - .cmd_data = GPIO_DT_SPEC_INST_GET(inst, cmd_data_gpios), \ - .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), \ + .mipi_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .dbi_config = { \ + .mode = MIPI_DBI_MODE_SPI_4WIRE, \ + .config = MIPI_DBI_SPI_CONFIG_DT_INST(inst, \ + SPI_OP_MODE_MASTER | \ + SPI_WORD_SET(8), 0), \ + }, \ .pixel_format = DT_INST_PROP(inst, pixel_format), \ .orientation = DT_INST_ENUM_IDX(inst, orientation), \ .x_resolution = DT_INST_PROP(inst, width), \ diff --git a/drivers/display/display_ili9xxx.c b/drivers/display/display_ili9xxx.c index c3a173078fafb..fd3cd4e7b9eb1 100644 --- a/drivers/display/display_ili9xxx.c +++ b/drivers/display/display_ili9xxx.c @@ -21,6 +21,49 @@ struct ili9xxx_data { enum display_orientation orientation; }; +#ifdef CONFIG_ILI9XXX_READ + +/* We set this LUT directly when reads are enabled, + * so that we can be sure the bitshift to convert GRAM data back + * to RGB565 will result in correct data + */ +const uint8_t ili9xxx_rgb_lut[] = { + 0, 2, 4, 6, + 8, 10, 12, 14, + 16, 18, 20, 22, + 24, 26, 28, 30, + 32, 34, 36, 38, + 40, 42, 44, 46, + 48, 50, 52, 54, + 56, 58, 60, 62, + 0, 1, 2, 3, + 4, 5, 6, 7, + 8, 9, 10, 11, + 12, 13, 14, 15, + 16, 17, 18, 19, + 20, 21, 22, 23, + 24, 25, 26, 27, + 28, 29, 30, 31, + 32, 33, 34, 35, + 36, 37, 38, 39, + 40, 41, 42, 43, + 44, 45, 46, 47, + 48, 49, 50, 51, + 52, 53, 54, 55, + 56, 57, 58, 59, + 60, 61, 62, 63, + 0, 2, 4, 6, + 8, 10, 12, 14, + 16, 18, 20, 22, + 24, 26, 28, 30, + 32, 34, 36, 38, + 40, 42, 44, 46, + 48, 50, 52, 54, + 56, 58, 60, 62 +}; + +#endif + int ili9xxx_transmit(const struct device *dev, uint8_t cmd, const void *tx_data, size_t tx_len) { @@ -142,6 +185,93 @@ static int ili9xxx_write(const struct device *dev, const uint16_t x, return 0; } +#ifdef CONFIG_ILI9XXX_READ + +static int ili9xxx_read(const struct device *dev, const uint16_t x, + const uint16_t y, + const struct display_buffer_descriptor *desc, void *buf) +{ + const struct ili9xxx_config *config = dev->config; + struct ili9xxx_data *data = dev->data; + struct display_buffer_descriptor mipi_desc; + int r; + uint32_t gram_data, nbr_of_reads; + uint16_t *read_data_start = (uint16_t *)buf; + + if (data->pixel_format != PIXEL_FORMAT_RGB_565) { + /* Only RGB565 can be supported, see note below */ + return -ENOTSUP; + } + + __ASSERT(desc->width <= desc->pitch, "Pitch is smaller than width"); + __ASSERT((desc->pitch * data->bytes_per_pixel * desc->height) <= + desc->buf_size, + "Output buffer to small"); + + LOG_DBG("Reading %dx%d (w,h) @ %dx%d (x,y)", desc->width, desc->height, + x, y); + + r = ili9xxx_set_mem_area(dev, x, y, desc->width, desc->height); + if (r < 0) { + return r; + } + + /* + * ILI9XXX stores all pixel data in graphics ram (GRAM) as 18 bit + * values. When using RGB565 pixel format, pixels are converted to + * 18 bit values via a lookup table. When using RGB888 format, the + * lower 2 bits of each pixel are simply dropped. When reading pixels, + * the response format will always look like so: + * | R[5:0] | x | x | G[5:0] | x | x | B[5:0] | x | x | + * Where x represents "don't care". The internal format of the + * ILI9XXX graphics RAM results in the following restrictions: + * - RGB888 mode can't be supported. + * - we can only read one pixel at once (since we need to do + * byte manipulation on the output) + */ + + /* Setup MIPI descriptor to read 3 bytes (one pixel in GRAM) */ + mipi_desc.width = 1; + mipi_desc.height = 1; + /* Per MIPI API, pitch must always match width */ + mipi_desc.pitch = 1; + + nbr_of_reads = desc->width * desc->height; + + /* Initial read command should consist of RAMRD command, plus + * 8 dummy clock cycles + */ + uint8_t cmd[] = {ILI9XXX_RAMRD, 0xFF}; + + for (uint32_t read_cnt = 0; read_cnt < nbr_of_reads; read_cnt++) { + r = mipi_dbi_command_read(config->mipi_dev, + &config->dbi_config, + cmd, sizeof(cmd), + (uint8_t *)&gram_data, 3); + if (r < 0) { + return r; + } + + /* Bitshift the graphics RAM data to RGB565. + * For more details on the formatting of this data, + * see "Read data through 4-line SPI mode" diagram + * on page 64 of datasheet. + */ + read_data_start[read_cnt] = + ((gram_data & 0xF80000) >> 11) | /* Blue */ + ((gram_data & 0x1C00) << 3) | /* Green */ + ((gram_data & 0xE000) >> 13) | /* Green */ + (gram_data & 0xF8); /* Red */ + + /* After first read, we should use read memory continue command */ + cmd[0] = ILI9XXX_RAMRD_CONT; + } + + return 0; +} + +#endif + static int ili9xxx_display_blanking_off(const struct device *dev) { LOG_DBG("Turning display blanking off"); @@ -321,6 +451,11 @@ static int ili9xxx_init(const struct device *dev) return r; } +#ifdef CONFIG_ILI9XXX_READ + /* Set RGB LUT table to enable display read API */ + ili9xxx_transmit(dev, ILI9XXX_RGBSET, ili9xxx_rgb_lut, sizeof(ili9xxx_rgb_lut)); +#endif + k_sleep(K_MSEC(ILI9XXX_RESET_WAIT_TIME)); ili9xxx_display_blanking_on(dev); @@ -344,6 +479,9 @@ static const struct display_driver_api ili9xxx_api = { .blanking_on = ili9xxx_display_blanking_on, .blanking_off = ili9xxx_display_blanking_off, .write = ili9xxx_write, +#ifdef CONFIG_ILI9XXX_READ + .read = ili9xxx_read, +#endif .get_capabilities = ili9xxx_get_capabilities, .set_pixel_format = ili9xxx_set_pixel_format, .set_orientation = ili9xxx_set_orientation, diff --git a/drivers/display/display_ili9xxx.h b/drivers/display/display_ili9xxx.h index ddf8254224ebc..861b26d436099 100644 --- a/drivers/display/display_ili9xxx.h +++ b/drivers/display/display_ili9xxx.h @@ -22,8 +22,11 @@ #define ILI9XXX_CASET 0x2a #define ILI9XXX_PASET 0x2b #define ILI9XXX_RAMWR 0x2c +#define ILI9XXX_RGBSET 0x2d +#define ILI9XXX_RAMRD 0x2e #define ILI9XXX_MADCTL 0x36 #define ILI9XXX_PIXSET 0x3A +#define ILI9XXX_RAMRD_CONT 0x3e /* MADCTL register fields. */ #define ILI9XXX_MADCTL_MY BIT(7U) diff --git a/drivers/display/display_mcux_elcdif.c b/drivers/display/display_mcux_elcdif.c index e4b45f89d40dd..9c5785342d956 100644 --- a/drivers/display/display_mcux_elcdif.c +++ b/drivers/display/display_mcux_elcdif.c @@ -190,6 +190,9 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u return ret; } k_sem_take(&dev_data->pxp_done, K_FOREVER); + } else { + LOG_WRN("PXP rotation will not work correctly unless a full sized " + "framebuffer is provided"); } #endif /* CONFIG_MCUX_ELCDIF_PXP */ @@ -200,8 +203,10 @@ static int mcux_elcdif_write(const struct device *dev, const uint16_t x, const u /* Update index of active framebuffer */ dev_data->next_idx = (dev_data->next_idx + 1) % CONFIG_MCUX_ELCDIF_FB_NUM; #endif - /* Enable frame buffer completion interrupt */ - ELCDIF_EnableInterrupts(config->base, kELCDIF_CurFrameDoneInterruptEnable); + + if (IS_ENABLED(CONFIG_MCUX_ELCDIF_LP)) { + ELCDIF_EnableInterrupts(config->base, kELCDIF_CurFrameDoneInterruptEnable); + } /* Wait for frame send to complete */ k_sem_take(&dev_data->sem, K_FOREVER); return ret; @@ -294,10 +299,11 @@ static void mcux_elcdif_isr(const struct device *dev) status = ELCDIF_GetInterruptStatus(config->base); ELCDIF_ClearInterruptStatus(config->base, status); if (config->base->CUR_BUF == ((uint32_t)dev_data->active_fb)) { - /* Disable frame completion interrupt, post to - * sem to notify that frame send is complete. - */ - ELCDIF_DisableInterrupts(config->base, kELCDIF_CurFrameDoneInterruptEnable); + if (IS_ENABLED(CONFIG_MCUX_ELCDIF_LP)) { + /* Disable frame completion interrupt if Low power mode is activated*/ + ELCDIF_DisableInterrupts(config->base, kELCDIF_CurFrameDoneInterruptEnable); + } + /* Post to sem to notify that frame display is complete.*/ k_sem_give(&dev_data->sem); } } @@ -335,6 +341,9 @@ static int mcux_elcdif_init(const struct device *dev) dev_data->active_fb = dev_data->fb[0]; ELCDIF_RgbModeInit(config->base, &dev_data->rgb_mode); + if (!IS_ENABLED(CONFIG_MCUX_ELCDIF_LP)) { + ELCDIF_EnableInterrupts(config->base, kELCDIF_CurFrameDoneInterruptEnable); + } ELCDIF_RgbModeStart(config->base); return 0; diff --git a/drivers/display/display_renesas_lcdc.c b/drivers/display/display_renesas_lcdc.c index c09b48ac003a3..a5d3d412a1aff 100644 --- a/drivers/display/display_renesas_lcdc.c +++ b/drivers/display/display_renesas_lcdc.c @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include #include LOG_MODULE_REGISTER(smartbond_display, CONFIG_DISPLAY_LOG_LEVEL); @@ -72,6 +75,9 @@ struct display_smartbond_data { struct k_sem dma_sync_sem; /* Granted DMA channel used for memory transfers */ int dma_channel; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + ATOMIC_DEFINE(pm_policy_state_flag, 1); +#endif }; struct display_smartbond_config { @@ -93,6 +99,29 @@ struct display_smartbond_config { enum display_pixel_format pixel_format; }; +static inline void lcdc_smartbond_pm_policy_state_lock_get(struct display_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) { + /* + * Prevent the SoC from etering the normal sleep state as PDC does not support + * waking up the application core following LCDC events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void lcdc_smartbond_pm_policy_state_lock_put(struct display_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) { + /* Allow the SoC to enter the nornmal sleep state once LCDC is inactive */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + /* Display pixel to layer color format translation */ static uint8_t lcdc_smartbond_pixel_to_lcm(enum display_pixel_format pixel_format) { @@ -180,6 +209,44 @@ static void smartbond_display_isr(const void *arg) k_sem_give(&data->sync_sem); } +static void display_smartbond_dma_cb(const struct device *dma, void *arg, + uint32_t id, int status) +{ + struct display_smartbond_data *data = arg; + + if (status < 0) { + LOG_WRN("DMA transfer did not complete"); + } + + k_sem_give(&data->dma_sync_sem); +} + +static int display_smartbond_dma_config(const struct device *dev) +{ + struct display_smartbond_data *data = dev->data; + + data->dma = DEVICE_DT_GET(DT_NODELABEL(dma)); + if (!device_is_ready(data->dma)) { + LOG_ERR("DMA device is not ready"); + return -ENODEV; + } + + data->dma_cfg.channel_direction = MEMORY_TO_MEMORY; + data->dma_cfg.user_data = data; + data->dma_cfg.dma_callback = display_smartbond_dma_cb; + data->dma_cfg.block_count = 1; + data->dma_cfg.head_block = &data->dma_block_cfg; + + /* Request an arbitrary DMA channel */ + data->dma_channel = dma_request_channel(data->dma, NULL); + if (data->dma_channel < 0) { + LOG_ERR("Could not acquire a DMA channel"); + return -EIO; + } + + return 0; +} + static int display_smartbond_resume(const struct device *dev) { const struct display_smartbond_config *config = dev->config; @@ -207,47 +274,43 @@ static int display_smartbond_resume(const struct device *dev) } #endif + ret = display_smartbond_dma_config(dev); + if (ret < 0) { + return ret; + } + return display_smartbond_configure(dev); } -static void display_smartbond_dma_cb(const struct device *dma, void *arg, - uint32_t id, int status) +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static void display_smartbond_dma_deconfig(const struct device *dev) { - struct display_smartbond_data *data = arg; + struct display_smartbond_data *data = dev->data; - if (status < 0) { - LOG_WRN("DMA transfer did not complete"); - } + __ASSERT(data->dma, "DMA should be already initialized"); - k_sem_give(&data->dma_sync_sem); + dma_release_channel(data->dma, data->dma_channel); } -static int display_smartbond_dma_config(const struct device *dev) +static int display_smartbond_suspend(const struct device *dev) { - struct display_smartbond_data *data = dev->data; + const struct display_smartbond_config *config = dev->config; + int ret; - data->dma = DEVICE_DT_GET(DT_NODELABEL(dma)); - if (!device_is_ready(data->dma)) { - LOG_ERR("DMA device is not ready"); - return -ENODEV; + /* Select sleep state; it's OK if settings fails for any reason */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0) { + LOG_WRN("Could not apply DISPLAY pins' sleep state"); } - data->dma_cfg.channel_direction = MEMORY_TO_MEMORY; - data->dma_cfg.user_data = data; - data->dma_cfg.dma_callback = display_smartbond_dma_cb; - data->dma_cfg.block_count = 1; - data->dma_cfg.head_block = &data->dma_block_cfg; + /* Disable host controller to minimize power consumption */ + da1469x_lcdc_set_status(false, false, 0); - /* Request an arbitrary DMA channel */ - data->dma_channel = dma_request_channel(data->dma, NULL); - if (data->dma_channel < 0) { - LOG_ERR("Could not acquire a DMA channel"); - return -EIO; - } + display_smartbond_dma_deconfig(dev); return 0; } - +#endif static int display_smartbond_init(const struct device *dev) { @@ -271,33 +334,24 @@ static int display_smartbond_init(const struct device *dev) } } - ret = display_smartbond_resume(dev); - if (ret < 0) { - return ret; - } - - ret = display_smartbond_dma_config(dev); - if (ret < 0) { - return ret; - } - IRQ_CONNECT(SMARTBOND_IRQN, SMARTBOND_IRQ_PRIO, smartbond_display_isr, DEVICE_DT_INST_GET(0), 0); -#if CONFIG_PM - /* - * When in continues mode, the display device should always be refreshed - * and so the controller is not allowed to be turned off. The latter, is - * powered by PD_SYS which is turned off when the SoC enters the extended - * sleep state. By acquiring PD_SYS, the deep sleep state is prevented - * and the system enters the low-power state (i.e. ARM WFI) when possible. - * - * XXX CONFIG_PM_DEVICE_RUNTIME is no supported yet! - */ - da1469x_pd_acquire_noconf(MCU_PD_DOMAIN_SYS); +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); +#else + /* Resume if either PM is not used at all or if PM without runtime is used. */ + ret = display_smartbond_resume(dev); + if (ret == 0) { + /* Display port should be enabled at this moment and so sleep is not allowed. */ + lcdc_smartbond_pm_policy_state_lock_get(data); + } #endif - return 0; + return ret; } static int display_smartbond_blanking_on(const struct device *dev) @@ -323,6 +377,12 @@ static int display_smartbond_blanking_on(const struct device *dev) } } + /* + * At this moment the display panel should be turned off and so the device + * can enter the suspend state. + */ + lcdc_smartbond_pm_policy_state_lock_put(data); + k_sem_give(&data->device_sem); return ret; @@ -351,6 +411,12 @@ static int display_smartbond_blanking_off(const struct device *dev) */ LCDC->LCDC_MODE_REG &= ~LCDC_LCDC_MODE_REG_LCDC_FORCE_BLANK_Msk; + /* + * At this moment the display should be turned on and so the device + * cannot enter the suspend state. + */ + lcdc_smartbond_pm_policy_state_lock_get(data); + k_sem_give(&data->device_sem); return ret; @@ -515,8 +581,32 @@ static int display_smartbond_write(const struct device *dev, return 0; } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static int display_smartbond_pm_action(const struct device *dev, enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* A non-zero value should not affect sleep */ + (void)display_smartbond_suspend(dev); + break; + case PM_DEVICE_ACTION_RESUME: + /* + * The resume error code should not be taken into consideration + * by the PM subsystem + */ + ret = display_smartbond_resume(dev); + break; + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif -static struct display_driver_api display_smartbond_driver_api = { +static const struct display_driver_api display_smartbond_driver_api = { .write = display_smartbond_write, .read = display_smartbond_read, .get_framebuffer = display_smartbond_get_framebuffer, @@ -527,6 +617,7 @@ static struct display_driver_api display_smartbond_driver_api = { #define SMARTBOND_DISPLAY_INIT(inst) \ PINCTRL_DT_INST_DEFINE(inst); \ + PM_DEVICE_DT_INST_DEFINE(inst, display_smartbond_pm_action); \ \ __aligned(4) static uint8_t buffer_ ## inst[(((DT_INST_PROP(inst, width) * \ DISPLAY_SMARTBOND_PIXEL_SIZE(inst)) + 0x3) & ~0x3) * \ @@ -572,7 +663,7 @@ static struct display_driver_api display_smartbond_driver_api = { }; \ \ \ - DEVICE_DT_INST_DEFINE(inst, display_smartbond_init, NULL, \ + DEVICE_DT_INST_DEFINE(inst, display_smartbond_init, PM_DEVICE_DT_INST_GET(inst), \ &display_smartbond_data_## inst, \ &display_smartbond_config_## inst, \ POST_KERNEL, \ diff --git a/drivers/display/display_st7735r.c b/drivers/display/display_st7735r.c index 88c282d89f88e..1626cb5204b23 100644 --- a/drivers/display/display_st7735r.c +++ b/drivers/display/display_st7735r.c @@ -5,6 +5,7 @@ * Copyright (c) 2019 PHYTEC Messtechnik GmbH * Copyright (c) 2020 Endian Technologies AB * Copyright (c) 2020 Kim Bøndergaard + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,7 +15,7 @@ #include "display_st7735r.h" #include -#include +#include #include #include #include @@ -23,15 +24,14 @@ #include LOG_MODULE_REGISTER(display_st7735r, CONFIG_DISPLAY_LOG_LEVEL); -#define ST7735R_RESET_TIME K_MSEC(1) +#define ST7735R_RESET_TIME 1 #define ST7735R_EXIT_SLEEP_TIME K_MSEC(120) #define ST7735R_PIXEL_SIZE 2u struct st7735r_config { - struct spi_dt_spec bus; - struct gpio_dt_spec cmd_data; - struct gpio_dt_spec reset; + const struct device *mipi_dev; + const struct mipi_dbi_config dbi_config; uint16_t height; uint16_t width; uint8_t madctl; @@ -68,38 +68,13 @@ static void st7735r_set_lcd_margins(const struct device *dev, data->y_offset = y_offset; } -static void st7735r_set_cmd(const struct device *dev, int is_cmd) -{ - const struct st7735r_config *config = dev->config; - - gpio_pin_set_dt(&config->cmd_data, is_cmd); -} - static int st7735r_transmit_hold(const struct device *dev, uint8_t cmd, const uint8_t *tx_data, size_t tx_count) { const struct st7735r_config *config = dev->config; - struct spi_buf tx_buf = { .buf = &cmd, .len = 1 }; - struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 }; - int ret; - - st7735r_set_cmd(dev, 1); - ret = spi_write_dt(&config->bus, &tx_bufs); - if (ret < 0) { - return ret; - } - if (tx_data != NULL) { - tx_buf.buf = (void *)tx_data; - tx_buf.len = tx_count; - st7735r_set_cmd(dev, 0); - ret = spi_write_dt(&config->bus, &tx_bufs); - if (ret < 0) { - return ret; - } - } - - return 0; + return mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, tx_data, tx_count); } static int st7735r_transmit(const struct device *dev, uint8_t cmd, @@ -109,7 +84,7 @@ static int st7735r_transmit(const struct device *dev, uint8_t cmd, int ret; ret = st7735r_transmit_hold(dev, cmd, tx_data, tx_count); - spi_release_dt(&config->bus); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return ret; } @@ -133,11 +108,8 @@ static int st7735r_reset_display(const struct device *dev) int ret; LOG_DBG("Resetting display"); - if (config->reset.port != NULL) { - gpio_pin_set_dt(&config->reset, 1); - k_sleep(ST7735R_RESET_TIME); - gpio_pin_set_dt(&config->reset, 0); - } else { + ret = mipi_dbi_reset(config->mipi_dev, ST7735R_RESET_TIME); + if (ret != 0) { ret = st7735r_transmit(dev, ST7735R_CMD_SW_RESET, NULL, 0); if (ret < 0) { return ret; @@ -204,12 +176,12 @@ static int st7735r_write(const struct device *dev, { const struct st7735r_config *config = dev->config; const uint8_t *write_data_start = (uint8_t *) buf; - struct spi_buf tx_buf; - struct spi_buf_set tx_bufs; uint16_t write_cnt; uint16_t nbr_of_writes; uint16_t write_h; int ret; + enum display_pixel_format fmt; + struct display_buffer_descriptor mipi_desc; __ASSERT(desc->width <= desc->pitch, "Pitch is smaller than width"); __ASSERT((desc->pitch * ST7735R_PIXEL_SIZE * desc->height) @@ -225,9 +197,24 @@ static int st7735r_write(const struct device *dev, if (desc->pitch > desc->width) { write_h = 1U; nbr_of_writes = desc->height; + mipi_desc.height = 1; + mipi_desc.buf_size = desc->pitch * ST7735R_PIXEL_SIZE; } else { write_h = desc->height; nbr_of_writes = 1U; + mipi_desc.height = desc->height; + mipi_desc.buf_size = desc->width * ST7735R_PIXEL_SIZE * write_h; + } + + mipi_desc.width = desc->width; + /* Per MIPI API, pitch must always match width */ + mipi_desc.pitch = desc->width; + + + if (!(config->madctl & ST7735R_MADCTL_BGR) != !config->rgb_is_inverted) { + fmt = PIXEL_FORMAT_BGR_565; + } else { + fmt = PIXEL_FORMAT_RGB_565; } ret = st7735r_transmit_hold(dev, ST7735R_CMD_RAMWR, @@ -237,14 +224,13 @@ static int st7735r_write(const struct device *dev, goto out; } - tx_bufs.buffers = &tx_buf; - tx_bufs.count = 1; - write_data_start += (desc->pitch * ST7735R_PIXEL_SIZE); for (write_cnt = 1U; write_cnt < nbr_of_writes; ++write_cnt) { - tx_buf.buf = (void *)write_data_start; - tx_buf.len = desc->width * ST7735R_PIXEL_SIZE * write_h; - ret = spi_write_dt(&config->bus, &tx_bufs); + ret = mipi_dbi_write_display(config->mipi_dev, + &config->dbi_config, + write_data_start, + &mipi_desc, + fmt); if (ret < 0) { goto out; } @@ -254,7 +240,7 @@ static int st7735r_write(const struct device *dev, ret = 0; out: - spi_release_dt(&config->bus); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return ret; } @@ -445,36 +431,11 @@ static int st7735r_init(const struct device *dev) const struct st7735r_config *config = dev->config; int ret; - if (!spi_is_ready_dt(&config->bus)) { - LOG_ERR("SPI bus %s not ready", config->bus.bus->name); - return -ENODEV; - } - - if (config->reset.port != NULL) { - if (!gpio_is_ready_dt(&config->reset)) { - LOG_ERR("Reset GPIO port for display not ready"); - return -ENODEV; - } - - ret = gpio_pin_configure_dt(&config->reset, - GPIO_OUTPUT_INACTIVE); - if (ret) { - LOG_ERR("Couldn't configure reset pin"); - return ret; - } - } - - if (!gpio_is_ready_dt(&config->cmd_data)) { - LOG_ERR("cmd/DATA GPIO port not ready"); + if (!device_is_ready(config->mipi_dev)) { + LOG_ERR("MIPI bus %s not ready", config->mipi_dev->name); return -ENODEV; } - ret = gpio_pin_configure_dt(&config->cmd_data, GPIO_OUTPUT); - if (ret) { - LOG_ERR("Couldn't configure cmd/DATA pin"); - return ret; - } - ret = st7735r_reset_display(dev); if (ret < 0) { LOG_ERR("Couldn't reset display"); @@ -530,11 +491,13 @@ static const struct display_driver_api st7735r_api = { #define ST7735R_INIT(inst) \ const static struct st7735r_config st7735r_config_ ## inst = { \ - .bus = SPI_DT_SPEC_INST_GET( \ - inst, SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ - SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \ - .cmd_data = GPIO_DT_SPEC_INST_GET(inst, cmd_data_gpios), \ - .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}), \ + .mipi_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .dbi_config = MIPI_DBI_CONFIG_DT_INST(inst, \ + SPI_OP_MODE_MASTER | \ + ((DT_INST_PROP(inst, mipi_mode) == \ + MIPI_DBI_MODE_SPI_4WIRE) ? SPI_WORD_SET(8) : \ + SPI_WORD_SET(9)) | \ + SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \ .width = DT_INST_PROP(inst, width), \ .height = DT_INST_PROP(inst, height), \ .madctl = DT_INST_PROP(inst, madctl), \ diff --git a/drivers/display/display_st7789v.c b/drivers/display/display_st7789v.c index 72ae4eb043631..69e4e2cdb021b 100644 --- a/drivers/display/display_st7789v.c +++ b/drivers/display/display_st7789v.c @@ -14,8 +14,7 @@ #include "display_st7789v.h" #include -#include -#include +#include #include #include #include @@ -25,9 +24,8 @@ LOG_MODULE_REGISTER(display_st7789v); struct st7789v_config { - struct spi_dt_spec bus; - struct gpio_dt_spec cmd_data_gpio; - struct gpio_dt_spec reset_gpio; + const struct device *mipi_dbi; + const struct mipi_dbi_config dbi_config; uint8_t vcom; uint8_t gctrl; bool vdv_vrh_enable; @@ -73,38 +71,9 @@ static void st7789v_transmit(const struct device *dev, uint8_t cmd, uint8_t *tx_data, size_t tx_count) { const struct st7789v_config *config = dev->config; - uint16_t data = cmd; - - struct spi_buf tx_buf = { .buf = &cmd, .len = 1 }; - struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 }; - - if (config->cmd_data_gpio.port != NULL) { - if (cmd != ST7789V_CMD_NONE) { - gpio_pin_set_dt(&config->cmd_data_gpio, 1); - spi_write_dt(&config->bus, &tx_bufs); - } - - if (tx_data != NULL) { - tx_buf.buf = tx_data; - tx_buf.len = tx_count; - gpio_pin_set_dt(&config->cmd_data_gpio, 0); - spi_write_dt(&config->bus, &tx_bufs); - } - } else { - tx_buf.buf = &data; - tx_buf.len = 2; - - if (cmd != ST7789V_CMD_NONE) { - spi_write_dt(&config->bus, &tx_bufs); - } - - if (tx_data != NULL) { - for (size_t index = 0; index < tx_count; ++index) { - data = 0x0100 | tx_data[index]; - spi_write_dt(&config->bus, &tx_bufs); - } - } - } + + mipi_dbi_command_write(config->mipi_dbi, &config->dbi_config, cmd, + tx_data, tx_count); } static void st7789v_exit_sleep(const struct device *dev) @@ -115,18 +84,19 @@ static void st7789v_exit_sleep(const struct device *dev) static void st7789v_reset_display(const struct device *dev) { + const struct st7789v_config *config = dev->config; + int ret; + LOG_DBG("Resetting display"); - const struct st7789v_config *config = dev->config; - if (config->reset_gpio.port != NULL) { - k_sleep(K_MSEC(1)); - gpio_pin_set_dt(&config->reset_gpio, 1); - k_sleep(K_MSEC(6)); - gpio_pin_set_dt(&config->reset_gpio, 0); - k_sleep(K_MSEC(20)); - } else { + k_sleep(K_MSEC(1)); + ret = mipi_dbi_reset(config->mipi_dbi, 6); + if (ret == -ENOTSUP) { + /* Send software reset command */ st7789v_transmit(dev, ST7789V_CMD_SW_RESET, NULL, 0); k_sleep(K_MSEC(5)); + } else { + k_sleep(K_MSEC(20)); } } @@ -166,9 +136,12 @@ static int st7789v_write(const struct device *dev, const struct display_buffer_descriptor *desc, const void *buf) { + const struct st7789v_config *config = dev->config; + struct display_buffer_descriptor mipi_desc; const uint8_t *write_data_start = (uint8_t *) buf; uint16_t nbr_of_writes; uint16_t write_h; + enum display_pixel_format pixfmt; __ASSERT(desc->width <= desc->pitch, "Pitch is smaller then width"); __ASSERT((desc->pitch * ST7789V_PIXEL_SIZE * desc->height) <= desc->buf_size, @@ -181,15 +154,31 @@ static int st7789v_write(const struct device *dev, if (desc->pitch > desc->width) { write_h = 1U; nbr_of_writes = desc->height; + mipi_desc.height = 1; + mipi_desc.buf_size = desc->pitch * ST7789V_PIXEL_SIZE; } else { write_h = desc->height; nbr_of_writes = 1U; + mipi_desc.height = desc->height; + mipi_desc.buf_size = desc->width * write_h * ST7789V_PIXEL_SIZE; } + if (IS_ENABLED(CONFIG_ST7789V_RGB565)) { + pixfmt = PIXEL_FORMAT_RGB_565; + } else { + pixfmt = PIXEL_FORMAT_RGB_888; + } + + mipi_desc.width = desc->width; + /* Per MIPI API, pitch must always match width */ + mipi_desc.pitch = desc->width; + + /* Send RAMWR command */ + st7789v_transmit(dev, ST7789V_CMD_RAMWR, NULL, 0); for (uint16_t write_cnt = 0U; write_cnt < nbr_of_writes; ++write_cnt) { - st7789v_transmit(dev, write_cnt == 0U ? ST7789V_CMD_RAMWR : ST7789V_CMD_NONE, - (void *) write_data_start, - desc->width * ST7789V_PIXEL_SIZE * write_h); + mipi_dbi_write_display(config->mipi_dbi, &config->dbi_config, + write_data_start, &mipi_desc, pixfmt); + write_data_start += (desc->pitch * ST7789V_PIXEL_SIZE); } @@ -326,35 +315,11 @@ static int st7789v_init(const struct device *dev) { const struct st7789v_config *config = dev->config; - if (!spi_is_ready_dt(&config->bus)) { - LOG_ERR("SPI device not ready"); + if (!device_is_ready(config->mipi_dbi)) { + LOG_ERR("MIPI DBI device not ready"); return -ENODEV; } - if (config->reset_gpio.port != NULL) { - if (!gpio_is_ready_dt(&config->reset_gpio)) { - LOG_ERR("Reset GPIO device not ready"); - return -ENODEV; - } - - if (gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE)) { - LOG_ERR("Couldn't configure reset pin"); - return -EIO; - } - } - - if (config->cmd_data_gpio.port != NULL) { - if (!gpio_is_ready_dt(&config->cmd_data_gpio)) { - LOG_ERR("CMD/DATA GPIO device not ready"); - return -ENODEV; - } - - if (gpio_pin_configure_dt(&config->cmd_data_gpio, GPIO_OUTPUT)) { - LOG_ERR("Couldn't configure CMD/DATA pin"); - return -EIO; - } - } - st7789v_reset_display(dev); st7789v_blanking_on(dev); @@ -398,14 +363,14 @@ static const struct display_driver_api st7789v_api = { }; #define ST7789V_WORD_SIZE(inst) \ - COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, cmd_data_gpios), (8), (9)) - + ((DT_INST_PROP(inst, mipi_mode) == MIPI_DBI_MODE_SPI_4WIRE) ? \ + SPI_WORD_SET(8) : SPI_WORD_SET(9)) #define ST7789V_INIT(inst) \ static const struct st7789v_config st7789v_config_ ## inst = { \ - .bus = SPI_DT_SPEC_INST_GET(inst, SPI_OP_MODE_MASTER | \ - SPI_WORD_SET(ST7789V_WORD_SIZE(inst)), 0), \ - .cmd_data_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, cmd_data_gpios, {}), \ - .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}), \ + .mipi_dbi = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + .dbi_config = MIPI_DBI_CONFIG_DT_INST(inst, \ + ST7789V_WORD_SIZE(inst) | \ + SPI_OP_MODE_MASTER, 0), \ .vcom = DT_INST_PROP(inst, vcom), \ .gctrl = DT_INST_PROP(inst, gctrl), \ .vdv_vrh_enable = (DT_INST_NODE_HAS_PROP(inst, vrhs) \ diff --git a/drivers/display/display_st7789v.h b/drivers/display/display_st7789v.h index aa16e8d5633b6..191135b02fe6e 100644 --- a/drivers/display/display_st7789v.h +++ b/drivers/display/display_st7789v.h @@ -68,6 +68,4 @@ #define ST7789V_CMD_PVGAMCTRL 0xe0 #define ST7789V_CMD_NVGAMCTRL 0xe1 -#define ST7789V_CMD_NONE 0xff - #endif diff --git a/drivers/display/display_st7796s.c b/drivers/display/display_st7796s.c index 131928b2fc736..257a456c84bc5 100644 --- a/drivers/display/display_st7796s.c +++ b/drivers/display/display_st7796s.c @@ -7,8 +7,6 @@ #define DT_DRV_COMPAT sitronix_st7796s #include -#include -#include #include #include #include @@ -30,8 +28,6 @@ LOG_MODULE_REGISTER(display_st7796s, CONFIG_DISPLAY_LOG_LEVEL); struct st7796s_config { const struct device *mipi_dbi; const struct mipi_dbi_config dbi_config; - const struct gpio_dt_spec cmd_data_gpio; - const struct gpio_dt_spec reset_gpio; uint16_t width; uint16_t height; bool inverted; /* Display color inversion */ @@ -50,6 +46,7 @@ struct st7796s_config { uint8_t pgc[14]; /* Positive gamma control */ uint8_t ngc[14]; /* Negative gamma control */ uint8_t madctl; /* Memory data access control */ + bool rgb_is_inverted; }; static int st7796s_send_cmd(const struct device *dev, @@ -96,6 +93,52 @@ static int st7796s_blanking_off(const struct device *dev) return st7796s_send_cmd(dev, ST7796S_CMD_DISPON, NULL, 0); } +static int st7796s_get_pixelfmt(const struct device *dev) +{ + const struct st7796s_config *config = dev->config; + + /* + * Invert the pixel format for 8-bit 8080 Parallel Interface. + * + * Zephyr uses big endian byte order when the pixel format has + * multiple bytes. + * + * For RGB565, Red is placed in byte 1 and Blue in byte 0. + * For BGR565, Red is placed in byte 0 and Blue in byte 1. + * + * This is not an issue when using a 16-bit interface. + * For RGB565, this would map to Red being in D[11:15] and + * Blue in D[0:4] and vice versa for BGR565. + * + * However this is an issue when using a 8-bit interface. + * For RGB565, Blue is placed in byte 0 as mentioned earlier. + * However the controller expects Red to be in D[3:7] of byte 0. + * + * Hence we report pixel format as RGB when MADCTL setting is BGR + * and vice versa. + */ + if (config->dbi_config.mode == MIPI_DBI_MODE_8080_BUS_8_BIT) { + if (config->madctl & ST7796S_MADCTL_BGR) { + return PIXEL_FORMAT_RGB_565; + } else { + return PIXEL_FORMAT_BGR_565; + } + } + + /* + * Invert the pixel format if rgb_is_inverted is enabled. + * Report pixel format as the same format set in the MADCTL + * if rgb_is_inverted is disabled. + * Report pixel format as RGB if MADCTL setting is BGR and vice versa + * if rgb_is_inverted is enabled. + * It is a workaround for supporting buggy modules that display RGB as BGR. + */ + if (!(config->madctl & ST7796S_MADCTL_BGR) != !config->rgb_is_inverted) { + return PIXEL_FORMAT_BGR_565; + } else { + return PIXEL_FORMAT_RGB_565; + } +} static int st7796s_write(const struct device *dev, const uint16_t x, @@ -122,12 +165,7 @@ static int st7796s_write(const struct device *dev, return ret; } - if (config->madctl & ST7796S_MADCTL_BGR) { - /* Zephyr treats RGB565 as BGR565 */ - pixfmt = PIXEL_FORMAT_RGB_565; - } else { - pixfmt = PIXEL_FORMAT_BGR_565; - } + pixfmt = st7796s_get_pixelfmt(dev); return mipi_dbi_write_display(config->mipi_dbi, &config->dbi_config, buf, @@ -141,12 +179,8 @@ static void st7796s_get_capabilities(const struct device *dev, memset(capabilities, 0, sizeof(struct display_capabilities)); - if (config->madctl & ST7796S_MADCTL_BGR) { - /* Zephyr treats RGB565 as BGR565 */ - capabilities->current_pixel_format = PIXEL_FORMAT_RGB_565; - } else { - capabilities->current_pixel_format = PIXEL_FORMAT_BGR_565; - } + capabilities->current_pixel_format = st7796s_get_pixelfmt(dev); + capabilities->x_resolution = config->width; capabilities->y_resolution = config->height; capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL; @@ -323,7 +357,8 @@ static const struct display_driver_api st7796s_api = { SPI_OP_MODE_MASTER | \ SPI_WORD_SET(8), \ 0), \ - .mode = MIPI_DBI_MODE_SPI_4WIRE, \ + .mode = DT_INST_PROP_OR(n, mipi_mode, \ + MIPI_DBI_MODE_SPI_4WIRE), \ }, \ .width = DT_INST_PROP(n, width), \ .height = DT_INST_PROP(n, height), \ @@ -342,6 +377,7 @@ static const struct display_driver_api st7796s_api = { .pgc = DT_INST_PROP(n, pgc), \ .ngc = DT_INST_PROP(n, ngc), \ .madctl = DT_INST_PROP(n, madctl), \ + .rgb_is_inverted = DT_INST_PROP(n, rgb_is_inverted), \ }; \ \ DEVICE_DT_INST_DEFINE(n, st7796s_init, \ diff --git a/drivers/display/ls0xx.c b/drivers/display/ls0xx.c index 95f640ee4a137..0616148e93267 100644 --- a/drivers/display/ls0xx.c +++ b/drivers/display/ls0xx.c @@ -278,7 +278,7 @@ static const struct ls0xx_config ls0xx_config = { #endif }; -static struct display_driver_api ls0xx_driver_api = { +static const struct display_driver_api ls0xx_driver_api = { .blanking_on = ls0xx_blanking_on, .blanking_off = ls0xx_blanking_off, .write = ls0xx_write, diff --git a/drivers/display/ssd1306.c b/drivers/display/ssd1306.c index 563c8d2071f88..9ed263749e160 100644 --- a/drivers/display/ssd1306.c +++ b/drivers/display/ssd1306.c @@ -455,7 +455,7 @@ static int ssd1306_init(const struct device *dev) return 0; } -static struct display_driver_api ssd1306_driver_api = { +static const struct display_driver_api ssd1306_driver_api = { .blanking_on = ssd1306_suspend, .blanking_off = ssd1306_resume, .write = ssd1306_write, diff --git a/drivers/display/ssd16xx.c b/drivers/display/ssd16xx.c index 53da2c33f4050..7dfaa1211771b 100644 --- a/drivers/display/ssd16xx.c +++ b/drivers/display/ssd16xx.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2022 Andreas Sandberg * Copyright (c) 2018-2020 PHYTEC Messtechnik GmbH + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,7 +15,7 @@ LOG_MODULE_REGISTER(ssd16xx); #include #include #include -#include +#include #include #include @@ -66,6 +67,7 @@ struct ssd16xx_data { uint8_t scan_mode; bool blanking_on; enum ssd16xx_profile_type profile; + enum display_orientation orientation; }; struct ssd16xx_dt_array { @@ -89,10 +91,9 @@ struct ssd16xx_profile { }; struct ssd16xx_config { - struct spi_dt_spec bus; - struct gpio_dt_spec dc_gpio; + const struct device *mipi_dev; + const struct mipi_dbi_config dbi_config; struct gpio_dt_spec busy_gpio; - struct gpio_dt_spec reset_gpio; const struct ssd16xx_quirks *quirks; @@ -100,7 +101,7 @@ struct ssd16xx_config { const struct ssd16xx_profile *profiles[SSD16XX_NUM_PROFILES]; - bool orientation; + uint16_t rotation; uint16_t height; uint16_t width; uint8_t tssv; @@ -125,39 +126,13 @@ static inline int ssd16xx_write_cmd(const struct device *dev, uint8_t cmd, const uint8_t *data, size_t len) { const struct ssd16xx_config *config = dev->config; - struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)}; - struct spi_buf_set buf_set = {.buffers = &buf, .count = 1}; - int err = 0; + int err; ssd16xx_busy_wait(dev); - err = gpio_pin_set_dt(&config->dc_gpio, 1); - if (err < 0) { - return err; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - - if (data != NULL) { - buf.buf = (void *)data; - buf.len = len; - - err = gpio_pin_set_dt(&config->dc_gpio, 0); - if (err < 0) { - goto spi_out; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - } - -spi_out: - spi_release_dt(&config->bus); + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, data, len); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return err; } @@ -172,9 +147,6 @@ static inline int ssd16xx_read_cmd(const struct device *dev, uint8_t cmd, { const struct ssd16xx_config *config = dev->config; const struct ssd16xx_data *dev_data = dev->data; - struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)}; - struct spi_buf_set buf_set = {.buffers = &buf, .count = 1}; - int err = 0; if (!dev_data->read_supported) { return -ENOTSUP; @@ -182,34 +154,8 @@ static inline int ssd16xx_read_cmd(const struct device *dev, uint8_t cmd, ssd16xx_busy_wait(dev); - err = gpio_pin_set_dt(&config->dc_gpio, 1); - if (err < 0) { - return err; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - - if (data != NULL) { - buf.buf = data; - buf.len = len; - - err = gpio_pin_set_dt(&config->dc_gpio, 0); - if (err < 0) { - goto spi_out; - } - - err = spi_read_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - } - -spi_out: - spi_release_dt(&config->bus); - return err; + return mipi_dbi_command_read(config->mipi_dev, &config->dbi_config, + &cmd, 1, data, len); } static inline size_t push_x_param(const struct device *dev, @@ -380,53 +326,78 @@ static int ssd16xx_set_window(const struct device *dev, return -ENOTSUP; } - if ((y + desc->height) > panel_h) { - LOG_ERR("Buffer out of bounds (height)"); - return -EINVAL; - } + if (data->orientation == DISPLAY_ORIENTATION_NORMAL || + data->orientation == DISPLAY_ORIENTATION_ROTATED_180) { + if ((y + desc->height) > panel_h) { + LOG_ERR("Buffer out of bounds (height)"); + return -EINVAL; + } - if ((x + desc->width) > config->width) { - LOG_ERR("Buffer out of bounds (width)"); - return -EINVAL; - } + if ((x + desc->width) > config->width) { + LOG_ERR("Buffer out of bounds (width)"); + return -EINVAL; + } - if ((desc->height % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0U) { - LOG_ERR("Buffer height not multiple of %d", - EPD_PANEL_NUMOF_ROWS_PER_PAGE); - return -EINVAL; - } + if ((desc->height % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0U) { + LOG_ERR("Buffer height not multiple of %d", EPD_PANEL_NUMOF_ROWS_PER_PAGE); + return -EINVAL; + } - if ((y % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0U) { - LOG_ERR("Y coordinate not multiple of %d", - EPD_PANEL_NUMOF_ROWS_PER_PAGE); - return -EINVAL; + if ((y % EPD_PANEL_NUMOF_ROWS_PER_PAGE) != 0U) { + LOG_ERR("Y coordinate not multiple of %d", EPD_PANEL_NUMOF_ROWS_PER_PAGE); + return -EINVAL; + } + } else { + if ((y + desc->height) > config->width) { + LOG_ERR("Buffer out of bounds (height)"); + return -EINVAL; + } + + if ((x + desc->width) > panel_h) { + LOG_ERR("Buffer out of bounds (width)"); + return -EINVAL; + } + + if ((desc->width % SSD16XX_PIXELS_PER_BYTE) != 0U) { + LOG_ERR("Buffer width not multiple of %d", SSD16XX_PIXELS_PER_BYTE); + return -EINVAL; + } + + if ((x % SSD16XX_PIXELS_PER_BYTE) != 0U) { + LOG_ERR("X coordinate not multiple of %d", SSD16XX_PIXELS_PER_BYTE); + return -EINVAL; + } } - switch (data->scan_mode) { - case SSD16XX_DATA_ENTRY_XIYDY: + switch (data->orientation) { + case DISPLAY_ORIENTATION_NORMAL: + x_start = (panel_h - 1 - y) / SSD16XX_PIXELS_PER_BYTE; + x_end = (panel_h - 1 - (y + desc->height - 1)) / SSD16XX_PIXELS_PER_BYTE; + y_start = x; + y_end = (x + desc->width - 1); + break; + case DISPLAY_ORIENTATION_ROTATED_90: + x_start = (panel_h - 1 - x) / SSD16XX_PIXELS_PER_BYTE; + x_end = (panel_h - 1 - (x + desc->width - 1)) / SSD16XX_PIXELS_PER_BYTE; + y_start = (config->width - 1 - y); + y_end = (config->width - 1 - (y + desc->height - 1)); + break; + case DISPLAY_ORIENTATION_ROTATED_180: x_start = y / SSD16XX_PIXELS_PER_BYTE; x_end = (y + desc->height - 1) / SSD16XX_PIXELS_PER_BYTE; y_start = (x + desc->width - 1); y_end = x; break; - - case SSD16XX_DATA_ENTRY_XDYIY: - x_start = (panel_h - 1 - y) / SSD16XX_PIXELS_PER_BYTE; - x_end = (panel_h - 1 - (y + desc->height - 1)) / - SSD16XX_PIXELS_PER_BYTE; - y_start = x; - y_end = (x + desc->width - 1); + case DISPLAY_ORIENTATION_ROTATED_270: + x_start = x / SSD16XX_PIXELS_PER_BYTE; + x_end = (x + desc->width - 1) / SSD16XX_PIXELS_PER_BYTE; + y_start = y; + y_end = (y + desc->height - 1); break; default: return -EINVAL; } - err = ssd16xx_write_cmd(dev, SSD16XX_CMD_ENTRY_MODE, - &data->scan_mode, sizeof(data->scan_mode)); - if (err < 0) { - return err; - } - err = ssd16xx_set_ram_param(dev, x_start, x_end, y_start, y_end); if (err < 0) { return err; @@ -585,6 +556,7 @@ static void ssd16xx_get_capabilities(const struct device *dev, struct display_capabilities *caps) { const struct ssd16xx_config *config = dev->config; + struct ssd16xx_data *data = dev->data; memset(caps, 0, sizeof(struct display_capabilities)); caps->x_resolution = config->width; @@ -592,9 +564,14 @@ static void ssd16xx_get_capabilities(const struct device *dev, config->height % EPD_PANEL_NUMOF_ROWS_PER_PAGE; caps->supported_pixel_formats = PIXEL_FORMAT_MONO10; caps->current_pixel_format = PIXEL_FORMAT_MONO10; - caps->screen_info = SCREEN_INFO_MONO_VTILED | - SCREEN_INFO_MONO_MSB_FIRST | - SCREEN_INFO_EPD; + caps->screen_info = SCREEN_INFO_MONO_MSB_FIRST | SCREEN_INFO_EPD; + + if (data->orientation == DISPLAY_ORIENTATION_NORMAL || + data->orientation == DISPLAY_ORIENTATION_ROTATED_180) { + caps->screen_info |= SCREEN_INFO_MONO_VTILED; + } + + caps->current_orientation = data->orientation; } static int ssd16xx_set_pixel_format(const struct device *dev, @@ -608,6 +585,32 @@ static int ssd16xx_set_pixel_format(const struct device *dev, return -ENOTSUP; } +static int ssd16xx_set_orientation(const struct device *dev, + const enum display_orientation orientation) +{ + struct ssd16xx_data *data = dev->data; + int err; + + if (orientation == DISPLAY_ORIENTATION_NORMAL) { + data->scan_mode = SSD16XX_DATA_ENTRY_XDYIY; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_90) { + data->scan_mode = SSD16XX_DATA_ENTRY_XDYDX; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_180) { + data->scan_mode = SSD16XX_DATA_ENTRY_XIYDY; + } else if (orientation == DISPLAY_ORIENTATION_ROTATED_270) { + data->scan_mode = SSD16XX_DATA_ENTRY_XIYIX; + } + + err = ssd16xx_write_uint8(dev, SSD16XX_CMD_ENTRY_MODE, data->scan_mode); + if (err < 0) { + return err; + } + + data->orientation = orientation; + + return 0; +} + static int ssd16xx_clear_cntlr_mem(const struct device *dev, uint8_t ram_cmd) { const struct ssd16xx_config *config = dev->config; @@ -831,6 +834,11 @@ static int ssd16xx_set_profile(const struct device *dev, } } + err = ssd16xx_write_uint8(dev, SSD16XX_CMD_ENTRY_MODE, data->scan_mode); + if (err < 0) { + return err; + } + data->profile = type; return 0; @@ -840,6 +848,7 @@ static int ssd16xx_controller_init(const struct device *dev) { const struct ssd16xx_config *config = dev->config; struct ssd16xx_data *data = dev->data; + enum display_orientation orientation; int err; LOG_DBG(""); @@ -847,25 +856,13 @@ static int ssd16xx_controller_init(const struct device *dev) data->blanking_on = false; data->profile = SSD16XX_PROFILE_INVALID; - err = gpio_pin_set_dt(&config->reset_gpio, 1); - if (err < 0) { - return err; - } - - k_msleep(SSD16XX_RESET_DELAY); - err = gpio_pin_set_dt(&config->reset_gpio, 0); + err = mipi_dbi_reset(config->mipi_dev, SSD16XX_RESET_DELAY); if (err < 0) { return err; } k_msleep(SSD16XX_RESET_DELAY); - if (config->orientation == 1) { - data->scan_mode = SSD16XX_DATA_ENTRY_XIYDY; - } else { - data->scan_mode = SSD16XX_DATA_ENTRY_XDYIY; - } - err = ssd16xx_set_profile(dev, SSD16XX_PROFILE_FULL); if (err < 0) { return err; @@ -881,6 +878,21 @@ static int ssd16xx_controller_init(const struct device *dev) return err; } + if (config->rotation == 0U) { + orientation = DISPLAY_ORIENTATION_NORMAL; + } else if (config->rotation == 90U) { + orientation = DISPLAY_ORIENTATION_ROTATED_90; + } else if (config->rotation == 180U) { + orientation = DISPLAY_ORIENTATION_ROTATED_180; + } else { + orientation = DISPLAY_ORIENTATION_ROTATED_270; + } + + err = ssd16xx_set_orientation(dev, orientation); + if (err < 0) { + return err; + } + err = ssd16xx_update_display(dev); if (err < 0) { return err; @@ -897,35 +909,13 @@ static int ssd16xx_init(const struct device *dev) LOG_DBG(""); - if (!spi_is_ready_dt(&config->bus)) { - LOG_ERR("SPI bus %s not ready", config->bus.bus->name); + if (!device_is_ready(config->mipi_dev)) { + LOG_ERR("MIPI Device not ready"); return -ENODEV; } data->read_supported = - (config->bus.config.operation & SPI_HALF_DUPLEX) != 0; - - if (!gpio_is_ready_dt(&config->reset_gpio)) { - LOG_ERR("Reset GPIO device not ready"); - return -ENODEV; - } - - err = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); - if (err < 0) { - LOG_ERR("Failed to configure reset GPIO"); - return err; - } - - if (!gpio_is_ready_dt(&config->dc_gpio)) { - LOG_ERR("DC GPIO device not ready"); - return -ENODEV; - } - - err = gpio_pin_configure_dt(&config->dc_gpio, GPIO_OUTPUT_INACTIVE); - if (err < 0) { - LOG_ERR("Failed to configure DC GPIO"); - return err; - } + (config->dbi_config.config.operation & SPI_HALF_DUPLEX) != 0; if (!gpio_is_ready_dt(&config->busy_gpio)) { LOG_ERR("Busy GPIO device not ready"); @@ -947,13 +937,14 @@ static int ssd16xx_init(const struct device *dev) return ssd16xx_controller_init(dev); } -static struct display_driver_api ssd16xx_driver_api = { +static const struct display_driver_api ssd16xx_driver_api = { .blanking_on = ssd16xx_blanking_on, .blanking_off = ssd16xx_blanking_off, .write = ssd16xx_write, .read = ssd16xx_read, .get_capabilities = ssd16xx_get_capabilities, .set_pixel_format = ssd16xx_set_pixel_format, + .set_orientation = ssd16xx_set_orientation, }; #if DT_HAS_COMPAT_STATUS_OKAY(solomon_ssd1608) @@ -1060,17 +1051,18 @@ static struct ssd16xx_quirks quirks_solomon_ssd1681 = { DT_FOREACH_CHILD(n, SSD16XX_PROFILE); \ \ static const struct ssd16xx_config ssd16xx_cfg_ ## n = { \ - .bus = SPI_DT_SPEC_GET(n, \ - SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ - SPI_HOLD_ON_CS | SPI_LOCK_ON, \ - 0), \ - .reset_gpio = GPIO_DT_SPEC_GET(n, reset_gpios), \ - .dc_gpio = GPIO_DT_SPEC_GET(n, dc_gpios), \ + .mipi_dev = DEVICE_DT_GET(DT_PARENT(n)), \ + .dbi_config = { \ + .mode = MIPI_DBI_MODE_SPI_4WIRE, \ + .config = MIPI_DBI_SPI_CONFIG_DT(n, \ + SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ + SPI_HOLD_ON_CS | SPI_LOCK_ON, 0), \ + }, \ .busy_gpio = GPIO_DT_SPEC_GET(n, busy_gpios), \ .quirks = quirks_ptr, \ .height = DT_PROP(n, height), \ .width = DT_PROP(n, width), \ - .orientation = DT_PROP(n, orientation_flipped), \ + .rotation = DT_PROP(n, rotation), \ .tssv = DT_PROP_OR(n, tssv, 0), \ .softstart = SSD16XX_ASSIGN_ARRAY(n, softstart), \ .profiles = { \ diff --git a/drivers/display/uc81xx.c b/drivers/display/uc81xx.c index 56cebee552b2f..cac7d1d20c67c 100644 --- a/drivers/display/uc81xx.c +++ b/drivers/display/uc81xx.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2022 Andreas Sandberg * Copyright (c) 2020 PHYTEC Messtechnik GmbH + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -10,7 +11,7 @@ #include #include #include -#include +#include #include #include "uc81xx_regs.h" @@ -75,10 +76,9 @@ struct uc81xx_quirks { struct uc81xx_config { const struct uc81xx_quirks *quirks; - struct spi_dt_spec bus; - struct gpio_dt_spec dc_gpio; + const struct device *mipi_dev; + const struct mipi_dbi_config dbi_config; struct gpio_dt_spec busy_gpio; - struct gpio_dt_spec reset_gpio; uint16_t height; uint16_t width; @@ -110,39 +110,13 @@ static inline int uc81xx_write_cmd(const struct device *dev, uint8_t cmd, const uint8_t *data, size_t len) { const struct uc81xx_config *config = dev->config; - struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)}; - struct spi_buf_set buf_set = {.buffers = &buf, .count = 1}; int err; uc81xx_busy_wait(dev); - err = gpio_pin_set_dt(&config->dc_gpio, 1); - if (err < 0) { - return err; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - - if (data != NULL) { - buf.buf = (void *)data; - buf.len = len; - - err = gpio_pin_set_dt(&config->dc_gpio, 0); - if (err < 0) { - goto spi_out; - } - - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - } - -spi_out: - spi_release_dt(&config->bus); + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, data, len); + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return err; } @@ -151,43 +125,42 @@ static inline int uc81xx_write_cmd_pattern(const struct device *dev, uint8_t pattern, size_t len) { const struct uc81xx_config *config = dev->config; - struct spi_buf buf = {.buf = &cmd, .len = sizeof(cmd)}; - struct spi_buf_set buf_set = {.buffers = &buf, .count = 1}; + struct display_buffer_descriptor mipi_desc; int err; uint8_t data[64]; uc81xx_busy_wait(dev); - err = gpio_pin_set_dt(&config->dc_gpio, 1); + err = mipi_dbi_command_write(config->mipi_dev, &config->dbi_config, + cmd, NULL, 0); if (err < 0) { return err; } - err = spi_write_dt(&config->bus, &buf_set); - if (err < 0) { - goto spi_out; - } - - err = gpio_pin_set_dt(&config->dc_gpio, 0); - if (err < 0) { - goto spi_out; - } + /* + * MIPI display write API requires a display buffer descriptor. + * Create one that describes the buffer we are writing + */ + mipi_desc.height = 1; memset(data, pattern, sizeof(data)); while (len) { - buf.buf = data; - buf.len = MIN(len, sizeof(data)); + mipi_desc.buf_size = mipi_desc.width = mipi_desc.pitch = + MIN(len, sizeof(data)); - err = spi_write_dt(&config->bus, &buf_set); + err = mipi_dbi_write_display(config->mipi_dev, + &config->dbi_config, + data, &mipi_desc, + PIXEL_FORMAT_MONO10); if (err < 0) { - goto spi_out; + goto out; } - len -= buf.len; + len -= mipi_desc.buf_size; } -spi_out: - spi_release_dt(&config->bus); +out: + mipi_dbi_release(config->mipi_dev, &config->dbi_config); return err; } @@ -544,9 +517,7 @@ static int uc81xx_controller_init(const struct device *dev) const struct uc81xx_config *config = dev->config; struct uc81xx_data *data = dev->data; - gpio_pin_set_dt(&config->reset_gpio, 1); - k_sleep(K_MSEC(UC81XX_RESET_DELAY)); - gpio_pin_set_dt(&config->reset_gpio, 0); + mipi_dbi_reset(config->mipi_dev, UC81XX_RESET_DELAY); k_sleep(K_MSEC(UC81XX_RESET_DELAY)); uc81xx_busy_wait(dev); @@ -570,26 +541,11 @@ static int uc81xx_init(const struct device *dev) LOG_DBG(""); - if (!spi_is_ready_dt(&config->bus)) { - LOG_ERR("SPI bus %s not ready", config->bus.bus->name); - return -ENODEV; - } - - if (!gpio_is_ready_dt(&config->reset_gpio)) { - LOG_ERR("Reset GPIO device not ready"); - return -ENODEV; - } - - gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); - - if (!gpio_is_ready_dt(&config->dc_gpio)) { - LOG_ERR("DC GPIO device not ready"); + if (!device_is_ready(config->mipi_dev)) { + LOG_ERR("MIPI device not ready"); return -ENODEV; } - gpio_pin_configure_dt(&config->dc_gpio, GPIO_OUTPUT_INACTIVE); - - if (!gpio_is_ready_dt(&config->busy_gpio)) { LOG_ERR("Busy GPIO device not ready"); return -ENODEV; @@ -754,7 +710,7 @@ static const struct uc81xx_quirks uc8179_quirks = { }; #endif -static struct display_driver_api uc81xx_driver_api = { +static const struct display_driver_api uc81xx_driver_api = { .blanking_on = uc81xx_blanking_on, .blanking_off = uc81xx_blanking_off, .write = uc81xx_write, @@ -816,12 +772,14 @@ static struct display_driver_api uc81xx_driver_api = { \ static const struct uc81xx_config uc81xx_cfg_ ## n = { \ .quirks = quirks_ptr, \ - .bus = SPI_DT_SPEC_GET(n, \ - SPI_OP_MODE_MASTER | SPI_WORD_SET(8) | \ - SPI_LOCK_ON, \ - 0), \ - .reset_gpio = GPIO_DT_SPEC_GET(n, reset_gpios), \ - .dc_gpio = GPIO_DT_SPEC_GET(n, dc_gpios), \ + .mipi_dev = DEVICE_DT_GET(DT_PARENT(n)), \ + .dbi_config = { \ + .mode = MIPI_DBI_MODE_SPI_4WIRE, \ + .config = MIPI_DBI_SPI_CONFIG_DT(n, \ + SPI_OP_MODE_MASTER | \ + SPI_LOCK_ON | SPI_WORD_SET(8), \ + 0), \ + }, \ .busy_gpio = GPIO_DT_SPEC_GET(n, busy_gpios), \ \ .height = DT_PROP(n, height), \ diff --git a/drivers/dma/Kconfig.intel_adsp_hda b/drivers/dma/Kconfig.intel_adsp_hda index 20ced567cb084..3761470fc95e7 100644 --- a/drivers/dma/Kconfig.intel_adsp_hda +++ b/drivers/dma/Kconfig.intel_adsp_hda @@ -45,6 +45,7 @@ config DMA_INTEL_ADSP_HDA config DMA_INTEL_ADSP_HDA_TIMING_L1_EXIT bool "Intel ADSP HDA Host L1 Exit Interrupt" default y if SOC_INTEL_ACE15_MTPM + default y if SOC_INTEL_ACE20_LNL depends on DMA_INTEL_ADSP_HDA_HOST_IN || DMA_INTEL_ADSP_HDA_HOST_OUT help Intel ADSP HDA Host Interrupt for L1 exit. diff --git a/drivers/dma/dma_handlers.c b/drivers/dma/dma_handlers.c index d84c151015219..9ebce367482ea 100644 --- a/drivers/dma/dma_handlers.c +++ b/drivers/dma/dma_handlers.c @@ -16,11 +16,11 @@ static inline int z_vrfy_dma_start(const struct device *dev, uint32_t channel) K_OOPS(K_SYSCALL_DRIVER_DMA(dev, start)); return z_impl_dma_start((const struct device *)dev, channel); } -#include +#include static inline int z_vrfy_dma_stop(const struct device *dev, uint32_t channel) { K_OOPS(K_SYSCALL_DRIVER_DMA(dev, stop)); return z_impl_dma_stop((const struct device *)dev, channel); } -#include +#include diff --git a/drivers/dma/dma_smartbond.c b/drivers/dma/dma_smartbond.c index 855e56b9aff5f..493ac222836de 100644 --- a/drivers/dma/dma_smartbond.c +++ b/drivers/dma/dma_smartbond.c @@ -9,10 +9,14 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include #include LOG_MODULE_REGISTER(dma_smartbond, CONFIG_DMA_LOG_LEVEL); @@ -154,6 +158,10 @@ struct dma_smartbond_data { ATOMIC_DEFINE(channels_atomic, DMA_CHANNELS_COUNT); +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + ATOMIC_DEFINE(pm_policy_state_flag, 1); +#endif + /* User callbacks and data to be stored per channel */ struct dma_channel_data channel_data[DMA_CHANNELS_COUNT]; }; @@ -175,7 +183,31 @@ static bool dma_smartbond_is_dma_active(void) return false; } -static void dma_smartbond_set_channel_status(uint32_t channel, bool status) +static inline void dma_smartbond_pm_policy_state_lock_get(const struct device *dev) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + struct dma_smartbond_data *data = dev->data; + + if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) { + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void dma_smartbond_pm_policy_state_lock_put(const struct device *dev) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + struct dma_smartbond_data *data = dev->data; + + /* Make PM lock put has a matched PM lock get invocation */ + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) { + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static void dma_smartbond_set_channel_status(const struct device *dev, + uint32_t channel, bool status) { unsigned int key; struct channel_regs *regs = DMA_CHN2REG(channel); @@ -191,6 +223,8 @@ static void dma_smartbond_set_channel_status(uint32_t channel, bool status) /* Check if this is the first attempt to enable DMA interrupts. */ if (!irq_is_enabled(SMARTBOND_IRQN)) { irq_enable(SMARTBOND_IRQN); + /* Prevent sleep as long as DMA operations are ongoing */ + dma_smartbond_pm_policy_state_lock_get(dev); } DMA_CTRL_REG_SET_FIELD(DMA_ON, regs->DMA_CTRL_REG, 0x1); @@ -212,6 +246,8 @@ static void dma_smartbond_set_channel_status(uint32_t channel, bool status) /* DMA interrupts should be disabled only if all channels are disabled. */ if (!dma_smartbond_is_dma_active()) { irq_disable(SMARTBOND_IRQN); + /* Allow entering sleep once all DMA channels are inactive */ + dma_smartbond_pm_policy_state_lock_put(dev); } } @@ -307,6 +343,7 @@ static bool dma_channel_update_dreq_mode(enum dma_channel_direction direction, DMA_CTRL_REG_SET_FIELD(DREQ_MODE, *dma_ctrl_reg, DREQ_MODE_SW); break; case PERIPHERAL_TO_MEMORY: + case MEMORY_TO_PERIPHERAL: case PERIPHERAL_TO_PERIPHERAL: /* DMA channels starts by peripheral DMA req */ DMA_CTRL_REG_SET_FIELD(DREQ_MODE, *dma_ctrl_reg, DREQ_MODE_HW); @@ -707,7 +744,7 @@ static int dma_smartbond_start(const struct device *dev, uint32_t channel) return 0; } - dma_smartbond_set_channel_status(channel, true); + dma_smartbond_set_channel_status(dev, channel, true); return 0; } @@ -727,7 +764,7 @@ static int dma_smartbond_stop(const struct device *dev, uint32_t channel) * the corresponding register mask and disable NVIC if there is no other * channel in use. */ - dma_smartbond_set_channel_status(channel, false); + dma_smartbond_set_channel_status(dev, channel, false); return 0; } @@ -928,6 +965,57 @@ static void smartbond_dma_isr(const void *arg) } } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static bool dma_smartbond_is_sleep_allowed(const struct device *dev) +{ + struct dma_smartbond_data *data = dev->data; + + for (int i = 0; i < data->dma_ctx.dma_channels; i++) { + if (atomic_test_bit(data->dma_ctx.atomic, i)) { + /* Abort sleeping if at least one dma channel is acquired */ + return false; + } + } + + return true; +} + +static int dma_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* + * When we reach this point there should be no ongoing DMA transfers. + * However, a DMA channel can still be acquired and so the configured + * channel(s) should be retained. To avoid reconfiguring DMA or + * read/write DMA channels' registers we assume that sleep is not allowed + * as long as all DMA channels are released. + */ + if (!dma_smartbond_is_sleep_allowed(dev)) { + ret = -EBUSY; + } + /* + * No need to perform any actions here as the DMA engine + * should already be turned off. + */ + break; + case PM_DEVICE_ACTION_RESUME: + /* + * No need to perform any actions here as the DMA engine + * will be configured by application explicitly. + */ + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + static int dma_smartbond_init(const struct device *dev) { #ifdef CONFIG_DMA_64BIT @@ -945,7 +1033,7 @@ static int dma_smartbond_init(const struct device *dev) /* Make sure that all channels are disabled. */ for (idx = 0; idx < DMA_CHANNELS_COUNT; idx++) { - dma_smartbond_set_channel_status(idx, false); + dma_smartbond_set_channel_status(dev, idx, false); data->channel_data[idx].is_dma_configured = false; } @@ -958,9 +1046,12 @@ static int dma_smartbond_init(const struct device *dev) #define SMARTBOND_DMA_INIT(inst) \ BUILD_ASSERT((inst) == 0, "multiple instances are not supported"); \ \ + PM_DEVICE_DT_INST_DEFINE(inst, dma_smartbond_pm_action); \ + \ static struct dma_smartbond_data dma_smartbond_data_ ## inst; \ \ - DEVICE_DT_INST_DEFINE(0, dma_smartbond_init, NULL, \ + DEVICE_DT_INST_DEFINE(0, dma_smartbond_init, \ + PM_DEVICE_DT_INST_GET(inst), \ &dma_smartbond_data_ ## inst, NULL, \ POST_KERNEL, \ CONFIG_DMA_INIT_PRIORITY, \ diff --git a/drivers/dma/dma_stm32.h b/drivers/dma/dma_stm32.h index f21cb07e1834c..553e09838d84d 100644 --- a/drivers/dma/dma_stm32.h +++ b/drivers/dma/dma_stm32.h @@ -52,7 +52,11 @@ uint32_t dma_stm32_slot_to_channel(uint32_t id); #endif typedef void (*dma_stm32_clear_flag_func)(DMA_TypeDef *DMAx); +#if !defined(CONFIG_SOC_SERIES_STM32G0X) typedef uint32_t (*dma_stm32_check_flag_func)(DMA_TypeDef *DMAx); +#else +typedef uint32_t (*dma_stm32_check_flag_func)(const DMA_TypeDef *DMAx); +#endif bool dma_stm32_is_tc_active(DMA_TypeDef *DMAx, uint32_t id); void dma_stm32_clear_tc(DMA_TypeDef *DMAx, uint32_t id); diff --git a/drivers/dma/dma_stm32u5.c b/drivers/dma/dma_stm32u5.c index 88ab979df625e..91871292fafce 100644 --- a/drivers/dma/dma_stm32u5.c +++ b/drivers/dma/dma_stm32u5.c @@ -543,13 +543,7 @@ static int dma_stm32_reload(const struct device *dev, uint32_t id, dma_stm32_id_to_stream(id), src, dst); - if (stream->source_periph) { - LL_DMA_SetBlkDataLength(dma, dma_stm32_id_to_stream(id), - size / stream->src_size); - } else { - LL_DMA_SetBlkDataLength(dma, dma_stm32_id_to_stream(id), - size / stream->dst_size); - } + LL_DMA_SetBlkDataLength(dma, dma_stm32_id_to_stream(id), size); /* When reloading the dma, the stream is busy again before enabling */ stream->busy = true; diff --git a/drivers/dma/dmamux_stm32.c b/drivers/dma/dmamux_stm32.c index bca6514190e64..d12a294eb7ff1 100644 --- a/drivers/dma/dmamux_stm32.c +++ b/drivers/dma/dmamux_stm32.c @@ -70,19 +70,24 @@ uint32_t table_ll_channel[] = { LISTIFY(DT_INST_PROP(0, dma_channels), DMAMUX_CHANNEL, (,)) }; -uint32_t (*func_ll_is_active_so[])(DMAMUX_Channel_TypeDef *DMAMUXx) = { +#if !defined(CONFIG_SOC_SERIES_STM32G0X) +#define dmamux_channel_typedef DMAMUX_Channel_TypeDef +#else +#define dmamux_channel_typedef const DMAMUX_Channel_TypeDef +#endif +uint32_t (*func_ll_is_active_so[])(dmamux_channel_typedef * DMAMUXx) = { LISTIFY(DT_INST_PROP(0, dma_channels), IS_ACTIVE_FLAG_SOX, (,)) }; -void (*func_ll_clear_so[])(DMAMUX_Channel_TypeDef *DMAMUXx) = { +void (*func_ll_clear_so[])(dmamux_channel_typedef * DMAMUXx) = { LISTIFY(DT_INST_PROP(0, dma_channels), CLEAR_FLAG_SOX, (,)) }; -uint32_t (*func_ll_is_active_rgo[])(DMAMUX_Channel_TypeDef *DMAMUXx) = { +uint32_t (*func_ll_is_active_rgo[])(dmamux_channel_typedef * DMAMUXx) = { LISTIFY(DT_INST_PROP(0, dma_generators), IS_ACTIVE_FLAG_RGOX, (,)) }; -void (*func_ll_clear_rgo[])(DMAMUX_Channel_TypeDef *DMAMUXx) = { +void (*func_ll_clear_rgo[])(dmamux_channel_typedef * DMAMUXx) = { LISTIFY(DT_INST_PROP(0, dma_generators), CLEAR_FLAG_RGOX, (,)) }; diff --git a/drivers/dp/CMakeLists.txt b/drivers/dp/CMakeLists.txt new file mode 100644 index 0000000000000..dd49b759ab817 --- /dev/null +++ b/drivers/dp/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2019, PHYTEC Messtechnik GmbH +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_SWDP_BITBANG_DRIVER swdp_bitbang.c) diff --git a/drivers/dp/Kconfig b/drivers/dp/Kconfig new file mode 100644 index 0000000000000..b811529bcb5ce --- /dev/null +++ b/drivers/dp/Kconfig @@ -0,0 +1,31 @@ +# Copyright (c) 2019 Phytec Messtechnik GmbH +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig DP_DRIVER + bool "Debug Port interface driver [EXPERIMENTAL]" + select EXPERIMENTAL + help + Enable Debug Port interface driver + +if DP_DRIVER + +module = DP_DRIVER +module-str = dp drv +source "subsys/logging/Kconfig.template.log_config" + +config DP_DRIVER_INIT_PRIO + int "Debug Port driver initialization priority" + default 80 + help + Set the initialization priority number. + +config SWDP_BITBANG_DRIVER + bool "Serial Wire Debug Port bit-bang driver" + default y + depends on DT_HAS_ZEPHYR_SWDP_GPIO_ENABLED + depends on GPIO + help + Serial Wire Debug Port bit-bang driver. + +endif # DP_DRIVER diff --git a/drivers/dp/swdp_bitbang.c b/drivers/dp/swdp_bitbang.c new file mode 100644 index 0000000000000..ba46c629604aa --- /dev/null +++ b/drivers/dp/swdp_bitbang.c @@ -0,0 +1,718 @@ +/* + * Copyright (c) 2018-2019 PHYTEC Messtechnik GmbH + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file is based on SW_DP.c from CMSIS-DAP Source (Revision: V2.0.0) + * https://github.com/ARM-software/CMSIS_5/tree/develop/CMSIS/DAP/Firmware + * Copyright (c) 2013-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + */ + + +/* Serial Wire Debug Port interface bit-bang driver */ + +#define DT_DRV_COMPAT zephyr_swdp_gpio + +#include +#include +#include + +#include "swdp_ll_pin.h" + +#include +LOG_MODULE_REGISTER(swdp, CONFIG_DP_DRIVER_LOG_LEVEL); + +#define CLOCK_DELAY(swclk_freq, port_write_cycles) \ + ((CPU_CLOCK / 2 / swclk_freq) - port_write_cycles) + +/* + * Default SWCLK frequency in Hz. + * sw_clock can be used to overwrite this default value. + */ +#define SWDP_DEFAULT_SWCLK_FREQUENCY 1000000U + +#define DELAY_SLOW_CYCLES 3U + +struct sw_config { + struct gpio_dt_spec clk; + struct gpio_dt_spec dout; + struct gpio_dt_spec dio; + struct gpio_dt_spec dnoe; + void *dout_reg; + void *dio_reg; + void *dnoe_reg; + struct gpio_dt_spec noe; + struct gpio_dt_spec reset; + uint32_t port_write_cycles; + void *clk_reg; +}; + +struct sw_cfg_data { + uint32_t clock_delay; + uint8_t turnaround; + bool data_phase; + bool fast_clock; +}; + +/* + * Move A[2:3], RnW, APnDP bits to their position, + * add start bit, stop bit(6), park bit and parity bit. + * For example, reading IDCODE would be APnDP=0, RnW=1, A2=0, A3=0. + * The request would be 0xa5, which is 10100101 in binary. + * + * For more information, see: + * - CMSIS-DAP Command Specification, DAP_Transfer + * - ARM Debug Interface v5 Architecture Specification + */ +const static uint8_t sw_request_lut[16] = { + 0x81, 0xa3, 0xa5, 0x87, 0xa9, 0x8b, 0x8d, 0xaf, + 0xb1, 0x93, 0x95, 0xb7, 0x99, 0xbb, 0xbd, 0x9f +}; + +static ALWAYS_INLINE uint32_t sw_get32bit_parity(uint32_t data) +{ + data ^= data >> 16; + data ^= data >> 8; + data ^= data >> 4; + data ^= data >> 2; + data ^= data >> 1; + + return data & 1U; +} + +/* Set SWCLK DAP hardware output pin to high level */ +static ALWAYS_INLINE void pin_swclk_set(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_set(config->clk_reg, config->clk.pin); + } else { + gpio_pin_set_dt(&config->clk, 1); + } +} + +/* Set SWCLK DAP hardware output pin to low level */ +static ALWAYS_INLINE void pin_swclk_clr(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_clr(config->clk_reg, config->clk.pin); + } else { + gpio_pin_set_dt(&config->clk, 0); + } +} + +/* Set the SWDIO DAP hardware output pin to high level */ +static ALWAYS_INLINE void pin_swdio_set(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + if (config->dout.port) { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_set(config->dout_reg, config->dout.pin); + } else { + gpio_pin_set_dt(&config->dout, 1); + } + } else { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_set(config->dio_reg, config->dio.pin); + } else { + gpio_pin_set_dt(&config->dio, 1); + } + } +} + +/* Set the SWDIO DAP hardware output pin to low level */ +static ALWAYS_INLINE void pin_swdio_clr(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + if (config->dout.port) { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_clr(config->dout_reg, config->dout.pin); + } else { + gpio_pin_set_dt(&config->dout, 0); + } + } else { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_clr(config->dio_reg, config->dio.pin); + } else { + gpio_pin_set_dt(&config->dio, 0); + } + } +} + +/* Set the SWDIO DAP hardware output pin to bit level */ +static ALWAYS_INLINE void pin_swdio_out(const struct device *dev, + const uint32_t bit) +{ + if (bit & 1U) { + pin_swdio_set(dev); + } else { + pin_swdio_clr(dev); + } +} + +/* Return current level of the SWDIO DAP hardware input pin */ +static ALWAYS_INLINE uint32_t pin_swdio_in(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + if (FAST_BITBANG_HW_SUPPORT) { + return swdp_ll_pin_get(config->dio_reg, config->dio.pin); + } else { + return gpio_pin_get_dt(&config->dio); + } +} + +/* + * Configure the SWDIO DAP hardware to output mode. + * This is default configuration for every transfer. + */ +static ALWAYS_INLINE void pin_swdio_out_enable(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + if (config->dnoe.port) { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_set(config->dnoe_reg, config->dnoe.pin); + } else { + gpio_pin_set_dt(&config->dnoe, 1); + } + } else { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_output(config->dio_reg, config->dio.pin); + } else { + gpio_pin_configure_dt(&config->dio, GPIO_OUTPUT_ACTIVE); + } + } +} + +/* + * Configure the SWDIO DAP hardware to input mode. + */ +static ALWAYS_INLINE void pin_swdio_out_disable(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + if (config->dnoe.port) { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_clr(config->dnoe_reg, config->dnoe.pin); + } else { + gpio_pin_set_dt(&config->dnoe, 0); + } + } else { + if (FAST_BITBANG_HW_SUPPORT) { + swdp_ll_pin_input(config->dio_reg, config->dio.pin); + } else { + gpio_pin_configure_dt(&config->dio, GPIO_INPUT); + } + } +} + +#define SW_CLOCK_CYCLE(dev, delay) \ + do { \ + pin_swclk_clr(dev); \ + pin_delay_asm(delay); \ + pin_swclk_set(dev); \ + pin_delay_asm(delay); \ + } while (0) + +#define SW_WRITE_BIT(dev, bit, delay) \ + do { \ + pin_swdio_out(dev, bit); \ + pin_swclk_clr(dev); \ + pin_delay_asm(delay); \ + pin_swclk_set(dev); \ + pin_delay_asm(delay); \ + } while (0) + +#define SW_READ_BIT(dev, bit, delay) \ + do { \ + pin_swclk_clr(dev); \ + pin_delay_asm(delay); \ + bit = pin_swdio_in(dev); \ + pin_swclk_set(dev); \ + pin_delay_asm(delay); \ + } while (0) + +static int sw_output_sequence(const struct device *dev, uint32_t count, + const uint8_t *data) +{ + struct sw_cfg_data *sw_data = dev->data; + unsigned int key; + uint32_t val = 0; /* current byte */ + uint32_t n = 0; /* bit counter */ + + LOG_DBG("writing %u bits", count); + LOG_HEXDUMP_DBG(data, count, "sequence bit data"); + key = irq_lock(); + + pin_swdio_out_enable(dev); + while (count--) { + if (n == 0U) { + val = *data++; + n = 8U; + } + if (val & 1U) { + pin_swdio_set(dev); + } else { + pin_swdio_clr(dev); + } + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + val >>= 1; + n--; + } + + irq_unlock(key); + + return 0; +} + +static int sw_input_sequence(const struct device *dev, uint32_t count, + uint8_t *data) +{ + struct sw_cfg_data *sw_data = dev->data; + unsigned int key; + uint32_t val = 0U; /* current byte */ + uint32_t n = 8U; /* bit counter */ + uint32_t bit; + + LOG_DBG("reading %u bits", count); + key = irq_lock(); + + pin_swdio_out_disable(dev); + while (count--) { + if (n == 0U) { + *data++ = val; + val = 0; + n = 8U; + } + SW_READ_BIT(dev, bit, sw_data->clock_delay); + LOG_DBG("Read bit: %d", bit); + val = (val << 1 | bit); + n--; + } + + *data = val; /* write last byte */ + irq_unlock(key); + + return 0; +} + +static ALWAYS_INLINE void sw_cycle_turnaround(const struct device *dev) +{ + struct sw_cfg_data *sw_data = dev->data; + uint32_t n; + + for (n = sw_data->turnaround; n; n--) { + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + } +} + +static int sw_transfer(const struct device *dev, + const uint8_t request, uint32_t *const data, + const uint8_t idle_cycles, uint8_t *const response) +{ + struct sw_cfg_data *sw_data = dev->data; + unsigned int key; + uint32_t ack; + uint32_t bit; + uint32_t val; + uint32_t parity = 0; + uint32_t n; + + pin_swdio_out_enable(dev); + + LOG_DBG("request 0x%02x idle %u", request, idle_cycles); + if (!(request & SWDP_REQUEST_RnW)) { + LOG_DBG("write data 0x%08x", *data); + parity = sw_get32bit_parity(*data); + } + + key = irq_lock(); + + val = sw_request_lut[request & 0xFU]; + for (n = 8U; n; n--) { + SW_WRITE_BIT(dev, val, sw_data->clock_delay); + val >>= 1; + } + + pin_swdio_out_disable(dev); + sw_cycle_turnaround(dev); + + /* Acknowledge response */ + SW_READ_BIT(dev, bit, sw_data->clock_delay); + ack = bit << 0; + SW_READ_BIT(dev, bit, sw_data->clock_delay); + ack |= bit << 1; + SW_READ_BIT(dev, bit, sw_data->clock_delay); + ack |= bit << 2; + + if (ack == SWDP_ACK_OK) { + /* Data transfer */ + if (request & SWDP_REQUEST_RnW) { + /* Read data */ + val = 0U; + for (n = 32U; n; n--) { + /* Read RDATA[0:31] */ + SW_READ_BIT(dev, bit, sw_data->clock_delay); + val >>= 1; + val |= bit << 31; + } + + /* Read parity bit */ + SW_READ_BIT(dev, bit, sw_data->clock_delay); + sw_cycle_turnaround(dev); + pin_swdio_out_enable(dev); + + if ((sw_get32bit_parity(val) ^ bit) & 1U) { + ack = SWDP_TRANSFER_ERROR; + } + + if (data) { + *data = val; + } + + } else { + sw_cycle_turnaround(dev); + + pin_swdio_out_enable(dev); + /* Write data */ + val = *data; + for (n = 32U; n; n--) { + SW_WRITE_BIT(dev, val, sw_data->clock_delay); + val >>= 1; + } + + /* Write parity bit */ + SW_WRITE_BIT(dev, parity, sw_data->clock_delay); + } + /* Idle cycles */ + n = idle_cycles; + if (n) { + pin_swdio_out(dev, 0U); + for (; n; n--) { + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + } + } + + pin_swdio_out(dev, 1U); + irq_unlock(key); + if (request & SWDP_REQUEST_RnW) { + LOG_DBG("read data 0x%08x", *data); + } + + if (response) { + *response = (uint8_t)ack; + } + + return 0; + } + + if ((ack == SWDP_ACK_WAIT) || (ack == SWDP_ACK_FAULT)) { + /* WAIT OR fault response */ + if (sw_data->data_phase) { + for (n = 32U + 1U + sw_data->turnaround; n; n--) { + /* Dummy Read RDATA[0:31] + Parity */ + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + } + } else { + sw_cycle_turnaround(dev); + } + + pin_swdio_out_enable(dev); + pin_swdio_out(dev, 1U); + irq_unlock(key); + LOG_DBG("Transfer wait or fault"); + if (response) { + *response = (uint8_t)ack; + } + + return 0; + } + + /* Protocol error */ + for (n = sw_data->turnaround + 32U + 1U; n; n--) { + /* Back off data phase */ + SW_CLOCK_CYCLE(dev, sw_data->clock_delay); + } + + pin_swdio_out_enable(dev); + pin_swdio_out(dev, 1U); + irq_unlock(key); + LOG_INF("Protocol error"); + if (response) { + *response = (uint8_t)ack; + } + + return 0; +} + +static int sw_set_pins(const struct device *dev, + const uint8_t pins, const uint8_t value) +{ + const struct sw_config *config = dev->config; + + LOG_DBG("pins 0x%02x value 0x%02x", pins, value); + + if (pins & BIT(SWDP_SWCLK_PIN)) { + if (value & BIT(SWDP_SWCLK_PIN)) { + gpio_pin_set_dt(&config->clk, 1); + } else { + gpio_pin_set_dt(&config->clk, 0); + } + } + + if (config->dout_reg != NULL) { + if (pins & BIT(SWDP_SWDIO_PIN)) { + if (value & BIT(SWDP_SWDIO_PIN)) { + gpio_pin_set_dt(&config->dout, 1); + } else { + gpio_pin_set_dt(&config->dout, 0); + } + } + } else { + if (pins & BIT(SWDP_SWDIO_PIN)) { + if (value & BIT(SWDP_SWDIO_PIN)) { + gpio_pin_set_dt(&config->dio, 1); + } else { + gpio_pin_set_dt(&config->dio, 0); + } + } + } + + if (config->reset.port) { + if (pins & BIT(SWDP_nRESET_PIN)) { + if (value & BIT(SWDP_nRESET_PIN)) { + gpio_pin_set_dt(&config->reset, 1); + } else { + gpio_pin_set_dt(&config->reset, 0); + } + } + } + + return 0; +} + +static int sw_get_pins(const struct device *dev, uint8_t *const state) +{ + const struct sw_config *config = dev->config; + uint32_t val; + + if (config->reset.port) { + val = gpio_pin_get_dt(&config->reset); + *state = val ? BIT(SWDP_nRESET_PIN) : 0; + } + + val = gpio_pin_get_dt(&config->dio); + *state |= val ? BIT(SWDP_SWDIO_PIN) : 0; + + val = gpio_pin_get_dt(&config->clk); + *state |= val ? BIT(SWDP_SWCLK_PIN) : 0; + + LOG_DBG("pins state 0x%02x", *state); + + return 0; +} + +static int sw_set_clock(const struct device *dev, const uint32_t clock) +{ + const struct sw_config *config = dev->config; + struct sw_cfg_data *sw_data = dev->data; + uint32_t delay; + + sw_data->fast_clock = false; + delay = ((CPU_CLOCK / 2U) + (clock - 1U)) / clock; + + if (delay > config->port_write_cycles) { + delay -= config->port_write_cycles; + delay = (delay + (DELAY_SLOW_CYCLES - 1U)) / DELAY_SLOW_CYCLES; + } else { + delay = 1U; + } + + sw_data->clock_delay = delay; + + LOG_WRN("cpu_clock %d, delay %d", CPU_CLOCK, sw_data->clock_delay); + + return 0; +} + +static int sw_configure(const struct device *dev, + const uint8_t turnaround, const bool data_phase) +{ + struct sw_cfg_data *sw_data = dev->data; + + sw_data->turnaround = turnaround; + sw_data->data_phase = data_phase; + + LOG_INF("turnaround %d, data_phase %d", + sw_data->turnaround, sw_data->data_phase); + + return 0; +} + +static int sw_port_on(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + gpio_pin_set_dt(&config->clk, 1); + + if (config->dnoe.port) { + gpio_pin_set_dt(&config->dnoe, 1); + } + + if (config->dout.port) { + gpio_pin_set_dt(&config->dout, 1); + } else { + int ret; + + ret = gpio_pin_configure_dt(&config->dio, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } + + if (config->noe.port) { + gpio_pin_set_dt(&config->noe, 1); + } + if (config->reset.port) { + gpio_pin_set_dt(&config->reset, 1); + } + + return 0; +} + +static int sw_port_off(const struct device *dev) +{ + const struct sw_config *config = dev->config; + + if (config->dnoe.port) { + gpio_pin_set_dt(&config->dnoe, 0); + } + + if (config->dout.port) { + gpio_pin_set_dt(&config->dout, 0); + } else { + int ret; + + ret = gpio_pin_configure_dt(&config->dio, GPIO_INPUT); + if (ret) { + return ret; + } + } + + if (config->noe.port) { + gpio_pin_set_dt(&config->noe, 0); + } + if (config->reset.port) { + gpio_pin_set_dt(&config->reset, 1); + } + + return 0; +} + +static int sw_gpio_init(const struct device *dev) +{ + const struct sw_config *config = dev->config; + struct sw_cfg_data *sw_data = dev->data; + int ret; + + ret = gpio_pin_configure_dt(&config->clk, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + + ret = gpio_pin_configure_dt(&config->dio, GPIO_INPUT); + if (ret) { + return ret; + } + + if (config->dout.port) { + ret = gpio_pin_configure_dt(&config->dout, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } + + if (config->dnoe.port) { + ret = gpio_pin_configure_dt(&config->dnoe, GPIO_OUTPUT_INACTIVE); + if (ret) { + return ret; + } + } + + if (config->noe.port) { + ret = gpio_pin_configure_dt(&config->noe, GPIO_OUTPUT_INACTIVE); + if (ret) { + return ret; + } + } + + if (config->reset.port) { + ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } + + sw_data->turnaround = 1U; + sw_data->data_phase = false; + sw_data->fast_clock = false; + sw_data->clock_delay = CLOCK_DELAY(SWDP_DEFAULT_SWCLK_FREQUENCY, + config->port_write_cycles); + + return 0; +} + +static struct swdp_api swdp_bitbang_api = { + .swdp_output_sequence = sw_output_sequence, + .swdp_input_sequence = sw_input_sequence, + .swdp_transfer = sw_transfer, + .swdp_set_pins = sw_set_pins, + .swdp_get_pins = sw_get_pins, + .swdp_set_clock = sw_set_clock, + .swdp_configure = sw_configure, + .swdp_port_on = sw_port_on, + .swdp_port_off = sw_port_off, +}; + +#define SW_GPIOS_GET_REG(n, gpios) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(n, gpios), \ + (INT_TO_POINTER(DT_REG_ADDR(DT_PHANDLE(DT_DRV_INST(n), gpios)))), \ + (NULL)) + +#define SW_DEVICE_DEFINE(n) \ + BUILD_ASSERT((DT_INST_NODE_HAS_PROP(n, dout_gpios)) == \ + (DT_INST_NODE_HAS_PROP(n, dnoe_gpios)), \ + "Either the dout-gpios or dnoe-gpios property is missing."); \ + \ + static const struct sw_config sw_cfg_##n = { \ + .clk = GPIO_DT_SPEC_INST_GET(n, clk_gpios), \ + .clk_reg = SW_GPIOS_GET_REG(n, clk_gpios), \ + .dio = GPIO_DT_SPEC_INST_GET(n, dio_gpios), \ + .dio_reg = SW_GPIOS_GET_REG(n, dio_gpios), \ + .dout = GPIO_DT_SPEC_INST_GET_OR(n, dout_gpios, {0}), \ + .dout_reg = SW_GPIOS_GET_REG(n, dout_gpios), \ + .dnoe = GPIO_DT_SPEC_INST_GET_OR(n, dnoe_gpios, {0}), \ + .dnoe_reg = SW_GPIOS_GET_REG(n, dnoe_gpios), \ + .noe = GPIO_DT_SPEC_INST_GET_OR(n, noe_gpios, {0}), \ + .reset = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), \ + .port_write_cycles = DT_INST_PROP(n, port_write_cycles), \ + }; \ + \ + static struct sw_cfg_data sw_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, sw_gpio_init, NULL, \ + &sw_data_##n, &sw_cfg_##n, \ + POST_KERNEL, CONFIG_DP_DRIVER_INIT_PRIO, \ + &swdp_bitbang_api); + +DT_INST_FOREACH_STATUS_OKAY(SW_DEVICE_DEFINE) diff --git a/drivers/dp/swdp_ll_pin.h b/drivers/dp/swdp_ll_pin.h new file mode 100644 index 0000000000000..3044931a228a8 --- /dev/null +++ b/drivers/dp/swdp_ll_pin.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#if defined(CONFIG_SOC_SERIES_NRF52X) +#define CPU_CLOCK 64000000U +#else +#define CPU_CLOCK CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC +#endif + +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) +#define FAST_BITBANG_HW_SUPPORT 1 +#else +#define FAST_BITBANG_HW_SUPPORT 0 +#endif + +static ALWAYS_INLINE void pin_delay_asm(uint32_t delay) +{ +#if defined(CONFIG_CPU_CORTEX_M) + __asm volatile ("movs r3, %[p]\n" + ".start_%=:\n" + "subs r3, #1\n" + "bne .start_%=\n" + : + : [p] "r" (delay) + : "r3", "cc" + ); +#else +#warning "Pin delay is not defined" +#endif +} + +static ALWAYS_INLINE void swdp_ll_pin_input(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + reg->PIN_CNF[pin] = 0b0000; +#endif +} + +static ALWAYS_INLINE void swdp_ll_pin_output(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + reg->PIN_CNF[pin] = 0b0001; +#endif +} + + +static ALWAYS_INLINE void swdp_ll_pin_set(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + reg->OUTSET = BIT(pin); +#endif +} + +static ALWAYS_INLINE void swdp_ll_pin_clr(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + reg->OUTCLR = BIT(pin); +#endif +} + +static ALWAYS_INLINE uint32_t swdp_ll_pin_get(void *const base, uint8_t pin) +{ +#if defined(CONFIG_SOC_SERIES_NRF52X) || defined(CONFIG_SOC_SERIES_NRF53X) + NRF_GPIO_Type * reg = base; + + return ((reg->IN >> pin) & 1); +#else + return 0UL; +#endif +} diff --git a/drivers/edac/edac_ibecc.c b/drivers/edac/edac_ibecc.c index 06033a2bbb407..f8ea556f434ba 100644 --- a/drivers/edac/edac_ibecc.c +++ b/drivers/edac/edac_ibecc.c @@ -387,7 +387,7 @@ static bool handle_nmi(void) return true; } -bool z_x86_do_kernel_nmi(const z_arch_esf_t *esf) +bool z_x86_do_kernel_nmi(const struct arch_esf *esf) { const struct device *const dev = DEVICE_DT_GET(DEVICE_NODE); struct ibecc_data *data = dev->data; diff --git a/drivers/eeprom/Kconfig b/drivers/eeprom/Kconfig index 29405f4ed65fb..43eb02e5f283a 100644 --- a/drivers/eeprom/Kconfig +++ b/drivers/eeprom/Kconfig @@ -64,22 +64,36 @@ config EMUL_EEPROM_AT2X [DEPRECATED] Select EEPROM_AT2X_EMUL instead. config EEPROM_AT24 - bool "Atmel AT24 (and compatible) I2C EEPROM support" + bool "I2C EEPROMs compatible with Atmel's AT24 family" default y depends on DT_HAS_ATMEL_AT24_ENABLED select I2C select EEPROM_AT2X help - Enable support for Atmel AT24 (and compatible) I2C EEPROMs. + Enable support for I2C EEPROMs compatible with Atmel's AT24 family. + + There are multiple vendors manufacturing I2C EEPROMs compatible with + the programming model of the Atmel AT24. + + Examples of compatible EEPROM families: + - Microchip AT24xxx + - ST M24xxx config EEPROM_AT25 - bool "Atmel AT25 (and compatible) SPI EEPROM support" + bool "SPI EEPROMs compatibile with Atmel's AT25 family" default y depends on DT_HAS_ATMEL_AT25_ENABLED select SPI select EEPROM_AT2X help - Enable support for Atmel AT25 (and compatible) SPI EEPROMs. + Enable support for SPI EEPROMs compatible with Atmel's AT25 family. + + There are multiple vendors manufacturing SPI EEPROMs compatible with + the programming model of the Atmel AT25. + + Examples of compatible EEPROM families: + - Microchip AT25xxx + - ST M95xxx config EEPROM_AT2X_INIT_PRIORITY int "AT2X EEPROM init priority" diff --git a/drivers/eeprom/eeprom_handlers.c b/drivers/eeprom/eeprom_handlers.c index 9b1406a60043a..94a3d4f473ed0 100644 --- a/drivers/eeprom/eeprom_handlers.c +++ b/drivers/eeprom/eeprom_handlers.c @@ -16,7 +16,7 @@ static inline int z_vrfy_eeprom_read(const struct device *dev, off_t offset, (void *)data, len); } -#include +#include static inline int z_vrfy_eeprom_write(const struct device *dev, off_t offset, const void *data, size_t len) @@ -26,11 +26,11 @@ static inline int z_vrfy_eeprom_write(const struct device *dev, off_t offset, return z_impl_eeprom_write((const struct device *)dev, offset, (const void *)data, len); } -#include +#include static inline size_t z_vrfy_eeprom_get_size(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_EEPROM(dev, size)); return z_impl_eeprom_get_size((const struct device *)dev); } -#include +#include diff --git a/drivers/entropy/entropy_handlers.c b/drivers/entropy/entropy_handlers.c index 76b7df3d0bd70..643aa77c16ad4 100644 --- a/drivers/entropy/entropy_handlers.c +++ b/drivers/entropy/entropy_handlers.c @@ -17,4 +17,4 @@ static inline int z_vrfy_entropy_get_entropy(const struct device *dev, (uint8_t *)buffer, len); } -#include +#include diff --git a/drivers/entropy/entropy_smartbond.c b/drivers/entropy/entropy_smartbond.c index 28b6f08e100bf..fecb7b07491e2 100644 --- a/drivers/entropy/entropy_smartbond.c +++ b/drivers/entropy/entropy_smartbond.c @@ -10,6 +10,12 @@ #include #include #include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(smartbond_entropy, CONFIG_ENTROPY_LOG_LEVEL); #define DT_DRV_COMPAT renesas_smartbond_trng @@ -41,6 +47,10 @@ struct entropy_smartbond_dev_data { RNG_POOL_DEFINE(isr, CONFIG_ENTROPY_SMARTBOND_ISR_POOL_SIZE); RNG_POOL_DEFINE(thr, CONFIG_ENTROPY_SMARTBOND_THR_POOL_SIZE); + +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + ATOMIC_DEFINE(pm_policy_state_flag, 1); +#endif }; static struct entropy_smartbond_dev_data entropy_smartbond_data; @@ -52,6 +62,33 @@ static struct entropy_smartbond_dev_data entropy_smartbond_data; #define FIFO_COUNT_MASK \ (TRNG_TRNG_FIFOLVL_REG_TRNG_FIFOFULL_Msk | TRNG_TRNG_FIFOLVL_REG_TRNG_FIFOLVL_Msk) +static inline void entropy_smartbond_pm_policy_state_lock_get(const struct device *dev) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + struct entropy_smartbond_dev_data *data = dev->data; + + if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) { + /* + * Prevent the SoC from etering the normal sleep state as PDC does not support + * waking up the application core following TRNG events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void entropy_smartbond_pm_policy_state_lock_put(const struct device *dev) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + struct entropy_smartbond_dev_data *data = dev->data; + + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) { + /* Allow the SoC to enter the nornmal sleep state once TRNG is inactive */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + static void trng_enable(bool enable) { unsigned int key; @@ -60,9 +97,17 @@ static void trng_enable(bool enable) if (enable) { CRG_TOP->CLK_AMBA_REG |= CRG_TOP_CLK_AMBA_REG_TRNG_CLK_ENABLE_Msk; TRNG->TRNG_CTRL_REG = TRNG_TRNG_CTRL_REG_TRNG_ENABLE_Msk; + + /* + * Sleep is not allowed as long as the ISR and thread SW FIFOs + * are being filled with random numbers. + */ + entropy_smartbond_pm_policy_state_lock_get(DEVICE_DT_INST_GET(0)); } else { CRG_TOP->CLK_AMBA_REG &= ~CRG_TOP_CLK_AMBA_REG_TRNG_CLK_ENABLE_Msk; TRNG->TRNG_CTRL_REG = 0; + + entropy_smartbond_pm_policy_state_lock_put(DEVICE_DT_INST_GET(0)); } irq_unlock(key); } @@ -312,11 +357,11 @@ static int entropy_smartbond_get_entropy_isr(const struct device *dev, uint8_t * } NVIC_ClearPendingIRQ(IRQN); - if (random_word_get(buf) != 0) { + if (random_word_get(bytes) != 0) { continue; } - while (ptr < limit) { + while (ptr < limit && len) { buf[--len] = *ptr++; } /* Store remaining data for later use */ @@ -334,6 +379,33 @@ static int entropy_smartbond_get_entropy_isr(const struct device *dev, uint8_t * return cnt; } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static int entropy_smartbond_pm_action(const struct device *dev, enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + /* + * No need to turn on TRNG. It should be done when we the space in the FIFOs + * are below the defined ISR and thread FIFO's thresholds. + * + * \sa CONFIG_ENTROPY_SMARTBOND_THR_THRESHOLD + * \sa CONFIG_ENTROPY_SMARTBOND_ISR_THRESHOLD + * + */ + break; + case PM_DEVICE_ACTION_SUSPEND: + /* At this point TRNG should be disabled; no need to turn it off. */ + break; + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif + static const struct entropy_driver_api entropy_smartbond_api_funcs = { .get_entropy = entropy_smartbond_get_entropy, .get_entropy_isr = entropy_smartbond_get_entropy_isr}; @@ -361,8 +433,18 @@ static int entropy_smartbond_init(const struct device *dev) trng_enable(true); +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + return pm_device_runtime_enable(dev); +#endif + return 0; } -DEVICE_DT_INST_DEFINE(0, entropy_smartbond_init, NULL, &entropy_smartbond_data, NULL, PRE_KERNEL_1, - CONFIG_ENTROPY_INIT_PRIORITY, &entropy_smartbond_api_funcs); +PM_DEVICE_DT_INST_DEFINE(0, entropy_smartbond_pm_action); + +DEVICE_DT_INST_DEFINE(0, entropy_smartbond_init, PM_DEVICE_DT_INST_GET(0), + &entropy_smartbond_data, NULL, PRE_KERNEL_1, + CONFIG_ENTROPY_INIT_PRIORITY, &entropy_smartbond_api_funcs); diff --git a/drivers/entropy/entropy_stm32.c b/drivers/entropy/entropy_stm32.c index a9cbda2abc730..2b079da3b8bf9 100644 --- a/drivers/entropy/entropy_stm32.c +++ b/drivers/entropy/entropy_stm32.c @@ -112,6 +112,10 @@ static int entropy_stm32_suspend(void) RNG_TypeDef *rng = dev_data->rng; int res; +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + /* Prevent concurrent access with PM */ + z_stm32_hsem_lock(CFG_HW_RNG_SEMID, HSEM_LOCK_WAIT_FOREVER); +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ LL_RNG_Disable(rng); #ifdef CONFIG_SOC_SERIES_STM32WBAX @@ -136,6 +140,10 @@ static int entropy_stm32_suspend(void) res = clock_control_off(dev_data->clock, (clock_control_subsys_t)&dev_cfg->pclken[0]); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + z_stm32_hsem_unlock(CFG_HW_RNG_SEMID); +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ + return res; } @@ -710,7 +718,12 @@ static int entropy_stm32_rng_pm_action(const struct device *dev, switch (action) { case PM_DEVICE_ACTION_SUSPEND: - res = entropy_stm32_suspend(); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + /* Lock to Prevent concurrent access with PM */ + z_stm32_hsem_lock(CFG_HW_RNG_SEMID, HSEM_LOCK_WAIT_FOREVER); + /* Call release_rng instead of entropy_stm32_suspend to avoid double hsem_unlock */ +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ + release_rng(); break; case PM_DEVICE_ACTION_RESUME: if (IS_ENABLED(CONFIG_PM_S2RAM)) { @@ -724,7 +737,15 @@ static int entropy_stm32_rng_pm_action(const struct device *dev, entropy_stm32_rng_init(dev); } else if (!entropy_stm32_rng_data.filling_pools) { /* Resume RNG only if it was suspended during filling pool */ - entropy_stm32_suspend(); +#if defined(CONFIG_SOC_SERIES_STM32WBX) || defined(CONFIG_STM32H7_DUAL_CORE) + /* Lock to Prevent concurrent access with PM */ + z_stm32_hsem_lock(CFG_HW_RNG_SEMID, HSEM_LOCK_WAIT_FOREVER); + /* + * Call release_rng instead of entropy_stm32_suspend + * to avoid double hsem_unlock + */ +#endif /* CONFIG_SOC_SERIES_STM32WBX || CONFIG_STM32H7_DUAL_CORE */ + release_rng(); } #endif /* health_test_config */ } else { diff --git a/drivers/espi/CMakeLists.txt b/drivers/espi/CMakeLists.txt index 5379d00ea2106..4826880f48299 100644 --- a/drivers/espi/CMakeLists.txt +++ b/drivers/espi/CMakeLists.txt @@ -10,8 +10,8 @@ zephyr_library_sources_ifdef(CONFIG_ESPI_NPCX host_subs_npcx.c) zephyr_library_sources_ifdef(CONFIG_ESPI_TAF_NPCX espi_taf_npcx.c) zephyr_library_sources_ifdef(CONFIG_USERSPACE espi_handlers.c) zephyr_library_sources_ifdef(CONFIG_ESPI_EMUL espi_emul.c) -zephyr_library_sources_ifdef(CONFIG_ESPI_SAF_XEC espi_saf_mchp_xec.c) +zephyr_library_sources_ifdef(CONFIG_ESPI_TAF_XEC espi_saf_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_ESPI_XEC_V2 espi_mchp_xec_v2.c) zephyr_library_sources_ifdef(CONFIG_ESPI_XEC_V2 espi_mchp_xec_host_v2.c) zephyr_library_sources_ifdef(CONFIG_ESPI_IT8XXX2 espi_it8xxx2.c) -zephyr_library_sources_ifdef(CONFIG_ESPI_SAF_XEC_V2 espi_saf_mchp_xec_v2.c) +zephyr_library_sources_ifdef(CONFIG_ESPI_TAF_XEC_V2 espi_saf_mchp_xec_v2.c) diff --git a/drivers/espi/Kconfig b/drivers/espi/Kconfig index 0a8f6173b8d73..0bfacd1581259 100644 --- a/drivers/espi/Kconfig +++ b/drivers/espi/Kconfig @@ -22,11 +22,11 @@ module = ESPI module-str = espi source "subsys/logging/Kconfig.template.log_config" -config ESPI_SLAVE - bool "ESPI slave driver" +config ESPI_TARGET + bool "ESPI target driver" default y help - Enables eSPI driver in slave mode. + Enables eSPI driver in target mode. config ESPI_INIT_PRIORITY int "ESPI Controller driver initialization priority" @@ -50,20 +50,20 @@ config ESPI_AUTOMATIC_WARNING_ACKNOWLEDGE bool "Automatic acknowledge for eSPI HOST warnings" default y depends on ESPI_VWIRE_CHANNEL - depends on ESPI_SLAVE + depends on ESPI_TARGET help - Enable automatic acknowledgment from eSPI slave towards eSPI host + Enable automatic acknowledgment from eSPI target towards eSPI controller whenever it receives suspend or reset warning. If this is disabled, it means the app wants to be give the opportunity to prepare for either HOST suspend or reset. config ESPI_AUTOMATIC_BOOT_DONE_ACKNOWLEDGE - bool "Automatic acknowledge slave boot status" + bool "Automatic acknowledge target boot status" default y depends on ESPI_VWIRE_CHANNEL - depends on ESPI_SLAVE + depends on ESPI_TARGET help - Enable automatic acknowledgment from slave basic configuration been + Enable automatic acknowledgment from target basic configuration been completed by sending a virtual wire message to the eSPI master. This depends on SPI boot configuration. It could be either very early in the flow after the VW channel is configured. Or it could be @@ -176,19 +176,19 @@ config ESPI_OOB_CHANNEL_RX_ASYNC Enables asynchronous handling for host-initiated OOB traffic. Otherwise OOB traffic is assumed to be always client-initiated. -config ESPI_SAF - bool "ESPI SAF driver" +config ESPI_TAF + bool "ESPI TAF driver" depends on ESPI_FLASH_CHANNEL help - Enable Slave Attached Flash eSPI driver. SAF depends upon ESPI driver + Enable Target Attached Flash eSPI driver. TAF depends upon ESPI driver and flash channel. -config ESPI_SAF_INIT_PRIORITY - int "ESPI SAF driver initialization priority" - depends on ESPI_SAF +config ESPI_TAF_INIT_PRIORITY + int "ESPI TAF driver initialization priority" + depends on ESPI_TAF default 4 help - Driver initialization priority for eSPI SAF driver. SAF driver must + Driver initialization priority for eSPI TAF driver. TAF driver must initialize after the ESPI driver. endif # ESPI diff --git a/drivers/espi/Kconfig.it8xxx2 b/drivers/espi/Kconfig.it8xxx2 index e018f86951571..6c19eb2514c1e 100644 --- a/drivers/espi/Kconfig.it8xxx2 +++ b/drivers/espi/Kconfig.it8xxx2 @@ -127,4 +127,19 @@ config ESPI_IT8XXX2_PNPCFG_DEVICE_KBC_MOUSE With this option enabled, EC will send IRQ12 signal to host when the KBC mouse output buffer is full. +# On IT8xxx2 series, this configuration option has limitation: +# Port 80 and 81 I/O cycles share the same interrupt source and there is no +# status bit to indicate which cycle triggered the interrupt and data registers +# of these two ports are read only. Hence EC have to read these two data +# registers at the same time in the ISR. +# It means that the Host must alwasy write 2 bytes of data to port 80 otherwise +# port 81 data will not be updated. +config ESPI_IT8XXX2_PORT_81_CYCLE + bool "EC accepts 0x81 I/O cycle from eSPI transaction" + depends on ESPI_PERIPHERAL_DEBUG_PORT_80 + help + With this option enabled, EC will accept 0x81 I/O cycle from the Host. + This allows EC to accept 2 bytes of port 80 data written from the Host. + (e.g. using iotools: iotools io_write16 0x80 0x1234) + endif #ESPI_IT8XXX2 diff --git a/drivers/espi/Kconfig.npcx b/drivers/espi/Kconfig.npcx index 0d0d1202f8e89..884b5cdd4d9a1 100644 --- a/drivers/espi/Kconfig.npcx +++ b/drivers/espi/Kconfig.npcx @@ -46,6 +46,7 @@ config ESPI_NPCX_BYPASS_CH_ENABLE_FATAL_ERROR config ESPI_NPCX_PERIPHERAL_DEBUG_PORT_80_MULTI_BYTE bool "Host can write 1/2/4 bytes of Port80 data in a eSPI transaction" depends on (SOC_SERIES_NPCX9 || SOC_SERIES_NPCX4) && ESPI_PERIPHERAL_DEBUG_PORT_80 + select RING_BUFFER help EC can accept 1/2/4 bytes of Port 80 data written from the Host in an eSPI transaction. diff --git a/drivers/espi/Kconfig.xec b/drivers/espi/Kconfig.xec index b1752285c59c7..cbf749467c7ca 100644 --- a/drivers/espi/Kconfig.xec +++ b/drivers/espi/Kconfig.xec @@ -63,21 +63,21 @@ config ESPI_FLASH_BUFFER_SIZE Use maximum RAM buffer size defined by spec but allow applications to override if eSPI host doesn't support it. -config ESPI_SAF_XEC - bool "XEC Microchip ESPI SAF driver" +config ESPI_TAF_XEC + bool "XEC Microchip ESPI TAF driver" default y depends on SOC_SERIES_MEC15XX depends on DT_HAS_MICROCHIP_XEC_ESPI_SAF_ENABLED help - Enable the Microchip XEC SAF ESPI driver for MEC15xx family. + Enable the Microchip XEC TAF ESPI driver for MEC15xx family. -config ESPI_SAF_XEC_V2 - bool "XEC Microchip ESPI SAF V2 driver" +config ESPI_TAF_XEC_V2 + bool "XEC Microchip ESPI TAF V2 driver" default y depends on SOC_SERIES_MEC172X depends on DT_HAS_MICROCHIP_XEC_ESPI_SAF_V2_ENABLED help - Enable the Microchip XEC SAF ESPI driver for MEC172x series. + Enable the Microchip XEC TAF ESPI driver for MEC172x series. endif #ESPI_XEC @@ -154,19 +154,19 @@ config ESPI_PERIPHERAL_XEC_EMI2 endif #ESPI_PERIPHERAL_CHANNEL -config ESPI_SAF - bool "XEC Microchip ESPI SAF driver" +config ESPI_TAF + bool "XEC Microchip ESPI TAF driver" depends on ESPI_FLASH_CHANNEL help - Enable Slave Attached Flash eSPI driver. SAF depends upon ESPI XEC driver + Enable Target Attached Flash eSPI driver. TAF depends upon ESPI XEC driver and flash channel. -config ESPI_SAF_INIT_PRIORITY - int "ESPI SAF driver initialization priority" - depends on ESPI_SAF +config ESPI_TAF_INIT_PRIORITY + int "ESPI TAF driver initialization priority" + depends on ESPI_TAF default 4 help - Driver initialization priority for eSPI SAF driver. + Driver initialization priority for ESPI TAF driver. config ESPI_PERIPHERAL_ACPI_EC_IBF_EVT_DATA bool "Read ACPI EC Event Data in IBF ISR" diff --git a/drivers/espi/espi_handlers.c b/drivers/espi/espi_handlers.c index c215838fd7951..703300adc6a44 100644 --- a/drivers/espi/espi_handlers.c +++ b/drivers/espi/espi_handlers.c @@ -19,7 +19,7 @@ static inline int z_vrfy_espi_config(const struct device *dev, return z_impl_espi_config(dev, &cfg_copy); } -#include +#include static inline bool z_vrfy_espi_get_channel_status(const struct device *dev, enum espi_channel ch) @@ -28,7 +28,7 @@ static inline bool z_vrfy_espi_get_channel_status(const struct device *dev, return z_impl_espi_get_channel_status(dev, ch); } -#include +#include static inline int z_vrfy_espi_read_lpc_request(const struct device *dev, enum lpc_peripheral_opcode op, @@ -44,7 +44,7 @@ static inline int z_vrfy_espi_read_lpc_request(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_write_lpc_request(const struct device *dev, enum lpc_peripheral_opcode op, @@ -57,7 +57,7 @@ static inline int z_vrfy_espi_write_lpc_request(const struct device *dev, return z_impl_espi_write_lpc_request(dev, op, &data_copy); } -#include +#include static inline int z_vrfy_espi_send_vwire(const struct device *dev, enum espi_vwire_signal signal, @@ -67,7 +67,7 @@ static inline int z_vrfy_espi_send_vwire(const struct device *dev, return z_impl_espi_send_vwire(dev, signal, level); } -#include +#include static inline int z_vrfy_espi_receive_vwire(const struct device *dev, enum espi_vwire_signal signal, @@ -83,7 +83,7 @@ static inline int z_vrfy_espi_receive_vwire(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_read_request(const struct device *dev, struct espi_request_packet *req) @@ -103,7 +103,7 @@ static inline int z_vrfy_espi_read_request(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_write_request(const struct device *dev, struct espi_request_packet *req) @@ -120,7 +120,7 @@ static inline int z_vrfy_espi_write_request(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_send_oob(const struct device *dev, struct espi_oob_packet *pckt) @@ -137,7 +137,7 @@ static inline int z_vrfy_espi_send_oob(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_receive_oob(const struct device *dev, struct espi_oob_packet *pckt) @@ -156,7 +156,7 @@ static inline int z_vrfy_espi_receive_oob(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_read_flash(const struct device *dev, struct espi_flash_packet *pckt) @@ -175,7 +175,7 @@ static inline int z_vrfy_espi_read_flash(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_write_flash(const struct device *dev, struct espi_flash_packet *pckt) @@ -192,7 +192,7 @@ static inline int z_vrfy_espi_write_flash(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_espi_flash_erase(const struct device *dev, struct espi_flash_packet *pckt) @@ -209,4 +209,4 @@ static inline int z_vrfy_espi_flash_erase(const struct device *dev, return ret; } -#include +#include diff --git a/drivers/espi/espi_it8xxx2.c b/drivers/espi/espi_it8xxx2.c index bd0d83c02103e..f0510c7f1f586 100644 --- a/drivers/espi/espi_it8xxx2.c +++ b/drivers/espi/espi_it8xxx2.c @@ -517,7 +517,11 @@ static void port80_it8xxx2_isr(const struct device *dev) ESPI_PERIPHERAL_NODATA }; - evt.evt_data = gctrl->GCTRL_P80HDR; + if (IS_ENABLED(CONFIG_ESPI_IT8XXX2_PORT_81_CYCLE)) { + evt.evt_data = gctrl->GCTRL_P80HDR | (gctrl->GCTRL_P81HDR << 8); + } else { + evt.evt_data = gctrl->GCTRL_P80HDR; + } /* Write 1 to clear this bit */ gctrl->GCTRL_P80H81HSR |= BIT(0); @@ -529,8 +533,13 @@ static void port80_it8xxx2_init(const struct device *dev) ARG_UNUSED(dev); struct gctrl_it8xxx2_regs *const gctrl = ESPI_IT8XXX2_GET_GCTRL_BASE; - /* Accept Port 80h Cycle */ - gctrl->GCTRL_SPCTRL1 |= IT8XXX2_GCTRL_ACP80; + /* Accept Port 80h (and 81h) Cycle */ + if (IS_ENABLED(CONFIG_ESPI_IT8XXX2_PORT_81_CYCLE)) { + gctrl->GCTRL_SPCTRL1 |= + (IT8XXX2_GCTRL_ACP80 | IT8XXX2_GCTRL_ACP81); + } else { + gctrl->GCTRL_SPCTRL1 |= IT8XXX2_GCTRL_ACP80; + } IRQ_CONNECT(IT8XXX2_PORT_80_IRQ, 0, port80_it8xxx2_isr, DEVICE_DT_INST_GET(0), 0); irq_enable(IT8XXX2_PORT_80_IRQ); diff --git a/drivers/espi/espi_npcx.c b/drivers/espi/espi_npcx.c index d7cece4eb07d5..3d3f2c7107314 100644 --- a/drivers/espi/espi_npcx.c +++ b/drivers/espi/espi_npcx.c @@ -69,6 +69,7 @@ struct espi_npcx_data { #define NPCX_ESPI_MAXFREQ_25 1 #define NPCX_ESPI_MAXFREQ_33 2 #define NPCX_ESPI_MAXFREQ_50 3 +#define NPCX_ESPI_MAXFREQ_66 4 /* Minimum delay before acknowledging a virtual wire */ #define NPCX_ESPI_VWIRE_ACK_DELAY 10ul /* 10 us */ @@ -309,8 +310,8 @@ static void espi_bus_cfg_update_isr(const struct device *dev) espi_vw_send_bootload_done(dev); } -#if (defined(CONFIG_ESPI_FLASH_CHANNEL) && defined(CONFIG_ESPI_SAF)) - /* If CONFIG_ESPI_SAF is set, set to auto or manual mode accroding +#if (defined(CONFIG_ESPI_FLASH_CHANNEL) && defined(CONFIG_ESPI_TAF)) + /* If CONFIG_ESPI_TAF is set, set to auto or manual mode accroding * to configuration. */ if (IS_BIT_SET(inst->ESPICFG, NPCX_ESPICFG_FLCHANMODE)) { @@ -347,7 +348,7 @@ static void espi_bus_oob_rx_isr(const struct device *dev) #endif #if defined(CONFIG_ESPI_FLASH_CHANNEL) -#if defined(CONFIG_ESPI_SAF) +#if defined(CONFIG_ESPI_TAF) static struct espi_taf_pckt taf_pckt; static uint32_t espi_taf_parse(const struct device *dev) @@ -363,7 +364,7 @@ static uint32_t espi_taf_parse(const struct device *dev) taf_pckt.len = (((uint16_t)taf_head.tag_hlen & 0xF) << 8) | taf_head.llen; taf_pckt.tag = taf_head.tag_hlen >> 4; - if ((taf_pckt.len == 0) && ((taf_pckt.type & 0xF) == NPCX_ESPI_TAF_REQ_READ)) { + if ((taf_pckt.len == 0) && (taf_pckt.type == NPCX_ESPI_TAF_REQ_READ)) { taf_pckt.len = KB(4); } @@ -372,7 +373,7 @@ static uint32_t espi_taf_parse(const struct device *dev) taf_pckt.addr = sys_cpu_to_be32(taf_addr); /* Get written data if eSPI TAF write */ - if ((taf_pckt.type & 0xF) == NPCX_ESPI_TAF_REQ_WRITE) { + if (taf_pckt.type == NPCX_ESPI_TAF_REQ_WRITE) { roundsize = DIV_ROUND_UP(taf_pckt.len, sizeof(uint32_t)); for (i = 0; i < roundsize; i++) { taf_pckt.src[i] = inst->FLASHRXBUF[2 + i]; @@ -381,7 +382,7 @@ static uint32_t espi_taf_parse(const struct device *dev) return (uint32_t)&taf_pckt; } -#endif /* CONFIG_ESPI_SAF */ +#endif /* CONFIG_ESPI_TAF */ static void espi_bus_flash_rx_isr(const struct device *dev) { @@ -403,9 +404,9 @@ static void espi_bus_flash_rx_isr(const struct device *dev) #endif k_sem_give(&data->flash_rx_lock); } else { /* Target Attached Flash Access */ -#if defined(CONFIG_ESPI_SAF) +#if defined(CONFIG_ESPI_TAF) struct espi_event evt = { - .evt_type = ESPI_BUS_SAF_NOTIFICATION, + .evt_type = ESPI_BUS_TAF_NOTIFICATION, .evt_details = ESPI_CHANNEL_FLASH, .evt_data = espi_taf_parse(dev), }; @@ -415,27 +416,7 @@ static void espi_bus_flash_rx_isr(const struct device *dev) #endif } } - -static void espi_bus_completion_sent_isr(const struct device *dev) -{ - struct espi_reg *const inst = HAL_INSTANCE(dev); - - /* check that ESPISTS.FLNACS is clear. */ - if (IS_BIT_SET(inst->ESPISTS, NPCX_ESPISTS_FLNACS)) { - LOG_ERR("ESPISTS_FLNACS not clear\r\n"); - } - - /* flash operation is done, Make sure the TAFS transmit buffer is empty */ - if (IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL)) { - LOG_ERR("FLASH_TX_AVAIL not clear\r\n"); - } - - /* In auto mode, release FLASH_NP_FREE here to get next SAF request.*/ - if (IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_SAF_AUTO_READ)) { - inst->FLASHCTL |= BIT(NPCX_FLASHCTL_FLASH_NP_FREE); - } -} -#endif +#endif /* CONFIG_ESPI_FLASH_CHANNEL */ const struct espi_bus_isr espi_bus_isr_tbl[] = { NPCX_ESPI_BUS_INT_ITEM(BERR, espi_bus_err_isr), @@ -447,7 +428,6 @@ const struct espi_bus_isr espi_bus_isr_tbl[] = { #endif #if defined(CONFIG_ESPI_FLASH_CHANNEL) NPCX_ESPI_BUS_INT_ITEM(FLASHRX, espi_bus_flash_rx_isr), - NPCX_ESPI_BUS_INT_ITEM(FLNACS, espi_bus_completion_sent_isr), #endif }; @@ -697,6 +677,11 @@ static int espi_npcx_configure(const struct device *dev, struct espi_cfg *cfg) case 50: max_freq = NPCX_ESPI_MAXFREQ_50; break; +#ifdef CONFIG_SOC_SERIES_NPCX4 + case 66: + max_freq = NPCX_ESPI_MAXFREQ_66; + break; +#endif default: return -EINVAL; } @@ -1416,6 +1401,10 @@ static int espi_npcx_init(const struct device *dev) /* Configure host sub-modules which HW blocks belong to core domain */ npcx_host_init_subs_core_domain(dev, &data->callbacks); +#if defined(CONFIG_ESPI_FLASH_CHANNEL) && defined(CONFIG_ESPI_TAF) + npcx_init_taf(dev, &data->callbacks); +#endif + /* eSPI Bus interrupt installation */ IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), diff --git a/drivers/espi/espi_saf_mchp_xec.c b/drivers/espi/espi_saf_mchp_xec.c index 6dd39b4f1b0fe..d649deaaa14f0 100644 --- a/drivers/espi/espi_saf_mchp_xec.c +++ b/drivers/espi/espi_saf_mchp_xec.c @@ -849,7 +849,7 @@ static const struct espi_saf_xec_config espi_saf_xec_config = { DEVICE_DT_INST_DEFINE(0, &espi_saf_xec_init, NULL, &espi_saf_xec_data, &espi_saf_xec_config, POST_KERNEL, - CONFIG_ESPI_SAF_INIT_PRIORITY, &espi_saf_xec_driver_api); + CONFIG_ESPI_TAF_INIT_PRIORITY, &espi_saf_xec_driver_api); static int espi_saf_xec_init(const struct device *dev) { diff --git a/drivers/espi/espi_saf_mchp_xec_v2.c b/drivers/espi/espi_saf_mchp_xec_v2.c index aa7ea6905816d..67fb4a5162fe2 100644 --- a/drivers/espi/espi_saf_mchp_xec_v2.c +++ b/drivers/espi/espi_saf_mchp_xec_v2.c @@ -1027,7 +1027,7 @@ static void espi_saf_done_isr(const struct device *dev) struct mchp_espi_saf * const regs = xcfg->saf_base; const struct espi_xec_irq_info *safirq = &xcfg->irq_info_list[0]; uint32_t ecp_status = regs->SAF_ECP_STATUS; - struct espi_event evt = { .evt_type = ESPI_BUS_SAF_NOTIFICATION, + struct espi_event evt = { .evt_type = ESPI_BUS_TAF_NOTIFICATION, .evt_details = BIT(0), .evt_data = ecp_status }; @@ -1142,7 +1142,7 @@ static int espi_saf_xec_init(const struct device *dev) DEVICE_DT_INST_DEFINE(0, &espi_saf_xec_init, NULL, \ &espisaf_xec_data_##n, \ &espisaf_xec_config_##n, POST_KERNEL, \ - CONFIG_ESPI_SAF_INIT_PRIORITY, \ + CONFIG_ESPI_TAF_INIT_PRIORITY, \ &espi_saf_xec_driver_api); \ \ static void espi_saf_xec_connect_irqs_##n(void) \ diff --git a/drivers/espi/espi_taf_npcx.c b/drivers/espi/espi_taf_npcx.c index 722b26730e8cd..7878df2b123af 100644 --- a/drivers/espi/espi_taf_npcx.c +++ b/drivers/espi/espi_taf_npcx.c @@ -17,6 +17,14 @@ LOG_MODULE_REGISTER(espi_taf, CONFIG_ESPI_LOG_LEVEL); static const struct device *const spi_dev = DEVICE_DT_GET(DT_ALIAS(taf_flash)); +enum ESPI_TAF_ERASE_LEN { + NPCX_ESPI_TAF_ERASE_LEN_4KB, + NPCX_ESPI_TAF_ERASE_LEN_32KB, + NPCX_ESPI_TAF_ERASE_LEN_64KB, + NPCX_ESPI_TAF_ERASE_LEN_128KB, + NPCX_ESPI_TAF_ERASE_LEN_MAX, +}; + struct espi_taf_npcx_config { uintptr_t base; uintptr_t mapped_addr; @@ -26,9 +34,19 @@ struct espi_taf_npcx_config { }; struct espi_taf_npcx_data { - sys_slist_t callbacks; + sys_slist_t *callbacks; + const struct device *host_dev; + uint8_t taf_type; + uint8_t taf_tag; + uint32_t address; + uint16_t length; + uint32_t src[16]; + struct k_work work; }; +static struct espi_taf_npcx_data npcx_espi_taf_data; +static struct espi_callback espi_taf_cb; + #define HAL_INSTANCE(dev) \ ((struct espi_reg *)((const struct espi_taf_npcx_config *) \ (dev)->config)->base) @@ -45,6 +63,24 @@ struct espi_taf_npcx_data { GET_FIELD(inst->FLASH_PRTR_HADDR[i], NPCX_FLASH_PRTR_HADDR) \ << GET_FIELD_POS(NPCX_FLASH_PRTR_HADDR)) | 0xFFF; +static void espi_taf_get_pckt(const struct device *dev, struct espi_taf_npcx_data *pckt, + struct espi_event event) +{ + struct espi_taf_pckt *data_ptr; + + data_ptr = (struct espi_taf_pckt *)event.evt_data; + + pckt->taf_type = data_ptr->type; + pckt->length = data_ptr->len; + pckt->taf_tag = data_ptr->tag; + pckt->address = data_ptr->addr; + + if (data_ptr->type == NPCX_ESPI_TAF_REQ_WRITE) { + memcpy(pckt->src, data_ptr->src, sizeof(pckt->src)); + } +} + +#if defined(CONFIG_ESPI_TAF_MANUAL_MODE) /* Check access region of read request is protected or not */ static bool espi_taf_check_read_protect(const struct device *dev, uint32_t addr, uint32_t len, uint8_t tag) @@ -73,6 +109,7 @@ static bool espi_taf_check_read_protect(const struct device *dev, uint32_t addr, return false; } +#endif /* Check access region of write request is protected or not */ static bool espi_taf_check_write_protect(const struct device *dev, uint32_t addr, @@ -107,11 +144,16 @@ static int espi_taf_npcx_configure(const struct device *dev, const struct espi_s { struct espi_reg *const inst = HAL_INSTANCE(dev); + if (cfg->nflash_devices == 0U) { + return -EINVAL; + } + #if defined(CONFIG_ESPI_TAF_AUTO_MODE) inst->FLASHCTL |= BIT(NPCX_FLASHCTL_SAF_AUTO_READ); #else inst->FLASHCTL &= ~BIT(NPCX_FLASHCTL_SAF_AUTO_READ); #endif + return 0; } @@ -173,10 +215,17 @@ static int espi_taf_npcx_activate(const struct device *dev) static bool espi_taf_npcx_channel_ready(const struct device *dev) { struct espi_reg *const inst = HAL_INSTANCE(dev); + uint8_t ret = + GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLCAPA) & NPCX_FLASH_SHARING_CAP_SUPP_TAF; - if (!IS_BIT_SET(inst->ESPICFG, NPCX_ESPICFG_FLCHANMODE)) { + if (ret != NPCX_FLASH_SHARING_CAP_SUPP_TAF) { return false; } + + if (!device_is_ready(spi_dev)) { + return false; + } + return true; } @@ -214,52 +263,58 @@ static void taf_release_flash_np_free(const struct device *dev) inst->FLASHCTL = tmp; } -static int taf_npcx_completion_handler(const struct device *dev, uint32_t *buffer) +static int taf_npcx_completion_handler(const struct device *dev, uint8_t type, uint8_t tag, + uint16_t len, uint32_t *buffer) { - uint16_t size = DIV_ROUND_UP((uint8_t)(buffer[0]) + 1, sizeof(uint32_t)); struct espi_reg *const inst = HAL_INSTANCE(dev); - struct npcx_taf_head *head = (struct npcx_taf_head *)buffer; - uint8_t i; + struct npcx_taf_head taf_head; + uint16_t i, size; + uint32_t tx_buf[16]; + + taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN + len; + taf_head.type = type; + taf_head.tag_hlen = (tag << 4) | ((len & 0xF00) >> 8); + taf_head.llen = len & 0xFF; + + memcpy(&tx_buf[0], &taf_head, sizeof(struct npcx_taf_head)); + + if (type == CYC_SCS_CMP_WITH_DATA_ONLY || type == CYC_SCS_CMP_WITH_DATA_FIRST || + type == CYC_SCS_CMP_WITH_DATA_MIDDLE || type == CYC_SCS_CMP_WITH_DATA_LAST) { + memcpy(&tx_buf[1], buffer, (uint8_t)(len)); + } /* Check the Flash Access TX Queue is empty by polling * FLASH_TX_AVAIL. */ - if (WAIT_FOR(IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL), - NPCX_FLASH_CHK_TIMEOUT, NULL)) { + if (WAIT_FOR(!IS_BIT_SET(inst->FLASHCTL, NPCX_FLASHCTL_FLASH_TX_AVAIL), + NPCX_FLASH_CHK_TIMEOUT, NULL) == false) { LOG_ERR("Check TX Queue Is Empty Timeout"); return -EBUSY; } - /* Check ESPISTS.FLNACS is clear (no slave completion is detected) */ - if (WAIT_FOR(IS_BIT_SET(inst->ESPISTS, NPCX_ESPISTS_FLNACS), - NPCX_FLASH_CHK_TIMEOUT, NULL)) { - LOG_ERR("Check Slave Completion Timeout"); - return -EBUSY; - } - /* Write packet to FLASHTXBUF */ + size = DIV_ROUND_UP((uint8_t)(tx_buf[0]) + 1, sizeof(uint32_t)); for (i = 0; i < size; i++) { - inst->FLASHTXBUF[i] = buffer[i]; + inst->FLASHTXBUF[i] = tx_buf[i]; } /* Set the FLASHCTL.FLASH_TX_AVAIL bit to 1 to enqueue the packet */ taf_set_flash_c_avail(dev); /* Release FLASH_NP_FREE here to ready get next TAF request */ - if ((head->type != CYC_SCS_CMP_WITH_DATA_FIRST) && - (head->type != CYC_SCS_CMP_WITH_DATA_MIDDLE)) { + if ((type != CYC_SCS_CMP_WITH_DATA_FIRST) && (type != CYC_SCS_CMP_WITH_DATA_MIDDLE)) { taf_release_flash_np_free(dev); } return 0; } +#if defined(CONFIG_ESPI_TAF_MANUAL_MODE) static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_packet *pckt) { struct espi_reg *const inst = HAL_INSTANCE(dev); struct espi_taf_npcx_config *config = ((struct espi_taf_npcx_config *)(dev)->config); struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; - uint8_t *data_ptr = (uint8_t *)taf_data_ptr->data; uint8_t cycle_type = CYC_SCS_CMP_WITH_DATA_ONLY; uint32_t total_len = pckt->len; uint32_t len = total_len; @@ -267,7 +322,7 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa uint8_t flash_req_size = GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLASHREQSIZE); uint8_t target_max_size = GET_FIELD(inst->FLASHCFG, NPCX_FLASHCFG_FLREQSUP); uint16_t max_read_req = 32 << flash_req_size; - struct npcx_taf_head taf_head; + uint8_t read_buf[64]; int rc; if (flash_req_size > target_max_size) { @@ -297,21 +352,14 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa } do { - data_ptr = (uint8_t *)taf_data_ptr->data; - - taf_head.pkt_len = len + NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = cycle_type; - taf_head.tag_hlen = (taf_data_ptr->tag << 4) | ((len & 0xF00) >> 8); - taf_head.llen = len & 0xFF; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = flash_read(spi_dev, addr, data_ptr + 4, len); + rc = flash_read(spi_dev, addr, &read_buf[0], len); if (rc) { LOG_ERR("flash read fail 0x%x", rc); return -EIO; } - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, cycle_type, taf_data_ptr->tag, len, + (uint32_t *)&read_buf[0]); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -330,12 +378,12 @@ static int espi_taf_npcx_flash_read(const struct device *dev, struct espi_saf_pa return 0; } +#endif static int espi_taf_npcx_flash_write(const struct device *dev, struct espi_saf_packet *pckt) { struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; uint8_t *data_ptr = (uint8_t *)(taf_data_ptr->data); - struct npcx_taf_head taf_head; int rc; if (espi_taf_check_write_protect(dev, pckt->flash_addr, @@ -350,13 +398,8 @@ static int espi_taf_npcx_flash_write(const struct device *dev, struct espi_saf_p return -EIO; } - taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = CYC_SCS_CMP_WITHOUT_DATA; - taf_head.tag_hlen = (taf_data_ptr->tag << 4); - taf_head.llen = 0x0; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, CYC_SCS_CMP_WITHOUT_DATA, taf_data_ptr->tag, 0x0, + NULL); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -367,13 +410,19 @@ static int espi_taf_npcx_flash_write(const struct device *dev, struct espi_saf_p static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_packet *pckt) { + int erase_blk[] = {KB(4), KB(32), KB(64), KB(128)}; struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; - uint8_t *data_ptr = (uint8_t *)taf_data_ptr->data; uint32_t addr = pckt->flash_addr; - uint32_t len = pckt->len; - struct npcx_taf_head taf_head; + uint32_t len; int rc; + if ((pckt->len < 0) || (pckt->len >= NPCX_ESPI_TAF_ERASE_LEN_MAX)) { + LOG_ERR("Invalid erase block size"); + return -EINVAL; + } + + len = erase_blk[pckt->len]; + if (espi_taf_check_write_protect(dev, addr, len, taf_data_ptr->tag)) { LOG_ERR("Access protection region"); return -EINVAL; @@ -385,13 +434,8 @@ static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_p return -EIO; } - taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = CYC_SCS_CMP_WITHOUT_DATA; - taf_head.tag_hlen = (taf_data_ptr->tag << 4); - taf_head.llen = 0x0; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, CYC_SCS_CMP_WITHOUT_DATA, taf_data_ptr->tag, 0x0, + NULL); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -402,19 +446,11 @@ static int espi_taf_npcx_flash_erase(const struct device *dev, struct espi_saf_p static int espi_taf_npcx_flash_unsuccess(const struct device *dev, struct espi_saf_packet *pckt) { - struct espi_taf_npcx_pckt *taf_data_ptr - = (struct espi_taf_npcx_pckt *)pckt->buf; - uint8_t *data_ptr = (uint8_t *)taf_data_ptr->data; - struct npcx_taf_head taf_head; + struct espi_taf_npcx_pckt *taf_data_ptr = (struct espi_taf_npcx_pckt *)pckt->buf; int rc; - taf_head.pkt_len = NPCX_TAF_CMP_HEADER_LEN; - taf_head.type = CYC_UNSCS_CMP_WITHOUT_DATA_ONLY; - taf_head.tag_hlen = (taf_data_ptr->tag << 4); - taf_head.llen = 0x0; - memcpy(data_ptr, &taf_head, sizeof(taf_head)); - - rc = taf_npcx_completion_handler(dev, (uint32_t *)taf_data_ptr->data); + rc = taf_npcx_completion_handler(dev, CYC_UNSCS_CMP_WITHOUT_DATA_ONLY, taf_data_ptr->tag, + 0x0, NULL); if (rc) { LOG_ERR("espi taf completion handler fail"); return rc; @@ -423,6 +459,67 @@ static int espi_taf_npcx_flash_unsuccess(const struct device *dev, struct espi_s return 0; } +static void espi_taf_work(struct k_work *item) +{ + struct espi_taf_npcx_data *info = CONTAINER_OF(item, struct espi_taf_npcx_data, work); + int ret = 0; + + struct espi_taf_npcx_pckt taf_data; + struct espi_saf_packet pckt_taf; + + pckt_taf.flash_addr = info->address; + pckt_taf.len = info->length; + taf_data.tag = info->taf_tag; + if (info->taf_type == NPCX_ESPI_TAF_REQ_WRITE) { + taf_data.data = (uint8_t *)info->src; + } else { + taf_data.data = NULL; + } + pckt_taf.buf = (uint8_t *)&taf_data; + + switch (info->taf_type) { +#if defined(CONFIG_ESPI_TAF_MANUAL_MODE) + case NPCX_ESPI_TAF_REQ_READ: + ret = espi_taf_npcx_flash_read(info->host_dev, &pckt_taf); + break; +#endif + case NPCX_ESPI_TAF_REQ_ERASE: + ret = espi_taf_npcx_flash_erase(info->host_dev, &pckt_taf); + break; + case NPCX_ESPI_TAF_REQ_WRITE: + ret = espi_taf_npcx_flash_write(info->host_dev, &pckt_taf); + break; + } + + if (ret != 0) { + ret = espi_taf_npcx_flash_unsuccess(info->host_dev, &pckt_taf); + } +} + +static void espi_taf_event_handler(const struct device *dev, struct espi_callback *cb, + struct espi_event event) +{ + if ((event.evt_type != ESPI_BUS_TAF_NOTIFICATION) || + (event.evt_details != ESPI_CHANNEL_FLASH)) { + return; + } + + espi_taf_get_pckt(dev, &npcx_espi_taf_data, event); + k_work_submit(&npcx_espi_taf_data.work); +} + +int npcx_init_taf(const struct device *dev, sys_slist_t *callbacks) +{ + espi_init_callback(&espi_taf_cb, espi_taf_event_handler, ESPI_BUS_TAF_NOTIFICATION); + espi_add_callback(dev, &espi_taf_cb); + + npcx_espi_taf_data.host_dev = dev; + npcx_espi_taf_data.callbacks = callbacks; + k_work_init(&npcx_espi_taf_data.work, espi_taf_work); + + return 0; +} + static int espi_taf_npcx_init(const struct device *dev) { struct espi_reg *const inst = HAL_INSTANCE(dev); @@ -444,14 +541,8 @@ static const struct espi_saf_driver_api espi_taf_npcx_driver_api = { .set_protection_regions = espi_taf_npcx_set_pr, .activate = espi_taf_npcx_activate, .get_channel_status = espi_taf_npcx_channel_ready, - .flash_read = espi_taf_npcx_flash_read, - .flash_write = espi_taf_npcx_flash_write, - .flash_erase = espi_taf_npcx_flash_erase, - .flash_unsuccess = espi_taf_npcx_flash_unsuccess, }; -static struct espi_taf_npcx_data npcx_espi_taf_data; - static const struct espi_taf_npcx_config espi_taf_npcx_config = { .base = DT_INST_REG_ADDR(0), .mapped_addr = DT_INST_PROP(0, mapped_addr), diff --git a/drivers/espi/host_subs_npcx.c b/drivers/espi/host_subs_npcx.c index 41810666604a6..51802586c8c9e 100644 --- a/drivers/espi/host_subs_npcx.c +++ b/drivers/espi/host_subs_npcx.c @@ -191,6 +191,7 @@ struct host_sub_npcx_data host_sub_data; #define NPCX_C2H_TRANSACTION_TIMEOUT_US 200 /* Logical Device Number Assignments */ +#define EC_CFG_LDN_SP 0x03 #define EC_CFG_LDN_MOUSE 0x05 #define EC_CFG_LDN_KBC 0x06 #define EC_CFG_LDN_SHM 0x0F @@ -205,6 +206,13 @@ struct host_sub_npcx_data host_sub_data; #define EC_CFG_IDX_DATA_IO_ADDR_H 0x62 #define EC_CFG_IDX_DATA_IO_ADDR_L 0x63 +/* LDN Activation Enable */ +#define EC_CFG_IDX_CTRL_LDN_ENABLE 0x01 + +/* Index of SuperI/O Control and Configuration Registers */ +#define EC_CFG_IDX_SUPERIO_SIOCF9 0x29 +#define EC_CFG_IDX_SUPERIO_SIOCF9_CKEN 2 + /* Index of Special Logical Device Configuration (Shared Memory Module) */ #define EC_CFG_IDX_SHM_CFG 0xF1 #define EC_CFG_IDX_SHM_WND1_ADDR_0 0xF4 @@ -217,6 +225,11 @@ struct host_sub_npcx_data host_sub_data; #define EC_CFG_IDX_SHM_WND2_ADDR_3 0xFB #define EC_CFG_IDX_SHM_DP80_ADDR_RANGE 0xFD +/* Index of Special Logical Device Configuration (Serial Port/Host UART) */ +#define EC_CFG_IDX_SP_CFG 0xF0 +/* Enable selection of bank 2 and 3 for the Serial Port */ +#define EC_CFG_IDX_SP_CFG_BK_SL_ENABLE 7 + /* Host sub-device local inline functions */ static inline uint8_t host_shd_mem_wnd_size_sl(uint32_t size) { @@ -995,10 +1008,10 @@ void npcx_host_init_subs_host_domain(void) * modules by setting bit 0 in its Control (index is 0x30) reg. */ host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_KBC); - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_MOUSE); - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); } if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_HOST_IO)) { @@ -1007,7 +1020,7 @@ void npcx_host_init_subs_host_domain(void) * module by setting bit 0 in its Control (index is 0x30) reg. */ host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_ACPI); - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); } if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_EC_HOST_CMD) || @@ -1028,7 +1041,7 @@ void npcx_host_init_subs_host_domain(void) (CONFIG_ESPI_PERIPHERAL_HOST_CMD_DATA_PORT_NUM + 4) & 0xff); #endif /* Enable 'Host Command' io port (PM Channel 2) */ - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); /* Select 'Shared Memory' bank which LDN are 0x0F */ host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_SHM); @@ -1053,8 +1066,23 @@ void npcx_host_init_subs_host_domain(void) host_c2h_write_io_cfg_reg(EC_CFG_IDX_SHM_DP80_ADDR_RANGE, 0x0f); } /* Enable SHM direct memory access */ - host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, 0x01); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); } + + if (IS_ENABLED(CONFIG_ESPI_PERIPHERAL_UART)) { + /* Select Serial Port banks which LDN are 0x03. */ + host_c2h_write_io_cfg_reg(EC_CFG_IDX_LDN, EC_CFG_LDN_SP); + /* Enable SIO_CLK */ + host_c2h_write_io_cfg_reg(EC_CFG_IDX_SUPERIO_SIOCF9, + host_c2h_read_io_cfg_reg(EC_CFG_IDX_SUPERIO_SIOCF9) | + BIT(EC_CFG_IDX_SUPERIO_SIOCF9_CKEN)); + /* Enable Bank Select */ + host_c2h_write_io_cfg_reg(EC_CFG_IDX_SP_CFG, + host_c2h_read_io_cfg_reg(EC_CFG_IDX_SP_CFG) | + BIT(EC_CFG_IDX_SP_CFG_BK_SL_ENABLE)); + host_c2h_write_io_cfg_reg(EC_CFG_IDX_CTRL, EC_CFG_IDX_CTRL_LDN_ENABLE); + } + LOG_DBG("Hos sub-modules configurations are done!"); } diff --git a/drivers/ethernet/Kconfig.native_posix b/drivers/ethernet/Kconfig.native_posix index 8ab1033d477b2..d4c065fbdde45 100644 --- a/drivers/ethernet/Kconfig.native_posix +++ b/drivers/ethernet/Kconfig.native_posix @@ -15,12 +15,13 @@ if ETH_NATIVE_POSIX config ETH_NATIVE_POSIX_INTERFACE_COUNT int "Number of network interfaces created" default NET_GPTP_NUM_PORTS if NET_GPTP + default PTP_NUM_PORTS if PTP default 1 range 1 32 help By default only one network interface is created. It is possible to create multiple interfaces in certain use cases. For example if - multiple ports are defined in gPTP, then multiple network interfaces + multiple ports are defined in gPTP or PTP, then multiple network interfaces must be created here. config ETH_NATIVE_POSIX_DRV_NAME @@ -40,9 +41,9 @@ config ETH_NATIVE_POSIX_DEV_NAME config ETH_NATIVE_POSIX_PTP_CLOCK bool "PTP clock driver support" - default y if NET_GPTP + default y if NET_GPTP || PTP select PTP_CLOCK - depends on NET_GPTP + depends on NET_GPTP || PTP help Enable PTP clock support. diff --git a/drivers/ethernet/Kconfig.stm32_hal b/drivers/ethernet/Kconfig.stm32_hal index 4a11796dc8815..f980091a755ab 100644 --- a/drivers/ethernet/Kconfig.stm32_hal +++ b/drivers/ethernet/Kconfig.stm32_hal @@ -24,17 +24,17 @@ choice ETH_STM32_HAL_API_VERSION prompt "STM32Cube HAL Ethernet version" config ETH_STM32_HAL_API_V2 - bool "Use new HAL driver" + bool "Use official STM32Cube HAL driver" depends on SOC_SERIES_STM32H7X || SOC_SERIES_STM32H5X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X help - Use the new HAL driver instead of the legacy one. + Use the official STM32Cube HAL driver instead of the legacy one. config ETH_STM32_HAL_API_V1 - bool "Use new HAL driver" - depends on !SOC_SERIES_STM32H5X - select DEPRECATED if SOC_SERIES_STM32H7X || SOC_SERIES_STM32F4X || SOC_SERIES_STM32F7X + bool "Use legacy STM32Cube HAL driver" + depends on SOC_SERIES_STM32F1X || SOC_SERIES_STM32F2X help - Driver version based on legacy HAL version. Deprecated unless using STM32F2 series. + Driver version based on legacy HAL version as the current official API version. + Available only for STM32F1 and STM32F2 SoC series. endchoice diff --git a/drivers/ethernet/eth_dwmac_mmu.c b/drivers/ethernet/eth_dwmac_mmu.c index b78fbbc035d6b..f7136dfba4c49 100644 --- a/drivers/ethernet/eth_dwmac_mmu.c +++ b/drivers/ethernet/eth_dwmac_mmu.c @@ -47,12 +47,12 @@ void dwmac_platform_init(struct dwmac_priv *p) sys_cache_data_invd_range(dwmac_tx_rx_descriptors, sizeof(dwmac_tx_rx_descriptors)); - desc_phys_addr = z_mem_phys_addr(dwmac_tx_rx_descriptors); + desc_phys_addr = k_mem_phys_addr(dwmac_tx_rx_descriptors); /* remap descriptor rings uncached */ - z_phys_map(&desc_uncached_addr, desc_phys_addr, - sizeof(dwmac_tx_rx_descriptors), - K_MEM_PERM_RW | K_MEM_CACHE_NONE); + k_mem_map_phys_bare(&desc_uncached_addr, desc_phys_addr, + sizeof(dwmac_tx_rx_descriptors), + K_MEM_PERM_RW | K_MEM_CACHE_NONE); LOG_DBG("desc virt %p uncached %p phys 0x%lx", dwmac_tx_rx_descriptors, desc_uncached_addr, desc_phys_addr); diff --git a/drivers/ethernet/eth_enc28j60.c b/drivers/ethernet/eth_enc28j60.c index 979910f759aaf..7444c79e40100 100644 --- a/drivers/ethernet/eth_enc28j60.c +++ b/drivers/ethernet/eth_enc28j60.c @@ -527,6 +527,18 @@ static int eth_enc28j60_tx(const struct device *dev, struct net_pkt *pkt) if (tx_end & ENC28J60_BIT_ESTAT_TXABRT) { LOG_ERR("%s: TX failed!", dev->name); + + /* 12.1.3 "TRANSMIT ERROR INTERRUPT FLAG (TXERIF)" states: + * + * "After determining the problem and solution, the + * host controller should clear the LATECOL (if set) and + * TXABRT bits so that future aborts can be detected + * accurately." + */ + eth_enc28j60_clear_eth_reg(dev, ENC28J60_REG_ESTAT, + ENC28J60_BIT_ESTAT_TXABRT + | ENC28J60_BIT_ESTAT_LATECOL); + return -EIO; } diff --git a/drivers/ethernet/eth_liteeth.c b/drivers/ethernet/eth_liteeth.c index 332ad5e657187..5fc2780fdae96 100644 --- a/drivers/ethernet/eth_liteeth.c +++ b/drivers/ethernet/eth_liteeth.c @@ -180,6 +180,25 @@ static void eth_irq_handler(const struct device *port) } } +static int eth_set_config(const struct device *dev, enum ethernet_config_type type, + const struct ethernet_config *config) +{ + struct eth_liteeth_dev_data *context = dev->data; + int ret = -ENOTSUP; + + switch (type) { + case ETHERNET_CONFIG_TYPE_MAC_ADDRESS: + memcpy(context->mac_addr, config->mac_address.addr, sizeof(context->mac_addr)); + ret = net_if_set_link_addr(context->iface, context->mac_addr, + sizeof(context->mac_addr), NET_LINK_ETHERNET); + break; + default: + break; + } + + return ret; +} + #ifdef CONFIG_ETH_LITEETH_0 static struct eth_liteeth_dev_data eth_data = { @@ -247,6 +266,7 @@ static enum ethernet_hw_caps eth_caps(const struct device *dev) static const struct ethernet_api eth_api = { .iface_api.init = eth_iface_init, .get_capabilities = eth_caps, + .set_config = eth_set_config, .send = eth_tx }; diff --git a/drivers/ethernet/eth_stm32_hal.c b/drivers/ethernet/eth_stm32_hal.c index 0da1411c3112a..e27637a570618 100644 --- a/drivers/ethernet/eth_stm32_hal.c +++ b/drivers/ethernet/eth_stm32_hal.c @@ -352,7 +352,8 @@ static int eth_tx(const struct device *dev, struct net_pkt *pkt) #endif /* CONFIG_ETH_STM32_HAL_API_V2 */ #if defined(CONFIG_PTP_CLOCK_STM32_HAL) - timestamped_frame = eth_is_ptp_pkt(net_pkt_iface(pkt), pkt); + timestamped_frame = eth_is_ptp_pkt(net_pkt_iface(pkt), pkt) || + net_pkt_is_tx_timestamping(pkt); if (timestamped_frame) { /* Enable transmit timestamp */ #if defined(CONFIG_ETH_STM32_HAL_API_V2) @@ -789,13 +790,10 @@ static struct net_pkt *eth_rx(const struct device *dev) } #if defined(CONFIG_PTP_CLOCK_STM32_HAL) - if (eth_is_ptp_pkt(get_iface(dev_data), pkt)) { - pkt->timestamp.second = timestamp.second; - pkt->timestamp.nanosecond = timestamp.nanosecond; - } else { - /* Invalid value */ - pkt->timestamp.second = UINT64_MAX; - pkt->timestamp.nanosecond = UINT32_MAX; + pkt->timestamp.second = timestamp.second; + pkt->timestamp.nanosecond = timestamp.nanosecond; + if (timestamp.second != UINT64_MAX) { + net_pkt_set_rx_timestamping(pkt, true); } #endif /* CONFIG_PTP_CLOCK_STM32_HAL */ @@ -1823,7 +1821,7 @@ static int ptp_stm32_init(const struct device *port) #if defined(CONFIG_ETH_STM32_HAL_API_V2) /* Set PTP Configuration done */ - heth->IsPtpConfigured = HAL_ETH_PTP_CONFIGURATED; + heth->IsPtpConfigured = ETH_STM32_PTP_CONFIGURED; #endif return 0; diff --git a/drivers/ethernet/eth_stm32_hal_priv.h b/drivers/ethernet/eth_stm32_hal_priv.h index 55ae396c90dcc..6402a9a306969 100644 --- a/drivers/ethernet/eth_stm32_hal_priv.h +++ b/drivers/ethernet/eth_stm32_hal_priv.h @@ -9,6 +9,15 @@ #include #include +/* Naming of the ETH PTP Config Status changes depending on the stm32 serie */ +#if defined(CONFIG_SOC_SERIES_STM32F7X) || defined(CONFIG_SOC_SERIES_STM32F4X) +#define ETH_STM32_PTP_CONFIGURED HAL_ETH_PTP_CONFIGURATED +#define ETH_STM32_PTP_NOT_CONFIGURED HAL_ETH_PTP_NOT_CONFIGURATED +#else +#define ETH_STM32_PTP_CONFIGURED HAL_ETH_PTP_CONFIGURED +#define ETH_STM32_PTP_NOT_CONFIGURED HAL_ETH_PTP_NOT_CONFIGURED +#endif /* stm32F7x or sm32F4x */ + #define ST_OUI_B0 0x00 #define ST_OUI_B1 0x80 #define ST_OUI_B2 0xE1 diff --git a/drivers/ethernet/nxp_enet/Kconfig b/drivers/ethernet/nxp_enet/Kconfig index d2eb4d071358c..2801b3c9c864f 100644 --- a/drivers/ethernet/nxp_enet/Kconfig +++ b/drivers/ethernet/nxp_enet/Kconfig @@ -14,7 +14,7 @@ choice NXP_ENET_DRIVER config ETH_NXP_ENET bool "NXP ENET Ethernet driver" - select NOCACHE_MEMORY if HAS_MCUX_CACHE + select NOCACHE_MEMORY if HAS_MCUX_CACHE && CPU_HAS_DCACHE select ARM_MPU if CPU_CORTEX_M7 select MDIO if DT_HAS_NXP_ENET_MDIO_ENABLED select NET_POWER_MANAGEMENT if (PM_DEVICE && SOC_FAMILY_KINETIS) @@ -38,6 +38,13 @@ endchoice if ETH_NXP_ENET +config ETH_NXP_ENET_1G + bool "1G mode for ENET1G instance" + default y + depends on DT_HAS_NXP_ENET1G_ENABLED + help + Enable the use of the ENET1G ethernet instance in 1G mode. + config ETH_NXP_ENET_USE_DTCM_FOR_DMA_BUFFER bool "Use DTCM for hardware DMA buffers" default y @@ -48,6 +55,7 @@ config ETH_NXP_ENET_USE_DTCM_FOR_DMA_BUFFER config ETH_NXP_ENET_HW_ACCELERATION bool "Hardware acceleration" default y + depends on !NET_IPV6 help Enable hardware acceleration for the following: - IPv4, UDP and TCP checksum (both Rx and Tx) diff --git a/drivers/ethernet/nxp_enet/eth_nxp_enet.c b/drivers/ethernet/nxp_enet/eth_nxp_enet.c index befa92b91aed5..5168879b5b916 100644 --- a/drivers/ethernet/nxp_enet/eth_nxp_enet.c +++ b/drivers/ethernet/nxp_enet/eth_nxp_enet.c @@ -62,19 +62,27 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); #define ETH_NXP_ENET_UNIQUE_ID (OCOTP->FUSEN[40].FUSE) #elif defined(CONFIG_SOC_SERIES_KINETIS_K6X) #define ETH_NXP_ENET_UNIQUE_ID (SIM->UIDH ^ SIM->UIDMH ^ SIM->UIDML ^ SIM->UIDL) +#elif defined(CONFIG_SOC_SERIES_RW6XX) +#define ETH_NXP_ENET_UNIQUE_ID (OCOTP->OTP_SHADOW[46]) #else #define ETH_NXP_ENET_UNIQUE_ID 0xFFFFFF -#error "Unsupported SOC" #endif #define RING_ID 0 +enum mac_address_source { + MAC_ADDR_SOURCE_LOCAL, + MAC_ADDR_SOURCE_RANDOM, + MAC_ADDR_SOURCE_UNIQUE, + MAC_ADDR_SOURCE_FUSED, + MAC_ADDR_SOURCE_INVALID, +}; + struct nxp_enet_mac_config { - ENET_Type *base; + const struct device *module_dev; const struct device *clock_dev; clock_control_subsys_t clock_subsys; - bool generate_mac; - bool unique_mac; + enum mac_address_source mac_addr_source; const struct pinctrl_dev_config *pincfg; enet_buffer_config_t buffer_config; uint8_t phy_mode; @@ -87,6 +95,7 @@ struct nxp_enet_mac_config { }; struct nxp_enet_mac_data { + ENET_Type *base; struct net_if *iface; uint8_t mac_addr[6]; enet_handle_t enet_handle; @@ -194,7 +203,6 @@ static const struct device *eth_nxp_enet_get_ptp_clock(const struct device *dev) static int eth_nxp_enet_tx(const struct device *dev, struct net_pkt *pkt) { - const struct nxp_enet_mac_config *config = dev->config; struct nxp_enet_mac_data *data = dev->data; uint16_t total_len = net_pkt_get_len(pkt); bool frame_is_timestamped; @@ -214,7 +222,7 @@ static int eth_nxp_enet_tx(const struct device *dev, struct net_pkt *pkt) frame_is_timestamped = eth_get_ptp_data(net_pkt_iface(pkt), pkt); - ret = ENET_SendFrame(config->base, &data->enet_handle, data->tx_frame_buf, + ret = ENET_SendFrame(data->base, &data->enet_handle, data->tx_frame_buf, total_len, RING_ID, frame_is_timestamped, pkt); if (ret == kStatus_Success) { goto exit; @@ -224,7 +232,7 @@ static int eth_nxp_enet_tx(const struct device *dev, struct net_pkt *pkt) eth_wait_for_ptp_ts(dev, pkt); } else { LOG_ERR("ENET_SendFrame error: %d", ret); - ENET_ReclaimTxDescriptor(config->base, &data->enet_handle, RING_ID); + ENET_ReclaimTxDescriptor(data->base, &data->enet_handle, RING_ID); } exit: @@ -260,9 +268,14 @@ static void eth_nxp_enet_iface_init(struct net_if *iface) static enum ethernet_hw_caps eth_nxp_enet_get_capabilities(const struct device *dev) { +#if defined(CONFIG_ETH_NXP_ENET_1G) + const struct nxp_enet_mac_config *config = dev->config; +#else ARG_UNUSED(dev); +#endif + enum ethernet_hw_caps caps; - return ETHERNET_LINK_10BASE_T | + caps = ETHERNET_LINK_10BASE_T | ETHERNET_HW_FILTERING | #if defined(CONFIG_NET_VLAN) ETHERNET_HW_VLAN | @@ -278,6 +291,13 @@ static enum ethernet_hw_caps eth_nxp_enet_get_capabilities(const struct device * ETHERNET_HW_RX_CHKSUM_OFFLOAD | #endif ETHERNET_LINK_100BASE_T; + + if (COND_CODE_1(IS_ENABLED(CONFIG_ETH_NXP_ENET_1G), + (config->phy_mode == NXP_ENET_RGMII_MODE), (0))) { + caps |= ETHERNET_LINK_1000BASE_T; + } + + return caps; } static int eth_nxp_enet_set_config(const struct device *dev, @@ -285,14 +305,13 @@ static int eth_nxp_enet_set_config(const struct device *dev, const struct ethernet_config *cfg) { struct nxp_enet_mac_data *data = dev->data; - const struct nxp_enet_mac_config *config = dev->config; switch (type) { case ETHERNET_CONFIG_TYPE_MAC_ADDRESS: memcpy(data->mac_addr, cfg->mac_address.addr, sizeof(data->mac_addr)); - ENET_SetMacAddr(config->base, data->mac_addr); + ENET_SetMacAddr(data->base, data->mac_addr); net_if_set_link_addr(data->iface, data->mac_addr, sizeof(data->mac_addr), NET_LINK_ETHERNET); @@ -305,10 +324,10 @@ static int eth_nxp_enet_set_config(const struct device *dev, case ETHERNET_CONFIG_TYPE_FILTER: /* The ENET driver does not modify the address buffer but the API is not const */ if (cfg->filter.set) { - ENET_AddMulticastGroup(config->base, + ENET_AddMulticastGroup(data->base, (uint8_t *)cfg->filter.mac_address.addr); } else { - ENET_LeaveMulticastGroup(config->base, + ENET_LeaveMulticastGroup(data->base, (uint8_t *)cfg->filter.mac_address.addr); } return 0; @@ -321,7 +340,9 @@ static int eth_nxp_enet_set_config(const struct device *dev, static int eth_nxp_enet_rx(const struct device *dev) { +#if defined(CONFIG_PTP_CLOCK_NXP_ENET) const struct nxp_enet_mac_config *config = dev->config; +#endif struct nxp_enet_mac_data *data = dev->data; uint32_t frame_length = 0U; struct net_if *iface; @@ -356,7 +377,7 @@ static int eth_nxp_enet_rx(const struct device *dev) } k_mutex_lock(&data->rx_frame_buf_mutex, K_FOREVER); - status = ENET_ReadFrame(config->base, &data->enet_handle, + status = ENET_ReadFrame(data->base, &data->enet_handle, data->rx_frame_buf, frame_length, RING_ID, &ts); k_mutex_unlock(&data->rx_frame_buf_mutex); @@ -410,7 +431,7 @@ static int eth_nxp_enet_rx(const struct device *dev) * only report failure if there is no frame to flush, * which cannot happen in this context. */ - status = ENET_ReadFrame(config->base, &data->enet_handle, NULL, + status = ENET_ReadFrame(data->base, &data->enet_handle, NULL, 0, RING_ID, NULL); __ASSERT_NO_MSG(status == kStatus_Success); error: @@ -426,7 +447,6 @@ static void eth_nxp_enet_rx_thread(struct k_work *work) struct nxp_enet_mac_data *data = CONTAINER_OF(work, struct nxp_enet_mac_data, rx_work); const struct device *dev = data->dev; - const struct nxp_enet_mac_config *config = dev->config; int ret; if (k_sem_take(&data->rx_thread_sem, K_FOREVER)) { @@ -437,25 +457,21 @@ static void eth_nxp_enet_rx_thread(struct k_work *work) ret = eth_nxp_enet_rx(dev); } while (ret == 1); - ENET_EnableInterrupts(config->base, kENET_RxFrameInterrupt); + ENET_EnableInterrupts(data->base, kENET_RxFrameInterrupt); } -static int nxp_enet_phy_reset_and_configure(const struct device *phy) +static int nxp_enet_phy_configure(const struct device *phy, uint8_t phy_mode) { - int ret; + enum phy_link_speed speeds = LINK_HALF_10BASE_T | LINK_FULL_10BASE_T | + LINK_HALF_100BASE_T | LINK_FULL_100BASE_T; - /* Reset the PHY */ - ret = phy_write(phy, MII_BMCR, MII_BMCR_RESET); - if (ret) { - return ret; + if (COND_CODE_1(IS_ENABLED(CONFIG_ETH_NXP_ENET_1G), + (phy_mode == NXP_ENET_RGMII_MODE), (0))) { + speeds |= (LINK_HALF_1000BASE_T | LINK_FULL_1000BASE_T); } - /* 802.3u standard says reset takes up to 0.5s */ - k_busy_wait(500000); - /* Configure the PHY */ - return phy_configure_link(phy, LINK_HALF_10BASE_T | LINK_FULL_10BASE_T | - LINK_HALF_100BASE_T | LINK_FULL_100BASE_T); + return phy_configure_link(phy, speeds); } static void nxp_enet_phy_cb(const struct device *phy, @@ -464,19 +480,44 @@ static void nxp_enet_phy_cb(const struct device *phy, { const struct device *dev = eth_dev; struct nxp_enet_mac_data *data = dev->data; + const struct nxp_enet_mac_config *config = dev->config; + enet_mii_speed_t speed; + enet_mii_duplex_t duplex; + + if (state->is_up) { +#if defined(CONFIG_ETH_NXP_ENET_1G) + if (PHY_LINK_IS_SPEED_1000M(state->speed)) { + speed = kENET_MiiSpeed1000M; + } else if (PHY_LINK_IS_SPEED_100M(state->speed)) { +#else + if (PHY_LINK_IS_SPEED_100M(state->speed)) { +#endif + speed = kENET_MiiSpeed100M; + } else { + speed = kENET_MiiSpeed10M; + } + + if (PHY_LINK_IS_FULL_DUPLEX(state->speed)) { + duplex = kENET_MiiFullDuplex; + } else { + duplex = kENET_MiiHalfDuplex; + } + + ENET_SetMII(data->base, speed, duplex); + } if (!data->iface) { return; } + LOG_INF("Link is %s", state->is_up ? "up" : "down"); + if (!state->is_up) { net_eth_carrier_off(data->iface); - nxp_enet_phy_reset_and_configure(phy); + nxp_enet_phy_configure(phy, config->phy_mode); } else { net_eth_carrier_on(data->iface); } - - LOG_INF("Link is %s", state->is_up ? "up" : "down"); } @@ -485,7 +526,7 @@ static int nxp_enet_phy_init(const struct device *dev) const struct nxp_enet_mac_config *config = dev->config; int ret = 0; - ret = nxp_enet_phy_reset_and_configure(config->phy_dev); + ret = nxp_enet_phy_configure(config->phy_dev, config->phy_mode); if (ret) { return ret; } @@ -515,7 +556,6 @@ static void eth_callback(ENET_Type *base, enet_handle_t *handle, enet_event_t event, enet_frame_info_t *frameinfo, void *param) { const struct device *dev = param; - const struct nxp_enet_mac_config *config = dev->config; struct nxp_enet_mac_data *data = dev->data; switch (event) { @@ -528,7 +568,7 @@ static void eth_callback(ENET_Type *base, enet_handle_t *handle, break; case kENET_TimeStampEvent: /* Reset periodic timer to default value. */ - config->base->ATPER = NSEC_PER_SEC; + data->base->ATPER = NSEC_PER_SEC; break; default: break; @@ -547,16 +587,16 @@ static void eth_nxp_enet_isr(const struct device *dev) struct nxp_enet_mac_data *data = dev->data; unsigned int irq_lock_key = irq_lock(); - uint32_t eir = ENET_GetInterruptStatus(config->base); + uint32_t eir = ENET_GetInterruptStatus(data->base); if (eir & (kENET_RxFrameInterrupt)) { - ENET_ReceiveIRQHandler(ENET_IRQ_HANDLER_ARGS(config->base, &data->enet_handle)); - ENET_DisableInterrupts(config->base, kENET_RxFrameInterrupt); + ENET_ReceiveIRQHandler(ENET_IRQ_HANDLER_ARGS(data->base, &data->enet_handle)); + ENET_DisableInterrupts(data->base, kENET_RxFrameInterrupt); k_work_submit_to_queue(&rx_work_queue, &data->rx_work); } if (eir & kENET_TxFrameInterrupt) { - ENET_TransmitIRQHandler(ENET_IRQ_HANDLER_ARGS(config->base, &data->enet_handle)); + ENET_TransmitIRQHandler(ENET_IRQ_HANDLER_ARGS(data->base, &data->enet_handle)); } if (eir & ENET_EIR_MII_MASK) { @@ -566,11 +606,16 @@ static void eth_nxp_enet_isr(const struct device *dev) irq_unlock(irq_lock_key); } +/* Note this is not universally unique, it just is probably unique on a network */ static inline void nxp_enet_unique_mac(uint8_t *mac_addr) { uint32_t id = ETH_NXP_ENET_UNIQUE_ID; - mac_addr[0] = FREESCALE_OUI_B0; + if (id == 0xFFFFFF) + LOG_ERR("No unique MAC can be provided in this platform"); + + /* Setting LAA bit because it is not guaranteed universally unique */ + mac_addr[0] = FREESCALE_OUI_B0 | 0x02; mac_addr[1] = FREESCALE_OUI_B1; mac_addr[2] = FREESCALE_OUI_B2; mac_addr[3] = FIELD_GET(0xFF0000, id); @@ -578,6 +623,34 @@ static inline void nxp_enet_unique_mac(uint8_t *mac_addr) mac_addr[5] = FIELD_GET(0x0000FF, id); } +#ifdef CONFIG_SOC_FAMILY_NXP_IMXRT +#include +#endif + +static inline void nxp_enet_fused_mac(uint8_t *mac_addr) +{ +#ifdef CONFIG_SOC_FAMILY_NXP_IMXRT + uint32_t mac_addr_fuse[2] = {0}; + + OCOTP_ReadFuseShadowRegisterExt((OCOTP_Type *)OCOTP_BASE, +#if defined(CONFIG_SOC_SERIES_IMXRT10XX) + 0x620, +#elif defined(CONFIG_SOC_SERIES_IMXRT11XX) + 0xA90, +#endif + mac_addr_fuse, 2); + + mac_addr[0] = mac_addr_fuse[0] & 0x000000FF; + mac_addr[1] = mac_addr_fuse[0] & 0x0000FF00; + mac_addr[2] = mac_addr_fuse[0] & 0x00FF0000; + mac_addr[3] = mac_addr_fuse[0] & 0xFF000000; + mac_addr[4] = mac_addr_fuse[1] & 0x00FF; + mac_addr[5] = mac_addr_fuse[1] & 0xFF00; +#else + ARG_UNUSED(mac_addr); +#endif +} + static int eth_nxp_enet_init(const struct device *dev) { struct nxp_enet_mac_data *data = dev->data; @@ -586,6 +659,8 @@ static int eth_nxp_enet_init(const struct device *dev) uint32_t enet_module_clock_rate; int err; + data->base = (ENET_Type *)DEVICE_MMIO_GET(config->module_dev); + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); if (err) { return err; @@ -601,13 +676,21 @@ static int eth_nxp_enet_init(const struct device *dev) #endif k_work_init(&data->rx_work, eth_nxp_enet_rx_thread); - if (config->unique_mac) { - nxp_enet_unique_mac(data->mac_addr); - } - - if (config->generate_mac) { + switch (config->mac_addr_source) { + case MAC_ADDR_SOURCE_LOCAL: + break; + case MAC_ADDR_SOURCE_RANDOM: gen_random_mac(data->mac_addr, FREESCALE_OUI_B0, FREESCALE_OUI_B1, FREESCALE_OUI_B2); + break; + case MAC_ADDR_SOURCE_UNIQUE: + nxp_enet_unique_mac(data->mac_addr); + break; + case MAC_ADDR_SOURCE_FUSED: + nxp_enet_fused_mac(data->mac_addr); + break; + default: + return -ENOTSUP; } err = clock_control_get_rate(config->clock_dev, config->clock_subsys, @@ -640,6 +723,10 @@ static int eth_nxp_enet_init(const struct device *dev) enet_config.miiMode = kENET_MiiMode; } else if (config->phy_mode == NXP_ENET_RMII_MODE) { enet_config.miiMode = kENET_RmiiMode; +#if defined(CONFIG_ETH_NXP_ENET_1G) + } else if (config->phy_mode == NXP_ENET_RGMII_MODE) { + enet_config.miiMode = kENET_RgmiiMode; +#endif } else { return -EINVAL; } @@ -647,7 +734,7 @@ static int eth_nxp_enet_init(const struct device *dev) enet_config.callback = eth_callback; enet_config.userData = (void *)dev; - ENET_Up(config->base, + ENET_Up(data->base, &data->enet_handle, &enet_config, &config->buffer_config, @@ -662,7 +749,7 @@ static int eth_nxp_enet_init(const struct device *dev) ENET_SetTxReclaim(&data->enet_handle, true, 0); #endif - ENET_ActiveRead(config->base); + ENET_ActiveRead(data->base); err = nxp_enet_phy_init(dev); if (err) { @@ -756,14 +843,17 @@ static const struct ethernet_api api_funcs = { #define _nxp_enet_dma_desc_section __dtcm_bss_section #define _nxp_enet_dma_buffer_section __dtcm_noinit_section #define _nxp_enet_driver_buffer_section __dtcm_noinit_section +#define driver_cache_maintain false #elif defined(CONFIG_NOCACHE_MEMORY) #define _nxp_enet_dma_desc_section __nocache #define _nxp_enet_dma_buffer_section __nocache #define _nxp_enet_driver_buffer_section +#define driver_cache_maintain false #else #define _nxp_enet_dma_desc_section #define _nxp_enet_dma_buffer_section #define _nxp_enet_driver_buffer_section +#define driver_cache_maintain true #endif /* Use ENET_FRAME_MAX_VLANFRAMELEN for VLAN frame size @@ -783,7 +873,8 @@ static const struct ethernet_api api_funcs = { #define NXP_ENET_PHY_MODE(node_id) \ DT_ENUM_HAS_VALUE(node_id, phy_connection_type, mii) ? NXP_ENET_MII_MODE : \ (DT_ENUM_HAS_VALUE(node_id, phy_connection_type, rmii) ? NXP_ENET_RMII_MODE : \ - NXP_ENET_INVALID_MII_MODE) + (DT_ENUM_HAS_VALUE(node_id, phy_connection_type, rgmii) ? NXP_ENET_RGMII_MODE : \ + NXP_ENET_INVALID_MII_MODE)) #ifdef CONFIG_PTP_CLOCK_NXP_ENET #define NXP_ENET_PTP_DEV(n) .ptp_clock = DEVICE_DT_GET(DT_INST_PHANDLE(n, nxp_ptp_clock)), @@ -802,12 +893,31 @@ static const struct ethernet_api api_funcs = { #define NXP_ENET_NODE_HAS_MAC_ADDR_CHECK(n) \ BUILD_ASSERT(NODE_HAS_VALID_MAC_ADDR(DT_DRV_INST(n)) || \ DT_INST_PROP(n, zephyr_random_mac_address) || \ - DT_INST_PROP(n, nxp_unique_mac), \ + DT_INST_PROP(n, nxp_unique_mac) || \ + DT_INST_PROP(n, nxp_fused_mac), \ "MAC address not specified on ENET DT node"); +#define NXP_ENET_NODE_PHY_MODE_CHECK(n) \ +BUILD_ASSERT(NXP_ENET_PHY_MODE(DT_DRV_INST(n)) != NXP_ENET_RGMII_MODE || \ + (IS_ENABLED(CONFIG_ETH_NXP_ENET_1G) && \ + DT_NODE_HAS_COMPAT(DT_INST_PARENT(n), nxp_enet1g)), \ + "RGMII mode requires nxp,enet1g compatible on ENET DT node" \ + " and CONFIG_ETH_NXP_ENET_1G enabled"); + +#define NXP_ENET_MAC_ADDR_SOURCE(n) \ + COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), local_mac_address), \ + (MAC_ADDR_SOURCE_LOCAL), \ + (COND_CODE_1(DT_INST_PROP(n, zephyr_random_mac_address), \ + (MAC_ADDR_SOURCE_RANDOM), \ + (COND_CODE_1(DT_INST_PROP(n, nxp_unique_mac), (MAC_ADDR_SOURCE_UNIQUE), \ + (COND_CODE_1(DT_INST_PROP(n, nxp_fused_mac), (MAC_ADDR_SOURCE_FUSED), \ + (MAC_ADDR_SOURCE_INVALID)))))))) + #define NXP_ENET_MAC_INIT(n) \ NXP_ENET_NODE_HAS_MAC_ADDR_CHECK(n) \ \ + NXP_ENET_NODE_PHY_MODE_CHECK(n) \ + \ PINCTRL_DT_INST_DEFINE(n); \ \ NXP_ENET_FRAMEINFO_ARRAY(n) \ @@ -839,8 +949,8 @@ static const struct ethernet_api api_funcs = { [ETH_NXP_ENET_BUFFER_SIZE]; \ \ const struct nxp_enet_mac_config nxp_enet_##n##_config = { \ - .base = (ENET_Type *)DT_REG_ADDR(DT_INST_PARENT(n)), \ .irq_config_func = nxp_enet_##n##_irq_config_func, \ + .module_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(n))), \ .clock_subsys = (void *)DT_CLOCKS_CELL_BY_IDX( \ DT_INST_PARENT(n), 0, name), \ @@ -854,17 +964,15 @@ static const struct ethernet_api api_funcs = { .txBdStartAddrAlign = nxp_enet_##n##_tx_buffer_desc, \ .rxBufferAlign = nxp_enet_##n##_rx_buffer[0], \ .txBufferAlign = nxp_enet_##n##_tx_buffer[0], \ - .rxMaintainEnable = true, \ - .txMaintainEnable = true, \ + .rxMaintainEnable = driver_cache_maintain, \ + .txMaintainEnable = driver_cache_maintain, \ NXP_ENET_FRAMEINFO(n) \ }, \ .phy_mode = NXP_ENET_PHY_MODE(DT_DRV_INST(n)), \ .phy_dev = DEVICE_DT_GET(DT_INST_PHANDLE(n, phy_handle)), \ .mdio = DEVICE_DT_GET(DT_INST_PHANDLE(n, nxp_mdio)), \ NXP_ENET_PTP_DEV(n) \ - .generate_mac = DT_INST_PROP(n, \ - zephyr_random_mac_address), \ - .unique_mac = DT_INST_PROP(n, nxp_unique_mac), \ + .mac_addr_source = NXP_ENET_MAC_ADDR_SOURCE(n), \ }; \ \ static _nxp_enet_driver_buffer_section uint8_t \ @@ -889,22 +997,67 @@ static const struct ethernet_api api_funcs = { DT_INST_FOREACH_STATUS_OKAY(NXP_ENET_MAC_INIT) +struct nxp_enet_mod_config { + DEVICE_MMIO_ROM; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; +}; + +struct nxp_enet_mod_data { + DEVICE_MMIO_RAM; +}; + +static int nxp_enet_mod_init(const struct device *dev) +{ + const struct nxp_enet_mod_config *config = dev->config; + + clock_control_on(config->clock_dev, config->clock_subsys); + + DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE | K_MEM_DIRECT_MAP); + + ENET_Reset((ENET_Type *)DEVICE_MMIO_GET(dev)); + + return 0; +} + +#define NXP_ENET_INIT(n, compat) \ + \ +static const struct nxp_enet_mod_config nxp_enet_mod_cfg_##n = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_DRV_INST(n))), \ + .clock_subsys = (void *) DT_CLOCKS_CELL_BY_IDX( \ + DT_DRV_INST(n), 0, name), \ +}; \ + \ +static struct nxp_enet_mod_data nxp_enet_mod_data_##n; \ + \ +/* Init the module before any of the MAC, MDIO, or PTP clock */ \ +DEVICE_DT_INST_DEFINE(n, nxp_enet_mod_init, NULL, \ + &nxp_enet_mod_data_##n, &nxp_enet_mod_cfg_##n, \ + POST_KERNEL, 0, NULL); + #undef DT_DRV_COMPAT #define DT_DRV_COMPAT nxp_enet -#define NXP_ENET_INIT(n) \ - \ -int nxp_enet_##n##_init(void) \ -{ \ - clock_control_on(DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ - (void *)DT_INST_CLOCKS_CELL_BY_IDX(n, 0, name)); \ +DT_INST_FOREACH_STATUS_OKAY_VARGS(NXP_ENET_INIT, DT_DRV_COMPAT) + +#define NXP_ENET1G_INIT(n, compat) \ \ - ENET_Reset((ENET_Type *)DT_INST_REG_ADDR(n)); \ +static const struct nxp_enet_mod_config nxp_enet1g_mod_cfg_##n = { \ + DEVICE_MMIO_ROM_INIT(DT_DRV_INST(n)), \ + .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_DRV_INST(n))), \ + .clock_subsys = (void *) DT_CLOCKS_CELL_BY_IDX( \ + DT_DRV_INST(n), 0, name), \ +}; \ \ - return 0; \ -} \ +static struct nxp_enet_mod_data nxp_enet1g_mod_data_##n; \ \ - /* Init the module before any of the MAC, MDIO, or PTP clock */ \ - SYS_INIT(nxp_enet_##n##_init, POST_KERNEL, 0); +/* Init the module before any of the MAC, MDIO, or PTP clock */ \ +DEVICE_DT_INST_DEFINE(n, nxp_enet_mod_init, NULL, \ + &nxp_enet1g_mod_data_##n, &nxp_enet1g_mod_cfg_##n, \ + POST_KERNEL, 0, NULL); + +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_enet1g -DT_INST_FOREACH_STATUS_OKAY(NXP_ENET_INIT) +DT_INST_FOREACH_STATUS_OKAY_VARGS(NXP_ENET1G_INIT, DT_DRV_COMPAT) diff --git a/drivers/ethernet/phy/CMakeLists.txt b/drivers/ethernet/phy/CMakeLists.txt index ff25a9a4fa39c..65f9cd2e5938f 100644 --- a/drivers/ethernet/phy/CMakeLists.txt +++ b/drivers/ethernet/phy/CMakeLists.txt @@ -4,3 +4,4 @@ zephyr_library_sources_ifdef(CONFIG_PHY_GENERIC_MII phy_mii.c) zephyr_library_sources_ifdef(CONFIG_PHY_ADIN2111 phy_adin2111.c) zephyr_library_sources_ifdef(CONFIG_PHY_TJA1103 phy_tja1103.c) zephyr_library_sources_ifdef(CONFIG_PHY_MICROCHIP_KSZ8081 phy_microchip_ksz8081.c) +zephyr_library_sources_ifdef(CONFIG_PHY_REALTEK_RTL8211F phy_realtek_rtl8211f.c) diff --git a/drivers/ethernet/phy/Kconfig b/drivers/ethernet/phy/Kconfig index 8ff32b8fee2a7..9fb71571e0f02 100644 --- a/drivers/ethernet/phy/Kconfig +++ b/drivers/ethernet/phy/Kconfig @@ -41,13 +41,23 @@ config PHY_ADIN2111 Enable ADIN2111 PHY driver. config PHY_MICROCHIP_KSZ8081 - bool "Microchip KSZ8081 Phy Driver" + bool "Microchip KSZ8081 PHY Driver" default y depends on DT_HAS_MICROCHIP_KSZ8081_ENABLED depends on MDIO depends on GPIO help - Enable Microchip KSZ8081 Ethernet Phy Driver + Enable Microchip KSZ8081 Ethernet PHY Driver + +config PHY_REALTEK_RTL8211F + bool "Realtek RTL8211F PHY Driver" + default y + depends on DT_HAS_REALTEK_RTL8211F_ENABLED + depends on MDIO + depends on GPIO || (!$(dt_compat_any_has_prop,$(DT_COMPAT_REALTEK_RTL8211F),reset-gpios) && \ + !$(dt_compat_any_has_prop,$(DT_COMPAT_REALTEK_RTL8211F),int-gpios)) + help + Enable Realtek RTL8211F Ethernet PHY Driver config PHY_AUTONEG_TIMEOUT_MS int "Auto-negotiation timeout value in milliseconds" diff --git a/drivers/ethernet/phy/phy_microchip_ksz8081.c b/drivers/ethernet/phy/phy_microchip_ksz8081.c index 5eaf269f2b771..7ad4e0ec8e29e 100644 --- a/drivers/ethernet/phy/phy_microchip_ksz8081.c +++ b/drivers/ethernet/phy/phy_microchip_ksz8081.c @@ -42,10 +42,10 @@ struct mc_ksz8081_config { uint8_t addr; const struct device *mdio_dev; enum ksz8081_interface phy_iface; -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_reset_gpio) +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) const struct gpio_dt_spec reset_gpio; #endif -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_interrupt_gpio) +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) const struct gpio_dt_spec interrupt_gpio; #endif }; @@ -265,9 +265,9 @@ static int phy_mc_ksz8081_static_cfg(const struct device *dev) static int phy_mc_ksz8081_reset(const struct device *dev) { -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_reset_gpio) +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) const struct mc_ksz8081_config *config = dev->config; -#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_reset_gpio) */ +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */ struct mc_ksz8081_data *data = dev->data; int ret; @@ -278,7 +278,7 @@ static int phy_mc_ksz8081_reset(const struct device *dev) return ret; } -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_reset_gpio) +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) if (!config->reset_gpio.port) { goto skip_reset_gpio; } @@ -296,7 +296,7 @@ static int phy_mc_ksz8081_reset(const struct device *dev) ret = gpio_pin_set_dt(&config->reset_gpio, 1); goto done; skip_reset_gpio: -#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_reset_gpio) */ +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */ ret = phy_mc_ksz8081_write(dev, MII_BMCR, MII_BMCR_RESET); if (ret) { goto done; @@ -465,7 +465,7 @@ static int phy_mc_ksz8081_init(const struct device *dev) mdio_bus_enable(config->mdio_dev); -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_interrupt_gpio) +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) if (!config->interrupt_gpio.port) { goto skip_int_gpio; } @@ -477,16 +477,16 @@ static int phy_mc_ksz8081_init(const struct device *dev) } skip_int_gpio: -#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_interrupt_gpio) */ +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_reset_gpio) +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) if (config->reset_gpio.port) { ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_ACTIVE); if (ret) { return ret; } } -#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_reset_gpio) */ +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */ /* Reset PHY */ ret = phy_mc_ksz8081_reset(dev); @@ -508,16 +508,16 @@ static const struct ethphy_driver_api mc_ksz8081_phy_api = { .write = phy_mc_ksz8081_write, }; -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_reset_gpio) +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) #define RESET_GPIO(n) \ - .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(n, mc_reset_gpio, {0}), + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), #else #define RESET_GPIO(n) #endif /* reset gpio */ -#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(mc_interrupt_gpio) +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) #define INTERRUPT_GPIO(n) \ - .interrupt_gpio = GPIO_DT_SPEC_INST_GET_OR(n, mc_interrupt_gpio, {0}), + .interrupt_gpio = GPIO_DT_SPEC_INST_GET_OR(n, int_gpios, {0}), #else #define INTERRUPT_GPIO(n) #endif /* interrupt gpio */ @@ -526,7 +526,7 @@ static const struct ethphy_driver_api mc_ksz8081_phy_api = { static const struct mc_ksz8081_config mc_ksz8081_##n##_config = { \ .addr = DT_INST_REG_ADDR(n), \ .mdio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ - .phy_iface = DT_INST_ENUM_IDX(n, mc_interface_type), \ + .phy_iface = DT_INST_ENUM_IDX(n, microchip_interface_type), \ RESET_GPIO(n) \ INTERRUPT_GPIO(n) \ }; \ diff --git a/drivers/ethernet/phy/phy_realtek_rtl8211f.c b/drivers/ethernet/phy/phy_realtek_rtl8211f.c new file mode 100644 index 0000000000000..d0f25750128a9 --- /dev/null +++ b/drivers/ethernet/phy/phy_realtek_rtl8211f.c @@ -0,0 +1,682 @@ +/* + * Copyright 2023-2024 NXP + * + * Inspiration from phy_mii.c, which is: + * Copyright (c) 2021 IP-Logix Inc. + * Copyright 2022 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT realtek_rtl8211f + +#include +#include +#include +#include +#include +#include +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) || DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) +#include +#endif + +#define LOG_MODULE_NAME phy_rt_rtl8211f +#define LOG_LEVEL CONFIG_PHY_LOG_LEVEL +#include +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +#define REALTEK_OUI_MSB (0x1CU) + +#define PHY_RT_RTL8211F_PHYSR_REG (0x1A) + +#define PHY_RT_RTL8211F_PHYSR_LINKSTATUS_MASK BIT(2) +#define PHY_RT_RTL8211F_PHYSR_LINKDUPLEX_MASK BIT(3) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_MASK (BIT(4) | BIT(5)) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_SHIFT (4U) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_10M (0U) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_100M (1U) +#define PHY_RT_RTL8211F_PHYSR_LINKSPEED_1000M (2U) + +#define PHY_RT_RTL8211F_PAGSR_REG (0x1F) + +#define PHY_RT_RTL8211F_PAGE_MIICR_ADDR (0xD08) +#define PHY_RT_RTL8211F_MIICR1_REG (0x11) +#define PHY_RT_RTL8211F_MIICR2_REG (0x15) +#define PHY_RT_RTL8211F_MIICR1_TXDLY_MASK BIT(8) +#define PHY_RT_RTL8211F_MIICR2_RXDLY_MASK BIT(3) + +#define PHY_RT_RTL8211F_PAGE_INTR_PIN_ADDR (0xD40) +#define PHY_RT_RTL8211F_INTR_PIN_REG (0x16) +#define PHY_RT_RTL8211F_INTR_PIN_MASK BIT(5) + +#define PHY_RT_RTL8211F_PAGE_INTR_ADDR (0xA42U) +#define PHY_RT_RTL8211F_INER_REG (0x12U) +#define PHY_RT_RTL8211F_INER_LINKSTATUS_CHANGE_MASK BIT(4) +#define PHY_RT_RTL8211F_INSR_REG (0x1DU) + +#define PHY_RT_RTL8211F_RESET_HOLD_TIME_MS 10 + +struct rt_rtl8211f_config { + uint8_t addr; + const struct device *mdio_dev; +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + const struct gpio_dt_spec reset_gpio; +#endif +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + const struct gpio_dt_spec interrupt_gpio; +#endif +}; + +struct rt_rtl8211f_data { + const struct device *dev; + struct phy_link_state state; + phy_callback_t cb; +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + struct gpio_callback gpio_callback; +#endif + void *cb_data; + struct k_mutex mutex; + struct k_work_delayable phy_monitor_work; +}; + +static int phy_rt_rtl8211f_read(const struct device *dev, + uint16_t reg_addr, uint32_t *data) +{ + const struct rt_rtl8211f_config *config = dev->config; + int ret; + + /* Make sure excessive bits 16-31 are reset */ + *data = 0U; + + /* Read the PHY register */ + ret = mdio_read(config->mdio_dev, config->addr, reg_addr, (uint16_t *)data); + if (ret) { + return ret; + } + + return 0; +} + +static int phy_rt_rtl8211f_write(const struct device *dev, + uint16_t reg_addr, uint32_t data) +{ + const struct rt_rtl8211f_config *config = dev->config; + int ret; + + ret = mdio_write(config->mdio_dev, config->addr, reg_addr, (uint16_t)data); + if (ret) { + return ret; + } + + return 0; +} + +static int phy_rt_rtl8211f_reset(const struct device *dev) +{ + const struct rt_rtl8211f_config *config = dev->config; + uint32_t reg_val; + int ret; + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + if (config->reset_gpio.port) { + /* Start reset */ + ret = gpio_pin_set_dt(&config->reset_gpio, 0); + if (ret) { + return ret; + } + + /* Hold reset for the minimum time specified by datasheet */ + k_busy_wait(USEC_PER_MSEC * PHY_RT_RTL8211F_RESET_HOLD_TIME_MS); + + /* Reset over */ + ret = gpio_pin_set_dt(&config->reset_gpio, 1); + if (ret) { + return ret; + } + + /* Wait another 30 ms (circuits settling time) before accessing registers */ + k_busy_wait(USEC_PER_MSEC * 30); + + goto finalize_reset; + } +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */ + + /* Reset PHY using register */ + ret = phy_rt_rtl8211f_write(dev, MII_BMCR, MII_BMCR_RESET); + if (ret) { + LOG_ERR("Error writing phy (%d) basic control register", config->addr); + return ret; + } + + /* Wait for the minimum reset time specified by datasheet */ + k_busy_wait(USEC_PER_MSEC * PHY_RT_RTL8211F_RESET_HOLD_TIME_MS); + + /* Wait for the reset to be cleared */ + do { + ret = phy_rt_rtl8211f_read(dev, MII_BMCR, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) basic control register", config->addr); + return ret; + } + } while (reg_val & MII_BMCR_RESET); + + goto finalize_reset; + +finalize_reset: + /* Wait until correct data can be read from registers */ + do { + ret = phy_rt_rtl8211f_read(dev, MII_PHYID1R, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) identifier register 1", config->addr); + return ret; + } + } while (reg_val != REALTEK_OUI_MSB); + + return 0; +} + +static int phy_rt_rtl8211f_restart_autonegotiation(const struct device *dev) +{ + const struct rt_rtl8211f_config *config = dev->config; + uint32_t bmcr = 0; + int ret; + + /* Read control register to write back with autonegotiation bit */ + ret = phy_rt_rtl8211f_read(dev, MII_BMCR, &bmcr); + if (ret) { + LOG_ERR("Error reading phy (%d) basic control register", config->addr); + return ret; + } + + /* (re)start autonegotiation */ + LOG_DBG("PHY (%d) is entering autonegotiation sequence", config->addr); + bmcr |= MII_BMCR_AUTONEG_ENABLE | MII_BMCR_AUTONEG_RESTART; + + ret = phy_rt_rtl8211f_write(dev, MII_BMCR, bmcr); + if (ret) { + LOG_ERR("Error writing phy (%d) basic control register", config->addr); + return ret; + } + + return 0; +} + +static int phy_rt_rtl8211f_get_link(const struct device *dev, + struct phy_link_state *state) +{ + const struct rt_rtl8211f_config *config = dev->config; + struct rt_rtl8211f_data *data = dev->data; + int ret; + uint32_t physr = 0; + uint32_t duplex = 0; + struct phy_link_state old_state = data->state; + struct phy_link_state new_state = {}; + + /* Lock mutex */ + ret = k_mutex_lock(&data->mutex, K_FOREVER); + if (ret) { + LOG_ERR("PHY mutex lock error"); + return ret; + } + + /* Read PHY specific status register */ + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_PHYSR_REG, &physr); + if (ret) { + LOG_ERR("Error reading phy (%d) specific status register", config->addr); + (void)k_mutex_unlock(&data->mutex); + return ret; + } + + /* Unlock mutex */ + (void)k_mutex_unlock(&data->mutex); + + new_state.is_up = physr & PHY_RT_RTL8211F_PHYSR_LINKSTATUS_MASK; + + if (!new_state.is_up) { + goto result; + } + + duplex = (physr & PHY_RT_RTL8211F_PHYSR_LINKDUPLEX_MASK); + switch ((physr & PHY_RT_RTL8211F_PHYSR_LINKSPEED_MASK) + >> PHY_RT_RTL8211F_PHYSR_LINKSPEED_SHIFT) { + case PHY_RT_RTL8211F_PHYSR_LINKSPEED_100M: + if (duplex) { + new_state.speed = LINK_FULL_100BASE_T; + } else { + new_state.speed = LINK_HALF_100BASE_T; + } + break; + case PHY_RT_RTL8211F_PHYSR_LINKSPEED_1000M: + if (duplex) { + new_state.speed = LINK_FULL_1000BASE_T; + } else { + new_state.speed = LINK_HALF_1000BASE_T; + } + break; + case PHY_RT_RTL8211F_PHYSR_LINKSPEED_10M: + default: + if (duplex) { + new_state.speed = LINK_FULL_10BASE_T; + } else { + new_state.speed = LINK_HALF_10BASE_T; + } + break; + } +result: + if (memcmp(&old_state, &new_state, sizeof(struct phy_link_state)) != 0) { + LOG_INF("PHY %d is %s", config->addr, new_state.is_up ? "up" : "down"); + if (new_state.is_up) { + LOG_INF("PHY (%d) Link speed %s Mb, %s duplex", config->addr, + (PHY_LINK_IS_SPEED_1000M(new_state.speed) ? "1000" : + (PHY_LINK_IS_SPEED_100M(new_state.speed) ? "100" : "10")), + PHY_LINK_IS_FULL_DUPLEX(new_state.speed) ? "full" : "half"); + } + } + + memcpy(state, &new_state, sizeof(struct phy_link_state)); + + return ret; +} + +static int phy_rt_rtl8211f_cfg_link(const struct device *dev, + enum phy_link_speed speeds) +{ + const struct rt_rtl8211f_config *config = dev->config; + struct rt_rtl8211f_data *data = dev->data; + uint32_t anar; + uint32_t gbcr; + int ret; + + /* Lock mutex */ + ret = k_mutex_lock(&data->mutex, K_FOREVER); + if (ret) { + LOG_ERR("PHY mutex lock error"); + return ret; + } + + /* We are going to reconfigure the phy, don't need to monitor until done */ +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (!config->interrupt_gpio.port) { + k_work_cancel_delayable(&data->phy_monitor_work); + } +#else + k_work_cancel_delayable(&data->phy_monitor_work); +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + + /* Read ANAR register to write back */ + ret = phy_rt_rtl8211f_read(dev, MII_ANAR, &anar); + if (ret) { + LOG_ERR("Error reading phy (%d) advertising register", config->addr); + goto done; + } + + /* Read GBCR register to write back */ + ret = phy_rt_rtl8211f_read(dev, MII_1KTCR, &gbcr); + if (ret) { + LOG_ERR("Error reading phy (%d) 1000Base-T control register", config->addr); + goto done; + } + + /* Setup advertising register */ + if (speeds & LINK_FULL_100BASE_T) { + anar |= MII_ADVERTISE_100_FULL; + } else { + anar &= ~MII_ADVERTISE_100_FULL; + } + if (speeds & LINK_HALF_100BASE_T) { + anar |= MII_ADVERTISE_100_HALF; + } else { + anar &= ~MII_ADVERTISE_100_HALF; + } + if (speeds & LINK_FULL_10BASE_T) { + anar |= MII_ADVERTISE_10_FULL; + } else { + anar &= ~MII_ADVERTISE_10_FULL; + } + if (speeds & LINK_HALF_10BASE_T) { + anar |= MII_ADVERTISE_10_HALF; + } else { + anar &= ~MII_ADVERTISE_10_HALF; + } + + /* Setup 1000Base-T control register */ + if (speeds & LINK_FULL_1000BASE_T) { + gbcr |= MII_ADVERTISE_1000_FULL; + } else { + gbcr &= ~MII_ADVERTISE_1000_FULL; + } + + /* Write capabilities to advertising register */ + ret = phy_rt_rtl8211f_write(dev, MII_ANAR, anar); + if (ret) { + LOG_ERR("Error writing phy (%d) advertising register", config->addr); + goto done; + } + + /* Write capabilities to 1000Base-T control register */ + ret = phy_rt_rtl8211f_write(dev, MII_1KTCR, gbcr); + if (ret) { + LOG_ERR("Error writing phy (%d) 1000Base-T control register", config->addr); + goto done; + } + + /* (Re)start autonegotiation */ + ret = phy_rt_rtl8211f_restart_autonegotiation(dev); + if (ret) { + LOG_ERR("Error restarting autonegotiation"); + goto done; + } +done: + /* Unlock mutex */ + (void)k_mutex_unlock(&data->mutex); + + /* Start monitoring */ +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (!config->interrupt_gpio.port) { + k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); + } +#else + k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + + return ret; +} + +static int phy_rt_rtl8211f_link_cb_set(const struct device *dev, + phy_callback_t cb, void *user_data) +{ + struct rt_rtl8211f_data *data = dev->data; + + data->cb = cb; + data->cb_data = user_data; + + phy_rt_rtl8211f_get_link(dev, &data->state); + + data->cb(dev, &data->state, data->cb_data); + + return 0; +} + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) +static int phy_rt_rtl8211f_clear_interrupt(struct rt_rtl8211f_data *data) +{ + const struct device *dev = data->dev; + const struct rt_rtl8211f_config *config = dev->config; + uint32_t reg_val; + int ret; + + /* Lock mutex */ + ret = k_mutex_lock(&data->mutex, K_FOREVER); + if (ret) { + LOG_ERR("PHY mutex lock error"); + return ret; + } + + /* Read/clear PHY interrupt status register */ + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_INSR_REG, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) interrupt status register", config->addr); + } + + /* Unlock mutex */ + (void)k_mutex_unlock(&data->mutex); + + return ret; +} + +static void phy_rt_rtl8211f_interrupt_handler(const struct device *port, + struct gpio_callback *cb, + gpio_port_pins_t pins) +{ + struct rt_rtl8211f_data *data = CONTAINER_OF(cb, struct rt_rtl8211f_data, gpio_callback); + int ret; + + ret = k_work_reschedule(&data->phy_monitor_work, K_NO_WAIT); + if (ret < 0) { + LOG_ERR("Failed to schedule phy_monitor_work from ISR"); + } +} +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + +static void phy_rt_rtl8211f_monitor_work_handler(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct rt_rtl8211f_data *data = + CONTAINER_OF(dwork, struct rt_rtl8211f_data, phy_monitor_work); + const struct device *dev = data->dev; +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + const struct rt_rtl8211f_config *config = dev->config; +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + struct phy_link_state state = {}; + int ret; + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (config->interrupt_gpio.port) { + ret = phy_rt_rtl8211f_clear_interrupt(data); + if (ret) { + return; + } + } +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + + ret = phy_rt_rtl8211f_get_link(dev, &state); + + if (ret == 0 && memcmp(&state, &data->state, sizeof(struct phy_link_state)) != 0) { + memcpy(&data->state, &state, sizeof(struct phy_link_state)); + if (data->cb) { + data->cb(dev, &data->state, data->cb_data); + } + } + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (!config->interrupt_gpio.port) { + k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); + } +#else + k_work_reschedule(&data->phy_monitor_work, K_MSEC(CONFIG_PHY_MONITOR_PERIOD)); +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ +} + +static int phy_rt_rtl8211f_init(const struct device *dev) +{ + const struct rt_rtl8211f_config *config = dev->config; + struct rt_rtl8211f_data *data = dev->data; + uint32_t reg_val; + int ret; + + data->dev = dev; + + ret = k_mutex_init(&data->mutex); + if (ret) { + return ret; + } + + mdio_bus_enable(config->mdio_dev); + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + /* Configure reset pin */ + if (config->reset_gpio.port) { + ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */ + + /* Reset PHY */ + ret = phy_rt_rtl8211f_reset(dev); + if (ret) { + LOG_ERR("Failed to reset phy (%d)", config->addr); + return ret; + } + + /* Set RGMII Tx/Rx Delay. */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, + PHY_RT_RTL8211F_PAGE_MIICR_ADDR); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_MIICR1_REG, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) mii control register1", config->addr); + return ret; + } + + reg_val |= PHY_RT_RTL8211F_MIICR1_TXDLY_MASK; + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_MIICR1_REG, reg_val); + if (ret) { + LOG_ERR("Error writing phy (%d) mii control register1", config->addr); + return ret; + } + + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_MIICR2_REG, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) mii control register2", config->addr); + return ret; + } + + reg_val |= PHY_RT_RTL8211F_MIICR2_RXDLY_MASK; + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_MIICR2_REG, reg_val); + if (ret) { + LOG_ERR("Error writing phy (%d) mii control register2", config->addr); + return ret; + } + + /* Restore to default page 0 */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, 0); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + + k_work_init_delayable(&data->phy_monitor_work, phy_rt_rtl8211f_monitor_work_handler); + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) + if (!config->interrupt_gpio.port) { + phy_rt_rtl8211f_monitor_work_handler(&data->phy_monitor_work.work); + goto skip_int_gpio; + } + + /* Set INTB/PMEB pin to interrupt mode */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, + PHY_RT_RTL8211F_PAGE_INTR_PIN_ADDR); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_INTR_PIN_REG, ®_val); + if (!ret) { + reg_val &= ~PHY_RT_RTL8211F_INTR_PIN_MASK; + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_INTR_PIN_REG, reg_val); + if (ret) { + LOG_ERR("Error writing phy (%d) interrupt pin setting register", + config->addr); + return ret; + } + } else { + LOG_ERR("Error reading phy (%d) interrupt pin setting register", config->addr); + return ret; + } + /* Restore to default page 0 */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, 0); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + + /* Clear interrupt */ + ret = phy_rt_rtl8211f_clear_interrupt(data); + if (ret) { + return ret; + } + + /* Configure interrupt pin */ + ret = gpio_pin_configure_dt(&config->interrupt_gpio, GPIO_INPUT); + if (ret) { + return ret; + } + + gpio_init_callback(&data->gpio_callback, phy_rt_rtl8211f_interrupt_handler, + BIT(config->interrupt_gpio.pin)); + ret = gpio_add_callback_dt(&config->interrupt_gpio, &data->gpio_callback); + if (ret) { + return ret; + } + + ret = gpio_pin_interrupt_configure_dt(&config->interrupt_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (ret) { + return ret; + } + + /* Enable PHY interrupt. */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, + PHY_RT_RTL8211F_PAGE_INTR_ADDR); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } + ret = phy_rt_rtl8211f_read(dev, PHY_RT_RTL8211F_INER_REG, ®_val); + if (ret) { + LOG_ERR("Error reading phy (%d) interrupt enable register", config->addr); + return ret; + } + reg_val |= PHY_RT_RTL8211F_INER_LINKSTATUS_CHANGE_MASK; + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_INER_REG, reg_val); + if (ret) { + LOG_ERR("Error writing phy (%d) interrupt enable register", config->addr); + return ret; + } + /* Restore to default page 0 */ + ret = phy_rt_rtl8211f_write(dev, PHY_RT_RTL8211F_PAGSR_REG, 0); + if (ret) { + LOG_ERR("Error writing phy (%d) page select register", config->addr); + return ret; + } +skip_int_gpio: +#else + phy_rt_rtl8211f_monitor_work_handler(&data->phy_monitor_work.work); +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + + return 0; +} + +static const struct ethphy_driver_api rt_rtl8211f_phy_api = { + .get_link = phy_rt_rtl8211f_get_link, + .cfg_link = phy_rt_rtl8211f_cfg_link, + .link_cb_set = phy_rt_rtl8211f_link_cb_set, + .read = phy_rt_rtl8211f_read, + .write = phy_rt_rtl8211f_write, +}; + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) +#define RESET_GPIO(n) \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), +#else +#define RESET_GPIO(n) +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) */ + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) +#define INTERRUPT_GPIO(n) \ + .interrupt_gpio = GPIO_DT_SPEC_INST_GET_OR(n, int_gpios, {0}), +#else +#define INTERRUPT_GPIO(n) +#endif /* DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) */ + +#define REALTEK_RTL8211F_INIT(n) \ + static const struct rt_rtl8211f_config rt_rtl8211f_##n##_config = { \ + .addr = DT_INST_REG_ADDR(n), \ + .mdio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + RESET_GPIO(n) \ + INTERRUPT_GPIO(n) \ + }; \ + \ + static struct rt_rtl8211f_data rt_rtl8211f_##n##_data; \ + \ + DEVICE_DT_INST_DEFINE(n, &phy_rt_rtl8211f_init, NULL, \ + &rt_rtl8211f_##n##_data, &rt_rtl8211f_##n##_config, \ + POST_KERNEL, CONFIG_PHY_INIT_PRIORITY, \ + &rt_rtl8211f_phy_api); + +DT_INST_FOREACH_STATUS_OKAY(REALTEK_RTL8211F_INIT) diff --git a/drivers/flash/CMakeLists.txt b/drivers/flash/CMakeLists.txt index ac7564c4708ea..76ee659d0b133 100644 --- a/drivers/flash/CMakeLists.txt +++ b/drivers/flash/CMakeLists.txt @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +zephyr_library_sources(flash_util.c) + zephyr_syscall_header_ifdef( CONFIG_FLASH_SIMULATOR ${ZEPHYR_BASE}/include/zephyr/drivers/flash/flash_simulator.h @@ -42,6 +44,7 @@ zephyr_library_sources_ifdef(CONFIG_FLASH_NPCX_FIU_QSPI flash_npcx_fiu_qspi.c) zephyr_library_sources_ifdef(CONFIG_FLASH_NPCX_FIU_NOR flash_npcx_fiu_nor.c) zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_QSPI flash_stm32_qspi.c) zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_OSPI flash_stm32_ospi.c) +zephyr_library_sources_ifdef(CONFIG_FLASH_STM32_XSPI flash_stm32_xspi.c) zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_MX25UM51345G flash_mcux_flexspi_mx25um51345g.c) zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_NOR flash_mcux_flexspi_nor.c) zephyr_library_sources_ifdef(CONFIG_FLASH_MCUX_FLEXSPI_HYPERFLASH flash_mcux_flexspi_hyperflash.c) @@ -70,6 +73,8 @@ endif() if(CONFIG_SOC_FLASH_STM32) if(CONFIG_SOC_SERIES_STM32H7X) zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32H7_FLASH_CONTROLLER_ENABLED flash_stm32h7x.c) + elseif(CONFIG_SOC_SERIES_STM32H7RSX) + zephyr_library_sources_ifdef(CONFIG_DT_HAS_ST_STM32H7_FLASH_CONTROLLER_ENABLED flash_stm32h7x.c) elseif(CONFIG_SOC_SERIES_STM32WBAX) if(CONFIG_BT_STM32WBA) # BLE is enabled. Use implementation over Flash Manager for coexistence wit RF activities diff --git a/drivers/flash/Kconfig b/drivers/flash/Kconfig index 6a1f816aa55ac..4816db0b580f5 100644 --- a/drivers/flash/Kconfig +++ b/drivers/flash/Kconfig @@ -17,6 +17,56 @@ config FLASH_HAS_EX_OP This option is selected by drivers that support flash extended operations. +config FLASH_HAS_EXPLICIT_ERASE + bool + help + Device has does not do erase-on-write (erase-on-program, auto-erase + on write) and requires explicit erase procedure to be programmed + with random value, in place where it has already been programmed with + some other value, as program can only change bits from erased-value + to the opposite. + All pure Flash devices are evolution of EEPROM where erase has + been separated from write, EEPROM has erase-on-write, giving + it advantage of higher write speeds at a cost of larger erase block. + Note that explicit-erase capability does not warrants that + write without erase is not allowed, taking the above restrictions, + it only states that write of a random information will require + erase. + Erase is usually performed in pages, as we have chosen to name + the unit in Zephyr, that may have different naming in device + specifications, like pages, sectors or blocks, and may vary + in size, depending how they are named by vendor. + This option should be selected by drivers that serve devices with + such characteristic and is used and may be used by users to provide + paths in code that only serve such devices, and could be + optimized-out by compiler in case where there is no such device in + a system. + +config FLASH_HAS_NO_EXPLICIT_ERASE + bool + help + Device does not require explicit erase before programming + a new random value at any location that has been previously + programmed with some other value. + Note that the device may have erase-on-write (auto-erase), + as for example in EEPROM devices, but may also have no erase + at all. + A device driver may still provide erase callback, + especially if it is able to perform erase to accelerate + further writes or is able to fill the area requested for + erase, with single value, faster than consecutive writes + that would be used to emulate erase. + This option should be selected by drivers that serve + devices with such characteristic and is used and may be + used by users to provide paths in code that only serve + such devices, and could be optimized-out by compiler in + case where there is no such device in a system. + This option should be selected for any device that + can change storage bits, by write, from any value to opposite + value at any time. + When your driver sets this option you also need to set + no_explicit_erase capability in your drivers flash_parameters. + config FLASH_HAS_PAGE_LAYOUT bool help @@ -77,13 +127,30 @@ config FLASH_SHELL_BUFFER_SIZE endif # FLASH_SHELL +config FLASH_FILL_BUFFER_SIZE + int "Buffer size of flash_fill funciton" + default 32 + help + Size of a buffer used by flash_fill function to fill a device with + specific value; this buffer is allocated on stack. + The buffer is needed as most devices have write-block alignment + requirements that which imposes minimal size of data, which can + be written to a device, and alignment of write offset. + Even if device does not have such requirement, filling device by + single bytes is not efficient. + Value selected here should be multiply of the largest write-block-size + among all the memory devices used in system. + +if FLASH_HAS_PAGE_LAYOUT + config FLASH_PAGE_LAYOUT bool "API for retrieving the layout of pages" - depends on FLASH_HAS_PAGE_LAYOUT - default y + default FLASH_HAS_PAGE_LAYOUT help Enables API for retrieving the layout of flash memory pages. +endif + config FLASH_EX_OP_ENABLED bool "API for extended flash operations" depends on FLASH_HAS_EX_OP @@ -132,6 +199,8 @@ source "drivers/flash/Kconfig.stm32_qspi" source "drivers/flash/Kconfig.stm32_ospi" +source "drivers/flash/Kconfig.stm32_xspi" + source "drivers/flash/Kconfig.sam0" source "drivers/flash/Kconfig.sam" diff --git a/drivers/flash/Kconfig.ambiq b/drivers/flash/Kconfig.ambiq index cc84c0faf39f1..da0df1fcdab73 100644 --- a/drivers/flash/Kconfig.ambiq +++ b/drivers/flash/Kconfig.ambiq @@ -2,11 +2,14 @@ # SPDX-License-Identifier: Apache-2.0 config FLASH_AMBIQ - bool "Ambiq flash driver on MRAM" + bool "Ambiq flash driver on MRAM or flash" default y depends on DT_HAS_AMBIQ_FLASH_CONTROLLER_ENABLED select AMBIQ_HAL select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_NO_EXPLICIT_ERASE if SOC_SERIES_APOLLO4X + select FLASH_HAS_EXPLICIT_ERASE if SOC_SERIES_APOLLO3X help - Enables Ambiq flash driver on MRAM. + Enables Ambiq flash driver on MRAM (e.g. Apollo4x) or + flash (e.g. Apollo3x). diff --git a/drivers/flash/Kconfig.andes b/drivers/flash/Kconfig.andes index d639cf20467e6..0a1a563519533 100644 --- a/drivers/flash/Kconfig.andes +++ b/drivers/flash/Kconfig.andes @@ -12,6 +12,7 @@ menuconfig FLASH_ANDES_QSPI select FLASH_HAS_PAGE_LAYOUT select FLASH_JESD216 select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE depends on !SPI_NOR help Enable driver for Andes QSPI diff --git a/drivers/flash/Kconfig.at45 b/drivers/flash/Kconfig.at45 index c1c892e33fd80..bf5c0add72c7d 100644 --- a/drivers/flash/Kconfig.at45 +++ b/drivers/flash/Kconfig.at45 @@ -7,6 +7,7 @@ menuconfig SPI_FLASH_AT45 depends on DT_HAS_ATMEL_AT45_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select SPI help This driver can handle several instances of AT45 family chips that diff --git a/drivers/flash/Kconfig.b91 b/drivers/flash/Kconfig.b91 index 46a8b10e804bf..a3f35da8581f3 100644 --- a/drivers/flash/Kconfig.b91 +++ b/drivers/flash/Kconfig.b91 @@ -7,5 +7,6 @@ config SOC_FLASH_TELINK_B91 depends on DT_HAS_TELINK_B91_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables Telink B91 flash driver. diff --git a/drivers/flash/Kconfig.cadence_nand b/drivers/flash/Kconfig.cadence_nand index 52b7a1422b109..436592aa2d8ef 100644 --- a/drivers/flash/Kconfig.cadence_nand +++ b/drivers/flash/Kconfig.cadence_nand @@ -10,6 +10,7 @@ config FLASH_CDNS_NAND depends on DT_HAS_CDNS_NAND_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enable Cadence NAND support. diff --git a/drivers/flash/Kconfig.cadence_qspi_nor b/drivers/flash/Kconfig.cadence_qspi_nor index 0bc9a33402c65..4209b256cfdb9 100644 --- a/drivers/flash/Kconfig.cadence_qspi_nor +++ b/drivers/flash/Kconfig.cadence_qspi_nor @@ -7,6 +7,7 @@ config FLASH_CAD_QSPI_NOR depends on DT_HAS_CDNS_QSPI_NOR_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enable Cadence QSPI-NOR support. diff --git a/drivers/flash/Kconfig.cc13xx_cc26xx b/drivers/flash/Kconfig.cc13xx_cc26xx index 3abc4fc2d7d34..e691dddb4727a 100644 --- a/drivers/flash/Kconfig.cc13xx_cc26xx +++ b/drivers/flash/Kconfig.cc13xx_cc26xx @@ -7,6 +7,7 @@ config SOC_FLASH_CC13XX_CC26XX depends on DT_HAS_TI_CC13XX_CC26XX_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enables TI SimpleLink CC13xx/CC26xx flash controller driver. diff --git a/drivers/flash/Kconfig.esp32 b/drivers/flash/Kconfig.esp32 index 3d5790d4a2f52..4da80bce0c0fd 100644 --- a/drivers/flash/Kconfig.esp32 +++ b/drivers/flash/Kconfig.esp32 @@ -7,6 +7,7 @@ config SOC_FLASH_ESP32 depends on DT_HAS_ESPRESSIF_ESP32_FLASH_CONTROLLER_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE help Enable ESP32 internal flash driver. diff --git a/drivers/flash/Kconfig.gd32 b/drivers/flash/Kconfig.gd32 index c3c86bf35795a..c4d8921a6aad0 100644 --- a/drivers/flash/Kconfig.gd32 +++ b/drivers/flash/Kconfig.gd32 @@ -7,6 +7,7 @@ config SOC_FLASH_GD32 depends on (GD32_NV_FLASH_V1 || GD32_NV_FLASH_V2 || GD32_NV_FLASH_V3) select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the GigaDevice GD32 flash driver. diff --git a/drivers/flash/Kconfig.gecko b/drivers/flash/Kconfig.gecko index 903b08373b32e..fc5478eae2698 100644 --- a/drivers/flash/Kconfig.gecko +++ b/drivers/flash/Kconfig.gecko @@ -10,6 +10,7 @@ config SOC_FLASH_GECKO select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT select SOC_GECKO_MSC + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable Silicon Labs Gecko series internal flash driver. diff --git a/drivers/flash/Kconfig.ifx_cat1 b/drivers/flash/Kconfig.ifx_cat1 index f8871d4d1e30d..4964258c4ec20 100644 --- a/drivers/flash/Kconfig.ifx_cat1 +++ b/drivers/flash/Kconfig.ifx_cat1 @@ -12,6 +12,7 @@ config FLASH_INFINEON_CAT1 select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED select USE_INFINEON_FLASH + select FLASH_HAS_EXPLICIT_ERASE help Enable the Flash driver for Infineon CAT1 family. diff --git a/drivers/flash/Kconfig.it8xxx2 b/drivers/flash/Kconfig.it8xxx2 index 50b881335a4fe..ef0307f65a39e 100644 --- a/drivers/flash/Kconfig.it8xxx2 +++ b/drivers/flash/Kconfig.it8xxx2 @@ -10,6 +10,7 @@ config SOC_FLASH_ITE_IT8XXX2 select SOC_IT8XXX2_USE_ILM select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select HAS_FLASH_LOAD_OFFSET help The flash driver includes support for read, write and diff --git a/drivers/flash/Kconfig.lpc b/drivers/flash/Kconfig.lpc index 379a4cdaadc70..4d1fd1940e0f1 100644 --- a/drivers/flash/Kconfig.lpc +++ b/drivers/flash/Kconfig.lpc @@ -8,6 +8,7 @@ config SOC_FLASH_LPC DT_HAS_NXP_IAP_FMC54_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables the LPC IAP flash shim driver. WARNING: This driver will disable the system interrupts for diff --git a/drivers/flash/Kconfig.mcux b/drivers/flash/Kconfig.mcux index 2cf9eac494d28..7b3df8361076b 100644 --- a/drivers/flash/Kconfig.mcux +++ b/drivers/flash/Kconfig.mcux @@ -11,6 +11,7 @@ config SOC_FLASH_MCUX DT_HAS_NXP_IAP_MSF1_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enables the MCUX flash shim driver. @@ -41,6 +42,7 @@ config FLASH_MCUX_FLEXSPI_NOR depends on DT_HAS_NXP_IMX_FLEXSPI_NOR_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select FLASH_JESD216 select MEMC select MEMC_MCUX_FLEXSPI @@ -51,6 +53,7 @@ config FLASH_MCUX_FLEXSPI_MX25UM51345G depends on DT_HAS_NXP_IMX_FLEXSPI_MX25UM51345G_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MEMC select MEMC_MCUX_FLEXSPI @@ -60,6 +63,7 @@ config FLASH_MCUX_FLEXSPI_HYPERFLASH depends on DT_HAS_NXP_IMX_FLEXSPI_HYPERFLASH_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MEMC select MEMC_MCUX_FLEXSPI diff --git a/drivers/flash/Kconfig.nios2_qspi b/drivers/flash/Kconfig.nios2_qspi index bcad6d9e50dd1..ab834b5b95635 100644 --- a/drivers/flash/Kconfig.nios2_qspi +++ b/drivers/flash/Kconfig.nios2_qspi @@ -6,5 +6,6 @@ config SOC_FLASH_NIOS2_QSPI depends on HAS_ALTERA_HAL depends on DT_HAS_ALTR_NIOS2_QSPI_NOR_ENABLED select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables the Nios-II QSPI flash driver. diff --git a/drivers/flash/Kconfig.nor b/drivers/flash/Kconfig.nor index 8263f7f6785da..eed33c8e1807f 100644 --- a/drivers/flash/Kconfig.nor +++ b/drivers/flash/Kconfig.nor @@ -1,4 +1,6 @@ # Copyright (c) 2018 Savoir-Faire Linux. +# Copyright (c) 2024 Nordic Semiconductor ASA +# # SPDX-License-Identifier: Apache-2.0 menuconfig SPI_NOR @@ -6,6 +8,7 @@ menuconfig SPI_NOR default y depends on DT_HAS_JEDEC_SPI_NOR_ENABLED select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select FLASH_HAS_PAGE_LAYOUT select FLASH_JESD216 select FLASH_HAS_EX_OP diff --git a/drivers/flash/Kconfig.nordic_qspi_nor b/drivers/flash/Kconfig.nordic_qspi_nor index 4acce55856791..82e1e197e3753 100644 --- a/drivers/flash/Kconfig.nordic_qspi_nor +++ b/drivers/flash/Kconfig.nordic_qspi_nor @@ -7,6 +7,7 @@ menuconfig NORDIC_QSPI_NOR depends on DT_HAS_NORDIC_QSPI_NOR_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select NRFX_QSPI select FLASH_JESD216 select PINCTRL diff --git a/drivers/flash/Kconfig.npcx_fiu b/drivers/flash/Kconfig.npcx_fiu index e4ac74c9d444e..9d464f48bb78c 100644 --- a/drivers/flash/Kconfig.npcx_fiu +++ b/drivers/flash/Kconfig.npcx_fiu @@ -18,6 +18,7 @@ config FLASH_NPCX_FIU_NOR depends on FLASH_NPCX_FIU_QSPI select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select FLASH_JESD216 select FLASH_HAS_EX_OP help diff --git a/drivers/flash/Kconfig.nrf b/drivers/flash/Kconfig.nrf index 769ccc7a51d52..48c4e0d3fb94b 100644 --- a/drivers/flash/Kconfig.nrf +++ b/drivers/flash/Kconfig.nrf @@ -17,6 +17,7 @@ menuconfig SOC_FLASH_NRF depends on !FLASH_NRF_FORCE_ALT select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select NRFX_NVMC select MPU_ALLOW_FLASH_WRITE if ARM_MPU help diff --git a/drivers/flash/Kconfig.nrf_mram b/drivers/flash/Kconfig.nrf_mram index 0ef65864a622f..be41cead07f18 100644 --- a/drivers/flash/Kconfig.nrf_mram +++ b/drivers/flash/Kconfig.nrf_mram @@ -10,6 +10,7 @@ config SOC_FLASH_NRF_MRAM depends on DT_HAS_NORDIC_MRAM_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_NO_EXPLICIT_ERASE imply MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enables Nordic Semiconductor flash driver for MRAM in direct write mode. diff --git a/drivers/flash/Kconfig.nrf_rram b/drivers/flash/Kconfig.nrf_rram index 68efde1ab3026..84214f809eb43 100644 --- a/drivers/flash/Kconfig.nrf_rram +++ b/drivers/flash/Kconfig.nrf_rram @@ -8,8 +8,10 @@ menuconfig SOC_FLASH_NRF_RRAM bool "Nordic Semiconductor flash driver for nRF RRAM" default y depends on DT_HAS_NORDIC_RRAM_CONTROLLER_ENABLED + select NRFX_RRAMC select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_NO_EXPLICIT_ERASE select FLASH_NRF_FORCE_ALT select MPU_ALLOW_FLASH_WRITE if ARM_MPU help @@ -66,4 +68,17 @@ config SOC_FLASH_NRF_TIMEOUT_MULTIPLIER the multiplication would allow erasing all nRF flash pages in blocking mode. +config NRF_RRAM_REGION_ADDRESS_RESOLUTION + hex + default 0x400 + help + RRAMC's region protection address resolution. + Applies to region with configurable start address. + +config NRF_RRAM_REGION_SIZE_UNIT + hex + default 0x400 + help + Base unit for the size of RRAMC's region protection. + endif # SOC_FLASH_NRF_RRAM diff --git a/drivers/flash/Kconfig.numaker b/drivers/flash/Kconfig.numaker index 98d4790589d3f..4ab0f46271dc3 100644 --- a/drivers/flash/Kconfig.numaker +++ b/drivers/flash/Kconfig.numaker @@ -8,6 +8,7 @@ config SOC_FLASH_NUMAKER default y select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select HAS_NUMAKER_FMC depends on DT_HAS_NUVOTON_NUMAKER_FMC_ENABLED help diff --git a/drivers/flash/Kconfig.numaker_rmc b/drivers/flash/Kconfig.numaker_rmc index ae149115255f7..72fd64c4d494d 100644 --- a/drivers/flash/Kconfig.numaker_rmc +++ b/drivers/flash/Kconfig.numaker_rmc @@ -8,6 +8,7 @@ config SOC_FLASH_NUMAKER_RMC default y select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_NO_EXPLICIT_ERASE select HAS_NUMAKER_RMC depends on DT_HAS_NUVOTON_NUMAKER_RMC_ENABLED help diff --git a/drivers/flash/Kconfig.nxp_s32 b/drivers/flash/Kconfig.nxp_s32 index 08a96f1cec9bf..47db1ab654eea 100644 --- a/drivers/flash/Kconfig.nxp_s32 +++ b/drivers/flash/Kconfig.nxp_s32 @@ -9,6 +9,7 @@ config FLASH_NXP_S32_QSPI_NOR select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED select FLASH_JESD216 + select FLASH_HAS_EXPLICIT_ERASE help Enable the Flash driver for a NOR Serial Flash Memory device connected to an NXP S32 QSPI bus. diff --git a/drivers/flash/Kconfig.rpi_pico b/drivers/flash/Kconfig.rpi_pico index 4d7fee169417f..b41cd843c0899 100644 --- a/drivers/flash/Kconfig.rpi_pico +++ b/drivers/flash/Kconfig.rpi_pico @@ -8,6 +8,7 @@ config FLASH_RPI_PICO depends on DT_HAS_RASPBERRYPI_PICO_FLASH_CONTROLLER_ENABLED select FLASH_HAS_DRIVER_ENABLED select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select PICOSDK_USE_FLASH help Enable Raspberry Pi Pico flash driver. diff --git a/drivers/flash/Kconfig.rv32m1 b/drivers/flash/Kconfig.rv32m1 index 0dd7f29012918..46ada40d7c3f3 100644 --- a/drivers/flash/Kconfig.rv32m1 +++ b/drivers/flash/Kconfig.rv32m1 @@ -7,6 +7,7 @@ config SOC_FLASH_RV32M1 depends on DT_HAS_OPENISA_RV32M1_FTFE_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables the RV32M1 flash shim driver. WARNING: This driver will disable the system interrupts for diff --git a/drivers/flash/Kconfig.sam b/drivers/flash/Kconfig.sam index bb014d6527990..1e30636390d0f 100644 --- a/drivers/flash/Kconfig.sam +++ b/drivers/flash/Kconfig.sam @@ -9,6 +9,7 @@ config SOC_FLASH_SAM depends on DT_HAS_ATMEL_SAM_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the Atmel SAM series internal flash driver. diff --git a/drivers/flash/Kconfig.sam0 b/drivers/flash/Kconfig.sam0 index accaa30d3039d..f285aa868f847 100644 --- a/drivers/flash/Kconfig.sam0 +++ b/drivers/flash/Kconfig.sam0 @@ -9,6 +9,7 @@ menuconfig SOC_FLASH_SAM0 depends on DT_HAS_ATMEL_SAM0_NVMCTRL_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable the Atmel SAM0 series internal flash driver. diff --git a/drivers/flash/Kconfig.simulator b/drivers/flash/Kconfig.simulator index e32a2a72bb0da..fd75479b31682 100644 --- a/drivers/flash/Kconfig.simulator +++ b/drivers/flash/Kconfig.simulator @@ -22,12 +22,32 @@ config FLASH_SIMULATOR_UNALIGNED_READ Disable this option only if you want to simulate a specific FLASH interface that requires aligned read access. +config FLASH_SIMULATOR_EXPLICIT_ERASE + bool "Program-erase device" + select FLASH_HAS_EXPLICIT_ERASE + default y + help + Explicit erase (non-erase-on-write) Flash, which is device that requires erase + to erase-value prior to write as it only allows to change bits from erase-value + to the opposite. + +config FLASH_SIMULATOR_RAMLIKE + bool + default y if !FLASH_SIMULATOR_EXPLICIT_ERASE + select FLASH_HAS_NO_EXPLICIT_ERASE + select FLASH_SIMULATOR_DOUBLE_WRITES + help + This is used for setting FLASH_HAS_NO_EXPLICIT_ERASE. + config FLASH_SIMULATOR_DOUBLE_WRITES bool "Allow program units to be programmed more than once" help If selected, writing to a non-erased program unit will succeed, otherwise, it will return an error. Keep in mind that write operations can only change value of a bit from erase-value to the opposite. + This option does not impact FLASH_SIMULATOR_RAMLIKE. + In case when FLASH_SIMULATOR_EXPLICIT_ERASE is selected multiple writes to the same bit + but only change from erase-value to opposite will be registered. config FLASH_SIMULATOR_SIMULATE_TIMING bool "Hardware timing simulation" diff --git a/drivers/flash/Kconfig.smartbond b/drivers/flash/Kconfig.smartbond index 3cc587ba7e197..5d5dbd6a98e36 100644 --- a/drivers/flash/Kconfig.smartbond +++ b/drivers/flash/Kconfig.smartbond @@ -7,6 +7,7 @@ config SOC_FLASH_SMARTBOND depends on DT_HAS_RENESAS_SMARTBOND_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU help Enable flash driver for Renesas SmartBond(tm) MCU family. diff --git a/drivers/flash/Kconfig.stm32 b/drivers/flash/Kconfig.stm32 index 1ba8c33a7ec62..0c820da97c1c9 100644 --- a/drivers/flash/Kconfig.stm32 +++ b/drivers/flash/Kconfig.stm32 @@ -6,12 +6,22 @@ # Copyright (c) 2023 Google Inc # SPDX-License-Identifier: Apache-2.0 +config STM32_MEMMAP + bool "NOR Flash in MemoryMapped for XiP" + depends on XIP && \ + (DT_HAS_ST_STM32_OSPI_NOR_ENABLED || \ + DT_HAS_ST_STM32_QSPI_NOR_ENABLED) + help + This option enables the XIP mode for the external NOR flash + mounted on STM32 boards. + config SOC_FLASH_STM32 bool "STM32 flash driver" depends on DT_HAS_ST_STM32_FLASH_CONTROLLER_ENABLED select FLASH_HAS_DRIVER_ENABLED default y select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select MPU_ALLOW_FLASH_WRITE if ARM_MPU select USE_STM32_HAL_FLASH if BT_STM32WBA select USE_STM32_HAL_FLASH_EX if BT_STM32WBA @@ -64,6 +74,7 @@ config FLASH_STM32_READOUT_PROTECTION_PERMANENT_ALLOW config FLASH_STM32_BLOCK_REGISTERS bool "Extended operation for blocking option and control registers" + select FLASH_HAS_EX_OP default n help Enables flash extended operations that can be used to disable access diff --git a/drivers/flash/Kconfig.stm32_ospi b/drivers/flash/Kconfig.stm32_ospi index 305fcfac76d13..2cc2ffcab5c00 100644 --- a/drivers/flash/Kconfig.stm32_ospi +++ b/drivers/flash/Kconfig.stm32_ospi @@ -17,6 +17,7 @@ config FLASH_STM32_OSPI select FLASH_HAS_DRIVER_ENABLED select FLASH_JESD216 select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select DMA if $(DT_STM32_OCTOSPI_1_HAS_DMA) || $(DT_STM32_OCTOSPI_2_HAS_DMA) select USE_STM32_HAL_DMA if $(DT_STM32_OCTOSPI_1_HAS_DMA) || \ $(DT_STM32_OCTOSPI_2_HAS_DMA) diff --git a/drivers/flash/Kconfig.stm32_qspi b/drivers/flash/Kconfig.stm32_qspi index c97be5ef354b4..4aeeaf3e2ee34 100644 --- a/drivers/flash/Kconfig.stm32_qspi +++ b/drivers/flash/Kconfig.stm32_qspi @@ -15,6 +15,7 @@ config FLASH_STM32_QSPI select FLASH_HAS_DRIVER_ENABLED select FLASH_JESD216 select FLASH_HAS_PAGE_LAYOUT + select FLASH_HAS_EXPLICIT_ERASE select DMA if $(DT_STM32_QUADSPI_HAS_DMA) select USE_STM32_HAL_DMA if $(DT_STM32_QUADSPI_HAS_DMA) help diff --git a/drivers/flash/Kconfig.stm32_xspi b/drivers/flash/Kconfig.stm32_xspi new file mode 100644 index 0000000000000..56241e2ebd3a4 --- /dev/null +++ b/drivers/flash/Kconfig.stm32_xspi @@ -0,0 +1,26 @@ +# STM32 xSPI flash driver configuration options + +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +DT_STM32_XSPI_1_HAS_DMA := $(dt_nodelabel_has_prop,xspi1,dmas) +DT_STM32_XSPI_2_HAS_DMA := $(dt_nodelabel_has_prop,xspi2,dmas) + +config FLASH_STM32_XSPI + bool "STM32 XSPI Flash driver" + default y + depends on DT_HAS_ST_STM32_XSPI_ENABLED && DT_HAS_ST_STM32_XSPI_NOR_ENABLED + select USE_STM32_HAL_XSPI + select USE_STM32_LL_DLYB + select FLASH_HAS_DRIVER_ENABLED + select FLASH_JESD216 + select FLASH_PAGE_LAYOUT + select FLASH_HAS_PAGE_LAYOUT + select DMA if $(DT_STM32_XSPI_1_HAS_DMA) || $(DT_STM32_XSPI_2_HAS_DMA) + select USE_STM32_HAL_DMA if $(DT_STM32_XSPI_1_HAS_DMA) || \ + $(DT_STM32_XSPI_2_HAS_DMA) + select USE_STM32_HAL_DMA_EX if SOC_SERIES_STM32H5X && \ + ($(DT_STM32_XSPI_1_HAS_DMA) || \ + $(DT_STM32_XSPI_2_HAS_DMA)) + help + Enable XSPI-NOR support on the STM32 family of processors. diff --git a/drivers/flash/Kconfig.xmc4xxx b/drivers/flash/Kconfig.xmc4xxx index 60e5f08a759ef..eff7b1e5679e9 100644 --- a/drivers/flash/Kconfig.xmc4xxx +++ b/drivers/flash/Kconfig.xmc4xxx @@ -7,5 +7,6 @@ config SOC_FLASH_XMC4XXX depends on DT_HAS_INFINEON_XMC4XXX_FLASH_CONTROLLER_ENABLED select FLASH_HAS_PAGE_LAYOUT select FLASH_HAS_DRIVER_ENABLED + select FLASH_HAS_EXPLICIT_ERASE help Enables XMC4XXX flash driver. diff --git a/drivers/flash/flash_ambiq.c b/drivers/flash/flash_ambiq.c index fdc852c04ca8c..b496790b95868 100644 --- a/drivers/flash/flash_ambiq.c +++ b/drivers/flash/flash_ambiq.c @@ -15,15 +15,19 @@ LOG_MODULE_REGISTER(flash_ambiq, CONFIG_FLASH_LOG_LEVEL); -#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) -#define SOC_NV_FLASH_ADDR DT_REG_ADDR(SOC_NV_FLASH_NODE) -#define SOC_NV_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE) -#define MIN_WRITE_SIZE 16 +#define SOC_NV_FLASH_NODE DT_INST(0, soc_nv_flash) +#define SOC_NV_FLASH_ADDR DT_REG_ADDR(SOC_NV_FLASH_NODE) +#define SOC_NV_FLASH_SIZE DT_REG_SIZE(SOC_NV_FLASH_NODE) +#if (CONFIG_SOC_SERIES_APOLLO4X) +#define MIN_WRITE_SIZE 16 +#else +#define MIN_WRITE_SIZE 4 +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ #define FLASH_WRITE_BLOCK_SIZE MAX(DT_PROP(SOC_NV_FLASH_NODE, write_block_size), MIN_WRITE_SIZE) #define FLASH_ERASE_BLOCK_SIZE DT_PROP(SOC_NV_FLASH_NODE, erase_block_size) BUILD_ASSERT((FLASH_WRITE_BLOCK_SIZE & (MIN_WRITE_SIZE - 1)) == 0, - "The flash write block size must be a multiple of 16!"); + "The flash write block size must be a multiple of MIN_WRITE_SIZE!"); #define FLASH_ERASE_BYTE 0xFF #define FLASH_ERASE_WORD \ @@ -44,6 +48,11 @@ static struct k_sem flash_ambiq_sem; static const struct flash_parameters flash_ambiq_parameters = { .write_block_size = FLASH_WRITE_BLOCK_SIZE, .erase_value = FLASH_ERASE_BYTE, +#if defined(CONFIG_SOC_SERIES_APOLLO4X) + .caps = { + .no_explicit_erase = true, + }, +#endif }; static bool flash_ambiq_valid_range(off_t offset, size_t len) @@ -77,7 +86,7 @@ static int flash_ambiq_write(const struct device *dev, off_t offset, const void ARG_UNUSED(dev); int ret = 0; - uint32_t critical = 0; + unsigned int key = 0; uint32_t aligned[FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)] = {0}; uint32_t *src = (uint32_t *)data; @@ -96,22 +105,31 @@ static int flash_ambiq_write(const struct device *dev, off_t offset, const void FLASH_SEM_TAKE(); - critical = am_hal_interrupt_master_disable(); + key = irq_lock(); + for (int i = 0; i < len / FLASH_WRITE_BLOCK_SIZE; i++) { for (int j = 0; j < FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t); j++) { /* Make sure the source data is 4-byte aligned. */ aligned[j] = UNALIGNED_GET((uint32_t *)src); src++; } +#if (CONFIG_SOC_SERIES_APOLLO4X) ret = am_hal_mram_main_program( AM_HAL_MRAM_PROGRAM_KEY, aligned, (uint32_t *)(SOC_NV_FLASH_ADDR + offset + i * FLASH_WRITE_BLOCK_SIZE), FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)); +#elif (CONFIG_SOC_SERIES_APOLLO3X) + ret = am_hal_flash_program_main( + AM_HAL_FLASH_PROGRAM_KEY, aligned, + (uint32_t *)(SOC_NV_FLASH_ADDR + offset + i * FLASH_WRITE_BLOCK_SIZE), + FLASH_WRITE_BLOCK_SIZE / sizeof(uint32_t)); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ if (ret) { break; } } - am_hal_interrupt_master_set(critical); + + irq_unlock(key); FLASH_SEM_GIVE(); @@ -128,17 +146,42 @@ static int flash_ambiq_erase(const struct device *dev, off_t offset, size_t len) return -EINVAL; } - /* The erase address and length alignment check will be done in HAL.*/ - if (len == 0) { return 0; } +#if (CONFIG_SOC_SERIES_APOLLO4X) + /* The erase address and length alignment check will be done in HAL.*/ +#elif (CONFIG_SOC_SERIES_APOLLO3X) + if ((offset % FLASH_ERASE_BLOCK_SIZE) != 0) { + LOG_ERR("offset 0x%lx is not on a page boundary", (long)offset); + return -EINVAL; + } + + if ((len % FLASH_ERASE_BLOCK_SIZE) != 0) { + LOG_ERR("len %zu is not multiple of a page size", len); + return -EINVAL; + } +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ + FLASH_SEM_TAKE(); +#if (CONFIG_SOC_SERIES_APOLLO4X) ret = am_hal_mram_main_fill(AM_HAL_MRAM_PROGRAM_KEY, FLASH_ERASE_WORD, (uint32_t *)(SOC_NV_FLASH_ADDR + offset), (len / sizeof(uint32_t))); +#elif (CONFIG_SOC_SERIES_APOLLO3X) + unsigned int key = 0; + + key = irq_lock(); + + ret = am_hal_flash_page_erase( + AM_HAL_FLASH_PROGRAM_KEY, + AM_HAL_FLASH_ADDR2INST(((uint32_t)SOC_NV_FLASH_ADDR + offset)), + AM_HAL_FLASH_ADDR2PAGE(((uint32_t)SOC_NV_FLASH_ADDR + offset))); + + irq_unlock(key); +#endif /* CONFIG_SOC_SERIES_APOLLO4X */ FLASH_SEM_GIVE(); diff --git a/drivers/flash/flash_handlers.c b/drivers/flash/flash_handlers.c index 8c047adbaf4a6..338c6c8402d61 100644 --- a/drivers/flash/flash_handlers.c +++ b/drivers/flash/flash_handlers.c @@ -16,7 +16,7 @@ static inline int z_vrfy_flash_read(const struct device *dev, off_t offset, (void *)data, len); } -#include +#include static inline int z_vrfy_flash_write(const struct device *dev, off_t offset, const void *data, size_t len) @@ -26,7 +26,7 @@ static inline int z_vrfy_flash_write(const struct device *dev, off_t offset, return z_impl_flash_write((const struct device *)dev, offset, (const void *)data, len); } -#include +#include static inline int z_vrfy_flash_erase(const struct device *dev, off_t offset, size_t size) @@ -34,21 +34,37 @@ static inline int z_vrfy_flash_erase(const struct device *dev, off_t offset, K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, erase)); return z_impl_flash_erase((const struct device *)dev, offset, size); } -#include +#include static inline size_t z_vrfy_flash_get_write_block_size(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); return z_impl_flash_get_write_block_size(dev); } -#include +#include static inline const struct flash_parameters *z_vrfy_flash_get_parameters(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, get_parameters)); return z_impl_flash_get_parameters(dev); } -#include +#include + +int z_vrfy_flash_fill(const struct device *dev, uint8_t val, off_t offset, + size_t size) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); + return z_impl_flash_fill(dev, val, offset, size); +} +#include + +int z_vrfy_flash_flatten(const struct device *dev, off_t offset, size_t size) +{ + K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_FLASH)); + return z_impl_flash_flatten(dev, offset, size); +} + +#include #ifdef CONFIG_FLASH_PAGE_LAYOUT static inline int z_vrfy_flash_get_page_info_by_offs(const struct device *dev, @@ -61,7 +77,7 @@ static inline int z_vrfy_flash_get_page_info_by_offs(const struct device *dev, offs, (struct flash_pages_info *)info); } -#include +#include static inline int z_vrfy_flash_get_page_info_by_idx(const struct device *dev, uint32_t idx, @@ -73,14 +89,14 @@ static inline int z_vrfy_flash_get_page_info_by_idx(const struct device *dev, idx, (struct flash_pages_info *)info); } -#include +#include static inline size_t z_vrfy_flash_get_page_count(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_FLASH(dev, page_layout)); return z_impl_flash_get_page_count((const struct device *)dev); } -#include +#include #endif /* CONFIG_FLASH_PAGE_LAYOUT */ @@ -94,7 +110,7 @@ static inline int z_vrfy_flash_sfdp_read(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(data, len)); return z_impl_flash_sfdp_read(dev, offset, data, len); } -#include +#include static inline int z_vrfy_flash_read_jedec_id(const struct device *dev, uint8_t *id) @@ -103,7 +119,7 @@ static inline int z_vrfy_flash_read_jedec_id(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(id, 3)); return z_impl_flash_read_jedec_id(dev, id); } -#include +#include #endif /* CONFIG_FLASH_JESD216_API */ @@ -122,6 +138,6 @@ static inline int z_vrfy_flash_ex_op(const struct device *dev, uint16_t code, return z_impl_flash_ex_op(dev, code, in, out); } -#include +#include #endif /* CONFIG_FLASH_EX_OP_ENABLED */ diff --git a/drivers/flash/flash_mcux_flexspi_nor.c b/drivers/flash/flash_mcux_flexspi_nor.c index bfcef6daebd74..175e75554f24a 100644 --- a/drivers/flash/flash_mcux_flexspi_nor.c +++ b/drivers/flash/flash_mcux_flexspi_nor.c @@ -52,8 +52,10 @@ enum { READ_STATUS_REG, ERASE_CHIP, READ_JESD216, + /* Entries after this should be for scratch commands */ + FLEXSPI_INSTR_PROG_END, /* Used for temporary commands during initialization */ - SCRATCH_CMD, + SCRATCH_CMD = FLEXSPI_INSTR_PROG_END, SCRATCH_CMD2, /* Must be last entry */ FLEXSPI_INSTR_END, @@ -718,22 +720,23 @@ static int flash_flexspi_nor_config_flash(struct flash_flexspi_nor_data *data, /* Check to see if we can enable 4 byte addressing */ ret = jesd216_bfp_decode_dw16(&header->phdr[0], bfp, &dw16); - if (ret < 0) { - return ret; - } - - /* Attempt to enable 4 byte addressing */ - ret = flash_flexspi_nor_4byte_enable(data, flexspi_lut, dw16.enter_4ba); if (ret == 0) { - /* Use 4 byte address width */ - addr_width = 32; - /* Update LUT for ERASE_SECTOR and ERASE_BLOCK to use 32 bit addr */ - flexspi_lut[ERASE_SECTOR][0] = FLEXSPI_LUT_SEQ( - kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_SE, - kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, addr_width); - flexspi_lut[ERASE_BLOCK][0] = FLEXSPI_LUT_SEQ( - kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_BE, - kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, addr_width); + /* Attempt to enable 4 byte addressing */ + ret = flash_flexspi_nor_4byte_enable(data, flexspi_lut, + dw16.enter_4ba); + if (ret == 0) { + /* Use 4 byte address width */ + addr_width = 32; + /* Update LUT for ERASE_SECTOR and ERASE_BLOCK to use 32 bit addr */ + flexspi_lut[ERASE_SECTOR][0] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, + SPI_NOR_CMD_SE, kFLEXSPI_Command_RADDR_SDR, + kFLEXSPI_1PAD, addr_width); + flexspi_lut[ERASE_BLOCK][0] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, + SPI_NOR_CMD_BE, kFLEXSPI_Command_RADDR_SDR, + kFLEXSPI_1PAD, addr_width); + } } /* Extract the read command. * Note- enhanced XIP not currently supported, nor is 4-4-4 mode. @@ -764,20 +767,21 @@ static int flash_flexspi_nor_config_flash(struct flash_flexspi_nor_data *data, kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0); /* Read 1S-4S-4S enable method */ ret = jesd216_bfp_decode_dw15(&header->phdr[0], bfp, &dw15); - if (ret < 0) { - return ret; - } - ret = flash_flexspi_nor_quad_enable(data, flexspi_lut, dw15.qer); - if (ret < 0) { - return ret; + if (ret == 0) { + ret = flash_flexspi_nor_quad_enable(data, flexspi_lut, + dw15.qer); + if (ret == 0) { + /* Now, install 1S-1S-4S page program command */ + flexspi_lut[PAGE_PROGRAM][0] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, + SPI_NOR_CMD_PP_1_1_4, kFLEXSPI_Command_RADDR_SDR, + kFLEXSPI_1PAD, addr_width); + flexspi_lut[PAGE_PROGRAM][1] = FLEXSPI_LUT_SEQ( + kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, + 0x4, kFLEXSPI_Command_STOP, + kFLEXSPI_1PAD, 0x0); + } } - /* Now, install 1S-1S-4S page program command */ - flexspi_lut[PAGE_PROGRAM][0] = FLEXSPI_LUT_SEQ( - kFLEXSPI_Command_SDR, kFLEXSPI_1PAD, SPI_NOR_CMD_PP_1_1_4, - kFLEXSPI_Command_RADDR_SDR, kFLEXSPI_1PAD, addr_width); - flexspi_lut[PAGE_PROGRAM][1] = FLEXSPI_LUT_SEQ( - kFLEXSPI_Command_WRITE_SDR, kFLEXSPI_4PAD, 0x4, - kFLEXSPI_Command_STOP, kFLEXSPI_1PAD, 0x0); } else if (jesd216_bfp_read_support(&header->phdr[0], bfp, JESD216_MODE_122, &instr) > 0) { @@ -817,7 +821,8 @@ static int flash_flexspi_nor_config_flash(struct flash_flexspi_nor_data *data, /* Now, read DW14 to determine the polling method we should use while programming */ ret = jesd216_bfp_decode_dw14(&header->phdr[0], bfp, &dw14); if (ret < 0) { - return ret; + /* Default to legacy polling mode */ + dw14.poll_options = 0x0; } if (dw14.poll_options & BIT(1)) { /* Read instruction used for polling is 0x70 */ @@ -1014,7 +1019,7 @@ static int flash_flexspi_nor_probe(struct flash_flexspi_nor_data *data) */ ret = memc_flexspi_set_device_config(&data->controller, &data->config, (uint32_t *)flexspi_lut, - FLEXSPI_INSTR_END * MEMC_FLEXSPI_CMD_PER_SEQ, + FLEXSPI_INSTR_PROG_END * MEMC_FLEXSPI_CMD_PER_SEQ, data->port); if (ret < 0) { return ret; diff --git a/drivers/flash/flash_shell.c b/drivers/flash/flash_shell.c index 015bbbe99158e..a0d6a19a2332a 100644 --- a/drivers/flash/flash_shell.c +++ b/drivers/flash/flash_shell.c @@ -73,9 +73,11 @@ static int parse_helper(const struct shell *sh, size_t *argc, static int cmd_erase(const struct shell *sh, size_t argc, char *argv[]) { + int result = -ENOTSUP; + +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) const struct device *flash_dev; uint32_t page_addr; - int result; uint32_t size; result = parse_helper(sh, &argc, &argv, &flash_dev, &page_addr); @@ -106,6 +108,7 @@ static int cmd_erase(const struct shell *sh, size_t argc, char *argv[]) } else { shell_print(sh, "Erase success."); } +#endif return result; } diff --git a/drivers/flash/flash_simulator.c b/drivers/flash/flash_simulator.c index 12cd86078550c..3a7d578a250a6 100644 --- a/drivers/flash/flash_simulator.c +++ b/drivers/flash/flash_simulator.c @@ -162,7 +162,12 @@ static const struct flash_driver_api flash_sim_api; static const struct flash_parameters flash_sim_parameters = { .write_block_size = FLASH_SIMULATOR_PROG_UNIT, - .erase_value = FLASH_SIMULATOR_ERASE_VALUE + .erase_value = FLASH_SIMULATOR_ERASE_VALUE, + .caps = { +#if !defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) + .no_explicit_erase = false, +#endif + }, }; static int flash_range_is_valid(const struct device *dev, off_t offset, @@ -226,8 +231,12 @@ static int flash_sim_write(const struct device *dev, const off_t offset, FLASH_SIM_STATS_INC(flash_sim_stats, flash_write_calls); +#if defined(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) /* check if any unit has been already programmed */ memset(buf, FLASH_SIMULATOR_ERASE_VALUE, sizeof(buf)); +#else + memcpy(buf, MOCK_FLASH(offset), sizeof(buf)); +#endif for (uint32_t i = 0; i < len; i += FLASH_SIMULATOR_PROG_UNIT) { if (memcmp(buf, MOCK_FLASH(offset + i), sizeof(buf))) { FLASH_SIM_STATS_INC(flash_sim_stats, double_writes); @@ -265,10 +274,14 @@ static int flash_sim_write(const struct device *dev, const off_t offset, #endif /* CONFIG_FLASH_SIMULATOR_STATS */ /* only pull bits to zero */ +#if IS_ENABLED(CONFIG_FLASH_SIMULATOR_EXPLICIT_ERASE) #if FLASH_SIMULATOR_ERASE_VALUE == 0xFF *(MOCK_FLASH(offset + i)) &= *((uint8_t *)data + i); #else *(MOCK_FLASH(offset + i)) |= *((uint8_t *)data + i); +#endif +#else + *(MOCK_FLASH(offset + i)) = *((uint8_t *)data + i); #endif } @@ -491,6 +504,6 @@ void *z_vrfy_flash_simulator_get_memory(const struct device *dev, return z_impl_flash_simulator_get_memory(dev, mock_size); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/drivers/flash/flash_stm32.h b/drivers/flash/flash_stm32.h index 3583a1379c6cd..ca08b7e16ae1c 100644 --- a/drivers/flash/flash_stm32.h +++ b/drivers/flash/flash_stm32.h @@ -45,6 +45,17 @@ struct flash_stm32_priv { #define OPTR OPTCR #endif /* CONFIG_SOC_SERIES_STM32H5X */ +/* Register mapping for the stm32H7RS serie (single bank)*/ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define FLASH_NB_32BITWORD_IN_FLASHWORD 4 /* 128 bits */ +#define CR1 CR +#define SR1 SR +/* flash sectore Nb [0-7] */ +#define FLASH_CR_SNB FLASH_CR_SSN +#define FLASH_CR_SNB_Pos FLASH_CR_SSN_Pos +#define KEYR1 KEYR +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ + /* Differentiate between arm trust-zone non-secure/secure, and others. */ #if defined(FLASH_NSSR_NSBSY) || defined(FLASH_NSSR_BSY) /* For mcu w. TZ in non-secure mode */ #define FLASH_SECURITY_NS diff --git a/drivers/flash/flash_stm32_ospi.c b/drivers/flash/flash_stm32_ospi.c index fa9df2937e7b7..c893545db226f 100644 --- a/drivers/flash/flash_stm32_ospi.c +++ b/drivers/flash/flash_stm32_ospi.c @@ -36,6 +36,9 @@ LOG_MODULE_REGISTER(flash_stm32_ospi, CONFIG_FLASH_LOG_LEVEL); (_CONCAT(HAL_OSPIM_, DT_STRING_TOKEN(STM32_OSPI_NODE, prop))), \ ((default_value))) +#define DT_OSPI_PROP_OR(prop, default_value) \ + DT_PROP_OR(STM32_OSPI_NODE, prop, default_value) + /* Get the base address of the flash from the DTS node */ #define STM32_OSPI_BASE_ADDRESS DT_INST_REG_ADDR(0) @@ -895,6 +898,8 @@ static int stm32_ospi_mem_reset(const struct device *dev) struct flash_stm32_ospi_data *dev_data = dev->data; #if STM32_OSPI_RESET_GPIO + const struct flash_stm32_ospi_config *dev_cfg = dev->config; + /* Generate RESETn pulse for the flash memory */ gpio_pin_configure_dt(&dev_cfg->reset, GPIO_OUTPUT_ACTIVE); k_msleep(DT_INST_PROP(0, reset_gpios_duration)); @@ -975,11 +980,149 @@ static int stm32_ospi_mem_reset(const struct device *dev) return 0; } +#ifdef CONFIG_STM32_MEMMAP +/* Function to configure the octoflash in MemoryMapped mode */ +static int stm32_ospi_set_memorymap(const struct device *dev) +{ + HAL_StatusTypeDef ret; + const struct flash_stm32_ospi_config *dev_cfg = dev->config; + struct flash_stm32_ospi_data *dev_data = dev->data; + OSPI_RegularCmdTypeDef s_command; + OSPI_MemoryMappedTypeDef s_MemMappedCfg; + + /* Configure octoflash in MemoryMapped mode */ + if ((dev_cfg->data_mode == OSPI_SPI_MODE) && + (stm32_ospi_hal_address_size(dev) == HAL_OSPI_ADDRESS_24_BITS)) { + /* OPI mode and 3-bytes address size not supported by memory */ + LOG_ERR("OSPI_SPI_MODE in 3Bytes addressing is not supported"); + return -EIO; + } + + /* Initialize the read command */ + s_command.OperationType = HAL_OSPI_OPTYPE_READ_CFG; + s_command.FlashId = HAL_OSPI_FLASH_ID_1; + s_command.InstructionMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? HAL_OSPI_INSTRUCTION_1_LINE + : HAL_OSPI_INSTRUCTION_8_LINES) + : HAL_OSPI_INSTRUCTION_8_LINES; + s_command.InstructionDtrMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? HAL_OSPI_INSTRUCTION_DTR_DISABLE + : HAL_OSPI_INSTRUCTION_DTR_ENABLE; + s_command.InstructionSize = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? HAL_OSPI_INSTRUCTION_8_BITS + : HAL_OSPI_INSTRUCTION_16_BITS) + : HAL_OSPI_INSTRUCTION_16_BITS; + s_command.Instruction = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? ((stm32_ospi_hal_address_size(dev) == + HAL_OSPI_ADDRESS_24_BITS) + ? SPI_NOR_CMD_READ_FAST + : SPI_NOR_CMD_READ_FAST_4B) + : dev_data->read_opcode) + : SPI_NOR_OCMD_DTR_RD; + s_command.AddressMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? HAL_OSPI_ADDRESS_1_LINE + : HAL_OSPI_ADDRESS_8_LINES) + : HAL_OSPI_ADDRESS_8_LINES; + s_command.AddressDtrMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? HAL_OSPI_ADDRESS_DTR_DISABLE + : HAL_OSPI_ADDRESS_DTR_ENABLE; + s_command.AddressSize = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? stm32_ospi_hal_address_size(dev) + : HAL_OSPI_ADDRESS_32_BITS; + s_command.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE; + s_command.DataMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? HAL_OSPI_DATA_1_LINE + : HAL_OSPI_DATA_8_LINES) + : HAL_OSPI_DATA_8_LINES; + s_command.DataDtrMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? HAL_OSPI_DATA_DTR_DISABLE + : HAL_OSPI_DATA_DTR_ENABLE; + s_command.DummyCycles = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? ((dev_cfg->data_mode == OSPI_SPI_MODE) + ? SPI_NOR_DUMMY_RD + : SPI_NOR_DUMMY_RD_OCTAL) + : SPI_NOR_DUMMY_RD_OCTAL_DTR; + s_command.DQSMode = (dev_cfg->data_rate == OSPI_STR_TRANSFER) + ? HAL_OSPI_DQS_DISABLE + : HAL_OSPI_DQS_ENABLE; + + s_command.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD; + + ret = HAL_OSPI_Command(&dev_data->hospi, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); + if (ret != HAL_OK) { + LOG_ERR("%d: Failed to set memory map", ret); + return -EIO; + } + + /* Initialize the program command */ + s_command.OperationType = HAL_OSPI_OPTYPE_WRITE_CFG; + if (dev_cfg->data_rate == OSPI_STR_TRANSFER) { + s_command.Instruction = (dev_cfg->data_mode == OSPI_SPI_MODE) + ? ((stm32_ospi_hal_address_size(dev) == + HAL_OSPI_ADDRESS_24_BITS) + ? SPI_NOR_CMD_PP + : SPI_NOR_CMD_PP_4B) + : SPI_NOR_OCMD_PAGE_PRG; + } else { + s_command.Instruction = SPI_NOR_OCMD_PAGE_PRG; + } + s_command.DQSMode = HAL_OSPI_DQS_DISABLE; + + ret = HAL_OSPI_Command(&dev_data->hospi, &s_command, HAL_OSPI_TIMEOUT_DEFAULT_VALUE); + if (ret != HAL_OK) { + LOG_ERR("%d: Failed to set memory mapped", ret); + return -EIO; + } + + /* Enable the memory-mapping */ + s_MemMappedCfg.TimeOutActivation = HAL_OSPI_TIMEOUT_COUNTER_DISABLE; + + ret = HAL_OSPI_MemoryMapped(&dev_data->hospi, &s_MemMappedCfg); + if (ret != HAL_OK) { + LOG_ERR("%d: Failed to set memory mapped", ret); + return -EIO; + } + + LOG_INF("MemoryMap mode enabled"); + return 0; +} + +/* Function to return true if the octoflash is in MemoryMapped else false */ +static bool stm32_ospi_is_memorymap(const struct device *dev) +{ + struct flash_stm32_ospi_data *dev_data = dev->data; + + return ((READ_BIT(dev_data->hospi.Instance->CR, + OCTOSPI_CR_FMODE) == OCTOSPI_CR_FMODE) ? + true : false); +} + +static int stm32_ospi_abort(const struct device *dev) +{ + struct flash_stm32_ospi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_OSPI_Abort(&dev_data->hospi); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: OSPI abort failed", hal_ret); + return -EIO; + } + + return 0; +} +#endif /* CONFIG_STM32_MEMMAP */ + /* * Function to erase the flash : chip or sector with possible OSPI/SPI and STR/DTR * to erase the complete chip (using dedicated command) : * set size >= flash size * set addr = 0 + * NOTE: cannot erase in MemoryMapped mode */ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, size_t size) @@ -1009,6 +1152,20 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, return -ENOTSUP; } + ospi_lock_thread(dev); + +#ifdef CONFIG_STM32_MEMMAP + if (stm32_ospi_is_memorymap(dev)) { + /* Abort ongoing transfer to force CS high/BUSY deasserted */ + ret = stm32_ospi_abort(dev); + if (ret != 0) { + LOG_ERR("Failed to abort memory-mapped access before erase"); + goto end_erase; + } + } + /* Continue with Indirect Mode */ +#endif /* CONFIG_STM32_MEMMAP */ + OSPI_RegularCmdTypeDef cmd_erase = { .OperationType = HAL_OSPI_OPTYPE_COMMON_CFG, .FlashId = HAL_OSPI_FLASH_ID_1, @@ -1019,13 +1176,11 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, .SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD, }; - ospi_lock_thread(dev); - if (stm32_ospi_mem_ready(dev_data, dev_cfg->data_mode, dev_cfg->data_rate) != 0) { - ospi_unlock_thread(dev); LOG_ERR("Erase failed : flash busy"); - return -EBUSY; + ret = -EBUSY; + goto end_erase; } cmd_erase.InstructionMode = (dev_cfg->data_mode == OSPI_OPI_MODE) @@ -1131,9 +1286,10 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, ret = stm32_ospi_mem_ready(dev_data, dev_cfg->data_mode, dev_cfg->data_rate); } - } + goto end_erase; +end_erase: ospi_unlock_thread(dev); return ret; @@ -1143,9 +1299,7 @@ static int flash_stm32_ospi_erase(const struct device *dev, off_t addr, static int flash_stm32_ospi_read(const struct device *dev, off_t addr, void *data, size_t size) { - const struct flash_stm32_ospi_config *dev_cfg = dev->config; - struct flash_stm32_ospi_data *dev_data = dev->data; - int ret; + int ret = 0; if (!ospi_address_is_valid(dev, addr, size)) { LOG_ERR("Error: address or size exceeds expected values: " @@ -1158,6 +1312,25 @@ static int flash_stm32_ospi_read(const struct device *dev, off_t addr, return 0; } +#ifdef CONFIG_STM32_MEMMAP + /* If not MemMapped then configure it */ + if (!stm32_ospi_is_memorymap(dev)) { + if (stm32_ospi_set_memorymap(dev) != 0) { + LOG_ERR("READ failed: cannot enable MemoryMap"); + return -EIO; + } + } + /* Now in MemMapped mode : read with memcopy */ + LOG_DBG("MemoryMapped Read offset: 0x%lx, len: %zu", + (long)(STM32_OSPI_BASE_ADDRESS + addr), + size); + memcpy(data, (uint8_t *)STM32_OSPI_BASE_ADDRESS + addr, size); + +#else /* CONFIG_STM32_MEMMAP */ + const struct flash_stm32_ospi_config *dev_cfg = dev->config; + struct flash_stm32_ospi_data *dev_data = dev->data; + + OSPI_RegularCmdTypeDef cmd = ospi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); if (dev_cfg->data_mode != OSPI_OPI_MODE) { @@ -1223,10 +1396,14 @@ static int flash_stm32_ospi_read(const struct device *dev, off_t addr, ospi_unlock_thread(dev); +#endif /* CONFIG_STM32_MEMMAP */ return ret; } -/* Function to write the flash (page program) : with possible OSPI/SPI and STR/DTR */ +/* + * Function to write the flash (page program) : with possible OSPI/SPI and STR/DTR + * NOTE: writing in MemoryMapped mode is not guaranted + */ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, const void *data, size_t size) { @@ -1246,6 +1423,19 @@ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, return 0; } + ospi_lock_thread(dev); + +#ifdef CONFIG_STM32_MEMMAP + if (stm32_ospi_is_memorymap(dev)) { + /* Abort ongoing transfer to force CS high/BUSY deasserted */ + ret = stm32_ospi_abort(dev); + if (ret != 0) { + LOG_ERR("Failed to abort memory-mapped access before write"); + goto end_write; + } + } + /* Continue with Indirect Mode */ +#endif /* CONFIG_STM32_MEMMAP */ /* page program for STR or DTR mode */ OSPI_RegularCmdTypeDef cmd_pp = ospi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); @@ -1289,7 +1479,6 @@ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, cmd_pp.DummyCycles = 0U; LOG_DBG("OSPI: write %zu data", size); - ospi_lock_thread(dev); ret = stm32_ospi_mem_ready(dev_data, dev_cfg->data_mode, dev_cfg->data_rate); @@ -1338,7 +1527,9 @@ static int flash_stm32_ospi_write(const struct device *dev, off_t addr, break; } } + goto end_write; +end_write: ospi_unlock_thread(dev); return ret; @@ -1910,6 +2101,16 @@ static int flash_stm32_ospi_init(const struct device *dev) return -ENODEV; } +#ifdef CONFIG_STM32_MEMMAP + /* If MemoryMapped then configure skip init */ + if (stm32_ospi_is_memorymap(dev)) { + LOG_DBG("NOR init'd in MemMapped mode\n"); + /* Force HAL instance in correct state */ + dev_data->hospi.State = HAL_OSPI_STATE_BUSY_MEM_MAPPED; + return 0; + } +#endif /* CONFIG_STM32_MEMMAP */ + #if STM32_OSPI_USE_DMA /* * DMA configuration @@ -2094,17 +2295,17 @@ static int flash_stm32_ospi_init(const struct device *dev) OSPIM_CfgTypeDef ospi_mgr_cfg = {0}; if (dev_data->hospi.Instance == OCTOSPI1) { - ospi_mgr_cfg.ClkPort = 1; - ospi_mgr_cfg.DQSPort = 1; - ospi_mgr_cfg.NCSPort = 1; + ospi_mgr_cfg.ClkPort = DT_OSPI_PROP_OR(clk_port, 1); + ospi_mgr_cfg.DQSPort = DT_OSPI_PROP_OR(dqs_port, 1); + ospi_mgr_cfg.NCSPort = DT_OSPI_PROP_OR(ncs_port, 1); ospi_mgr_cfg.IOLowPort = DT_OSPI_IO_PORT_PROP_OR(io_low_port, HAL_OSPIM_IOPORT_1_LOW); ospi_mgr_cfg.IOHighPort = DT_OSPI_IO_PORT_PROP_OR(io_high_port, HAL_OSPIM_IOPORT_1_HIGH); } else if (dev_data->hospi.Instance == OCTOSPI2) { - ospi_mgr_cfg.ClkPort = 2; - ospi_mgr_cfg.DQSPort = 2; - ospi_mgr_cfg.NCSPort = 2; + ospi_mgr_cfg.ClkPort = DT_OSPI_PROP_OR(clk_port, 2); + ospi_mgr_cfg.DQSPort = DT_OSPI_PROP_OR(dqs_port, 2); + ospi_mgr_cfg.NCSPort = DT_OSPI_PROP_OR(ncs_port, 2); ospi_mgr_cfg.IOLowPort = DT_OSPI_IO_PORT_PROP_OR(io_low_port, HAL_OSPIM_IOPORT_2_LOW); ospi_mgr_cfg.IOHighPort = DT_OSPI_IO_PORT_PROP_OR(io_high_port, @@ -2289,9 +2490,21 @@ static int flash_stm32_ospi_init(const struct device *dev) } #endif /* CONFIG_FLASH_PAGE_LAYOUT */ - LOG_INF("NOR octo-flash at 0x%lx (0x%x bytes)", +#ifdef CONFIG_STM32_MEMMAP + /* Now configure the octo Flash in MemoryMapped (access by address) */ + ret = stm32_ospi_set_memorymap(dev); + if (ret != 0) { + LOG_ERR("Error (%d): setting NOR in MemoryMapped mode", ret); + return -EINVAL; + } + LOG_DBG("NOR octo-flash in MemoryMapped mode at 0x%lx (0x%x bytes)", + (long)(STM32_OSPI_BASE_ADDRESS), + dev_cfg->flash_size); +#else + LOG_DBG("NOR octo-flash at 0x%lx (0x%x bytes)", (long)(STM32_OSPI_BASE_ADDRESS), dev_cfg->flash_size); +#endif /* CONFIG_STM32_MEMMAP */ return 0; } diff --git a/drivers/flash/flash_stm32_qspi.c b/drivers/flash/flash_stm32_qspi.c index 326c1129a3638..0ff33baf55dac 100644 --- a/drivers/flash/flash_stm32_qspi.c +++ b/drivers/flash/flash_stm32_qspi.c @@ -12,8 +12,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -33,7 +35,7 @@ #define STM32_QSPI_BASE_ADDRESS DT_INST_REG_ADDR(0) #define STM32_QSPI_RESET_GPIO DT_INST_NODE_HAS_PROP(0, reset_gpios) -#define STM32_QSPI_RESET_CMD DT_INST_NODE_HAS_PROP(0, reset_cmd) +#define STM32_QSPI_RESET_CMD DT_PROP(DT_NODELABEL(quadspi), set_cmd) #include @@ -123,6 +125,11 @@ struct flash_stm32_qspi_data { bool flag_access_32bit: 1; }; +static const QSPI_CommandTypeDef cmd_write_en = { + .Instruction = SPI_NOR_CMD_WREN, + .InstructionMode = QSPI_INSTRUCTION_1_LINE +}; + static inline void qspi_lock_thread(const struct device *dev) { struct flash_stm32_qspi_data *dev_data = dev->data; @@ -189,7 +196,7 @@ static inline int qspi_prepare_quad_program(const struct device *dev, /* * Send a command over QSPI bus. */ -static int qspi_send_cmd(const struct device *dev, QSPI_CommandTypeDef *cmd) +static int qspi_send_cmd(const struct device *dev, const QSPI_CommandTypeDef *cmd) { const struct flash_stm32_qspi_config *dev_cfg = dev->config; struct flash_stm32_qspi_data *dev_data = dev->data; @@ -201,7 +208,7 @@ static int qspi_send_cmd(const struct device *dev, QSPI_CommandTypeDef *cmd) dev_data->cmd_status = 0; - hal_ret = HAL_QSPI_Command_IT(&dev_data->hqspi, cmd); + hal_ret = HAL_QSPI_Command_IT(&dev_data->hqspi, (QSPI_CommandTypeDef *)cmd); if (hal_ret != HAL_OK) { LOG_ERR("%d: Failed to send QSPI instruction", hal_ret); return -EIO; @@ -385,6 +392,66 @@ static bool qspi_address_is_valid(const struct device *dev, off_t addr, return (addr >= 0) && ((uint64_t)addr + (uint64_t)size <= flash_size); } +#ifdef CONFIG_STM32_MEMMAP +/* Must be called inside qspi_lock_thread(). */ +static int stm32_qspi_set_memory_mapped(const struct device *dev) +{ + int ret; + HAL_StatusTypeDef hal_ret; + struct flash_stm32_qspi_data *dev_data = dev->data; + + QSPI_CommandTypeDef cmd = { + .Instruction = SPI_NOR_CMD_READ, + .Address = 0, + .InstructionMode = QSPI_INSTRUCTION_1_LINE, + .AddressMode = QSPI_ADDRESS_1_LINE, + .DataMode = QSPI_DATA_1_LINE, + }; + + qspi_set_address_size(dev, &cmd); + if (IS_ENABLED(STM32_QSPI_USE_QUAD_IO)) { + ret = qspi_prepare_quad_read(dev, &cmd); + if (ret < 0) { + return ret; + } + } + + QSPI_MemoryMappedTypeDef mem_mapped = { + .TimeOutActivation = QSPI_TIMEOUT_COUNTER_DISABLE, + }; + + hal_ret = HAL_QSPI_MemoryMapped(&dev_data->hqspi, &cmd, &mem_mapped); + if (hal_ret != 0) { + LOG_ERR("%d: Failed to enable memory mapped", hal_ret); + return -EIO; + } + + LOG_DBG("MemoryMap mode enabled"); + return 0; +} + +static bool stm32_qspi_is_memory_mapped(const struct device *dev) +{ + struct flash_stm32_qspi_data *dev_data = dev->data; + + return READ_BIT(dev_data->hqspi.Instance->CCR, QUADSPI_CCR_FMODE) == QUADSPI_CCR_FMODE; +} + +static int stm32_qspi_abort(const struct device *dev) +{ + struct flash_stm32_qspi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_QSPI_Abort(&dev_data->hqspi); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: QSPI abort failed", hal_ret); + return -EIO; + } + + return 0; +} +#endif + static int flash_stm32_qspi_read(const struct device *dev, off_t addr, void *data, size_t size) { @@ -401,6 +468,27 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr, return 0; } +#ifdef CONFIG_STM32_MEMMAP + qspi_lock_thread(dev); + + /* Do reads through memory-mapping instead of indirect */ + if (!stm32_qspi_is_memory_mapped(dev)) { + ret = stm32_qspi_set_memory_mapped(dev); + if (ret != 0) { + LOG_ERR("READ: failed to set memory mapped"); + goto end; + } + } + + __ASSERT_NO_MSG(stm32_qspi_is_memory_mapped(dev)); + + uintptr_t mmap_addr = STM32_QSPI_BASE_ADDRESS + addr; + + LOG_DBG("Memory-mapped read from 0x%08lx, len %zu", mmap_addr, size); + memcpy(data, (void *)mmap_addr, size); + ret = 0; + goto end; +#else QSPI_CommandTypeDef cmd = { .Instruction = SPI_NOR_CMD_READ, .Address = addr, @@ -420,7 +508,10 @@ static int flash_stm32_qspi_read(const struct device *dev, off_t addr, qspi_lock_thread(dev); ret = qspi_read_access(dev, &cmd, data, size); + goto end; +#endif +end: qspi_unlock_thread(dev); return ret; @@ -460,11 +551,6 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr, return 0; } - QSPI_CommandTypeDef cmd_write_en = { - .Instruction = SPI_NOR_CMD_WREN, - .InstructionMode = QSPI_INSTRUCTION_1_LINE, - }; - QSPI_CommandTypeDef cmd_pp = { .Instruction = SPI_NOR_CMD_PP, .InstructionMode = QSPI_INSTRUCTION_1_LINE, @@ -482,6 +568,17 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr, qspi_lock_thread(dev); +#ifdef CONFIG_STM32_MEMMAP + if (stm32_qspi_is_memory_mapped(dev)) { + /* Abort ongoing transfer to force CS high/BUSY deasserted */ + ret = stm32_qspi_abort(dev); + if (ret != 0) { + LOG_ERR("Failed to abort memory-mapped access before write"); + goto end; + } + } +#endif + while (size > 0) { size_t to_write = size; @@ -517,7 +614,9 @@ static int flash_stm32_qspi_write(const struct device *dev, off_t addr, break; } } + goto end; +end: qspi_unlock_thread(dev); return ret; @@ -541,11 +640,6 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr, return 0; } - QSPI_CommandTypeDef cmd_write_en = { - .Instruction = SPI_NOR_CMD_WREN, - .InstructionMode = QSPI_INSTRUCTION_1_LINE, - }; - QSPI_CommandTypeDef cmd_erase = { .Instruction = 0, .InstructionMode = QSPI_INSTRUCTION_1_LINE, @@ -555,6 +649,17 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr, qspi_set_address_size(dev, &cmd_erase); qspi_lock_thread(dev); +#ifdef CONFIG_STM32_MEMMAP + if (stm32_qspi_is_memory_mapped(dev)) { + /* Abort ongoing transfer to force CS high/BUSY deasserted */ + ret = stm32_qspi_abort(dev); + if (ret != 0) { + LOG_ERR("Failed to abort memory-mapped access before erase"); + goto end; + } + } +#endif + while ((size > 0) && (ret == 0)) { cmd_erase.Address = addr; qspi_send_cmd(dev, &cmd_write_en); @@ -596,7 +701,9 @@ static int flash_stm32_qspi_erase(const struct device *dev, off_t addr, } qspi_wait_until_ready(dev); } + goto end; +end: qspi_unlock_thread(dev); return ret; @@ -807,10 +914,6 @@ static int qspi_program_addr_4b(const struct device *dev, bool write_enable) /* Send write enable command, if required */ if (write_enable) { - QSPI_CommandTypeDef cmd_write_en = { - .Instruction = SPI_NOR_CMD_WREN, - .InstructionMode = QSPI_INSTRUCTION_1_LINE, - }; ret = qspi_send_cmd(dev, &cmd_write_en); if (ret != 0) { return ret; @@ -918,11 +1021,6 @@ static int qspi_write_enable(const struct device *dev) uint8_t reg; int ret; - QSPI_CommandTypeDef cmd_write_en = { - .Instruction = SPI_NOR_CMD_WREN, - .InstructionMode = QSPI_INSTRUCTION_1_LINE, - }; - ret = qspi_send_cmd(dev, &cmd_write_en); if (ret) { return ret; @@ -1280,10 +1378,28 @@ static int flash_stm32_qspi_init(const struct device *dev) dev_data->hqspi.Init.ClockPrescaler = prescaler; /* Give a bit position from 0 to 31 to the HAL init minus 1 for the DCR1 reg */ dev_data->hqspi.Init.FlashSize = find_lsb_set(dev_cfg->flash_size) - 2; +#if DT_PROP(DT_NODELABEL(quadspi), dual_flash) && defined(QUADSPI_CR_DFM) + /* + * When the DTS has , it means Dual Flash Mode + * Even in DUAL flash config, the SDFP is read from one single quad-NOR + * else the magic nb is wrong (0x46465353) + * That means that the Dual Flash config is set after the SFDP sequence + */ + dev_data->hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE; + dev_data->hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_3_CYCLE; + dev_data->hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE; + /* Set Dual Flash Mode only on MemoryMapped */ + dev_data->hqspi.Init.FlashID = QSPI_FLASH_ID_1; +#endif /* dual_flash */ HAL_QSPI_Init(&dev_data->hqspi); -#if DT_NODE_HAS_PROP(DT_NODELABEL(quadspi), flash_id) +#if DT_NODE_HAS_PROP(DT_NODELABEL(quadspi), flash_id) && \ + defined(QUADSPI_CR_FSEL) + /* + * Some stm32 mcu with quadspi (like stm32l47x or stm32l48x) + * does not support Dual-Flash Mode + */ uint8_t qspi_flash_id = DT_PROP(DT_NODELABEL(quadspi), flash_id); HAL_QSPI_SetFlashID(&dev_data->hqspi, @@ -1367,9 +1483,30 @@ static int flash_stm32_qspi_init(const struct device *dev) } #endif /* CONFIG_FLASH_PAGE_LAYOUT */ +#ifdef CONFIG_STM32_MEMMAP +#if DT_PROP(DT_NODELABEL(quadspi), dual_flash) && defined(QUADSPI_CR_DFM) + /* + * When the DTS has dual_flash, it means Dual Flash Mode for Memory MAPPED + * Force Dual Flash mode now, after the SFDP sequence which is reading + * one quad-NOR only + */ + MODIFY_REG(dev_data->hqspi.Instance->CR, (QUADSPI_CR_DFM), QSPI_DUALFLASH_ENABLE); + LOG_DBG("Dual Flash Mode"); +#endif /* dual_flash */ + + ret = stm32_qspi_set_memory_mapped(dev); + if (ret != 0) { + LOG_ERR("Failed to enable memory-mapped mode: %d", ret); + return ret; + } + LOG_INF("Memory-mapped NOR quad-flash at 0x%lx (0x%x bytes)", + (long)(STM32_QSPI_BASE_ADDRESS), + dev_cfg->flash_size); +#else LOG_INF("NOR quad-flash at 0x%lx (0x%x bytes)", (long)(STM32_QSPI_BASE_ADDRESS), dev_cfg->flash_size); +#endif return 0; } diff --git a/drivers/flash/flash_stm32_xspi.c b/drivers/flash/flash_stm32_xspi.c new file mode 100644 index 0000000000000..c99bf7b279395 --- /dev/null +++ b/drivers/flash/flash_stm32_xspi.c @@ -0,0 +1,2254 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * ************************************************************************** + * xSPI flash controller driver for stm32 serie with xSPI periherals + * This driver is based on the stm32Cube HAL XSPI driver + * with one xspi DTS NODE + * ************************************************************************** + */ +#define DT_DRV_COMPAT st_stm32_xspi_nor + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spi_nor.h" +#include "jesd216.h" + +#include +LOG_MODULE_REGISTER(flash_stm32_xspi, CONFIG_FLASH_LOG_LEVEL); + +#define STM32_XSPI_NODE DT_INST_PARENT(0) + +#define DT_XSPI_IO_PORT_PROP_OR(prop, default_value) \ + COND_CODE_1(DT_NODE_HAS_PROP(STM32_XSPI_NODE, prop), \ + (_CONCAT(HAL_XSPIM_, DT_STRING_TOKEN(STM32_XSPI_NODE, prop))), \ + ((default_value))) + +/* Get the base address of the flash from the DTS node */ +#define STM32_XSPI_BASE_ADDRESS DT_INST_REG_ADDR(0) + +#define STM32_XSPI_RESET_GPIO DT_INST_NODE_HAS_PROP(0, reset_gpios) + +#define STM32_XSPI_DLYB_BYPASSED DT_PROP(STM32_XSPI_NODE, dlyb_bypass) + +#define STM32_XSPI_USE_DMA DT_NODE_HAS_PROP(STM32_XSPI_NODE, dmas) + +#if STM32_XSPI_USE_DMA +#include +#include +#include +#endif /* STM32_XSPI_USE_DMA */ + +#include "flash_stm32_xspi.h" + +static inline void xspi_lock_thread(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + k_sem_take(&dev_data->sem, K_FOREVER); +} + +static inline void xspi_unlock_thread(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + k_sem_give(&dev_data->sem); +} + +static int xspi_send_cmd(const struct device *dev, XSPI_RegularCmdTypeDef *cmd) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + LOG_DBG("Instruction 0x%x", cmd->Instruction); + + dev_data->cmd_status = 0; + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + LOG_DBG("CCR 0x%x", dev_data->hxspi.Instance->CCR); + + return dev_data->cmd_status; +} + +static int xspi_read_access(const struct device *dev, XSPI_RegularCmdTypeDef *cmd, + uint8_t *data, const size_t size) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + LOG_DBG("Instruction 0x%x", cmd->Instruction); + + cmd->DataLength = size; + + dev_data->cmd_status = 0; + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + +#if STM32_XSPI_USE_DMA + hal_ret = HAL_XSPI_Receive_DMA(&dev_data->hxspi, data); +#else + hal_ret = HAL_XSPI_Receive_IT(&dev_data->hxspi, data); +#endif + + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to read data", hal_ret); + return -EIO; + } + + k_sem_take(&dev_data->sync, K_FOREVER); + + return dev_data->cmd_status; +} + +static int xspi_write_access(const struct device *dev, XSPI_RegularCmdTypeDef *cmd, + const uint8_t *data, const size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + HAL_StatusTypeDef hal_ret; + + LOG_DBG("Instruction 0x%x", cmd->Instruction); + + cmd->DataLength = size; + + dev_data->cmd_status = 0; + + /* in OPI/STR the 3-byte AddressWidth is not supported by the NOR flash */ + if ((dev_cfg->data_mode == XSPI_OCTO_MODE) && + (cmd->AddressWidth != HAL_XSPI_ADDRESS_32_BITS)) { + LOG_ERR("XSPI wr in OPI/STR mode is for 32bit address only"); + return -EIO; + } + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + +#if STM32_XSPI_USE_DMA + hal_ret = HAL_XSPI_Transmit_DMA(&dev_data->hxspi, (uint8_t *)data); +#else + hal_ret = HAL_XSPI_Transmit_IT(&dev_data->hxspi, (uint8_t *)data); +#endif + + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to write data", hal_ret); + return -EIO; + } + + k_sem_take(&dev_data->sync, K_FOREVER); + + return dev_data->cmd_status; +} + +/* + * Gives a XSPI_RegularCmdTypeDef with all parameters set + * except Instruction, Address, DummyCycles, NbData + */ +static XSPI_RegularCmdTypeDef xspi_prepare_cmd(const uint8_t transfer_mode, + const uint8_t transfer_rate) +{ + XSPI_RegularCmdTypeDef cmd_tmp = { + .OperationType = HAL_XSPI_OPTYPE_COMMON_CFG, + .InstructionWidth = ((transfer_mode == XSPI_OCTO_MODE) + ? HAL_XSPI_INSTRUCTION_16_BITS + : HAL_XSPI_INSTRUCTION_8_BITS), + .InstructionDTRMode = ((transfer_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_INSTRUCTION_DTR_ENABLE + : HAL_XSPI_INSTRUCTION_DTR_DISABLE), + .AddressDTRMode = ((transfer_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_ADDRESS_DTR_ENABLE + : HAL_XSPI_ADDRESS_DTR_DISABLE), + /* AddressWidth must be set to 32bits for init and mem config phase */ + .AddressWidth = HAL_XSPI_ADDRESS_32_BITS, + .AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE, + .DataDTRMode = ((transfer_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_DATA_DTR_ENABLE + : HAL_XSPI_DATA_DTR_DISABLE), + .DQSMode = (transfer_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_DQS_ENABLE + : HAL_XSPI_DQS_DISABLE, + .SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD, + }; + + switch (transfer_mode) { + case XSPI_OCTO_MODE: { + cmd_tmp.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES; + cmd_tmp.AddressMode = HAL_XSPI_ADDRESS_8_LINES; + cmd_tmp.DataMode = HAL_XSPI_DATA_8_LINES; + break; + } + case XSPI_QUAD_MODE: { + cmd_tmp.InstructionMode = HAL_XSPI_INSTRUCTION_4_LINES; + cmd_tmp.AddressMode = HAL_XSPI_ADDRESS_4_LINES; + cmd_tmp.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + case XSPI_DUAL_MODE: { + cmd_tmp.InstructionMode = HAL_XSPI_INSTRUCTION_2_LINES; + cmd_tmp.AddressMode = HAL_XSPI_ADDRESS_2_LINES; + cmd_tmp.DataMode = HAL_XSPI_DATA_2_LINES; + break; + } + default: { + cmd_tmp.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd_tmp.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd_tmp.DataMode = HAL_XSPI_DATA_1_LINE; + break; + } + } + + return cmd_tmp; +} + +static uint32_t stm32_xspi_hal_address_size(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + if (dev_data->address_width == 4U) { + return HAL_XSPI_ADDRESS_32_BITS; + } + + return HAL_XSPI_ADDRESS_24_BITS; +} + +#if defined(CONFIG_FLASH_JESD216_API) +/* + * Read the JEDEC ID data from the external Flash at init + * and store in the jedec_id Table of the flash_stm32_xspi_data + * The JEDEC ID is not given by a DTS property + */ +static int stm32_xspi_read_jedec_id(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + /* This is a SPI/STR command to issue to the external Flash device */ + XSPI_RegularCmdTypeDef cmd = xspi_prepare_cmd(XSPI_SPI_MODE, XSPI_STR_TRANSFER); + + cmd.Instruction = JESD216_CMD_READ_ID; + cmd.AddressWidth = stm32_xspi_hal_address_size(dev); + cmd.AddressMode = HAL_XSPI_ADDRESS_NONE; + cmd.DataLength = JESD216_READ_ID_LEN; /* 3 bytes in the READ ID */ + + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, &cmd, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + + /* Place the received data directly into the jedec Table */ + hal_ret = HAL_XSPI_Receive(&dev_data->hxspi, dev_data->jedec_id, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to read data", hal_ret); + return -EIO; + } + + LOG_DBG("Jedec ID = [%02x %02x %02x]", + dev_data->jedec_id[0], dev_data->jedec_id[1], dev_data->jedec_id[2]); + + dev_data->cmd_status = 0; + + return 0; +} + +/* + * Read Serial Flash ID : + * just gives the values received by the external Flash + */ +static int xspi_read_jedec_id(const struct device *dev, uint8_t *id) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + /* Take jedec Id values from the table (issued from the octoFlash) */ + memcpy(id, dev_data->jedec_id, JESD216_READ_ID_LEN); + + LOG_INF("Manuf ID = %02x Memory Type = %02x Memory Density = %02x", + id[0], id[1], id[2]); + + return 0; +} +#endif /* CONFIG_FLASH_JESD216_API */ + +/* + * Read Serial Flash Discovery Parameter from the external Flash at init : + * perform a read access over SPI bus for SDFP (DataMode is already set) + * The SFDP table is not given by a DTS property + */ +static int stm32_xspi_read_sfdp(const struct device *dev, off_t addr, + void *data, + size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + + XSPI_RegularCmdTypeDef cmd = xspi_prepare_cmd(dev_cfg->data_mode, + dev_cfg->data_rate); + if (dev_cfg->data_mode == XSPI_OCTO_MODE) { + cmd.Instruction = JESD216_OCMD_READ_SFDP; + cmd.DummyCycles = 20U; + cmd.AddressWidth = HAL_XSPI_ADDRESS_32_BITS; + } else { + cmd.Instruction = JESD216_CMD_READ_SFDP; + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.DataMode = HAL_XSPI_DATA_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd.DummyCycles = 8U; + cmd.AddressWidth = HAL_XSPI_ADDRESS_24_BITS; + } + cmd.Address = addr; + cmd.DataLength = size; + + HAL_StatusTypeDef hal_ret; + + hal_ret = HAL_XSPI_Command(&dev_data->hxspi, &cmd, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to send XSPI instruction", hal_ret); + return -EIO; + } + + hal_ret = HAL_XSPI_Receive(&dev_data->hxspi, (uint8_t *)data, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE); + if (hal_ret != HAL_OK) { + LOG_ERR("%d: Failed to read data", hal_ret); + return -EIO; + } + + dev_data->cmd_status = 0; + + return 0; +} + +/* + * Read Serial Flash Discovery Parameter : + * perform a read access over SPI bus for SDFP (DataMode is already set) + */ +static int xspi_read_sfdp(const struct device *dev, off_t addr, void *data, + size_t size) +{ + LOG_INF("Read SFDP from externalFlash"); + /* Get the SFDP from the external Flash (no sfdp-bfp table in the DeviceTree) */ + if (stm32_xspi_read_sfdp(dev, addr, data, size) == 0) { + /* If valid, then ignore any table from the DTS */ + return 0; + } + LOG_INF("Error reading SFDP from external Flash and none in the DTS"); + return -EINVAL; +} + +static bool xspi_address_is_valid(const struct device *dev, off_t addr, + size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + size_t flash_size = dev_cfg->flash_size; + + return (addr >= 0) && ((uint64_t)addr + (uint64_t)size <= flash_size); +} + +static int stm32_xspi_wait_auto_polling(const struct device *dev, + XSPI_AutoPollingTypeDef *s_config, uint32_t timeout_ms) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + dev_data->cmd_status = 0; + + if (HAL_XSPI_AutoPolling_IT(&dev_data->hxspi, s_config) != HAL_OK) { + LOG_ERR("XSPI AutoPoll failed"); + return -EIO; + } + + if (k_sem_take(&dev_data->sync, K_MSEC(timeout_ms)) != 0) { + LOG_ERR("XSPI AutoPoll wait failed"); + HAL_XSPI_Abort(&dev_data->hxspi); + k_sem_reset(&dev_data->sync); + return -EIO; + } + + /* HAL_XSPI_AutoPolling_IT enables transfer error interrupt which sets + * cmd_status. + */ + return dev_data->cmd_status; +} + +/* + * This function Polls the WEL (write enable latch) bit to become to 0 + * When the Chip Erase Cycle is completed, the Write Enable Latch (WEL) bit is cleared. + * in nor_mode SPI/OPI XSPI_SPI_MODE or XSPI_OCTO_MODE + * and nor_rate transfer STR/DTR XSPI_STR_TRANSFER or XSPI_DTR_TRANSFER + */ +static int stm32_xspi_mem_erased(const struct device *dev) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + uint8_t nor_mode = dev_cfg->data_mode; + uint8_t nor_rate = dev_cfg->data_rate; + + XSPI_AutoPollingTypeDef s_config = {0}; + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Configure automatic polling mode command to wait for memory ready */ + if (nor_mode == XSPI_OCTO_MODE) { + s_command.Instruction = SPI_NOR_OCMD_RDSR; + s_command.DummyCycles = (nor_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_DUMMY_REG_OCTAL_DTR + : SPI_NOR_DUMMY_REG_OCTAL; + } else { + s_command.Instruction = SPI_NOR_CMD_RDSR; + /* force 1-line InstructionMode for any non-OSPI transfer */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + s_command.AddressMode = HAL_XSPI_ADDRESS_NONE; + /* force 1-line DataMode for any non-OSPI transfer */ + s_command.DataMode = HAL_XSPI_DATA_1_LINE; + s_command.DummyCycles = 0; + } + s_command.DataLength = ((nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U); + s_command.Address = 0U; + + /* Set the mask to 0x02 to mask all Status REG bits except WEL */ + /* Set the match to 0x00 to check if the WEL bit is Reset */ + s_config.MatchValue = SPI_NOR_WEL_MATCH; + s_config.MatchMask = SPI_NOR_WEL_MASK; /* Write Enable Latch */ + + s_config.MatchMode = HAL_XSPI_MATCH_MODE_AND; + s_config.IntervalTime = SPI_NOR_AUTO_POLLING_INTERVAL; + s_config.AutomaticStop = HAL_XSPI_AUTOMATIC_STOP_ENABLE; + + if (HAL_XSPI_Command(&dev_data->hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI AutoPoll command (WEL) failed"); + return -EIO; + } + + /* Start Automatic-Polling mode to wait until the memory is totally erased */ + return stm32_xspi_wait_auto_polling(dev, + &s_config, STM32_XSPI_BULK_ERASE_MAX_TIME); +} + +/* + * This function Polls the WIP(Write In Progress) bit to become to 0 + * in nor_mode SPI/OPI XSPI_SPI_MODE or XSPI_OCTO_MODE + * and nor_rate transfer STR/DTR XSPI_STR_TRANSFER or XSPI_DTR_TRANSFER + */ +static int stm32_xspi_mem_ready(const struct device *dev, uint8_t nor_mode, + uint8_t nor_rate) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + XSPI_AutoPollingTypeDef s_config = {0}; + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Configure automatic polling mode command to wait for memory ready */ + if (nor_mode == XSPI_OCTO_MODE) { + s_command.Instruction = SPI_NOR_OCMD_RDSR; + s_command.DummyCycles = (nor_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_DUMMY_REG_OCTAL_DTR + : SPI_NOR_DUMMY_REG_OCTAL; + } else { + s_command.Instruction = SPI_NOR_CMD_RDSR; + /* force 1-line InstructionMode for any non-OSPI transfer */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + s_command.AddressMode = HAL_XSPI_ADDRESS_NONE; + /* force 1-line DataMode for any non-OSPI transfer */ + s_command.DataMode = HAL_XSPI_DATA_1_LINE; + s_command.DummyCycles = 0; + } + s_command.DataLength = ((nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U); + s_command.Address = 0U; + + /* Set the mask to 0x01 to mask all Status REG bits except WIP */ + /* Set the match to 0x00 to check if the WIP bit is Reset */ + s_config.MatchValue = SPI_NOR_MEM_RDY_MATCH; + s_config.MatchMask = SPI_NOR_MEM_RDY_MASK; /* Write in progress */ + s_config.MatchMode = HAL_XSPI_MATCH_MODE_AND; + s_config.IntervalTime = SPI_NOR_AUTO_POLLING_INTERVAL; + s_config.AutomaticStop = HAL_XSPI_AUTOMATIC_STOP_ENABLE; + + if (HAL_XSPI_Command(&dev_data->hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI AutoPoll command failed"); + return -EIO; + } + + /* Start Automatic-Polling mode to wait until the memory is ready WIP=0 */ + return stm32_xspi_wait_auto_polling(dev, &s_config, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); +} + +/* Enables writing to the memory sending a Write Enable and wait it is effective */ +static int stm32_xspi_write_enable(const struct device *dev, + uint8_t nor_mode, uint8_t nor_rate) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + XSPI_AutoPollingTypeDef s_config = {0}; + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Initialize the write enable command */ + if (nor_mode == XSPI_OCTO_MODE) { + s_command.Instruction = SPI_NOR_OCMD_WREN; + } else { + s_command.Instruction = SPI_NOR_CMD_WREN; + /* force 1-line InstructionMode for any non-OSPI transfer */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + } + s_command.AddressMode = HAL_XSPI_ADDRESS_NONE; + s_command.DataMode = HAL_XSPI_DATA_NONE; + s_command.DummyCycles = 0U; + + if (HAL_XSPI_Command(&dev_data->hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI flash write enable cmd failed"); + return -EIO; + } + + /* New command to Configure automatic polling mode to wait for write enabling */ + if (nor_mode == XSPI_OCTO_MODE) { + s_command.Instruction = SPI_NOR_OCMD_RDSR; + s_command.AddressMode = HAL_XSPI_ADDRESS_8_LINES; + s_command.DataMode = HAL_XSPI_DATA_8_LINES; + s_command.DummyCycles = (nor_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_DUMMY_REG_OCTAL_DTR + : SPI_NOR_DUMMY_REG_OCTAL; + } else { + s_command.Instruction = SPI_NOR_CMD_RDSR; + /* force 1-line DataMode for any non-OSPI transfer */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + s_command.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + s_command.DataMode = HAL_XSPI_DATA_1_LINE; + s_command.DummyCycles = 0; + + /* DummyCycles remains 0 */ + } + s_command.DataLength = (nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U; + s_command.Address = 0U; + + if (HAL_XSPI_Command(&dev_data->hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI config auto polling cmd failed"); + return -EIO; + } + + s_config.MatchValue = SPI_NOR_WREN_MATCH; + s_config.MatchMask = SPI_NOR_WREN_MASK; + s_config.MatchMode = HAL_XSPI_MATCH_MODE_AND; + s_config.IntervalTime = SPI_NOR_AUTO_POLLING_INTERVAL; + s_config.AutomaticStop = HAL_XSPI_AUTOMATIC_STOP_ENABLE; + + return stm32_xspi_wait_auto_polling(dev, &s_config, HAL_XSPI_TIMEOUT_DEFAULT_VALUE); +} + +/* Write Flash configuration register 2 with new dummy cycles */ +static int stm32_xspi_write_cfg2reg_dummy(XSPI_HandleTypeDef *hxspi, + uint8_t nor_mode, uint8_t nor_rate) +{ + uint8_t transmit_data = SPI_NOR_CR2_DUMMY_CYCLES_66MHZ; + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Initialize the writing of configuration register 2 */ + s_command.Instruction = (nor_mode == XSPI_SPI_MODE) + ? SPI_NOR_CMD_WR_CFGREG2 + : SPI_NOR_OCMD_WR_CFGREG2; + s_command.Address = SPI_NOR_REG2_ADDR3; + s_command.DummyCycles = 0U; + s_command.DataLength = (nor_mode == XSPI_SPI_MODE) ? 1U + : ((nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U); + + if (HAL_XSPI_Command(hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI transmit cmd"); + return -EIO; + } + + if (HAL_XSPI_Transmit(hxspi, &transmit_data, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI transmit "); + return -EIO; + } + + return 0; +} + +/* Write Flash configuration register 2 with new single or octal SPI protocol */ +static int stm32_xspi_write_cfg2reg_io(XSPI_HandleTypeDef *hxspi, + uint8_t nor_mode, uint8_t nor_rate, uint8_t op_enable) +{ + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Initialize the writing of configuration register 2 */ + s_command.Instruction = (nor_mode == XSPI_SPI_MODE) + ? SPI_NOR_CMD_WR_CFGREG2 + : SPI_NOR_OCMD_WR_CFGREG2; + s_command.Address = SPI_NOR_REG2_ADDR1; + s_command.DummyCycles = 0U; + s_command.DataLength = (nor_mode == XSPI_SPI_MODE) ? 1U + : ((nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U); + + if (HAL_XSPI_Command(hxspi, &s_command, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("Write Flash configuration reg2 failed"); + return -EIO; + } + + if (HAL_XSPI_Transmit(hxspi, &op_enable, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("Write Flash configuration reg2 failed"); + return -EIO; + } + + return 0; +} + +/* Read Flash configuration register 2 with new single or octal SPI protocol */ +static int stm32_xspi_read_cfg2reg(XSPI_HandleTypeDef *hxspi, + uint8_t nor_mode, uint8_t nor_rate, uint8_t *value) +{ + XSPI_RegularCmdTypeDef s_command = xspi_prepare_cmd(nor_mode, nor_rate); + + /* Initialize the writing of configuration register 2 */ + s_command.Instruction = (nor_mode == XSPI_SPI_MODE) + ? SPI_NOR_CMD_RD_CFGREG2 + : SPI_NOR_OCMD_RD_CFGREG2; + s_command.Address = SPI_NOR_REG2_ADDR1; + s_command.DummyCycles = (nor_mode == XSPI_SPI_MODE) + ? 0U + : ((nor_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_DUMMY_REG_OCTAL_DTR + : SPI_NOR_DUMMY_REG_OCTAL); + s_command.DataLength = (nor_rate == XSPI_DTR_TRANSFER) ? 2U : 1U; + + if (HAL_XSPI_Command(hxspi, &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("Write Flash configuration reg2 failed"); + return -EIO; + } + + if (HAL_XSPI_Receive(hxspi, value, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("Write Flash configuration reg2 failed"); + return -EIO; + } + + return 0; +} + +/* Set the NOR Flash to desired Interface mode : SPI/OSPI and STR/DTR according to the DTS */ +static int stm32_xspi_config_mem(const struct device *dev) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + uint8_t reg[2]; + + /* Going to set the SPI mode and STR transfer rate : done */ + if ((dev_cfg->data_mode != XSPI_OCTO_MODE) + && (dev_cfg->data_rate == XSPI_STR_TRANSFER)) { + LOG_INF("OSPI flash config is SPI|DUAL|QUAD / STR"); + return 0; + } + + /* Going to set the XPI mode (STR or DTR transfer rate) */ + LOG_DBG("XSPI configuring Octo SPI mode"); + + if (stm32_xspi_write_enable(dev, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("OSPI write Enable failed"); + return -EIO; + } + + /* Write Configuration register 2 (with new dummy cycles) */ + if (stm32_xspi_write_cfg2reg_dummy(&dev_data->hxspi, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("XSPI write CFGR2 failed"); + return -EIO; + } + if (stm32_xspi_mem_ready(dev, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("XSPI autopolling failed"); + return -EIO; + } + if (stm32_xspi_write_enable(dev, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("XSPI write Enable 2 failed"); + return -EIO; + } + + /* Write Configuration register 2 (with Octal I/O SPI protocol : choose STR or DTR) */ + uint8_t mode_enable = ((dev_cfg->data_rate == XSPI_DTR_TRANSFER) + ? SPI_NOR_CR2_DTR_OPI_EN + : SPI_NOR_CR2_STR_OPI_EN); + if (stm32_xspi_write_cfg2reg_io(&dev_data->hxspi, + XSPI_SPI_MODE, XSPI_STR_TRANSFER, mode_enable) != 0) { + LOG_ERR("XSPI write CFGR2 failed"); + return -EIO; + } + + /* Wait that the configuration is effective and check that memory is ready */ + k_busy_wait(STM32_XSPI_WRITE_REG_MAX_TIME * USEC_PER_MSEC); + + /* Reconfigure the memory type of the peripheral */ + dev_data->hxspi.Init.MemoryType = HAL_XSPI_MEMTYPE_MACRONIX; + dev_data->hxspi.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_ENABLE; + if (HAL_XSPI_Init(&dev_data->hxspi) != HAL_OK) { + LOG_ERR("XSPI mem type MACRONIX failed"); + return -EIO; + } + + if (dev_cfg->data_rate == XSPI_STR_TRANSFER) { + if (stm32_xspi_mem_ready(dev, + XSPI_OCTO_MODE, XSPI_STR_TRANSFER) != 0) { + /* Check Flash busy ? */ + LOG_ERR("XSPI flash busy failed"); + return -EIO; + } + + if (stm32_xspi_read_cfg2reg(&dev_data->hxspi, + XSPI_OCTO_MODE, XSPI_STR_TRANSFER, reg) != 0) { + /* Check the configuration has been correctly done on SPI_NOR_REG2_ADDR1 */ + LOG_ERR("XSPI flash config read failed"); + return -EIO; + } + + LOG_INF("XSPI flash config is OCTO / STR"); + } + + if (dev_cfg->data_rate == XSPI_DTR_TRANSFER) { + if (stm32_xspi_mem_ready(dev, + XSPI_OCTO_MODE, XSPI_DTR_TRANSFER) != 0) { + /* Check Flash busy ? */ + LOG_ERR("XSPI flash busy failed"); + return -EIO; + } + + LOG_INF("XSPI flash config is OCTO / DTR"); + } + + return 0; +} + +/* gpio or send the different reset command to the NOR flash in SPI/OSPI and STR/DTR */ +static int stm32_xspi_mem_reset(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + +#if STM32_XSPI_RESET_GPIO + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + + /* Generate RESETn pulse for the flash memory */ + gpio_pin_configure_dt(&dev_cfg->reset, GPIO_OUTPUT_ACTIVE); + k_msleep(DT_INST_PROP(0, reset_gpios_duration)); + gpio_pin_set_dt(&dev_cfg->reset, 0); +#else + + /* Reset command sent sucessively for each mode SPI/OPS & STR/DTR */ + XSPI_RegularCmdTypeDef s_command = { + .OperationType = HAL_XSPI_OPTYPE_COMMON_CFG, + .AddressMode = HAL_XSPI_ADDRESS_NONE, + .InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE, + .InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE, + .Instruction = SPI_NOR_CMD_RESET_EN, + .InstructionWidth = HAL_XSPI_INSTRUCTION_8_BITS, + .AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE, + .DataLength = HAL_XSPI_DATA_NONE, + .DummyCycles = 0U, + .DQSMode = HAL_XSPI_DQS_DISABLE, + .SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD, + }; + + /* Reset enable in SPI mode and STR transfer mode */ + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset enable (SPI/STR) failed"); + return -EIO; + } + + /* Reset memory in SPI mode and STR transfer mode */ + s_command.Instruction = SPI_NOR_CMD_RESET_MEM; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset memory (SPI/STR) failed"); + return -EIO; + } + + /* Reset enable in OPI mode and STR transfer mode */ + s_command.InstructionMode = HAL_XSPI_INSTRUCTION_8_LINES; + s_command.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_DISABLE; + s_command.Instruction = SPI_NOR_OCMD_RESET_EN; + s_command.InstructionWidth = HAL_XSPI_INSTRUCTION_16_BITS; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset enable (OCTO/STR) failed"); + return -EIO; + } + + /* Reset memory in OPI mode and STR transfer mode */ + s_command.Instruction = SPI_NOR_OCMD_RESET_MEM; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset memory (OCTO/STR) failed"); + return -EIO; + } + + /* Reset enable in OPI mode and DTR transfer mode */ + s_command.InstructionDTRMode = HAL_XSPI_INSTRUCTION_DTR_ENABLE; + s_command.Instruction = SPI_NOR_OCMD_RESET_EN; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset enable (OCTO/DTR) failed"); + return -EIO; + } + + /* Reset memory in OPI mode and DTR transfer mode */ + s_command.Instruction = SPI_NOR_OCMD_RESET_MEM; + if (HAL_XSPI_Command(&dev_data->hxspi, + &s_command, HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI reset memory (OCTO/DTR) failed"); + return -EIO; + } + +#endif /* STM32_XSPI_RESET_GPIO */ + /* Wait after SWreset CMD, in case SWReset occurred during erase operation */ + k_busy_wait(STM32_XSPI_RESET_MAX_TIME * USEC_PER_MSEC); + + return 0; +} + +/* + * Function to erase the flash : chip or sector with possible OCTO/SPI and STR/DTR + * to erase the complete chip (using dedicated command) : + * set size >= flash size + * set addr = 0 + */ +static int flash_stm32_xspi_erase(const struct device *dev, off_t addr, + size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + int ret = 0; + + /* Ignore zero size erase */ + if (size == 0) { + return 0; + } + + /* Maximise erase size : means the complete chip */ + if (size > dev_cfg->flash_size) { + size = dev_cfg->flash_size; + } + + if (!xspi_address_is_valid(dev, addr, size)) { + LOG_ERR("Error: address or size exceeds expected values: " + "addr 0x%lx, size %zu", (long)addr, size); + return -EINVAL; + } + + if (((size % SPI_NOR_SECTOR_SIZE) != 0) && (size < dev_cfg->flash_size)) { + LOG_ERR("Error: wrong sector size 0x%x", size); + return -ENOTSUP; + } + + XSPI_RegularCmdTypeDef cmd_erase = { + .OperationType = HAL_XSPI_OPTYPE_COMMON_CFG, + .AlternateBytesMode = HAL_XSPI_ALT_BYTES_NONE, + .DataMode = HAL_XSPI_DATA_NONE, + .DummyCycles = 0U, + .DQSMode = HAL_XSPI_DQS_DISABLE, + .SIOOMode = HAL_XSPI_SIOO_INST_EVERY_CMD, + }; + + xspi_lock_thread(dev); + + if (stm32_xspi_mem_ready(dev, + dev_cfg->data_mode, dev_cfg->data_rate) != 0) { + xspi_unlock_thread(dev); + LOG_ERR("Erase failed : flash busy"); + return -EBUSY; + } + + cmd_erase.InstructionMode = (dev_cfg->data_mode == XSPI_OCTO_MODE) + ? HAL_XSPI_INSTRUCTION_8_LINES + : HAL_XSPI_INSTRUCTION_1_LINE; + cmd_erase.InstructionDTRMode = (dev_cfg->data_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_INSTRUCTION_DTR_ENABLE + : HAL_XSPI_INSTRUCTION_DTR_DISABLE; + cmd_erase.InstructionWidth = (dev_cfg->data_mode == XSPI_OCTO_MODE) + ? HAL_XSPI_INSTRUCTION_16_BITS + : HAL_XSPI_INSTRUCTION_8_BITS; + + while ((size > 0) && (ret == 0)) { + + ret = stm32_xspi_write_enable(dev, + dev_cfg->data_mode, dev_cfg->data_rate); + if (ret != 0) { + LOG_ERR("Erase failed : write enable"); + break; + } + + if (size == dev_cfg->flash_size) { + /* Chip erase */ + LOG_DBG("Chip Erase"); + + cmd_erase.Address = 0; + cmd_erase.Instruction = (dev_cfg->data_mode == XSPI_OCTO_MODE) + ? SPI_NOR_OCMD_BULKE + : SPI_NOR_CMD_BULKE; + cmd_erase.AddressMode = HAL_XSPI_ADDRESS_NONE; + /* Full chip erase (Bulk) command */ + xspi_send_cmd(dev, &cmd_erase); + + size -= dev_cfg->flash_size; + /* Chip (Bulk) erase started, wait until WEL becomes 0 */ + ret = stm32_xspi_mem_erased(dev); + if (ret != 0) { + LOG_ERR("Chip Erase failed"); + break; + } + } else { + /* Sector or Block erase depending on the size */ + LOG_DBG("Sector/Block Erase"); + + cmd_erase.AddressMode = + (dev_cfg->data_mode == XSPI_OCTO_MODE) + ? HAL_XSPI_ADDRESS_8_LINES + : HAL_XSPI_ADDRESS_1_LINE; + cmd_erase.AddressDTRMode = + (dev_cfg->data_rate == XSPI_DTR_TRANSFER) + ? HAL_XSPI_ADDRESS_DTR_ENABLE + : HAL_XSPI_ADDRESS_DTR_DISABLE; + cmd_erase.AddressWidth = stm32_xspi_hal_address_size(dev); + cmd_erase.Address = addr; + + const struct jesd216_erase_type *erase_types = + dev_data->erase_types; + const struct jesd216_erase_type *bet = NULL; + + for (uint8_t ei = 0; + ei < JESD216_NUM_ERASE_TYPES; ++ei) { + const struct jesd216_erase_type *etp = + &erase_types[ei]; + + if ((etp->exp != 0) + && SPI_NOR_IS_ALIGNED(addr, etp->exp) + && (size >= BIT(etp->exp)) + && ((bet == NULL) + || (etp->exp > bet->exp))) { + bet = etp; + cmd_erase.Instruction = bet->cmd; + } else if (bet == NULL) { + /* Use the default sector erase cmd */ + if (dev_cfg->data_mode == XSPI_OCTO_MODE) { + cmd_erase.Instruction = SPI_NOR_OCMD_SE; + } else { + cmd_erase.Instruction = + (stm32_xspi_hal_address_size(dev) == + HAL_XSPI_ADDRESS_32_BITS) + ? SPI_NOR_CMD_SE_4B + : SPI_NOR_CMD_SE; + } + } + /* Avoid using wrong erase type, + * if zero entries are found in erase_types + */ + bet = NULL; + } + LOG_DBG("Sector/Block Erase addr 0x%x, asize 0x%x amode 0x%x instr 0x%x", + cmd_erase.Address, cmd_erase.AddressWidth, + cmd_erase.AddressMode, cmd_erase.Instruction); + + xspi_send_cmd(dev, &cmd_erase); + + if (bet != NULL) { + addr += BIT(bet->exp); + size -= BIT(bet->exp); + } else { + addr += SPI_NOR_SECTOR_SIZE; + size -= SPI_NOR_SECTOR_SIZE; + } + + ret = stm32_xspi_mem_ready(dev, dev_cfg->data_mode, + dev_cfg->data_rate); + } + + } + + xspi_unlock_thread(dev); + + return ret; +} + +/* Function to read the flash with possible OCTO/SPI and STR/DTR */ +static int flash_stm32_xspi_read(const struct device *dev, off_t addr, + void *data, size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + int ret; + + if (!xspi_address_is_valid(dev, addr, size)) { + LOG_ERR("Error: address or size exceeds expected values: " + "addr 0x%lx, size %zu", (long)addr, size); + return -EINVAL; + } + + /* Ignore zero size read */ + if (size == 0) { + return 0; + } + + XSPI_RegularCmdTypeDef cmd = xspi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); + + if (dev_cfg->data_mode != XSPI_OCTO_MODE) { + switch (dev_data->read_mode) { + case JESD216_MODE_112: { + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd.DataMode = HAL_XSPI_DATA_2_LINES; + break; + } + case JESD216_MODE_122: { + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_2_LINES; + cmd.DataMode = HAL_XSPI_DATA_2_LINES; + break; + } + case JESD216_MODE_114: { + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + case JESD216_MODE_144: { + cmd.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd.AddressMode = HAL_XSPI_ADDRESS_4_LINES; + cmd.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + default: + /* use the mode from ospi_prepare_cmd */ + break; + } + } + + /* Instruction and DummyCycles are set below */ + cmd.Address = addr; /* AddressSize is 32bits in OPSI mode */ + cmd.AddressWidth = stm32_xspi_hal_address_size(dev); + /* DataSize is set by the read cmd */ + + /* Configure other parameters */ + if (dev_cfg->data_rate == XSPI_DTR_TRANSFER) { + /* DTR transfer rate (==> Octal mode) */ + cmd.Instruction = SPI_NOR_OCMD_DTR_RD; + cmd.DummyCycles = SPI_NOR_DUMMY_RD_OCTAL_DTR; + } else { + /* STR transfer rate */ + if (dev_cfg->data_mode == XSPI_OCTO_MODE) { + /* OPI and STR */ + cmd.Instruction = SPI_NOR_OCMD_RD; + cmd.DummyCycles = SPI_NOR_DUMMY_RD_OCTAL; + } else { + /* use SFDP:BFP read instruction */ + cmd.Instruction = dev_data->read_opcode; + cmd.DummyCycles = dev_data->read_dummy; + /* in SPI and STR : expecting SPI_NOR_CMD_READ_FAST_4B */ + } + } + + LOG_DBG("XSPI: read %zu data", size); + xspi_lock_thread(dev); + + ret = xspi_read_access(dev, &cmd, data, size); + + xspi_unlock_thread(dev); + + return ret; +} + +/* Function to write the flash (page program) : with possible OCTO/SPI and STR/DTR */ +static int flash_stm32_xspi_write(const struct device *dev, off_t addr, + const void *data, size_t size) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + size_t to_write; + int ret = 0; + + if (!xspi_address_is_valid(dev, addr, size)) { + LOG_ERR("Error: address or size exceeds expected values: " + "addr 0x%lx, size %zu", (long)addr, size); + return -EINVAL; + } + + /* Ignore zero size write */ + if (size == 0) { + return 0; + } + + /* page program for STR or DTR mode */ + XSPI_RegularCmdTypeDef cmd_pp = xspi_prepare_cmd(dev_cfg->data_mode, dev_cfg->data_rate); + + /* using 32bits address also in SPI/STR mode */ + cmd_pp.Instruction = dev_data->write_opcode; + + if (dev_cfg->data_mode != XSPI_OCTO_MODE) { + switch (cmd_pp.Instruction) { + case SPI_NOR_CMD_PP_4B: + __fallthrough; + case SPI_NOR_CMD_PP: { + cmd_pp.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd_pp.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd_pp.DataMode = HAL_XSPI_DATA_1_LINE; + break; + } + case SPI_NOR_CMD_PP_1_1_4_4B: + __fallthrough; + case SPI_NOR_CMD_PP_1_1_4: { + cmd_pp.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd_pp.AddressMode = HAL_XSPI_ADDRESS_1_LINE; + cmd_pp.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + case SPI_NOR_CMD_PP_1_4_4_4B: + __fallthrough; + case SPI_NOR_CMD_PP_1_4_4: { + cmd_pp.InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE; + cmd_pp.AddressMode = HAL_XSPI_ADDRESS_4_LINES; + cmd_pp.DataMode = HAL_XSPI_DATA_4_LINES; + break; + } + default: + /* use the mode from ospi_prepare_cmd */ + break; + } + } + + cmd_pp.Address = addr; + cmd_pp.AddressWidth = stm32_xspi_hal_address_size(dev); + cmd_pp.DummyCycles = 0U; + + LOG_DBG("XSPI: write %zu data", size); + xspi_lock_thread(dev); + + ret = stm32_xspi_mem_ready(dev, + dev_cfg->data_mode, dev_cfg->data_rate); + if (ret != 0) { + xspi_unlock_thread(dev); + LOG_ERR("XSPI: write not ready"); + return -EIO; + } + + while ((size > 0) && (ret == 0)) { + to_write = size; + ret = stm32_xspi_write_enable(dev, + dev_cfg->data_mode, dev_cfg->data_rate); + if (ret != 0) { + LOG_ERR("XSPI: write not enabled"); + break; + } + /* Don't write more than a page. */ + if (to_write >= SPI_NOR_PAGE_SIZE) { + to_write = SPI_NOR_PAGE_SIZE; + } + + /* Don't write across a page boundary */ + if (((addr + to_write - 1U) / SPI_NOR_PAGE_SIZE) + != (addr / SPI_NOR_PAGE_SIZE)) { + to_write = SPI_NOR_PAGE_SIZE - + (addr % SPI_NOR_PAGE_SIZE); + } + cmd_pp.Address = addr; + + ret = xspi_write_access(dev, &cmd_pp, data, to_write); + if (ret != 0) { + LOG_ERR("XSPI: write not access"); + break; + } + + size -= to_write; + data = (const uint8_t *)data + to_write; + addr += to_write; + + /* Configure automatic polling mode to wait for end of program */ + ret = stm32_xspi_mem_ready(dev, + dev_cfg->data_mode, dev_cfg->data_rate); + if (ret != 0) { + LOG_ERR("XSPI: write PP not ready"); + break; + } + } + + xspi_unlock_thread(dev); + + return ret; +} + +static const struct flash_parameters flash_stm32_xspi_parameters = { + .write_block_size = 1, + .erase_value = 0xff +}; + +static const struct flash_parameters * +flash_stm32_xspi_get_parameters(const struct device *dev) +{ + ARG_UNUSED(dev); + + return &flash_stm32_xspi_parameters; +} + +static void flash_stm32_xspi_isr(const struct device *dev) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + HAL_XSPI_IRQHandler(&dev_data->hxspi); +} + +#if !defined(CONFIG_SOC_SERIES_STM32H7X) +/* weak function required for HAL compilation */ +__weak HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma) +{ + return HAL_OK; +} + +/* weak function required for HAL compilation */ +__weak HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma) +{ + return HAL_OK; +} +#endif /* !CONFIG_SOC_SERIES_STM32H7X */ + +/* This function is executed in the interrupt context */ +#if STM32_XSPI_USE_DMA +static void xspi_dma_callback(const struct device *dev, void *arg, + uint32_t channel, int status) +{ + DMA_HandleTypeDef *hdma = arg; + + ARG_UNUSED(dev); + + if (status < 0) { + LOG_ERR("DMA callback error with channel %d.", channel); + } + + HAL_DMA_IRQHandler(hdma); +} +#endif + + +/* + * Transfer Error callback. + */ +void HAL_XSPI_ErrorCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Error cb"); + + dev_data->cmd_status = -EIO; + + k_sem_give(&dev_data->sync); +} + +/* + * Command completed callback. + */ +void HAL_XSPI_CmdCpltCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Cmd Cplt cb"); + + k_sem_give(&dev_data->sync); +} + +/* + * Rx Transfer completed callback. + */ +void HAL_XSPI_RxCpltCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Rx Cplt cb"); + + k_sem_give(&dev_data->sync); +} + +/* + * Tx Transfer completed callback. + */ +void HAL_XSPI_TxCpltCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Tx Cplt cb"); + + k_sem_give(&dev_data->sync); +} + +/* + * Status Match callback. + */ +void HAL_XSPI_StatusMatchCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Status Match cb"); + + k_sem_give(&dev_data->sync); +} + +/* + * Timeout callback. + */ +void HAL_XSPI_TimeOutCallback(XSPI_HandleTypeDef *hxspi) +{ + struct flash_stm32_xspi_data *dev_data = + CONTAINER_OF(hxspi, struct flash_stm32_xspi_data, hxspi); + + LOG_DBG("Timeout cb"); + + dev_data->cmd_status = -EIO; + + k_sem_give(&dev_data->sync); +} + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) +static void flash_stm32_xspi_pages_layout(const struct device *dev, + const struct flash_pages_layout **layout, + size_t *layout_size) +{ + struct flash_stm32_xspi_data *dev_data = dev->data; + + *layout = &dev_data->layout; + *layout_size = 1; +} +#endif + +static const struct flash_driver_api flash_stm32_xspi_driver_api = { + .read = flash_stm32_xspi_read, + .write = flash_stm32_xspi_write, + .erase = flash_stm32_xspi_erase, + .get_parameters = flash_stm32_xspi_get_parameters, +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + .page_layout = flash_stm32_xspi_pages_layout, +#endif +#if defined(CONFIG_FLASH_JESD216_API) + .sfdp_read = xspi_read_sfdp, + .read_jedec_id = xspi_read_jedec_id, +#endif /* CONFIG_FLASH_JESD216_API */ +}; + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) +static int setup_pages_layout(const struct device *dev) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *data = dev->data; + const size_t flash_size = dev_cfg->flash_size; + uint32_t layout_page_size = data->page_size; + uint8_t value = 0; + int rv = 0; + + /* Find the smallest erase size. */ + for (size_t i = 0; i < ARRAY_SIZE(data->erase_types); ++i) { + const struct jesd216_erase_type *etp = &data->erase_types[i]; + + if ((etp->cmd != 0) + && ((value == 0) || (etp->exp < value))) { + value = etp->exp; + } + } + + uint32_t erase_size = BIT(value); + + if (erase_size == 0) { + erase_size = SPI_NOR_SECTOR_SIZE; + } + + /* We need layout page size to be compatible with erase size */ + if ((layout_page_size % erase_size) != 0) { + LOG_DBG("layout page %u not compatible with erase size %u", + layout_page_size, erase_size); + LOG_DBG("erase size will be used as layout page size"); + layout_page_size = erase_size; + } + + /* Warn but accept layout page sizes that leave inaccessible + * space. + */ + if ((flash_size % layout_page_size) != 0) { + LOG_DBG("layout page %u wastes space with device size %zu", + layout_page_size, flash_size); + } + + data->layout.pages_size = layout_page_size; + data->layout.pages_count = flash_size / layout_page_size; + LOG_DBG("layout %u x %u By pages", data->layout.pages_count, + data->layout.pages_size); + + return rv; +} +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ + +static int stm32_xspi_read_status_register(const struct device *dev, uint8_t reg_num, uint8_t *reg) +{ + XSPI_RegularCmdTypeDef s_command = { + .InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE, + .DataMode = HAL_XSPI_DATA_1_LINE, + }; + + switch (reg_num) { + case 1U: + s_command.Instruction = SPI_NOR_CMD_RDSR; + break; + case 2U: + s_command.Instruction = SPI_NOR_CMD_RDSR2; + break; + case 3U: + s_command.Instruction = SPI_NOR_CMD_RDSR3; + break; + default: + return -EINVAL; + } + + return xspi_read_access(dev, &s_command, reg, sizeof(*reg)); +} + +static int stm32_xspi_write_status_register(const struct device *dev, uint8_t reg_num, uint8_t reg) +{ + struct flash_stm32_xspi_data *data = dev->data; + XSPI_RegularCmdTypeDef s_command = { + .Instruction = SPI_NOR_CMD_WRSR, + .InstructionMode = HAL_XSPI_INSTRUCTION_1_LINE, + .DataMode = HAL_XSPI_DATA_1_LINE + }; + size_t size; + uint8_t regs[4] = { 0 }; + uint8_t *regs_p; + int ret; + + if (reg_num == 1U) { + size = 1U; + regs[0] = reg; + regs_p = ®s[0]; + /* 1 byte write clears SR2, write SR2 as well */ + if (data->qer_type == JESD216_DW15_QER_S2B1v1) { + ret = stm32_xspi_read_status_register(dev, 2, ®s[1]); + if (ret < 0) { + return ret; + } + size = 2U; + } + } else if (reg_num == 2U) { + s_command.Instruction = SPI_NOR_CMD_WRSR2; + size = 1U; + regs[1] = reg; + regs_p = ®s[1]; + /* if SR2 write needs SR1 */ + if ((data->qer_type == JESD216_DW15_QER_VAL_S2B1v1) || + (data->qer_type == JESD216_DW15_QER_VAL_S2B1v4) || + (data->qer_type == JESD216_DW15_QER_VAL_S2B1v5)) { + ret = stm32_xspi_read_status_register(dev, 1, ®s[0]); + if (ret < 0) { + return ret; + } + s_command.Instruction = SPI_NOR_CMD_WRSR; + size = 2U; + regs_p = ®s[0]; + } + } else if (reg_num == 3U) { + s_command.Instruction = SPI_NOR_CMD_WRSR3; + size = 1U; + regs[2] = reg; + regs_p = ®s[2]; + } else { + return -EINVAL; + } + + return xspi_write_access(dev, &s_command, regs_p, size); +} + +static int stm32_xspi_enable_qe(const struct device *dev) +{ + struct flash_stm32_xspi_data *data = dev->data; + uint8_t qe_reg_num; + uint8_t qe_bit; + uint8_t reg; + int ret; + + switch (data->qer_type) { + case JESD216_DW15_QER_NONE: + /* no QE bit, device detects reads based on opcode */ + return 0; + case JESD216_DW15_QER_S1B6: + qe_reg_num = 1U; + qe_bit = BIT(6U); + break; + case JESD216_DW15_QER_S2B7: + qe_reg_num = 2U; + qe_bit = BIT(7U); + break; + case JESD216_DW15_QER_S2B1v1: + __fallthrough; + case JESD216_DW15_QER_S2B1v4: + __fallthrough; + case JESD216_DW15_QER_S2B1v5: + __fallthrough; + case JESD216_DW15_QER_S2B1v6: + qe_reg_num = 2U; + qe_bit = BIT(1U); + break; + default: + return -ENOTSUP; + } + + ret = stm32_xspi_read_status_register(dev, qe_reg_num, ®); + if (ret < 0) { + return ret; + } + + /* exit early if QE bit is already set */ + if ((reg & qe_bit) != 0U) { + return 0; + } + + ret = stm32_xspi_write_enable(dev, XSPI_SPI_MODE, XSPI_STR_TRANSFER); + if (ret < 0) { + return ret; + } + + reg |= qe_bit; + + ret = stm32_xspi_write_status_register(dev, qe_reg_num, reg); + if (ret < 0) { + return ret; + } + + ret = stm32_xspi_mem_ready(dev, XSPI_SPI_MODE, XSPI_STR_TRANSFER); + if (ret < 0) { + return ret; + } + + /* validate that QE bit is set */ + ret = stm32_xspi_read_status_register(dev, qe_reg_num, ®); + if (ret < 0) { + return ret; + } + + if ((reg & qe_bit) == 0U) { + LOG_ERR("Status Register %u [0x%02x] not set", qe_reg_num, reg); + ret = -EIO; + } + + return ret; +} + +static void spi_nor_process_bfp_addrbytes(const struct device *dev, + const uint8_t jesd216_bfp_addrbytes) +{ + struct flash_stm32_xspi_data *data = dev->data; + + if ((jesd216_bfp_addrbytes == JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_4B) || + (jesd216_bfp_addrbytes == JESD216_SFDP_BFP_DW1_ADDRBYTES_VAL_3B4B)) { + data->address_width = 4U; + } else { + data->address_width = 3U; + } +} + +static inline uint8_t spi_nor_convert_read_to_4b(const uint8_t opcode) +{ + switch (opcode) { + case SPI_NOR_CMD_READ: + return SPI_NOR_CMD_READ_4B; + case SPI_NOR_CMD_DREAD: + return SPI_NOR_CMD_DREAD_4B; + case SPI_NOR_CMD_2READ: + return SPI_NOR_CMD_2READ_4B; + case SPI_NOR_CMD_QREAD: + return SPI_NOR_CMD_QREAD_4B; + case SPI_NOR_CMD_4READ: + return SPI_NOR_CMD_4READ_4B; + default: + /* use provided */ + return opcode; + } +} + +static inline uint8_t spi_nor_convert_write_to_4b(const uint8_t opcode) +{ + switch (opcode) { + case SPI_NOR_CMD_PP: + return SPI_NOR_CMD_PP_4B; + case SPI_NOR_CMD_PP_1_1_4: + return SPI_NOR_CMD_PP_1_1_4_4B; + case SPI_NOR_CMD_PP_1_4_4: + return SPI_NOR_CMD_PP_1_4_4_4B; + default: + /* use provided */ + return opcode; + } +} + +static int spi_nor_process_bfp(const struct device *dev, + const struct jesd216_param_header *php, + const struct jesd216_bfp *bfp) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *data = dev->data; + /* must be kept in data mode order, ignore 1-1-1 (always supported) */ + const enum jesd216_mode_type supported_read_modes[] = { JESD216_MODE_112, JESD216_MODE_122, + JESD216_MODE_114, + JESD216_MODE_144 }; + size_t supported_read_modes_max_idx; + struct jesd216_erase_type *etp = data->erase_types; + size_t idx; + const size_t flash_size = jesd216_bfp_density(bfp) / 8U; + struct jesd216_instr read_instr = { 0 }; + struct jesd216_bfp_dw15 dw15; + + if (flash_size != dev_cfg->flash_size) { + LOG_DBG("Unexpected flash size: %u", flash_size); + } + + LOG_DBG("%s: %u MiBy flash", dev->name, (uint32_t)(flash_size >> 20)); + + /* Copy over the erase types, preserving their order. (The + * Sector Map Parameter table references them by index.) + */ + memset(data->erase_types, 0, sizeof(data->erase_types)); + for (idx = 1U; idx <= ARRAY_SIZE(data->erase_types); ++idx) { + if (jesd216_bfp_erase(bfp, idx, etp) == 0) { + LOG_DBG("Erase %u with %02x", + (uint32_t)BIT(etp->exp), etp->cmd); + } + ++etp; + } + + spi_nor_process_bfp_addrbytes(dev, jesd216_bfp_addrbytes(bfp)); + LOG_DBG("Address width: %u Bytes", data->address_width); + + /* use PP opcode based on configured data mode if nothing is set in DTS */ + if (data->write_opcode == SPI_NOR_WRITEOC_NONE) { + switch (dev_cfg->data_mode) { + case XSPI_OCTO_MODE: + data->write_opcode = SPI_NOR_OCMD_PAGE_PRG; + break; + case XSPI_QUAD_MODE: + data->write_opcode = SPI_NOR_CMD_PP_1_4_4; + break; + case XSPI_DUAL_MODE: + data->write_opcode = SPI_NOR_CMD_PP_1_1_2; + break; + default: + data->write_opcode = SPI_NOR_CMD_PP; + break; + } + } + + if (dev_cfg->data_mode != XSPI_OCTO_MODE) { + /* determine supported read modes, begin from the slowest */ + data->read_mode = JESD216_MODE_111; + data->read_opcode = SPI_NOR_CMD_READ; + data->read_dummy = 0U; + + if (dev_cfg->data_mode != XSPI_SPI_MODE) { + if (dev_cfg->data_mode == XSPI_DUAL_MODE) { + /* the index of JESD216_MODE_114 in supported_read_modes */ + supported_read_modes_max_idx = 2U; + } else { + supported_read_modes_max_idx = ARRAY_SIZE(supported_read_modes); + } + + for (idx = 0U; idx < supported_read_modes_max_idx; ++idx) { + if (jesd216_bfp_read_support(php, bfp, supported_read_modes[idx], + &read_instr) < 0) { + /* not supported */ + continue; + } + + LOG_DBG("Supports read mode: %d, instr: 0x%X", + supported_read_modes[idx], read_instr.instr); + data->read_mode = supported_read_modes[idx]; + data->read_opcode = read_instr.instr; + data->read_dummy = + (read_instr.wait_states + read_instr.mode_clocks); + } + } + + /* convert 3-Byte opcodes to 4-Byte (if required) */ + if (IS_ENABLED(DT_INST_PROP(0, four_byte_opcodes))) { + if (data->address_width != 4U) { + LOG_DBG("4-Byte opcodes require 4-Byte address width"); + return -ENOTSUP; + } + data->read_opcode = spi_nor_convert_read_to_4b(data->read_opcode); + data->write_opcode = spi_nor_convert_write_to_4b(data->write_opcode); + } + + /* enable quad mode (if required) */ + if (dev_cfg->data_mode == XSPI_QUAD_MODE) { + if (jesd216_bfp_decode_dw15(php, bfp, &dw15) < 0) { + /* will use QER from DTS or default (refer to device data) */ + LOG_WRN("Unable to decode QE requirement [DW15]"); + } else { + /* bypass DTS QER value */ + data->qer_type = dw15.qer; + } + + LOG_DBG("QE requirement mode: %x", data->qer_type); + + if (stm32_xspi_enable_qe(dev) < 0) { + LOG_ERR("Failed to enable QUAD mode"); + return -EIO; + } + + LOG_DBG("QUAD mode enabled"); + } + } + + data->page_size = jesd216_bfp_page_size(php, bfp); + + LOG_DBG("Page size %u bytes", data->page_size); + LOG_DBG("Flash size %zu bytes", flash_size); + LOG_DBG("Using read mode: %d, instr: 0x%X, dummy cycles: %u", + data->read_mode, data->read_opcode, data->read_dummy); + LOG_DBG("Using write instr: 0x%X", data->write_opcode); + + return 0; +} + +#if STM32_XSPI_USE_DMA +static int flash_stm32_xspi_dma_init(DMA_HandleTypeDef *hdma, struct stream *dma_stream) +{ + int ret; + /* + * DMA configuration + * Due to use of XSPI HAL API in current driver, + * both HAL and Zephyr DMA drivers should be configured. + * The required configuration for Zephyr DMA driver should only provide + * the minimum information to inform the DMA slot will be in used and + * how to route callbacks. + */ + + if (!device_is_ready(dma_stream->dev)) { + LOG_ERR("DMA %s device not ready", dma_stream->dev->name); + return -ENODEV; + } + /* Proceed to the minimum Zephyr DMA driver init of the channel */ + dma_stream->cfg.user_data = hdma; + /* HACK: This field is used to inform driver that it is overridden */ + dma_stream->cfg.linked_channel = STM32_DMA_HAL_OVERRIDE; + /* Because of the STREAM OFFSET, the DMA channel given here is from 1 - 8 */ + ret = dma_config(dma_stream->dev, + (dma_stream->channel + STM32_DMA_STREAM_OFFSET), &dma_stream->cfg); + if (ret != 0) { + LOG_ERR("Failed to configure DMA channel %d", + dma_stream->channel + STM32_DMA_STREAM_OFFSET); + return ret; + } + + /* Proceed to the HAL DMA driver init */ + if (dma_stream->cfg.source_data_size != dma_stream->cfg.dest_data_size) { + LOG_ERR("DMA Source and destination data sizes not aligned"); + return -EINVAL; + } + + hdma->Init.SrcDataWidth = DMA_SRC_DATAWIDTH_WORD; /* Fixed value */ + hdma->Init.DestDataWidth = DMA_DEST_DATAWIDTH_WORD; /* Fixed value */ + hdma->Init.SrcInc = (dma_stream->src_addr_increment) + ? DMA_SINC_INCREMENTED + : DMA_SINC_FIXED; + hdma->Init.DestInc = (dma_stream->dst_addr_increment) + ? DMA_DINC_INCREMENTED + : DMA_DINC_FIXED; + hdma->Init.SrcBurstLength = 4; + hdma->Init.DestBurstLength = 4; + hdma->Init.Priority = table_priority[dma_stream->cfg.channel_priority]; + hdma->Init.Direction = table_direction[dma_stream->cfg.channel_direction]; + hdma->Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT0 | DMA_SRC_ALLOCATED_PORT1; + hdma->Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER; + hdma->Init.Mode = DMA_NORMAL; + hdma->Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST; + hdma->Init.Request = dma_stream->cfg.dma_slot; + + /* + * HAL expects a valid DMA channel (not DMAMUX). + * The channel is from 0 to 7 because of the STM32_DMA_STREAM_OFFSET + * in the dma_stm32 driver + */ + hdma->Instance = LL_DMA_GET_CHANNEL_INSTANCE(dma_stream->reg, + dma_stream->channel); + + /* Initialize DMA HAL */ + if (HAL_DMA_Init(hdma) != HAL_OK) { + LOG_ERR("XSPI DMA Init failed"); + return -EIO; + } + + if (HAL_DMA_ConfigChannelAttributes(hdma, DMA_CHANNEL_NPRIV) != HAL_OK) { + LOG_ERR("XSPI DMA Init failed"); + return -EIO; + } + + LOG_DBG("XSPI with DMA transfer"); + return 0; +} +#endif /* STM32_XSPI_USE_DMA */ + + +static int flash_stm32_xspi_init(const struct device *dev) +{ + const struct flash_stm32_xspi_config *dev_cfg = dev->config; + struct flash_stm32_xspi_data *dev_data = dev->data; + uint32_t ahb_clock_freq; + uint32_t prescaler = STM32_XSPI_CLOCK_PRESCALER_MIN; + int ret; + + /* The SPI/DTR is not a valid config of data_mode/data_rate according to the DTS */ + if ((dev_cfg->data_mode != XSPI_OCTO_MODE) + && (dev_cfg->data_rate == XSPI_DTR_TRANSFER)) { + /* already the right config, continue */ + LOG_ERR("XSPI mode SPI|DUAL|QUAD/DTR is not valid"); + return -ENOTSUP; + } + + /* Signals configuration */ + ret = pinctrl_apply_state(dev_cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("XSPI pinctrl setup failed (%d)", ret); + return ret; + } + + if (!device_is_ready(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE))) { + LOG_ERR("clock control device not ready"); + return -ENODEV; + } + + if (dev_cfg->pclk_len > 3) { + /* Max 3 domain clock are expected */ + LOG_ERR("Could not select %d XSPI domain clock", dev_cfg->pclk_len); + return -EIO; + } + + /* Clock configuration */ + if (clock_control_on(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken[0]) != 0) { + LOG_ERR("Could not enable XSPI clock"); + return -EIO; + } + if (clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken[0], + &ahb_clock_freq) < 0) { + LOG_ERR("Failed call clock_control_get_rate(pclken)"); + return -EIO; + } + /* Alternate clock config for peripheral if any */ + if (IS_ENABLED(STM32_XSPI_DOMAIN_CLOCK_SUPPORT) && (dev_cfg->pclk_len > 1)) { + if (clock_control_configure(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken[1], + NULL) != 0) { + LOG_ERR("Could not select XSPI domain clock"); + return -EIO; + } + /* + * Get the clock rate from this one (update ahb_clock_freq) + * TODO: retrieve index in the clocks property where clocks has "xspi-ker" + * Assuming index is 1 + */ + if (clock_control_get_rate(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken[1], + &ahb_clock_freq) < 0) { + LOG_ERR("Failed call clock_control_get_rate(pclken)"); + return -EIO; + } + } + /* Clock domain corresponding to the IO-Mgr (XSPIM) */ + if (IS_ENABLED(STM32_XSPI_DOMAIN_CLOCK_SUPPORT) && (dev_cfg->pclk_len > 2)) { + if (clock_control_on(DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE), + (clock_control_subsys_t) &dev_cfg->pclken[2]) != 0) { + LOG_ERR("Could not enable XSPI Manager clock"); + return -EIO; + } + /* Do NOT Get the clock rate from this one */ + } + + for (; prescaler <= STM32_XSPI_CLOCK_PRESCALER_MAX; prescaler++) { + uint32_t clk = STM32_XSPI_CLOCK_COMPUTE(ahb_clock_freq, prescaler); + + if (clk <= dev_cfg->max_frequency) { + break; + } + } + __ASSERT_NO_MSG(prescaler >= STM32_XSPI_CLOCK_PRESCALER_MIN && + prescaler <= STM32_XSPI_CLOCK_PRESCALER_MAX); + + /* Initialize XSPI HAL structure completely */ + dev_data->hxspi.Init.ClockPrescaler = prescaler; + /* The stm32 hal_xspi driver does not reduce DEVSIZE before writing the DCR1 */ + dev_data->hxspi.Init.MemorySize = find_lsb_set(dev_cfg->flash_size) - 2; +#if defined(XSPI_DCR2_WRAPSIZE) + dev_data->hxspi.Init.WrapSize = HAL_XSPI_WRAP_NOT_SUPPORTED; +#endif /* XSPI_DCR2_WRAPSIZE */ + /* STR mode else Macronix for DTR mode */ + if (dev_cfg->data_rate == XSPI_DTR_TRANSFER) { + dev_data->hxspi.Init.MemoryType = HAL_XSPI_MEMTYPE_MACRONIX; + dev_data->hxspi.Init.DelayHoldQuarterCycle = HAL_XSPI_DHQC_ENABLE; + } else { + + } +#if STM32_XSPI_DLYB_BYPASSED + dev_data->hxspi.Init.DelayBlockBypass = HAL_XSPI_DELAY_BLOCK_BYPASS; +#else + dev_data->hxspi.Init.DelayBlockBypass = HAL_XSPI_DELAY_BLOCK_ON; +#endif /* STM32_XSPI_DLYB_BYPASSED */ + + + if (HAL_XSPI_Init(&dev_data->hxspi) != HAL_OK) { + LOG_ERR("XSPI Init failed"); + return -EIO; + } + + LOG_DBG("XSPI Init'd"); + +#if defined(HAL_XSPIM_IOPORT_1) || defined(HAL_XSPIM_IOPORT_2) + /* XSPI I/O manager init Function */ + XSPIM_CfgTypeDef xspi_mgr_cfg; + + if (dev_data->hxspi.Instance == XSPI1) { + xspi_mgr_cfg.IOPort = HAL_XSPIM_IOPORT_1; + } else if (dev_data->hxspi.Instance == XSPI2) { + xspi_mgr_cfg.IOPort = HAL_XSPIM_IOPORT_2; + } + xspi_mgr_cfg.nCSOverride = HAL_XSPI_CSSEL_OVR_DISABLED; + xspi_mgr_cfg.Req2AckTime = 1; + + if (HAL_XSPIM_Config(&dev_data->hxspi, &xspi_mgr_cfg, + HAL_XSPI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) { + LOG_ERR("XSPI M config failed"); + return -EIO; + } + +#endif /* XSPIM */ + +#if defined(DLYB_XSPI1) || defined(DLYB_XSPI2) || defined(DLYB_OCTOSPI1) || defined(DLYB_OCTOSPI2) + /* XSPI delay block init Function */ + HAL_XSPI_DLYB_CfgTypeDef xspi_delay_block_cfg = {0}; + + (void)HAL_XSPI_DLYB_GetClockPeriod(&dev_data->hxspi, &xspi_delay_block_cfg); + /* with DTR, set the PhaseSel/4 (empiric value from stm32Cube) */ + xspi_delay_block_cfg.PhaseSel /= 4; + + if (HAL_XSPI_DLYB_SetConfig(&dev_data->hxspi, &xspi_delay_block_cfg) != HAL_OK) { + LOG_ERR("XSPI DelayBlock failed"); + return -EIO; + } + + LOG_DBG("Delay Block Init"); + +#endif /* DLYB_ */ + +#if STM32_XSPI_USE_DMA + /* Configure and enable the DMA channels after XSPI config */ + static DMA_HandleTypeDef hdma_tx; + static DMA_HandleTypeDef hdma_rx; + + if (flash_stm32_xspi_dma_init(&hdma_tx, &dev_data->dma_tx) != 0) { + LOG_ERR("XSPI DMA Tx init failed"); + return -EIO; + } + + /* The dma_tx handle is hold by the dma_stream.cfg.user_data */ + __HAL_LINKDMA(&dev_data->hxspi, hdmatx, hdma_tx); + + if (flash_stm32_xspi_dma_init(&hdma_rx, &dev_data->dma_rx) != 0) { + LOG_ERR("XSPI DMA Rx init failed"); + return -EIO; + } + + /* The dma_rx handle is hold by the dma_stream.cfg.user_data */ + __HAL_LINKDMA(&dev_data->hxspi, hdmarx, hdma_rx); + +#endif /* CONFIG_USE_STM32_HAL_DMA */ + /* Initialize semaphores */ + k_sem_init(&dev_data->sem, 1, 1); + k_sem_init(&dev_data->sync, 0, 1); + + /* Run IRQ init */ + dev_cfg->irq_config(dev); + + /* Reset NOR flash memory : still with the SPI/STR config for the NOR */ + if (stm32_xspi_mem_reset(dev) != 0) { + LOG_ERR("XSPI reset failed"); + return -EIO; + } + + LOG_DBG("Reset Mem (SPI/STR)"); + + /* Check if memory is ready in the SPI/STR mode */ + if (stm32_xspi_mem_ready(dev, + XSPI_SPI_MODE, XSPI_STR_TRANSFER) != 0) { + LOG_ERR("XSPI memory not ready"); + return -EIO; + } + + LOG_DBG("Mem Ready (SPI/STR)"); + +#if defined(CONFIG_FLASH_JESD216_API) + /* Process with the RDID (jedec read ID) instruction at init and fill jedec_id Table */ + ret = stm32_xspi_read_jedec_id(dev); + if (ret != 0) { + LOG_ERR("Read ID failed: %d", ret); + return ret; + } +#endif /* CONFIG_FLASH_JESD216_API */ + + if (stm32_xspi_config_mem(dev) != 0) { + LOG_ERR("OSPI mode not config'd (%u rate %u)", + dev_cfg->data_mode, dev_cfg->data_rate); + return -EIO; + } + + /* Send the instruction to read the SFDP */ + const uint8_t decl_nph = 2; + union { + /* We only process BFP so use one parameter block */ + uint8_t raw[JESD216_SFDP_SIZE(decl_nph)]; + struct jesd216_sfdp_header sfdp; + } u; + const struct jesd216_sfdp_header *hp = &u.sfdp; + + ret = xspi_read_sfdp(dev, 0, u.raw, sizeof(u.raw)); + if (ret != 0) { + LOG_ERR("SFDP read failed: %d", ret); + return ret; + } + + uint32_t magic = jesd216_sfdp_magic(hp); + + if (magic != JESD216_SFDP_MAGIC) { + LOG_ERR("SFDP magic %08x invalid", magic); + return -EINVAL; + } + + LOG_DBG("%s: SFDP v %u.%u AP %x with %u PH", dev->name, + hp->rev_major, hp->rev_minor, hp->access, 1 + hp->nph); + + const struct jesd216_param_header *php = hp->phdr; + const struct jesd216_param_header *phpe = php + + MIN(decl_nph, 1 + hp->nph); + + while (php != phpe) { + uint16_t id = jesd216_param_id(php); + + LOG_DBG("PH%u: %04x rev %u.%u: %u DW @ %x", + (php - hp->phdr), id, php->rev_major, php->rev_minor, + php->len_dw, jesd216_param_addr(php)); + + if (id == JESD216_SFDP_PARAM_ID_BFP) { + union { + uint32_t dw[20]; + struct jesd216_bfp bfp; + } u2; + const struct jesd216_bfp *bfp = &u2.bfp; + + ret = xspi_read_sfdp(dev, jesd216_param_addr(php), + (uint8_t *)u2.dw, + MIN(sizeof(uint32_t) * php->len_dw, sizeof(u2.dw))); + if (ret == 0) { + ret = spi_nor_process_bfp(dev, php, bfp); + } + + if (ret != 0) { + LOG_ERR("SFDP BFP failed: %d", ret); + break; + } + } + if (id == JESD216_SFDP_PARAM_ID_4B_ADDR_INSTR) { + + if (dev_data->address_width == 4U) { + /* + * Check table 4 byte address instruction table to get supported + * erase opcodes when running in 4 byte address mode + */ + union { + uint32_t dw[2]; + struct { + uint32_t dummy; + uint8_t type[4]; + } types; + } u2; + ret = xspi_read_sfdp(dev, jesd216_param_addr(php), + (uint8_t *)u2.dw, + MIN(sizeof(uint32_t) * php->len_dw, sizeof(u2.dw))); + if (ret != 0) { + break; + } + for (uint8_t ei = 0; ei < JESD216_NUM_ERASE_TYPES; ++ei) { + struct jesd216_erase_type *etp = &dev_data->erase_types[ei]; + const uint8_t cmd = u2.types.type[ei]; + /* 0xff means not supported */ + if (cmd == 0xff) { + etp->exp = 0; + etp->cmd = 0; + } else { + etp->cmd = cmd; + }; + } + } + } + ++php; + } + +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + ret = setup_pages_layout(dev); + if (ret != 0) { + LOG_ERR("layout setup failed: %d", ret); + return -ENODEV; + } +#endif /* CONFIG_FLASH_PAGE_LAYOUT */ + + LOG_INF("NOR external-flash at 0x%lx (0x%x bytes)", + (long)(STM32_XSPI_BASE_ADDRESS), + dev_cfg->flash_size); + + return 0; +} + + +#if STM32_XSPI_USE_DMA +#define DMA_CHANNEL_CONFIG(node, dir) \ + DT_DMAS_CELL_BY_NAME(node, dir, channel_config) + +#define XSPI_DMA_CHANNEL_INIT(node, dir, dir_cap, src_dev, dest_dev) \ + .dev = DEVICE_DT_GET(DT_DMAS_CTLR(node)), \ + .channel = DT_DMAS_CELL_BY_NAME(node, dir, channel), \ + .reg = (DMA_TypeDef *)DT_REG_ADDR( \ + DT_PHANDLE_BY_NAME(node, dmas, dir)), \ + .cfg = { \ + .dma_slot = DT_DMAS_CELL_BY_NAME(node, dir, slot), \ + .channel_direction = STM32_DMA_CONFIG_DIRECTION( \ + DMA_CHANNEL_CONFIG(node, dir)), \ + .channel_priority = STM32_DMA_CONFIG_PRIORITY( \ + DMA_CHANNEL_CONFIG(node, dir)), \ + .dma_callback = xspi_dma_callback, \ + }, \ + .src_addr_increment = STM32_DMA_CONFIG_##src_dev##_ADDR_INC( \ + DMA_CHANNEL_CONFIG(node, dir)), \ + .dst_addr_increment = STM32_DMA_CONFIG_##dest_dev##_ADDR_INC( \ + DMA_CHANNEL_CONFIG(node, dir)), + +#define XSPI_DMA_CHANNEL(node, dir, DIR, src, dest) \ + .dma_##dir = { \ + COND_CODE_1(DT_DMAS_HAS_NAME(node, dir), \ + (XSPI_DMA_CHANNEL_INIT(node, dir, DIR, src, dest)), \ + (NULL)) \ + }, +#else +#define XSPI_DMA_CHANNEL(node, dir, DIR, src, dest) +#endif /* CONFIG_USE_STM32_HAL_DMA */ + +#define XSPI_FLASH_MODULE(drv_id, flash_id) \ + (DT_DRV_INST(drv_id), xspi_nor_flash_##flash_id) + +#define DT_WRITEOC_PROP_OR(inst, default_value) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, writeoc), \ + (_CONCAT(SPI_NOR_CMD_, DT_STRING_TOKEN(DT_DRV_INST(inst), writeoc))), \ + ((default_value))) + +#define DT_QER_PROP_OR(inst, default_value) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, quad_enable_requirements), \ + (_CONCAT(JESD216_DW15_QER_VAL_, \ + DT_STRING_TOKEN(DT_DRV_INST(inst), quad_enable_requirements))), \ + ((default_value))) + +static void flash_stm32_xspi_irq_config_func(const struct device *dev); + +static const struct stm32_pclken pclken[] = STM32_DT_CLOCKS(STM32_XSPI_NODE); + +PINCTRL_DT_DEFINE(STM32_XSPI_NODE); + +static const struct flash_stm32_xspi_config flash_stm32_xspi_cfg = { + .pclken = pclken, + .pclk_len = DT_NUM_CLOCKS(STM32_XSPI_NODE), + .irq_config = flash_stm32_xspi_irq_config_func, + .flash_size = DT_INST_REG_ADDR_BY_IDX(0, 1), + .max_frequency = DT_INST_PROP(0, ospi_max_frequency), + .data_mode = DT_INST_PROP(0, spi_bus_width), /* SPI or OPI */ + .data_rate = DT_INST_PROP(0, data_rate), /* DTR or STR */ + .pcfg = PINCTRL_DT_DEV_CONFIG_GET(STM32_XSPI_NODE), +#if STM32_XSPI_RESET_GPIO + .reset = GPIO_DT_SPEC_INST_GET(0, reset_gpios), +#endif /* STM32_XSPI_RESET_GPIO */ +#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_ospi_nor), sfdp_bfp) + .sfdp_bfp = DT_INST_PROP(0, sfdp_bfp), +#endif /* sfdp_bfp */ +}; + +static struct flash_stm32_xspi_data flash_stm32_xspi_dev_data = { + .hxspi = { + .Instance = (XSPI_TypeDef *)DT_REG_ADDR(STM32_XSPI_NODE), + .Init = { + .FifoThresholdByte = STM32_XSPI_FIFO_THRESHOLD, + .SampleShifting = (DT_PROP(STM32_XSPI_NODE, ssht_enable) + ? HAL_XSPI_SAMPLE_SHIFT_HALFCYCLE + : HAL_XSPI_SAMPLE_SHIFT_NONE), + .ChipSelectHighTimeCycle = 1, + .ClockMode = HAL_XSPI_CLOCK_MODE_0, + .ChipSelectBoundary = 0, + .MemoryMode = HAL_XSPI_SINGLE_MEM, +#if defined(HAL_XSPIM_IOPORT_1) || defined(HAL_XSPIM_IOPORT_2) + .MemorySelect = ((DT_INST_PROP(0, ncs_line) == 1) + ? HAL_XSPI_CSSEL_NCS1 + : HAL_XSPI_CSSEL_NCS2), +#endif + .FreeRunningClock = HAL_XSPI_FREERUNCLK_DISABLE, +#if defined(OCTOSPI_DCR4_REFRESH) + .Refresh = 0, +#endif /* OCTOSPI_DCR4_REFRESH */ + }, + }, + .qer_type = DT_QER_PROP_OR(0, JESD216_DW15_QER_VAL_S1B6), + .write_opcode = DT_WRITEOC_PROP_OR(0, SPI_NOR_WRITEOC_NONE), + .page_size = SPI_NOR_PAGE_SIZE, /* by default, to be updated by sfdp */ +#if DT_NODE_HAS_PROP(DT_INST(0, st_stm32_ospi_nor), jedec_id) + .jedec_id = DT_INST_PROP(0, jedec_id), +#endif /* jedec_id */ + XSPI_DMA_CHANNEL(STM32_XSPI_NODE, tx, TX, MEMORY, PERIPHERAL) + XSPI_DMA_CHANNEL(STM32_XSPI_NODE, rx, RX, PERIPHERAL, MEMORY) +}; + +static void flash_stm32_xspi_irq_config_func(const struct device *dev) +{ + IRQ_CONNECT(DT_IRQN(STM32_XSPI_NODE), DT_IRQ(STM32_XSPI_NODE, priority), + flash_stm32_xspi_isr, DEVICE_DT_INST_GET(0), 0); + irq_enable(DT_IRQN(STM32_XSPI_NODE)); +} + +DEVICE_DT_INST_DEFINE(0, &flash_stm32_xspi_init, NULL, + &flash_stm32_xspi_dev_data, &flash_stm32_xspi_cfg, + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &flash_stm32_xspi_driver_api); diff --git a/drivers/flash/flash_stm32_xspi.h b/drivers/flash/flash_stm32_xspi.h new file mode 100644 index 0000000000000..316efdbcd8788 --- /dev/null +++ b/drivers/flash/flash_stm32_xspi.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_FLASH_XSPI_STM32_H_ +#define ZEPHYR_DRIVERS_FLASH_XSPI_STM32_H_ + +/* Macro to check if any xspi device has a domain clock or more */ +#define STM32_XSPI_DOMAIN_CLOCK_INST_SUPPORT(inst) \ + DT_CLOCKS_HAS_IDX(DT_INST_PARENT(inst), 1) || +#define STM32_XSPI_INST_DEV_DOMAIN_CLOCK_SUPPORT \ + (DT_INST_FOREACH_STATUS_OKAY(STM32_XSPI_DOMAIN_CLOCK_INST_SUPPORT) 0) + +/* This symbol takes the value 1 if device instance has a domain clock in its dts */ +#if STM32_XSPI_INST_DEV_DOMAIN_CLOCK_SUPPORT +#define STM32_XSPI_DOMAIN_CLOCK_SUPPORT 1 +#else +#define STM32_XSPI_DOMAIN_CLOCK_SUPPORT 0 +#endif + +#define STM32_XSPI_FIFO_THRESHOLD 4U + +/* Valid range is [0, 255] */ +#define STM32_XSPI_CLOCK_PRESCALER_MIN 0U +#define STM32_XSPI_CLOCK_PRESCALER_MAX 255U +#define STM32_XSPI_CLOCK_COMPUTE(bus_freq, prescaler) ((bus_freq) / ((prescaler) + 1U)) + +/* Max Time value during reset or erase operation */ +#define STM32_XSPI_RESET_MAX_TIME 100U +#define STM32_XSPI_BULK_ERASE_MAX_TIME 460000U +#define STM32_XSPI_SECTOR_ERASE_MAX_TIME 1000U +#define STM32_XSPI_SUBSECTOR_4K_ERASE_MAX_TIME 400U +#define STM32_XSPI_WRITE_REG_MAX_TIME 40U + +/* used as default value for DTS writeoc */ +#define SPI_NOR_WRITEOC_NONE 0xFF + +#if STM32_XSPI_USE_DMA +/* Lookup table to set dma priority from the DTS */ +static const uint32_t table_priority[] = { + DMA_LOW_PRIORITY_LOW_WEIGHT, + DMA_LOW_PRIORITY_MID_WEIGHT, + DMA_LOW_PRIORITY_HIGH_WEIGHT, + DMA_HIGH_PRIORITY, +}; + +/* Lookup table to set dma channel direction from the DTS */ +static const uint32_t table_direction[] = { + DMA_MEMORY_TO_MEMORY, + DMA_MEMORY_TO_PERIPH, + DMA_PERIPH_TO_MEMORY, +}; + +struct stream { + DMA_TypeDef *reg; + const struct device *dev; + uint32_t channel; + struct dma_config cfg; + uint8_t priority; + bool src_addr_increment; + bool dst_addr_increment; +}; +#endif /* STM32_XSPI_USE_DMA */ + +typedef void (*irq_config_func_t)(const struct device *dev); + +struct flash_stm32_xspi_config { + const struct stm32_pclken *pclken; + size_t pclk_len; + irq_config_func_t irq_config; + size_t flash_size; + uint32_t max_frequency; + int data_mode; /* SPI or QSPI or OSPI */ + int data_rate; /* DTR or STR */ + const struct pinctrl_dev_config *pcfg; +#if STM32_XSPI_RESET_GPIO + const struct gpio_dt_spec reset; +#endif /* STM32_XSPI_RESET_GPIO */ +}; + +struct flash_stm32_xspi_data { + /* XSPI handle is modifiable ; so part of data struct */ + XSPI_HandleTypeDef hxspi; + struct k_sem sem; + struct k_sem sync; +#if defined(CONFIG_FLASH_PAGE_LAYOUT) + struct flash_pages_layout layout; +#endif + struct jesd216_erase_type erase_types[JESD216_NUM_ERASE_TYPES]; + /* Number of bytes per page */ + uint16_t page_size; + /* Address width in bytes */ + uint8_t address_width; + /* Read operation dummy cycles */ + uint8_t read_dummy; + uint32_t read_opcode; + uint32_t write_opcode; + enum jesd216_mode_type read_mode; + enum jesd216_dw15_qer_type qer_type; +#if defined(CONFIG_FLASH_JESD216_API) + /* Table to hold the jedec Read ID given by the octoFlash const */ + uint8_t jedec_id[JESD216_READ_ID_LEN]; +#endif /* CONFIG_FLASH_JESD216_API */ + int cmd_status; +#if STM32_XSPI_USE_DMA + struct stream dma_tx; + struct stream dma_rx; +#endif /* STM32_XSPI_USE_DMA */ +}; + +#endif /* ZEPHYR_DRIVERS_FLASH_XSPI_STM32_H_ */ diff --git a/drivers/flash/flash_stm32h7x.c b/drivers/flash/flash_stm32h7x.c index 271bb413194cd..8896fa7433fd6 100644 --- a/drivers/flash/flash_stm32h7x.c +++ b/drivers/flash/flash_stm32h7x.c @@ -14,8 +14,13 @@ #include #include #include +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#include +#include +#else #include #include +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ #include "flash_stm32.h" #include "stm32_hsem.h" @@ -117,14 +122,41 @@ static int flash_stm32_check_status(const struct device *dev) * ECC errors. Corrected data is returned for single ECC * errors, so in this case we just log a warning. */ - uint32_t const error_bank1 = (FLASH_FLAG_ALL_ERRORS_BANK1 - & ~FLASH_FLAG_SNECCERR_BANK1); #ifdef DUAL_BANK uint32_t const error_bank2 = (FLASH_FLAG_ALL_ERRORS_BANK2 & ~FLASH_FLAG_SNECCERR_BANK2); #endif uint32_t sr; +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) + uint32_t const error_bank = (FLASH_FLAG_ECC_ERRORS + & ~FLASH_FLAG_SNECCERR + & ~FLASH_FLAG_DBECCERR); + + + /* Read the Interrupt status flags. */ + sr = regs->ISR; + if (sr & (FLASH_FLAG_SNECCERR)) { + uint32_t word = regs->ECCSFADDR & FLASH_ECCSFADDR_SEC_FADD; + + LOG_WRN("Bank%d ECC error at 0x%08x", 1, + word * 4 * FLASH_NB_32BITWORD_IN_FLASHWORD); + } + + if (sr & (FLASH_FLAG_DBECCERR)) { + uint32_t word = regs->ECCDFADDR & FLASH_ECCDFADDR_DED_FADD; + + LOG_WRN("Bank%d ECC error at 0x%08x", 1, + word * 4 * FLASH_NB_32BITWORD_IN_FLASHWORD); + } + + /* Clear the ECC flags (including FA) */ + regs->ICR = FLASH_FLAG_ECC_ERRORS; + if (sr & error_bank) { +#else + uint32_t const error_bank1 = (FLASH_FLAG_ALL_ERRORS_BANK1 + & ~FLASH_FLAG_SNECCERR_BANK1); + /* Read the status flags. */ sr = regs->SR1; if (sr & (FLASH_FLAG_SNECCERR_BANK1|FLASH_FLAG_DBECCERR_BANK1)) { @@ -135,7 +167,9 @@ static int flash_stm32_check_status(const struct device *dev) } /* Clear the flags (including FA1R) */ regs->CCR1 = FLASH_FLAG_ALL_BANK1; + if (sr & error_bank1) { +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ LOG_ERR("Status Bank%d: 0x%08x", 1, sr); return -EIO; } diff --git a/drivers/flash/flash_stm32l5x.c b/drivers/flash/flash_stm32l5x.c index 59b649731e948..49e4259969f23 100644 --- a/drivers/flash/flash_stm32l5x.c +++ b/drivers/flash/flash_stm32l5x.c @@ -367,10 +367,16 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, } if (icache_enabled) { + int rc2; + /* Since i-cache was disabled, this would start the * invalidation procedure, so wait for completion. */ - rc = icache_wait_for_invalidate_complete(); + rc2 = icache_wait_for_invalidate_complete(); + + if (!rc) { + rc = rc2; + } /* I-cache should be enabled only after the * invalidation is complete. diff --git a/drivers/flash/flash_stm32wbax.c b/drivers/flash/flash_stm32wbax.c index db158f71a9a27..8660d46c26500 100644 --- a/drivers/flash/flash_stm32wbax.c +++ b/drivers/flash/flash_stm32wbax.c @@ -262,10 +262,16 @@ int flash_stm32_write_range(const struct device *dev, unsigned int offset, } if (icache_enabled) { + int rc2; + /* Since i-cache was disabled, this would start the * invalidation procedure, so wait for completion. */ - rc = icache_wait_for_invalidate_complete(); + rc2 = icache_wait_for_invalidate_complete(); + + if (!rc) { + rc = rc2; + } /* I-cache should be enabled only after the * invalidation is complete. diff --git a/drivers/flash/flash_util.c b/drivers/flash/flash_util.c new file mode 100644 index 0000000000000..cbaaa2049097c --- /dev/null +++ b/drivers/flash/flash_util.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#include + +#include +#include +#include + +LOG_MODULE_REGISTER(flash, CONFIG_FLASH_LOG_LEVEL); + +int z_impl_flash_fill(const struct device *dev, uint8_t val, off_t offset, + size_t size) +{ + uint8_t filler[CONFIG_FLASH_FILL_BUFFER_SIZE]; + const struct flash_driver_api *api = + (const struct flash_driver_api *)dev->api; + const struct flash_parameters *fparams = api->get_parameters(dev); + int rc = 0; + size_t stored = 0; + + if (sizeof(filler) < fparams->write_block_size) { + LOG_ERR("Size of CONFIG_FLASH_FILL_BUFFER_SIZE"); + return -EINVAL; + } + /* The flash_write will, probably, check write alignment but this + * is too late, as we write datain chunks; data alignment may be + * broken by the size of the last chunk, that is why the check + * happens here too. + * Note that we have no way to check whether offset and size are + * are correct, as such info is only available at the level of + * a driver, so only basic check on offset. + */ + if (offset < 0) { + LOG_ERR("Negative offset not allowed\n"); + return -EINVAL; + } + if ((size | (size_t)offset) & (fparams->write_block_size - 1)) { + LOG_ERR("Incorrect size or offset alignment, expected %zx\n", + fparams->write_block_size); + return -EINVAL; + } + + memset(filler, val, sizeof(filler)); + + while (stored < size) { + size_t chunk = MIN(sizeof(filler), size); + + rc = api->write(dev, offset + stored, filler, chunk); + if (rc < 0) { + LOG_DBG("Fill to dev %p failed at offset 0x%zx\n", + dev, (size_t)offset + stored); + break; + } + stored += chunk; + } + return rc; +} + +int z_impl_flash_flatten(const struct device *dev, off_t offset, size_t size) +{ + const struct flash_driver_api *api = + (const struct flash_driver_api *)dev->api; + __maybe_unused const struct flash_parameters *params = api->get_parameters(dev); + +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) + if ((flash_params_get_erase_cap(params) & FLASH_ERASE_C_EXPLICIT) && + api->erase != NULL) { + return api->erase(dev, offset, size); + } +#endif + +#if IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + return flash_fill(dev, params->erase_value, offset, size); +#else + return -ENOSYS; +#endif +} diff --git a/drivers/flash/nrf_qspi_nor.c b/drivers/flash/nrf_qspi_nor.c index b3a6fbb2ec1ff..81ccf123ce90d 100644 --- a/drivers/flash/nrf_qspi_nor.c +++ b/drivers/flash/nrf_qspi_nor.c @@ -1366,7 +1366,7 @@ void z_vrfy_nrf_qspi_nor_xip_enable(const struct device *dev, bool enable) z_impl_nrf_qspi_nor_xip_enable(dev, enable); } -#include +#include #endif /* CONFIG_USERSPACE */ static struct qspi_nor_data qspi_nor_dev_data = { diff --git a/drivers/flash/soc_flash_nrf.c b/drivers/flash/soc_flash_nrf.c index cc840309264e6..de9cfd423450d 100644 --- a/drivers/flash/soc_flash_nrf.c +++ b/drivers/flash/soc_flash_nrf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2023 Nordic Semiconductor ASA + * Copyright (c) 2017-2024 Nordic Semiconductor ASA * Copyright (c) 2016 Linaro Limited * Copyright (c) 2016 Intel Corporation * diff --git a/drivers/flash/soc_flash_nrf_mram.c b/drivers/flash/soc_flash_nrf_mram.c index 9b33ee05d6f6c..5d8215f7af30b 100644 --- a/drivers/flash/soc_flash_nrf_mram.c +++ b/drivers/flash/soc_flash_nrf_mram.c @@ -142,6 +142,9 @@ static const struct flash_parameters *nrf_mram_get_parameters(const struct devic static const struct flash_parameters parameters = { .write_block_size = WRITE_BLOCK_SIZE, .erase_value = ERASE_VALUE, + .caps = { + .no_explicit_erase = true, + }, }; return ¶meters; diff --git a/drivers/flash/soc_flash_nrf_rram.c b/drivers/flash/soc_flash_nrf_rram.c index b8ab3afa8feb2..35a6c98862c69 100644 --- a/drivers/flash/soc_flash_nrf_rram.c +++ b/drivers/flash/soc_flash_nrf_rram.c @@ -41,7 +41,11 @@ LOG_MODULE_REGISTER(flash_nrf_rram, CONFIG_FLASH_LOG_LEVEL); #define RRAM DT_INST(0, soc_nv_flash) +#if defined(CONFIG_SOC_SERIES_BSIM_NRFXX) +#define RRAM_START NRF_RRAM_BASE_ADDR +#else #define RRAM_START DT_REG_ADDR(RRAM) +#endif #define RRAM_SIZE DT_REG_SIZE(RRAM) #define PAGE_SIZE DT_PROP(RRAM, erase_block_size) @@ -305,6 +309,9 @@ static const struct flash_parameters *nrf_rram_get_parameters(const struct devic static const struct flash_parameters parameters = { .write_block_size = WRITE_LINE_SIZE, .erase_value = ERASE_VALUE, + .caps = { + .no_explicit_erase = true, + }, }; return ¶meters; diff --git a/drivers/flash/soc_flash_numaker_rmc.c b/drivers/flash/soc_flash_numaker_rmc.c index 7e7d81f348b8c..4a6b4ff6b5f53 100644 --- a/drivers/flash/soc_flash_numaker_rmc.c +++ b/drivers/flash/soc_flash_numaker_rmc.c @@ -29,6 +29,9 @@ struct flash_numaker_data { static const struct flash_parameters flash_numaker_parameters = { .write_block_size = SOC_NV_FLASH_WRITE_BLOCK_SIZE, .erase_value = 0xff, + .caps = { + .no_explicit_erase = true, + }, }; /* Validate offset and length */ diff --git a/drivers/flash/spi_nor.c b/drivers/flash/spi_nor.c index ccf492f0255c3..36d7a664f70c2 100644 --- a/drivers/flash/spi_nor.c +++ b/drivers/flash/spi_nor.c @@ -155,7 +155,6 @@ struct spi_nor_config { bool dpd_exist:1; bool dpd_wakeup_sequence_exist:1; bool mxicy_mx25r_power_mode_exist:1; - bool enter_4byte_addr_exist:1; bool reset_gpios_exist:1; bool requires_ulbpr_exist:1; bool wp_gpios_exist:1; @@ -516,13 +515,14 @@ static int enter_dpd(const struct device *const dev) static int exit_dpd(const struct device *const dev) { int ret = 0; +#if ANY_INST_HAS_DPD const struct spi_nor_config *cfg = dev->config; if (cfg->dpd_exist) { delay_until_exit_dpd_ok(dev); -#if ANY_INST_HAS_DPD_WAKEUP_SEQUENCE if (cfg->dpd_wakeup_sequence_exist) { +#if ANY_INST_HAS_DPD_WAKEUP_SEQUENCE /* Assert CSn and wait for tCRDP. * * Unfortunately the SPI API doesn't allow us to @@ -535,6 +535,7 @@ static int exit_dpd(const struct device *const dev) /* Deassert CSn and wait for tRDP */ k_sleep(K_MSEC(cfg->t_rdp_ms)); +#endif /* ANY_INST_HAS_DPD_WAKEUP_SEQUENCE */ } else { ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_RDPD); @@ -546,8 +547,8 @@ static int exit_dpd(const struct device *const dev) } #endif /* T_EXIT_DPD */ } -#endif /* DPD_WAKEUP_SEQUENCE */ } +#endif /* ANY_INST_HAS_DPD */ return ret; } @@ -625,13 +626,15 @@ static int spi_nor_wrsr(const struct device *dev, { int ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); - if (ret == 0) { - ret = spi_nor_access(dev, SPI_NOR_CMD_WRSR, NOR_ACCESS_WRITE, 0, &sr, - sizeof(sr)); - spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); + if (ret != 0) { + return ret; } - - return ret; + ret = spi_nor_access(dev, SPI_NOR_CMD_WRSR, NOR_ACCESS_WRITE, 0, &sr, + sizeof(sr)); + if (ret != 0) { + return ret; + } + return spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); } #if ANY_INST_HAS_MXICY_MX25R_POWER_MODE @@ -693,18 +696,23 @@ static int mxicy_wrcr(const struct device *dev, } ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); + if (ret != 0) { + return ret; + } - if (ret == 0) { - uint8_t data[] = { - sr, - cr & 0xFF, /* Configuration register 1 */ - cr >> 8 /* Configuration register 2 */ - }; - - ret = spi_nor_access(dev, SPI_NOR_CMD_WRSR, NOR_ACCESS_WRITE, 0, - data, sizeof(data)); - spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); + uint8_t data[] = { + sr, + cr & 0xFF, /* Configuration register 1 */ + cr >> 8 /* Configuration register 2 */ + }; + + ret = spi_nor_access(dev, SPI_NOR_CMD_WRSR, NOR_ACCESS_WRITE, 0, + data, sizeof(data)); + if (ret != 0) { + return ret; } + + ret = spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); } return ret; @@ -852,7 +860,10 @@ static int spi_nor_write(const struct device *dev, off_t addr, src = (const uint8_t *)src + to_write; addr += to_write; - spi_nor_wait_until_ready(dev, WAIT_READY_WRITE); + ret = spi_nor_wait_until_ready(dev, WAIT_READY_WRITE); + if (ret != 0) { + break; + } } } @@ -890,11 +901,14 @@ static int spi_nor_erase(const struct device *dev, off_t addr, size_t size) ret = spi_nor_write_protection_set(dev, false); while ((size > 0) && (ret == 0)) { - spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); + ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); + if (ret) { + break; + } if (size == flash_size) { /* chip erase */ - spi_nor_cmd_write(dev, SPI_NOR_CMD_CE); + ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_CE); size -= flash_size; } else { const struct jesd216_erase_type *erase_types = @@ -914,7 +928,7 @@ static int spi_nor_erase(const struct device *dev, off_t addr, size_t size) } } if (bet != NULL) { - spi_nor_cmd_addr_write(dev, bet->cmd, addr, NULL, 0); + ret = spi_nor_cmd_addr_write(dev, bet->cmd, addr, NULL, 0); addr += BIT(bet->exp); size -= BIT(bet->exp); } else { @@ -923,18 +937,11 @@ static int spi_nor_erase(const struct device *dev, off_t addr, size_t size) ret = -EINVAL; } } + if (ret != 0) { + break; + } -#ifdef __XCC__ - /* - * FIXME: remove this hack once XCC is fixed. - * - * Without this volatile return value, XCC would segfault - * compiling this file complaining about failure in CGPREP - * phase. - */ - volatile int xcc_ret = -#endif - spi_nor_wait_until_ready(dev, WAIT_READY_ERASE); + ret = spi_nor_wait_until_ready(dev, WAIT_READY_ERASE); } int ret2 = spi_nor_write_protection_set(dev, true); @@ -1034,10 +1041,10 @@ static int spi_nor_read_jedec_id(const struct device *dev, static int spi_nor_set_address_mode(const struct device *dev, uint8_t enter_4byte_addr) { - const struct spi_nor_config *cfg = dev->config; - int ret = -ENOSYS; + int ret = 0; + + LOG_DBG("Checking enter-4byte-addr %02x", enter_4byte_addr); - if (cfg->enter_4byte_addr_exist) { /* Do nothing if not provided (either no bits or all bits * set). */ @@ -1046,8 +1053,6 @@ static int spi_nor_set_address_mode(const struct device *dev, return 0; } - LOG_DBG("Checking enter-4byte-addr %02x", enter_4byte_addr); - /* This currently only supports command 0xB7 (Enter 4-Byte * Address Mode), with or without preceding WREN. */ @@ -1061,18 +1066,18 @@ static int spi_nor_set_address_mode(const struct device *dev, /* Enter after WREN. */ ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_WREN); } + if (ret == 0) { ret = spi_nor_cmd_write(dev, SPI_NOR_CMD_4BA); - } - if (ret == 0) { - struct spi_nor_data *data = dev->data; + if (ret == 0) { + struct spi_nor_data *data = dev->data; - data->flag_access_32bit = true; + data->flag_access_32bit = true; + } } release_device(dev); - } return ret; } @@ -1324,9 +1329,13 @@ static int spi_nor_configure(const struct device *dev) rc = spi_nor_rdsr(dev); if (rc > 0 && (rc & SPI_NOR_WIP_BIT)) { LOG_WRN("Waiting until flash is ready"); - spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); + rc = spi_nor_wait_until_ready(dev, WAIT_READY_REGISTER); } release_device(dev); + if (rc < 0) { + LOG_ERR("Failed to wait until flash is ready (%d)", rc); + return -ENODEV; + } /* now the spi bus is configured, we can verify SPI * connectivity by reading the JEDEC ID. @@ -1414,11 +1423,6 @@ static int spi_nor_configure(const struct device *dev) } #endif /* ANY_INST_HAS_MXICY_MX25R_POWER_MODE */ - if (IS_ENABLED(CONFIG_SPI_NOR_IDLE_IN_DPD) - && (enter_dpd(dev) != 0)) { - return -ENODEV; - } - return 0; } @@ -1660,7 +1664,6 @@ static const struct flash_driver_api spi_nor_api = { .dpd_exist = DT_INST_PROP(idx, has_dpd), \ .dpd_wakeup_sequence_exist = DT_INST_NODE_HAS_PROP(idx, dpd_wakeup_sequence), \ .mxicy_mx25r_power_mode_exist = DT_INST_NODE_HAS_PROP(idx, mxicy_mx25r_power_mode), \ - .enter_4byte_addr_exist = DT_INST_NODE_HAS_PROP(idx, enter_4byte_addr), \ .reset_gpios_exist = DT_INST_NODE_HAS_PROP(idx, reset_gpios), \ .requires_ulbpr_exist = DT_INST_PROP(idx, requires_ulbpr), \ .wp_gpios_exist = DT_INST_NODE_HAS_PROP(idx, wp_gpios), \ diff --git a/drivers/fpga/fpga_shell.c b/drivers/fpga/fpga_shell.c index af1a28eb8e115..4afeba42ef97c 100644 --- a/drivers/fpga/fpga_shell.c +++ b/drivers/fpga/fpga_shell.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include diff --git a/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c b/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c index 2382fcad77b40..538d93f84b6d3 100644 --- a/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c +++ b/drivers/fuel_gauge/emul_fuel_gauge_syscall_handlers.c @@ -14,7 +14,7 @@ static inline int z_vrfy_emul_fuel_gauge_is_battery_cutoff(const struct emul *ta return z_impl_emul_fuel_gauge_is_battery_cutoff(target, cutoff); } -#include +#include static inline int z_vrfy_emul_fuel_gauge_set_battery_charging(const struct emul *target, uint32_t uV, int uA) @@ -22,4 +22,4 @@ static inline int z_vrfy_emul_fuel_gauge_set_battery_charging(const struct emul return z_impl_emul_fuel_gauge_set_battery_charging(target, uV, uA); } -#include +#include diff --git a/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c b/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c index 312564c35a62f..75b93d3a53129 100644 --- a/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c +++ b/drivers/fuel_gauge/fuel_gauge_syscall_handlers.c @@ -24,7 +24,7 @@ static inline int z_vrfy_fuel_gauge_get_prop(const struct device *dev, fuel_gaug return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_get_props(const struct device *dev, fuel_gauge_prop_t *props, union fuel_gauge_prop_val *vals, size_t len) @@ -44,7 +44,7 @@ static inline int z_vrfy_fuel_gauge_get_props(const struct device *dev, fuel_gau return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev, fuel_gauge_prop_t prop, union fuel_gauge_prop_val val) @@ -56,7 +56,7 @@ static inline int z_vrfy_fuel_gauge_set_prop(const struct device *dev, fuel_gaug return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_set_props(const struct device *dev, fuel_gauge_prop_t *props, union fuel_gauge_prop_val *vals, size_t len) @@ -77,7 +77,7 @@ static inline int z_vrfy_fuel_gauge_set_props(const struct device *dev, fuel_gau return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev, fuel_gauge_prop_t prop, void *dst, @@ -92,7 +92,7 @@ static inline int z_vrfy_fuel_gauge_get_buffer_prop(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_fuel_gauge_battery_cutoff(const struct device *dev) { @@ -101,4 +101,4 @@ static inline int z_vrfy_fuel_gauge_battery_cutoff(const struct device *dev) return z_impl_fuel_gauge_battery_cutoff(dev); } -#include +#include diff --git a/drivers/gnss/CMakeLists.txt b/drivers/gnss/CMakeLists.txt index 77631bcb9710a..05192ca5400eb 100644 --- a/drivers/gnss/CMakeLists.txt +++ b/drivers/gnss/CMakeLists.txt @@ -4,6 +4,7 @@ zephyr_library() zephyr_library_sources(gnss_publish.c) zephyr_library_sources_ifdef(CONFIG_GNSS_DUMP gnss_dump.c) +zephyr_library_sources_ifdef(CONFIG_GNSS_EMUL gnss_emul.c) zephyr_library_sources_ifdef(CONFIG_GNSS_PARSE gnss_parse.c) zephyr_library_sources_ifdef(CONFIG_GNSS_NMEA0183 gnss_nmea0183.c) zephyr_library_sources_ifdef(CONFIG_GNSS_NMEA0183_MATCH gnss_nmea0183_match.c) diff --git a/drivers/gnss/Kconfig b/drivers/gnss/Kconfig index 98602d4194997..94aaf7a02ba84 100644 --- a/drivers/gnss/Kconfig +++ b/drivers/gnss/Kconfig @@ -70,6 +70,7 @@ module = GNSS module-str = gnss source "subsys/logging/Kconfig.template.log_config" +rsource "Kconfig.emul" rsource "Kconfig.generic" rsource "Kconfig.quectel_lcx6g" rsource "Kconfig.u_blox_m10" diff --git a/drivers/gnss/Kconfig.emul b/drivers/gnss/Kconfig.emul new file mode 100644 index 0000000000000..9ae9a40647284 --- /dev/null +++ b/drivers/gnss/Kconfig.emul @@ -0,0 +1,10 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +config GNSS_EMUL + bool "Emulated GNSS driver" + default y + depends on DT_HAS_ZEPHYR_GNSS_EMUL_ENABLED + select TIMEOUT_64BIT + help + Enable emulated GNSS driver. diff --git a/drivers/gnss/gnss_emul.c b/drivers/gnss/gnss_emul.c new file mode 100644 index 0000000000000..37245341f036f --- /dev/null +++ b/drivers/gnss/gnss_emul.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#undef _POSIX_C_SOURCE +#define _POSIX_C_SOURCE 200809L /* Required for gmtime_r */ + +#include +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(gnss_emul, CONFIG_GNSS_LOG_LEVEL); + +#define DT_DRV_COMPAT zephyr_gnss_emul + +#define GNSS_EMUL_DEFAULT_FIX_INTERVAL_MS 1000 +#define GNSS_EMUL_MIN_FIX_INTERVAL_MS 100 +#define GNSS_EMUL_FIX_ACQUIRE_TIME_MS 5000 +#define GNSS_EMUL_DEFAULT_NAV_MODE GNSS_NAVIGATION_MODE_BALANCED_DYNAMICS +#define GNSS_EMUL_SUPPORTED_SYSTEMS_MASK 0xFF +#define GNSS_EMUL_SUPPORTED_SYSTEMS_COUNT 8 +#define GNSS_EMUL_DEFAULT_ENABLED_SYSTEMS_MASK GNSS_EMUL_SUPPORTED_SYSTEMS_MASK + +struct gnss_emul_data { + const struct device *dev; + struct k_work_delayable data_dwork; + struct k_sem lock; + int64_t resume_timestamp_ms; + int64_t fix_timestamp_ms; + uint32_t fix_interval_ms; + enum gnss_navigation_mode nav_mode; + gnss_systems_t enabled_systems; + struct gnss_data data; + +#ifdef CONFIG_GNSS_SATELLITES + struct gnss_satellite satellites[GNSS_EMUL_SUPPORTED_SYSTEMS_COUNT]; + uint8_t satellites_len; +#endif +}; + +static void gnss_emul_lock_sem(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + (void)k_sem_take(&data->lock, K_FOREVER); +} + +static void gnss_emul_unlock_sem(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + k_sem_give(&data->lock); +} + +static void gnss_emul_update_fix_timestamp(const struct device *dev, bool resuming) +{ + struct gnss_emul_data *data = dev->data; + int64_t uptime_ms; + + uptime_ms = k_uptime_get(); + data->fix_timestamp_ms = ((uptime_ms / data->fix_interval_ms) + 1) * data->fix_interval_ms; + + if (resuming) { + data->resume_timestamp_ms = data->fix_timestamp_ms; + } +} + +static bool gnss_emul_fix_is_acquired(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + int64_t time_since_resume; + + time_since_resume = data->fix_timestamp_ms - data->resume_timestamp_ms; + return time_since_resume >= GNSS_EMUL_FIX_ACQUIRE_TIME_MS; +} + +#ifdef CONFIG_PM_DEVICE +static void gnss_emul_clear_fix_timestamp(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->fix_timestamp_ms = 0; +} +#endif + +static void gnss_emul_schedule_work(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + k_work_schedule(&data->data_dwork, K_TIMEOUT_ABS_MS(data->fix_timestamp_ms)); +} + +static bool gnss_emul_cancel_work(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + struct k_work_sync sync; + + return k_work_cancel_delayable_sync(&data->data_dwork, &sync); +} + +static bool gnss_emul_is_resumed(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + return data->fix_timestamp_ms > 0; +} + +static void gnss_emul_lock(const struct device *dev) +{ + gnss_emul_lock_sem(dev); + gnss_emul_cancel_work(dev); +} + +static void gnss_emul_unlock(const struct device *dev) +{ + if (gnss_emul_is_resumed(dev)) { + gnss_emul_schedule_work(dev); + } + + gnss_emul_unlock_sem(dev); +} + +static int gnss_emul_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms) +{ + struct gnss_emul_data *data = dev->data; + + if (fix_interval_ms < GNSS_EMUL_MIN_FIX_INTERVAL_MS) { + return -EINVAL; + } + + data->fix_interval_ms = fix_interval_ms; + return 0; +} + +static int gnss_emul_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms) +{ + struct gnss_emul_data *data = dev->data; + + *fix_interval_ms = data->fix_interval_ms; + return 0; +} + +static int gnss_emul_set_navigation_mode(const struct device *dev, + enum gnss_navigation_mode mode) +{ + struct gnss_emul_data *data = dev->data; + + if (mode > GNSS_NAVIGATION_MODE_HIGH_DYNAMICS) { + return -EINVAL; + } + + data->nav_mode = mode; + return 0; +} + +static int gnss_emul_get_navigation_mode(const struct device *dev, + enum gnss_navigation_mode *mode) +{ + struct gnss_emul_data *data = dev->data; + + *mode = data->nav_mode; + return 0; +} + +static int gnss_emul_set_enabled_systems(const struct device *dev, gnss_systems_t systems) +{ + struct gnss_emul_data *data = dev->data; + + if (systems > GNSS_EMUL_SUPPORTED_SYSTEMS_MASK) { + return -EINVAL; + } + + data->enabled_systems = systems; + return 0; +} + +static int gnss_emul_get_enabled_systems(const struct device *dev, gnss_systems_t *systems) +{ + struct gnss_emul_data *data = dev->data; + + *systems = data->enabled_systems; + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static void gnss_emul_resume(const struct device *dev) +{ + gnss_emul_update_fix_timestamp(dev, true); +} + +static void gnss_emul_suspend(const struct device *dev) +{ + gnss_emul_clear_fix_timestamp(dev); +} + +static int gnss_emul_pm_action(const struct device *dev, enum pm_device_action action) +{ + int ret = 0; + + gnss_emul_lock(dev); + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + gnss_emul_suspend(dev); + break; + + case PM_DEVICE_ACTION_RESUME: + gnss_emul_resume(dev); + break; + + default: + ret = -ENOTSUP; + break; + } + + gnss_emul_unlock(dev); + return ret; +} +#endif + +static int gnss_emul_api_set_fix_rate(const struct device *dev, uint32_t fix_interval_ms) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_set_fix_rate(dev, fix_interval_ms); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_get_fix_rate(const struct device *dev, uint32_t *fix_interval_ms) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_get_fix_rate(dev, fix_interval_ms); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_set_navigation_mode(const struct device *dev, + enum gnss_navigation_mode mode) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_set_navigation_mode(dev, mode); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_get_navigation_mode(const struct device *dev, + enum gnss_navigation_mode *mode) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_get_navigation_mode(dev, mode); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_set_enabled_systems(const struct device *dev, gnss_systems_t systems) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_set_enabled_systems(dev, systems); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_get_enabled_systems(const struct device *dev, gnss_systems_t *systems) +{ + int ret = -ENODEV; + + gnss_emul_lock(dev); + + if (!gnss_emul_is_resumed(dev)) { + goto unlock_return; + } + + ret = gnss_emul_get_enabled_systems(dev, systems); + +unlock_return: + gnss_emul_unlock(dev); + return ret; +} + +static int gnss_emul_api_get_supported_systems(const struct device *dev, gnss_systems_t *systems) +{ + *systems = GNSS_EMUL_SUPPORTED_SYSTEMS_MASK; + return 0; +} + +static const struct gnss_driver_api api = { + .set_fix_rate = gnss_emul_api_set_fix_rate, + .get_fix_rate = gnss_emul_api_get_fix_rate, + .set_navigation_mode = gnss_emul_api_set_navigation_mode, + .get_navigation_mode = gnss_emul_api_get_navigation_mode, + .set_enabled_systems = gnss_emul_api_set_enabled_systems, + .get_enabled_systems = gnss_emul_api_get_enabled_systems, + .get_supported_systems = gnss_emul_api_get_supported_systems, +}; + +static void gnss_emul_clear_data(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + memset(&data->data, 0, sizeof(data->data)); +} + +static void gnss_emul_set_fix(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->data.info.satellites_cnt = 8; + data->data.info.hdop = 100; + data->data.info.fix_status = GNSS_FIX_STATUS_GNSS_FIX; + data->data.info.fix_quality = GNSS_FIX_QUALITY_GNSS_SPS; +} + +static void gnss_emul_set_utc(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + time_t timestamp; + struct tm datetime; + uint16_t millisecond; + + timestamp = (time_t)(data->fix_timestamp_ms / 1000); + gmtime_r(×tamp, &datetime); + + millisecond = (uint16_t)(data->fix_timestamp_ms % 1000) + + (uint16_t)(datetime.tm_sec * 1000); + + data->data.utc.hour = datetime.tm_hour; + data->data.utc.millisecond = millisecond; + data->data.utc.minute = datetime.tm_min; + data->data.utc.month = datetime.tm_mon + 1; + data->data.utc.century_year = datetime.tm_year % 100; +} + +static void gnss_emul_set_nav_data(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->data.nav_data.latitude = 10000000000; + data->data.nav_data.longitude = -10000000000; + data->data.nav_data.bearing = 3000; + data->data.nav_data.speed = 0; + data->data.nav_data.altitude = 20000; +} + +#ifdef CONFIG_GNSS_SATELLITES +static void gnss_emul_clear_satellites(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->satellites_len = 0; +} + +static bool gnss_emul_system_enabled(const struct device *dev, uint8_t system_bit) +{ + struct gnss_emul_data *data = dev->data; + + return BIT(system_bit) & data->enabled_systems; +} + +static void gnss_emul_add_satellite(const struct device *dev, uint8_t system_bit) +{ + struct gnss_emul_data *data = dev->data; + + /* Unique values synthesized from GNSS system */ + data->satellites[data->satellites_len].prn = system_bit; + data->satellites[data->satellites_len].snr = system_bit + 20; + data->satellites[data->satellites_len].elevation = system_bit + 40; + data->satellites[data->satellites_len].azimuth = system_bit + 60; + data->satellites[data->satellites_len].system = BIT(system_bit); + data->satellites[data->satellites_len].is_tracked = true; + data->satellites_len++; +} + +static void gnss_emul_set_satellites(const struct device *dev) +{ + gnss_emul_clear_satellites(dev); + + for (uint8_t i = 0; i < GNSS_EMUL_SUPPORTED_SYSTEMS_COUNT; i++) { + if (!gnss_emul_system_enabled(dev, i)) { + continue; + } + + gnss_emul_add_satellite(dev, i); + } +} +#endif + +static void gnss_emul_work_handler(struct k_work *work) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(work); + struct gnss_emul_data *data = CONTAINER_OF(dwork, struct gnss_emul_data, data_dwork); + const struct device *dev = data->dev; + + if (!gnss_emul_fix_is_acquired(dev)) { + gnss_emul_clear_data(dev); + } else { + gnss_emul_set_fix(dev); + gnss_emul_set_utc(dev); + gnss_emul_set_nav_data(dev); + } + + gnss_publish_data(dev, &data->data); + +#ifdef CONFIG_GNSS_SATELLITES + gnss_emul_set_satellites(dev); + gnss_publish_satellites(dev, data->satellites, data->satellites_len); +#endif + + gnss_emul_update_fix_timestamp(dev, false); + gnss_emul_schedule_work(dev); +} + +static void gnss_emul_init_data(const struct device *dev) +{ + struct gnss_emul_data *data = dev->data; + + data->dev = dev; + k_sem_init(&data->lock, 1, 1); + k_work_init_delayable(&data->data_dwork, gnss_emul_work_handler); +} + +static int gnss_emul_init(const struct device *dev) +{ + gnss_emul_init_data(dev); + + if (pm_device_is_powered(dev)) { + gnss_emul_update_fix_timestamp(dev, true); + gnss_emul_schedule_work(dev); + } else { + pm_device_init_off(dev); + } + + return pm_device_runtime_enable(dev); +} + +#define GNSS_EMUL_NAME(inst, name) _CONCAT(name, inst) + +#define GNSS_EMUL_DEVICE(inst) \ + static struct gnss_emul_data GNSS_EMUL_NAME(inst, data) = { \ + .fix_interval_ms = GNSS_EMUL_DEFAULT_FIX_INTERVAL_MS, \ + .nav_mode = GNSS_EMUL_DEFAULT_NAV_MODE, \ + .enabled_systems = GNSS_EMUL_DEFAULT_ENABLED_SYSTEMS_MASK, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, gnss_emul_pm_action); \ + \ + DEVICE_DT_INST_DEFINE( \ + inst, \ + gnss_emul_init, \ + PM_DEVICE_DT_INST_GET(inst), \ + &GNSS_EMUL_NAME(inst, data), \ + NULL, \ + POST_KERNEL, \ + CONFIG_GNSS_INIT_PRIORITY, \ + &api \ + ); + +DT_INST_FOREACH_STATUS_OKAY(GNSS_EMUL_DEVICE) diff --git a/drivers/gnss/gnss_luatos_air530z.c b/drivers/gnss/gnss_luatos_air530z.c index a24c8245ac329..0d26b8b71ac94 100644 --- a/drivers/gnss/gnss_luatos_air530z.c +++ b/drivers/gnss/gnss_luatos_air530z.c @@ -336,28 +336,28 @@ static int luatos_air530z_get_supported_systems(const struct device *dev, gnss_s return 0; } -static struct gnss_driver_api gnss_api = { +static const struct gnss_driver_api gnss_api = { .set_fix_rate = luatos_air530z_set_fix_rate, .set_enabled_systems = luatos_air530z_set_enabled_systems, .get_supported_systems = luatos_air530z_get_supported_systems, }; -#define LUATOS_AIR530Z(inst) \ - static struct gnss_luatos_air530z_config gnss_luatos_air530z_cfg_##inst = { \ - .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ - .on_off_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, on_off_gpios, { 0 }), \ - }; \ - \ - static struct gnss_luatos_air530z_data gnss_luatos_air530z_data_##inst = { \ - .chat_delimiter = {'\r', '\n'}, \ - .dynamic_separators_buf = {',', '*'}, \ - }; \ - \ - PM_DEVICE_DT_INST_DEFINE(inst, luatos_air530z_pm_action); \ - \ - DEVICE_DT_INST_DEFINE(inst, gnss_luatos_air530z_init, \ - PM_DEVICE_DT_INST_GET(inst), \ - &gnss_luatos_air530z_data_##inst, \ +#define LUATOS_AIR530Z(inst) \ + static const struct gnss_luatos_air530z_config gnss_luatos_air530z_cfg_##inst = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ + .on_off_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, on_off_gpios, { 0 }), \ + }; \ + \ + static struct gnss_luatos_air530z_data gnss_luatos_air530z_data_##inst = { \ + .chat_delimiter = {'\r', '\n'}, \ + .dynamic_separators_buf = {',', '*'}, \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, luatos_air530z_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, gnss_luatos_air530z_init, \ + PM_DEVICE_DT_INST_GET(inst), \ + &gnss_luatos_air530z_data_##inst, \ &gnss_luatos_air530z_cfg_##inst, \ POST_KERNEL, CONFIG_GNSS_INIT_PRIORITY, &gnss_api); diff --git a/drivers/gnss/gnss_nmea_generic.c b/drivers/gnss/gnss_nmea_generic.c index 2c92ce480ba4f..b42d08acfad31 100644 --- a/drivers/gnss/gnss_nmea_generic.c +++ b/drivers/gnss/gnss_nmea_generic.c @@ -81,7 +81,7 @@ static int gnss_nmea_generic_resume(const struct device *dev) return ret; } -static struct gnss_driver_api gnss_api = { +static const struct gnss_driver_api gnss_api = { }; static int gnss_nmea_generic_init_nmea0183_match(const struct device *dev) @@ -183,7 +183,7 @@ MODEM_CHAT_SCRIPT_EMPTY_DEFINE(gnss_nmea_generic_init_chat_script); #endif #define GNSS_NMEA_GENERIC(inst) \ - static struct gnss_nmea_generic_config gnss_nmea_generic_cfg_##inst = { \ + static const struct gnss_nmea_generic_config gnss_nmea_generic_cfg_##inst = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .init_chat_script = &_CONCAT(DT_DRV_COMPAT, _init_chat_script), \ }; \ diff --git a/drivers/gnss/gnss_quectel_lcx6g.c b/drivers/gnss/gnss_quectel_lcx6g.c index d3ac854ae9663..95d611cefc51b 100644 --- a/drivers/gnss/gnss_quectel_lcx6g.c +++ b/drivers/gnss/gnss_quectel_lcx6g.c @@ -59,13 +59,12 @@ struct quectel_lcx6g_data { uint8_t chat_delimiter[2]; uint8_t *chat_argv[32]; - /* Dynamic chat script */ - uint8_t dynamic_match_buf[32]; - uint8_t dynamic_separators_buf[2]; - uint8_t dynamic_request_buf[32]; - struct modem_chat_match dynamic_match; - struct modem_chat_script_chat dynamic_script_chat; - struct modem_chat_script dynamic_script; + /* Pair chat script */ + uint8_t pair_request_buf[32]; + uint8_t pair_match_buf[32]; + struct modem_chat_match pair_match; + struct modem_chat_script_chat pair_script_chat; + struct modem_chat_script pair_script; /* Allocation for responses from GNSS modem */ union { @@ -141,23 +140,29 @@ static int quectel_lcx6g_configure_pps(const struct device *dev) break; } - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR752,%u,%u", pps_mode, config->pps_pulse_width); if (ret < 0) { return ret; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + return ret; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,752,0"); if (ret < 0) { return ret; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + return ret; + } - return modem_chat_run_script(&data->chat, &data->dynamic_script); + return modem_chat_run_script(&data->chat, &data->pair_script); } static void quectel_lcx6g_lock(const struct device *dev) @@ -312,23 +317,29 @@ static int quectel_lcx6g_set_fix_rate(const struct device *dev, uint32_t fix_int quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR050,%u", fix_interval_ms); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,050,0"); if (ret < 0) { goto unlock_return; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + ret = modem_chat_run_script(&data->chat, &data->pair_script); if (ret < 0) { goto unlock_return; } @@ -362,20 +373,26 @@ static int quectel_lcx6g_get_fix_rate(const struct device *dev, uint32_t *fix_in quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR051"); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - strncpy(data->dynamic_match_buf, "$PAIR051,", sizeof(data->dynamic_match_buf)); - data->dynamic_match.match_size = sizeof("$PAIR051,") - 1; - data->dynamic_match.callback = quectel_lcx6g_get_fix_rate_callback; + strncpy(data->pair_match_buf, "$PAIR051,", sizeof(data->pair_match_buf)); + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); - data->dynamic_match.callback = NULL; + modem_chat_match_set_callback(&data->pair_match, quectel_lcx6g_get_fix_rate_callback); + ret = modem_chat_run_script(&data->chat, &data->pair_script); + modem_chat_match_set_callback(&data->pair_match, NULL); if (ret < 0) { goto unlock_return; } @@ -414,23 +431,29 @@ static int quectel_lcx6g_set_navigation_mode(const struct device *dev, quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR080,%u", navigation_mode); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,080,0"); if (ret < 0) { goto unlock_return; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + ret = modem_chat_run_script(&data->chat, &data->pair_script); if (ret < 0) { goto unlock_return; } @@ -440,8 +463,8 @@ static int quectel_lcx6g_set_navigation_mode(const struct device *dev, return ret; } -static void quectel_lcx6g_get_navigation_mode_callback(struct modem_chat *chat, char **argv, - uint16_t argc, void *user_data) +static void quectel_lcx6g_get_nav_mode_callback(struct modem_chat *chat, char **argv, + uint16_t argc, void *user_data) { struct quectel_lcx6g_data *data = user_data; int32_t tmp; @@ -481,20 +504,26 @@ static int quectel_lcx6g_get_navigation_mode(const struct device *dev, quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR081"); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - strncpy(data->dynamic_match_buf, "$PAIR081,", sizeof(data->dynamic_match_buf)); - data->dynamic_match.match_size = sizeof("$PAIR081,") - 1; - data->dynamic_match.callback = quectel_lcx6g_get_navigation_mode_callback; + strncpy(data->pair_match_buf, "$PAIR081,", sizeof(data->pair_match_buf)); + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); - data->dynamic_match.callback = NULL; + modem_chat_match_set_callback(&data->pair_match, quectel_lcx6g_get_nav_mode_callback); + ret = modem_chat_run_script(&data->chat, &data->pair_script); + modem_chat_match_set_callback(&data->pair_match, NULL); if (ret < 0) { goto unlock_return; } @@ -521,7 +550,7 @@ static int quectel_lcx6g_set_enabled_systems(const struct device *dev, gnss_syst quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR066,%u,%u,%u,%u,%u,0", (0 < (systems & GNSS_SYSTEM_GPS)), (0 < (systems & GNSS_SYSTEM_GLONASS)), @@ -532,38 +561,50 @@ static int quectel_lcx6g_set_enabled_systems(const struct device *dev, gnss_syst goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,066,0"); if (ret < 0) { goto unlock_return; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + ret = modem_chat_run_script(&data->chat, &data->pair_script); if (ret < 0) { goto unlock_return; } - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR410,%u", (0 < (systems & GNSS_SYSTEM_SBAS))); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - ret = gnss_nmea0183_snprintk(data->dynamic_match_buf, sizeof(data->dynamic_match_buf), + ret = gnss_nmea0183_snprintk(data->pair_match_buf, sizeof(data->pair_match_buf), "PAIR001,410,0"); if (ret < 0) { goto unlock_return; } - data->dynamic_match.match_size = ret; + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); + ret = modem_chat_run_script(&data->chat, &data->pair_script); if (ret < 0) { goto unlock_return; } @@ -614,38 +655,50 @@ static int quectel_lcx6g_get_enabled_systems(const struct device *dev, gnss_syst quectel_lcx6g_lock(dev); - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR067"); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - strncpy(data->dynamic_match_buf, "$PAIR067,", sizeof(data->dynamic_match_buf)); - data->dynamic_match.match_size = sizeof("$PAIR067,") - 1; - data->dynamic_match.callback = quectel_lcx6g_get_search_mode_callback; + strncpy(data->pair_match_buf, "$PAIR067,", sizeof(data->pair_match_buf)); + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); - data->dynamic_match.callback = NULL; + modem_chat_match_set_callback(&data->pair_match, quectel_lcx6g_get_search_mode_callback); + ret = modem_chat_run_script(&data->chat, &data->pair_script); + modem_chat_match_set_callback(&data->pair_match, NULL); if (ret < 0) { goto unlock_return; } - ret = gnss_nmea0183_snprintk(data->dynamic_request_buf, sizeof(data->dynamic_request_buf), + ret = gnss_nmea0183_snprintk(data->pair_request_buf, sizeof(data->pair_request_buf), "PAIR411"); if (ret < 0) { goto unlock_return; } - data->dynamic_script_chat.request_size = ret; + ret = modem_chat_script_chat_set_request(&data->pair_script_chat, data->pair_request_buf); + if (ret < 0) { + goto unlock_return; + } - strncpy(data->dynamic_match_buf, "$PAIR411,", sizeof(data->dynamic_match_buf)); - data->dynamic_match.match_size = sizeof("$PAIR411,") - 1; - data->dynamic_match.callback = quectel_lcx6g_get_sbas_status_callback; + strncpy(data->pair_match_buf, "$PAIR411,", sizeof(data->pair_match_buf)); + ret = modem_chat_match_set_match(&data->pair_match, data->pair_match_buf); + if (ret < 0) { + goto unlock_return; + } - ret = modem_chat_run_script(&data->chat, &data->dynamic_script); - data->dynamic_match.callback = NULL; + modem_chat_match_set_callback(&data->pair_match, quectel_lcx6g_get_sbas_status_callback); + ret = modem_chat_run_script(&data->chat, &data->pair_script); + modem_chat_match_set_callback(&data->pair_match, NULL); if (ret < 0) { goto unlock_return; } @@ -664,7 +717,7 @@ static int quectel_lcx6g_get_supported_systems(const struct device *dev, gnss_sy return 0; } -static struct gnss_driver_api gnss_api = { +static const struct gnss_driver_api gnss_api = { .set_fix_rate = quectel_lcx6g_set_fix_rate, .get_fix_rate = quectel_lcx6g_get_fix_rate, .set_navigation_mode = quectel_lcx6g_set_navigation_mode, @@ -726,28 +779,22 @@ static int quectel_lcx6g_init_chat(const struct device *dev) return modem_chat_init(&data->chat, &chat_config); } -static void quectel_lcx6g_init_dynamic_script(const struct device *dev) +static void quectel_lcx6g_init_pair_script(const struct device *dev) { struct quectel_lcx6g_data *data = dev->data; - data->dynamic_match.match = data->dynamic_match_buf; - data->dynamic_match.separators = data->dynamic_separators_buf; - data->dynamic_match.separators_size = sizeof(data->dynamic_separators_buf); - data->dynamic_match.wildcards = false; - data->dynamic_match.partial = false; - - data->dynamic_script_chat.request = data->dynamic_request_buf; - data->dynamic_script_chat.response_matches = &data->dynamic_match; - data->dynamic_script_chat.response_matches_size = 1; - data->dynamic_script_chat.timeout = 0; - - data->dynamic_script.name = "pair"; - data->dynamic_script.script_chats = &data->dynamic_script_chat; - data->dynamic_script.script_chats_size = 1; - data->dynamic_script.abort_matches = NULL; - data->dynamic_script.abort_matches_size = 0; - data->dynamic_script.callback = NULL; - data->dynamic_script.timeout = 10; + modem_chat_match_init(&data->pair_match); + modem_chat_match_set_separators(&data->pair_match, ",*"); + + modem_chat_script_chat_init(&data->pair_script_chat); + modem_chat_script_chat_set_response_matches(&data->pair_script_chat, + &data->pair_match, 1); + + modem_chat_script_init(&data->pair_script); + modem_chat_script_set_name(&data->pair_script, "pair"); + modem_chat_script_set_script_chats(&data->pair_script, &data->pair_script_chat, 1); + modem_chat_script_set_abort_matches(&data->pair_script, NULL, 0); + modem_chat_script_set_timeout(&data->pair_script, 10); } static int quectel_lcx6g_init(const struct device *dev) @@ -769,7 +816,7 @@ static int quectel_lcx6g_init(const struct device *dev) return ret; } - quectel_lcx6g_init_dynamic_script(dev); + quectel_lcx6g_init_pair_script(dev); quectel_lcx6g_pm_changed(dev); @@ -790,7 +837,7 @@ static int quectel_lcx6g_init(const struct device *dev) _CONCAT(_CONCAT(_CONCAT(name, _), DT_DRV_COMPAT), inst) #define LCX6G_DEVICE(inst) \ - static struct quectel_lcx6g_config LCX6G_INST_NAME(inst, config) = { \ + static const struct quectel_lcx6g_config LCX6G_INST_NAME(inst, config) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .pps_mode = DT_INST_STRING_UPPER_TOKEN(inst, pps_mode), \ .pps_pulse_width = DT_INST_PROP(inst, pps_pulse_width), \ @@ -798,7 +845,6 @@ static int quectel_lcx6g_init(const struct device *dev) \ static struct quectel_lcx6g_data LCX6G_INST_NAME(inst, data) = { \ .chat_delimiter = {'\r', '\n'}, \ - .dynamic_separators_buf = {',', '*'}, \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, quectel_lcx6g_pm_action); \ diff --git a/drivers/gnss/gnss_u_blox_m10.c b/drivers/gnss/gnss_u_blox_m10.c index a5bb8d1e07def..e5641ab634a93 100644 --- a/drivers/gnss/gnss_u_blox_m10.c +++ b/drivers/gnss/gnss_u_blox_m10.c @@ -933,7 +933,7 @@ static int ubx_m10_get_fix_rate(const struct device *dev, uint32_t *fix_interval return ret; } -static struct gnss_driver_api gnss_api = { +static const struct gnss_driver_api gnss_api = { .set_fix_rate = ubx_m10_set_fix_rate, .get_fix_rate = ubx_m10_get_fix_rate, .set_navigation_mode = ubx_m10_set_navigation_mode, @@ -1020,7 +1020,7 @@ static int ubx_m10_init(const struct device *dev) } #define UBX_M10(inst) \ - static struct ubx_m10_config ubx_m10_cfg_##inst = { \ + static const struct ubx_m10_config ubx_m10_cfg_##inst = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .uart_baudrate = DT_PROP(DT_DRV_INST(inst), uart_baudrate), \ }; \ diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 655de8340d79e..e150c8c8ea3b1 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library() # zephyr-keep-sorted-start zephyr_library_sources_ifdef(CONFIG_GPIO_AD559X gpio_ad559x.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_ADP5585 gpio_adp5585.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ADS114S0X gpio_ads114s0x.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ALTERA_PIO gpio_altera_pio.c) zephyr_library_sources_ifdef(CONFIG_GPIO_AMBIQ gpio_ambiq.c) @@ -31,12 +32,14 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_GECKO gpio_gecko.c) zephyr_library_sources_ifdef(CONFIG_GPIO_IMX gpio_imx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INFINEON_CAT1 gpio_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INTEL gpio_intel.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_IPROC gpio_iproc.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ITE_IT8XXX2 gpio_ite_it8xxx2.c) zephyr_library_sources_ifdef(CONFIG_GPIO_ITE_IT8XXX2_V2 gpio_ite_it8xxx2_v2.c) zephyr_library_sources_ifdef(CONFIG_GPIO_KSCAN_ITE_IT8XXX2 gpio_kscan_ite_it8xxx2.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LITEX gpio_litex.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LMP90XXX gpio_lmp90xxx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LPC11U6X gpio_lpc11u6x.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_MAX32 gpio_max32.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MCHP_MSS gpio_mchp_mss.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MCP230XX gpio_mcp230xx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_MCP23S17 gpio_mcp23s17.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 12caaac1378d2..e6aac9e04ceb5 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -17,6 +17,7 @@ source "subsys/logging/Kconfig.template.log_config" config GPIO_SHELL bool "GPIO Shell" depends on SHELL + imply DEVICE_DT_METADATA help Enable GPIO Shell for testing. @@ -29,6 +30,13 @@ config GPIO_SHELL_INFO_CMD This command provides a shell user extra information about gpio controller reserved pins and line names. +config GPIO_SHELL_TOGGLE_CMD + bool "GPIO Shell toggle command" + default y + depends on GPIO_SHELL + help + Enable GPIO Shell toggle command. + config GPIO_SHELL_BLINK_CMD bool "GPIO Shell blink command" default y @@ -88,6 +96,7 @@ config GPIO_ENABLE_DISABLE_INTERRUPT # zephyr-keep-sorted-start source "drivers/gpio/Kconfig.ad559x" +source "drivers/gpio/Kconfig.adp5585" source "drivers/gpio/Kconfig.ads114s0x" source "drivers/gpio/Kconfig.altera" source "drivers/gpio/Kconfig.ambiq" @@ -116,10 +125,12 @@ source "drivers/gpio/Kconfig.gecko" source "drivers/gpio/Kconfig.ifx_cat1" source "drivers/gpio/Kconfig.imx" source "drivers/gpio/Kconfig.intel" +source "drivers/gpio/Kconfig.iproc" source "drivers/gpio/Kconfig.it8xxx2" source "drivers/gpio/Kconfig.litex" source "drivers/gpio/Kconfig.lmp90xxx" source "drivers/gpio/Kconfig.lpc11u6x" +source "drivers/gpio/Kconfig.max32" source "drivers/gpio/Kconfig.mchp_mss" source "drivers/gpio/Kconfig.mcp23s17" source "drivers/gpio/Kconfig.mcp23xxx" diff --git a/drivers/gpio/Kconfig.adp5585 b/drivers/gpio/Kconfig.adp5585 new file mode 100644 index 0000000000000..d531f858f1d27 --- /dev/null +++ b/drivers/gpio/Kconfig.adp5585 @@ -0,0 +1,18 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +menuconfig GPIO_ADP5585 + bool "ADP5585_GPIO I2C GPIO chip" + default y + depends on DT_HAS_ADI_ADP5585_GPIO_ENABLED + select MFD + select I2C + help + Enable the ADP5585 GPIO driver. + +config GPIO_ADP5585_INIT_PRIORITY + int "Init priority" + default 70 + depends on GPIO_ADP5585 + help + Device driver initialization priority. diff --git a/drivers/gpio/Kconfig.iproc b/drivers/gpio/Kconfig.iproc new file mode 100644 index 0000000000000..8bec1c966d434 --- /dev/null +++ b/drivers/gpio/Kconfig.iproc @@ -0,0 +1,11 @@ +# Copyright 2020 Broadcom +# Copyright 2024 Meta +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_IPROC + bool "Broadcom iProc GPIO controller driver" + default y + depends on DT_HAS_BRCM_IPROC_GPIO_ENABLED + help + This option enables the GPIO driver for iProc family + of GPIO controller. diff --git a/drivers/gpio/Kconfig.max32 b/drivers/gpio/Kconfig.max32 new file mode 100644 index 0000000000000..6f0a5e7ef058f --- /dev/null +++ b/drivers/gpio/Kconfig.max32 @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config GPIO_MAX32 + bool "GPIO Driver for MAX32 family of MCUs" + default y + depends on DT_HAS_ADI_MAX32_GPIO_ENABLED + help + Enable GPIO driver for MAX32 line of MCUs diff --git a/drivers/gpio/Kconfig.mcux_lpc b/drivers/gpio/Kconfig.mcux_lpc index fb2b6cf8905f9..c56af535a029a 100644 --- a/drivers/gpio/Kconfig.mcux_lpc +++ b/drivers/gpio/Kconfig.mcux_lpc @@ -6,6 +6,6 @@ config GPIO_MCUX_LPC bool "MCUX LPC GPIO driver" default y - depends on DT_HAS_NXP_LPC_GPIO_ENABLED + depends on DT_HAS_NXP_LPC_GPIO_PORT_ENABLED help Enable the MCUX LPC pinmux driver. diff --git a/drivers/gpio/Kconfig.smartbond b/drivers/gpio/Kconfig.smartbond index 59c8b2f109f15..5e624cd30119a 100644 --- a/drivers/gpio/Kconfig.smartbond +++ b/drivers/gpio/Kconfig.smartbond @@ -5,6 +5,5 @@ config GPIO_SMARTBOND bool "Renesas SmartBond(tm) GPIO driver" default y depends on DT_HAS_RENESAS_SMARTBOND_GPIO_ENABLED - select PM_DEVICE if PM help Enable GPIO driver for Renesas SmartBond(tm) MCU family. diff --git a/drivers/gpio/gpio_adp5585.c b/drivers/gpio/gpio_adp5585.c new file mode 100644 index 0000000000000..0a1da5e63f4aa --- /dev/null +++ b/drivers/gpio/gpio_adp5585.c @@ -0,0 +1,469 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define DT_DRV_COMPAT adi_adp5585_gpio + +LOG_MODULE_REGISTER(adp5585_gpio, CONFIG_GPIO_LOG_LEVEL); + +#define ADP5585_BANK(offs) (offs >> 3) +#define ADP5585_BIT(offs) (offs & GENMASK(2, 0)) + +enum adp5585_gpio_pin_direction { + adp5585_pin_input = 0U, + adp5585_pin_output, +}; + +enum adp5585_gpio_pin_drive_mode { + adp5585_pin_drive_pp = 0U, + adp5585_pin_drive_od, +}; + +enum adp5585_gpio_pull_config { + adp5585_pull_up_300k = 0U, + adp5585_pull_dn_300k, + adp5585_pull_up_100k, /* not used */ + adp5585_pull_disable, +}; + +enum adp5585_gpio_int_en { + adp5585_int_disable = 0U, + adp5585_int_enable, +}; + +enum adp5585_gpio_int_level { + adp5585_int_active_low = 0U, + adp5585_int_active_high, +}; + +/** Configuration data */ +struct adp5585_gpio_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + const struct device *mfd_dev; + const struct gpio_dt_spec gpio_int; +}; + +/** Runtime driver data */ +struct adp5585_gpio_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + uint16_t output; + + sys_slist_t callbacks; +}; + +static int gpio_adp5585_config(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct adp5585_gpio_config *cfg = dev->config; + struct adp5585_gpio_data *data = dev->data; + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + + int ret = 0; + uint8_t reg_value; + + /* ADP5585 has non-contiguous gpio pin layouts, account for this */ + if ((pin & cfg->common.port_pin_mask) == 0) { + LOG_ERR("pin %d is invalid for this device", pin); + return -ENOTSUP; + } + + uint8_t bank = ADP5585_BANK(pin); + uint8_t bank_pin = ADP5585_BIT(pin); + + /* Can't do I2C bus operations from an ISR */ + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + /* Simultaneous PU & PD mode not supported */ + if (((flags & GPIO_PULL_UP) != 0) && ((flags & GPIO_PULL_DOWN) != 0)) { + return -ENOTSUP; + } + + /* Simultaneous input & output mode not supported */ + if (((flags & GPIO_INPUT) != 0) && ((flags & GPIO_OUTPUT) != 0)) { + return -ENOTSUP; + } + + k_sem_take(&parent_data->lock, K_FOREVER); + + if ((flags & GPIO_SINGLE_ENDED) != 0) { + reg_value = adp5585_pin_drive_od << bank_pin; + } else { + reg_value = adp5585_pin_drive_pp << bank_pin; + } + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, ADP5585_GPO_OUT_MODE_A + bank, + BIT(bank_pin), reg_value); + if (ret != 0) { + goto out; + } + + uint8_t regaddr = ADP5585_RPULL_CONFIG_A + (bank << 1); + uint8_t shift = bank_pin << 1; + + if (bank_pin > 3U) { + regaddr += 1U; + shift = (bank_pin - 3U) << 1; + } + if ((flags & GPIO_PULL_UP) != 0) { + reg_value = adp5585_pull_up_300k << shift; + } else if ((flags & GPIO_PULL_DOWN) != 0) { + reg_value = adp5585_pull_dn_300k << shift; + } else { + reg_value = adp5585_pull_disable << shift; + } + + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, regaddr, + 0b11U << shift, reg_value); + if (ret != 0) { + goto out; + } + + /* Ensure either Output or Input is specified */ + if ((flags & GPIO_OUTPUT) != 0) { + + /* Set Low or High if specified */ + if ((flags & GPIO_OUTPUT_INIT_LOW) != 0) { + data->output &= ~BIT(pin); + } else if ((flags & GPIO_OUTPUT_INIT_HIGH) != 0) { + data->output |= BIT(pin); + } + if (bank == 0) { + /* reg_value for ADP5585_GPO_OUT_MODE */ + reg_value = (uint8_t)data->output; + } else { + /* reg_value for ADP5585_GPO_OUT_MODE */ + reg_value = (uint8_t)(data->output >> 8); + } + ret = i2c_reg_write_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPO_OUT_MODE_A + bank, + reg_value); + if (ret != 0) { + goto out; + } + /* reg_value for ADP5585_GPIO_DIRECTION */ + reg_value = adp5585_pin_output << bank_pin; + } else if ((flags & GPIO_INPUT) != 0) { + /* reg_value for ADP5585_GPIO_DIRECTION */ + reg_value = adp5585_pin_output << bank_pin; + } + + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPIO_DIRECTION_A + bank, + BIT(bank_pin), reg_value); + +out: + k_sem_give(&parent_data->lock); + if (ret != 0) { + LOG_ERR("pin configure error: %d", ret); + } + return ret; +} + +static int gpio_adp5585_port_read(const struct device *dev, gpio_port_value_t *value) +{ + const struct adp5585_gpio_config *cfg = dev->config; + /* struct adp5585_gpio_data *data = dev->data; */ + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + + uint16_t input_data = 0; + int ret = 0; + + /* Can't do I2C bus operations from an ISR */ + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + k_sem_take(&parent_data->lock, K_FOREVER); + + /** Read Input Register */ + + uint8_t gpi_status_reg; + uint8_t gpi_status_buf[2]; + + ret = i2c_write_read_dt(&parent_cfg->i2c_bus, &gpi_status_reg, 1U, + gpi_status_buf, 2U); + if (ret) { + goto out; + } + input_data = sys_le16_to_cpu(*((uint16_t *)gpi_status_buf)); + *value = input_data; + +out: + k_sem_give(&parent_data->lock); + LOG_DBG("read %x got %d", input_data, ret); + return ret; +} + +static int gpio_adp5585_port_write(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value, gpio_port_value_t toggle) +{ + const struct adp5585_gpio_config *cfg = dev->config; + struct adp5585_gpio_data *data = dev->data; + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + + uint16_t orig_out; + uint16_t out; + uint8_t reg_value; + int ret; + + /* Can't do I2C bus operations from an ISR */ + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + k_sem_take(&parent_data->lock, K_FOREVER); + + orig_out = data->output; + out = ((orig_out & ~mask) | (value & mask)) ^ toggle; + + reg_value = (uint8_t)out; + uint8_t gpo_data_out_buf[] = { ADP5585_GPO_DATA_OUT_A, + (uint8_t)out, (uint8_t)(out >> 8) }; + + ret = i2c_write_dt(&parent_cfg->i2c_bus, gpo_data_out_buf, sizeof(gpo_data_out_buf)); + if (ret) { + goto out; + } + + data->output = out; + +out: + k_sem_give(&parent_data->lock); + LOG_DBG("write %x msk %08x val %08x => %x: %d", orig_out, mask, value, out, ret); + return ret; +} + +static int gpio_adp5585_port_set_masked(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + return gpio_adp5585_port_write(dev, mask, value, 0); +} + +static int gpio_adp5585_port_set_bits(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_adp5585_port_write(dev, pins, pins, 0); +} + +static int gpio_adp5585_port_clear_bits(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_adp5585_port_write(dev, pins, 0, 0); +} + +static int gpio_adp5585_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + return gpio_adp5585_port_write(dev, 0, 0, pins); +} + +static int gpio_adp5585_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct adp5585_gpio_config *cfg = dev->config; + /* struct adp5585_gpio_data *data = dev->data; */ + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + int ret = 0; + + if (parent_cfg->nint_gpio.port == NULL) { + return -ENOTSUP; + } + + /* ADP5585 has non-contiguous gpio pin layouts, account for this */ + if ((pin & cfg->common.port_pin_mask) == 0) { + LOG_ERR("pin %d is invalid for this device", pin); + return -ENOTSUP; + } + + /* This device supports only level-triggered interrupts. */ + /* This device does NOT support either-level interrupt. */ + if (mode == GPIO_INT_MODE_EDGE || trig == GPIO_INT_TRIG_BOTH) { + return -ENOTSUP; + } + if (k_is_in_isr()) { + return -EWOULDBLOCK; + } + + uint8_t bank = ADP5585_BANK(pin); + uint8_t bank_pin = ADP5585_BIT(pin); + + k_sem_take(&parent_data->lock, K_FOREVER); + + if (mode == GPIO_INT_MODE_DISABLED) { + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPI_INTERRUPT_EN_A + bank, BIT(bank_pin), + (adp5585_int_disable << bank_pin)); + } else if ((trig & GPIO_INT_TRIG_BOTH) != 0) { + if (trig == GPIO_INT_TRIG_LOW) { + ret = i2c_reg_update_byte_dt( + &parent_cfg->i2c_bus, ADP5585_GPI_INT_LEVEL_A + bank, + BIT(bank_pin), (adp5585_int_active_low << bank_pin)); + } else { + ret = i2c_reg_update_byte_dt( + &parent_cfg->i2c_bus, ADP5585_GPI_INT_LEVEL_A + bank, + BIT(bank_pin), (adp5585_int_active_high << bank_pin)); + } + + /* make sure GPI_n_EVENT_EN is disabled, otherwise it will generate FIFO event */ + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPI_EVENT_EN_A + bank, BIT(bank_pin), 0U); + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, + ADP5585_GPI_INTERRUPT_EN_A + bank, + BIT(bank_pin), (adp5585_int_enable << bank_pin)); + } + + k_sem_give(&parent_data->lock); + return ret; +} + +static int gpio_adp5585_manage_callback(const struct device *dev, struct gpio_callback *callback, + bool set) +{ + struct adp5585_gpio_data *data = dev->data; + + return gpio_manage_callback(&data->callbacks, callback, set); +} + +void gpio_adp5585_irq_handler(const struct device *dev) +{ + const struct adp5585_gpio_config *cfg = dev->config; + struct adp5585_gpio_data *data = dev->data; + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + + uint16_t reg_int_status; + int ret = 0; + + k_sem_take(&parent_data->lock, K_FOREVER); + + /* Read Input Register */ + ret = i2c_burst_read_dt(&parent_cfg->i2c_bus, ADP5585_GPI_INT_STAT_A, + (uint8_t *)®_int_status, 2U); + if (ret != 0) { + LOG_WRN("%s failed to read interrupt status %d", dev->name, ret); + goto out; + } + +out: + k_sem_give(&parent_data->lock); + + if (ret == 0 && reg_int_status != 0) { + gpio_fire_callbacks(&data->callbacks, dev, reg_int_status); + } +} + +/** + * @brief Initialization function of ADP5585_GPIO + * + * This sets initial input/ output configuration and output states. + * The interrupt is configured if this is enabled. + * + * @param dev Device struct + * @return 0 if successful, failed otherwise. + */ +static int gpio_adp5585_init(const struct device *dev) +{ + const struct adp5585_gpio_config *cfg = dev->config; + struct adp5585_gpio_data *data = dev->data; + const struct mfd_adp5585_config *parent_cfg = + (struct mfd_adp5585_config *)(cfg->mfd_dev->config); + struct mfd_adp5585_data *parent_data = (struct mfd_adp5585_data *)(cfg->mfd_dev->data); + int ret = 0; + + if (!device_is_ready(cfg->mfd_dev)) { + LOG_ERR("%s: parent dev not ready", dev->name); + ret = -ENODEV; + goto out; + } + + if (!device_is_ready(parent_cfg->i2c_bus.bus)) { + LOG_ERR("I2C bus device not found"); + ret = -EIO; + goto out; + } + + k_sem_take(&parent_data->lock, K_FOREVER); + + /** Read output register */ + uint8_t gpo_data_out_buf[] = { ADP5585_GPO_DATA_OUT_A, + 0x00, 0x00 }; + + ret = i2c_write_read_dt(&parent_cfg->i2c_bus, gpo_data_out_buf, 1U, + gpo_data_out_buf + 1, 2U); + if (ret) { + goto out; + } + data->output = sys_le16_to_cpu(*((uint16_t *)(gpo_data_out_buf + 1))); + + /** Set RPULL to high-z by default */ + uint8_t rpull_config_buf[] = { ADP5585_RPULL_CONFIG_A, + 0xffU, 0x03U, 0xffU, 0x03U }; + + ret = i2c_write_dt(&parent_cfg->i2c_bus, rpull_config_buf, sizeof(rpull_config_buf)); + if (ret) { + goto out; + } + + parent_data->child.gpio_dev = dev; + + /** Enable GPI interrupt */ + if ((ret == 0) && gpio_is_ready_dt(&parent_cfg->nint_gpio)) { + ret = i2c_reg_update_byte_dt(&parent_cfg->i2c_bus, ADP5585_INT_EN, (1U << 1), + (1U << 1)); + } + +out: + k_sem_give(&parent_data->lock); + if (ret) { + LOG_ERR("%s init failed: %d", dev->name, ret); + } else { + LOG_INF("%s init ok", dev->name); + } + return ret; +} + +static const struct gpio_driver_api api_table = { + .pin_configure = gpio_adp5585_config, + .port_get_raw = gpio_adp5585_port_read, + .port_set_masked_raw = gpio_adp5585_port_set_masked, + .port_set_bits_raw = gpio_adp5585_port_set_bits, + .port_clear_bits_raw = gpio_adp5585_port_clear_bits, + .port_toggle_bits = gpio_adp5585_port_toggle_bits, + .pin_interrupt_configure = gpio_adp5585_pin_interrupt_configure, + .manage_callback = gpio_adp5585_manage_callback, +}; + +#define GPIO_ADP5585_INIT(inst) \ + static const struct adp5585_gpio_config adp5585_gpio_cfg_##inst = { \ + .common = { \ + .port_pin_mask = GPIO_DT_INST_PORT_PIN_MASK_NGPIOS_EXC( \ + inst, DT_INST_PROP(inst, ngpios)) \ + }, \ + .mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ + }; \ + static struct adp5585_gpio_data adp5585_gpio_drvdata_##inst; \ + DEVICE_DT_INST_DEFINE(inst, gpio_adp5585_init, NULL, \ + &adp5585_gpio_drvdata_##inst, \ + &adp5585_gpio_cfg_##inst, POST_KERNEL, \ + CONFIG_GPIO_ADP5585_INIT_PRIORITY, &api_table); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_ADP5585_INIT) diff --git a/drivers/gpio/gpio_ads114s0x.c b/drivers/gpio/gpio_ads114s0x.c index 13f4f7f12669b..5c0cd261e2689 100644 --- a/drivers/gpio/gpio_ads114s0x.c +++ b/drivers/gpio/gpio_ads114s0x.c @@ -138,7 +138,7 @@ BUILD_ASSERT(CONFIG_GPIO_ADS114S0X_INIT_PRIORITY > CONFIG_ADC_INIT_PRIORITY, \ static struct gpio_ads114s0x_data gpio_ads114s0x_##id##_data; \ \ - DEVICE_DT_INST_DEFINE(id, &gpio_ads114s0x_init, NULL, &gpio_ads114s0x_##id##_data, \ + DEVICE_DT_INST_DEFINE(id, gpio_ads114s0x_init, NULL, &gpio_ads114s0x_##id##_data, \ &gpio_ads114s0x_##id##_cfg, POST_KERNEL, \ CONFIG_GPIO_ADS114S0X_INIT_PRIORITY, &gpio_ads114s0x_api); diff --git a/drivers/gpio/gpio_ambiq.c b/drivers/gpio/gpio_ambiq.c index e264a4096d8ce..24e08a4057232 100644 --- a/drivers/gpio/gpio_ambiq.c +++ b/drivers/gpio/gpio_ambiq.c @@ -37,6 +37,41 @@ static int ambiq_gpio_pin_configure(const struct device *dev, gpio_pin_t pin, gp { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + pin += dev_cfg->offset; + + am_hal_gpio_pincfg_t pincfg = g_AM_HAL_GPIO_DEFAULT; + + if (flags & GPIO_INPUT) { + pincfg = g_AM_HAL_GPIO_INPUT; + if (flags & GPIO_PULL_UP) { + pincfg.ePullup = AM_HAL_GPIO_PIN_PULLUP_1_5K; + } else if (flags & GPIO_PULL_DOWN) { + pincfg.ePullup = AM_HAL_GPIO_PIN_PULLDOWN; + } + } + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_SINGLE_ENDED) { + if (flags & GPIO_LINE_OPEN_DRAIN) { + pincfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN; + } + } else { + pincfg.eGPOutcfg = AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL; + } + } + if (flags & GPIO_DISCONNECTED) { + pincfg = g_AM_HAL_GPIO_DEFAULT; + } + + if (flags & GPIO_OUTPUT_INIT_HIGH) { + pincfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH; + am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_SET); + + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + pincfg.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW; + am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR); + } +#else pin += (dev_cfg->offset >> 2); am_hal_gpio_pincfg_t pincfg = am_hal_gpio_pincfg_default; @@ -70,7 +105,7 @@ static int ambiq_gpio_pin_configure(const struct device *dev, gpio_pin_t pin, gp pincfg.GP.cfg_b.eCEpol = AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW; am_hal_gpio_state_write(pin, AM_HAL_GPIO_OUTPUT_CLEAR); } - +#endif am_hal_gpio_pinconfig(pin, pincfg); return 0; @@ -82,6 +117,40 @@ static int ambiq_gpio_get_config(const struct device *dev, gpio_pin_t pin, gpio_ const struct ambiq_gpio_config *const dev_cfg = dev->config; am_hal_gpio_pincfg_t pincfg; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + pin += dev_cfg->offset; + + am_hal_gpio_pinconfig_get(pin, &pincfg); + + if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_DISABLE && + pincfg.eGPInput == AM_HAL_GPIO_PIN_INPUT_NONE) { + *out_flags = GPIO_DISCONNECTED; + } + if (pincfg.eGPInput == AM_HAL_GPIO_PIN_INPUT_ENABLE) { + *out_flags = GPIO_INPUT; + if (pincfg.ePullup == AM_HAL_GPIO_PIN_PULLUP_1_5K) { + *out_flags |= GPIO_PULL_UP; + } else if (pincfg.ePullup == AM_HAL_GPIO_PIN_PULLDOWN) { + *out_flags |= GPIO_PULL_DOWN; + } + } + if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL) { + *out_flags = GPIO_OUTPUT | GPIO_PUSH_PULL; + if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH) { + *out_flags |= GPIO_OUTPUT_HIGH; + } else if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW) { + *out_flags |= GPIO_OUTPUT_LOW; + } + } + if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN) { + *out_flags = GPIO_OUTPUT | GPIO_OPEN_DRAIN; + if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVEHIGH) { + *out_flags |= GPIO_OUTPUT_HIGH; + } else if (pincfg.eCEpol == AM_HAL_GPIO_PIN_CEPOL_ACTIVELOW) { + *out_flags |= GPIO_OUTPUT_LOW; + } + } +#else pin += (dev_cfg->offset >> 2); am_hal_gpio_pinconfig_get(pin, &pincfg); @@ -114,7 +183,7 @@ static int ambiq_gpio_get_config(const struct device *dev, gpio_pin_t pin, gpio_ *out_flags |= GPIO_OUTPUT_LOW; } } - +#endif return 0; } #endif @@ -127,6 +196,33 @@ static int ambiq_gpio_port_get_direction(const struct device *dev, gpio_port_pin am_hal_gpio_pincfg_t pincfg; gpio_port_pins_t ip = 0; gpio_port_pins_t op = 0; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; + + if (inputs != NULL) { + for (int i = 0; i < dev_cfg->ngpios; i++) { + if ((map >> i) & 1) { + am_hal_gpio_pinconfig_get(i + pin_offset, &pincfg); + if (pincfg.eGPInput == AM_HAL_GPIO_PIN_INPUT_ENABLE) { + ip |= BIT(i); + } + } + } + *inputs = ip; + } + if (outputs != NULL) { + for (int i = 0; i < dev_cfg->ngpios; i++) { + if ((map >> i) & 1) { + am_hal_gpio_pinconfig_get(i + pin_offset, &pincfg); + if (pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_PUSHPULL || + pincfg.eGPOutcfg == AM_HAL_GPIO_PIN_OUTCFG_OPENDRAIN) { + op |= BIT(i); + } + } + } + *outputs = op; + } +#else uint32_t pin_offset = dev_cfg->offset >> 2; if (inputs != NULL) { @@ -152,7 +248,7 @@ static int ambiq_gpio_port_get_direction(const struct device *dev, gpio_port_pin } *outputs = op; } - +#endif return 0; } #endif @@ -161,8 +257,11 @@ static int ambiq_gpio_port_get_raw(const struct device *dev, gpio_port_value_t * { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + *value = (*AM_HAL_GPIO_RDn(dev_cfg->offset)); +#else *value = (*AM_HAL_GPIO_RDn(dev_cfg->offset >> 2)); - +#endif return 0; } @@ -170,8 +269,11 @@ static int ambiq_gpio_port_set_masked_raw(const struct device *dev, gpio_port_pi gpio_port_value_t value) { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; +#else uint32_t pin_offset = dev_cfg->offset >> 2; - +#endif for (int i = 0; i < dev_cfg->ngpios; i++) { if ((mask >> i) & 1) { am_hal_gpio_state_write(i + pin_offset, ((value >> i) & 1)); @@ -184,7 +286,11 @@ static int ambiq_gpio_port_set_masked_raw(const struct device *dev, gpio_port_pi static int ambiq_gpio_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; +#else uint32_t pin_offset = dev_cfg->offset >> 2; +#endif for (int i = 0; i < dev_cfg->ngpios; i++) { if ((pins >> i) & 1) { @@ -198,7 +304,11 @@ static int ambiq_gpio_port_set_bits_raw(const struct device *dev, gpio_port_pins static int ambiq_gpio_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; +#else uint32_t pin_offset = dev_cfg->offset >> 2; +#endif for (int i = 0; i < dev_cfg->ngpios; i++) { if ((pins >> i) & 1) { @@ -212,7 +322,11 @@ static int ambiq_gpio_port_clear_bits_raw(const struct device *dev, gpio_port_pi static int ambiq_gpio_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) { const struct ambiq_gpio_config *const dev_cfg = dev->config; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t pin_offset = dev_cfg->offset; +#else uint32_t pin_offset = dev_cfg->offset >> 2; +#endif for (int i = 0; i < dev_cfg->ngpios; i++) { if ((pins >> i) & 1) { @@ -223,17 +337,49 @@ static int ambiq_gpio_port_toggle_bits(const struct device *dev, gpio_port_pins_ return 0; } +#define APOLLO3_HANDLE_SHARED_GPIO_IRQ(n) \ + static const struct device *const dev_##n = DEVICE_DT_INST_GET(n); \ + const struct ambiq_gpio_config *cfg_##n = dev_##n->config; \ + struct ambiq_gpio_data *const data_##n = dev_##n->data; \ + uint32_t status_##n = (uint32_t)(ui64Status >> cfg_##n->offset); \ + if (status_##n) { \ + gpio_fire_callbacks(&data_##n->cb, dev_##n, status_##n); \ + } + +#define APOLLO3P_HANDLE_SHARED_GPIO_IRQ(n) \ + static const struct device *const dev_##n = DEVICE_DT_INST_GET(n); \ + struct ambiq_gpio_data *const data_##n = dev_##n->data; \ + if (pGpioIntStatusMask->U.Msk[n]) { \ + gpio_fire_callbacks(&data_##n->cb, dev_##n, pGpioIntStatusMask->U.Msk[n]); \ + } + static void ambiq_gpio_isr(const struct device *dev) { +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + ARG_UNUSED(dev); + +#if defined(CONFIG_SOC_APOLLO3_BLUE) + uint64_t ui64Status; + + am_hal_gpio_interrupt_status_get(false, &ui64Status); + am_hal_gpio_interrupt_clear(ui64Status); + DT_INST_FOREACH_STATUS_OKAY(APOLLO3_HANDLE_SHARED_GPIO_IRQ) +#elif defined(CONFIG_SOC_APOLLO3P_BLUE) + AM_HAL_GPIO_MASKCREATE(GpioIntStatusMask); + am_hal_gpio_interrupt_status_get(false, pGpioIntStatusMask); + am_hal_gpio_interrupt_clear(pGpioIntStatusMask); + DT_INST_FOREACH_STATUS_OKAY(APOLLO3P_HANDLE_SHARED_GPIO_IRQ) +#endif +#else + uint32_t int_status; struct ambiq_gpio_data *const data = dev->data; const struct ambiq_gpio_config *const dev_cfg = dev->config; - uint32_t int_status; - am_hal_gpio_interrupt_irq_status_get(dev_cfg->irq_num, false, &int_status); am_hal_gpio_interrupt_irq_clear(dev_cfg->irq_num, int_status); gpio_fire_callbacks(&data->cb, dev, int_status); +#endif } static int ambiq_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, @@ -242,10 +388,57 @@ static int ambiq_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin const struct ambiq_gpio_config *const dev_cfg = dev->config; struct ambiq_gpio_data *const data = dev->data; - am_hal_gpio_pincfg_t pincfg; + int ret; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_gpio_pincfg_t pincfg = g_AM_HAL_GPIO_DEFAULT; + int gpio_pin = pin + dev_cfg->offset; + + ret = am_hal_gpio_pinconfig_get(gpio_pin, &pincfg); + + if (mode == GPIO_INT_MODE_DISABLED) { + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_NONE; + ret = am_hal_gpio_pinconfig(gpio_pin, pincfg); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + AM_HAL_GPIO_MASKCREATE(GpioIntMask); + ret = am_hal_gpio_interrupt_clear(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin)); + ret = am_hal_gpio_interrupt_disable(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin)); + k_spin_unlock(&data->lock, key); + + } else { + if (mode == GPIO_INT_MODE_LEVEL) { + return -ENOTSUP; + } + switch (trig) { + case GPIO_INT_TRIG_LOW: + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_HI2LO; + break; + case GPIO_INT_TRIG_HIGH: + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_LO2HI; + break; + case GPIO_INT_TRIG_BOTH: + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_BOTH; + break; + default: + pincfg.eIntDir = AM_HAL_GPIO_PIN_INTDIR_NONE; + break; + } + ret = am_hal_gpio_pinconfig(gpio_pin, pincfg); + + irq_enable(dev_cfg->irq_num); + + k_spinlock_key_t key = k_spin_lock(&data->lock); + + AM_HAL_GPIO_MASKCREATE(GpioIntMask); + ret = am_hal_gpio_interrupt_clear(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin)); + ret = am_hal_gpio_interrupt_enable(AM_HAL_GPIO_MASKBIT(pGpioIntMask, gpio_pin)); + k_spin_unlock(&data->lock, key); + } +#else + am_hal_gpio_pincfg_t pincfg = am_hal_gpio_pincfg_default; int gpio_pin = pin + (dev_cfg->offset >> 2); uint32_t int_status; - int ret; ret = am_hal_gpio_pinconfig_get(gpio_pin, &pincfg); @@ -295,6 +488,7 @@ static int ambiq_gpio_pin_interrupt_configure(const struct device *dev, gpio_pin (void *)&gpio_pin); k_spin_unlock(&data->lock, key); } +#endif return ret; } @@ -306,14 +500,36 @@ static int ambiq_gpio_manage_callback(const struct device *dev, struct gpio_call return gpio_manage_callback(&data->cb, callback, set); } +#if defined(CONFIG_SOC_SERIES_APOLLO3X) +static void ambiq_gpio_cfg_func(void) +{ + /* Apollo3 GPIO banks share the same irq number, connect to bank0 once when init and handle + * different banks in ambiq_gpio_isr + */ + static bool global_irq_init = true; + + if (!global_irq_init) { + return; + } + + global_irq_init = false; + + /* Shared irq config default to BANK0. */ + IRQ_CONNECT(GPIO_IRQn, DT_INST_IRQ(0, priority), ambiq_gpio_isr, DEVICE_DT_INST_GET(0), 0); +} +#endif + static int ambiq_gpio_init(const struct device *port) { const struct ambiq_gpio_config *const dev_cfg = port->config; NVIC_ClearPendingIRQ(dev_cfg->irq_num); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + ambiq_gpio_cfg_func(); +#else dev_cfg->cfg_func(); - +#endif return 0; } @@ -334,10 +550,25 @@ static const struct gpio_driver_api ambiq_gpio_drv_api = { #endif }; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) +/* Apollo3 GPIO banks share the same irq number, connect irq here will cause build error, so we + * leave this function blank here and do it in ambiq_gpio_cfg_func + */ +#define AMBIQ_GPIO_CONFIG_FUNC(n) static void ambiq_gpio_cfg_func_##n(void){}; +#else +#define AMBIQ_GPIO_CONFIG_FUNC(n) \ + static void ambiq_gpio_cfg_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), ambiq_gpio_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + return; \ + }; +#endif + #define AMBIQ_GPIO_DEFINE(n) \ static struct ambiq_gpio_data ambiq_gpio_data_##n; \ static void ambiq_gpio_cfg_func_##n(void); \ - \ static const struct ambiq_gpio_config ambiq_gpio_config_##n = { \ .common = \ { \ @@ -348,16 +579,8 @@ static const struct gpio_driver_api ambiq_gpio_drv_api = { .ngpios = DT_INST_PROP(n, ngpios), \ .irq_num = DT_INST_IRQN(n), \ .cfg_func = ambiq_gpio_cfg_func_##n}; \ - static void ambiq_gpio_cfg_func_##n(void) \ - { \ - \ - IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), ambiq_gpio_isr, \ - DEVICE_DT_INST_GET(n), 0); \ - \ - return; \ - }; \ - \ - DEVICE_DT_INST_DEFINE(n, &ambiq_gpio_init, NULL, &ambiq_gpio_data_##n, \ + AMBIQ_GPIO_CONFIG_FUNC(n) \ + DEVICE_DT_INST_DEFINE(n, ambiq_gpio_init, NULL, &ambiq_gpio_data_##n, \ &ambiq_gpio_config_##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ &ambiq_gpio_drv_api); diff --git a/drivers/gpio/gpio_axp192.c b/drivers/gpio/gpio_axp192.c index 5b1b41c758c45..661348bc1be3f 100644 --- a/drivers/gpio/gpio_axp192.c +++ b/drivers/gpio/gpio_axp192.c @@ -313,7 +313,7 @@ static int gpio_axp192_init(const struct device *dev) \ static struct gpio_axp192_data gpio_axp192_data##inst; \ \ - DEVICE_DT_INST_DEFINE(inst, &gpio_axp192_init, NULL, &gpio_axp192_data##inst, \ + DEVICE_DT_INST_DEFINE(inst, gpio_axp192_init, NULL, &gpio_axp192_data##inst, \ &gpio_axp192_config##inst, POST_KERNEL, \ CONFIG_GPIO_AXP192_INIT_PRIORITY, &gpio_axp192_api); diff --git a/drivers/gpio/gpio_cc32xx.c b/drivers/gpio/gpio_cc32xx.c index c575237003b54..88d2f7eee27fb 100644 --- a/drivers/gpio/gpio_cc32xx.c +++ b/drivers/gpio/gpio_cc32xx.c @@ -256,7 +256,7 @@ static const struct gpio_driver_api api_funcs = { } #define GPIO_CC32XX_DEVICE_INIT(n) \ - DEVICE_DT_INST_DEFINE(n, &gpio_cc32xx_a##n##_init, \ + DEVICE_DT_INST_DEFINE(n, gpio_cc32xx_a##n##_init, \ NULL, &gpio_cc32xx_a##n##_data, \ &gpio_cc32xx_a##n##_config, \ POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ diff --git a/drivers/gpio/gpio_davinci.c b/drivers/gpio/gpio_davinci.c index 205e0112cde8f..b3ff9d4b22984 100644 --- a/drivers/gpio/gpio_davinci.c +++ b/drivers/gpio/gpio_davinci.c @@ -191,7 +191,7 @@ static int gpio_davinci_init(const struct device *dev) static struct gpio_davinci_data gpio_davinci_##n##_data; \ \ DEVICE_DT_INST_DEFINE(n, \ - &gpio_davinci_init, \ + gpio_davinci_init, \ NULL, \ &gpio_davinci_##n##_data, \ &gpio_davinci_##n##_config, \ diff --git a/drivers/gpio/gpio_esp32.c b/drivers/gpio/gpio_esp32.c index 3851200b18130..7a1b6790388b7 100644 --- a/drivers/gpio/gpio_esp32.c +++ b/drivers/gpio/gpio_esp32.c @@ -20,7 +20,7 @@ #include #include #include -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include #else #include @@ -42,6 +42,15 @@ LOG_MODULE_REGISTER(gpio_esp32, CONFIG_LOG_DEFAULT_LEVEL); /* arch_curr_cpu() is not available for riscv based chips */ #define CPU_ID() 0 #define ISR_HANDLER isr_handler_t +#elif defined(CONFIG_SOC_SERIES_ESP32C6) +/* gpio structs in esp32c6 are also different */ +#define out out.out_data_orig +#define in in.in_data_next +#define out_w1ts out_w1ts.val +#define out_w1tc out_w1tc.val +/* arch_curr_cpu() is not available for riscv based chips */ +#define CPU_ID() 0 +#define ISR_HANDLER isr_handler_t #else #define CPU_ID() arch_curr_cpu()->id #define ISR_HANDLER intr_handler_t diff --git a/drivers/gpio/gpio_gd32.c b/drivers/gpio/gpio_gd32.c index 376c70f463f04..744f5e4a7768d 100644 --- a/drivers/gpio/gpio_gd32.c +++ b/drivers/gpio/gpio_gd32.c @@ -373,7 +373,7 @@ static int gpio_gd32_init(const struct device *port) \ static struct gpio_gd32_data gpio_gd32_data##n; \ \ - DEVICE_DT_INST_DEFINE(n, &gpio_gd32_init, NULL, &gpio_gd32_data##n, \ + DEVICE_DT_INST_DEFINE(n, gpio_gd32_init, NULL, &gpio_gd32_data##n, \ &gpio_gd32_config##n, PRE_KERNEL_1, \ CONFIG_GPIO_INIT_PRIORITY, &gpio_gd32_api); diff --git a/drivers/gpio/gpio_gecko.c b/drivers/gpio/gpio_gecko.c index dc3e5317d4d62..1025f1eaa7ab0 100644 --- a/drivers/gpio/gpio_gecko.c +++ b/drivers/gpio/gpio_gecko.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #ifdef CONFIG_SOC_GECKO_DEV_INIT @@ -63,9 +64,8 @@ #define GECKO_GPIO_MODEH(pin, mode) (mode << ((pin - 8) * 4)) -#define member_size(type, member) sizeof(((type *)0)->member) -#define NUMBER_OF_PORTS (member_size(GPIO_TypeDef, P) / \ - member_size(GPIO_TypeDef, P[0])) +#define NUMBER_OF_PORTS (SIZEOF_FIELD(GPIO_TypeDef, P) / \ + SIZEOF_FIELD(GPIO_TypeDef, P[0])) struct gpio_gecko_common_config { }; diff --git a/drivers/gpio/gpio_handlers.c b/drivers/gpio/gpio_handlers.c index 99fbc6f45d91c..405b54afeb333 100644 --- a/drivers/gpio/gpio_handlers.c +++ b/drivers/gpio/gpio_handlers.c @@ -16,7 +16,7 @@ static inline int z_vrfy_gpio_pin_configure(const struct device *port, pin, flags); } -#include +#include #ifdef CONFIG_GPIO_GET_CONFIG static inline int z_vrfy_gpio_pin_get_config(const struct device *port, @@ -28,7 +28,7 @@ static inline int z_vrfy_gpio_pin_get_config(const struct device *port, return z_impl_gpio_pin_get_config(port, pin, flags); } -#include +#include #endif static inline int z_vrfy_gpio_port_get_raw(const struct device *port, @@ -39,7 +39,7 @@ static inline int z_vrfy_gpio_port_get_raw(const struct device *port, return z_impl_gpio_port_get_raw((const struct device *)port, (gpio_port_value_t *)value); } -#include +#include static inline int z_vrfy_gpio_port_set_masked_raw(const struct device *port, gpio_port_pins_t mask, @@ -50,7 +50,7 @@ static inline int z_vrfy_gpio_port_set_masked_raw(const struct device *port, mask, value); } -#include +#include static inline int z_vrfy_gpio_port_set_bits_raw(const struct device *port, gpio_port_pins_t pins) @@ -59,7 +59,7 @@ static inline int z_vrfy_gpio_port_set_bits_raw(const struct device *port, return z_impl_gpio_port_set_bits_raw((const struct device *)port, pins); } -#include +#include static inline int z_vrfy_gpio_port_clear_bits_raw(const struct device *port, gpio_port_pins_t pins) @@ -68,7 +68,7 @@ static inline int z_vrfy_gpio_port_clear_bits_raw(const struct device *port, return z_impl_gpio_port_clear_bits_raw((const struct device *)port, pins); } -#include +#include static inline int z_vrfy_gpio_port_toggle_bits(const struct device *port, gpio_port_pins_t pins) @@ -76,7 +76,7 @@ static inline int z_vrfy_gpio_port_toggle_bits(const struct device *port, K_OOPS(K_SYSCALL_DRIVER_GPIO(port, port_toggle_bits)); return z_impl_gpio_port_toggle_bits((const struct device *)port, pins); } -#include +#include static inline int z_vrfy_gpio_pin_interrupt_configure(const struct device *port, gpio_pin_t pin, @@ -87,7 +87,7 @@ static inline int z_vrfy_gpio_pin_interrupt_configure(const struct device *port, pin, flags); } -#include +#include static inline int z_vrfy_gpio_get_pending_int(const struct device *dev) { @@ -95,7 +95,7 @@ static inline int z_vrfy_gpio_get_pending_int(const struct device *dev) return z_impl_gpio_get_pending_int((const struct device *)dev); } -#include +#include #ifdef CONFIG_GPIO_GET_DIRECTION static inline int z_vrfy_gpio_port_get_direction(const struct device *dev, gpio_port_pins_t map, @@ -114,5 +114,5 @@ static inline int z_vrfy_gpio_port_get_direction(const struct device *dev, gpio_ return z_impl_gpio_port_get_direction(dev, map, inputs, outputs); } -#include +#include #endif /* CONFIG_GPIO_GET_DIRECTION */ diff --git a/drivers/gpio/gpio_ifx_cat1.c b/drivers/gpio/gpio_ifx_cat1.c index 5d1851ef9e4c4..f97b6f446c733 100644 --- a/drivers/gpio/gpio_ifx_cat1.c +++ b/drivers/gpio/gpio_ifx_cat1.c @@ -59,7 +59,15 @@ struct gpio_cat1_data { /* Map port number to device object */ static const struct device *const port_dev_obj[IOSS_GPIO_GPIO_PORT_NR] = { - LISTIFY(15, GET_DEV_OBJ_FROM_LIST, (,)) + /* the integer used as the first variable in listify is equivalent to + * IOSS_GPIO_GPIO_PORT_NR for the respective categories, but using + * the macro in LISTIFY causes build failures + */ + #if CONFIG_SOC_FAMILY_INFINEON_CAT1A + LISTIFY(15, GET_DEV_OBJ_FROM_LIST, (,)) + #elif CONFIG_SOC_FAMILY_INFINEON_CAT1B + LISTIFY(6, GET_DEV_OBJ_FROM_LIST, (,)) + #endif }; static int gpio_cat1_configure(const struct device *dev, diff --git a/drivers/gpio/gpio_imx.c b/drivers/gpio/gpio_imx.c index 68caf1786da87..91159c918c7d1 100644 --- a/drivers/gpio/gpio_imx.c +++ b/drivers/gpio/gpio_imx.c @@ -82,7 +82,11 @@ static int imx_gpio_configure(const struct device *port, gpio_pin_t pin, /* Init pin configuration struct, and use pinctrl api to apply settings */ __ASSERT_NO_MSG(pin < config->mux_count); + memcpy(&pin_cfg.pinmux, &config->pin_muxes[pin], sizeof(pin_cfg.pinmux)); + + unsigned int key = irq_lock(); + /* cfg register will be set by pinctrl_configure_pins */ pin_cfg.pin_ctrl_flags = reg; pinctrl_configure_pins(&pin_cfg, 1, PINCTRL_REG_NONE); @@ -106,6 +110,8 @@ static int imx_gpio_configure(const struct device *port, gpio_pin_t pin, WRITE_BIT(base->GDIR, pin, 0U); } + irq_unlock(key); + return 0; } @@ -126,8 +132,10 @@ static int imx_gpio_port_set_masked_raw(const struct device *port, const struct imx_gpio_config *config = port->config; GPIO_Type *base = config->base; + unsigned int key = irq_lock(); GPIO_WritePortOutput(base, (GPIO_ReadPortInput(base) & ~mask) | (value & mask)); + irq_unlock(key); return 0; } @@ -138,7 +146,9 @@ static int imx_gpio_port_set_bits_raw(const struct device *port, const struct imx_gpio_config *config = port->config; GPIO_Type *base = config->base; + unsigned int key = irq_lock(); GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) | pins); + irq_unlock(key); return 0; } @@ -149,7 +159,9 @@ static int imx_gpio_port_clear_bits_raw(const struct device *port, const struct imx_gpio_config *config = port->config; GPIO_Type *base = config->base; + unsigned int key = irq_lock(); GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) & ~pins); + irq_unlock(key); return 0; } @@ -160,7 +172,9 @@ static int imx_gpio_port_toggle_bits(const struct device *port, const struct imx_gpio_config *config = port->config; GPIO_Type *base = config->base; + unsigned int key = irq_lock(); GPIO_WritePortOutput(base, GPIO_ReadPortInput(base) ^ pins); + irq_unlock(key); return 0; } @@ -232,7 +246,7 @@ static void imx_gpio_port_isr(const struct device *port) struct imx_gpio_data *data = port->data; uint32_t int_status; - int_status = config->base->ISR; + int_status = config->base->ISR & config->base->IMR; config->base->ISR = int_status; diff --git a/drivers/gpio/gpio_iproc.c b/drivers/gpio/gpio_iproc.c new file mode 100644 index 0000000000000..def1a07dd4ea8 --- /dev/null +++ b/drivers/gpio/gpio_iproc.c @@ -0,0 +1,225 @@ +/* + * Copyright 2020 Broadcom + * Copyright 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT brcm_iproc_gpio + +#include +#include +#include +#include +#include +#include + +#define IPROC_GPIO_DATA_IN_OFFSET 0x00 +#define IPROC_GPIO_DATA_OUT_OFFSET 0x04 +#define IPROC_GPIO_OUT_EN_OFFSET 0x08 +#define IPROC_GPIO_INT_TYPE_OFFSET 0x0c +#define IPROC_GPIO_INT_DE_OFFSET 0x10 +#define IPROC_GPIO_INT_EDGE_OFFSET 0x14 +#define IPROC_GPIO_INT_MSK_OFFSET 0x18 +#define IPROC_GPIO_INT_STAT_OFFSET 0x1c +#define IPROC_GPIO_INT_MSTAT_OFFSET 0x20 +#define IPROC_GPIO_INT_CLR_OFFSET 0x24 +#define IPROC_GPIO_PAD_RES_OFFSET 0x34 +#define IPROC_GPIO_RES_EN_OFFSET 0x38 + +struct gpio_iproc_config { + /* gpio_driver_config needs to be first */ + struct gpio_driver_config common; + mem_addr_t base; + void (*irq_config_func)(const struct device *dev); +}; + +struct gpio_iproc_data { + /* gpio_driver_data needs to be first */ + struct gpio_driver_data common; + sys_slist_t cb; +}; + +#define DEV_CFG(dev) ((const struct gpio_iproc_config *const)(dev)->config) +#define DEV_DATA(dev) ((struct gpio_iproc_data *const)(dev)->data) + +static int gpio_iproc_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + /* Setup the pin direcion. */ + if (flags & GPIO_OUTPUT) { + /* configure pin for output */ + sys_set_bit(base + IPROC_GPIO_OUT_EN_OFFSET, pin); + } else if (flags & GPIO_INPUT) { + /* configure pin for input */ + sys_clear_bit(base + IPROC_GPIO_OUT_EN_OFFSET, pin); + } + + return 0; +} + +static int gpio_iproc_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + *value = sys_read32(base + IPROC_GPIO_DATA_IN_OFFSET); + + return 0; +} + +static int gpio_iproc_port_set_masked_raw(const struct device *dev, uint32_t mask, uint32_t value) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + value = sys_read32(base + IPROC_GPIO_DATA_OUT_OFFSET); + value = (value & (~mask)) | (value & mask); + sys_write32(base + IPROC_GPIO_DATA_OUT_OFFSET, value); + + return 0; +} + +static int gpio_iproc_port_set_bits_raw(const struct device *dev, uint32_t mask) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + sys_write32(base + IPROC_GPIO_DATA_OUT_OFFSET, mask); + + return 0; +} + +static int gpio_iproc_port_clear_bits_raw(const struct device *dev, uint32_t mask) +{ + uint32_t value; + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + /* Clear pins. */ + value = sys_read32(base + IPROC_GPIO_DATA_OUT_OFFSET); + value = (value & ~mask); + sys_write32(base + IPROC_GPIO_DATA_OUT_OFFSET, value); + + return 0; +} + +static int gpio_iproc_port_toggle_bits(const struct device *dev, uint32_t mask) +{ + uint32_t value; + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + /* toggles pins. */ + value = sys_read32(base + IPROC_GPIO_DATA_OUT_OFFSET); + value = (value ^ mask); + sys_write32(base + IPROC_GPIO_DATA_OUT_OFFSET, value); + + return 0; +} + +static int gpio_iproc_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + + /* check for interrupt configurations */ + if (mode & GPIO_INT_ENABLE) { + if (mode & GPIO_INT_EDGE) { + sys_clear_bit(base + IPROC_GPIO_INT_TYPE_OFFSET, pin); + } else { + sys_set_bit(base + IPROC_GPIO_INT_TYPE_OFFSET, pin); + } + + /* Generate interrupt of both falling/rising edge */ + if (trig & GPIO_INT_EDGE_BOTH) { + sys_set_bit(base + IPROC_GPIO_INT_DE_OFFSET, pin); + } else if (trig & GPIO_INT_HIGH_1) { + /* Generate interrupt on rising edge */ + sys_clear_bit(base + IPROC_GPIO_INT_DE_OFFSET, pin); + sys_set_bit(base + IPROC_GPIO_INT_EDGE_OFFSET, pin); + } else if (trig & GPIO_INT_LOW_0) { + /* Generate interrupt on falling edge */ + sys_clear_bit(base + IPROC_GPIO_INT_DE_OFFSET, pin); + sys_clear_bit(base + IPROC_GPIO_INT_EDGE_OFFSET, pin); + } + + /* Unmask the interrupt */ + sys_clear_bit(base + IPROC_GPIO_INT_MSTAT_OFFSET, pin); + } else { + sys_set_bit(base + IPROC_GPIO_INT_MSK_OFFSET, pin); + } + return 0; +} + +static void gpio_iproc_isr(const struct device *dev) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + mem_addr_t base = cfg->base; + struct gpio_iproc_data *context = dev->data; + uint32_t int_stat; + + int_stat = sys_read32(base + IPROC_GPIO_INT_STAT_OFFSET); + + /* Clear the source of the interrupt */ + sys_write32(int_stat, base + IPROC_GPIO_INT_CLR_OFFSET); + + /* Handle the interrupt */ + gpio_fire_callbacks(&context->cb, dev, int_stat); +} + +static int gpio_iproc_manage_callback(const struct device *port, struct gpio_callback *callback, + bool set) +{ + struct gpio_iproc_data *context = port->data; + + return gpio_manage_callback(&context->cb, callback, set); +} + +static const struct gpio_driver_api gpio_iproc_api = { + .pin_configure = gpio_iproc_configure, + .port_get_raw = gpio_iproc_port_get_raw, + .port_set_masked_raw = gpio_iproc_port_set_masked_raw, + .port_set_bits_raw = gpio_iproc_port_set_bits_raw, + .port_clear_bits_raw = gpio_iproc_port_clear_bits_raw, + .port_toggle_bits = gpio_iproc_port_toggle_bits, + .pin_interrupt_configure = gpio_iproc_pin_interrupt_configure, + .manage_callback = gpio_iproc_manage_callback, +}; + +int gpio_iproc_init(const struct device *dev) +{ + const struct gpio_iproc_config *const cfg = DEV_CFG(dev); + + cfg->irq_config_func(dev); + + return 0; +} + +#define GPIO_IPROC_INIT(n) \ + static void port_iproc_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), gpio_iproc_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct gpio_iproc_config gpio_port_config_##n = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ + }, \ + .base = DT_INST_REG_ADDR(n), \ + .irq_config_func = port_iproc_config_func_##n, \ + }; \ + \ + static struct gpio_iproc_data gpio_port_data_##n; \ + \ + DEVICE_DT_INST_DEFINE(n, gpio_iproc_init, NULL, &gpio_port_data_##n, \ + &gpio_port_config_##n, POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_iproc_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_IPROC_INIT) diff --git a/drivers/gpio/gpio_lmp90xxx.c b/drivers/gpio/gpio_lmp90xxx.c index 2514ef35211ce..55dd01de978f7 100644 --- a/drivers/gpio/gpio_lmp90xxx.c +++ b/drivers/gpio/gpio_lmp90xxx.c @@ -161,7 +161,7 @@ BUILD_ASSERT(CONFIG_GPIO_LMP90XXX_INIT_PRIORITY > static struct gpio_lmp90xxx_data gpio_lmp90xxx_##id##_data; \ \ DEVICE_DT_INST_DEFINE(id, \ - &gpio_lmp90xxx_init, \ + gpio_lmp90xxx_init, \ NULL, \ &gpio_lmp90xxx_##id##_data, \ &gpio_lmp90xxx_##id##_cfg, POST_KERNEL, \ diff --git a/drivers/gpio/gpio_max32.c b/drivers/gpio/gpio_max32.c new file mode 100644 index 0000000000000..66f5d155a7a7a --- /dev/null +++ b/drivers/gpio/gpio_max32.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define DT_DRV_COMPAT adi_max32_gpio + +LOG_MODULE_REGISTER(gpio_max32, CONFIG_GPIO_LOG_LEVEL); + +struct max32_gpio_config { + struct gpio_driver_config common; + mxc_gpio_regs_t *regs; + const struct device *clock; + void (*irq_func)(void); + struct max32_perclk perclk; +}; + +struct max32_gpio_data { + struct gpio_driver_data common; + sys_slist_t cb_list; +}; + +static int api_port_get_raw(const struct device *dev, uint32_t *value) +{ + const struct max32_gpio_config *cfg = dev->config; + + *value = MXC_GPIO_InGet(cfg->regs, (unsigned int)-1); + return 0; +} + +static int api_port_set_masked_raw(const struct device *dev, gpio_port_pins_t mask, + gpio_port_value_t value) +{ + const struct max32_gpio_config *cfg = dev->config; + + MXC_GPIO_OutPut(cfg->regs, mask, value); + return 0; +} + +static int api_port_set_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct max32_gpio_config *cfg = dev->config; + + MXC_GPIO_OutSet(cfg->regs, pins); + return 0; +} + +static int api_port_clear_bits_raw(const struct device *dev, gpio_port_pins_t pins) +{ + const struct max32_gpio_config *cfg = dev->config; + + MXC_GPIO_OutClr(cfg->regs, pins); + return 0; +} + +static int api_port_toggle_bits(const struct device *dev, gpio_port_pins_t pins) +{ + const struct max32_gpio_config *cfg = dev->config; + + MXC_GPIO_OutToggle(cfg->regs, pins); + return 0; +} + +static int api_pin_configure(const struct device *dev, gpio_pin_t pin, gpio_flags_t flags) +{ + const struct max32_gpio_config *cfg = dev->config; + mxc_gpio_cfg_t gpio_cfg; + int ret; + + /* MAX32xxx MCUs does not support SINGLE_ENDED, open drain, mode */ + if (flags & GPIO_SINGLE_ENDED) { + return -ENOTSUP; + } + + gpio_cfg.port = cfg->regs; + gpio_cfg.mask = BIT(pin); + + if (flags & GPIO_PULL_UP) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_UP; + } else if (flags & GPIO_PULL_DOWN) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_DOWN; + } else if (flags & MAX32_GPIO_WEAK_PULL_UP) { + gpio_cfg.pad = MXC_GPIO_PAD_WEAK_PULL_UP; + } else if (flags & MAX32_GPIO_WEAK_PULL_DOWN) { + gpio_cfg.pad = MXC_GPIO_PAD_WEAK_PULL_DOWN; + } else { + gpio_cfg.pad = MXC_GPIO_PAD_NONE; + } + + if (flags & GPIO_OUTPUT) { + gpio_cfg.func = MXC_GPIO_FUNC_OUT; + } else if (flags & GPIO_INPUT) { + gpio_cfg.func = MXC_GPIO_FUNC_IN; + } else { + /* this case will not occur this function call for gpio mode in/out */ + gpio_cfg.func = MXC_GPIO_FUNC_ALT1; /* TODO: Think on it */ + } + + if (flags & MAX32_GPIO_VSEL_VDDIOH) { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIOH; + } else { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIO; + } + + switch (flags & MAX32_GPIO_DRV_STRENGTH_MASK) { + case MAX32_GPIO_DRV_STRENGTH_1: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_1; + break; + case MAX32_GPIO_DRV_STRENGTH_2: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_2; + break; + case MAX32_GPIO_DRV_STRENGTH_3: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_3; + break; + default: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_0; + break; + } + + ret = MXC_GPIO_Config(&gpio_cfg); + if (ret != 0) { + return -ENOTSUP; + } + + if (flags & GPIO_OUTPUT) { + if (flags & GPIO_OUTPUT_INIT_LOW) { + MXC_GPIO_OutClr(cfg->regs, BIT(pin)); + } else if (flags & GPIO_OUTPUT_INIT_HIGH) { + MXC_GPIO_OutSet(cfg->regs, BIT(pin)); + } + } + + return 0; +} + +static int api_pin_interrupt_configure(const struct device *dev, gpio_pin_t pin, + enum gpio_int_mode mode, enum gpio_int_trig trig) +{ + const struct max32_gpio_config *cfg = dev->config; + mxc_gpio_cfg_t gpio_cfg; + + gpio_cfg.port = cfg->regs; + gpio_cfg.mask = BIT(pin); + /* rest of the parameters not necessary */ + + if (mode == GPIO_INT_MODE_DISABLED) { + MXC_GPIO_DisableInt(cfg->regs, gpio_cfg.mask); + + /* clear interrupt flags */ + MXC_GPIO_ClearFlags(cfg->regs, (MXC_GPIO_GetFlags(cfg->regs) & gpio_cfg.mask)); + + return 0; + } + + switch (mode) { + case GPIO_INT_MODE_LEVEL: + if (trig == GPIO_INT_TRIG_LOW) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_LOW); + } else if (trig == GPIO_INT_TRIG_HIGH) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_HIGH); + } else if (trig == GPIO_INT_TRIG_BOTH) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_BOTH); + } else { + return -EINVAL; + } + break; + case GPIO_INT_MODE_EDGE: + if (trig == GPIO_INT_TRIG_LOW) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_FALLING); + } else if (trig == GPIO_INT_TRIG_HIGH) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_RISING); + } else if (trig == GPIO_INT_TRIG_BOTH) { + MXC_GPIO_IntConfig(&gpio_cfg, MXC_GPIO_INT_BOTH); + } else { + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + cfg->irq_func(); + MXC_GPIO_EnableInt(cfg->regs, gpio_cfg.mask); + + return 0; +} + +static int api_manage_callback(const struct device *dev, struct gpio_callback *callback, bool set) +{ + struct max32_gpio_data *data = dev->data; + + return gpio_manage_callback(&(data->cb_list), callback, set); +} + +static const struct gpio_driver_api gpio_max32_driver = { + .pin_configure = api_pin_configure, + .port_get_raw = api_port_get_raw, + .port_set_masked_raw = api_port_set_masked_raw, + .port_set_bits_raw = api_port_set_bits_raw, + .port_clear_bits_raw = api_port_clear_bits_raw, + .port_toggle_bits = api_port_toggle_bits, + .pin_interrupt_configure = api_pin_interrupt_configure, + .manage_callback = api_manage_callback, +}; + +static void gpio_max32_isr(const void *param) +{ + const struct device *dev = param; + const struct max32_gpio_config *cfg = dev->config; + struct max32_gpio_data *data = dev->data; + + unsigned int flags = MXC_GPIO_GetFlags(cfg->regs); + /* clear interrupt flags */ + MXC_GPIO_ClearFlags(cfg->regs, flags); + + gpio_fire_callbacks(&(data->cb_list), dev, flags); +} + +static int gpio_max32_init(const struct device *dev) +{ + int ret = 0; + const struct max32_gpio_config *cfg = dev->config; + + if (cfg->clock != NULL) { + /* enable clock */ + ret = clock_control_on(cfg->clock, (clock_control_subsys_t)&cfg->perclk); + if (ret != 0) { + LOG_ERR("cannot enable GPIO clock"); + return ret; + } + } + + return ret; +} + +#define MAX32_GPIO_INIT(_num) \ + static void gpio_max32_irq_init_##_num(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(_num), DT_INST_IRQ(_num, priority), gpio_max32_isr, \ + DEVICE_DT_INST_GET(_num), 0); \ + irq_enable(DT_INST_IRQN(_num)); \ + } \ + static struct max32_gpio_data max32_gpio_data_##_num; \ + static const struct max32_gpio_config max32_gpio_config_##_num = { \ + .common = \ + { \ + .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(_num), \ + }, \ + .regs = (mxc_gpio_regs_t *)DT_INST_REG_ADDR(_num), \ + .irq_func = &gpio_max32_irq_init_##_num, \ + .clock = DEVICE_DT_GET_OR_NULL(DT_INST_CLOCKS_CTLR(_num)), \ + .perclk.bus = DT_INST_PHA_BY_IDX_OR(_num, clocks, 0, offset, 0), \ + .perclk.bit = DT_INST_PHA_BY_IDX_OR(_num, clocks, 1, bit, 0), \ + }; \ + DEVICE_DT_INST_DEFINE(_num, gpio_max32_init, NULL, &max32_gpio_data_##_num, \ + &max32_gpio_config_##_num, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ + (void *)&gpio_max32_driver); + +DT_INST_FOREACH_STATUS_OKAY(MAX32_GPIO_INIT) diff --git a/drivers/gpio/gpio_mcux.c b/drivers/gpio/gpio_mcux.c index 8fa48abc8c675..f7d15e3cf0cba 100644 --- a/drivers/gpio/gpio_mcux.c +++ b/drivers/gpio/gpio_mcux.c @@ -332,6 +332,40 @@ static void gpio_mcux_port_isr(const struct device *dev) gpio_fire_callbacks(&data->callbacks, dev, int_status); } +#define GPIO_HAS_SHARED_IRQ DT_HAS_COMPAT_STATUS_OKAY(nxp_gpio_cluster) + +#if GPIO_HAS_SHARED_IRQ +static void gpio_mcux_shared_cluster_isr(const struct device *ports[]) +{ + const struct device **current_port = &ports[0]; + + while (*current_port != NULL) { + gpio_mcux_port_isr(*current_port); + current_port++; + } +} + +#define CLUSTER_ARRAY_ELEMENT(node_id) DEVICE_DT_GET(node_id), + +#define GPIO_MCUX_CLUSTER_INIT(node_id) \ + const struct device *shared_array##node_id[DT_CHILD_NUM_STATUS_OKAY(node_id) + 1] = \ + {DT_FOREACH_CHILD_STATUS_OKAY(node_id, CLUSTER_ARRAY_ELEMENT) NULL}; \ + \ + static int gpio_mcux_shared_interrupt_init##node_id(void) \ + { \ + IRQ_CONNECT(DT_IRQN(node_id), \ + DT_IRQ(node_id, priority), \ + gpio_mcux_shared_cluster_isr, \ + shared_array##node_id, 0); \ + irq_enable(DT_IRQN(node_id)); \ + \ + return 0; \ + } \ + SYS_INIT(gpio_mcux_shared_interrupt_init##node_id, POST_KERNEL, 0); + +DT_FOREACH_STATUS_OKAY(nxp_gpio_cluster, GPIO_MCUX_CLUSTER_INIT) +#endif + #ifdef CONFIG_GPIO_GET_DIRECTION static int gpio_mcux_port_get_direction(const struct device *dev, gpio_port_pins_t map, gpio_port_pins_t *inputs, gpio_port_pins_t *outputs) @@ -388,7 +422,8 @@ static const struct gpio_driver_api gpio_mcux_driver_api = { }, \ .gpio_base = (GPIO_Type *) DT_INST_REG_ADDR(n), \ .port_base = (PORT_Type *) GPIO_PORT_BASE_ADDR(n), \ - .flags = UTIL_AND(DT_INST_IRQ_HAS_IDX(n, 0), GPIO_INT_ENABLE),\ + .flags = UTIL_AND(UTIL_OR(DT_INST_IRQ_HAS_IDX(n, 0), \ + GPIO_HAS_SHARED_IRQ), GPIO_INT_ENABLE), \ }; \ \ static struct gpio_mcux_data gpio_mcux_port## n ##_data; \ diff --git a/drivers/gpio/gpio_mcux_lpc.c b/drivers/gpio/gpio_mcux_lpc.c index 8895a984dc28d..7c6550e761723 100644 --- a/drivers/gpio/gpio_mcux_lpc.c +++ b/drivers/gpio/gpio_mcux_lpc.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT nxp_lpc_gpio +#define DT_DRV_COMPAT nxp_lpc_gpio_port /** @file * @brief GPIO driver for LPC54XXX family @@ -457,10 +457,10 @@ static const struct gpio_driver_api gpio_mcux_lpc_driver_api = { .common = { \ .port_pin_mask = GPIO_PORT_PIN_MASK_FROM_DT_INST(n), \ }, \ - .gpio_base = GPIO, \ + .gpio_base = (GPIO_Type *)DT_REG_ADDR(DT_INST_PARENT(n)), \ .pinmux_base = PINMUX_BASE, \ .int_source = DT_INST_ENUM_IDX(n, int_source), \ - .port_no = DT_INST_PROP(n, port) \ + .port_no = DT_INST_REG_ADDR(n) \ }; \ \ static struct gpio_mcux_lpc_data gpio_mcux_lpc_data_##n; \ diff --git a/drivers/gpio/gpio_neorv32.c b/drivers/gpio/gpio_neorv32.c index b14c51c147173..21bd6fe85ef63 100644 --- a/drivers/gpio/gpio_neorv32.c +++ b/drivers/gpio/gpio_neorv32.c @@ -221,7 +221,7 @@ static const struct gpio_driver_api neorv32_gpio_driver_api = { }; \ \ DEVICE_DT_INST_DEFINE(n, \ - &neorv32_gpio_init, \ + neorv32_gpio_init, \ NULL, \ &neorv32_gpio_##n##_data, \ &neorv32_gpio_##n##_config, \ diff --git a/drivers/gpio/gpio_npm1300.c b/drivers/gpio/gpio_npm1300.c index 0018530207d92..96725b61ddf3f 100644 --- a/drivers/gpio/gpio_npm1300.c +++ b/drivers/gpio/gpio_npm1300.c @@ -222,7 +222,7 @@ static int gpio_npm1300_init(const struct device *dev) \ static struct gpio_npm1300_data gpio_npm1300_data##n; \ \ - DEVICE_DT_INST_DEFINE(n, &gpio_npm1300_init, NULL, &gpio_npm1300_data##n, \ + DEVICE_DT_INST_DEFINE(n, gpio_npm1300_init, NULL, &gpio_npm1300_data##n, \ &gpio_npm1300_config##n, POST_KERNEL, \ CONFIG_GPIO_NPM1300_INIT_PRIORITY, &gpio_npm1300_api); diff --git a/drivers/gpio/gpio_npm6001.c b/drivers/gpio/gpio_npm6001.c index f722c4275d6e9..b69df1f369ae2 100644 --- a/drivers/gpio/gpio_npm6001.c +++ b/drivers/gpio/gpio_npm6001.c @@ -223,7 +223,7 @@ static int gpio_npm6001_init(const struct device *dev) \ static struct gpio_npm6001_data gpio_npm6001_data##n; \ \ - DEVICE_DT_INST_DEFINE(n, &gpio_npm6001_init, NULL, \ + DEVICE_DT_INST_DEFINE(n, gpio_npm6001_init, NULL, \ &gpio_npm6001_data##n, &gpio_npm6001_config##n, \ POST_KERNEL, CONFIG_GPIO_NPM6001_INIT_PRIORITY, \ &gpio_npm6001_api); diff --git a/drivers/gpio/gpio_numaker.c b/drivers/gpio/gpio_numaker.c index 3a1c8ad8eeefd..a4fe054221782 100644 --- a/drivers/gpio/gpio_numaker.c +++ b/drivers/gpio/gpio_numaker.c @@ -52,21 +52,6 @@ static int gpio_numaker_configure(const struct device *dev, gpio_pin_t pin, gpio return -EINVAL; } - SYS_UnlockReg(); - - /* Enable GPIO clock */ - struct numaker_scc_subsys scc_subsys; - - memset(&scc_subsys, 0x00, sizeof(scc_subsys)); - scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC; - scc_subsys.pcc.clk_modidx = config->clk_modidx; - - /* Equivalent to CLK_EnableModuleClock(config->clk_modidx) */ - err = clock_control_on(config->clk_dev, (clock_control_subsys_t)&scc_subsys); - if (err != 0) { - goto move_exit; - } - /* Configure GPIO direction */ switch (flags & GPIO_DIR_MASK) { case GPIO_INPUT: @@ -114,7 +99,6 @@ static int gpio_numaker_configure(const struct device *dev, gpio_pin_t pin, gpio } move_exit: - SYS_LockReg(); return err; } @@ -265,10 +249,23 @@ static void gpio_numaker_isr(const struct device *dev) \ static int gpio_numaker_init##n(const struct device *dev) \ { \ - IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), (GPIO_NUMAKER_IRQ_INIT(n);)) \ - return 0; \ + const struct gpio_numaker_config *config = dev->config; \ + struct numaker_scc_subsys scc_subsys; \ + int err; \ + \ + SYS_UnlockReg(); \ + memset(&scc_subsys, 0x00, sizeof(scc_subsys)); \ + scc_subsys.subsys_id = NUMAKER_SCC_SUBSYS_ID_PCC; \ + scc_subsys.pcc.clk_modidx = config->clk_modidx; \ + err = clock_control_on(config->clk_dev, (clock_control_subsys_t)&scc_subsys); \ + if (err == 0) { \ + IF_ENABLED(DT_INST_IRQ_HAS_IDX(n, 0), (GPIO_NUMAKER_IRQ_INIT(n);)) \ + } \ + \ + SYS_LockReg(); \ + return err; \ } \ - DEVICE_DT_INST_DEFINE(n, &gpio_numaker_init##n, NULL, &gpio_numaker_data##n, \ + DEVICE_DT_INST_DEFINE(n, gpio_numaker_init##n, NULL, &gpio_numaker_data##n, \ &gpio_numaker_config##n, PRE_KERNEL_1, CONFIG_GPIO_INIT_PRIORITY, \ &gpio_numaker_api); diff --git a/drivers/gpio/gpio_pcal64xxa.c b/drivers/gpio/gpio_pcal64xxa.c index 687cf53c1bf26..93cc4814993e5 100644 --- a/drivers/gpio/gpio_pcal64xxa.c +++ b/drivers/gpio/gpio_pcal64xxa.c @@ -204,6 +204,7 @@ static int pcal64xxa_process_input(const struct device *dev, gpio_port_value_t * if (rc != 0) { LOG_ERR("failed to read inputs from device %s", dev->name); + k_sem_give(&drv_data->lock); return rc; } diff --git a/drivers/gpio/gpio_sedi.c b/drivers/gpio/gpio_sedi.c index 806ec422c95d8..d4d273d6d6d8a 100644 --- a/drivers/gpio/gpio_sedi.c +++ b/drivers/gpio/gpio_sedi.c @@ -331,7 +331,7 @@ static int gpio_sedi_init(const struct device *dev) }; \ PM_DEVICE_DEFINE(gpio_##n, gpio_sedi_pm_action); \ DEVICE_DT_INST_DEFINE(n, \ - &gpio_sedi_init, \ + gpio_sedi_init, \ PM_DEVICE_GET(gpio_##n), \ &gpio##n##_data, \ &gpio##n##_config, \ diff --git a/drivers/gpio/gpio_shell.c b/drivers/gpio/gpio_shell.c index 48d7e95f7a752..1460eadafb033 100644 --- a/drivers/gpio/gpio_shell.c +++ b/drivers/gpio/gpio_shell.c @@ -134,16 +134,43 @@ DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_PIN_GET) static const struct gpio_ctrl gpio_list[] = {DT_FOREACH_STATUS_OKAY_NODE(IS_GPIO_CTRL_LIST)}; -static const struct gpio_ctrl *get_gpio_ctrl(char *name) +static const struct gpio_ctrl *get_gpio_ctrl_helper(const struct device *dev) { - const struct device *dev = device_get_binding(name); size_t i; + if (dev == NULL) { + return NULL; + } + for (i = 0; i < ARRAY_SIZE(gpio_list); i++) { if (gpio_list[i].dev == dev) { return &gpio_list[i]; } } + + return NULL; +} + +/* Look up a device by some human-readable string identifier. We + * always search among device names. If the feature is available, we + * search by node label as well. + */ +static const struct gpio_ctrl *get_gpio_ctrl(char *id) +{ + const struct gpio_ctrl *ctrl; + + ctrl = get_gpio_ctrl_helper(device_get_binding(id)); + if (ctrl != NULL) { + return ctrl; + } + +#ifdef CONFIG_DEVICE_DT_METADATA + ctrl = get_gpio_ctrl_helper(device_get_by_dt_nodelabel(id)); + if (ctrl != NULL) { + return ctrl; + } +#endif /* CONFIG_DEVICE_DT_METADATA */ + return NULL; } @@ -381,6 +408,55 @@ static int cmd_gpio_set(const struct shell *sh, size_t argc, char **argv) return 0; } +static int cmd_gpio_toggle(const struct shell *sh, size_t argc, char **argv) +{ + struct sh_gpio gpio; + int ret = 0; + + ret = get_sh_gpio(sh, argv, &gpio); + if (ret != 0) { + shell_help(sh); + return SHELL_CMD_HELP_PRINTED; + } + + ret = gpio_pin_toggle(gpio.dev, gpio.pin); + if (ret != 0) { + shell_error(sh, "error: %d", ret); + return ret; + } + + return 0; +} + +static int cmd_gpio_devices(const struct shell *sh, size_t argc, char **argv) +{ + size_t i; + + shell_fprintf(sh, SHELL_NORMAL, "%-16s Other names\n", "Device"); + + for (i = 0; i < ARRAY_SIZE(gpio_list); i++) { + const struct device *dev = gpio_list[i].dev; + + shell_fprintf(sh, SHELL_NORMAL, "%-16s", dev->name); + +#ifdef CONFIG_DEVICE_DT_METADATA + const struct device_dt_nodelabels *nl = device_get_dt_nodelabels(dev); + + if (nl->num_nodelabels > 0) { + for (size_t j = 0; j < nl->num_nodelabels; j++) { + const char *nodelabel = nl->nodelabels[j]; + + shell_fprintf(sh, SHELL_NORMAL, " %s", nodelabel); + } + } +#endif + + shell_fprintf(sh, SHELL_NORMAL, "\n"); + } + + return 0; +} + /* 500 msec = 1/2 sec */ #define SLEEP_TIME_MS 500 @@ -595,6 +671,12 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_gpio, SHELL_CMD_ARG(set, &sub_gpio_dev, "Set GPIO pin value\n" "Usage: gpio set ", cmd_gpio_set, 4, 0), + SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_TOGGLE_CMD, toggle, &sub_gpio_dev, + "Toggle GPIO pin\n" + "Usage: gpio toggle ", cmd_gpio_toggle, 3, 0), + SHELL_CMD(devices, NULL, + "List all GPIO devices\n" + "Usage: gpio devices", cmd_gpio_devices), SHELL_COND_CMD_ARG(CONFIG_GPIO_SHELL_BLINK_CMD, blink, &sub_gpio_dev, "Blink GPIO pin\n" "Usage: gpio blink ", cmd_gpio_blink, 3, 0), diff --git a/drivers/gpio/gpio_stm32.c b/drivers/gpio/gpio_stm32.c index d835c3454ccb8..4c147ff486ce3 100644 --- a/drivers/gpio/gpio_stm32.c +++ b/drivers/gpio/gpio_stm32.c @@ -22,11 +22,17 @@ #include #include #include +#include +#include #include "stm32_hsem.h" #include "gpio_stm32.h" #include +#include + +LOG_MODULE_REGISTER(stm32, CONFIG_GPIO_LOG_LEVEL); + /** * @brief Common GPIO driver for STM32 MCUs. */ @@ -270,7 +276,7 @@ static void gpio_stm32_configure_raw(const struct device *dev, int pin, static int gpio_stm32_clock_request(const struct device *dev, bool on) { const struct gpio_stm32_config *cfg = dev->config; - int ret = 0; + int ret; __ASSERT_NO_MSG(dev != NULL); @@ -285,10 +291,6 @@ static int gpio_stm32_clock_request(const struct device *dev, bool on) (clock_control_subsys_t)&cfg->pclken); } - if (ret != 0) { - return ret; - } - return ret; } @@ -299,11 +301,16 @@ static inline uint32_t gpio_stm32_pin_to_exti_line(int pin) return ((pin % 4 * 4) << 16) | (pin / 4); #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) return ((pin & 0x3) << (16 + 3)) | (pin >> 2); +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti) + /* Gives the LL_SBS_EXTI_LINEn corresponding to the pin */ + return (((pin % 4 * 4) << LL_SBS_REGISTER_PINPOS_SHFT) | (pin / 4)); #else return (0xF << ((pin % 4 * 4) + 16)) | (pin / 4); #endif } + +/* Set the EXTI line corresponding to the PORT [STM32_PORTA .. ] and pin [0..15] */ static void gpio_stm32_set_exti_source(int port, int pin) { uint32_t line = gpio_stm32_pin_to_exti_line(pin); @@ -326,12 +333,15 @@ static void gpio_stm32_set_exti_source(int port, int pin) #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) LL_EXTI_SetEXTISource(port, line); +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti) + LL_SBS_SetEXTISource(port, line); #else LL_SYSCFG_SetEXTISource(port, line); #endif z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID); } +/* Gives the PORT [STM32_PORTA .. ] corresponding to the EXTI line of the pin [0..15] */ static int gpio_stm32_get_exti_source(int pin) { uint32_t line = gpio_stm32_pin_to_exti_line(pin); @@ -341,6 +351,8 @@ static int gpio_stm32_get_exti_source(int pin) port = LL_GPIO_AF_GetEXTISource(line); #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) port = LL_EXTI_GetEXTISource(line); +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7rs_exti) + port = LL_SBS_GetEXTISource(line); #else port = LL_SYSCFG_GetEXTISource(line); #endif @@ -369,14 +381,18 @@ static int gpio_stm32_enable_int(int port, int pin) defined(CONFIG_SOC_SERIES_STM32F4X) || \ defined(CONFIG_SOC_SERIES_STM32F7X) || \ defined(CONFIG_SOC_SERIES_STM32H7X) || \ + defined(CONFIG_SOC_SERIES_STM32H7RSX) || \ defined(CONFIG_SOC_SERIES_STM32L1X) || \ defined(CONFIG_SOC_SERIES_STM32L4X) || \ defined(CONFIG_SOC_SERIES_STM32G4X) const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); struct stm32_pclken pclken = { -#ifdef CONFIG_SOC_SERIES_STM32H7X +#if defined(CONFIG_SOC_SERIES_STM32H7X) .bus = STM32_CLOCK_BUS_APB4, .enr = LL_APB4_GRP1_PERIPH_SYSCFG +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) + .bus = STM32_CLOCK_BUS_APB4, + .enr = LL_APB4_GRP1_PERIPH_SBS #else .bus = STM32_CLOCK_BUS_APB2, .enr = LL_APB2_GRP1_PERIPH_SYSCFG @@ -541,6 +557,25 @@ static int gpio_stm32_config(const struct device *dev, gpio_stm32_configure_raw(dev, pin, pincfg, 0); +#ifdef CONFIG_STM32_WKUP_PINS + if (flags & STM32_GPIO_WKUP) { +#ifdef CONFIG_POWEROFF + struct gpio_dt_spec gpio_dt_cfg = { + .port = dev, + .pin = pin, + .dt_flags = (gpio_dt_flags_t)flags, + }; + + if (stm32_pwr_wkup_pin_cfg_gpio((const struct gpio_dt_spec *)&gpio_dt_cfg)) { + LOG_ERR("Could not configure GPIO %s pin %d as a wake-up source", + gpio_dt_cfg.port->name, gpio_dt_cfg.pin); + } +#else + LOG_DBG("STM32_GPIO_WKUP flag has no effect when CONFIG_POWEROFF=n"); +#endif /* CONFIG_POWEROFF */ + } +#endif /* CONFIG_STM32_WKUP_PINS */ + /* Release clock only if pin is disconnected */ if (((flags & GPIO_OUTPUT) == 0) && ((flags & GPIO_INPUT) == 0)) { err = pm_device_runtime_put(dev); @@ -760,46 +795,24 @@ static int gpio_stm32_init(const struct device *dev) DT_CLOCKS_CELL(DT_NODELABEL(gpio##__suffix), bits),\ DT_CLOCKS_CELL(DT_NODELABEL(gpio##__suffix), bus)) -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) -GPIO_DEVICE_INIT_STM32(a, A); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioa), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) -GPIO_DEVICE_INIT_STM32(b, B); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiob), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioc), okay) -GPIO_DEVICE_INIT_STM32(c, C); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioc), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiod), okay) -GPIO_DEVICE_INIT_STM32(d, D); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiod), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioe), okay) -GPIO_DEVICE_INIT_STM32(e, E); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioe), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiof), okay) -GPIO_DEVICE_INIT_STM32(f, F); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiof), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiog), okay) -GPIO_DEVICE_INIT_STM32(g, G); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiog), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioh), okay) -GPIO_DEVICE_INIT_STM32(h, H); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioh), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioi), okay) -GPIO_DEVICE_INIT_STM32(i, I); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioi), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpioj), okay) -GPIO_DEVICE_INIT_STM32(j, J); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpioj), okay) */ - -#if DT_NODE_HAS_STATUS(DT_NODELABEL(gpiok), okay) -GPIO_DEVICE_INIT_STM32(k, K); -#endif /* DT_NODE_HAS_STATUS(DT_NODELABEL(gpiok), okay) */ +#define GPIO_DEVICE_INIT_STM32_IF_OKAY(__suffix, __SUFFIX) \ + COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(gpio##__suffix), okay), \ + (GPIO_DEVICE_INIT_STM32(__suffix, __SUFFIX)), \ + ()) + +GPIO_DEVICE_INIT_STM32_IF_OKAY(a, A); +GPIO_DEVICE_INIT_STM32_IF_OKAY(b, B); +GPIO_DEVICE_INIT_STM32_IF_OKAY(c, C); +GPIO_DEVICE_INIT_STM32_IF_OKAY(d, D); +GPIO_DEVICE_INIT_STM32_IF_OKAY(e, E); +GPIO_DEVICE_INIT_STM32_IF_OKAY(f, F); +GPIO_DEVICE_INIT_STM32_IF_OKAY(g, G); +GPIO_DEVICE_INIT_STM32_IF_OKAY(h, H); +GPIO_DEVICE_INIT_STM32_IF_OKAY(i, I); +GPIO_DEVICE_INIT_STM32_IF_OKAY(j, J); +GPIO_DEVICE_INIT_STM32_IF_OKAY(k, K); + +GPIO_DEVICE_INIT_STM32_IF_OKAY(m, M); +GPIO_DEVICE_INIT_STM32_IF_OKAY(n, N); +GPIO_DEVICE_INIT_STM32_IF_OKAY(o, O); +GPIO_DEVICE_INIT_STM32_IF_OKAY(p, P); diff --git a/drivers/gpio/gpio_stm32.h b/drivers/gpio/gpio_stm32.h index 5e9da057ea95a..9aa83a546e972 100644 --- a/drivers/gpio/gpio_stm32.h +++ b/drivers/gpio/gpio_stm32.h @@ -100,6 +100,20 @@ #define STM32_PERIPH_GPIOI LL_AHB4_GRP1_PERIPH_GPIOI #define STM32_PERIPH_GPIOJ LL_AHB4_GRP1_PERIPH_GPIOJ #define STM32_PERIPH_GPIOK LL_AHB4_GRP1_PERIPH_GPIOK +#elif CONFIG_SOC_SERIES_STM32H7RSX +#define STM32_CLOCK_BUS_GPIO STM32_CLOCK_BUS_AHB4 +#define STM32_PERIPH_GPIOA LL_AHB4_GRP1_PERIPH_GPIOA +#define STM32_PERIPH_GPIOB LL_AHB4_GRP1_PERIPH_GPIOB +#define STM32_PERIPH_GPIOC LL_AHB4_GRP1_PERIPH_GPIOC +#define STM32_PERIPH_GPIOD LL_AHB4_GRP1_PERIPH_GPIOD +#define STM32_PERIPH_GPIOE LL_AHB4_GRP1_PERIPH_GPIOE +#define STM32_PERIPH_GPIOF LL_AHB4_GRP1_PERIPH_GPIOF +#define STM32_PERIPH_GPIOG LL_AHB4_GRP1_PERIPH_GPIOG +#define STM32_PERIPH_GPIOH LL_AHB4_GRP1_PERIPH_GPIOH +#define STM32_PERIPH_GPIOM LL_AHB4_GRP1_PERIPH_GPIOM +#define STM32_PERIPH_GPION LL_AHB4_GRP1_PERIPH_GPION +#define STM32_PERIPH_GPIOO LL_AHB4_GRP1_PERIPH_GPIOO +#define STM32_PERIPH_GPIOP LL_AHB4_GRP1_PERIPH_GPIOP #elif CONFIG_SOC_SERIES_STM32G0X #define STM32_CLOCK_BUS_GPIO STM32_CLOCK_BUS_IOP #define STM32_PERIPH_GPIOA LL_IOP_GRP1_PERIPH_GPIOA diff --git a/drivers/gpio/gpio_xlnx_axi.c b/drivers/gpio/gpio_xlnx_axi.c index f6ba2dd260610..4b50bf85cd6ec 100644 --- a/drivers/gpio/gpio_xlnx_axi.c +++ b/drivers/gpio/gpio_xlnx_axi.c @@ -450,7 +450,7 @@ static const struct gpio_driver_api gpio_xlnx_axi_driver_api = { irq_enable(DT_INST_IRQN(n)); \ })) \ \ - DEVICE_DT_INST_DEFINE(n, &gpio_xlnx_axi_init, NULL, &gpio_xlnx_axi_##n##_data, \ + DEVICE_DT_INST_DEFINE(n, gpio_xlnx_axi_init, NULL, &gpio_xlnx_axi_##n##_data, \ &gpio_xlnx_axi_##n##_config, PRE_KERNEL_1, \ CONFIG_GPIO_INIT_PRIORITY, &gpio_xlnx_axi_driver_api); diff --git a/drivers/hwinfo/CMakeLists.txt b/drivers/hwinfo/CMakeLists.txt index 2e7d91141be9c..6730e60491f0a 100644 --- a/drivers/hwinfo/CMakeLists.txt +++ b/drivers/hwinfo/CMakeLists.txt @@ -8,6 +8,9 @@ zephyr_library_sources_ifdef(CONFIG_USERSPACE hwinfo_handlers.c) zephyr_library_sources_ifdef(CONFIG_HWINFO hwinfo_weak_impl.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SHELL hwinfo_shell.c) +# zephyr-keep-sorted-start +zephyr_library_sources_ifdef(CONFIG_HWINFO_AMBIQ hwinfo_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_HWINFO_ANDES hwinfo_andes.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_CC13XX_CC26XX hwinfo_cc13xx_cc26xx.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_ESP32 hwinfo_esp32.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_GECKO hwinfo_gecko.c) @@ -21,11 +24,11 @@ zephyr_library_sources_ifdef(CONFIG_HWINFO_MCUX_SYSCON hwinfo_mcux_syscon.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_NRF hwinfo_nrf.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_PSOC6 hwinfo_psoc6.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_RPI_PICO hwinfo_rpi_pico.c) -zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM_RSTC hwinfo_sam_rstc.c) +zephyr_library_sources_ifdef(CONFIG_HWINFO_RW61X hwinfo_rw61x.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM hwinfo_sam.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM0 hwinfo_sam0.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM4L hwinfo_sam4l.c) +zephyr_library_sources_ifdef(CONFIG_HWINFO_SAM_RSTC hwinfo_sam_rstc.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_SMARTBOND hwinfo_smartbond.c) zephyr_library_sources_ifdef(CONFIG_HWINFO_STM32 hwinfo_stm32.c) -zephyr_library_sources_ifdef(CONFIG_HWINFO_ANDES hwinfo_andes.c) -zephyr_library_sources_ifdef(CONFIG_HWINFO_RW61X hwinfo_rw61x.c) +# zephyr-keep-sorted-stop diff --git a/drivers/hwinfo/Kconfig b/drivers/hwinfo/Kconfig index 703201410dec5..0352215a97e96 100644 --- a/drivers/hwinfo/Kconfig +++ b/drivers/hwinfo/Kconfig @@ -173,14 +173,16 @@ config HWINFO_LITEX config HWINFO_PSOC6 bool "Cypress PSoC-6 unique device ID" default y - depends on SOC_FAMILY_PSOC6 + depends on SOC_FAMILY_PSOC6_LEGACY help Enable Cypress PSoC-6 hwinfo driver. config HWINFO_GECKO bool "GECKO hwinfo" default y - depends on SOC_VENDOR_SILABS && !SOC_SERIES_EFR32MG21 && !SOC_SERIES_EFR32BG22 + depends on SOC_FAMILY_SILABS_S0 || SOC_FAMILY_SILABS_S1 || SOC_FAMILY_SILABS_S2 + depends on !SOC_SERIES_EFR32MG21 + depends on !SOC_SERIES_EFR32BG22 select SOC_GECKO_RMU help Enable Silabs GECKO hwinfo driver. @@ -200,4 +202,13 @@ config HWINFO_RW61X help Enable RW61X hwinfo driver +config HWINFO_AMBIQ + bool "AMBIQ hwinfo" + default y + depends on SOC_SERIES_APOLLO4X + select AMBIQ_HAL + select AMBIQ_HAL_USE_HWINFO + help + Enable AMBIQ hwinfo driver + endif diff --git a/drivers/hwinfo/hwinfo_ambiq.c b/drivers/hwinfo/hwinfo_ambiq.c new file mode 100644 index 0000000000000..80bcf62763ad5 --- /dev/null +++ b/drivers/hwinfo/hwinfo_ambiq.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2024 Ambiq + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +ssize_t z_impl_hwinfo_get_device_id(uint8_t *buffer, size_t length) +{ + + struct ambiq_hwinfo { + /* Ambiq Chip ID0 */ + uint32_t chip_id_0; + /* Ambiq Chip ID1 */ + uint32_t chip_id_1; + /* Ambiq Factory Trim Revision */ + /* Can be used in Ambiq HAL for additional code support */ + uint32_t factory_trim_version; + }; + + struct ambiq_hwinfo dev_hw_info = {0}; + + /* Contains the HAL hardware information about the device. */ + am_hal_mcuctrl_device_t mcu_ctrl_device; + + am_hal_mram_info_read(1, AM_REG_INFO1_TRIM_REV_O / 4, 1, &dev_hw_info.factory_trim_version); + am_hal_mcuctrl_info_get(AM_HAL_MCUCTRL_INFO_DEVICEID, &mcu_ctrl_device); + + dev_hw_info.chip_id_0 = mcu_ctrl_device.ui32ChipID0; + dev_hw_info.chip_id_1 = mcu_ctrl_device.ui32ChipID1; + + if (length > sizeof(dev_hw_info)) { + length = sizeof(dev_hw_info); + } + + dev_hw_info.chip_id_0 = BSWAP_32(dev_hw_info.chip_id_0); + dev_hw_info.chip_id_1 = BSWAP_32(dev_hw_info.chip_id_1); + dev_hw_info.factory_trim_version = BSWAP_32(dev_hw_info.factory_trim_version); + memcpy(buffer, &dev_hw_info, length); + + return length; +} + +int z_impl_hwinfo_get_reset_cause(uint32_t *cause) +{ + uint32_t flags = 0; + uint32_t reset_status = 0; + am_hal_reset_status_t status = {0}; + + /* Print out reset status register upon entry */ + am_hal_reset_status_get(&status); + reset_status = status.eStatus; + + /* EXTERNAL PIN */ + if (reset_status & AM_HAL_RESET_STATUS_EXTERNAL) { + flags |= RESET_PIN; + } + + /* POWER CYCLE */ + if (reset_status & AM_HAL_RESET_STATUS_POR) { + flags |= RESET_POR; + } + + /* BROWNOUT DETECTOR */ + if (reset_status & AM_HAL_RESET_STATUS_BOD) { + flags |= RESET_BROWNOUT; + } + + /* SOFTWARE POR */ + if (reset_status & AM_HAL_RESET_STATUS_SWPOR) { + flags |= RESET_SOFTWARE; + } + + /* SOFTWARE POI */ + if (reset_status & AM_HAL_RESET_STATUS_SWPOI) { + flags |= RESET_SOFTWARE; + } + + /* DEBUGGER */ + if (reset_status & AM_HAL_RESET_STATUS_DEBUGGER) { + flags |= RESET_DEBUG; + } + + /* WATCHDOG */ + if (reset_status & AM_HAL_RESET_STATUS_WDT) { + flags |= RESET_WATCHDOG; + } + + /* BOUNREG */ + if (reset_status & AM_HAL_RESET_STATUS_BOUNREG) { + flags |= RESET_HARDWARE; + } + + /* BOCORE */ + if (reset_status & AM_HAL_RESET_STATUS_BOCORE) { + flags |= RESET_HARDWARE; + } + + /* BOMEM */ + if (reset_status & AM_HAL_RESET_STATUS_BOMEM) { + flags |= RESET_HARDWARE; + } + + /* BOHPMEM */ + if (reset_status & AM_HAL_RESET_STATUS_BOHPMEM) { + flags |= RESET_HARDWARE; + } + + *cause = flags; + return 0; +} + +int z_impl_hwinfo_clear_reset_cause(void) +{ + /* SBL maintains the RSTGEN->STAT register in + * INFO1 space even upon clearing RSTGEN->STAT + * register. + * - INFO1_RESETSTATUS + */ + + return -ENOSYS; +} + +int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported) +{ + *supported = RESET_PIN + | RESET_SOFTWARE + | RESET_POR + | RESET_WATCHDOG + | RESET_HARDWARE + | RESET_BROWNOUT; + return 0; +} diff --git a/drivers/hwinfo/hwinfo_handlers.c b/drivers/hwinfo/hwinfo_handlers.c index a1eb9e2c830a9..fc39241ff3238 100644 --- a/drivers/hwinfo/hwinfo_handlers.c +++ b/drivers/hwinfo/hwinfo_handlers.c @@ -13,7 +13,7 @@ ssize_t z_vrfy_hwinfo_get_device_id(uint8_t *buffer, size_t length) return z_impl_hwinfo_get_device_id((uint8_t *)buffer, (size_t)length); } -#include +#include ssize_t z_vrfy_hwinfo_get_device_eui64(uint8_t *buffer) { @@ -21,7 +21,7 @@ ssize_t z_vrfy_hwinfo_get_device_eui64(uint8_t *buffer) return z_impl_hwinfo_get_device_eui64((uint8_t *)buffer); } -#include +#include int z_vrfy_hwinfo_get_reset_cause(uint32_t *cause) { @@ -33,14 +33,14 @@ int z_vrfy_hwinfo_get_reset_cause(uint32_t *cause) return ret; } -#include +#include int z_vrfy_hwinfo_clear_reset_cause(void) { return z_impl_hwinfo_clear_reset_cause(); } -#include +#include int z_vrfy_hwinfo_get_supported_reset_cause(uint32_t *supported) { @@ -52,4 +52,4 @@ int z_vrfy_hwinfo_get_supported_reset_cause(uint32_t *supported) return ret; } -#include +#include diff --git a/drivers/hwinfo/hwinfo_stm32.c b/drivers/hwinfo/hwinfo_stm32.c index 75029d7495ceb..239e54972f7e3 100644 --- a/drivers/hwinfo/hwinfo_stm32.c +++ b/drivers/hwinfo/hwinfo_stm32.c @@ -150,7 +150,7 @@ int z_impl_hwinfo_get_reset_cause(uint32_t *cause) if (LL_PWR_IsActiveFlag_C1SB()) { flags |= RESET_LOW_POWER_WAKE; } -#elif defined(PWR_FLAG_SB) +#elif defined(PWR_FLAG_SB) || defined(PWR_FLAG_SBF) if (LL_PWR_IsActiveFlag_SB()) { flags |= RESET_LOW_POWER_WAKE; } @@ -169,6 +169,8 @@ int z_impl_hwinfo_clear_reset_cause(void) LL_PWR_ClearFlag_CPU2(); #elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CORE_CM7) LL_PWR_ClearFlag_CPU(); +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) + LL_PWR_ClearFlag_STOP_SB(); #elif defined(CONFIG_SOC_SERIES_STM32MP1X) LL_PWR_ClearFlag_MCU(); #elif defined(CONFIG_SOC_SERIES_STM32WLX) || defined(CONFIG_SOC_SERIES_STM32WBX) diff --git a/drivers/hwspinlock/hwspinlock_handlers.c b/drivers/hwspinlock/hwspinlock_handlers.c index 7064293be4bfe..dbb1a94f68ed9 100644 --- a/drivers/hwspinlock/hwspinlock_handlers.c +++ b/drivers/hwspinlock/hwspinlock_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_hwspinlock_trylock(const struct device *dev, uint32_t i return z_impl_hwspinlock_trylock(dev, id); } -#include +#include static inline void z_vrfy_hwspinlock_lock(const struct device *dev, uint32_t id) { @@ -21,7 +21,7 @@ static inline void z_vrfy_hwspinlock_lock(const struct device *dev, uint32_t id) z_impl_hwspinlock_lock(dev, id); } -#include +#include static inline void z_vrfy_hwspinlock_unlock(const struct device *dev, uint32_t id) { @@ -29,7 +29,7 @@ static inline void z_vrfy_hwspinlock_unlock(const struct device *dev, uint32_t i z_impl_hwspinlock_unlock(dev, id); } -#include +#include static inline uint32_t z_vrfy_hwspinlock_get_max_id(const struct device *dev) { @@ -37,4 +37,4 @@ static inline uint32_t z_vrfy_hwspinlock_get_max_id(const struct device *dev) return z_impl_hwspinlock_get_max_id(dev); } -#include +#include diff --git a/drivers/i2c/CMakeLists.txt b/drivers/i2c/CMakeLists.txt index 13878b66d3b3f..aa46769ed850b 100644 --- a/drivers/i2c/CMakeLists.txt +++ b/drivers/i2c/CMakeLists.txt @@ -10,6 +10,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_RTIO i2c_rtio.c) zephyr_library_sources_ifdef(CONFIG_I2C_SHELL i2c_shell.c) zephyr_library_sources_ifdef(CONFIG_I2C_BITBANG i2c_bitbang.c) zephyr_library_sources_ifdef(CONFIG_I2C_TELINK_B91 i2c_b91.c) +zephyr_library_sources_ifdef(CONFIG_I2C_IPROC i2c_bcm_iproc.c) zephyr_library_sources_ifdef(CONFIG_I2C_CC13XX_CC26XX i2c_cc13xx_cc26xx.c) zephyr_library_sources_ifdef(CONFIG_I2C_CC32XX i2c_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_I2C_ESP32 i2c_esp32.c) @@ -29,7 +30,19 @@ else() endif() zephyr_library_sources_ifdef(CONFIG_I2C_EMUL i2c_emul.c) -zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWI i2c_nrfx_twi.c) + +if(CONFIG_I2C_RTIO) + zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWI + i2c_nrfx_twi_rtio.c + i2c_nrfx_twi_common.c + ) +else() + zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWI + i2c_nrfx_twi.c + i2c_nrfx_twi_common.c + ) +endif() + zephyr_library_sources_ifdef(CONFIG_I2C_NRFX_TWIM i2c_nrfx_twim.c) zephyr_library_sources_ifdef(CONFIG_I2C_SAM_TWI i2c_sam_twi.c) @@ -66,6 +79,7 @@ zephyr_library_sources_ifdef(CONFIG_I2C_AMBIQ i2c_ambiq.c) zephyr_library_sources_ifdef(CONFIG_I2C_ENE_KB1200 i2c_ene_kb1200.c) zephyr_library_sources_ifdef(CONFIG_GPIO_I2C_SWITCH gpio_i2c_switch.c) zephyr_library_sources_ifdef(CONFIG_I2C_NUMAKER i2c_numaker.c) +zephyr_library_sources_ifdef(CONFIG_I2C_MAX32 i2c_max32.c) zephyr_library_sources_ifdef(CONFIG_I2C_STM32_V1 i2c_ll_stm32_v1.c diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 8af4bbbeb8b3e..2002813da526a 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -94,6 +94,7 @@ endif # I2C_RTIO # Include these first so that any properties (e.g. defaults) below can be # overridden (by defining symbols in multiple locations) source "drivers/i2c/Kconfig.b91" +source "drivers/i2c/Kconfig.bcm_iproc" source "drivers/i2c/Kconfig.cc13xx_cc26xx" source "drivers/i2c/Kconfig.dw" source "drivers/i2c/Kconfig.esp32" @@ -127,6 +128,7 @@ source "drivers/i2c/Kconfig.ambiq" source "drivers/i2c/Kconfig.numaker" source "drivers/i2c/Kconfig.mcux" source "drivers/i2c/Kconfig.ene" +source "drivers/i2c/Kconfig.max32" config I2C_INIT_PRIORITY int "Init priority" diff --git a/drivers/i2c/Kconfig.ambiq b/drivers/i2c/Kconfig.ambiq index 040a93866e978..04a80848d9f4b 100644 --- a/drivers/i2c/Kconfig.ambiq +++ b/drivers/i2c/Kconfig.ambiq @@ -13,3 +13,14 @@ config I2C_AMBIQ select AMBIQ_HAL_USE_I2C help Enable driver for Ambiq I2C. + +config I2C_AMBIQ_DMA + bool "AMBIQ APOLLO I2C DMA Support" + help + Enable DMA for Ambiq I2C. + +config I2C_DMA_TCB_BUFFER_SIZE + int "DMA Transfer Control Buffer size in words." + default 1024 + help + DMA Transfer Control Buffer size in words diff --git a/drivers/i2c/Kconfig.bcm_iproc b/drivers/i2c/Kconfig.bcm_iproc new file mode 100644 index 0000000000000..b192dc1483139 --- /dev/null +++ b/drivers/i2c/Kconfig.bcm_iproc @@ -0,0 +1,10 @@ +# Copyright 2020 Broadcom +# Copyright 2024 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +config I2C_IPROC + bool "Broadcom iProc I2C controller" + default y + depends on DT_HAS_BRCM_IPROC_I2C_ENABLED + help + Enable support for Broadcom iProc I2C controller. diff --git a/drivers/i2c/Kconfig.max32 b/drivers/i2c/Kconfig.max32 new file mode 100644 index 0000000000000..b41f5ec862077 --- /dev/null +++ b/drivers/i2c/Kconfig.max32 @@ -0,0 +1,20 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +menuconfig I2C_MAX32 + bool "Analog Devices MAX32 I2C driver" + default y + depends on DT_HAS_ADI_MAX32_I2C_ENABLED + help + i2c driver for max32 family. + +if I2C_MAX32 + +config I2C_MAX32_INTERRUPT + bool "Interrupt support for MAX32 I2C driver" + default y + help + Enable interrupt support for MAX32 I2C controller mode + transfers. + +endif # I2C_MAX32 diff --git a/drivers/i2c/Kconfig.mcux b/drivers/i2c/Kconfig.mcux index 744f5025eb066..f91876390147b 100644 --- a/drivers/i2c/Kconfig.mcux +++ b/drivers/i2c/Kconfig.mcux @@ -8,6 +8,7 @@ menuconfig I2C_MCUX_FLEXCOMM default y depends on DT_HAS_NXP_LPC_I2C_ENABLED select PINCTRL + select RESET help Enable the mcux flexcomm i2c driver. diff --git a/drivers/i2c/Kconfig.nrfx b/drivers/i2c/Kconfig.nrfx index 6898d6e42a93e..3c0596fc5b9b9 100644 --- a/drivers/i2c/Kconfig.nrfx +++ b/drivers/i2c/Kconfig.nrfx @@ -17,6 +17,7 @@ if I2C_NRFX config I2C_NRFX_TWI def_bool y depends on DT_HAS_NORDIC_NRF_TWI_ENABLED + select HAS_I2C_RTIO select NRFX_TWI0 if HAS_HW_NRF_TWI0 select NRFX_TWI1 if HAS_HW_NRF_TWI1 diff --git a/drivers/i2c/Kconfig.stm32 b/drivers/i2c/Kconfig.stm32 index e6e98df33a083..274cecac8cb18 100644 --- a/drivers/i2c/Kconfig.stm32 +++ b/drivers/i2c/Kconfig.stm32 @@ -50,4 +50,10 @@ config I2C_STM32_BUS_RECOVERY help Enable STM32 driver bus recovery support via GPIO bitbanging. +config I2C_STM32_V2_TIMING + bool "compute the I2C V2 bus timing" + depends on I2C_STM32_V2 + help + Enable STM32 driver bus to calculate the Timing. + endif # I2C_STM32 diff --git a/drivers/i2c/i2c_ambiq.c b/drivers/i2c/i2c_ambiq.c index e8b62fb2c45a7..f3c5b90e90031 100644 --- a/drivers/i2c/i2c_ambiq.c +++ b/drivers/i2c/i2c_ambiq.c @@ -19,7 +19,8 @@ LOG_MODULE_REGISTER(ambiq_i2c, CONFIG_I2C_LOG_LEVEL); typedef int (*ambiq_i2c_pwr_func_t)(void); -#define PWRCTRL_MAX_WAIT_US 5 +#define PWRCTRL_MAX_WAIT_US 5 +#define I2C_TRANSFER_TIMEOUT_MSEC 500 /* Transfer timeout period */ #include "i2c-priv.h" @@ -29,13 +30,50 @@ struct i2c_ambiq_config { uint32_t bitrate; const struct pinctrl_dev_config *pcfg; ambiq_i2c_pwr_func_t pwr_func; + void (*irq_config_func)(void); }; +typedef void (*i2c_ambiq_callback_t)(const struct device *dev, int result, void *data); + struct i2c_ambiq_data { am_hal_iom_config_t iom_cfg; - void *IOMHandle; + void *iom_handler; + struct k_sem bus_sem; + struct k_sem transfer_sem; + i2c_ambiq_callback_t callback; + void *callback_data; + int inst_idx; + uint32_t transfer_status; }; +#ifdef CONFIG_I2C_AMBIQ_DMA +static __aligned(32) struct { + __aligned(32) uint32_t buf[CONFIG_I2C_DMA_TCB_BUFFER_SIZE]; +} i2c_dma_tcb_buf[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)] __attribute__((__section__(".nocache"))); + +static void i2c_ambiq_callback(void *callback_ctxt, uint32_t status) +{ + const struct device *dev = callback_ctxt; + struct i2c_ambiq_data *data = dev->data; + + if (data->callback) { + data->callback(dev, status, data->callback_data); + } + data->transfer_status = status; + k_sem_give(&data->transfer_sem); +} +#endif + +static void i2c_ambiq_isr(const struct device *dev) +{ + uint32_t ui32Status; + struct i2c_ambiq_data *data = dev->data; + + am_hal_iom_interrupt_status_get(data->iom_handler, false, &ui32Status); + am_hal_iom_interrupt_clear(data->iom_handler, ui32Status); + am_hal_iom_interrupt_service(data->iom_handler, ui32Status); +} + static int i2c_ambiq_read(const struct device *dev, struct i2c_msg *msg, uint16_t addr) { struct i2c_ambiq_data *data = dev->data; @@ -50,9 +88,24 @@ static int i2c_ambiq_read(const struct device *dev, struct i2c_msg *msg, uint16_ trans.ui32NumBytes = msg->len; trans.pui32RxBuffer = (uint32_t *)msg->buf; - ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); - - return ret; +#ifdef CONFIG_I2C_AMBIQ_DMA + data->transfer_status = -EFAULT; + ret = am_hal_iom_nonblocking_transfer(data->iom_handler, &trans, i2c_ambiq_callback, + (void *)dev); + if (k_sem_take(&data->transfer_sem, K_MSEC(I2C_TRANSFER_TIMEOUT_MSEC))) { + LOG_ERR("Timeout waiting for transfer complete"); + /* cancel timed out transaction */ + am_hal_iom_disable(data->iom_handler); + /* clean up for next xfer */ + k_sem_reset(&data->transfer_sem); + am_hal_iom_enable(data->iom_handler); + return -ETIMEDOUT; + } + ret = data->transfer_status; +#else + ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans); +#endif + return (ret != AM_HAL_STATUS_SUCCESS) ? -EIO : 0; } static int i2c_ambiq_write(const struct device *dev, struct i2c_msg *msg, uint16_t addr) @@ -69,9 +122,26 @@ static int i2c_ambiq_write(const struct device *dev, struct i2c_msg *msg, uint16 trans.ui32NumBytes = msg->len; trans.pui32TxBuffer = (uint32_t *)msg->buf; - ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); +#ifdef CONFIG_I2C_AMBIQ_DMA + data->transfer_status = -EFAULT; + ret = am_hal_iom_nonblocking_transfer(data->iom_handler, &trans, i2c_ambiq_callback, + (void *)dev); + + if (k_sem_take(&data->transfer_sem, K_MSEC(I2C_TRANSFER_TIMEOUT_MSEC))) { + LOG_ERR("Timeout waiting for transfer complete"); + /* cancel timed out transaction */ + am_hal_iom_disable(data->iom_handler); + /* clean up for next xfer */ + k_sem_reset(&data->transfer_sem); + am_hal_iom_enable(data->iom_handler); + return -ETIMEDOUT; + } + ret = data->transfer_status; +#else + ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans); +#endif - return ret; + return (ret != AM_HAL_STATUS_SUCCESS) ? -EIO : 0; } static int i2c_ambiq_configure(const struct device *dev, uint32_t dev_config) @@ -96,7 +166,12 @@ static int i2c_ambiq_configure(const struct device *dev, uint32_t dev_config) return -EINVAL; } - am_hal_iom_configure(data->IOMHandle, &data->iom_cfg); +#ifdef CONFIG_I2C_AMBIQ_DMA + data->iom_cfg.pNBTxnBuf = i2c_dma_tcb_buf[data->inst_idx].buf; + data->iom_cfg.ui32NBTxnBufLength = CONFIG_I2C_DMA_TCB_BUFFER_SIZE; +#endif + + am_hal_iom_configure(data->iom_handler, &data->iom_cfg); return 0; } @@ -104,12 +179,16 @@ static int i2c_ambiq_configure(const struct device *dev, uint32_t dev_config) static int i2c_ambiq_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr) { + struct i2c_ambiq_data *data = dev->data; int ret = 0; if (!num_msgs) { return 0; } + /* Send out messages */ + k_sem_take(&data->bus_sem, K_FOREVER); + for (int i = 0; i < num_msgs; i++) { if (msgs[i].flags & I2C_MSG_READ) { ret = i2c_ambiq_read(dev, &(msgs[i]), addr); @@ -122,6 +201,8 @@ static int i2c_ambiq_transfer(const struct device *dev, struct i2c_msg *msgs, ui } } + k_sem_give(&data->bus_sem); + return 0; } @@ -134,21 +215,41 @@ static int i2c_ambiq_init(const struct device *dev) data->iom_cfg.eInterfaceMode = AM_HAL_IOM_I2C_MODE; - ret = am_hal_iom_initialize((config->base - REG_IOM_BASEADDR) / config->size, - &data->IOMHandle); + if (AM_HAL_STATUS_SUCCESS != + am_hal_iom_initialize((config->base - REG_IOM_BASEADDR) / config->size, + &data->iom_handler)) { + LOG_ERR("Fail to initialize I2C\n"); + return -ENXIO; + } ret = config->pwr_func(); - ret = i2c_ambiq_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg); + ret |= i2c_ambiq_configure(dev, I2C_MODE_CONTROLLER | bitrate_cfg); + if (ret < 0) { + LOG_ERR("Fail to config I2C\n"); + goto end; + } ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (ret < 0) { - return ret; + LOG_ERR("Fail to config I2C pins\n"); + goto end; } - ret = am_hal_iom_enable(data->IOMHandle); +#ifdef CONFIG_I2C_AMBIQ_DMA + am_hal_iom_interrupt_clear(data->iom_handler, AM_HAL_IOM_INT_CQUPD | AM_HAL_IOM_INT_ERR); + am_hal_iom_interrupt_enable(data->iom_handler, AM_HAL_IOM_INT_CQUPD | AM_HAL_IOM_INT_ERR); + config->irq_config_func(); +#endif + if (AM_HAL_STATUS_SUCCESS != am_hal_iom_enable(data->iom_handler)) { + LOG_ERR("Fail to enable I2C\n"); + ret = -EIO; + } +end: + if (ret < 0) { + am_hal_iom_uninitialize(data->iom_handler); + } return ret; } @@ -167,12 +268,23 @@ static const struct i2c_driver_api i2c_ambiq_driver_api = { k_busy_wait(PWRCTRL_MAX_WAIT_US); \ return 0; \ } \ - static struct i2c_ambiq_data i2c_ambiq_data##n; \ + static void i2c_irq_config_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), i2c_ambiq_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + }; \ + static struct i2c_ambiq_data i2c_ambiq_data##n = { \ + .bus_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.bus_sem, 1, 1), \ + .transfer_sem = Z_SEM_INITIALIZER(i2c_ambiq_data##n.transfer_sem, 0, 1), \ + .inst_idx = n, \ + }; \ static const struct i2c_ambiq_config i2c_ambiq_config##n = { \ .base = DT_INST_REG_ADDR(n), \ .size = DT_INST_REG_SIZE(n), \ .bitrate = DT_INST_PROP(n, clock_frequency), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .irq_config_func = i2c_irq_config_func_##n, \ .pwr_func = pwr_on_ambiq_i2c_##n}; \ I2C_DEVICE_DT_INST_DEFINE(n, i2c_ambiq_init, NULL, &i2c_ambiq_data##n, \ &i2c_ambiq_config##n, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ diff --git a/drivers/i2c/i2c_bcm_iproc.c b/drivers/i2c/i2c_bcm_iproc.c new file mode 100644 index 0000000000000..fbc5dc4758373 --- /dev/null +++ b/drivers/i2c/i2c_bcm_iproc.c @@ -0,0 +1,950 @@ +/* + * Copyright 2020 Broadcom + * Copyright 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT brcm_iproc_i2c + +#include +#include + +#include +#include +#include + +#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL +LOG_MODULE_REGISTER(iproc_i2c); + +#include "i2c-priv.h" + +/* Registers */ +#define CFG_OFFSET 0x00 +#define CFG_RESET_SHIFT 31 +#define CFG_EN_SHIFT 30 +#define CFG_M_RETRY_CNT_SHIFT 16 +#define CFG_M_RETRY_CNT_MASK 0x0f + +#define TIM_CFG_OFFSET 0x04 +#define TIM_CFG_MODE_400_SHIFT 31 +#define TIM_RAND_TARGET_STRETCH_SHIFT 24 +#define TIM_RAND_TARGET_STRETCH_MASK 0x7f + +#define S_ADDR_OFFSET 0x08 +#define S_ADDR_OFFSET_ADDR0_MASK 0x7f +#define S_ADDR_OFFSET_ADDR0_SHIFT 0 +#define S_ADDR_OFFSET_ADDR0_EN_BIT 7 + +#define M_FIFO_CTRL_OFFSET 0x0c +#define M_FIFO_RX_FLUSH_SHIFT 31 +#define M_FIFO_TX_FLUSH_SHIFT 30 +#define M_FIFO_RX_CNT_SHIFT 16 +#define M_FIFO_RX_CNT_MASK 0x7f +#define M_FIFO_RX_THLD_SHIFT 8 +#define M_FIFO_RX_THLD_MASK 0x3f + +#define S_FIFO_CTRL_OFFSET 0x10 +#define S_FIFO_RX_FLUSH_SHIFT 31 +#define S_FIFO_TX_FLUSH_SHIFT 30 + +#define M_CMD_OFFSET 0x30 +#define M_CMD_START_BUSY_SHIFT 31 +#define M_CMD_STATUS_SHIFT 25 +#define M_CMD_STATUS_MASK 0x07 +#define M_CMD_STATUS_SUCCESS 0x0 +#define M_CMD_STATUS_LOST_ARB 0x1 +#define M_CMD_STATUS_NACK_ADDR 0x2 +#define M_CMD_STATUS_NACK_DATA 0x3 +#define M_CMD_STATUS_TIMEOUT 0x4 +#define M_CMD_STATUS_FIFO_UNDERRUN 0x5 +#define M_CMD_STATUS_RX_FIFO_FULL 0x6 +#define M_CMD_SMB_PROT_SHIFT 9 +#define M_CMD_SMB_PROT_QUICK 0x0 +#define M_CMD_SMB_PROT_MASK 0xf +#define M_CMD_SMB_PROT_BLK_WR 0x7 +#define M_CMD_SMB_PROT_BLK_RD 0x8 +#define M_CMD_PEC_SHIFT 8 +#define M_CMD_RD_CNT_MASK 0xff + +#define S_CMD_OFFSET 0x34 +#define S_CMD_START_BUSY_SHIFT 31 +#define S_CMD_STATUS_SHIFT 23 +#define S_CMD_STATUS_MASK 0x07 +#define S_CMD_STATUS_TIMEOUT 0x5 +#define S_CMD_STATUS_MASTER_ABORT 0x7 + +#define IE_OFFSET 0x38 +#define IE_M_RX_FIFO_FULL_SHIFT 31 +#define IE_M_RX_THLD_SHIFT 30 +#define IE_M_START_BUSY_SHIFT 28 +#define IE_M_TX_UNDERRUN_SHIFT 27 +#define IE_S_RX_FIFO_FULL_SHIFT 26 +#define IE_S_RX_THLD_SHIFT 25 +#define IE_S_RX_EVENT_SHIFT 24 +#define IE_S_START_BUSY_SHIFT 23 +#define IE_S_TX_UNDERRUN_SHIFT 22 +#define IE_S_RD_EN_SHIFT 21 + +#define IS_OFFSET 0x3c +#define IS_M_RX_FIFO_FULL_SHIFT 31 +#define IS_M_RX_THLD_SHIFT 30 +#define IS_M_START_BUSY_SHIFT 28 +#define IS_M_TX_UNDERRUN_SHIFT 27 +#define IS_S_RX_FIFO_FULL_SHIFT 26 +#define IS_S_RX_THLD_SHIFT 25 +#define IS_S_RX_EVENT_SHIFT 24 +#define IS_S_START_BUSY_SHIFT 23 +#define IS_S_TX_UNDERRUN_SHIFT 22 +#define IS_S_RD_EN_SHIFT 21 + +#define M_TX_OFFSET 0x40 +#define M_TX_WR_STATUS_SHIFT 31 +#define M_TX_DATA_MASK 0xff + +#define M_RX_OFFSET 0x44 +#define M_RX_STATUS_SHIFT 30 +#define M_RX_STATUS_MASK 0x03 +#define M_RX_PEC_ERR_SHIFT 29 +#define M_RX_DATA_SHIFT 0 +#define M_RX_DATA_MASK 0xff + +#define S_TX_OFFSET 0x48 +#define S_TX_WR_STATUS_SHIFT 31 + +#define S_RX_OFFSET 0x4c +#define S_RX_STATUS_SHIFT 30 +#define S_RX_STATUS_MASK 0x03 +#define S_RX_DATA_SHIFT 0x0 +#define S_RX_DATA_MASK 0xff + +#define I2C_TIMEOUT_MSEC 100 +#define TX_RX_FIFO_SIZE 64 +#define M_RX_FIFO_MAX_THLD_VALUE (TX_RX_FIFO_SIZE - 1) +#define M_RX_FIFO_THLD_VALUE 50 + +#define I2C_MAX_TARGET_ADDR 0x7f + +#define I2C_TARGET_RX_FIFO_EMPTY 0x0 +#define I2C_TARGET_RX_START 0x1 +#define I2C_TARGET_RX_DATA 0x2 +#define I2C_TARGET_RX_END 0x3 + +#define IE_S_ALL_INTERRUPT_SHIFT 21 +#define IE_S_ALL_INTERRUPT_MASK 0x3f + +#define TARGET_CLOCK_STRETCH_TIME 25 + +/* + * To keep running in ISR for less time, + * max target read per interrupt is set to 10 bytes. + */ +#define MAX_TARGET_RX_PER_INT 10 + +#define ISR_MASK_TARGET \ + (BIT(IS_S_START_BUSY_SHIFT) | BIT(IS_S_RX_EVENT_SHIFT) | BIT(IS_S_RD_EN_SHIFT) | \ + BIT(IS_S_TX_UNDERRUN_SHIFT) | BIT(IS_S_RX_FIFO_FULL_SHIFT) | BIT(IS_S_RX_THLD_SHIFT)) + +#define ISR_MASK \ + (BIT(IS_M_START_BUSY_SHIFT) | BIT(IS_M_TX_UNDERRUN_SHIFT) | BIT(IS_M_RX_THLD_SHIFT)) + +#define DEV_CFG(dev) ((struct iproc_i2c_config *)(dev)->config) +#define DEV_DATA(dev) ((struct iproc_i2c_data *)(dev)->data) +#define DEV_BASE(dev) ((DEV_CFG(dev))->base) + +struct iproc_i2c_config { + mem_addr_t base; + uint32_t bitrate; + void (*irq_config_func)(const struct device *dev); +}; + +struct iproc_i2c_data { + struct i2c_target_config *target_cfg; + struct i2c_msg *msg; + uint32_t tx_bytes; + uint32_t rx_bytes; + uint32_t thld_bytes; + uint32_t tx_underrun; + struct k_sem device_sync_sem; + uint32_t target_int_mask; + bool rx_start_rcvd; + bool target_read_complete; + bool target_rx_only; +}; + +static void iproc_i2c_enable_disable(const struct device *dev, bool enable) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + val = sys_read32(base + CFG_OFFSET); + if (enable) { + val |= BIT(CFG_EN_SHIFT); + } else { + val &= ~BIT(CFG_EN_SHIFT); + } + sys_write32(val, base + CFG_OFFSET); +} + +static void iproc_i2c_reset_controller(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + /* put controller in reset */ + val = sys_read32(base + CFG_OFFSET); + val |= BIT(CFG_RESET_SHIFT); + val &= ~BIT(CFG_EN_SHIFT); + sys_write32(val, base + CFG_OFFSET); + + k_busy_wait(100); + + /* bring controller out of reset */ + sys_clear_bit(base + CFG_OFFSET, CFG_RESET_SHIFT); +} + +#ifdef CONFIG_I2C_TARGET +/* Set target addr */ +static int iproc_i2c_target_set_address(const struct device *dev, uint16_t addr) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + if ((addr == 0) && (addr > I2C_MAX_TARGET_ADDR)) { + LOG_ERR("Invalid target address(0x%x) received", addr); + return -EINVAL; + } + + addr = ((addr & S_ADDR_OFFSET_ADDR0_MASK) | BIT(S_ADDR_OFFSET_ADDR0_EN_BIT)); + val = sys_read32(base + S_ADDR_OFFSET); + val &= ~(S_ADDR_OFFSET_ADDR0_MASK | BIT(S_ADDR_OFFSET_ADDR0_EN_BIT)); + val |= addr; + sys_write32(val, base + S_ADDR_OFFSET); + + return 0; +} + +static int iproc_i2c_target_init(const struct device *dev, bool need_reset) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + mem_addr_t base = DEV_BASE(dev); + struct i2c_target_config *target_config = dd->target_cfg; + uint32_t val; + int ret; + + if (need_reset) { + iproc_i2c_reset_controller(dev); + } + + /* flush target TX/RX FIFOs */ + val = BIT(S_FIFO_RX_FLUSH_SHIFT) | BIT(S_FIFO_TX_FLUSH_SHIFT); + sys_write32(val, base + S_FIFO_CTRL_OFFSET); + + /* Maximum target stretch time */ + val = sys_read32(base + TIM_CFG_OFFSET); + val &= ~(TIM_RAND_TARGET_STRETCH_MASK << TIM_RAND_TARGET_STRETCH_SHIFT); + val |= (TARGET_CLOCK_STRETCH_TIME << TIM_RAND_TARGET_STRETCH_SHIFT); + sys_write32(val, base + TIM_CFG_OFFSET); + + /* Set target address */ + ret = iproc_i2c_target_set_address(dev, target_config->address); + if (ret) { + return ret; + } + + /* clear all pending target interrupts */ + sys_write32(ISR_MASK_TARGET, base + IS_OFFSET); + + /* Enable interrupt register to indicate a valid byte in receive fifo */ + val = BIT(IE_S_RX_EVENT_SHIFT); + /* Enable interrupt register to indicate target Rx FIFO Full */ + val |= BIT(IE_S_RX_FIFO_FULL_SHIFT); + /* Enable interrupt register to indicate a Master read transaction */ + val |= BIT(IE_S_RD_EN_SHIFT); + /* Enable interrupt register for the target BUSY command */ + val |= BIT(IE_S_START_BUSY_SHIFT); + dd->target_int_mask = val; + sys_write32(val, base + IE_OFFSET); + + return ret; +} + +static int iproc_i2c_check_target_status(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + val = sys_read32(base + S_CMD_OFFSET); + /* status is valid only when START_BUSY is cleared after it was set */ + if (val & BIT(S_CMD_START_BUSY_SHIFT)) { + return -EBUSY; + } + + val = (val >> S_CMD_STATUS_SHIFT) & S_CMD_STATUS_MASK; + if ((val == S_CMD_STATUS_TIMEOUT) || (val == S_CMD_STATUS_MASTER_ABORT)) { + if (val == S_CMD_STATUS_TIMEOUT) { + LOG_ERR("target random stretch time timeout"); + } else if (val == S_CMD_STATUS_MASTER_ABORT) { + LOG_ERR("Master aborted read transaction"); + } + + /* re-initialize i2c for recovery */ + iproc_i2c_enable_disable(dev, false); + iproc_i2c_target_init(dev, true); + iproc_i2c_enable_disable(dev, true); + + return -ETIMEDOUT; + } + + return 0; +} + +static void iproc_i2c_target_read(const struct device *dev) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + struct i2c_target_config *target_cfg = dd->target_cfg; + mem_addr_t base = DEV_BASE(dev); + uint8_t rx_data, rx_status; + uint32_t rx_bytes = 0; + uint32_t val; + + while (rx_bytes < MAX_TARGET_RX_PER_INT) { + val = sys_read32(base + S_RX_OFFSET); + rx_status = (val >> S_RX_STATUS_SHIFT) & S_RX_STATUS_MASK; + rx_data = ((val >> S_RX_DATA_SHIFT) & S_RX_DATA_MASK); + + if (rx_status == I2C_TARGET_RX_START) { + /* Start of SMBUS Master write */ + target_cfg->callbacks->write_requested(target_cfg); + dd->rx_start_rcvd = true; + dd->target_read_complete = false; + } else if ((rx_status == I2C_TARGET_RX_DATA) && dd->rx_start_rcvd) { + /* Middle of SMBUS Master write */ + target_cfg->callbacks->write_received(target_cfg, rx_data); + } else if ((rx_status == I2C_TARGET_RX_END) && dd->rx_start_rcvd) { + /* End of SMBUS Master write */ + if (dd->target_rx_only) { + target_cfg->callbacks->write_received(target_cfg, rx_data); + } + target_cfg->callbacks->stop(target_cfg); + } else if (rx_status == I2C_TARGET_RX_FIFO_EMPTY) { + dd->rx_start_rcvd = false; + dd->target_read_complete = true; + break; + } + + rx_bytes++; + } +} + +static void iproc_i2c_target_rx(const struct device *dev) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + mem_addr_t base = DEV_BASE(dev); + + iproc_i2c_target_read(dev); + + if (!dd->target_rx_only && dd->target_read_complete) { + /* + * In case of single byte master-read request, + * IS_S_TX_UNDERRUN_SHIFT event is generated before + * IS_S_START_BUSY_SHIFT event. Hence start target data send + * from first IS_S_TX_UNDERRUN_SHIFT event. + * + * This means don't send any data from target when + * IS_S_RD_EN_SHIFT event is generated else it will increment + * eeprom or other backend target driver read pointer twice. + */ + dd->tx_underrun = 0; + dd->target_int_mask |= BIT(IE_S_TX_UNDERRUN_SHIFT); + + /* clear IS_S_RD_EN_SHIFT interrupt */ + sys_write32(BIT(IS_S_RD_EN_SHIFT), base + IS_OFFSET); + } + + /* enable target interrupts */ + sys_write32(dd->target_int_mask, base + IE_OFFSET); +} + +static void iproc_i2c_target_isr(const struct device *dev, uint32_t status) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + struct i2c_target_config *target_cfg = dd->target_cfg; + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + uint8_t data; + + LOG_DBG("iproc_i2c(0x%x): %s: sl_sts 0x%x", (uint32_t)base, __func__, status); + + if (status & BIT(IS_S_RX_EVENT_SHIFT) || status & BIT(IS_S_RD_EN_SHIFT) || + status & BIT(IS_S_RX_FIFO_FULL_SHIFT)) { + /* disable target interrupts */ + val = sys_read32(base + IE_OFFSET); + val &= ~dd->target_int_mask; + sys_write32(val, base + IE_OFFSET); + + if (status & BIT(IS_S_RD_EN_SHIFT)) { + /* Master-write-read request */ + dd->target_rx_only = false; + } else { + /* Master-write request only */ + dd->target_rx_only = true; + } + + /* + * Clear IS_S_RX_EVENT_SHIFT & + * IS_S_RX_FIFO_FULL_SHIFT interrupt + */ + val = BIT(IS_S_RX_EVENT_SHIFT); + if (status & BIT(IS_S_RX_FIFO_FULL_SHIFT)) { + val |= BIT(IS_S_RX_FIFO_FULL_SHIFT); + } + sys_write32(val, base + IS_OFFSET); + + iproc_i2c_target_rx(dev); + } + + if (status & BIT(IS_S_TX_UNDERRUN_SHIFT)) { + dd->tx_underrun++; + if (dd->tx_underrun == 1) { + /* Start of SMBUS for Master Read */ + target_cfg->callbacks->read_requested(target_cfg, &data); + } else { + /* Master read other than start */ + target_cfg->callbacks->read_processed(target_cfg, &data); + } + + sys_write32(data, base + S_TX_OFFSET); + /* start transfer */ + val = BIT(S_CMD_START_BUSY_SHIFT); + sys_write32(val, base + S_CMD_OFFSET); + + sys_write32(BIT(IS_S_TX_UNDERRUN_SHIFT), base + IS_OFFSET); + } + + /* Stop received from master in case of master read transaction */ + if (status & BIT(IS_S_START_BUSY_SHIFT)) { + /* + * Disable interrupt for TX FIFO becomes empty and + * less than PKT_LENGTH bytes were output on the SMBUS + */ + dd->target_int_mask &= ~BIT(IE_S_TX_UNDERRUN_SHIFT); + sys_write32(dd->target_int_mask, base + IE_OFFSET); + + /* End of SMBUS for Master Read */ + val = BIT(S_TX_WR_STATUS_SHIFT); + sys_write32(val, base + S_TX_OFFSET); + + val = BIT(S_CMD_START_BUSY_SHIFT); + sys_write32(val, base + S_CMD_OFFSET); + + /* flush TX FIFOs */ + val = sys_read32(base + S_FIFO_CTRL_OFFSET); + val |= (BIT(S_FIFO_TX_FLUSH_SHIFT)); + sys_write32(val, base + S_FIFO_CTRL_OFFSET); + + target_cfg->callbacks->stop(target_cfg); + + sys_write32(BIT(IS_S_START_BUSY_SHIFT), base + IS_OFFSET); + } + + /* check target transmit status only if target is transmitting */ + if (!dd->target_rx_only) { + iproc_i2c_check_target_status(dev); + } +} + +static int iproc_i2c_target_register(const struct device *dev, + struct i2c_target_config *target_config) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + mem_addr_t base = DEV_BASE(dev); + int ret = 0; + + if (dd->target_cfg) { + LOG_ERR("Target already registered"); + return -EBUSY; + } + + /* Save pointer to received target config */ + dd->target_cfg = target_config; + + ret = iproc_i2c_target_init(dev, false); + if (ret < 0) { + LOG_ERR("Failed to register iproc_i2c(0x%x) as target, ret %d", (uint32_t)base, + ret); + return ret; + } + + return 0; +} + +static int iproc_i2c_target_unregister(const struct device *dev, struct i2c_target_config *config) +{ + uint32_t val; + mem_addr_t base = DEV_BASE(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + + if (!dd->target_cfg) { + return -EINVAL; + } + + /* Erase the target address programmed */ + sys_write32(0x0, base + S_ADDR_OFFSET); + + /* disable all target interrupts */ + val = sys_read32(base + IE_OFFSET); + val &= ~(IE_S_ALL_INTERRUPT_MASK << IE_S_ALL_INTERRUPT_SHIFT); + sys_write32(val, base + IE_OFFSET); + + dd->target_cfg = NULL; + + return 0; +} +#endif /* CONFIG_I2C_TARGET */ + +static void iproc_i2c_common_init(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + + iproc_i2c_reset_controller(dev); + + /* flush TX/RX FIFOs and set RX FIFO threshold to zero */ + val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT); + sys_write32(val, base + M_FIFO_CTRL_OFFSET); + + /* disable all interrupts */ + sys_write32(0, base + IE_OFFSET); + + /* clear all pending interrupts */ + sys_write32(~0, base + IS_OFFSET); +} + +static int iproc_i2c_check_status(const struct device *dev, uint16_t dev_addr, struct i2c_msg *msg) +{ + mem_addr_t base = DEV_BASE(dev); + uint32_t val; + int rc; + + val = sys_read32(base + M_CMD_OFFSET); + val >>= M_CMD_STATUS_SHIFT; + val &= M_CMD_STATUS_MASK; + + switch (val) { + case M_CMD_STATUS_SUCCESS: + rc = 0; + break; + + case M_CMD_STATUS_LOST_ARB: + LOG_ERR("lost bus arbitration"); + rc = -EAGAIN; + break; + + case M_CMD_STATUS_NACK_ADDR: + LOG_ERR("NAK addr:0x%02x", dev_addr); + rc = -ENXIO; + break; + + case M_CMD_STATUS_NACK_DATA: + LOG_ERR("NAK data"); + rc = -ENXIO; + break; + + case M_CMD_STATUS_TIMEOUT: + LOG_ERR("bus timeout"); + rc = -ETIMEDOUT; + break; + + case M_CMD_STATUS_FIFO_UNDERRUN: + LOG_ERR("FIFO Under-run"); + rc = -ENXIO; + break; + + case M_CMD_STATUS_RX_FIFO_FULL: + LOG_ERR("RX FIFO full"); + rc = -ETIMEDOUT; + break; + + default: + LOG_ERR("Unknown Error : 0x%x", val); + iproc_i2c_enable_disable(dev, false); + iproc_i2c_common_init(dev); + iproc_i2c_enable_disable(dev, true); + rc = -EIO; + break; + } + + if (rc < 0) { + /* flush both Master TX/RX FIFOs */ + val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT); + sys_write32(val, base + M_FIFO_CTRL_OFFSET); + } + + return rc; +} + +static int iproc_i2c_configure(const struct device *dev, uint32_t dev_cfg_raw) +{ + mem_addr_t base = DEV_BASE(dev); + + if (I2C_ADDR_10_BITS & dev_cfg_raw) { + LOG_ERR("10-bit addressing not supported"); + return -ENOTSUP; + } + + switch (I2C_SPEED_GET(dev_cfg_raw)) { + case I2C_SPEED_STANDARD: + sys_clear_bit(base + TIM_CFG_OFFSET, TIM_CFG_MODE_400_SHIFT); + break; + case I2C_SPEED_FAST: + sys_set_bit(base + TIM_CFG_OFFSET, TIM_CFG_MODE_400_SHIFT); + break; + default: + LOG_ERR("Only standard or Fast speed modes are supported"); + return -ENOTSUP; + } + + return 0; +} + +static void iproc_i2c_read_valid_bytes(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + struct i2c_msg *msg = dd->msg; + uint32_t val; + + /* Read valid data from RX FIFO */ + while (dd->rx_bytes < msg->len) { + val = sys_read32(base + M_RX_OFFSET); + + /* rx fifo empty */ + if (!((val >> M_RX_STATUS_SHIFT) & M_RX_STATUS_MASK)) { + break; + } + + msg->buf[dd->rx_bytes] = (val >> M_RX_DATA_SHIFT) & M_RX_DATA_MASK; + dd->rx_bytes++; + } +} + +static int iproc_i2c_data_recv(const struct device *dev) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + mem_addr_t base = DEV_BASE(dev); + struct i2c_msg *msg = dd->msg; + uint32_t bytes_left, val; + + iproc_i2c_read_valid_bytes(dev); + + bytes_left = msg->len - dd->rx_bytes; + if (bytes_left == 0) { + /* finished reading all data, disable rx thld event */ + sys_clear_bit(base + IE_OFFSET, IS_M_RX_THLD_SHIFT); + } else if (bytes_left < dd->thld_bytes) { + /* set bytes left as threshold */ + val = sys_read32(base + M_FIFO_CTRL_OFFSET); + val &= ~(M_FIFO_RX_THLD_MASK << M_FIFO_RX_THLD_SHIFT); + val |= (bytes_left << M_FIFO_RX_THLD_SHIFT); + sys_write32(val, base + M_FIFO_CTRL_OFFSET); + dd->thld_bytes = bytes_left; + } + /* + * if bytes_left >= dd->thld_bytes, no need to change the THRESHOLD. + * It will remain as dd->thld_bytes itself + */ + + return 0; +} + +static int iproc_i2c_transfer_one(const struct device *dev, struct i2c_msg *msg, uint16_t dev_addr) +{ + mem_addr_t base = DEV_BASE(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + uint32_t val, addr, tx_bytes, val_intr_en; + int rc; + + if (!!(sys_read32(base + M_CMD_OFFSET) & BIT(M_CMD_START_BUSY_SHIFT))) { + LOG_ERR("Bus busy, prev xfer ongoing"); + return -EBUSY; + } + + LOG_DBG("%s: msg dev_addr 0x%x flags 0x%x len 0x%x val 0x%x\n", __func__, dev_addr, + msg->flags, msg->len, msg->buf[0]); + + /* Save current i2c_msg */ + dd->msg = msg; + + addr = dev_addr << 1 | (msg->flags & I2C_MSG_READ ? 1 : 0); + sys_write32(addr, base + M_TX_OFFSET); + + tx_bytes = MIN(msg->len, (TX_RX_FIFO_SIZE - 1)); + if (!(msg->flags & I2C_MSG_READ)) { + /* Fill master TX fifo */ + for (uint32_t i = 0; i < tx_bytes; i++) { + val = msg->buf[i]; + /* For the last byte, set MASTER_WR_STATUS bit */ + if (i == msg->len - 1) { + val |= BIT(M_TX_WR_STATUS_SHIFT); + } + sys_write32(val, base + M_TX_OFFSET); + } + + dd->tx_bytes = tx_bytes; + } + + /* + * Enable the "start busy" interrupt, which will be triggered after the + * transaction is done, i.e., the internal start_busy bit, transitions + * from 1 to 0. + */ + val_intr_en = BIT(IE_M_START_BUSY_SHIFT); + + if (!(msg->flags & I2C_MSG_READ) && (msg->len > dd->tx_bytes)) { + val_intr_en |= BIT(IE_M_TX_UNDERRUN_SHIFT); + } + + /* + * Program master command register (0x30) with protocol type and set + * start_busy_command bit to initiate the write transaction + */ + val = BIT(M_CMD_START_BUSY_SHIFT); + if (msg->len == 0) { + /* SMBUS QUICK Command (Read/Write) */ + val |= (M_CMD_SMB_PROT_QUICK << M_CMD_SMB_PROT_SHIFT); + } else if (msg->flags & I2C_MSG_READ) { + uint32_t tmp; + + dd->rx_bytes = 0; + + /* SMBUS Block Read Command */ + val |= M_CMD_SMB_PROT_BLK_RD << M_CMD_SMB_PROT_SHIFT; + val |= msg->len; + + if (msg->len > M_RX_FIFO_MAX_THLD_VALUE) { + dd->thld_bytes = M_RX_FIFO_THLD_VALUE; + } else { + dd->thld_bytes = msg->len; + } + + /* set threshold value */ + tmp = sys_read32(base + M_FIFO_CTRL_OFFSET); + tmp &= ~(M_FIFO_RX_THLD_MASK << M_FIFO_RX_THLD_SHIFT); + tmp |= dd->thld_bytes << M_FIFO_RX_THLD_SHIFT; + sys_write32(tmp, base + M_FIFO_CTRL_OFFSET); + + /* enable the RX threshold interrupt */ + val_intr_en |= BIT(IE_M_RX_THLD_SHIFT); + } else { + /* SMBUS Block Write Command */ + val |= M_CMD_SMB_PROT_BLK_WR << M_CMD_SMB_PROT_SHIFT; + } + + sys_write32(val_intr_en, base + IE_OFFSET); + + sys_write32(val, base + M_CMD_OFFSET); + + /* Wait for the transfer to complete or timeout */ + rc = k_sem_take(&dd->device_sync_sem, K_MSEC(I2C_TIMEOUT_MSEC)); + + /* disable all interrupts */ + sys_write32(0, base + IE_OFFSET); + + if (rc != 0) { + /* flush both Master TX/RX FIFOs */ + val = BIT(M_FIFO_RX_FLUSH_SHIFT) | BIT(M_FIFO_TX_FLUSH_SHIFT); + sys_write32(val, base + M_FIFO_CTRL_OFFSET); + return rc; + } + + /* Check for Master Xfer status */ + rc = iproc_i2c_check_status(dev, dev_addr, msg); + + return rc; +} + +static int iproc_i2c_transfer_multi(const struct device *dev, struct i2c_msg *msgs, + uint8_t num_msgs, uint16_t addr) +{ + int rc; + struct i2c_msg *msgs_chk = msgs; + + if (!msgs_chk) { + return -EINVAL; + } + + /* pre-check all msgs */ + for (uint8_t i = 0; i < num_msgs; i++, msgs_chk++) { + if (!msgs_chk->buf) { + LOG_ERR("Invalid msg buffer"); + return -EINVAL; + } + + if (I2C_MSG_ADDR_10_BITS & msgs_chk->flags) { + LOG_ERR("10-bit addressing not supported"); + return -ENOTSUP; + } + } + + for (uint8_t i = 0; i < num_msgs; i++, msgs++) { + rc = iproc_i2c_transfer_one(dev, msgs, addr); + if (rc < 0) { + return rc; + } + } + + return 0; +} + +static void iproc_i2c_send_data(const struct device *dev) +{ + mem_addr_t base = DEV_BASE(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + struct i2c_msg *msg = dd->msg; + uint32_t tx_bytes = msg->len - dd->tx_bytes; + + /* can only fill up to the FIFO size */ + tx_bytes = MIN(tx_bytes, TX_RX_FIFO_SIZE); + for (uint32_t i = 0; i < tx_bytes; i++) { + /* start from where we left over */ + uint32_t idx = dd->tx_bytes + i; + + uint32_t val = msg->buf[idx]; + + /* mark the last byte */ + if (idx == (msg->len - 1)) { + uint32_t tmp; + + val |= BIT(M_TX_WR_STATUS_SHIFT); + + /* + * Since this is the last byte, we should now + * disable TX FIFO underrun interrupt + */ + tmp = sys_read32(base + IE_OFFSET); + tmp &= ~BIT(IE_M_TX_UNDERRUN_SHIFT); + sys_write32(tmp, base + IE_OFFSET); + } + + /* load data into TX FIFO */ + sys_write32(val, base + M_TX_OFFSET); + } + + /* update number of transferred bytes */ + dd->tx_bytes += tx_bytes; +} + +static void iproc_i2c_master_isr(const struct device *dev, uint32_t status) +{ + struct iproc_i2c_data *dd = DEV_DATA(dev); + + /* TX FIFO is empty and we have more data to send */ + if (status & BIT(IS_M_TX_UNDERRUN_SHIFT)) { + iproc_i2c_send_data(dev); + } + + /* RX FIFO threshold is reached and data needs to be read out */ + if (status & BIT(IS_M_RX_THLD_SHIFT)) { + iproc_i2c_data_recv(dev); + } + + /* transfer is done */ + if (status & BIT(IS_M_START_BUSY_SHIFT)) { + k_sem_give(&dd->device_sync_sem); + } +} + +static void iproc_i2c_isr(void *arg) +{ + const struct device *dev = (const struct device *)arg; + mem_addr_t base = DEV_BASE(dev); + uint32_t status; + uint32_t sl_status, curr_irqs; + + curr_irqs = sys_read32(base + IE_OFFSET); + status = sys_read32(base + IS_OFFSET); + + /* process only target interrupt which are enabled */ + sl_status = status & curr_irqs & ISR_MASK_TARGET; + LOG_DBG("iproc_i2c(0x%x): sts 0x%x, sl_sts 0x%x, curr_ints 0x%x", (uint32_t)base, status, + sl_status, curr_irqs); + +#ifdef CONFIG_I2C_TARGET + /* target events */ + if (sl_status) { + iproc_i2c_target_isr(dev, sl_status); + return; + } +#endif + + status &= ISR_MASK; + /* master events */ + if (status) { + iproc_i2c_master_isr(dev, status); + sys_write32(status, base + IS_OFFSET); + } +} + +static int iproc_i2c_init(const struct device *dev) +{ + const struct iproc_i2c_config *config = DEV_CFG(dev); + struct iproc_i2c_data *dd = DEV_DATA(dev); + uint32_t bitrate = config->bitrate; + int error; + + k_sem_init(&dd->device_sync_sem, 0, 1); + + iproc_i2c_common_init(dev); + + /* Set default clock frequency */ + bitrate = i2c_map_dt_bitrate(bitrate); + + if (dd->target_cfg == NULL) { + bitrate |= I2C_MODE_CONTROLLER; + } + + error = iproc_i2c_configure(dev, bitrate); + if (error) { + return error; + } + + config->irq_config_func(dev); + + iproc_i2c_enable_disable(dev, true); + + return 0; +} + +static const struct i2c_driver_api iproc_i2c_driver_api = { + .configure = iproc_i2c_configure, + .transfer = iproc_i2c_transfer_multi, +#ifdef CONFIG_I2C_TARGET + .target_register = iproc_i2c_target_register, + .target_unregister = iproc_i2c_target_unregister, +#endif +}; + +#define IPROC_I2C_DEVICE_INIT(n) \ + static void iproc_i2c_irq_config_func_##n(const struct device *dev) \ + { \ + ARG_UNUSED(dev); \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), iproc_i2c_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static const struct iproc_i2c_config iproc_i2c_config_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .irq_config_func = iproc_i2c_irq_config_func_##n, \ + .bitrate = DT_INST_PROP(n, clock_frequency), \ + }; \ + \ + static struct iproc_i2c_data iproc_i2c_data_##n; \ + \ + I2C_DEVICE_DT_INST_DEFINE(n, &iproc_i2c_init, NULL, &iproc_i2c_data_##n, \ + &iproc_i2c_config_##n, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ + &iproc_i2c_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(IPROC_I2C_DEVICE_INIT) diff --git a/drivers/i2c/i2c_bitbang.c b/drivers/i2c/i2c_bitbang.c index b92583c888f92..4f99eb1b6dd1c 100644 --- a/drivers/i2c/i2c_bitbang.c +++ b/drivers/i2c/i2c_bitbang.c @@ -60,6 +60,19 @@ int i2c_bitbang_configure(struct i2c_bitbang *context, uint32_t dev_config) return -ENOTSUP; } + context->dev_config = dev_config; + + return 0; +} + +int i2c_bitbang_get_config(struct i2c_bitbang *context, uint32_t *config) +{ + if (context->dev_config == 0) { + return -EIO; + } + + *config = context->dev_config; + return 0; } diff --git a/drivers/i2c/i2c_bitbang.h b/drivers/i2c/i2c_bitbang.h index aa0a8dd6bdddd..14432c30e48b8 100644 --- a/drivers/i2c/i2c_bitbang.h +++ b/drivers/i2c/i2c_bitbang.h @@ -28,7 +28,8 @@ struct i2c_bitbang_io { struct i2c_bitbang { const struct i2c_bitbang_io *io; void *io_context; - uint32_t delays[2]; + uint32_t delays[2]; + uint32_t dev_config; }; /** @@ -48,6 +49,12 @@ void i2c_bitbang_init(struct i2c_bitbang *bitbang, */ int i2c_bitbang_configure(struct i2c_bitbang *bitbang, uint32_t dev_config); +/** + * Implementation of the functionality required by the 'get_config' function + * in struct i2c_driver_api. + */ +int i2c_bitbang_get_config(struct i2c_bitbang *context, uint32_t *config); + /** * Implementation of the functionality required by the 'recover_bus' * function in struct i2c_driver_api. diff --git a/drivers/i2c/i2c_dw.c b/drivers/i2c/i2c_dw.c index 73bb4b6cfe661..6bb2fc5c64df1 100644 --- a/drivers/i2c/i2c_dw.c +++ b/drivers/i2c/i2c_dw.c @@ -252,7 +252,9 @@ static inline void i2c_dw_data_ask(const struct device *dev) data |= IC_DATA_CMD_STOP; } +#ifdef CONFIG_I2C_TARGET clear_bit_intr_mask_tx_empty(reg_base); +#endif /* CONFIG_I2C_TARGET */ write_cmd_data(data, reg_base); @@ -413,6 +415,7 @@ static void i2c_dw_isr(const struct device *port) i2c_dw_data_read(port); } +#ifdef CONFIG_I2C_TARGET /* Check if the TX FIFO is ready for commands. * TX FIFO also serves as command queue where read requests * are written to TX FIFO. @@ -421,6 +424,7 @@ static void i2c_dw_isr(const struct device *port) == I2C_MSG_READ) { set_bit_intr_mask_tx_empty(reg_base); } +#endif /* CONFIG_I2C_TARGET */ if (intr_stat.bits.tx_empty) { if ((dw->xfr_flags & I2C_MSG_RW_MASK) diff --git a/drivers/i2c/i2c_esp32.c b/drivers/i2c/i2c_esp32.c index fdb78a2c6ed32..c6554afa53903 100644 --- a/drivers/i2c/i2c_esp32.c +++ b/drivers/i2c/i2c_esp32.c @@ -91,7 +91,6 @@ struct i2c_esp32_config { int irq_source; - const uint32_t default_config; const uint32_t bitrate; const uint32_t scl_timeout; }; @@ -262,14 +261,17 @@ static int i2c_esp32_recover(const struct device *dev) return 0; } -static void IRAM_ATTR i2c_esp32_configure_timeout(const struct device *dev) +static void IRAM_ATTR i2c_esp32_configure_bitrate(const struct device *dev, uint32_t bitrate) { const struct i2c_esp32_config *config = dev->config; struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; + i2c_clock_source_t sclk = i2c_get_clk_src(bitrate); + uint32_t clk_freq_mhz = i2c_get_src_clk_freq(sclk); + + i2c_hal_set_bus_timing(&data->hal, bitrate, sclk, clk_freq_mhz); + if (config->scl_timeout > 0) { - i2c_clock_source_t sclk = i2c_get_clk_src(config->bitrate); - uint32_t clk_freq_mhz = i2c_get_src_clk_freq(sclk); uint32_t timeout_cycles = MIN(I2C_LL_MAX_TIMEOUT, clk_freq_mhz / MHZ(1) * config->scl_timeout); i2c_ll_set_tout(data->hal.dev, timeout_cycles); @@ -281,20 +283,15 @@ static void IRAM_ATTR i2c_esp32_configure_timeout(const struct device *dev) */ i2c_ll_set_tout(data->hal.dev, I2C_LL_MAX_TIMEOUT); } + + i2c_ll_update(data->hal.dev); } -static int i2c_esp32_configure(const struct device *dev, uint32_t dev_config) +static void i2c_esp32_configure_data_mode(const struct device *dev) { const struct i2c_esp32_config *config = dev->config; struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; - if (!(dev_config & I2C_MODE_CONTROLLER)) { - LOG_ERR("Only I2C Master mode supported."); - return -ENOTSUP; - } - - data->dev_config = dev_config; - i2c_trans_mode_t tx_mode = I2C_DATA_MODE_MSB_FIRST; i2c_trans_mode_t rx_mode = I2C_DATA_MODE_MSB_FIRST; @@ -306,21 +303,59 @@ static int i2c_esp32_configure(const struct device *dev, uint32_t dev_config) rx_mode = I2C_DATA_MODE_LSB_FIRST; } - i2c_hal_master_init(&data->hal); i2c_ll_set_data_mode(data->hal.dev, tx_mode, rx_mode); i2c_ll_set_filter(data->hal.dev, I2C_FILTER_CYC_NUM_DEF); i2c_ll_update(data->hal.dev); - if (config->bitrate == 0) { +} + +static int i2c_esp32_configure(const struct device *dev, uint32_t dev_config) +{ + const struct i2c_esp32_config *config = dev->config; + struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; + uint32_t bitrate; + + if (!(dev_config & I2C_MODE_CONTROLLER)) { + LOG_ERR("Only I2C Master mode supported."); + return -ENOTSUP; + } + + switch (I2C_SPEED_GET(dev_config)) { + case I2C_SPEED_STANDARD: + bitrate = KHZ(100); + break; + case I2C_SPEED_FAST: + bitrate = KHZ(400); + break; + case I2C_SPEED_FAST_PLUS: + bitrate = MHZ(1); + break; + default: LOG_ERR("Error configuring I2C speed."); return -ENOTSUP; } - i2c_clock_source_t sclk = i2c_get_clk_src(config->bitrate); + k_sem_take(&data->transfer_sem, K_FOREVER); - i2c_hal_set_bus_timing(&data->hal, config->bitrate, sclk, i2c_get_src_clk_freq(sclk)); - i2c_esp32_configure_timeout(dev); - i2c_ll_update(data->hal.dev); + data->dev_config = dev_config; + + i2c_esp32_configure_bitrate(dev, bitrate); + + k_sem_give(&data->transfer_sem); + + return 0; +} + +static int i2c_esp32_get_config(const struct device *dev, uint32_t *config) +{ + struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; + + if (data->dev_config == 0) { + LOG_ERR("I2C controller not configured"); + return -EIO; + } + + *config = data->dev_config; return 0; } @@ -694,6 +729,7 @@ static void IRAM_ATTR i2c_esp32_isr(void *arg) static const struct i2c_driver_api i2c_esp32_driver_api = { .configure = i2c_esp32_configure, + .get_config = i2c_esp32_get_config, .transfer = i2c_esp32_transfer, .recover_bus = i2c_esp32_recover }; @@ -701,9 +737,9 @@ static const struct i2c_driver_api i2c_esp32_driver_api = { static int IRAM_ATTR i2c_esp32_init(const struct device *dev) { const struct i2c_esp32_config *config = dev->config; -#ifndef SOC_I2C_SUPPORT_HW_CLR_BUS struct i2c_esp32_data *data = (struct i2c_esp32_data *const)(dev)->data; +#ifndef SOC_I2C_SUPPORT_HW_CLR_BUS if (!gpio_is_ready_dt(&config->scl.gpio)) { LOG_ERR("SCL GPIO device is not ready"); return -EINVAL; @@ -730,7 +766,11 @@ static int IRAM_ATTR i2c_esp32_init(const struct device *dev) esp_intr_alloc(config->irq_source, 0, i2c_esp32_isr, (void *)dev, NULL); - return i2c_esp32_configure(dev, config->default_config); + i2c_hal_master_init(&data->hal); + + i2c_esp32_configure_data_mode(dev); + + return i2c_esp32_configure(dev, I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->bitrate)); } #define I2C(idx) DT_NODELABEL(i2c##idx) @@ -788,7 +828,6 @@ static int IRAM_ATTR i2c_esp32_init(const struct device *dev) .irq_source = ETS_I2C_EXT##idx##_INTR_SOURCE, \ .bitrate = I2C_FREQUENCY(idx), \ .scl_timeout = I2C_ESP32_TIMEOUT(idx), \ - .default_config = I2C_MODE_CONTROLLER, \ }; \ I2C_DEVICE_DT_DEFINE(I2C(idx), i2c_esp32_init, NULL, &i2c_esp32_data_##idx, \ &i2c_esp32_config_##idx, POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ diff --git a/drivers/i2c/i2c_gpio.c b/drivers/i2c/i2c_gpio.c index 4cb5606507a99..80c20f38ba67a 100644 --- a/drivers/i2c/i2c_gpio.c +++ b/drivers/i2c/i2c_gpio.c @@ -93,6 +93,23 @@ static int i2c_gpio_configure(const struct device *dev, uint32_t dev_config) return rc; } +static int i2c_gpio_get_config(const struct device *dev, uint32_t *config) +{ + struct i2c_gpio_context *context = dev->data; + int rc; + + k_mutex_lock(&context->mutex, K_FOREVER); + + rc = i2c_bitbang_get_config(&context->bitbang, config); + if (rc < 0) { + LOG_ERR("I2C controller not configured: %d", rc); + } + + k_mutex_unlock(&context->mutex); + + return rc; +} + static int i2c_gpio_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t slave_address) { @@ -125,6 +142,7 @@ static int i2c_gpio_recover_bus(const struct device *dev) static const struct i2c_driver_api api = { .configure = i2c_gpio_configure, + .get_config = i2c_gpio_get_config, .transfer = i2c_gpio_transfer, .recover_bus = i2c_gpio_recover_bus, }; diff --git a/drivers/i2c/i2c_handlers.c b/drivers/i2c/i2c_handlers.c index 20ec2a6f5788c..e5b87bc2d4cdd 100644 --- a/drivers/i2c/i2c_handlers.c +++ b/drivers/i2c/i2c_handlers.c @@ -14,7 +14,7 @@ static inline int z_vrfy_i2c_configure(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_I2C(dev, configure)); return z_impl_i2c_configure((const struct device *)dev, dev_config); } -#include +#include static inline int z_vrfy_i2c_get_config(const struct device *dev, uint32_t *dev_config) @@ -24,7 +24,7 @@ static inline int z_vrfy_i2c_get_config(const struct device *dev, return z_impl_i2c_get_config(dev, dev_config); } -#include +#include static uint32_t copy_msgs_and_transfer(const struct device *dev, const struct i2c_msg *msgs, @@ -69,25 +69,25 @@ static inline int z_vrfy_i2c_transfer(const struct device *dev, (struct i2c_msg *)msgs, (uint8_t)num_msgs, (uint16_t)addr); } -#include +#include static inline int z_vrfy_i2c_target_driver_register(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); return z_impl_i2c_target_driver_register(dev); } -#include +#include static inline int z_vrfy_i2c_target_driver_unregister(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); return z_impl_i2c_target_driver_unregister(dev); } -#include +#include static inline int z_vrfy_i2c_recover_bus(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_I2C)); return z_impl_i2c_recover_bus(dev); } -#include +#include diff --git a/drivers/i2c/i2c_litex.c b/drivers/i2c/i2c_litex.c index 58636209bf6a9..b237790e91cf8 100644 --- a/drivers/i2c/i2c_litex.c +++ b/drivers/i2c/i2c_litex.c @@ -8,6 +8,11 @@ #include #include + +#include +LOG_MODULE_REGISTER(i2c_litex, CONFIG_I2C_LOG_LEVEL); + +#include "i2c-priv.h" #include "i2c_bitbang.h" #include @@ -25,6 +30,7 @@ struct i2c_litex_cfg { uint32_t write_addr; uint32_t read_addr; + uint32_t bitrate; }; #define GET_I2C_CFG(dev) \ @@ -87,11 +93,18 @@ static int i2c_litex_init(const struct device *dev) { const struct i2c_litex_cfg *config = GET_I2C_CFG(dev); struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev); + int ret; litex_write8(litex_read8(config->write_addr) | HIGH_STATE_ON_I2C_LINES, config->write_addr); i2c_bitbang_init(bitbang, &i2c_litex_bitbang_io, (void *)config); - return 0; + ret = i2c_bitbang_configure(bitbang, + I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->bitrate)); + if (ret != 0) { + LOG_ERR("failed to configure I2C bitbang: %d", ret); + } + + return ret; } static int i2c_litex_configure(const struct device *dev, uint32_t dev_config) @@ -101,6 +114,13 @@ static int i2c_litex_configure(const struct device *dev, uint32_t dev_config) return i2c_bitbang_configure(bitbang, dev_config); } +static int i2c_litex_get_config(const struct device *dev, uint32_t *config) +{ + struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev); + + return i2c_bitbang_get_config(bitbang, config); +} + static int i2c_litex_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t addr) { @@ -109,9 +129,18 @@ static int i2c_litex_transfer(const struct device *dev, struct i2c_msg *msgs, return i2c_bitbang_transfer(bitbang, msgs, num_msgs, addr); } +static int i2c_litex_recover_bus(const struct device *dev) +{ + struct i2c_bitbang *bitbang = GET_I2C_BITBANG(dev); + + return i2c_bitbang_recover_bus(bitbang); +} + static const struct i2c_driver_api i2c_litex_driver_api = { .configure = i2c_litex_configure, + .get_config = i2c_litex_get_config, .transfer = i2c_litex_transfer, + .recover_bus = i2c_litex_recover_bus, }; /* Device Instantiation */ @@ -120,6 +149,7 @@ static const struct i2c_driver_api i2c_litex_driver_api = { static const struct i2c_litex_cfg i2c_litex_cfg_##n = { \ .write_addr = DT_INST_REG_ADDR_BY_NAME(n, write), \ .read_addr = DT_INST_REG_ADDR_BY_NAME(n, read), \ + .bitrate = DT_INST_PROP(n, clock_frequency), \ }; \ \ static struct i2c_bitbang i2c_bitbang_##n; \ diff --git a/drivers/i2c/i2c_ll_stm32.c b/drivers/i2c/i2c_ll_stm32.c index 29f5a5ae08fe5..15eb4558d79c4 100644 --- a/drivers/i2c/i2c_ll_stm32.c +++ b/drivers/i2c/i2c_ll_stm32.c @@ -56,6 +56,26 @@ int i2c_stm32_get_config(const struct device *dev, uint32_t *config) *config = data->dev_config; +#if CONFIG_I2C_STM32_V2_TIMING + /* Print the timing parameter of device data */ + LOG_INF("I2C timing value, report to the DTS :"); + + /* I2C BIT RATE */ + if (data->current_timing.i2c_speed == 100000) { + LOG_INF("timings = <%d I2C_BITRATE_STANDARD 0x%X>;", + data->current_timing.periph_clock, + data->current_timing.timing_setting); + } else if (data->current_timing.i2c_speed == 400000) { + LOG_INF("timings = <%d I2C_BITRATE_FAST 0x%X>;", + data->current_timing.periph_clock, + data->current_timing.timing_setting); + } else if (data->current_timing.i2c_speed == 1000000) { + LOG_INF("timings = <%d I2C_SPEED_FAST_PLUS 0x%X>;", + data->current_timing.periph_clock, + data->current_timing.timing_setting); + } +#endif /* CONFIG_I2C_STM32_V2_TIMING */ + return 0; } diff --git a/drivers/i2c/i2c_ll_stm32.h b/drivers/i2c/i2c_ll_stm32.h index 0a9dc1be350a6..ec6db5b32a083 100644 --- a/drivers/i2c/i2c_ll_stm32.h +++ b/drivers/i2c/i2c_ll_stm32.h @@ -56,6 +56,10 @@ struct i2c_stm32_data { #endif struct k_sem bus_mutex; uint32_t dev_config; +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_i2c_v2) + /* Store the current timing structure set by runtime config */ + struct i2c_config_timing current_timing; +#endif #ifdef CONFIG_I2C_STM32_V1 uint16_t slave_address; #endif diff --git a/drivers/i2c/i2c_ll_stm32_v2.c b/drivers/i2c/i2c_ll_stm32_v2.c index a685ebebeb786..24d51eed45ea7 100644 --- a/drivers/i2c/i2c_ll_stm32_v2.c +++ b/drivers/i2c/i2c_ll_stm32_v2.c @@ -29,6 +29,94 @@ LOG_MODULE_REGISTER(i2c_ll_stm32_v2); #define STM32_I2C_TRANSFER_TIMEOUT_MSEC 500 +#ifdef CONFIG_I2C_STM32_V2_TIMING +/* Use the algorithm to calcuate the I2C timing */ +#ifndef STM32_I2C_VALID_TIMING_NBR +#define STM32_I2C_VALID_TIMING_NBR 128U +#endif +#define STM32_I2C_SPEED_FREQ_STANDARD 0U /* 100 kHz */ +#define STM32_I2C_SPEED_FREQ_FAST 1U /* 400 kHz */ +#define STM32_I2C_SPEED_FREQ_FAST_PLUS 2U /* 1 MHz */ +#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50U /* ns */ +#define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260U /* ns */ +#define STM32_I2C_USE_ANALOG_FILTER 1U +#define STM32_I2C_DIGITAL_FILTER_COEF 0U +#define STM32_I2C_PRESC_MAX 16U +#define STM32_I2C_SCLDEL_MAX 16U +#define STM32_I2C_SDADEL_MAX 16U +#define STM32_I2C_SCLH_MAX 256U +#define STM32_I2C_SCLL_MAX 256U + +/* I2C_DEVICE_Private_Types */ +struct stm32_i2c_charac_t { + uint32_t freq; /* Frequency in Hz */ + uint32_t freq_min; /* Minimum frequency in Hz */ + uint32_t freq_max; /* Maximum frequency in Hz */ + uint32_t hddat_min; /* Minimum data hold time in ns */ + uint32_t vddat_max; /* Maximum data valid time in ns */ + uint32_t sudat_min; /* Minimum data setup time in ns */ + uint32_t lscl_min; /* Minimum low period of the SCL clock in ns */ + uint32_t hscl_min; /* Minimum high period of SCL clock in ns */ + uint32_t trise; /* Rise time in ns */ + uint32_t tfall; /* Fall time in ns */ + uint32_t dnf; /* Digital noise filter coefficient */ +}; + +struct stm32_i2c_timings_t { + uint32_t presc; /* Timing prescaler */ + uint32_t tscldel; /* SCL delay */ + uint32_t tsdadel; /* SDA delay */ + uint32_t sclh; /* SCL high period */ + uint32_t scll; /* SCL low period */ +}; + +/* I2C_DEVICE Private Constants */ +static const struct stm32_i2c_charac_t stm32_i2c_charac[] = { + [STM32_I2C_SPEED_FREQ_STANDARD] = { + .freq = 100000, + .freq_min = 80000, + .freq_max = 120000, + .hddat_min = 0, + .vddat_max = 3450, + .sudat_min = 250, + .lscl_min = 4700, + .hscl_min = 4000, + .trise = 640, + .tfall = 20, + .dnf = STM32_I2C_DIGITAL_FILTER_COEF, + }, + [STM32_I2C_SPEED_FREQ_FAST] = { + .freq = 400000, + .freq_min = 320000, + .freq_max = 480000, + .hddat_min = 0, + .vddat_max = 900, + .sudat_min = 100, + .lscl_min = 1300, + .hscl_min = 600, + .trise = 250, + .tfall = 100, + .dnf = STM32_I2C_DIGITAL_FILTER_COEF, + }, + [STM32_I2C_SPEED_FREQ_FAST_PLUS] = { + .freq = 1000000, + .freq_min = 800000, + .freq_max = 1200000, + .hddat_min = 0, + .vddat_max = 450, + .sudat_min = 50, + .lscl_min = 500, + .hscl_min = 260, + .trise = 60, + .tfall = 100, + .dnf = STM32_I2C_DIGITAL_FILTER_COEF, + }, +}; + +static struct stm32_i2c_timings_t i2c_valid_timing[STM32_I2C_VALID_TIMING_NBR]; +static uint32_t i2c_valid_timing_nbr; +#endif /* CONFIG_I2C_STM32_V2_TIMING */ + static inline void msg_init(const struct device *dev, struct i2c_msg *msg, uint8_t *next_msg_flags, uint16_t slave, uint32_t transfer) @@ -725,6 +813,240 @@ static int stm32_i2c_msg_read(const struct device *dev, struct i2c_msg *msg, } #endif +#ifdef CONFIG_I2C_STM32_V2_TIMING +/* + * Macro used to fix the compliance check warning : + * "DEEP_INDENTATION: Too many leading tabs - consider code refactoring + * in the i2c_compute_scll_sclh() function below + */ +#define I2C_LOOP_SCLH(); \ + if ((tscl >= clk_min) && \ + (tscl <= clk_max) && \ + (tscl_h >= stm32_i2c_charac[i2c_speed].hscl_min) && \ + (ti2cclk < tscl_h)) { \ + \ + int32_t error = (int32_t)tscl - (int32_t)ti2cspeed; \ + \ + if (error < 0) { \ + error = -error; \ + } \ + \ + if ((uint32_t)error < prev_error) { \ + prev_error = (uint32_t)error; \ + i2c_valid_timing[count].scll = scll; \ + i2c_valid_timing[count].sclh = sclh; \ + ret = count; \ + } \ + } + +/* + * @brief Calculate SCLL and SCLH and find best configuration. + * @param clock_src_freq I2C source clock in Hz. + * @param i2c_speed I2C frequency (index). + * @retval config index (0 to I2C_VALID_TIMING_NBR], 0xFFFFFFFF for no valid config. + */ +uint32_t i2c_compute_scll_sclh(uint32_t clock_src_freq, uint32_t i2c_speed) +{ + uint32_t ret = 0xFFFFFFFFU; + uint32_t ti2cclk; + uint32_t ti2cspeed; + uint32_t prev_error; + uint32_t dnf_delay; + uint32_t clk_min, clk_max; + uint32_t scll, sclh; + uint32_t tafdel_min; + + ti2cclk = (NSEC_PER_SEC + (clock_src_freq / 2U)) / clock_src_freq; + ti2cspeed = (NSEC_PER_SEC + (stm32_i2c_charac[i2c_speed].freq / 2U)) / + stm32_i2c_charac[i2c_speed].freq; + + tafdel_min = (STM32_I2C_USE_ANALOG_FILTER == 1U) ? + STM32_I2C_ANALOG_FILTER_DELAY_MIN : + 0U; + + /* tDNF = DNF x tI2CCLK */ + dnf_delay = stm32_i2c_charac[i2c_speed].dnf * ti2cclk; + + clk_max = NSEC_PER_SEC / stm32_i2c_charac[i2c_speed].freq_min; + clk_min = NSEC_PER_SEC / stm32_i2c_charac[i2c_speed].freq_max; + + prev_error = ti2cspeed; + + for (uint32_t count = 0; count < STM32_I2C_VALID_TIMING_NBR; count++) { + /* tPRESC = (PRESC+1) x tI2CCLK*/ + uint32_t tpresc = (i2c_valid_timing[count].presc + 1U) * ti2cclk; + + for (scll = 0; scll < STM32_I2C_SCLL_MAX; scll++) { + /* tLOW(min) <= tAF(min) + tDNF + 2 x tI2CCLK + [(SCLL+1) x tPRESC ] */ + uint32_t tscl_l = tafdel_min + dnf_delay + + (2U * ti2cclk) + ((scll + 1U) * tpresc); + + /* + * The I2CCLK period tI2CCLK must respect the following conditions: + * tI2CCLK < (tLOW - tfilters) / 4 and tI2CCLK < tHIGH + */ + if ((tscl_l > stm32_i2c_charac[i2c_speed].lscl_min) && + (ti2cclk < ((tscl_l - tafdel_min - dnf_delay) / 4U))) { + for (sclh = 0; sclh < STM32_I2C_SCLH_MAX; sclh++) { + /* + * tHIGH(min) <= tAF(min) + tDNF + + * 2 x tI2CCLK + [(SCLH+1) x tPRESC] + */ + uint32_t tscl_h = tafdel_min + dnf_delay + + (2U * ti2cclk) + ((sclh + 1U) * tpresc); + + /* tSCL = tf + tLOW + tr + tHIGH */ + uint32_t tscl = tscl_l + + tscl_h + stm32_i2c_charac[i2c_speed].trise + + stm32_i2c_charac[i2c_speed].tfall; + + /* get timings with the lowest clock error */ + I2C_LOOP_SCLH(); + } + } + } + } + + return ret; +} + +/* + * Macro used to fix the compliance check warning : + * "DEEP_INDENTATION: Too many leading tabs - consider code refactoring + * in the i2c_compute_presc_scldel_sdadel() function below + */ +#define I2C_LOOP_SDADEL(); \ + \ + if ((tsdadel >= (uint32_t)tsdadel_min) && \ + (tsdadel <= (uint32_t)tsdadel_max)) { \ + if (presc != prev_presc) { \ + i2c_valid_timing[i2c_valid_timing_nbr].presc = presc; \ + i2c_valid_timing[i2c_valid_timing_nbr].tscldel = scldel; \ + i2c_valid_timing[i2c_valid_timing_nbr].tsdadel = sdadel; \ + prev_presc = presc; \ + i2c_valid_timing_nbr++; \ + \ + if (i2c_valid_timing_nbr >= STM32_I2C_VALID_TIMING_NBR) { \ + break; \ + } \ + } \ + } + +/* + * @brief Compute PRESC, SCLDEL and SDADEL. + * @param clock_src_freq I2C source clock in Hz. + * @param i2c_speed I2C frequency (index). + * @retval None. + */ +void i2c_compute_presc_scldel_sdadel(uint32_t clock_src_freq, uint32_t i2c_speed) +{ + uint32_t prev_presc = STM32_I2C_PRESC_MAX; + uint32_t ti2cclk; + int32_t tsdadel_min, tsdadel_max; + int32_t tscldel_min; + uint32_t presc, scldel, sdadel; + uint32_t tafdel_min, tafdel_max; + + ti2cclk = (NSEC_PER_SEC + (clock_src_freq / 2U)) / clock_src_freq; + + tafdel_min = (STM32_I2C_USE_ANALOG_FILTER == 1U) ? + STM32_I2C_ANALOG_FILTER_DELAY_MIN : 0U; + tafdel_max = (STM32_I2C_USE_ANALOG_FILTER == 1U) ? + STM32_I2C_ANALOG_FILTER_DELAY_MAX : 0U; + /* + * tDNF = DNF x tI2CCLK + * tPRESC = (PRESC+1) x tI2CCLK + * SDADEL >= {tf +tHD;DAT(min) - tAF(min) - tDNF - [3 x tI2CCLK]} / {tPRESC} + * SDADEL <= {tVD;DAT(max) - tr - tAF(max) - tDNF- [4 x tI2CCLK]} / {tPRESC} + */ + tsdadel_min = (int32_t)stm32_i2c_charac[i2c_speed].tfall + + (int32_t)stm32_i2c_charac[i2c_speed].hddat_min - + (int32_t)tafdel_min - + (int32_t)(((int32_t)stm32_i2c_charac[i2c_speed].dnf + 3) * + (int32_t)ti2cclk); + + tsdadel_max = (int32_t)stm32_i2c_charac[i2c_speed].vddat_max - + (int32_t)stm32_i2c_charac[i2c_speed].trise - + (int32_t)tafdel_max - + (int32_t)(((int32_t)stm32_i2c_charac[i2c_speed].dnf + 4) * + (int32_t)ti2cclk); + + /* {[tr+ tSU;DAT(min)] / [tPRESC]} - 1 <= SCLDEL */ + tscldel_min = (int32_t)stm32_i2c_charac[i2c_speed].trise + + (int32_t)stm32_i2c_charac[i2c_speed].sudat_min; + + if (tsdadel_min <= 0) { + tsdadel_min = 0; + } + + if (tsdadel_max <= 0) { + tsdadel_max = 0; + } + + for (presc = 0; presc < STM32_I2C_PRESC_MAX; presc++) { + for (scldel = 0; scldel < STM32_I2C_SCLDEL_MAX; scldel++) { + /* TSCLDEL = (SCLDEL+1) * (PRESC+1) * TI2CCLK */ + uint32_t tscldel = (scldel + 1U) * (presc + 1U) * ti2cclk; + + if (tscldel >= (uint32_t)tscldel_min) { + for (sdadel = 0; sdadel < STM32_I2C_SDADEL_MAX; sdadel++) { + /* TSDADEL = SDADEL * (PRESC+1) * TI2CCLK */ + uint32_t tsdadel = (sdadel * (presc + 1U)) * ti2cclk; + + I2C_LOOP_SDADEL(); + } + + if (i2c_valid_timing_nbr >= STM32_I2C_VALID_TIMING_NBR) { + return; + } + } + } + } +} + +int stm32_i2c_configure_timing(const struct device *dev, uint32_t clock) +{ + const struct i2c_stm32_config *cfg = dev->config; + struct i2c_stm32_data *data = dev->data; + I2C_TypeDef *i2c = cfg->i2c; + uint32_t timing = 0U; + uint32_t idx; + uint32_t speed = 0U; + uint32_t i2c_freq = cfg->bitrate; + + /* Reset valid timing count at the beginning of each new computation */ + i2c_valid_timing_nbr = 0; + + if ((clock != 0U) && (i2c_freq != 0U)) { + for (speed = 0 ; speed <= (uint32_t)STM32_I2C_SPEED_FREQ_FAST_PLUS ; speed++) { + if ((i2c_freq >= stm32_i2c_charac[speed].freq_min) && + (i2c_freq <= stm32_i2c_charac[speed].freq_max)) { + i2c_compute_presc_scldel_sdadel(clock, speed); + idx = i2c_compute_scll_sclh(clock, speed); + if (idx < STM32_I2C_VALID_TIMING_NBR) { + timing = ((i2c_valid_timing[idx].presc & + 0x0FU) << 28) | + ((i2c_valid_timing[idx].tscldel & 0x0FU) << 20) | + ((i2c_valid_timing[idx].tsdadel & 0x0FU) << 16) | + ((i2c_valid_timing[idx].sclh & 0xFFU) << 8) | + ((i2c_valid_timing[idx].scll & 0xFFU) << 0); + } + break; + } + } + } + + /* Fill the current timing value in data structure at runtime */ + data->current_timing.periph_clock = clock; + data->current_timing.i2c_speed = i2c_freq; + data->current_timing.timing_setting = timing; + + LL_I2C_SetTiming(i2c, timing); + + return 0; +} +#else/* CONFIG_I2C_STM32_V2_TIMING */ + int stm32_i2c_configure_timing(const struct device *dev, uint32_t clock) { const struct i2c_stm32_config *cfg = dev->config; @@ -797,10 +1119,12 @@ int stm32_i2c_configure_timing(const struct device *dev, uint32_t clock) return -EINVAL; } + LOG_INF("I2C TIMING = 0x%x\n", timing); LL_I2C_SetTiming(i2c, timing); return 0; } +#endif /* CONFIG_I2C_STM32_V2_TIMING */ int stm32_i2c_transaction(const struct device *dev, struct i2c_msg msg, uint8_t *next_msg_flags, diff --git a/drivers/i2c/i2c_max32.c b/drivers/i2c/i2c_max32.c new file mode 100644 index 0000000000000..8783e6d7e4863 --- /dev/null +++ b/drivers/i2c/i2c_max32.c @@ -0,0 +1,732 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_max32_i2c + +#include +#include +#include +#include +#include + +#include + +#define ADI_MAX32_I2C_INT_FL0_MASK 0x00FFFFFF +#define ADI_MAX32_I2C_INT_FL1_MASK 0x7 + +#define ADI_MAX32_I2C_STATUS_MASTER_BUSY BIT(5) + +#define I2C_RECOVER_MAX_RETRIES 3 + +/* Driver config */ +struct max32_i2c_config { + mxc_i2c_regs_t *regs; + const struct pinctrl_dev_config *pctrl; + const struct device *clock; + struct max32_perclk perclk; + uint32_t bitrate; +#if defined(CONFIG_I2C_TARGET) || defined(CONFIG_I2C_MAX32_INTERRUPT) + uint8_t irqn; + void (*irq_config_func)(const struct device *dev); +#endif +}; + +struct max32_i2c_data { + mxc_i2c_req_t req; + const struct device *dev; + struct k_sem lock; + uint8_t target_mode; + uint8_t flags; +#ifdef CONFIG_I2C_TARGET + struct i2c_target_config *target_cfg; + bool first_write; +#endif /* CONFIG_I2C_TARGET */ + uint32_t readb; + uint32_t written; +#if defined(CONFIG_I2C_MAX32_INTERRUPT) + struct k_sem xfer; + int err; +#endif +}; + +static int api_configure(const struct device *dev, uint32_t dev_cfg) +{ + int ret = 0; + const struct max32_i2c_config *const cfg = dev->config; + mxc_i2c_regs_t *i2c = cfg->regs; + + switch (I2C_SPEED_GET(dev_cfg)) { + case I2C_SPEED_STANDARD: /** I2C Standard Speed: 100 kHz */ + ret = MXC_I2C_SetFrequency(i2c, MXC_I2C_STD_MODE); + break; + + case I2C_SPEED_FAST: /** I2C Fast Speed: 400 kHz */ + ret = MXC_I2C_SetFrequency(i2c, MXC_I2C_FAST_SPEED); + break; + +#if defined(MXC_I2C_FASTPLUS_SPEED) + case I2C_SPEED_FAST_PLUS: /** I2C Fast Plus Speed: 1 MHz */ + ret = MXC_I2C_SetFrequency(i2c, MXC_I2C_FASTPLUS_SPEED); + break; +#endif + +#if defined(MXC_I2C_HIGH_SPEED) + case I2C_SPEED_HIGH: /** I2C High Speed: 3.4 MHz */ + ret = MXC_I2C_SetFrequency(i2c, MXC_I2C_HIGH_SPEED); + break; +#endif + + default: + /* Speed not supported */ + return -ENOTSUP; + } + + return ret; +} + +#ifdef CONFIG_I2C_TARGET +static int api_target_register(const struct device *dev, struct i2c_target_config *cfg) +{ + const struct max32_i2c_config *config = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = config->regs; + int ret; + + data->target_cfg = cfg; + + ret = MXC_I2C_Init(i2c, 0, cfg->address); + if (ret == E_NO_ERROR) { + data->target_mode = 1; + irq_enable(config->irqn); + MXC_I2C_SlaveTransactionAsync(i2c, NULL); + } + + return ret == E_NO_ERROR ? 0 : E_FAIL; +} + +static int api_target_unregister(const struct device *dev, struct i2c_target_config *cfg) +{ + const struct max32_i2c_config *config = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = config->regs; + + data->target_cfg = NULL; + data->target_mode = 0; + +#ifndef CONFIG_I2C_MAX32_INTERRUPT + irq_disable(config->irqn); +#endif + + return MXC_I2C_Init(i2c, 1, 0); +} + +static int i2c_max32_target_callback(const struct device *dev, mxc_i2c_regs_t *i2c, + mxc_i2c_slave_event_t event) +{ + struct max32_i2c_data *data = dev->data; + const struct i2c_target_callbacks *target_cb = data->target_cfg->callbacks; + static uint8_t rxval, txval, rxcnt; + + switch (event) { + case MXC_I2C_EVT_MASTER_WR: + if (data->first_write && target_cb->write_requested) { + target_cb->write_requested(data->target_cfg); + data->first_write = false; + } + break; + case MXC_I2C_EVT_MASTER_RD: + break; + case MXC_I2C_EVT_RX_THRESH: + case MXC_I2C_EVT_OVERFLOW: + rxcnt = MXC_I2C_GetRXFIFOAvailable(i2c); + if (target_cb->write_received) { + while (rxcnt--) { + MXC_I2C_ReadRXFIFO(i2c, &rxval, 1); + target_cb->write_received(data->target_cfg, rxval); + } + } else { + MXC_I2C_ClearRXFIFO(i2c); + } + break; + case MXC_I2C_EVT_TX_THRESH: + case MXC_I2C_EVT_UNDERFLOW: + if (target_cb->read_requested) { + target_cb->read_requested(data->target_cfg, &txval); + MXC_I2C_WriteTXFIFO(i2c, &txval, 1); + } + if (target_cb->read_processed) { + target_cb->read_processed(data->target_cfg, &txval); + } + break; + case MXC_I2C_EVT_TRANS_COMP: + if (target_cb->stop) { + target_cb->stop(data->target_cfg); + } + data->first_write = true; + break; + } + + return 0; +} +#endif /* CONFIG_I2C_TARGET */ + +static int api_recover_bus(const struct device *dev) +{ + int ret; + const struct max32_i2c_config *const cfg = dev->config; + mxc_i2c_regs_t *i2c = cfg->regs; + + ret = MXC_I2C_Recover(i2c, I2C_RECOVER_MAX_RETRIES); + + return ret; +} + +#ifndef CONFIG_I2C_MAX32_INTERRUPT +static int i2c_max32_transfer_sync(mxc_i2c_regs_t *i2c, struct max32_i2c_data *data) +{ + uint32_t int_fl0, int_fl1; + uint32_t readb = 0; + mxc_i2c_req_t *req = &data->req; + + /* Wait for acknowledge */ + if (data->flags & (I2C_MSG_RESTART | I2C_MSG_READ)) { + do { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + } while (!(int_fl0 & ADI_MAX32_I2C_INT_FL0_ADDR_ACK) && + !(int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR)); + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + return -EIO; + } + + while (req->tx_len > data->written) { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_TX_THD) { + data->written += MXC_I2C_WriteTXFIFO(i2c, &req->tx_buf[data->written], + req->tx_len - data->written); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_TX_THD, 0); + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + return -EIO; + } + } + + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_DONE, 0); + Wrap_MXC_I2C_SetRxCount(i2c, req->rx_len); + while (req->rx_len > readb) { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + if (int_fl0 & (ADI_MAX32_I2C_INT_FL0_RX_THD | ADI_MAX32_I2C_INT_FL0_DONE)) { + readb += MXC_I2C_ReadRXFIFO(i2c, &req->rx_buf[readb], req->rx_len - readb); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_RX_THD, 0); + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + return -EIO; + } + + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + if ((int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE) && (req->rx_len > readb) && + MXC_I2C_GetRXFIFOAvailable(i2c) == 0) { + Wrap_MXC_I2C_SetRxCount(i2c, req->rx_len - readb); + Wrap_MXC_I2C_Restart(i2c); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_DONE, 0); + i2c->fifo = (req->addr << 1) | 0x1; + } + } + + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + return -EIO; + } + + if (data->flags & I2C_MSG_STOP) { + MXC_I2C_Stop(i2c); + do { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + } while (!(int_fl0 & ADI_MAX32_I2C_INT_FL0_STOP)); + } + + if (req->rx_len) { + do { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + } while (!(int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE)); + } else { + while (Wrap_MXC_I2C_GetTxFIFOLevel(i2c) > 0) { + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + } + } + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + + return 0; +} +#endif /* CONFIG_I2C_MAX32_INTERRUPT */ + +#ifdef CONFIG_I2C_MAX32_INTERRUPT +static int i2c_max32_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t target_address) +{ + int ret = 0; + const struct max32_i2c_config *const cfg = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = cfg->regs; + mxc_i2c_req_t *req = &data->req; + uint8_t target_rw; + unsigned int i = 0; + + req->i2c = i2c; + req->addr = target_address; + + k_sem_take(&data->lock, K_FOREVER); + + MXC_I2C_ClearRXFIFO(i2c); + MXC_I2C_ClearTXFIFO(i2c); + MXC_I2C_SetRXThreshold(i2c, 1); + + /* First message should always begin with a START condition */ + msgs[0].flags |= I2C_MSG_RESTART; + + for (i = 0; i < num_msgs; i++) { + if (msgs[i].flags & I2C_MSG_READ) { + req->rx_buf = (unsigned char *)msgs[i].buf; + req->rx_len = msgs[i].len; + req->tx_buf = NULL; + req->tx_len = 0; + target_rw = (target_address << 1) | 0x1; + } else { + req->tx_buf = (unsigned char *)msgs[i].buf; + req->tx_len = msgs[i].len; + req->rx_buf = NULL; + req->rx_len = 0; + target_rw = (target_address << 1) & ~0x1; + } + + /* + * If previous message ends with a STOP condition, this message + * should begin with a START + */ + if (i > 0) { + if ((msgs[i - 1].flags & (I2C_MSG_STOP | I2C_MSG_READ))) { + msgs[i].flags |= I2C_MSG_RESTART; + } + } + + data->flags = msgs[i].flags; + data->readb = 0; + data->written = 0; + data->err = 0; + + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_ERR, 0); + Wrap_MXC_I2C_SetRxCount(i2c, req->rx_len); + if ((data->flags & I2C_MSG_RESTART)) { + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_ADDR_ACK, 0); + MXC_I2C_Start(i2c); + Wrap_MXC_I2C_WaitForRestart(i2c); + MXC_I2C_WriteTXFIFO(i2c, &target_rw, 1); + } else { + if (req->tx_len) { + data->written = MXC_I2C_WriteTXFIFO(i2c, req->tx_buf, 1); + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_TX_THD, 0); + } else { + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_RX_THD, 0); + } + } + + ret = k_sem_take(&data->xfer, K_FOREVER); + if (data->err) { + MXC_I2C_Stop(i2c); + ret = data->err; + } else { + if (data->flags & I2C_MSG_STOP) { + /* Wait for busy flag to be cleared */ + while (i2c->status & ADI_MAX32_I2C_STATUS_MASTER_BUSY) { + } + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, + ADI_MAX32_I2C_INT_FL1_MASK); + } + } + if (ret) { + break; + } + } + + k_sem_give(&data->lock); + + return ret; +} +#else +static int i2c_max32_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t target_address) +{ + int ret = 0; + const struct max32_i2c_config *const cfg = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = cfg->regs; + mxc_i2c_req_t *req = &data->req; + uint8_t target_rw; + unsigned int i = 0; + + req->i2c = i2c; + req->addr = target_address; + + k_sem_take(&data->lock, K_FOREVER); + + MXC_I2C_ClearRXFIFO(i2c); + + /* First message should always begin with a START condition */ + msgs[0].flags |= I2C_MSG_RESTART; + + for (i = 0; i < num_msgs; i++) { + if (msgs[i].flags & I2C_MSG_READ) { + req->rx_buf = (unsigned char *)msgs[i].buf; + req->rx_len = msgs[i].len; + req->tx_buf = NULL; + req->tx_len = 0; + target_rw = (target_address << 1) | 0x1; + } else { + req->tx_buf = (unsigned char *)msgs[i].buf; + req->tx_len = msgs[i].len; + req->rx_buf = NULL; + req->rx_len = 0; + target_rw = (target_address << 1) & ~0x1; + } + + /* + * If previous message ends with a STOP condition, this message + * should begin with a START + */ + if (i > 0) { + if ((msgs[i - 1].flags & (I2C_MSG_STOP | I2C_MSG_READ))) { + msgs[i].flags |= I2C_MSG_RESTART; + } + } + + data->flags = msgs[i].flags; + data->readb = 0; + data->written = 0; + + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + + Wrap_MXC_I2C_SetIntEn(i2c, 0, 0); + if (data->flags & I2C_MSG_RESTART) { + MXC_I2C_Start(i2c); + Wrap_MXC_I2C_WaitForRestart(i2c); + MXC_I2C_WriteTXFIFO(i2c, &target_rw, 1); + } + ret = i2c_max32_transfer_sync(i2c, data); + if (ret) { + MXC_I2C_Stop(i2c); + break; + } + } + + k_sem_give(&data->lock); + + return ret; +} +#endif /* CONFIG_I2C_MAX32_INTERRUPT */ + +static int api_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, + uint16_t target_address) +{ + return i2c_max32_transfer(dev, msgs, num_msgs, target_address); +} + +#ifdef CONFIG_I2C_TARGET +static void i2c_max32_isr_target(const struct device *dev, mxc_i2c_regs_t *i2c) +{ + uint32_t ctrl; + uint32_t int_fl0; + uint32_t int_fl1; + uint32_t int_en0; + uint32_t int_en1; + + ctrl = i2c->ctrl; + Wrap_MXC_I2C_GetIntEn(i2c, &int_en0, &int_en1); + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + /* Error occurred, notify callback function and end transaction */ + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_TRANS_COMP); + + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + MXC_I2C_ClearTXFIFO(i2c); + MXC_I2C_ClearRXFIFO(i2c); + } + + /* Check whether data is available if we received an interrupt occurred while receiving */ + if (int_en0 & ADI_MAX32_I2C_INT_EN0_RX_THD || int_en1 & ADI_MAX32_I2C_INT_EN1_RX_OVERFLOW) { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_RX_THD) { + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_RX_THRESH); + } + + if (int_fl1 & ADI_MAX32_I2C_INT_FL1_RX_OVERFLOW) { + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_OVERFLOW); + } + } + + /* Check whether TX FIFO needs to be refilled if interrupt ocurred while transmitting */ + if (int_en0 & (ADI_MAX32_I2C_INT_EN0_TX_THD | ADI_MAX32_I2C_INT_EN0_TX_LOCK_OUT) || + int_en1 & ADI_MAX32_I2C_INT_EN1_TX_UNDERFLOW) { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_TX_THD) { + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_TX_THRESH); + } + + if (int_fl1 & ADI_MAX32_I2C_INT_EN1_TX_UNDERFLOW) { + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_UNDERFLOW); + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_TX_LOCK_OUT) { + int_en0 = ADI_MAX32_I2C_INT_EN0_ADDR_MATCH; + int_en1 = 0; + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_TRANS_COMP); + } + } + + /* Check if transaction completed or restart occurred */ + if (int_en0 & ADI_MAX32_I2C_INT_EN0_DONE) { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_STOP) { + /* Stop/NACK condition occurred, transaction complete */ + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_TRANS_COMP); + int_en0 = ADI_MAX32_I2C_INT_EN0_ADDR_MATCH; + } else if (int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE) { + /* Restart detected, re-arm address match interrupt */ + int_en0 = ADI_MAX32_I2C_INT_EN0_ADDR_MATCH; + } + int_en1 = 0; + } + + /* Check for address match interrupt */ + if (int_en0 & ADI_MAX32_I2C_INT_EN0_ADDR_MATCH) { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ADDR_MATCH) { + /* Address match occurred, prepare for transaction */ + if (i2c->ctrl & MXC_F_I2C_CTRL_READ) { + /* Read request received from the master */ + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_MASTER_RD); + int_en0 = ADI_MAX32_I2C_INT_EN0_TX_THD | + ADI_MAX32_I2C_INT_EN0_TX_LOCK_OUT | + ADI_MAX32_I2C_INT_EN0_DONE | ADI_MAX32_I2C_INT_EN0_ERR; + int_en1 = ADI_MAX32_I2C_INT_EN1_TX_UNDERFLOW; + } else { + /* Write request received from the master */ + i2c_max32_target_callback(dev, i2c, MXC_I2C_EVT_MASTER_WR); + int_en0 = ADI_MAX32_I2C_INT_EN0_RX_THD | + ADI_MAX32_I2C_INT_EN0_DONE | ADI_MAX32_I2C_INT_EN0_ERR; + int_en1 = ADI_MAX32_I2C_INT_EN1_RX_OVERFLOW; + } + } + } + Wrap_MXC_I2C_SetIntEn(i2c, int_en0, int_en1); +} +#endif /* CONFIG_I2C_TARGET */ + +#ifdef CONFIG_I2C_MAX32_INTERRUPT +static void i2c_max32_isr_controller(const struct device *dev, mxc_i2c_regs_t *i2c) +{ + struct max32_i2c_data *data = dev->data; + mxc_i2c_req_t *req = &data->req; + uint32_t written, readb; + uint32_t txfifolevel; + uint32_t int_fl0, int_fl1; + uint32_t int_en0, int_en1; + + written = data->written; + readb = data->readb; + + Wrap_MXC_I2C_GetIntEn(i2c, &int_en0, &int_en1); + MXC_I2C_GetFlags(i2c, &int_fl0, &int_fl1); + MXC_I2C_ClearFlags(i2c, ADI_MAX32_I2C_INT_FL0_MASK, ADI_MAX32_I2C_INT_FL1_MASK); + txfifolevel = Wrap_MXC_I2C_GetTxFIFOLevel(i2c); + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ERR) { + data->err = -EIO; + Wrap_MXC_I2C_SetIntEn(i2c, 0, 0); + k_sem_give(&data->xfer); + return; + } + + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_ADDR_ACK) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_ADDR_ACK, 0); + if (written < req->tx_len) { + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_TX_THD, 0); + } else if (readb < req->rx_len) { + MXC_I2C_EnableInt( + i2c, ADI_MAX32_I2C_INT_EN0_RX_THD | ADI_MAX32_I2C_INT_EN0_DONE, 0); + } + } + + if (req->tx_len && + (int_fl0 & (ADI_MAX32_I2C_INT_FL0_TX_THD | ADI_MAX32_I2C_INT_FL0_DONE))) { + if (written < req->tx_len) { + written += MXC_I2C_WriteTXFIFO(i2c, &req->tx_buf[written], + req->tx_len - written); + } else { + if (!(int_en0 & ADI_MAX32_I2C_INT_EN0_DONE)) { + /* We are done, stop sending more data */ + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_TX_THD, 0); + if (data->flags & I2C_MSG_STOP) { + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_DONE, 0); + /* Done flag is not set if stop/restart is not set */ + Wrap_MXC_I2C_Stop(i2c); + } else { + k_sem_give(&data->xfer); + } + } + + if ((int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE)) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_DONE, 0); + k_sem_give(&data->xfer); + } + } + } else if ((int_fl0 & (ADI_MAX32_I2C_INT_FL0_RX_THD | ADI_MAX32_I2C_INT_FL0_DONE))) { + readb += MXC_I2C_ReadRXFIFO(i2c, &req->rx_buf[readb], req->rx_len - readb); + if (readb == req->rx_len) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_RX_THD, 0); + if (data->flags & I2C_MSG_STOP) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_DONE, 0); + Wrap_MXC_I2C_Stop(i2c); + k_sem_give(&data->xfer); + } else { + if (int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE) { + MXC_I2C_DisableInt(i2c, ADI_MAX32_I2C_INT_EN0_DONE, 0); + k_sem_give(&data->xfer); + } + } + } else if ((int_en0 & ADI_MAX32_I2C_INT_EN0_DONE) && + (int_fl0 & ADI_MAX32_I2C_INT_FL0_DONE)) { + MXC_I2C_DisableInt( + i2c, (ADI_MAX32_I2C_INT_EN0_RX_THD | ADI_MAX32_I2C_INT_EN0_DONE), + 0); + Wrap_MXC_I2C_SetRxCount(i2c, req->rx_len - readb); + MXC_I2C_EnableInt(i2c, ADI_MAX32_I2C_INT_EN0_ADDR_ACK, 0); + i2c->fifo = (req->addr << 1) | 0x1; + Wrap_MXC_I2C_Restart(i2c); + } + } + + data->written = written; + data->readb = readb; +} +#endif /* CONFIG_I2C_MAX32_INTERRUPT */ + +#if defined(CONFIG_I2C_TARGET) || defined(CONFIG_I2C_MAX32_INTERRUPT) +static void i2c_max32_isr(const struct device *dev) +{ + const struct max32_i2c_config *cfg = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = cfg->regs; + +#ifdef CONFIG_I2C_MAX32_INTERRUPT + if (data->target_mode == 0) { + i2c_max32_isr_controller(dev, i2c); + return; + } +#endif /* CONFIG_I2C_MAX32_INTERRUPT */ + +#ifdef CONFIG_I2C_TARGET + if (data->target_mode == 1) { + i2c_max32_isr_target(dev, i2c); + } +#endif +} +#endif /* CONFIG_I2C_TARGET || CONFIG_I2C_MAX32_INTERRUPT */ + +static const struct i2c_driver_api api = { + .configure = api_configure, + .transfer = api_transfer, +#ifdef CONFIG_I2C_TARGET + .target_register = api_target_register, + .target_unregister = api_target_unregister, +#endif + .recover_bus = api_recover_bus, +}; + +static int i2c_max32_init(const struct device *dev) +{ + const struct max32_i2c_config *const cfg = dev->config; + struct max32_i2c_data *data = dev->data; + mxc_i2c_regs_t *i2c = cfg->regs; + int ret = 0; + + if (!device_is_ready(cfg->clock)) { + return -ENODEV; + } + + MXC_I2C_Shutdown(i2c); /* Clear everything out */ + + ret = clock_control_on(cfg->clock, (clock_control_subsys_t)&cfg->perclk); + if (ret) { + return ret; + } + + ret = pinctrl_apply_state(cfg->pctrl, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } + + ret = MXC_I2C_Init(i2c, 1, 0); /* Configure as master */ + if (ret) { + return ret; + } + + MXC_I2C_SetFrequency(i2c, cfg->bitrate); + + k_sem_init(&data->lock, 1, 1); + +#if defined(CONFIG_I2C_TARGET) || defined(CONFIG_I2C_MAX32_INTERRUPT) + cfg->irq_config_func(dev); +#endif + +#ifdef CONFIG_I2C_MAX32_INTERRUPT + irq_enable(cfg->irqn); + + k_sem_init(&data->xfer, 0, 1); +#endif + +#if defined(CONFIG_I2C_TARGET) + data->first_write = true; + data->target_mode = 0; +#endif + data->dev = dev; + + return ret; +} + +#if defined(CONFIG_I2C_TARGET) || defined(CONFIG_I2C_MAX32_INTERRUPT) +#define I2C_MAX32_CONFIG_IRQ_FUNC(n) \ + .irq_config_func = i2c_max32_irq_config_func_##n, .irqn = DT_INST_IRQN(n), + +#define I2C_MAX32_IRQ_CONFIG_FUNC(n) \ + static void i2c_max32_irq_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), i2c_max32_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + } +#else +#define I2C_MAX32_CONFIG_IRQ_FUNC(n) +#define I2C_MAX32_IRQ_CONFIG_FUNC(n) +#endif + +#define DEFINE_I2C_MAX32(_num) \ + PINCTRL_DT_INST_DEFINE(_num); \ + I2C_MAX32_IRQ_CONFIG_FUNC(_num) \ + static const struct max32_i2c_config max32_i2c_dev_cfg_##_num = { \ + .regs = (mxc_i2c_regs_t *)DT_INST_REG_ADDR(_num), \ + .pctrl = PINCTRL_DT_INST_DEV_CONFIG_GET(_num), \ + .clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(_num)), \ + .perclk.bus = DT_INST_CLOCKS_CELL(_num, offset), \ + .perclk.bit = DT_INST_CLOCKS_CELL(_num, bit), \ + .bitrate = DT_INST_PROP(_num, clock_frequency), \ + I2C_MAX32_CONFIG_IRQ_FUNC(_num)}; \ + static struct max32_i2c_data max32_i2c_data_##_num; \ + I2C_DEVICE_DT_INST_DEFINE(_num, i2c_max32_init, NULL, &max32_i2c_data_##_num, \ + &max32_i2c_dev_cfg_##_num, PRE_KERNEL_2, \ + CONFIG_I2C_INIT_PRIORITY, &api); + +DT_INST_FOREACH_STATUS_OKAY(DEFINE_I2C_MAX32) diff --git a/drivers/i2c/i2c_mcux_flexcomm.c b/drivers/i2c/i2c_mcux_flexcomm.c index eeb77cb68e115..f75c65650ec07 100644 --- a/drivers/i2c/i2c_mcux_flexcomm.c +++ b/drivers/i2c/i2c_mcux_flexcomm.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,7 @@ struct mcux_flexcomm_config { void (*irq_config_func)(const struct device *dev); uint32_t bitrate; const struct pinctrl_dev_config *pincfg; + const struct reset_dt_spec reset; }; #ifdef CONFIG_I2C_TARGET @@ -470,6 +472,16 @@ static int mcux_flexcomm_init(const struct device *dev) i2c_master_config_t master_config; int error; + if (!device_is_ready(config->reset.dev)) { + LOG_ERR("Reset device not ready"); + return -ENODEV; + } + + error = reset_line_toggle(config->reset.dev, config->reset.id); + if (error) { + return error; + } + error = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); if (error) { return error; @@ -527,6 +539,7 @@ static const struct i2c_driver_api mcux_flexcomm_driver_api = { .irq_config_func = mcux_flexcomm_config_func_##id, \ .bitrate = DT_INST_PROP(id, clock_frequency), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ + .reset = RESET_DT_SPEC_INST_GET(id), \ }; \ static struct mcux_flexcomm_data mcux_flexcomm_data_##id; \ I2C_DEVICE_DT_INST_DEFINE(id, \ diff --git a/drivers/i2c/i2c_nrfx_twi.c b/drivers/i2c/i2c_nrfx_twi.c index 8af5fe4ddeeca..56d3727e125ef 100644 --- a/drivers/i2c/i2c_nrfx_twi.c +++ b/drivers/i2c/i2c_nrfx_twi.c @@ -11,6 +11,7 @@ #include #include #include +#include "i2c_nrfx_twi_common.h" #include #include @@ -23,19 +24,19 @@ LOG_MODULE_REGISTER(i2c_nrfx_twi, CONFIG_I2C_LOG_LEVEL); #endif struct i2c_nrfx_twi_data { + uint32_t dev_config; struct k_sem transfer_sync; struct k_sem completion_sync; volatile nrfx_err_t res; - uint32_t dev_config; -}; - -struct i2c_nrfx_twi_config { - nrfx_twi_t twi; - nrfx_twi_config_t config; - const struct pinctrl_dev_config *pcfg; }; -static int i2c_nrfx_twi_recover_bus(const struct device *dev); +/* Enforce dev_config matches the same offset as the common structure, + * otherwise common API won't be compatible with i2c_nrfx_twi. + */ +BUILD_ASSERT( + offsetof(struct i2c_nrfx_twi_data, dev_config) == + offsetof(struct i2c_nrfx_twi_common_data, dev_config) +); static int i2c_nrfx_twi_transfer(const struct device *dev, struct i2c_msg *msgs, @@ -53,60 +54,17 @@ static int i2c_nrfx_twi_transfer(const struct device *dev, nrfx_twi_enable(&config->twi); for (size_t i = 0; i < num_msgs; i++) { - if (I2C_MSG_ADDR_10_BITS & msgs[i].flags) { - ret = -ENOTSUP; + bool more_msgs = ((i < (num_msgs - 1)) && + !(msgs[i + 1].flags & I2C_MSG_RESTART)); + + ret = i2c_nrfx_twi_msg_transfer(dev, msgs[i].flags, + msgs[i].buf, + msgs[i].len, addr, + more_msgs); + if (ret) { break; } - nrfx_twi_xfer_desc_t cur_xfer = { - .p_primary_buf = msgs[i].buf, - .primary_length = msgs[i].len, - .address = addr, - .type = (msgs[i].flags & I2C_MSG_READ) ? - NRFX_TWI_XFER_RX : NRFX_TWI_XFER_TX - }; - uint32_t xfer_flags = 0; - nrfx_err_t res; - - /* In case the STOP condition is not supposed to appear after - * the current message, check what is requested further: - */ - if (!(msgs[i].flags & I2C_MSG_STOP)) { - /* - if the transfer consists of more messages - * and the I2C repeated START is not requested - * to appear before the next message, suspend - * the transfer after the current message, - * so that it can be resumed with the next one, - * resulting in the two messages merged into - * a continuous transfer on the bus - */ - if ((i < (num_msgs - 1)) && - !(msgs[i + 1].flags & I2C_MSG_RESTART)) { - xfer_flags |= NRFX_TWI_FLAG_SUSPEND; - /* - otherwise, just finish the transfer without - * generating the STOP condition, unless the current - * message is an RX request, for which such feature - * is not supported - */ - } else if (msgs[i].flags & I2C_MSG_READ) { - ret = -ENOTSUP; - break; - } else { - xfer_flags |= NRFX_TWI_FLAG_TX_NO_STOP; - } - } - - res = nrfx_twi_xfer(&config->twi, &cur_xfer, xfer_flags); - if (res != NRFX_SUCCESS) { - if (res == NRFX_ERROR_BUSY) { - ret = -EBUSY; - break; - } else { - ret = -EIO; - break; - } - } - ret = k_sem_take(&data->completion_sync, I2C_TRANSFER_TIMEOUT_MSEC); if (ret != 0) { @@ -132,8 +90,7 @@ static int i2c_nrfx_twi_transfer(const struct device *dev, break; } - res = data->res; - if (res != NRFX_SUCCESS) { + if (data->res != NRFX_SUCCESS) { ret = -EIO; break; } @@ -147,7 +104,8 @@ static int i2c_nrfx_twi_transfer(const struct device *dev, static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context) { - struct i2c_nrfx_twi_data *dev_data = p_context; + const struct device *dev = p_context; + struct i2c_nrfx_twi_data *dev_data = (struct i2c_nrfx_twi_data *)dev->data; switch (p_event->type) { case NRFX_TWI_EVT_DONE: @@ -167,115 +125,12 @@ static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context) k_sem_give(&dev_data->completion_sync); } -static int i2c_nrfx_twi_configure(const struct device *dev, - uint32_t dev_config) -{ - const struct i2c_nrfx_twi_config *config = dev->config; - struct i2c_nrfx_twi_data *data = dev->data; - nrfx_twi_t const *inst = &config->twi; - - if (I2C_ADDR_10_BITS & dev_config) { - return -EINVAL; - } - - switch (I2C_SPEED_GET(dev_config)) { - case I2C_SPEED_STANDARD: - nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_100K); - break; - case I2C_SPEED_FAST: - nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_400K); - break; - default: - LOG_ERR("unsupported speed"); - return -EINVAL; - } - data->dev_config = dev_config; - - return 0; -} - -static int i2c_nrfx_twi_recover_bus(const struct device *dev) -{ - const struct i2c_nrfx_twi_config *config = dev->config; - uint32_t scl_pin; - uint32_t sda_pin; - nrfx_err_t err; - - scl_pin = nrf_twi_scl_pin_get(config->twi.p_twi); - sda_pin = nrf_twi_sda_pin_get(config->twi.p_twi); - - err = nrfx_twi_bus_recover(scl_pin, sda_pin); - return (err == NRFX_SUCCESS ? 0 : -EBUSY); -} - static const struct i2c_driver_api i2c_nrfx_twi_driver_api = { .configure = i2c_nrfx_twi_configure, .transfer = i2c_nrfx_twi_transfer, .recover_bus = i2c_nrfx_twi_recover_bus, }; -static int init_twi(const struct device *dev) -{ - const struct i2c_nrfx_twi_config *config = dev->config; - struct i2c_nrfx_twi_data *dev_data = dev->data; - nrfx_err_t result = nrfx_twi_init(&config->twi, &config->config, - event_handler, dev_data); - if (result != NRFX_SUCCESS) { - LOG_ERR("Failed to initialize device: %s", - dev->name); - return -EBUSY; - } - - return 0; -} - -#ifdef CONFIG_PM_DEVICE -static int twi_nrfx_pm_action(const struct device *dev, - enum pm_device_action action) -{ - const struct i2c_nrfx_twi_config *config = dev->config; - struct i2c_nrfx_twi_data *data = dev->data; - int ret = 0; - - switch (action) { - case PM_DEVICE_ACTION_RESUME: - ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (ret < 0) { - return ret; - } - init_twi(dev); - if (data->dev_config) { - i2c_nrfx_twi_configure(dev, data->dev_config); - } - break; - - case PM_DEVICE_ACTION_SUSPEND: - nrfx_twi_uninit(&config->twi); - - ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); - if (ret < 0) { - return ret; - } - break; - - default: - ret = -ENOTSUP; - } - - return ret; -} -#endif /* CONFIG_PM_DEVICE */ - -#define I2C_NRFX_TWI_INVALID_FREQUENCY ((nrf_twi_frequency_t)-1) -#define I2C_NRFX_TWI_FREQUENCY(bitrate) \ - (bitrate == I2C_BITRATE_STANDARD ? NRF_TWI_FREQ_100K \ - : bitrate == 250000 ? NRF_TWI_FREQ_250K \ - : bitrate == I2C_BITRATE_FAST ? NRF_TWI_FREQ_400K \ - : I2C_NRFX_TWI_INVALID_FREQUENCY) -#define I2C(idx) DT_NODELABEL(i2c##idx) -#define I2C_FREQUENCY(idx) \ - I2C_NRFX_TWI_FREQUENCY(DT_PROP(I2C(idx), clock_frequency)) - #define I2C_NRFX_TWI_DEVICE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx)); \ BUILD_ASSERT(I2C_FREQUENCY(idx) != \ @@ -291,7 +146,7 @@ static int twi_nrfx_pm_action(const struct device *dev, if (err < 0) { \ return err; \ } \ - return init_twi(dev); \ + return i2c_nrfx_twi_init(dev); \ } \ static struct i2c_nrfx_twi_data twi_##idx##_data = { \ .transfer_sync = Z_SEM_INITIALIZER( \ @@ -307,6 +162,7 @@ static int twi_nrfx_pm_action(const struct device *dev, .skip_psel_cfg = true, \ .frequency = I2C_FREQUENCY(idx), \ }, \ + .event_handler = event_handler, \ .pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2C(idx)), \ }; \ PM_DEVICE_DT_DEFINE(I2C(idx), twi_nrfx_pm_action); \ diff --git a/drivers/i2c/i2c_nrfx_twi_common.c b/drivers/i2c/i2c_nrfx_twi_common.c new file mode 100644 index 0000000000000..0d8bda63425f7 --- /dev/null +++ b/drivers/i2c/i2c_nrfx_twi_common.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2024, Croxel Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include "i2c_nrfx_twi_common.h" + +#include +LOG_MODULE_DECLARE(i2c_nrfx_twi); + +int i2c_nrfx_twi_init(const struct device *dev) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + nrfx_err_t result = nrfx_twi_init(&config->twi, &config->config, + config->event_handler, (void *)dev); + if (result != NRFX_SUCCESS) { + LOG_ERR("Failed to initialize device: %s", + dev->name); + return -EBUSY; + } + + return 0; +} + +int i2c_nrfx_twi_configure(const struct device *dev, uint32_t dev_config) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + struct i2c_nrfx_twi_common_data *data = dev->data; + nrfx_twi_t const *inst = &config->twi; + + if (I2C_ADDR_10_BITS & dev_config) { + return -EINVAL; + } + + switch (I2C_SPEED_GET(dev_config)) { + case I2C_SPEED_STANDARD: + nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_100K); + break; + case I2C_SPEED_FAST: + nrf_twi_frequency_set(inst->p_twi, NRF_TWI_FREQ_400K); + break; + default: + LOG_ERR("unsupported speed"); + return -EINVAL; + } + data->dev_config = dev_config; + + return 0; +} + +int i2c_nrfx_twi_recover_bus(const struct device *dev) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + uint32_t scl_pin; + uint32_t sda_pin; + nrfx_err_t err; + + scl_pin = nrf_twi_scl_pin_get(config->twi.p_twi); + sda_pin = nrf_twi_sda_pin_get(config->twi.p_twi); + + err = nrfx_twi_bus_recover(scl_pin, sda_pin); + return (err == NRFX_SUCCESS ? 0 : -EBUSY); +} + +int i2c_nrfx_twi_msg_transfer(const struct device *dev, uint8_t flags, + uint8_t *buf, size_t buf_len, + uint16_t i2c_addr, bool more_msgs) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + int ret = 0; + uint32_t xfer_flags = 0; + nrfx_err_t res; + nrfx_twi_xfer_desc_t cur_xfer = { + .p_primary_buf = buf, + .primary_length = buf_len, + .address = i2c_addr, + .type = (flags & I2C_MSG_READ) ? + NRFX_TWI_XFER_RX : NRFX_TWI_XFER_TX, + }; + + if (flags & I2C_MSG_ADDR_10_BITS) { + LOG_ERR("10-bit I2C Addr devices not supported"); + ret = -ENOTSUP; + } else if (!(flags & I2C_MSG_STOP)) { + /* - if the transfer consists of more messages + * and the I2C repeated START is not requested + * to appear before the next message, suspend + * the transfer after the current message, + * so that it can be resumed with the next one, + * resulting in the two messages merged into + * a continuous transfer on the bus + */ + if (more_msgs) { + xfer_flags |= NRFX_TWI_FLAG_SUSPEND; + /* - otherwise, just finish the transfer without + * generating the STOP condition, unless the current + * message is an RX request, for which such feature + * is not supported + */ + } else if (flags & I2C_MSG_READ) { + ret = -ENOTSUP; + } else { + xfer_flags |= NRFX_TWI_FLAG_TX_NO_STOP; + } + } + + if (!ret) { + res = nrfx_twi_xfer(&config->twi, &cur_xfer, xfer_flags); + switch (res) { + case NRFX_SUCCESS: + break; + case NRFX_ERROR_BUSY: + ret = -EBUSY; + break; + default: + ret = -EIO; + break; + } + } + + return ret; +} + +#ifdef CONFIG_PM_DEVICE +int twi_nrfx_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + struct i2c_nrfx_twi_common_data *data = dev->data; + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + i2c_nrfx_twi_init(dev); + if (data->dev_config) { + i2c_nrfx_twi_configure(dev, data->dev_config); + } + break; + + case PM_DEVICE_ACTION_SUSPEND: + nrfx_twi_uninit(&config->twi); + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0) { + return ret; + } + break; + + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif /* CONFIG_PM_DEVICE */ diff --git a/drivers/i2c/i2c_nrfx_twi_common.h b/drivers/i2c/i2c_nrfx_twi_common.h new file mode 100644 index 0000000000000..a8925d3f75b16 --- /dev/null +++ b/drivers/i2c/i2c_nrfx_twi_common.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2024, Croxel Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_I2C_I2C_NRFX_TWI_COMMON_H_ +#define ZEPHYR_DRIVERS_I2C_I2C_NRFX_TWI_COMMON_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define I2C_NRFX_TWI_INVALID_FREQUENCY ((nrf_twi_frequency_t)-1) +#define I2C_NRFX_TWI_FREQUENCY(bitrate) \ + (bitrate == I2C_BITRATE_STANDARD ? NRF_TWI_FREQ_100K \ + : bitrate == 250000 ? NRF_TWI_FREQ_250K \ + : bitrate == I2C_BITRATE_FAST ? NRF_TWI_FREQ_400K \ + : I2C_NRFX_TWI_INVALID_FREQUENCY) +#define I2C(idx) DT_NODELABEL(i2c##idx) +#define I2C_FREQUENCY(idx) \ + I2C_NRFX_TWI_FREQUENCY(DT_PROP(I2C(idx), clock_frequency)) + +struct i2c_nrfx_twi_common_data { + uint32_t dev_config; +}; + +struct i2c_nrfx_twi_config { + nrfx_twi_t twi; + nrfx_twi_config_t config; + nrfx_twi_evt_handler_t event_handler; + const struct pinctrl_dev_config *pcfg; +}; + +static inline nrfx_err_t i2c_nrfx_twi_get_evt_result(nrfx_twi_evt_t const *p_event) +{ + switch (p_event->type) { + case NRFX_TWI_EVT_DONE: + return NRFX_SUCCESS; + case NRFX_TWI_EVT_ADDRESS_NACK: + return NRFX_ERROR_DRV_TWI_ERR_ANACK; + case NRFX_TWI_EVT_DATA_NACK: + return NRFX_ERROR_DRV_TWI_ERR_DNACK; + default: + return NRFX_ERROR_INTERNAL; + } +} + +int i2c_nrfx_twi_init(const struct device *dev); +int i2c_nrfx_twi_configure(const struct device *dev, uint32_t dev_config); +int i2c_nrfx_twi_recover_bus(const struct device *dev); +int i2c_nrfx_twi_msg_transfer(const struct device *dev, uint8_t flags, + uint8_t *buf, size_t buf_len, + uint16_t i2c_addr, bool more_msgs); + +#ifdef CONFIG_PM_DEVICE +int twi_nrfx_pm_action(const struct device *dev, enum pm_device_action action); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_I2C_I2C_NRFX_TWI_COMMON_H_ */ diff --git a/drivers/i2c/i2c_nrfx_twi_rtio.c b/drivers/i2c/i2c_nrfx_twi_rtio.c new file mode 100644 index 0000000000000..7f5d5becf0472 --- /dev/null +++ b/drivers/i2c/i2c_nrfx_twi_rtio.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2018, Nordic Semiconductor ASA + * Copyright (c) 2024, Croxel Inc + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include "i2c_nrfx_twi_common.h" + +#include +#include +LOG_MODULE_REGISTER(i2c_nrfx_twi, CONFIG_I2C_LOG_LEVEL); + +struct i2c_nrfx_twi_rtio_data { + uint32_t dev_config; + bool twi_enabled; + struct i2c_rtio *ctx; +}; + +/* Enforce dev_config matches the same offset as the common structure, + * otherwise common API won't be compatible with i2c_nrfx_twi_rtio. + */ +BUILD_ASSERT( + offsetof(struct i2c_nrfx_twi_rtio_data, dev_config) == + offsetof(struct i2c_nrfx_twi_common_data, dev_config) +); + +static void i2c_nrfx_twi_rtio_complete(const struct device *dev, int status); + +static bool i2c_nrfx_twi_rtio_msg_start(const struct device *dev, uint8_t flags, + uint8_t *buf, size_t buf_len, uint16_t i2c_addr) +{ + const struct i2c_nrfx_twi_config *config = dev->config; + struct i2c_nrfx_twi_rtio_data *const dev_data = dev->data; + struct i2c_rtio *ctx = dev_data->ctx; + int ret = 0; + + /** Enabling while already enabled ends up in a failed assertion: skip it. */ + if (!dev_data->twi_enabled) { + nrfx_twi_enable(&config->twi); + dev_data->twi_enabled = true; + } + + ret = i2c_nrfx_twi_msg_transfer(dev, flags, buf, buf_len, i2c_addr, false); + if (ret != 0) { + nrfx_twi_disable(&config->twi); + dev_data->twi_enabled = false; + + return i2c_rtio_complete(ctx, ret); + } + + return false; +} + +static bool i2c_nrfx_twi_rtio_start(const struct device *dev) +{ + struct i2c_nrfx_twi_rtio_data *const dev_data = dev->data; + struct i2c_rtio *ctx = dev_data->ctx; + struct rtio_sqe *sqe = &ctx->txn_curr->sqe; + struct i2c_dt_spec *dt_spec = sqe->iodev->data; + + switch (sqe->op) { + case RTIO_OP_RX: + return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_READ | sqe->iodev_flags, + sqe->buf, sqe->buf_len, dt_spec->addr); + case RTIO_OP_TINY_TX: + return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, + sqe->tiny_buf, sqe->tiny_buf_len, dt_spec->addr); + case RTIO_OP_TX: + return i2c_nrfx_twi_rtio_msg_start(dev, I2C_MSG_WRITE | sqe->iodev_flags, + sqe->buf, sqe->buf_len, dt_spec->addr); + case RTIO_OP_I2C_CONFIGURE: + (void)i2c_nrfx_twi_configure(dev, sqe->i2c_config); + return false; + case RTIO_OP_I2C_RECOVER: + (void)i2c_rtio_recover(ctx); + return false; + default: + LOG_ERR("Invalid op code %d for submission %p\n", sqe->op, (void *)sqe); + return i2c_rtio_complete(ctx, -EINVAL); + } +} + +static void i2c_nrfx_twi_rtio_complete(const struct device *dev, int status) +{ + /** Finalize if there are no more pending xfers */ + const struct i2c_nrfx_twi_config *config = dev->config; + struct i2c_nrfx_twi_rtio_data *data = dev->data; + struct i2c_rtio *const ctx = data->ctx; + + if (i2c_rtio_complete(ctx, status)) { + (void)i2c_nrfx_twi_rtio_start(dev); + } else { + nrfx_twi_disable(&config->twi); + data->twi_enabled = false; + } +} + +static int i2c_nrfx_twi_rtio_transfer(const struct device *dev, struct i2c_msg *msgs, + uint8_t num_msgs, uint16_t addr) +{ + struct i2c_rtio *const ctx = ((struct i2c_nrfx_twi_rtio_data *) + dev->data)->ctx; + + return i2c_rtio_transfer(ctx, msgs, num_msgs, addr); +} + +static void event_handler(nrfx_twi_evt_t const *p_event, void *p_context) +{ + const struct device *dev = p_context; + int status = 0; + + if (i2c_nrfx_twi_get_evt_result(p_event) != NRFX_SUCCESS) { + status = -EIO; + } + + i2c_nrfx_twi_rtio_complete(dev, status); +} + +static void i2c_nrfx_twi_rtio_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_seq) +{ + struct i2c_nrfx_twi_rtio_data *data = dev->data; + struct i2c_rtio *const ctx = data->ctx; + + if (i2c_rtio_submit(ctx, iodev_seq)) { + (void)i2c_nrfx_twi_rtio_start(dev); + } +} + +static const struct i2c_driver_api i2c_nrfx_twi_rtio_driver_api = { + .configure = i2c_nrfx_twi_configure, + .transfer = i2c_nrfx_twi_rtio_transfer, + .recover_bus = i2c_nrfx_twi_recover_bus, + .iodev_submit = i2c_nrfx_twi_rtio_submit, +}; + +#define I2C_NRFX_TWI_RTIO_DEVICE(idx) \ + NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(I2C(idx)); \ + BUILD_ASSERT(I2C_FREQUENCY(idx) != \ + I2C_NRFX_TWI_INVALID_FREQUENCY, \ + "Wrong I2C " #idx " frequency setting in dts"); \ + static int twi_##idx##_init(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_IRQN(I2C(idx)), DT_IRQ(I2C(idx), priority), \ + nrfx_isr, nrfx_twi_##idx##_irq_handler, 0); \ + const struct i2c_nrfx_twi_config *config = dev->config; \ + const struct i2c_nrfx_twi_rtio_data *dev_data = dev->data; \ + int err = pinctrl_apply_state(config->pcfg, \ + PINCTRL_STATE_DEFAULT); \ + if (err < 0) { \ + return err; \ + } \ + i2c_rtio_init(dev_data->ctx, dev); \ + return i2c_nrfx_twi_init(dev); \ + } \ + I2C_RTIO_DEFINE(_i2c##idx##_twi_rtio, \ + DT_INST_PROP_OR(n, sq_size, CONFIG_I2C_RTIO_SQ_SIZE), \ + DT_INST_PROP_OR(n, cq_size, CONFIG_I2C_RTIO_CQ_SIZE)); \ + static struct i2c_nrfx_twi_rtio_data twi_##idx##_data = { \ + .ctx = &_i2c##idx##_twi_rtio, \ + }; \ + PINCTRL_DT_DEFINE(I2C(idx)); \ + static const struct i2c_nrfx_twi_config twi_##idx##z_config = { \ + .twi = NRFX_TWI_INSTANCE(idx), \ + .config = { \ + .skip_gpio_cfg = true, \ + .skip_psel_cfg = true, \ + .frequency = I2C_FREQUENCY(idx), \ + }, \ + .event_handler = event_handler, \ + .pcfg = PINCTRL_DT_DEV_CONFIG_GET(I2C(idx)), \ + }; \ + PM_DEVICE_DT_DEFINE(I2C(idx), twi_nrfx_pm_action); \ + I2C_DEVICE_DT_DEFINE(I2C(idx), \ + twi_##idx##_init, \ + PM_DEVICE_DT_GET(I2C(idx)), \ + &twi_##idx##_data, \ + &twi_##idx##z_config, \ + POST_KERNEL, \ + CONFIG_I2C_INIT_PRIORITY, \ + &i2c_nrfx_twi_rtio_driver_api) + +#ifdef CONFIG_HAS_HW_NRF_TWI0 +I2C_NRFX_TWI_RTIO_DEVICE(0); +#endif + +#ifdef CONFIG_HAS_HW_NRF_TWI1 +I2C_NRFX_TWI_RTIO_DEVICE(1); +#endif diff --git a/drivers/i2c/i2c_rtio.c b/drivers/i2c/i2c_rtio.c index 0a43acc4f6242..d921f5604efe4 100644 --- a/drivers/i2c/i2c_rtio.c +++ b/drivers/i2c/i2c_rtio.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include #define LOG_LEVEL CONFIG_I2C_LOG_LEVEL @@ -55,14 +55,12 @@ struct rtio_sqe *i2c_rtio_copy(struct rtio *r, struct rtio_iodev *iodev, const s void i2c_rtio_init(struct i2c_rtio *ctx, const struct device *dev) { k_sem_init(&ctx->lock, 1, 1); - rtio_mpsc_init(&ctx->io_q); + mpsc_init(&ctx->io_q); ctx->txn_curr = NULL; ctx->txn_head = NULL; ctx->dt_spec.bus = dev; ctx->iodev.data = &ctx->dt_spec; ctx->iodev.api = &i2c_iodev_api; - /* TODO drop the builtin submission queue? */ - rtio_mpsc_init(&ctx->iodev.iodev_sq); } /** @@ -82,7 +80,7 @@ static bool i2c_rtio_next(struct i2c_rtio *ctx, bool completion) return false; } - struct rtio_mpsc_node *next = rtio_mpsc_pop(&ctx->io_q); + struct mpsc_node *next = mpsc_pop(&ctx->io_q); /* Nothing left to do */ if (next == NULL) { @@ -119,7 +117,7 @@ bool i2c_rtio_complete(struct i2c_rtio *ctx, int status) } bool i2c_rtio_submit(struct i2c_rtio *ctx, struct rtio_iodev_sqe *iodev_sqe) { - rtio_mpsc_push(&ctx->io_q, &iodev_sqe->q); + mpsc_push(&ctx->io_q, &iodev_sqe->q); return i2c_rtio_next(ctx, false); } @@ -142,8 +140,6 @@ int i2c_rtio_transfer(struct i2c_rtio *ctx, struct i2c_msg *msgs, uint8_t num_ms goto out; } - sqe->flags &= ~RTIO_SQE_TRANSACTION; - rtio_submit(r, 1); cqe = rtio_cqe_consume(r); diff --git a/drivers/i2c/i2c_sbcon.c b/drivers/i2c/i2c_sbcon.c index e3ddd62b26247..9e077a81956e9 100644 --- a/drivers/i2c/i2c_sbcon.c +++ b/drivers/i2c/i2c_sbcon.c @@ -17,6 +17,11 @@ #include #include #include + +#include +LOG_MODULE_REGISTER(i2c_sbcon, CONFIG_I2C_LOG_LEVEL); + +#include "i2c-priv.h" #include "i2c_bitbang.h" /* SBCon hardware registers layout */ @@ -35,6 +40,7 @@ struct sbcon { /* Driver config */ struct i2c_sbcon_config { struct sbcon *sbcon; /* Address of hardware registers */ + uint32_t bitrate; /* I2C bus speed in Hz */ }; /* Driver instance data */ @@ -84,6 +90,13 @@ static int i2c_sbcon_configure(const struct device *dev, uint32_t dev_config) return i2c_bitbang_configure(&context->bitbang, dev_config); } +static int i2c_sbcon_get_config(const struct device *dev, uint32_t *config) +{ + struct i2c_sbcon_context *context = dev->data; + + return i2c_bitbang_get_config(&context->bitbang, config); +} + static int i2c_sbcon_transfer(const struct device *dev, struct i2c_msg *msgs, uint8_t num_msgs, uint16_t slave_address) { @@ -93,19 +106,35 @@ static int i2c_sbcon_transfer(const struct device *dev, struct i2c_msg *msgs, slave_address); } +static int i2c_sbcon_recover_bus(const struct device *dev) +{ + struct i2c_sbcon_context *context = dev->data; + + return i2c_bitbang_recover_bus(&context->bitbang); +} + static const struct i2c_driver_api api = { .configure = i2c_sbcon_configure, + .get_config = i2c_sbcon_get_config, .transfer = i2c_sbcon_transfer, + .recover_bus = i2c_sbcon_recover_bus, }; static int i2c_sbcon_init(const struct device *dev) { struct i2c_sbcon_context *context = dev->data; const struct i2c_sbcon_config *config = dev->config; + int ret; i2c_bitbang_init(&context->bitbang, &io_fns, config->sbcon); - return 0; + ret = i2c_bitbang_configure(&context->bitbang, + I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->bitrate)); + if (ret != 0) { + LOG_ERR("failed to configure I2C bitbang: %d", ret); + } + + return ret; } #define DEFINE_I2C_SBCON(_num) \ @@ -113,7 +142,8 @@ static int i2c_sbcon_init(const struct device *dev) static struct i2c_sbcon_context i2c_sbcon_dev_data_##_num; \ \ static const struct i2c_sbcon_config i2c_sbcon_dev_cfg_##_num = { \ - .sbcon = (void *)DT_INST_REG_ADDR(_num), \ + .sbcon = (void *)DT_INST_REG_ADDR(_num), \ + .bitrate = DT_INST_PROP(_num, clock_frequency), \ }; \ \ I2C_DEVICE_DT_INST_DEFINE(_num, \ diff --git a/drivers/i2c/i2c_shell.c b/drivers/i2c/i2c_shell.c index 4bbefcc5734e1..176a0d46c561d 100644 --- a/drivers/i2c/i2c_shell.c +++ b/drivers/i2c/i2c_shell.c @@ -195,9 +195,6 @@ static int i2c_read_to_buffer(const struct shell *shell_ctx, uint8_t *buf, uint8_t buf_length) { const struct device *dev; - uint8_t reg_addr_buf[MAX_BYTES_FOR_REGISTER_INDEX]; - int reg_addr_bytes; - int reg_addr; int dev_addr; int ret; @@ -209,15 +206,23 @@ static int i2c_read_to_buffer(const struct shell *shell_ctx, } dev_addr = strtol(s_dev_addr, NULL, 16); - reg_addr = strtol(s_reg_addr, NULL, 16); - reg_addr_bytes = get_bytes_count_for_hex(s_reg_addr); - sys_put_be32(reg_addr, reg_addr_buf); + if (s_reg_addr != NULL) { + uint8_t reg_addr_buf[MAX_BYTES_FOR_REGISTER_INDEX]; + int reg_addr_bytes; + int reg_addr; + + reg_addr = strtol(s_reg_addr, NULL, 16); + reg_addr_bytes = get_bytes_count_for_hex(s_reg_addr); + sys_put_be32(reg_addr, reg_addr_buf); + + ret = i2c_write_read(dev, dev_addr, + reg_addr_buf + MAX_BYTES_FOR_REGISTER_INDEX - reg_addr_bytes, + reg_addr_bytes, buf, buf_length); + } else { + ret = i2c_read(dev, buf, buf_length, dev_addr); + } - ret = i2c_write_read(dev, dev_addr, - reg_addr_buf + - MAX_BYTES_FOR_REGISTER_INDEX - reg_addr_bytes, - reg_addr_bytes, buf, buf_length); if (ret < 0) { shell_error(shell_ctx, "Failed to read from device: %s", s_dev_addr); @@ -270,6 +275,30 @@ static int cmd_i2c_read(const struct shell *shell_ctx, size_t argc, char **argv) return ret; } +/* i2c direct_read [] */ +static int cmd_i2c_direct_read(const struct shell *shell_ctx, size_t argc, char **argv) +{ + uint8_t buf[MAX_I2C_BYTES]; + int num_bytes; + int ret; + + if (argc > 3) { + num_bytes = strtol(argv[3], NULL, 16); + if (num_bytes > MAX_I2C_BYTES) { + num_bytes = MAX_I2C_BYTES; + } + } else { + num_bytes = MAX_I2C_BYTES; + } + + ret = i2c_read_to_buffer(shell_ctx, argv[ARGV_DEV], argv[ARGV_ADDR], NULL, buf, num_bytes); + if (ret == 0) { + shell_hexdump(shell_ctx, buf, num_bytes); + } + + return ret; +} + /* i2c speed * For: speed see constants like I2C_SPEED_STANDARD */ @@ -336,6 +365,11 @@ SHELL_STATIC_SUBCMD_SET_CREATE(sub_i2c_cmds, "Read a byte from an I2C device\n" "Usage: read_byte ", cmd_i2c_read_byte, 4, 0), + SHELL_CMD_ARG(direct_read, &dsub_device_name, + "Read byte stream directly from an I2C device without " + "writing a register address first\n" + "Usage: direct_read []", + cmd_i2c_direct_read, 3, 1), SHELL_CMD_ARG(write, &dsub_device_name, "Write bytes to an I2C device\n" "Usage: write [, ...]", diff --git a/drivers/i2c/i2c_smartbond.c b/drivers/i2c/i2c_smartbond.c index d0b7ee20b453d..2c3e61416419d 100644 --- a/drivers/i2c/i2c_smartbond.c +++ b/drivers/i2c/i2c_smartbond.c @@ -11,6 +11,10 @@ #include #include #include +#include +#include +#include +#include #include LOG_MODULE_REGISTER(i2c_smartbond); @@ -31,8 +35,57 @@ struct i2c_smartbond_data { uint32_t transmit_cnt, receive_cnt; i2c_callback_t cb; void *userdata; +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + ATOMIC_DEFINE(pm_policy_state_flag, 1); +#endif }; +static inline void i2c_smartbond_pm_policy_state_lock_get(struct i2c_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) { + /* + * Prevent the SoC from etering the normal sleep state as PDC does not support + * waking up the application core following I2C events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void i2c_smartbond_pm_policy_state_lock_put(struct i2c_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) { + /* + * Allow the SoC to enter the nornmal sleep state once I2C transactions are done. + */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline bool i2c_smartbond_is_idle(const struct device *dev) +{ + const struct i2c_smartbond_cfg *config = dev->config; + uint32_t mask = I2C_I2C_STATUS_REG_I2C_ACTIVITY_Msk | + I2C_I2C_STATUS_REG_RFNE_Msk | + I2C_I2C_STATUS_REG_TFE_Msk; + + return ((config->regs->I2C_STATUS_REG & mask) == I2C_I2C_STATUS_REG_TFE_Msk); +} + +static void i2c_smartbond_disable_when_inactive(const struct device *dev) +{ + const struct i2c_smartbond_cfg *config = dev->config; + + if ((config->regs->I2C_ENABLE_REG & I2C_I2C_ENABLE_REG_I2C_EN_Msk)) { + while (!i2c_smartbond_is_idle(dev)) { + }; + config->regs->I2C_ENABLE_REG &= ~I2C_I2C_ENABLE_REG_I2C_EN_Msk; + } +} + static int i2c_smartbond_configure(const struct device *dev, uint32_t dev_config) { const struct i2c_smartbond_cfg *config = dev->config; @@ -73,11 +126,7 @@ static int i2c_smartbond_configure(const struct device *dev, uint32_t dev_config key = k_spin_lock(&data->lock); - if (!!(config->regs->I2C_ENABLE_REG & I2C_I2C_ENABLE_REG_I2C_EN_Msk)) { - while (!!(config->regs->I2C_STATUS_REG & I2C_I2C_STATUS_REG_I2C_ACTIVITY_Msk)) { - }; - config->regs->I2C_ENABLE_REG &= ~I2C_I2C_ENABLE_REG_I2C_EN_Msk; - } + i2c_smartbond_disable_when_inactive(dev); /* Write control register*/ config->regs->I2C_CON_REG = con_reg; @@ -149,6 +198,7 @@ static inline void i2c_smartbond_set_target_address(const struct i2c_smartbond_c } else { config->regs->I2C_CON_REG &= ~(I2C_I2C_CON_REG_I2C_10BITADDR_MASTER_Msk); } + /* Change the Target Address */ config->regs->I2C_TAR_REG = ((config->regs->I2C_TAR_REG & ~I2C_I2C_TAR_REG_IC_TAR_Msk) | (addr & I2C_I2C_TAR_REG_IC_TAR_Msk)); @@ -286,7 +336,7 @@ static int i2c_smartbond_transfer(const struct device *dev, struct i2c_msg *msgs struct i2c_smartbond_data *data = dev->data; int ret = 0; - while (!!(config->regs->I2C_STATUS_REG & I2C_I2C_STATUS_REG_I2C_ACTIVITY_Msk)) { + while (!i2c_smartbond_is_idle(dev)) { }; ret = i2c_smartbond_prep_transfer(dev, msgs, num_msgs, addr); @@ -294,6 +344,8 @@ static int i2c_smartbond_transfer(const struct device *dev, struct i2c_msg *msgs return ret; } + i2c_smartbond_pm_policy_state_lock_get(data); + for (; data->num_msgs > 0; data->num_msgs--, data->msgs++) { data->transmit_cnt = 0; data->receive_cnt = 0; @@ -323,6 +375,7 @@ static int i2c_smartbond_transfer(const struct device *dev, struct i2c_msg *msgs } finish: + i2c_smartbond_pm_policy_state_lock_put(data); return ret; } @@ -377,6 +430,8 @@ static int i2c_smartbond_transfer_cb(const struct device *dev, struct i2c_msg *m return ret; } + i2c_smartbond_pm_policy_state_lock_get(data); + i2c_smartbond_enable_msg_interrupts(config, data); LOG_INF("async transfer started"); @@ -441,6 +496,7 @@ static inline void i2c_smartbond_async_msg_done(const struct device *dev) data->cb = NULL; LOG_INF("async transfer finished"); cb(dev, 0, data->userdata); + i2c_smartbond_pm_policy_state_lock_put(data); } } @@ -493,7 +549,7 @@ static const struct i2c_driver_api i2c_smartbond_driver_api = { #endif }; -static int i2c_smartbond_init(const struct device *dev) +static int i2c_smartbond_resume(const struct device *dev) { const struct i2c_smartbond_cfg *config = dev->config; int err; @@ -515,7 +571,75 @@ static int i2c_smartbond_init(const struct device *dev) I2C_MODE_CONTROLLER | i2c_map_dt_bitrate(config->bitrate)); } +#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) +static int i2c_smartbond_suspend(const struct device *dev) +{ + int ret; + const struct i2c_smartbond_cfg *config = dev->config; + + /* Disable the I2C digital block */ + config->regs->I2C_ENABLE_REG &= ~I2C_I2C_ENABLE_REG_I2C_EN_Msk; + /* Gate I2C clocking */ + CRG_COM->RESET_CLK_COM_REG = config->periph_clock_config; + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0) { + LOG_WRN("Fialid to configure the I2C pins to inactive state"); + } + + return ret; +} + +static int i2c_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + /* + * Although the GPIO driver should already be initialized, make sure PD_COM + * is up and running before accessing the I2C block. + */ + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + ret = i2c_smartbond_resume(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = i2c_smartbond_suspend(dev); + /* + * Once the I2C block is turned off its power domain can + * be released, as well. + */ + da1469x_pd_release(MCU_PD_DOMAIN_COM); + break; + default: + return -ENOTSUP; + } + + return ret; +} +#endif + + +static int i2c_smartbond_init(const struct device *dev) +{ + int ret; + +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); +#else + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + ret = i2c_smartbond_resume(dev); +#endif + + return ret; +} + #define I2C_SMARTBOND_DEVICE(id) \ + PM_DEVICE_DT_INST_DEFINE(id, i2c_smartbond_pm_action); \ PINCTRL_DT_INST_DEFINE(id); \ static const struct i2c_smartbond_cfg i2c_smartbond_##id##_cfg = { \ .regs = (I2C_Type *)DT_INST_REG_ADDR(id), \ @@ -529,8 +653,9 @@ static int i2c_smartbond_init(const struct device *dev) I2C_SMARTBOND_CONFIGURE(id); \ return ret; \ } \ - I2C_DEVICE_DT_INST_DEFINE(id, i2c_smartbond_##id##_init, NULL, &i2c_smartbond_##id##_data, \ - &i2c_smartbond_##id##_cfg, POST_KERNEL, \ - CONFIG_I2C_INIT_PRIORITY, &i2c_smartbond_driver_api); + I2C_DEVICE_DT_INST_DEFINE(id, i2c_smartbond_##id##_init, PM_DEVICE_DT_INST_GET(id), \ + &i2c_smartbond_##id##_data, \ + &i2c_smartbond_##id##_cfg, POST_KERNEL, \ + CONFIG_I2C_INIT_PRIORITY, &i2c_smartbond_driver_api); DT_INST_FOREACH_STATUS_OKAY(I2C_SMARTBOND_DEVICE) diff --git a/drivers/i2c/target/eeprom_target.c b/drivers/i2c/target/eeprom_target.c index 8cef8ea255316..e2820749b206b 100644 --- a/drivers/i2c/target/eeprom_target.c +++ b/drivers/i2c/target/eeprom_target.c @@ -22,7 +22,8 @@ struct i2c_eeprom_target_data { uint32_t buffer_size; uint8_t *buffer; uint32_t buffer_idx; - bool first_write; + uint32_t idx_write_cnt; + uint8_t address_width; }; struct i2c_eeprom_target_config { @@ -86,7 +87,7 @@ static int eeprom_target_write_requested(struct i2c_target_config *config) LOG_DBG("eeprom: write req"); - data->first_write = true; + data->idx_write_cnt = 0; return 0; } @@ -121,9 +122,13 @@ static int eeprom_target_write_received(struct i2c_target_config *config, * I2C controller support */ - if (data->first_write) { - data->buffer_idx = val; - data->first_write = false; + if (data->idx_write_cnt < (data->address_width >> 3)) { + if (data->idx_write_cnt == 0) { + data->buffer_idx = 0; + } + + data->buffer_idx = val | (data->buffer_idx << 8); + data->idx_write_cnt++; } else { data->buffer[data->buffer_idx++] = val; } @@ -162,7 +167,7 @@ static int eeprom_target_stop(struct i2c_target_config *config) LOG_DBG("eeprom: stop"); - data->first_write = true; + data->idx_write_cnt = 0; return 0; } @@ -246,11 +251,18 @@ static int i2c_eeprom_target_init(const struct device *dev) #define I2C_EEPROM_INIT(inst) \ static struct i2c_eeprom_target_data \ - i2c_eeprom_target_##inst##_dev_data; \ + i2c_eeprom_target_##inst##_dev_data = { \ + .address_width = DT_INST_PROP_OR(inst, \ + address_width, 8), \ + }; \ \ static uint8_t \ i2c_eeprom_target_##inst##_buffer[(DT_INST_PROP(inst, size))]; \ \ + BUILD_ASSERT(DT_INST_PROP(inst, size) <= \ + (1 << DT_INST_PROP_OR(inst, address_width, 8)), \ + "size must be <= than 2^address_width"); \ + \ static const struct i2c_eeprom_target_config \ i2c_eeprom_target_##inst##_cfg = { \ .bus = I2C_DT_SPEC_INST_GET(inst), \ diff --git a/drivers/i2s/i2s_handlers.c b/drivers/i2s/i2s_handlers.c index 0ef1f6e6cd554..3f1c31a46c7aa 100644 --- a/drivers/i2s/i2s_handlers.c +++ b/drivers/i2s/i2s_handlers.c @@ -41,7 +41,7 @@ static inline int z_vrfy_i2s_configure(const struct device *dev, out: return ret; } -#include +#include static inline int z_vrfy_i2s_buf_read(const struct device *dev, void *buf, size_t *size) @@ -74,7 +74,7 @@ static inline int z_vrfy_i2s_buf_read(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_i2s_buf_write(const struct device *dev, void *buf, size_t size) @@ -111,7 +111,7 @@ static inline int z_vrfy_i2s_buf_write(const struct device *dev, return ret; } -#include +#include static inline int z_vrfy_i2s_trigger(const struct device *dev, enum i2s_dir dir, @@ -121,4 +121,4 @@ static inline int z_vrfy_i2s_trigger(const struct device *dev, return z_impl_i2s_trigger((const struct device *)dev, dir, cmd); } -#include +#include diff --git a/drivers/i2s/i2s_ll_stm32.c b/drivers/i2s/i2s_ll_stm32.c index b289ddabe750d..696394e7a51be 100644 --- a/drivers/i2s/i2s_ll_stm32.c +++ b/drivers/i2s/i2s_ll_stm32.c @@ -30,6 +30,23 @@ static unsigned int div_round_closest(uint32_t dividend, uint32_t divisor) return (dividend + (divisor / 2U)) / divisor; } +static bool queue_is_empty(struct ring_buf *rb) +{ + unsigned int key; + + key = irq_lock(); + + if (rb->tail != rb->head) { + /* Ring buffer is not empty */ + irq_unlock(key); + return false; + } + + irq_unlock(key); + + return true; +} + /* * Get data from the queue */ @@ -39,8 +56,7 @@ static int queue_get(struct ring_buf *rb, void **mem_block, size_t *size) key = irq_lock(); - if (rb->tail == rb->head) { - /* Ring buffer is empty */ + if (queue_is_empty(rb) == true) { irq_unlock(key); return -ENOMEM; } @@ -174,9 +190,6 @@ static int i2s_stm32_configure(const struct device *dev, enum i2s_dir dir, int ret; if (dir == I2S_DIR_RX) { -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) - return -ENOSYS; -#endif stream = &dev_data->rx; } else if (dir == I2S_DIR_TX) { stream = &dev_data->tx; @@ -293,6 +306,7 @@ static int i2s_stm32_trigger(const struct device *dev, enum i2s_dir dir, enum i2s_trigger_cmd cmd) { struct i2s_stm32_data *const dev_data = dev->data; + const struct i2s_stm32_cfg *const cfg = dev->config; struct stream *stream; unsigned int key; int ret; @@ -335,11 +349,20 @@ static int i2s_stm32_trigger(const struct device *dev, enum i2s_dir dir, LOG_ERR("STOP trigger: invalid state"); return -EIO; } +do_trigger_stop: + if (ll_func_i2s_dma_busy(cfg->i2s)) { + stream->state = I2S_STATE_STOPPING; + /* + * Indicate that the transition to I2S_STATE_STOPPING + * is triggered by STOP command + */ + stream->tx_stop_for_drain = false; + } else { + stream->stream_disable(stream, dev); + stream->state = I2S_STATE_READY; + stream->last_block = true; + } irq_unlock(key); - stream->stream_disable(stream, dev); - stream->queue_drop(stream); - stream->state = I2S_STATE_READY; - stream->last_block = true; break; case I2S_TRIGGER_DRAIN: @@ -349,9 +372,26 @@ static int i2s_stm32_trigger(const struct device *dev, enum i2s_dir dir, LOG_ERR("DRAIN trigger: invalid state"); return -EIO; } - stream->stream_disable(stream, dev); - stream->queue_drop(stream); - stream->state = I2S_STATE_READY; + + if (dir == I2S_DIR_TX) { + if ((queue_is_empty(&stream->mem_block_queue) == false) || + (ll_func_i2s_dma_busy(cfg->i2s))) { + stream->state = I2S_STATE_STOPPING; + /* + * Indicate that the transition to I2S_STATE_STOPPING + * is triggered by DRAIN command + */ + stream->tx_stop_for_drain = true; + } else { + stream->stream_disable(stream, dev); + stream->state = I2S_STATE_READY; + } + } else if (dir == I2S_DIR_RX) { + goto do_trigger_stop; + } else { + LOG_ERR("Unavailable direction"); + return -EINVAL; + } irq_unlock(key); break; @@ -603,6 +643,28 @@ static void dma_tx_callback(const struct device *dma_dev, void *arg, goto tx_disable; } + /* Check if we finished transferring one block and stopping is requested */ + if ((stream->state == I2S_STATE_STOPPING) && (status == DMA_STATUS_COMPLETE)) { + /* + * Check if all tx samples have been completely handled + * as stated in zephyr i2s specification, in case of DRAIN command + * send all data in the transmit queue and stop the transmission. + */ + if (queue_is_empty(&stream->mem_block_queue) == true) { + stream->queue_drop(stream); + stream->state = I2S_STATE_READY; + goto tx_disable; + } else if (stream->tx_stop_for_drain == false) { + /* + * In case of STOP command, just stop the transmission + * at the current. The transmission can be resumed. + */ + stream->state = I2S_STATE_READY; + goto tx_disable; + } + /* else: DRAIN trigger -> continue TX normally until queue is empty */ + } + /* Stop transmission if we were requested */ if (stream->last_block) { stream->state = I2S_STATE_READY; @@ -652,11 +714,6 @@ static uint32_t i2s_stm32_irq_udr_count; static void i2s_stm32_isr(const struct device *dev) { const struct i2s_stm32_cfg *cfg = dev->config; - struct i2s_stm32_data *const dev_data = dev->data; - struct stream *stream = &dev_data->rx; - - LOG_ERR("%s: err=%d", __func__, (int)LL_I2S_ReadReg(cfg->i2s, SR)); - stream->state = I2S_STATE_ERROR; /* OVR error must be explicitly cleared */ if (LL_I2S_IsActiveFlag_OVR(cfg->i2s)) { @@ -677,8 +734,12 @@ static int i2s_stm32_initialize(const struct device *dev) { const struct i2s_stm32_cfg *cfg = dev->config; struct i2s_stm32_data *const dev_data = dev->data; + struct stream *stream = &dev_data->tx; int ret, i; + /* Initialize the variable used to handle the TX */ + stream->tx_stop_for_drain = false; + /* Enable I2S clock propagation */ ret = i2s_stm32_enable_clock(dev); if (ret < 0) { @@ -871,6 +932,8 @@ static void tx_stream_disable(struct stream *stream, const struct device *dev) stream->mem_block = NULL; } + /* Wait for TX queue to drain before disabling */ + k_busy_wait(100); LL_I2S_Disable(cfg->i2s); active_dma_tx_channel[stream->dma_channel] = NULL; diff --git a/drivers/i2s/i2s_ll_stm32.h b/drivers/i2s/i2s_ll_stm32.h index 2351b8e2cea56..1f9d0eb0113dc 100644 --- a/drivers/i2s/i2s_ll_stm32.h +++ b/drivers/i2s/i2s_ll_stm32.h @@ -41,6 +41,7 @@ struct stream { bool src_addr_increment; bool dst_addr_increment; uint8_t fifo_threshold; + bool tx_stop_for_drain; struct i2s_config cfg; struct ring_buf mem_block_queue; @@ -58,4 +59,16 @@ struct i2s_stm32_data { struct stream tx; }; +/* checks that DMA Tx packet is fully transmitted over the I2S */ +static inline uint32_t ll_func_i2s_dma_busy(SPI_TypeDef *i2s) +{ +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_i2s) + return LL_SPI_IsActiveFlag_TXC(i2s) == 0; +#else + /* the I2S Tx empty and busy flags are needed */ + return (LL_SPI_IsActiveFlag_TXE(i2s) && + !LL_SPI_IsActiveFlag_BSY(i2s)); +#endif +} + #endif /* _STM32_I2S_H_ */ diff --git a/drivers/i3c/i3c_ccc.c b/drivers/i3c/i3c_ccc.c index efe65e6756e14..7b03b5b9f429f 100644 --- a/drivers/i3c/i3c_ccc.c +++ b/drivers/i3c/i3c_ccc.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -254,8 +255,7 @@ int i3c_ccc_do_setmwl_all(const struct device *controller, ccc_payload.ccc.data_len = sizeof(data); /* The actual data is MSB first. So order the data. */ - data[0] = (uint8_t)((mwl->len & 0xFF00U) >> 8); - data[1] = (uint8_t)(mwl->len & 0xFFU); + sys_put_be16(mwl->len, data); return i3c_do_ccc(controller, &ccc_payload); } @@ -282,8 +282,7 @@ int i3c_ccc_do_setmwl(const struct i3c_device_desc *target, ccc_payload.targets.num_targets = 1; /* The actual length is MSB first. So order the data. */ - data[0] = (uint8_t)((mwl->len & 0xFF00U) >> 8); - data[1] = (uint8_t)(mwl->len & 0xFFU); + sys_put_be16(mwl->len, data); return i3c_do_ccc(target->bus, &ccc_payload); } @@ -314,7 +313,7 @@ int i3c_ccc_do_getmwl(const struct i3c_device_desc *target, if (ret == 0) { /* The actual length is MSB first. So order the data. */ - mwl->len = (data[0] << 8) | data[1]; + mwl->len = sys_get_be16(data); } return ret; @@ -337,8 +336,7 @@ int i3c_ccc_do_setmrl_all(const struct device *controller, ccc_payload.ccc.data_len = has_ibi_size ? 3 : 2; /* The actual length is MSB first. So order the data. */ - data[0] = (uint8_t)((mrl->len & 0xFF00U) >> 8); - data[1] = (uint8_t)(mrl->len & 0xFFU); + sys_put_be16(mrl->len, data); if (has_ibi_size) { data[2] = mrl->ibi_len; @@ -368,8 +366,7 @@ int i3c_ccc_do_setmrl(const struct i3c_device_desc *target, ccc_payload.targets.num_targets = 1; /* The actual length is MSB first. So order the data. */ - data[0] = (uint8_t)((mrl->len & 0xFF00U) >> 8); - data[1] = (uint8_t)(mrl->len & 0xFFU); + sys_put_be16(mrl->len, data); if ((target->bcr & I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) == I3C_BCR_IBI_PAYLOAD_HAS_DATA_BYTE) { @@ -413,7 +410,7 @@ int i3c_ccc_do_getmrl(const struct i3c_device_desc *target, if (ret == 0) { /* The actual length is MSB first. So order the data. */ - mrl->len = (data[0] << 8) | data[1]; + mrl->len = sys_get_be16(data); if (has_ibi_sz) { mrl->ibi_len = data[2]; @@ -477,13 +474,112 @@ int i3c_ccc_do_getstatus(const struct i3c_device_desc *target, if (ret == 0) { /* Received data is MSB first. So order the data. */ if (fmt == GETSTATUS_FORMAT_1) { - status->fmt1.status = (data[0] << 8) | data[1]; + status->fmt1.status = sys_get_be16(data); } else if (fmt == GETSTATUS_FORMAT_2) { switch (defbyte) { case GETSTATUS_FORMAT_2_TGTSTAT: __fallthrough; case GETSTATUS_FORMAT_2_PRECR: - status->fmt2.raw_u16 = (data[0] << 8) | data[1]; + status->fmt2.raw_u16 = sys_get_be16(data); + break; + default: + break; + } + } + } + +out: + return ret; +} + +int i3c_ccc_do_getcaps(const struct i3c_device_desc *target, + union i3c_ccc_getcaps *caps, + enum i3c_ccc_getcaps_fmt fmt, + enum i3c_ccc_getcaps_defbyte defbyte) +{ + struct i3c_ccc_payload ccc_payload; + struct i3c_ccc_target_payload ccc_tgt_payload; + uint8_t defining_byte; + uint8_t data[4]; + uint8_t len; + int ret; + + __ASSERT_NO_MSG(target != NULL); + __ASSERT_NO_MSG(target->bus != NULL); + __ASSERT_NO_MSG(caps != NULL); + + ccc_tgt_payload.addr = target->dynamic_addr; + ccc_tgt_payload.rnw = 1; + ccc_tgt_payload.data = &data[0]; + + if (fmt == GETCAPS_FORMAT_1) { + /* Could be 1-4 Data Bytes Returned */ + ccc_tgt_payload.data_len = 4; + } else if (fmt == GETCAPS_FORMAT_2) { + switch (defbyte) { + case GETCAPS_FORMAT_2_CRCAPS: + __fallthrough; + case GETCAPS_FORMAT_2_VTCAPS: + /* Could be 1-2 Data Bytes Returned*/ + ccc_tgt_payload.data_len = 2; + break; + case GETCAPS_FORMAT_2_TGTCAPS: + __fallthrough; + case GETCAPS_FORMAT_2_TESTPAT: + /* Could be 1-4 Data Bytes Returned */ + ccc_tgt_payload.data_len = 4; + break; + default: + ret = -EINVAL; + goto out; + } + } else { + ret = -EINVAL; + goto out; + } + + memset(&ccc_payload, 0, sizeof(ccc_payload)); + ccc_payload.ccc.id = I3C_CCC_GETCAPS; + ccc_payload.targets.payloads = &ccc_tgt_payload; + ccc_payload.targets.num_targets = 1; + + if (fmt == GETCAPS_FORMAT_2) { + defining_byte = (uint8_t)defbyte; + + ccc_payload.ccc.data = &defining_byte; + ccc_payload.ccc.data_len = 1; + } + + ret = i3c_do_ccc(target->bus, &ccc_payload); + + if (ret == 0) { + /* GETCAPS will return a variable length */ + len = ccc_tgt_payload.num_xfer; + + if (fmt == GETCAPS_FORMAT_1) { + memcpy(caps->fmt1.getcaps, data, len); + /* for values not received, assume default (1'b0) */ + memset(&caps->fmt1.getcaps[len], 0, sizeof(caps->fmt1.getcaps) - len); + } else if (fmt == GETCAPS_FORMAT_2) { + switch (defbyte) { + case GETCAPS_FORMAT_2_CRCAPS: + memcpy(caps->fmt2.crcaps, data, len); + /* for values not received, assume default (1'b0) */ + memset(&caps->fmt2.crcaps[len], 0, sizeof(caps->fmt2.crcaps) - len); + case GETCAPS_FORMAT_2_VTCAPS: + memcpy(caps->fmt2.vtcaps, data, len); + /* for values not received, assume default (1'b0) */ + memset(&caps->fmt2.vtcaps[len], 0, sizeof(caps->fmt2.vtcaps) - len); + break; + case GETCAPS_FORMAT_2_TGTCAPS: + memcpy(caps->fmt2.tgtcaps, data, len); + /* for values not received, assume default (1'b0) */ + memset(&caps->fmt2.tgtcaps[len], 0, + sizeof(caps->fmt2.tgtcaps) - len); + break; + case GETCAPS_FORMAT_2_TESTPAT: + /* should always be 4 data bytes */ + caps->fmt2.testpat = sys_get_be32(data); break; default: break; diff --git a/drivers/i3c/i3c_cdns.c b/drivers/i3c/i3c_cdns.c index ef361523e4e22..fab1df7f4abe4 100644 --- a/drivers/i3c/i3c_cdns.c +++ b/drivers/i3c/i3c_cdns.c @@ -1350,9 +1350,42 @@ static void cdns_i3c_complete_transfer(const struct device *dev) } break; + case CMDR_M0_ERROR: { + uint8_t ccc = data->xfer.cmds[i].cmd1 & 0xFF; + /* + * The M0 is an illegally formatted CCC. i.e. the Controller + * receives 1 byte instead of 2 with the GETMWL CCC. This can + * be problematic for CCCs that can have variable length such + * as GETMXDS and GETCAPS. Verify the number of bytes received matches + * what's expected from the specification and ignore the error. The IP will + * still retramsit the same CCC and theres nothing that can be done to + * prevent this. It it still up to the application to read `num_xfer` to + * determine the number of bytes returned. + */ + if (ccc == I3C_CCC_GETMXDS) { + /* + * Whether GETMXDS format 1 and format 2 can't be known ahead of + * time which will be returned. + */ + if ((*data->xfer.cmds[i].num_xfer != + sizeof(((union i3c_ccc_getmxds *)0)->fmt1)) && + (*data->xfer.cmds[i].num_xfer != + sizeof(((union i3c_ccc_getmxds *)0)->fmt2))) { + ret = -EIO; + } + } else if (ccc == I3C_CCC_GETCAPS) { + /* GETCAPS can only return 1-4 bytes */ + if (*data->xfer.cmds[i].num_xfer > sizeof(union i3c_ccc_getcaps)) { + ret = -EIO; + } + } else { + ret = -EIO; + } + break; + } + case CMDR_DDR_PREAMBLE_ERROR: case CMDR_DDR_PARITY_ERROR: - case CMDR_M0_ERROR: case CMDR_M1_ERROR: case CMDR_M2_ERROR: case CMDR_NACK_RESP: diff --git a/drivers/i3c/i3c_common.c b/drivers/i3c/i3c_common.c index 93b30388da1a5..f58521bd483d9 100644 --- a/drivers/i3c/i3c_common.c +++ b/drivers/i3c/i3c_common.c @@ -512,6 +512,7 @@ int i3c_device_basic_info_get(struct i3c_device_desc *target) struct i3c_ccc_getdcr dcr = {0}; struct i3c_ccc_mrl mrl = {0}; struct i3c_ccc_mwl mwl = {0}; + union i3c_ccc_getcaps caps = {0}; /* * Since some CCC functions requires BCR to function @@ -547,6 +548,21 @@ int i3c_device_basic_info_get(struct i3c_device_desc *target) LOG_DBG("No settable limit for GETMWL"); } + /* GETCAPS */ + ret = i3c_ccc_do_getcaps_fmt1(target, &caps); + /* + * GETCAPS (GETHDRCAP) is required to be supported for I3C v1.0 targets that support HDR + * modes and required if the Target's I3C version is v1.1 or later, but which the version it + * supports it can't be known ahead of time. So if the BCR bit for Advanced capabilities is + * set, then it is expected for GETCAPS to always be supported. Otherwise, then it's a I3C + * v1.0 device without any HDR modes so do not treat as an error if no valid response. + */ + if (ret == 0) { + memcpy(&target->getcaps, &caps, sizeof(target->getcaps)); + } else if ((ret != 0) && (target->bcr & I3C_BCR_ADV_CAPABILITIES)) { + goto out; + } + target->dcr = dcr.dcr; target->data_length.mrl = mrl.len; target->data_length.mwl = mwl.len; diff --git a/drivers/i3c/i3c_handlers.c b/drivers/i3c/i3c_handlers.c index a5d218992a332..99708eb7a83b2 100644 --- a/drivers/i3c/i3c_handlers.c +++ b/drivers/i3c/i3c_handlers.c @@ -35,7 +35,7 @@ static inline int z_vrfy_i3c_do_ccc(const struct device *dev, return z_impl_i3c_do_ccc(dev, payload); } -#include +#include static uint32_t copy_i3c_msgs_and_transfer(struct i3c_device_desc *target, const struct i3c_msg *msgs, @@ -79,4 +79,4 @@ static inline int z_vrfy_i3c_transfer(struct i3c_device_desc *target, (struct i3c_msg *)msgs, (uint8_t)num_msgs); } -#include +#include diff --git a/drivers/i3c/i3c_npcx.c b/drivers/i3c/i3c_npcx.c index 9790e593915e2..5c19d17e8f7fa 100644 --- a/drivers/i3c/i3c_npcx.c +++ b/drivers/i3c/i3c_npcx.c @@ -39,10 +39,12 @@ LOG_MODULE_REGISTER(npcx_i3c, CONFIG_I3C_LOG_LEVEL); #define MCLKD_FREQ_45_MHZ MHZ(45) -#define I3C_STATUS_CLR_MASK \ - (BIT(NPCX_I3C_MSTATUS_TGTSTART) | BIT(NPCX_I3C_MSTATUS_MCTRLDONE) | \ - BIT(NPCX_I3C_MSTATUS_COMPLETE) | BIT(NPCX_I3C_MSTATUS_IBIWON) | \ - BIT(NPCX_I3C_MSTATUS_NOWCNTLR)) +#define I3C_STATUS_CLR_MASK \ + (BIT(NPCX_I3C_MSTATUS_MCTRLDONE) | BIT(NPCX_I3C_MSTATUS_COMPLETE) | \ + BIT(NPCX_I3C_MSTATUS_IBIWON) | BIT(NPCX_I3C_MSTATUS_NOWCNTLR)) + +#define HDR_DDR_CMD_AND_CRC_SZ_WORD 0x2 /* 2 words = Command(1 word) + CRC(1 word) */ +#define HDR_RD_CMD 0x80 /* Supported I3C MCLKD frequency */ enum npcx_i3c_speed { @@ -217,7 +219,7 @@ static inline void npcx_i3c_interrupt_enable(struct i3c_reg *inst, uint32_t mask static bool npcx_i3c_has_error(struct i3c_reg *inst) { if (IS_BIT_SET(inst->MSTATUS, NPCX_I3C_MSTATUS_ERRWARN)) { - LOG_WRN("ERROR: MSTATUS 0x%08x MERRWARN 0x%08x", inst->MSTATUS, inst->MERRWARN); + LOG_ERR("ERROR: MSTATUS 0x%08x MERRWARN 0x%08x", inst->MSTATUS, inst->MERRWARN); return true; } @@ -314,7 +316,8 @@ static inline int npcx_i3c_request_auto_ibi(struct i3c_reg *inst) * param[in] addr Dyamic address for xfer or 0x7E for CCC command. * param[in] op_type Request type. * param[in] is_read Read(true) or write(false) operation. - * param[in] read_sz Read size. + * param[in] read_sz Read size in bytes. + * If op_tye is HDR-DDR, the read_sz must be the number of words. * * return 0, success * else, error @@ -354,7 +357,7 @@ static int npcx_i3c_request_emit_start(struct i3c_reg *inst, uint8_t addr, /* Check NACK after MCTRLDONE is get */ if (IS_BIT_SET(inst->MERRWARN, NPCX_I3C_MERRWARN_NACK)) { - LOG_DBG("%s: nack", __func__); + LOG_DBG("Address nacked"); return -ENODEV; } @@ -380,8 +383,8 @@ static inline int npcx_i3c_request_emit_stop(struct i3c_reg *inst) uint32_t i3c_state = npcx_i3c_state_get(inst); /* Make sure we are in a state where we can emit STOP */ - if ((i3c_state != MSTATUS_STATE_NORMACT) && (i3c_state != MSTATUS_STATE_DAA)) { - LOG_ERR("Request stop state error, state= %#x", i3c_state); + if (i3c_state == MSTATUS_STATE_IDLE) { + LOG_WRN("Request stop in idle state, state= %#x", i3c_state); return -ECANCELED; } @@ -396,6 +399,56 @@ static inline int npcx_i3c_request_emit_stop(struct i3c_reg *inst) return 0; } +static inline int npcx_i3c_request_hdr_exit(struct i3c_reg *inst) +{ + uint32_t val = 0; + uint32_t state; + int ret; + + /* Before sending the HDR exit command, check the HDR mode */ + state = npcx_i3c_state_get(inst); + if (state != MSTATUS_STATE_MSGDDR) { + LOG_ERR("%s, state error: %#x", __func__, state); + return -EPERM; + } + + SET_FIELD(val, NPCX_I3C_MCTRL_TYPE, MCTRL_TYPE_HDR_EXIT); + SET_FIELD(val, NPCX_I3C_MCTRL_REQUEST, MCTRL_REQUEST_FORCEEXIT); + + ret = npcx_i3c_send_request(inst, val); + if (ret != 0) { + LOG_ERR("Request hdr exit error %d", ret); + return ret; + } + + return 0; +} + +static inline int npcx_i3c_xfer_stop(struct i3c_reg *inst) +{ + uint32_t state; + int ret; + + state = npcx_i3c_state_get(inst); + LOG_DBG("Current working state=%d", state); + + switch (state) { + case MSTATUS_STATE_NORMACT: /* SDR */ + ret = npcx_i3c_request_emit_stop(inst); + break; + case MSTATUS_STATE_MSGDDR: /* HDR-DDR */ + ret = npcx_i3c_request_hdr_exit(inst); + break; + default: + /* Not supported */ + ret = -ENOTSUP; + LOG_WRN("xfer_stop state not supported, state:%d", state); + break; + } + + return ret; +} + static inline int npcx_i3c_ibi_respond_nack(struct i3c_reg *inst) { uint32_t val = 0; @@ -535,7 +588,7 @@ static int npcx_i3c_xfer_write_fifo(struct i3c_reg *inst, uint8_t *buf, uint8_t /* Check tx fifo not full */ if (WAIT_FOR(!IS_BIT_SET(inst->MDATACTRL, NPCX_I3C_MDATACTRL_TXFULL), NPCX_I3C_CHK_TIMEOUT_US, NULL) == false) { - LOG_DBG("%s: Check tx fifo not full timed out", __func__); + LOG_DBG("Check tx fifo not full timed out"); return -ETIMEDOUT; } @@ -642,14 +695,13 @@ static int npcx_i3c_xfer_write_fifo_dma(const struct device *dev, uint8_t *buf, /* Wait I3C COMPLETE */ ret = i3c_ctrl_wait_completion(dev); if (ret < 0) { - LOG_DBG("%s: Check complete time out, buf_size:%d", __func__, buf_sz); + LOG_DBG("Check complete time out, buf_size:%d", buf_sz); goto out_wr_fifo_dma; } /* Check and clear DMA TC after complete */ if (!IS_BIT_SET(mdma_inst->MDMA_CTL1, NPCX_MDMA_CTL_TC)) { - LOG_DBG("%s: DMA busy, TC=%d", __func__, - IS_BIT_SET(mdma_inst->MDMA_CTL1, NPCX_MDMA_CTL_TC)); + LOG_DBG("DMA busy, TC=%d", IS_BIT_SET(mdma_inst->MDMA_CTL1, NPCX_MDMA_CTL_TC)); ret = -EBUSY; goto out_wr_fifo_dma; } @@ -668,6 +720,7 @@ static int npcx_i3c_xfer_write_fifo_dma(const struct device *dev, uint8_t *buf, /* * brief: Perform DMA read transaction. + * (Data width used for DMA transfers is "byte") * * For read end, use the MDMA end-of-transfer interrupt(SIEN bit) * instead of using the I3CI interrupt generated by COMPLETE bit in MSTATUS register. @@ -700,7 +753,7 @@ static int npcx_i3c_xfer_read_fifo_dma(const struct device *dev, uint8_t *buf, u /* Wait MDMA TC */ ret = i3c_ctrl_wait_completion(dev); if (ret < 0) { - LOG_DBG("%s: Check DMA done time out", __func__); + LOG_DBG("Check DMA done time out"); } else { ret = buf_sz - mdma_inst->MDMA_CTCNT0; /* Set transferred count */ LOG_DBG("Read cnt=%d", ret); @@ -717,6 +770,7 @@ static int npcx_i3c_xfer_read_fifo_dma(const struct device *dev, uint8_t *buf, u /* * brief: Perform one transfer transaction by DMA. + * (Support SDR and HDR-DDR) * * param[in] inst Pointer to controller registers. * param[in] addr Target address. @@ -731,18 +785,45 @@ static int npcx_i3c_xfer_read_fifo_dma(const struct device *dev, uint8_t *buf, u */ static int npcx_i3c_do_one_xfer_dma(const struct device *dev, uint8_t addr, enum npcx_i3c_mctrl_type op_type, uint8_t *buf, size_t buf_sz, - bool is_read, bool emit_start, bool emit_stop) + bool is_read, bool emit_start, bool emit_stop, uint8_t hdr_cmd) { const struct npcx_i3c_config *config = dev->config; struct i3c_reg *inst = config->base; int ret = 0; + bool is_hdr_ddr = (op_type == NPCX_I3C_MCTRL_TYPE_I3C_HDR_DDR) ? true : false; + size_t rd_len = buf_sz; npcx_i3c_status_clear_all(inst); npcx_i3c_errwarn_clear_all(inst); + /* Check HDR-DDR moves data by words */ + if (is_hdr_ddr && (buf_sz % 2 != 0)) { + LOG_ERR("%s, HDR-DDR data length should be even, len=%#x", __func__, buf_sz); + return -EINVAL; + } + /* Emit START if needed */ if (emit_start) { - ret = npcx_i3c_request_emit_start(inst, addr, op_type, is_read, buf_sz); + /* + * For HDR-DDR mode read, RDTERM also includes one word (16 bits) for CRC. + * For example, to read 8 bytes, set RDTERM to 6. + * (1 word HDR-DDR command + 4 words data + 1 word for CRC) + */ + if (is_hdr_ddr) { + if (is_read) { + /* The unit of rd_len is "word" in DDR mode */ + rd_len /= sizeof(uint16_t); /* byte to word */ + rd_len += HDR_DDR_CMD_AND_CRC_SZ_WORD; + hdr_cmd |= HDR_RD_CMD; + } else { + hdr_cmd &= ~HDR_RD_CMD; + } + + /* Write the command code for the HDR-DDR message */ + inst->MWDATAB = hdr_cmd; + } + + ret = npcx_i3c_request_emit_start(inst, addr, op_type, is_read, rd_len); if (ret != 0) { LOG_ERR("%s: emit start fail", __func__); goto out_do_one_xfer_dma; @@ -773,9 +854,9 @@ static int npcx_i3c_do_one_xfer_dma(const struct device *dev, uint8_t addr, } out_do_one_xfer_dma: - /* Emit STOP if needed */ + /* Emit STOP or exit DDR if needed */ if (emit_stop) { - npcx_i3c_request_emit_stop(inst); + npcx_i3c_xfer_stop(inst); } return ret; @@ -784,6 +865,7 @@ static int npcx_i3c_do_one_xfer_dma(const struct device *dev, uint8_t addr, /* * brief: Perform one transfer transaction. + * (Support SDR only) * * param[in] inst Pointer to controller registers. * param[in] addr Target address. @@ -839,7 +921,7 @@ static int npcx_i3c_do_one_xfer(struct i3c_reg *inst, uint8_t addr, /* Wait message transfer complete */ if (WAIT_FOR(IS_BIT_SET(inst->MSTATUS, NPCX_I3C_MSTATUS_COMPLETE), NPCX_I3C_CHK_TIMEOUT_US, NULL) == false) { - LOG_DBG("%s: timed out addr 0x%02x, buf_sz %u", __func__, addr, buf_sz); + LOG_DBG("Wait COMPLETE timed out, addr 0x%02x, buf_sz %u", addr, buf_sz); ret = -ETIMEDOUT; emit_stop = true; @@ -882,10 +964,12 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t { const struct npcx_i3c_config *config = dev->config; struct i3c_reg *inst = config->base; + struct npcx_i3c_data *data = dev->data; uint32_t intmask; int xfered_len, ret = 0; bool send_broadcast = true; bool is_xfer_done = true; + enum npcx_i3c_mctrl_type op_type; if (msgs == NULL) { return -EINVAL; @@ -913,7 +997,6 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t /* Iterate over all the messages */ for (int i = 0; i < num_msgs; i++) { - /* * Check message is read or write operaion. * For write operation, check the last data byte of a transmit message. @@ -958,35 +1041,63 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t } #endif - /* - * Two ways to do read/write transfer . - * 1. [S] + [0x7E] + [address] + [data] + [Sr or P] - * 2. [S] + [address] + [data] + [Sr or P] - * - * Send broadcast header(0x7E) on first transfer or after a STOP, - * unless flag is set not to. - */ - if (!(msgs[i].flags & I3C_MSG_NBCH) && (send_broadcast)) { - ret = npcx_i3c_request_emit_start(inst, I3C_BROADCAST_ADDR, - NPCX_I3C_MCTRL_TYPE_I3C, false, 0); - if (ret < 0) { - LOG_ERR("%s: emit start of broadcast addr failed, error (%d)", - __func__, ret); + /* Check message SDR or HDR mode */ + bool is_msg_hdr = (msgs[i].flags & I3C_MSG_HDR) == I3C_MSG_HDR; + + /* Set emit start type SDR or HDR-DDR mode */ + if (!is_msg_hdr || msgs[i].hdr_mode == 0) { + op_type = NPCX_I3C_MCTRL_TYPE_I3C; /* Set operation type SDR */ + + /* + * SDR, send boradcast header(0x7E) + * + * Two ways to do read/write transfer (SDR mode). + * 1. [S] + [0x7E] + [address] + [data] + [Sr or P] + * 2. [S] + [address] + [data] + [Sr or P] + * + * Send broadcast header(0x7E) on first transfer or after a STOP, + * unless flag is set not to. + */ + if (!(msgs[i].flags & I3C_MSG_NBCH) && send_broadcast) { + ret = npcx_i3c_request_emit_start(inst, I3C_BROADCAST_ADDR, + NPCX_I3C_MCTRL_TYPE_I3C, false, + 0); + if (ret < 0) { + LOG_ERR("%s: emit start of broadcast addr failed, error " + "(%d)", + __func__, ret); + break; + } + send_broadcast = false; + } + } else if ((data->common.ctrl_config.supported_hdr & I3C_MSG_HDR_DDR) && + (msgs[i].hdr_mode == I3C_MSG_HDR_DDR) && is_msg_hdr) { + + op_type = NPCX_I3C_MCTRL_TYPE_I3C_HDR_DDR; /* Set operation type DDR */ + + /* Check HDR-DDR moves data by words */ + if ((msgs[i].len % 2) != 0x0) { + LOG_ERR("HDR-DDR data length should be number of words , xfer " + "len=%d", msgs[i].num_xfer); + ret = -EINVAL; break; } - send_broadcast = false; + } else { + LOG_ERR("%s: %s controller HDR Mode %#x\r\n" + "msg HDR mode %#x, msg flag %#x", + __func__, dev->name, data->common.ctrl_config.supported_hdr, + msgs[i].hdr_mode, msgs[i].flags); + ret = -ENOTSUP; + break; } #ifdef CONFIG_I3C_NPCX_DMA /* Do transfer with target device */ - xfered_len = npcx_i3c_do_one_xfer_dma(dev, target->dynamic_addr, - NPCX_I3C_MCTRL_TYPE_I3C, msgs[i].buf, - msgs[i].len, is_read, emit_start, emit_stop); -#else - xfered_len = npcx_i3c_do_one_xfer(inst, target->dynamic_addr, - NPCX_I3C_MCTRL_TYPE_I3C, msgs[i].buf, msgs[i].len, - is_read, emit_start, emit_stop, no_ending); + xfered_len = npcx_i3c_do_one_xfer_dma(dev, target->dynamic_addr, op_type, + msgs[i].buf, msgs[i].len, is_read, emit_start, + emit_stop, msgs[i].hdr_cmd_code); #endif + if (xfered_len < 0) { LOG_ERR("%s: do xfer fail", __func__); ret = xfered_len; /* Set error code to ret */ @@ -997,7 +1108,7 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t msgs[i].num_xfer = xfered_len; if (emit_stop) { - /* After a STOP, send broadcast header before next msg */ + /* SDR. After a STOP, send broadcast header before next msg */ send_broadcast = true; } @@ -1009,7 +1120,7 @@ static int npcx_i3c_transfer(const struct device *dev, struct i3c_device_desc *t /* Emit stop if error occurs or stop flag not in the msg */ if ((ret != 0) || (is_xfer_done == false)) { - npcx_i3c_request_emit_stop(inst); + npcx_i3c_xfer_stop(inst); } npcx_i3c_errwarn_clear_all(inst); @@ -1354,9 +1465,10 @@ static void npcx_i3c_ibi_work(struct k_work *work) if (npcx_i3c_state_get(inst) != MSTATUS_STATE_TGTREQ) { LOG_DBG("IBI work %p running not because of IBI", work); + LOG_ERR("%s: IBI not in TGTREQ state, state : %#x", __func__, + npcx_i3c_state_get(inst)); LOG_ERR("%s: MSTATUS 0x%08x MERRWARN 0x%08x", __func__, inst->MSTATUS, inst->MERRWARN); - npcx_i3c_request_emit_stop(inst); goto out_ibi_work; @@ -1369,6 +1481,9 @@ static void npcx_i3c_ibi_work(struct k_work *work) if (WAIT_FOR(IS_BIT_SET(inst->MSTATUS, NPCX_I3C_MSTATUS_IBIWON), NPCX_I3C_CHK_TIMEOUT_US, NULL) == false) { LOG_ERR("IBI work, IBIWON timeout"); + LOG_ERR("%s: MSTATUS 0x%08x MERRWARN 0x%08x", __func__, inst->MSTATUS, + inst->MERRWARN); + npcx_i3c_request_emit_stop(inst); goto out_ibi_work; } @@ -1378,21 +1493,14 @@ static void npcx_i3c_ibi_work(struct k_work *work) switch (ibitype) { case MSTATUS_IBITYPE_IBI: - target = i3c_dev_list_i3c_addr_find(dev_list, (uint8_t)ibiaddr); - if (target != NULL) { - ret = npcx_i3c_xfer_read_fifo(inst, &payload[0], sizeof(payload)); - if (ret >= 0) { - payload_sz = (size_t)ret; - } else { - LOG_ERR("Error reading IBI payload"); - - npcx_i3c_request_emit_stop(inst); - - goto out_ibi_work; - } + ret = npcx_i3c_xfer_read_fifo(inst, &payload[0], sizeof(payload)); + if (ret >= 0) { + payload_sz = (size_t)ret; } else { - /* NACK IBI coming from unknown device */ - npcx_i3c_ibi_respond_nack(inst); + LOG_ERR("Error reading IBI payload"); + npcx_i3c_request_emit_stop(inst); + + goto out_ibi_work; } break; case MSTATUS_IBITYPE_HJ: @@ -1402,12 +1510,14 @@ static void npcx_i3c_ibi_work(struct k_work *work) case MSTATUS_IBITYPE_CR: LOG_DBG("Controller role handoff not supported"); npcx_i3c_ibi_respond_nack(inst); + npcx_i3c_request_emit_stop(inst); break; default: break; } if (npcx_i3c_has_error(inst)) { + LOG_ERR("%s: unexpected error, ibi type:%d", __func__, ibitype); /* * If the controller detects any errors, simply * emit a STOP to abort the IBI. The target will @@ -1420,10 +1530,13 @@ static void npcx_i3c_ibi_work(struct k_work *work) switch (ibitype) { case MSTATUS_IBITYPE_IBI: + target = i3c_dev_list_i3c_addr_find(dev_list, (uint8_t)ibiaddr); if (target != NULL) { if (i3c_ibi_work_enqueue_target_irq(target, &payload[0], payload_sz) != 0) { LOG_ERR("Error enqueue IBI IRQ work"); } + } else { + LOG_ERR("IBI (MDB) target not in the list"); } /* Finishing the IBI transaction */ @@ -1435,7 +1548,7 @@ static void npcx_i3c_ibi_work(struct k_work *work) } break; case MSTATUS_IBITYPE_CR: - /* Not supported */ + /* Not supported, for future use. */ break; default: break; @@ -1679,13 +1792,23 @@ static void npcx_i3c_isr(const struct device *dev) #endif /* CONFIG_I3C_NPCX_DMA */ #ifdef CONFIG_I3C_USE_IBI + int ret; + /* Target start detected */ if (IS_BIT_SET(inst->MSTATUS, NPCX_I3C_MSTATUS_TGTSTART)) { + LOG_DBG("ISR TGTSTART !"); + /* Disable further target initiated IBI interrupt */ inst->MINTCLR = BIT(NPCX_I3C_MINTCLR_TGTSTART); + /* Clear TGTSTART interrupt */ + inst->MSTATUS = BIT(NPCX_I3C_MSTATUS_TGTSTART); /* Handle IBI in workqueue */ - i3c_ibi_work_enqueue_cb(dev, npcx_i3c_ibi_work); + ret = i3c_ibi_work_enqueue_cb(dev, npcx_i3c_ibi_work); + if (ret < 0) { + LOG_ERR("Enqueuing ibi work fail, ret %d", ret); + inst->MINTSET = BIT(NPCX_I3C_MINTSET_TGTSTART); + } } #endif /* CONFIG_I3C_USE_IBI */ @@ -1958,7 +2081,7 @@ static int npcx_i3c_init(const struct device *dev) } ctrl_config->is_secondary = false; /* Currently can only act as primary controller. */ - ctrl_config->supported_hdr = 0U; /* HDR mode not supported at the moment. */ + ctrl_config->supported_hdr = I3C_MSG_HDR_DDR; /* HDR-DDR mode is supported. */ ctrl_config->scl.i3c = config->clocks.i3c_pp_scl_hz; /* Set I3C frequency */ ret = npcx_i3c_configure(dev, I3C_CONFIG_CONTROLLER, ctrl_config); diff --git a/drivers/i3c/i3c_shell.c b/drivers/i3c/i3c_shell.c index d4f3269dff095..8cd2c2b57e58b 100644 --- a/drivers/i3c/i3c_shell.c +++ b/drivers/i3c/i3c_shell.c @@ -217,7 +217,8 @@ static int cmd_i3c_info(const struct shell *shell_ctx, size_t argc, char **argv) "\tmax_read_turnaround: 0x%08x\n" "\tmrl: 0x%04x\n" "\tmwl: 0x%04x\n" - "\tmax_ibi: 0x%02x", + "\tmax_ibi: 0x%02x\n" + "\tgetcaps: 0x%02x; 0x%02x; 0x%02x; 0x%02x", desc->dev->name, (uint64_t)desc->pid, desc->static_addr, desc->dynamic_addr, #if defined(CONFIG_I3C_USE_GROUP_ADDR) @@ -227,7 +228,9 @@ static int cmd_i3c_info(const struct shell *shell_ctx, size_t argc, char **argv) desc->data_speed.maxwr, desc->data_speed.max_read_turnaround, desc->data_length.mrl, desc->data_length.mwl, - desc->data_length.max_ibi); + desc->data_length.max_ibi, + desc->getcaps.getcap1, desc->getcaps.getcap2, + desc->getcaps.getcap3, desc->getcaps.getcap4); found = true; break; } @@ -262,7 +265,8 @@ static int cmd_i3c_info(const struct shell *shell_ctx, size_t argc, char **argv) "\tmax_read_turnaround: 0x%08x\n" "\tmrl: 0x%04x\n" "\tmwl: 0x%04x\n" - "\tmax_ibi: 0x%02x", + "\tmax_ibi: 0x%02x\n" + "\tgetcaps: 0x%02x; 0x%02x; 0x%02x; 0x%02x", desc->dev->name, (uint64_t)desc->pid, desc->static_addr, desc->dynamic_addr, #if defined(CONFIG_I3C_USE_GROUP_ADDR) @@ -272,7 +276,9 @@ static int cmd_i3c_info(const struct shell *shell_ctx, size_t argc, char **argv) desc->data_speed.maxwr, desc->data_speed.max_read_turnaround, desc->data_length.mrl, desc->data_length.mwl, - desc->data_length.max_ibi); + desc->data_length.max_ibi, desc->getcaps.getcap1, + desc->getcaps.getcap2, desc->getcaps.getcap3, + desc->getcaps.getcap4); } } else { shell_print(shell_ctx, "I3C: No devices found."); @@ -877,11 +883,11 @@ static int cmd_i3c_ccc_setmrl_bc(const struct shell *shell_ctx, size_t argc, cha } mrl.len = strtol(argv[2], NULL, 16); - if (argc > 2) { + if (argc > 3) { mrl.ibi_len = strtol(argv[3], NULL, 16); } - ret = i3c_ccc_do_setmrl_all(dev, &mrl, argc > 2); + ret = i3c_ccc_do_setmrl_all(dev, &mrl, argc > 3); if (ret < 0) { shell_error(shell_ctx, "I3C: unable to send CCC SETMRL BC."); return ret; @@ -1083,7 +1089,7 @@ static int cmd_i3c_ccc_getstatus(const struct shell *shell_ctx, size_t argc, cha } /* If there is a defining byte, then it is assumed to be Format 2*/ - if (argc > 2) { + if (argc > 3) { fmt = GETSTATUS_FORMAT_2; defbyte = strtol(argv[3], NULL, 16); if (defbyte != GETSTATUS_FORMAT_2_TGTSTAT || defbyte != GETSTATUS_FORMAT_2_PRECR) { @@ -1113,6 +1119,81 @@ static int cmd_i3c_ccc_getstatus(const struct shell *shell_ctx, size_t argc, cha return ret; } +/* i3c ccc getcaps [] */ +static int cmd_i3c_ccc_getcaps(const struct shell *shell_ctx, size_t argc, char **argv) +{ + const struct device *dev, *tdev; + struct i3c_device_desc *desc; + union i3c_ccc_getcaps caps; + enum i3c_ccc_getcaps_fmt fmt; + enum i3c_ccc_getcaps_defbyte defbyte = GETCAPS_FORMAT_2_INVALID; + int ret; + + dev = device_get_binding(argv[ARGV_DEV]); + if (!dev) { + shell_error(shell_ctx, "I3C: Device driver %s not found.", argv[ARGV_DEV]); + return -ENODEV; + } + tdev = device_get_binding(argv[ARGV_TDEV]); + if (!tdev) { + shell_error(shell_ctx, "I3C: Device driver %s not found.", argv[ARGV_TDEV]); + return -ENODEV; + } + desc = get_i3c_attached_desc_from_dev_name(dev, tdev->name); + if (!desc) { + shell_error(shell_ctx, "I3C: Device %s not attached to bus.", tdev->name); + return -ENODEV; + } + + if (!(desc->bcr & I3C_BCR_ADV_CAPABILITIES)) { + shell_error(shell_ctx, "I3C: Device %s does not support advanced capabilities", + desc->dev->name); + return -ENOTSUP; + } + + /* If there is a defining byte, then it is assumed to be Format 2 */ + if (argc > 3) { + fmt = GETCAPS_FORMAT_2; + defbyte = strtol(argv[3], NULL, 16); + if (defbyte != GETCAPS_FORMAT_2_TGTCAPS || defbyte != GETCAPS_FORMAT_2_TESTPAT || + defbyte != GETCAPS_FORMAT_2_CRCAPS || defbyte != GETCAPS_FORMAT_2_VTCAPS || + defbyte != GETCAPS_FORMAT_2_DBGCAPS) { + shell_error(shell_ctx, "Invalid defining byte."); + return -EINVAL; + } + } else { + fmt = GETCAPS_FORMAT_1; + } + + ret = i3c_ccc_do_getcaps(desc, &caps, fmt, defbyte); + if (ret < 0) { + shell_error(shell_ctx, "I3C: unable to send CCC GETCAPS."); + return ret; + } + + if (fmt == GETCAPS_FORMAT_2) { + if (defbyte == GETCAPS_FORMAT_2_TGTCAPS) { + shell_print(shell_ctx, "TGTCAPS: 0x%02x; 0x%02x; 0x%02x; 0x%02x", + caps.fmt2.tgtcaps[0], caps.fmt2.tgtcaps[1], + caps.fmt2.tgtcaps[2], caps.fmt2.tgtcaps[3]); + } else if (defbyte == GETCAPS_FORMAT_2_TESTPAT) { + shell_print(shell_ctx, "TESTPAT: 0x%08x", caps.fmt2.testpat); + } else if (defbyte == GETCAPS_FORMAT_2_CRCAPS) { + shell_print(shell_ctx, "CRCAPS: 0x%02x; 0x%02x", caps.fmt2.crcaps[0], + caps.fmt2.crcaps[1]); + } else if (defbyte == GETCAPS_FORMAT_2_VTCAPS) { + shell_print(shell_ctx, "VTCAPS: 0x%02x; 0x%02x", caps.fmt2.vtcaps[0], + caps.fmt2.vtcaps[1]); + } + } else { + shell_print(shell_ctx, "GETCAPS: 0x%02x; 0x%02x; 0x%02x; 0x%02x", + caps.fmt1.getcaps[0], caps.fmt1.getcaps[1], caps.fmt1.getcaps[2], + caps.fmt1.getcaps[3]); + } + + return ret; +} + static int cmd_i3c_attach(const struct shell *shell_ctx, size_t argc, char **argv) { const struct device *dev, *tdev; @@ -1383,6 +1464,10 @@ SHELL_STATIC_SUBCMD_SET_CREATE( "Send CCC GETSTATUS\n" "Usage: ccc getstatus []", cmd_i3c_ccc_getstatus, 3, 1), + SHELL_CMD_ARG(getcaps, &dsub_i3c_device_attached_name, + "Send CCC GETCAPS\n" + "Usage: ccc getcaps []", + cmd_i3c_ccc_getcaps, 3, 1), SHELL_SUBCMD_SET_END /* Array terminated. */ ); diff --git a/drivers/ieee802154/Kconfig.nrf5 b/drivers/ieee802154/Kconfig.nrf5 index 9acb811e6b602..43217f8d37a3f 100644 --- a/drivers/ieee802154/Kconfig.nrf5 +++ b/drivers/ieee802154/Kconfig.nrf5 @@ -72,7 +72,7 @@ config IEEE802154_NRF5_FCS_IN_LENGTH config IEEE802154_NRF5_DELAY_TRX_ACC int "Clock accuracy for delayed operations" - default CLOCK_CONTROL_NRF_ACCURACY if CLOCK_CONTROL_NRF_ACCURACY < 255 + default CLOCK_CONTROL_NRF_ACCURACY if (CLOCK_CONTROL_NRF && (CLOCK_CONTROL_NRF_ACCURACY < 255)) default 255 help Accuracy of the clock used for scheduling radio delayed operations (delayed transmission diff --git a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c index 7f2356e8ecfec..3f6d7067705b6 100644 --- a/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c +++ b/drivers/ieee802154/ieee802154_cc13xx_cc26xx_subg.c @@ -403,7 +403,11 @@ static void cmd_prop_rx_adv_callback(RF_Handle h, RF_CmdHandle ch, LOG_DBG("ch: %u cmd: %04x st: %04x e: 0x%" PRIx64, ch, op->commandNo, op->status, e); - if (e & RF_EventRxEntryDone) { + /* If PROP_ERROR_RXBUF is returned, then RF_EventRxEntryDone is never + * triggered. So finished buffers need to be cleaned up even on this + * status. + */ + if (e & RF_EventRxEntryDone || op->status == PROP_ERROR_RXBUF) { drv_rx_done(drv_data); } diff --git a/drivers/ieee802154/ieee802154_nrf5.c b/drivers/ieee802154/ieee802154_nrf5.c index 4cbdd9eb6072e..13f4132a01dfd 100644 --- a/drivers/ieee802154/ieee802154_nrf5.c +++ b/drivers/ieee802154/ieee802154_nrf5.c @@ -126,7 +126,11 @@ static void nrf5_get_eui64(uint8_t *mac) mac[index++] = (IEEE802154_NRF5_VENDOR_OUI >> 8) & 0xff; mac[index++] = IEEE802154_NRF5_VENDOR_OUI & 0xff; -#if defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) && defined(NRF_FICR_S) +#if defined(NRF54H_SERIES) + /* Can't access SICR with device id on a radio core. Use BLE.ADDR. */ + deviceid[0] = NRF_FICR->BLE.ADDR[0]; + deviceid[1] = NRF_FICR->BLE.ADDR[1]; +#elif defined(CONFIG_TRUSTED_EXECUTION_NONSECURE) && defined(NRF_FICR_S) soc_secure_read_deviceid(deviceid); #else deviceid[0] = nrf_ficr_deviceid_get(NRF_FICR, 0); @@ -1005,6 +1009,10 @@ static int nrf5_configure(const struct device *dev, case IEEE802154_CONFIG_RX_ON_WHEN_IDLE: nrf_802154_rx_on_when_idle_set(config->rx_on_when_idle); nrf5_data.rx_on_when_idle = config->rx_on_when_idle; + + if (config->rx_on_when_idle == false) { + (void)nrf_802154_sleep_if_idle(); + } break; default: diff --git a/drivers/input/CMakeLists.txt b/drivers/input/CMakeLists.txt index bab58e5c6d302..a996cb93ead3b 100644 --- a/drivers/input/CMakeLists.txt +++ b/drivers/input/CMakeLists.txt @@ -24,6 +24,7 @@ zephyr_library_sources_ifdef(CONFIG_INPUT_PAT912X input_pat912x.c) zephyr_library_sources_ifdef(CONFIG_INPUT_PAW32XX input_paw32xx.c) zephyr_library_sources_ifdef(CONFIG_INPUT_PINNACLE input_pinnacle.c) zephyr_library_sources_ifdef(CONFIG_INPUT_PMW3610 input_pmw3610.c) +zephyr_library_sources_ifdef(CONFIG_INPUT_SBUS input_sbus.c) zephyr_library_sources_ifdef(CONFIG_INPUT_STMPE811 input_stmpe811.c) zephyr_library_sources_ifdef(CONFIG_INPUT_XEC_KBD input_xec_kbd.c) zephyr_library_sources_ifdef(CONFIG_INPUT_XPT2046 input_xpt2046.c) diff --git a/drivers/input/Kconfig b/drivers/input/Kconfig index e810b5b0914c4..34363e3eca94c 100644 --- a/drivers/input/Kconfig +++ b/drivers/input/Kconfig @@ -26,6 +26,7 @@ source "drivers/input/Kconfig.pat912x" source "drivers/input/Kconfig.paw32xx" source "drivers/input/Kconfig.pinnacle" source "drivers/input/Kconfig.pmw3610" +source "drivers/input/Kconfig.sbus" source "drivers/input/Kconfig.sdl" source "drivers/input/Kconfig.stmpe811" source "drivers/input/Kconfig.xec" diff --git a/drivers/input/Kconfig.analog_axis b/drivers/input/Kconfig.analog_axis index 472b611acea8e..47f90e9fcb4c5 100644 --- a/drivers/input/Kconfig.analog_axis +++ b/drivers/input/Kconfig.analog_axis @@ -5,8 +5,8 @@ config INPUT_ANALOG_AXIS bool "ADC based analog axis input driver" default y depends on DT_HAS_ANALOG_AXIS_ENABLED - depends on ADC depends on MULTITHREADING + select ADC help ADC based analog axis input driver diff --git a/drivers/input/Kconfig.sbus b/drivers/input/Kconfig.sbus new file mode 100644 index 0000000000000..a3d1532161ed7 --- /dev/null +++ b/drivers/input/Kconfig.sbus @@ -0,0 +1,54 @@ +# Copyright (c) 2024 NXP Semiconductors +# SPDX-License-Identifier: Apache-2.0 + +config INPUT_SBUS + bool "SBUS driver" + default y + depends on DT_HAS_FUTABA_SBUS_ENABLED + depends on UART_INTERRUPT_DRIVEN + select UART_USE_RUNTIME_CONFIGURE + help + Enable driver for SBUS Remote controller. + +if INPUT_SBUS + +config INPUT_SBUS_THREAD_STACK_SIZE + int "Stack size for the sbus thread" + default 1024 + help + Size of the stack used for the sbus thread. + +config INPUT_SBUS_THREAD_PRIORITY + int "Priority for the sbus thread" + default 0 + help + Priority level of the sbus thread. + +config INPUT_SBUS_REPORT_FILTER + int "Minimal change in signal to report" + default 1 + help + SBUS tends to be a bit noisy you can increase the threshold to + to lower the amounts of input events. Set to 0 for no filtering + +config INPUT_SBUS_SEND_SYNC + bool "Send Sync to input subsys on each SBUS frame" + default y + help + Sends sync message to input subsys with sync bit. + +config INPUT_SBUS_CHANNEL_VALUE_ONE + int "Threshold value > for INPUT_EV_KEY value 1" + default 1800 + help + SBUS sends analogue values for digital switches. This config value + sets the threshold to interperted the analogue value as an logic 1 + +config INPUT_SBUS_CHANNEL_VALUE_ZERO + int "Threshold value < for INPUT_EV_KEY value 0" + default 1200 + help + SBUS sends analogue values for digital switches. This config value + sets the threshold to interperted the analogue value as an logic 0 + +endif # INPUT_SBUS diff --git a/drivers/input/input_analog_axis.c b/drivers/input/input_analog_axis.c index 4217fdc765014..44c0cc34cb6ea 100644 --- a/drivers/input/input_analog_axis.c +++ b/drivers/input/input_analog_axis.c @@ -13,6 +13,9 @@ #include #include #include +#include +#include +#include #include LOG_MODULE_REGISTER(analog_axis, CONFIG_INPUT_LOG_LEVEL); @@ -45,6 +48,11 @@ struct analog_axis_data { K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_INPUT_ANALOG_AXIS_THREAD_STACK_SIZE); + +#ifdef CONFIG_PM_DEVICE + atomic_t suspended; + struct k_sem wakeup; +#endif }; int analog_axis_num_axes(const struct device *dev) @@ -229,11 +237,13 @@ static void analog_axis_thread(void *arg1, void *arg2, void *arg3) } } - k_timer_init(&data->timer, NULL, NULL); - k_timer_start(&data->timer, - K_MSEC(cfg->poll_period_ms), K_MSEC(cfg->poll_period_ms)); - while (true) { +#ifdef CONFIG_PM_DEVICE + if (atomic_get(&data->suspended) == 1) { + k_sem_take(&data->wakeup, K_FOREVER); + } +#endif + analog_axis_loop(dev); k_timer_status_sync(&data->timer); } @@ -245,6 +255,11 @@ static int analog_axis_init(const struct device *dev) k_tid_t tid; k_sem_init(&data->cal_lock, 1, 1); + k_timer_init(&data->timer, NULL, NULL); + +#ifdef CONFIG_PM_DEVICE + k_sem_init(&data->wakeup, 0, 1); +#endif tid = k_thread_create(&data->thread, data->thread_stack, K_KERNEL_STACK_SIZEOF(data->thread_stack), @@ -258,9 +273,54 @@ static int analog_axis_init(const struct device *dev) k_thread_name_set(&data->thread, dev->name); +#ifndef CONFIG_PM_DEVICE_RUNTIME + const struct analog_axis_config *cfg = dev->config; + + k_timer_start(&data->timer, + K_MSEC(cfg->poll_period_ms), K_MSEC(cfg->poll_period_ms)); +#else + int ret; + + atomic_set(&data->suspended, 1); + + pm_device_init_suspended(dev); + ret = pm_device_runtime_enable(dev); + if (ret < 0) { + LOG_ERR("Failed to enable runtime power management"); + return ret; + } +#endif + return 0; } +#ifdef CONFIG_PM_DEVICE +static int analog_axis_pm_action(const struct device *dev, + enum pm_device_action action) +{ + const struct analog_axis_config *cfg = dev->config; + struct analog_axis_data *data = dev->data; + + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + atomic_set(&data->suspended, 1); + k_timer_stop(&data->timer); + break; + case PM_DEVICE_ACTION_RESUME: + k_timer_start(&data->timer, + K_MSEC(cfg->poll_period_ms), + K_MSEC(cfg->poll_period_ms)); + atomic_set(&data->suspended, 0); + k_sem_give(&data->wakeup); + break; + default: + return -ENOTSUP; + } + + return 0; +} +#endif + #define ANALOG_AXIS_CHANNEL_CFG_DEF(node_id) \ { \ .adc = ADC_DT_SPEC_GET(node_id), \ @@ -301,7 +361,9 @@ static int analog_axis_init(const struct device *dev) \ static struct analog_axis_data analog_axis_data_##inst; \ \ - DEVICE_DT_INST_DEFINE(inst, analog_axis_init, NULL, \ + PM_DEVICE_DT_INST_DEFINE(inst, analog_axis_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, analog_axis_init, PM_DEVICE_DT_INST_GET(inst), \ &analog_axis_data_##inst, &analog_axis_cfg_##inst, \ POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); diff --git a/drivers/input/input_gpio_keys.c b/drivers/input/input_gpio_keys.c index 7fca24a55ed42..fa27ca5bd6440 100644 --- a/drivers/input/input_gpio_keys.c +++ b/drivers/input/input_gpio_keys.c @@ -106,6 +106,14 @@ static __maybe_unused void gpio_keys_change_deferred(struct k_work *work) const struct gpio_keys_config *cfg = dev->config; int key_index = pin_data - (struct gpio_keys_pin_data *)cfg->pin_data; +#ifdef CONFIG_PM_DEVICE + struct gpio_keys_data *data = dev->data; + + if (atomic_get(&data->suspended) == 1) { + return; + } +#endif + gpio_keys_poll_pin(dev, key_index); } diff --git a/drivers/input/input_ite_it8xxx2_kbd.c b/drivers/input/input_ite_it8xxx2_kbd.c index 5e62e6ee32e1a..5681b33183322 100644 --- a/drivers/input/input_ite_it8xxx2_kbd.c +++ b/drivers/input/input_ite_it8xxx2_kbd.c @@ -16,6 +16,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(input_ite_it8xxx2_kbd); @@ -58,24 +59,27 @@ static void it8xxx2_kbd_drive_column(const struct device *dev, int col) const struct it8xxx2_kbd_config *const config = dev->config; const struct input_kbd_matrix_common_config *common = &config->common; struct kscan_it8xxx2_regs *const inst = config->base; - int mask; + const uint32_t kso_mask = BIT_MASK(common->col_size); + const uint8_t ksol_mask = kso_mask & 0xff; + const uint8_t ksoh1_mask = (kso_mask >> 8) & 0xff; + uint32_t kso_val; /* Tri-state all outputs */ if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_NONE) { - mask = 0x3ffff; + kso_val = kso_mask; /* Assert all outputs */ } else if (col == INPUT_KBD_MATRIX_COLUMN_DRIVE_ALL) { - mask = 0; + kso_val = 0; /* Assert a single output */ } else { - mask = 0x3ffff ^ BIT(col); + kso_val = kso_mask ^ BIT(col); } /* Set KSO[17:0] output data */ - inst->KBS_KSOL = (uint8_t) (mask & 0xff); - inst->KBS_KSOH1 = (uint8_t) ((mask >> 8) & 0xff); + inst->KBS_KSOL = (inst->KBS_KSOL & ~ksol_mask) | (kso_val & ksol_mask); + inst->KBS_KSOH1 = (inst->KBS_KSOH1 & ~ksoh1_mask) | ((kso_val >> 8) & ksoh1_mask); if (common->col_size > 16) { - inst->KBS_KSOH2 = (uint8_t) ((mask >> 16) & 0xff); + inst->KBS_KSOH2 = (kso_val >> 16) & 0xff; } } @@ -138,6 +142,9 @@ static int it8xxx2_kbd_init(const struct device *dev) const struct input_kbd_matrix_common_config *common = &config->common; struct it8xxx2_kbd_data *data = dev->data; struct kscan_it8xxx2_regs *const inst = config->base; + const uint32_t kso_mask = BIT_MASK(common->col_size); + const uint8_t ksol_mask = kso_mask & 0xff; + const uint8_t ksoh1_mask = (kso_mask >> 8) & 0xff; int status; /* Disable wakeup and interrupt of KSI pins before configuring */ @@ -171,8 +178,8 @@ static int it8xxx2_kbd_init(const struct device *dev) } /* KSO[17:0] pins output low */ - inst->KBS_KSOL = 0x00; - inst->KBS_KSOH1 = 0x00; + inst->KBS_KSOL = inst->KBS_KSOL & ~ksol_mask; + inst->KBS_KSOH1 = inst->KBS_KSOH1 & ~ksoh1_mask; if (common->col_size > 16) { inst->KBS_KSOH2 = 0x00; } @@ -241,4 +248,4 @@ DEVICE_DT_INST_DEFINE(0, &it8xxx2_kbd_init, NULL, BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1, "only one ite,it8xxx2-kbd compatible node can be supported"); BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, row_size), 1, 8), "invalid row-size"); -BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, col_size), 16, 18), "invalid col-size"); +BUILD_ASSERT(IN_RANGE(DT_INST_PROP(0, col_size), 1, 18), "invalid col-size"); diff --git a/drivers/input/input_sbus.c b/drivers/input/input_sbus.c new file mode 100644 index 0000000000000..ef88f5fc677f0 --- /dev/null +++ b/drivers/input/input_sbus.c @@ -0,0 +1,376 @@ +/* + * Copyright (c) 2024 CogniPilot Foundation + * Copyright (c) 2024 NXP Semiconductors + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT futaba_sbus + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(futaba_sbus, CONFIG_INPUT_LOG_LEVEL); + +/* Driver config */ +struct sbus_input_channel { + uint32_t sbus_channel; + uint32_t type; + uint32_t zephyr_code; +}; + +const struct uart_config uart_cfg_sbus = { + .baudrate = 100000, + .parity = UART_CFG_PARITY_EVEN, + .stop_bits = UART_CFG_STOP_BITS_2, + .data_bits = UART_CFG_DATA_BITS_8, + .flow_ctrl = UART_CFG_FLOW_CTRL_NONE +}; + +struct input_sbus_config { + uint8_t num_channels; + const struct sbus_input_channel *channel_info; + const struct device *uart_dev; + uart_irq_callback_user_data_t cb; +}; + +#define SBUS_FRAME_LEN 25 +#define SBUS_HEADER 0x0F +#define SBUS_FOOTER 0x00 + +#define SBUS_SERVO_LEN 22 +#define SBUS_SERVO_CH_MASK 0x7FF + +#define SBUS_BYTE24_IDX 23 +#define SBUS_BYTE24_CH17 0x01 +#define SBUS_BYTE24_CH18 0x02 +#define SBUS_BYTE24_FRAME_LOST 0x04 +#define SBUS_BYTE24_FAILSAFE 0x08 + +#define SBUS_TRANSMISSION_TIME_MS 4 /* Max transmission of a single SBUS frame */ +#define SBUS_INTERFRAME_SPACING_MS 20 /* Max spacing between SBUS frames */ +#define SBUS_CHANNEL_COUNT 16 + +#define REPORT_FILTER CONFIG_INPUT_SBUS_REPORT_FILTER +#define CHANNEL_VALUE_ZERO CONFIG_INPUT_SBUS_CHANNEL_VALUE_ZERO +#define CHANNEL_VALUE_ONE CONFIG_INPUT_SBUS_CHANNEL_VALUE_ONE + +struct input_sbus_data { + struct k_thread thread; + struct k_sem report_lock; + + uint16_t xfer_bytes; + uint8_t rd_data[SBUS_FRAME_LEN]; + uint8_t sbus_frame[SBUS_FRAME_LEN]; + bool partial_sync; + bool in_sync; + uint32_t last_rx_time; + + uint16_t last_reported_value[SBUS_CHANNEL_COUNT]; + int8_t channel_mapping[SBUS_CHANNEL_COUNT]; + + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_INPUT_SBUS_THREAD_STACK_SIZE); +}; + +static void input_sbus_report(const struct device *dev, unsigned int sbus_channel, + unsigned int value) +{ + const struct input_sbus_config *const config = dev->config; + struct input_sbus_data *const data = dev->data; + + int channel = data->channel_mapping[sbus_channel]; + + /* Not Mapped */ + if (channel == -1) { + return; + } + + if (value >= (data->last_reported_value[channel] + REPORT_FILTER) || + value <= (data->last_reported_value[channel] - REPORT_FILTER)) { + switch (config->channel_info[channel].type) { + case INPUT_EV_ABS: + case INPUT_EV_MSC: + input_report(dev, config->channel_info[channel].type, + config->channel_info[channel].zephyr_code, value, false, + K_FOREVER); + break; + + default: + if (value > CHANNEL_VALUE_ONE) { + input_report_key(dev, config->channel_info[channel].zephyr_code, 1, + false, K_FOREVER); + } else if (value < CHANNEL_VALUE_ZERO) { + input_report_key(dev, config->channel_info[channel].zephyr_code, 0, + false, K_FOREVER); + } + } + data->last_reported_value[channel] = value; + } +} + +static void input_sbus_input_report_thread(const struct device *dev, void *dummy2, void *dummy3) +{ + struct input_sbus_data *const data = dev->data; + + ARG_UNUSED(dummy2); + ARG_UNUSED(dummy3); + + uint8_t i, channel; + uint8_t *sbus_channel_data = &data->sbus_frame[1]; /* Omit header */ + uint16_t value; + int bits_read; + unsigned int key; + int ret; + bool connected_reported = false; + + while (true) { + if (!data->in_sync) { + k_sem_take(&data->report_lock, K_FOREVER); + if (data->in_sync) { + LOG_DBG("SBUS receiver connected"); + } else { + continue; + } + } else { + ret = k_sem_take(&data->report_lock, K_MSEC(SBUS_INTERFRAME_SPACING_MS)); + if (ret == -EBUSY) { + continue; + } else if (ret < 0 || !data->in_sync) { + /* We've lost sync with the UART receiver */ + key = irq_lock(); + + data->partial_sync = false; + data->in_sync = false; + data->xfer_bytes = 0; + irq_unlock(key); + + connected_reported = false; + LOG_DBG("SBUS receiver connection lost"); + + /* Report connection lost */ + continue; + } + } + + if (connected_reported && + data->sbus_frame[SBUS_BYTE24_IDX] & SBUS_BYTE24_FRAME_LOST) { + LOG_DBG("SBUS controller connection lost"); + connected_reported = false; + } else if (!connected_reported && + !(data->sbus_frame[SBUS_BYTE24_IDX] & SBUS_BYTE24_FRAME_LOST)) { + LOG_DBG("SBUS controller connected"); + connected_reported = true; + } + + /* Parse the data */ + channel = 0; + value = 0; + bits_read = 0; + + for (i = 0; i < SBUS_SERVO_LEN; i++) { + /* Read the next byte */ + unsigned char byte = sbus_channel_data[i]; + + /* Extract bits and construct the 11-bit value */ + value |= byte << bits_read; + bits_read += 8; + + /* Check if we've read enough bits to form a full 11-bit value */ + while (bits_read >= 11) { + input_sbus_report(dev, channel, value & SBUS_SERVO_CH_MASK); + + /* Shift right to prepare for the next 11 bits */ + value >>= 11; + bits_read -= 11; + channel++; + } + } + +#ifdef CONFIG_INPUT_SBUS_SEND_SYNC + input_report(dev, 0, 0, 0, true, K_FOREVER); +#endif + } +} + +static void sbus_resync(const struct device *uart_dev, struct input_sbus_data *const data) +{ + uint8_t *rd_data = data->rd_data; + + if (data->partial_sync) { + data->xfer_bytes += uart_fifo_read(uart_dev, &rd_data[data->xfer_bytes], + SBUS_FRAME_LEN - data->xfer_bytes); + if (data->xfer_bytes == SBUS_FRAME_LEN) { + /* Transfer took longer then 4ms probably faulty */ + if (k_uptime_get_32() - data->last_rx_time > SBUS_TRANSMISSION_TIME_MS) { + data->xfer_bytes = 0; + data->partial_sync = false; + } else if (rd_data[0] == SBUS_HEADER && + rd_data[SBUS_FRAME_LEN - 1] == SBUS_FOOTER) { + data->in_sync = true; + } else { + /* Dummy read to clear fifo */ + uart_fifo_read(uart_dev, &rd_data[0], 1); + data->xfer_bytes = 0; + data->partial_sync = false; + } + } + } else { + if (uart_fifo_read(uart_dev, &rd_data[0], 1) == 1) { + if (rd_data[0] == SBUS_HEADER) { + data->partial_sync = true; + data->xfer_bytes = 1; + data->last_rx_time = k_uptime_get_32(); + } + } + } +} + +static void sbus_uart_isr(const struct device *uart_dev, void *user_data) +{ + const struct device *dev = user_data; + struct input_sbus_data *const data = dev->data; + uint8_t *rd_data = data->rd_data; + + if (uart_dev == NULL) { + LOG_DBG("UART device is NULL"); + return; + } + + if (!uart_irq_update(uart_dev)) { + LOG_DBG("Unable to start processing interrupts"); + return; + } + + while (uart_irq_rx_ready(uart_dev) && data->xfer_bytes <= SBUS_FRAME_LEN) { + if (data->in_sync) { + if (data->xfer_bytes == 0) { + data->last_rx_time = k_uptime_get_32(); + } + data->xfer_bytes += uart_fifo_read(uart_dev, &rd_data[data->xfer_bytes], + SBUS_FRAME_LEN - data->xfer_bytes); + } else { + sbus_resync(uart_dev, data); + } + } + + if (data->in_sync && (k_uptime_get_32() - data->last_rx_time > + SBUS_INTERFRAME_SPACING_MS)) { + data->partial_sync = false; + data->in_sync = false; + data->xfer_bytes = 0; + k_sem_give(&data->report_lock); + } else if (data->in_sync && data->xfer_bytes == SBUS_FRAME_LEN) { + data->xfer_bytes = 0; + + if (rd_data[0] == SBUS_HEADER && rd_data[SBUS_FRAME_LEN - 1] == SBUS_FOOTER) { + memcpy(data->sbus_frame, rd_data, SBUS_FRAME_LEN); + k_sem_give(&data->report_lock); + } else { + data->partial_sync = false; + data->in_sync = false; + } + } +} + +/* + * @brief Initialize sbus driver + */ +static int input_sbus_init(const struct device *dev) +{ + const struct input_sbus_config *const config = dev->config; + struct input_sbus_data *const data = dev->data; + int i, ret; + + uart_irq_rx_disable(config->uart_dev); + uart_irq_tx_disable(config->uart_dev); + + LOG_DBG("Initializing SBUS driver"); + + for (i = 0; i < SBUS_CHANNEL_COUNT; i++) { + data->last_reported_value[i] = 0; + data->channel_mapping[i] = -1; + } + + data->xfer_bytes = 0; + data->in_sync = false; + data->partial_sync = false; + data->last_rx_time = 0; + + for (i = 0; i < config->num_channels; i++) { + data->channel_mapping[config->channel_info[i].sbus_channel - 1] = i; + } + + ret = uart_configure(config->uart_dev, &uart_cfg_sbus); + if (ret < 0) { + LOG_ERR("Unable to configure UART port: %d", ret); + return ret; + } + + ret = uart_irq_callback_user_data_set(config->uart_dev, config->cb, (void *)dev); + if (ret < 0) { + if (ret == -ENOTSUP) { + LOG_ERR("Interrupt-driven UART API support not enabled"); + } else if (ret == -ENOSYS) { + LOG_ERR("UART device does not support interrupt-driven API"); + } else { + LOG_ERR("Error setting UART callback: %d", ret); + } + return ret; + } + + uart_irq_rx_enable(config->uart_dev); + + k_sem_init(&data->report_lock, 0, 1); + + k_thread_create(&data->thread, data->thread_stack, + K_KERNEL_STACK_SIZEOF(data->thread_stack), + (k_thread_entry_t)input_sbus_input_report_thread, (void *)dev, NULL, NULL, + CONFIG_INPUT_SBUS_THREAD_PRIORITY, 0, K_NO_WAIT); + + k_thread_name_set(&data->thread, dev->name); + + return ret; +} + +#define INPUT_CHANNEL_CHECK(input_channel_id) \ + BUILD_ASSERT(IN_RANGE(DT_PROP(input_channel_id, channel), 1, 16), \ + "invalid channel number"); \ + BUILD_ASSERT(DT_PROP(input_channel_id, type) == INPUT_EV_ABS || \ + DT_PROP(input_channel_id, type) == INPUT_EV_KEY || \ + DT_PROP(input_channel_id, type) == INPUT_EV_MSC, \ + "invalid channel type"); + +#define SBUS_INPUT_CHANNEL_INITIALIZER(input_channel_id) \ + { \ + .sbus_channel = DT_PROP(input_channel_id, channel), \ + .type = DT_PROP(input_channel_id, type), \ + .zephyr_code = DT_PROP(input_channel_id, zephyr_code), \ + }, + +#define INPUT_SBUS_INIT(n) \ + \ + static const struct sbus_input_channel input_##id[] = { \ + DT_INST_FOREACH_CHILD(n, SBUS_INPUT_CHANNEL_INITIALIZER) \ + }; \ + DT_INST_FOREACH_CHILD(n, INPUT_CHANNEL_CHECK) \ + \ + static struct input_sbus_data sbus_data_##n; \ + \ + static const struct input_sbus_config sbus_cfg_##n = { \ + .channel_info = input_##id, \ + .uart_dev = DEVICE_DT_GET(DT_INST_BUS(n)), \ + .num_channels = ARRAY_SIZE(input_##id), \ + .cb = sbus_uart_isr, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, input_sbus_init, NULL, &sbus_data_##n, &sbus_cfg_##n, \ + POST_KERNEL, CONFIG_INPUT_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(INPUT_SBUS_INIT) diff --git a/drivers/interrupt_controller/CMakeLists.txt b/drivers/interrupt_controller/CMakeLists.txt index 9e07386e59eb1..e9b7488f05b5f 100644 --- a/drivers/interrupt_controller/CMakeLists.txt +++ b/drivers/interrupt_controller/CMakeLists.txt @@ -41,6 +41,7 @@ zephyr_library_sources_ifdef(CONFIG_XMC4XXX_INTC intc_xmc4xxx.c) zephyr_library_sources_ifdef(CONFIG_NXP_PINT intc_nxp_pint.c) zephyr_library_sources_ifdef(CONFIG_RENESAS_RA_ICU intc_renesas_ra_icu.c) zephyr_library_sources_ifdef(CONFIG_NXP_IRQSTEER intc_nxp_irqsteer.c) +zephyr_library_sources_ifdef(CONFIG_INTC_MTK_ADSP intc_mtk_adsp.c) if(CONFIG_INTEL_VTD_ICTL) zephyr_library_include_directories(${ZEPHYR_BASE}/arch/x86/include) diff --git a/drivers/interrupt_controller/Kconfig b/drivers/interrupt_controller/Kconfig index a956afdf1f602..250309d20833c 100644 --- a/drivers/interrupt_controller/Kconfig +++ b/drivers/interrupt_controller/Kconfig @@ -26,7 +26,7 @@ config SWERV_PIC config VEXRISCV_LITEX_IRQ bool "VexRiscv LiteX Interrupt controller" default y - depends on DT_HAS_VEXRISCV_INTC0_ENABLED + depends on DT_HAS_LITEX_VEXRISCV_INTC0_ENABLED help IRQ implementation for LiteX VexRiscv @@ -106,4 +106,6 @@ source "drivers/interrupt_controller/Kconfig.renesas_ra" source "drivers/interrupt_controller/Kconfig.nxp_irqsteer" +source "drivers/interrupt_controller/Kconfig.mtk_adsp" + endmenu diff --git a/drivers/interrupt_controller/Kconfig.clic b/drivers/interrupt_controller/Kconfig.clic index fff8d1dffadeb..db7fe0b6b0d56 100644 --- a/drivers/interrupt_controller/Kconfig.clic +++ b/drivers/interrupt_controller/Kconfig.clic @@ -14,6 +14,7 @@ config NRFX_CLIC bool "VPR Core Local Interrpt Controller (CLIC)" default y depends on DT_HAS_NORDIC_NRF_CLIC_ENABLED + select GEN_IRQ_VECTOR_TABLE help Interrupt controller for Nordic VPR cores. diff --git a/drivers/interrupt_controller/Kconfig.esp32 b/drivers/interrupt_controller/Kconfig.esp32 index 1d88fcb196605..26d6a0f56fef8 100644 --- a/drivers/interrupt_controller/Kconfig.esp32 +++ b/drivers/interrupt_controller/Kconfig.esp32 @@ -5,7 +5,7 @@ config INTC_ESP32 bool "Interrupt allocator for Xtensa-based Espressif SoCs" - default y if SOC_FAMILY_ESPRESSIF_ESP32 && !SOC_SERIES_ESP32C3 + default y if SOC_FAMILY_ESPRESSIF_ESP32 && !SOC_SERIES_ESP32C3 && !SOC_SERIES_ESP32C6 help Enable custom interrupt allocator for Espressif SoCs based on Xtensa architecture. diff --git a/drivers/interrupt_controller/Kconfig.esp32c3 b/drivers/interrupt_controller/Kconfig.esp32c3 index c6d4b7da88f6f..f2bb54b0fc80e 100644 --- a/drivers/interrupt_controller/Kconfig.esp32c3 +++ b/drivers/interrupt_controller/Kconfig.esp32c3 @@ -3,7 +3,7 @@ config INTC_ESP32C3 bool "ESP32C3 interrupt controller driver" - depends on SOC_SERIES_ESP32C3 + depends on SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32C6 default y help Enables the esp32c3 interrupt controller driver to handle ISR diff --git a/drivers/interrupt_controller/Kconfig.mtk_adsp b/drivers/interrupt_controller/Kconfig.mtk_adsp new file mode 100644 index 0000000000000..0c8875973e8ad --- /dev/null +++ b/drivers/interrupt_controller/Kconfig.mtk_adsp @@ -0,0 +1,9 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +config INTC_MTK_ADSP + bool "MediaTek Audio DSP Interrupt Controller" + help + Very simple cascaded interrupt controller consisting of two + bitfield registers (status and enable) and one mask value + defining valid interrupts. diff --git a/drivers/interrupt_controller/intc_cavs.c b/drivers/interrupt_controller/intc_cavs.c index 47e4940e13977..38e22c233e817 100644 --- a/drivers/interrupt_controller/intc_cavs.c +++ b/drivers/interrupt_controller/intc_cavs.c @@ -8,9 +8,11 @@ #include #include +#include #include #include #include +#include #include "intc_cavs.h" #if defined(CONFIG_SMP) && (CONFIG_MP_MAX_NUM_CPUS > 1) @@ -150,6 +152,10 @@ static const struct irq_next_level_api cavs_apis = { IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), \ cavs_ictl_isr, DEVICE_DT_INST_GET(n), \ DT_INST_IRQ(n, sense)); \ - } + } \ + IRQ_PARENT_ENTRY_DEFINE( \ + intc_cavs_##n, DEVICE_DT_INST_GET(n), DT_INST_IRQN(n), \ + INTC_INST_ISR_TBL_OFFSET(n), \ + DT_INST_INTC_GET_AGGREGATOR_LEVEL(n)); DT_INST_FOREACH_STATUS_OKAY(CAVS_ICTL_INIT) diff --git a/drivers/interrupt_controller/intc_dw.c b/drivers/interrupt_controller/intc_dw.c index 3d221b50370ca..1abee2e514eaf 100644 --- a/drivers/interrupt_controller/intc_dw.c +++ b/drivers/interrupt_controller/intc_dw.c @@ -14,7 +14,9 @@ */ #include +#include #include +#include #include "intc_dw.h" #include #include @@ -156,3 +158,6 @@ static void dw_ictl_config_irq(const struct device *port) DEVICE_DT_INST_GET(0), DT_INST_IRQ(0, sense)); } + +IRQ_PARENT_ENTRY_DEFINE(intc_dw, DEVICE_DT_INST_GET(0), DT_INST_IRQN(0), + INTC_INST_ISR_TBL_OFFSET(0), DT_INST_INTC_GET_AGGREGATOR_LEVEL(0)); diff --git a/drivers/interrupt_controller/intc_dw_ace.c b/drivers/interrupt_controller/intc_dw_ace.c index 9bda4bddcfa4b..40f61a69e4e6a 100644 --- a/drivers/interrupt_controller/intc_dw_ace.c +++ b/drivers/interrupt_controller/intc_dw_ace.c @@ -4,13 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ +#define DT_DRV_COMPAT intel_ace_intc + #include #include +#include #include #include -#ifdef CONFIG_DYNAMIC_INTERRUPTS #include -#endif #include #include #include @@ -68,7 +69,7 @@ * ACE_INTC[core_id].irq_inten_l |= interrupt_bit; */ -#define ACE_INTC ((volatile struct dw_ictl_registers *)DT_REG_ADDR(DT_NODELABEL(ace_intc))) +#define ACE_INTC ((volatile struct dw_ictl_registers *)DT_INST_REG_ADDR(0)) static inline bool is_dw_irq(uint32_t irq) { @@ -175,6 +176,10 @@ static const struct dw_ace_v1_ictl_driver_api dw_ictl_ace_v1x_apis = { #endif }; -DEVICE_DT_DEFINE(DT_NODELABEL(ace_intc), dw_ace_init, NULL, NULL, NULL, +DEVICE_DT_INST_DEFINE(0, dw_ace_init, NULL, NULL, NULL, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, &dw_ictl_ace_v1x_apis); + +IRQ_PARENT_ENTRY_DEFINE(ace_intc, DEVICE_DT_INST_GET(0), DT_INST_IRQN(0), + INTC_BASE_ISR_TBL_OFFSET(DT_DRV_INST(0)), + DT_INST_INTC_GET_AGGREGATOR_LEVEL(0)); diff --git a/drivers/interrupt_controller/intc_esp32c3.c b/drivers/interrupt_controller/intc_esp32c3.c index 6293afd07f123..575254ecdfae7 100644 --- a/drivers/interrupt_controller/intc_esp32c3.c +++ b/drivers/interrupt_controller/intc_esp32c3.c @@ -41,7 +41,34 @@ LOG_MODULE_REGISTER(intc_esp32c3, CONFIG_LOG_DEFAULT_LEVEL); #define ESP32C3_INTC_SRCS_PER_IRQ 2 #define ESP32C3_INTC_AVAILABLE_IRQS 30 -static uint32_t esp_intr_enabled_mask[2] = {0, 0}; +#if defined(CONFIG_SOC_SERIES_ESP32C6) + +#define IRQ_NA 0xFF /* IRQ not available */ +#define IRQ_FREE 0xFE + +#define ESP32C6_INTC_SRCS_PER_IRQ 2 +#define ESP32C6_INTC_AVAILABLE_IRQS 31 + +/* For ESP32C6 only CPU peripheral interrupts number + * 1, 2, 5, 6, 8 ~ 31 are available. + * IRQ 31 is reserved for disabled interrupts + */ +static uint8_t esp_intr_irq_alloc[ESP32C6_INTC_AVAILABLE_IRQS][ESP32C6_INTC_SRCS_PER_IRQ] = { + [0] = {IRQ_NA, IRQ_NA}, + [3] = {IRQ_NA, IRQ_NA}, + [4] = {IRQ_NA, IRQ_NA}, + [7] = {IRQ_NA, IRQ_NA}, + [1 ... 2] = {IRQ_FREE, IRQ_FREE}, + [5 ... 6] = {IRQ_FREE, IRQ_FREE}, + [8 ... 30] = {IRQ_FREE, IRQ_FREE} +}; +#endif + +#define STATUS_MASK_NUM 3 + +static uint32_t esp_intr_enabled_mask[STATUS_MASK_NUM] = {0, 0, 0}; + +#if defined(CONFIG_SOC_SERIES_ESP32C3) static uint32_t esp_intr_find_irq_for_source(uint32_t source) { @@ -62,6 +89,33 @@ static uint32_t esp_intr_find_irq_for_source(uint32_t source) return irq; } +#elif defined(CONFIG_SOC_SERIES_ESP32C6) + +static uint32_t esp_intr_find_irq_for_source(uint32_t source) +{ + uint32_t irq = 0; + + /* First allocate one source per IRQ, then two + * if there are more sources than free IRQs + */ + for (int j = 0; j < ESP32C6_INTC_SRCS_PER_IRQ; j++) { + for (int i = 0; i < ESP32C6_INTC_AVAILABLE_IRQS; i++) { + if (esp_intr_irq_alloc[i][j] == IRQ_FREE) { + esp_intr_irq_alloc[i][j] = (uint8_t)source; + irq = i; + goto found; + } + } + } + +found: + INTC_LOG("Found IRQ: %d for source: %d", irq, source); + + return irq; +} + +#endif + void esp_intr_initialize(void) { /* IRQ 31 is reserved for disabled interrupts, @@ -75,6 +129,18 @@ void esp_intr_initialize(void) esp_rom_intr_matrix_set(0, i, ESP32C3_INTC_DISABLED_SLOT); } +#if defined(CONFIG_SOC_SERIES_ESP32C6) + /* Clear up IRQ allocation */ + for (int j = 0; j < ESP32C6_INTC_SRCS_PER_IRQ; j++) { + for (int i = 0; i < ESP32C6_INTC_AVAILABLE_IRQS; i++) { + /* screen out reserved IRQs */ + if (esp_intr_irq_alloc[i][j] != IRQ_NA) { + esp_intr_irq_alloc[i][j] = IRQ_FREE; + } + } + } +#endif + /* set global esp32c3's INTC masking level */ esprv_intc_int_set_threshold(ESP32C3_INTC_DEFAULT_THRESHOLD); } @@ -106,12 +172,14 @@ int esp_intr_alloc(int source, if (source < 32) { esp_intr_enabled_mask[0] |= (1 << source); - } else { + } else if (source < 64) { esp_intr_enabled_mask[1] |= (1 << (source - 32)); + } else if (source < 96) { + esp_intr_enabled_mask[2] |= (1 << (source - 64)); } - INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X", - esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]); + INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X", + esp_intr_enabled_mask[0], esp_intr_enabled_mask[1], esp_intr_enabled_mask[2]); irq_unlock(key); irq_enable(source); @@ -131,14 +199,28 @@ int esp_intr_disable(int source) source, ESP32C3_INTC_DISABLED_SLOT); +#if defined(CONFIG_SOC_SERIES_ESP32C6) + for (int j = 0; j < ESP32C6_INTC_SRCS_PER_IRQ; j++) { + for (int i = 0; i < ESP32C6_INTC_AVAILABLE_IRQS; i++) { + if (esp_intr_irq_alloc[i][j] == source) { + esp_intr_irq_alloc[i][j] = IRQ_FREE; + goto freed; + } + } + } +freed: +#endif + if (source < 32) { esp_intr_enabled_mask[0] &= ~(1 << source); - } else { + } else if (source < 64) { esp_intr_enabled_mask[1] &= ~(1 << (source - 32)); + } else if (source < 96) { + esp_intr_enabled_mask[2] &= ~(1 << (source - 64)); } - INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X", - esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]); + INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X", + esp_intr_enabled_mask[0], esp_intr_enabled_mask[1], esp_intr_enabled_mask[2]); irq_unlock(key); @@ -158,12 +240,14 @@ int esp_intr_enable(int source) if (source < 32) { esp_intr_enabled_mask[0] |= (1 << source); - } else { + } else if (source < 64) { esp_intr_enabled_mask[1] |= (1 << (source - 32)); + } else if (source < 96) { + esp_intr_enabled_mask[2] |= (1 << (source - 64)); } - INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X", - esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]); + INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X", + esp_intr_enabled_mask[0], esp_intr_enabled_mask[1], esp_intr_enabled_mask[2]); esprv_intc_int_set_priority(irq, ESP32C3_INTC_DEFAULT_PRIO); esprv_intc_int_set_type(irq, INTR_TYPE_LEVEL); @@ -176,12 +260,12 @@ int esp_intr_enable(int source) uint32_t esp_intr_get_enabled_intmask(int status_mask_number) { - INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X", - esp_intr_enabled_mask[0], esp_intr_enabled_mask[1]); + INTC_LOG("Enabled ISRs -- 0: 0x%X -- 1: 0x%X -- 2: 0x%X", + esp_intr_enabled_mask[0], esp_intr_enabled_mask[1], esp_intr_enabled_mask[2]); - if (status_mask_number == 0) { - return esp_intr_enabled_mask[0]; + if (status_mask_number < STATUS_MASK_NUM) { + return esp_intr_enabled_mask[status_mask_number]; } else { - return esp_intr_enabled_mask[1]; + return 0; /* error */ } } diff --git a/drivers/interrupt_controller/intc_loapic.c b/drivers/interrupt_controller/intc_loapic.c index c7faaa39cdb0a..5d6aa8537f340 100644 --- a/drivers/interrupt_controller/intc_loapic.c +++ b/drivers/interrupt_controller/intc_loapic.c @@ -200,7 +200,7 @@ uint32_t z_loapic_irq_base(void) * * This associates an IRQ with the desired vector in the IDT. */ -__boot_func +__pinned_func void z_loapic_int_vec_set(unsigned int irq, /* IRQ number of the interrupt */ unsigned int vector /* vector to copy into the LVT */ ) diff --git a/drivers/interrupt_controller/intc_mtk_adsp.c b/drivers/interrupt_controller/intc_mtk_adsp.c new file mode 100644 index 0000000000000..b562c9b501b7a --- /dev/null +++ b/drivers/interrupt_controller/intc_mtk_adsp.c @@ -0,0 +1,82 @@ +/* Copyright 2023 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +#define DT_DRV_COMPAT mediatek_adsp_intc + +struct intc_mtk_cfg { + uint32_t xtensa_irq; + uint32_t irq_mask; + uint32_t sw_isr_off; + volatile uint32_t *enable_reg; + volatile uint32_t *status_reg; +}; + +bool intc_mtk_adsp_get_enable(const struct device *dev, int irq) +{ + const struct intc_mtk_cfg *cfg = dev->config; + + return (*cfg->enable_reg | (BIT(irq) & cfg->irq_mask)) != 0; +} + +void intc_mtk_adsp_set_enable(const struct device *dev, int irq, bool val) +{ + const struct intc_mtk_cfg *cfg = dev->config; + + irq_enable(cfg->xtensa_irq); + + if ((BIT(irq) & cfg->irq_mask) != 0) { + if (val) { + *cfg->enable_reg |= BIT(irq); + } else { + *cfg->enable_reg &= ~BIT(irq); + } + } +} + +static void intc_isr(const void *arg) +{ + const struct intc_mtk_cfg *cfg = ((struct device *)arg)->config; + uint32_t irqs = *cfg->status_reg & cfg->irq_mask; + + while (irqs != 0) { + uint32_t irq = find_msb_set(irqs) - 1; + uint32_t off = cfg->sw_isr_off + irq; + + _sw_isr_table[off].isr(_sw_isr_table[off].arg); + irqs &= ~BIT(irq); + } +} + +static void dev_init(const struct device *dev) +{ + const struct intc_mtk_cfg *cfg = dev->config; + + *cfg->enable_reg = 0; + irq_enable(cfg->xtensa_irq); +} + +#define DEV_INIT(N) \ + IRQ_CONNECT(DT_INST_IRQN(N), 0, intc_isr, DEVICE_DT_INST_GET(N), 0); \ + dev_init(DEVICE_DT_INST_GET(N)); + +static int intc_init(void) +{ + DT_INST_FOREACH_STATUS_OKAY(DEV_INIT); + return 0; +} + +SYS_INIT(intc_init, PRE_KERNEL_1, 0); + +#define DEF_DEV(N) \ +static const struct intc_mtk_cfg dev_cfg##N = { \ + .xtensa_irq = DT_INST_IRQN(N), \ + .irq_mask = DT_INST_PROP(N, mask), \ + .sw_isr_off = (N + 1) * 32, \ + .enable_reg = (void *)DT_INST_REG_ADDR(N), \ + .status_reg = (void *)DT_INST_PROP(N, status_reg) }; \ +DEVICE_DT_INST_DEFINE(N, NULL, NULL, NULL, &dev_cfg##N, PRE_KERNEL_1, 0, NULL); + +DT_INST_FOREACH_STATUS_OKAY(DEF_DEV); diff --git a/drivers/interrupt_controller/intc_nxp_irqsteer.c b/drivers/interrupt_controller/intc_nxp_irqsteer.c index cd06b23854acf..41157f08cde04 100644 --- a/drivers/interrupt_controller/intc_nxp_irqsteer.c +++ b/drivers/interrupt_controller/intc_nxp_irqsteer.c @@ -223,9 +223,11 @@ */ #include +#include #include #include #include +#include #include "sw_isr_common.h" @@ -478,3 +480,10 @@ DEVICE_DT_INST_DEFINE(0, NULL, &irqsteer_config, PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY, NULL); + +#define NXP_IRQSTEER_MASTER_IRQ_ENTRY_DEF(node_id) \ + IRQ_PARENT_ENTRY_DEFINE(CONCAT(nxp_irqsteer_master_, DT_NODE_CHILD_IDX(node_id)), NULL, \ + DT_IRQN(node_id), INTC_CHILD_ISR_TBL_OFFSET(node_id), \ + DT_INTC_GET_AGGREGATOR_LEVEL(node_id)); + +DT_INST_FOREACH_CHILD_STATUS_OKAY(0, NXP_IRQSTEER_MASTER_IRQ_ENTRY_DEF); diff --git a/drivers/interrupt_controller/intc_plic.c b/drivers/interrupt_controller/intc_plic.c index f5f762e4aba9d..144e448a04d4a 100644 --- a/drivers/interrupt_controller/intc_plic.c +++ b/drivers/interrupt_controller/intc_plic.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -75,6 +76,7 @@ struct plic_config { uint32_t max_prio; uint32_t num_irqs; riscv_plic_irq_config_func_t irq_config_func; + struct _isr_table_entry *isr_table; }; struct plic_stats { @@ -366,15 +368,8 @@ static void plic_irq_handler(const struct device *dev) } #endif - const uint32_t parent_irq = COND_CODE_1(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS), - (z_get_sw_isr_irq_from_device(dev)), (0U)); - const uint32_t irq = irq_to_level_2(local_irq) | parent_irq; - const unsigned int isr_offset = - COND_CODE_1(IS_ENABLED(CONFIG_DYNAMIC_INTERRUPTS), (z_get_sw_isr_table_idx(irq)), - (irq_from_level_2(irq) + CONFIG_2ND_LVL_ISR_TBL_OFFSET)); - /* Call the corresponding IRQ handler in _sw_isr_table */ - ite = (struct _isr_table_entry *)&_sw_isr_table[isr_offset]; + ite = &config->isr_table[local_irq]; ite->isr(ite->arg); /* @@ -572,10 +567,15 @@ SHELL_CMD_ARG_REGISTER(plic, &plic_cmds, "PLIC shell commands", .max_prio = DT_INST_PROP(n, riscv_max_priority), \ .num_irqs = DT_INST_PROP(n, riscv_ndev), \ .irq_config_func = plic_irq_config_func_##n, \ + .isr_table = &_sw_isr_table[INTC_INST_ISR_TBL_OFFSET(n)], \ }; \ PLIC_INTC_IRQ_FUNC_DEFINE(n) #define PLIC_INTC_DEVICE_INIT(n) \ + IRQ_PARENT_ENTRY_DEFINE( \ + plic##n, DEVICE_DT_INST_GET(n), DT_INST_IRQN(n), \ + INTC_INST_ISR_TBL_OFFSET(n), \ + DT_INST_INTC_GET_AGGREGATOR_LEVEL(n)); \ PLIC_INTC_CONFIG_INIT(n) \ PLIC_INTC_DATA_INIT(n) \ DEVICE_DT_INST_DEFINE(n, &plic_init, NULL, \ diff --git a/drivers/interrupt_controller/intc_rv32m1_intmux.c b/drivers/interrupt_controller/intc_rv32m1_intmux.c index b9b10c042112e..f5af9f70e7ebc 100644 --- a/drivers/interrupt_controller/intc_rv32m1_intmux.c +++ b/drivers/interrupt_controller/intc_rv32m1_intmux.c @@ -23,6 +23,7 @@ */ #include +#include #include #include #include @@ -218,3 +219,10 @@ static int rv32m1_intmux_init(const struct device *dev) DEVICE_DT_INST_DEFINE(0, &rv32m1_intmux_init, NULL, NULL, &rv32m1_intmux_cfg, PRE_KERNEL_1, CONFIG_RV32M1_INTMUX_INIT_PRIORITY, &rv32m1_intmux_apis); + +#define INTC_CHILD_IRQ_ENTRY_DEF(node_id) \ + IRQ_PARENT_ENTRY_DEFINE(CONCAT(DT_DRV_COMPAT, _child_, DT_NODE_CHILD_IDX(node_id)), NULL, \ + DT_IRQN(node_id), INTC_CHILD_ISR_TBL_OFFSET(node_id), \ + DT_INTC_GET_AGGREGATOR_LEVEL(node_id)); + +DT_INST_FOREACH_CHILD_STATUS_OKAY(0, INTC_CHILD_IRQ_ENTRY_DEF); diff --git a/drivers/interrupt_controller/intc_system_apic.c b/drivers/interrupt_controller/intc_system_apic.c index b9ad0b70bbfa5..6089e453405d6 100644 --- a/drivers/interrupt_controller/intc_system_apic.c +++ b/drivers/interrupt_controller/intc_system_apic.c @@ -19,7 +19,7 @@ #include #include -#define IS_IOAPIC_IRQ(irq) (irq < z_loapic_irq_base()) +#define IS_IOAPIC_IRQ(irq) ((irq) < z_loapic_irq_base()) #define HARDWARE_IRQ_LIMIT ((z_loapic_irq_base() + LOAPIC_IRQ_COUNT) - 1) /** diff --git a/drivers/interrupt_controller/intc_vexriscv_litex.c b/drivers/interrupt_controller/intc_vexriscv_litex.c index 2d5d2233ab2e3..0356e848d22c6 100644 --- a/drivers/interrupt_controller/intc_vexriscv_litex.c +++ b/drivers/interrupt_controller/intc_vexriscv_litex.c @@ -4,7 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT vexriscv_intc0 +#define DT_DRV_COMPAT litex_vexriscv_intc0 #include #include diff --git a/drivers/ipm/Kconfig.imx b/drivers/ipm/Kconfig.imx index 67fbc370ac860..743c7d9c6a55d 100644 --- a/drivers/ipm/Kconfig.imx +++ b/drivers/ipm/Kconfig.imx @@ -5,6 +5,7 @@ config IPM_MCUX bool "MCUX IPM driver" default y depends on DT_HAS_NXP_LPC_MAILBOX_ENABLED + select RESET help Driver for MCUX mailbox diff --git a/drivers/ipm/ipm_handlers.c b/drivers/ipm/ipm_handlers.c index 259644ae8d0e6..f049a090f1ee6 100644 --- a/drivers/ipm/ipm_handlers.c +++ b/drivers/ipm/ipm_handlers.c @@ -16,25 +16,25 @@ static inline int z_vrfy_ipm_send(const struct device *dev, int wait, return z_impl_ipm_send((const struct device *)dev, wait, id, (const void *)data, size); } -#include +#include static inline int z_vrfy_ipm_max_data_size_get(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_IPM(dev, max_data_size_get)); return z_impl_ipm_max_data_size_get((const struct device *)dev); } -#include +#include static inline uint32_t z_vrfy_ipm_max_id_val_get(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_IPM(dev, max_id_val_get)); return z_impl_ipm_max_id_val_get((const struct device *)dev); } -#include +#include static inline int z_vrfy_ipm_set_enabled(const struct device *dev, int enable) { K_OOPS(K_SYSCALL_DRIVER_IPM(dev, set_enabled)); return z_impl_ipm_set_enabled((const struct device *)dev, enable); } -#include +#include diff --git a/drivers/ipm/ipm_mcux.c b/drivers/ipm/ipm_mcux.c index 2365f58aacc29..e323dc9ec786e 100644 --- a/drivers/ipm/ipm_mcux.c +++ b/drivers/ipm/ipm_mcux.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #define MCUX_IPM_DATA_REGS 1 #define MCUX_IPM_MAX_ID_VAL 0 @@ -36,9 +38,12 @@ #endif #endif +#define MAILBOX_USES_RESET COND_CODE_1(DT_ANY_INST_HAS_PROP_STATUS_OKAY(resets), (true), (false)) + struct mcux_mailbox_config { MAILBOX_Type *base; void (*irq_config_func)(const struct device *dev); + const struct reset_dt_spec reset; }; struct mcux_mailbox_data { @@ -143,10 +148,34 @@ static int mcux_mailbox_ipm_set_enabled(const struct device *d, int enable) return 0; } +static inline int mcux_mailbox_reset(const struct device *dev) +{ + const struct mcux_mailbox_config *config = dev->config; + int ret = 0; + + /* on some platforms, explicit reset is not needed or possible for the mailbox */ + if (!MAILBOX_USES_RESET) { + return 0; + } + + if (!device_is_ready(config->reset.dev)) { + ret = -ENODEV; + } else { + ret = reset_line_toggle(config->reset.dev, config->reset.id); + } + + return ret; +} static int mcux_mailbox_init(const struct device *dev) { const struct mcux_mailbox_config *config = dev->config; + int ret = 0; + + ret = mcux_mailbox_reset(dev); + if (ret) { + return ret; + } MAILBOX_Init(config->base); config->irq_config_func(dev); @@ -169,6 +198,7 @@ static void mcux_mailbox_config_func_0(const struct device *dev); static const struct mcux_mailbox_config mcux_mailbox_0_config = { .base = (MAILBOX_Type *)DT_INST_REG_ADDR(0), .irq_config_func = mcux_mailbox_config_func_0, + .reset = RESET_DT_SPEC_INST_GET_OR(0, {0}), }; static struct mcux_mailbox_data mcux_mailbox_0_data; diff --git a/drivers/kscan/kscan_handlers.c b/drivers/kscan/kscan_handlers.c index 98809687430a8..81c97c19d04f7 100644 --- a/drivers/kscan/kscan_handlers.c +++ b/drivers/kscan/kscan_handlers.c @@ -15,7 +15,7 @@ static inline int z_vrfy_kscan_config(const struct device *dev, "callback cannot be set from user mode")); return z_impl_kscan_config((const struct device *)dev, callback_isr); } -#include +#include static inline int z_vrfy_kscan_disable_callback(const struct device *dev) { @@ -23,7 +23,7 @@ static inline int z_vrfy_kscan_disable_callback(const struct device *dev) return z_impl_kscan_disable_callback((const struct device *)dev); } -#include +#include static int z_vrfy_kscan_enable_callback(const struct device *dev) { @@ -31,4 +31,4 @@ static int z_vrfy_kscan_enable_callback(const struct device *dev) return z_impl_kscan_enable_callback((const struct device *)dev); } -#include +#include diff --git a/drivers/led/CMakeLists.txt b/drivers/led/CMakeLists.txt index c3d90d0ba06ff..09ea5e202fdf5 100644 --- a/drivers/led/CMakeLists.txt +++ b/drivers/led/CMakeLists.txt @@ -18,6 +18,7 @@ zephyr_library_sources_ifdef(CONFIG_NCP5623 ncp5623.c) zephyr_library_sources_ifdef(CONFIG_PCA9633 pca9633.c) zephyr_library_sources_ifdef(CONFIG_TLC59108 tlc59108.c) zephyr_library_sources_ifdef(CONFIG_IS31FL3733 is31fl3733.c) +zephyr_library_sources_ifdef(CONFIG_IS31FL3194 is31fl3194.c) zephyr_library_sources_ifdef(CONFIG_LED_SHELL led_shell.c) diff --git a/drivers/led/Kconfig b/drivers/led/Kconfig index 7808a1013ae9c..26bf49cd5e2ae 100644 --- a/drivers/led/Kconfig +++ b/drivers/led/Kconfig @@ -40,5 +40,6 @@ source "drivers/led/Kconfig.pwm" source "drivers/led/Kconfig.tlc59108" source "drivers/led/Kconfig.xec" source "drivers/led/Kconfig.is31fl3733" +source "drivers/led/Kconfig.is31fl3194" endif # LED diff --git a/drivers/led/Kconfig.is31fl3194 b/drivers/led/Kconfig.is31fl3194 new file mode 100644 index 0000000000000..42166805a1d16 --- /dev/null +++ b/drivers/led/Kconfig.is31fl3194 @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Arduino SA +# SPDX-License-Identifier: Apache-2.0 + +config IS31FL3194 + bool "IS31FL3194 LED driver" + default y + depends on DT_HAS_ISSI_IS31FL3194_ENABLED + select I2C + help + Enable LED driver for Lumissil Microsystems (a division of ISSI) + IS31FL3194. This chip supports one RGB LED or 3 independent LEDs. diff --git a/drivers/led/is31fl3194.c b/drivers/led/is31fl3194.c new file mode 100644 index 0000000000000..5b0c34ebf571c --- /dev/null +++ b/drivers/led/is31fl3194.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT issi_is31fl3194 + +/** + * @file + * @brief IS31FL3194 LED driver + * + * The IS31FL3194 is a 3-channel LED driver that communicates over I2C. + */ + +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(is31fl3194, CONFIG_LED_LOG_LEVEL); + +#define IS31FL3194_PROD_ID_REG 0x00 +#define IS31FL3194_CONF_REG 0x01 +#define IS31FL3194_CURRENT_REG 0x03 +#define IS31FL3194_OUT1_REG 0x10 +#define IS31FL3194_OUT2_REG 0x21 +#define IS31FL3194_OUT3_REG 0x32 +#define IS31FL3194_UPDATE_REG 0x40 + +#define IS31FL3194_PROD_ID_VAL 0xce +#define IS31FL3194_CONF_ENABLE 0x01 +#define IS31FL3194_UPDATE_VAL 0xc5 + +#define IS31FL3194_CHANNEL_COUNT 3 + +static const uint8_t led_channels[] = { + IS31FL3194_OUT1_REG, + IS31FL3194_OUT2_REG, + IS31FL3194_OUT3_REG +}; + +struct is31fl3194_config { + struct i2c_dt_spec bus; + uint8_t num_leds; + const struct led_info *led_infos; + const uint8_t *current_limits; +}; + +static const struct led_info *is31fl3194_led_to_info(const struct is31fl3194_config *config, + uint32_t led) +{ + if (led < config->num_leds) { + return &config->led_infos[led]; + } + + return NULL; +} + +static int is31fl3194_get_info(const struct device *dev, + uint32_t led, + const struct led_info **info_out) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = is31fl3194_led_to_info(config, led); + + if (info == NULL) { + return -EINVAL; + } + + *info_out = info; + return 0; +} + +static int is31fl3194_set_color(const struct device *dev, uint32_t led, uint8_t num_colors, + const uint8_t *color) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = is31fl3194_led_to_info(config, led); + int ret; + + if (info == NULL) { + return -ENODEV; + } + + if (info->num_colors != 3) { + return -ENOTSUP; + } + + if (num_colors != 3) { + return -EINVAL; + } + + for (int i = 0; i < 3; i++) { + uint8_t value; + + switch (info->color_mapping[i]) { + case LED_COLOR_ID_RED: + value = color[0]; + break; + case LED_COLOR_ID_GREEN: + value = color[1]; + break; + case LED_COLOR_ID_BLUE: + value = color[2]; + break; + default: + /* unreachable: mapping already tested in is31fl3194_check_config */ + continue; + } + + ret = i2c_reg_write_byte_dt(&config->bus, led_channels[i], value); + if (ret != 0) { + break; + } + } + + if (ret == 0) { + ret = i2c_reg_write_byte_dt(&config->bus, + IS31FL3194_UPDATE_REG, + IS31FL3194_UPDATE_VAL); + } + + if (ret != 0) { + LOG_ERR("%s: LED write failed: %d", dev->name, ret); + } + + return ret; +} + +static int is31fl3194_set_brightness(const struct device *dev, uint32_t led, uint8_t value) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = is31fl3194_led_to_info(config, led); + int ret = 0; + + if (info == NULL) { + return -ENODEV; + } + + if (info->num_colors != 1) { + return -ENOTSUP; + } + + if (value > 100) { + return -EINVAL; + } + + /* Rescale 0..100 to 0..255 */ + value = value * 255 / 100; + + ret = i2c_reg_write_byte_dt(&config->bus, led_channels[led], value); + if (ret == 0) { + ret = i2c_reg_write_byte_dt(&config->bus, + IS31FL3194_UPDATE_REG, + IS31FL3194_UPDATE_VAL); + } + + if (ret != 0) { + LOG_ERR("%s: LED write failed", dev->name); + } + + return ret; +} + +static inline int is31fl3194_led_on(const struct device *dev, uint32_t led) +{ + return is31fl3194_set_brightness(dev, led, 100); +} + +static inline int is31fl3194_led_off(const struct device *dev, uint32_t led) +{ + return is31fl3194_set_brightness(dev, led, 0); +} + +/* + * Counts red, green, blue channels; returns true if color_id is valid + * and no more than one channel maps to the same color + */ +static bool is31fl3194_count_colors(const struct device *dev, + uint8_t color_id, uint8_t *rgb_counts) +{ + bool ret = false; + + switch (color_id) { + case LED_COLOR_ID_RED: + ret = (++rgb_counts[0] == 1); + break; + case LED_COLOR_ID_GREEN: + ret = (++rgb_counts[1] == 1); + break; + case LED_COLOR_ID_BLUE: + ret = (++rgb_counts[2] == 1); + break; + } + + if (!ret) { + LOG_ERR("%s: invalid color %d (duplicate or not RGB)", + dev->name, color_id); + } + + return ret; +} + +static int is31fl3194_check_config(const struct device *dev) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info; + uint8_t rgb_counts[3] = { 0 }; + uint8_t i; + + switch (config->num_leds) { + case 1: + /* check that it is a three-channel LED */ + info = &config->led_infos[0]; + + if (info->num_colors != 3) { + LOG_ERR("%s: invalid number of colors %d " + "(must be 3 for RGB LED)", + dev->name, info->num_colors); + return -EINVAL; + } + + for (i = 0; i < 3; i++) { + if (!is31fl3194_count_colors(dev, info->color_mapping[i], rgb_counts)) { + return -EINVAL; + } + + } + break; + case 3: + /* check that each LED is single-color */ + for (i = 0; i < 3; i++) { + info = &config->led_infos[i]; + + if (info->num_colors != 1) { + LOG_ERR("%s: invalid number of colors %d " + "(must be 1 when defining multiple LEDs)", + dev->name, info->num_colors); + return -EINVAL; + } + + if (!is31fl3194_count_colors(dev, info->color_mapping[0], rgb_counts)) { + return -EINVAL; + } + } + break; + default: + LOG_ERR("%s: invalid number of LEDs %d (must be 1 or 3)", + dev->name, config->num_leds); + return -EINVAL; + } + + return 0; +} + +static int is31fl3194_init(const struct device *dev) +{ + const struct is31fl3194_config *config = dev->config; + const struct led_info *info = NULL; + int i, ret; + uint8_t prod_id, band; + uint8_t current_reg = 0; + + ret = is31fl3194_check_config(dev); + if (ret != 0) { + return ret; + } + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("%s: I2C device not ready", dev->name); + return -ENODEV; + } + + ret = i2c_reg_read_byte_dt(&config->bus, IS31FL3194_PROD_ID_REG, &prod_id); + if (ret != 0) { + LOG_ERR("%s: failed to read product ID", dev->name); + return ret; + } + + if (prod_id != IS31FL3194_PROD_ID_VAL) { + LOG_ERR("%s: invalid product ID 0x%02x (expected 0x%02x)", dev->name, prod_id, + IS31FL3194_PROD_ID_VAL); + return -ENODEV; + } + + /* calc current limit register value */ + info = &config->led_infos[0]; + if (info->num_colors == IS31FL3194_CHANNEL_COUNT) { + /* one RGB LED: set all channels to the same current limit */ + band = (config->current_limits[0] / 10) - 1; + for (i = 0; i < IS31FL3194_CHANNEL_COUNT; i++) { + current_reg |= band << (2 * i); + } + } else { + /* single-channel LEDs: independent limits */ + for (i = 0; i < config->num_leds; i++) { + band = (config->current_limits[i] / 10) - 1; + current_reg |= band << (2 * i); + } + } + + ret = i2c_reg_write_byte_dt(&config->bus, IS31FL3194_CURRENT_REG, current_reg); + if (ret != 0) { + LOG_ERR("%s: failed to set current limit", dev->name); + return ret; + } + + /* enable device */ + return i2c_reg_write_byte_dt(&config->bus, IS31FL3194_CONF_REG, IS31FL3194_CONF_ENABLE); +} + +static const struct led_driver_api is31fl3194_led_api = { + .set_brightness = is31fl3194_set_brightness, + .on = is31fl3194_led_on, + .off = is31fl3194_led_off, + .get_info = is31fl3194_get_info, + .set_color = is31fl3194_set_color, +}; + +#define COLOR_MAPPING(led_node_id) \ + static const uint8_t color_mapping_##led_node_id[] = \ + DT_PROP(led_node_id, color_mapping); + +#define LED_INFO(led_node_id) \ + { \ + .label = DT_PROP(led_node_id, label), \ + .num_colors = DT_PROP_LEN(led_node_id, color_mapping), \ + .color_mapping = color_mapping_##led_node_id, \ + }, + +#define LED_CURRENT(led_node_id) \ + DT_PROP(led_node_id, current_limit), + +#define IS31FL3194_DEFINE(id) \ + \ + DT_INST_FOREACH_CHILD(id, COLOR_MAPPING) \ + \ + static const struct led_info is31fl3194_leds_##id[] = \ + { DT_INST_FOREACH_CHILD(id, LED_INFO) }; \ + static const uint8_t is31fl3194_currents_##id[] = \ + { DT_INST_FOREACH_CHILD(id, LED_CURRENT) }; \ + BUILD_ASSERT(ARRAY_SIZE(is31fl3194_leds_##id) > 0, \ + "No LEDs defined for " #id); \ + \ + static const struct is31fl3194_config is31fl3194_config_##id = { \ + .bus = I2C_DT_SPEC_INST_GET(id), \ + .num_leds = ARRAY_SIZE(is31fl3194_leds_##id), \ + .led_infos = is31fl3194_leds_##id, \ + .current_limits = is31fl3194_currents_##id, \ + }; \ + DEVICE_DT_INST_DEFINE(id, &is31fl3194_init, NULL, NULL, \ + &is31fl3194_config_##id, POST_KERNEL, \ + CONFIG_LED_INIT_PRIORITY, &is31fl3194_led_api); + +DT_INST_FOREACH_STATUS_OKAY(IS31FL3194_DEFINE) diff --git a/drivers/led/led_handlers.c b/drivers/led/led_handlers.c index a089846e6951e..5fde5e53c1b0d 100644 --- a/drivers/led/led_handlers.c +++ b/drivers/led/led_handlers.c @@ -14,7 +14,7 @@ static inline int z_vrfy_led_blink(const struct device *dev, uint32_t led, return z_impl_led_blink((const struct device *)dev, led, delay_on, delay_off); } -#include +#include static inline int z_vrfy_led_get_info(const struct device *dev, uint32_t led, const struct led_info **info) @@ -23,7 +23,7 @@ static inline int z_vrfy_led_get_info(const struct device *dev, uint32_t led, K_OOPS(K_SYSCALL_MEMORY_WRITE(info, sizeof(*info))); return z_impl_led_get_info(dev, led, info); } -#include +#include static inline int z_vrfy_led_set_brightness(const struct device *dev, uint32_t led, @@ -33,7 +33,7 @@ static inline int z_vrfy_led_set_brightness(const struct device *dev, return z_impl_led_set_brightness((const struct device *)dev, led, value); } -#include +#include static inline int z_vrfy_led_write_channels(const struct device *dev, uint32_t start_channel, @@ -43,7 +43,7 @@ z_vrfy_led_write_channels(const struct device *dev, uint32_t start_channel, K_OOPS(K_SYSCALL_MEMORY_READ(buf, num_channels)); return z_impl_led_write_channels(dev, start_channel, num_channels, buf); } -#include +#include static inline int z_vrfy_led_set_channel(const struct device *dev, uint32_t channel, uint8_t value) @@ -51,7 +51,7 @@ static inline int z_vrfy_led_set_channel(const struct device *dev, K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_LED)); return z_impl_led_set_channel(dev, channel, value); } -#include +#include static inline int z_vrfy_led_set_color(const struct device *dev, uint32_t led, uint8_t num_colors, const uint8_t *color) @@ -60,18 +60,18 @@ static inline int z_vrfy_led_set_color(const struct device *dev, uint32_t led, K_OOPS(K_SYSCALL_MEMORY_READ(color, num_colors)); return z_impl_led_set_color(dev, led, num_colors, color); } -#include +#include static inline int z_vrfy_led_on(const struct device *dev, uint32_t led) { K_OOPS(K_SYSCALL_DRIVER_LED(dev, on)); return z_impl_led_on((const struct device *)dev, led); } -#include +#include static inline int z_vrfy_led_off(const struct device *dev, uint32_t led) { K_OOPS(K_SYSCALL_DRIVER_LED(dev, off)); return z_impl_led_off((const struct device *)dev, led); } -#include +#include diff --git a/drivers/led/led_shell.c b/drivers/led/led_shell.c index 3e26c915c3cbb..b138403e499e0 100644 --- a/drivers/led/led_shell.c +++ b/drivers/led/led_shell.c @@ -6,6 +6,7 @@ #include #include +#include #include #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL @@ -84,6 +85,28 @@ static int cmd_on(const struct shell *sh, size_t argc, char **argv) return err; } +static const char *led_color_to_str(uint8_t color) +{ + switch (color) { + case LED_COLOR_ID_WHITE: + return "white"; + case LED_COLOR_ID_RED: + return "red"; + case LED_COLOR_ID_GREEN: + return "green"; + case LED_COLOR_ID_BLUE: + return "blue"; + case LED_COLOR_ID_VIOLET: + return "violet"; + case LED_COLOR_ID_YELLOW: + return "yellow"; + case LED_COLOR_ID_IR: + return "IR"; + default: + return "unknown"; + } +} + static int cmd_get_info(const struct shell *sh, size_t argc, char **argv) { const struct device *dev; @@ -109,11 +132,11 @@ static int cmd_get_info(const struct shell *sh, size_t argc, char **argv) shell_print(sh, "Index : %d", info->index); shell_print(sh, "Num colors : %d", info->num_colors); if (info->color_mapping) { - shell_fprintf(sh, SHELL_NORMAL, "Colors : %d", - info->color_mapping[0]); + shell_fprintf(sh, SHELL_NORMAL, "Colors : %s", + led_color_to_str(info->color_mapping[0])); for (i = 1; i < info->num_colors; i++) { - shell_fprintf(sh, SHELL_NORMAL, ":%d", - info->color_mapping[i]); + shell_fprintf(sh, SHELL_NORMAL, ":%s", + led_color_to_str(info->color_mapping[i])); } shell_fprintf(sh, SHELL_NORMAL, "\n"); } diff --git a/drivers/led_strip/CMakeLists.txt b/drivers/led_strip/CMakeLists.txt index aa4e95722a716..b293782e620fb 100644 --- a/drivers/led_strip/CMakeLists.txt +++ b/drivers/led_strip/CMakeLists.txt @@ -9,3 +9,4 @@ zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_SPI ws2812_spi.c) zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_I2S ws2812_i2s.c) zephyr_library_sources_ifdef(CONFIG_WS2812_STRIP_RPI_PICO_PIO ws2812_rpi_pico_pio.c) zephyr_library_sources_ifdef(CONFIG_TLC5971_STRIP tlc5971.c) +zephyr_library_sources_ifdef(CONFIG_TLC59731_STRIP tlc59731.c) diff --git a/drivers/led_strip/Kconfig b/drivers/led_strip/Kconfig index 269657dd0b8a0..3be80de47298c 100644 --- a/drivers/led_strip/Kconfig +++ b/drivers/led_strip/Kconfig @@ -35,4 +35,6 @@ source "drivers/led_strip/Kconfig.apa102" source "drivers/led_strip/Kconfig.tlc5971" +source "drivers/led_strip/Kconfig.tlc59731" + endif # LED_STRIP diff --git a/drivers/led_strip/Kconfig.tlc59731 b/drivers/led_strip/Kconfig.tlc59731 new file mode 100644 index 0000000000000..3857c08dc5f0d --- /dev/null +++ b/drivers/led_strip/Kconfig.tlc59731 @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Javad Rahimipetroudi +# SPDX-License-Identifier: Apache-2.0 + +config TLC59731_STRIP + bool "TLC59731 LED controller" + default y + depends on DT_HAS_TI_TLC59731_ENABLED + select GPIO + help + Enable driver for the Texas Instruments TLC59731 EasySet LED + controllers. diff --git a/drivers/led_strip/apa102.c b/drivers/led_strip/apa102.c index cea394d79018b..9f7de642358b7 100644 --- a/drivers/led_strip/apa102.c +++ b/drivers/led_strip/apa102.c @@ -14,6 +14,7 @@ struct apa102_config { struct spi_dt_spec bus; + size_t length; }; static int apa102_update(const struct device *dev, void *buf, size_t size) @@ -73,11 +74,11 @@ static int apa102_update_rgb(const struct device *dev, struct led_rgb *pixels, return apa102_update(dev, pixels, sizeof(struct led_rgb) * count); } -static int apa102_update_channels(const struct device *dev, uint8_t *channels, - size_t num_channels) +static size_t apa102_length(const struct device *dev) { - /* Not implemented */ - return -EINVAL; + const struct apa102_config *config = dev->config; + + return config->length; } static int apa102_init(const struct device *dev) @@ -93,7 +94,7 @@ static int apa102_init(const struct device *dev) static const struct led_strip_driver_api apa102_api = { .update_rgb = apa102_update_rgb, - .update_channels = apa102_update_channels, + .length = apa102_length, }; #define APA102_DEVICE(idx) \ @@ -102,6 +103,7 @@ static const struct led_strip_driver_api apa102_api = { idx, \ SPI_OP_MODE_MASTER | SPI_TRANSFER_MSB | SPI_WORD_SET(8), \ 0), \ + .length = DT_INST_PROP(idx, chain_length), \ }; \ \ DEVICE_DT_INST_DEFINE(idx, \ diff --git a/drivers/led_strip/lpd880x.c b/drivers/led_strip/lpd880x.c index a1fa90e6415c5..991e2e3fb57e9 100644 --- a/drivers/led_strip/lpd880x.c +++ b/drivers/led_strip/lpd880x.c @@ -36,6 +36,7 @@ LOG_MODULE_REGISTER(lpd880x); struct lpd880x_config { struct spi_dt_spec bus; + size_t length; }; static int lpd880x_update(const struct device *dev, void *data, size_t size) @@ -125,6 +126,13 @@ static int lpd880x_strip_update_channels(const struct device *dev, return lpd880x_update(dev, channels, num_channels); } +static size_t lpd880x_strip_length(const struct device *dev) +{ + const struct lpd880x_config *config = dev->config; + + return config->length; +} + static int lpd880x_strip_init(const struct device *dev) { const struct lpd880x_config *config = dev->config; @@ -138,12 +146,14 @@ static int lpd880x_strip_init(const struct device *dev) } static const struct lpd880x_config lpd880x_config = { - .bus = SPI_DT_SPEC_INST_GET(0, LPD880X_SPI_OPERATION, 0) + .bus = SPI_DT_SPEC_INST_GET(0, LPD880X_SPI_OPERATION, 0), + .length = DT_INST_PROP(0, chain_length), }; static const struct led_strip_driver_api lpd880x_strip_api = { .update_rgb = lpd880x_strip_update_rgb, .update_channels = lpd880x_strip_update_channels, + .length = lpd880x_strip_length, }; DEVICE_DT_INST_DEFINE(0, lpd880x_strip_init, NULL, diff --git a/drivers/led_strip/tlc5971.c b/drivers/led_strip/tlc5971.c index 06d36455d5806..ace45414fbf82 100644 --- a/drivers/led_strip/tlc5971.c +++ b/drivers/led_strip/tlc5971.c @@ -248,25 +248,16 @@ static int tlc5971_transmit_data(const struct device *dev, size_t num_pixels) static int tlc5971_update_rgb(const struct device *dev, struct led_rgb *pixels, size_t num_pixels) { - const struct tlc5971_config *cfg = dev->config; - - if (num_pixels > cfg->num_pixels) { - LOG_ERR("invalid number of pixels, %zu vs actual %i", num_pixels, cfg->num_pixels); - return -EINVAL; - } - tlc5971_fill_data_buffer(dev, pixels, num_pixels); return tlc5971_transmit_data(dev, num_pixels); } -static int tlc5971_update_channels(const struct device *dev, uint8_t *channels, size_t num_channels) +static size_t tlc5971_length(const struct device *dev) { - ARG_UNUSED(dev); - ARG_UNUSED(channels); - ARG_UNUSED(num_channels); + const struct tlc5971_config *cfg = dev->config; - return -ENOTSUP; + return (size_t)cfg->num_pixels; } int tlc5971_set_global_brightness(const struct device *dev, struct led_rgb pixel) @@ -333,7 +324,7 @@ static int tlc5971_init(const struct device *dev) static const struct led_strip_driver_api tlc5971_api = { .update_rgb = tlc5971_update_rgb, - .update_channels = tlc5971_update_channels, + .length = tlc5971_length, }; #define TLC5971_DATA_BUFFER_LENGTH(inst) \ diff --git a/drivers/led_strip/tlc59731.c b/drivers/led_strip/tlc59731.c new file mode 100644 index 0000000000000..c8501156e8143 --- /dev/null +++ b/drivers/led_strip/tlc59731.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2024 Javad Rahimipetroudi + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ti_tlc59731 + +/** + * @file + * @brief LED driver for the TLC59731 LED driver. + * + * TLC59731 is a 3-Channel, 8-Bit, PWM LED Driver + * With Single-Wire Interface (EasySet) + * + * The EasySet protocol is based on short pulses and the time between + * them. At least one pulse must be sent every T_CYCLE, which can be + * between 1.67us and 50us. We want to go as fast as possible, but + * delays under 1us don't work very well, so we settle on 5us for the + * cycle time. + * A pulse must be high for at least 14ns. In practice, turning a GPIO on + * and immediately off again already takes longer than that, so no delay + * is needed there. + * A zero is represented by no additional pulses within a cycle. + * A one is represented by an additional pulse between 275ns and 2.5us + * (half a cycle) after the first one. We need at least some delay to get to + * 275ns, but because of the limited granularity of k_busy_wait we use a + * full 1us. After the pulse, we wait an additional T_CYCLE_1 to complete + * the cycle. This time can be slightly shorter because the second pulse + * already closes the cycle. + * Finally we need to keep the line low for T_H0 to complete the address + * for a single chip, and T_H1 to complete the write for all chips. + */ + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(tlc59731, CONFIG_LED_STRIP_LOG_LEVEL); + +/* Pulse timing */ +#define TLC59731_DELAY 0x01 /* us */ +#define TLC59731_T_CYCLE_0 0x04 /* us */ +#define TLC59731_T_CYCLE_1 0x01 /* us */ +#define TLC59731_T_H0 (4 * TLC59731_T_CYCLE_0) +#define TLC59731_T_H1 (8 * TLC59731_T_CYCLE_0) +/* Threshould levels */ +#define TLC59731_HIGH 0x01 +#define TLC59731_LOW 0x00 + +/* Write command */ +#define TLC59731_WR 0x3A + +struct tlc59731_cfg { + struct gpio_dt_spec sdi_gpio; + size_t length; +}; + +static inline int rgb_pulse(const struct gpio_dt_spec *led_dev) +{ + int fret = 0; + + fret = gpio_pin_set_dt(led_dev, TLC59731_HIGH); + if (fret != 0) { + return fret; + } + + fret = gpio_pin_set_dt(led_dev, TLC59731_LOW); + if (fret != 0) { + return fret; + } + + return fret; +} + +static int rgb_write_bit(const struct gpio_dt_spec *led_dev, uint8_t data) +{ + rgb_pulse(led_dev); + + k_busy_wait(TLC59731_DELAY); + + if (data) { + rgb_pulse(led_dev); + k_busy_wait(TLC59731_T_CYCLE_1); + } else { + k_busy_wait(TLC59731_T_CYCLE_0); + } + + return 0; +} + +static int rgb_write_data(const struct gpio_dt_spec *led_dev, uint8_t data) +{ + int8_t idx = 7; + + while (idx >= 0) { + rgb_write_bit(led_dev, data & BIT((idx--))); + } + + return 0; +} + +static int tlc59731_led_set_color(const struct device *dev, struct led_rgb *pixel) +{ + + const struct tlc59731_cfg *tlc_conf = dev->config; + const struct gpio_dt_spec *led_gpio = &tlc_conf->sdi_gpio; + + rgb_write_data(led_gpio, TLC59731_WR); + rgb_write_data(led_gpio, pixel->r); + rgb_write_data(led_gpio, pixel->g); + rgb_write_data(led_gpio, pixel->b); + + return 0; +} + +static int tlc59731_gpio_update_rgb(const struct device *dev, struct led_rgb *pixels, + size_t num_pixels) +{ + size_t i; + int err = 0; + + for (i = 0; i < num_pixels; i++) { + err = tlc59731_led_set_color(dev, &pixels[i]); + if (err) { + break; + } + } + + return err; +} + +static size_t tlc59731_length(const struct device *dev) +{ + const struct tlc59731_cfg *config = dev->config; + + return config->length; +} + +static const struct led_strip_driver_api tlc59731_gpio_api = { + .update_rgb = tlc59731_gpio_update_rgb, + .length = tlc59731_length, +}; + +static int tlc59731_gpio_init(const struct device *dev) +{ + const struct tlc59731_cfg *tlc_conf = dev->config; + const struct gpio_dt_spec *led = &tlc_conf->sdi_gpio; + int err = 0; + + if (!device_is_ready(led->port)) { + LOG_ERR("%s: no LEDs found (DT child nodes missing)", dev->name); + err = -ENODEV; + goto scape; + } + + err = gpio_pin_configure_dt(led, GPIO_OUTPUT_ACTIVE); + if (err < 0) { + LOG_ERR("%s: Unable to setup SDI port", dev->name); + err = -EIO; + goto scape; + } + + err = gpio_pin_set_dt(led, TLC59731_LOW); + if (err < 0) { + LOG_ERR("%s: Unable to set the SDI-GPIO)", dev->name); + err = -EIO; + goto scape; + } + + gpio_pin_set_dt(led, TLC59731_HIGH); + gpio_pin_set_dt(led, TLC59731_LOW); + + k_busy_wait((TLC59731_DELAY + TLC59731_T_CYCLE_0)); +scape: + return err; +} + +#define TLC59731_DEVICE(i) \ + static struct tlc59731_cfg tlc59731_cfg_##i = { \ + .sdi_gpio = GPIO_DT_SPEC_INST_GET(i, gpios), \ + .length = DT_INST_PROP(i, chain_length), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(i, tlc59731_gpio_init, NULL, NULL, &tlc59731_cfg_##i, POST_KERNEL, \ + CONFIG_LED_STRIP_INIT_PRIORITY, &tlc59731_gpio_api); +DT_INST_FOREACH_STATUS_OKAY(TLC59731_DEVICE) diff --git a/drivers/led_strip/ws2812_gpio.c b/drivers/led_strip/ws2812_gpio.c index bba534f1bbe7b..9c0d47d3afb0d 100644 --- a/drivers/led_strip/ws2812_gpio.c +++ b/drivers/led_strip/ws2812_gpio.c @@ -28,6 +28,7 @@ struct ws2812_gpio_cfg { struct gpio_dt_spec gpio; uint8_t num_colors; const uint8_t *color_mapping; + size_t length; }; /* @@ -179,17 +180,16 @@ static int ws2812_gpio_update_rgb(const struct device *dev, return send_buf(dev, (uint8_t *)pixels, num_pixels * config->num_colors); } -static int ws2812_gpio_update_channels(const struct device *dev, - uint8_t *channels, - size_t num_channels) +static size_t ws2812_gpio_length(const struct device *dev) { - LOG_ERR("update_channels not implemented"); - return -ENOTSUP; + const struct ws2812_gpio_cfg *config = dev->config; + + return config->length; } static const struct led_strip_driver_api ws2812_gpio_api = { .update_rgb = ws2812_gpio_update_rgb, - .update_channels = ws2812_gpio_update_channels, + .length = ws2812_gpio_length, }; /* @@ -245,6 +245,7 @@ static const uint8_t ws2812_gpio_##idx##_color_mapping[] = \ .gpio = GPIO_DT_SPEC_INST_GET(idx, gpios), \ .num_colors = WS2812_NUM_COLORS(idx), \ .color_mapping = ws2812_gpio_##idx##_color_mapping, \ + .length = DT_INST_PROP(idx, chain_length), \ }; \ \ DEVICE_DT_INST_DEFINE(idx, \ diff --git a/drivers/led_strip/ws2812_i2s.c b/drivers/led_strip/ws2812_i2s.c index 19baefff8e2bf..b1b951216282a 100644 --- a/drivers/led_strip/ws2812_i2s.c +++ b/drivers/led_strip/ws2812_i2s.c @@ -38,6 +38,7 @@ struct ws2812_i2s_cfg { size_t tx_buf_bytes; struct k_mem_slab *mem_slab; uint8_t num_colors; + size_t length; const uint8_t *color_mapping; uint16_t reset_words; uint32_t lrck_period; @@ -163,11 +164,11 @@ static int ws2812_strip_update_rgb(const struct device *dev, struct led_rgb *pix return ret; } -static int ws2812_strip_update_channels(const struct device *dev, uint8_t *channels, - size_t num_channels) +static size_t ws2812_strip_length(const struct device *dev) { - LOG_ERR("update_channels not implemented"); - return -ENOTSUP; + const struct ws2812_i2s_cfg *cfg = dev->config; + + return cfg->length; } static int ws2812_i2s_init(const struct device *dev) @@ -217,7 +218,7 @@ static int ws2812_i2s_init(const struct device *dev) static const struct led_strip_driver_api ws2812_i2s_api = { .update_rgb = ws2812_strip_update_rgb, - .update_channels = ws2812_strip_update_channels, + .length = ws2812_strip_length, }; /* Integer division, but always rounds up: e.g. 10/3 = 4 */ @@ -250,6 +251,7 @@ static const struct led_strip_driver_api ws2812_i2s_api = { .tx_buf_bytes = WS2812_I2S_BUFSIZE(idx), \ .mem_slab = &ws2812_i2s_##idx##_slab, \ .num_colors = WS2812_NUM_COLORS(idx), \ + .length = DT_INST_PROP(idx, chain_length), \ .color_mapping = ws2812_i2s_##idx##_color_mapping, \ .lrck_period = WS2812_I2S_LRCK_PERIOD_US(idx), \ .extra_wait_time_us = DT_INST_PROP(idx, extra_wait_time), \ diff --git a/drivers/led_strip/ws2812_rpi_pico_pio.c b/drivers/led_strip/ws2812_rpi_pico_pio.c index 5da5cc05f592a..45b19da8f8400 100644 --- a/drivers/led_strip/ws2812_rpi_pico_pio.c +++ b/drivers/led_strip/ws2812_rpi_pico_pio.c @@ -24,6 +24,7 @@ struct ws2812_led_strip_config { const struct device *piodev; const uint8_t gpio_pin; uint8_t num_colors; + size_t length; uint32_t frequency; const uint8_t *const color_mapping; uint16_t reset_delay; @@ -108,16 +109,16 @@ static int ws2812_led_strip_update_rgb(const struct device *dev, struct led_rgb return 0; } -static int ws2812_led_strip_update_channels(const struct device *dev, uint8_t *channels, - size_t num_channels) +static size_t ws2812_led_strip_length(const struct device *dev) { - LOG_DBG("update_channels not implemented"); - return -ENOTSUP; + const struct ws2812_led_strip_config *config = dev->config; + + return config->length; } static const struct led_strip_driver_api ws2812_led_strip_api = { .update_rgb = ws2812_led_strip_update_rgb, - .update_channels = ws2812_led_strip_update_channels, + .length = ws2812_led_strip_length, }; /* @@ -190,6 +191,7 @@ static int ws2812_rpi_pico_pio_init(const struct device *dev) .piodev = DEVICE_DT_GET(DT_PARENT(DT_PARENT(node))), \ .gpio_pin = DT_GPIO_PIN_BY_IDX(node, gpios, 0), \ .num_colors = DT_PROP_LEN(node, color_mapping), \ + .length = DT_PROP(node, chain_length), \ .color_mapping = ws2812_led_strip_##node##_color_mapping, \ .reset_delay = DT_PROP(node, reset_delay), \ .frequency = DT_PROP(node, frequency), \ diff --git a/drivers/led_strip/ws2812_spi.c b/drivers/led_strip/ws2812_spi.c index 44cfecebc9ea5..536da5463c9a0 100644 --- a/drivers/led_strip/ws2812_spi.c +++ b/drivers/led_strip/ws2812_spi.c @@ -39,11 +39,11 @@ LOG_MODULE_REGISTER(ws2812_spi); struct ws2812_spi_cfg { struct spi_dt_spec bus; uint8_t *px_buf; - size_t px_buf_size; uint8_t one_frame; uint8_t zero_frame; uint8_t num_colors; const uint8_t *color_mapping; + size_t length; uint16_t reset_delay; }; @@ -67,20 +67,6 @@ static inline void ws2812_spi_ser(uint8_t buf[8], uint8_t color, } } -/* - * Returns true if and only if cfg->px_buf is big enough to convert - * num_pixels RGB color values into SPI frames. - */ -static inline bool num_pixels_ok(const struct ws2812_spi_cfg *cfg, - size_t num_pixels) -{ - size_t nbytes; - bool overflow; - - overflow = size_mul_overflow(num_pixels, cfg->num_colors * 8, &nbytes); - return !overflow && (nbytes <= cfg->px_buf_size); -} - /* * Latch current color values on strip and reset its state machines. */ @@ -97,7 +83,7 @@ static int ws2812_strip_update_rgb(const struct device *dev, const uint8_t one = cfg->one_frame, zero = cfg->zero_frame; struct spi_buf buf = { .buf = cfg->px_buf, - .len = cfg->px_buf_size, + .len = (cfg->length * 8 * cfg->num_colors), }; const struct spi_buf_set tx = { .buffers = &buf, @@ -107,10 +93,6 @@ static int ws2812_strip_update_rgb(const struct device *dev, size_t i; int rc; - if (!num_pixels_ok(cfg, num_pixels)) { - return -ENOMEM; - } - /* * Convert pixel data into SPI frames. Each frame has pixel data * in color mapping on-wire format (e.g. GRB, GRBW, RGB, etc). @@ -152,12 +134,11 @@ static int ws2812_strip_update_rgb(const struct device *dev, return rc; } -static int ws2812_strip_update_channels(const struct device *dev, - uint8_t *channels, - size_t num_channels) +static size_t ws2812_strip_length(const struct device *dev) { - LOG_ERR("update_channels not implemented"); - return -ENOTSUP; + const struct ws2812_spi_cfg *cfg = dev_cfg(dev); + + return cfg->length; } static int ws2812_spi_init(const struct device *dev) @@ -190,7 +171,7 @@ static int ws2812_spi_init(const struct device *dev) static const struct led_strip_driver_api ws2812_spi_api = { .update_rgb = ws2812_strip_update_rgb, - .update_channels = ws2812_strip_update_channels, + .length = ws2812_strip_length, }; #define WS2812_SPI_NUM_PIXELS(idx) \ @@ -226,11 +207,11 @@ static const struct led_strip_driver_api ws2812_spi_api = { static const struct ws2812_spi_cfg ws2812_spi_##idx##_cfg = { \ .bus = SPI_DT_SPEC_INST_GET(idx, SPI_OPER(idx), 0), \ .px_buf = ws2812_spi_##idx##_px_buf, \ - .px_buf_size = WS2812_SPI_BUFSZ(idx), \ .one_frame = WS2812_SPI_ONE_FRAME(idx), \ .zero_frame = WS2812_SPI_ZERO_FRAME(idx), \ .num_colors = WS2812_NUM_COLORS(idx), \ .color_mapping = ws2812_spi_##idx##_color_mapping, \ + .length = DT_INST_PROP(idx, chain_length), \ .reset_delay = WS2812_RESET_DELAY(idx), \ }; \ \ diff --git a/drivers/lora/CMakeLists.txt b/drivers/lora/CMakeLists.txt index 81cb1468ed09a..85a37f0d55948 100644 --- a/drivers/lora/CMakeLists.txt +++ b/drivers/lora/CMakeLists.txt @@ -20,3 +20,4 @@ endif() zephyr_library_sources_ifdef(CONFIG_LORA_SX126X sx126x_standalone.c) zephyr_library_sources_ifdef(CONFIG_LORA_STM32WL_SUBGHZ_RADIO sx126x_stm32wl.c) +zephyr_library_sources_ifdef(CONFIG_LORA_RYLRXXX rylrxxx.c) diff --git a/drivers/lora/Kconfig b/drivers/lora/Kconfig index 585f122c3d6fd..6319ccf6be9e2 100644 --- a/drivers/lora/Kconfig +++ b/drivers/lora/Kconfig @@ -33,4 +33,6 @@ config LORA_INIT_PRIORITY source "drivers/lora/Kconfig.sx12xx" +source "drivers/lora/Kconfig.rylrxxx" + endif # LORA diff --git a/drivers/lora/Kconfig.rylrxxx b/drivers/lora/Kconfig.rylrxxx new file mode 100644 index 0000000000000..8daf137338d37 --- /dev/null +++ b/drivers/lora/Kconfig.rylrxxx @@ -0,0 +1,44 @@ +# +# Copyright (c) 2024 David Ullmann +# +# SPDX-License-Identifier: Apache-2.0 +# + +config LORA_RYLRXXX + bool "Reyax LYLR driver" + depends on DT_HAS_REYAX_RYLRXXX_ENABLED + select MODEM_MODULES + select MODEM_CHAT + select MODEM_PIPE + select MODEM_BACKEND_UART + select GPIO + help + Enable the Reyax LYLR driver + +if LORA_RYLRXXX + +config LORA_RYLRXX_CMD_BUF_SIZE + int "cmd buffer size" + default 256 + help + Configure the cmd buffer size + +config RYLRXXX_UNSOLICITED_RX_MSGQ_SIZE + int "number of message to store in message queue" + default 1 + help + Configure the size of message queue + +config RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS + int "timeout when waiting for response from radio serial interface after send cmd" + default 500 + help + Configure the number of milliseconds before timing out when waiting for acknowledgment from radio after sending cmd + +config RYLRXXX_MODEM_BUFFERS_SIZE + int "size of buffers for modem library" + default 512 + help + Configure the size of buffers for modem library + +endif # LORA_RYLRXXX diff --git a/drivers/lora/rylrxxx.c b/drivers/lora/rylrxxx.c new file mode 100644 index 0000000000000..57e4e6ff0142c --- /dev/null +++ b/drivers/lora/rylrxxx.c @@ -0,0 +1,684 @@ +/* + * Copyright (C) 2024 David Ullmann + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#define DT_DRV_COMPAT reyax_rylrxxx + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(rylr, CONFIG_LORA_LOG_LEVEL); + +#define RYLR_CMD_BAND_FORMAT "AT+BAND=%u\r\n" +#define RYLR_CMD_BAND_PARM_CHARS 9U +#define RYLR_CMD_BAND_FORMAT_NUM_WILDCARDS 1U +#define RYLR_CMD_BAND_FORMAT_WILDCARD_CHARS (RYLR_CMD_BAND_FORMAT_NUM_WILDCARDS * 2) +#define RYLR_CMD_BAND_FORMAT_LEN_WITHOUT_WILDCARDS \ + (sizeof(RYLR_CMD_BAND_FORMAT) - RYLR_CMD_BAND_FORMAT_WILDCARD_CHARS - 1) +#define RYLR_CMD_BAND_LENGTH (RYLR_CMD_BAND_FORMAT_LEN_WITHOUT_WILDCARDS + RYLR_CMD_BAND_PARM_CHARS) + +#define RYLR_CMD_SEND_FORMAT "AT+SEND=0,%u,%s\r\n" +#define RYLR_CMD_SEND_FORMAT_NUM_WILDCARDS 2U +#define RYLR_CMD_SEND_FORMAT_WILDCARD_CHARS (RYLR_CMD_SEND_FORMAT_NUM_WILDCARDS * 2) +#define RYLR_CMD_SEND_FORMAT_LEN_WITHOUT_WILDCARDS \ + (sizeof(RYLR_CMD_SEND_FORMAT) - RYLR_CMD_SEND_FORMAT_WILDCARD_CHARS - 1) +#define RYLR_PAYLOAD_LENGTH_FIELD_CHARS(payload_len) \ + (payload_len >= 100 ? 3 : (payload_len >= 10 ? 2 : 1)) +#define RYLR_CMD_SEND_LENGTH(payload_len) \ + (RYLR_CMD_SEND_FORMAT_LEN_WITHOUT_WILDCARDS + \ + RYLR_PAYLOAD_LENGTH_FIELD_CHARS(payload_len) + payload_len) + +#define RYLR_CMD_RF_SETTINGS_FORMAT "AT+PARAMETER=%u,%u,%u,%u\r\n" +#define RYLR_CMD_RF_SETTINGS_FORMAT_NUM_WILDCARDS 4U +#define RYLR_CMD_RF_SETTINGS_FORMAT_WILDCARD_CHARS (RYLR_CMD_RF_SETTINGS_FORMAT_NUM_WILDCARDS * 2U) +#define RYLR_CMD_RF_SETTINGS_FORMAT_LEN_WITHOUT_WILDCARDS \ + (sizeof(RYLR_CMD_RF_SETTINGS_FORMAT) - RYLR_CMD_RF_SETTINGS_FORMAT_WILDCARD_CHARS - 1) +#define RYLR_CMD_RF_SETTINGS_FORMAT_PARAM_CHARS(spread_factor) \ + (RYLR_CMD_RF_SETTINGS_FORMAT_NUM_WILDCARDS - 1) + (spread_factor >= 10U ? 2U : 1U) +#define RYLR_CMD_RF_SETTINGS_LEN(spread_factor) \ + (RYLR_CMD_RF_SETTINGS_FORMAT_LEN_WITHOUT_WILDCARDS + \ + RYLR_CMD_RF_SETTINGS_FORMAT_PARAM_CHARS(spread_factor)) + +#define RYLR_CMD_POWER_FORMAT "AT+CRFOP=%u\r\n" +#define RYLR_CMD_POWER_FORMAT_NUM_WILDCARDS 1U +#define RYLR_CMD_POWER_FORMAT_WILDCARD_CHARS (RYLR_CMD_POWER_FORMAT_NUM_WILDCARDS * 2U) +#define RYLR_CMD_POWER_FORMAT_LEN_WITHOUT_WILDCARDS \ + (sizeof(RYLR_CMD_POWER_FORMAT) - RYLR_CMD_POWER_FORMAT_WILDCARD_CHARS - 1) +#define RYLR_CMD_POWER_FORMAT_PARAM_CHARS(power) (power >= 10U ? 2U : 1U) +#define RYLR_CMD_POWER_LEN(power) \ + (RYLR_CMD_POWER_FORMAT_LEN_WITHOUT_WILDCARDS + RYLR_CMD_POWER_FORMAT_PARAM_CHARS(power)) + +#define RYLR_MAX_RESPONSE 256 +#define RYLR_MAX_MSG_BYTES 256 + +#define RYLR_ALLOC_TIMEOUT K_SECONDS(1) + +#define RYLR_TX_PENDING_FLAG_POS (0U) +#define RYLR_RX_PENDING_FLAG_POS (1U) + +#define RYLR_IS_TX_PENDING(flags) (flags & (0x01 << RYLR_TX_PENDING_FLAG_POS)) +#define RYLR_IS_RX_PENDING(flags) (flags & (0x01 << RYLR_RX_PENDING_FLAG_POS)) + +#define RYLR_SET_TX_PENDING(flags) (flags |= (0x01 << RYLR_TX_PENDING_FLAG_POS)) +#define RYLR_SET_RX_PENDING(flags) (flags |= (0x01 << RYLR_RX_PENDING_FLAG_POS)) + +#define RYLR_CLEAR_TX_PENDING(flags) (flags &= ~(0x01 << RYLR_TX_PENDING_FLAG_POS)) +#define RYLR_CLEAR_RX_PENDING(flags) (flags &= ~(0x01 << RYLR_RX_PENDING_FLAG_POS)) + +#define RYLR_IS_ASYNC_OP_PENDING(flags) (RYLR_IS_RX_PENDING(flags) || RYLR_IS_TX_PENDING(flags)) + +#define RYLR_MAX_RESPONSE_ARGS 6U + +#define RYLR_MIN_RESET_MSECS (100U) +#define RYLR_RESET_WAIT_MSECS (RYLR_MIN_RESET_MSECS + 10U) + +struct rylr_config { + const struct device *uart; + const struct gpio_dt_spec reset; +}; + +struct rylr_data { + uint8_t cmd_buffer[CONFIG_LORA_RYLRXX_CMD_BUF_SIZE]; + size_t curr_cmd_len; + bool is_tx; + int handler_error; + struct k_msgq rx_msgq; + struct k_sem script_sem; + struct k_sem operation_sem; + uint8_t pending_async_flags; + struct k_poll_signal *async_tx_signal; + lora_recv_cb async_rx_cb; + const struct device *dev; + uint8_t msgq_buffer[CONFIG_RYLRXXX_UNSOLICITED_RX_MSGQ_SIZE]; + struct modem_pipe *modem_pipe; + uint8_t uart_backend_rx_buff[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE]; + uint8_t uart_backend_tx_buff[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE]; + struct modem_pipe *uart_pipe; + struct modem_backend_uart uart_backend; + uint8_t chat_rx_buf[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE]; + uint8_t chat_tx_buf[CONFIG_RYLRXXX_MODEM_BUFFERS_SIZE]; + uint8_t *chat_argv[RYLR_MAX_RESPONSE_ARGS]; + struct modem_chat chat; + struct modem_chat_script dynamic_script; + struct modem_chat_script_chat dynamic_chat; +}; + +struct rylr_recv_msg { + uint16_t addr; + uint8_t length; + uint8_t *data; + uint8_t rssi; + uint8_t snr; +}; + +static void on_ok(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data) +{ + int err = 0; + struct rylr_data *driver_data = user_data; + + driver_data->handler_error = err; +} + +static void on_err(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data) +{ + int radio_err = 0; + struct rylr_data *driver_data = user_data; + + driver_data->handler_error = -EIO; + + if (argc != 2) { + driver_data->handler_error = -EBADMSG; + LOG_ERR("malformed error message from radio"); + return; + } + + radio_err = atoi(argv[1]); + LOG_ERR("error from rylr: %d", radio_err); +} + +static void on_rx(struct modem_chat *chat, char **argv, uint16_t argc, void *user_data) +{ + struct rylr_data *driver_data = user_data; + struct rylr_recv_msg msg; + int err = 0; + + driver_data->handler_error = 0; + + if (argc != 6) { + driver_data->handler_error = -EBADMSG; + return; + } + + msg.addr = atoi(argv[1]); + msg.length = atoi(argv[2]); + msg.data = argv[3]; + msg.rssi = atoi(argv[4]); + msg.snr = atoi(argv[5]); + + if (RYLR_IS_RX_PENDING(driver_data->pending_async_flags)) { + driver_data->async_rx_cb(driver_data->dev, msg.data, msg.length, msg.rssi, msg.snr); + } else { + err = k_msgq_put(&driver_data->rx_msgq, &msg, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error adding messgae to queue: %d", err); + driver_data->handler_error = err; + } + } +} + +static void on_script_finished(struct modem_chat *chat, enum modem_chat_script_result result, + void *user_data) +{ + struct rylr_data *driver_data = user_data; + + if (RYLR_IS_TX_PENDING(driver_data->pending_async_flags)) { + RYLR_CLEAR_TX_PENDING(driver_data->pending_async_flags); + k_poll_signal_raise(driver_data->async_tx_signal, driver_data->handler_error); + k_sem_give(&driver_data->operation_sem); + } + + k_sem_give(&driver_data->script_sem); +} + +MODEM_CHAT_MATCH_DEFINE(ok_match, "+OK", "", on_ok); + +MODEM_CHAT_MATCHES_DEFINE(abort_matches, MODEM_CHAT_MATCH("+ERR=", "", on_err)); + +MODEM_CHAT_MATCHES_DEFINE(unsol_matches, MODEM_CHAT_MATCH("+RCV=", ",", on_rx)); + +MODEM_CHAT_SCRIPT_CMDS_DEFINE(ping_cmd, MODEM_CHAT_SCRIPT_CMD_RESP("AT\r\n", ok_match)); + +MODEM_CHAT_SCRIPT_DEFINE(ping_script, ping_cmd, abort_matches, on_script_finished, + CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS); + +static void rylr_reset_dynamic_script(struct rylr_data *data) +{ + data->dynamic_chat.response_matches = &ok_match; + data->dynamic_chat.response_matches_size = 1; + data->dynamic_chat.timeout = 0; + + data->dynamic_script.script_chats = &data->dynamic_chat; + data->dynamic_script.script_chats_size = 1; + data->dynamic_script.abort_matches = abort_matches; + data->dynamic_script.abort_matches_size = 1; + data->dynamic_script.callback = on_script_finished; + data->dynamic_script.timeout = CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS; +} + +static uint32_t rylr_get_bandwidth_index(enum lora_signal_bandwidth bw) +{ + switch (bw) { + case BW_125_KHZ: + return 7; + case BW_250_KHZ: + return 8; + case BW_500_KHZ: + return 9; + default: + return 7; + } +} + +static int rylr_send_cmd_buffer(const struct device *dev) +{ + int err = 0; + struct rylr_data *data = dev->data; + + rylr_reset_dynamic_script(data); + + data->dynamic_chat.request = data->cmd_buffer; + data->dynamic_chat.request_size = data->curr_cmd_len; + + err = modem_chat_run_script(&data->chat, &data->dynamic_script); + if (err != 0) { + LOG_ERR("could not send cmd: %s. err: %d", data->cmd_buffer, err); + return err; + } + err = k_sem_take(&data->script_sem, K_MSEC(CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS)); + if (err) { + LOG_ERR("error waiting for response: %d", err); + return err; + } + return data->handler_error; +} + +static int rylr_set_rf_band(const struct device *dev, uint32_t frequency) +{ + struct rylr_data *data = dev->data; + + if (sprintf(data->cmd_buffer, RYLR_CMD_BAND_FORMAT, frequency) != RYLR_CMD_BAND_LENGTH) { + LOG_ERR("could not create frequency string"); + return -EINVAL; + } + + data->curr_cmd_len = RYLR_CMD_BAND_LENGTH; + return rylr_send_cmd_buffer(dev); +} + +static int rylr_set_rf_parameters(const struct device *dev, uint32_t datarate, uint32_t bandwidth, + uint32_t coding_rate, uint32_t preamble_length) +{ + struct rylr_data *data = dev->data; + size_t cmd_len; + + if (datarate < 7 || datarate > 12) { + LOG_ERR("datarate/spread factor must be between 7 and 12 inclusive"); + return -EINVAL; + } + + if (coding_rate < 1 || coding_rate > 4) { + LOG_ERR("coding rate must be between 1 and 4 inclusive"); + return -EINVAL; + } + + if (preamble_length < 4 || preamble_length > 7) { + LOG_ERR("preamble length must be between 4 and 7 inclusive"); + return -EINVAL; + } + + cmd_len = sprintf(data->cmd_buffer, RYLR_CMD_RF_SETTINGS_FORMAT, datarate, + rylr_get_bandwidth_index(bandwidth), coding_rate, preamble_length); + if (cmd_len != RYLR_CMD_RF_SETTINGS_LEN(datarate)) { + LOG_ERR("could not create rf settings string"); + return -EINVAL; + } + + data->curr_cmd_len = cmd_len; + return rylr_send_cmd_buffer(dev); +} + +static int rylr_set_power(const struct device *dev, uint32_t power) +{ + struct rylr_data *data = dev->data; + size_t cmd_len; + + if (power > 15) { + LOG_ERR("power cannot be greater than 15"); + return -EINVAL; + } + + cmd_len = RYLR_CMD_POWER_LEN(power); + if (sprintf(data->cmd_buffer, RYLR_CMD_POWER_FORMAT, power) != cmd_len) { + LOG_ERR("could not create power string"); + return -EINVAL; + } + + data->curr_cmd_len = cmd_len; + return rylr_send_cmd_buffer(dev); +} + +static int rylr_config(const struct device *dev, struct lora_modem_config *config) +{ + int err = 0; + struct rylr_data *data = dev->data; + + err = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error taking operation semaphore: %d", err); + return err; + } + + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + err = -EBUSY; + goto exit; + } + + err = rylr_set_rf_band(dev, config->frequency); + if (err != 0) { + LOG_ERR("could not send frequency cmd: %d", err); + goto exit; + } + + err = rylr_set_rf_parameters(dev, config->datarate, config->bandwidth, config->coding_rate, + config->preamble_len); + if (err != 0) { + LOG_ERR("could not send rf params cmd: %d", err); + goto exit; + } + + err = rylr_set_power(dev, config->tx_power); + if (err != 0) { + LOG_ERR("could not send power cmd: %d", err); + goto exit; + } + + data->is_tx = config->tx; + +exit: + k_sem_give(&data->operation_sem); + return err; +} + +int rylr_send(const struct device *dev, uint8_t *payload, uint32_t payload_len) +{ + int err = 0; + struct rylr_data *data = dev->data; + int cmd_len = RYLR_CMD_SEND_LENGTH(payload_len); + + err = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error taking operation semaphore: %d", err); + return err; + } + + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + err = -EBUSY; + goto exit; + } + + if (!data->is_tx) { + LOG_ERR("radio not configured in tx mode"); + err = -EOPNOTSUPP; + goto exit; + } + + if (cmd_len > CONFIG_LORA_RYLRXX_CMD_BUF_SIZE) { + LOG_ERR("payload too long"); + err = -EINVAL; + goto exit; + } + + snprintf(data->cmd_buffer, cmd_len + 1, RYLR_CMD_SEND_FORMAT, payload_len, payload); + data->curr_cmd_len = cmd_len; + err = rylr_send_cmd_buffer(dev); + if (err != 0) { + LOG_ERR("error sending data: %d", err); + goto exit; + } + +exit: + k_sem_give(&data->operation_sem); + return err; +} + +int rylr_send_async(const struct device *dev, uint8_t *payload, uint32_t payload_len, + struct k_poll_signal *async) +{ + int err = 0; + struct rylr_data *data = dev->data; + int cmd_len; + + err = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error taking operation sem: %d", err); + return err; + } + + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + err = -EBUSY; + goto bail; + } + + RYLR_SET_TX_PENDING(data->pending_async_flags); + + if (!data->is_tx) { + LOG_ERR("radio not configured in tx mode"); + err = -EOPNOTSUPP; + goto bail; + } + + cmd_len = RYLR_CMD_SEND_LENGTH(payload_len); + if (cmd_len > CONFIG_LORA_RYLRXX_CMD_BUF_SIZE) { + LOG_ERR("payload too long"); + err = -EINVAL; + goto bail; + } + + if (async == NULL) { + LOG_ERR("async signal cannot be null"); + err = -EINVAL; + goto bail; + } + + data->async_tx_signal = async; + data->curr_cmd_len = + snprintf(data->cmd_buffer, cmd_len + 1, RYLR_CMD_SEND_FORMAT, payload_len, payload); + rylr_reset_dynamic_script(data); + data->dynamic_chat.request = data->cmd_buffer; + data->dynamic_chat.request_size = data->curr_cmd_len; + + return modem_chat_run_script_async(&data->chat, &data->dynamic_script); +bail: + RYLR_CLEAR_TX_PENDING(data->pending_async_flags); + k_sem_give(&data->operation_sem); + return err; +} + +int rylr_recv(const struct device *dev, uint8_t *ret_msg, uint8_t size, k_timeout_t timeout, + int16_t *rssi, int8_t *snr) +{ + + int ret = 0; + struct rylr_data *data = dev->data; + struct rylr_recv_msg msg; + + ret = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (ret != 0) { + LOG_ERR("error taking operation semaphore: %d", ret); + return ret; + } + + if (data->is_tx) { + LOG_ERR("radio is configured for tx"); + ret = -EOPNOTSUPP; + goto exit; + } + + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + ret = -EBUSY; + goto exit; + } + + ret = k_msgq_get(&data->rx_msgq, &msg, timeout); + if (ret != 0) { + LOG_ERR("error getting msg from queue: %d", ret); + goto exit; + } + + ret = data->handler_error; + if (ret != 0) { + LOG_ERR("error in recv cb: %d", ret); + goto exit; + } + + if (msg.length > size) { + LOG_ERR("buf len of %u too small for message len of %u", size, msg.length); + ret = -ENOBUFS; + goto exit; + } + + *rssi = msg.rssi; + *snr = msg.snr; + memcpy(ret_msg, msg.data, msg.length); + ret = msg.length; + +exit: + k_sem_give(&data->operation_sem); + return ret; +} + +int rylr_recv_async(const struct device *dev, lora_recv_cb cb) +{ + int err = 0; + struct rylr_data *data = dev->data; + + err = k_sem_take(&data->operation_sem, K_NO_WAIT); + if (err != 0) { + LOG_ERR("error taking operation semaphore: %d", err); + return err; + } + + /* This is not a user error but the documeted way to cancel async reception in lora api*/ + if (cb == NULL) { + goto bail; + } + + if (data->is_tx) { + LOG_ERR("radio is configured for tx"); + err = -EOPNOTSUPP; + goto bail; + } + + data->async_rx_cb = cb; + if (RYLR_IS_ASYNC_OP_PENDING(data->pending_async_flags)) { + LOG_ERR("pending async opperation"); + err = -EBUSY; + goto bail; + } + RYLR_SET_RX_PENDING(data->pending_async_flags); + + return err; +bail: + RYLR_CLEAR_RX_PENDING(data->pending_async_flags); + k_sem_give(&data->operation_sem); + return err; +} + +int rylr_test_cw(const struct device *dev, uint32_t frequency, int8_t tx_power, uint16_t duration) +{ + return -ENOSYS; +} + +static int rylr_init(const struct device *dev) +{ + int err = 0; + struct rylr_data *data = dev->data; + const struct rylr_config *config = dev->config; + + if (!gpio_is_ready_dt(&config->reset)) { + return -ENODEV; + } + + if (!device_is_ready(config->uart)) { + return -ENODEV; + } + + err = gpio_pin_configure_dt(&config->reset, config->reset.dt_flags); + if (err != 0) { + LOG_ERR("error configuring reset gpio: %d", err); + return err; + } + + k_msgq_init(&data->rx_msgq, data->msgq_buffer, sizeof(struct rylr_recv_msg), + ARRAY_SIZE(data->msgq_buffer)); + + err = k_sem_init(&data->script_sem, 0, 1); + if (err != 0) { + LOG_ERR("error initializing response semaphore. err=%d", err); + } + + err = k_sem_init(&data->operation_sem, 1, 1); + if (err != 0) { + LOG_ERR("error initializing operation semaphore. err=%d", err); + } + + const struct modem_backend_uart_config uart_backend_config = { + .uart = config->uart, + .receive_buf = data->uart_backend_rx_buff, + .receive_buf_size = ARRAY_SIZE(data->uart_backend_rx_buff), + .transmit_buf = data->uart_backend_tx_buff, + .transmit_buf_size = ARRAY_SIZE(data->uart_backend_tx_buff), + }; + + data->uart_pipe = modem_backend_uart_init(&data->uart_backend, &uart_backend_config); + + const struct modem_chat_config chat_config = { + .user_data = data, + .receive_buf = data->chat_rx_buf, + .receive_buf_size = ARRAY_SIZE(data->chat_rx_buf), + .delimiter = "\r\n", + .delimiter_size = sizeof("\r\n") - 1, + .filter = NULL, + .filter_size = 0, + .argv = data->chat_argv, + .argv_size = ARRAY_SIZE(data->chat_argv), + .unsol_matches = unsol_matches, + .unsol_matches_size = ARRAY_SIZE(unsol_matches), + }; + + err = modem_chat_init(&data->chat, &chat_config); + if (err != 0) { + LOG_ERR("error initializing chat %d", err); + return err; + } + + err = modem_chat_attach(&data->chat, data->uart_pipe); + if (err != 0) { + LOG_ERR("error attaching chat %d", err); + return err; + } + + err = modem_pipe_open(data->uart_pipe); + if (err != 0) { + LOG_ERR("error opening uart pipe %d", err); + return err; + } + + err = gpio_pin_set_dt(&config->reset, 1); + if (err != 0) { + LOG_ERR("error setting reset line: %d", err); + return err; + } + + k_sleep(K_MSEC(RYLR_RESET_WAIT_MSECS)); + + err = gpio_pin_set_dt(&config->reset, 0); + if (err != 0) { + LOG_ERR("error unsetting reset line: %d", err); + return err; + } + + k_sleep(K_MSEC(RYLR_RESET_WAIT_MSECS)); /* wait a bit more for module to boot up*/ + + err = modem_chat_run_script(&data->chat, &ping_script); + if (err != 0) { + LOG_ERR("error pinging radio: %d", err); + return err; + } + + err = k_sem_take(&data->script_sem, K_MSEC(CONFIG_RYLRXXX_RADIO_CMD_RESPONSE_TIMEOUT_MS)); + if (err != 0) { + LOG_ERR("error waiting for ping response from radio %d", err); + return err; + } + + LOG_INF("successfully initialized rylr"); + return err; +} + +static const struct lora_driver_api rylr_lora_api = { + .config = rylr_config, + .send = rylr_send, + .send_async = rylr_send_async, + .recv = rylr_recv, + .recv_async = rylr_recv_async, + .test_cw = rylr_test_cw, +}; + +#define RYLR_DEVICE_INIT(n) \ + static struct rylr_data dev_data_##n; \ + static const struct rylr_config dev_config_##n = { \ + .uart = DEVICE_DT_GET(DT_INST_BUS(n)), \ + .reset = GPIO_DT_SPEC_INST_GET(n, reset_gpios), \ + }; \ + DEVICE_DT_INST_DEFINE(n, &rylr_init, NULL, &dev_data_##n, &dev_config_##n, POST_KERNEL, \ + CONFIG_LORA_INIT_PRIORITY, &rylr_lora_api); + +DT_INST_FOREACH_STATUS_OKAY(RYLR_DEVICE_INIT) diff --git a/drivers/mbox/CMakeLists.txt b/drivers/mbox/CMakeLists.txt index 1d5c65cded770..ce0cbbc6e9c5c 100644 --- a/drivers/mbox/CMakeLists.txt +++ b/drivers/mbox/CMakeLists.txt @@ -14,3 +14,4 @@ zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_VEVIF_LOCAL mbox_nrf_vevif_local.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_VEVIF_REMOTE mbox_nrf_vevif_remote.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_BELLBOARD_LOCAL mbox_nrf_bellboard_local.c) zephyr_library_sources_ifdef(CONFIG_MBOX_NRF_BELLBOARD_REMOTE mbox_nrf_bellboard_remote.c) +zephyr_library_sources_ifdef(CONFIG_MBOX_STM32_HSEM mbox_stm32_hsem.c) diff --git a/drivers/mbox/Kconfig b/drivers/mbox/Kconfig index 7f00324ba474a..ba72f0e894f58 100644 --- a/drivers/mbox/Kconfig +++ b/drivers/mbox/Kconfig @@ -19,6 +19,7 @@ source "drivers/mbox/Kconfig.nxp_mailbox" source "drivers/mbox/Kconfig.andes" source "drivers/mbox/Kconfig.nrf_vevif" source "drivers/mbox/Kconfig.nrf_bellboard" +source "drivers/mbox/Kconfig.stm32_hsem" config MBOX_INIT_PRIORITY int "MBOX init priority" diff --git a/drivers/mbox/Kconfig.stm32_hsem b/drivers/mbox/Kconfig.stm32_hsem new file mode 100644 index 0000000000000..586061bccbc69 --- /dev/null +++ b/drivers/mbox/Kconfig.stm32_hsem @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Celina Sophie Kalus +# SPDX-License-Identifier: Apache-2.0 + +config MBOX_STM32_HSEM + bool "MBOX STM32 HSEM driver" + depends on DT_HAS_ST_MBOX_STM32_HSEM_ENABLED + help + MBOX Driver for STM32 hardware semaphore diff --git a/drivers/mbox/mbox_handlers.c b/drivers/mbox/mbox_handlers.c index 2340ab016b5b6..aca4fb9b38200 100644 --- a/drivers/mbox/mbox_handlers.c +++ b/drivers/mbox/mbox_handlers.c @@ -17,7 +17,7 @@ static inline int z_vrfy_mbox_send(const struct device *dev, return z_impl_mbox_send(dev, channel_id, msg); } -#include +#include static inline int z_vrfy_mbox_mtu_get(const struct device *dev) { @@ -25,7 +25,7 @@ static inline int z_vrfy_mbox_mtu_get(const struct device *dev) return z_impl_mbox_mtu_get(dev); } -#include +#include static inline uint32_t z_vrfy_mbox_max_channels_get(const struct device *dev) { @@ -33,7 +33,7 @@ static inline uint32_t z_vrfy_mbox_max_channels_get(const struct device *dev) return z_impl_mbox_max_channels_get(dev); } -#include +#include static inline int z_vrfy_mbox_set_enabled(const struct device *dev, mbox_channel_id_t channel_id, @@ -43,4 +43,4 @@ static inline int z_vrfy_mbox_set_enabled(const struct device *dev, return z_impl_mbox_set_enabled(dev, channel_id, enabled); } -#include +#include diff --git a/drivers/mbox/mbox_stm32_hsem.c b/drivers/mbox/mbox_stm32_hsem.c new file mode 100644 index 0000000000000..a1e9ca92607f0 --- /dev/null +++ b/drivers/mbox/mbox_stm32_hsem.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include + +#include "stm32_hsem.h" + +LOG_MODULE_REGISTER(mbox_stm32_hsem_ipc, CONFIG_MBOX_LOG_LEVEL); + +#define DT_DRV_COMPAT st_mbox_stm32_hsem + +#define HSEM_CPU1 1 +#define HSEM_CPU2 2 + +#if DT_NODE_EXISTS(DT_NODELABEL(cpu0)) +#define HSEM_CPU_ID HSEM_CPU1 +#elif DT_NODE_EXISTS(DT_NODELABEL(cpu1)) +#define HSEM_CPU_ID HSEM_CPU2 +#else +#error "Neither cpu0 nor cpu1 defined!" +#endif + +#if HSEM_CPU_ID == HSEM_CPU1 +#define MBOX_TX_HSEM_ID CFG_HW_IPM_CPU2_SEMID +#define MBOX_RX_HSEM_ID CFG_HW_IPM_CPU1_SEMID +#else /* HSEM_CPU2 */ +#define MBOX_TX_HSEM_ID CFG_HW_IPM_CPU1_SEMID +#define MBOX_RX_HSEM_ID CFG_HW_IPM_CPU2_SEMID +#endif /* HSEM_CPU_ID */ + +#define MAX_CHANNELS 2 + +struct mbox_stm32_hsem_data { + const struct device *dev; + mbox_callback_t cb; + void *user_data; +}; + +static struct mbox_stm32_hsem_data stm32_hsem_mbox_data; + +static struct mbox_stm32_hsem_conf { + struct stm32_pclken pclken; +} stm32_hsem_mbox_conf = { + .pclken = { + .bus = DT_INST_CLOCKS_CELL(0, bus), + .enr = DT_INST_CLOCKS_CELL(0, bits) + }, +}; + +static inline void stm32_hsem_enable_rx_interrupt(void) +{ + const uint32_t mask_hsem_id = BIT(MBOX_RX_HSEM_ID); + +#if HSEM_CPU_ID == HSEM_CPU1 + LL_HSEM_EnableIT_C1IER(HSEM, mask_hsem_id); +#else /* HSEM_CPU2 */ + LL_HSEM_EnableIT_C2IER(HSEM, mask_hsem_id); +#endif /* HSEM_CPU_ID */ +} + +static inline void stm32_hsem_disable_rx_interrupt(void) +{ + const uint32_t mask_hsem_id = BIT(MBOX_RX_HSEM_ID); + +#if HSEM_CPU_ID == HSEM_CPU1 + LL_HSEM_DisableIT_C1IER(HSEM, mask_hsem_id); +#else /* HSEM_CPU2 */ + LL_HSEM_DisableIT_C2IER(HSEM, mask_hsem_id); +#endif /* HSEM_CPU_ID */ +} + +static inline void stm32_hsem_clear_rx_interrupt(void) +{ + const uint32_t mask_hsem_id = BIT(MBOX_RX_HSEM_ID); + +#if HSEM_CPU_ID == HSEM_CPU1 + LL_HSEM_ClearFlag_C1ICR(HSEM, mask_hsem_id); +#else /* HSEM_CPU2 */ + LL_HSEM_ClearFlag_C2ICR(HSEM, mask_hsem_id); +#endif /* HSEM_CPU_ID */ +} + +static inline uint32_t stm32_hsem_is_rx_interrupt_active(void) +{ + const uint32_t mask_hsem_id = BIT(MBOX_RX_HSEM_ID); + +#if HSEM_CPU_ID == HSEM_CPU1 + return LL_HSEM_IsActiveFlag_C1ISR(HSEM, mask_hsem_id); +#else /* HSEM_CPU2 */ + return LL_HSEM_IsActiveFlag_C2ISR(HSEM, mask_hsem_id); +#endif /* HSEM_CPU_ID */ +} + +static inline bool is_rx_channel_valid(const struct device *dev, uint32_t ch) +{ + /* Only support one RX channel */ + return (ch == MBOX_RX_HSEM_ID); +} + +static inline bool is_tx_channel_valid(const struct device *dev, uint32_t ch) +{ + /* Only support one TX channel */ + return (ch == MBOX_TX_HSEM_ID); +} + +static void mbox_dispatcher(const struct device *dev) +{ + struct mbox_stm32_hsem_data *data = dev->data; + + /* Check semaphore rx_semid interrupt status */ + if (!stm32_hsem_is_rx_interrupt_active()) + return; + + if (data->cb != NULL) { + data->cb(dev, MBOX_RX_HSEM_ID, data->user_data, NULL); + } + + /* Clear semaphore rx_semid interrupt status and masked status */ + stm32_hsem_clear_rx_interrupt(); +} + +static int mbox_stm32_hsem_send(const struct device *dev, uint32_t channel, + const struct mbox_msg *msg) +{ + if (msg) { + LOG_ERR("Sending data not supported."); + return -EINVAL; + } + + if (!is_tx_channel_valid(dev, channel)) { + return -EINVAL; + } + + /* + * Locking and unlocking the hardware semaphore + * causes an interrupt on the receiving side. + */ + z_stm32_hsem_lock(MBOX_TX_HSEM_ID, HSEM_LOCK_DEFAULT_RETRY); + z_stm32_hsem_unlock(MBOX_TX_HSEM_ID); + + return 0; +} + +static int mbox_stm32_hsem_register_callback(const struct device *dev, uint32_t channel, + mbox_callback_t cb, void *user_data) +{ + struct mbox_stm32_hsem_data *data = dev->data; + + if (!(is_rx_channel_valid(dev, channel))) { + return -EINVAL; + } + + data->cb = cb; + data->user_data = user_data; + + return 0; +} + +static int mbox_stm32_hsem_mtu_get(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* We only support signalling */ + return 0; +} + +static uint32_t mbox_stm32_hsem_max_channels_get(const struct device *dev) +{ + ARG_UNUSED(dev); + + /* Only two channels supported, one RX and one TX */ + return MAX_CHANNELS; +} + +static int mbox_stm32_hsem_set_enabled(const struct device *dev, uint32_t channel, bool enable) +{ + if (!is_rx_channel_valid(dev, channel)) { + return -EINVAL; + } + + if (enable) { + stm32_hsem_clear_rx_interrupt(); + stm32_hsem_enable_rx_interrupt(); + } else { + stm32_hsem_disable_rx_interrupt(); + } + + return 0; +} + +#if HSEM_CPU_ID == HSEM_CPU1 +static int mbox_stm32_clock_init(const struct device *dev) +{ + const struct mbox_stm32_hsem_conf *cfg = dev->config; + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + + if (!device_is_ready(clk)) { + LOG_ERR("Clock control device not ready."); + return -ENODEV; + } + + if (clock_control_on(clk, (clock_control_subsys_t *)&cfg->pclken) != 0) { + LOG_WRN("Failed to enable clock."); + return -EIO; + } + + return 0; +} +#endif /* HSEM_CPU_ID */ + +static int mbox_stm32_hsem_init(const struct device *dev) +{ + struct mbox_stm32_hsem_data *data = dev->data; + int ret = 0; + + data->dev = dev; + +#if HSEM_CPU_ID == HSEM_CPU1 + ret = mbox_stm32_clock_init(dev); + + if (ret != 0) { + return ret; + } +#endif /* HSEM_CPU_ID */ + + /* Configure interrupt service routine */ + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + mbox_dispatcher, DEVICE_DT_INST_GET(0), 0); + + irq_enable(DT_INST_IRQN(0)); + + return ret; +} + +static const struct mbox_driver_api mbox_stm32_hsem_driver_api = { + .send = mbox_stm32_hsem_send, + .register_callback = mbox_stm32_hsem_register_callback, + .mtu_get = mbox_stm32_hsem_mtu_get, + .max_channels_get = mbox_stm32_hsem_max_channels_get, + .set_enabled = mbox_stm32_hsem_set_enabled, +}; + +DEVICE_DT_INST_DEFINE( + 0, + mbox_stm32_hsem_init, + NULL, + &stm32_hsem_mbox_data, + &stm32_hsem_mbox_conf, + POST_KERNEL, + CONFIG_MBOX_INIT_PRIORITY, + &mbox_stm32_hsem_driver_api); diff --git a/drivers/mdio/mdio_nxp_enet.c b/drivers/mdio/mdio_nxp_enet.c index f91158ed505cc..896de74790329 100644 --- a/drivers/mdio/mdio_nxp_enet.c +++ b/drivers/mdio/mdio_nxp_enet.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -14,11 +14,10 @@ #include #include #include -#include struct nxp_enet_mdio_config { - ENET_Type *base; const struct pinctrl_dev_config *pincfg; + const struct device *module_dev; const struct device *clock_dev; clock_control_subsys_t clock_subsys; uint32_t mdc_freq; @@ -27,6 +26,7 @@ struct nxp_enet_mdio_config { }; struct nxp_enet_mdio_data { + ENET_Type *base; struct k_mutex mdio_mutex; struct k_sem mdio_sem; bool interrupt_up; @@ -43,7 +43,7 @@ static int nxp_enet_mdio_wait_xfer(const struct device *dev) { const struct nxp_enet_mdio_config *config = dev->config; struct nxp_enet_mdio_data *data = dev->data; - ENET_Type *base = config->base; + ENET_Type *base = data->base; int ret = 0; /* This function will not make sense from IRQ context */ @@ -83,7 +83,6 @@ static int nxp_enet_mdio_wait_xfer(const struct device *dev) static int nxp_enet_mdio_read(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t *read_data) { - const struct nxp_enet_mdio_config *config = dev->config; struct nxp_enet_mdio_data *data = dev->data; int ret; @@ -94,7 +93,7 @@ static int nxp_enet_mdio_read(const struct device *dev, * Clear the bit (W1C) that indicates MDIO transfer is ready to * prepare to wait for it to be set once this read is done */ - config->base->EIR |= ENET_EIR_MII_MASK; + data->base->EIR |= ENET_EIR_MII_MASK; /* * Write MDIO frame to MII management register which will @@ -106,7 +105,7 @@ static int nxp_enet_mdio_read(const struct device *dev, * TA = Turnaround, must be 2 to be valid * data = data to be written to the PHY register */ - config->base->MMFR = ENET_MMFR_ST(0x1U) | + data->base->MMFR = ENET_MMFR_ST(0x1U) | ENET_MMFR_OP(MDIO_OP_C22_READ) | ENET_MMFR_PA(prtad) | ENET_MMFR_RA(regad) | @@ -119,10 +118,10 @@ static int nxp_enet_mdio_read(const struct device *dev, } /* The data is received in the same register that we wrote the command to */ - *read_data = (config->base->MMFR & ENET_MMFR_DATA_MASK) >> ENET_MMFR_DATA_SHIFT; + *read_data = (data->base->MMFR & ENET_MMFR_DATA_MASK) >> ENET_MMFR_DATA_SHIFT; /* Clear the same bit as before because the event has been handled */ - config->base->EIR |= ENET_EIR_MII_MASK; + data->base->EIR |= ENET_EIR_MII_MASK; /* This MDIO interaction is finished */ (void)k_mutex_unlock(&data->mdio_mutex); @@ -134,7 +133,6 @@ static int nxp_enet_mdio_read(const struct device *dev, static int nxp_enet_mdio_write(const struct device *dev, uint8_t prtad, uint8_t regad, uint16_t write_data) { - const struct nxp_enet_mdio_config *config = dev->config; struct nxp_enet_mdio_data *data = dev->data; int ret; @@ -145,7 +143,7 @@ static int nxp_enet_mdio_write(const struct device *dev, * Clear the bit (W1C) that indicates MDIO transfer is ready to * prepare to wait for it to be set once this write is done */ - config->base->EIR |= ENET_EIR_MII_MASK; + data->base->EIR |= ENET_EIR_MII_MASK; /* * Write MDIO frame to MII management register which will @@ -157,7 +155,7 @@ static int nxp_enet_mdio_write(const struct device *dev, * TA = Turnaround, must be 2 to be valid * data = data to be written to the PHY register */ - config->base->MMFR = ENET_MMFR_ST(0x1U) | + data->base->MMFR = ENET_MMFR_ST(0x1U) | ENET_MMFR_OP(MDIO_OP_C22_WRITE) | ENET_MMFR_PA(prtad) | ENET_MMFR_RA(regad) | @@ -171,7 +169,7 @@ static int nxp_enet_mdio_write(const struct device *dev, } /* Clear the same bit as before because the event has been handled */ - config->base->EIR |= ENET_EIR_MII_MASK; + data->base->EIR |= ENET_EIR_MII_MASK; /* This MDIO interaction is finished */ (void)k_mutex_unlock(&data->mdio_mutex); @@ -186,19 +184,19 @@ static const struct mdio_driver_api nxp_enet_mdio_api = { static void nxp_enet_mdio_isr_cb(const struct device *dev) { - const struct nxp_enet_mdio_config *config = dev->config; struct nxp_enet_mdio_data *data = dev->data; /* Signal that operation finished */ k_sem_give(&data->mdio_sem); /* Disable the interrupt */ - config->base->EIMR &= ~ENET_EIMR_MII_MASK; + data->base->EIMR &= ~ENET_EIMR_MII_MASK; } static void nxp_enet_mdio_post_module_reset_init(const struct device *dev) { const struct nxp_enet_mdio_config *config = dev->config; + struct nxp_enet_mdio_data *data = dev->data; uint32_t enet_module_clock_rate; /* Set up MSCR register */ @@ -210,7 +208,7 @@ static void nxp_enet_mdio_post_module_reset_init(const struct device *dev) (NSEC_PER_SEC / enet_module_clock_rate) - 1; uint32_t mscr = ENET_MSCR_MII_SPEED(mii_speed) | ENET_MSCR_HOLDTIME(holdtime) | (config->disable_preamble ? ENET_MSCR_DIS_PRE_MASK : 0); - config->base->MSCR = mscr; + data->base->MSCR = mscr; } void nxp_enet_mdio_callback(const struct device *dev, @@ -241,6 +239,8 @@ static int nxp_enet_mdio_init(const struct device *dev) struct nxp_enet_mdio_data *data = dev->data; int ret = 0; + data->base = (ENET_Type *)DEVICE_MMIO_GET(config->module_dev); + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); if (ret) { return ret; @@ -266,7 +266,7 @@ static int nxp_enet_mdio_init(const struct device *dev) PINCTRL_DT_INST_DEFINE(inst); \ \ static const struct nxp_enet_mdio_config nxp_enet_mdio_cfg_##inst = { \ - .base = (ENET_Type *) DT_REG_ADDR(DT_INST_PARENT(inst)), \ + .module_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ .timeout = CONFIG_MDIO_NXP_ENET_TIMEOUT, \ .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(inst))), \ diff --git a/drivers/memc/CMakeLists.txt b/drivers/memc/CMakeLists.txt index 2e020548610bd..1648343c18f00 100644 --- a/drivers/memc/CMakeLists.txt +++ b/drivers/memc/CMakeLists.txt @@ -23,3 +23,4 @@ if((DEFINED CONFIG_FLASH_MCUX_FLEXSPI_XIP) AND (DEFINED CONFIG_FLASH)) endif() zephyr_library_sources_ifdef(CONFIG_MEMC_NXP_S32_QSPI memc_nxp_s32_qspi.c) +zephyr_library_sources_ifdef(CONFIG_MEMC_SMARTBOND memc_smartbond_nor_psram.c) diff --git a/drivers/memc/Kconfig b/drivers/memc/Kconfig index f64165573556c..afab61994af1a 100644 --- a/drivers/memc/Kconfig +++ b/drivers/memc/Kconfig @@ -31,4 +31,6 @@ source "drivers/memc/Kconfig.sifive" source "drivers/memc/Kconfig.nxp_s32" +source "drivers/memc/Kconfig.smartbond" + endif diff --git a/drivers/memc/Kconfig.mcux b/drivers/memc/Kconfig.mcux index 6d2f30933e96c..dd6c2da48f443 100644 --- a/drivers/memc/Kconfig.mcux +++ b/drivers/memc/Kconfig.mcux @@ -30,6 +30,26 @@ config MEMC_MCUX_FLEXSPI_IS66WVQ8M4 depends on DT_HAS_NXP_IMX_FLEXSPI_IS66WVQ8M4_ENABLED select MEMC_MCUX_FLEXSPI +config MEMC_MCUX_FLEXSPI_INIT_PRIORITY + int "MCUX FLEXSPI MEMC driver initialization priority" + default MEMC_INIT_PRIORITY + help + Initialization priority for FlexSPI MEMC driver. In cases where the + flash driver must initialize before the MEMC RAM driver, + initialization priorities can be set such that + MEMC_MCUX_FLEXSPI_INIT_PRIORITY < FLASH_INIT_PRIORITY < + MEMC_INIT_PRIORITY + +config MEMC_MCUX_FLEXSPI_INIT_XIP + bool "Initialize FLEXSPI when using device for XIP" + help + Initialize the FLEXSPI device even when using it for XIP. If this + Kconfig is enabled, the user must ensure that the pin control + state used does not reconfigure the pins used to interface with + the flash device used for XIP, and that the configuration settings + used for the FLEXSPI are compatible with those needed for XIP from + the flash device. + config MEMC_MCUX_FLEXSPI bool select PINCTRL diff --git a/drivers/memc/Kconfig.smartbond b/drivers/memc/Kconfig.smartbond new file mode 100644 index 0000000000000..32cb8c94f467e --- /dev/null +++ b/drivers/memc/Kconfig.smartbond @@ -0,0 +1,11 @@ +# Smartbond Cryptographic Accelerator configuration options + +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +config MEMC_SMARTBOND + bool "Smartbond NOR/PSRAM memory controller" + depends on DT_HAS_RENESAS_SMARTBOND_NOR_PSRAM_ENABLED + default y + help + Enable Smartbond NOR/PSRAM memory controller. diff --git a/drivers/memc/memc_mcux_flexspi.c b/drivers/memc/memc_mcux_flexspi.c index 951d3f99a1e94..c3ad20aab4b2d 100644 --- a/drivers/memc/memc_mcux_flexspi.c +++ b/drivers/memc/memc_mcux_flexspi.c @@ -188,9 +188,12 @@ int memc_flexspi_set_device_config(const struct device *dev, /* Update lut offset with new value */ data->port_luts[port].lut_offset = lut_used; } - data->port_luts[port].lut_used = lut_count; - tmp_config.ARDSeqIndex += data->port_luts[port].lut_offset; - tmp_config.AWRSeqIndex += data->port_luts[port].lut_offset; + /* LUTs should only be installed on sequence boundaries, every + * 4 entries. Round LUT usage up to nearest sequence + */ + data->port_luts[port].lut_used = ROUND_UP(lut_count, 4); + tmp_config.ARDSeqIndex += data->port_luts[port].lut_offset / MEMC_FLEXSPI_CMD_PER_SEQ; + tmp_config.AWRSeqIndex += data->port_luts[port].lut_offset / MEMC_FLEXSPI_CMD_PER_SEQ; /* Lock IRQs before reconfiguring FlexSPI, to prevent XIP */ key = irq_lock(); @@ -215,12 +218,29 @@ int memc_flexspi_reset(const struct device *dev) int memc_flexspi_transfer(const struct device *dev, flexspi_transfer_t *transfer) { + flexspi_transfer_t tmp; struct memc_flexspi_data *data = dev->data; status_t status; + uint32_t seq_off, addr_offset = 0U; + int i; - /* Adjust transfer LUT index based on port */ - transfer->seqIndex += data->port_luts[transfer->port].lut_offset; - status = FLEXSPI_TransferBlocking(data->base, transfer); + /* Calculate sequence offset and address offset based on port */ + seq_off = data->port_luts[transfer->port].lut_offset / + MEMC_FLEXSPI_CMD_PER_SEQ; + for (i = 0; i < transfer->port; i++) { + addr_offset += data->size[i]; + } + + if ((seq_off != 0) || (addr_offset != 0)) { + /* Adjust device address and sequence index for transfer */ + memcpy(&tmp, transfer, sizeof(tmp)); + tmp.seqIndex += seq_off; + tmp.deviceAddress += addr_offset; + status = FLEXSPI_TransferBlocking(data->base, &tmp); + } else { + /* Transfer does not need adjustment */ + status = FLEXSPI_TransferBlocking(data->base, transfer); + } if (status != kStatus_Success) { LOG_ERR("Transfer error: %d", status); @@ -260,19 +280,21 @@ static int memc_flexspi_init(const struct device *dev) { struct memc_flexspi_data *data = dev->data; flexspi_config_t flexspi_config; + uint32_t flash_sizes[kFLEXSPI_PortCount]; + int ret; + uint8_t i; /* we should not configure the device we are running on */ if (memc_flexspi_is_running_xip(dev)) { - LOG_DBG("XIP active on %s, skipping init", dev->name); - return 0; + if (!IS_ENABLED(CONFIG_MEMC_MCUX_FLEXSPI_INIT_XIP)) { + LOG_DBG("XIP active on %s, skipping init", dev->name); + return 0; + } } - /* * SOCs such as the RT1064 and RT1024 have internal flash, and no pinmux * settings, continue if no pinctrl state found. */ - int ret; - ret = pinctrl_apply_state(data->pincfg, PINCTRL_STATE_DEFAULT); if (ret < 0 && ret != -ENOENT) { return ret; @@ -308,7 +330,7 @@ FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB /* Configure AHB RX buffers, if any configuration settings are present */ __ASSERT(data->buf_cfg_cnt < FSL_FEATURE_FLEXSPI_AHB_BUFFER_COUNT, "Maximum RX buffer configuration count exceeded"); - for (uint8_t i = 0; i < data->buf_cfg_cnt; i++) { + for (i = 0; i < data->buf_cfg_cnt; i++) { /* Should AHB prefetch up to buffer size? */ flexspi_config.ahbConfig.buffer[i].enablePrefetch = data->buf_cfg[i].prefetch; /* AHB access priority (used for suspending control of AHB prefetching )*/ @@ -319,8 +341,25 @@ FSL_FEATURE_FLEXSPI_SUPPORT_SEPERATE_RXCLKSRC_PORTB flexspi_config.ahbConfig.buffer[i].bufferSize = data->buf_cfg[i].buf_size; } + if (memc_flexspi_is_running_xip(dev)) { + /* Save flash sizes- FlexSPI init will reset them */ + for (i = 0; i < kFLEXSPI_PortCount; i++) { + flash_sizes[i] = data->base->FLSHCR0[i]; + } + } + FLEXSPI_Init(data->base, &flexspi_config); + if (memc_flexspi_is_running_xip(dev)) { + /* Restore flash sizes */ + for (i = 0; i < kFLEXSPI_PortCount; i++) { + data->base->FLSHCR0[i] = flash_sizes[i]; + } + + /* Reenable FLEXSPI module */ + data->base->MCR0 &= ~FLEXSPI_MCR0_MDIS_MASK; + } + return 0; } @@ -404,7 +443,7 @@ static int memc_flexspi_pm_action(const struct device *dev, enum pm_device_actio &memc_flexspi_data_##n, \ NULL, \ POST_KERNEL, \ - CONFIG_MEMC_INIT_PRIORITY, \ + CONFIG_MEMC_MCUX_FLEXSPI_INIT_PRIORITY, \ NULL); DT_INST_FOREACH_STATUS_OKAY(MEMC_FLEXSPI) diff --git a/drivers/memc/memc_mcux_flexspi.h b/drivers/memc/memc_mcux_flexspi.h index 707d9f088cc37..6863649bc94a5 100644 --- a/drivers/memc/memc_mcux_flexspi.h +++ b/drivers/memc/memc_mcux_flexspi.h @@ -57,7 +57,7 @@ int memc_flexspi_update_clock(const struct device *dev, * @param dev: FlexSPI device * @param device_config: External device configuration. * @param lut_array: Lookup table of FlexSPI flash commands for device - * @param lut_count: number of command entries (16 bytes each) in LUT + * @param lut_count: number of LUT entries (4 bytes each) in lut array * @param port: FlexSPI port to use for this external device * @return 0 on success, negative value on failure */ diff --git a/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c b/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c index e3ba54f2a5d68..7ce698b3dd650 100644 --- a/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c +++ b/drivers/memc/memc_mcux_flexspi_is66wvq8m4.c @@ -169,8 +169,6 @@ static int memc_flexspi_is66wvq8m4_init(const struct device *dev) return -EINVAL; } - memc_flexspi_reset(data->controller); - if (memc_flexspi_is66wvq8m4_get_vendor_id(dev, &vendor_id)) { LOG_ERR("Could not read vendor id"); return -EIO; diff --git a/drivers/memc/memc_smartbond_nor_psram.c b/drivers/memc/memc_smartbond_nor_psram.c new file mode 100644 index 0000000000000..37584f99dcc9b --- /dev/null +++ b/drivers/memc/memc_smartbond_nor_psram.c @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT renesas_smartbond_nor_psram + +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(smartbond_nor_psram, CONFIG_MEMC_LOG_LEVEL); + +#define CLK_AMBA_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(CRG_TOP_CLK_AMBA_REG_ ## _field ## _Msk)) | \ + (((_val) << CRG_TOP_CLK_AMBA_REG_ ## _field ## _Pos) & \ + CRG_TOP_CLK_AMBA_REG_ ## _field ## _Msk) + +#define QSPIC2_CTRLMODE_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(QSPIC2_QSPIC2_CTRLMODE_REG_ ## _field ## _Msk)) | \ + (((_val) << QSPIC2_QSPIC2_CTRLMODE_REG_ ## _field ## _Pos) & \ + QSPIC2_QSPIC2_CTRLMODE_REG_ ## _field ## _Msk) + +#define QSPIC2_BURSTCMDA_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(QSPIC2_QSPIC2_BURSTCMDA_REG_ ## _field ## _Msk)) | \ + (((_val) << QSPIC2_QSPIC2_BURSTCMDA_REG_ ## _field ## _Pos) & \ + QSPIC2_QSPIC2_BURSTCMDA_REG_ ## _field ## _Msk) + +#define QSPIC2_BURSTCMDB_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(QSPIC2_QSPIC2_BURSTCMDB_REG_ ## _field ## _Msk)) | \ + (((_val) << QSPIC2_QSPIC2_BURSTCMDB_REG_ ## _field ## _Pos) & \ + QSPIC2_QSPIC2_BURSTCMDB_REG_ ## _field ## _Msk) + +#define QSPIC2_AWRITECMD_REG_SET_FIELD(_field, _var, _val) \ + ((_var)) = \ + ((_var) & ~(QSPIC2_QSPIC2_AWRITECMD_REG_ ## _field ## _Msk)) | \ + (((_val) << QSPIC2_QSPIC2_AWRITECMD_REG_ ## _field ## _Pos) & \ + QSPIC2_QSPIC2_AWRITECMD_REG_ ## _field ## _Msk) + +static void memc_set_status(bool status, int clk_div) +{ + unsigned int key; + uint32_t clk_amba_reg; + + /* Clock AMBA register might be accessed by multiple driver classes */ + key = irq_lock(); + clk_amba_reg = CRG_TOP->CLK_AMBA_REG; + + if (status) { + CLK_AMBA_REG_SET_FIELD(QSPI2_ENABLE, clk_amba_reg, 1); + CLK_AMBA_REG_SET_FIELD(QSPI2_DIV, clk_amba_reg, clk_div); + } else { + CLK_AMBA_REG_SET_FIELD(QSPI2_ENABLE, clk_amba_reg, 0); + } + + CRG_TOP->CLK_AMBA_REG = clk_amba_reg; + irq_unlock(key); +} + +static void memc_automode_configure(void) +{ + uint32_t reg; + + reg = QSPIC2->QSPIC2_CTRLMODE_REG; + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_SRAM_EN, reg, + DT_INST_PROP(0, is_ram)); + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_USE_32BA, reg, + DT_INST_ENUM_IDX(0, addr_range)); + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_CLK_MD, reg, + DT_INST_ENUM_IDX(0, clock_mode)); + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_AUTO_MD, reg, 1); + QSPIC2->QSPIC2_CTRLMODE_REG = reg; + + reg = QSPIC2->QSPIC2_BURSTCMDA_REG; + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_DMY_TX_MD, reg, + DT_INST_ENUM_IDX(0, rx_dummy_mode)); + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_ADR_TX_MD, reg, + DT_INST_ENUM_IDX(0, rx_addr_mode)); + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_INST_TX_MD, reg, + DT_INST_ENUM_IDX(0, rx_inst_mode)); + #if DT_INST_PROP(0, extra_byte_enable) + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_EXT_TX_MD, reg, + DT_INST_ENUM_IDX(0, rx_extra_mode)); + #endif + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_INST, reg, + DT_INST_PROP(0, read_cmd)); + #if DT_INST_PROP(0, extra_byte_enable) + QSPIC2_BURSTCMDA_REG_SET_FIELD(QSPIC_EXT_BYTE, reg, + DT_INST_PROP(0, extra_byte)); + #endif + QSPIC2->QSPIC2_BURSTCMDA_REG = reg; + + reg = QSPIC2->QSPIC2_BURSTCMDB_REG; + QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_DMY_NUM, reg, + DT_INST_ENUM_IDX(0, dummy_bytes_count)); + QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_DAT_RX_MD, reg, + DT_INST_ENUM_IDX(0, rx_data_mode)); + QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_INST_MD, reg, 0); + QSPIC2_BURSTCMDB_REG_SET_FIELD(QSPIC_EXT_BYTE_EN, reg, + DT_INST_PROP(0, extra_byte_enable)); + QSPIC2->QSPIC2_BURSTCMDB_REG = reg; + + reg = QSPIC2->QSPIC2_AWRITECMD_REG; + QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_DAT_TX_MD, reg, + DT_INST_ENUM_IDX(0, tx_data_mode)); + QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_ADR_TX_MD, reg, + DT_INST_ENUM_IDX(0, tx_addr_mode)); + QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_INST_TX_MD, reg, + DT_INST_ENUM_IDX(0, tx_inst_mode)); + QSPIC2_AWRITECMD_REG_SET_FIELD(QSPIC_WR_INST, reg, + DT_INST_PROP(0, write_cmd)); + QSPIC2->QSPIC2_AWRITECMD_REG = reg; +} + +/* Read PSRAM/NOR device ID using JEDEC commands. */ +static bool memc_jedec_read_and_verify_id(QSPIC_TYPE qspi_id) +{ + uint16_t device_density; + bool ret = 0; + qspi_memory_id_t memory_id; + + da1469x_qspi_memory_jedec_read_id(qspi_id, &memory_id); + + device_density = DT_INST_PROP(0, dev_density); + ret |= !(memory_id.id == DT_INST_PROP(0, dev_id)); + ret |= !(memory_id.type == DT_INST_PROP(0, dev_type)); + ret |= !((memory_id.density & (device_density >> 8)) == (device_density & 0xFF)); + + return ret; +} + +static int memc_smartbond_init(const struct device *dev) +{ + uint32_t qspic_ctrlmode_reg; + + /* First QSPI controller is enabled so registers can be accessed */ + memc_set_status(true, DT_INST_PROP_OR(0, clock_div, 0)); + + /* Apply the min. required settings before performing any transaction in manual mode. */ + qspic_ctrlmode_reg = QSPIC2->QSPIC2_CTRLMODE_REG; + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_CLK_MD, qspic_ctrlmode_reg, + DT_INST_ENUM_IDX(0, clock_mode)); + QSPIC2_CTRLMODE_REG_SET_FIELD(QSPIC_AUTO_MD, qspic_ctrlmode_reg, 0); + QSPIC2->QSPIC2_CTRLMODE_REG = qspic_ctrlmode_reg; + + /* Reset PSRAM/NOR device using JDEC commands */ + da1469x_qspi_memory_jedec_reset(QSPIC2_ID); + + /* Wait till reset is completed */ + k_usleep(DT_INST_PROP(0, reset_delay_us)); + + if (memc_jedec_read_and_verify_id(QSPIC2_ID)) { + LOG_ERR("Device detection failed"); + memc_set_status(false, 0); + + return -EINVAL; + } + +#if DT_INST_PROP(0, enter_qpi_mode) + da1469x_qspi_enter_exit_qpi_mode(QSPIC2_ID, true, DT_INST_PROP(0, enter_qpi_cmd)); +#endif + + /* Should be called prior to switching to auto mode and when the quad bus is selected! */ + da1469x_qspi_set_bus_mode(QSPIC2_ID, QSPI_BUS_MODE_QUAD); + +#if CONFIG_PM_DEVICE_RUNTIME + /* + * Turn off the controller to minimize power consumption. Application is responsible to + * configure/de-configure the controller before interacting with the memory. + */ + memc_set_status(false, 0); + + /* Make sure device is marked as suspended */ + pm_device_init_suspended(dev); + + return pm_device_runtime_enable(dev); +#else + da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); + + /* From this point onwards memory device should be seen as memory mapped device. */ + memc_automode_configure(); +#endif + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static int memc_smartbond_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_SUSPEND: + /* + * CLK_AMBA_REG, that controlls QSPIC2, is retained during sleep + * (resides in PD_AON). However, unused blocks should be disabled + * to minimize power consumption at sleep. + */ + memc_set_status(false, 0); + + da1469x_pd_release(MCU_PD_DOMAIN_SYS); + break; + case PM_DEVICE_ACTION_RESUME: + + /* + * Mainly, required when in PM runtime mode. When in PM static mode, + * the device will block till an ongoing/pending AMBA bus transfer + * completes. + */ + da1469x_pd_acquire(MCU_PD_DOMAIN_SYS); + + /* + * QSPIC2 is powered by PD_SYS which is turned off during sleep and + * so QSPIC2 auto mode re-initialization is required. + * + * XXX: It's assumed that memory device's power rail, that should + * be 1V8P, is not turned off and so the device itsef does not + * require re-initialization. Revisit this part if power settings + * are changed in the future, that should include: + * + * 1. Powering off the memory device by turning off 1V8P + * (valid for FLASH/PSRAM). + * 2. Powering down the memory device so it enters the suspend/low-power + * state during sleep (valid for FLASH/NOR devices). + */ + memc_set_status(true, DT_INST_PROP_OR(0, clock_div, 0)); + memc_automode_configure(); + default: + return -ENOTSUP; + } + + return 0; +} +#endif + +#define SMARTBOND_MEMC_INIT(inst) \ + BUILD_ASSERT(inst == 0, "multiple instances are not permitted"); \ + BUILD_ASSERT(DT_INST_PROP(inst, is_ram), \ + "current driver version suports only PSRAM devices"); \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, memc_smartbond_pm_action); \ + \ + DEVICE_DT_INST_DEFINE(inst, memc_smartbond_init, PM_DEVICE_DT_INST_GET(inst), \ + NULL, NULL, \ + POST_KERNEL, CONFIG_MEMC_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(SMARTBOND_MEMC_INIT) diff --git a/drivers/mfd/CMakeLists.txt b/drivers/mfd/CMakeLists.txt index bcd9b190e1563..fa6ab5ddceda0 100644 --- a/drivers/mfd/CMakeLists.txt +++ b/drivers/mfd/CMakeLists.txt @@ -3,6 +3,7 @@ zephyr_library() +zephyr_library_sources_ifdef(CONFIG_MFD_ADP5585 mfd_adp5585.c) zephyr_library_sources_ifdef(CONFIG_MFD_MAX20335 mfd_max20335.c) zephyr_library_sources_ifdef(CONFIG_MFD_NCT38XX mfd_nct38xx.c) zephyr_library_sources_ifdef(CONFIG_MFD_NPM1300 mfd_npm1300.c) diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b487c3556b00e..c384249daed3e 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -19,6 +19,7 @@ config MFD_INIT_PRIORITY Multi-function devices initialization priority. source "drivers/mfd/Kconfig.ad559x" +source "drivers/mfd/Kconfig.adp5585" source "drivers/mfd/Kconfig.axp192" source "drivers/mfd/Kconfig.bd8lb600fs" source "drivers/mfd/Kconfig.max20335" diff --git a/drivers/mfd/Kconfig.ad559x b/drivers/mfd/Kconfig.ad559x index 1597f60e3b244..ff0a49549428d 100644 --- a/drivers/mfd/Kconfig.ad559x +++ b/drivers/mfd/Kconfig.ad559x @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 menuconfig MFD_AD559X bool "Analog AD559x I2C/SPI configurable ADC/DAC/GPIO chip" diff --git a/drivers/mfd/Kconfig.adp5585 b/drivers/mfd/Kconfig.adp5585 new file mode 100644 index 0000000000000..e08f119a72cbc --- /dev/null +++ b/drivers/mfd/Kconfig.adp5585 @@ -0,0 +1,17 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +menuconfig MFD_ADP5585 + bool "Analog ADP5585 I2C configurable GPIO/PWM/KeyScan chip" + default y + depends on DT_HAS_ADI_ADP5585_ENABLED + depends on I2C + help + Enable driver for Analog ADP5585. + +config MFD_ADP5585_INIT_PRIORITY + int "Init priority" + default 65 + depends on MFD_ADP5585 + help + Device driver initialization priority. diff --git a/drivers/mfd/Kconfig.axp192 b/drivers/mfd/Kconfig.axp192 index fed776d365645..da76c4cc615a8 100644 --- a/drivers/mfd/Kconfig.axp192 +++ b/drivers/mfd/Kconfig.axp192 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Martin Kiepfer -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_AXP192 bool "AXP192 PMIC multi-function device driver" diff --git a/drivers/mfd/Kconfig.bd8lb600fs b/drivers/mfd/Kconfig.bd8lb600fs index 4029f1f2e85cb..752eb942fe41e 100644 --- a/drivers/mfd/Kconfig.bd8lb600fs +++ b/drivers/mfd/Kconfig.bd8lb600fs @@ -1,5 +1,5 @@ # Copyright (c) 2024 SILA Embedded Solutions GmbH -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_BD8LB600FS bool "BD8LB600FS low side switch multi-function device driver" diff --git a/drivers/mfd/Kconfig.max20335 b/drivers/mfd/Kconfig.max20335 index 3d146de17f089..bc9ee006edc17 100644 --- a/drivers/mfd/Kconfig.max20335 +++ b/drivers/mfd/Kconfig.max20335 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_MAX20335 bool "MAX20335 PMIC multi-function device driver" diff --git a/drivers/mfd/Kconfig.max31790 b/drivers/mfd/Kconfig.max31790 index 2c542982d9fb0..1e2e9ac4e111a 100644 --- a/drivers/mfd/Kconfig.max31790 +++ b/drivers/mfd/Kconfig.max31790 @@ -1,5 +1,5 @@ # Copyright (c) 2024 SILA Embedded Solutions GmbH -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_MAX31790 bool "Maxim Integrated MAX31790 I2C configurable PWM controller" diff --git a/drivers/mfd/Kconfig.nct38xx b/drivers/mfd/Kconfig.nct38xx index aa852d974bb1b..743e07689b6a5 100644 --- a/drivers/mfd/Kconfig.nct38xx +++ b/drivers/mfd/Kconfig.nct38xx @@ -1,5 +1,5 @@ # Copyright (c) 2023 Google, LLC -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_NCT38XX bool "Nuvton NCT38xx multi-function device driver" diff --git a/drivers/mfd/Kconfig.npm1300 b/drivers/mfd/Kconfig.npm1300 index 506508bd90210..56a54f3005ab8 100644 --- a/drivers/mfd/Kconfig.npm1300 +++ b/drivers/mfd/Kconfig.npm1300 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_NPM1300 bool "nPM1300 PMIC multi-function device driver" diff --git a/drivers/mfd/Kconfig.npm6001 b/drivers/mfd/Kconfig.npm6001 index b81c942f2d63c..46c0bc0d9c548 100644 --- a/drivers/mfd/Kconfig.npm6001 +++ b/drivers/mfd/Kconfig.npm6001 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_NPM6001 bool "nPM6001 PMIC multi-function device driver" diff --git a/drivers/mfd/Kconfig.tle9104 b/drivers/mfd/Kconfig.tle9104 index 8432e067adbf0..e102eec013b68 100644 --- a/drivers/mfd/Kconfig.tle9104 +++ b/drivers/mfd/Kconfig.tle9104 @@ -1,5 +1,5 @@ # Copyright (c) 2024 SILA Embedded Solutions GmbH -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MFD_TLE9104 bool "Infineon TLE9104 SPI powertrain switch" diff --git a/drivers/mfd/mfd_adp5585.c b/drivers/mfd/mfd_adp5585.c new file mode 100644 index 0000000000000..d57b82035dca4 --- /dev/null +++ b/drivers/mfd/mfd_adp5585.c @@ -0,0 +1,145 @@ +/* + * Copyright 2024 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_adp5585 + +#include +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(adp5585, CONFIG_GPIO_LOG_LEVEL); + +static int mfd_adp5585_software_reset(const struct device *dev) +{ + const struct mfd_adp5585_config *config = dev->config; + int ret = 0; + + /** Set CONFIG to gpio by default */ + uint8_t pin_config_buf[] = { ADP5585_PIN_CONFIG_A, 0x00U, 0x00U }; + + ret = i2c_write_dt(&config->i2c_bus, pin_config_buf, sizeof(pin_config_buf)); + if (ret) { + goto out; + } + +out: + if (ret) { + LOG_ERR("%s: software reset failed: %d", dev->name, ret); + } + return ret; +} + +static void mfd_adp5585_int_gpio_handler(const struct device *dev, struct gpio_callback *gpio_cb, + uint32_t pins) +{ + ARG_UNUSED(dev); + ARG_UNUSED(pins); + + struct mfd_adp5585_data *data = CONTAINER_OF(gpio_cb, struct mfd_adp5585_data, int_gpio_cb); + + k_work_submit(&data->work); +} + +static void mfd_adp5585_work_handler(struct k_work *work) +{ + struct mfd_adp5585_data *data = CONTAINER_OF(work, struct mfd_adp5585_data, work); + const struct mfd_adp5585_config *config = data->dev->config; + uint8_t reg_int_status; + int ret = 0; + + k_sem_take(&data->lock, K_FOREVER); + /* Read Interrput Flag */ + if (ret == 0) { + ret = i2c_reg_read_byte_dt(&config->i2c_bus, ADP5585_INT_STATUS, ®_int_status); + } + /* Clear Interrput Flag */ + if (ret == 0) { + ret = i2c_reg_write_byte_dt(&config->i2c_bus, ADP5585_INT_STATUS, reg_int_status); + } + + k_sem_give(&data->lock); + +#ifdef CONFIG_GPIO_ADP5585 + if ((reg_int_status & ADP5585_INT_GPI) && device_is_ready(data->child.gpio_dev)) { + (void)gpio_adp5585_irq_handler(data->child.gpio_dev); + } +#endif /* CONFIG_GPIO_ADP5585 */ +} + +static int mfd_adp5585_init(const struct device *dev) +{ + const struct mfd_adp5585_config *config = dev->config; + struct mfd_adp5585_data *data = dev->data; + int ret; + + if (!i2c_is_ready_dt(&config->i2c_bus)) { + return -ENODEV; + } + + /* reset gpio can be left float */ + if (gpio_is_ready_dt(&config->reset_gpio)) { + ret = gpio_pin_configure_dt(&config->reset_gpio, GPIO_OUTPUT_INACTIVE); + if (ret) { + LOG_ERR("%s: configure reset pin failed: %d", dev->name, ret); + return ret; + } + } else { + LOG_WRN("%s: reset pin not configured", dev->name); + } + + ret = mfd_adp5585_software_reset(dev); + if (ret) { + return ret; + } + + if (gpio_is_ready_dt(&config->nint_gpio)) { + ret = gpio_pin_configure_dt(&config->nint_gpio, GPIO_INPUT); + if (ret < 0) { + return ret; + } + ret = gpio_pin_interrupt_configure_dt(&config->nint_gpio, GPIO_INT_EDGE_TO_ACTIVE); + if (ret != 0) { + LOG_ERR("%s: failed to configure INT interrupt: %d", dev->name, ret); + return ret; + } + + gpio_init_callback(&data->int_gpio_cb, mfd_adp5585_int_gpio_handler, + BIT(config->nint_gpio.pin)); + ret = gpio_add_callback_dt(&config->nint_gpio, &data->int_gpio_cb); + if (ret != 0) { + LOG_ERR("%s: failed to add INT callback: %d", dev->name, ret); + return ret; + } + } else { + LOG_WRN("%s: nint pin not configured", dev->name); + } + + LOG_DBG("%s: init ok\r\n", dev->name); + + return 0; +} + +#define MFD_ADP5585_DEFINE(inst) \ + static const struct mfd_adp5585_config mfd_adp5585_config_##inst = { \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {0}), \ + .nint_gpio = GPIO_DT_SPEC_INST_GET_OR(n, nint_gpios, {0}), \ + .i2c_bus = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + static struct mfd_adp5585_data mfd_adp5585_data_##inst = { \ + .work = Z_WORK_INITIALIZER(mfd_adp5585_work_handler), \ + .lock = Z_SEM_INITIALIZER(mfd_adp5585_data_##inst.lock, 1, 1), \ + .dev = DEVICE_DT_INST_GET(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, mfd_adp5585_init, NULL, &mfd_adp5585_data_##inst, \ + &mfd_adp5585_config_##inst, POST_KERNEL, \ + CONFIG_MFD_ADP5585_INIT_PRIORITY, NULL); + +DT_INST_FOREACH_STATUS_OKAY(MFD_ADP5585_DEFINE); diff --git a/drivers/mipi_dbi/CMakeLists.txt b/drivers/mipi_dbi/CMakeLists.txt index fbcdc4d177b6b..5e9f475d151d6 100644 --- a/drivers/mipi_dbi/CMakeLists.txt +++ b/drivers/mipi_dbi/CMakeLists.txt @@ -5,3 +5,15 @@ zephyr_sources_ifdef(CONFIG_MIPI_DBI_SPI mipi_dbi_spi.c) zephyr_sources_ifdef(CONFIG_MIPI_DBI_SMARTBOND mipi_dbi_smartbond.c) zephyr_sources_ifdef(CONFIG_MIPI_DBI_NXP_LCDIC mipi_dbi_nxp_lcdic.c) +zephyr_sources_ifdef(CONFIG_MIPI_DBI_NXP_FLEXIO_LCDIF mipi_dbi_nxp_flexio_lcdif.c) +# Data bus width is used by the SDK driver and processes it as a compile time option +if(CONFIG_MIPI_DBI_NXP_FLEXIO_LCDIF) + dt_chosen(flexio0_lcd PROPERTY "zephyr,display") + dt_prop(data_bus_width PATH "${flexio0_lcd}" PROPERTY "mipi-mode") + # Values for mipi-mode property are defined inside dt-bindings/mipi_dbi/mipi_dbi.h. + # We pass a define to the SDK driver if we are using 8-bit mode. + if((data_bus_width EQUAL 8) OR (data_bus_width EQUAL 5)) + zephyr_compile_definitions(FLEXIO_MCULCD_DATA_BUS_WIDTH=8) + endif() + zephyr_compile_definitions(FLEXIO_MCULCD_LEGACY_GPIO_FUNC=0) +endif() diff --git a/drivers/mipi_dbi/Kconfig b/drivers/mipi_dbi/Kconfig index 16b7fc41c2d0a..51181ddd1e42c 100644 --- a/drivers/mipi_dbi/Kconfig +++ b/drivers/mipi_dbi/Kconfig @@ -24,5 +24,6 @@ config MIPI_DBI_INIT_PRIORITY source "drivers/mipi_dbi/Kconfig.spi" source "drivers/mipi_dbi/Kconfig.smartbond" source "drivers/mipi_dbi/Kconfig.nxp_lcdic" +source "drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif" endif diff --git a/drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif b/drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif new file mode 100644 index 0000000000000..ae4e2ad2d4b00 --- /dev/null +++ b/drivers/mipi_dbi/Kconfig.nxp_flexio_lcdif @@ -0,0 +1,12 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config MIPI_DBI_NXP_FLEXIO_LCDIF + bool "MIPI DBI driver for NXP Flexio LCDIF" + default y + depends on DT_HAS_NXP_MIPI_DBI_FLEXIO_LCDIF_ENABLED + depends on CLOCK_CONTROL + select MCUX_FLEXIO + select DMA + help + Enable support for MIPI DBI driver for NXP FlexIO based LCDIF controller. diff --git a/drivers/mipi_dbi/mipi_dbi_nxp_flexio_lcdif.c b/drivers/mipi_dbi/mipi_dbi_nxp_flexio_lcdif.c new file mode 100644 index 0000000000000..15156cc4fad06 --- /dev/null +++ b/drivers/mipi_dbi/mipi_dbi_nxp_flexio_lcdif.c @@ -0,0 +1,485 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_mipi_dbi_flexio_lcdif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(display_mcux_flexio_lcdif, CONFIG_DISPLAY_LOG_LEVEL); + +struct stream { + const struct device *dma_dev; + uint32_t channel; /* stores the channel for dma */ + struct dma_config dma_cfg; + struct dma_block_config dma_blk_cfg; +}; + +struct mcux_flexio_lcdif_config { + FLEXIO_MCULCD_Type *flexio_lcd_dev; + const struct device *flexio_dev; + const struct pinctrl_dev_config *pincfg; + const struct nxp_flexio_child *child; + /* Reset GPIO */ + const struct gpio_dt_spec reset; + const struct gpio_dt_spec cs_gpio; + const struct gpio_dt_spec rs_gpio; + const struct gpio_dt_spec rdwr_gpio; +}; + +struct mcux_flexio_lcdif_data { + struct stream dma_tx; + struct k_sem transfer_done; + const struct mipi_dbi_config *active_cfg; + uint8_t data_bus_width; +}; + +static void flexio_lcdif_dma_callback(const struct device *dev, void *arg, + uint32_t channel, int status) +{ + const struct device *flexio_dev = (struct device *)arg; + struct mcux_flexio_lcdif_data *lcdif_data = flexio_dev->data; + const struct mcux_flexio_lcdif_config *config = flexio_dev->config; + FLEXIO_MCULCD_Type *flexio_lcd = config->flexio_lcd_dev; + + FLEXIO_MCULCD_EnableTxDMA(flexio_lcd, false); + + /* Now the data are in shifter, wait for the data send out from the shifter. */ + FLEXIO_MCULCD_WaitTransmitComplete(); + + /* Disable the TX shifter and the timer. */ + FLEXIO_MCULCD_ClearMultiBeatsWriteConfig(flexio_lcd); + + /* De-assert nCS. */ + FLEXIO_MCULCD_StopTransfer(flexio_lcd); + + k_sem_give(&lcdif_data->transfer_done); +} + + +static void flexio_lcdif_set_cs(bool set, void *param) +{ + const struct device *flexio_dev = (struct device *)param; + const struct mcux_flexio_lcdif_config *config = flexio_dev->config; + + gpio_pin_set_dt(&config->cs_gpio, (int)set); +} + +static void flexio_lcdif_set_rs(bool set, void *param) +{ + const struct device *flexio_dev = (struct device *)param; + const struct mcux_flexio_lcdif_config *config = flexio_dev->config; + + gpio_pin_set_dt(&config->rs_gpio, (int)set); +} + +static void flexio_lcdif_set_rd_wr(bool set, void *param) +{ + const struct device *flexio_dev = (struct device *)param; + const struct mcux_flexio_lcdif_config *config = flexio_dev->config; + + gpio_pin_set_dt(&config->rdwr_gpio, (int)set); +} + +static edma_modulo_t flexio_lcdif_get_edma_modulo(uint8_t shifterNum) +{ + edma_modulo_t ret = kEDMA_ModuloDisable; + + switch (shifterNum) { + case 1U: + ret = kEDMA_Modulo4bytes; + break; + case 2U: + ret = kEDMA_Modulo8bytes; + break; + case 4U: + ret = kEDMA_Modulo16bytes; + break; + case 8U: + ret = kEDMA_Modulo32bytes; + break; + default: + ret = kEDMA_ModuloDisable; + break; + } + + return ret; +} + +static void flexio_lcdif_write_data_array(FLEXIO_MCULCD_Type *base, + const void *data, + size_t size) +{ + assert(size > 0U); + + uint32_t i; + const uint8_t *data8Bit; + FLEXIO_Type *flexioBase = base->flexioBase; + + /* Assert the RS pin. */ + base->setRSPin(true, base->userData); + /* For 6800, de-assert the RDWR pin. */ + if (kFLEXIO_MCULCD_6800 == base->busType) { + base->setRDWRPin(false, base->userData); + } + + /* Configure the timer and TX shifter. */ + FLEXIO_MCULCD_SetSingleBeatWriteConfig(base); + + data8Bit = (const uint8_t *)data; + + for (i = 0; i < size; i++) { + flexioBase->SHIFTBUF[base->txShifterStartIndex] = data8Bit[i]; + + /* Wait for the data send out. */ + while (0U == ((1UL << base->timerIndex) & flexioBase->TIMSTAT)) { + } + + /* Clear the timer stat. */ + flexioBase->TIMSTAT = 1UL << base->timerIndex; + } + + /* Stop the timer and TX shifter. */ + FLEXIO_MCULCD_ClearSingleBeatWriteConfig(base); +} + +static int mipi_dbi_flexio_lcdif_configure(const struct device *dev, + const struct mipi_dbi_config *dbi_config) +{ + const struct mcux_flexio_lcdif_config *config = dev->config; + struct mcux_flexio_lcdif_data *lcdif_data = dev->data; + flexio_mculcd_config_t flexioMcuLcdConfig; + int err; + uint32_t clock_freq; + uint32_t mipi_mode = dbi_config->mode; + status_t status; + + /* 9-bit mode is not supported by the SDK driver */ + if ((mipi_mode == MIPI_DBI_MODE_6800_BUS_9_BIT) || + (mipi_mode == MIPI_DBI_MODE_8080_BUS_9_BIT)) { + return -EINVAL; + } + + if (dbi_config == lcdif_data->active_cfg) { + return 0; + } + + err = gpio_pin_configure_dt(&config->cs_gpio, GPIO_OUTPUT_HIGH); + if (err) { + return err; + } + + err = gpio_pin_configure_dt(&config->rs_gpio, GPIO_OUTPUT_HIGH); + if (err) { + return err; + } + + if ((mipi_mode == MIPI_DBI_MODE_6800_BUS_16_BIT) || + (mipi_mode == MIPI_DBI_MODE_6800_BUS_8_BIT)) { + /* RDWR GPIO is only used in 68K mode */ + err = gpio_pin_configure_dt(&config->rdwr_gpio, GPIO_OUTPUT_HIGH); + if (err) { + return err; + } + config->flexio_lcd_dev->busType = kFLEXIO_MCULCD_6800; + } else { + config->flexio_lcd_dev->busType = kFLEXIO_MCULCD_8080; + } + + if ((mipi_mode == MIPI_DBI_MODE_6800_BUS_8_BIT) || + (mipi_mode == MIPI_DBI_MODE_8080_BUS_8_BIT)) { + lcdif_data->data_bus_width = 8; + } else { + lcdif_data->data_bus_width = 16; + } + + FLEXIO_MCULCD_GetDefaultConfig(&flexioMcuLcdConfig); + flexioMcuLcdConfig.baudRate_Bps = dbi_config->config.frequency * + lcdif_data->data_bus_width; + + if (nxp_flexio_get_rate(config->flexio_dev, &clock_freq)) { + return -EINVAL; + } + + nxp_flexio_lock(config->flexio_dev); + /* Resets the FlexIO module, then configures FlexIO MCULCD */ + status = FLEXIO_MCULCD_Init(config->flexio_lcd_dev, &flexioMcuLcdConfig, clock_freq); + nxp_flexio_unlock(config->flexio_dev); + + if (kStatus_Success != status) { + return -EINVAL; + } + + lcdif_data->active_cfg = dbi_config; + + return 0; +} + +static int mipi_dbi_flexio_ldcif_write_display(const struct device *dev, + const struct mipi_dbi_config *dbi_config, + const uint8_t *framebuf, + struct display_buffer_descriptor *desc, + enum display_pixel_format pixfmt) +{ + const struct mcux_flexio_lcdif_config *config = dev->config; + struct mcux_flexio_lcdif_data *lcdif_data = dev->data; + FLEXIO_MCULCD_Type *flexio_lcd = config->flexio_lcd_dev; + struct dma_block_config *blk_cfg; + struct stream *stream = &lcdif_data->dma_tx; + uint8_t num_of_shifters = 0; + int ret; + + ARG_UNUSED(pixfmt); + + ret = mipi_dbi_flexio_lcdif_configure(dev, dbi_config); + if (ret) { + return ret; + } + + num_of_shifters = (flexio_lcd->txShifterEndIndex - flexio_lcd->txShifterStartIndex + 1); + + blk_cfg = &stream->dma_blk_cfg; + + /* Assert the nCS. */ + FLEXIO_MCULCD_StartTransfer(config->flexio_lcd_dev); + + /* prepare the block for this TX DMA channel */ + memset(blk_cfg, 0, sizeof(struct dma_block_config)); + + /* tx direction has memory as source and periph as dest. */ + blk_cfg->source_address = (uint32_t)framebuf; + + /* Destination is FLEXIO Shifters */ + blk_cfg->dest_address = FLEXIO_MCULCD_GetTxDataRegisterAddress(flexio_lcd); + blk_cfg->block_size = desc->buf_size; + /* Transfer in each DMA loop is based on the number of shifters used */ + stream->dma_cfg.source_burst_length = num_of_shifters * 4; + + stream->dma_cfg.head_block = &stream->dma_blk_cfg; + /* Give the client dev as arg, as the callback comes from the dma */ + stream->dma_cfg.user_data = (struct device *)dev; + + /* Set the source size in bytes */ + stream->dma_cfg.source_data_size = lcdif_data->data_bus_width / 8; + + /* Configure the DMA */ + dma_config(lcdif_data->dma_tx.dma_dev, lcdif_data->dma_tx.channel, &stream->dma_cfg); + + /* The DMA driver does not support setting this Modulo value which is required + * in case of the flexio module to form a circular chain between the Shift buffer + * in the FLEXIO module. + */ + EDMA_SetModulo(DMA0, lcdif_data->dma_tx.channel, kEDMA_ModuloDisable, + flexio_lcdif_get_edma_modulo(num_of_shifters)); + + /* For 6800, de-assert the RDWR pin. */ + if (kFLEXIO_MCULCD_6800 == flexio_lcd->busType) { + flexio_lcdif_set_rd_wr(false, (void *)dev); + } + + nxp_flexio_lock(config->flexio_dev); + FLEXIO_MCULCD_SetMultiBeatsWriteConfig(flexio_lcd); + FLEXIO_MCULCD_EnableTxDMA(flexio_lcd, true); + nxp_flexio_unlock(config->flexio_dev); + + /* Start the data transfer */ + dma_start(lcdif_data->dma_tx.dma_dev, lcdif_data->dma_tx.channel); + + /* Wait for transfer done. */ + k_sem_take(&lcdif_data->transfer_done, K_FOREVER); + + return 0; +} + +static int mipi_dbi_flexio_lcdif_command_write(const struct device *dev, + const struct mipi_dbi_config *dbi_config, + uint8_t cmd, const uint8_t *data_buf, + size_t len) +{ + const struct mcux_flexio_lcdif_config *config = dev->config; + FLEXIO_MCULCD_Type *flexio_lcd = config->flexio_lcd_dev; + int ret; + + ARG_UNUSED(dbi_config); + + ret = mipi_dbi_flexio_lcdif_configure(dev, dbi_config); + if (ret) { + return ret; + } + + FLEXIO_MCULCD_StartTransfer(flexio_lcd); + + nxp_flexio_lock(config->flexio_dev); + + FLEXIO_MCULCD_WriteCommandBlocking(flexio_lcd, cmd); + + if ((data_buf != NULL) && (len != 0)) { + flexio_lcdif_write_data_array(flexio_lcd, data_buf, len); + } + + nxp_flexio_unlock(config->flexio_dev); + + FLEXIO_MCULCD_StopTransfer(flexio_lcd); + + return kStatus_Success; + +} + +static int mipi_dbi_flexio_lcdif_reset(const struct device *dev, uint32_t delay) +{ + int err; + const struct mcux_flexio_lcdif_config *config = dev->config; + + /* Check if a reset port is provided to reset the LCD controller */ + if (config->reset.port == NULL) { + return 0; + } + + /* Reset the LCD controller. */ + err = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT_HIGH); + if (err) { + return err; + } + + err = gpio_pin_set_dt(&config->reset, 0); + if (err < 0) { + return err; + } + + k_msleep(delay); + + err = gpio_pin_set_dt(&config->reset, 1); + if (err < 0) { + return err; + } + + LOG_DBG("%s device reset complete", dev->name); + + return 0; +} + +static int flexio_lcdif_init(const struct device *dev) +{ + const struct mcux_flexio_lcdif_config *config = dev->config; + struct mcux_flexio_lcdif_data *lcdif_data = dev->data; + int err; + uint8_t shifter_end = config->child->res.shifter_count - 1; + + if (!device_is_ready(lcdif_data->dma_tx.dma_dev)) { + LOG_ERR("%s device is not ready", lcdif_data->dma_tx.dma_dev->name); + return -ENODEV; + } + + err = nxp_flexio_child_attach(config->flexio_dev, config->child); + if (err < 0) { + return err; + } + + config->flexio_lcd_dev->txShifterStartIndex = config->child->res.shifter_index[0]; + config->flexio_lcd_dev->txShifterEndIndex = config->child->res.shifter_index[shifter_end]; + + config->flexio_lcd_dev->rxShifterStartIndex = config->flexio_lcd_dev->txShifterStartIndex; + config->flexio_lcd_dev->rxShifterEndIndex = config->flexio_lcd_dev->txShifterEndIndex; + + config->flexio_lcd_dev->timerIndex = config->child->res.timer_index[0]; + + if (config->flexio_lcd_dev->txShifterEndIndex != + config->flexio_lcd_dev->txShifterStartIndex + shifter_end) { + LOG_ERR("Shifters should be continuous"); + return -ENODEV; + } + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (err) { + return err; + } + + /* Pass the FlexIO LCD device as parameter to the function + * callbacks for setting GPIO signals. + */ + config->flexio_lcd_dev->userData = (void *)dev; + + + k_sem_init(&lcdif_data->transfer_done, 0, 1); + + LOG_DBG("%s device init complete", dev->name); + + return 0; +} + +static struct mipi_dbi_driver_api mipi_dbi_lcdif_driver_api = { + .reset = mipi_dbi_flexio_lcdif_reset, + .command_write = mipi_dbi_flexio_lcdif_command_write, + .write_display = mipi_dbi_flexio_ldcif_write_display, +}; + +#define MCUX_FLEXIO_LCDIF_DEVICE_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static FLEXIO_MCULCD_Type flexio_mculcd_##n = { \ + .flexioBase = (FLEXIO_Type *)DT_REG_ADDR(DT_INST_PARENT(n)), \ + .dataPinStartIndex = DT_INST_PROP(n, data_pin_start), \ + .ENWRPinIndex = DT_INST_PROP(n, enwr_pin), \ + .RDPinIndex = DT_INST_PROP_OR(n, rd_pin, 0), \ + .setCSPin = flexio_lcdif_set_cs, \ + .setRSPin = flexio_lcdif_set_rs, \ + .setRDWRPin = flexio_lcdif_set_rd_wr, \ + }; \ + \ + static uint8_t mcux_flexio_lcdif_shifters_##n[DT_INST_PROP(n, shifters_count)]; \ + static uint8_t mcux_flexio_lcdif_timers_##n[DT_INST_PROP(n, timers_count)]; \ + \ + static const struct nxp_flexio_child lcdif_child_##n = { \ + .isr = NULL, \ + .user_data = (void *)DEVICE_DT_INST_GET(n), \ + .res = { \ + .shifter_index = mcux_flexio_lcdif_shifters_##n, \ + .shifter_count = ARRAY_SIZE(mcux_flexio_lcdif_shifters_##n), \ + .timer_index = mcux_flexio_lcdif_timers_##n, \ + .timer_count = ARRAY_SIZE(mcux_flexio_lcdif_timers_##n), \ + } \ + }; \ + \ + struct mcux_flexio_lcdif_config mcux_flexio_lcdif_config_##n = { \ + .flexio_lcd_dev = &flexio_mculcd_##n, \ + .flexio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .child = &lcdif_child_##n, \ + .reset = GPIO_DT_SPEC_INST_GET(n, reset_gpios), \ + .cs_gpio = GPIO_DT_SPEC_INST_GET(n, cs_gpios), \ + .rs_gpio = GPIO_DT_SPEC_INST_GET(n, rs_gpios), \ + .rdwr_gpio = GPIO_DT_SPEC_INST_GET_OR(n, rdwr_gpios, {0}), \ + }; \ + struct mcux_flexio_lcdif_data mcux_flexio_lcdif_data_##n = { \ + .dma_tx = { \ + .dma_dev = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(n, tx)), \ + .channel = DT_INST_DMAS_CELL_BY_NAME(n, tx, mux), \ + .dma_cfg = { \ + .channel_direction = MEMORY_TO_MEMORY, \ + .dma_callback = flexio_lcdif_dma_callback, \ + .dest_data_size = 4, \ + .block_count = 1, \ + .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, tx, source) \ + } \ + }, \ + }; \ + DEVICE_DT_INST_DEFINE(n, \ + &flexio_lcdif_init, \ + NULL, \ + &mcux_flexio_lcdif_data_##n, \ + &mcux_flexio_lcdif_config_##n, \ + POST_KERNEL, \ + CONFIG_MIPI_DBI_INIT_PRIORITY, \ + &mipi_dbi_lcdif_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MCUX_FLEXIO_LCDIF_DEVICE_INIT) diff --git a/drivers/mipi_dbi/mipi_dbi_smartbond.c b/drivers/mipi_dbi/mipi_dbi_smartbond.c index 034831075b2e8..da0e5e154cec1 100644 --- a/drivers/mipi_dbi/mipi_dbi_smartbond.c +++ b/drivers/mipi_dbi/mipi_dbi_smartbond.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -62,10 +63,6 @@ struct mipi_dbi_smartbond_data { struct k_sem sync_sem; /* Flag indicating whether or not an underflow took place */ volatile bool underflow_flag; -#if defined(CONFIG_PM_DEVICE) || defined(CONFIG_PM_DEVICE_RUNTIME) - /* Flag to designate whether or not a frame update is in progress */ - bool is_active; -#endif /* Layer settings */ lcdc_smartbond_layer_cfg layer; }; @@ -82,23 +79,20 @@ struct mipi_dbi_smartbond_config { }; /* Mark the device is is progress and so it's not allowed to enter the sleep state. */ -static void mipi_dbi_pm_get(const struct device *dev) +static inline void mipi_dbi_smartbond_pm_policy_state_lock_get(void) { -#ifdef CONFIG_PM_DEVICE - struct mipi_dbi_smartbond_data *data = dev->data; - - data->is_active = true; -#endif + /* + * Prevent the SoC from etering the normal sleep state as PDC does not support + * waking up the application core following LCDC events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); } /* Mark that device is inactive and so it's allowed to enter the sleep state */ -static void mipi_dbi_pm_put(const struct device *dev) +static inline void mipi_dbi_smartbond_pm_policy_state_lock_put(void) { -#ifdef CONFIG_PM_DEVICE - struct mipi_dbi_smartbond_data *data = dev->data; - - data->is_active = false; -#endif + /* Allow the SoC to enter the nornmal sleep state once LCDC is inactive */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); } /* Helper function to trigger the LCDC fetching data from frame buffer to the connected display */ @@ -217,6 +211,8 @@ static int mipi_dbi_smartbond_command_read(const struct device *dev, k_sem_take(&data->device_sem, K_FOREVER); + mipi_dbi_smartbond_pm_policy_state_lock_get(); + /* * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data * engine should not be affected. @@ -283,6 +279,8 @@ static int mipi_dbi_smartbond_command_read(const struct device *dev, LOG_ERR("Could not apply MIPI DBI pins' default state (%d)", ret); } + mipi_dbi_smartbond_pm_policy_state_lock_put(); + k_sem_give(&data->device_sem); return ret; @@ -300,7 +298,7 @@ static int mipi_dbi_smartbond_command_write(const struct device *dev, k_sem_take(&data->device_sem, K_FOREVER); - mipi_dbi_pm_get(dev); + mipi_dbi_smartbond_pm_policy_state_lock_get(); /* * Add an arbitrary valid color format to satisfy subroutine. The MIPI DBI command/data @@ -321,7 +319,7 @@ static int mipi_dbi_smartbond_command_write(const struct device *dev, da1469x_lcdc_send_cmd_data(false, data_buf, len); } - mipi_dbi_pm_put(dev); + mipi_dbi_smartbond_pm_policy_state_lock_put(); k_sem_give(&data->device_sem); @@ -349,7 +347,7 @@ static int mipi_dbi_smartbond_write_display(const struct device *dev, k_sem_take(&data->device_sem, K_FOREVER); - mipi_dbi_pm_get(dev); + mipi_dbi_smartbond_pm_policy_state_lock_get(); /* * Mainly check if the frame generator is busy with a pending frame update (might happen @@ -388,7 +386,7 @@ static int mipi_dbi_smartbond_write_display(const struct device *dev, _mipi_dbi_write_exit: - mipi_dbi_pm_put(dev); + mipi_dbi_smartbond_pm_policy_state_lock_put(); k_sem_give(&data->device_sem); @@ -488,20 +486,14 @@ static int mipi_dbi_smartbond_suspend(const struct device *dev) static int mipi_dbi_smartbond_pm_action(const struct device *dev, enum pm_device_action action) { - /* Initialize with an error code that should abort sleeping */ - int ret = -EBUSY; - struct mipi_dbi_smartbond_data *data = dev->data; + int ret = 0; switch (action) { case PM_DEVICE_ACTION_SUSPEND: - /* Sleep is only allowed when there are no active LCDC operations */ - if (!data->is_active) { - (void)mipi_dbi_smartbond_suspend(dev); - ret = 0; - } + /* A non-zero value should not affect sleep */ + (void)mipi_dbi_smartbond_suspend(dev); break; case PM_DEVICE_ACTION_RESUME: - __ASSERT_NO_MSG(!data->is_active); /* * The resume error code should not be taken into consideration * by the PM subsystem. diff --git a/drivers/mipi_dbi/mipi_dbi_spi.c b/drivers/mipi_dbi/mipi_dbi_spi.c index 0314fe5c31f13..e2b3aefe53bf6 100644 --- a/drivers/mipi_dbi/mipi_dbi_spi.c +++ b/drivers/mipi_dbi/mipi_dbi_spi.c @@ -66,21 +66,21 @@ static int mipi_dbi_spi_write_helper(const struct device *dev, if (dbi_config->mode == MIPI_DBI_MODE_SPI_3WIRE && IS_ENABLED(CONFIG_MIPI_DBI_SPI_3WIRE)) { - struct spi_config tmp_cfg; - /* We have to emulate 3 wire mode by packing the data/command - * bit into the upper bit of the SPI transfer. - * switch SPI to 9 bit mode, and write the transfer + /* 9 bit word mode must be used, as the command/data bit + * is stored before the data word. */ - memcpy(&tmp_cfg, &dbi_config->config, sizeof(tmp_cfg)); - tmp_cfg.operation &= ~SPI_WORD_SIZE_MASK; - tmp_cfg.operation |= SPI_WORD_SET(9); + if ((dbi_config->config.operation & SPI_WORD_SIZE_MASK) + != SPI_WORD_SET(9)) { + return -ENOTSUP; + } buffer.buf = &data->spi_byte; - buffer.len = 1; + buffer.len = 2; /* Send command */ if (cmd_present) { data->spi_byte = cmd; - ret = spi_write(config->spi_dev, &tmp_cfg, &buf_set); + ret = spi_write(config->spi_dev, &dbi_config->config, + &buf_set); if (ret < 0) { goto out; } @@ -88,7 +88,8 @@ static int mipi_dbi_spi_write_helper(const struct device *dev, /* Write data, byte by byte */ for (size_t i = 0; i < len; i++) { data->spi_byte = MIPI_DBI_DC_BIT | data_buf[i]; - ret = spi_write(config->spi_dev, &tmp_cfg, &buf_set); + ret = spi_write(config->spi_dev, &dbi_config->config, + &buf_set); if (ret < 0) { goto out; } diff --git a/drivers/misc/devmux/devmux.c b/drivers/misc/devmux/devmux.c index 653236f903dea..675b635b5d081 100644 --- a/drivers/misc/devmux/devmux.c +++ b/drivers/misc/devmux/devmux.c @@ -94,7 +94,7 @@ ssize_t z_vrfy_devmux_select_get(const struct device *dev) { return z_impl_devmux_select_get(dev); } -#include +#include #endif int z_impl_devmux_select_set(struct device *dev, size_t index) @@ -124,7 +124,7 @@ int z_vrfy_devmux_select_set(struct device *dev, size_t index) { return z_impl_devmux_select_set(dev, index); } -#include +#include #endif static int devmux_init(struct device *const dev) diff --git a/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c b/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c index 1904db4218dad..0745db600a206 100644 --- a/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c +++ b/drivers/misc/timeaware_gpio/timeaware_gpio_handlers.c @@ -12,7 +12,7 @@ static inline int z_vrfy_tgpio_port_get_time(const struct device *port, uint64_t K_OOPS(Z_SYSCALL_MEMORY_WRITE(current_time, sizeof(uint64_t))); return z_impl_tgpio_port_get_time((const struct device *)port, (uint64_t *)current_time); } -#include +#include static inline int z_vrfy_tgpio_port_get_cycles_per_second(const struct device *port, uint32_t *cycles) @@ -22,7 +22,7 @@ static inline int z_vrfy_tgpio_port_get_cycles_per_second(const struct device *p return z_impl_tgpio_port_get_cycles_per_second((const struct device *)port, (uint32_t *)cycles); } -#include +#include static inline int z_vrfy_tgpio_pin_periodic_output(const struct device *port, uint32_t pin, uint64_t start_time, uint64_t repeat_interval, @@ -32,14 +32,14 @@ static inline int z_vrfy_tgpio_pin_periodic_output(const struct device *port, ui return z_impl_tgpio_pin_periodic_output((const struct device *)port, pin, start_time, repeat_interval, periodic_enable); } -#include +#include static inline int z_vrfy_tgpio_pin_disable(const struct device *port, uint32_t pin) { K_OOPS(Z_SYSCALL_DRIVER_TGPIO(port, pin_disable)); return z_impl_tgpio_pin_disable((const struct device *)port, pin); } -#include +#include static inline int z_vrfy_tgpio_pin_config_ext_timestamp(const struct device *port, uint32_t pin, uint32_t event_polarity) @@ -48,7 +48,7 @@ static inline int z_vrfy_tgpio_pin_config_ext_timestamp(const struct device *por return z_impl_tgpio_pin_config_ext_timestamp((const struct device *)port, pin, event_polarity); } -#include +#include static inline int z_vrfy_tgpio_pin_read_ts_ec(const struct device *port, uint32_t pin, uint64_t *timestamp, uint64_t *event_count) @@ -57,4 +57,4 @@ static inline int z_vrfy_tgpio_pin_read_ts_ec(const struct device *port, uint32_ return z_impl_tgpio_pin_read_ts_ec((const struct device *)port, pin, (uint64_t *)timestamp, (uint64_t *)event_count); } -#include +#include diff --git a/drivers/mm/mm_drv_intel_adsp.h b/drivers/mm/mm_drv_intel_adsp.h index 8de9ccc42cab6..861621a510f44 100644 --- a/drivers/mm/mm_drv_intel_adsp.h +++ b/drivers/mm/mm_drv_intel_adsp.h @@ -30,10 +30,7 @@ #include "mm_drv_common.h" -DEVICE_MMIO_TOPLEVEL_STATIC(tlb_regs, DT_DRV_INST(0)); - -#define TLB_BASE \ - ((mm_reg_t)DEVICE_MMIO_TOPLEVEL_GET(tlb_regs)) +#define TLB_BASE (mm_reg_t)DT_REG_ADDR(DT_NODELABEL(tlb)) /* * Number of significant bits in the page index (defines the size of diff --git a/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c b/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c index b78a247ae0122..5b0bc5e576be0 100644 --- a/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c +++ b/drivers/mm/mm_drv_intel_adsp_mtl_tlb.c @@ -26,6 +26,7 @@ #include #include #include +#include #define SRAM_BANK_PAGE_NUM (SRAM_BANK_SIZE / CONFIG_MM_DRV_PAGE_SIZE) @@ -268,6 +269,9 @@ int sys_mm_drv_map_page(void *virt, uintptr_t phys, uint32_t flags) tlb_entries[entry_idx] = entry; +#ifdef CONFIG_MMU + arch_mem_map(virt, va, CONFIG_MM_DRV_PAGE_SIZE, flags); +#endif /* * Invalid the cache of the newly mapped virtual page to * avoid stale data. @@ -329,7 +333,7 @@ int sys_mm_drv_map_array(void *virt, uintptr_t *phys, return sys_mm_drv_simple_map_array(va, phys, cnt, flags); } -int sys_mm_drv_unmap_page(void *virt) +static int sys_mm_drv_unmap_page_wflush(void *virt, bool flush_data) { k_spinlock_key_t key; uint32_t entry_idx, bank_idx; @@ -358,8 +362,14 @@ int sys_mm_drv_unmap_page(void *virt) /* * Flush the cache to make sure the backing physical page * has the latest data. + * No flush when called from sys_mm_drv_mm_init(). */ - sys_cache_data_flush_range(virt, CONFIG_MM_DRV_PAGE_SIZE); + if (flush_data) { + sys_cache_data_flush_range(virt, CONFIG_MM_DRV_PAGE_SIZE); +#ifdef CONFIG_MMU + arch_mem_unmap(virt, CONFIG_MM_DRV_PAGE_SIZE); +#endif + } entry_idx = get_tlb_entry_idx(va); pa = tlb_entry_to_pa(tlb_entries[entry_idx]); @@ -391,6 +401,11 @@ int sys_mm_drv_unmap_page(void *virt) return ret; } +int sys_mm_drv_unmap_page(void *virt) +{ + return sys_mm_drv_unmap_page_wflush(virt, true); +} + int sys_mm_drv_unmap_region(void *virt, size_t size) { void *va = (__sparse_force void *)sys_cache_cached_ptr_get(virt); @@ -441,6 +456,42 @@ int sys_mm_drv_update_page_flags(void *virt, uint32_t flags) return ret; } +#ifdef CONFIG_MM_DRV_INTEL_ADSP_TLB_REMAP_UNUSED_RAM +static int sys_mm_drv_unmap_region_initial(void *virt_in, size_t size) +{ + void *virt = (__sparse_force void *)sys_cache_cached_ptr_get(virt_in); + + k_spinlock_key_t key; + int ret = 0; + size_t offset; + + CHECKIF(!sys_mm_drv_is_virt_addr_aligned(virt) || + !sys_mm_drv_is_size_aligned(size)) { + ret = -EINVAL; + goto out; + } + + key = k_spin_lock(&sys_mm_drv_common_lock); + + for (offset = 0; offset < size; offset += CONFIG_MM_DRV_PAGE_SIZE) { + uint8_t *va = (uint8_t *)virt + offset; + + int ret2 = sys_mm_drv_unmap_page_wflush(va, false); + + if (ret2 != 0) { + __ASSERT(false, "cannot unmap %p\n", va); + + ret = ret2; + } + } + + k_spin_unlock(&sys_mm_drv_common_lock, key); + +out: + return ret; +} +#endif + int sys_mm_drv_page_phys_get(void *virt, uintptr_t *phys) { uint16_t *tlb_entries = UINT_TO_POINTER(TLB_BASE); @@ -721,8 +772,9 @@ static int sys_mm_drv_mm_init(const struct device *dev) size_t unused_size = CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_SIZE - UNUSED_L2_START_ALIGNED; - ret = sys_mm_drv_unmap_region(UINT_TO_POINTER(UNUSED_L2_START_ALIGNED), - unused_size); + ret = sys_mm_drv_unmap_region_initial(UINT_TO_POINTER(UNUSED_L2_START_ALIGNED), + unused_size); + /* Need to reset max pages statistics after unmap */ for (int i = 0; i < L2_SRAM_BANK_NUM; i++) { diff --git a/drivers/modem/CMakeLists.txt b/drivers/modem/CMakeLists.txt index a97568dfc65c5..62b84bd792946 100644 --- a/drivers/modem/CMakeLists.txt +++ b/drivers/modem/CMakeLists.txt @@ -27,10 +27,6 @@ if(CONFIG_MODEM_WNCM14A2A) zephyr_library_sources(wncm14a2a.c) endif() -if(CONFIG_MODEM_GSM_PPP) - zephyr_library_sources(gsm_ppp.c) -endif() - if (CONFIG_MODEM_HL7800) zephyr_library_sources(hl7800.c) endif() @@ -40,3 +36,4 @@ if (CONFIG_MODEM_SIM7080) endif() zephyr_library_sources_ifdef(CONFIG_MODEM_CELLULAR modem_cellular.c) +zephyr_library_sources_ifdef(CONFIG_MODEM_AT_SHELL modem_at_shell.c) diff --git a/drivers/modem/Kconfig b/drivers/modem/Kconfig index 02e3557918f64..7219312e18f73 100644 --- a/drivers/modem/Kconfig +++ b/drivers/modem/Kconfig @@ -155,7 +155,7 @@ config MODEM_SOCKET modem_socket_init(). Note that the modem socket uses runtime allocated file descriptors reserved from the fdtable, for which the max count is set using the - Kconfig option POSIX_MAX_FDS. Make sure to update this value as both + Kconfig option ZVFS_OPEN_MAX. Make sure to update this value as both the modem sockets and the POSIX_API, if used, share them. config MODEM_SOCKET_PACKET_COUNT @@ -189,8 +189,8 @@ config MODEM_CELL_INFO source "drivers/modem/Kconfig.ublox-sara-r4" source "drivers/modem/Kconfig.quectel-bg9x" source "drivers/modem/Kconfig.wncm14a2a" -source "drivers/modem/Kconfig.gsm" source "drivers/modem/Kconfig.cellular" +source "drivers/modem/Kconfig.at_shell" source "drivers/modem/Kconfig.hl7800" source "drivers/modem/Kconfig.simcom-sim7080" diff --git a/drivers/modem/Kconfig.at_shell b/drivers/modem/Kconfig.at_shell new file mode 100644 index 0000000000000..b2f6f42e39362 --- /dev/null +++ b/drivers/modem/Kconfig.at_shell @@ -0,0 +1,36 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +config MODEM_AT_SHELL + bool "AT command shell based on modem modules" + select MODEM_MODULES + select MODEM_CHAT + select MODEM_PIPE + select MODEM_PIPELINK + depends on !MODEM_SHELL + depends on !SHELL_WILDCARD + depends on $(dt_alias_enabled,modem) + +if MODEM_AT_SHELL + +config MODEM_AT_SHELL_USER_PIPE + int "User pipe number to use" + default 0 + +config MODEM_AT_SHELL_RESPONSE_TIMEOUT_S + int "Timeout waiting for response to AT command in seconds" + default 5 + +config MODEM_AT_SHELL_COMMAND_MAX_SIZE + int "Maximum size of AT command" + default 32 + +config MODEM_AT_SHELL_RESPONSE_MAX_SIZE + int "Maximum size of AT response" + default 64 + +config MODEM_AT_SHELL_CHAT_RECEIVE_BUF_SIZE + int "Size of modem chat receive buffer in bytes" + default 128 + +endif # MODEM_AT_SHELL diff --git a/drivers/modem/Kconfig.cellular b/drivers/modem/Kconfig.cellular index 23446c62b728e..224ffdfdb97a8 100644 --- a/drivers/modem/Kconfig.cellular +++ b/drivers/modem/Kconfig.cellular @@ -8,11 +8,12 @@ config MODEM_CELLULAR select MODEM_CMUX select MODEM_CHAT select MODEM_PIPE + select MODEM_PIPELINK select MODEM_BACKEND_UART select RING_BUFFER select NET_L2_PPP_OPTION_MRU select NET_L2_PPP_PAP - depends on (DT_HAS_QUECTEL_BG95_ENABLED || DT_HAS_ZEPHYR_GSM_PPP_ENABLED || \ + depends on (DT_HAS_QUECTEL_BG95_ENABLED || \ DT_HAS_SIMCOM_SIM7080_ENABLED || DT_HAS_U_BLOX_SARA_R4_ENABLED || \ DT_HAS_U_BLOX_SARA_R5_ENABLED || DT_HAS_SWIR_HL7800_ENABLED || \ DT_HAS_TELIT_ME910G1_ENABLED || DT_HAS_QUECTEL_EG25_G_ENABLED || \ @@ -21,8 +22,7 @@ config MODEM_CELLULAR This driver uses the generic 3gpp AT commands, along with the standard protocols CMUX and PPP, to configure cellular modems to establish a point-to-point - network connection. It is a plug-in replacement for the - existing GSM_PPP driver, and a template for tailored + network connection. It is a template for tailored drivers for the ublox, quectel and other modems, which include power management and more complex device specific features. @@ -51,4 +51,8 @@ config MODEM_CELLULAR_CHAT_BUFFER_SIZES int "The size of the buffers used for the chat scripts in bytes." default 128 +config MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES + int "The size of the buffers used for each user pipe in bytes." + default 128 + endif diff --git a/drivers/modem/Kconfig.gsm b/drivers/modem/Kconfig.gsm deleted file mode 100644 index 101c1e2ece4ee..0000000000000 --- a/drivers/modem/Kconfig.gsm +++ /dev/null @@ -1,141 +0,0 @@ -# Copyright (c) 2020 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 - -config MODEM_GSM_PPP - bool "[DEPRECATED] Support GSM modems" - select MODEM_CONTEXT - select MODEM_CMD_HANDLER - select MODEM_IFACE_UART - select NET_MGMT - select NET_MGMT_EVENT - select DEPRECATED - help - This driver is deprecated, use the MODEM_CELLULAR driver instead. - -if MODEM_GSM_PPP - -choice MODEM_GSM_TYPE - prompt "Modem type" - default MODEM_GSM_GENERIC - help - Type/manufacturer of the GSM modem - -config MODEM_GSM_GENERIC - bool "Generic GSM modem" - help - The modem does not need any special handling etc. - -config MODEM_GSM_SIMCOM - bool "SIMCOM modem" - help - Use this if you have SIMCOM based modem like SIM800 etc. - -config MODEM_GSM_QUECTEL - bool "Quectel modem" - help - Use this if you have Quectel based modem like EC2X etc. - -endchoice - -choice MODEM_GSM_STATUS_COMMAND - prompt "Select status command Type" - default MODEM_GSM_STATUS_CMD_USE_CREG - help - Use particular type of AT command for cell tower registration status. - -config MODEM_GSM_STATUS_CMD_USE_CREG - bool "CREG command" - -config MODEM_GSM_STATUS_CMD_USE_CEREG - bool "CEREG command" - -endchoice - -config MODEM_GSM_STATUS_COMMAND - string "Status Command" - default "CREG" if MODEM_GSM_STATUS_CMD_USE_CREG - default "CEREG" if MODEM_GSM_STATUS_CMD_USE_CEREG - -config MODEM_GSM_RX_STACK_SIZE - int "Size of the stack allocated for receiving data from modem" - default 512 - help - Sets the stack size which will be used by the GSM RX thread. - -config MODEM_GSM_WORKQ_STACK_SIZE - int "Size of the stack allocated for the dedicated gsm workqueue" - default 768 - help - Sets the stack size which will be used by the dedicated GSM workqueue - thread. - -config MODEM_GSM_INIT_PRIORITY - int "Init priority for the GSM modem driver" - default 60 - range 0 99 - help - The GSM modem is initialized in POST_KERNEL using priority in - the range 0-99. - -config MODEM_GSM_APN - string "Access Point Name" - default "internet" - help - Specify Access Point Name, i.e. the name to identify Internet IP - GPRS cellular data context. - -config GSM_PPP_AUTOSTART - bool "Auto-start PPP at boot" - default y - help - This setting lets driver connect to network and initialize PPP at - boot. Unselect this if you want to run application code before - modem connects to network. See contents of "drivers/gsm_ppp.h" - to get an idea of the API. - -config MODEM_GSM_ATTACH_TIMEOUT - int "Timeout for attaching to packet service" - default 30 - help - Before activating PPP, attachment to packet service is checked - using AT+CGATT. This setting dictates how much time in seconds - we give the modem before giving up. - -config MODEM_GSM_REGISTER_TIMEOUT - int "Timeout for registering to cellular tower" - default 300 - help - Before attachment to packet service, modem is checked if it is - connected to the cellular tower. This setting dictates how much - time in seconds we give the modem before giving up. - -config MODEM_GSM_MANUAL_MCCMNO - string "MCC/MNO for establishing network connection" - help - This setting is used in the AT+COPS command to set the MCC/MNO - for the network connection context. This value is specific to - the network provider and may need to be changed if auto is not - selected. - -config MODEM_GSM_RSSI_POLLING_PERIOD - int "Configure RSSI polling period (in seconds)" - default 30 - help - This settings is used to configure the period of RSSI polling - -config MODEM_GSM_ENABLE_CESQ_RSSI - bool "+CESQ RSSI measurement" - help - If this is enabled, RSRP, RSCP and RXREL values are read from the - modem with +CESQ. Otherwise only RSSI value is read with +CSQ - from the modem. - -config MODEM_GSM_FACTORY_RESET_AT_BOOT - bool "Factory reset modem at boot" - help - If this is enabled, the modem will be reset to factory default - settings first thing in the initialization sequence. This is - helpful if your modem has a tendency to get stuck due to cached - state. - -endif diff --git a/drivers/modem/gsm_ppp.c b/drivers/modem/gsm_ppp.c deleted file mode 100644 index 88ea47b832a0a..0000000000000 --- a/drivers/modem/gsm_ppp.c +++ /dev/null @@ -1,1362 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#define DT_DRV_COMPAT zephyr_gsm_ppp - -#include -LOG_MODULE_REGISTER(modem_gsm, CONFIG_MODEM_LOG_LEVEL); - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "modem_context.h" -#include "modem_iface_uart.h" -#include "modem_cmd_handler.h" -#include "../console/gsm_mux.h" - -#include - -#define GSM_UART_NODE DT_INST_BUS(0) -#define GSM_CMD_READ_BUF 128 -#define GSM_CMD_AT_TIMEOUT K_SECONDS(2) -#define GSM_CMD_SETUP_TIMEOUT K_SECONDS(6) -/* GSM_CMD_LOCK_TIMEOUT should be longer than GSM_CMD_AT_TIMEOUT & GSM_CMD_SETUP_TIMEOUT, - * otherwise the gsm_ppp_stop might fail to lock tx. - */ -#define GSM_CMD_LOCK_TIMEOUT K_SECONDS(10) -#define GSM_RECV_MAX_BUF 30 -#define GSM_RECV_BUF_SIZE 128 -#define GSM_ATTACH_RETRY_DELAY_MSEC 1000 -#define GSM_REGISTER_DELAY_MSEC 1000 -#define GSM_RETRY_DELAY K_SECONDS(1) - -#define GSM_RSSI_RETRY_DELAY_MSEC 2000 -#define GSM_RSSI_RETRIES 10 -#define GSM_RSSI_INVALID -1000 - -#if defined(CONFIG_MODEM_GSM_ENABLE_CESQ_RSSI) - #define GSM_RSSI_MAXVAL 0 -#else - #define GSM_RSSI_MAXVAL -51 -#endif - -/* Modem network registration state */ -enum network_state { - GSM_NET_INIT = -1, - GSM_NET_NOT_REGISTERED, - GSM_NET_HOME_NETWORK, - GSM_NET_SEARCHING, - GSM_NET_REGISTRATION_DENIED, - GSM_NET_UNKNOWN, - GSM_NET_ROAMING, -}; - -static struct gsm_modem { - struct k_mutex lock; - const struct device *dev; - struct modem_context context; - - struct modem_cmd_handler_data cmd_handler_data; - uint8_t cmd_match_buf[GSM_CMD_READ_BUF]; - struct k_sem sem_response; - struct k_sem sem_if_down; - - struct modem_iface_uart_data gsm_data; - struct k_work_delayable gsm_configure_work; - char gsm_rx_rb_buf[PPP_MRU * 3]; - - uint8_t *ppp_recv_buf; - size_t ppp_recv_buf_len; - - enum gsm_ppp_state { - GSM_PPP_START, - GSM_PPP_WAIT_AT, - GSM_PPP_AT_RDY, - GSM_PPP_STATE_INIT, - GSM_PPP_STATE_CONTROL_CHANNEL = GSM_PPP_STATE_INIT, - GSM_PPP_STATE_PPP_CHANNEL, - GSM_PPP_STATE_AT_CHANNEL, - GSM_PPP_STATE_DONE, - GSM_PPP_SETUP = GSM_PPP_STATE_DONE, - GSM_PPP_REGISTERING, - GSM_PPP_ATTACHING, - GSM_PPP_ATTACHED, - GSM_PPP_SETUP_DONE, - GSM_PPP_STOP, - GSM_PPP_STATE_ERROR, - } state; - - const struct device *ppp_dev; - const struct device *at_dev; - const struct device *control_dev; - - struct net_if *iface; - - struct k_thread rx_thread; - struct k_work_q workq; - struct k_work_delayable rssi_work_handle; - struct gsm_ppp_modem_info minfo; - - enum network_state net_state; - - int retries; - bool modem_info_queried : 1; - - void *user_data; - - gsm_modem_power_cb modem_on_cb; - gsm_modem_power_cb modem_off_cb; - struct net_mgmt_event_callback gsm_mgmt_cb; -} modem; - -NET_BUF_POOL_DEFINE(gsm_recv_pool, GSM_RECV_MAX_BUF, GSM_RECV_BUF_SIZE, 0, NULL); -K_KERNEL_STACK_DEFINE(gsm_rx_stack, CONFIG_MODEM_GSM_RX_STACK_SIZE); -K_KERNEL_STACK_DEFINE(gsm_workq_stack, CONFIG_MODEM_GSM_WORKQ_STACK_SIZE); - -static inline void gsm_ppp_lock(struct gsm_modem *gsm) -{ - (void)k_mutex_lock(&gsm->lock, K_FOREVER); -} - -static inline void gsm_ppp_unlock(struct gsm_modem *gsm) -{ - (void)k_mutex_unlock(&gsm->lock); -} - -static inline int gsm_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay) -{ - return k_work_reschedule_for_queue(&modem.workq, dwork, delay); -} - -#if defined(CONFIG_MODEM_GSM_ENABLE_CESQ_RSSI) - /* helper macro to keep readability */ -#define ATOI(s_, value_, desc_) modem_atoi(s_, value_, desc_, __func__) - -/** - * @brief Convert string to long integer, but handle errors - * - * @param s: string with representation of integer number - * @param err_value: on error return this value instead - * @param desc: name the string being converted - * @param func: function where this is called (typically __func__) - * - * @retval return integer conversion on success, or err_value on error - */ -static int modem_atoi(const char *s, const int err_value, - const char *desc, const char *func) -{ - int ret; - char *endptr; - - ret = (int)strtol(s, &endptr, 10); - if ((endptr == NULL) || (*endptr != '\0')) { - LOG_ERR("bad %s '%s' in %s", s, - desc, func); - return err_value; - } - - return ret; -} -#endif - -static void gsm_rx(void *p1, void *p2, void *p3) -{ - ARG_UNUSED(p2); - ARG_UNUSED(p3); - - struct gsm_modem *gsm = p1; - LOG_DBG("starting"); - - while (true) { - modem_iface_uart_rx_wait(&gsm->context.iface, K_FOREVER); - - /* The handler will listen AT channel */ - modem_cmd_handler_process(&gsm->context.cmd_handler, &gsm->context.iface); - } -} - -MODEM_CMD_DEFINE(gsm_cmd_ok) -{ - (void)modem_cmd_handler_set_error(data, 0); - LOG_DBG("ok"); - k_sem_give(&modem.sem_response); - return 0; -} - -MODEM_CMD_DEFINE(gsm_cmd_error) -{ - (void)modem_cmd_handler_set_error(data, -EINVAL); - LOG_DBG("error"); - k_sem_give(&modem.sem_response); - return 0; -} - -/* Handler: +CME Error: [0] */ -MODEM_CMD_DEFINE(gsm_cmd_exterror) -{ - /* TODO: map extended error codes to values */ - (void)modem_cmd_handler_set_error(data, -EIO); - k_sem_give(&modem.sem_response); - return 0; -} - -static const struct modem_cmd response_cmds[] = { - MODEM_CMD("OK", gsm_cmd_ok, 0U, ""), - MODEM_CMD("ERROR", gsm_cmd_error, 0U, ""), - MODEM_CMD("+CME ERROR: ", gsm_cmd_exterror, 1U, ""), - MODEM_CMD("CONNECT", gsm_cmd_ok, 0U, ""), -}; - -static int unquoted_atoi(const char *s, int base) -{ - if (*s == '"') { - s++; - } - - return strtol(s, NULL, base); -} - -/* - * Handler: +COPS: [0],[1],[2] - */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_cops) -{ - if (argc >= 1) { -#if defined(CONFIG_MODEM_CELL_INFO) - if (argc >= 3) { - modem.context.data_operator = unquoted_atoi(argv[2], 10); - LOG_INF("operator: %u", - modem.context.data_operator); - } -#endif - if (unquoted_atoi(argv[0], 10) == 0) { - modem.context.is_automatic_oper = true; - } else { - modem.context.is_automatic_oper = false; - } - } - - return 0; -} - -/* - * Provide modem info if modem shell is enabled. This can be shown with - * "modem list" shell command. - */ - -/* Handler: */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_manufacturer) -{ - size_t out_len; - - out_len = net_buf_linearize(modem.minfo.mdm_manufacturer, - sizeof(modem.minfo.mdm_manufacturer) - 1, - data->rx_buf, 0, len); - modem.minfo.mdm_manufacturer[out_len] = '\0'; - LOG_INF("Manufacturer: %s", modem.minfo.mdm_manufacturer); - - return 0; -} - -/* Handler: */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_model) -{ - size_t out_len; - - out_len = net_buf_linearize(modem.minfo.mdm_model, - sizeof(modem.minfo.mdm_model) - 1, - data->rx_buf, 0, len); - modem.minfo.mdm_model[out_len] = '\0'; - LOG_INF("Model: %s", modem.minfo.mdm_model); - - return 0; -} - -/* Handler: */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_revision) -{ - size_t out_len; - - out_len = net_buf_linearize(modem.minfo.mdm_revision, - sizeof(modem.minfo.mdm_revision) - 1, - data->rx_buf, 0, len); - modem.minfo.mdm_revision[out_len] = '\0'; - LOG_INF("Revision: %s", modem.minfo.mdm_revision); - - return 0; -} - -/* Handler: */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imei) -{ - size_t out_len; - - out_len = net_buf_linearize(modem.minfo.mdm_imei, sizeof(modem.minfo.mdm_imei) - 1, - data->rx_buf, 0, len); - modem.minfo.mdm_imei[out_len] = '\0'; - LOG_INF("IMEI: %s", modem.minfo.mdm_imei); - - return 0; -} - -#if defined(CONFIG_MODEM_SIM_NUMBERS) -/* Handler: */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_imsi) -{ - size_t out_len; - - out_len = net_buf_linearize(modem.minfo.mdm_imsi, sizeof(modem.minfo.mdm_imsi) - 1, - data->rx_buf, 0, len); - modem.minfo.mdm_imsi[out_len] = '\0'; - LOG_INF("IMSI: %s", modem.minfo.mdm_imsi); - - return 0; -} - -/* Handler: */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_iccid) -{ - size_t out_len; - - out_len = net_buf_linearize(modem.minfo.mdm_iccid, sizeof(modem.minfo.mdm_iccid) - 1, - data->rx_buf, 0, len); - modem.minfo.mdm_iccid[out_len] = '\0'; - if (modem.minfo.mdm_iccid[0] == '+') { - /* Seen on U-blox SARA: "+CCID: nnnnnnnnnnnnnnnnnnnn". - * Skip over the +CCID bit, which other modems omit. - */ - char *p = strchr(modem.minfo.mdm_iccid, ' '); - - if (p) { - size_t iccid_len = strlen(p+1); - - (void)memmove(modem.minfo.mdm_iccid, p+1, iccid_len+1); - } - } - LOG_INF("ICCID: %s", modem.minfo.mdm_iccid); - - return 0; -} -#endif /* CONFIG_MODEM_SIM_NUMBERS */ - -MODEM_CMD_DEFINE(on_cmd_net_reg_sts) -{ - modem.net_state = (enum network_state)atoi(argv[1]); - - switch (modem.net_state) { - case GSM_NET_NOT_REGISTERED: - LOG_DBG("Network %s.", "not registered"); - break; - case GSM_NET_HOME_NETWORK: - LOG_DBG("Network %s.", "registered, home network"); - break; - case GSM_NET_SEARCHING: - LOG_DBG("Searching for network..."); - break; - case GSM_NET_REGISTRATION_DENIED: - LOG_DBG("Network %s.", "registration denied"); - break; - case GSM_NET_UNKNOWN: - LOG_DBG("Network %s.", "unknown"); - break; - case GSM_NET_ROAMING: - LOG_DBG("Network %s.", "registered, roaming"); - break; - default: - break; - } - - return 0; -} - -#if defined(CONFIG_MODEM_CELL_INFO) - -/* - * Handler: +CEREG: [0],[1],[2],[3],[4] - */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_cereg) -{ - if (argc >= 4) { - modem.context.data_lac = unquoted_atoi(argv[2], 16); - modem.context.data_cellid = unquoted_atoi(argv[3], 16); - LOG_INF("lac: %u, cellid: %u", - modem.context.data_lac, - modem.context.data_cellid); - } - - if (argc >= 5) { - modem.context.data_act = unquoted_atoi(argv[4], 10); - LOG_INF("act: %u", modem.context.data_act); - } - - return 0; -} - -static const struct setup_cmd query_cellinfo_cmds[] = { - SETUP_CMD_NOHANDLE("AT+CEREG=2"), - SETUP_CMD("AT+CEREG?", "", on_cmd_atcmdinfo_cereg, 5U, ","), - SETUP_CMD_NOHANDLE("AT+COPS=3,2"), - SETUP_CMD("AT+COPS?", "", on_cmd_atcmdinfo_cops, 3U, ","), -}; - -static int gsm_query_cellinfo(struct gsm_modem *gsm) -{ - int ret; - - ret = modem_cmd_handler_setup_cmds_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - query_cellinfo_cmds, - ARRAY_SIZE(query_cellinfo_cmds), - &gsm->sem_response, - GSM_CMD_SETUP_TIMEOUT); - if (ret < 0) { - LOG_WRN("modem query for cell info returned %d", ret); - } - - return ret; -} -#endif /* CONFIG_MODEM_CELL_INFO */ - -#if defined(CONFIG_MODEM_GSM_ENABLE_CESQ_RSSI) -/* - * Handler: +CESQ: [0],[1],[2],[3],[4],[5] - */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_rssi_cesq) -{ - int rsrp, rscp, rxlev; - - rsrp = ATOI(argv[5], 0, "rsrp"); - rscp = ATOI(argv[2], 0, "rscp"); - rxlev = ATOI(argv[0], 0, "rxlev"); - - if ((rsrp >= 0) && (rsrp <= 97)) { - modem.minfo.mdm_rssi = -140 + (rsrp - 1); - LOG_DBG("RSRP: %d", modem.minfo.mdm_rssi); - } else if ((rscp >= 0) && (rscp <= 96)) { - modem.minfo.mdm_rssi = -120 + (rscp - 1); - LOG_DBG("RSCP: %d", modem.minfo.mdm_rssi); - } else if ((rxlev >= 0) && (rxlev <= 63)) { - modem.minfo.mdm_rssi = -110 + (rxlev - 1); - LOG_DBG("RSSI: %d", modem.minfo.mdm_rssi); - } else { - modem.minfo.mdm_rssi = GSM_RSSI_INVALID; - LOG_DBG("RSRP/RSCP/RSSI not known"); - } - - return 0; -} -#else -/* Handler: +CSQ: [0],[1] */ -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_rssi_csq) -{ - /* Expected response is "+CSQ: ," */ - if (argc > 0) { - int rssi = atoi(argv[0]); - - if ((rssi >= 0) && (rssi <= 31)) { - rssi = -113 + (rssi * 2); - } else { - rssi = GSM_RSSI_INVALID; - } - - modem.minfo.mdm_rssi = rssi; - LOG_DBG("RSSI: %d", rssi); - } - - return 0; -} -#endif - -#if defined(CONFIG_MODEM_GSM_ENABLE_CESQ_RSSI) -static const struct modem_cmd read_rssi_cmd = - MODEM_CMD("+CESQ:", on_cmd_atcmdinfo_rssi_cesq, 6U, ","); -#else -static const struct modem_cmd read_rssi_cmd = - MODEM_CMD("+CSQ:", on_cmd_atcmdinfo_rssi_csq, 2U, ","); -#endif - -static const struct setup_cmd setup_modem_info_cmds[] = { - /* query modem info */ - SETUP_CMD("AT+CGMI", "", on_cmd_atcmdinfo_manufacturer, 0U, ""), - SETUP_CMD("AT+CGMM", "", on_cmd_atcmdinfo_model, 0U, ""), - SETUP_CMD("AT+CGMR", "", on_cmd_atcmdinfo_revision, 0U, ""), - SETUP_CMD("AT+CGSN", "", on_cmd_atcmdinfo_imei, 0U, ""), -#if defined(CONFIG_MODEM_SIM_NUMBERS) - SETUP_CMD("AT+CIMI", "", on_cmd_atcmdinfo_imsi, 0U, ""), - SETUP_CMD("AT+CCID", "", on_cmd_atcmdinfo_iccid, 0U, ""), -#endif -}; - -static const struct setup_cmd setup_cmds[] = { - /* no echo */ - SETUP_CMD_NOHANDLE("ATE0"), - /* hang up */ - SETUP_CMD_NOHANDLE("ATH"), - /* extended errors in numeric form */ - SETUP_CMD_NOHANDLE("AT+CMEE=1"), - /* disable unsolicited network registration codes */ - SETUP_CMD_NOHANDLE("AT+CREG=0"), - /* create PDP context */ - SETUP_CMD_NOHANDLE("AT+CGDCONT=1,\"IP\",\"" CONFIG_MODEM_GSM_APN "\""), -#if IS_ENABLED(DT_PROP(GSM_UART_NODE, hw_flow_control)) - /* enable hardware flow control */ - SETUP_CMD_NOHANDLE("AT+IFC=2,2"), -#endif -}; - -MODEM_CMD_DEFINE(on_cmd_atcmdinfo_attached) -{ - /* Expected response is "+CGATT: 0|1" so simply look for '1' */ - if ((argc > 0) && (atoi(argv[0]) == 1)) { - LOG_INF("Attached to packet service!"); - } - - return 0; -} - - -static const struct modem_cmd read_cops_cmd = - MODEM_CMD_ARGS_MAX("+COPS:", on_cmd_atcmdinfo_cops, 1U, 4U, ","); - -static const struct modem_cmd check_net_reg_cmd = - MODEM_CMD("+" CONFIG_MODEM_GSM_STATUS_COMMAND, on_cmd_net_reg_sts, 2U, ","); - -static const struct modem_cmd check_attached_cmd = - MODEM_CMD("+CGATT:", on_cmd_atcmdinfo_attached, 1U, ","); - -static const struct setup_cmd connect_cmds[] = { - /* connect to network */ - SETUP_CMD_NOHANDLE("ATD*99#"), -}; - -static int gsm_query_modem_info(struct gsm_modem *gsm) -{ - int ret; - - if (gsm->modem_info_queried) { - return 0; - } - - ret = modem_cmd_handler_setup_cmds_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - setup_modem_info_cmds, - ARRAY_SIZE(setup_modem_info_cmds), - &gsm->sem_response, - GSM_CMD_SETUP_TIMEOUT); - - if (ret < 0) { - return ret; - } - - gsm->modem_info_queried = true; - - return 0; -} - -static int gsm_setup_mccmno(struct gsm_modem *gsm) -{ - int ret = 0; - - if (CONFIG_MODEM_GSM_MANUAL_MCCMNO[0] != '\0') { - /* use manual MCC/MNO entry */ - ret = modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - NULL, 0, - "AT+COPS=1,2,\"" - CONFIG_MODEM_GSM_MANUAL_MCCMNO - "\"", - &gsm->sem_response, - GSM_CMD_AT_TIMEOUT); - } else { - -/* First AT+COPS? is sent to check if automatic selection for operator - * is already enabled, if yes we do not send the command AT+COPS= 0,0. - */ - - ret = modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - &read_cops_cmd, - 1, "AT+COPS?", - &gsm->sem_response, - GSM_CMD_SETUP_TIMEOUT); - - if (ret < 0) { - return ret; - } - - if (!gsm->context.is_automatic_oper) { - /* register operator automatically */ - ret = modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - NULL, 0, "AT+COPS=0,0", - &gsm->sem_response, - GSM_CMD_AT_TIMEOUT); - } - } - - if (ret < 0) { - LOG_ERR("AT+COPS ret:%d", ret); - } - - return ret; -} - -static struct net_if *ppp_net_if(void) -{ - return net_if_get_first_by_type(&NET_L2_GET_NAME(PPP)); -} - -static void set_ppp_carrier_on(struct gsm_modem *gsm) -{ - const struct device *ppp_dev = device_get_binding(CONFIG_NET_PPP_DRV_NAME); - struct net_if *iface = gsm->iface; - - if (ppp_dev == NULL) { - LOG_ERR("Cannot find PPP %s!", CONFIG_NET_PPP_DRV_NAME); - return; - } - - net_if_up(iface); -} - -static void query_rssi(struct gsm_modem *gsm, bool lock) -{ - int ret; - -#if defined(CONFIG_MODEM_GSM_ENABLE_CESQ_RSSI) - ret = modem_cmd_send_ext(&gsm->context.iface, &gsm->context.cmd_handler, &read_rssi_cmd, 1, - "AT+CESQ", &gsm->sem_response, GSM_CMD_SETUP_TIMEOUT, - lock ? 0 : MODEM_NO_TX_LOCK); -#else - ret = modem_cmd_send_ext(&gsm->context.iface, &gsm->context.cmd_handler, &read_rssi_cmd, 1, - "AT+CSQ", &gsm->sem_response, GSM_CMD_SETUP_TIMEOUT, - lock ? 0 : MODEM_NO_TX_LOCK); -#endif - - if (ret < 0) { - LOG_DBG("No answer to RSSI readout, %s", "ignoring..."); - } -} - -static inline void query_rssi_lock(struct gsm_modem *gsm) -{ - query_rssi(gsm, true); -} - -static inline void query_rssi_nolock(struct gsm_modem *gsm) -{ - query_rssi(gsm, false); -} - -static void rssi_handler(struct k_work *work) -{ - struct k_work_delayable *dwork = k_work_delayable_from_work(work); - struct gsm_modem *gsm = CONTAINER_OF(dwork, struct gsm_modem, rssi_work_handle); - - gsm_ppp_lock(gsm); - query_rssi_lock(gsm); - -#if defined(CONFIG_MODEM_CELL_INFO) - (void)gsm_query_cellinfo(gsm); -#endif - (void)gsm_work_reschedule(&gsm->rssi_work_handle, - K_SECONDS(CONFIG_MODEM_GSM_RSSI_POLLING_PERIOD)); - gsm_ppp_unlock(gsm); -} - -static void gsm_finalize_connection(struct k_work *work) -{ - int ret = 0; - struct k_work_delayable *dwork = k_work_delayable_from_work(work); - struct gsm_modem *gsm = CONTAINER_OF(dwork, struct gsm_modem, gsm_configure_work); - - gsm_ppp_lock(gsm); - - /* If already attached, jump right to RSSI readout */ - if (gsm->state == GSM_PPP_ATTACHED) { - goto attached; - } - - /* If attach check failed, we should not redo every setup step */ - if (gsm->state == GSM_PPP_ATTACHING) { - goto attaching; - } - - /* If modem is searching for network, we should skip the setup step */ - if (gsm->state == GSM_PPP_REGISTERING) { - goto registering; - } - - if (IS_ENABLED(CONFIG_GSM_MUX)) { - ret = modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - &response_cmds[0], - ARRAY_SIZE(response_cmds), - "AT", &gsm->sem_response, - GSM_CMD_AT_TIMEOUT); - if (ret < 0) { - LOG_ERR("%s returned %d, %s", "AT", ret, "retrying..."); - (void)gsm_work_reschedule(&gsm->gsm_configure_work, GSM_RETRY_DELAY); - goto unlock; - } - } - gsm->state = GSM_PPP_SETUP; - - if (IS_ENABLED(CONFIG_MODEM_GSM_FACTORY_RESET_AT_BOOT)) { - (void)modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - &response_cmds[0], - ARRAY_SIZE(response_cmds), - "AT&F", &gsm->sem_response, - GSM_CMD_AT_TIMEOUT); - (void)k_sleep(K_SECONDS(1)); - } - - ret = gsm_setup_mccmno(gsm); - if (ret < 0) { - LOG_ERR("%s returned %d, %s", "gsm_setup_mccmno", ret, "retrying..."); - - (void)gsm_work_reschedule(&gsm->gsm_configure_work, GSM_RETRY_DELAY); - goto unlock; - } - - ret = modem_cmd_handler_setup_cmds_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - setup_cmds, - ARRAY_SIZE(setup_cmds), - &gsm->sem_response, - GSM_CMD_SETUP_TIMEOUT); - if (ret < 0) { - LOG_DBG("%s returned %d, %s", "setup_cmds", ret, "retrying..."); - (void)gsm_work_reschedule(&gsm->gsm_configure_work, GSM_RETRY_DELAY); - goto unlock; - } - - ret = gsm_query_modem_info(gsm); - if (ret < 0) { - LOG_DBG("Unable to query modem information %d", ret); - (void)gsm_work_reschedule(&gsm->gsm_configure_work, GSM_RETRY_DELAY); - goto unlock; - } - - gsm->state = GSM_PPP_REGISTERING; -registering: - /* Wait for cell tower registration */ - ret = modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - &check_net_reg_cmd, 1, - "AT+" CONFIG_MODEM_GSM_STATUS_COMMAND "?", - &gsm->sem_response, - GSM_CMD_SETUP_TIMEOUT); - if ((ret < 0) || ((gsm->net_state != GSM_NET_ROAMING) && - (gsm->net_state != GSM_NET_HOME_NETWORK))) { - if (gsm->retries == 0) { - gsm->retries = CONFIG_MODEM_GSM_REGISTER_TIMEOUT * - (MSEC_PER_SEC / GSM_REGISTER_DELAY_MSEC); - } else { - gsm->retries--; - } - - (void)gsm_work_reschedule(&gsm->gsm_configure_work, - K_MSEC(GSM_REGISTER_DELAY_MSEC)); - goto unlock; - } - - gsm->retries = 0; - gsm->state = GSM_PPP_ATTACHING; -attaching: - /* Don't initialize PPP until we're attached to packet service */ - ret = modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - &check_attached_cmd, 1, - "AT+CGATT?", - &gsm->sem_response, - GSM_CMD_SETUP_TIMEOUT); - if (ret < 0) { - /* - * retries not set -> trigger N attach retries - * retries set -> decrement and retry - * retries set, becomes 0 -> trigger full retry - */ - if (gsm->retries == 0) { - gsm->retries = CONFIG_MODEM_GSM_ATTACH_TIMEOUT * - (MSEC_PER_SEC / GSM_ATTACH_RETRY_DELAY_MSEC); - } else { - gsm->retries--; - } - - LOG_DBG("Not attached, %s", "retrying..."); - - (void)gsm_work_reschedule(&gsm->gsm_configure_work, - K_MSEC(GSM_ATTACH_RETRY_DELAY_MSEC)); - goto unlock; - } - - /* Attached, clear retry counter */ - LOG_DBG("modem attach returned %d, %s", ret, "read RSSI"); - gsm->state = GSM_PPP_ATTACHED; - gsm->retries = GSM_RSSI_RETRIES; - - attached: - - if (!IS_ENABLED(CONFIG_GSM_MUX)) { - /* Read connection quality (RSSI) before PPP carrier is ON */ - query_rssi_nolock(gsm); - - if (!((gsm->minfo.mdm_rssi) && (gsm->minfo.mdm_rssi != GSM_RSSI_INVALID) && - (gsm->minfo.mdm_rssi <= GSM_RSSI_MAXVAL))) { - - LOG_DBG("Not valid RSSI, %s", "retrying..."); - if (gsm->retries-- > 0) { - (void)gsm_work_reschedule(&gsm->gsm_configure_work, - K_MSEC(GSM_RSSI_RETRY_DELAY_MSEC)); - goto unlock; - } - } -#if defined(CONFIG_MODEM_CELL_INFO) - (void)gsm_query_cellinfo(gsm); -#endif - } - - LOG_DBG("modem RSSI: %d, %s", gsm->minfo.mdm_rssi, "enable PPP"); - - ret = modem_cmd_handler_setup_cmds_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - connect_cmds, - ARRAY_SIZE(connect_cmds), - &gsm->sem_response, - GSM_CMD_SETUP_TIMEOUT); - if (ret < 0) { - LOG_DBG("%s returned %d, %s", "connect_cmds", ret, "retrying..."); - (void)gsm_work_reschedule(&gsm->gsm_configure_work, GSM_RETRY_DELAY); - goto unlock; - } - - gsm->state = GSM_PPP_SETUP_DONE; - set_ppp_carrier_on(gsm); - - if (IS_ENABLED(CONFIG_GSM_MUX)) { - /* Re-use the original iface for AT channel */ - ret = modem_iface_uart_init_dev(&gsm->context.iface, - gsm->at_dev); - if (ret < 0) { - LOG_DBG("iface %suart error %d", "AT ", ret); - gsm->state = GSM_PPP_STATE_ERROR; - } else { - /* Do a test and try to send AT command to modem */ - ret = modem_cmd_send_nolock( - &gsm->context.iface, - &gsm->context.cmd_handler, - &response_cmds[0], - ARRAY_SIZE(response_cmds), - "AT", &gsm->sem_response, - GSM_CMD_AT_TIMEOUT); - if (ret < 0) { - LOG_WRN("%s returned %d, %s", "AT", ret, "iface failed"); - gsm->state = GSM_PPP_STATE_ERROR; - } else { - LOG_INF("AT channel %d connected to %s", - DLCI_AT, gsm->at_dev->name); - } - } - - modem_cmd_handler_tx_unlock(&gsm->context.cmd_handler); - if (gsm->state != GSM_PPP_STATE_ERROR) { - (void)gsm_work_reschedule(&gsm->rssi_work_handle, - K_SECONDS(CONFIG_MODEM_GSM_RSSI_POLLING_PERIOD)); - } - } - -unlock: - gsm_ppp_unlock(gsm); -} - -static int mux_enable(struct gsm_modem *gsm) -{ - int ret; - - /* Turn on muxing */ - if (IS_ENABLED(CONFIG_MODEM_GSM_SIMCOM)) { - ret = modem_cmd_send_nolock( - &gsm->context.iface, - &gsm->context.cmd_handler, - &response_cmds[0], - ARRAY_SIZE(response_cmds), -#if defined(SIMCOM_LTE) - /* FIXME */ - /* Some SIMCOM modems can set the channels */ - /* Control channel always at DLCI 0 */ - "AT+CMUXSRVPORT=0,0;" - /* PPP should be at DLCI 1 */ - "+CMUXSRVPORT=" STRINGIFY(DLCI_PPP) ",1;" - /* AT should be at DLCI 2 */ - "+CMUXSRVPORT=" STRINGIFY(DLCI_AT) ",1;" -#else - "AT" -#endif - "+CMUX=0,0,5," - STRINGIFY(CONFIG_GSM_MUX_MRU_DEFAULT_LEN), - &gsm->sem_response, - GSM_CMD_AT_TIMEOUT); - } else if (IS_ENABLED(CONFIG_MODEM_GSM_QUECTEL)) { - ret = modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - &response_cmds[0], - ARRAY_SIZE(response_cmds), - "AT+CMUX=0,0,5," - STRINGIFY(CONFIG_GSM_MUX_MRU_DEFAULT_LEN), - &gsm->sem_response, - GSM_CMD_AT_TIMEOUT); - - /* Arbitrary delay for Quectel modems to initialize the CMUX, - * without this the AT cmd will fail. - */ - (void)k_sleep(K_SECONDS(1)); - } else { - /* Generic GSM modem */ - ret = modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - &response_cmds[0], - ARRAY_SIZE(response_cmds), - "AT+CMUX=0", &gsm->sem_response, - GSM_CMD_AT_TIMEOUT); - } - - if (ret < 0) { - LOG_ERR("AT+CMUX ret:%d", ret); - } - - return ret; -} - -static void mux_setup_next(struct gsm_modem *gsm) -{ - (void)gsm_work_reschedule(&gsm->gsm_configure_work, K_MSEC(1)); -} - -static void mux_attach_cb(const struct device *mux, int dlci_address, - bool connected, void *user_data) -{ - LOG_DBG("DLCI %d to %s %s", dlci_address, mux->name, - connected ? "connected" : "disconnected"); - - if (connected) { - uart_irq_rx_enable(mux); - uart_irq_tx_enable(mux); - } - - mux_setup_next(user_data); -} - -static int mux_attach(const struct device *mux, const struct device *uart, - int dlci_address, void *user_data) -{ - int ret = uart_mux_attach(mux, uart, dlci_address, mux_attach_cb, - user_data); - if (ret < 0) { - LOG_ERR("Cannot attach DLCI %d (%s) to %s (%d)", dlci_address, - mux->name, uart->name, ret); - return ret; - } - - return 0; -} - -static void mux_setup(struct k_work *work) -{ - struct k_work_delayable *dwork = k_work_delayable_from_work(work); - struct gsm_modem *gsm = CONTAINER_OF(dwork, struct gsm_modem, - gsm_configure_work); - const struct device *const uart = DEVICE_DT_GET(GSM_UART_NODE); - int ret; - - gsm_ppp_lock(gsm); - - switch (gsm->state) { - case GSM_PPP_STATE_CONTROL_CHANNEL: - /* We need to call this to reactivate mux ISR. Note: This is only called - * after re-initing gsm_ppp. - */ - if (gsm->ppp_dev != NULL) { - uart_mux_enable(gsm->ppp_dev); - } - - /* Get UART device. There is one dev / DLCI */ - if (gsm->control_dev == NULL) { - gsm->control_dev = uart_mux_alloc(); - if (gsm->control_dev == NULL) { - LOG_DBG("Cannot get UART mux for %s channel", - "control"); - goto fail; - } - } - - ret = mux_attach(gsm->control_dev, uart, DLCI_CONTROL, gsm); - if (ret < 0) { - goto fail; - } - - gsm->state = GSM_PPP_STATE_PPP_CHANNEL; - goto unlock; - - case GSM_PPP_STATE_PPP_CHANNEL: - if (gsm->ppp_dev == NULL) { - gsm->ppp_dev = uart_mux_alloc(); - if (gsm->ppp_dev == NULL) { - LOG_DBG("Cannot get UART mux for %s channel", - "PPP"); - goto fail; - } - } - - ret = mux_attach(gsm->ppp_dev, uart, DLCI_PPP, gsm); - if (ret < 0) { - goto fail; - } - - gsm->state = GSM_PPP_STATE_AT_CHANNEL; - goto unlock; - - case GSM_PPP_STATE_AT_CHANNEL: - if (gsm->at_dev == NULL) { - gsm->at_dev = uart_mux_alloc(); - if (gsm->at_dev == NULL) { - LOG_DBG("Cannot get UART mux for %s channel", - "AT"); - goto fail; - } - } - - ret = mux_attach(gsm->at_dev, uart, DLCI_AT, gsm); - if (ret < 0) { - goto fail; - } - - gsm->state = GSM_PPP_STATE_DONE; - goto unlock; - - case GSM_PPP_STATE_DONE: - /* At least the SIMCOM modem expects that the Internet - * connection is created in PPP channel. We will need - * to attach the AT channel to context iface after the - * PPP connection is established in order to give AT commands - * to the modem. - */ - ret = modem_iface_uart_init_dev(&gsm->context.iface, - gsm->ppp_dev); - if (ret < 0) { - LOG_DBG("iface %suart error %d", "PPP ", ret); - goto fail; - } - - LOG_INF("PPP channel %d connected to %s", - DLCI_PPP, gsm->ppp_dev->name); - - k_work_init_delayable(&gsm->gsm_configure_work, gsm_finalize_connection); - (void)gsm_work_reschedule(&gsm->gsm_configure_work, K_NO_WAIT); - goto unlock; - default: - __ASSERT(0, "%s while in state: %d", "mux_setup", gsm->state); - /* In case CONFIG_ASSERT is off, goto fail */ - goto fail; - } - -fail: - gsm->state = GSM_PPP_STATE_ERROR; -unlock: - gsm_ppp_unlock(gsm); -} - -static void gsm_configure(struct k_work *work) -{ - struct k_work_delayable *dwork = k_work_delayable_from_work(work); - struct gsm_modem *gsm = CONTAINER_OF(dwork, struct gsm_modem, - gsm_configure_work); - int ret = -1; - - gsm_ppp_lock(gsm); - - if (gsm->state == GSM_PPP_WAIT_AT) { - goto wait_at; - } - - if (gsm->state == GSM_PPP_START) { - LOG_DBG("Starting modem %p configuration", gsm); - - if (gsm->modem_on_cb != NULL) { - gsm->modem_on_cb(gsm->dev, gsm->user_data); - } - - gsm->state = GSM_PPP_WAIT_AT; - } - -wait_at: - ret = modem_cmd_send_nolock(&gsm->context.iface, - &gsm->context.cmd_handler, - &response_cmds[0], - ARRAY_SIZE(response_cmds), - "AT", &gsm->sem_response, - GSM_CMD_AT_TIMEOUT); - if (ret < 0) { - LOG_DBG("modem not ready %d", ret); - goto retry; - } - - gsm->state = GSM_PPP_AT_RDY; - - if (IS_ENABLED(CONFIG_GSM_MUX)) { - if (mux_enable(gsm) == 0) { - LOG_DBG("GSM muxing %s", "enabled"); - } else { - LOG_DBG("GSM muxing %s", "disabled"); - goto retry; - } - - gsm->state = GSM_PPP_STATE_INIT; - - k_work_init_delayable(&gsm->gsm_configure_work, mux_setup); - } else { - k_work_init_delayable(&gsm->gsm_configure_work, gsm_finalize_connection); - } - -retry: - (void)gsm_work_reschedule(&gsm->gsm_configure_work, K_NO_WAIT); - gsm_ppp_unlock(gsm); -} - -void gsm_ppp_start(const struct device *dev) -{ - int ret; - struct gsm_modem *gsm = dev->data; - - gsm_ppp_lock(gsm); - - if (gsm->state != GSM_PPP_STOP) { - LOG_ERR("gsm_ppp is already %s", "started"); - goto unlock; - } - - gsm->state = GSM_PPP_START; - - /* Re-init underlying UART comms */ - ret = modem_iface_uart_init_dev(&gsm->context.iface, DEVICE_DT_GET(GSM_UART_NODE)); - if (ret < 0) { - LOG_ERR("modem_iface_uart_init returned %d", ret); - gsm->state = GSM_PPP_STATE_ERROR; - goto unlock; - } - - k_work_init_delayable(&gsm->gsm_configure_work, gsm_configure); - (void)gsm_work_reschedule(&gsm->gsm_configure_work, K_NO_WAIT); - -unlock: - gsm_ppp_unlock(gsm); -} - -void gsm_ppp_stop(const struct device *dev) -{ - struct gsm_modem *gsm = dev->data; - struct net_if *iface = gsm->iface; - struct k_work_sync work_sync; - - if (gsm->state == GSM_PPP_STOP) { - LOG_ERR("gsm_ppp is already %s", "stopped"); - return; - } - - (void)k_work_cancel_delayable_sync(&gsm->gsm_configure_work, &work_sync); - if (IS_ENABLED(CONFIG_GSM_MUX)) { - (void)k_work_cancel_delayable_sync(&gsm->rssi_work_handle, &work_sync); - } - - gsm_ppp_lock(gsm); - - /* wait for the interface to be properly down */ - if (net_if_is_up(iface)) { - net_if_down(ppp_net_if()); - (void)k_sem_take(&gsm->sem_if_down, K_FOREVER); - } - - if (IS_ENABLED(CONFIG_GSM_MUX)) { - if (gsm->ppp_dev != NULL) { - uart_mux_disable(gsm->ppp_dev); - } - - if (modem_cmd_handler_tx_lock(&gsm->context.cmd_handler, - GSM_CMD_LOCK_TIMEOUT) < 0) { - LOG_WRN("Failed locking modem cmds!"); - } - } - - if (gsm->modem_off_cb != NULL) { - gsm->modem_off_cb(gsm->dev, gsm->user_data); - } - - gsm->state = GSM_PPP_STOP; - gsm->net_state = GSM_NET_INIT; - gsm_ppp_unlock(gsm); -} - -void gsm_ppp_register_modem_power_callback(const struct device *dev, - gsm_modem_power_cb modem_on, - gsm_modem_power_cb modem_off, - void *user_data) -{ - struct gsm_modem *gsm = dev->data; - - gsm_ppp_lock(gsm); - - gsm->modem_on_cb = modem_on; - gsm->modem_off_cb = modem_off; - - gsm->user_data = user_data; - gsm_ppp_unlock(gsm); -} - -const struct gsm_ppp_modem_info *gsm_ppp_modem_info(const struct device *dev) -{ - struct gsm_modem *gsm = dev->data; - - return &gsm->minfo; -} - -static void gsm_mgmt_event_handler(struct net_mgmt_event_callback *cb, - uint32_t mgmt_event, struct net_if *iface) -{ - if ((mgmt_event & NET_EVENT_IF_DOWN) != mgmt_event) { - return; - } - - /* Right now we only support 1 GSM instance */ - if (iface != modem.iface) { - return; - } - - if (mgmt_event == NET_EVENT_IF_DOWN) { - LOG_INF("GSM network interface down"); - /* raise semaphore to indicate the interface is down */ - k_sem_give(&modem.sem_if_down); - return; - } -} - -static int gsm_init(const struct device *dev) -{ - struct gsm_modem *gsm = dev->data; - int ret; - - LOG_DBG("Generic GSM modem (%p)", gsm); - - (void)k_mutex_init(&gsm->lock); - gsm->dev = dev; - - const struct modem_cmd_handler_config cmd_handler_config = { - .match_buf = &gsm->cmd_match_buf[0], - .match_buf_len = sizeof(gsm->cmd_match_buf), - .buf_pool = &gsm_recv_pool, - .alloc_timeout = K_NO_WAIT, - .eol = "\r", - .user_data = NULL, - .response_cmds = response_cmds, - .response_cmds_len = ARRAY_SIZE(response_cmds), - .unsol_cmds = NULL, - .unsol_cmds_len = 0, - }; - - (void)k_sem_init(&gsm->sem_response, 0, 1); - (void)k_sem_init(&gsm->sem_if_down, 0, 1); - - ret = modem_cmd_handler_init(&gsm->context.cmd_handler, &gsm->cmd_handler_data, - &cmd_handler_config); - if (ret < 0) { - LOG_DBG("cmd handler error %d", ret); - return ret; - } - -#if defined(CONFIG_MODEM_SHELL) - /* modem information storage */ - gsm->context.data_manufacturer = gsm->minfo.mdm_manufacturer; - gsm->context.data_model = gsm->minfo.mdm_model; - gsm->context.data_revision = gsm->minfo.mdm_revision; - gsm->context.data_imei = gsm->minfo.mdm_imei; -#if defined(CONFIG_MODEM_SIM_NUMBERS) - gsm->context.data_imsi = gsm->minfo.mdm_imsi; - gsm->context.data_iccid = gsm->minfo.mdm_iccid; -#endif /* CONFIG_MODEM_SIM_NUMBERS */ - gsm->context.data_rssi = &gsm->minfo.mdm_rssi; -#endif /* CONFIG_MODEM_SHELL */ - - gsm->context.is_automatic_oper = false; - - const struct modem_iface_uart_config uart_config = { - .rx_rb_buf = &gsm->gsm_rx_rb_buf[0], - .rx_rb_buf_len = sizeof(gsm->gsm_rx_rb_buf), - .hw_flow_control = DT_PROP(GSM_UART_NODE, hw_flow_control), - .dev = DEVICE_DT_GET(GSM_UART_NODE), - }; - - ret = modem_iface_uart_init(&gsm->context.iface, &gsm->gsm_data, &uart_config); - if (ret < 0) { - LOG_DBG("iface uart error %d", ret); - return ret; - } - - ret = modem_context_register(&gsm->context); - if (ret < 0) { - LOG_DBG("context error %d", ret); - return ret; - } - - /* Initialize to stop state so that it can be started later */ - gsm->state = GSM_PPP_STOP; - - gsm->net_state = GSM_NET_INIT; - - LOG_DBG("iface->read %p iface->write %p", - gsm->context.iface.read, gsm->context.iface.write); - - (void)k_thread_create(&gsm->rx_thread, gsm_rx_stack, - K_KERNEL_STACK_SIZEOF(gsm_rx_stack), - gsm_rx, - gsm, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); - (void)k_thread_name_set(&gsm->rx_thread, "gsm_rx"); - - /* initialize the work queue */ - k_work_queue_init(&gsm->workq); - k_work_queue_start(&gsm->workq, gsm_workq_stack, K_KERNEL_STACK_SIZEOF(gsm_workq_stack), - K_PRIO_COOP(7), NULL); - (void)k_thread_name_set(&gsm->workq.thread, "gsm_workq"); - - if (IS_ENABLED(CONFIG_GSM_MUX)) { - k_work_init_delayable(&gsm->rssi_work_handle, rssi_handler); - } - - gsm->iface = ppp_net_if(); - if (gsm->iface == NULL) { - LOG_ERR("Couldn't find ppp net_if!"); - return -ENODEV; - } - - net_mgmt_init_event_callback(&gsm->gsm_mgmt_cb, gsm_mgmt_event_handler, - NET_EVENT_IF_DOWN); - net_mgmt_add_event_callback(&gsm->gsm_mgmt_cb); - - if (IS_ENABLED(CONFIG_GSM_PPP_AUTOSTART)) { - gsm_ppp_start(dev); - } - - return 0; -} - -DEVICE_DT_DEFINE(DT_DRV_INST(0), gsm_init, NULL, &modem, NULL, - POST_KERNEL, CONFIG_MODEM_GSM_INIT_PRIORITY, NULL); diff --git a/drivers/modem/modem_at_shell.c b/drivers/modem/modem_at_shell.c new file mode 100644 index 0000000000000..5d2820d7483ed --- /dev/null +++ b/drivers/modem/modem_at_shell.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(modem_at_shell, CONFIG_MODEM_LOG_LEVEL); + +#define AT_SHELL_MODEM_NODE DT_ALIAS(modem) +#define AT_SHELL_PIPELINK_NAME _CONCAT(user_pipe_, CONFIG_MODEM_AT_SHELL_USER_PIPE) + +#define AT_SHELL_STATE_ATTACHED_BIT 0 +#define AT_SHELL_STATE_SCRIPT_RUNNING_BIT 1 + +MODEM_PIPELINK_DT_DECLARE(AT_SHELL_MODEM_NODE, AT_SHELL_PIPELINK_NAME); + +static struct modem_pipelink *at_shell_pipelink = + MODEM_PIPELINK_DT_GET(AT_SHELL_MODEM_NODE, AT_SHELL_PIPELINK_NAME); + +static struct modem_chat at_shell_chat; +static uint8_t at_shell_chat_receive_buf[CONFIG_MODEM_AT_SHELL_CHAT_RECEIVE_BUF_SIZE]; +static uint8_t *at_shell_chat_argv_buf[2]; +static uint8_t at_shell_request_buf[CONFIG_MODEM_AT_SHELL_COMMAND_MAX_SIZE]; +static struct modem_chat_script_chat at_shell_script_chat[1]; +static struct modem_chat_match at_shell_script_chat_matches[2]; +static uint8_t at_shell_match_buf[CONFIG_MODEM_AT_SHELL_RESPONSE_MAX_SIZE]; +static const struct shell *at_shell_active_shell; +static struct k_work at_shell_open_pipe_work; +static struct k_work at_shell_attach_chat_work; +static struct k_work at_shell_release_chat_work; +static atomic_t at_shell_state; + +static void at_shell_print_any_match(struct modem_chat *chat, char **argv, uint16_t argc, + void *user_data) +{ + if (at_shell_active_shell == NULL) { + return; + } + + if (argc != 2) { + return; + } + + shell_print(at_shell_active_shell, "%s", argv[1]); +} + +static void at_shell_print_match(struct modem_chat *chat, char **argv, uint16_t argc, + void *user_data) +{ + if (at_shell_active_shell == NULL) { + return; + } + + if (argc != 1) { + return; + } + + shell_print(at_shell_active_shell, "%s", argv[0]); +} + +MODEM_CHAT_MATCHES_DEFINE( + at_shell_abort_matches, + MODEM_CHAT_MATCH("ERROR", "", at_shell_print_match), +); + +static void at_shell_script_callback(struct modem_chat *chat, + enum modem_chat_script_result result, + void *user_data) +{ + atomic_clear_bit(&at_shell_state, AT_SHELL_STATE_SCRIPT_RUNNING_BIT); +} + +MODEM_CHAT_SCRIPT_DEFINE( + at_shell_script, + at_shell_script_chat, + at_shell_abort_matches, + at_shell_script_callback, + CONFIG_MODEM_AT_SHELL_RESPONSE_TIMEOUT_S +); + +static void at_shell_pipe_callback(struct modem_pipe *pipe, + enum modem_pipe_event event, + void *user_data) +{ + ARG_UNUSED(user_data); + + switch (event) { + case MODEM_PIPE_EVENT_OPENED: + LOG_INF("pipe opened"); + k_work_submit(&at_shell_attach_chat_work); + break; + + default: + break; + } +} + +void at_shell_pipelink_callback(struct modem_pipelink *link, + enum modem_pipelink_event event, + void *user_data) +{ + ARG_UNUSED(user_data); + + switch (event) { + case MODEM_PIPELINK_EVENT_CONNECTED: + LOG_INF("pipe connected"); + k_work_submit(&at_shell_open_pipe_work); + break; + + case MODEM_PIPELINK_EVENT_DISCONNECTED: + LOG_INF("pipe disconnected"); + k_work_submit(&at_shell_release_chat_work); + break; + + default: + break; + } +} + +static void at_shell_open_pipe_handler(struct k_work *work) +{ + ARG_UNUSED(work); + + LOG_INF("opening pipe"); + + modem_pipe_attach(modem_pipelink_get_pipe(at_shell_pipelink), + at_shell_pipe_callback, + NULL); + + modem_pipe_open_async(modem_pipelink_get_pipe(at_shell_pipelink)); +} + +static void at_shell_attach_chat_handler(struct k_work *work) +{ + ARG_UNUSED(work); + + modem_chat_attach(&at_shell_chat, modem_pipelink_get_pipe(at_shell_pipelink)); + atomic_set_bit(&at_shell_state, AT_SHELL_STATE_ATTACHED_BIT); + LOG_INF("chat attached"); +} + +static void at_shell_release_chat_handler(struct k_work *work) +{ + ARG_UNUSED(work); + + modem_chat_release(&at_shell_chat); + atomic_clear_bit(&at_shell_state, AT_SHELL_STATE_ATTACHED_BIT); + LOG_INF("chat released"); +} + +static void at_shell_init_work(void) +{ + k_work_init(&at_shell_open_pipe_work, at_shell_open_pipe_handler); + k_work_init(&at_shell_attach_chat_work, at_shell_attach_chat_handler); + k_work_init(&at_shell_release_chat_work, at_shell_release_chat_handler); +} + +static void at_shell_init_chat(void) +{ + const struct modem_chat_config at_shell_chat_config = { + .receive_buf = at_shell_chat_receive_buf, + .receive_buf_size = sizeof(at_shell_chat_receive_buf), + .delimiter = "\r", + .delimiter_size = sizeof("\r") - 1, + .filter = "\n", + .filter_size = sizeof("\n") - 1, + .argv = at_shell_chat_argv_buf, + .argv_size = ARRAY_SIZE(at_shell_chat_argv_buf), + }; + + modem_chat_init(&at_shell_chat, &at_shell_chat_config); +} + +static void at_shell_init_script_chat(void) +{ + /* Match anything except the expected response without progressing script */ + modem_chat_match_init(&at_shell_script_chat_matches[0]); + modem_chat_match_set_match(&at_shell_script_chat_matches[0], ""); + modem_chat_match_set_separators(&at_shell_script_chat_matches[0], ""); + modem_chat_match_set_callback(&at_shell_script_chat_matches[0], at_shell_print_any_match); + modem_chat_match_set_partial(&at_shell_script_chat_matches[0], true); + modem_chat_match_enable_wildcards(&at_shell_script_chat_matches[0], false); + + /* Match the expected response and terminate script */ + modem_chat_match_init(&at_shell_script_chat_matches[1]); + modem_chat_match_set_match(&at_shell_script_chat_matches[1], ""); + modem_chat_match_set_separators(&at_shell_script_chat_matches[1], ""); + modem_chat_match_set_callback(&at_shell_script_chat_matches[1], at_shell_print_match); + modem_chat_match_set_partial(&at_shell_script_chat_matches[1], false); + modem_chat_match_enable_wildcards(&at_shell_script_chat_matches[1], false); + + modem_chat_script_chat_init(at_shell_script_chat); + modem_chat_script_chat_set_response_matches(at_shell_script_chat, + at_shell_script_chat_matches, + ARRAY_SIZE(at_shell_script_chat_matches)); + modem_chat_script_chat_set_timeout(at_shell_script_chat, + CONFIG_MODEM_AT_SHELL_RESPONSE_TIMEOUT_S); +} + +static void at_shell_init_pipelink(void) +{ + modem_pipelink_attach(at_shell_pipelink, at_shell_pipelink_callback, NULL); +} + +static int at_shell_init(void) +{ + at_shell_init_work(); + at_shell_init_chat(); + at_shell_init_script_chat(); + at_shell_init_pipelink(); + return 0; +} + +SYS_INIT(at_shell_init, POST_KERNEL, 99); + +static int at_shell_cmd_handler(const struct shell *sh, size_t argc, char **argv) +{ + int ret; + + if (argc < 2) { + return -EINVAL; + } + + if (!atomic_test_bit(&at_shell_state, AT_SHELL_STATE_ATTACHED_BIT)) { + shell_error(sh, "modem is not ready"); + return -EPERM; + } + + if (atomic_test_and_set_bit(&at_shell_state, AT_SHELL_STATE_SCRIPT_RUNNING_BIT)) { + shell_error(sh, "script is already running"); + return -EBUSY; + } + + strncpy(at_shell_request_buf, argv[1], sizeof(at_shell_request_buf) - 1); + ret = modem_chat_script_chat_set_request(at_shell_script_chat, at_shell_request_buf); + if (ret < 0) { + return -EINVAL; + } + + if (argc == 3) { + strncpy(at_shell_match_buf, argv[2], sizeof(at_shell_match_buf) - 1); + } else { + strncpy(at_shell_match_buf, "OK", sizeof(at_shell_match_buf) - 1); + } + + ret = modem_chat_match_set_match(&at_shell_script_chat_matches[1], at_shell_match_buf); + if (ret < 0) { + return -EINVAL; + } + + at_shell_active_shell = sh; + + ret = modem_chat_run_script_async(&at_shell_chat, &at_shell_script); + if (ret < 0) { + shell_error(sh, "failed to start script"); + atomic_clear_bit(&at_shell_state, AT_SHELL_STATE_SCRIPT_RUNNING_BIT); + } + + return ret; +} + +SHELL_STATIC_SUBCMD_SET_CREATE(modem_sub_cmds, + SHELL_CMD_ARG(at, NULL, "at ", at_shell_cmd_handler, 1, 2), + SHELL_SUBCMD_SET_END +); + +SHELL_CMD_REGISTER(modem, &modem_sub_cmds, "Modem commands", NULL); diff --git a/drivers/modem/modem_cellular.c b/drivers/modem/modem_cellular.c index 7f646f4e78951..a3622adf2f499 100644 --- a/drivers/modem/modem_cellular.c +++ b/drivers/modem/modem_cellular.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -33,6 +34,8 @@ LOG_MODULE_REGISTER(modem_cellular, CONFIG_MODEM_LOG_LEVEL); #define MODEM_CELLULAR_DATA_MANUFACTURER_LEN (65) #define MODEM_CELLULAR_DATA_FW_VERSION_LEN (65) +#define MODEM_CELLULAR_RESERVED_DLCIS (2) + /* Magic constants */ #define CSQ_RSSI_UNKNOWN (99) #define CESQ_RSRP_UNKNOWN (255) @@ -86,6 +89,7 @@ struct modem_cellular_data { struct modem_cmux cmux; uint8_t cmux_receive_buf[CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE]; uint8_t cmux_transmit_buf[2 * CONFIG_MODEM_CELLULAR_CMUX_MAX_FRAME_SIZE]; + struct modem_cmux_dlci dlci1; struct modem_cmux_dlci dlci2; struct modem_pipe *dlci1_pipe; @@ -132,18 +136,29 @@ struct modem_cellular_data { struct k_mutex event_rb_lock; }; +struct modem_cellular_user_pipe { + struct modem_cmux_dlci dlci; + uint8_t dlci_address; + uint8_t *dlci_receive_buf; + uint16_t dlci_receive_buf_size; + struct modem_pipe *pipe; + struct modem_pipelink *pipelink; +}; + struct modem_cellular_config { const struct device *uart; - const struct gpio_dt_spec power_gpio; - const struct gpio_dt_spec reset_gpio; - const uint16_t power_pulse_duration_ms; - const uint16_t reset_pulse_duration_ms; - const uint16_t startup_time_ms; - const uint16_t shutdown_time_ms; - const bool autostarts; + struct gpio_dt_spec power_gpio; + struct gpio_dt_spec reset_gpio; + uint16_t power_pulse_duration_ms; + uint16_t reset_pulse_duration_ms; + uint16_t startup_time_ms; + uint16_t shutdown_time_ms; + bool autostarts; const struct modem_chat_script *init_chat_script; const struct modem_chat_script *dial_chat_script; const struct modem_chat_script *periodic_chat_script; + struct modem_cellular_user_pipe *user_pipes; + uint8_t user_pipes_size; }; static const char *modem_cellular_state_str(enum modem_cellular_state state) @@ -219,6 +234,34 @@ static bool modem_cellular_gpio_is_enabled(const struct gpio_dt_spec *gpio) return gpio->port != NULL; } +static void modem_cellular_notify_user_pipes_connected(struct modem_cellular_data *data) +{ + const struct modem_cellular_config *config = + (const struct modem_cellular_config *)data->dev->config; + struct modem_cellular_user_pipe *user_pipe; + struct modem_pipelink *pipelink; + + for (uint8_t i = 0; i < config->user_pipes_size; i++) { + user_pipe = &config->user_pipes[i]; + pipelink = user_pipe->pipelink; + modem_pipelink_notify_connected(pipelink); + } +} + +static void modem_cellular_notify_user_pipes_disconnected(struct modem_cellular_data *data) +{ + const struct modem_cellular_config *config = + (const struct modem_cellular_config *)data->dev->config; + struct modem_cellular_user_pipe *user_pipe; + struct modem_pipelink *pipelink; + + for (uint8_t i = 0; i < config->user_pipes_size; i++) { + user_pipe = &config->user_pipes[i]; + pipelink = user_pipe->pipelink; + modem_pipelink_notify_disconnected(pipelink); + } +} + static void modem_cellular_enter_state(struct modem_cellular_data *data, enum modem_cellular_state state); @@ -530,6 +573,7 @@ static int modem_cellular_on_idle_state_enter(struct modem_cellular_data *data) gpio_pin_set_dt(&config->reset_gpio, 1); } + modem_cellular_notify_user_pipes_disconnected(data); modem_chat_release(&data->chat); modem_ppp_release(data->ppp); modem_cmux_release(&data->cmux); @@ -766,6 +810,7 @@ static void modem_cellular_connect_cmux_event_handler(struct modem_cellular_data break; case MODEM_CELLULAR_EVENT_CMUX_CONNECTED: + modem_cellular_notify_user_pipes_connected(data); modem_cellular_enter_state(data, MODEM_CELLULAR_STATE_OPEN_DLCI1); break; @@ -994,6 +1039,7 @@ static void modem_cellular_init_power_off_event_handler(struct modem_cellular_da static int modem_cellular_on_init_power_off_state_leave(struct modem_cellular_data *data) { + modem_cellular_notify_user_pipes_disconnected(data); modem_chat_release(&data->chat); modem_ppp_release(data->ppp); return 0; @@ -1560,6 +1606,20 @@ static int modem_cellular_init(const struct device *dev) &dlci2_config); } + for (uint8_t i = 0; i < config->user_pipes_size; i++) { + struct modem_cellular_user_pipe *user_pipe = &config->user_pipes[i]; + const struct modem_cmux_dlci_config user_dlci_config = { + .dlci_address = user_pipe->dlci_address, + .receive_buf = user_pipe->dlci_receive_buf, + .receive_buf_size = user_pipe->dlci_receive_buf_size, + }; + + user_pipe->pipe = modem_cmux_dlci_init(&data->cmux, &user_pipe->dlci, + &user_dlci_config); + + modem_pipelink_init(user_pipe->pipelink, user_pipe->pipe); + } + { const struct modem_chat_config chat_config = { .user_data = data, @@ -1698,57 +1758,6 @@ MODEM_CHAT_SCRIPT_DEFINE(quectel_eg25_g_periodic_chat_script, modem_cellular_chat_callback_handler, 4); #endif -#if DT_HAS_COMPAT_STATUS_OKAY(zephyr_gsm_ppp) -MODEM_CHAT_SCRIPT_CMDS_DEFINE(zephyr_gsm_ppp_init_chat_script_cmds, - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), - MODEM_CHAT_SCRIPT_CMD_RESP("ATE0", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=4", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CMEE=1", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG=1", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG=1", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG=1", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGSN", imei_match), - MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGMM", cgmm_match), - MODEM_CHAT_SCRIPT_CMD_RESP("", ok_match), - /* The 300ms delay after sending the AT+CMUX command is required - * for some modems to ensure they get enough time to enter CMUX - * mode before sending the first CMUX command. If this delay is - * too short, modems have been observed to simply deadlock, - * refusing to respond to any CMUX command. - */ - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT+CMUX=0,0,5,127", 300)); - -MODEM_CHAT_SCRIPT_DEFINE(zephyr_gsm_ppp_init_chat_script, zephyr_gsm_ppp_init_chat_script_cmds, - abort_matches, modem_cellular_chat_callback_handler, 10); - -MODEM_CHAT_SCRIPT_CMDS_DEFINE(zephyr_gsm_ppp_dial_chat_script_cmds, - MODEM_CHAT_SCRIPT_CMD_RESP_MULT("AT+CGACT=0,1", allow_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGDCONT=1,\"IP\"," - "\""CONFIG_MODEM_CELLULAR_APN"\"", - ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CFUN=1", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP_NONE("ATD*99***1#", 0),); - -MODEM_CHAT_SCRIPT_DEFINE(zephyr_gsm_ppp_dial_chat_script, zephyr_gsm_ppp_dial_chat_script_cmds, - dial_abort_matches, modem_cellular_chat_callback_handler, 10); - -MODEM_CHAT_SCRIPT_CMDS_DEFINE(zephyr_gsm_ppp_periodic_chat_script_cmds, - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CREG?", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CEREG?", ok_match), - MODEM_CHAT_SCRIPT_CMD_RESP("AT+CGREG?", ok_match)); - -MODEM_CHAT_SCRIPT_DEFINE(zephyr_gsm_ppp_periodic_chat_script, - zephyr_gsm_ppp_periodic_chat_script_cmds, abort_matches, - modem_cellular_chat_callback_handler, 4); -#endif - #if DT_HAS_COMPAT_STATUS_OKAY(simcom_sim7080) MODEM_CHAT_SCRIPT_CMDS_DEFINE(simcom_sim7080_init_chat_script_cmds, MODEM_CHAT_SCRIPT_CMD_RESP_NONE("AT", 100), @@ -2078,7 +2087,27 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, #endif #define MODEM_CELLULAR_INST_NAME(name, inst) \ - _CONCAT(_CONCAT(_CONCAT(name, _), DT_DRV_COMPAT), inst) + _CONCAT_4(name, _, DT_DRV_COMPAT, inst) + +#define MODEM_CELLULAR_DEFINE_USER_PIPE_DATA(inst, name, size) \ + MODEM_PIPELINK_DT_INST_DEFINE(inst, name); \ + static uint8_t MODEM_CELLULAR_INST_NAME(name, inst)[size] \ + +#define MODEM_CELLULAR_INIT_USER_PIPE(_inst, _name, _dlci_address) \ + { \ + .dlci_address = _dlci_address, \ + .dlci_receive_buf = MODEM_CELLULAR_INST_NAME(_name, _inst), \ + .dlci_receive_buf_size = sizeof(MODEM_CELLULAR_INST_NAME(_name, _inst)), \ + .pipelink = MODEM_PIPELINK_DT_INST_GET(_inst, _name), \ + } + +#define MODEM_CELLULAR_DEFINE_USER_PIPES(inst, ...) \ + static struct modem_cellular_user_pipe MODEM_CELLULAR_INST_NAME(user_pipes, inst)[] = { \ + __VA_ARGS__ \ + } + +#define MODEM_CELLULAR_GET_USER_PIPES(inst) \ + MODEM_CELLULAR_INST_NAME(user_pipes, inst) #define MODEM_CELLULAR_DEVICE_QUECTEL_BG95(inst) \ MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ @@ -2089,7 +2118,32 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + gnss_pipe, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_0, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_1, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPES( \ + inst, \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, gnss_pipe, 3), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_0, 4), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_1, 5), \ + ); \ + \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2100,6 +2154,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .init_chat_script = &quectel_bg95_init_chat_script, \ .dial_chat_script = &quectel_bg95_dial_chat_script, \ .periodic_chat_script = &_CONCAT(DT_DRV_COMPAT, _periodic_chat_script), \ + .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ + .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ @@ -2118,7 +2174,32 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + gnss_pipe, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_0, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_1, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPES( \ + inst, \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, gnss_pipe, 3), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_0, 4), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_1, 5), \ + ); \ + \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2129,6 +2210,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .init_chat_script = &quectel_eg25_g_init_chat_script, \ .dial_chat_script = &quectel_eg25_g_dial_chat_script, \ .periodic_chat_script = &_CONCAT(DT_DRV_COMPAT, _periodic_chat_script), \ + .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ + .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ @@ -2138,7 +2221,7 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, \ &modem_cellular_api); -#define MODEM_CELLULAR_DEVICE_GSM_PPP(inst) \ +#define MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080(inst) \ MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ \ static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ @@ -2147,36 +2230,32 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ - .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ - .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ - .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ - .power_pulse_duration_ms = 1500, \ - .reset_pulse_duration_ms = 100, \ - .startup_time_ms = 10000, \ - .shutdown_time_ms = 5000, \ - .init_chat_script = &zephyr_gsm_ppp_init_chat_script, \ - .dial_chat_script = &zephyr_gsm_ppp_dial_chat_script, \ - .periodic_chat_script = &zephyr_gsm_ppp_periodic_chat_script, \ - }; \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + gnss_pipe, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ \ - PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_0, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ \ - DEVICE_DT_INST_DEFINE(inst, modem_cellular_init, PM_DEVICE_DT_INST_GET(inst), \ - &MODEM_CELLULAR_INST_NAME(data, inst), \ - &MODEM_CELLULAR_INST_NAME(config, inst), POST_KERNEL, 99, \ - &modem_cellular_api); - -#define MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080(inst) \ - MODEM_PPP_DEFINE(MODEM_CELLULAR_INST_NAME(ppp, inst), NULL, 98, 1500, 64); \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_1, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ \ - static struct modem_cellular_data MODEM_CELLULAR_INST_NAME(data, inst) = { \ - .chat_delimiter = "\r", \ - .chat_filter = "\n", \ - .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ - }; \ + MODEM_CELLULAR_DEFINE_USER_PIPES( \ + inst, \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, gnss_pipe, 3), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_0, 4), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_1, 5), \ + ); \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2187,6 +2266,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .init_chat_script = &simcom_sim7080_init_chat_script, \ .dial_chat_script = &simcom_sim7080_dial_chat_script, \ .periodic_chat_script = &simcom_sim7080_periodic_chat_script, \ + .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ + .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ @@ -2205,7 +2286,32 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + gnss_pipe, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_0, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_1, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPES( \ + inst, \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, gnss_pipe, 3), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_0, 4), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_1, 5), \ + ); \ + \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2216,6 +2322,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .init_chat_script = &u_blox_sara_r4_init_chat_script, \ .dial_chat_script = &u_blox_sara_r4_dial_chat_script, \ .periodic_chat_script = &u_blox_sara_r4_periodic_chat_script, \ + .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ + .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ @@ -2234,7 +2342,32 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + gnss_pipe, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_0, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_1, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPES( \ + inst, \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, gnss_pipe, 3), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_0, 4), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_1, 5), \ + ); \ + \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2246,6 +2379,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .init_chat_script = &u_blox_sara_r5_init_chat_script, \ .dial_chat_script = &u_blox_sara_r5_dial_chat_script, \ .periodic_chat_script = &u_blox_sara_r5_periodic_chat_script, \ + .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ + .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ @@ -2264,7 +2399,32 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + gnss_pipe, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_0, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_1, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPES( \ + inst, \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, gnss_pipe, 3), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_0, 4), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_1, 5), \ + ); \ + \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2275,6 +2435,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .init_chat_script = &swir_hl7800_init_chat_script, \ .dial_chat_script = &swir_hl7800_dial_chat_script, \ .periodic_chat_script = &swir_hl7800_periodic_chat_script, \ + .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ + .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ @@ -2293,7 +2455,32 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + gnss_pipe, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_0, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_1, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPES( \ + inst, \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, gnss_pipe, 3), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_0, 4), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_1, 5), \ + ); \ + \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2304,6 +2491,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .init_chat_script = &telit_me910g1_init_chat_script, \ .dial_chat_script = &telit_me910g1_dial_chat_script, \ .periodic_chat_script = &telit_me910g1_periodic_chat_script, \ + .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ + .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ @@ -2321,7 +2510,32 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + gnss_pipe, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_0, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_1, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPES( \ + inst, \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, gnss_pipe, 3), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_0, 4), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_1, 5), \ + ); \ + \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2332,6 +2546,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .init_chat_script = &nordic_nrf91_slm_init_chat_script, \ .dial_chat_script = &nordic_nrf91_slm_dial_chat_script, \ .periodic_chat_script = &nordic_nrf91_slm_periodic_chat_script, \ + .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ + .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ @@ -2350,7 +2566,32 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .ppp = &MODEM_CELLULAR_INST_NAME(ppp, inst), \ }; \ \ - static struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + gnss_pipe, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_0, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPE_DATA( \ + inst, \ + user_pipe_1, \ + CONFIG_MODEM_CELLULAR_USER_PIPE_BUFFER_SIZES \ + ); \ + \ + MODEM_CELLULAR_DEFINE_USER_PIPES( \ + inst, \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, gnss_pipe, 3), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_0, 4), \ + MODEM_CELLULAR_INIT_USER_PIPE(inst, user_pipe_1, 5), \ + ); \ + \ + static const struct modem_cellular_config MODEM_CELLULAR_INST_NAME(config, inst) = { \ .uart = DEVICE_DT_GET(DT_INST_BUS(inst)), \ .power_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_power_gpios, {}), \ .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(inst, mdm_reset_gpios, {}), \ @@ -2362,6 +2603,8 @@ MODEM_CHAT_SCRIPT_DEFINE(sqn_gm02s_periodic_chat_script, .init_chat_script = &sqn_gm02s_init_chat_script, \ .dial_chat_script = &sqn_gm02s_dial_chat_script, \ .periodic_chat_script = &sqn_gm02s_periodic_chat_script, \ + .user_pipes = MODEM_CELLULAR_GET_USER_PIPES(inst), \ + .user_pipes_size = ARRAY_SIZE(MODEM_CELLULAR_GET_USER_PIPES(inst)), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, modem_cellular_pm_action); \ @@ -2379,10 +2622,6 @@ DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_QUECTEL_BG95) DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_QUECTEL_EG25_G) #undef DT_DRV_COMPAT -#define DT_DRV_COMPAT zephyr_gsm_ppp -DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_GSM_PPP) -#undef DT_DRV_COMPAT - #define DT_DRV_COMPAT simcom_sim7080 DT_INST_FOREACH_STATUS_OKAY(MODEM_CELLULAR_DEVICE_SIMCOM_SIM7080) #undef DT_DRV_COMPAT diff --git a/drivers/modem/modem_iface_uart_interrupt.c b/drivers/modem/modem_iface_uart_interrupt.c index 985e2d5d40685..5bc06f5985884 100644 --- a/drivers/modem/modem_iface_uart_interrupt.c +++ b/drivers/modem/modem_iface_uart_interrupt.c @@ -125,18 +125,6 @@ static int modem_iface_uart_read(struct modem_iface *iface, return 0; } -static bool mux_is_active(struct modem_iface *iface) -{ - bool active = false; - -#if defined(CONFIG_UART_MUX_DEVICE_NAME) - active = strncmp(CONFIG_UART_MUX_DEVICE_NAME, iface->dev->name, - sizeof(CONFIG_UART_MUX_DEVICE_NAME) - 1) == 0; -#endif /* CONFIG_UART_MUX_DEVICE_NAME */ - - return active; -} - static int modem_iface_uart_write(struct modem_iface *iface, const uint8_t *buf, size_t size) { @@ -148,18 +136,9 @@ static int modem_iface_uart_write(struct modem_iface *iface, return 0; } - /* If we're using gsm_mux, We don't want to use poll_out because sending - * one byte at a time causes each byte to get wrapped in muxing headers. - * But we can safely call uart_fifo_fill outside of ISR context when - * muxing because uart_mux implements it in software. - */ - if (mux_is_active(iface)) { - uart_fifo_fill(iface->dev, buf, size); - } else { - do { - uart_poll_out(iface->dev, *buf++); - } while (--size); - } + do { + uart_poll_out(iface->dev, *buf++); + } while (--size); return 0; } diff --git a/drivers/modem/modem_shell.c b/drivers/modem/modem_shell.c index ba824a3289a0a..191a486d7cfcf 100644 --- a/drivers/modem/modem_shell.c +++ b/drivers/modem/modem_shell.c @@ -17,7 +17,6 @@ #include #include #include -#include #include @@ -154,36 +153,6 @@ static int cmd_modem_send(const struct shell *sh, size_t argc, return 0; } -#if defined(CONFIG_GSM_MUX) -static void uart_mux_cb(const struct device *uart, const struct device *dev, - int dlci_address, void *user_data) -{ - struct modem_shell_user_data *data = user_data; - const struct shell *sh = data->sh; - int *count = data->user_data; - const char *ch = "?"; - - if (*count == 0) { - shell_fprintf(sh, SHELL_NORMAL, - "\nReal UART\tMUX UART\tDLCI\n"); - } - - (*count)++; - - if (dlci_address == CONFIG_GSM_MUX_DLCI_AT) { - ch = "AT"; - } else if (dlci_address == CONFIG_GSM_MUX_DLCI_PPP) { - ch = "PPP"; - } else if (dlci_address == 0) { - ch = "control"; - } - - shell_fprintf(sh, SHELL_NORMAL, - "%s\t\t%s\t\t%d (%s)\n", - uart->name, dev->name, dlci_address, ch); -} -#endif - static int cmd_modem_info(const struct shell *sh, size_t argc, char *argv[]) { struct ms_context *mdm_ctx; @@ -227,20 +196,7 @@ static int cmd_modem_info(const struct shell *sh, size_t argc, char *argv[]) mdm_ctx->data_imei, mdm_ctx->data_rssi ? *mdm_ctx->data_rssi : 0); - shell_fprintf(sh, SHELL_NORMAL, - "GSM 07.10 muxing : %s\n", - IS_ENABLED(CONFIG_GSM_MUX) ? "enabled" : "disabled"); - -#if defined(CONFIG_GSM_MUX) - struct modem_shell_user_data user_data; - int count = 0; - - user_data.sh = sh; - user_data.user_data = &count; - - uart_mux_foreach(uart_mux_cb, &user_data); -#endif - + shell_fprintf(sh, SHELL_NORMAL, "GSM 07.10 muxing : disabled\n"); return 0; } diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1ca8bb909fdb9..fc316d0f0296b 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -15,14 +15,12 @@ menuconfig NET_PPP depends on NET_NATIVE select RING_BUFFER select CRC - select UART_MUX if GSM_MUX if NET_PPP config NET_PPP_ASYNC_UART bool "Asynchronous UART API is used" depends on UART_ASYNC_API - depends on !GSM_MUX config NET_PPP_DRV_NAME string "PPP Driver name" diff --git a/drivers/net/nsos.h b/drivers/net/nsos.h index 1ba4584a4a6c7..f1e2f12eb553f 100644 --- a/drivers/net/nsos.h +++ b/drivers/net/nsos.h @@ -126,6 +126,10 @@ int nsos_adapt_sendto(int fd, const void *buf, size_t len, int flags, int nsos_adapt_sendmsg(int fd, const struct nsos_mid_msghdr *msg_mid, int flags); int nsos_adapt_recvfrom(int fd, void *buf, size_t len, int flags, struct nsos_mid_sockaddr *addr, size_t *addrlen); +int nsos_adapt_getsockopt(int fd, int level, int optname, + void *optval, size_t *optlen); +int nsos_adapt_setsockopt(int fd, int level, int optname, + const void *optval, size_t optlen); void nsos_adapt_poll_add(struct nsos_mid_pollfd *pollfd); void nsos_adapt_poll_remove(struct nsos_mid_pollfd *pollfd); @@ -134,6 +138,10 @@ void nsos_adapt_poll_update(struct nsos_mid_pollfd *pollfd); int nsos_adapt_fcntl_getfl(int fd); int nsos_adapt_fcntl_setfl(int fd, int flags); +int nsos_adapt_fionread(int fd, int *avail); + +int nsos_adapt_dup(int oldfd); + int nsos_adapt_getaddrinfo(const char *node, const char *service, const struct nsos_mid_addrinfo *hints, struct nsos_mid_addrinfo **res, diff --git a/drivers/net/nsos_adapt.c b/drivers/net/nsos_adapt.c index 86aaa743681db..91be0b4cf5b48 100644 --- a/drivers/net/nsos_adapt.c +++ b/drivers/net/nsos_adapt.c @@ -10,14 +10,18 @@ * Linux (bottom) side of NSOS (Native Simulator Offloaded Sockets). */ +#define _DEFAULT_SOURCE + #include #include #include #include +#include #include #include #include #include +#include #include #include @@ -25,6 +29,7 @@ #include "nsos_errno.h" #include "nsos_fcntl.h" #include "nsos_netdb.h" +#include "nsos_socket.h" #include "board_soc.h" #include "irq_ctrl.h" @@ -511,6 +516,245 @@ int nsos_adapt_recvfrom(int fd, void *buf, size_t len, int flags, return ret; } +static int nsos_adapt_getsockopt_int(int fd, int level, int optname, + void *optval, size_t *nsos_mid_optlen) +{ + socklen_t optlen = *nsos_mid_optlen; + int ret; + + ret = getsockopt(fd, level, optname, optval, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + *nsos_mid_optlen = optlen; + + return 0; +} + +int nsos_adapt_getsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, + void *nsos_mid_optval, size_t *nsos_mid_optlen) +{ + switch (nsos_mid_level) { + case NSOS_MID_SOL_SOCKET: + switch (nsos_mid_optname) { + case NSOS_MID_SO_ERROR: { + int err; + socklen_t optlen = sizeof(err); + int ret; + + ret = getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + *(int *)nsos_mid_optval = errno_to_nsos_mid(err); + + return 0; + } + case NSOS_MID_SO_TYPE: { + int type; + socklen_t optlen = sizeof(type); + int ret; + int err; + + ret = getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + err = socket_type_to_nsos_mid(type, nsos_mid_optval); + if (err) { + return err; + } + + return 0; + } + case NSOS_MID_SO_PROTOCOL: { + int proto; + socklen_t optlen = sizeof(proto); + int ret; + int err; + + ret = getsockopt(fd, SOL_SOCKET, SO_PROTOCOL, &proto, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + err = socket_proto_to_nsos_mid(proto, nsos_mid_optval); + if (err) { + return err; + } + + return 0; + } + case NSOS_MID_SO_DOMAIN: { + int family; + socklen_t optlen = sizeof(family); + int ret; + int err; + + ret = getsockopt(fd, SOL_SOCKET, SO_DOMAIN, &family, &optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + err = socket_family_to_nsos_mid(family, nsos_mid_optval); + if (err) { + return err; + } + + return 0; + } + case NSOS_MID_SO_RCVBUF: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_SNDBUF: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_REUSEADDR: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_REUSEPORT: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_REUSEPORT, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_LINGER: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_LINGER, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_KEEPALIVE: + return nsos_adapt_getsockopt_int(fd, SOL_SOCKET, SO_KEEPALIVE, + nsos_mid_optval, nsos_mid_optlen); + } + + case NSOS_MID_IPPROTO_TCP: + switch (nsos_mid_optname) { + case NSOS_MID_TCP_NODELAY: + return nsos_adapt_getsockopt_int(fd, IPPROTO_TCP, TCP_NODELAY, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPIDLE: + return nsos_adapt_getsockopt_int(fd, IPPROTO_TCP, TCP_KEEPIDLE, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPINTVL: + return nsos_adapt_getsockopt_int(fd, IPPROTO_TCP, TCP_KEEPINTVL, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPCNT: + return nsos_adapt_getsockopt_int(fd, IPPROTO_TCP, TCP_KEEPCNT, + nsos_mid_optval, nsos_mid_optlen); + } + + case NSOS_MID_IPPROTO_IPV6: + switch (nsos_mid_optname) { + case NSOS_MID_IPV6_V6ONLY: + return nsos_adapt_getsockopt_int(fd, IPPROTO_IPV6, IPV6_V6ONLY, + nsos_mid_optval, nsos_mid_optlen); + } + } + + return -NSOS_MID_EOPNOTSUPP; +} + +static int nsos_adapt_setsockopt_int(int fd, int level, int optname, + const void *optval, size_t optlen) +{ + int ret; + + ret = setsockopt(fd, level, optname, optval, optlen); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + return 0; +} + +int nsos_adapt_setsockopt(int fd, int nsos_mid_level, int nsos_mid_optname, + const void *nsos_mid_optval, size_t nsos_mid_optlen) +{ + switch (nsos_mid_level) { + case NSOS_MID_SOL_SOCKET: + switch (nsos_mid_optname) { + case NSOS_MID_SO_PRIORITY: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_PRIORITY, + nsos_mid_optval, nsos_mid_optlen); + + case NSOS_MID_SO_RCVTIMEO: { + const struct nsos_mid_timeval *nsos_mid_tv = nsos_mid_optval; + struct timeval tv = { + .tv_sec = nsos_mid_tv->tv_sec, + .tv_usec = nsos_mid_tv->tv_usec, + }; + int ret; + + ret = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, + &tv, sizeof(tv)); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + return 0; + } + case NSOS_MID_SO_SNDTIMEO: { + const struct nsos_mid_timeval *nsos_mid_tv = nsos_mid_optval; + struct timeval tv = { + .tv_sec = nsos_mid_tv->tv_sec, + .tv_usec = nsos_mid_tv->tv_usec, + }; + int ret; + + ret = setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, + &tv, sizeof(tv)); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + return 0; + } + case NSOS_MID_SO_RCVBUF: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_RCVBUF, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_SNDBUF: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_SNDBUF, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_REUSEADDR: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_REUSEADDR, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_REUSEPORT: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_REUSEPORT, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_LINGER: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_LINGER, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_SO_KEEPALIVE: + return nsos_adapt_setsockopt_int(fd, SOL_SOCKET, SO_KEEPALIVE, + nsos_mid_optval, nsos_mid_optlen); + } + + case NSOS_MID_IPPROTO_TCP: + switch (nsos_mid_optname) { + case NSOS_MID_TCP_NODELAY: + return nsos_adapt_setsockopt_int(fd, IPPROTO_TCP, TCP_NODELAY, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPIDLE: + return nsos_adapt_setsockopt_int(fd, IPPROTO_TCP, TCP_KEEPIDLE, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPINTVL: + return nsos_adapt_setsockopt_int(fd, IPPROTO_TCP, TCP_KEEPINTVL, + nsos_mid_optval, nsos_mid_optlen); + case NSOS_MID_TCP_KEEPCNT: + return nsos_adapt_setsockopt_int(fd, IPPROTO_TCP, TCP_KEEPCNT, + nsos_mid_optval, nsos_mid_optlen); + } + + case NSOS_MID_IPPROTO_IPV6: + switch (nsos_mid_optname) { + case NSOS_MID_IPV6_V6ONLY: + return nsos_adapt_setsockopt_int(fd, IPPROTO_IPV6, IPV6_V6ONLY, + nsos_mid_optval, nsos_mid_optlen); + } + } + + return -NSOS_MID_EOPNOTSUPP; +} + #define MAP_POLL_EPOLL(_event_from, _event_to) \ if (events_from & (_event_from)) { \ events_from &= ~(_event_from); \ @@ -524,6 +768,7 @@ static int nsos_poll_to_epoll_events(int events_from) MAP_POLL_EPOLL(POLLIN, EPOLLIN); MAP_POLL_EPOLL(POLLOUT, EPOLLOUT); MAP_POLL_EPOLL(POLLERR, EPOLLERR); + MAP_POLL_EPOLL(POLLHUP, EPOLLHUP); return events_to; } @@ -535,6 +780,7 @@ static int nsos_epoll_to_poll_events(int events_from) MAP_POLL_EPOLL(EPOLLIN, POLLIN); MAP_POLL_EPOLL(EPOLLOUT, POLLOUT); MAP_POLL_EPOLL(EPOLLERR, POLLERR); + MAP_POLL_EPOLL(EPOLLHUP, POLLHUP); return events_to; } @@ -759,6 +1005,30 @@ int nsos_adapt_fcntl_setfl(int fd, int flags) return 0; } +int nsos_adapt_fionread(int fd, int *avail) +{ + int ret; + + ret = ioctl(fd, FIONREAD, avail); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + return 0; +} + +int nsos_adapt_dup(int oldfd) +{ + int ret; + + ret = dup(oldfd); + if (ret < 0) { + return -errno_to_nsos_mid(errno); + } + + return ret; +} + static void nsos_adapt_init(void) { nsos_epoll_fd = epoll_create(1); diff --git a/drivers/net/nsos_fcntl.c b/drivers/net/nsos_fcntl.c index be49d3ec63e57..ab4d22ce51a24 100644 --- a/drivers/net/nsos_fcntl.c +++ b/drivers/net/nsos_fcntl.c @@ -16,7 +16,14 @@ * symbols. */ +/* + * When building for Zephyr, use Zephyr specific fcntl definitions. + */ +#ifdef __ZEPHYR__ +#include +#else #include +#endif #include "nsos_errno.h" #include "nsos_fcntl.h" diff --git a/drivers/net/nsos_socket.h b/drivers/net/nsos_socket.h new file mode 100644 index 0000000000000..66f54130d175d --- /dev/null +++ b/drivers/net/nsos_socket.h @@ -0,0 +1,134 @@ +/** + * Copyright (c) 2024 Marcin Niestroj + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DRIVERS_NET_NSOS_SOCKET_H__ +#define __DRIVERS_NET_NSOS_SOCKET_H__ + +#include + +/** + * @name Socket level options (NSOS_MID_SOL_SOCKET) + * @{ + */ +/** Socket-level option */ +#define NSOS_MID_SOL_SOCKET 1 + +/* Socket options for NSOS_MID_SOL_SOCKET level */ + +/** Recording debugging information (ignored, for compatibility) */ +#define NSOS_MID_SO_DEBUG 1 +/** address reuse */ +#define NSOS_MID_SO_REUSEADDR 2 +/** Type of the socket */ +#define NSOS_MID_SO_TYPE 3 +/** Async error */ +#define NSOS_MID_SO_ERROR 4 +/** Bypass normal routing and send directly to host (ignored, for compatibility) */ +#define NSOS_MID_SO_DONTROUTE 5 +/** Transmission of broadcast messages is supported (ignored, for compatibility) */ +#define NSOS_MID_SO_BROADCAST 6 + +/** Size of socket send buffer */ +#define NSOS_MID_SO_SNDBUF 7 +/** Size of socket recv buffer */ +#define NSOS_MID_SO_RCVBUF 8 + +/** Enable sending keep-alive messages on connections */ +#define NSOS_MID_SO_KEEPALIVE 9 +/** Place out-of-band data into receive stream (ignored, for compatibility) */ +#define NSOS_MID_SO_OOBINLINE 10 +/** Socket priority */ +#define NSOS_MID_SO_PRIORITY 12 +/** Socket lingers on close (ignored, for compatibility) */ +#define NSOS_MID_SO_LINGER 13 +/** Allow multiple sockets to reuse a single port */ +#define NSOS_MID_SO_REUSEPORT 15 + +/** Receive low watermark (ignored, for compatibility) */ +#define NSOS_MID_SO_RCVLOWAT 18 +/** Send low watermark (ignored, for compatibility) */ +#define NSOS_MID_SO_SNDLOWAT 19 + +/** + * Receive timeout + * Applies to receive functions like recv(), but not to connect() + */ +#define NSOS_MID_SO_RCVTIMEO 20 +/** Send timeout */ +#define NSOS_MID_SO_SNDTIMEO 21 + +/** Bind a socket to an interface */ +#define NSOS_MID_SO_BINDTODEVICE 25 + +/** Socket accepts incoming connections (ignored, for compatibility) */ +#define NSOS_MID_SO_ACCEPTCONN 30 + +/** Timestamp TX packets */ +#define NSOS_MID_SO_TIMESTAMPING 37 +/** Protocol used with the socket */ +#define NSOS_MID_SO_PROTOCOL 38 + +/** Domain used with SOCKET */ +#define NSOS_MID_SO_DOMAIN 39 + +/** Enable SOCKS5 for Socket */ +#define NSOS_MID_SO_SOCKS5 60 + +/** Socket TX time (when the data should be sent) */ +#define NSOS_MID_SO_TXTIME 61 + +struct nsos_mid_timeval { + int64_t tv_sec; + int64_t tv_usec; +}; + +/** @} */ + +/** + * @name TCP level options (NSOS_MID_IPPROTO_TCP) + * @{ + */ +/* Socket options for NSOS_MID_IPPROTO_TCP level */ +/** Disable TCP buffering (ignored, for compatibility) */ +#define NSOS_MID_TCP_NODELAY 1 +/** Start keepalives after this period (seconds) */ +#define NSOS_MID_TCP_KEEPIDLE 2 +/** Interval between keepalives (seconds) */ +#define NSOS_MID_TCP_KEEPINTVL 3 +/** Number of keepalives before dropping connection */ +#define NSOS_MID_TCP_KEEPCNT 4 + +/** @} */ + +/** + * @name IPv6 level options (NSOS_MID_IPPROTO_IPV6) + * @{ + */ +/* Socket options for NSOS_MID_IPPROTO_IPV6 level */ +/** Set the unicast hop limit for the socket. */ +#define NSOS_MID_IPV6_UNICAST_HOPS 16 + +/** Set the multicast hop limit for the socket. */ +#define NSOS_MID_IPV6_MULTICAST_HOPS 18 + +/** Join IPv6 multicast group. */ +#define NSOS_MID_IPV6_ADD_MEMBERSHIP 20 + +/** Leave IPv6 multicast group. */ +#define NSOS_MID_IPV6_DROP_MEMBERSHIP 21 + +/** Don't support IPv4 access */ +#define NSOS_MID_IPV6_V6ONLY 26 + +/** Pass an IPV6_RECVPKTINFO ancillary message that contains a + * in6_pktinfo structure that supplies some information about the + * incoming packet. See RFC 3542. + */ +#define NSOS_MID_IPV6_RECVPKTINFO 49 + +/** @} */ + +#endif /* __DRIVERS_NET_NSOS_SOCKET_H__ */ diff --git a/drivers/net/nsos_sockets.c b/drivers/net/nsos_sockets.c index c177342599549..1e6c03abca8c9 100644 --- a/drivers/net/nsos_sockets.c +++ b/drivers/net/nsos_sockets.c @@ -13,6 +13,9 @@ #undef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L +#include +LOG_MODULE_REGISTER(nsos_sockets); + #include #include #include @@ -28,6 +31,7 @@ #include "nsos_errno.h" #include "nsos_fcntl.h" #include "nsos_netdb.h" +#include "nsos_socket.h" #include "nsi_host_trampolines.h" @@ -36,15 +40,25 @@ BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE > 0); #define NSOS_IRQ_FLAGS (0) #define NSOS_IRQ_PRIORITY (2) +struct nsos_socket; + +struct nsos_socket_poll { + struct nsos_mid_pollfd mid; + struct k_poll_signal signal; + + sys_dnode_t node; +}; + struct nsos_socket { int fd; - struct nsos_mid_pollfd pollfd; - struct k_poll_signal poll; - sys_dnode_t node; + k_timeout_t recv_timeout; + k_timeout_t send_timeout; + + struct nsos_socket_poll poll; }; -static sys_dlist_t nsos_sockets = SYS_DLIST_STATIC_INIT(&nsos_sockets); +static sys_dlist_t nsos_polls = SYS_DLIST_STATIC_INIT(&nsos_polls); static int socket_family_to_nsos_mid(int family, int *family_mid) { @@ -179,10 +193,12 @@ static int nsos_socket_create(int family, int type, int proto) } sock->fd = fd; + sock->recv_timeout = K_FOREVER; + sock->send_timeout = K_FOREVER; - sock->pollfd.fd = nsos_adapt_socket(family_mid, type_mid, proto_mid); - if (sock->pollfd.fd < 0) { - errno = errno_from_nsos_mid(-sock->pollfd.fd); + sock->poll.mid.fd = nsos_adapt_socket(family_mid, type_mid, proto_mid); + if (sock->poll.mid.fd < 0) { + errno = errno_from_nsos_mid(-sock->poll.mid.fd); goto free_sock; } @@ -209,7 +225,7 @@ static ssize_t nsos_read(void *obj, void *buf, size_t sz) struct nsos_socket *sock = obj; int ret; - ret = nsi_host_read(sock->pollfd.fd, buf, sz); + ret = nsi_host_read(sock->poll.mid.fd, buf, sz); if (ret < 0) { errno = nsos_adapt_get_zephyr_errno(); } @@ -222,7 +238,7 @@ static ssize_t nsos_write(void *obj, const void *buf, size_t sz) struct nsos_socket *sock = obj; int ret; - ret = nsi_host_write(sock->pollfd.fd, buf, sz); + ret = nsi_host_write(sock->poll.mid.fd, buf, sz); if (ret < 0) { errno = nsos_adapt_get_zephyr_errno(); } @@ -235,7 +251,7 @@ static int nsos_close(void *obj) struct nsos_socket *sock = obj; int ret; - ret = nsi_host_close(sock->pollfd.fd); + ret = nsi_host_close(sock->poll.mid.fd); if (ret < 0) { errno = nsos_adapt_get_zephyr_errno(); } @@ -243,34 +259,34 @@ static int nsos_close(void *obj) return ret; } -static void pollcb(struct nsos_mid_pollfd *pollfd) +static void pollcb(struct nsos_mid_pollfd *mid) { - struct nsos_socket *sock = CONTAINER_OF(pollfd, struct nsos_socket, pollfd); + struct nsos_socket_poll *poll = CONTAINER_OF(mid, struct nsos_socket_poll, mid); - k_poll_signal_raise(&sock->poll, sock->pollfd.revents); + k_poll_signal_raise(&poll->signal, poll->mid.revents); } static int nsos_poll_prepare(struct nsos_socket *sock, struct zsock_pollfd *pfd, - struct k_poll_event **pev, struct k_poll_event *pev_end) + struct k_poll_event **pev, struct k_poll_event *pev_end, + struct nsos_socket_poll *poll) { unsigned int signaled; int flags; - sock->pollfd.events = pfd->events; - sock->pollfd.revents = 0; - sock->pollfd.cb = pollcb; + poll->mid.events = pfd->events; + poll->mid.revents = 0; + poll->mid.cb = pollcb; if (*pev == pev_end) { - errno = ENOMEM; - return -1; + return -ENOMEM; } - k_poll_signal_init(&sock->poll); - k_poll_event_init(*pev, K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &sock->poll); + k_poll_signal_init(&poll->signal); + k_poll_event_init(*pev, K_POLL_TYPE_SIGNAL, K_POLL_MODE_NOTIFY_ONLY, &poll->signal); - sys_dlist_append(&nsos_sockets, &sock->node); + sys_dlist_append(&nsos_polls, &poll->node); - nsos_adapt_poll_add(&sock->pollfd); + nsos_adapt_poll_add(&poll->mid); /* Let other sockets use another k_poll_event */ (*pev)++; @@ -278,7 +294,7 @@ static int nsos_poll_prepare(struct nsos_socket *sock, struct zsock_pollfd *pfd, signaled = 0; flags = 0; - k_poll_signal_check(&sock->poll, &signaled, &flags); + k_poll_signal_check(&poll->signal, &signaled, &flags); if (!signaled) { return 0; } @@ -288,7 +304,7 @@ static int nsos_poll_prepare(struct nsos_socket *sock, struct zsock_pollfd *pfd, } static int nsos_poll_update(struct nsos_socket *sock, struct zsock_pollfd *pfd, - struct k_poll_event **pev) + struct k_poll_event **pev, struct nsos_socket_poll *poll) { unsigned int signaled; int flags; @@ -298,15 +314,15 @@ static int nsos_poll_update(struct nsos_socket *sock, struct zsock_pollfd *pfd, signaled = 0; flags = 0; - if (!sys_dnode_is_linked(&sock->node)) { - nsos_adapt_poll_update(&sock->pollfd); + if (!sys_dnode_is_linked(&poll->node)) { + nsos_adapt_poll_update(&poll->mid); return 0; } - nsos_adapt_poll_remove(&sock->pollfd); - sys_dlist_remove(&sock->node); + nsos_adapt_poll_remove(&poll->mid); + sys_dlist_remove(&poll->node); - k_poll_signal_check(&sock->poll, &signaled, &flags); + k_poll_signal_check(&poll->signal, &signaled, &flags); if (!signaled) { return 0; } @@ -330,7 +346,7 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) pev = va_arg(args, struct k_poll_event **); pev_end = va_arg(args, struct k_poll_event *); - return nsos_poll_prepare(obj, pfd, pev, pev_end); + return nsos_poll_prepare(obj, pfd, pev, pev_end, &sock->poll); } case ZFD_IOCTL_POLL_UPDATE: { @@ -340,7 +356,7 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) pfd = va_arg(args, struct zsock_pollfd *); pev = va_arg(args, struct k_poll_event **); - return nsos_poll_update(obj, pfd, pev); + return nsos_poll_update(obj, pfd, pev, &sock->poll); } case ZFD_IOCTL_POLL_OFFLOAD: @@ -349,7 +365,7 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) case F_GETFL: { int flags; - flags = nsos_adapt_fcntl_getfl(sock->pollfd.fd); + flags = nsos_adapt_fcntl_getfl(sock->poll.mid.fd); return fl_from_nsos_mid(flags); } @@ -363,7 +379,16 @@ static int nsos_ioctl(void *obj, unsigned int request, va_list args) return -errno_from_nsos_mid(-ret); } - ret = nsos_adapt_fcntl_setfl(sock->pollfd.fd, flags); + ret = nsos_adapt_fcntl_setfl(sock->poll.mid.fd, flags); + + return -errno_from_nsos_mid(-ret); + } + + case ZFD_IOCTL_FIONREAD: { + int *avail = va_arg(args, int *); + int ret; + + ret = nsos_adapt_fionread(sock->poll.mid.fd, avail); return -errno_from_nsos_mid(-ret); } @@ -469,31 +494,77 @@ static int sockaddr_from_nsos_mid(struct sockaddr *addr, socklen_t *addrlen, return -NSOS_MID_EINVAL; } -static int nsos_bind(void *obj, const struct sockaddr *addr, socklen_t addrlen) +static int nsos_wait_for_poll(struct nsos_socket *sock, int events, + k_timeout_t timeout) { - struct nsos_socket *sock = obj; - struct nsos_mid_sockaddr_storage addr_storage_mid; - struct nsos_mid_sockaddr *addr_mid = (struct nsos_mid_sockaddr *)&addr_storage_mid; - size_t addrlen_mid; + struct zsock_pollfd pfd = { + .fd = sock->fd, + .events = events, + }; + struct k_poll_event poll_events[1]; + struct k_poll_event *pev = poll_events; + struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events); + struct nsos_socket_poll socket_poll = {}; int ret; - ret = sockaddr_to_nsos_mid(addr, addrlen, &addr_mid, &addrlen_mid); + ret = nsos_adapt_dup(sock->poll.mid.fd); if (ret < 0) { goto return_ret; } - ret = nsos_adapt_bind(sock->pollfd.fd, addr_mid, addrlen_mid); + socket_poll.mid.fd = ret; + + ret = nsos_poll_prepare(sock, &pfd, &pev, pev_end, &socket_poll); + if (ret == -EALREADY) { + ret = 0; + goto poll_update; + } else if (ret < 0) { + goto close_dup; + } + + ret = k_poll(poll_events, ARRAY_SIZE(poll_events), timeout); + if (ret != 0 && ret != -EAGAIN && ret != -EINTR) { + goto poll_update; + } + + ret = 0; + +poll_update: + pev = poll_events; + nsos_poll_update(sock, &pfd, &pev, &socket_poll); + +close_dup: + nsi_host_close(socket_poll.mid.fd); return_ret: if (ret < 0) { - errno = errno_from_nsos_mid(-ret); - return -1; + return -errno_to_nsos_mid(-ret); } - return ret; + return 0; } -static int nsos_connect(void *obj, const struct sockaddr *addr, socklen_t addrlen) +static int nsos_poll_if_blocking(struct nsos_socket *sock, int events, + k_timeout_t timeout, int flags) +{ + int sock_flags; + bool non_blocking; + + if (flags & ZSOCK_MSG_DONTWAIT) { + non_blocking = true; + } else { + sock_flags = nsos_adapt_fcntl_getfl(sock->poll.mid.fd); + non_blocking = sock_flags & NSOS_MID_O_NONBLOCK; + } + + if (!non_blocking) { + return nsos_wait_for_poll(sock, events, timeout); + } + + return 0; +} + +static int nsos_bind(void *obj, const struct sockaddr *addr, socklen_t addrlen) { struct nsos_socket *sock = obj; struct nsos_mid_sockaddr_storage addr_storage_mid; @@ -506,7 +577,7 @@ static int nsos_connect(void *obj, const struct sockaddr *addr, socklen_t addrle goto return_ret; } - ret = nsos_adapt_connect(sock->pollfd.fd, addr_mid, addrlen_mid); + ret = nsos_adapt_bind(sock->poll.mid.fd, addr_mid, addrlen_mid); return_ret: if (ret < 0) { @@ -517,68 +588,87 @@ static int nsos_connect(void *obj, const struct sockaddr *addr, socklen_t addrle return ret; } -static int nsos_listen(void *obj, int backlog) +static int nsos_connect_blocking(struct nsos_socket *sock, + struct nsos_mid_sockaddr *addr_mid, + size_t addrlen_mid, + int fcntl_flags) { - struct nsos_socket *sock = obj; + int clear_nonblock_ret; int ret; - ret = nsos_adapt_listen(sock->pollfd.fd, backlog); + ret = nsos_adapt_fcntl_setfl(sock->poll.mid.fd, fcntl_flags | NSOS_MID_O_NONBLOCK); if (ret < 0) { - errno = errno_from_nsos_mid(-ret); - return -1; + return ret; + } + + ret = nsos_adapt_connect(sock->poll.mid.fd, addr_mid, addrlen_mid); + if (ret == -NSOS_MID_EINPROGRESS) { + int so_err; + size_t so_err_len = sizeof(so_err); + + ret = nsos_wait_for_poll(sock, ZSOCK_POLLOUT, sock->send_timeout); + if (ret < 0) { + goto clear_nonblock; + } + + ret = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_ERROR, &so_err, &so_err_len); + if (ret < 0) { + goto clear_nonblock; + } + + ret = so_err; + } + +clear_nonblock: + clear_nonblock_ret = nsos_adapt_fcntl_setfl(sock->poll.mid.fd, fcntl_flags); + if (clear_nonblock_ret < 0) { + LOG_ERR("Failed to clear O_NONBLOCK: %d", clear_nonblock_ret); } return ret; } -static int nsos_wait_for_pollin(struct nsos_socket *sock) +static int nsos_connect(void *obj, const struct sockaddr *addr, socklen_t addrlen) { - struct zsock_pollfd pfd = { - .fd = sock->fd, - .events = ZSOCK_POLLIN, - }; - struct k_poll_event poll_events[1]; - struct k_poll_event *pev = poll_events; - struct k_poll_event *pev_end = poll_events + ARRAY_SIZE(poll_events); + struct nsos_socket *sock = obj; + struct nsos_mid_sockaddr_storage addr_storage_mid; + struct nsos_mid_sockaddr *addr_mid = (struct nsos_mid_sockaddr *)&addr_storage_mid; + size_t addrlen_mid; + int flags; int ret; - ret = nsos_poll_prepare(sock, &pfd, &pev, pev_end); - if (ret == -EALREADY) { - return 0; - } else if (ret < 0) { - return ret; + ret = sockaddr_to_nsos_mid(addr, addrlen, &addr_mid, &addrlen_mid); + if (ret < 0) { + goto return_ret; } - ret = k_poll(poll_events, ARRAY_SIZE(poll_events), K_FOREVER); - if (ret != 0 && ret != -EAGAIN && ret != -EINTR) { - return ret; + flags = nsos_adapt_fcntl_getfl(sock->poll.mid.fd); + + if (flags & NSOS_MID_O_NONBLOCK) { + ret = nsos_adapt_connect(sock->poll.mid.fd, addr_mid, addrlen_mid); + } else { + ret = nsos_connect_blocking(sock, addr_mid, addrlen_mid, flags); } - pev = poll_events; - nsos_poll_update(sock, &pfd, &pev); +return_ret: + if (ret < 0) { + errno = errno_from_nsos_mid(-ret); + return -1; + } - return 0; + return ret; } -static int nsos_accept_with_poll(struct nsos_socket *sock, - struct nsos_mid_sockaddr *addr_mid, - size_t *addrlen_mid) +static int nsos_listen(void *obj, int backlog) { - int ret = 0; - int flags; - - flags = nsos_adapt_fcntl_getfl(sock->pollfd.fd); - - if (!(flags & NSOS_MID_O_NONBLOCK)) { - ret = nsos_wait_for_pollin(sock); - if (ret < 0) { - return ret; - } - } + struct nsos_socket *sock = obj; + int ret; - ret = nsos_adapt_accept(sock->pollfd.fd, addr_mid, addrlen_mid); + ret = nsos_adapt_listen(sock->poll.mid.fd, backlog); if (ret < 0) { - return -errno_from_nsos_mid(-ret); + errno = errno_from_nsos_mid(-ret); + return -1; } return ret; @@ -595,33 +685,38 @@ static int nsos_accept(void *obj, struct sockaddr *addr, socklen_t *addrlen) struct nsos_socket *conn_sock; int ret; - ret = nsos_accept_with_poll(accept_sock, addr_mid, &addrlen_mid); + ret = nsos_poll_if_blocking(accept_sock, ZSOCK_POLLIN, + accept_sock->recv_timeout, 0); if (ret < 0) { - errno = errno_from_nsos_mid(-ret); - return -1; + goto return_ret; + } + + ret = nsos_adapt_accept(accept_sock->poll.mid.fd, addr_mid, &addrlen_mid); + if (ret < 0) { + goto return_ret; } adapt_fd = ret; ret = sockaddr_from_nsos_mid(addr, addrlen, addr_mid, addrlen_mid); if (ret < 0) { - errno = errno_from_nsos_mid(-ret); goto close_adapt_fd; } zephyr_fd = z_reserve_fd(); if (zephyr_fd < 0) { + ret = -errno_to_nsos_mid(-zephyr_fd); goto close_adapt_fd; } conn_sock = k_malloc(sizeof(*conn_sock)); if (!conn_sock) { - errno = ENOMEM; + ret = -NSOS_MID_ENOMEM; goto free_zephyr_fd; } conn_sock->fd = zephyr_fd; - conn_sock->pollfd.fd = adapt_fd; + conn_sock->poll.mid.fd = adapt_fd; z_finalize_fd(zephyr_fd, conn_sock, &nsos_socket_fd_op_vtable.fd_vtable); @@ -633,6 +728,8 @@ static int nsos_accept(void *obj, struct sockaddr *addr, socklen_t *addrlen) close_adapt_fd: nsi_host_close(adapt_fd); +return_ret: + errno = errno_from_nsos_mid(-ret); return -1; } @@ -658,7 +755,12 @@ static ssize_t nsos_sendto(void *obj, const void *buf, size_t len, int flags, goto return_ret; } - ret = nsos_adapt_sendto(sock->pollfd.fd, buf, len, flags_mid, + ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, sock->send_timeout, flags); + if (ret < 0) { + goto return_ret; + } + + ret = nsos_adapt_sendto(sock->poll.mid.fd, buf, len, flags_mid, addr_mid, addrlen_mid); return_ret: @@ -695,7 +797,7 @@ static ssize_t nsos_sendmsg(void *obj, const struct msghdr *msg, int flags) msg_iov = k_calloc(msg->msg_iovlen, sizeof(*msg_iov)); if (!msg_iov) { - ret = -ENOMEM; + ret = -NSOS_MID_ENOMEM; goto return_ret; } @@ -712,8 +814,14 @@ static ssize_t nsos_sendmsg(void *obj, const struct msghdr *msg, int flags) msg_mid.msg_controllen = 0; msg_mid.msg_flags = 0; - ret = nsos_adapt_sendmsg(sock->pollfd.fd, &msg_mid, flags_mid); + ret = nsos_poll_if_blocking(sock, ZSOCK_POLLOUT, sock->send_timeout, flags); + if (ret < 0) { + goto free_msg_iov; + } + + ret = nsos_adapt_sendmsg(sock->poll.mid.fd, &msg_mid, flags_mid); +free_msg_iov: k_free(msg_iov); return_ret: @@ -725,36 +833,6 @@ static ssize_t nsos_sendmsg(void *obj, const struct msghdr *msg, int flags) return ret; } -static int nsos_recvfrom_with_poll(struct nsos_socket *sock, void *buf, size_t len, int flags, - struct nsos_mid_sockaddr *addr_mid, size_t *addrlen_mid) -{ - int ret = 0; - int sock_flags; - bool non_blocking; - - if (flags & ZSOCK_MSG_DONTWAIT) { - non_blocking = true; - } else { - sock_flags = nsos_adapt_fcntl_getfl(sock->pollfd.fd); - non_blocking = sock_flags & NSOS_MID_O_NONBLOCK; - } - - if (!non_blocking) { - ret = nsos_wait_for_pollin(sock); - if (ret < 0) { - return ret; - } - } - - ret = nsos_adapt_recvfrom(sock->pollfd.fd, buf, len, flags, - addr_mid, addrlen_mid); - if (ret < 0) { - return -errno_from_nsos_mid(-ret); - } - - return ret; -} - static ssize_t nsos_recvfrom(void *obj, void *buf, size_t len, int flags, struct sockaddr *addr, socklen_t *addrlen) { @@ -772,8 +850,13 @@ static ssize_t nsos_recvfrom(void *obj, void *buf, size_t len, int flags, flags_mid = ret; - ret = nsos_recvfrom_with_poll(sock, buf, len, flags_mid, - addr_mid, &addrlen_mid); + ret = nsos_poll_if_blocking(sock, ZSOCK_POLLIN, sock->recv_timeout, flags); + if (ret < 0) { + goto return_ret; + } + + ret = nsos_adapt_recvfrom(sock->poll.mid.fd, buf, len, flags_mid, + addr_mid, &addrlen_mid); if (ret < 0) { goto return_ret; } @@ -795,6 +878,422 @@ static ssize_t nsos_recvmsg(void *obj, struct msghdr *msg, int flags) return -1; } +static int socket_type_from_nsos_mid(int type_mid, int *type) +{ + switch (type_mid) { + case NSOS_MID_SOCK_STREAM: + *type = SOCK_STREAM; + break; + case NSOS_MID_SOCK_DGRAM: + *type = SOCK_DGRAM; + break; + case NSOS_MID_SOCK_RAW: + *type = SOCK_RAW; + break; + default: + return -NSOS_MID_ESOCKTNOSUPPORT; + } + + return 0; +} + +static int socket_proto_from_nsos_mid(int proto_mid, int *proto) +{ + switch (proto_mid) { + case NSOS_MID_IPPROTO_IP: + *proto = IPPROTO_IP; + break; + case NSOS_MID_IPPROTO_ICMP: + *proto = IPPROTO_ICMP; + break; + case NSOS_MID_IPPROTO_IGMP: + *proto = IPPROTO_IGMP; + break; + case NSOS_MID_IPPROTO_IPIP: + *proto = IPPROTO_IPIP; + break; + case NSOS_MID_IPPROTO_TCP: + *proto = IPPROTO_TCP; + break; + case NSOS_MID_IPPROTO_UDP: + *proto = IPPROTO_UDP; + break; + case NSOS_MID_IPPROTO_IPV6: + *proto = IPPROTO_IPV6; + break; + case NSOS_MID_IPPROTO_RAW: + *proto = IPPROTO_RAW; + break; + default: + return -NSOS_MID_EPROTONOSUPPORT; + } + + return 0; +} + +static int socket_family_from_nsos_mid(int family_mid, int *family) +{ + switch (family_mid) { + case NSOS_MID_AF_UNSPEC: + *family = AF_UNSPEC; + break; + case NSOS_MID_AF_INET: + *family = AF_INET; + break; + case NSOS_MID_AF_INET6: + *family = AF_INET6; + break; + default: + return -NSOS_MID_EAFNOSUPPORT; + } + + return 0; +} + +static int nsos_getsockopt_int(struct nsos_socket *sock, int nsos_mid_level, int nsos_mid_optname, + void *optval, socklen_t *optlen) +{ + size_t nsos_mid_optlen = sizeof(int); + int err; + + if (*optlen != sizeof(int)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_KEEPALIVE, optval, &nsos_mid_optlen); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + *optlen = nsos_mid_optlen; + + return 0; +} + +static int nsos_getsockopt(void *obj, int level, int optname, + void *optval, socklen_t *optlen) +{ + struct nsos_socket *sock = obj; + + switch (level) { + case SOL_SOCKET: + switch (optname) { + case SO_ERROR: { + int nsos_mid_err; + int err; + + if (*optlen != sizeof(int)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_ERROR, &nsos_mid_err, NULL); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + *(int *)optval = errno_from_nsos_mid(nsos_mid_err); + + return 0; + } + case SO_TYPE: { + int nsos_mid_type; + int err; + + if (*optlen != sizeof(nsos_mid_type)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_TYPE, &nsos_mid_type, NULL); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + err = socket_type_from_nsos_mid(nsos_mid_type, optval); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; + } + case SO_PROTOCOL: { + int nsos_mid_proto; + int err; + + if (*optlen != sizeof(nsos_mid_proto)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_PROTOCOL, &nsos_mid_proto, NULL); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + err = socket_proto_from_nsos_mid(nsos_mid_proto, optval); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; + } + case SO_DOMAIN: { + int nsos_mid_family; + int err; + + if (*optlen != sizeof(nsos_mid_family)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_getsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_DOMAIN, &nsos_mid_family, NULL); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + err = socket_family_from_nsos_mid(nsos_mid_family, optval); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; + } + case SO_RCVBUF: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_RCVBUF, + optval, optlen); + case SO_SNDBUF: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_SNDBUF, + optval, optlen); + case SO_REUSEADDR: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEADDR, + optval, optlen); + case SO_REUSEPORT: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEPORT, + optval, optlen); + case SO_KEEPALIVE: + return nsos_getsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_KEEPALIVE, + optval, optlen); + } + + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_NODELAY, + optval, optlen); + case TCP_KEEPIDLE: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPIDLE, + optval, optlen); + case TCP_KEEPINTVL: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPINTVL, + optval, optlen); + case TCP_KEEPCNT: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPCNT, + optval, optlen); + } + + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + return nsos_getsockopt_int(sock, + NSOS_MID_IPPROTO_IPV6, NSOS_MID_IPV6_V6ONLY, + optval, optlen); + } + } + + errno = EOPNOTSUPP; + return -1; +} + +static int nsos_setsockopt_int(struct nsos_socket *sock, int nsos_mid_level, int nsos_mid_optname, + const void *optval, socklen_t optlen) +{ + int err; + + if (optlen != sizeof(int)) { + errno = EINVAL; + return -1; + } + + err = nsos_adapt_setsockopt(sock->poll.mid.fd, nsos_mid_level, nsos_mid_optname, + optval, optlen); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; +} + +static int nsos_setsockopt(void *obj, int level, int optname, + const void *optval, socklen_t optlen) +{ + struct nsos_socket *sock = obj; + + switch (level) { + case SOL_SOCKET: + switch (optname) { + case SO_PRIORITY: { + int nsos_mid_priority; + int err; + + if (optlen != sizeof(uint8_t)) { + errno = EINVAL; + return -1; + } + + nsos_mid_priority = *(uint8_t *)optval; + + err = nsos_adapt_setsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_PRIORITY, &nsos_mid_priority, + sizeof(nsos_mid_priority)); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + return 0; + } + case SO_RCVTIMEO: { + const struct zsock_timeval *tv = optval; + struct nsos_mid_timeval nsos_mid_tv; + int err; + + if (optlen != sizeof(struct zsock_timeval)) { + errno = EINVAL; + return -1; + } + + nsos_mid_tv.tv_sec = tv->tv_sec; + nsos_mid_tv.tv_usec = tv->tv_usec; + + err = nsos_adapt_setsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_RCVTIMEO, &nsos_mid_tv, + sizeof(nsos_mid_tv)); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + if (tv->tv_sec == 0 && tv->tv_usec == 0) { + sock->recv_timeout = K_FOREVER; + } else { + sock->recv_timeout = K_USEC(tv->tv_sec * 1000000LL + tv->tv_usec); + } + + return 0; + } + case SO_SNDTIMEO: { + const struct zsock_timeval *tv = optval; + struct nsos_mid_timeval nsos_mid_tv; + int err; + + if (optlen != sizeof(struct zsock_timeval)) { + errno = EINVAL; + return -1; + } + + nsos_mid_tv.tv_sec = tv->tv_sec; + nsos_mid_tv.tv_usec = tv->tv_usec; + + err = nsos_adapt_setsockopt(sock->poll.mid.fd, NSOS_MID_SOL_SOCKET, + NSOS_MID_SO_SNDTIMEO, &nsos_mid_tv, + sizeof(nsos_mid_tv)); + if (err) { + errno = errno_from_nsos_mid(-err); + return -1; + } + + if (tv->tv_sec == 0 && tv->tv_usec == 0) { + sock->send_timeout = K_FOREVER; + } else { + sock->send_timeout = K_USEC(tv->tv_sec * 1000000LL + tv->tv_usec); + } + + return 0; + } + case SO_RCVBUF: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_RCVBUF, + optval, optlen); + case SO_SNDBUF: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_SNDBUF, + optval, optlen); + case SO_REUSEADDR: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEADDR, + optval, optlen); + case SO_REUSEPORT: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_REUSEPORT, + optval, optlen); + case SO_LINGER: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_LINGER, + optval, optlen); + case SO_KEEPALIVE: + return nsos_setsockopt_int(sock, + NSOS_MID_SOL_SOCKET, NSOS_MID_SO_KEEPALIVE, + optval, optlen); + } + + case IPPROTO_TCP: + switch (optname) { + case TCP_NODELAY: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_NODELAY, + optval, optlen); + case TCP_KEEPIDLE: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPIDLE, + optval, optlen); + case TCP_KEEPINTVL: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPINTVL, + optval, optlen); + case TCP_KEEPCNT: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_TCP, NSOS_MID_TCP_KEEPCNT, + optval, optlen); + } + + case IPPROTO_IPV6: + switch (optname) { + case IPV6_V6ONLY: + return nsos_setsockopt_int(sock, + NSOS_MID_IPPROTO_IPV6, NSOS_MID_IPV6_V6ONLY, + optval, optlen); + } + } + + errno = EOPNOTSUPP; + return -1; +} + static const struct socket_op_vtable nsos_socket_fd_op_vtable = { .fd_vtable = { .read = nsos_read, @@ -810,6 +1309,8 @@ static const struct socket_op_vtable nsos_socket_fd_op_vtable = { .sendmsg = nsos_sendmsg, .recvfrom = nsos_recvfrom, .recvmsg = nsos_recvmsg, + .getsockopt = nsos_getsockopt, + .setsockopt = nsos_setsockopt, }; static bool nsos_is_supported(int family, int type, int proto) @@ -970,11 +1471,11 @@ static const struct socket_dns_offload nsos_dns_ops = { static void nsos_isr(const void *obj) { - struct nsos_socket *sock; + struct nsos_socket_poll *poll; - SYS_DLIST_FOR_EACH_CONTAINER(&nsos_sockets, sock, node) { - if (sock->pollfd.revents) { - sock->pollfd.cb(&sock->pollfd); + SYS_DLIST_FOR_EACH_CONTAINER(&nsos_polls, poll, node) { + if (poll->mid.revents) { + poll->mid.cb(&poll->mid); } } } diff --git a/drivers/net/ppp.c b/drivers/net/ppp.c index 7904612b9a4e7..24a046e8d1942 100644 --- a/drivers/net/ppp.c +++ b/drivers/net/ppp.c @@ -30,7 +30,6 @@ LOG_MODULE_REGISTER(net_ppp, LOG_LEVEL); #include #include #include -#include #include #include #include @@ -326,7 +325,7 @@ static int ppp_save_byte(struct ppp_driver_context *ppp, uint8_t byte) */ if (ppp->available == 1) { ret = net_pkt_alloc_buffer(ppp->pkt, - CONFIG_NET_BUF_DATA_SIZE, + CONFIG_NET_BUF_DATA_SIZE + ppp->available, AF_UNSPEC, K_NO_WAIT); if (ret < 0) { LOG_ERR("[%p] cannot allocate new data buffer", ppp); @@ -421,33 +420,24 @@ static int ppp_send_flush(struct ppp_driver_context *ppp, int off) NET_ETH_PTYPE_HDLC); } - /* If we're using gsm_mux, We don't want to use poll_out because sending - * one byte at a time causes each byte to get wrapped in muxing headers. - * But we can safely call uart_fifo_fill outside of ISR context when - * muxing because uart_mux implements it in software. - */ - if (IS_ENABLED(CONFIG_GSM_MUX)) { - (void)uart_fifo_fill(ppp->dev, buf, off); - } else if (IS_ENABLED(CONFIG_NET_PPP_ASYNC_UART)) { #if defined(CONFIG_NET_PPP_ASYNC_UART) - int ret; - const int32_t timeout = CONFIG_NET_PPP_ASYNC_UART_TX_TIMEOUT - ? CONFIG_NET_PPP_ASYNC_UART_TX_TIMEOUT * USEC_PER_MSEC - : SYS_FOREVER_US; + int ret; + const int32_t timeout = CONFIG_NET_PPP_ASYNC_UART_TX_TIMEOUT + ? CONFIG_NET_PPP_ASYNC_UART_TX_TIMEOUT * USEC_PER_MSEC + : SYS_FOREVER_US; - k_sem_take(&uarte_tx_finished, K_FOREVER); + k_sem_take(&uarte_tx_finished, K_FOREVER); - ret = uart_tx(ppp->dev, buf, off, timeout); - if (ret) { - LOG_ERR("uart_tx() failed, err %d", ret); - k_sem_give(&uarte_tx_finished); - } -#endif - } else { - while (off--) { - uart_poll_out(ppp->dev, *buf++); - } + ret = uart_tx(ppp->dev, buf, off, timeout); + if (ret) { + LOG_ERR("uart_tx() failed, err %d", ret); + k_sem_give(&uarte_tx_finished); + } +#else + while (off--) { + uart_poll_out(ppp->dev, *buf++); } +#endif return 0; } @@ -1052,14 +1042,13 @@ static void ppp_iface_init(struct net_if *iface) memset(ppp->buf, 0, sizeof(ppp->buf)); - /* If we have a GSM modem with PPP support or interface autostart is disabled - * from Kconfig, then do not start the interface automatically but only - * after the modem is ready or when manually started. +#if defined(CONFIG_PPP_NET_IF_NO_AUTO_START) + /* + * If interface autostart is disabled from Kconfig, then do not start the + * interface automatically but only when manually started. */ - if (IS_ENABLED(CONFIG_MODEM_GSM_PPP) || - IS_ENABLED(CONFIG_PPP_NET_IF_NO_AUTO_START)) { - net_if_flag_set(iface, NET_IF_NO_AUTO_START); - } + net_if_flag_set(iface, NET_IF_NO_AUTO_START); +#endif } #if defined(CONFIG_NET_STATISTICS_PPP) @@ -1110,34 +1099,11 @@ static int ppp_start(const struct device *dev) { struct ppp_driver_context *context = dev->data; - /* Init the PPP UART only once. This should only be done after - * the GSM muxing is setup and enabled. GSM modem will call this - * after everything is ready to be connected. - */ + /* Init the PPP UART. This should only be called once. */ #if !defined(CONFIG_NET_TEST) if (atomic_cas(&context->modem_init_done, false, true)) { - /* Now try to figure out what device to open. If GSM muxing - * is enabled, then use it. If not, then check if modem - * configuration is enabled, and use that. If none are enabled, - * then use our own config. - */ -#if defined(CONFIG_GSM_MUX) - const struct device *mux; - - mux = uart_mux_find(CONFIG_GSM_MUX_DLCI_PPP); - if (mux == NULL) { - LOG_ERR("Cannot find GSM mux dev for DLCI %d", - CONFIG_GSM_MUX_DLCI_PPP); - return -ENOENT; - } - - context->dev = mux; -#elif IS_ENABLED(CONFIG_MODEM_GSM_PPP) - context->dev = DEVICE_DT_GET(DT_BUS(DT_INST(0, zephyr_gsm_ppp))); -#else - /* dts chosen zephyr,ppp-uart case */ context->dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_ppp_uart)); -#endif + LOG_DBG("Initializing PPP to use %s", context->dev->name); if (!device_is_ready(context->dev)) { diff --git a/drivers/pcie/host/msi.c b/drivers/pcie/host/msi.c index f78f5b171a61a..7718175159aac 100644 --- a/drivers/pcie/host/msi.c +++ b/drivers/pcie/host/msi.c @@ -96,9 +96,9 @@ static bool map_msix_table_entries(pcie_bdf_t bdf, return false; } - z_phys_map((uint8_t **)&mapped_table, - bar.phys_addr + table_offset, - n_vector * PCIE_MSIR_TABLE_ENTRY_SIZE, K_MEM_PERM_RW); + k_mem_map_phys_bare((uint8_t **)&mapped_table, + bar.phys_addr + table_offset, + n_vector * PCIE_MSIR_TABLE_ENTRY_SIZE, K_MEM_PERM_RW); for (i = 0; i < n_vector; i++) { vectors[i].msix_vector = (struct msix_vector *) diff --git a/drivers/pcie/host/pcie.c b/drivers/pcie/host/pcie.c index 0a98d8e8e069a..c2261af5de4e7 100644 --- a/drivers/pcie/host/pcie.c +++ b/drivers/pcie/host/pcie.c @@ -37,23 +37,6 @@ static bool prt_en; /* functions documented in drivers/pcie/pcie.h */ -bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id) -{ - uint32_t data; - - data = pcie_conf_read(bdf, PCIE_CONF_ID); - - if (!PCIE_ID_IS_VALID(data)) { - return false; - } - - if (id == PCIE_ID_NONE) { - return true; - } - - return (id == data); -} - void pcie_set_cmd(pcie_bdf_t bdf, uint32_t bits, bool on) { uint32_t cmdstat; @@ -179,8 +162,8 @@ static bool pcie_get_bar(pcie_bdf_t bdf, reg++; phys_addr |= ((uint64_t)pcie_conf_read(bdf, reg)) << 32; - if (PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_INVAL64 || - PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_NONE) { + if ((PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_INVAL64) || + (PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_NONE)) { /* Discard on invalid address */ goto err_exit; } @@ -188,8 +171,8 @@ static bool pcie_get_bar(pcie_bdf_t bdf, pcie_conf_write(bdf, reg, 0xFFFFFFFFU); size |= ((uint64_t)pcie_conf_read(bdf, reg)) << 32; pcie_conf_write(bdf, reg, (uint32_t)((uint64_t)phys_addr >> 32)); - } else if (PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_INVAL || - PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_NONE) { + } else if ((PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_INVAL) || + (PCIE_CONF_BAR_ADDR(phys_addr) == PCIE_CONF_BAR_NONE)) { /* Discard on invalid address */ goto err_exit; } @@ -253,7 +236,7 @@ static bool pcie_probe_bar(pcie_bdf_t bdf, uint32_t reg; for (reg = PCIE_CONF_BAR0; - index > 0 && reg <= PCIE_CONF_BAR5; reg++, index--) { + (index > 0) && (reg <= PCIE_CONF_BAR5); reg++, index--) { uintptr_t addr = pcie_conf_read(bdf, reg); if (PCIE_CONF_BAR_MEM(addr) && PCIE_CONF_BAR_64(addr)) { @@ -306,8 +289,8 @@ unsigned int pcie_alloc_irq(pcie_bdf_t bdf) data = pcie_conf_read(bdf, PCIE_CONF_INTR); irq = PCIE_CONF_INTR_IRQ(data); - if (irq == PCIE_CONF_INTR_IRQ_NONE || - irq >= CONFIG_MAX_IRQ_LINES || + if ((irq == PCIE_CONF_INTR_IRQ_NONE) || + (irq >= CONFIG_MAX_IRQ_LINES) || arch_irq_is_used(irq)) { /* In some platforms, PCI interrupts are hardwired to specific interrupt inputs @@ -385,40 +368,6 @@ void pcie_irq_enable(pcie_bdf_t bdf, unsigned int irq) irq_enable(irq); } -struct lookup_data { - pcie_bdf_t bdf; - pcie_id_t id; -}; - -static bool lookup_cb(pcie_bdf_t bdf, pcie_id_t id, void *cb_data) -{ - struct lookup_data *data = cb_data; - - if (id == data->id) { - data->bdf = bdf; - return false; - } - - return true; -} - -pcie_bdf_t pcie_bdf_lookup(pcie_id_t id) -{ - struct lookup_data data = { - .bdf = PCIE_BDF_NONE, - .id = id, - }; - struct pcie_scan_opt opt = { - .cb = lookup_cb, - .cb_data = &data, - .flags = (PCIE_SCAN_RECURSIVE | PCIE_SCAN_CB_ALL), - }; - - pcie_scan(&opt); - - return data.bdf; -} - static bool scan_flag(const struct pcie_scan_opt *opt, uint32_t flag) { return ((opt->flags & flag) != 0U); diff --git a/drivers/peci/peci_handlers.c b/drivers/peci/peci_handlers.c index 64947a8743d9f..c0f532a24cc09 100644 --- a/drivers/peci/peci_handlers.c +++ b/drivers/peci/peci_handlers.c @@ -15,7 +15,7 @@ static inline int z_vrfy_peci_config(const struct device *dev, return z_impl_peci_config(dev, bitrate); } -#include +#include static inline int z_vrfy_peci_enable(const struct device *dev) { @@ -23,7 +23,7 @@ static inline int z_vrfy_peci_enable(const struct device *dev) return z_impl_peci_enable(dev); } -#include +#include static inline int z_vrfy_peci_disable(const struct device *dev) { @@ -31,7 +31,7 @@ static inline int z_vrfy_peci_disable(const struct device *dev) return z_impl_peci_disable(dev); } -#include +#include static inline int z_vrfy_peci_transfer(const struct device *dev, struct peci_msg *msg) @@ -43,4 +43,4 @@ static inline int z_vrfy_peci_transfer(const struct device *dev, return z_impl_peci_transfer(dev, &msg_copy); } -#include +#include diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index 91bbb8b3d5161..1dce91d597786 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -37,5 +37,6 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_QUICKLOGIC_EOS_S3 pinctrl_eos_s3.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_MCI_IO_MUX pinctrl_mci_io_mux.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_ENE_KB1200 pinctrl_ene_kb1200.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_IMX_SCU pinctrl_imx_scu.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_MAX32 pinctrl_max32.c) add_subdirectory(renesas) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index ab6ea86bcc9a8..b919fa0f169b0 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -65,6 +65,7 @@ source "drivers/pinctrl/Kconfig.eos_s3" source "drivers/pinctrl/Kconfig.mci_io_mux" source "drivers/pinctrl/Kconfig.ene" source "drivers/pinctrl/Kconfig.zynqmp" +source "drivers/pinctrl/Kconfig.max32" rsource "renesas/Kconfig" diff --git a/drivers/pinctrl/Kconfig.max32 b/drivers/pinctrl/Kconfig.max32 new file mode 100644 index 0000000000000..13d5ef77a1c06 --- /dev/null +++ b/drivers/pinctrl/Kconfig.max32 @@ -0,0 +1,9 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config PINCTRL_MAX32 + bool "Analog Devices MAX32 MCUs pin controller driver" + default y + depends on DT_HAS_ADI_MAX32_PINCTRL_ENABLED + help + Pin controller driver support for max32 SoC series diff --git a/drivers/pinctrl/pinctrl_esp32.c b/drivers/pinctrl/pinctrl_esp32.c index ee3811604511e..581cc2b2dc6ca 100644 --- a/drivers/pinctrl/pinctrl_esp32.c +++ b/drivers/pinctrl/pinctrl_esp32.c @@ -18,6 +18,12 @@ #define in in.data #define out_w1ts out_w1ts.val #define out_w1tc out_w1tc.val +#elif CONFIG_SOC_SERIES_ESP32C6 +/* gpio structs in esp32c6 are also different */ +#define out out.out_data_orig +#define in in.in_data_next +#define out_w1ts out_w1ts.val +#define out_w1tc out_w1tc.val #endif #ifndef SOC_GPIO_SUPPORT_RTC_INDEPENDENT @@ -242,12 +248,12 @@ static int esp32_pin_configure(const uint32_t pin_mux, const uint32_t pin_cfg) if (ESP32_PORT_IDX(pin_num) == 0) { gpio_dev_t *const gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0)); - gpio_dev->out_w1ts = pin_num; + gpio_dev->out_w1ts = BIT(pin_num); #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay) } else { gpio_dev_t *const gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio1)); - gpio_dev->out1_w1ts.data = pin_num; + gpio_dev->out1_w1ts.data = BIT(pin_num - 32); #endif } } @@ -256,12 +262,12 @@ static int esp32_pin_configure(const uint32_t pin_mux, const uint32_t pin_cfg) if (ESP32_PORT_IDX(pin_num) == 0) { gpio_dev_t *const gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio0)); - gpio_dev->out_w1tc = pin_num; + gpio_dev->out_w1tc = BIT(pin_num); #if DT_NODE_HAS_STATUS(DT_NODELABEL(gpio1), okay) } else { gpio_dev_t *const gpio_dev = (gpio_dev_t *)DT_REG_ADDR(DT_NODELABEL(gpio1)); - gpio_dev->out1_w1tc.data = pin_num; + gpio_dev->out1_w1tc.data = BIT(pin_num - 32); #endif } } diff --git a/drivers/pinctrl/pinctrl_ifx_cat1.c b/drivers/pinctrl/pinctrl_ifx_cat1.c index dbeaab855f300..d1806346a8fa2 100644 --- a/drivers/pinctrl/pinctrl_ifx_cat1.c +++ b/drivers/pinctrl/pinctrl_ifx_cat1.c @@ -10,7 +10,6 @@ */ #include -#include #include #define GPIO_PORT_OR_NULL(node_id) \ diff --git a/drivers/pinctrl/pinctrl_ite_it8xxx2.c b/drivers/pinctrl/pinctrl_ite_it8xxx2.c index 33ed9130b62e2..f7d71adc43e5f 100644 --- a/drivers/pinctrl/pinctrl_ite_it8xxx2.c +++ b/drivers/pinctrl/pinctrl_ite_it8xxx2.c @@ -20,6 +20,8 @@ LOG_MODULE_REGISTER(pinctrl_ite_it8xxx2, LOG_LEVEL_ERR); struct pinctrl_it8xxx2_gpio { /* gpio port control register (byte mapping to pin) */ uint8_t *reg_gpcr; + /* port driving select control */ + uint8_t *reg_pdsc; /* function 3 general control register */ uintptr_t func3_gcr[GPIO_GROUP_MEMBERS]; /* function 3 enable mask */ @@ -74,6 +76,7 @@ static int pinctrl_it8xxx2_set(const pinctrl_soc_pin_t *pins) uint8_t pin = pins->pin; volatile uint8_t *reg_gpcr = (uint8_t *)gpio->reg_gpcr + pin; volatile uint8_t *reg_volt_sel = (uint8_t *)(gpio->volt_sel[pin]); + volatile uint8_t *reg_pdsc = (uint8_t *)gpio->reg_pdsc; /* Setting pull-up or pull-down. */ switch (IT8XXX2_DT_PINCFG_PUPDR(pincfg)) { @@ -125,6 +128,18 @@ static int pinctrl_it8xxx2_set(const pinctrl_soc_pin_t *pins) GPCR_PORT_PIN_MODE_PULLDOWN); } + /* Driving current selection. */ + if (reg_pdsc != NULL && + IT8XXX2_DT_PINCFG_DRIVE_CURRENT(pincfg) != IT8XXX2_DRIVE_DEFAULT) { + if (IT8XXX2_DT_PINCFG_DRIVE_CURRENT(pincfg) & IT8XXX2_PDSCX_MASK) { + /* Driving current selects low. */ + *reg_pdsc |= BIT(pin); + } else { + /* Driving current selects high. */ + *reg_pdsc &= ~BIT(pin); + } + } + return 0; } @@ -366,6 +381,7 @@ static int pinctrl_it8xxx2_init(const struct device *dev) COND_CODE_1(DT_INST_PROP(inst, gpio_group), \ (.gpio = { \ .reg_gpcr = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 0), \ + .reg_pdsc = (uint8_t *)DT_INST_REG_ADDR_BY_IDX(inst, 1), \ .func3_gcr = DT_INST_PROP(inst, func3_gcr), \ .func3_en_mask = DT_INST_PROP(inst, func3_en_mask), \ .func3_ext = DT_INST_PROP_OR(inst, func3_ext, {0}), \ diff --git a/drivers/pinctrl/pinctrl_max32.c b/drivers/pinctrl/pinctrl_max32.c new file mode 100644 index 0000000000000..e9fcf65aa8591 --- /dev/null +++ b/drivers/pinctrl/pinctrl_max32.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +#define ADI_MAX32_GET_PORT_ADDR_OR_NONE(nodelabel) \ + IF_ENABLED(DT_NODE_EXISTS(DT_NODELABEL(nodelabel)), \ + (DT_REG_ADDR(DT_NODELABEL(nodelabel)),)) + +/** GPIO port addresses */ +static const uint32_t gpios[] = { + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio0) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio1) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio2) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio3) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio4) + ADI_MAX32_GET_PORT_ADDR_OR_NONE(gpio5) +}; + +static int pinctrl_configure_pin(pinctrl_soc_pin_t soc_pin) +{ + uint32_t port; + uint32_t pin; + uint32_t afx; + int pincfg; + mxc_gpio_cfg_t gpio_cfg; + + port = MAX32_PINMUX_PORT(soc_pin.pinmux); + pin = MAX32_PINMUX_PIN(soc_pin.pinmux); + afx = MAX32_PINMUX_MODE(soc_pin.pinmux); + pincfg = soc_pin.pincfg; + + if (gpios[port] == 0) { + return -EINVAL; + } + + gpio_cfg.port = (mxc_gpio_regs_t *)gpios[port]; + gpio_cfg.mask = BIT(pin); + + if (pincfg & BIT(MAX32_BIAS_PULL_UP_SHIFT)) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_UP; + } else if (pincfg & BIT(MAX32_BIAS_PULL_DOWN_SHIFT)) { + gpio_cfg.pad = MXC_GPIO_PAD_PULL_DOWN; + } else { + gpio_cfg.pad = MXC_GPIO_PAD_NONE; + } + + if (pincfg & BIT(MAX32_INPUT_ENABLE_SHIFT)) { + gpio_cfg.func = MXC_GPIO_FUNC_IN; + } else if (pincfg & BIT(MAX32_OUTPUT_ENABLE_SHIFT)) { + gpio_cfg.func = MXC_GPIO_FUNC_OUT; + } else { + /* Add +1 to index match */ + gpio_cfg.func = (mxc_gpio_func_t)(afx + 1); + } + + if (pincfg & BIT(MAX32_POWER_SOURCE_SHIFT)) { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIOH; + } else { + gpio_cfg.vssel = MXC_GPIO_VSSEL_VDDIO; + } + + switch (pincfg & MAX32_GPIO_DRV_STRENGTH_MASK) { + case MAX32_GPIO_DRV_STRENGTH_1: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_1; + break; + case MAX32_GPIO_DRV_STRENGTH_2: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_2; + break; + case MAX32_GPIO_DRV_STRENGTH_3: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_3; + break; + default: + gpio_cfg.drvstr = MXC_GPIO_DRVSTR_0; + break; + } + + if (MXC_GPIO_Config(&gpio_cfg) != 0) { + return -ENOTSUP; + } + + if (pincfg & BIT(MAX32_OUTPUT_ENABLE_SHIFT)) { + if (pincfg & BIT(MAX32_OUTPUT_HIGH_SHIFT)) { + MXC_GPIO_OutSet(gpio_cfg.port, BIT(pin)); + } else { + MXC_GPIO_OutClr(gpio_cfg.port, BIT(pin)); + } + } + + return 0; +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, uintptr_t reg) +{ + ARG_UNUSED(reg); + + int ret; + + for (uint8_t i = 0U; i < pin_cnt; i++) { + ret = pinctrl_configure_pin(*pins++); + if (ret) { + return ret; + } + } + + return 0; +} diff --git a/drivers/pinctrl/pinctrl_nrf.c b/drivers/pinctrl/pinctrl_nrf.c index 0bf09e5e460ed..17193c160cad1 100644 --- a/drivers/pinctrl/pinctrl_nrf.c +++ b/drivers/pinctrl/pinctrl_nrf.c @@ -162,7 +162,10 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, dir = NRF_GPIO_PIN_DIR_OUTPUT; input = NRF_GPIO_PIN_INPUT_DISCONNECT; #if NRF_GPIO_HAS_CLOCKPIN && defined(NRF_SPIM_CLOCKPIN_MOSI_NEEDED) - clockpin = true; + /* CLOCKPIN setting must not be applied to SPIM12x instances. */ + if (!NRF_SPIM_IS_320MHZ_SPIM((void *)reg)) { + clockpin = true; + } #endif break; case NRF_FUN_SPIM_MISO: @@ -360,6 +363,17 @@ int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, input = NRF_GPIO_PIN_INPUT_DISCONNECT; break; #endif /* defined(NRF_PSEL_QSPI) */ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_can) + /* Pin routing is controlled by secure domain, via UICR */ + case NRF_FUN_CAN_TX: + dir = NRF_GPIO_PIN_DIR_OUTPUT; + input = NRF_GPIO_PIN_INPUT_DISCONNECT; + break; + case NRF_FUN_CAN_RX: + dir = NRF_GPIO_PIN_DIR_INPUT; + input = NRF_GPIO_PIN_INPUT_CONNECT; + break; +#endif /* DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_can) */ default: return -ENOTSUP; } diff --git a/drivers/pinctrl/pinctrl_numaker.c b/drivers/pinctrl/pinctrl_numaker.c index a443f705edf45..e29f214a1833a 100644 --- a/drivers/pinctrl/pinctrl_numaker.c +++ b/drivers/pinctrl/pinctrl_numaker.c @@ -16,7 +16,9 @@ #define GPIO_SIZE DT_REG_SIZE(DT_NODELABEL(gpioa)) #define SLEWCTL_PIN_SHIFT(pin_idx) ((pin_idx) * 2) -#define SLEWCTL_MASK(pin_idx) (3 << SLEWCTL_PIN_SHIFT(pin_idx)) +#define SLEWCTL_MASK(pin_idx) (3 << SLEWCTL_PIN_SHIFT(pin_idx)) +#define DINOFF_PIN_SHIFT(pin_idx) (pin_idx + GPIO_DINOFF_DINOFF0_Pos) +#define DINOFF_MASK(pin_idx) (1 << DINOFF_PIN_SHIFT(pin_idx)) static void gpio_configure(const pinctrl_soc_pin_t *pin, uint8_t port_idx, uint8_t pin_idx) { @@ -28,7 +30,8 @@ static void gpio_configure(const pinctrl_soc_pin_t *pin, uint8_t port_idx, uint8 ((pin->schmitt_enable ? 1 : 0) << pin_idx); port->SLEWCTL = (port->SLEWCTL & ~SLEWCTL_MASK(pin_idx)) | (pin->slew_rate << SLEWCTL_PIN_SHIFT(pin_idx)); - + port->DINOFF = (port->DINOFF & ~DINOFF_MASK(pin_idx)) | + ((pin->digital_disable ? 1 : 0) << DINOFF_PIN_SHIFT(pin_idx)); } /** * Configure pin multi-function diff --git a/drivers/pinctrl/pinctrl_stm32.c b/drivers/pinctrl/pinctrl_stm32.c index b6a1b550e8bfb..9dc3e26f37cca 100644 --- a/drivers/pinctrl/pinctrl_stm32.c +++ b/drivers/pinctrl/pinctrl_stm32.c @@ -58,6 +58,11 @@ static const struct device *const gpio_ports[] = { DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioi)), DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioj)), DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiok)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiol)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiom)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpion)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpioo)), + DEVICE_DT_GET_OR_NULL(DT_NODELABEL(gpiop)), }; /** Number of GPIO ports. */ diff --git a/drivers/power_domain/power_domain_intel_adsp.c b/drivers/power_domain/power_domain_intel_adsp.c index 3f816c6914657..50b4582507ac0 100644 --- a/drivers/power_domain/power_domain_intel_adsp.c +++ b/drivers/power_domain/power_domain_intel_adsp.c @@ -8,6 +8,7 @@ #include #include #include +#include #if CONFIG_SOC_INTEL_ACE15_MTPM #include @@ -27,10 +28,10 @@ static int pd_intel_adsp_set_power_enable(struct pg_bits *bits, bool power_enabl uint16_t SPA_bit_mask = BIT(bits->SPA_bit); if (power_enable) { - sys_write16(sys_read16((mem_addr_t)&ACE_DfPMCCU.dfpwrctl) | SPA_bit_mask, - (mem_addr_t)&ACE_DfPMCCU.dfpwrctl); + sys_write16(sys_read16((mem_addr_t)ACE_PWRCTL) | SPA_bit_mask, + (mem_addr_t)ACE_PWRCTL); - if (!WAIT_FOR(sys_read16((mem_addr_t)&ACE_DfPMCCU.dfpwrsts) & BIT(bits->CPA_bit), + if (!WAIT_FOR(sys_read16((mem_addr_t)ACE_PWRSTS) & BIT(bits->CPA_bit), 10000, k_busy_wait(1))) { return -EIO; } @@ -46,8 +47,8 @@ static int pd_intel_adsp_set_power_enable(struct pg_bits *bits, bool power_enabl return -EINVAL; } #endif - sys_write16(sys_read16((mem_addr_t)&ACE_DfPMCCU.dfpwrctl) & ~(SPA_bit_mask), - (mem_addr_t)&ACE_DfPMCCU.dfpwrctl); + sys_write16(sys_read16((mem_addr_t)ACE_PWRCTL) & ~(SPA_bit_mask), + (mem_addr_t)ACE_PWRCTL); } return 0; diff --git a/drivers/ps2/ps2_handlers.c b/drivers/ps2/ps2_handlers.c index 91835e85ea555..db93d93b8bbfb 100644 --- a/drivers/ps2/ps2_handlers.c +++ b/drivers/ps2/ps2_handlers.c @@ -15,14 +15,14 @@ static inline int z_vrfy_ps2_config(const struct device *dev, "callback not be set from user mode")); return z_impl_ps2_config(dev, callback_isr); } -#include +#include static inline int z_vrfy_ps2_write(const struct device *dev, uint8_t value) { K_OOPS(K_SYSCALL_DRIVER_PS2(dev, write)); return z_impl_ps2_write(dev, value); } -#include +#include static inline int z_vrfy_ps2_read(const struct device *dev, uint8_t *value) { @@ -30,18 +30,18 @@ static inline int z_vrfy_ps2_read(const struct device *dev, uint8_t *value) K_OOPS(K_SYSCALL_MEMORY_WRITE(value, sizeof(uint8_t))); return z_impl_ps2_read(dev, value); } -#include +#include static inline int z_vrfy_ps2_enable_callback(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_PS2(dev, enable_callback)); return z_impl_ps2_enable_callback(dev); } -#include +#include static inline int z_vrfy_ps2_disable_callback(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_PS2(dev, disable_callback)); return z_impl_ps2_disable_callback(dev); } -#include +#include diff --git a/drivers/ptp_clock/ptp_clock.c b/drivers/ptp_clock/ptp_clock.c index 0ac0e5c242f78..d0db19ca3a191 100644 --- a/drivers/ptp_clock/ptp_clock.c +++ b/drivers/ptp_clock/ptp_clock.c @@ -28,5 +28,5 @@ int z_vrfy_ptp_clock_get(const struct device *dev, return ret; } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/drivers/ptp_clock/ptp_clock_nxp_enet.c b/drivers/ptp_clock/ptp_clock_nxp_enet.c index 286c6c91d57c5..b5e1cbb9bd32c 100644 --- a/drivers/ptp_clock/ptp_clock_nxp_enet.c +++ b/drivers/ptp_clock/ptp_clock_nxp_enet.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * * Based on a commit to drivers/ethernet/eth_mcux.c which was: * Copyright (c) 2018 Intel Coporation @@ -19,8 +19,8 @@ #include struct ptp_clock_nxp_enet_config { - ENET_Type *base; const struct pinctrl_dev_config *pincfg; + const struct device *module_dev; const struct device *port; const struct device *clock_dev; struct device *clock_subsys; @@ -28,6 +28,7 @@ struct ptp_clock_nxp_enet_config { }; struct ptp_clock_nxp_enet_data { + ENET_Type *base; double clock_ratio; enet_handle_t enet_handle; struct k_mutex ptp_mutex; @@ -36,14 +37,13 @@ struct ptp_clock_nxp_enet_data { static int ptp_clock_nxp_enet_set(const struct device *dev, struct net_ptp_time *tm) { - const struct ptp_clock_nxp_enet_config *config = dev->config; struct ptp_clock_nxp_enet_data *data = dev->data; enet_ptp_time_t enet_time; enet_time.second = tm->second; enet_time.nanosecond = tm->nanosecond; - ENET_Ptp1588SetTimer(config->base, &data->enet_handle, &enet_time); + ENET_Ptp1588SetTimer(data->base, &data->enet_handle, &enet_time); return 0; } @@ -51,11 +51,10 @@ static int ptp_clock_nxp_enet_set(const struct device *dev, static int ptp_clock_nxp_enet_get(const struct device *dev, struct net_ptp_time *tm) { - const struct ptp_clock_nxp_enet_config *config = dev->config; struct ptp_clock_nxp_enet_data *data = dev->data; enet_ptp_time_t enet_time; - ENET_Ptp1588GetTimer(config->base, &data->enet_handle, &enet_time); + ENET_Ptp1588GetTimer(data->base, &data->enet_handle, &enet_time); tm->second = enet_time.second; tm->nanosecond = enet_time.nanosecond; @@ -66,7 +65,7 @@ static int ptp_clock_nxp_enet_get(const struct device *dev, static int ptp_clock_nxp_enet_adjust(const struct device *dev, int increment) { - const struct ptp_clock_nxp_enet_config *config = dev->config; + struct ptp_clock_nxp_enet_data *data = dev->data; int ret = 0; int key; @@ -75,13 +74,13 @@ static int ptp_clock_nxp_enet_adjust(const struct device *dev, ret = -EINVAL; } else { key = irq_lock(); - if (config->base->ATPER != NSEC_PER_SEC) { + if (data->base->ATPER != NSEC_PER_SEC) { ret = -EBUSY; } else { /* Seconds counter is handled by software. Change the * period of one software second to adjust the clock. */ - config->base->ATPER = NSEC_PER_SEC - increment; + data->base->ATPER = NSEC_PER_SEC - increment; ret = 0; } irq_unlock(key); @@ -144,7 +143,7 @@ static int ptp_clock_nxp_enet_rate_adjust(const struct device *dev, k_mutex_lock(&data->ptp_mutex, K_FOREVER); - ENET_Ptp1588AdjustTimer(config->base, corr, mul); + ENET_Ptp1588AdjustTimer(data->base, corr, mul); k_mutex_unlock(&data->ptp_mutex); @@ -167,17 +166,17 @@ void nxp_enet_ptp_clock_callback(const struct device *dev, (void) clock_control_get_rate(config->clock_dev, config->clock_subsys, &enet_ref_pll_rate); - ENET_AddMulticastGroup(config->base, ptp_multicast); - ENET_AddMulticastGroup(config->base, ptp_peer_multicast); + ENET_AddMulticastGroup(data->base, ptp_multicast); + ENET_AddMulticastGroup(data->base, ptp_peer_multicast); /* only for ERRATA_2579 */ ptp_config.channel = kENET_PtpTimerChannel3; ptp_config.ptp1588ClockSrc_Hz = enet_ref_pll_rate; data->clock_ratio = 1.0; - ENET_Ptp1588SetChannelMode(config->base, kENET_PtpTimerChannel3, + ENET_Ptp1588SetChannelMode(data->base, kENET_PtpTimerChannel3, kENET_PtpChannelPulseHighonCompare, true); - ENET_Ptp1588Configure(config->base, &data->enet_handle, + ENET_Ptp1588Configure(data->base, &data->enet_handle, &ptp_config); } @@ -193,6 +192,8 @@ static int ptp_clock_nxp_enet_init(const struct device *port) struct ptp_clock_nxp_enet_data *data = port->data; int ret; + data->base = (ENET_Type *)DEVICE_MMIO_GET(config->module_dev); + ret = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); if (ret) { return ret; @@ -207,7 +208,6 @@ static int ptp_clock_nxp_enet_init(const struct device *port) static void ptp_clock_nxp_enet_isr(const struct device *dev) { - const struct ptp_clock_nxp_enet_config *config = dev->config; struct ptp_clock_nxp_enet_data *data = dev->data; enet_ptp_timer_channel_t channel; @@ -215,12 +215,12 @@ static void ptp_clock_nxp_enet_isr(const struct device *dev) /* clear channel */ for (channel = kENET_PtpTimerChannel1; channel <= kENET_PtpTimerChannel4; channel++) { - if (ENET_Ptp1588GetChannelStatus(config->base, channel)) { - ENET_Ptp1588ClearChannelStatus(config->base, channel); + if (ENET_Ptp1588GetChannelStatus(data->base, channel)) { + ENET_Ptp1588ClearChannelStatus(data->base, channel); } } - ENET_TimeStampIRQHandler(config->base, &data->enet_handle); + ENET_TimeStampIRQHandler(data->base, &data->enet_handle); irq_unlock(irq_lock_key); } @@ -247,7 +247,6 @@ static const struct ptp_clock_driver_api ptp_clock_nxp_enet_api = { \ static const struct ptp_clock_nxp_enet_config \ ptp_clock_nxp_enet_##n##_config = { \ - .base = (ENET_Type *) DT_REG_ADDR(DT_INST_PARENT(n)), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .port = DEVICE_DT_INST_GET(n), \ .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ diff --git a/drivers/pwm/CMakeLists.txt b/drivers/pwm/CMakeLists.txt index 2ac86d3e38ebc..3a6eef0123621 100644 --- a/drivers/pwm/CMakeLists.txt +++ b/drivers/pwm/CMakeLists.txt @@ -18,6 +18,7 @@ zephyr_library_sources_ifdef(CONFIG_MCPWM_ESP32 pwm_mc_esp32.c) zephyr_library_sources_ifdef(CONFIG_PWM_SAM pwm_sam.c) zephyr_library_sources_ifdef(CONFIG_PWM_MCUX pwm_mcux.c) zephyr_library_sources_ifdef(CONFIG_PWM_MCUX_SCTIMER pwm_mcux_sctimer.c) +zephyr_library_sources_ifdef(CONFIG_PWM_MCUX_QTMR pwm_mcux_qtmr.c) zephyr_library_sources_ifdef(CONFIG_PWM_XEC pwm_mchp_xec.c) zephyr_library_sources_ifdef(CONFIG_PWM_LITEX pwm_litex.c) zephyr_library_sources_ifdef(CONFIG_PWM_RV32M1_TPM pwm_rv32m1_tpm.c) @@ -39,6 +40,7 @@ zephyr_library_sources_ifdef(CONFIG_PWM_XMC4XXX_CCU4 pwm_xmc4xxx_ccu4.c) zephyr_library_sources_ifdef(CONFIG_PWM_XMC4XXX_CCU8 pwm_xmc4xxx_ccu8.c) zephyr_library_sources_ifdef(CONFIG_PWM_MCUX_CTIMER pwm_mcux_ctimer.c) zephyr_library_sources_ifdef(CONFIG_PWM_NUMAKER pwm_numaker.c) +zephyr_library_sources_ifdef(CONFIG_PWM_NXP_FLEXIO pwm_nxp_flexio.c) zephyr_library_sources_ifdef(CONFIG_PWM_NXP_S32_EMIOS pwm_nxp_s32_emios.c) zephyr_library_sources_ifdef(CONFIG_PWM_ENE_KB1200 pwm_ene_kb1200.c) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index d8a412078f9b6..002ff4dd2dbeb 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -58,6 +58,8 @@ source "drivers/pwm/Kconfig.mcux" source "drivers/pwm/Kconfig.mcux_sctimer" +source "drivers/pwm/Kconfig.mcux_qtmr" + source "drivers/pwm/Kconfig.xec" source "drivers/pwm/Kconfig.litex" @@ -100,6 +102,8 @@ source "drivers/pwm/Kconfig.numaker" source "drivers/pwm/Kconfig.nxp_s32_emios" +source "drivers/pwm/Kconfig.nxp_flexio" + source "drivers/pwm/Kconfig.ene" endif # PWM diff --git a/drivers/pwm/Kconfig.mcux_qtmr b/drivers/pwm/Kconfig.mcux_qtmr new file mode 100644 index 0000000000000..bb8329bbdaade --- /dev/null +++ b/drivers/pwm/Kconfig.mcux_qtmr @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config PWM_MCUX_QTMR + bool "MCUX QMTR PWM driver" + default y + depends on DT_HAS_NXP_QTMR_PWM_ENABLED + depends on CLOCK_CONTROL && PINCTRL + help + Enable QTMR based pwm driver. diff --git a/drivers/pwm/Kconfig.nxp_flexio b/drivers/pwm/Kconfig.nxp_flexio new file mode 100644 index 0000000000000..a1a47670a91a8 --- /dev/null +++ b/drivers/pwm/Kconfig.nxp_flexio @@ -0,0 +1,12 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config PWM_NXP_FLEXIO + bool "NXP Flexio PWM driver" + default y + depends on DT_HAS_NXP_FLEXIO_ENABLED + depends on CLOCK_CONTROL + depends on DT_HAS_NXP_FLEXIO_PWM_ENABLED + select MCUX_FLEXIO + help + Enable flexio based pwm driver. diff --git a/drivers/pwm/pwm_cc13xx_cc26xx_timer.c b/drivers/pwm/pwm_cc13xx_cc26xx_timer.c index 4855c134aa626..9edb19b647fd8 100644 --- a/drivers/pwm/pwm_cc13xx_cc26xx_timer.c +++ b/drivers/pwm/pwm_cc13xx_cc26xx_timer.c @@ -140,7 +140,7 @@ static int get_timer_inst_number(const struct pwm_cc13xx_cc26xx_config *config) case GPT3_BASE: return 3; default: - __ASSERT_UNREACHABLE; + CODE_UNREACHABLE; } } #else @@ -156,7 +156,7 @@ static int get_timer_peripheral(const struct pwm_cc13xx_cc26xx_config *config) case GPT3_BASE: return PRCM_PERIPH_TIMER3; default: - __ASSERT_UNREACHABLE; + CODE_UNREACHABLE; } } #endif /* CONFIG_PM */ diff --git a/drivers/pwm/pwm_handlers.c b/drivers/pwm/pwm_handlers.c index 3ffaaa61e465a..5c342a89068fc 100644 --- a/drivers/pwm/pwm_handlers.c +++ b/drivers/pwm/pwm_handlers.c @@ -16,7 +16,7 @@ static inline int z_vrfy_pwm_set_cycles(const struct device *dev, return z_impl_pwm_set_cycles((const struct device *)dev, channel, period, pulse, flags); } -#include +#include static inline int z_vrfy_pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel, @@ -27,7 +27,7 @@ static inline int z_vrfy_pwm_get_cycles_per_sec(const struct device *dev, return z_impl_pwm_get_cycles_per_sec((const struct device *)dev, channel, (uint64_t *)cycles); } -#include +#include #ifdef CONFIG_PWM_CAPTURE @@ -37,7 +37,7 @@ static inline int z_vrfy_pwm_enable_capture(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_PWM(dev, enable_capture)); return z_impl_pwm_enable_capture((const struct device *)dev, channel); } -#include +#include static inline int z_vrfy_pwm_disable_capture(const struct device *dev, uint32_t channel) @@ -45,7 +45,7 @@ static inline int z_vrfy_pwm_disable_capture(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_PWM(dev, disable_capture)); return z_impl_pwm_disable_capture((const struct device *)dev, channel); } -#include +#include static inline int z_vrfy_pwm_capture_cycles(const struct device *dev, uint32_t channel, pwm_flags_t flags, @@ -75,6 +75,6 @@ static inline int z_vrfy_pwm_capture_cycles(const struct device *dev, return err; } -#include +#include #endif /* CONFIG_PWM_CAPTURE */ diff --git a/drivers/pwm/pwm_ite_it8xxx2.c b/drivers/pwm/pwm_ite_it8xxx2.c index 610815505636d..1e5e47f33507f 100644 --- a/drivers/pwm/pwm_ite_it8xxx2.c +++ b/drivers/pwm/pwm_ite_it8xxx2.c @@ -43,6 +43,12 @@ struct pwm_it8xxx2_cfg { const struct pinctrl_dev_config *pcfg; }; +struct pwm_it8xxx2_data { + uint32_t ctr; + uint32_t cxcprs; + uint32_t target_freq_prev; +}; + static void pwm_enable(const struct device *dev, int enabled) { const struct pwm_it8xxx2_cfg *config = dev->config; @@ -92,11 +98,12 @@ static int pwm_it8xxx2_set_cycles(const struct device *dev, { const struct pwm_it8xxx2_cfg *config = dev->config; struct pwm_it8xxx2_regs *const inst = config->base; + struct pwm_it8xxx2_data *data = dev->data; volatile uint8_t *reg_dcr = (uint8_t *)config->reg_dcr; volatile uint8_t *reg_pwmpol = (uint8_t *)config->reg_pwmpol; int ch = config->channel; int prs_sel = config->prs_sel; - uint32_t actual_freq = 0xffffffff, target_freq, deviation, cxcprs, ctr; + uint32_t actual_freq = 0xffffffff, target_freq, deviation; uint64_t pwm_clk_src; /* Select PWM inverted polarity (ex. active-low pulse) */ @@ -162,48 +169,59 @@ static int pwm_it8xxx2_set_cycles(const struct device *dev, * CTRx[7:0] value 00h results in a divisor 1 * CTRx[7:0] value FFh results in a divisor 256 */ - for (ctr = 0xFF; ctr >= PWM_CTRX_MIN; ctr--) { - cxcprs = (((uint32_t) pwm_clk_src) / (ctr + 1) / target_freq); - /* - * Make sure cxcprs isn't zero, or we will have - * divide-by-zero on calculating actual_freq. - */ - if (cxcprs != 0) { - actual_freq = ((uint32_t) pwm_clk_src) / (ctr + 1) / cxcprs; - if (abs(actual_freq - target_freq) < deviation) { - /* CxCPRS[15:0] = cxcprs - 1 */ - cxcprs--; - break; + if (target_freq != data->target_freq_prev) { + uint32_t ctr, cxcprs; + + for (ctr = 0xFF; ctr >= PWM_CTRX_MIN; ctr--) { + cxcprs = (((uint32_t) pwm_clk_src) / (ctr + 1) / target_freq); + /* + * Make sure cxcprs isn't zero, or we will have + * divide-by-zero on calculating actual_freq. + */ + if (cxcprs != 0) { + actual_freq = ((uint32_t) pwm_clk_src) / (ctr + 1) / cxcprs; + if (abs(actual_freq - target_freq) < deviation) { + /* CxCPRS[15:0] = cxcprs - 1 */ + cxcprs--; + break; + } } } - } - if (cxcprs > UINT16_MAX) { - LOG_ERR("PWM prescaler CxCPRS only support 2 bytes !"); - return -EINVAL; + if (cxcprs > UINT16_MAX) { + LOG_ERR("PWM prescaler CxCPRS only support 2 bytes !"); + return -EINVAL; + } + + /* Store ctr and cxcprs with successful frequency change */ + data->ctr = ctr; + data->cxcprs = cxcprs; } /* Set PWM prescaler clock divide and cycle time register */ if (prs_sel == PWM_PRESCALER_C4) { - inst->C4CPRS = cxcprs & 0xFF; - inst->C4MCPRS = (cxcprs >> 8) & 0xFF; - inst->CTR1 = ctr; + inst->C4CPRS = data->cxcprs & 0xFF; + inst->C4MCPRS = (data->cxcprs >> 8) & 0xFF; + inst->CTR1 = data->ctr; } else if (prs_sel == PWM_PRESCALER_C6) { - inst->C6CPRS = cxcprs & 0xFF; - inst->C6MCPRS = (cxcprs >> 8) & 0xFF; - inst->CTR2 = ctr; + inst->C6CPRS = data->cxcprs & 0xFF; + inst->C6MCPRS = (data->cxcprs >> 8) & 0xFF; + inst->CTR2 = data->ctr; } else if (prs_sel == PWM_PRESCALER_C7) { - inst->C7CPRS = cxcprs & 0xFF; - inst->C7MCPRS = (cxcprs >> 8) & 0xFF; - inst->CTR3 = ctr; + inst->C7CPRS = data->cxcprs & 0xFF; + inst->C7MCPRS = (data->cxcprs >> 8) & 0xFF; + inst->CTR3 = data->ctr; } /* Set PWM channel duty cycle register */ - *reg_dcr = (ctr * pulse_cycles) / period_cycles; + *reg_dcr = (data->ctr * pulse_cycles) / period_cycles; /* PWM channel clock source not gating */ pwm_enable(dev, 1); + /* Store the frequency to be compared */ + data->target_freq_prev = target_freq; + LOG_DBG("clock source freq %d, target freq %d", (uint32_t) pwm_clk_src, target_freq); @@ -277,10 +295,12 @@ static const struct pwm_driver_api pwm_it8xxx2_api = { .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ }; \ \ + static struct pwm_it8xxx2_data pwm_it8xxx2_data_##inst; \ + \ DEVICE_DT_INST_DEFINE(inst, \ &pwm_it8xxx2_init, \ NULL, \ - NULL, \ + &pwm_it8xxx2_data_##inst, \ &pwm_it8xxx2_cfg_##inst, \ PRE_KERNEL_1, \ CONFIG_PWM_INIT_PRIORITY, \ diff --git a/drivers/pwm/pwm_led_esp32.c b/drivers/pwm/pwm_led_esp32.c index 1754d5dc36d7f..fb20ae19ce7d9 100644 --- a/drivers/pwm/pwm_led_esp32.c +++ b/drivers/pwm/pwm_led_esp32.c @@ -124,7 +124,11 @@ static int pwm_led_esp32_calculate_max_resolution(struct pwm_ledc_esp32_channel_ * Max duty resolution can be obtained with * max_res = log2(CLK_FREQ/FREQ) */ +#if SOC_LEDC_SUPPORT_APB_CLOCK uint64_t clock_freq = channel->clock_src == LEDC_APB_CLK ? APB_CLK_FREQ : REF_CLK_FREQ; +#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK + uint64_t clock_freq = SCLK_CLK_FREQ; +#endif uint32_t max_precision_n = clock_freq/channel->freq; for (uint8_t i = 0; i <= SOC_LEDC_TIMER_BIT_WIDTH; i++) { @@ -159,7 +163,9 @@ static int pwm_led_esp32_timer_config(struct pwm_ledc_esp32_channel_config *chan * If the given frequency doesn't support it, we move to the next clock source. */ +#if SOC_LEDC_SUPPORT_APB_CLOCK channel->clock_src = LEDC_APB_CLK; +#endif if (!pwm_led_esp32_calculate_max_resolution(channel)) { return 0; } @@ -194,6 +200,7 @@ static int pwm_led_esp32_timer_set(const struct device *dev, __ASSERT_NO_MSG(channel->freq > 0); switch (channel->clock_src) { +#if SOC_LEDC_SUPPORT_APB_CLOCK case LEDC_APB_CLK: /** This expression comes from ESP32 Espressif's Technical Reference * Manual chapter 13.2.2 Timers. @@ -201,6 +208,12 @@ static int pwm_led_esp32_timer_set(const struct device *dev, */ prescaler = ((uint64_t) APB_CLK_FREQ << 8) / channel->freq / precision; break; +#endif +#if SOC_LEDC_SUPPORT_PLL_DIV_CLOCK + case LEDC_SCLK: + prescaler = ((uint64_t) SCLK_CLK_FREQ << 8) / channel->freq / precision; + break; +#endif #if SOC_LEDC_SUPPORT_REF_TICK case LEDC_REF_TICK: prescaler = ((uint64_t) REF_CLK_FREQ << 8) / channel->freq / precision; @@ -245,7 +258,11 @@ static int pwm_led_esp32_get_cycles_per_sec(const struct device *dev, return -EINVAL; } +#if SOC_LEDC_SUPPORT_APB_CLOCK *cycles = channel->clock_src == LEDC_APB_CLK ? APB_CLK_FREQ : REF_CLK_FREQ; +#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK + *cycles = SCLK_CLK_FREQ; +#endif return 0; } @@ -338,6 +355,12 @@ static const struct pwm_driver_api pwm_led_esp32_api = { PINCTRL_DT_INST_DEFINE(0); +#if SOC_LEDC_SUPPORT_APB_CLOCK + #define CLOCK_SOURCE LEDC_APB_CLK +#elif SOC_LEDC_SUPPORT_PLL_DIV_CLOCK + #define CLOCK_SOURCE LEDC_SCLK +#endif + #define CHANNEL_CONFIG(node_id) \ { \ .idx = DT_REG_ADDR(node_id), \ @@ -346,7 +369,7 @@ PINCTRL_DT_INST_DEFINE(0); .speed_mode = DT_REG_ADDR(node_id) < SOC_LEDC_CHANNEL_NUM \ ? LEDC_LOW_SPEED_MODE \ : !LEDC_LOW_SPEED_MODE, \ - .clock_src = LEDC_APB_CLK, \ + .clock_src = CLOCK_SOURCE, \ }, static struct pwm_ledc_esp32_channel_config channel_config[] = { diff --git a/drivers/pwm/pwm_mcux.c b/drivers/pwm/pwm_mcux.c index d753682f46e46..617ac3e4b7f7c 100644 --- a/drivers/pwm/pwm_mcux.c +++ b/drivers/pwm/pwm_mcux.c @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -35,9 +36,10 @@ struct pwm_mcux_config { struct pwm_mcux_data { uint32_t period_cycles[CHANNEL_COUNT]; pwm_signal_param_t channel[CHANNEL_COUNT]; + struct k_mutex lock; }; -static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, +static int mcux_pwm_set_cycles_internal(const struct device *dev, uint32_t channel, uint32_t period_cycles, uint32_t pulse_cycles, pwm_flags_t flags) { @@ -45,24 +47,6 @@ static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, struct pwm_mcux_data *data = dev->data; pwm_level_select_t level; - if (channel >= CHANNEL_COUNT) { - LOG_ERR("Invalid channel"); - return -EINVAL; - } - - if (period_cycles == 0) { - LOG_ERR("Channel can not be set to inactive level"); - return -ENOTSUP; - } - - if (period_cycles > UINT16_MAX) { - /* 16-bit resolution */ - LOG_ERR("Too long period (%u), adjust pwm prescaler!", - period_cycles); - /* TODO: dynamically adjust prescaler */ - return -EINVAL; - } - if (flags & PWM_POLARITY_INVERTED) { level = kPWM_LowTrue; } else { @@ -158,6 +142,36 @@ static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, return 0; } +static int mcux_pwm_set_cycles(const struct device *dev, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles, + pwm_flags_t flags) +{ + struct pwm_mcux_data *data = dev->data; + int result; + + if (channel >= CHANNEL_COUNT) { + LOG_ERR("Invalid channel"); + return -EINVAL; + } + + if (period_cycles == 0) { + LOG_ERR("Channel can not be set to inactive level"); + return -ENOTSUP; + } + + if (period_cycles > UINT16_MAX) { + /* 16-bit resolution */ + LOG_ERR("Too long period (%u), adjust pwm prescaler!", + period_cycles); + /* TODO: dynamically adjust prescaler */ + return -EINVAL; + } + k_mutex_lock(&data->lock, K_FOREVER); + result = mcux_pwm_set_cycles_internal(dev, channel, period_cycles, pulse_cycles, flags); + k_mutex_unlock(&data->lock); + return result; +} + static int mcux_pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel, uint64_t *cycles) { @@ -181,6 +195,8 @@ static int pwm_mcux_init(const struct device *dev) status_t status; int i, err; + k_mutex_init(&data->lock); + if (!device_is_ready(config->clock_dev)) { LOG_ERR("clock control device not ready"); return -ENODEV; diff --git a/drivers/pwm/pwm_mcux_qtmr.c b/drivers/pwm/pwm_mcux_qtmr.c new file mode 100644 index 0000000000000..b78f43b0436b1 --- /dev/null +++ b/drivers/pwm/pwm_mcux_qtmr.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2024, NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_qtmr_pwm + +#include +#include +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(pwm_mcux_qtmr, CONFIG_PWM_LOG_LEVEL); + +#define CHANNEL_COUNT TMR_CNTR_COUNT + +struct pwm_mcux_qtmr_config { + TMR_Type *base; + uint32_t prescaler; + const struct pinctrl_dev_config *pincfg; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; +}; + +struct pwm_mcux_qtmr_data { + struct k_mutex lock; +}; + +static int mcux_qtmr_pwm_set_cycles(const struct device *dev, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles, + pwm_flags_t flags) +{ + const struct pwm_mcux_qtmr_config *config = dev->config; + struct pwm_mcux_qtmr_data *data = dev->data; + uint32_t periodCount, highCount, lowCount; + uint16_t reg; + + if (channel >= CHANNEL_COUNT) { + LOG_ERR("Invalid channel"); + return -EINVAL; + } + + /* Counter values to generate a PWM signal */ + periodCount = period_cycles; + highCount = pulse_cycles; + lowCount = period_cycles - pulse_cycles; + + if (highCount > 0U) { + highCount -= 1U; + } + if (lowCount > 0U) { + lowCount -= 1U; + } + + if ((highCount > 0xFFFFU) || (lowCount > 0xFFFFU)) { + /* This should not be a 16-bit overflow value. If it is, change to a larger divider + * for clock source. + */ + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + /* Set OFLAG pin for output mode and force out a low on the pin */ + config->base->CHANNEL[channel].SCTRL |= (TMR_SCTRL_FORCE_MASK | TMR_SCTRL_OEN_MASK); + + QTMR_StopTimer(config->base, channel); + + /* Setup the compare registers for PWM output */ + config->base->CHANNEL[channel].COMP1 = (uint16_t)lowCount; + config->base->CHANNEL[channel].COMP2 = (uint16_t)highCount; + + /* Setup the pre-load registers for PWM output */ + config->base->CHANNEL[channel].CMPLD1 = (uint16_t)lowCount; + config->base->CHANNEL[channel].CMPLD2 = (uint16_t)highCount; + + reg = config->base->CHANNEL[channel].CSCTRL; + /* Setup the compare load control for COMP1 and COMP2. + * Load COMP1 when CSCTRL[TCF2] is asserted, load COMP2 when CSCTRL[TCF1] is asserted + */ + reg &= (uint16_t)(~(TMR_CSCTRL_CL1_MASK | TMR_CSCTRL_CL2_MASK)); + reg |= (TMR_CSCTRL_CL1(kQTMR_LoadOnComp2) | TMR_CSCTRL_CL2(kQTMR_LoadOnComp1)); + config->base->CHANNEL[channel].CSCTRL = reg; + + reg = config->base->CHANNEL[channel].CTRL; + reg &= ~(uint16_t)TMR_CTRL_OUTMODE_MASK; + if (highCount == periodCount) { + /* Set OFLAG output on compare */ + reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_SetOnCompare)); + } else if (periodCount == 0U) { + /* Clear OFLAG output on compare */ + reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ClearOnCompare)); + } else { + /* Toggle OFLAG output using alternating compare register */ + reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg)); + } + + config->base->CHANNEL[channel].CTRL = reg; + + QTMR_StartTimer(config->base, channel, kQTMR_PriSrcRiseEdge); + + k_mutex_unlock(&data->lock); + + return 0; +} + +static int mcux_qtmr_pwm_get_cycles_per_sec(const struct device *dev, uint32_t channel, + uint64_t *cycles) +{ + const struct pwm_mcux_qtmr_config *config = dev->config; + uint32_t clock_freq; + + if (clock_control_get_rate(config->clock_dev, config->clock_subsys, &clock_freq)) { + return -EINVAL; + } + + *cycles = clock_freq / config->prescaler; + + return 0; +} + +static int mcux_qtmr_pwm_init(const struct device *dev) +{ + const struct pwm_mcux_qtmr_config *config = dev->config; + struct pwm_mcux_qtmr_data *data = dev->data; + qtmr_config_t qtmr_config; + int err; + + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (err) { + return err; + } + + k_mutex_init(&data->lock); + + QTMR_GetDefaultConfig(&qtmr_config); + qtmr_config.primarySource = kQTMR_ClockDivide_1 + (31 - __builtin_clz(config->prescaler)); + + for (int i = 0; i < CHANNEL_COUNT; i++) { + QTMR_Init(config->base, i, &qtmr_config); + } + + return 0; +} + +static const struct pwm_driver_api pwm_mcux_qtmr_driver_api = { + .set_cycles = mcux_qtmr_pwm_set_cycles, + .get_cycles_per_sec = mcux_qtmr_pwm_get_cycles_per_sec, +}; + +#define PWM_MCUX_QTMR_DEVICE_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static struct pwm_mcux_qtmr_data pwm_mcux_qtmr_data_##n; \ + \ + static const struct pwm_mcux_qtmr_config pwm_mcux_qtmr_config_##n = { \ + .base = (TMR_Type *)DT_INST_REG_ADDR(n), \ + .prescaler = DT_INST_PROP(n, prescaler), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(n)), \ + .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(n, name), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, mcux_qtmr_pwm_init, NULL, &pwm_mcux_qtmr_data_##n, \ + &pwm_mcux_qtmr_config_##n, POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ + &pwm_mcux_qtmr_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(PWM_MCUX_QTMR_DEVICE_INIT) diff --git a/drivers/pwm/pwm_nxp_flexio.c b/drivers/pwm/pwm_nxp_flexio.c new file mode 100644 index 0000000000000..4dbafd8250f9e --- /dev/null +++ b/drivers/pwm/pwm_nxp_flexio.c @@ -0,0 +1,339 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + + +#define DT_DRV_COMPAT nxp_flexio_pwm + +#include +#include +#include +#include +#include +#include + +#include +#include + + +LOG_MODULE_REGISTER(pwm_nxp_flexio, CONFIG_PWM_LOG_LEVEL); + +#define FLEXIO_PWM_TIMER_CMP_MAX_VALUE (0xFFFFU) +#define FLEXIO_PWM_TIMCMP_CMP_UPPER_SHIFT (0x8U) +#define FLEXIO_MAX_PWM_CHANNELS 8 + +enum pwm_nxp_flexio_polarity { + FLEXIO_PWM_ACTIVE_HIGH = 0x0U, + FLEXIO_PWM_ACTIVE_LOW = 0x1U +}; + +enum pwm_nxp_flexio_timerinit { + /** Timer Initial output is logic one */ + FLEXIO_PWM_TIMER_INIT_HIGH = 0x00U, + /** Timer Initial output is logic zero */ + FLEXIO_PWM_TIMER_INIT_LOW = 0x1U +}; + +enum pwm_nxp_flexio_prescaler { + /* Decrement counter on Flexio clock */ + FLEXIO_PWM_CLK_DIV_1 = 0U, + /* Decrement counter on Flexio clock divided by 16 */ + FLEXIO_PWM_CLK_DIV_16 = 4U, + /* Decrement counter on Flexio clock divided by 256 */ + FLEXIO_PWM_CLK_DIV_256 = 5U +}; + +enum pwm_nxp_flexio_timer_mode { + /** Timer disabled */ + FLEXIO_PWM_TIMER_DISABLED = 0x00U, + /** Timer in 8 bit Pwm High mode */ + FLEXIO_PWM_TIMER_PWM_HIGH = 0x02U, + /** Timer in 8 bit Pwm Low mode */ + FLEXIO_PWM_TIMER_PWM_LOW = 0x06U +}; + +enum pwm_nxp_flexio_timer_pin { + /** Timer Pin output disabled */ + FLEXIO_PWM_TIMER_PIN_OUTPUT_DISABLE = 0x00U, + /** Timer Pin Output mode */ + FLEXIO_PWM_TIMER_PIN_OUTPUT_ENABLE = 0x03U +}; + +struct pwm_nxp_flexio_channel_config { + /** Flexio used pin index */ + uint8_t pin_id; + /** Counter decrement clock prescaler */ + enum pwm_nxp_flexio_prescaler prescaler; + /** Actual Prescaler divisor */ + uint8_t prescaler_div; +}; + +struct pwm_nxp_flexio_pulse_info { + uint8_t pwm_pulse_channels; + struct pwm_nxp_flexio_channel_config *pwm_info; +}; + +struct pwm_nxp_flexio_config { + const struct device *flexio_dev; + FLEXIO_Type *flexio_base; + const struct pinctrl_dev_config *pincfg; + const struct device *clock_dev; + clock_control_subsys_t clock_subsys; + const struct pwm_nxp_flexio_pulse_info *pulse_info; + const struct nxp_flexio_child *child; +}; + +struct pwm_nxp_flexio_data { + uint32_t period_cycles[FLEXIO_MAX_PWM_CHANNELS]; + uint32_t flexio_clk; +}; + +static int pwm_nxp_flexio_set_cycles(const struct device *dev, + uint32_t channel, uint32_t period_cycles, + uint32_t pulse_cycles, pwm_flags_t flags) +{ + const struct pwm_nxp_flexio_config *config = dev->config; + struct pwm_nxp_flexio_data *data = dev->data; + flexio_timer_config_t timerConfig; + struct pwm_nxp_flexio_channel_config *pwm_info; + FLEXIO_Type *flexio_base = (FLEXIO_Type *)(config->flexio_base); + struct nxp_flexio_child *child = (struct nxp_flexio_child *)(config->child); + enum pwm_nxp_flexio_polarity polarity; + + /* Check received parameters for sanity */ + if (channel >= config->pulse_info->pwm_pulse_channels) { + LOG_ERR("Invalid channel"); + return -EINVAL; + } + + if (period_cycles == 0) { + LOG_ERR("Channel can not be set to inactive level"); + return -ENOTSUP; + } + + if (FLEXIO_PWM_TIMER_CMP_MAX_VALUE <= (uint16_t)pulse_cycles) { + LOG_ERR("Duty cycle is out of range"); + return -EINVAL; + } + + if (FLEXIO_PWM_TIMER_CMP_MAX_VALUE <= (uint16_t)(period_cycles - pulse_cycles)) { + LOG_ERR("low period of the cycle is out of range"); + return -EINVAL; + } + + if (pulse_cycles > period_cycles) { + LOG_ERR("Duty cycle cannot be greater than 100 percent"); + return -EINVAL; + } + + pwm_info = &config->pulse_info->pwm_info[channel]; + + if ((flags & PWM_POLARITY_INVERTED) == 0) { + polarity = FLEXIO_PWM_ACTIVE_HIGH; + } else { + polarity = FLEXIO_PWM_ACTIVE_LOW; + } + + if (polarity == FLEXIO_PWM_ACTIVE_HIGH) { + timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset; + timerConfig.timerMode = kFLEXIO_TimerModeDual8BitPWM; + + } else { + timerConfig.timerOutput = kFLEXIO_TimerOutputZeroNotAffectedByReset; + timerConfig.timerMode = kFLEXIO_TimerModeDual8BitPWMLow; + } + + data->period_cycles[channel] = period_cycles; + + timerConfig.timerCompare = ((uint8_t)(pulse_cycles - 1U)) | + ((uint8_t)(data->period_cycles[channel] - pulse_cycles - 1U) + << FLEXIO_PWM_TIMCMP_CMP_UPPER_SHIFT); + + timerConfig.timerDecrement = pwm_info->prescaler; + timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled; + timerConfig.timerEnable = kFLEXIO_TimerEnabledAlways; + timerConfig.timerDisable = kFLEXIO_TimerDisableNever; + timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled; + timerConfig.timerReset = kFLEXIO_TimerResetNever; + timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal; + + /* Enable the pin out for the selected timer */ + timerConfig.pinConfig = FLEXIO_PWM_TIMER_PIN_OUTPUT_ENABLE; + timerConfig.pinPolarity = polarity; + + /* Select the pin that the selected timer will output the signal on */ + timerConfig.pinSelect = pwm_info->pin_id; + + FLEXIO_SetTimerConfig(flexio_base, child->res.timer_index[channel], &timerConfig); + +#if (defined(FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER) && FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER) + /* Disable pin override if active to support channels working in cases not 0% 100% */ + if (FLEXIO_GetPinOverride(flexio_base, pwm_info->pin_id)) { + FLEXIO_ConfigPinOverride(flexio_base, pwm_info->pin_id, false); + } +#endif + return 0; +} + +static int pwm_nxp_flexio_get_cycles_per_sec(const struct device *dev, + uint32_t channel, + uint64_t *cycles) +{ + const struct pwm_nxp_flexio_config *config = dev->config; + struct pwm_nxp_flexio_data *data = dev->data; + struct pwm_nxp_flexio_channel_config *pwm_info; + + /* If get_cycles is called directly after init */ + if (data->period_cycles[channel] == 0) { + LOG_ERR("First set the period of this channel to a non zero value"); + return -ENOTSUP; + } + + pwm_info = &config->pulse_info->pwm_info[channel]; + *cycles = (uint64_t)(((data->flexio_clk) * 2) / + ((data->period_cycles[channel]) * (pwm_info->prescaler_div))); + + return 0; +} + +static int mcux_flexio_pwm_init(const struct device *dev) +{ + const struct pwm_nxp_flexio_config *config = dev->config; + struct pwm_nxp_flexio_data *data = dev->data; + flexio_timer_config_t timerConfig; + uint8_t ch_id = 0; + int err; + struct pwm_nxp_flexio_channel_config *pwm_info; + FLEXIO_Type *flexio_base = (FLEXIO_Type *)(config->flexio_base); + struct nxp_flexio_child *child = (struct nxp_flexio_child *)(config->child); + + if (!device_is_ready(config->clock_dev)) { + return -ENODEV; + } + + if (clock_control_get_rate(config->clock_dev, config->clock_subsys, + &data->flexio_clk)) { + return -EINVAL; + } + + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (err) { + return err; + } + + err = nxp_flexio_child_attach(config->flexio_dev, child); + if (err < 0) { + return err; + } + + for (ch_id = 0; ch_id < config->pulse_info->pwm_pulse_channels; ch_id++) { + pwm_info = &config->pulse_info->pwm_info[ch_id]; + + /* Reset timer settings */ + (void)memset(&timerConfig, 0, sizeof(timerConfig)); + FLEXIO_SetTimerConfig(flexio_base, child->res.timer_index[ch_id], &timerConfig); + +#if (defined(FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER) && FSL_FEATURE_FLEXIO_HAS_PIN_REGISTER) + /* Reset the value driven on the corresponding pin */ + FLEXIO_SetPinLevel(flexio_base, pwm_info->pin_id, false); + FLEXIO_ConfigPinOverride(flexio_base, pwm_info->pin_id, false); +#endif + /* Timer output is logic one and is not affected by timer reset */ + timerConfig.timerOutput = kFLEXIO_TimerOutputOneNotAffectedByReset; + /* Set the timer mode to dual 8-bit counter PWM high */ + timerConfig.timerMode = kFLEXIO_TimerModeDual8BitPWM; + + /* Timer scaling factor w.r.t Flexio Clock */ + timerConfig.timerDecrement = pwm_info->prescaler; + + /* Program the PWM pulse */ + timerConfig.timerCompare = 0; + + /* Configure Timer CFG and CTL bits to support PWM mode */ + timerConfig.timerStop = kFLEXIO_TimerStopBitDisabled; + timerConfig.timerEnable = kFLEXIO_TimerEnabledAlways; + timerConfig.timerDisable = kFLEXIO_TimerDisableNever; + timerConfig.timerStart = kFLEXIO_TimerStartBitDisabled; + timerConfig.timerReset = kFLEXIO_TimerResetNever; + timerConfig.triggerSource = kFLEXIO_TimerTriggerSourceInternal; + + /* Enable the pin out and set a default polarity for the selected timer */ + timerConfig.pinConfig = FLEXIO_PWM_TIMER_PIN_OUTPUT_ENABLE; + timerConfig.pinPolarity = kFLEXIO_PinActiveHigh; + + /* Select the pin that the selected timer will output the signal on */ + timerConfig.pinSelect = pwm_info->pin_id; + + FLEXIO_SetTimerConfig(flexio_base, child->res.timer_index[ch_id], &timerConfig); + } + + return 0; +} + +static const struct pwm_driver_api pwm_nxp_flexio_driver_api = { + .set_cycles = pwm_nxp_flexio_set_cycles, + .get_cycles_per_sec = pwm_nxp_flexio_get_cycles_per_sec, +}; + +#define _FLEXIO_PWM_PULSE_GEN_CONFIG(n) \ + { \ + .pin_id = DT_PROP(n, pin_id), \ + .prescaler = _CONCAT(FLEXIO_PWM_CLK_DIV_, DT_PROP(n, prescaler)), \ + .prescaler_div = DT_PROP(n, prescaler), \ + }, + +#define FLEXIO_PWM_PULSE_GEN_CONFIG(n) \ + static struct pwm_nxp_flexio_channel_config flexio_pwm_##n##_init[] = { \ + DT_INST_FOREACH_CHILD_STATUS_OKAY(n, _FLEXIO_PWM_PULSE_GEN_CONFIG) \ + }; \ + static const struct pwm_nxp_flexio_pulse_info flexio_pwm_##n##_info = { \ + .pwm_pulse_channels = ARRAY_SIZE(flexio_pwm_##n##_init), \ + .pwm_info = flexio_pwm_##n##_init, \ + }; + +#define FLEXIO_PWM_TIMER_INDEX_INIT(n) \ + static uint8_t flexio_pwm_##n##_timer_index[ARRAY_SIZE(flexio_pwm_##n##_init)]; + +#define FLEXIO_PWM_CHILD_CONFIG(n) \ + static const struct nxp_flexio_child mcux_flexio_pwm_child_##n = { \ + .isr = NULL, \ + .user_data = NULL, \ + .res = { \ + .shifter_index = NULL, \ + .shifter_count = 0, \ + .timer_index = (uint8_t *)flexio_pwm_##n##_timer_index, \ + .timer_count = ARRAY_SIZE(flexio_pwm_##n##_init) \ + } \ + }; + +#define FLEXIO_PWM_PULSE_GEN_GET_CONFIG(n) \ + .pulse_info = &flexio_pwm_##n##_info, + + +#define PWM_NXP_FLEXIO_PWM_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + FLEXIO_PWM_PULSE_GEN_CONFIG(n) \ + FLEXIO_PWM_TIMER_INDEX_INIT(n) \ + FLEXIO_PWM_CHILD_CONFIG(n) \ + static const struct pwm_nxp_flexio_config pwm_nxp_flexio_config_##n = { \ + .flexio_dev = DEVICE_DT_GET(DT_INST_PARENT(n)), \ + .flexio_base = (FLEXIO_Type *)DT_REG_ADDR(DT_INST_PARENT(n)), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .clock_dev = DEVICE_DT_GET(DT_CLOCKS_CTLR(DT_INST_PARENT(n))), \ + .clock_subsys = (clock_control_subsys_t)DT_CLOCKS_CELL(DT_INST_PARENT(n), name),\ + .child = &mcux_flexio_pwm_child_##n, \ + FLEXIO_PWM_PULSE_GEN_GET_CONFIG(n) \ + }; \ + \ + static struct pwm_nxp_flexio_data pwm_nxp_flexio_data_##n; \ + DEVICE_DT_INST_DEFINE(n, \ + &mcux_flexio_pwm_init, \ + NULL, \ + &pwm_nxp_flexio_data_##n, \ + &pwm_nxp_flexio_config_##n, \ + POST_KERNEL, CONFIG_PWM_INIT_PRIORITY, \ + &pwm_nxp_flexio_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(PWM_NXP_FLEXIO_PWM_INIT) diff --git a/drivers/pwm/pwm_stm32.c b/drivers/pwm/pwm_stm32.c index c8e44633ad5f9..70006e377b1b0 100644 --- a/drivers/pwm/pwm_stm32.c +++ b/drivers/pwm/pwm_stm32.c @@ -141,9 +141,7 @@ static void (*const set_timer_compare[TIMER_MAX_CH])(TIM_TypeDef *, }; /** Channel to capture get function mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32F4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32MP1X) +#if !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t __maybe_unused (*const get_channel_capture[])(const TIM_TypeDef *) = { #else static uint32_t __maybe_unused (*const get_channel_capture[])(TIM_TypeDef *) = { @@ -166,9 +164,7 @@ static void __maybe_unused (*const disable_capture_interrupt[])(TIM_TypeDef *) = }; /** Channel to is capture active flag mapping. */ -#if !defined(CONFIG_SOC_SERIES_STM32F4X) && \ - !defined(CONFIG_SOC_SERIES_STM32G4X) && \ - !defined(CONFIG_SOC_SERIES_STM32MP1X) +#if !defined(CONFIG_SOC_SERIES_STM32MP1X) static uint32_t __maybe_unused (*const is_capture_active[])(const TIM_TypeDef *) = { #else static uint32_t __maybe_unused (*const is_capture_active[])(TIM_TypeDef *) = { diff --git a/drivers/regulator/Kconfig.adp5360 b/drivers/regulator/Kconfig.adp5360 index 0785ba54abf0a..f93df2ef163ed 100644 --- a/drivers/regulator/Kconfig.adp5360 +++ b/drivers/regulator/Kconfig.adp5360 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_ADP5360 bool "ADP5360 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.axp192 b/drivers/regulator/Kconfig.axp192 index 8c8fad5cdb44c..b56868ccdb7a1 100644 --- a/drivers/regulator/Kconfig.axp192 +++ b/drivers/regulator/Kconfig.axp192 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Martin Kiepfer -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_AXP192 bool "X-Power AXP192 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.da1469x b/drivers/regulator/Kconfig.da1469x index 142634ae5e81f..e6722c1cb9fd7 100644 --- a/drivers/regulator/Kconfig.da1469x +++ b/drivers/regulator/Kconfig.da1469x @@ -4,14 +4,13 @@ config REGULATOR_DA1469X bool "DA1469X regulators driver" default y - select PM_DEVICE if PM depends on DT_HAS_RENESAS_SMARTBOND_REGULATOR_ENABLED help Enable support for the Smartbond DA1469x regulators. config REGULATOR_DA1469X_INIT_PRIORITY int "Renesas DA1469x regulators driver init priority" - default KERNEL_INIT_PRIORITY_DEVICE + default 20 depends on REGULATOR_DA1469X help Init priority for the Renesas DA1469x regulators driver. diff --git a/drivers/regulator/Kconfig.max20335 b/drivers/regulator/Kconfig.max20335 index a92743afdb536..df0eafe515813 100644 --- a/drivers/regulator/Kconfig.max20335 +++ b/drivers/regulator/Kconfig.max20335 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_MAX20335 bool "MAX20335 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.npm1100 b/drivers/regulator/Kconfig.npm1100 index 56301a7beca2f..97c7cbefc35b0 100644 --- a/drivers/regulator/Kconfig.npm1100 +++ b/drivers/regulator/Kconfig.npm1100 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_NPM1100 bool "nPM1100 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.npm1300 b/drivers/regulator/Kconfig.npm1300 index 997934cabb798..19adee0ebab2f 100644 --- a/drivers/regulator/Kconfig.npm1300 +++ b/drivers/regulator/Kconfig.npm1300 @@ -1,5 +1,5 @@ # Copyright (c) 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_NPM1300 bool "nPM1300 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.npm6001 b/drivers/regulator/Kconfig.npm6001 index a9c290475deac..d171a4bdd6f9d 100644 --- a/drivers/regulator/Kconfig.npm6001 +++ b/drivers/regulator/Kconfig.npm6001 @@ -1,5 +1,5 @@ # Copyright (c) 2022 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_NPM6001 bool "nPM6001 PMIC regulator driver" diff --git a/drivers/regulator/Kconfig.nxp_vref b/drivers/regulator/Kconfig.nxp_vref index 3bfb068b78656..b26614b75daaa 100644 --- a/drivers/regulator/Kconfig.nxp_vref +++ b/drivers/regulator/Kconfig.nxp_vref @@ -1,5 +1,5 @@ # Copyright 2023 NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_NXP_VREF bool "NXP VREF peripheral driver" diff --git a/drivers/regulator/Kconfig.pca9420 b/drivers/regulator/Kconfig.pca9420 index 9a2d2377c6147..bf87ed50d23af 100644 --- a/drivers/regulator/Kconfig.pca9420 +++ b/drivers/regulator/Kconfig.pca9420 @@ -1,5 +1,5 @@ # Copyright (c) 2021, NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config REGULATOR_PCA9420 bool "NXP PCA9420 PMIC regulator driver" diff --git a/drivers/regulator/regulator_da1469x.c b/drivers/regulator/regulator_da1469x.c index 50887e4b4531b..fe6d6a8ccc1ff 100644 --- a/drivers/regulator/regulator_da1469x.c +++ b/drivers/regulator/regulator_da1469x.c @@ -13,6 +13,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(regulator_da1469x, CONFIG_REGULATOR_LOG_LEVEL); @@ -22,6 +23,9 @@ LOG_MODULE_REGISTER(regulator_da1469x, CONFIG_REGULATOR_LOG_LEVEL); #define DA1469X_LDO_3V0_MODE_VBAT BIT(8) #define DA1469X_LDO_3V0_MODE_VBUS BIT(9) +#define PLL_FREQ DT_PROP(DT_NODELABEL(pll), clock_frequency) +#define PLL_VDD_UV 1200000 + static const struct linear_range curren_ranges[] = { LINEAR_RANGE_INIT(30000, 30000, 0, 31), }; @@ -281,6 +285,20 @@ static int regulator_da1469x_set_voltage(const struct device *dev, int32_t min_u uint16_t idx; uint32_t mask; + if ((SystemCoreClock == PLL_FREQ) && (config->rail == VDD)) { + /* PLL requires that VDD be @1.2V */ + if (max_uv < PLL_VDD_UV) { + return -EPERM; + } + /* + * The get index API should select the min voltage; + * make sure the correct voltage is applied. + */ + if (min_uv < PLL_VDD_UV) { + min_uv = PLL_VDD_UV; + } + } + ret = linear_range_group_get_win_index(config->desc->voltage_ranges, config->desc->voltage_range_count, min_uv, max_uv, &idx); @@ -307,7 +325,7 @@ static int regulator_da1469x_get_voltage(const struct device *dev, uint16_t idx; if (config->desc->voltage_idx_mask) { - idx = FIELD_GET(CRG_TOP->POWER_CTRL_REG, config->desc->voltage_idx_mask); + idx = FIELD_GET(config->desc->voltage_idx_mask, CRG_TOP->POWER_CTRL_REG); } else { idx = 0; } @@ -358,8 +376,8 @@ static int regulator_da1469x_get_current_limit(const struct device *dev, if (config->desc->current_ranges == NULL) { return -ENOTSUP; } - idx = FIELD_GET(*config->desc->dcdc_register, - DCDC_DCDC_V14_REG_DCDC_V14_CUR_LIM_MAX_HV_Msk); + idx = FIELD_GET(DCDC_DCDC_V14_REG_DCDC_V14_CUR_LIM_MAX_HV_Msk, + *config->desc->dcdc_register); ret = linear_range_group_get_value(config->desc->current_ranges, 1, idx, curr_ua); return ret; @@ -442,7 +460,8 @@ static int regulator_da1469x_pm_action(const struct device *dev, (DT_PROP(node, renesas_regulator_dcdc_vbat_high) * \ DCDC_DCDC_VDD_REG_DCDC_VDD_ENABLE_HV_Msk) | \ (DT_PROP(node, renesas_regulator_dcdc_vbat_low) * \ - DCDC_DCDC_VDD_REG_DCDC_VDD_ENABLE_LV_Msk) \ + DCDC_DCDC_VDD_REG_DCDC_VDD_ENABLE_LV_Msk), \ + .rail = rail_id, \ }; \ PM_DEVICE_DT_DEFINE(node, regulator_da1469x_pm_action); \ DEVICE_DT_DEFINE(node, regulator_da1469x_init, \ diff --git a/drivers/regulator/regulator_gpio.c b/drivers/regulator/regulator_gpio.c index 49d373897b38e..d888a5fd6dcc4 100644 --- a/drivers/regulator/regulator_gpio.c +++ b/drivers/regulator/regulator_gpio.c @@ -167,8 +167,6 @@ static int regulator_gpio_init(const struct device *dev) regulator_common_data_init(dev); for (unsigned int gpio_idx = 0; gpio_idx < cfg->num_gpios; gpio_idx++) { - int ret; - if (!gpio_is_ready_dt(&cfg->gpios[gpio_idx])) { LOG_ERR("%s: gpio pin: %s not ready", dev->name, cfg->gpios[gpio_idx].port ? cfg->gpios[gpio_idx].port->name diff --git a/drivers/regulator/regulator_npm6001.c b/drivers/regulator/regulator_npm6001.c index 1b854cbf83059..2ade708271adc 100644 --- a/drivers/regulator/regulator_npm6001.c +++ b/drivers/regulator/regulator_npm6001.c @@ -211,7 +211,7 @@ static int regulator_npm6001_ldo0_set_voltage(const struct device *dev, int32_t int32_t max_uv) { const struct regulator_npm6001_config *config = dev->config; - uint8_t val; + uint8_t val = 0U; size_t i; for (i = 0U; i < ARRAY_SIZE(ldo0_voltages); i++) { diff --git a/drivers/regulator/regulator_nxp_vref.c b/drivers/regulator/regulator_nxp_vref.c index 3d2ba23010e31..d3aa0f48a1524 100644 --- a/drivers/regulator/regulator_nxp_vref.c +++ b/drivers/regulator/regulator_nxp_vref.c @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * SPDX-License-Identifier: Apache-2.0 */ @@ -24,7 +24,6 @@ struct regulator_nxp_vref_data { struct regulator_nxp_vref_config { struct regulator_common_config common; VREF_Type *base; - uint8_t gnd_sel; uint16_t buf_start_delay; uint16_t bg_start_time; }; @@ -165,7 +164,7 @@ static int regulator_nxp_vref_get_voltage(const struct device *dev, /* Linear range index is the register value */ idx = (base->UTRIM & VREF_UTRIM_TRIM2V1_MASK) >> VREF_UTRIM_TRIM2V1_SHIFT; - ret = linear_range_get_value(&utrim_range, base->UTRIM, volt_uv); + ret = linear_range_get_value(&utrim_range, idx, volt_uv); return ret; } @@ -183,16 +182,10 @@ static const struct regulator_driver_api api = { static int regulator_nxp_vref_init(const struct device *dev) { - const struct regulator_nxp_vref_config *config = dev->config; - VREF_Type *base = config->base; int ret; regulator_common_data_init(dev); - /* Select ground */ - base->CSR &= ~VREF_CSR_REFL_GRD_SEL_MASK; - base->CSR |= config->gnd_sel; - ret = regulator_nxp_vref_disable(dev); if (ret < 0) { return ret; @@ -207,7 +200,6 @@ static int regulator_nxp_vref_init(const struct device *dev) static const struct regulator_nxp_vref_config config_##inst = { \ .common = REGULATOR_DT_INST_COMMON_CONFIG_INIT(inst), \ .base = (VREF_Type *) DT_INST_REG_ADDR(inst), \ - .gnd_sel = DT_INST_ENUM_IDX_OR(inst, nxp_ground_select, 0), \ .buf_start_delay = DT_INST_PROP(inst, \ nxp_buffer_startup_delay_us), \ .bg_start_time = DT_INST_PROP(inst, \ diff --git a/drivers/regulator/regulator_shell.c b/drivers/regulator/regulator_shell.c index f9d61431cc966..ba0c29e34b803 100644 --- a/drivers/regulator/regulator_shell.c +++ b/drivers/regulator/regulator_shell.c @@ -74,8 +74,7 @@ static int strtomicro(char *inp, char units, int32_t *val) static void microtoshell(const struct shell *sh, char unit, int32_t val) { if (val > 100000) { - shell_print(sh, "%d.%03d %c", val / 1000000, - (val % 1000000) / 1000, unit); + shell_print(sh, "%d.%06d %c", val / 1000000, val % 1000000, unit); } else if (val > 1000) { shell_print(sh, "%d.%03d m%c", val / 1000, val % 1000, unit); } else { @@ -399,9 +398,9 @@ static int cmd_adset(const struct shell *sh, size_t argc, char **argv) return -ENODEV; } - if (strcmp(argv[2], "enable")) { + if (strcmp(argv[2], "enable") == 0) { ad = true; - } else if (strcmp(argv[2], "disable")) { + } else if (strcmp(argv[2], "disable") == 0) { ad = false; } else { shell_error(sh, "Invalid parameter"); diff --git a/drivers/reset/CMakeLists.txt b/drivers/reset/CMakeLists.txt index f27f31f683c11..84f0443cabb5f 100644 --- a/drivers/reset/CMakeLists.txt +++ b/drivers/reset/CMakeLists.txt @@ -10,3 +10,5 @@ zephyr_library_sources_ifdef(CONFIG_RESET_STM32 reset_stm32.c) zephyr_library_sources_ifdef(CONFIG_RESET_NUMAKER reset_numaker.c) zephyr_library_sources_ifdef(CONFIG_RESET_INTEL_SOCFPGA reset_intel_socfpga.c) zephyr_library_sources_ifdef(CONFIG_RESET_NPCX reset_npcx.c) +zephyr_library_sources_ifdef(CONFIG_RESET_NXP_SYSCON reset_lpc_syscon.c) +zephyr_library_sources_ifdef(CONFIG_RESET_NXP_RSTCTL reset_nxp_rstctl.c) diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 1d361aa8e243d..87ba9c7576cac 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -34,5 +34,7 @@ rsource "Kconfig.stm32" rsource "Kconfig.numaker" rsource "Kconfig.intel_socfpga" rsource "Kconfig.npcx" +rsource "Kconfig.lpc_syscon" +rsource "Kconfig.nxp_rstctl" endif # RESET diff --git a/drivers/reset/Kconfig.lpc_syscon b/drivers/reset/Kconfig.lpc_syscon new file mode 100644 index 0000000000000..cfa6bcdd55857 --- /dev/null +++ b/drivers/reset/Kconfig.lpc_syscon @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config RESET_NXP_SYSCON + bool "NXP Syscon Reset controller driver" + default y + depends on DT_HAS_NXP_LPC_SYSCON_RESET_ENABLED + help + Enable the NXP syscon reset controller driver. + Syscon is found on LPC parts and LPC heritage parts. diff --git a/drivers/reset/Kconfig.nxp_rstctl b/drivers/reset/Kconfig.nxp_rstctl new file mode 100644 index 0000000000000..6e604b9664345 --- /dev/null +++ b/drivers/reset/Kconfig.nxp_rstctl @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config RESET_NXP_RSTCTL + bool "NXP RSTCTL driver" + default y + depends on DT_HAS_NXP_RSTCTL_ENABLED + help + Enable the driver for the NXP RSTCTL, + a peripheral reset controller. diff --git a/drivers/reset/reset_lpc_syscon.c b/drivers/reset/reset_lpc_syscon.c new file mode 100644 index 0000000000000..9effda6651898 --- /dev/null +++ b/drivers/reset/reset_lpc_syscon.c @@ -0,0 +1,65 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_lpc_syscon_reset + +#include +#include +#include + +#include + +#define LPC_RESET_OFFSET(id) (id >> 16) +#define LPC_RESET_BIT(id) (BIT(id & 0xFFFF)) + +static int reset_nxp_syscon_status(const struct device *dev, uint32_t id, uint8_t *status) +{ + const volatile uint32_t *ctrl_reg = ((uint32_t *)dev->config)+(LPC_RESET_OFFSET(id)); + *status = (uint8_t)FIELD_GET((uint32_t)LPC_RESET_BIT(id), *ctrl_reg); + + return 0; +} + +static int reset_nxp_syscon_line_assert(const struct device *dev, uint32_t id) +{ + SYSCON->PRESETCTRLSET[LPC_RESET_OFFSET(id)] = FIELD_PREP(LPC_RESET_BIT(id), 0b1); + + return 0; +} + +static int reset_nxp_syscon_line_deassert(const struct device *dev, uint32_t id) +{ + SYSCON->PRESETCTRLCLR[LPC_RESET_OFFSET(id)] = FIELD_PREP(LPC_RESET_BIT(id), 0b1); + + return 0; +} + +static int reset_nxp_syscon_line_toggle(const struct device *dev, uint32_t id) +{ + uint8_t status = 0; + + reset_nxp_syscon_line_assert(dev, id); + + do { + reset_nxp_syscon_status(dev, id, &status); + } while (status != 0b1); + + reset_nxp_syscon_line_deassert(dev, id); + + return 0; +} + +static const struct reset_driver_api reset_nxp_syscon_driver_api = { + .status = reset_nxp_syscon_status, + .line_assert = reset_nxp_syscon_line_assert, + .line_deassert = reset_nxp_syscon_line_deassert, + .line_toggle = reset_nxp_syscon_line_toggle, +}; + +DEVICE_DT_INST_DEFINE(0, NULL, NULL, NULL, + (void *)(DT_REG_ADDR(DT_INST_PARENT(0)) + 0x100), + PRE_KERNEL_1, CONFIG_RESET_INIT_PRIORITY, + &reset_nxp_syscon_driver_api); diff --git a/drivers/reset/reset_nxp_rstctl.c b/drivers/reset/reset_nxp_rstctl.c new file mode 100644 index 0000000000000..22d7cfa065088 --- /dev/null +++ b/drivers/reset/reset_nxp_rstctl.c @@ -0,0 +1,80 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_rstctl + +#include +#include +#include + +#include + +#define NXP_RSTCTL_OFFSET(id) ((id >> 16) * sizeof(uint32_t)) +#define NXP_RSTCTL_BIT(id) (BIT(id & 0xFFFF)) +#define NXP_RSTCTL_CTL(id) (NXP_RSTCTL_OFFSET(id) + 0x10) +#define NXP_RSTCTL_SET(id) (NXP_RSTCTL_OFFSET(id) + 0x40) +#define NXP_RSTCTL_CLR(id) (NXP_RSTCTL_OFFSET(id) + 0x70) + +static int reset_nxp_rstctl_status(const struct device *dev, uint32_t id, uint8_t *status) +{ + const uint32_t *base = dev->config; + volatile const uint32_t *ctl_reg = base+(NXP_RSTCTL_CTL(id)/sizeof(uint32_t)); + uint32_t val = *ctl_reg; + + *status = (uint8_t)FIELD_GET(NXP_RSTCTL_BIT(id), val); + + return 0; +} + +static int reset_nxp_rstctl_line_assert(const struct device *dev, uint32_t id) +{ + const uint32_t *base = dev->config; + volatile uint32_t *set_reg = (uint32_t *)base+(NXP_RSTCTL_SET(id)/sizeof(uint32_t)); + + *set_reg = FIELD_PREP(NXP_RSTCTL_BIT(id), 0b1); + + return 0; +} + +static int reset_nxp_rstctl_line_deassert(const struct device *dev, uint32_t id) +{ + const uint32_t *base = dev->config; + volatile uint32_t *clr_reg = (uint32_t *)base+(NXP_RSTCTL_CLR(id)/sizeof(uint32_t)); + + *clr_reg = FIELD_PREP(NXP_RSTCTL_BIT(id), 0b1); + + return 0; +} + +static int reset_nxp_rstctl_line_toggle(const struct device *dev, uint32_t id) +{ + uint8_t status = 0; + + reset_nxp_rstctl_line_assert(dev, id); + + do { + reset_nxp_rstctl_status(dev, id, &status); + } while (status != 0b1); + + reset_nxp_rstctl_line_deassert(dev, id); + + return 0; +} + +static const struct reset_driver_api reset_nxp_rstctl_driver_api = { + .status = reset_nxp_rstctl_status, + .line_assert = reset_nxp_rstctl_line_assert, + .line_deassert = reset_nxp_rstctl_line_deassert, + .line_toggle = reset_nxp_rstctl_line_toggle, +}; + +#define NXP_RSTCTL_INIT(n) \ + DEVICE_DT_INST_DEFINE(n, NULL, NULL, NULL, \ + (void *)DT_INST_REG_ADDR(n), \ + PRE_KERNEL_1, CONFIG_RESET_INIT_PRIORITY, \ + &reset_nxp_rstctl_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(NXP_RSTCTL_INIT) diff --git a/drivers/retained_mem/retained_mem_handlers.c b/drivers/retained_mem/retained_mem_handlers.c index d344e37b42c36..1d0035818576d 100644 --- a/drivers/retained_mem/retained_mem_handlers.c +++ b/drivers/retained_mem/retained_mem_handlers.c @@ -12,7 +12,7 @@ static inline ssize_t z_vrfy_retained_mem_size(const struct device *dev) K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); return z_impl_retained_mem_size(dev); } -#include +#include static inline int z_vrfy_retained_mem_read(const struct device *dev, off_t offset, uint8_t *buffer, size_t size) @@ -21,7 +21,7 @@ static inline int z_vrfy_retained_mem_read(const struct device *dev, off_t offse K_OOPS(K_SYSCALL_MEMORY_WRITE(buffer, size)); return z_impl_retained_mem_read(dev, offset, buffer, size); } -#include +#include static inline int z_vrfy_retained_mem_write(const struct device *dev, off_t offset, const uint8_t *buffer, size_t size) @@ -30,11 +30,11 @@ static inline int z_vrfy_retained_mem_write(const struct device *dev, off_t offs K_OOPS(K_SYSCALL_MEMORY_READ(buffer, size)); return z_impl_retained_mem_write(dev, offset, buffer, size); } -#include +#include static inline int z_vrfy_retained_mem_clear(const struct device *dev) { K_OOPS(K_SYSCALL_OBJ(dev, K_OBJ_DRIVER_RETAINED_MEM)); return z_impl_retained_mem_clear(dev); } -#include +#include diff --git a/drivers/rtc/CMakeLists.txt b/drivers/rtc/CMakeLists.txt index 85ff98320dd2a..eb631cd5ac117 100644 --- a/drivers/rtc/CMakeLists.txt +++ b/drivers/rtc/CMakeLists.txt @@ -20,4 +20,5 @@ zephyr_library_sources_ifdef(CONFIG_RTC_FAKE rtc_fake.c) zephyr_library_sources_ifdef(CONFIG_RTC_SMARTBOND rtc_smartbond.c) zephyr_library_sources_ifdef(CONFIG_RTC_ATMEL_SAM rtc_sam.c) zephyr_library_sources_ifdef(CONFIG_RTC_RPI_PICO rtc_rpi_pico.c) +zephyr_library_sources_ifdef(CONFIG_RTC_RV3028 rtc_rv3028.c) zephyr_library_sources_ifdef(CONFIG_RTC_NUMAKER rtc_numaker.c) diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 46bd2562dd937..8dd4034ece122 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -49,6 +49,7 @@ source "drivers/rtc/Kconfig.mc146818" source "drivers/rtc/Kconfig.pcf8523" source "drivers/rtc/Kconfig.pcf8563" source "drivers/rtc/Kconfig.rpi_pico" +source "drivers/rtc/Kconfig.rv3028" source "drivers/rtc/Kconfig.sam" source "drivers/rtc/Kconfig.smartbond" source "drivers/rtc/Kconfig.stm32" diff --git a/drivers/rtc/Kconfig.rv3028 b/drivers/rtc/Kconfig.rv3028 new file mode 100644 index 0000000000000..10cd6ca2998c7 --- /dev/null +++ b/drivers/rtc/Kconfig.rv3028 @@ -0,0 +1,10 @@ +# Copyright (c) 2024 ANITRA system s.r.o. +# SPDX-License-Identifier: Apache-2.0 + +config RTC_RV3028 + bool "Micro Crystal RV3028 I2C extreme low power RTC driver" + default y + depends on DT_HAS_MICROCRYSTAL_RV3028_ENABLED + select I2C + help + Enable the Micro Crystal RV3028 I2C RTC driver. diff --git a/drivers/rtc/rtc_handlers.c b/drivers/rtc/rtc_handlers.c index 33bb907697110..499171de3a112 100644 --- a/drivers/rtc/rtc_handlers.c +++ b/drivers/rtc/rtc_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_rtc_set_time(const struct device *dev, const struct rtc K_OOPS(K_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_set_time(dev, timeptr); } -#include +#include static inline int z_vrfy_rtc_get_time(const struct device *dev, struct rtc_time *timeptr) { @@ -21,7 +21,7 @@ static inline int z_vrfy_rtc_get_time(const struct device *dev, struct rtc_time K_OOPS(K_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_get_time(dev, timeptr); } -#include +#include #ifdef CONFIG_RTC_ALARM static inline int z_vrfy_rtc_alarm_get_supported_fields(const struct device *dev, uint16_t id, @@ -31,7 +31,7 @@ static inline int z_vrfy_rtc_alarm_get_supported_fields(const struct device *dev K_OOPS(K_SYSCALL_MEMORY_WRITE(mask, sizeof(uint16_t))); return z_impl_rtc_alarm_get_supported_fields(dev, id, mask); } -#include +#include static inline int z_vrfy_rtc_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, const struct rtc_time *timeptr) @@ -40,7 +40,7 @@ static inline int z_vrfy_rtc_alarm_set_time(const struct device *dev, uint16_t i K_OOPS(K_SYSCALL_MEMORY_READ(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_alarm_set_time(dev, id, mask, timeptr); } -#include +#include static inline int z_vrfy_rtc_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, struct rtc_time *timeptr) @@ -50,14 +50,14 @@ static inline int z_vrfy_rtc_alarm_get_time(const struct device *dev, uint16_t i K_OOPS(K_SYSCALL_MEMORY_WRITE(timeptr, sizeof(struct rtc_time))); return z_impl_rtc_alarm_get_time(dev, id, mask, timeptr); } -#include +#include static inline int z_vrfy_rtc_alarm_is_pending(const struct device *dev, uint16_t id) { K_OOPS(K_SYSCALL_DRIVER_RTC(dev, alarm_is_pending)); return z_impl_rtc_alarm_is_pending(dev, id); } -#include +#include #endif /* CONFIG_RTC_ALARM */ #ifdef CONFIG_RTC_CALIBRATION @@ -67,7 +67,7 @@ static inline int z_vrfy_rtc_set_calibration(const struct device *dev, int32_t c return z_impl_rtc_set_calibration(dev, calibration); } -#include +#include static inline int z_vrfy_rtc_get_calibration(const struct device *dev, int32_t *calibration) { @@ -75,5 +75,5 @@ static inline int z_vrfy_rtc_get_calibration(const struct device *dev, int32_t * K_OOPS(K_SYSCALL_MEMORY_WRITE(calibration, sizeof(int32_t))); return z_impl_rtc_get_calibration(dev, calibration); } -#include +#include #endif /* CONFIG_RTC_CALIBRATION */ diff --git a/drivers/rtc/rtc_ll_stm32.c b/drivers/rtc/rtc_ll_stm32.c index 1051c8fc0d1da..024669a1a9498 100644 --- a/drivers/rtc/rtc_ll_stm32.c +++ b/drivers/rtc/rtc_ll_stm32.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2023 Prevas A/S * Copyright (c) 2023 Syslinbit + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 * @@ -22,15 +23,25 @@ #include #include #include +#ifdef CONFIG_RTC_ALARM +#include +#endif /* CONFIG_RTC_ALARM */ #include +#ifdef CONFIG_RTC_ALARM +#include +#endif /* CONFIG_RTC_ALARM */ #include +#include "rtc_utils.h" + +#include "rtc_ll_stm32.h" LOG_MODULE_REGISTER(rtc_stm32, CONFIG_RTC_LOG_LEVEL); -#if defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SUBSECOND_SUPPORT) -/* subsecond counting is not supported by some STM32L1x MCUs */ +#if (defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SUBSECOND_SUPPORT)) \ + || defined(CONFIG_SOC_SERIES_STM32F2X) +/* subsecond counting is not supported by some STM32L1x MCUs (Cat.1) & by STM32F2x SoC series */ #define HW_SUBSECOND_SUPPORT (0) #else #define HW_SUBSECOND_SUPPORT (1) @@ -67,6 +78,36 @@ LOG_MODULE_REGISTER(rtc_stm32, CONFIG_RTC_LOG_LEVEL); /* Timeout in microseconds used to wait for flags */ #define RTC_TIMEOUT 1000000 +#ifdef CONFIG_RTC_ALARM +#define RTC_STM32_ALARMS_COUNT DT_INST_PROP(0, alarms_count) + +#define RTC_STM32_ALRM_A 0U +#define RTC_STM32_ALRM_B 1U + +/* Zephyr mask supported by RTC device, values from RTC_ALARM_TIME_MASK */ +#define RTC_STM32_SUPPORTED_ALARM_FIELDS \ + (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE \ + | RTC_ALARM_TIME_MASK_HOUR | RTC_ALARM_TIME_MASK_WEEKDAY \ + | RTC_ALARM_TIME_MASK_MONTHDAY) + +#if DT_INST_NODE_HAS_PROP(0, alrm_exti_line) +#define RTC_STM32_EXTI_LINE CONCAT(LL_EXTI_LINE_, DT_INST_PROP(0, alrm_exti_line)) +#else +#define RTC_STM32_EXTI_LINE 0 +#endif /* DT_INST_NODE_HAS_PROP(0, alrm_exti_line) */ +#endif /* CONFIG_RTC_ALARM */ + +#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +/* + * After system reset, the RTC registers are protected against parasitic write access by the + * DBP bit in the power control peripheral (PWR). + * Hence, DBP bit must be set in order to enable RTC registers write access. + */ +#define RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION (1) +#else +#define RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION (0) +#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPCR_DBP || PWR_DBPR_DBP */ + struct rtc_stm32_config { uint32_t async_prescaler; uint32_t sync_prescaler; @@ -76,8 +117,23 @@ struct rtc_stm32_config { #endif }; +#ifdef CONFIG_RTC_ALARM +struct rtc_stm32_alrm { + LL_RTC_AlarmTypeDef ll_rtc_alrm; + /* user-defined alarm mask, values from RTC_ALARM_TIME_MASK */ + uint16_t user_mask; + rtc_alarm_callback user_callback; + void *user_data; + bool is_pending; +}; +#endif /* CONFIG_RTC_ALARM */ + struct rtc_stm32_data { struct k_mutex lock; +#ifdef CONFIG_RTC_ALARM + struct rtc_stm32_alrm rtc_alrm_a; + struct rtc_stm32_alrm rtc_alrm_b; +#endif /* CONFIG_RTC_ALARM */ }; static int rtc_stm32_configure(const struct device *dev) @@ -126,6 +182,152 @@ static int rtc_stm32_configure(const struct device *dev) return err; } +#ifdef CONFIG_RTC_ALARM +static inline ErrorStatus rtc_stm32_init_alarm(RTC_TypeDef *rtc, uint32_t format, + LL_RTC_AlarmTypeDef *ll_alarm_struct, uint16_t id) +{ + ll_alarm_struct->AlarmDateWeekDaySel = RTC_STM32_ALRM_DATEWEEKDAYSEL_DATE; + /* + * RTC write protection is disabled & enabled again inside LL_RTC_ALMx_Init functions + * The LL_RTC_ALMx_Init does convert bin2bcd by itself + */ + if (id == RTC_STM32_ALRM_A) { + return LL_RTC_ALMA_Init(rtc, format, ll_alarm_struct); + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + return LL_RTC_ALMB_Init(rtc, format, ll_alarm_struct); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ + + return 0; +} + +static inline void rtc_stm32_clear_alarm_flag(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_ClearFlag_ALRA(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_ClearFlag_ALRB(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline uint32_t rtc_stm32_is_active_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + return LL_RTC_IsActiveFlag_ALRA(rtc); + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + return LL_RTC_IsActiveFlag_ALRB(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ + + return 0; +} + +static inline void rtc_stm32_enable_interrupt_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_EnableIT_ALRA(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_EnableIT_ALRB(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline void rtc_stm32_disable_interrupt_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_DisableIT_ALRA(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_DisableIT_ALRB(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline void rtc_stm32_enable_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_ALMA_Enable(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_ALMB_Enable(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline void rtc_stm32_disable_alarm(RTC_TypeDef *rtc, uint16_t id) +{ + if (id == RTC_STM32_ALRM_A) { + LL_RTC_ALMA_Disable(rtc); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + LL_RTC_ALMB_Disable(rtc); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +void rtc_stm32_isr(const struct device *dev) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + int id = 0; + +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_EnableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + + for (id = 0; id < RTC_STM32_ALARMS_COUNT; id++) { + if (rtc_stm32_is_active_alarm(RTC, (uint16_t)id) != 0) { + LL_RTC_DisableWriteProtection(RTC); + rtc_stm32_clear_alarm_flag(RTC, (uint16_t)id); + LL_RTC_EnableWriteProtection(RTC); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else { + p_rtc_alrm = &(data->rtc_alrm_b); + } + + p_rtc_alrm->is_pending = true; + + if (p_rtc_alrm->user_callback != NULL) { + p_rtc_alrm->user_callback(dev, (uint16_t)id, p_rtc_alrm->user_data); + } + } + } + +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_DisableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + + ll_func_exti_clear_rtc_alarm_flag(RTC_STM32_EXTI_LINE); +} + +static void rtc_stm32_irq_config(const struct device *dev) +{ + IRQ_CONNECT(DT_INST_IRQN(0), + DT_INST_IRQ(0, priority), + rtc_stm32_isr, DEVICE_DT_INST_GET(0), 0); + irq_enable(DT_INST_IRQN(0)); +} +#endif /* CONFIG_RTC_ALARM */ + static int rtc_stm32_init(const struct device *dev) { const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); @@ -148,9 +350,9 @@ static int rtc_stm32_init(const struct device *dev) k_mutex_init(&data->lock); /* Enable Backup access */ -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_EnableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ /* Enable RTC clock source */ if (clock_control_configure(clk, (clock_control_subsys_t)&cfg->pclken[1], NULL) != 0) { @@ -158,17 +360,34 @@ static int rtc_stm32_init(const struct device *dev) return -EIO; } +/* + * On STM32WBAX series, there is no bit in BCDR register to enable RTC. + * Enabling RTC is done directly via the RCC APB register bit. + */ +#ifndef CONFIG_SOC_SERIES_STM32WBAX z_stm32_hsem_lock(CFG_HW_RCC_SEMID, HSEM_LOCK_DEFAULT_RETRY); LL_RCC_EnableRTC(); z_stm32_hsem_unlock(CFG_HW_RCC_SEMID); +#endif /* CONFIG_SOC_SERIES_STM32WBAX */ err = rtc_stm32_configure(dev); -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_DisableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + +#ifdef CONFIG_RTC_ALARM + rtc_stm32_irq_config(dev); + + ll_func_exti_enable_rtc_alarm_it(RTC_STM32_EXTI_LINE); + + k_mutex_lock(&data->lock, K_FOREVER); + memset(&(data->rtc_alrm_a), 0, sizeof(struct rtc_stm32_alrm)); + memset(&(data->rtc_alrm_b), 0, sizeof(struct rtc_stm32_alrm)); + k_mutex_unlock(&data->lock); +#endif /* CONFIG_RTC_ALARM */ return err; } @@ -176,9 +395,9 @@ static int rtc_stm32_init(const struct device *dev) static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *timeptr) { struct rtc_stm32_data *data = dev->data; - + LL_RTC_TimeTypeDef rtc_time; + LL_RTC_DateTypeDef rtc_date; uint32_t real_year = timeptr->tm_year + TM_YEAR_REF; - int err = 0; if (real_year < RTC_YEAR_REF) { @@ -196,51 +415,53 @@ static int rtc_stm32_set_time(const struct device *dev, const struct rtc_time *t return err; } - LOG_INF("Setting clock"); + LOG_DBG("Setting clock"); -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_EnableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ - - LL_RTC_DisableWriteProtection(RTC); - - ErrorStatus status = LL_RTC_EnterInitMode(RTC); - - if (status != SUCCESS) { -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) - LL_PWR_DisableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ - k_mutex_unlock(&data->lock); - return -EIO; - } +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + + /* Enter Init mode inside the LL_RTC_Time and Date Init functions */ + rtc_time.Hours = bin2bcd(timeptr->tm_hour); + rtc_time.Minutes = bin2bcd(timeptr->tm_min); + rtc_time.Seconds = bin2bcd(timeptr->tm_sec); + LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BCD, &rtc_time); + + /* Set Date after Time to be sure the DR is correctly updated on stm32F2 serie. */ + rtc_date.Year = bin2bcd((real_year - RTC_YEAR_REF)); + rtc_date.Month = bin2bcd((timeptr->tm_mon + 1)); + rtc_date.Day = bin2bcd(timeptr->tm_mday); + rtc_date.WeekDay = ((timeptr->tm_wday == 0) ? (LL_RTC_WEEKDAY_SUNDAY) : (timeptr->tm_wday)); + /* WeekDay sunday (tm_wday = 0) is not represented by the same value in hardware, + * all the other values are consistent with what is expected by hardware. + */ + LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BCD, &rtc_date); - LL_RTC_DATE_SetYear(RTC, bin2bcd(real_year - RTC_YEAR_REF)); - LL_RTC_DATE_SetMonth(RTC, bin2bcd(timeptr->tm_mon + 1)); - LL_RTC_DATE_SetDay(RTC, bin2bcd(timeptr->tm_mday)); +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_DisableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ - if (timeptr->tm_wday == 0) { - /* sunday (tm_wday = 0) is not represented by the same value in hardware */ - LL_RTC_DATE_SetWeekDay(RTC, LL_RTC_WEEKDAY_SUNDAY); - } else { - /* all the other values are consistent with what is expected by hardware */ - LL_RTC_DATE_SetWeekDay(RTC, timeptr->tm_wday); +#ifdef CONFIG_SOC_SERIES_STM32F2X + /* + * Because stm32F2 serie has no shadow registers, + * wait until TR and DR registers are synchronised : flag RS + */ + while (LL_RTC_IsActiveFlag_RS(RTC) != 1) { + ; } - - - LL_RTC_TIME_SetHour(RTC, bin2bcd(timeptr->tm_hour)); - LL_RTC_TIME_SetMinute(RTC, bin2bcd(timeptr->tm_min)); - LL_RTC_TIME_SetSecond(RTC, bin2bcd(timeptr->tm_sec)); - - LL_RTC_DisableInitMode(RTC); - - LL_RTC_EnableWriteProtection(RTC); - -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) - LL_PWR_DisableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* CONFIG_SOC_SERIES_STM32F2X */ k_mutex_unlock(&data->lock); + LOG_DBG("Calendar set : %d/%d/%d - %dh%dm%ds", + LL_RTC_DATE_GetDay(RTC), + LL_RTC_DATE_GetMonth(RTC), + LL_RTC_DATE_GetYear(RTC), + LL_RTC_TIME_GetHour(RTC), + LL_RTC_TIME_GetMinute(RTC), + LL_RTC_TIME_GetSecond(RTC) + ); + return err; } @@ -253,7 +474,12 @@ static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr #if HW_SUBSECOND_SUPPORT const struct rtc_stm32_config *cfg = dev->config; uint32_t rtc_subsecond; -#endif +#endif /* HW_SUBSECOND_SUPPORT */ + + if (timeptr == NULL) { + LOG_ERR("NULL rtc_time pointer"); + return -EINVAL; + } int err = k_mutex_lock(&data->lock, K_NO_WAIT); @@ -282,13 +508,14 @@ static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr rtc_time = LL_RTC_TIME_Get(RTC); #if HW_SUBSECOND_SUPPORT rtc_subsecond = LL_RTC_TIME_GetSubSecond(RTC); -#endif +#endif /* HW_SUBSECOND_SUPPORT */ } while (rtc_time != LL_RTC_TIME_Get(RTC)); } while (rtc_date != LL_RTC_DATE_Get(RTC)); k_mutex_unlock(&data->lock); - timeptr->tm_year = bcd2bin(__LL_RTC_GET_YEAR(rtc_date)) + RTC_YEAR_REF - TM_YEAR_REF; + /* tm_year is the value since 1900 and Rtc year is from 2000 */ + timeptr->tm_year = bcd2bin(__LL_RTC_GET_YEAR(rtc_date)) + (RTC_YEAR_REF - TM_YEAR_REF); /* tm_mon allowed values are 0-11 */ timeptr->tm_mon = bcd2bin(__LL_RTC_GET_MONTH(rtc_date)) - 1; timeptr->tm_mday = bcd2bin(__LL_RTC_GET_DAY(rtc_date)); @@ -314,14 +541,419 @@ static int rtc_stm32_get_time(const struct device *dev, struct rtc_time *timeptr #else timeptr->tm_nsec = 0; #endif - /* unknown values */ timeptr->tm_yday = -1; timeptr->tm_isdst = -1; + /* __LL_RTC_GET_YEAR(rtc_date)is the real year (from 2000) */ + LOG_DBG("Calendar get : %d/%d/%d - %dh%dm%ds", + timeptr->tm_mday, + timeptr->tm_mon, + __LL_RTC_GET_YEAR(rtc_date), + timeptr->tm_hour, + timeptr->tm_min, + timeptr->tm_sec); + + return 0; +} + +#ifdef CONFIG_RTC_ALARM +static void rtc_stm32_init_ll_alrm_struct(LL_RTC_AlarmTypeDef *p_rtc_alarm, + const struct rtc_time *timeptr, uint16_t mask) +{ + LL_RTC_TimeTypeDef *p_rtc_alrm_time = &(p_rtc_alarm->AlarmTime); + uint32_t ll_mask = 0; + + /* + * STM32 RTC Alarm LL mask should be set for all fields beyond the broadest one + * that's being matched with RTC calendar to trigger alarm periodically, + * the opposite of Zephyr RTC Alarm mask which is set for active fields. + */ + ll_mask = RTC_STM32_ALRM_MASK_ALL; + + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + ll_mask &= ~RTC_STM32_ALRM_MASK_SECONDS; + p_rtc_alrm_time->Seconds = bin2bcd(timeptr->tm_sec); + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + ll_mask &= ~RTC_STM32_ALRM_MASK_MINUTES; + p_rtc_alrm_time->Minutes = bin2bcd(timeptr->tm_min); + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + ll_mask &= ~RTC_STM32_ALRM_MASK_HOURS; + p_rtc_alrm_time->Hours = bin2bcd(timeptr->tm_hour); + } + + if (mask & RTC_ALARM_TIME_MASK_WEEKDAY) { + /* the Alarm Mask field compares with the day of the week */ + ll_mask &= ~RTC_STM32_ALRM_MASK_DATEWEEKDAY; + p_rtc_alarm->AlarmDateWeekDaySel = RTC_STM32_ALRM_DATEWEEKDAYSEL_WEEKDAY; + + if (timeptr->tm_wday == 0) { + /* sunday (tm_wday = 0) is not represented by the same value in hardware */ + p_rtc_alarm->AlarmDateWeekDay = LL_RTC_WEEKDAY_SUNDAY; + } else { + /* all the other values are consistent with what is expected by hardware */ + p_rtc_alarm->AlarmDateWeekDay = bin2bcd(timeptr->tm_wday); + } + + } else if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + /* the Alarm compares with the day number & ignores the day of the week */ + ll_mask &= ~RTC_STM32_ALRM_MASK_DATEWEEKDAY; + p_rtc_alarm->AlarmDateWeekDaySel = RTC_STM32_ALRM_DATEWEEKDAYSEL_DATE; + p_rtc_alarm->AlarmDateWeekDay = bin2bcd(timeptr->tm_mday); + } + + p_rtc_alrm_time->TimeFormat = LL_RTC_TIME_FORMAT_AM_OR_24; + + p_rtc_alarm->AlarmMask = ll_mask; +} + +static inline void rtc_stm32_get_ll_alrm_time(uint16_t id, struct rtc_time *timeptr) +{ + if (id == RTC_STM32_ALRM_A) { + timeptr->tm_sec = bcd2bin(LL_RTC_ALMA_GetSecond(RTC)); + timeptr->tm_min = bcd2bin(LL_RTC_ALMA_GetMinute(RTC)); + timeptr->tm_hour = bcd2bin(LL_RTC_ALMA_GetHour(RTC)); + timeptr->tm_wday = bcd2bin(LL_RTC_ALMA_GetWeekDay(RTC)); + timeptr->tm_mday = bcd2bin(LL_RTC_ALMA_GetDay(RTC)); + return; + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + timeptr->tm_sec = bcd2bin(LL_RTC_ALMB_GetSecond(RTC)); + timeptr->tm_min = bcd2bin(LL_RTC_ALMB_GetMinute(RTC)); + timeptr->tm_hour = bcd2bin(LL_RTC_ALMB_GetHour(RTC)); + timeptr->tm_wday = bcd2bin(LL_RTC_ALMB_GetWeekDay(RTC)); + timeptr->tm_mday = bcd2bin(LL_RTC_ALMB_GetDay(RTC)); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ +} + +static inline uint16_t rtc_stm32_get_ll_alrm_mask(uint16_t id) +{ + uint32_t ll_alarm_mask = 0; + uint16_t zephyr_alarm_mask = 0; + uint32_t week_day = 0; + + /* + * STM32 RTC Alarm LL mask is set for all fields beyond the broadest one + * that's being matched with RTC calendar to trigger alarm periodically, + * the opposite of Zephyr RTC Alarm mask which is set for active fields. + */ + + if (id == RTC_STM32_ALRM_A) { + ll_alarm_mask = LL_RTC_ALMA_GetMask(RTC); + } + +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + ll_alarm_mask = LL_RTC_ALMB_GetMask(RTC); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ + + if ((ll_alarm_mask & RTC_STM32_ALRM_MASK_SECONDS) == 0x0) { + zephyr_alarm_mask = RTC_ALARM_TIME_MASK_SECOND; + } + if ((ll_alarm_mask & RTC_STM32_ALRM_MASK_MINUTES) == 0x0) { + zephyr_alarm_mask |= RTC_ALARM_TIME_MASK_MINUTE; + } + if ((ll_alarm_mask & RTC_STM32_ALRM_MASK_HOURS) == 0x0) { + zephyr_alarm_mask |= RTC_ALARM_TIME_MASK_HOUR; + } + if ((ll_alarm_mask & RTC_STM32_ALRM_MASK_DATEWEEKDAY) == 0x0) { + if (id == RTC_STM32_ALRM_A) { + week_day = LL_RTC_ALMA_GetWeekDay(RTC); + } +#if RTC_STM32_ALARMS_COUNT > 1 + if (id == RTC_STM32_ALRM_B) { + week_day = LL_RTC_ALMB_GetWeekDay(RTC); + } +#endif /* RTC_STM32_ALARMS_COUNT > 1 */ + if (week_day) { + zephyr_alarm_mask |= RTC_ALARM_TIME_MASK_WEEKDAY; + } else { + zephyr_alarm_mask |= RTC_ALARM_TIME_MASK_MONTHDAY; + } + } + + return zephyr_alarm_mask; +} + +static int rtc_stm32_alarm_get_supported_fields(const struct device *dev, uint16_t id, + uint16_t *mask) +{ + if (mask == NULL) { + LOG_ERR("NULL mask pointer"); + return -EINVAL; + } + + if ((id != RTC_STM32_ALRM_A) && (id != RTC_STM32_ALRM_B)) { + LOG_ERR("invalid alarm ID %d", id); + return -EINVAL; + } + + *mask = (uint16_t)RTC_STM32_SUPPORTED_ALARM_FIELDS; + return 0; } +static int rtc_stm32_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, + struct rtc_time *timeptr) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + LL_RTC_AlarmTypeDef *p_ll_rtc_alarm; + LL_RTC_TimeTypeDef *p_ll_rtc_alrm_time; + int err = 0; + + if ((mask == NULL) || (timeptr == NULL)) { + LOG_ERR("NULL pointer"); + return -EINVAL; + } + + k_mutex_lock(&data->lock, K_FOREVER); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else if (id == RTC_STM32_ALRM_B) { + p_rtc_alrm = &(data->rtc_alrm_b); + } else { + LOG_ERR("invalid alarm ID %d", id); + err = -EINVAL; + goto unlock; + } + + p_ll_rtc_alarm = &(p_rtc_alrm->ll_rtc_alrm); + p_ll_rtc_alrm_time = &(p_ll_rtc_alarm->AlarmTime); + + memset(timeptr, -1, sizeof(struct rtc_time)); + + rtc_stm32_get_ll_alrm_time(id, timeptr); + + p_rtc_alrm->user_mask = rtc_stm32_get_ll_alrm_mask(id); + + *mask = p_rtc_alrm->user_mask; + + LOG_DBG("get alarm: mday = %d, wday = %d, hour = %d, min = %d, sec = %d, " + "mask = 0x%04x", timeptr->tm_mday, timeptr->tm_wday, timeptr->tm_hour, + timeptr->tm_min, timeptr->tm_sec, *mask); + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +static int rtc_stm32_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, + const struct rtc_time *timeptr) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + LL_RTC_AlarmTypeDef *p_ll_rtc_alarm; + LL_RTC_TimeTypeDef *p_ll_rtc_alrm_time; + int err = 0; + + k_mutex_lock(&data->lock, K_FOREVER); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else if (id == RTC_STM32_ALRM_B) { + p_rtc_alrm = &(data->rtc_alrm_b); + } else { + LOG_ERR("invalid alarm ID %d", id); + err = -EINVAL; + goto unlock; + } + + if ((mask == 0) && (timeptr == NULL)) { + memset(&(p_rtc_alrm->ll_rtc_alrm), 0, sizeof(LL_RTC_AlarmTypeDef)); + p_rtc_alrm->user_callback = NULL; + p_rtc_alrm->user_data = NULL; + p_rtc_alrm->is_pending = false; +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_EnableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + if (rtc_stm32_is_active_alarm(RTC, id)) { + LL_RTC_DisableWriteProtection(RTC); + rtc_stm32_disable_alarm(RTC, id); + rtc_stm32_disable_interrupt_alarm(RTC, id); + LL_RTC_EnableWriteProtection(RTC); + } + LOG_DBG("Alarm %d has been disabled", id); + goto disable_bkup_access; + } + + if ((mask & ~RTC_STM32_SUPPORTED_ALARM_FIELDS) != 0) { + LOG_ERR("unsupported alarm %d field mask 0x%04x", id, mask); + err = -EINVAL; + goto unlock; + } + + if (timeptr == NULL) { + LOG_ERR("timeptr is invalid"); + err = -EINVAL; + goto unlock; + } + + if (!rtc_utils_validate_rtc_time(timeptr, mask)) { + LOG_DBG("One or multiple time values are invalid"); + err = -EINVAL; + goto unlock; + } + + p_ll_rtc_alarm = &(p_rtc_alrm->ll_rtc_alrm); + p_ll_rtc_alrm_time = &(p_ll_rtc_alarm->AlarmTime); + + memset(p_ll_rtc_alrm_time, 0, sizeof(LL_RTC_TimeTypeDef)); + rtc_stm32_init_ll_alrm_struct(p_ll_rtc_alarm, timeptr, mask); + + p_rtc_alrm->user_mask = mask; + + LOG_DBG("set alarm %d : second = %d, min = %d, hour = %d," + " wday = %d, mday = %d, mask = 0x%04x", + id, timeptr->tm_sec, timeptr->tm_min, timeptr->tm_hour, + timeptr->tm_wday, timeptr->tm_mday, mask); + +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_EnableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTC); + + /* Disable ALARM so that the RTC_ISR_ALRAWF/RTC_ISR_ALRBWF is 0 */ + rtc_stm32_disable_alarm(RTC, id); + rtc_stm32_disable_interrupt_alarm(RTC, id); + +#ifdef RTC_ISR_ALRAWF + if (id == RTC_STM32_ALRM_A) { + /* Wait till RTC ALRAWF flag is set before writing to RTC registers */ + while (!LL_RTC_IsActiveFlag_ALRAW(RTC)) { + ; + } + } +#endif /* RTC_ISR_ALRAWF */ + +#ifdef RTC_ISR_ALRBWF + if (id == RTC_STM32_ALRM_B) { + /* Wait till RTC ALRBWF flag is set before writing to RTC registers */ + while (!LL_RTC_IsActiveFlag_ALRBW(RTC)) { + ; + } + } +#endif /* RTC_ISR_ALRBWF */ + + /* init Alarm */ + /* write protection is disabled & enabled again inside the LL_RTC_ALMx_Init function */ + if (rtc_stm32_init_alarm(RTC, LL_RTC_FORMAT_BCD, p_ll_rtc_alarm, id) != SUCCESS) { + LOG_ERR("Could not initialize Alarm %d", id); + err = -ECANCELED; + goto disable_bkup_access; + } + + /* Disable the write protection for RTC registers */ + LL_RTC_DisableWriteProtection(RTC); + + /* Enable Alarm */ + rtc_stm32_enable_alarm(RTC, id); + /* Clear Alarm flag */ + rtc_stm32_clear_alarm_flag(RTC, id); + /* Enable Alarm IT */ + rtc_stm32_enable_interrupt_alarm(RTC, id); + + ll_func_exti_enable_rtc_alarm_it(RTC_STM32_EXTI_LINE); + + /* Enable the write protection for RTC registers */ + LL_RTC_EnableWriteProtection(RTC); + +disable_bkup_access: +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION + LL_PWR_DisableBkUpAccess(); +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ + +unlock: + k_mutex_unlock(&data->lock); + + if (id == RTC_STM32_ALRM_A) { + LOG_DBG("Alarm A : %dh%dm%ds mask = 0x%x", + LL_RTC_ALMA_GetHour(RTC), + LL_RTC_ALMA_GetMinute(RTC), + LL_RTC_ALMA_GetSecond(RTC), + LL_RTC_ALMA_GetMask(RTC)); + } +#ifdef RTC_ALARM_B + if (id == RTC_STM32_ALRM_B) { + LOG_DBG("Alarm B : %dh%dm%ds mask = 0x%x", + LL_RTC_ALMB_GetHour(RTC), + LL_RTC_ALMB_GetMinute(RTC), + LL_RTC_ALMB_GetSecond(RTC), + LL_RTC_ALMB_GetMask(RTC)); + } +#endif /* #ifdef RTC_ALARM_B */ + return err; +} + +static int rtc_stm32_alarm_set_callback(const struct device *dev, uint16_t id, + rtc_alarm_callback callback, void *user_data) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + int err = 0; + + k_mutex_lock(&data->lock, K_FOREVER); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else if (id == RTC_STM32_ALRM_B) { + p_rtc_alrm = &(data->rtc_alrm_b); + } else { + LOG_ERR("invalid alarm ID %d", id); + err = -EINVAL; + goto unlock; + } + + /* Passing the callback function and userdata filled by the user */ + p_rtc_alrm->user_callback = callback; + p_rtc_alrm->user_data = user_data; + +unlock: + k_mutex_unlock(&data->lock); + + return err; +} + +static int rtc_stm32_alarm_is_pending(const struct device *dev, uint16_t id) +{ + struct rtc_stm32_data *data = dev->data; + struct rtc_stm32_alrm *p_rtc_alrm; + int ret = 0; + + k_mutex_lock(&data->lock, K_FOREVER); + + if (id == RTC_STM32_ALRM_A) { + p_rtc_alrm = &(data->rtc_alrm_a); + } else if (id == RTC_STM32_ALRM_B) { + p_rtc_alrm = &(data->rtc_alrm_b); + } else { + LOG_ERR("invalid alarm ID %d", id); + ret = -EINVAL; + goto unlock; + } + + __disable_irq(); + ret = p_rtc_alrm->is_pending ? 1 : 0; + p_rtc_alrm->is_pending = false; + __enable_irq(); + +unlock: + k_mutex_unlock(&data->lock); + return ret; +} +#endif /* CONFIG_RTC_ALARM */ + #ifdef CONFIG_RTC_CALIBRATION #if !defined(CONFIG_SOC_SERIES_STM32F2X) && \ !(defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SMOOTHCALIB_SUPPORT)) @@ -361,9 +993,9 @@ static int rtc_stm32_set_calibration(const struct device *dev, int32_t calibrati return -EIO; } -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_EnableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ LL_RTC_DisableWriteProtection(RTC); @@ -371,9 +1003,9 @@ static int rtc_stm32_set_calibration(const struct device *dev, int32_t calibrati LL_RTC_EnableWriteProtection(RTC); -#if defined(PWR_CR_DBP) || defined(PWR_CR1_DBP) || defined(PWR_DBPCR_DBP) || defined(PWR_DBPR_DBP) +#if RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION LL_PWR_DisableBkUpAccess(); -#endif /* PWR_CR_DBP || PWR_CR1_DBP || PWR_DBPR_DBP */ +#endif /* RTC_STM32_BACKUP_DOMAIN_WRITE_PROTECTION */ return 0; } @@ -403,8 +1035,13 @@ static int rtc_stm32_get_calibration(const struct device *dev, int32_t *calibrat static const struct rtc_driver_api rtc_stm32_driver_api = { .set_time = rtc_stm32_set_time, .get_time = rtc_stm32_get_time, - /* RTC_ALARM not supported */ - /* RTC_UPDATE not supported */ +#ifdef CONFIG_RTC_ALARM + .alarm_get_supported_fields = rtc_stm32_alarm_get_supported_fields, + .alarm_set_time = rtc_stm32_alarm_set_time, + .alarm_get_time = rtc_stm32_alarm_get_time, + .alarm_set_callback = rtc_stm32_alarm_set_callback, + .alarm_is_pending = rtc_stm32_alarm_is_pending, +#endif /* CONFIG_RTC_ALARM */ #ifdef CONFIG_RTC_CALIBRATION #if !defined(CONFIG_SOC_SERIES_STM32F2X) && \ !(defined(CONFIG_SOC_SERIES_STM32L1X) && !defined(RTC_SMOOTHCALIB_SUPPORT)) diff --git a/drivers/rtc/rtc_ll_stm32.h b/drivers/rtc/rtc_ll_stm32.h new file mode 100644 index 0000000000000..16f381081c174 --- /dev/null +++ b/drivers/rtc/rtc_ll_stm32.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_RTC_RTC_LL_STM32_H_ +#define ZEPHYR_DRIVERS_RTC_RTC_LL_STM32_H_ + +#ifdef CONFIG_RTC_ALARM + +/* STM32 RTC alarms, A & B, LL masks are equal */ +#define RTC_STM32_ALRM_MASK_ALL LL_RTC_ALMA_MASK_ALL +#define RTC_STM32_ALRM_MASK_SECONDS LL_RTC_ALMA_MASK_SECONDS +#define RTC_STM32_ALRM_MASK_MINUTES LL_RTC_ALMA_MASK_MINUTES +#define RTC_STM32_ALRM_MASK_HOURS LL_RTC_ALMA_MASK_HOURS +#define RTC_STM32_ALRM_MASK_DATEWEEKDAY LL_RTC_ALMA_MASK_DATEWEEKDAY + +#define RTC_STM32_ALRM_DATEWEEKDAYSEL_WEEKDAY LL_RTC_ALMA_DATEWEEKDAYSEL_WEEKDAY +#define RTC_STM32_ALRM_DATEWEEKDAYSEL_DATE LL_RTC_ALMA_DATEWEEKDAYSEL_DATE + +static inline void ll_func_exti_enable_rtc_alarm_it(uint32_t exti_line) +{ +#if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) + LL_C2_EXTI_EnableIT_0_31(exti_line); + LL_EXTI_EnableRisingTrig_0_31(exti_line); +#elif defined(CONFIG_SOC_SERIES_STM32U5X) || defined(CONFIG_SOC_SERIES_STM32WBAX) + /* in STM32U5 & STM32WBAX series, RTC Alarm event is not routed to EXTI */ +#else + LL_EXTI_EnableIT_0_31(exti_line); + LL_EXTI_EnableRisingTrig_0_31(exti_line); +#endif /* CONFIG_SOC_SERIES_STM32H7X and CONFIG_CPU_CORTEX_M4 */ +} + +static inline void ll_func_exti_clear_rtc_alarm_flag(uint32_t exti_line) +{ +#if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4) + LL_C2_EXTI_ClearFlag_0_31(exti_line); +#elif defined(CONFIG_SOC_SERIES_STM32U5X) || defined(CONFIG_SOC_SERIES_STM32WBAX) + /* in STM32U5 & STM32WBAX series, RTC Alarm event is not routed to EXTI */ +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti) + LL_EXTI_ClearRisingFlag_0_31(exti_line); +#else + LL_EXTI_ClearFlag_0_31(exti_line); +#endif /* CONFIG_SOC_SERIES_STM32H7X and CONFIG_CPU_CORTEX_M4 */ +} +#endif /* CONFIG_RTC_ALARM */ + +#endif /* ZEPHYR_DRIVERS_RTC_RTC_LL_STM32_H_ */ diff --git a/drivers/rtc/rtc_mc146818.c b/drivers/rtc/rtc_mc146818.c index 15d36c623b094..66257cf8d7461 100644 --- a/drivers/rtc/rtc_mc146818.c +++ b/drivers/rtc/rtc_mc146818.c @@ -377,13 +377,13 @@ static int rtc_mc146818_alarm_get_time(const struct device *dev, uint16_t id, ui } value = rtc_read(RTC_ALARM_MIN); - if (value <= MAX_SEC) { + if (value <= MAX_MIN) { timeptr->tm_min = value; (*mask) |= RTC_ALARM_TIME_MASK_MINUTE; } value = rtc_read(RTC_ALARM_HOUR); - if (value <= MAX_SEC) { + if (value <= MAX_HOUR) { timeptr->tm_hour = value; (*mask) |= RTC_ALARM_TIME_MASK_HOUR; } diff --git a/drivers/rtc/rtc_rv3028.c b/drivers/rtc/rtc_rv3028.c new file mode 100644 index 0000000000000..da220bef68659 --- /dev/null +++ b/drivers/rtc/rtc_rv3028.c @@ -0,0 +1,986 @@ +/* + * Copyright (c) 2024 ANITRA system s.r.o. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT microcrystal_rv3028 + +#include +#include +#include +#include +#include +#include +#include "rtc_utils.h" + +LOG_MODULE_REGISTER(rv3028, CONFIG_RTC_LOG_LEVEL); + +/* RV3028 RAM register addresses */ +#define RV3028_REG_SECONDS 0x00 +#define RV3028_REG_MINUTES 0x01 +#define RV3028_REG_HOURS 0x02 +#define RV3028_REG_WEEKDAY 0x03 +#define RV3028_REG_DATE 0x04 +#define RV3028_REG_MONTH 0x05 +#define RV3028_REG_YEAR 0x06 +#define RV3028_REG_ALARM_MINUTES 0x07 +#define RV3028_REG_ALARM_HOURS 0x08 +#define RV3028_REG_ALARM_WEEKDAY 0x09 +#define RV3028_REG_STATUS 0x0E +#define RV3028_REG_CONTROL1 0x0F +#define RV3028_REG_CONTROL2 0x10 +#define RV3028_REG_EVENT_CONTROL 0x13 +#define RV3028_REG_TS_COUNT 0x14 +#define RV3028_REG_TS_SECONDS 0x15 +#define RV3028_REG_TS_MINUTES 0x16 +#define RV3028_REG_TS_HOURS 0x17 +#define RV3028_REG_TS_DATE 0x18 +#define RV3028_REG_TS_MONTH 0x19 +#define RV3028_REG_TS_YEAR 0x1A +#define RV3028_REG_UNIXTIME0 0x1B +#define RV3028_REG_UNIXTIME1 0x1C +#define RV3028_REG_UNIXTIME2 0x1D +#define RV3028_REG_UNIXTIME3 0x1E +#define RV3028_REG_USER_RAM1 0x1F +#define RV3028_REG_USER_RAM2 0x20 +#define RV3028_REG_EEPROM_ADDRESS 0x25 +#define RV3028_REG_EEPROM_DATA 0x26 +#define RV3028_REG_EEPROM_COMMAND 0x27 +#define RV3028_REG_ID 0x28 +#define RV3028_REG_CLKOUT 0x35 +#define RV3028_REG_OFFSET 0x36 +#define RV3028_REG_BACKUP 0x37 + +#define RV3028_CONTROL1_TD BIT(0) +#define RV3028_CONTROL1_TE GENMASK(2, 1) +#define RV3028_CONTROL1_EERD BIT(3) +#define RV3028_CONTROL1_USEL BIT(4) +#define RV3028_CONTROL1_WADA BIT(5) +#define RV3028_CONTROL1_TRPT BIT(7) + +#define RV3028_CONTROL2_RESET BIT(0) +#define RV3028_CONTROL2_12_24 BIT(1) +#define RV3028_CONTROL2_EIE BIT(2) +#define RV3028_CONTROL2_AIE BIT(3) +#define RV3028_CONTROL2_TIE BIT(4) +#define RV3028_CONTROL2_UIE BIT(5) +#define RV3028_CONTROL2_TSE BIT(7) + +#define RV3028_STATUS_PORF BIT(0) +#define RV3028_STATUS_EVF BIT(1) +#define RV3028_STATUS_AF BIT(2) +#define RV3028_STATUS_TF BIT(3) +#define RV3028_STATUS_UF BIT(4) +#define RV3028_STATUS_BSF BIT(5) +#define RV3028_STATUS_CLKF BIT(6) +#define RV3028_STATUS_EEBUSY BIT(7) + +#define RV3028_CLKOUT_FD GENMASK(2, 0) +#define RV3028_CLKOUT_PORIE BIT(3) +#define RV3028_CLKOUT_CLKSY BIT(6) +#define RV3028_CLKOUT_CLKOE BIT(7) + +#define RV3028_CLKOUT_FD_LOW 0x7 + +#define RV3028_BACKUP_TCE BIT(5) +#define RV3028_BACKUP_TCR GENMASK(1, 0) +#define RV3028_BACKUP_BSM GENMASK(3, 2) + +#define RV3028_BSM_LEVEL 0x3 +#define RV3028_BSM_DIRECT 0x1 +#define RV3028_BSM_DISABLED 0x0 + +/* RV3028 EE command register values */ +#define RV3028_EEPROM_CMD_INIT 0x00 +#define RV3028_EEPROM_CMD_UPDATE 0x11 +#define RV3028_EEPROM_CMD_REFRESH 0x12 +#define RV3028_EEPROM_CMD_WRITE 0x21 +#define RV3028_EEPROM_CMD_READ 0x22 + +#define RV3028_SECONDS_MASK GENMASK(6, 0) +#define RV3028_MINUTES_MASK GENMASK(6, 0) +#define RV3028_HOURS_AMPM BIT(5) +#define RV3028_HOURS_12H_MASK GENMASK(4, 0) +#define RV3028_HOURS_24H_MASK GENMASK(5, 0) +#define RV3028_DATE_MASK GENMASK(5, 0) +#define RV3028_WEEKDAY_MASK GENMASK(2, 0) +#define RV3028_MONTH_MASK GENMASK(4, 0) +#define RV3028_YEAR_MASK GENMASK(7, 0) + +#define RV3028_ALARM_MINUTES_AE_M BIT(7) +#define RV3028_ALARM_MINUTES_MASK GENMASK(6, 0) +#define RV3028_ALARM_HOURS_AE_H BIT(7) +#define RV3028_ALARM_HOURS_AMPM BIT(5) +#define RV3028_ALARM_HOURS_12H_MASK GENMASK(4, 0) +#define RV3028_ALARM_HOURS_24H_MASK GENMASK(5, 0) +#define RV3028_ALARM_DATE_AE_WD BIT(7) +#define RV3028_ALARM_DATE_MASK GENMASK(5, 0) + +/* The RV3028 only supports two-digit years. Leap years are correctly handled from 2000 to 2099 */ +#define RV3028_YEAR_OFFSET (2000 - 1900) + +/* The RV3028 enumerates months 1 to 12 */ +#define RV3028_MONTH_OFFSET 1 + +#define RV3028_EEBUSY_POLL_US 10000 +#define RV3028_EEBUSY_TIMEOUT_MS 100 + +/* RTC alarm time fields supported by the RV3028 */ +#define RV3028_RTC_ALARM_TIME_MASK \ + (RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | RTC_ALARM_TIME_MASK_MONTHDAY) + +/* RTC time fields supported by the RV3028 */ +#define RV3028_RTC_TIME_MASK \ + (RTC_ALARM_TIME_MASK_SECOND | RTC_ALARM_TIME_MASK_MINUTE | RTC_ALARM_TIME_MASK_HOUR | \ + RTC_ALARM_TIME_MASK_MONTH | RTC_ALARM_TIME_MASK_YEAR) + +/* Helper macro to guard int-gpios related code */ +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(int_gpios) && \ + (defined(CONFIG_RTC_ALARM) || defined(CONFIG_RTC_UPDATE)) +#define RV3028_INT_GPIOS_IN_USE 1 +#endif + +struct rv3028_config { + const struct i2c_dt_spec i2c; +#ifdef RV3028_INT_GPIOS_IN_USE + struct gpio_dt_spec gpio_int; +#endif /* RV3028_INT_GPIOS_IN_USE */ + uint8_t cof; + uint8_t backup; +}; + +struct rv3028_data { + struct k_sem lock; +#if RV3028_INT_GPIOS_IN_USE + const struct device *dev; + struct gpio_callback int_callback; + struct k_work work; + +#ifdef CONFIG_RTC_ALARM + rtc_alarm_callback alarm_callback; + void *alarm_user_data; +#endif /* CONFIG_RTC_ALARM */ +#ifdef CONFIG_RTC_UPDATE + rtc_update_callback update_callback; + void *update_user_data; +#endif /* CONFIG_RTC_UPDATE */ +#endif /* RV3028_INT_GPIOS_IN_USE */ +}; + +static void rv3028_lock_sem(const struct device *dev) +{ + struct rv3028_data *data = dev->data; + + (void)k_sem_take(&data->lock, K_FOREVER); +} + +static void rv3028_unlock_sem(const struct device *dev) +{ + struct rv3028_data *data = dev->data; + + k_sem_give(&data->lock); +} + +static int rv3028_read_regs(const struct device *dev, uint8_t addr, void *buf, size_t len) +{ + const struct rv3028_config *config = dev->config; + int err; + + err = i2c_write_read_dt(&config->i2c, &addr, sizeof(addr), buf, len); + if (err) { + LOG_ERR("failed to read reg addr 0x%02x, len %d (err %d)", addr, len, err); + return err; + } + + return 0; +} + +static int rv3028_read_reg8(const struct device *dev, uint8_t addr, uint8_t *val) +{ + return rv3028_read_regs(dev, addr, val, sizeof(*val)); +} + +static int rv3028_write_regs(const struct device *dev, uint8_t addr, void *buf, size_t len) +{ + const struct rv3028_config *config = dev->config; + uint8_t block[sizeof(addr) + len]; + int err; + + block[0] = addr; + memcpy(&block[1], buf, len); + + err = i2c_write_dt(&config->i2c, block, sizeof(block)); + if (err) { + LOG_ERR("failed to write reg addr 0x%02x, len %d (err %d)", addr, len, err); + return err; + } + + return 0; +} + +static int rv3028_write_reg8(const struct device *dev, uint8_t addr, uint8_t val) +{ + return rv3028_write_regs(dev, addr, &val, sizeof(val)); +} + +static int rv3028_update_reg8(const struct device *dev, uint8_t addr, uint8_t mask, uint8_t val) +{ + const struct rv3028_config *config = dev->config; + int err; + + err = i2c_reg_update_byte_dt(&config->i2c, addr, mask, val); + if (err) { + LOG_ERR("failed to update reg addr 0x%02x, mask 0x%02x, val 0x%02x (err %d)", addr, + mask, val, err); + return err; + } + + return 0; +} + +static int rv3028_eeprom_wait_busy(const struct device *dev) +{ + uint8_t status = 0; + int err; + int64_t timeout_time = k_uptime_get() + RV3028_EEBUSY_TIMEOUT_MS; + + /* Wait while the EEPROM is busy */ + for (;;) { + err = rv3028_read_reg8(dev, RV3028_REG_STATUS, &status); + if (err) { + return err; + } + + if (!(status & RV3028_STATUS_EEBUSY)) { + break; + } + + if (k_uptime_get() > timeout_time) { + return -ETIME; + } + + k_busy_wait(RV3028_EEBUSY_POLL_US); + } + + return 0; +} + +static int rv3028_exit_eerd(const struct device *dev) +{ + return rv3028_update_reg8(dev, RV3028_REG_CONTROL1, RV3028_CONTROL1_EERD, 0); +} + +static int rv3028_enter_eerd(const struct device *dev) +{ + uint8_t ctrl1; + bool eerd; + int ret; + + ret = rv3028_read_reg8(dev, RV3028_REG_CONTROL1, &ctrl1); + if (ret) { + return ret; + } + + eerd = ctrl1 & RV3028_CONTROL1_EERD; + if (eerd) { + return 0; + } + + ret = rv3028_update_reg8(dev, RV3028_REG_CONTROL1, RV3028_CONTROL1_EERD, + RV3028_CONTROL1_EERD); + + ret = rv3028_eeprom_wait_busy(dev); + if (ret) { + rv3028_exit_eerd(dev); + return ret; + } + + return ret; +} + +static int rv3028_eeprom_command(const struct device *dev, uint8_t command) +{ + int err; + + err = rv3028_write_reg8(dev, RV3028_REG_EEPROM_COMMAND, RV3028_EEPROM_CMD_INIT); + if (err) { + return err; + } + + return rv3028_write_reg8(dev, RV3028_REG_EEPROM_COMMAND, command); +} + +static int rv3028_update(const struct device *dev) +{ + int err; + + err = rv3028_eeprom_command(dev, RV3028_EEPROM_CMD_UPDATE); + if (err) { + goto exit_eerd; + } + + err = rv3028_eeprom_wait_busy(dev); + +exit_eerd: + rv3028_exit_eerd(dev); + + return err; +} + +static int rv3028_refresh(const struct device *dev) +{ + int err; + + err = rv3028_eeprom_command(dev, RV3028_EEPROM_CMD_REFRESH); + if (err) { + goto exit_eerd; + } + + err = rv3028_eeprom_wait_busy(dev); + +exit_eerd: + rv3028_exit_eerd(dev); + + return err; +} + +static int rv3028_update_cfg(const struct device *dev, uint8_t addr, uint8_t mask, uint8_t val) +{ + uint8_t val_old, val_new; + int err; + + err = rv3028_read_reg8(dev, addr, &val_old); + if (err) { + return err; + } + + val_new = (val_old & ~mask) | (val & mask); + if (val_new == val_old) { + return 0; + } + + err = rv3028_enter_eerd(dev); + if (err) { + return err; + } + + err = rv3028_write_reg8(dev, addr, val_new); + if (err) { + rv3028_exit_eerd(dev); + return err; + } + + return rv3028_update(dev); +} + +#if RV3028_INT_GPIOS_IN_USE + +static int rv3028_int_enable_unlocked(const struct device *dev, bool enable) +{ + const struct rv3028_config *config = dev->config; + uint8_t clkout = 0; + int err; + + if (enable || config->cof == RV3028_CLKOUT_FD_LOW) { + /* Disable CLKOUT */ + clkout |= FIELD_PREP(RV3028_CLKOUT_FD, RV3028_CLKOUT_FD_LOW); + } else { + /* Configure CLKOUT frequency */ + clkout |= RV3028_CLKOUT_CLKOE | + FIELD_PREP(RV3028_CLKOUT_FD, config->cof); + } + + /* Configure the CLKOUT register */ + err = rv3028_update_cfg(dev, + RV3028_REG_CLKOUT, + RV3028_CLKOUT_FD | RV3028_CLKOUT_CLKOE, + clkout); + if (err) { + return err; + } + + err = gpio_pin_interrupt_configure_dt(&config->gpio_int, + enable ? GPIO_INT_EDGE_TO_ACTIVE : GPIO_INT_DISABLE); + if (err) { + LOG_ERR("failed to %s GPIO interrupt (err %d)", enable ? "enable" : "disable", err); + return err; + } + + return 0; +} + +static void rv3028_work_cb(struct k_work *work) +{ + struct rv3028_data *data = CONTAINER_OF(work, struct rv3028_data, work); + const struct device *dev = data->dev; + rtc_alarm_callback alarm_callback = NULL; + void *alarm_user_data = NULL; + rtc_update_callback update_callback = NULL; + void *update_user_data = NULL; + uint8_t status; + int err; + + rv3028_lock_sem(dev); + + err = rv3028_read_reg8(data->dev, RV3028_REG_STATUS, &status); + if (err) { + goto unlock; + } + +#ifdef CONFIG_RTC_ALARM + if ((status & RV3028_STATUS_AF) && data->alarm_callback != NULL) { + status &= ~(RV3028_STATUS_AF); + alarm_callback = data->alarm_callback; + alarm_user_data = data->alarm_user_data; + } +#endif /* CONFIG_RTC_ALARM */ + +#ifdef CONFIG_RTC_UPDATE + if ((status & RV3028_STATUS_UF) && data->update_callback != NULL) { + status &= ~(RV3028_STATUS_UF); + update_callback = data->update_callback; + update_user_data = data->update_user_data; + } +#endif /* CONFIG_RTC_UPDATE */ + + err = rv3028_write_reg8(dev, RV3028_REG_STATUS, status); + if (err) { + goto unlock; + } + + /* Check if interrupt occurred between STATUS read/write */ + err = rv3028_read_reg8(dev, RV3028_REG_STATUS, &status); + if (err) { + goto unlock; + } + + if (((status & RV3028_STATUS_AF) && alarm_callback != NULL) || + ((status & RV3028_STATUS_UF) && update_callback != NULL)) { + /* Another interrupt occurred while servicing this one */ + k_work_submit(&data->work); + } + +unlock: + rv3028_unlock_sem(dev); + + if (alarm_callback != NULL) { + alarm_callback(dev, 0U, alarm_user_data); + alarm_callback = NULL; + } + + if (update_callback != NULL) { + update_callback(dev, update_user_data); + update_callback = NULL; + } +} + +static void rv3028_int_handler(const struct device *port, struct gpio_callback *cb, + gpio_port_pins_t pins) +{ + struct rv3028_data *data = CONTAINER_OF(cb, struct rv3028_data, int_callback); + + ARG_UNUSED(port); + ARG_UNUSED(pins); + + k_work_submit(&data->work); +} + +#endif /* RV3028_INT_GPIOS_IN_USE */ + +static int rv3028_set_time(const struct device *dev, const struct rtc_time *timeptr) +{ + uint8_t date[7]; + int err; + + if (timeptr == NULL || + !rtc_utils_validate_rtc_time(timeptr, RV3028_RTC_TIME_MASK) || + (timeptr->tm_year < RV3028_YEAR_OFFSET)) { + LOG_ERR("invalid time"); + return -EINVAL; + } + + rv3028_lock_sem(dev); + + LOG_DBG("set time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, " + "min = %d, sec = %d", + timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); + + date[0] = bin2bcd(timeptr->tm_sec) & RV3028_SECONDS_MASK; + date[1] = bin2bcd(timeptr->tm_min) & RV3028_MINUTES_MASK; + date[2] = bin2bcd(timeptr->tm_hour) & RV3028_HOURS_24H_MASK; + date[3] = bin2bcd(timeptr->tm_wday) & RV3028_WEEKDAY_MASK; + date[4] = bin2bcd(timeptr->tm_mday) & RV3028_DATE_MASK; + date[5] = bin2bcd(timeptr->tm_mon + RV3028_MONTH_OFFSET) & RV3028_MONTH_MASK; + date[6] = bin2bcd(timeptr->tm_year - RV3028_YEAR_OFFSET) & RV3028_YEAR_MASK; + + err = rv3028_write_regs(dev, RV3028_REG_SECONDS, &date, sizeof(date)); + if (err) { + goto unlock; + } + + /* Clear Power On Reset Flag */ + err = rv3028_update_reg8(dev, RV3028_REG_STATUS, RV3028_STATUS_PORF, 0); + +unlock: + rv3028_unlock_sem(dev); + + return err; +} + +static int rv3028_get_time(const struct device *dev, struct rtc_time *timeptr) +{ + uint8_t status; + uint8_t date[7]; + int err; + + if (timeptr == NULL) { + return -EINVAL; + } + + err = rv3028_read_reg8(dev, RV3028_REG_STATUS, &status); + if (err) { + return err; + } + + if (status & RV3028_STATUS_PORF) { + /* Power On Reset Flag indicates invalid data */ + return -ENODATA; + } + + err = rv3028_read_regs(dev, RV3028_REG_SECONDS, date, sizeof(date)); + if (err) { + return err; + } + + memset(timeptr, 0U, sizeof(*timeptr)); + timeptr->tm_sec = bcd2bin(date[0] & RV3028_SECONDS_MASK); + timeptr->tm_min = bcd2bin(date[1] & RV3028_MINUTES_MASK); + timeptr->tm_hour = bcd2bin(date[2] & RV3028_HOURS_24H_MASK); + timeptr->tm_wday = bcd2bin(date[3] & RV3028_WEEKDAY_MASK); + timeptr->tm_mday = bcd2bin(date[4] & RV3028_DATE_MASK); + timeptr->tm_mon = bcd2bin(date[5] & RV3028_MONTH_MASK) - RV3028_MONTH_OFFSET; + timeptr->tm_year = bcd2bin(date[6] & RV3028_YEAR_MASK) + RV3028_YEAR_OFFSET; + timeptr->tm_yday = -1; + timeptr->tm_isdst = -1; + + LOG_DBG("get time: year = %d, mon = %d, mday = %d, wday = %d, hour = %d, " + "min = %d, sec = %d", + timeptr->tm_year, timeptr->tm_mon, timeptr->tm_mday, timeptr->tm_wday, + timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec); + + return 0; +} + +#ifdef CONFIG_RTC_ALARM + +static int rv3028_alarm_get_supported_fields(const struct device *dev, uint16_t id, uint16_t *mask) +{ + ARG_UNUSED(dev); + + if (id != 0U) { + LOG_ERR("invalid alarm ID %d", id); + return -EINVAL; + } + + *mask = RV3028_RTC_ALARM_TIME_MASK; + + return 0; +} + +static int rv3028_alarm_set_time(const struct device *dev, uint16_t id, uint16_t mask, + const struct rtc_time *timeptr) +{ + uint8_t regs[3]; + + if (id != 0U) { + LOG_ERR("invalid alarm ID %d", id); + return -EINVAL; + } + + if (mask & ~(RV3028_RTC_ALARM_TIME_MASK)) { + LOG_ERR("unsupported alarm field mask 0x%04x", mask); + return -EINVAL; + } + + if (!rtc_utils_validate_rtc_time(timeptr, mask)) { + LOG_ERR("invalid alarm time"); + return -EINVAL; + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + regs[0] = bin2bcd(timeptr->tm_min) & RV3028_ALARM_MINUTES_MASK; + } else { + regs[0] = RTC_ALARM_TIME_MASK_MINUTE; + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + regs[1] = bin2bcd(timeptr->tm_hour) & RV3028_ALARM_HOURS_24H_MASK; + } else { + regs[1] = RV3028_ALARM_HOURS_AE_H; + } + + if (mask & RTC_ALARM_TIME_MASK_MONTHDAY) { + regs[2] = bin2bcd(timeptr->tm_mday) & RV3028_ALARM_DATE_MASK; + } else { + regs[2] = RV3028_ALARM_DATE_AE_WD; + } + + LOG_DBG("set alarm: mday = %d, hour = %d, min = %d, mask = 0x%04x", + timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, mask); + + /* Write registers RV3028_REG_ALARM_MINUTES through RV3028_REG_ALARM_WEEKDAY */ + return rv3028_write_regs(dev, RV3028_REG_ALARM_MINUTES, ®s, sizeof(regs)); +} + +static int rv3028_alarm_get_time(const struct device *dev, uint16_t id, uint16_t *mask, + struct rtc_time *timeptr) +{ + uint8_t regs[3]; + int err; + + if (id != 0U) { + LOG_ERR("invalid alarm ID %d", id); + return -EINVAL; + } + + /* Read registers RV3028_REG_ALARM_MINUTES through RV3028_REG_ALARM_WEEKDAY */ + err = rv3028_read_regs(dev, RV3028_REG_ALARM_MINUTES, ®s, sizeof(regs)); + if (err) { + return err; + } + + memset(timeptr, 0U, sizeof(*timeptr)); + *mask = 0U; + + if ((regs[0] & RV3028_ALARM_MINUTES_AE_M) == 0) { + timeptr->tm_min = bcd2bin(regs[0] & RV3028_ALARM_MINUTES_MASK); + *mask |= RTC_ALARM_TIME_MASK_MINUTE; + } + + if ((regs[1] & RV3028_ALARM_HOURS_AE_H) == 0) { + timeptr->tm_hour = bcd2bin(regs[1] & RV3028_ALARM_HOURS_24H_MASK); + *mask |= RTC_ALARM_TIME_MASK_HOUR; + } + + if ((regs[2] & RV3028_ALARM_DATE_AE_WD) == 0) { + timeptr->tm_mday = bcd2bin(regs[2] & RV3028_ALARM_DATE_MASK); + *mask |= RTC_ALARM_TIME_MASK_MONTHDAY; + } + + LOG_DBG("get alarm: mday = %d, hour = %d, min = %d, mask = 0x%04x", + timeptr->tm_mday, timeptr->tm_hour, timeptr->tm_min, *mask); + + return 0; +} + +static int rv3028_alarm_is_pending(const struct device *dev, uint16_t id) +{ + uint8_t status; + int err; + + if (id != 0U) { + LOG_ERR("invalid alarm ID %d", id); + return -EINVAL; + } + + rv3028_lock_sem(dev); + + err = rv3028_read_reg8(dev, RV3028_REG_STATUS, &status); + if (err) { + goto unlock; + } + + if (status & RV3028_STATUS_AF) { + /* Clear alarm flag */ + status &= ~(RV3028_STATUS_AF); + + err = rv3028_write_reg8(dev, RV3028_REG_STATUS, status); + if (err) { + goto unlock; + } + + /* Alarm pending */ + err = 1; + } + +unlock: + rv3028_unlock_sem(dev); + + return err; +} + +#if RV3028_INT_GPIOS_IN_USE + +static int rv3028_alarm_set_callback(const struct device *dev, uint16_t id, + rtc_alarm_callback callback, void *user_data) +{ + const struct rv3028_config *config = dev->config; + struct rv3028_data *data = dev->data; + uint8_t control_2; + int err = 0; + + if (config->gpio_int.port == NULL) { + return -ENOTSUP; + } + + if (id != 0U) { + LOG_ERR("invalid alarm ID %d", id); + return -EINVAL; + } + + rv3028_lock_sem(dev); + + data->alarm_callback = callback; + data->alarm_user_data = user_data; + + err = rv3028_read_reg8(dev, RV3028_REG_CONTROL2, &control_2); + if (err) { + goto unlock; + } + + if (callback != NULL) { + control_2 |= RV3028_CONTROL2_AIE; + } else { + control_2 &= ~(RV3028_CONTROL2_AIE); + } + + if ((control_2 & RV3028_CONTROL2_UIE) == 0U) { + /* Only change INT GPIO if periodic time update interrupt not enabled */ + err = rv3028_int_enable_unlocked(dev, callback != NULL); + if (err) { + goto unlock; + } + } + + err = rv3028_write_reg8(dev, RV3028_REG_CONTROL2, control_2); + if (err) { + goto unlock; + } + +unlock: + rv3028_unlock_sem(dev); + + /* Alarm flag may already be set */ + k_work_submit(&data->work); + + return err; +} + +#endif /* RV3028_INT_GPIOS_IN_USE */ +#endif /* CONFIG_RTC_ALARM */ + +#if RV3028_INT_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE) + +static int rv3028_update_set_callback(const struct device *dev, rtc_update_callback callback, + void *user_data) +{ + const struct rv3028_config *config = dev->config; + struct rv3028_data *data = dev->data; + uint8_t control_2; + int err; + + if (config->gpio_int.port == NULL) { + return -ENOTSUP; + } + + rv3028_lock_sem(dev); + + data->update_callback = callback; + data->update_user_data = user_data; + + err = rv3028_read_reg8(dev, RV3028_REG_CONTROL2, &control_2); + if (err) { + goto unlock; + } + + if (callback != NULL) { + control_2 |= RV3028_CONTROL2_UIE; + } else { + control_2 &= ~(RV3028_CONTROL2_UIE); + } + + if ((control_2 & RV3028_CONTROL2_AIE) == 0U) { + /* Only change INT GPIO if alarm interrupt not enabled */ + err = rv3028_int_enable_unlocked(dev, callback != NULL); + if (err) { + goto unlock; + } + } + + err = rv3028_write_reg8(dev, RV3028_REG_CONTROL2, control_2); + if (err) { + goto unlock; + } + +unlock: + rv3028_unlock_sem(dev); + + /* Seconds flag may already be set */ + k_work_submit(&data->work); + + return err; +} + +#endif /* RV3028_INT_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE) */ + +static int rv3028_init(const struct device *dev) +{ + const struct rv3028_config *config = dev->config; + struct rv3028_data *data = dev->data; + uint8_t regs[3]; + uint8_t val; + int err; + + k_sem_init(&data->lock, 1, 1); + + if (!i2c_is_ready_dt(&config->i2c)) { + LOG_ERR("I2C bus not ready"); + return -ENODEV; + } + + err = rv3028_read_reg8(dev, RV3028_REG_ID, &val); + if (err) { + return -ENODEV; + } + + LOG_DBG("HID: 0x%02x, VID: 0x%02x", (val & 0xF0) >> 0x04, val & 0x0F); + +#if RV3028_INT_GPIOS_IN_USE + if (config->gpio_int.port != NULL) { + if (!gpio_is_ready_dt(&config->gpio_int)) { + LOG_ERR("GPIO not ready"); + return -ENODEV; + } + + err = gpio_pin_configure_dt(&config->gpio_int, GPIO_INPUT); + if (err) { + LOG_ERR("failed to configure GPIO (err %d)", err); + return -ENODEV; + } + + gpio_init_callback(&data->int_callback, rv3028_int_handler, + BIT(config->gpio_int.pin)); + + err = gpio_add_callback_dt(&config->gpio_int, &data->int_callback); + if (err) { + LOG_ERR("failed to add GPIO callback (err %d)", err); + return -ENODEV; + } + + data->dev = dev; + data->work.handler = rv3028_work_cb; + } +#endif /* RV3028_INT_GPIOS_IN_USE */ + + err = rv3028_read_reg8(dev, RV3028_REG_STATUS, &val); + if (err) { + return -ENODEV; + } + + if (val & RV3028_STATUS_AF) { + LOG_WRN("an alarm may have been missed"); + } + + /* Refresh the settings in the RAM with the settings from the EEPROM */ + err = rv3028_enter_eerd(dev); + if (err) { + return -ENODEV; + } + err = rv3028_refresh(dev); + if (err) { + return -ENODEV; + } + + /* Configure the CLKOUT register */ + val = FIELD_PREP(RV3028_CLKOUT_FD, config->cof) | + (config->cof != RV3028_CLKOUT_FD_LOW ? RV3028_CLKOUT_CLKOE : 0); + err = rv3028_update_cfg(dev, + RV3028_REG_CLKOUT, + RV3028_CLKOUT_FD | RV3028_CLKOUT_CLKOE, + val); + if (err) { + return -ENODEV; + } + + err = rv3028_update_cfg(dev, + RV3028_REG_BACKUP, + RV3028_BACKUP_TCE | RV3028_BACKUP_TCR | RV3028_BACKUP_BSM, + config->backup); + if (err) { + return -ENODEV; + } + + err = rv3028_update_reg8(dev, RV3028_REG_CONTROL1, RV3028_CONTROL1_WADA, + RV3028_CONTROL1_WADA); + if (err) { + return -ENODEV; + } + + /* Disable the alarms */ + err = rv3028_update_reg8(dev, + RV3028_REG_CONTROL2, + RV3028_CONTROL2_AIE | RV3028_CONTROL2_UIE, + 0); + if (err) { + return -ENODEV; + } + + err = rv3028_read_regs(dev, RV3028_REG_ALARM_MINUTES, regs, sizeof(regs)); + if (err) { + return -ENODEV; + } + + regs[0] |= RV3028_ALARM_MINUTES_AE_M; + regs[1] |= RV3028_ALARM_HOURS_AE_H; + regs[2] |= RV3028_ALARM_DATE_AE_WD; + + err = rv3028_write_regs(dev, RV3028_REG_ALARM_MINUTES, regs, sizeof(regs)); + if (err) { + return -ENODEV; + } + + return 0; +} + +static const struct rtc_driver_api rv3028_driver_api = { + .set_time = rv3028_set_time, + .get_time = rv3028_get_time, +#ifdef CONFIG_RTC_ALARM + .alarm_get_supported_fields = rv3028_alarm_get_supported_fields, + .alarm_set_time = rv3028_alarm_set_time, + .alarm_get_time = rv3028_alarm_get_time, + .alarm_is_pending = rv3028_alarm_is_pending, +#if RV3028_INT_GPIOS_IN_USE + .alarm_set_callback = rv3028_alarm_set_callback, +#endif /* RV3028_INT_GPIOS_IN_USE */ +#endif /* CONFIG_RTC_ALARM */ +#if RV3028_INT_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE) + .update_set_callback = rv3028_update_set_callback, +#endif /* RV3028_INT_GPIOS_IN_USE && defined(CONFIG_RTC_UPDATE) */ +}; + +#define RV3028_BSM_FROM_DT_INST(inst) \ + UTIL_CAT(RV3028_BSM_, DT_INST_STRING_UPPER_TOKEN(inst, backup_switch_mode)) + +#define RV3028_BACKUP_FROM_DT_INST(inst) \ + ((FIELD_PREP(RV3028_BACKUP_BSM, RV3028_BSM_FROM_DT_INST(inst))) | \ + (FIELD_PREP(RV3028_BACKUP_TCR, DT_INST_ENUM_IDX_OR(inst, trickle_resistor_ohms, 0))) | \ + (DT_INST_NODE_HAS_PROP(inst, trickle_resistor_ohms) ? RV3028_BACKUP_TCE : 0)) + +#define RV3028_INIT(inst) \ + static const struct rv3028_config rv3028_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + .cof = DT_INST_ENUM_IDX_OR(inst, clkout_frequency, RV3028_CLKOUT_FD_LOW), \ + .backup = RV3028_BACKUP_FROM_DT_INST(inst), \ + IF_ENABLED(RV3028_INT_GPIOS_IN_USE, \ + (.gpio_int = GPIO_DT_SPEC_INST_GET_OR(inst, int_gpios, {0})))}; \ + \ + static struct rv3028_data rv3028_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, &rv3028_init, NULL, &rv3028_data_##inst, \ + &rv3028_config_##inst, POST_KERNEL, CONFIG_RTC_INIT_PRIORITY, \ + &rv3028_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RV3028_INIT) diff --git a/drivers/rtc/rtc_shell.c b/drivers/rtc/rtc_shell.c index bc9980d20aff5..a87056c6ed707 100644 --- a/drivers/rtc/rtc_shell.c +++ b/drivers/rtc/rtc_shell.c @@ -210,13 +210,23 @@ static int cmd_get(const struct shell *sh, size_t argc, char **argv) return res; } - shell_print(sh, "%04d-%02d-%02dT%02d:%02d:%02d:%06d", rtctime.tm_year + 1900, + shell_print(sh, "%04d-%02d-%02dT%02d:%02d:%02d.%03d", rtctime.tm_year + 1900, rtctime.tm_mon + 1, rtctime.tm_mday, rtctime.tm_hour, rtctime.tm_min, rtctime.tm_sec, rtctime.tm_nsec / 1000000); return 0; } +static void device_name_get(size_t idx, struct shell_static_entry *entry) +{ + const struct device *dev = shell_device_lookup(idx, NULL); + + entry->syntax = (dev != NULL) ? dev->name : NULL; + entry->handler = NULL; + entry->help = NULL; + entry->subcmd = NULL; +} + #define RTC_GET_HELP \ ("Get current time (UTC)\n" \ "Usage: rtc get ") @@ -225,10 +235,12 @@ static int cmd_get(const struct shell *sh, size_t argc, char **argv) ("Set UTC time\n" \ "Usage: rtc set | | ") +SHELL_DYNAMIC_CMD_CREATE(dsub_device_name, device_name_get); + SHELL_STATIC_SUBCMD_SET_CREATE(sub_rtc, /* Alphabetically sorted */ - SHELL_CMD_ARG(set, NULL, RTC_SET_HELP, cmd_set, 3, 0), - SHELL_CMD_ARG(get, NULL, RTC_GET_HELP, cmd_get, 2, 0), + SHELL_CMD_ARG(set, &dsub_device_name, RTC_SET_HELP, cmd_set, 3, 0), + SHELL_CMD_ARG(get, &dsub_device_name, RTC_GET_HELP, cmd_get, 2, 0), SHELL_SUBCMD_SET_END); SHELL_CMD_REGISTER(rtc, &sub_rtc, "RTC commands", NULL); diff --git a/drivers/rtc/rtc_smartbond.c b/drivers/rtc/rtc_smartbond.c index bfac974e874c0..7aa0d461d2733 100644 --- a/drivers/rtc/rtc_smartbond.c +++ b/drivers/rtc/rtc_smartbond.c @@ -16,6 +16,7 @@ #include #include #include +#include "rtc_utils.h" #include LOG_MODULE_REGISTER(rtc_smartbond, CONFIG_RTC_LOG_LEVEL); @@ -266,8 +267,7 @@ static int rtc_smartbond_get_time(const struct device *dev, struct rtc_time *tim } if (!data->is_rtc_configured) { - LOG_ERR("RTC is not initialized yet"); - return -ENODATA; + LOG_WRN("RTC is not initialized yet"); } k_mutex_lock(&data->lock, K_FOREVER); @@ -286,7 +286,10 @@ static int rtc_smartbond_get_time(const struct device *dev, struct rtc_time *tim #if defined(CONFIG_RTC_ALARM) BUILD_ASSERT(RTC_ALARMS_COUNT, "At least one alarm event should be supported"); -/* Define a valid calendar value as a zero sub-field is not valid for the alarm calendar value */ +/* + * Parse only the alarm fields indicated by the mask. Default valid values should be assigned + * to unused fields as it might happen that application has provided with invalid values. + */ static uint32_t alarm_calendar_to_bcd(const struct rtc_time *timeptr, uint16_t mask) { uint32_t rtc_calendar_alarm_reg = 0x0108; @@ -304,14 +307,28 @@ static uint32_t alarm_calendar_to_bcd(const struct rtc_time *timeptr, uint16_t m return rtc_calendar_alarm_reg; } -/* No need to parse the alarm mask as a zero sub-field is valid for the alarm time counter. */ -static inline uint32_t alarm_time_to_bcd(const struct rtc_time *timeptr) +/* + * Parse only the alarm fields indicated by the mask. Default valid values should be assigned + * to unused fields as it might happen that application has provided with invalid values. + */ +static inline uint32_t alarm_time_to_bcd(const struct rtc_time *timeptr, uint16_t mask) { uint32_t rtc_time_alarm_reg = 0; - RTC_TIME_ALARM_REG_SET_FIELD(S, rtc_time_alarm_reg, bin2bcd(timeptr->tm_sec)); /*[0, 59]*/ - RTC_TIME_ALARM_REG_SET_FIELD(M, rtc_time_alarm_reg, bin2bcd(timeptr->tm_min)); /*[0, 59]*/ - RTC_TIME_ALARM_REG_SET_FIELD(HR, rtc_time_alarm_reg, bin2bcd(timeptr->tm_hour)); /*[0, 23]*/ + if (mask & RTC_ALARM_TIME_MASK_SECOND) { + /*[0, 59]*/ + RTC_TIME_ALARM_REG_SET_FIELD(S, rtc_time_alarm_reg, bin2bcd(timeptr->tm_sec)); + } + + if (mask & RTC_ALARM_TIME_MASK_MINUTE) { + /*[0, 59]*/ + RTC_TIME_ALARM_REG_SET_FIELD(M, rtc_time_alarm_reg, bin2bcd(timeptr->tm_min)); + } + + if (mask & RTC_ALARM_TIME_MASK_HOUR) { + /*[0, 23]*/ + RTC_TIME_ALARM_REG_SET_FIELD(HR, rtc_time_alarm_reg, bin2bcd(timeptr->tm_hour)); + } return rtc_time_alarm_reg; } @@ -408,6 +425,11 @@ static int rtc_smartbond_alarm_set_time(const struct device *dev, uint16_t id, u return -EINVAL; } + if (!rtc_utils_validate_rtc_time(timeptr, mask)) { + LOG_ERR("Invalid alarm fields values"); + return -EINVAL; + } + if (!data->is_rtc_configured) { LOG_WRN("RTC is not initialized yet"); } @@ -425,7 +447,7 @@ static int rtc_smartbond_alarm_set_time(const struct device *dev, uint16_t id, u rtc_time_alarm_reg = RTC->RTC_TIME_ALARM_REG; rtc_calendar_alarm_reg = RTC->RTC_CALENDAR_ALARM_REG; - RTC->RTC_TIME_ALARM_REG = alarm_time_to_bcd(timeptr); + RTC->RTC_TIME_ALARM_REG = alarm_time_to_bcd(timeptr, mask); RTC->RTC_CALENDAR_ALARM_REG = alarm_calendar_to_bcd(timeptr, mask); rtc_status_reg = RTC->RTC_STATUS_REG; diff --git a/drivers/sdhc/Kconfig.esp32 b/drivers/sdhc/Kconfig.esp32 index e5c505885bcf0..cf95a4317a03b 100644 --- a/drivers/sdhc/Kconfig.esp32 +++ b/drivers/sdhc/Kconfig.esp32 @@ -1,5 +1,5 @@ # Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config SDHC_ESP32 bool "ESP32 SDHC Driver" diff --git a/drivers/sdhc/Kconfig.imx b/drivers/sdhc/Kconfig.imx index 48e47a126212a..47bb84db553f2 100644 --- a/drivers/sdhc/Kconfig.imx +++ b/drivers/sdhc/Kconfig.imx @@ -1,5 +1,5 @@ # Copyright (c) 2022, NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config IMX_USDHC bool "NXP IMX USDHC Driver" diff --git a/drivers/sdhc/Kconfig.mcux_sdif b/drivers/sdhc/Kconfig.mcux_sdif index 528df6de763aa..2b66a42e5641d 100644 --- a/drivers/sdhc/Kconfig.mcux_sdif +++ b/drivers/sdhc/Kconfig.mcux_sdif @@ -1,5 +1,5 @@ # Copyright 2022, NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config MCUX_SDIF bool "NXP MCUX SDIF Driver" diff --git a/drivers/sdhc/Kconfig.sam_hsmci b/drivers/sdhc/Kconfig.sam_hsmci index 68265dcabed1c..fca9bafdaffeb 100644 --- a/drivers/sdhc/Kconfig.sam_hsmci +++ b/drivers/sdhc/Kconfig.sam_hsmci @@ -1,5 +1,5 @@ # Copyright 2023 Nikhef -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config SAM_HSMCI bool "ATMEL SAM HSMCI driver" diff --git a/drivers/sdhc/Kconfig.spi b/drivers/sdhc/Kconfig.spi index 555f11619b0ae..ce861f1d02df4 100644 --- a/drivers/sdhc/Kconfig.spi +++ b/drivers/sdhc/Kconfig.spi @@ -1,5 +1,5 @@ # Copyright (c) 2022, NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 config SPI_SDHC bool "SD protocol over SPI bus" diff --git a/drivers/sdhc/imx_usdhc.c b/drivers/sdhc/imx_usdhc.c index 84f8f2aee3b0b..2909ea104b15d 100644 --- a/drivers/sdhc/imx_usdhc.c +++ b/drivers/sdhc/imx_usdhc.c @@ -159,6 +159,14 @@ static void card_detect_gpio_cb(const struct device *port, } } +static void imx_usdhc_select_1_8v(USDHC_Type *base, bool enable_1_8v) +{ +#if !(defined(FSL_FEATURE_USDHC_HAS_NO_VOLTAGE_SELECT) && \ + (FSL_FEATURE_USDHC_HAS_NO_VOLTAGE_SELECT)) + UDSHC_SelectVoltage(base, enable_1_8v); +#endif +} + static int imx_usdhc_dat3_pull(const struct usdhc_config *cfg, bool pullup) { @@ -256,7 +264,7 @@ static int imx_usdhc_reset(const struct device *dev) { const struct usdhc_config *cfg = dev->config; /* Switch to default I/O voltage of 3.3V */ - UDSHC_SelectVoltage(cfg->base, false); + imx_usdhc_select_1_8v(cfg->base, false); USDHC_EnableDDRMode(cfg->base, false, 0U); #if defined(FSL_FEATURE_USDHC_HAS_SDR50_MODE) && (FSL_FEATURE_USDHC_HAS_SDR50_MODE) USDHC_EnableStandardTuning(cfg->base, 0, 0, false); @@ -271,22 +279,7 @@ static int imx_usdhc_reset(const struct device *dev) #endif /* Reset data/command/tuning circuit */ - return USDHC_Reset(cfg->base, kUSDHC_ResetAll, 100U) == true ? 0 : -ETIMEDOUT; -} - -/* Wait for USDHC to gate clock when it is disabled */ -static inline void imx_usdhc_wait_clock_gate(USDHC_Type *base) -{ - uint32_t timeout = 1000; - - while (timeout--) { - if (base->PRES_STATE & USDHC_PRES_STATE_SDOFF_MASK) { - break; - } - } - if (timeout == 0) { - LOG_WRN("SD clock did not gate in time"); - } + return USDHC_Reset(cfg->base, kUSDHC_ResetAll, 1000U) == true ? 0 : -ETIMEDOUT; } /* @@ -353,7 +346,7 @@ static int imx_usdhc_set_io(const struct device *dev, struct sdhc_io *ios) switch (ios->signal_voltage) { case SD_VOL_3_3_V: case SD_VOL_3_0_V: - UDSHC_SelectVoltage(cfg->base, false); + imx_usdhc_select_1_8v(cfg->base, false); break; case SD_VOL_1_8_V: /** @@ -367,7 +360,7 @@ static int imx_usdhc_set_io(const struct device *dev, struct sdhc_io *ios) * 10 ms, then allow it to be gated again. */ /* Switch to 1.8V */ - UDSHC_SelectVoltage(cfg->base, true); + imx_usdhc_select_1_8v(cfg->base, true); /* Wait 10 ms- clock will be gated during this period */ k_msleep(10); /* Force the clock on */ diff --git a/drivers/sdhc/rcar_mmc.c b/drivers/sdhc/rcar_mmc.c index 2e5d20ee86adf..8cea5f6fb9a66 100644 --- a/drivers/sdhc/rcar_mmc.c +++ b/drivers/sdhc/rcar_mmc.c @@ -28,15 +28,6 @@ LOG_MODULE_REGISTER(rcar_mmc, CONFIG_LOG_DEFAULT_LEVEL); #define MMC_POLL_FLAGS_TIMEOUT_US 100000 #define MMC_POLL_FLAGS_ONE_CYCLE_TIMEOUT_US 1 #define MMC_BUS_CLOCK_FREQ 800000000 -/* - * SD/MMC clock for Gen3/Gen4 R-car boards can't be equal to 208 MHz, - * but we can run SDR104 on lower frequencies: - * "SDR104: UHS-I 1.8V signaling, Frequency up to 208 MHz" - * so according to SD card standard it is possible to use lower frequencies, - * and we need to pass check of frequency in sdmmc in order to use sdr104 mode. - * This is the reason why it is needed this correction. - */ -#define MMC_MAX_FREQ_CORRECTION 8000000 #ifdef CONFIG_RCAR_MMC_DMA_SUPPORT #define ALIGN_BUF_DMA __aligned(CONFIG_SDHC_BUFFER_ALIGNMENT) @@ -575,7 +566,7 @@ static int rcar_mmc_dma_rx_tx_data(const struct device *dev, struct sdhc_data *d reg |= RCAR_MMC_EXTMODE_DMA_EN; rcar_mmc_write_reg32(dev, RCAR_MMC_EXTMODE, reg); - dma_addr = z_mem_phys_addr(data->data); + dma_addr = k_mem_phys_addr(data->data); rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_ADDR_L, dma_addr); rcar_mmc_write_reg32(dev, RCAR_MMC_DMA_ADDR_H, 0); @@ -839,7 +830,7 @@ static int rcar_mmc_rx_tx_data(const struct device *dev, struct sdhc_data *data, int ret = 0; #ifdef CONFIG_RCAR_MMC_DMA_SUPPORT - if (!(z_mem_phys_addr(data->data) >> 32)) { + if (!(k_mem_phys_addr(data->data) >> 32)) { ret = rcar_mmc_dma_rx_tx_data(dev, data, is_read); } else #endif @@ -1941,7 +1932,7 @@ static void rcar_mmc_init_host_props(const struct device *dev) /* Note: init only properties that are used for mmc/sdhc */ - props->f_max = cfg->max_frequency + MMC_MAX_FREQ_CORRECTION; + props->f_max = cfg->max_frequency; /* * note: actually, it's possible to get lower frequency * if we use divider from cpg too @@ -2176,7 +2167,7 @@ static int rcar_mmc_init(const struct device *dev) exit_unmap: #if defined(DEVICE_MMIO_IS_IN_RAM) && defined(CONFIG_MMU) - z_phys_unmap((uint8_t *)DEVICE_MMIO_GET(dev), DEVICE_MMIO_ROM_PTR(dev)->size); + k_mem_unmap_phys_bare((uint8_t *)DEVICE_MMIO_GET(dev), DEVICE_MMIO_ROM_PTR(dev)->size); #endif return ret; } diff --git a/drivers/sdhc/sdhc_spi.c b/drivers/sdhc/sdhc_spi.c index 7462e711dcd40..7e7e22b9f17ac 100644 --- a/drivers/sdhc/sdhc_spi.c +++ b/drivers/sdhc/sdhc_spi.c @@ -1,5 +1,5 @@ /* - * Copyright 2022 NXP + * Copyright 2022,2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -143,6 +143,7 @@ static int sdhc_spi_init_card(const struct device *dev) spi_cfg->operation |= SPI_CS_ACTIVE_HIGH; ret = sdhc_spi_rx(config->spi_dev, spi_cfg, data->scratch, 10); if (ret != 0) { + spi_release(config->spi_dev, spi_cfg); spi_cfg->operation &= ~SPI_CS_ACTIVE_HIGH; return ret; } @@ -603,7 +604,7 @@ static int sdhc_spi_request(const struct device *dev, { const struct sdhc_spi_config *config = dev->config; struct sdhc_spi_data *dev_data = dev->data; - int ret, retries = cmd->retries; + int ret, stop_ret, retries = cmd->retries; const struct sdhc_command stop_cmd = { .opcode = SD_STOP_TRANSMISSION, .arg = 0, @@ -617,6 +618,7 @@ static int sdhc_spi_request(const struct device *dev, } while ((ret != 0) && (retries-- > 0)); } else { do { + retries--; ret = sdhc_spi_send_cmd(dev, cmd, true); if (ret) { continue; @@ -628,16 +630,27 @@ static int sdhc_spi_request(const struct device *dev, ret = sdhc_spi_read_data(dev, data); } if (ret || (cmd->opcode == SD_READ_MULTIPLE_BLOCK)) { + int stop_retries = cmd->retries; + /* CMD12 is required after multiple read, or * to retry failed transfer */ - sdhc_spi_send_cmd(dev, + stop_ret = sdhc_spi_send_cmd(dev, (struct sdhc_command *)&stop_cmd, false); + while ((stop_ret != 0) && (stop_retries > 0)) { + /* Retry stop command */ + ret = stop_ret = sdhc_spi_send_cmd(dev, + (struct sdhc_command *)&stop_cmd, + false); + stop_retries--; + } } - } while ((ret != 0) && (retries-- > 0)); + } while ((ret != 0) && (retries > 0)); } if (ret) { + /* Release SPI bus */ + spi_release(config->spi_dev, dev_data->spi_cfg); return ret; } /* Release SPI bus */ diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt index 2a952bb2614ed..76a8cff9b96bb 100644 --- a/drivers/sensor/CMakeLists.txt +++ b/drivers/sensor/CMakeLists.txt @@ -61,6 +61,8 @@ add_subdirectory_ifdef(CONFIG_S11059 s11059) add_subdirectory_ifdef(CONFIG_SBS_GAUGE sbs_gauge) add_subdirectory_ifdef(CONFIG_SX9500 sx9500) add_subdirectory_ifdef(CONFIG_TH02 th02) +add_subdirectory_ifdef(CONFIG_TSIC_XX6 tsic_xx6) +add_subdirectory_ifdef(CONFIG_VEAA_X_3 veaa_x_3) add_subdirectory_ifdef(CONFIG_VOLTAGE_DIVIDER voltage_divider) add_subdirectory_ifdef(CONFIG_TACH_ENE_KB1200 ene_tach_kb1200) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig index 3636641cb7a97..85589a541c959 100644 --- a/drivers/sensor/Kconfig +++ b/drivers/sensor/Kconfig @@ -142,6 +142,8 @@ source "drivers/sensor/s11059/Kconfig" source "drivers/sensor/sbs_gauge/Kconfig" source "drivers/sensor/sx9500/Kconfig" source "drivers/sensor/th02/Kconfig" +source "drivers/sensor/tsic_xx6/Kconfig" +source "drivers/sensor/veaa_x_3/Kconfig" source "drivers/sensor/voltage_divider/Kconfig" source "drivers/sensor/ene_tach_kb1200/Kconfig" diff --git a/drivers/sensor/adi/adxl362/adxl362.c b/drivers/sensor/adi/adxl362/adxl362.c index 9d38788118213..fcd94b1792bb7 100644 --- a/drivers/sensor/adi/adxl362/adxl362.c +++ b/drivers/sensor/adi/adxl362/adxl362.c @@ -561,7 +561,8 @@ static void adxl362_accel_convert(struct sensor_value *val, int accel, static void adxl362_temp_convert(struct sensor_value *val, int temp) { /* See sensitivity and bias specifications in table 1 of datasheet */ - int milli_c = (temp - ADXL362_TEMP_BIAS_LSB) * ADXL362_TEMP_MC_PER_LSB; + int milli_c = (temp - ADXL362_TEMP_BIAS_LSB) * ADXL362_TEMP_MC_PER_LSB + + (ADXL362_TEMP_BIAS_TEST_CONDITION * 1000); val->val1 = milli_c / 1000; val->val2 = (milli_c % 1000) * 1000; diff --git a/drivers/sensor/adi/adxl362/adxl362.h b/drivers/sensor/adi/adxl362/adxl362.h index 5dea56e107a74..ac41a2ff2ee98 100644 --- a/drivers/sensor/adi/adxl362/adxl362.h +++ b/drivers/sensor/adi/adxl362/adxl362.h @@ -169,6 +169,7 @@ /* ADXL362 temperature sensor specifications */ #define ADXL362_TEMP_MC_PER_LSB 65 #define ADXL362_TEMP_BIAS_LSB 350 +#define ADXL362_TEMP_BIAS_TEST_CONDITION 25 struct adxl362_config { struct spi_dt_spec bus; diff --git a/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c b/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c index f33e5cd9134f8..08ef4026ccf5b 100644 --- a/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c +++ b/drivers/sensor/amd_sb_tsi/sb_tsi_emul.c @@ -99,7 +99,7 @@ static int sb_tsi_emul_init(const struct emul *target, const struct device *pare return 0; } -static int sb_tsi_emul_set_channel(const struct emul *target, enum sensor_channel chan, +static int sb_tsi_emul_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { struct sb_tsi_emul_data *data = target->data; @@ -107,7 +107,7 @@ static int sb_tsi_emul_set_channel(const struct emul *target, enum sensor_channe int32_t millicelsius; int32_t reg_value; - if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + if (ch.chan_type != SENSOR_CHAN_AMBIENT_TEMP && ch.chan_idx != 0) { return -ENOTSUP; } @@ -121,10 +121,10 @@ static int sb_tsi_emul_set_channel(const struct emul *target, enum sensor_channe return 0; } -static int sb_tsi_emul_get_sample_range(const struct emul *target, enum sensor_channel chan, +static int sb_tsi_emul_get_sample_range(const struct emul *target, struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) { - if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + if (ch.chan_type != SENSOR_CHAN_AMBIENT_TEMP || ch.chan_idx != 0) { return -ENOTSUP; } diff --git a/drivers/sensor/asahi_kasei/akm09918c/akm09918c.h b/drivers/sensor/asahi_kasei/akm09918c/akm09918c.h index 742c7d3be3867..a4b35c64dd838 100644 --- a/drivers/sensor/asahi_kasei/akm09918c/akm09918c.h +++ b/drivers/sensor/asahi_kasei/akm09918c/akm09918c.h @@ -93,6 +93,6 @@ int akm09918c_sample_fetch_helper(const struct device *dev, enum sensor_channel int akm09918c_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder); -int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); +void akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); #endif /* ZEPHYR_DRIVERS_SENSOR_AKM09918C_AKM09918C_H_ */ diff --git a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c index 438ca24780d46..6fb5d901ec4d0 100644 --- a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c +++ b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_async.c @@ -9,7 +9,7 @@ LOG_MODULE_DECLARE(AKM09918C, CONFIG_SENSOR_LOG_LEVEL); -int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +void akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { uint32_t min_buf_len = sizeof(struct akm09918c_encoded_data); int rc; @@ -22,7 +22,7 @@ int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) if (rc != 0) { LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } edata = (struct akm09918c_encoded_data *)buf; @@ -33,10 +33,8 @@ int akm09918c_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) if (rc != 0) { LOG_ERR("Failed to fetch samples"); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } rtio_iodev_sqe_ok(iodev_sqe, 0); - - return 0; } diff --git a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_decoder.c b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_decoder.c index 9bd6b312b7a0e..7a17e959dc4dd 100644 --- a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_decoder.c +++ b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_decoder.c @@ -5,22 +5,24 @@ #include "akm09918c.h" -static int akm09918c_decoder_get_frame_count(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint16_t *frame_count) +#define DT_DRV_COMPAT asahi_kasei_akm09918c + +static int akm09918c_decoder_get_frame_count(const uint8_t *buffer, + struct sensor_chan_spec chan_spec, + uint16_t *frame_count) { ARG_UNUSED(buffer); - ARG_UNUSED(channel); - ARG_UNUSED(channel_idx); + ARG_UNUSED(chan_spec); /* This sensor lacks a FIFO; there will always only be one frame at a time. */ *frame_count = 1; return 0; } -static int akm09918c_decoder_get_size_info(enum sensor_channel channel, size_t *base_size, +static int akm09918c_decoder_get_size_info(struct sensor_chan_spec chan_spec, size_t *base_size, size_t *frame_size) { - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_MAGN_X: case SENSOR_CHAN_MAGN_Y: case SENSOR_CHAN_MAGN_Z: @@ -48,9 +50,8 @@ static int akm09918c_convert_raw_to_q31(int16_t reading, q31_t *out) return 0; } -static int akm09918c_decoder_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, - uint16_t max_count, void *data_out) +static int akm09918c_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct akm09918c_encoded_data *edata = (const struct akm09918c_encoded_data *)buffer; @@ -58,7 +59,7 @@ static int akm09918c_decoder_decode(const uint8_t *buffer, enum sensor_channel c return 0; } - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_MAGN_X: case SENSOR_CHAN_MAGN_Y: case SENSOR_CHAN_MAGN_Z: diff --git a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c index db541b8b4fb4b..5dce0d0d82716 100644 --- a/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c +++ b/drivers/sensor/asahi_kasei/akm09918c/akm09918c_emul.c @@ -133,7 +133,7 @@ static int akm09918c_emul_init(const struct emul *target, const struct device *p return 0; } -static int akm09918c_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, +static int akm09918c_emul_backend_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { if (!target || !target->data) { @@ -143,7 +143,7 @@ static int akm09918c_emul_backend_set_channel(const struct emul *target, enum se struct akm09918c_emul_data *data = target->data; uint8_t reg; - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_MAGN_X: reg = AKM09918C_REG_HXL; break; @@ -178,7 +178,7 @@ static int akm09918c_emul_backend_set_channel(const struct emul *target, enum se } static int akm09918c_emul_backend_get_sample_range(const struct emul *target, - enum sensor_channel ch, q31_t *lower, + struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) { ARG_UNUSED(target); @@ -187,7 +187,7 @@ static int akm09918c_emul_backend_get_sample_range(const struct emul *target, return -EINVAL; } - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_MAGN_X: case SENSOR_CHAN_MAGN_Y: case SENSOR_CHAN_MAGN_Z: diff --git a/drivers/sensor/bosch/bma4xx/bma4xx.c b/drivers/sensor/bosch/bma4xx/bma4xx.c index 9d8656d67aa80..1d1609c64b36b 100644 --- a/drivers/sensor/bosch/bma4xx/bma4xx.c +++ b/drivers/sensor/bosch/bma4xx/bma4xx.c @@ -338,12 +338,12 @@ static int bma4xx_temp_fetch(const struct device *dev, int8_t *temp) * RTIO submit and encoding */ -static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +static void bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { struct bma4xx_data *bma4xx = dev->data; const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; - const enum sensor_channel *const channels = cfg->channels; + const struct sensor_chan_spec *const channels = cfg->channels; const size_t num_channels = cfg->count; uint32_t min_buf_len = sizeof(struct bma4xx_encoded_data); @@ -357,7 +357,7 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq if (rc != 0) { LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } /* Prepare response */ @@ -370,7 +370,12 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq /* Determine what channels we need to fetch */ for (int i = 0; i < num_channels; i++) { - switch (channels[i]) { + if (channels[i].chan_idx != 0) { + LOG_ERR("Only channel index 0 supported"); + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); + return; + } + switch (channels[i].chan_type) { case SENSOR_CHAN_ALL: edata->has_accel = 1; #ifdef CONFIG_BMA4XX_TEMPERATURE @@ -389,8 +394,10 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq break; #endif /* CONFIG_BMA4XX_TEMPERATURE */ default: - LOG_ERR("Requested unsupported channel ID %d", channels[i]); - return -ENOTSUP; + LOG_ERR("Requested unsupported channel type %d, idx %d", + channels[i].chan_type, channels[i].chan_idx); + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); + return; } } @@ -400,7 +407,7 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq if (rc != 0) { LOG_ERR("Failed to fetch accel samples"); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } } @@ -410,44 +417,42 @@ static int bma4xx_submit_one_shot(const struct device *dev, struct rtio_iodev_sq if (rc != 0) { LOG_ERR("Failed to fetch temp sample"); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } } #endif /* CONFIG_BMA4XX_TEMPERATURE */ rtio_iodev_sqe_ok(iodev_sqe, 0); - - return 0; } -static int bma4xx_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +static void bma4xx_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; + /* TODO: Add streaming support */ if (!cfg->is_streaming) { - return bma4xx_submit_one_shot(dev, iodev_sqe); + bma4xx_submit_one_shot(dev, iodev_sqe); + } else { + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); } - /* TODO: Add streaming support */ - - return -ENOTSUP; } /* * RTIO decoder */ -static int bma4xx_decoder_get_frame_count(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint16_t *frame_count) +static int bma4xx_decoder_get_frame_count(const uint8_t *buffer, struct sensor_chan_spec ch, + uint16_t *frame_count) { const struct bma4xx_encoded_data *edata = (const struct bma4xx_encoded_data *)buffer; const struct bma4xx_decoder_header *header = &edata->header; - if (channel_idx != 0) { + if (ch.chan_idx != 0) { return -ENOTSUP; } if (!header->is_fifo) { - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -467,10 +472,10 @@ static int bma4xx_decoder_get_frame_count(const uint8_t *buffer, enum sensor_cha return -ENOTSUP; } -static int bma4xx_decoder_get_size_info(enum sensor_channel channel, size_t *base_size, +static int bma4xx_decoder_get_size_info(struct sensor_chan_spec ch, size_t *base_size, size_t *frame_size) { - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -487,9 +492,9 @@ static int bma4xx_decoder_get_size_info(enum sensor_channel channel, size_t *bas } } -static int bma4xx_get_shift(enum sensor_channel channel, uint8_t accel_fs, int8_t *shift) +static int bma4xx_get_shift(struct sensor_chan_spec ch, uint8_t accel_fs, int8_t *shift) { - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -562,9 +567,8 @@ static void bma4xx_convert_raw_temp_to_q31(int8_t raw_val, q31_t *out) } #endif /* CONFIG_BMA4XX_TEMPERATURE */ -static int bma4xx_one_shot_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, - void *data_out) +static int bma4xx_one_shot_decode(const uint8_t *buffer, struct sensor_chan_spec ch, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct bma4xx_encoded_data *edata = (const struct bma4xx_encoded_data *)buffer; const struct bma4xx_decoder_header *header = &edata->header; @@ -573,11 +577,11 @@ static int bma4xx_one_shot_decode(const uint8_t *buffer, enum sensor_channel cha if (*fit != 0) { return 0; } - if (max_count == 0 || channel_idx != 0) { + if (max_count == 0 || ch.chan_idx != 0) { return -EINVAL; } - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -590,7 +594,9 @@ static int bma4xx_one_shot_decode(const uint8_t *buffer, enum sensor_channel cha out->header.base_timestamp_ns = edata->header.timestamp; out->header.reading_count = 1; - rc = bma4xx_get_shift(SENSOR_CHAN_ACCEL_XYZ, header->accel_fs, &out->shift); + rc = bma4xx_get_shift((struct sensor_chan_spec){.chan_type = SENSOR_CHAN_ACCEL_XYZ, + .chan_idx = 0}, + header->accel_fs, &out->shift); if (rc != 0) { return -EINVAL; } @@ -628,8 +634,8 @@ static int bma4xx_one_shot_decode(const uint8_t *buffer, enum sensor_channel cha } } -static int bma4xx_decoder_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, +static int bma4xx_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec ch, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct bma4xx_decoder_header *header = (const struct bma4xx_decoder_header *)buffer; @@ -639,7 +645,7 @@ static int bma4xx_decoder_decode(const uint8_t *buffer, enum sensor_channel chan return -ENOTSUP; } - return bma4xx_one_shot_decode(buffer, channel, channel_idx, fit, max_count, data_out); + return bma4xx_one_shot_decode(buffer, ch, fit, max_count, data_out); } SENSOR_DECODER_API_DT_DEFINE() = { diff --git a/drivers/sensor/bosch/bma4xx/bma4xx_emul.c b/drivers/sensor/bosch/bma4xx/bma4xx_emul.c index efc4012e29c56..ec5f069da536e 100644 --- a/drivers/sensor/bosch/bma4xx/bma4xx_emul.c +++ b/drivers/sensor/bosch/bma4xx/bma4xx_emul.c @@ -216,7 +216,7 @@ void bma4xx_emul_set_accel_data(const struct emul *target, q31_t value, int8_t s data->regs[reg + 1] = FIELD_GET(GENMASK(11, 4), reg_val); } -static int bma4xx_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, +static int bma4xx_emul_backend_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { @@ -226,7 +226,7 @@ static int bma4xx_emul_backend_set_channel(const struct emul *target, enum senso struct bma4xx_emul_data *data = target->data; - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: bma4xx_emul_set_accel_data(target, value[0], shift, BMA4XX_REG_DATA_8); break; @@ -250,15 +250,15 @@ static int bma4xx_emul_backend_set_channel(const struct emul *target, enum senso return 0; } -static int bma4xx_emul_backend_get_sample_range(const struct emul *target, enum sensor_channel ch, - q31_t *lower, q31_t *upper, q31_t *epsilon, - int8_t *shift) +static int bma4xx_emul_backend_get_sample_range(const struct emul *target, + struct sensor_chan_spec ch, q31_t *lower, + q31_t *upper, q31_t *epsilon, int8_t *shift) { if (!lower || !upper || !epsilon || !shift) { return -EINVAL; } - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: diff --git a/drivers/sensor/bosch/bme280/CMakeLists.txt b/drivers/sensor/bosch/bme280/CMakeLists.txt index 115c11359788a..7ce886907f671 100644 --- a/drivers/sensor/bosch/bme280/CMakeLists.txt +++ b/drivers/sensor/bosch/bme280/CMakeLists.txt @@ -3,3 +3,4 @@ zephyr_library() zephyr_library_sources(bme280.c bme280_spi.c bme280_i2c.c) +zephyr_library_sources_ifdef(CONFIG_SENSOR_ASYNC_API bme280_decoder.c bme280_async.c) diff --git a/drivers/sensor/bosch/bme280/bme280.c b/drivers/sensor/bosch/bme280/bme280.c index f2bd7514c0190..8c0f1bead3a3a 100644 --- a/drivers/sensor/bosch/bme280/bme280.c +++ b/drivers/sensor/bosch/bme280/bme280.c @@ -26,38 +26,6 @@ LOG_MODULE_REGISTER(BME280, CONFIG_SENSOR_LOG_LEVEL); #warning "BME280 driver enabled without any devices" #endif -struct bme280_data { - /* Compensation parameters. */ - uint16_t dig_t1; - int16_t dig_t2; - int16_t dig_t3; - uint16_t dig_p1; - int16_t dig_p2; - int16_t dig_p3; - int16_t dig_p4; - int16_t dig_p5; - int16_t dig_p6; - int16_t dig_p7; - int16_t dig_p8; - int16_t dig_p9; - uint8_t dig_h1; - int16_t dig_h2; - uint8_t dig_h3; - int16_t dig_h4; - int16_t dig_h5; - int8_t dig_h6; - - /* Compensated values. */ - int32_t comp_temp; - uint32_t comp_press; - uint32_t comp_humidity; - - /* Carryover between temperature and pressure/humidity compensation. */ - int32_t t_fine; - - uint8_t chip_id; -}; - struct bme280_config { union bme280_bus bus; const struct bme280_bus_io *bus_io; @@ -90,7 +58,7 @@ static inline int bme280_reg_write(const struct device *dev, uint8_t reg, * Compensation code taken from BME280 datasheet, Section 4.2.3 * "Compensation formula". */ -static void bme280_compensate_temp(struct bme280_data *data, int32_t adc_temp) +static int32_t bme280_compensate_temp(struct bme280_data *data, int32_t adc_temp) { int32_t var1, var2; @@ -101,10 +69,10 @@ static void bme280_compensate_temp(struct bme280_data *data, int32_t adc_temp) ((int32_t)data->dig_t3)) >> 14; data->t_fine = var1 + var2; - data->comp_temp = (data->t_fine * 5 + 128) >> 8; + return (data->t_fine * 5 + 128) >> 8; } -static void bme280_compensate_press(struct bme280_data *data, int32_t adc_press) +static uint32_t bme280_compensate_press(struct bme280_data *data, int32_t adc_press) { int64_t var1, var2, p; @@ -118,8 +86,7 @@ static void bme280_compensate_press(struct bme280_data *data, int32_t adc_press) /* Avoid exception caused by division by zero. */ if (var1 == 0) { - data->comp_press = 0U; - return; + return 0; } p = 1048576 - adc_press; @@ -128,10 +95,10 @@ static void bme280_compensate_press(struct bme280_data *data, int32_t adc_press) var2 = (((int64_t)data->dig_p8) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((int64_t)data->dig_p7) << 4); - data->comp_press = (uint32_t)p; + return (uint32_t)p; } -static void bme280_compensate_humidity(struct bme280_data *data, +static uint32_t bme280_compensate_humidity(struct bme280_data *data, int32_t adc_humidity) { int32_t h; @@ -146,7 +113,7 @@ static void bme280_compensate_humidity(struct bme280_data *data, ((int32_t)data->dig_h1)) >> 4)); h = (h > 419430400 ? 419430400 : h); - data->comp_humidity = (uint32_t)(h >> 12); + return (uint32_t)(h >> 12); } static int bme280_wait_until_ready(const struct device *dev) @@ -166,10 +133,10 @@ static int bme280_wait_until_ready(const struct device *dev) return 0; } -static int bme280_sample_fetch(const struct device *dev, - enum sensor_channel chan) +int bme280_sample_fetch_helper(const struct device *dev, + enum sensor_channel chan, struct bme280_reading *reading) { - struct bme280_data *data = dev->data; + struct bme280_data *dev_data = dev->data; uint8_t buf[8]; int32_t adc_press, adc_temp, adc_humidity; int size = 6; @@ -197,7 +164,7 @@ static int bme280_sample_fetch(const struct device *dev, return ret; } - if (data->chip_id == BME280_CHIP_ID) { + if (dev_data->chip_id == BME280_CHIP_ID) { size = 8; } ret = bme280_reg_read(dev, BME280_REG_PRESS_MSB, buf, size); @@ -208,17 +175,24 @@ static int bme280_sample_fetch(const struct device *dev, adc_press = (buf[0] << 12) | (buf[1] << 4) | (buf[2] >> 4); adc_temp = (buf[3] << 12) | (buf[4] << 4) | (buf[5] >> 4); - bme280_compensate_temp(data, adc_temp); - bme280_compensate_press(data, adc_press); + reading->comp_temp = bme280_compensate_temp(dev_data, adc_temp); + reading->comp_press = bme280_compensate_press(dev_data, adc_press); - if (data->chip_id == BME280_CHIP_ID) { + if (dev_data->chip_id == BME280_CHIP_ID) { adc_humidity = (buf[6] << 8) | buf[7]; - bme280_compensate_humidity(data, adc_humidity); + reading->comp_humidity = bme280_compensate_humidity(dev_data, adc_humidity); } return 0; } +int bme280_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct bme280_data *data = dev->data; + + return bme280_sample_fetch_helper(dev, chan, &data->reading); +} + static int bme280_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) @@ -228,21 +202,21 @@ static int bme280_channel_get(const struct device *dev, switch (chan) { case SENSOR_CHAN_AMBIENT_TEMP: /* - * data->comp_temp has a resolution of 0.01 degC. So + * comp_temp has a resolution of 0.01 degC. So * 5123 equals 51.23 degC. */ - val->val1 = data->comp_temp / 100; - val->val2 = data->comp_temp % 100 * 10000; + val->val1 = data->reading.comp_temp / 100; + val->val2 = data->reading.comp_temp % 100 * 10000; break; case SENSOR_CHAN_PRESS: /* - * data->comp_press has 24 integer bits and 8 + * comp_press has 24 integer bits and 8 * fractional. Output value of 24674867 represents * 24674867/256 = 96386.2 Pa = 963.862 hPa */ - val->val1 = (data->comp_press >> 8) / 1000U; - val->val2 = (data->comp_press >> 8) % 1000 * 1000U + - (((data->comp_press & 0xff) * 1000U) >> 8); + val->val1 = (data->reading.comp_press >> 8) / 1000U; + val->val2 = (data->reading.comp_press >> 8) % 1000 * 1000U + + (((data->reading.comp_press & 0xff) * 1000U) >> 8); break; case SENSOR_CHAN_HUMIDITY: /* The BMP280 doesn't have a humidity sensor */ @@ -250,12 +224,12 @@ static int bme280_channel_get(const struct device *dev, return -ENOTSUP; } /* - * data->comp_humidity has 22 integer bits and 10 + * comp_humidity has 22 integer bits and 10 * fractional. Output value of 47445 represents * 47445/1024 = 46.333 %RH */ - val->val1 = (data->comp_humidity >> 10); - val->val2 = (((data->comp_humidity & 0x3ff) * 1000U * 1000U) >> 10); + val->val1 = (data->reading.comp_humidity >> 10); + val->val2 = (((data->reading.comp_humidity & 0x3ff) * 1000U * 1000U) >> 10); break; default: return -ENOTSUP; @@ -267,6 +241,10 @@ static int bme280_channel_get(const struct device *dev, static const struct sensor_driver_api bme280_api_funcs = { .sample_fetch = bme280_sample_fetch, .channel_get = bme280_channel_get, +#ifdef CONFIG_SENSOR_ASYNC_API + .submit = bme280_submit, + .get_decoder = bme280_get_decoder, +#endif }; static int bme280_read_compensation(const struct device *dev) diff --git a/drivers/sensor/bosch/bme280/bme280.h b/drivers/sensor/bosch/bme280/bme280.h index afc4ce275dcee..2499174d5e6d1 100644 --- a/drivers/sensor/bosch/bme280/bme280.h +++ b/drivers/sensor/bosch/bme280/bme280.h @@ -14,6 +14,8 @@ #include #include #include +#include +#include #define DT_DRV_COMPAT bosch_bme280 @@ -158,4 +160,64 @@ extern const struct bme280_bus_io bme280_bus_io_i2c; BME280_TEMP_OVER | \ BME280_MODE_SLEEP) +struct bme280_reading { + /* Compensated values. */ + int32_t comp_temp; + uint32_t comp_press; + uint32_t comp_humidity; +}; + +struct bme280_data { + /* Compensation parameters. */ + uint16_t dig_t1; + int16_t dig_t2; + int16_t dig_t3; + uint16_t dig_p1; + int16_t dig_p2; + int16_t dig_p3; + int16_t dig_p4; + int16_t dig_p5; + int16_t dig_p6; + int16_t dig_p7; + int16_t dig_p8; + int16_t dig_p9; + uint8_t dig_h1; + int16_t dig_h2; + uint8_t dig_h3; + int16_t dig_h4; + int16_t dig_h5; + int8_t dig_h6; + + /* Carryover between temperature and pressure/humidity compensation. */ + int32_t t_fine; + + uint8_t chip_id; + + struct bme280_reading reading; +}; + +/* + * RTIO + */ + +struct bme280_decoder_header { + uint64_t timestamp; +} __attribute__((__packed__)); + +struct bme280_encoded_data { + struct bme280_decoder_header header; + struct bme280_reading reading; +}; + +int bme280_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder); + +void bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); + +int bme280_sample_fetch(const struct device *dev, + enum sensor_channel chan); + +int bme280_sample_fetch_helper(const struct device *dev, + enum sensor_channel chan, + struct bme280_reading *reading); + #endif /* ZEPHYR_DRIVERS_SENSOR_BME280_BME280_H_ */ diff --git a/drivers/sensor/bosch/bme280/bme280_async.c b/drivers/sensor/bosch/bme280/bme280_async.c new file mode 100644 index 0000000000000..780a7a28c1e40 --- /dev/null +++ b/drivers/sensor/bosch/bme280/bme280_async.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include "bme280.h" + +LOG_MODULE_DECLARE(BME280, CONFIG_SENSOR_LOG_LEVEL); + +void bme280_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +{ + uint32_t min_buf_len = sizeof(struct bme280_encoded_data); + int rc; + uint8_t *buf; + uint32_t buf_len; + + const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; + const struct sensor_chan_spec *const channels = cfg->channels; + const size_t num_channels = cfg->count; + + /* Check if the requested channels are supported */ + for (size_t i = 0; i < num_channels; i++) { + switch (channels[i].chan_type) { + case SENSOR_CHAN_AMBIENT_TEMP: + case SENSOR_CHAN_HUMIDITY: + case SENSOR_CHAN_PRESS: + case SENSOR_CHAN_ALL: + break; + default: + LOG_ERR("Unsupported channel type %d", channels[i].chan_type); + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); + return; + } + } + + rc = rtio_sqe_rx_buf(iodev_sqe, min_buf_len, min_buf_len, &buf, &buf_len); + if (rc != 0) { + LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); + rtio_iodev_sqe_err(iodev_sqe, rc); + return; + } + + struct bme280_encoded_data *edata; + + edata = (struct bme280_encoded_data *)buf; + + edata->header.timestamp = k_ticks_to_ns_floor64(k_uptime_ticks()); + + rc = bme280_sample_fetch_helper(dev, SENSOR_CHAN_ALL, &edata->reading); + if (rc != 0) { + LOG_ERR("Failed to fetch samples"); + rtio_iodev_sqe_err(iodev_sqe, rc); + return; + } + + rtio_iodev_sqe_ok(iodev_sqe, 0); +} diff --git a/drivers/sensor/bosch/bme280/bme280_decoder.c b/drivers/sensor/bosch/bme280/bme280_decoder.c new file mode 100644 index 0000000000000..7158fd37d5a8c --- /dev/null +++ b/drivers/sensor/bosch/bme280/bme280_decoder.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2024 Intel Corporation + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "bme280.h" +#include + +static int bme280_decoder_get_frame_count(const uint8_t *buffer, + struct sensor_chan_spec chan_spec, + uint16_t *frame_count) +{ + ARG_UNUSED(buffer); + ARG_UNUSED(chan_spec); + + /* This sensor lacks a FIFO; there will always only be one frame at a time. */ + *frame_count = 1; + return 0; +} + +static int bme280_decoder_get_size_info(struct sensor_chan_spec chan_spec, size_t *base_size, + size_t *frame_size) +{ + switch (chan_spec.chan_type) { + case SENSOR_CHAN_AMBIENT_TEMP: + case SENSOR_CHAN_HUMIDITY: + case SENSOR_CHAN_PRESS: + *base_size = sizeof(struct sensor_q31_sample_data); + *frame_size = sizeof(struct sensor_q31_sample_data); + return 0; + default: + return -ENOTSUP; + } +} + +#define BME280_HUM_SHIFT (22) +#define BME280_PRESS_SHIFT (24) +#define BME280_TEMP_SHIFT (24) + +static void bme280_convert_double_to_q31(double reading, int32_t shift, q31_t *out) +{ + reading = reading * pow(2, 31 - shift); + + int64_t reading_round = (reading < 0) ? (reading - 0.5) : (reading + 0.5); + int32_t reading_q31 = CLAMP(reading_round, INT32_MIN, INT32_MAX); + + if (reading_q31 < 0) { + reading_q31 = abs(reading_q31); + reading_q31 = ~reading_q31; + reading_q31++; + } + + *out = reading_q31; +} + +/* Refer to bme280.c bme280_channel_get() */ +static void bme280_convert_signed_temp_raw_to_q31(int32_t reading, q31_t *out) +{ + double temp_double = reading / 100.0; + + bme280_convert_double_to_q31(temp_double, BME280_TEMP_SHIFT, out); +} + +static void bme280_convert_unsigned_pressure_raw_to_q31(uint32_t reading, q31_t *out) +{ + double press_double = (reading / 256.0) / 1000.0; /* Pa -> hPa */ + + bme280_convert_double_to_q31(press_double, BME280_PRESS_SHIFT, out); +} + +static void bme280_convert_unsigned_humidity_raw_to_q31(uint32_t reading, q31_t *out) +{ + double hum_double = (reading / 1024.0); + + bme280_convert_double_to_q31(hum_double, BME280_HUM_SHIFT, out); +} + +static int bme280_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) +{ + const struct bme280_encoded_data *edata = (const struct bme280_encoded_data *)buffer; + + if (*fit != 0) { + return 0; + } + + struct sensor_q31_data *out = data_out; + + out->header.base_timestamp_ns = edata->header.timestamp; + out->header.reading_count = 1; + + switch (chan_spec.chan_type) { + case SENSOR_CHAN_AMBIENT_TEMP: + bme280_convert_signed_temp_raw_to_q31(edata->reading.comp_temp, + &out->readings[0].temperature); + out->shift = BME280_TEMP_SHIFT; + break; + case SENSOR_CHAN_PRESS: + bme280_convert_unsigned_pressure_raw_to_q31(edata->reading.comp_press, + &out->readings[0].pressure); + out->shift = BME280_PRESS_SHIFT; + break; + case SENSOR_CHAN_HUMIDITY: + bme280_convert_unsigned_humidity_raw_to_q31(edata->reading.comp_humidity, + &out->readings[0].humidity); + out->shift = BME280_HUM_SHIFT; + break; + default: + return -EINVAL; + } + + *fit = 1; + + return 1; +} + + +SENSOR_DECODER_API_DT_DEFINE() = { + .get_frame_count = bme280_decoder_get_frame_count, + .get_size_info = bme280_decoder_get_size_info, + .decode = bme280_decoder_decode, +}; + +int bme280_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder) +{ + ARG_UNUSED(dev); + *decoder = &SENSOR_DECODER_NAME(); + + return 0; +} diff --git a/drivers/sensor/bosch/bme680/bme680.c b/drivers/sensor/bosch/bme680/bme680.c index 2a9a21db889be..0f12314ffee3e 100644 --- a/drivers/sensor/bosch/bme680/bme680.c +++ b/drivers/sensor/bosch/bme680/bme680.c @@ -23,6 +23,13 @@ LOG_MODULE_REGISTER(bme680, CONFIG_SENSOR_LOG_LEVEL); +struct bme_data_regs { + uint8_t pressure[3]; + uint8_t temperature[3]; + uint8_t humidity[2]; + uint8_t padding[3]; + uint8_t gas[2]; +} __packed; #if BME680_BUS_SPI static inline bool bme680_is_on_spi(const struct device *dev) @@ -41,7 +48,7 @@ static inline int bme680_bus_check(const struct device *dev) } static inline int bme680_reg_read(const struct device *dev, - uint8_t start, uint8_t *buf, int size) + uint8_t start, void *buf, int size) { const struct bme680_config *config = dev->config; @@ -209,45 +216,54 @@ static int bme680_sample_fetch(const struct device *dev, enum sensor_channel chan) { struct bme680_data *data = dev->data; - uint8_t buff[BME680_LEN_FIELD] = { 0 }; + struct bme_data_regs data_regs; uint8_t gas_range; uint32_t adc_temp, adc_press; uint16_t adc_hum, adc_gas_res; - int size = BME680_LEN_FIELD; + uint8_t status; + int cnt = 0; int ret; __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); - ret = bme680_reg_read(dev, BME680_REG_FIELD0, buff, size); + /* Trigger the measurement */ + ret = bme680_reg_write(dev, BME680_REG_CTRL_MEAS, BME680_CTRL_MEAS_VAL); if (ret < 0) { return ret; } - data->new_data = buff[0] & BME680_MSK_NEW_DATA; - data->heatr_stab = buff[14] & BME680_MSK_HEATR_STAB; - - adc_press = (uint32_t)(((uint32_t)buff[2] << 12) | ((uint32_t)buff[3] << 4) - | ((uint32_t)buff[4] >> 4)); - adc_temp = (uint32_t)(((uint32_t)buff[5] << 12) | ((uint32_t)buff[6] << 4) - | ((uint32_t)buff[7] >> 4)); - adc_hum = (uint16_t)(((uint32_t)buff[8] << 8) | (uint32_t)buff[9]); - adc_gas_res = (uint16_t)((uint32_t)buff[13] << 2 | (((uint32_t)buff[14]) >> 6)); - gas_range = buff[14] & BME680_MSK_GAS_RANGE; - - if (data->new_data) { - bme680_calc_temp(data, adc_temp); - bme680_calc_press(data, adc_press); - bme680_calc_humidity(data, adc_hum); - bme680_calc_gas_resistance(data, gas_range, adc_gas_res); - } + do { + /* Wait for a maximum of 250ms for data. + * Initial delay after boot has been measured at 170ms. + * Subequent triggers are < 1ms. + */ + if (cnt++ > 250) { + return -EAGAIN; + } + k_sleep(K_MSEC(1)); + ret = bme680_reg_read(dev, BME680_REG_MEAS_STATUS, &status, 1); + if (ret < 0) { + return ret; + } + } while (!(status & BME680_MSK_NEW_DATA)); + LOG_DBG("New data after %d ms", cnt); - /* Trigger the next measurement */ - ret = bme680_reg_write(dev, BME680_REG_CTRL_MEAS, - BME680_CTRL_MEAS_VAL); + ret = bme680_reg_read(dev, BME680_REG_FIELD0, &data_regs, sizeof(data_regs)); if (ret < 0) { return ret; } + adc_press = sys_get_be24(data_regs.pressure) >> 4; + adc_temp = sys_get_be24(data_regs.temperature) >> 4; + adc_hum = sys_get_be16(data_regs.humidity); + adc_gas_res = sys_get_be16(data_regs.gas) >> 6; + data->heatr_stab = data_regs.gas[1] & BME680_MSK_HEATR_STAB; + gas_range = data_regs.gas[1] & BME680_MSK_GAS_RANGE; + + bme680_calc_temp(data, adc_temp); + bme680_calc_press(data, adc_press); + bme680_calc_humidity(data, adc_hum); + bme680_calc_gas_resistance(data, gas_range, adc_gas_res); return 0; } diff --git a/drivers/sensor/bosch/bme680/bme680.h b/drivers/sensor/bosch/bme680/bme680.h index 125aea1b27666..a0f63fc40780b 100644 --- a/drivers/sensor/bosch/bme680/bme680.h +++ b/drivers/sensor/bosch/bme680/bme680.h @@ -57,14 +57,14 @@ struct bme680_config { #define BME680_CHIP_ID 0x61 -#define BME680_LEN_FIELD 15 #define BME680_LEN_COEFF_ALL 42 #define BME680_LEN_COEFF1 23 #define BME680_LEN_COEFF2 14 #define BME680_LEN_COEFF3 5 #define BME680_REG_COEFF3 0x00 -#define BME680_REG_FIELD0 0x1d +#define BME680_REG_MEAS_STATUS 0x1D +#define BME680_REG_FIELD0 0x1F #define BME680_REG_IDAC_HEAT0 0x50 #define BME680_REG_RES_HEAT0 0x5A #define BME680_REG_GAS_WAIT0 0x64 @@ -72,9 +72,9 @@ struct bme680_config { #define BME680_REG_CTRL_GAS_0 0x70 #define BME680_REG_CTRL_GAS_1 0x71 #define BME680_REG_CTRL_HUM 0x72 +#define BME680_REG_STATUS 0x73 #define BME680_REG_CTRL_MEAS 0x74 #define BME680_REG_CONFIG 0x75 -#define BME680_REG_STATUS 0x73 #define BME680_REG_UNIQUE_ID 0x83 #define BME680_REG_COEFF1 0x8a #define BME680_REG_COEFF2 0xe1 @@ -204,7 +204,6 @@ struct bme680_data { uint32_t calc_gas_resistance; /* Additional information */ - uint8_t new_data; uint8_t heatr_stab; /* Carryover between temperature and pressure/humidity compensation. */ diff --git a/drivers/sensor/bosch/bmi160/emul_bmi160.c b/drivers/sensor/bosch/bmi160/emul_bmi160.c index 38c74a98813d1..9fc33b48b6aa9 100644 --- a/drivers/sensor/bosch/bmi160/emul_bmi160.c +++ b/drivers/sensor/bosch/bmi160/emul_bmi160.c @@ -279,7 +279,7 @@ static struct i2c_emul_api bmi160_emul_api_i2c = { }; #endif -static int bmi160_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, +static int bmi160_emul_backend_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { const struct bmi160_emul_cfg *cfg = target->cfg; @@ -288,11 +288,11 @@ static int bmi160_emul_backend_set_channel(const struct emul *target, enum senso int8_t scale_shift = 0; int reg_lsb; - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: - reg_lsb = BMI160_REG_DATA_ACC_X + (ch - SENSOR_CHAN_ACCEL_X) * 2; + reg_lsb = BMI160_REG_DATA_ACC_X + (ch.chan_type - SENSOR_CHAN_ACCEL_X) * 2; scale = 0x4e7404ea; switch (FIELD_GET(GENMASK(3, 0), cfg->reg[BMI160_REG_ACC_RANGE])) { @@ -313,7 +313,7 @@ static int bmi160_emul_backend_set_channel(const struct emul *target, enum senso case SENSOR_CHAN_GYRO_X: case SENSOR_CHAN_GYRO_Y: case SENSOR_CHAN_GYRO_Z: - reg_lsb = BMI160_REG_DATA_GYR_X + (ch - SENSOR_CHAN_GYRO_X) * 2; + reg_lsb = BMI160_REG_DATA_GYR_X + (ch.chan_type - SENSOR_CHAN_GYRO_X) * 2; scale = 0x45d02bea; switch (FIELD_GET(GENMASK(2, 0), cfg->reg[BMI160_REG_GYR_RANGE])) { @@ -353,7 +353,7 @@ static int bmi160_emul_backend_set_channel(const struct emul *target, enum senso intermediate <<= shift - scale_shift; } - if (ch == SENSOR_CHAN_DIE_TEMP) { + if (ch.chan_type == SENSOR_CHAN_DIE_TEMP) { /* Need to subtract 23C */ intermediate -= INT64_C(23) << (31 - scale_shift); } @@ -366,13 +366,13 @@ static int bmi160_emul_backend_set_channel(const struct emul *target, enum senso return 0; } -static int bmi160_emul_backend_get_sample_range(const struct emul *target, enum sensor_channel ch, - q31_t *lower, q31_t *upper, q31_t *epsilon, - int8_t *shift) +static int bmi160_emul_backend_get_sample_range(const struct emul *target, + struct sensor_chan_spec ch, q31_t *lower, + q31_t *upper, q31_t *epsilon, int8_t *shift) { const struct bmi160_emul_cfg *cfg = target->cfg; - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -440,10 +440,10 @@ static int bmi160_emul_backend_get_sample_range(const struct emul *target, enum } } -static int bmi160_emul_backend_set_offset(const struct emul *target, enum sensor_channel ch, +static int bmi160_emul_backend_set_offset(const struct emul *target, struct sensor_chan_spec ch, const q31_t *values, int8_t shift) { - if (ch != SENSOR_CHAN_ACCEL_XYZ && ch != SENSOR_CHAN_GYRO_XYZ) { + if (ch.chan_type != SENSOR_CHAN_ACCEL_XYZ && ch.chan_type != SENSOR_CHAN_GYRO_XYZ) { return -EINVAL; } @@ -452,20 +452,20 @@ static int bmi160_emul_backend_set_offset(const struct emul *target, enum sensor int8_t scale_shift = 0; if (values[0] == 0 && values[1] == 0 && values[2] == 0) { - if (ch == SENSOR_CHAN_ACCEL_XYZ) { + if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) { cfg->reg[BMI160_REG_OFFSET_EN] &= ~BIT(BMI160_ACC_OFS_EN_POS); } else { cfg->reg[BMI160_REG_OFFSET_EN] &= ~BIT(BMI160_GYR_OFS_EN_POS); } } else { - if (ch == SENSOR_CHAN_ACCEL_XYZ) { + if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) { cfg->reg[BMI160_REG_OFFSET_EN] |= BIT(BMI160_ACC_OFS_EN_POS); } else { cfg->reg[BMI160_REG_OFFSET_EN] |= BIT(BMI160_GYR_OFS_EN_POS); } } - if (ch == SENSOR_CHAN_ACCEL_XYZ) { + if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) { /* * bits = (values[i]mps2 / 9.80665g/mps2) / 0.0039g * = values[i] / 0.038245935mps2/bit @@ -493,11 +493,11 @@ static int bmi160_emul_backend_set_offset(const struct emul *target, enum sensor int64_t reg_value = intermediate / scale; - __ASSERT_NO_MSG(ch != SENSOR_CHAN_ACCEL_XYZ || + __ASSERT_NO_MSG(ch.chan_type != SENSOR_CHAN_ACCEL_XYZ || (reg_value >= INT8_MIN && reg_value <= INT8_MAX)); - __ASSERT_NO_MSG(ch != SENSOR_CHAN_GYRO_XYZ || + __ASSERT_NO_MSG(ch.chan_type != SENSOR_CHAN_GYRO_XYZ || (reg_value >= -0x1ff - 1 && reg_value <= 0x1ff)); - if (ch == SENSOR_CHAN_ACCEL_XYZ) { + if (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ) { cfg->reg[BMI160_REG_OFFSET_ACC_X + i] = reg_value & 0xff; } else { cfg->reg[BMI160_REG_OFFSET_GYR_X + i] = reg_value & 0xff; @@ -510,11 +510,11 @@ static int bmi160_emul_backend_set_offset(const struct emul *target, enum sensor return 0; } -static int bmi160_emul_backend_set_attribute(const struct emul *target, enum sensor_channel ch, +static int bmi160_emul_backend_set_attribute(const struct emul *target, struct sensor_chan_spec ch, enum sensor_attribute attribute, const void *value) { if (attribute == SENSOR_ATTR_OFFSET && - (ch == SENSOR_CHAN_ACCEL_XYZ || ch == SENSOR_CHAN_GYRO_XYZ)) { + (ch.chan_type == SENSOR_CHAN_ACCEL_XYZ || ch.chan_type == SENSOR_CHAN_GYRO_XYZ)) { const struct sensor_three_axis_attribute *attribute_value = value; return bmi160_emul_backend_set_offset(target, ch, attribute_value->values, @@ -524,12 +524,12 @@ static int bmi160_emul_backend_set_attribute(const struct emul *target, enum sen } static int bmi160_emul_backend_get_attribute_metadata(const struct emul *target, - enum sensor_channel ch, + struct sensor_chan_spec ch, enum sensor_attribute attribute, q31_t *min, q31_t *max, q31_t *increment, int8_t *shift) { ARG_UNUSED(target); - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: diff --git a/drivers/sensor/current_amp/Kconfig b/drivers/sensor/current_amp/Kconfig index 62ea9bc0d1280..b167221256da5 100644 --- a/drivers/sensor/current_amp/Kconfig +++ b/drivers/sensor/current_amp/Kconfig @@ -8,6 +8,6 @@ config CURRENT_AMP bool "Current sense amplifier driver" default y depends on DT_HAS_CURRENT_SENSE_AMPLIFIER_ENABLED - depends on ADC + select ADC help Enable current sense amplifier driver. diff --git a/drivers/sensor/current_amp/current_amp.c b/drivers/sensor/current_amp/current_amp.c index d760e4b34b018..e9d5e1a09a217 100644 --- a/drivers/sensor/current_amp/current_amp.c +++ b/drivers/sensor/current_amp/current_amp.c @@ -61,11 +61,11 @@ static int get(const struct device *dev, enum sensor_channel chan, struct sensor i_ma = raw_val; current_sense_amplifier_scale_dt(config, &i_ma); - LOG_DBG("%d/%d, %dmV, current:%duA", data->raw, + LOG_DBG("%d/%d, %dmV, current:%dmA", data->raw, (1 << data->sequence.resolution) - 1, raw_val, i_ma); val->val1 = i_ma / 1000; - val->val2 = i_ma % 1000; + val->val2 = (i_ma % 1000) * 1000; return 0; } diff --git a/drivers/sensor/default_rtio_sensor.c b/drivers/sensor/default_rtio_sensor.c index c21736f792aa2..c6b45e3e173a6 100644 --- a/drivers/sensor/default_rtio_sensor.c +++ b/drivers/sensor/default_rtio_sensor.c @@ -13,10 +13,10 @@ LOG_MODULE_REGISTER(sensor_compat, CONFIG_SENSOR_LOG_LEVEL); /* - * Ensure that the size of the generic header aligns with the sensor channel enum. If it doesn't, - * then cores that require aligned memory access will fail to read channel[0]. + * Ensure that the size of the generic header aligns with the sensor channel specifier . If it + * doesn't, then cores that require aligned memory access will fail to read channel[0]. */ -BUILD_ASSERT((sizeof(struct sensor_data_generic_header) % sizeof(enum sensor_channel)) == 0); +BUILD_ASSERT((sizeof(struct sensor_data_generic_header) % sizeof(struct sensor_chan_spec)) == 0); static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe); @@ -46,12 +46,13 @@ const struct rtio_iodev_api __sensor_iodev_api = { * @param[in] num_channels Number of channels on the @p channels array * @return The number of samples required to read the given channels */ -static inline int compute_num_samples(const enum sensor_channel *channels, size_t num_channels) +static inline int compute_num_samples(const struct sensor_chan_spec *const channels, + size_t num_channels) { int num_samples = 0; for (size_t i = 0; i < num_channels; ++i) { - num_samples += SENSOR_CHANNEL_3_AXIS(channels[i]) ? 3 : 1; + num_samples += SENSOR_CHANNEL_3_AXIS(channels[i].chan_type) ? 3 : 1; } return num_samples; @@ -68,7 +69,7 @@ static inline int compute_num_samples(const enum sensor_channel *channels, size_ static inline uint32_t compute_header_size(int num_output_samples) { uint32_t size = sizeof(struct sensor_data_generic_header) + - (num_output_samples * sizeof(enum sensor_channel)); + (num_output_samples * sizeof(struct sensor_chan_spec)); return (size + 3) & ~0x3; } @@ -92,12 +93,12 @@ static inline uint32_t compute_min_buf_len(int num_output_samples) * @return Index of the @p channel if found or negative if not found */ static inline int check_header_contains_channel(const struct sensor_data_generic_header *header, - enum sensor_channel channel, int num_channels) + struct sensor_chan_spec chan_spec, int num_channels) { - __ASSERT_NO_MSG(!SENSOR_CHANNEL_3_AXIS(channel)); + __ASSERT_NO_MSG(!SENSOR_CHANNEL_3_AXIS(chan_spec.chan_type)); for (int i = 0; i < num_channels; ++i) { - if (header->channels[i] == channel) { + if (sensor_chan_spec_eq(header->channels[i], chan_spec)) { return i; } } @@ -113,7 +114,7 @@ static inline int check_header_contains_channel(const struct sensor_data_generic static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; - const enum sensor_channel *const channels = cfg->channels; + const struct sensor_chan_spec *const channels = cfg->channels; const int num_output_samples = compute_num_samples(channels, cfg->count); uint32_t min_buf_len = compute_min_buf_len(num_output_samples); uint64_t timestamp_ns = k_ticks_to_ns_floor64(k_uptime_ticks()); @@ -148,23 +149,34 @@ static void sensor_submit_fallback(const struct device *dev, struct rtio_iodev_s /* Populate values, update shift, and set channels */ for (size_t i = 0, sample_idx = 0; i < cfg->count; ++i) { struct sensor_value value[3]; - const int num_samples = SENSOR_CHANNEL_3_AXIS(channels[i]) ? 3 : 1; + const int num_samples = SENSOR_CHANNEL_3_AXIS(channels[i].chan_type) ? 3 : 1; /* Get the current channel requested by the user */ - rc = sensor_channel_get(dev, channels[i], value); + rc = sensor_channel_get(dev, channels[i].chan_type, value); if (num_samples == 3) { - header->channels[sample_idx++] = - rc == 0 ? channels[i] - 3 : SENSOR_CHAN_MAX; - header->channels[sample_idx++] = - rc == 0 ? channels[i] - 2 : SENSOR_CHAN_MAX; - header->channels[sample_idx++] = - rc == 0 ? channels[i] - 1 : SENSOR_CHAN_MAX; + header->channels[sample_idx++] = (struct sensor_chan_spec) { + rc == 0 ? channels[i].chan_type - 3 : SENSOR_CHAN_MAX, + 0 + }; + header->channels[sample_idx++] = (struct sensor_chan_spec) { + rc == 0 ? channels[i].chan_type - 2 : SENSOR_CHAN_MAX, + 0 + }; + header->channels[sample_idx++] = (struct sensor_chan_spec) { + rc == 0 ? channels[i].chan_type - 1 : SENSOR_CHAN_MAX, + 0 + }; } else { - header->channels[sample_idx++] = rc == 0 ? channels[i] : SENSOR_CHAN_MAX; + header->channels[sample_idx++] = (struct sensor_chan_spec) { + rc == 0 ? channels[i].chan_type : SENSOR_CHAN_MAX, + 0 + }; } if (rc != 0) { + LOG_DBG("Failed to get channel (type: %d, index %d), skipping", + channels[i].chan_type, channels[i].chan_idx); continue; } @@ -277,45 +289,48 @@ void sensor_processing_with_callback(struct rtio *ctx, sensor_processing_callbac * @param[out] frame_count The number of frames in the buffer (always 1) * @return 0 in all cases */ -static int get_frame_count(const uint8_t *buffer, enum sensor_channel channel, size_t channel_idx, +static int get_frame_count(const uint8_t *buffer, struct sensor_chan_spec channel, uint16_t *frame_count) { struct sensor_data_generic_header *header = (struct sensor_data_generic_header *)buffer; - size_t count = 0; - switch (channel) { + switch (channel.chan_type) { case SENSOR_CHAN_ACCEL_XYZ: - channel = SENSOR_CHAN_ACCEL_X; + channel.chan_type = SENSOR_CHAN_ACCEL_X; break; case SENSOR_CHAN_GYRO_XYZ: - channel = SENSOR_CHAN_GYRO_X; + channel.chan_type = SENSOR_CHAN_GYRO_X; break; case SENSOR_CHAN_MAGN_XYZ: - channel = SENSOR_CHAN_MAGN_X; + channel.chan_type = SENSOR_CHAN_MAGN_X; + break; + case SENSOR_CHAN_POS_DXYZ: + channel.chan_type = SENSOR_CHAN_POS_DX; break; default: break; } for (size_t i = 0; i < header->num_channels; ++i) { - if (header->channels[i] == channel) { - if (channel_idx == count) { - *frame_count = 1; - return 0; - } - ++count; + if (sensor_chan_spec_eq(header->channels[i], channel)) { + *frame_count = 1; + return 0; } } return -ENOTSUP; } -int sensor_natively_supported_channel_size_info(enum sensor_channel channel, size_t *base_size, +int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, size_t *base_size, size_t *frame_size) { __ASSERT_NO_MSG(base_size != NULL); __ASSERT_NO_MSG(frame_size != NULL); - switch (channel) { + if (((int)channel.chan_type < 0) || channel.chan_type >= (SENSOR_CHAN_ALL)) { + return -ENOTSUP; + } + + switch (channel.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -331,52 +346,10 @@ int sensor_natively_supported_channel_size_info(enum sensor_channel channel, siz case SENSOR_CHAN_POS_DX: case SENSOR_CHAN_POS_DY: case SENSOR_CHAN_POS_DZ: + case SENSOR_CHAN_POS_DXYZ: *base_size = sizeof(struct sensor_three_axis_data); *frame_size = sizeof(struct sensor_three_axis_sample_data); return 0; - case SENSOR_CHAN_DIE_TEMP: - case SENSOR_CHAN_AMBIENT_TEMP: - case SENSOR_CHAN_PRESS: - case SENSOR_CHAN_HUMIDITY: - case SENSOR_CHAN_LIGHT: - case SENSOR_CHAN_IR: - case SENSOR_CHAN_RED: - case SENSOR_CHAN_GREEN: - case SENSOR_CHAN_BLUE: - case SENSOR_CHAN_ALTITUDE: - case SENSOR_CHAN_PM_1_0: - case SENSOR_CHAN_PM_2_5: - case SENSOR_CHAN_PM_10: - case SENSOR_CHAN_DISTANCE: - case SENSOR_CHAN_CO2: - case SENSOR_CHAN_VOC: - case SENSOR_CHAN_GAS_RES: - case SENSOR_CHAN_VOLTAGE: - case SENSOR_CHAN_CURRENT: - case SENSOR_CHAN_POWER: - case SENSOR_CHAN_RESISTANCE: - case SENSOR_CHAN_ROTATION: - case SENSOR_CHAN_RPM: - case SENSOR_CHAN_GAUGE_VOLTAGE: - case SENSOR_CHAN_GAUGE_AVG_CURRENT: - case SENSOR_CHAN_GAUGE_STDBY_CURRENT: - case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT: - case SENSOR_CHAN_GAUGE_TEMP: - case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE: - case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY: - case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY: - case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY: - case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY: - case SENSOR_CHAN_GAUGE_AVG_POWER: - case SENSOR_CHAN_GAUGE_STATE_OF_HEALTH: - case SENSOR_CHAN_GAUGE_TIME_TO_EMPTY: - case SENSOR_CHAN_GAUGE_TIME_TO_FULL: - case SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE: - case SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE: - case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT: - *base_size = sizeof(struct sensor_q31_data); - *frame_size = sizeof(struct sensor_q31_sample_data); - return 0; case SENSOR_CHAN_PROX: *base_size = sizeof(struct sensor_byte_data); *frame_size = sizeof(struct sensor_byte_sample_data); @@ -386,24 +359,20 @@ int sensor_natively_supported_channel_size_info(enum sensor_channel channel, siz *frame_size = sizeof(struct sensor_uint64_sample_data); return 0; default: - return -ENOTSUP; + *base_size = sizeof(struct sensor_q31_data); + *frame_size = sizeof(struct sensor_q31_sample_data); + return 0; } } static int get_q31_value(const struct sensor_data_generic_header *header, const q31_t *values, - enum sensor_channel channel, size_t channel_idx, q31_t *out) + struct sensor_chan_spec chan_spec, q31_t *out) { - size_t count = 0; - for (size_t i = 0; i < header->num_channels; ++i) { - if (channel != header->channels[i]) { - continue; - } - if (count == channel_idx) { + if (sensor_chan_spec_eq(chan_spec, header->channels[i])) { *out = values[i]; return 0; } - ++count; } return -EINVAL; } @@ -419,15 +388,18 @@ static int decode_three_axis(const struct sensor_data_generic_header *header, co data_out->shift = header->shift; data_out->readings[0].timestamp_delta = 0; - rc = get_q31_value(header, values, x, channel_idx, &data_out->readings[0].values[0]); + rc = get_q31_value(header, values, (struct sensor_chan_spec){x, channel_idx}, + &data_out->readings[0].values[0]); if (rc < 0) { return rc; } - rc = get_q31_value(header, values, y, channel_idx, &data_out->readings[0].values[1]); + rc = get_q31_value(header, values, (struct sensor_chan_spec){y, channel_idx}, + &data_out->readings[0].values[1]); if (rc < 0) { return rc; } - rc = get_q31_value(header, values, z, channel_idx, &data_out->readings[0].values[2]); + rc = get_q31_value(header, values, (struct sensor_chan_spec){z, channel_idx}, + &data_out->readings[0].values[2]); if (rc < 0) { return rc; } @@ -435,8 +407,7 @@ static int decode_three_axis(const struct sensor_data_generic_header *header, co } static int decode_q31(const struct sensor_data_generic_header *header, const q31_t *values, - struct sensor_q31_data *data_out, enum sensor_channel channel, - size_t channel_idx) + struct sensor_q31_data *data_out, struct sensor_chan_spec chan_spec) { int rc; @@ -445,7 +416,7 @@ static int decode_q31(const struct sensor_data_generic_header *header, const q31 data_out->shift = header->shift; data_out->readings[0].timestamp_delta = 0; - rc = get_q31_value(header, values, channel, channel_idx, &data_out->readings[0].value); + rc = get_q31_value(header, values, chan_spec, &data_out->readings[0].value); if (rc < 0) { return rc; } @@ -469,7 +440,7 @@ static int decode_q31(const struct sensor_data_generic_header *header, const q31 * @return >0 the number of decoded frames * @return <0 on error */ -static int decode(const uint8_t *buffer, enum sensor_channel channel, size_t channel_idx, +static int decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, uint32_t *fit, uint16_t max_count, void *data_out) { const struct sensor_data_generic_header *header = @@ -481,78 +452,46 @@ static int decode(const uint8_t *buffer, enum sensor_channel channel, size_t cha return -EINVAL; } + if (((int)chan_spec.chan_type < 0) || chan_spec.chan_type >= (SENSOR_CHAN_ALL)) { + return 0; + } + /* Check for 3d channel mappings */ - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: case SENSOR_CHAN_ACCEL_XYZ: count = decode_three_axis(header, q, data_out, SENSOR_CHAN_ACCEL_X, - SENSOR_CHAN_ACCEL_Y, SENSOR_CHAN_ACCEL_Z, channel_idx); + SENSOR_CHAN_ACCEL_Y, SENSOR_CHAN_ACCEL_Z, + chan_spec.chan_idx); break; case SENSOR_CHAN_GYRO_X: case SENSOR_CHAN_GYRO_Y: case SENSOR_CHAN_GYRO_Z: case SENSOR_CHAN_GYRO_XYZ: count = decode_three_axis(header, q, data_out, SENSOR_CHAN_GYRO_X, - SENSOR_CHAN_GYRO_Y, SENSOR_CHAN_GYRO_Z, channel_idx); + SENSOR_CHAN_GYRO_Y, SENSOR_CHAN_GYRO_Z, + chan_spec.chan_idx); break; case SENSOR_CHAN_MAGN_X: case SENSOR_CHAN_MAGN_Y: case SENSOR_CHAN_MAGN_Z: case SENSOR_CHAN_MAGN_XYZ: count = decode_three_axis(header, q, data_out, SENSOR_CHAN_MAGN_X, - SENSOR_CHAN_MAGN_Y, SENSOR_CHAN_MAGN_Z, channel_idx); + SENSOR_CHAN_MAGN_Y, SENSOR_CHAN_MAGN_Z, + chan_spec.chan_idx); break; case SENSOR_CHAN_POS_DX: case SENSOR_CHAN_POS_DY: case SENSOR_CHAN_POS_DZ: + case SENSOR_CHAN_POS_DXYZ: count = decode_three_axis(header, q, data_out, SENSOR_CHAN_POS_DX, - SENSOR_CHAN_POS_DY, SENSOR_CHAN_POS_DZ, channel_idx); - break; - case SENSOR_CHAN_DIE_TEMP: - case SENSOR_CHAN_AMBIENT_TEMP: - case SENSOR_CHAN_PRESS: - case SENSOR_CHAN_HUMIDITY: - case SENSOR_CHAN_LIGHT: - case SENSOR_CHAN_IR: - case SENSOR_CHAN_RED: - case SENSOR_CHAN_GREEN: - case SENSOR_CHAN_BLUE: - case SENSOR_CHAN_ALTITUDE: - case SENSOR_CHAN_PM_1_0: - case SENSOR_CHAN_PM_2_5: - case SENSOR_CHAN_PM_10: - case SENSOR_CHAN_DISTANCE: - case SENSOR_CHAN_CO2: - case SENSOR_CHAN_VOC: - case SENSOR_CHAN_GAS_RES: - case SENSOR_CHAN_VOLTAGE: - case SENSOR_CHAN_CURRENT: - case SENSOR_CHAN_POWER: - case SENSOR_CHAN_RESISTANCE: - case SENSOR_CHAN_ROTATION: - case SENSOR_CHAN_RPM: - case SENSOR_CHAN_GAUGE_VOLTAGE: - case SENSOR_CHAN_GAUGE_AVG_CURRENT: - case SENSOR_CHAN_GAUGE_STDBY_CURRENT: - case SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT: - case SENSOR_CHAN_GAUGE_TEMP: - case SENSOR_CHAN_GAUGE_STATE_OF_CHARGE: - case SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY: - case SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY: - case SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY: - case SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY: - case SENSOR_CHAN_GAUGE_AVG_POWER: - case SENSOR_CHAN_GAUGE_STATE_OF_HEALTH: - case SENSOR_CHAN_GAUGE_TIME_TO_EMPTY: - case SENSOR_CHAN_GAUGE_TIME_TO_FULL: - case SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE: - case SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE: - case SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT: - count = decode_q31(header, q, data_out, channel, channel_idx); + SENSOR_CHAN_POS_DY, SENSOR_CHAN_POS_DZ, + chan_spec.chan_idx); break; default: + count = decode_q31(header, q, data_out, chan_spec); break; } if (count > 0) { diff --git a/drivers/sensor/ens160/ens160.c b/drivers/sensor/ens160/ens160.c index a2b0fb7103e57..c5420b7cd39d5 100644 --- a/drivers/sensor/ens160/ens160.c +++ b/drivers/sensor/ens160/ens160.c @@ -148,6 +148,7 @@ static int ens160_channel_get(const struct device *dev, enum sensor_channel chan case SENSOR_CHAN_ENS160_AQI: val->val1 = data->aqi; val->val2 = 0; + break; default: return -ENOTSUP; } diff --git a/drivers/sensor/f75303/f75303_emul.c b/drivers/sensor/f75303/f75303_emul.c index 7e906af5f04d7..fe1dbc5d3452f 100644 --- a/drivers/sensor/f75303/f75303_emul.c +++ b/drivers/sensor/f75303/f75303_emul.c @@ -103,7 +103,7 @@ static int f75303_emul_init(const struct emul *target, const struct device *pare return 0; } -static int f75303_emul_set_channel(const struct emul *target, enum sensor_channel chan, +static int f75303_emul_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { struct f75303_emul_data *data = target->data; @@ -112,7 +112,7 @@ static int f75303_emul_set_channel(const struct emul *target, enum sensor_channe int32_t reg_value; uint8_t reg_h, reg_l; - switch ((int32_t)chan) { + switch ((int32_t)ch.chan_type) { case SENSOR_CHAN_AMBIENT_TEMP: reg_h = F75303_LOCAL_TEMP_H; reg_l = F75303_LOCAL_TEMP_L; @@ -139,12 +139,12 @@ static int f75303_emul_set_channel(const struct emul *target, enum sensor_channe return 0; } -static int f75303_emul_get_sample_range(const struct emul *target, enum sensor_channel chan, +static int f75303_emul_get_sample_range(const struct emul *target, struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) { - if (chan != SENSOR_CHAN_AMBIENT_TEMP && - chan != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE1 && - chan != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE2) { + if (ch.chan_type != SENSOR_CHAN_AMBIENT_TEMP && + ch.chan_type != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE1 && + ch.chan_type != (enum sensor_channel)SENSOR_CHAN_F75303_REMOTE2) { return -ENOTSUP; } diff --git a/drivers/sensor/grow_r502a/Kconfig b/drivers/sensor/grow_r502a/Kconfig index 53c31f3c80407..35297b90b655f 100644 --- a/drivers/sensor/grow_r502a/Kconfig +++ b/drivers/sensor/grow_r502a/Kconfig @@ -13,6 +13,15 @@ menuconfig GROW_R502A if GROW_R502A +config R502A_DATA_PKT_SIZE + int "Template data packet size" + default 128 + help + Template data packet size for upload and download + to the sensor device. + valid values are: + 32, 64, 128, 256. + choice prompt "Trigger mode" default GROW_R502A_TRIGGER_NONE diff --git a/drivers/sensor/grow_r502a/grow_r502a.c b/drivers/sensor/grow_r502a/grow_r502a.c index 028b591940722..15714314b95f4 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.c +++ b/drivers/sensor/grow_r502a/grow_r502a.c @@ -4,14 +4,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -#define DT_DRV_COMPAT hzgrow_r502a - #include #include #include #include #include #include +#include +#include #include #include "grow_r502a.h" @@ -19,35 +19,107 @@ #include LOG_MODULE_REGISTER(GROW_R502A, CONFIG_SENSOR_LOG_LEVEL); -static void transceive_packet(const struct device *dev, union r502a_packet *tx_packet, - union r502a_packet *rx_packet, char const data_len) +static int transceive_packet(const struct device *dev, union r502a_packet *tx_packet, + union r502a_packet *rx_packet, uint16_t data_len) { const struct grow_r502a_config *cfg = dev->config; struct grow_r502a_data *drv_data = dev->data; - uint16_t check_sum, pkg_len; - pkg_len = data_len + R502A_CHECKSUM_LEN; - check_sum = pkg_len + tx_packet->pid; + if (tx_packet) { + uint16_t check_sum, pkg_len; + + pkg_len = data_len + R502A_CHECKSUM_LEN; + check_sum = (pkg_len >> 8) + (pkg_len & 0xFF) + tx_packet->pid; + + tx_packet->start = sys_cpu_to_be16(R502A_STARTCODE); + tx_packet->addr = sys_cpu_to_be32(cfg->comm_addr); + tx_packet->len = sys_cpu_to_be16(pkg_len); + + for (int i = 0; i < data_len; i++) { + check_sum += tx_packet->data[i]; + } + sys_put_be16(check_sum, &tx_packet->buf[data_len + R502A_HEADER_LEN]); + + drv_data->tx_buf.len = pkg_len + R502A_HEADER_LEN; + drv_data->tx_buf.data = tx_packet->buf; + + LOG_HEXDUMP_DBG(drv_data->tx_buf.data, drv_data->tx_buf.len, "TX"); + + uart_irq_tx_enable(cfg->dev); - sys_put_be16(R502A_STARTCODE, tx_packet->start); - sys_put_be32(cfg->comm_addr, tx_packet->addr); - sys_put_be16(pkg_len, tx_packet->len); - for (int i = 0; i < data_len; i++) { - check_sum += tx_packet->data[i]; + if (k_sem_take(&drv_data->uart_tx_sem, K_MSEC(1500)) != 0) { + LOG_ERR("Tx data timeout"); + return -ETIMEDOUT; + } } - sys_put_be16(check_sum, &tx_packet->buf[data_len + R502A_HEADER_LEN]); - drv_data->tx_buf.len = pkg_len + R502A_HEADER_LEN; - drv_data->tx_buf.data = tx_packet->buf; + if (rx_packet) { + drv_data->rx_buf.data = rx_packet->buf; + drv_data->rx_buf.len = 0; + drv_data->pkt_len = R502A_HEADER_LEN; + uart_irq_rx_enable(cfg->dev); + if (k_sem_take(&drv_data->uart_rx_sem, K_MSEC(1500)) != 0) { + LOG_ERR("Rx data timeout"); + return -ETIMEDOUT; + } + } - drv_data->rx_buf.data = rx_packet->buf; + return 0; +} - LOG_HEXDUMP_DBG(drv_data->tx_buf.data, drv_data->tx_buf.len, "TX"); +static int r502a_validate_rx_packet(union r502a_packet *rx_packet) +{ + uint16_t recv_cks = 0, calc_cks = 0; + uint8_t cks_start_idx; - uart_irq_rx_disable(cfg->dev); - uart_irq_tx_enable(cfg->dev); + if (sys_be16_to_cpu(rx_packet->start) == R502A_STARTCODE) { + LOG_DBG("startcode matched 0x%X", sys_be16_to_cpu(rx_packet->start)); + } else { + LOG_ERR("startcode didn't match 0x%X", sys_be16_to_cpu(rx_packet->start)); + return -EINVAL; + } + + if (sys_be32_to_cpu(rx_packet->addr) == R502A_DEFAULT_ADDRESS) { + LOG_DBG("Address matched 0x%X", sys_be32_to_cpu(rx_packet->addr)); + } else { + LOG_ERR("Address didn't match 0x%X", sys_be32_to_cpu(rx_packet->addr)); + return -EINVAL; + } - k_sem_take(&drv_data->uart_rx_sem, K_FOREVER); + switch (rx_packet->pid) { + case R502A_DATA_PACKET: + LOG_DBG("Data Packet Received 0x%X", rx_packet->pid); + break; + case R502A_END_DATA_PACKET: + LOG_DBG("End of Data Packet Received 0x%X", rx_packet->pid); + break; + case R502A_ACK_PACKET: + LOG_DBG("Acknowledgment Packet Received 0x%X", rx_packet->pid); + break; + default: + LOG_ERR("Error Package ID 0x%X", rx_packet->pid); + return -EINVAL; + } + + cks_start_idx = sys_be16_to_cpu(rx_packet->len) - R502A_CHECKSUM_LEN; + + recv_cks = sys_get_be16(&rx_packet->data[cks_start_idx]); + + calc_cks += rx_packet->pid + (sys_be16_to_cpu(rx_packet->len) >> 8) + + (sys_be16_to_cpu(rx_packet->len) & 0xFF); + + for (int i = 0; i < cks_start_idx; i++) { + calc_cks += rx_packet->data[i]; + } + + if (recv_cks == calc_cks) { + LOG_DBG("Checksum matched calculated 0x%x received 0x%x", calc_cks, recv_cks); + } else { + LOG_ERR("Checksum mismatch calculated 0x%x received 0x%x", calc_cks, recv_cks); + return -EINVAL; + } + + return 0; } static void uart_cb_tx_handler(const struct device *dev) @@ -55,21 +127,18 @@ static void uart_cb_tx_handler(const struct device *dev) const struct grow_r502a_config *config = dev->config; struct grow_r502a_data *drv_data = dev->data; int sent = 0; - uint8_t retries = 3; - while (drv_data->tx_buf.len) { - sent = uart_fifo_fill(config->dev, &drv_data->tx_buf.data[sent], + if (drv_data->tx_buf.len > 0) { + sent = uart_fifo_fill(config->dev, drv_data->tx_buf.data, drv_data->tx_buf.len); + drv_data->tx_buf.data += sent; drv_data->tx_buf.len -= sent; } - while (retries--) { - if (uart_irq_tx_complete(config->dev)) { - uart_irq_tx_disable(config->dev); - drv_data->rx_buf.len = 0; - uart_irq_rx_enable(config->dev); - break; - } + if (!drv_data->tx_buf.len && uart_irq_tx_complete(config->dev) > 0) { + uart_irq_tx_disable(config->dev); + k_sem_give(&drv_data->uart_tx_sem); + return; } } @@ -77,7 +146,7 @@ static void uart_cb_handler(const struct device *dev, void *user_data) { const struct device *uart_dev = user_data; struct grow_r502a_data *drv_data = uart_dev->data; - int len, pkt_sz = 0; + int len = 0; int offset = drv_data->rx_buf.len; if ((uart_irq_update(dev) > 0) && (uart_irq_is_pending(dev) > 0)) { @@ -87,28 +156,131 @@ static void uart_cb_handler(const struct device *dev, void *user_data) while (uart_irq_rx_ready(dev)) { len = uart_fifo_read(dev, &drv_data->rx_buf.data[offset], - R502A_BUF_SIZE - offset); + drv_data->pkt_len); offset += len; drv_data->rx_buf.len = offset; - if (offset >= R502A_HEADER_LEN) { - pkt_sz = R502A_HEADER_LEN + - drv_data->rx_buf.data[R502A_HEADER_LEN-1]; + if (drv_data->pkt_len != len) { + drv_data->pkt_len -= len; + continue; } - if (offset < pkt_sz) { + + if (offset == R502A_HEADER_LEN) { + drv_data->pkt_len = sys_get_be16( + &drv_data->rx_buf.data[R502A_PKG_LEN_IDX] + ); continue; } + LOG_HEXDUMP_DBG(drv_data->rx_buf.data, offset, "RX"); + uart_irq_rx_disable(dev); k_sem_give(&drv_data->uart_rx_sem); break; } } } -static int fps_led_control(const struct device *dev, struct led_params *led_control) +/** + * @brief Set sensor device's basic parameters like baud rate, security level + * and data package length. + */ +static int fps_set_sys_param(const struct device *dev, const struct sensor_value *val) +{ + union r502a_packet rx_packet = {0}; + int ret = 0; + char const set_sys_param_len = 3; + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = { R502A_SETSYSPARAM, val->val1, val->val2} + }; + + ret = transceive_packet(dev, &tx_packet, &rx_packet, set_sys_param_len); + if (ret != 0) { + return ret; + } + + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; + } + + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("R502A set system parameter success"); + } else { + LOG_ERR("R502A set system parameter error %d", rx_packet.buf[R502A_CC_IDX]); + return -EIO; + } + + return 0; +} + +int r502a_read_sys_param(const struct device *dev, struct r502a_sys_param *val) +{ + struct grow_r502a_data *drv_data = dev->data; + + union r502a_packet rx_packet = {0}; + int offset = 0, ret = 0; + char const read_sys_param_len = 1; + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_READSYSPARAM} + }; + + k_mutex_lock(&drv_data->lock, K_FOREVER); + + ret = transceive_packet(dev, &tx_packet, &rx_packet, read_sys_param_len); + if (ret != 0) { + goto unlock; + } + + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + goto unlock; + } + + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("R502A read system parameter success"); + } else { + LOG_ERR("R502A read system parameter error %d", rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; + goto unlock; + } + + val->status_reg = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, status_reg) + 1] + ); + val->system_id = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, system_id) + 1] + ); + val->lib_size = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, lib_size) + 1] + ); + val->sec_level = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, sec_level) + 1] + ); + val->addr = sys_get_be32( + &rx_packet.data[offsetof(struct r502a_sys_param, addr) + 1] + ); + offset = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, data_pkt_size) + 1] + ); + val->data_pkt_size = 32 * (1 << offset); + val->baud = sys_get_be16( + &rx_packet.data[offsetof(struct r502a_sys_param, baud) + 1] + ) * 9600; + +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; +} + +static int fps_led_control(const struct device *dev, struct r502a_led_params *led_control) { union r502a_packet rx_packet = {0}; char const led_ctrl_len = 5; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, @@ -116,11 +288,14 @@ static int fps_led_control(const struct device *dev, struct led_params *led_cont led_control->speed, led_control->color_idx, led_control->cycle} }; - transceive_packet(dev, &tx_packet, &rx_packet, led_ctrl_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, led_ctrl_len); + if (ret != 0) { + return ret; + } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -138,6 +313,7 @@ static int fps_verify_password(const struct device *dev) { union r502a_packet rx_packet = {0}; char const verify_pwd_len = 5; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, @@ -146,17 +322,20 @@ static int fps_verify_password(const struct device *dev) sys_put_be32(R502A_DEFAULT_PASSWORD, &tx_packet.data[1]); - transceive_packet(dev, &tx_packet, &rx_packet, verify_pwd_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, verify_pwd_len); + if (ret != 0) { + return ret; + } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { LOG_DBG("Correct password, R502A verified"); } else { - LOG_ERR("Package receive error 0x%X", rx_packet.buf[R502A_CC_IDX]); + LOG_ERR("Password verification error 0x%X", rx_packet.buf[R502A_CC_IDX]); return -EIO; } @@ -168,17 +347,21 @@ static int fps_get_template_count(const struct device *dev) struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; char const get_temp_cnt_len = 1; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, .data = {R502A_TEMPLATECOUNT}, }; - transceive_packet(dev, &tx_packet, &rx_packet, get_temp_cnt_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, get_temp_cnt_len); + if (ret != 0) { + return ret; + } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -193,7 +376,7 @@ static int fps_get_template_count(const struct device *dev) return 0; } -static int fps_read_template_table(const struct device *dev) +static int fps_read_template_table(const struct device *dev, uint32_t *free_idx) { struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; @@ -207,13 +390,14 @@ static int fps_read_template_table(const struct device *dev) k_mutex_lock(&drv_data->lock, K_FOREVER); - transceive_packet(dev, &tx_packet, &rx_packet, temp_table_len); - - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = transceive_packet(dev, &tx_packet, &rx_packet, temp_table_len); + if (ret != 0) { goto unlock; + } + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + goto unlock; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -232,7 +416,7 @@ static int fps_read_template_table(const struct device *dev) continue; } - drv_data->free_idx = (group_idx * 8) + find_lsb_set(~group) - 1; + *free_idx = (group_idx * 8) + find_lsb_set(~group) - 1; goto unlock; } @@ -245,11 +429,12 @@ static int fps_get_image(const struct device *dev) { union r502a_packet rx_packet = {0}; char const get_img_len = 1; + int ret = 0; - struct led_params led_ctrl = { - .ctrl_code = LED_CTRL_BREATHING, - .color_idx = LED_COLOR_BLUE, - .speed = LED_SPEED_HALF, + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_BREATHING, + .color_idx = R502A_LED_COLOR_BLUE, + .speed = R502A_LED_SPEED_HALF, .cycle = 0x01, }; @@ -258,19 +443,22 @@ static int fps_get_image(const struct device *dev) .data = {R502A_GENIMAGE}, }; - transceive_packet(dev, &tx_packet, &rx_packet, get_img_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, get_img_len); + if (ret != 0) { + return ret; + } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { fps_led_control(dev, &led_ctrl); LOG_DBG("Image taken"); } else { - led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS; - led_ctrl.color_idx = LED_COLOR_RED; + led_ctrl.ctrl_code = R502A_LED_CTRL_ON_ALWAYS; + led_ctrl.color_idx = R502A_LED_COLOR_RED; fps_led_control(dev, &led_ctrl); LOG_ERR("Error getting image 0x%X", rx_packet.buf[R502A_CC_IDX]); return -EIO; @@ -283,17 +471,21 @@ static int fps_image_to_char(const struct device *dev, uint8_t char_buf_idx) { union r502a_packet rx_packet = {0}; char const img_to_char_len = 2; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, .data = {R502A_IMAGE2TZ, char_buf_idx} }; - transceive_packet(dev, &tx_packet, &rx_packet, img_to_char_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, img_to_char_len); + if (ret != 0) { + return ret; + } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -310,17 +502,21 @@ static int fps_create_model(const struct device *dev) { union r502a_packet rx_packet = {0}; char const create_model_len = 1; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, .data = {R502A_REGMODEL} }; - transceive_packet(dev, &tx_packet, &rx_packet, create_model_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, create_model_len); + if (ret != 0) { + return ret; + } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + return ret; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { @@ -335,13 +531,15 @@ static int fps_create_model(const struct device *dev) static int fps_store_model(const struct device *dev, uint16_t id) { + struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; char const store_model_len = 4; + int ret = 0; - struct led_params led_ctrl = { - .ctrl_code = LED_CTRL_BREATHING, - .color_idx = LED_COLOR_BLUE, - .speed = LED_SPEED_HALF, + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_BREATHING, + .color_idx = R502A_LED_COLOR_BLUE, + .speed = R502A_LED_SPEED_HALF, .cycle = 0x01, }; @@ -351,31 +549,39 @@ static int fps_store_model(const struct device *dev, uint16_t id) }; sys_put_be16(id, &tx_packet.data[2]); - transceive_packet(dev, &tx_packet, &rx_packet, store_model_len); + k_mutex_lock(&drv_data->lock, K_FOREVER); - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = transceive_packet(dev, &tx_packet, &rx_packet, store_model_len); + if (ret != 0) { + goto unlock; + } + + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + goto unlock; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { - led_ctrl.color_idx = LED_COLOR_BLUE; - led_ctrl.ctrl_code = LED_CTRL_FLASHING; + led_ctrl.color_idx = R502A_LED_COLOR_BLUE; + led_ctrl.ctrl_code = R502A_LED_CTRL_FLASHING; led_ctrl.cycle = 0x03; fps_led_control(dev, &led_ctrl); LOG_INF("Fingerprint stored! at ID #%d", id); } else { LOG_ERR("Error storing model 0x%X", rx_packet.buf[R502A_CC_IDX]); - return -EIO; + ret = -EIO; } - - return 0; +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; } static int fps_delete_model(const struct device *dev, uint16_t id, uint16_t count) { + struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; char const delete_model_len = 5; + int ret = 0; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, @@ -384,21 +590,27 @@ static int fps_delete_model(const struct device *dev, uint16_t id, uint16_t coun sys_put_be16(id, &tx_packet.data[1]); sys_put_be16(count + R502A_DELETE_COUNT_OFFSET, &tx_packet.data[3]); - transceive_packet(dev, &tx_packet, &rx_packet, delete_model_len); + k_mutex_lock(&drv_data->lock, K_FOREVER); - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = transceive_packet(dev, &tx_packet, &rx_packet, delete_model_len); + if (ret != 0) { + goto unlock; + } + + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + goto unlock; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { LOG_INF("Fingerprint Deleted from ID #%d to #%d", id, (id + count)); } else { LOG_ERR("Error deleting image 0x%X", rx_packet.buf[R502A_CC_IDX]); - return -EIO; + ret = -EIO; } - - return 0; +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; } static int fps_empty_db(const struct device *dev) @@ -415,11 +627,13 @@ static int fps_empty_db(const struct device *dev) k_mutex_lock(&drv_data->lock, K_FOREVER); - transceive_packet(dev, &tx_packet, &rx_packet, empty_db_len); + ret = transceive_packet(dev, &tx_packet, &rx_packet, empty_db_len); + if (ret != 0) { + goto unlock; + } - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - ret = -EIO; + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { goto unlock; } @@ -429,152 +643,320 @@ static int fps_empty_db(const struct device *dev) LOG_ERR("Error emptying fingerprint library 0x%X", rx_packet.buf[R502A_CC_IDX]); ret = -EIO; - goto unlock; } unlock: k_mutex_unlock(&drv_data->lock); - return 0; + return ret; } -static int fps_search(const struct device *dev, uint8_t char_buf_idx) +static int fps_search(const struct device *dev, struct sensor_value *val) { struct grow_r502a_data *drv_data = dev->data; union r502a_packet rx_packet = {0}; char const search_len = 6; + int ret = 0; - struct led_params led_ctrl = { - .ctrl_code = LED_CTRL_BREATHING, - .color_idx = LED_COLOR_BLUE, - .speed = LED_SPEED_HALF, + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_BREATHING, + .color_idx = R502A_LED_COLOR_BLUE, + .speed = R502A_LED_SPEED_HALF, .cycle = 0x01, }; union r502a_packet tx_packet = { .pid = R502A_COMMAND_PACKET, - .data = {R502A_SEARCH, char_buf_idx} + .data = {R502A_SEARCH, R502A_CHAR_BUF_1} }; - sys_put_be16(R02A_LIBRARY_START_IDX, &tx_packet.data[1]); - sys_put_be16(R502A_DEFAULT_CAPACITY, &tx_packet.data[3]); + sys_put_be16(R02A_LIBRARY_START_IDX, &tx_packet.data[2]); + sys_put_be16(R502A_DEFAULT_CAPACITY, &tx_packet.data[4]); - transceive_packet(dev, &tx_packet, &rx_packet, search_len); + k_mutex_lock(&drv_data->lock, K_FOREVER); - if (rx_packet.pid != R502A_ACK_PACKET) { - LOG_ERR("Error receiving ack packet 0x%X", rx_packet.pid); - return -EIO; + ret = transceive_packet(dev, &tx_packet, &rx_packet, search_len); + if (ret != 0) { + goto unlock; + } + + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + goto unlock; } if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { - led_ctrl.ctrl_code = LED_CTRL_FLASHING; - led_ctrl.color_idx = LED_COLOR_PURPLE; + led_ctrl.ctrl_code = R502A_LED_CTRL_FLASHING; + led_ctrl.color_idx = R502A_LED_COLOR_PURPLE; led_ctrl.cycle = 0x01; fps_led_control(dev, &led_ctrl); - drv_data->finger_id = sys_get_be16(&rx_packet.data[1]); - drv_data->matching_score = sys_get_be16(&rx_packet.data[3]); - LOG_INF("Found a matching print! at ID #%d", drv_data->finger_id); - } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_FOUND) { - led_ctrl.ctrl_code = LED_CTRL_BREATHING; - led_ctrl.color_idx = LED_COLOR_RED; + val->val1 = sys_get_be16(&rx_packet.data[1]); + val->val2 = sys_get_be16(&rx_packet.data[3]); + LOG_INF("Found a matching print! at ID #%d", val->val1); + } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_FOUND_CC) { + led_ctrl.ctrl_code = R502A_LED_CTRL_BREATHING; + led_ctrl.color_idx = R502A_LED_COLOR_RED; led_ctrl.cycle = 0x02; fps_led_control(dev, &led_ctrl); LOG_ERR("Did not find a match"); + ret = -ENOENT; } else { - led_ctrl.ctrl_code = LED_CTRL_ON_ALWAYS; - led_ctrl.color_idx = LED_COLOR_RED; + led_ctrl.ctrl_code = R502A_LED_CTRL_ON_ALWAYS; + led_ctrl.color_idx = R502A_LED_COLOR_RED; fps_led_control(dev, &led_ctrl); LOG_ERR("Error searching for image 0x%X", rx_packet.buf[R502A_CC_IDX]); - return -EIO; + ret = -EIO; } - - return 0; +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; } -static int fps_enroll(const struct device *dev, const struct sensor_value *val) +static int fps_load_template(const struct device *dev, uint16_t id) { struct grow_r502a_data *drv_data = dev->data; - int ret = -1; + union r502a_packet rx_packet = {0}; + char const load_tmp_len = 4; + int ret = 0; - if (val->val1 < 0 || val->val1 > R502A_DEFAULT_CAPACITY) { - LOG_ERR("Invalid ID number"); - return -EINVAL; + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_LOAD, R502A_CHAR_BUF_1} + }; + sys_put_be16(id, &tx_packet.data[2]); + + k_mutex_lock(&drv_data->lock, K_FOREVER); + + ret = transceive_packet(dev, &tx_packet, &rx_packet, load_tmp_len); + if (ret != 0) { + goto unlock; } + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + goto unlock; + } + + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("Load template data from id #%d to Char_buffer2", id); + } else { + LOG_ERR("Error Loading template 0x%X", + rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; + } + +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; +} + +static int fps_match_templates(const struct device *dev, struct sensor_value *val) +{ + struct grow_r502a_data *drv_data = dev->data; + union r502a_packet rx_packet = {0}; + char const match_templates_len = 1; + int ret = 0; + + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_BREATHING, + .color_idx = R502A_LED_COLOR_BLUE, + .speed = R502A_LED_SPEED_HALF, + .cycle = 0x01, + }; + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_MATCH} + }; + k_mutex_lock(&drv_data->lock, K_FOREVER); - ret = fps_get_image(dev); + ret = transceive_packet(dev, &tx_packet, &rx_packet, match_templates_len); if (ret != 0) { goto unlock; } - ret = fps_image_to_char(dev, R502A_CHAR_BUF_1); + ret = r502a_validate_rx_packet(&rx_packet); if (ret != 0) { goto unlock; } + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + fps_led_control(dev, &led_ctrl); + val->val1 = R502A_FINGER_MATCH_FOUND; + val->val2 = sys_get_be16(&rx_packet.data[1]); + LOG_INF("Fingerprint matched with a score %d", val->val2); + } else if (rx_packet.buf[R502A_CC_IDX] == R502A_NOT_MATCH_CC) { + val->val1 = R502A_FINGER_MATCH_NOT_FOUND; + LOG_ERR("Fingerprint not matched"); + ret = -ENOENT; + } else { + led_ctrl.ctrl_code = R502A_LED_CTRL_ON_ALWAYS; + led_ctrl.color_idx = R502A_LED_COLOR_RED; + fps_led_control(dev, &led_ctrl); + LOG_ERR("Error Matching templates 0x%X", + rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; + } +unlock: + k_mutex_unlock(&drv_data->lock); + return ret; +} + +static int fps_capture(const struct device *dev) +{ + struct grow_r502a_data *drv_data = dev->data; + int ret; + + k_mutex_lock(&drv_data->lock, K_FOREVER); + ret = fps_get_image(dev); if (ret != 0) { goto unlock; } - ret = fps_image_to_char(dev, R502A_CHAR_BUF_2); + ret = fps_image_to_char(dev, R502A_CHAR_BUF_1); if (ret != 0) { goto unlock; } - ret = fps_create_model(dev); + ret = fps_get_image(dev); if (ret != 0) { goto unlock; } - ret = fps_store_model(dev, val->val1); + ret = fps_image_to_char(dev, R502A_CHAR_BUF_2); unlock: k_mutex_unlock(&drv_data->lock); return ret; } -static int fps_delete(const struct device *dev, const struct sensor_value *val) +/** + * @brief upload template from sensor device's RAM buffer 1 to controller. + * + * @result temp->data holds the template to be uploaded to controller. + * temp->len holds the length of the template. + */ +int fps_upload_char_buf(const struct device *dev, struct r502a_template *temp) { struct grow_r502a_data *drv_data = dev->data; - int ret = -1; + union r502a_packet rx_packet = {0}; + char const upload_temp_len = 2; + int ret = 0, idx = 0; + + if (!temp->data || (temp->len < R502A_TEMPLATE_MAX_SIZE)) { + LOG_ERR("Invalid temp data"); + return -EINVAL; + } + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_UPCHAR, R502A_CHAR_BUF_1} + }; k_mutex_lock(&drv_data->lock, K_FOREVER); - ret = fps_delete_model(dev, val->val1, val->val2); + ret = transceive_packet(dev, &tx_packet, &rx_packet, upload_temp_len); if (ret != 0) { goto unlock; } - ret = fps_get_template_count(dev); + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + goto unlock; + } + + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("Upload to host controller"); + } else { + LOG_ERR("Error uploading template 0x%X", + rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; + goto unlock; + } + + do { + ret = transceive_packet(dev, NULL, &rx_packet, 0); + if (ret != 0) { + goto unlock; + } + + ret = r502a_validate_rx_packet(&rx_packet); + if (ret != 0) { + goto unlock; + } + + memcpy(&temp->data[idx], &rx_packet.data, + sys_be16_to_cpu(rx_packet.len) - R502A_CHECKSUM_LEN); + idx += sys_be16_to_cpu(rx_packet.len) - R502A_CHECKSUM_LEN; + } while (rx_packet.pid != R502A_END_DATA_PACKET); + + temp->len = idx; unlock: k_mutex_unlock(&drv_data->lock); return ret; } -static int fps_match(const struct device *dev, struct sensor_value *val) +/** + * @brief download template from controller to sensor device's RAM buffer. + * @Notes char_buf_id - other than value 1 will be considered as value 2 + * by R502A sensor. + */ +int fps_download_char_buf(const struct device *dev, uint8_t char_buf_id, + const struct r502a_template *temp) { struct grow_r502a_data *drv_data = dev->data; - int ret = -1; + union r502a_packet rx_packet = {0}; + char const down_temp_len = 2; + int ret = 0, i = 0; + + if (!temp->data || (temp->len < R502A_TEMPLATE_MAX_SIZE)) { + LOG_ERR("Invalid temp data"); + return -EINVAL; + } + + union r502a_packet tx_packet = { + .pid = R502A_COMMAND_PACKET, + .data = {R502A_DOWNCHAR, char_buf_id} + }; k_mutex_lock(&drv_data->lock, K_FOREVER); - ret = fps_get_image(dev); + ret = transceive_packet(dev, &tx_packet, &rx_packet, down_temp_len); if (ret != 0) { goto unlock; } - ret = fps_image_to_char(dev, R502A_CHAR_BUF_1); + ret = r502a_validate_rx_packet(&rx_packet); if (ret != 0) { goto unlock; } - ret = fps_search(dev, R502A_CHAR_BUF_1); - if (ret == 0) { - val->val1 = drv_data->finger_id; - val->val2 = drv_data->matching_score; + if (rx_packet.buf[R502A_CC_IDX] == R502A_OK) { + LOG_DBG("Download to R502A sensor"); + } else { + LOG_ERR("Error downloading template 0x%X", + rx_packet.buf[R502A_CC_IDX]); + ret = -EIO; + goto unlock; + } + + while (i < (R502A_TEMPLATE_MAX_SIZE - CONFIG_R502A_DATA_PKT_SIZE)) { + tx_packet.pid = R502A_DATA_PACKET; + memcpy(tx_packet.data, &temp->data[i], CONFIG_R502A_DATA_PKT_SIZE); + + ret = transceive_packet(dev, &tx_packet, NULL, CONFIG_R502A_DATA_PKT_SIZE); + if (ret != 0) { + goto unlock; + } + + i += CONFIG_R502A_DATA_PKT_SIZE; } + memcpy(tx_packet.data, &temp->data[i], (R502A_TEMPLATE_MAX_SIZE - i)); + tx_packet.pid = R502A_END_DATA_PACKET; + ret = transceive_packet(dev, &tx_packet, NULL, (R502A_TEMPLATE_MAX_SIZE - i)); + unlock: k_mutex_unlock(&drv_data->lock); return ret; @@ -583,12 +965,13 @@ static int fps_match(const struct device *dev, struct sensor_value *val) static int fps_init(const struct device *dev) { struct grow_r502a_data *drv_data = dev->data; + struct sensor_value val; int ret; - struct led_params led_ctrl = { - .ctrl_code = LED_CTRL_FLASHING, - .color_idx = LED_COLOR_PURPLE, - .speed = LED_SPEED_HALF, + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_FLASHING, + .color_idx = R502A_LED_COLOR_PURPLE, + .speed = R502A_LED_SPEED_HALF, .cycle = 0x02, }; @@ -599,6 +982,13 @@ static int fps_init(const struct device *dev) goto unlock; } + val.val1 = R502A_DATA_PKG_LEN; + val.val2 = LOG2(CONFIG_R502A_DATA_PKT_SIZE >> 5); + ret = fps_set_sys_param(dev, &val); + if (ret != 0) { + goto unlock; + } + ret = fps_led_control(dev, &led_ctrl); unlock: @@ -636,18 +1026,42 @@ static int grow_r502a_channel_get(const struct device *dev, enum sensor_channel static int grow_r502a_attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { + struct grow_r502a_data *drv_data = dev->data; + if ((enum sensor_channel_grow_r502a)chan != SENSOR_CHAN_FINGERPRINT) { LOG_ERR("Channel not supported"); return -ENOTSUP; } switch ((enum sensor_attribute_grow_r502a)attr) { + case SENSOR_ATTR_R502A_CAPTURE: + return fps_capture(dev); + case SENSOR_ATTR_R502A_TEMPLATE_CREATE: + return fps_create_model(dev); case SENSOR_ATTR_R502A_RECORD_ADD: - return fps_enroll(dev, val); + return fps_store_model(dev, val->val1); case SENSOR_ATTR_R502A_RECORD_DEL: - return fps_delete(dev, val); + return fps_delete_model(dev, val->val1, val->val2); case SENSOR_ATTR_R502A_RECORD_EMPTY: return fps_empty_db(dev); + case SENSOR_ATTR_R502A_RECORD_LOAD: + return fps_load_template(dev, val->val1); + case SENSOR_ATTR_R502A_SYS_PARAM: { + int ret = 0; + + if (val->val1 == R502A_DATA_PKG_LEN) { + LOG_ERR("Data package length should not be runtime configurable"); + return -EINVAL; + }; + k_mutex_lock(&drv_data->lock, K_FOREVER); + ret = fps_set_sys_param(dev, val); + if (ret != 0) { + k_mutex_unlock(&drv_data->lock); + return ret; + } + k_mutex_unlock(&drv_data->lock); + return 0; + } default: LOG_ERR("Sensor attribute not supported"); return -ENOTSUP; @@ -659,7 +1073,6 @@ static int grow_r502a_attr_get(const struct device *dev, enum sensor_channel cha enum sensor_attribute attr, struct sensor_value *val) { int ret; - struct grow_r502a_data *drv_data = dev->data; if ((enum sensor_channel_grow_r502a)chan != SENSOR_CHAN_FINGERPRINT) { LOG_ERR("Channel not supported"); @@ -668,11 +1081,13 @@ static int grow_r502a_attr_get(const struct device *dev, enum sensor_channel cha switch ((enum sensor_attribute_grow_r502a)attr) { case SENSOR_ATTR_R502A_RECORD_FIND: - ret = fps_match(dev, val); + ret = fps_search(dev, val); break; case SENSOR_ATTR_R502A_RECORD_FREE_IDX: - ret = fps_read_template_table(dev); - val->val1 = drv_data->free_idx; + ret = fps_read_template_table(dev, &val->val1); + break; + case SENSOR_ATTR_R502A_COMPARE: + ret = fps_match_templates(dev, val); break; default: LOG_ERR("Sensor attribute not supported"); @@ -734,9 +1149,13 @@ static int grow_r502a_init(const struct device *dev) k_mutex_init(&drv_data->lock); k_sem_init(&drv_data->uart_rx_sem, 0, 1); + k_sem_init(&drv_data->uart_tx_sem, 0, 1); uart_irq_callback_user_data_set(cfg->dev, uart_cb_handler, (void *)dev); + uart_irq_rx_disable(cfg->dev); + uart_irq_tx_disable(cfg->dev); + #ifdef CONFIG_GROW_R502A_TRIGGER ret = grow_r502a_init_interrupt(dev); @@ -759,6 +1178,53 @@ static const struct sensor_driver_api grow_r502a_api = { #endif }; +#ifdef CONFIG_LED +static int grow_r502a_led_set_color(const struct device *dev, uint32_t led, + uint8_t num_colors, const uint8_t *color) +{ + struct grow_r502a_data *drv_data = dev->data; + + if (!(*color)) { + LOG_ERR("invalid color code value"); + return -ENOTSUP; + } + drv_data->led_color = *color; + + return 0; +} + +static int grow_r502a_led_on(const struct device *dev, uint32_t led) +{ + struct grow_r502a_data *drv_data = dev->data; + + if (!drv_data->led_color) { + drv_data->led_color = R502A_LED_COLOR_BLUE; + } + + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_ON_ALWAYS, + .color_idx = drv_data->led_color, + }; + + return fps_led_control(dev, &led_ctrl); +} + +static int grow_r502a_led_off(const struct device *dev, uint32_t led) +{ + struct r502a_led_params led_ctrl = { + .ctrl_code = R502A_LED_CTRL_OFF_ALWAYS, + }; + + return fps_led_control(dev, &led_ctrl); +} + +static const struct led_driver_api grow_r502a_leds_api = { + .set_color = grow_r502a_led_set_color, + .on = grow_r502a_led_on, + .off = grow_r502a_led_off, +}; +#endif + #define GROW_R502A_INIT(index) \ static struct grow_r502a_data grow_r502a_data_##index; \ \ @@ -773,7 +1239,20 @@ static const struct sensor_driver_api grow_r502a_api = { }; \ \ DEVICE_DT_INST_DEFINE(index, &grow_r502a_init, NULL, &grow_r502a_data_##index, \ - &grow_r502a_config_##index, POST_KERNEL, \ - CONFIG_SENSOR_INIT_PRIORITY, &grow_r502a_api); + &grow_r502a_config_##index, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &grow_r502a_api); \ + +#define GROW_R502A_LED_INIT(index) \ + DEVICE_DT_INST_DEFINE(index, NULL, NULL, &grow_r502a_data_##index, \ + &grow_r502a_config_##index, POST_KERNEL, \ + CONFIG_LED_INIT_PRIORITY, &grow_r502a_leds_api); \ +#define DT_DRV_COMPAT hzgrow_r502a DT_INST_FOREACH_STATUS_OKAY(GROW_R502A_INIT) +#undef DT_DRV_COMPAT + +#ifdef CONFIG_LED +#define DT_DRV_COMPAT hzgrow_r502a_led +DT_INST_FOREACH_STATUS_OKAY(GROW_R502A_LED_INIT) +#undef DT_DRV_COMPAT +#endif diff --git a/drivers/sensor/grow_r502a/grow_r502a.h b/drivers/sensor/grow_r502a/grow_r502a.h index c8374fb17d3dd..154693f5701bf 100644 --- a/drivers/sensor/grow_r502a/grow_r502a.h +++ b/drivers/sensor/grow_r502a/grow_r502a.h @@ -61,7 +61,6 @@ */ #define R502A_OK 0x00 /*commad execution complete*/ -#define R502A_NOT_FOUND 0x09 /*fail to find the matching finger*/ /*Package Identifier's definition*/ #define R502A_COMMAND_PACKET 0x1 /*Command packet*/ @@ -95,6 +94,11 @@ #define R502A_HANDSHAKE 0x40 /*Handshake*/ #define R502A_BADPACKET 0xFE /* Bad packet was sent*/ +#define R502A_NOT_MATCH_CC 0x08 /* templates of two buffers not matching*/ +#define R502A_NOT_FOUND_CC 0x09 /*fail to find the matching finger*/ +#define R502A_FINGER_MATCH_NOT_FOUND 0 +#define R502A_FINGER_MATCH_FOUND 1 + #define R502A_STARTCODE 0xEF01 /*Fixed value, High byte transferred first*/ #define R502A_DEFAULT_PASSWORD 0x00000000 #define R502A_DEFAULT_ADDRESS 0xFFFFFFFF @@ -108,6 +112,8 @@ #define R502A_PKG_LEN_IDX 7 #define R502A_CC_IDX 9 /* Confirmation code index*/ +#define R502A_COMMON_ACK_LEN 12 + #define R502A_STARTCODE_LEN 2 #define R502A_ADDRESS_LEN 4 #define R502A_PKG_LEN 2 @@ -116,10 +122,14 @@ #define R502A_CHAR_BUF_1 1 #define R502A_CHAR_BUF_2 2 +#define R502A_CHAR_BUF_TOTAL 2 + #define R502A_CHAR_BUF_SIZE 384 /* Maximum size of characteristic value buffer*/ #define R502A_TEMPLATE_SIZE 768 /* Maximum size of template, twice of CHAR_BUF*/ -#define R502A_MAX_BUF_SIZE 779 /*sum of checksum, header and template sizes*/ -#define R502A_BUF_SIZE 64 +#define R502A_TEMPLATE_MAX_SIZE (R502A_CHAR_BUF_TOTAL * R502A_TEMPLATE_SIZE) + +#define R502A_MAX_BUF_SIZE (CONFIG_R502A_DATA_PKT_SIZE + R502A_COMMON_ACK_LEN) + #define R502A_TEMPLATES_PER_PAGE 256 #define R502A_TEMP_TABLE_BUF_SIZE 32 #define R502A_DELETE_COUNT_OFFSET 1 @@ -127,21 +137,40 @@ #define R502A_DELAY 200 #define R502A_RETRY_DELAY 5 -#define LED_CTRL_BREATHING 0x01 -#define LED_CTRL_FLASHING 0x02 -#define LED_CTRL_ON_ALWAYS 0x03 -#define LED_CTRL_OFF_ALWAYS 0x04 -#define LED_CTRL_ON_GRADUALLY 0x05 -#define LED_CTRL_OFF_GRADUALLY 0x06 +/*LED glow control code*/ +enum r502a_led_ctrl_code { + R502A_LED_CTRL_BREATHING = 0x01, + R502A_LED_CTRL_FLASHING, + R502A_LED_CTRL_ON_ALWAYS, + R502A_LED_CTRL_OFF_ALWAYS, + R502A_LED_CTRL_ON_GRADUALLY, + R502A_LED_CTRL_OFF_GRADUALLY, +}; -#define LED_SPEED_HALF 0x50 -#define LED_SPEED_FULL 0xFF +/* LED glow speed code + * if needed, use desired speed between 0-255 + */ +enum r502a_led_speed { + R502A_LED_SPEED_MAX = 0x00, + R502A_LED_SPEED_HALF = 0x50, + R502A_LED_SPEED_MIN = 0xFF, +}; + +/* LED glowing cycle + * if needed, use desired cycle count between 1-255 + */ +enum r502a_led_cycle { + R502A_LED_CYCLE_INFINITE = 0x00, + R502A_LED_CYCLE_1, + R502A_LED_CYCLE_2, + R502A_LED_CYCLE_3, + R502A_LED_CYCLE_4, + R502A_LED_CYCLE_5, + R502A_LED_CYCLE_255 = 0xFF, +}; -#define LED_COLOR_RED 0x01 -#define LED_COLOR_BLUE 0x02 -#define LED_COLOR_PURPLE 0x03 -struct led_params { +struct r502a_led_params { uint8_t ctrl_code; uint8_t color_idx; uint8_t speed; /* Speed 0x00-0xff */ @@ -150,14 +179,14 @@ struct led_params { union r502a_packet { struct { - uint8_t start[R502A_STARTCODE_LEN]; - uint8_t addr[R502A_ADDRESS_LEN]; + uint16_t start; + uint32_t addr; uint8_t pid; - uint8_t len[R502A_PKG_LEN]; - uint8_t data[R502A_BUF_SIZE]; - }; + uint16_t len; + uint8_t data[CONFIG_R502A_DATA_PKT_SIZE]; + } __packed; - uint8_t buf[R502A_BUF_SIZE]; + uint8_t buf[R502A_MAX_BUF_SIZE]; }; struct r502a_buf { @@ -183,14 +212,14 @@ struct grow_r502a_data { struct r502a_buf tx_buf; struct r502a_buf rx_buf; + uint16_t pkt_len; struct k_mutex lock; + struct k_sem uart_tx_sem; struct k_sem uart_rx_sem; - uint16_t finger_id; - uint16_t matching_score; uint16_t template_count; - int8_t free_idx; + uint8_t led_color; }; struct grow_r502a_config { diff --git a/drivers/sensor/maxim/ds18b20/Kconfig b/drivers/sensor/maxim/ds18b20/Kconfig index ac7fe02ac4697..82f5160ff732e 100644 --- a/drivers/sensor/maxim/ds18b20/Kconfig +++ b/drivers/sensor/maxim/ds18b20/Kconfig @@ -6,7 +6,7 @@ config DS18B20 bool "DS18B20 Temperature Sensor" default y - depends on DT_HAS_MAXIM_DS18B20_ENABLED + depends on DT_HAS_MAXIM_DS18B20_ENABLED || DT_HAS_MAXIM_DS18S20_ENABLED depends on W1_NET help Enable driver for DS18B20 1-Wire temperature sensors. diff --git a/drivers/sensor/maxim/ds18b20/ds18b20.c b/drivers/sensor/maxim/ds18b20/ds18b20.c index 15c7370b8e44a..35e9a82df0226 100644 --- a/drivers/sensor/maxim/ds18b20/ds18b20.c +++ b/drivers/sensor/maxim/ds18b20/ds18b20.c @@ -9,9 +9,11 @@ * A datasheet is available at: * https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf * + * Driver also support the older DS18S20 1-Wire temperature sensors. + * https://www.analog.com/media/en/technical-documentation/data-sheets/ds18b20.pdf + * * Parasite power configuration is not supported by the driver. */ -#define DT_DRV_COMPAT maxim_ds18b20 #include #include @@ -25,15 +27,25 @@ LOG_MODULE_REGISTER(DS18B20, CONFIG_SENSOR_LOG_LEVEL); static int ds18b20_configure(const struct device *dev); /* measure wait time for 9-bit, 10-bit, 11-bit, 12-bit resolution respectively */ -static const uint16_t measure_wait_ms[4] = { 94, 188, 376, 750 }; +static const uint16_t measure_wait_ds18b20_ms[4] = { 94, 188, 376, 750 }; -static inline void ds18b20_temperature_from_raw(uint8_t *temp_raw, +/* ds18s20 always needs 750ms */ +static const uint16_t measure_wait_ds18s20_ms = { 750 }; + +static inline void ds18b20_temperature_from_raw(const struct device *dev, + uint8_t *temp_raw, struct sensor_value *val) { - int16_t temp = sys_get_le16(temp_raw); - - val->val1 = temp / 16; - val->val2 = (temp % 16) * 1000000 / 16; + const struct ds18b20_config *cfg = dev->config; + int16_t temp = sys_get_le16 (temp_raw); + + if (cfg->chip == type_ds18s20) { + val->val1 = temp / 2; + val->val2 = (temp % 2) * 5000000; + } else { + val->val1 = temp / 16; + val->val2 = (temp % 16) * 1000000 / 16; + } } /* @@ -95,10 +107,20 @@ static void ds18b20_set_resolution(const struct device *dev, uint8_t resolution) data->scratchpad.config |= DS18B20_RESOLUTION(resolution); } +static uint16_t measure_wait_ms(const struct device *dev) +{ + const struct ds18b20_config *cfg = dev->config; + + if (cfg->chip == type_ds18s20) { + return measure_wait_ds18s20_ms; + } + + return measure_wait_ds18b20_ms[DS18B20_RESOLUTION_INDEX(cfg->resolution)]; +} + static int ds18b20_sample_fetch(const struct device *dev, enum sensor_channel chan) { - const struct ds18b20_config *cfg = dev->config; struct ds18b20_data *data = dev->data; int status; @@ -118,7 +140,7 @@ static int ds18b20_sample_fetch(const struct device *dev, LOG_DBG("W1 fetch error"); return status; } - k_msleep(measure_wait_ms[DS18B20_RESOLUTION_INDEX(cfg->resolution)]); + k_msleep(measure_wait_ms(dev)); return ds18b20_read_scratchpad(dev, &data->scratchpad); } @@ -132,7 +154,7 @@ static int ds18b20_channel_get(const struct device *dev, return -ENOTSUP; } - ds18b20_temperature_from_raw((uint8_t *)&data->scratchpad.temp, val); + ds18b20_temperature_from_raw(dev, (uint8_t *)&data->scratchpad.temp, val); return 0; } @@ -159,17 +181,19 @@ static int ds18b20_configure(const struct device *dev) } if ((cfg->family != 0) && (cfg->family != data->config.rom.family)) { - LOG_ERR("Found 1-Wire slave is not a DS18B20"); + LOG_ERR("Found 1-Wire slave is not a %s", dev->name); return -EINVAL; } /* write default configuration */ - ds18b20_set_resolution(dev, cfg->resolution); - ret = ds18b20_write_scratchpad(dev, data->scratchpad); - if (ret < 0) { - return ret; + if (cfg->chip == type_ds18b20) { + ds18b20_set_resolution(dev, cfg->resolution); + ret = ds18b20_write_scratchpad(dev, data->scratchpad); + if (ret < 0) { + return ret; + } } - LOG_DBG("Init DS18B20: ROM=%016llx\n", + LOG_DBG("Init %s: ROM=%016llx\n", dev->name, w1_rom_to_uint64(&data->config.rom)); return 0; @@ -214,24 +238,35 @@ static int ds18b20_init(const struct device *dev) return 0; } -#define DS18B20_CONFIG_INIT(inst) \ - { \ +#define DS18B20_CONFIG_INIT(inst, default_family_code, chip_type) \ + { \ .bus = DEVICE_DT_GET(DT_INST_BUS(inst)), \ - .family = (uint8_t)DT_INST_PROP_OR(inst, family_code, 0x28), \ - .resolution = DT_INST_PROP(inst, resolution), \ + .family = (uint8_t)DT_INST_PROP_OR(inst, family_code, default_family_code), \ + .resolution = DT_INST_PROP_OR(inst, resolution, 12), \ + .chip = chip_type, \ } -#define DS18B20_DEFINE(inst) \ - static struct ds18b20_data ds18b20_data_##inst; \ - static const struct ds18b20_config ds18b20_config_##inst = \ - DS18B20_CONFIG_INIT(inst); \ +#define DS18B20_DEFINE(inst, name, family_code, chip_type) \ + static struct ds18b20_data data_##name##_##inst; \ + static const struct ds18b20_config config_##name##_##inst = \ + DS18B20_CONFIG_INIT(inst, family_code, chip_type); \ SENSOR_DEVICE_DT_INST_DEFINE(inst, \ ds18b20_init, \ NULL, \ - &ds18b20_data_##inst, \ - &ds18b20_config_##inst, \ + &data_##name##_##inst, \ + &config_##name##_##inst, \ POST_KERNEL, \ CONFIG_SENSOR_INIT_PRIORITY, \ &ds18b20_driver_api); -DT_INST_FOREACH_STATUS_OKAY(DS18B20_DEFINE) +#define DT_DRV_COMPAT maxim_ds18b20 +DT_INST_FOREACH_STATUS_OKAY_VARGS(DS18B20_DEFINE, DT_DRV_COMPAT, + DS18B20_FAMILYCODE, + type_ds18b20) +#undef DT_DRV_COMPAT + +#define DT_DRV_COMPAT maxim_ds18s20 +DT_INST_FOREACH_STATUS_OKAY_VARGS(DS18B20_DEFINE, DT_DRV_COMPAT, + DS18S20_FAMILYCODE, + type_ds18s20) +#undef DT_DRV_COMPAT diff --git a/drivers/sensor/maxim/ds18b20/ds18b20.h b/drivers/sensor/maxim/ds18b20/ds18b20.h index cf318cb9f9f20..a85e91c58ae5b 100644 --- a/drivers/sensor/maxim/ds18b20/ds18b20.h +++ b/drivers/sensor/maxim/ds18b20/ds18b20.h @@ -31,6 +31,11 @@ /* convert resolution in bits to array index (for resolution specific elements) */ #define DS18B20_RESOLUTION_INDEX(res) (res - 9) +#define DS18B20_FAMILYCODE 0x28 +#define DS18S20_FAMILYCODE 0x10 + +enum chip_type {type_ds18b20, type_ds18s20}; + struct ds18b20_scratchpad { int16_t temp; uint8_t alarm_temp_high; @@ -44,6 +49,7 @@ struct ds18b20_config { const struct device *bus; uint8_t family; uint8_t resolution; + enum chip_type chip; }; struct ds18b20_data { diff --git a/drivers/sensor/meas/ms5837/ms5837.c b/drivers/sensor/meas/ms5837/ms5837.c index 9e1cdbfd7d078..d07d23071aa54 100644 --- a/drivers/sensor/meas/ms5837/ms5837.c +++ b/drivers/sensor/meas/ms5837/ms5837.c @@ -75,17 +75,17 @@ static void ms5837_compensate_30(const struct device *dev, temp_sq = (int64_t)(data->temperature - 2000) * (data->temperature - 2000); if (data->temperature < 2000) { - Ti = (3ll * dT * dT) / (1ll << 23); - OFFi = (3ll * temp_sq) / 1ll; + Ti = (3ll * dT * dT) / (1ll << 33); + OFFi = (3ll * temp_sq) / (1ll << 1); SENSi = (5ll * temp_sq) / (1ll << 3); if (data->temperature < -1500) { temp_sq = (data->temperature + 1500) * (data->temperature + 1500); OFFi += 7ll * temp_sq; - SENSi += 5ll * temp_sq; + SENSi += 4ll * temp_sq; } } else { - Ti = (1ll * dT * dT) / (1ll << 37); + Ti = (2ll * dT * dT) / (1ll << 37); OFFi = temp_sq / (1ll << 4); SENSi = 0; } diff --git a/drivers/sensor/nordic/CMakeLists.txt b/drivers/sensor/nordic/CMakeLists.txt index 0169664e6aa0a..89265c0e59d3b 100644 --- a/drivers/sensor/nordic/CMakeLists.txt +++ b/drivers/sensor/nordic/CMakeLists.txt @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 # zephyr-keep-sorted-start +add_subdirectory(temp) add_subdirectory_ifdef(CONFIG_NPM1300_CHARGER npm1300_charger) add_subdirectory_ifdef(CONFIG_QDEC_NRFX qdec_nrfx) -add_subdirectory_ifdef(CONFIG_TEMP_NRF5 nrf5) # zephyr-keep-sorted-stop diff --git a/drivers/sensor/nordic/Kconfig b/drivers/sensor/nordic/Kconfig index 42678ed2fcc00..27f1cfedf59af 100644 --- a/drivers/sensor/nordic/Kconfig +++ b/drivers/sensor/nordic/Kconfig @@ -3,6 +3,6 @@ # zephyr-keep-sorted-start source "drivers/sensor/nordic/npm1300_charger/Kconfig" -source "drivers/sensor/nordic/nrf5/Kconfig" source "drivers/sensor/nordic/qdec_nrfx/Kconfig" +source "drivers/sensor/nordic/temp/Kconfig" # zephyr-keep-sorted-stop diff --git a/drivers/sensor/nordic/nrf5/CMakeLists.txt b/drivers/sensor/nordic/nrf5/CMakeLists.txt deleted file mode 100644 index d57e18cdf1b63..0000000000000 --- a/drivers/sensor/nordic/nrf5/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -if(CONFIG_TEMP_NRF5 AND NOT CONFIG_TEMP_NRF5_FORCE_ALT) - zephyr_library() - zephyr_library_sources(temp_nrf5.c) -endif() diff --git a/drivers/sensor/nordic/nrf5/Kconfig b/drivers/sensor/nordic/nrf5/Kconfig deleted file mode 100644 index aa0e3d6fc0fdd..0000000000000 --- a/drivers/sensor/nordic/nrf5/Kconfig +++ /dev/null @@ -1,20 +0,0 @@ -# nRF5 temperature sensor configuration options - -# Copyright (c) 2016 ARM Ltd. -# SPDX-License-Identifier: Apache-2.0 - -config TEMP_NRF5_FORCE_ALT - bool - depends on SOC_COMPATIBLE_NRF - help - This option can be enabled to force an alternative implementation - of the temperature sensor driver. - -config TEMP_NRF5 - bool "nRF5 Temperature Sensor" - default y - depends on DT_HAS_NORDIC_NRF_TEMP_ENABLED - depends on HAS_HW_NRF_TEMP - depends on MULTITHREADING || TEMP_NRF5_FORCE_ALT - help - Enable driver for nRF5 temperature sensor. diff --git a/drivers/sensor/nordic/temp/CMakeLists.txt b/drivers/sensor/nordic/temp/CMakeLists.txt new file mode 100644 index 0000000000000..e3f81b50ac438 --- /dev/null +++ b/drivers/sensor/nordic/temp/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_TEMP_NRF5 AND NOT CONFIG_TEMP_NRF5_FORCE_ALT) + zephyr_library() + zephyr_library_sources(temp_nrf5.c) +elseif(CONFIG_TEMP_NRFS) + zephyr_library() + zephyr_library_sources(temp_nrfs.c) +endif() diff --git a/drivers/sensor/nordic/temp/Kconfig b/drivers/sensor/nordic/temp/Kconfig new file mode 100644 index 0000000000000..e32fb1b8fdd60 --- /dev/null +++ b/drivers/sensor/nordic/temp/Kconfig @@ -0,0 +1,38 @@ +# nRF temperature sensor configuration options + +# Copyright (c) 2016 ARM Ltd. +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config TEMP_NRF5_FORCE_ALT + bool + depends on SOC_COMPATIBLE_NRF + help + This option can be enabled to force an alternative implementation + of the temperature sensor driver. + +config TEMP_NRF5 + bool "nRF5 Temperature Sensor" + default y + depends on DT_HAS_NORDIC_NRF_TEMP_ENABLED + depends on MULTITHREADING || TEMP_NRF5_FORCE_ALT + help + Enable driver for nRF5 temperature sensor. + +config TEMP_NRFS + bool "nRF Temperature Sensor accessed via nrfs" + default y + depends on DT_HAS_NORDIC_NRF_TEMP_NRFS_ENABLED + depends on NRFS + help + Enable driver for nRF temperature sensor accessed through the nRF + Services (nrfs) layer. + +if TEMP_NRFS + +module = TEMP_NRFS +thread_priority = 10 +thread_stack_size = 1024 +source "drivers/sensor/Kconfig.trigger_template" + +endif # TEMP_NRFS diff --git a/drivers/sensor/nordic/nrf5/temp_nrf5.c b/drivers/sensor/nordic/temp/temp_nrf5.c similarity index 100% rename from drivers/sensor/nordic/nrf5/temp_nrf5.c rename to drivers/sensor/nordic/temp/temp_nrf5.c diff --git a/drivers/sensor/nordic/temp/temp_nrfs.c b/drivers/sensor/nordic/temp/temp_nrfs.c new file mode 100644 index 0000000000000..015e05918f04d --- /dev/null +++ b/drivers/sensor/nordic/temp/temp_nrfs.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nordic_nrf_temp_nrfs + +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(temp_nrfs, CONFIG_SENSOR_LOG_LEVEL); + +struct temp_nrfs_data { + struct k_sem measure_sem; + struct k_mutex mutex; + int32_t raw_temp; + +#ifdef CONFIG_TEMP_NRFS_TRIGGER + struct sensor_trigger trigger; + sensor_trigger_handler_t handler; + const struct device *dev; + struct sensor_value sampling_freq; + struct sensor_value up_threshold; + struct sensor_value low_threshold; +#endif +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) + K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_TEMP_NRFS_THREAD_STACK_SIZE); + struct k_thread thread; + struct k_sem event_sem; +#elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD) + struct k_work work; +#endif +}; + +#ifdef CONFIG_TEMP_NRFS_TRIGGER + +#define DEFAULT_SAMPLING_FREQ { 1, 0 } +#define DEFAULT_UP_THRESHOLD { 25, 0 } +#define DEFAULT_LOW_THRESHOLD { 0, 0 } + +static void temp_nrfs_handle_event(const struct device *dev) +{ + struct temp_nrfs_data *data = dev->data; + struct sensor_trigger trigger; + sensor_trigger_handler_t handler; + + k_mutex_lock(&data->mutex, K_FOREVER); + trigger = data->trigger; + handler = data->handler; + k_mutex_unlock(&data->mutex); + + if (handler) { + handler(dev, &trigger); + } +} + +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) +static void temp_nrfs_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + struct temp_nrfs_data *data = p1; + + while (1) { + k_sem_take(&data->event_sem, K_FOREVER); + temp_nrfs_handle_event(data->dev); + } +} +#elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD) +static void temp_nrfs_work_handler(struct k_work *work) +{ + struct temp_nrfs_data *data = + CONTAINER_OF(work, struct temp_nrfs_data, work); + + temp_nrfs_handle_event(data->dev); +} +#endif + +static uint16_t to_measure_rate_ms(const struct sensor_value *freq_val) +{ + uint32_t measure_rate_ms = (MSEC_PER_SEC * 1000) / + (uint32_t)sensor_value_to_milli(freq_val); + + return (uint16_t)MIN(measure_rate_ms, UINT16_MAX); +} + +static int32_t to_raw_temp(const struct sensor_value *temp_val) +{ + int32_t temp_mul_100 = (int32_t)(sensor_value_to_milli(temp_val) / 10); + + return nrfs_temp_to_raw(temp_mul_100); +} + +static int api_sensor_trigger_set(const struct device *dev, + const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct temp_nrfs_data *data = dev->data; + nrfs_err_t err; + + if (trig->chan != SENSOR_CHAN_ALL && + trig->chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + switch (trig->type) { + case SENSOR_TRIG_THRESHOLD: + k_mutex_lock(&data->mutex, K_FOREVER); + data->trigger = *trig; + data->handler = handler; + k_mutex_unlock(&data->mutex); + + if (handler) { + err = nrfs_temp_subscribe( + to_measure_rate_ms(&data->sampling_freq), + to_raw_temp(&data->low_threshold), + to_raw_temp(&data->up_threshold), + data); + } else { + err = nrfs_temp_unsubscribe(); + } + + switch (err) { + case NRFS_SUCCESS: + break; + case NRFS_ERR_INVALID_STATE: + return -EAGAIN; + default: + return -EIO; + } + break; + + default: + return -ENOTSUP; + } + + return 0; +} + +static int api_sensor_attr_set(const struct device *dev, + enum sensor_channel chan, + enum sensor_attribute attr, + const struct sensor_value *val) +{ + struct temp_nrfs_data *data = dev->data; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + switch (attr) { + case SENSOR_ATTR_SAMPLING_FREQUENCY: + if (sensor_value_to_milli(val) <= 0) { + return -EINVAL; + } + data->sampling_freq = *val; + break; + case SENSOR_ATTR_UPPER_THRESH: + data->up_threshold = *val; + break; + case SENSOR_ATTR_LOWER_THRESH: + data->low_threshold = *val; + break; + default: + return -ENOTSUP; + } + return 0; +} + +#endif /* CONFIG_TEMP_NRFS_TRIGGER */ + +static void sensor_handler(nrfs_temp_evt_t const *p_evt, void *context) +{ + ARG_UNUSED(context); + + struct temp_nrfs_data *data = context; + + switch (p_evt->type) { + case NRFS_TEMP_EVT_MEASURE_DONE: + data->raw_temp = p_evt->raw_temp; + k_sem_give(&data->measure_sem); + break; + +#ifdef CONFIG_TEMP_NRFS_TRIGGER + case NRFS_TEMP_EVT_CHANGE: + data->raw_temp = p_evt->raw_temp; +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) + k_sem_give(&data->event_sem); +#elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD) + k_work_submit(&data->work); +#endif + break; +#endif /* CONFIG_TEMP_NRFS_TRIGGER */ + + default: + LOG_DBG("Temperature handler - unsupported event: 0x%x", + p_evt->type); + break; + } +} + +static int api_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct temp_nrfs_data *data = dev->data; + int nrfs_rc; + int rc = 0; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + k_mutex_lock(&data->mutex, K_FOREVER); + nrfs_rc = nrfs_temp_measure_request(data); + switch (nrfs_rc) { + case NRFS_SUCCESS: + k_sem_take(&data->measure_sem, K_FOREVER); + LOG_DBG("Temperature sample: %d", data->raw_temp); + break; + case NRFS_ERR_INVALID_STATE: + LOG_DBG("Backend is not ready, try again."); + rc = -EAGAIN; + break; + default: + LOG_DBG("Measure request failed: %d", nrfs_rc); + rc = -EIO; + break; + } + k_mutex_unlock(&data->mutex); + + return rc; +} + +static int api_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct temp_nrfs_data *data = dev->data; + + if (chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + int32_t uval = nrfs_temp_from_raw(data->raw_temp); + + val->val1 = uval / 100; + val->val2 = (abs(uval) % 100) * 10000; + + LOG_DBG("Temperature: %d.%02u[C]", uval / 100, abs(uval) % 100); + + return 0; +} + +static int temp_nrfs_init(const struct device *dev) +{ + int rc; + + rc = nrfs_temp_init(sensor_handler); + if (rc < 0) { + return rc; + } + +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) + struct temp_nrfs_data *data = dev->data; + + k_thread_create(&data->thread, data->thread_stack, + CONFIG_TEMP_NRFS_THREAD_STACK_SIZE, + temp_nrfs_thread, + data, NULL, NULL, + K_PRIO_COOP(CONFIG_TEMP_NRFS_THREAD_PRIORITY), + 0, K_NO_WAIT); + k_thread_name_set(&data->thread, dev->name); +#endif + + return 0; +} + +static const struct sensor_driver_api temp_nrfs_drv_api = { +#ifdef CONFIG_TEMP_NRFS_TRIGGER + .attr_set = api_sensor_attr_set, + .trigger_set = api_sensor_trigger_set, +#endif + .sample_fetch = api_sample_fetch, + .channel_get = api_channel_get +}; + +static struct temp_nrfs_data temp_nrfs_drv_data = { + .mutex = Z_MUTEX_INITIALIZER(temp_nrfs_drv_data.mutex), + .measure_sem = Z_SEM_INITIALIZER(temp_nrfs_drv_data.measure_sem, 0, 1), +#ifdef CONFIG_TEMP_NRFS_TRIGGER + .dev = DEVICE_DT_INST_GET(0), + .sampling_freq = DEFAULT_SAMPLING_FREQ, + .up_threshold = DEFAULT_UP_THRESHOLD, + .low_threshold = DEFAULT_LOW_THRESHOLD, +#endif +#if defined(CONFIG_TEMP_NRFS_TRIGGER_OWN_THREAD) + .event_sem = Z_SEM_INITIALIZER(temp_nrfs_drv_data.event_sem, 0, 1), +#elif defined(CONFIG_TEMP_NRFS_TRIGGER_GLOBAL_THREAD) + .work = Z_WORK_INITIALIZER(temp_nrfs_work_handler), +#endif +}; + +DEVICE_DT_INST_DEFINE(0, temp_nrfs_init, NULL, + &temp_nrfs_drv_data, NULL, + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, + &temp_nrfs_drv_api); diff --git a/drivers/sensor/nxp/CMakeLists.txt b/drivers/sensor/nxp/CMakeLists.txt index 21e7825187ff4..05270c58dceec 100644 --- a/drivers/sensor/nxp/CMakeLists.txt +++ b/drivers/sensor/nxp/CMakeLists.txt @@ -5,6 +5,7 @@ add_subdirectory_ifdef(CONFIG_FXAS21002 fxas21002) add_subdirectory_ifdef(CONFIG_FXOS8700 fxos8700) add_subdirectory_ifdef(CONFIG_MCUX_ACMP mcux_acmp) +add_subdirectory_ifdef(CONFIG_MCUX_LPCMP mcux_lpcmp) add_subdirectory_ifdef(CONFIG_NXP_TEMPMON nxp_tempmon) add_subdirectory_ifdef(CONFIG_QDEC_MCUX qdec_mcux) add_subdirectory_ifdef(CONFIG_QDEC_NXP_S32 qdec_nxp_s32) diff --git a/drivers/sensor/nxp/Kconfig b/drivers/sensor/nxp/Kconfig index bf1565580aa24..3da1f9c647587 100644 --- a/drivers/sensor/nxp/Kconfig +++ b/drivers/sensor/nxp/Kconfig @@ -5,6 +5,7 @@ source "drivers/sensor/nxp/fxas21002/Kconfig" source "drivers/sensor/nxp/fxos8700/Kconfig" source "drivers/sensor/nxp/mcux_acmp/Kconfig" +source "drivers/sensor/nxp/mcux_lpcmp/Kconfig" source "drivers/sensor/nxp/nxp_kinetis_temp/Kconfig" source "drivers/sensor/nxp/nxp_tempmon/Kconfig" source "drivers/sensor/nxp/qdec_mcux/Kconfig" diff --git a/drivers/sensor/nxp/mcux_lpcmp/CMakeLists.txt b/drivers/sensor/nxp/mcux_lpcmp/CMakeLists.txt new file mode 100644 index 0000000000000..0ad6fe11b1a38 --- /dev/null +++ b/drivers/sensor/nxp/mcux_lpcmp/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_MCUX_LPCMP mcux_lpcmp.c) diff --git a/drivers/sensor/nxp/mcux_lpcmp/Kconfig b/drivers/sensor/nxp/mcux_lpcmp/Kconfig new file mode 100644 index 0000000000000..3e04b3c26c822 --- /dev/null +++ b/drivers/sensor/nxp/mcux_lpcmp/Kconfig @@ -0,0 +1,18 @@ +# NXP MCUX low power comparator (LPCMP) configuration options + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config MCUX_LPCMP + bool "NXP LPCMP driver" + default y + depends on DT_HAS_NXP_LPCMP_ENABLED + select PINCTRL + help + Enable the MCUX LPCMP driver. + +config MCUX_LPCMP_TRIGGER + bool "Trigger support" + depends on MCUX_LPCMP + help + Enable trigger support for the NXP LPCMP. diff --git a/drivers/sensor/nxp/mcux_lpcmp/mcux_lpcmp.c b/drivers/sensor/nxp/mcux_lpcmp/mcux_lpcmp.c new file mode 100644 index 0000000000000..97e55a7d3c628 --- /dev/null +++ b/drivers/sensor/nxp/mcux_lpcmp/mcux_lpcmp.c @@ -0,0 +1,451 @@ +/* + * Copyright (c) 2020 Vestas Wind Systems A/S + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_lpcmp + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(mcux_lpcmp, CONFIG_SENSOR_LOG_LEVEL); + +struct mcux_lpcmp_config { + LPCMP_Type *base; + const struct pinctrl_dev_config *pincfg; +#ifdef CONFIG_MCUX_LPCMP_TRIGGER + void (*irq_config_func)(const struct device *dev); +#endif /* CONFIG_MCUX_LPCMP_TRIGGER */ + bool output_enable: 1; + bool unfiltered: 1; + bool output_invert: 1; + lpcmp_hysteresis_mode_t hysteresis_level; + lpcmp_power_mode_t power_level; + lpcmp_functional_source_clock_t function_clock; +}; + +struct mcux_lpcmp_data { + lpcmp_config_t lpcmp_config; + lpcmp_dac_config_t dac_config; + lpcmp_filter_config_t filter_config; + lpcmp_window_control_config_t window_config; +#ifdef CONFIG_MCUX_LPCMP_TRIGGER + const struct device *dev; + const struct sensor_trigger *rising_trigger; + sensor_trigger_handler_t rising_handler; + const struct sensor_trigger *falling_trigger; + sensor_trigger_handler_t falling_handler; + struct k_work work; + volatile uint32_t status; +#endif /* CONFIG_MCUX_LPCMP_TRIGGER */ + bool cout; +}; + +static int mcux_lpcmp_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + const struct mcux_lpcmp_config *config = dev->config; + struct mcux_lpcmp_data *data = dev->data; + int32_t val1 = val->val1; + + __ASSERT_NO_MSG(val != NULL); + + if ((int16_t)chan != SENSOR_CHAN_MCUX_LPCMP_OUTPUT) { + return -ENOTSUP; + } + + if (val->val2 != 0) { + return -EINVAL; + } + + switch ((int16_t)attr) { + /** Analog input mux related attributes */ + case SENSOR_ATTR_MCUX_LPCMP_POSITIVE_MUX_INPUT: + LOG_DBG("positive mux = %d", val1); + if (val1 >= 0 && val1 < 8) { + config->base->CCR2 = ((config->base->CCR2 & (~LPCMP_CCR2_PSEL_MASK)) | + LPCMP_CCR2_PSEL(val1)); + } else { + return -EINVAL; + } + break; + case SENSOR_ATTR_MCUX_LPCMP_NEGATIVE_MUX_INPUT: + LOG_DBG("negative mux = %d", val1); + if (val1 >= 0 && val1 < 8) { + config->base->CCR2 = ((config->base->CCR2 & (~LPCMP_CCR2_MSEL_MASK)) | + LPCMP_CCR2_MSEL(val1)); + } else { + return -EINVAL; + } + break; + + /** DAC related attributes */ + case SENSOR_ATTR_MCUX_LPCMP_DAC_ENABLE: + LOG_DBG("dac enable = %d", val1); + if (val1 == 1) { + config->base->DCR |= LPCMP_DCR_DAC_EN_MASK; + } else if (val1 == 0) { + config->base->DCR &= ~LPCMP_DCR_DAC_EN_MASK; + } else { + return -EINVAL; + } + break; + case SENSOR_ATTR_MCUX_LPCMP_DAC_HIGH_POWER_MODE_ENABLE: + LOG_DBG("dac power mode = %d", val1); + if ((val1 == 1) || (val1 == 0)) { + data->dac_config.enableLowPowerMode = (bool)val1; + LPCMP_SetDACConfig(config->base, &data->dac_config); + } else { + return -EINVAL; + } + break; + case SENSOR_ATTR_MCUX_LPCMP_DAC_REFERENCE_VOLTAGE_SOURCE: + LOG_DBG("dac vref = %d", val1); + if (val1 >= kLPCMP_VrefSourceVin1 && val1 <= kLPCMP_VrefSourceVin2) { + data->dac_config.referenceVoltageSource = val1; + LPCMP_SetDACConfig(config->base, &data->dac_config); + } else { + return -EINVAL; + } + break; + case SENSOR_ATTR_MCUX_LPCMP_DAC_OUTPUT_VOLTAGE: + LOG_DBG("dac value = %d", val1); + if (val1 >= 0 && val1 < 256) { + data->dac_config.DACValue = val1; + LPCMP_SetDACConfig(config->base, &data->dac_config); + } else { + return -EINVAL; + } + break; + + /** Sample and filter related attributes */ + case SENSOR_ATTR_MCUX_LPCMP_SAMPLE_ENABLE: + LOG_DBG("Filter sample enable = %d", val1); + if ((val1 == 1) || (val1 == 0)) { + data->filter_config.enableSample = (bool)val1; + LPCMP_SetFilterConfig(config->base, &data->filter_config); + } else { + return -EINVAL; + } + break; + case SENSOR_ATTR_MCUX_LPCMP_FILTER_COUNT: + LOG_DBG("sample count = %d", val1); + data->filter_config.filterSampleCount = val1; + LPCMP_SetFilterConfig(config->base, &data->filter_config); + break; + case SENSOR_ATTR_MCUX_LPCMP_FILTER_PERIOD: + LOG_DBG("sample period = %d", val1); + data->filter_config.filterSamplePeriod = val1; + LPCMP_SetFilterConfig(config->base, &data->filter_config); + break; + + /** Window related attributes */ + case SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_ENABLE: + LOG_DBG("Window enable = %d", val1); + if ((val1 == 1) || (val1 == 0)) { + LPCMP_EnableWindowMode(config->base, (bool)val1); + } else { + return -EINVAL; + } + break; + + case SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_SIGNAL_INVERT_ENABLE: + LOG_DBG("Invert window signal = %d", val1); + if ((val1 == 1) || (val1 == 0)) { + data->window_config.enableInvertWindowSignal = (bool)val1; + LPCMP_SetWindowControl(config->base, &data->window_config); + } else { + return -EINVAL; + } + break; + case SENSOR_ATTR_MCUX_LPCMP_COUTA_SIGNAL: + LOG_DBG("COUTA signal = %d", val1); + if ((val1 >= (int32_t)kLPCMP_COUTASignalNoSet) && + (val1 < (int32_t)kLPCMP_COUTASignalHigh)) { + data->window_config.COUTASignal = val1; + LPCMP_SetWindowControl(config->base, &data->window_config); + } else { + return -EINVAL; + } + break; + case SENSOR_ATTR_MCUX_LPCMP_COUT_EVENT_TO_CLOSE_WINDOW: + LOG_DBG("COUT event = %d", val1); + if ((val1 >= (int32_t)kLPCMP_CLoseWindowEventNoSet) && + (val1 < (int32_t)kLPCMP_CLoseWindowEventBothEdge)) { + data->window_config.closeWindowEvent = val1; + LPCMP_SetWindowControl(config->base, &data->window_config); + } else { + return -EINVAL; + } + break; + + default: + return -ENOTSUP; + } + + return 0; +} + +static int mcux_lpcmp_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + const struct mcux_lpcmp_config *config = dev->config; + struct mcux_lpcmp_data *data = dev->data; + + __ASSERT_NO_MSG(val != NULL); + + if ((int16_t)chan != SENSOR_CHAN_MCUX_LPCMP_OUTPUT) { + return -ENOTSUP; + } + + switch ((int16_t)attr) { + /** Analog mux related attributes */ + case SENSOR_ATTR_MCUX_LPCMP_POSITIVE_MUX_INPUT: + val->val1 = (int32_t)((config->base->CCR2) & + LPCMP_CCR2_PSEL_MASK >> LPCMP_CCR2_PSEL_SHIFT); + break; + case SENSOR_ATTR_MCUX_LPCMP_NEGATIVE_MUX_INPUT: + val->val1 = (int32_t)((config->base->CCR2) & + LPCMP_CCR2_MSEL_MASK >> LPCMP_CCR2_MSEL_SHIFT); + break; + + /** DAC related attributes */ + case SENSOR_ATTR_MCUX_LPCMP_DAC_ENABLE: + val->val1 = (int32_t)((config->base->DCR) & + LPCMP_DCR_DAC_EN_MASK >> LPCMP_DCR_DAC_EN_SHIFT); + break; + case SENSOR_ATTR_MCUX_LPCMP_DAC_HIGH_POWER_MODE_ENABLE: + val->val1 = (int32_t)(data->dac_config.enableLowPowerMode); + break; + case SENSOR_ATTR_MCUX_LPCMP_DAC_REFERENCE_VOLTAGE_SOURCE: + val->val1 = (int32_t)(data->dac_config.referenceVoltageSource); + break; + case SENSOR_ATTR_MCUX_LPCMP_DAC_OUTPUT_VOLTAGE: + val->val1 = (int32_t)(data->dac_config.DACValue); + break; + + /** Sample and filter related attributes */ + case SENSOR_ATTR_MCUX_LPCMP_SAMPLE_ENABLE: + val->val1 = (int32_t)(data->filter_config.enableSample); + break; + case SENSOR_ATTR_MCUX_LPCMP_FILTER_COUNT: + val->val1 = (int32_t)(data->filter_config.filterSampleCount); + break; + case SENSOR_ATTR_MCUX_LPCMP_FILTER_PERIOD: + val->val1 = (int32_t)(data->filter_config.filterSamplePeriod); + break; + + /** Window related attributes */ + case SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_ENABLE: + val->val1 = (int32_t)((config->base->CCR1) & + LPCMP_CCR1_WINDOW_EN_MASK >> LPCMP_CCR1_WINDOW_EN_SHIFT); + break; + case SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_SIGNAL_INVERT_ENABLE: + val->val1 = (int32_t)(data->window_config.enableInvertWindowSignal); + break; + case SENSOR_ATTR_MCUX_LPCMP_COUTA_SIGNAL: + val->val1 = (int32_t)(data->window_config.COUTASignal); + break; + case SENSOR_ATTR_MCUX_LPCMP_COUT_EVENT_TO_CLOSE_WINDOW: + val->val1 = (int32_t)(data->window_config.closeWindowEvent); + break; + + default: + return -ENOTSUP; + } + + val->val2 = 0; + + return 0; +} + +static int mcux_lpcmp_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct mcux_lpcmp_config *config = dev->config; + struct mcux_lpcmp_data *data = dev->data; + + __ASSERT_NO_MSG(val != NULL); + + if (chan != SENSOR_CHAN_ALL && (int16_t)chan != SENSOR_CHAN_MCUX_LPCMP_OUTPUT) { + return -ENOTSUP; + } + + data->cout = ((LPCMP_GetStatusFlags(config->base) & + (uint32_t)kLPCMP_OutputAssertEventFlag) == kLPCMP_OutputAssertEventFlag); + + return 0; +} + +static int mcux_lpcmp_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct mcux_lpcmp_data *data = dev->data; + + __ASSERT_NO_MSG(val != NULL); + + if ((int16_t)chan != SENSOR_CHAN_MCUX_LPCMP_OUTPUT) { + return -ENOTSUP; + } + + val->val1 = data->cout ? 1 : 0; + val->val2 = 0; + + return 0; +} + +#ifdef CONFIG_MCUX_LPCMP_TRIGGER +static void mcux_lpcmp_isr(const struct device *dev) +{ + const struct mcux_lpcmp_config *config = dev->config; + struct mcux_lpcmp_data *data = dev->data; + + data->status = LPCMP_GetStatusFlags(config->base); + LPCMP_ClearStatusFlags(config->base, data->status); + + k_work_submit(&data->work); +} + +static int mcux_lpcmp_trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + struct mcux_lpcmp_data *data = dev->data; + + __ASSERT_NO_MSG(trig != NULL); + + if ((int16_t)trig->chan != SENSOR_CHAN_MCUX_LPCMP_OUTPUT) { + return -ENOTSUP; + } + + if ((int16_t)trig->type == SENSOR_TRIG_MCUX_LPCMP_OUTPUT_RISING) { + data->rising_handler = handler; + data->rising_trigger = trig; + } else if ((int16_t)trig->type == SENSOR_TRIG_MCUX_LPCMP_OUTPUT_FALLING) { + data->falling_handler = handler; + data->falling_trigger = trig; + } else { + return -ENOTSUP; + } + + return 0; +} + +static void mcux_lpcmp_trigger_work_handler(struct k_work *item) +{ + struct mcux_lpcmp_data *data = CONTAINER_OF(item, struct mcux_lpcmp_data, work); + const struct sensor_trigger *trigger; + sensor_trigger_handler_t handler = NULL; + + if (((data->status & kLPCMP_OutputRisingEventFlag) == kLPCMP_OutputRisingEventFlag) && + ((data->status & kLPCMP_OutputAssertEventFlag) == kLPCMP_OutputAssertEventFlag)) { + trigger = data->rising_trigger; + handler = data->rising_handler; + } else if (((data->status & kLPCMP_OutputFallingEventFlag) == + kLPCMP_OutputFallingEventFlag) && + ((data->status & kLPCMP_OutputAssertEventFlag) != + kLPCMP_OutputAssertEventFlag)) { + trigger = data->falling_trigger; + handler = data->falling_handler; + } else { + return; + } + + if (handler) { + handler(data->dev, trigger); + } +} +#endif /* CONFIG_MCUX_LPCMP_TRIGGER */ + +static int mcux_lpcmp_init(const struct device *dev) +{ + const struct mcux_lpcmp_config *config = dev->config; + struct mcux_lpcmp_data *data = dev->data; + int err; + + err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + if (err) { + return err; + } + + /* LPCMP configuration */ + LPCMP_GetDefaultConfig(&data->lpcmp_config); + data->lpcmp_config.powerMode = config->power_level; + data->lpcmp_config.hysteresisMode = config->hysteresis_level; + data->lpcmp_config.enableOutputPin = config->output_enable; + data->lpcmp_config.enableInvertOutput = config->output_invert; + data->lpcmp_config.useUnfilteredOutput = config->unfiltered; +#if defined(FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL) && FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL + data->lpcmp_config.functionalSourceClock = config->function_clock; +#endif /* FSL_FEATURE_LPCMP_HAS_CCR1_FUNC_CLK_SEL */ + LPCMP_Init(config->base, &data->lpcmp_config); + +#ifdef CONFIG_MCUX_LPCMP_TRIGGER + data->dev = dev; + k_work_init(&data->work, mcux_lpcmp_trigger_work_handler); + config->irq_config_func(dev); + LPCMP_EnableInterrupts(config->base, kLPCMP_OutputRisingInterruptEnable | + kLPCMP_OutputFallingInterruptEnable); +#endif /* CONFIG_MCUX_LPCMP_TRIGGER */ + + LPCMP_Enable(config->base, true); + + return 0; +} + +static const struct sensor_driver_api mcux_lpcmp_driver_api = { + .attr_set = mcux_lpcmp_attr_set, + .attr_get = mcux_lpcmp_attr_get, +#ifdef CONFIG_MCUX_LPCMP_TRIGGER + .trigger_set = mcux_lpcmp_trigger_set, +#endif /* CONFIG_MCUX_LPCMP_TRIGGER */ + .sample_fetch = mcux_lpcmp_sample_fetch, + .channel_get = mcux_lpcmp_channel_get, +}; + +#define MCUX_LPCMP_DECLARE_CONFIG(n, config_func_init) \ + static const struct mcux_lpcmp_config mcux_lpcmp_config_##n = { \ + .base = (LPCMP_Type *)DT_INST_REG_ADDR(n), \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .output_enable = DT_INST_PROP_OR(n, enable_output_pin, 0), \ + .unfiltered = DT_INST_PROP_OR(n, use_unfiltered_output, 0), \ + .output_invert = DT_INST_PROP_OR(n, output_invert, 0), \ + .hysteresis_level = DT_INST_PROP_OR(n, hysteresis_level, 0), \ + .power_level = DT_INST_ENUM_IDX(n, power_level), \ + .function_clock = DT_INST_ENUM_IDX(n, function_clock), \ + config_func_init} + +#ifdef CONFIG_MCUX_LPCMP_TRIGGER +#define MCUX_LPCMP_CONFIG_FUNC(n) \ + static void mcux_lpcmp_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), mcux_lpcmp_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } +#define MCUX_LPCMP_CONFIG_FUNC_INIT(n) .irq_config_func = mcux_lpcmp_config_func_##n +#define MCUX_LPCMP_INIT_CONFIG(n) MCUX_LPCMP_DECLARE_CONFIG(n, MCUX_LPCMP_CONFIG_FUNC_INIT(n)) +#else /* CONFIG_MCUX_LPCMP_TRIGGER */ +#define MCUX_LPCMP_CONFIG_FUNC(n) +#define MCUX_LPCMP_CONFIG_FUNC_INIT +#define MCUX_LPCMP_INIT_CONFIG(n) MCUX_LPCMP_DECLARE_CONFIG(n, MCUX_LPCMP_CONFIG_FUNC_INIT) +#endif /* !CONFIG_MCUX_LPCMP_TRIGGER */ + +#define MCUX_LPCMP_INIT(n) \ + static struct mcux_lpcmp_data mcux_lpcmp_data_##n; \ + static const struct mcux_lpcmp_config mcux_lpcmp_config_##n; \ + PINCTRL_DT_INST_DEFINE(n); \ + SENSOR_DEVICE_DT_INST_DEFINE(n, &mcux_lpcmp_init, NULL, &mcux_lpcmp_data_##n, \ + &mcux_lpcmp_config_##n, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &mcux_lpcmp_driver_api); \ + MCUX_LPCMP_CONFIG_FUNC(n) \ + MCUX_LPCMP_INIT_CONFIG(n); + +DT_INST_FOREACH_STATUS_OKAY(MCUX_LPCMP_INIT) diff --git a/drivers/sensor/nxp/nxp_kinetis_temp/Kconfig b/drivers/sensor/nxp/nxp_kinetis_temp/Kconfig index 63c91cde176c8..10436fda53a3d 100644 --- a/drivers/sensor/nxp/nxp_kinetis_temp/Kconfig +++ b/drivers/sensor/nxp/nxp_kinetis_temp/Kconfig @@ -7,7 +7,8 @@ config TEMP_KINETIS bool "NXP Kinetis Temperature Sensor" default y depends on DT_HAS_NXP_KINETIS_TEMPERATURE_ENABLED - depends on (ADC && SOC_FAMILY_KINETIS) + depends on SOC_FAMILY_KINETIS + select ADC help Enable driver for NXP Kinetis temperature sensor. diff --git a/drivers/sensor/nxp/nxp_kinetis_temp/temp_kinetis.c b/drivers/sensor/nxp/nxp_kinetis_temp/temp_kinetis.c index b72b5eece6ca4..7f5beda55ebad 100644 --- a/drivers/sensor/nxp/nxp_kinetis_temp/temp_kinetis.c +++ b/drivers/sensor/nxp/nxp_kinetis_temp/temp_kinetis.c @@ -159,7 +159,7 @@ static int temp_kinetis_init(const struct device *dev) }, }; - memset(&data->buffer, 0, ARRAY_SIZE(data->buffer)); + memset(&data->buffer, 0, sizeof(data->buffer)); if (!device_is_ready(config->adc)) { LOG_ERR("ADC device is not ready"); diff --git a/drivers/sensor/rpi_pico_temp/Kconfig b/drivers/sensor/rpi_pico_temp/Kconfig index 9b618984d88b4..33a9b7f9b2729 100644 --- a/drivers/sensor/rpi_pico_temp/Kconfig +++ b/drivers/sensor/rpi_pico_temp/Kconfig @@ -7,7 +7,7 @@ config RPI_PICO_TEMP bool "Raspberry Pi Pico CPU Temperature Sensor" default y depends on DT_HAS_RASPBERRYPI_PICO_TEMP_ENABLED - depends on ADC + select ADC help Enable driver for Raspberry Pi Pico CPU temperature sensor. diff --git a/drivers/sensor/seeed/grove/Kconfig b/drivers/sensor/seeed/grove/Kconfig index f3804f3323fbd..a91c66c099637 100644 --- a/drivers/sensor/seeed/grove/Kconfig +++ b/drivers/sensor/seeed/grove/Kconfig @@ -16,7 +16,7 @@ config GROVE_LIGHT_SENSOR bool "The Seeed Grove Light Sensor" default y depends on DT_HAS_SEEED_GROVE_LIGHT_ENABLED - depends on ADC && !MINIMAL_LIBC + select ADC help Setting this value will enable driver support for the Grove Light Sensor. @@ -25,7 +25,7 @@ config GROVE_TEMPERATURE_SENSOR bool "The Seeed Grove Temperature Sensor" default y depends on DT_HAS_SEEED_GROVE_TEMPERATURE_ENABLED - depends on ADC && !MINIMAL_LIBC + select ADC help Setting this value will enable driver support for the Grove Temperature Sensor. diff --git a/drivers/sensor/sensirion/shtcx/shtcx.c b/drivers/sensor/sensirion/shtcx/shtcx.c index 9e670087493e6..1abd4694a9860 100644 --- a/drivers/sensor/sensirion/shtcx/shtcx.c +++ b/drivers/sensor/sensirion/shtcx/shtcx.c @@ -237,10 +237,13 @@ static int shtcx_init(const struct device *dev) return 0; } +#define SHTCX_CHIP(inst) \ + (DT_INST_NODE_HAS_COMPAT(inst, sensirion_shtc1) ? CHIP_SHTC1 : CHIP_SHTC3) + #define SHTCX_CONFIG(inst) \ { \ .i2c = I2C_DT_SPEC_INST_GET(inst), \ - .chip = DT_INST_ENUM_IDX(inst, chip), \ + .chip = SHTCX_CHIP(inst), \ .measure_mode = DT_INST_ENUM_IDX(inst, measure_mode), \ .clock_stretching = DT_INST_PROP(inst, clock_stretching) \ } diff --git a/drivers/sensor/sensor_handlers.c b/drivers/sensor/sensor_handlers.c index 4643646c21557..ea82e20e9887e 100644 --- a/drivers/sensor/sensor_handlers.c +++ b/drivers/sensor/sensor_handlers.c @@ -17,7 +17,7 @@ static inline int z_vrfy_sensor_attr_set(const struct device *dev, return z_impl_sensor_attr_set((const struct device *)dev, chan, attr, (const struct sensor_value *)val); } -#include +#include static inline int z_vrfy_sensor_attr_get(const struct device *dev, enum sensor_channel chan, @@ -29,14 +29,14 @@ static inline int z_vrfy_sensor_attr_get(const struct device *dev, return z_impl_sensor_attr_get((const struct device *)dev, chan, attr, (struct sensor_value *)val); } -#include +#include static inline int z_vrfy_sensor_sample_fetch(const struct device *dev) { K_OOPS(K_SYSCALL_DRIVER_SENSOR(dev, sample_fetch)); return z_impl_sensor_sample_fetch((const struct device *)dev); } -#include +#include static inline int z_vrfy_sensor_sample_fetch_chan(const struct device *dev, enum sensor_channel type) @@ -45,7 +45,7 @@ static inline int z_vrfy_sensor_sample_fetch_chan(const struct device *dev, return z_impl_sensor_sample_fetch_chan((const struct device *)dev, type); } -#include +#include static inline int z_vrfy_sensor_channel_get(const struct device *dev, enum sensor_channel chan, @@ -56,7 +56,7 @@ static inline int z_vrfy_sensor_channel_get(const struct device *dev, return z_impl_sensor_channel_get((const struct device *)dev, chan, (struct sensor_value *)val); } -#include +#include #ifdef CONFIG_SENSOR_ASYNC_API static inline int z_vrfy_sensor_get_decoder(const struct device *dev, @@ -66,7 +66,7 @@ static inline int z_vrfy_sensor_get_decoder(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_READ(decoder, sizeof(struct sensor_decoder_api))); return z_impl_sensor_get_decoder(dev, decoder); } -#include +#include static inline int z_vrfy_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, const struct device *sensor, @@ -78,5 +78,5 @@ static inline int z_vrfy_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, K_OOPS(K_SYSCALL_MEMORY_READ(channels, sizeof(enum sensor_channel) * num_channels)); return z_impl_sensor_reconfigure_read_iodev(iodev, sensor, channels, num_channels); } -#include +#include #endif diff --git a/drivers/sensor/sensor_shell.c b/drivers/sensor/sensor_shell.c index 758e658816a94..a43378c01fe22 100644 --- a/drivers/sensor/sensor_shell.c +++ b/drivers/sensor/sensor_shell.c @@ -78,6 +78,7 @@ static const char *sensor_channel_name[SENSOR_CHAN_COMMON_COUNT] = { [SENSOR_CHAN_VOC] = "voc", [SENSOR_CHAN_GAS_RES] = "gas_resistance", [SENSOR_CHAN_VOLTAGE] = "voltage", + [SENSOR_CHAN_VSHUNT] = "vshunt", [SENSOR_CHAN_CURRENT] = "current", [SENSOR_CHAN_POWER] = "power", [SENSOR_CHAN_RESISTANCE] = "resistance", @@ -85,6 +86,7 @@ static const char *sensor_channel_name[SENSOR_CHAN_COMMON_COUNT] = { [SENSOR_CHAN_POS_DX] = "pos_dx", [SENSOR_CHAN_POS_DY] = "pos_dy", [SENSOR_CHAN_POS_DZ] = "pos_dz", + [SENSOR_CHAN_POS_DXYZ] = "pos_dxyz", [SENSOR_CHAN_RPM] = "rpm", [SENSOR_CHAN_GAUGE_VOLTAGE] = "gauge_voltage", [SENSOR_CHAN_GAUGE_AVG_CURRENT] = "gauge_avg_current", @@ -143,6 +145,20 @@ static struct sample_stats sensor_stats[CONFIG_SENSOR_SHELL_MAX_TRIGGER_DEVICES] static const struct device *sensor_trigger_devices[CONFIG_SENSOR_SHELL_MAX_TRIGGER_DEVICES]; +static bool device_is_sensor(const struct device *dev) +{ +#ifdef CONFIG_SENSOR_INFO + STRUCT_SECTION_FOREACH(sensor_info, sensor) { + if (sensor->dev == dev) { + return true; + } + } + return false; +#else + return true; +#endif /* CONFIG_SENSOR_INFO */ +} + static int find_sensor_trigger_device(const struct device *sensor) { for (int i = 0; i < CONFIG_SENSOR_SHELL_MAX_TRIGGER_DEVICES; i++) { @@ -217,7 +233,7 @@ static enum dynamic_command_context current_cmd_ctx = NONE; K_MUTEX_DEFINE(cmd_get_mutex); /* Crate a single common config for one-shot reading */ -static enum sensor_channel iodev_sensor_shell_channels[SENSOR_CHAN_ALL]; +static struct sensor_chan_spec iodev_sensor_shell_channels[SENSOR_CHAN_ALL]; static struct sensor_read_config iodev_sensor_shell_read_config = { .sensor = NULL, .is_streaming = false, @@ -330,23 +346,32 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len : sensor_trigger_table[trigger].name)); } - for (int channel = 0; channel < SENSOR_CHAN_ALL; ++channel) { + + + for (struct sensor_chan_spec ch = {0, 0}; ch.chan_type < SENSOR_CHAN_ALL; ch.chan_type++) { uint32_t fit = 0; size_t base_size; size_t frame_size; - size_t channel_idx = 0; uint16_t frame_count; - if (channel == SENSOR_CHAN_ACCEL_X || channel == SENSOR_CHAN_ACCEL_Y || - channel == SENSOR_CHAN_ACCEL_Z || channel == SENSOR_CHAN_GYRO_X || - channel == SENSOR_CHAN_GYRO_Y || channel == SENSOR_CHAN_GYRO_Z || - channel == SENSOR_CHAN_MAGN_X || channel == SENSOR_CHAN_MAGN_Y || - channel == SENSOR_CHAN_MAGN_Z || channel == SENSOR_CHAN_POS_DY || - channel == SENSOR_CHAN_POS_DZ) { + /* Channels with multi-axis equivalents are skipped */ + switch (ch.chan_type) { + case SENSOR_CHAN_ACCEL_X: + case SENSOR_CHAN_ACCEL_Y: + case SENSOR_CHAN_ACCEL_Z: + case SENSOR_CHAN_GYRO_X: + case SENSOR_CHAN_GYRO_Y: + case SENSOR_CHAN_GYRO_Z: + case SENSOR_CHAN_MAGN_X: + case SENSOR_CHAN_MAGN_Y: + case SENSOR_CHAN_MAGN_Z: + case SENSOR_CHAN_POS_DX: + case SENSOR_CHAN_POS_DY: + case SENSOR_CHAN_POS_DZ: continue; } - rc = decoder->get_size_info(channel, &base_size, &frame_size); + rc = decoder->get_size_info(ch, &base_size, &frame_size); if (rc != 0) { /* Channel not supported, skipping */ continue; @@ -354,23 +379,22 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len if (base_size > ARRAY_SIZE(decoded_buffer)) { shell_error(ctx->sh, - "Channel (%d) requires %zu bytes to decode, but only %zu are " - "available", - channel, base_size, ARRAY_SIZE(decoded_buffer)); + "Channel (type %d, idx %d) requires %zu bytes to decode, but " + "only %zu are available", + ch.chan_type, ch.chan_idx, base_size, + ARRAY_SIZE(decoded_buffer)); continue; } - while (decoder->get_frame_count(buf, channel, channel_idx, &frame_count) == 0) { + while (decoder->get_frame_count(buf, ch, &frame_count) == 0) { fit = 0; memset(&accumulator_buffer, 0, sizeof(accumulator_buffer)); - while (decoder->decode(buf, channel, channel_idx, &fit, 1, decoded_buffer) > - 0) { - - switch (channel) { + while (decoder->decode(buf, ch, &fit, 1, decoded_buffer) > 0) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_XYZ: case SENSOR_CHAN_GYRO_XYZ: case SENSOR_CHAN_MAGN_XYZ: - case SENSOR_CHAN_POS_DX: { + case SENSOR_CHAN_POS_DXYZ: { struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)decoded_buffer; @@ -420,11 +444,11 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len } /* Print the accumulated value average */ - switch (channel) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_XYZ: case SENSOR_CHAN_GYRO_XYZ: case SENSOR_CHAN_MAGN_XYZ: - case SENSOR_CHAN_POS_DX: { + case SENSOR_CHAN_POS_DXYZ: { struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)decoded_buffer; @@ -442,10 +466,10 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len data->readings[0].values[2] = (q31_t)(accumulator_buffer.values[2] / accumulator_buffer.count); shell_info(ctx->sh, - "channel idx=%d %s shift=%d num_samples=%d " + "channel type=%d(%s) index=%d shift=%d num_samples=%d " "value=%" PRIsensor_three_axis_data, - channel, sensor_channel_name[channel], - data->shift, accumulator_buffer.count, + ch.chan_type, sensor_channel_name[ch.chan_type], + ch.chan_idx, data->shift, accumulator_buffer.count, PRIsensor_three_axis_data_arg(*data, 0)); break; } @@ -463,10 +487,10 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len accumulator_buffer.values[0] / accumulator_buffer.count; shell_info(ctx->sh, - "channel idx=%d %s num_samples=%d " + "channel type=%d(%s) index=%d num_samples=%d " "value=%" PRIsensor_byte_data(is_near), - channel, sensor_channel_name[channel], - accumulator_buffer.count, + ch.chan_type, sensor_channel_name[ch.chan_type], + ch.chan_idx, accumulator_buffer.count, PRIsensor_byte_data_arg(*data, 0, is_near)); break; } @@ -485,17 +509,18 @@ void sensor_shell_processing_callback(int result, uint8_t *buf, uint32_t buf_len accumulator_buffer.count); shell_info(ctx->sh, - "channel idx=%d %s shift=%d num_samples=%d " + "channel type=%d(%s) index=%d shift=%d num_samples=%d " "value=%" PRIsensor_q31_data, - channel, - (channel >= ARRAY_SIZE(sensor_channel_name)) + ch.chan_type, + (ch.chan_type >= ARRAY_SIZE(sensor_channel_name)) ? "" - : sensor_channel_name[channel], + : sensor_channel_name[ch.chan_type], + ch.chan_idx, data->shift, accumulator_buffer.count, PRIsensor_q31_data_arg(*data, 0)); } } - ++channel_idx; + ++ch.chan_idx; } } } @@ -520,13 +545,19 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) return -ENODEV; } + if (!device_is_sensor(dev)) { + shell_error(sh, "Device is not a sensor (%s)", argv[1]); + k_mutex_unlock(&cmd_get_mutex); + return -ENODEV; + } + if (argc == 2) { - /* read all channels */ + /* read all channel types */ for (int i = 0; i < ARRAY_SIZE(iodev_sensor_shell_channels); ++i) { if (SENSOR_CHANNEL_3_AXIS(i)) { continue; } - iodev_sensor_shell_channels[count++] = i; + iodev_sensor_shell_channels[count++] = (struct sensor_chan_spec){i, 0}; } } else { /* read specific channels */ @@ -538,7 +569,8 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) shell_error(sh, "Failed to read channel (%s)", argv[i]); continue; } - iodev_sensor_shell_channels[count++] = chan; + iodev_sensor_shell_channels[count++] = + (struct sensor_chan_spec){chan, 0}; } } @@ -552,7 +584,7 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) ctx.dev = dev; ctx.sh = sh; - err = sensor_read(&iodev_sensor_shell_read, &sensor_read_rtio, &ctx); + err = sensor_read_async_mempool(&iodev_sensor_shell_read, &sensor_read_rtio, &ctx); if (err < 0) { shell_error(sh, "Failed to read sensor: %d", err); } @@ -570,7 +602,6 @@ static int cmd_get_sensor(const struct shell *sh, size_t argc, char *argv[]) return 0; } - static int cmd_sensor_attr_set(const struct shell *shell_ptr, size_t argc, char *argv[]) { const struct device *dev; @@ -582,6 +613,12 @@ static int cmd_sensor_attr_set(const struct shell *shell_ptr, size_t argc, char return -ENODEV; } + if (!device_is_sensor(dev)) { + shell_error(shell_ptr, "Device is not a sensor (%s)", argv[1]); + k_mutex_unlock(&cmd_get_mutex); + return -ENODEV; + } + for (size_t i = 2; i < argc; i += 3) { int channel = parse_named_int(argv[i], sensor_channel_name, ARRAY_SIZE(sensor_channel_name)); @@ -660,6 +697,12 @@ static int cmd_sensor_attr_get(const struct shell *shell_ptr, size_t argc, char return -ENODEV; } + if (!device_is_sensor(dev)) { + shell_error(shell_ptr, "Device is not a sensor (%s)", argv[1]); + k_mutex_unlock(&cmd_get_mutex); + return -ENODEV; + } + if (argc > 2) { for (size_t i = 2; i < argc; i += 2) { cmd_sensor_attr_get_handler(shell_ptr, dev, argv[i], argv[i + 1], @@ -943,8 +986,7 @@ static void data_ready_trigger_handler(const struct device *sensor, continue; } /* Skip 3 axis channels */ - if (i == SENSOR_CHAN_ACCEL_XYZ || i == SENSOR_CHAN_GYRO_XYZ || - i == SENSOR_CHAN_MAGN_XYZ) { + if (SENSOR_CHANNEL_3_AXIS(i)) { continue; } @@ -990,6 +1032,7 @@ static int cmd_trig_sensor(const struct shell *sh, size_t argc, char **argv) { const struct device *dev; int trigger; + bool trigger_enabled = false; int err; if (argc < 4) { @@ -1030,6 +1073,7 @@ static int cmd_trig_sensor(const struct shell *sh, size_t argc, char **argv) } err = sensor_trigger_set(dev, &sensor_trigger_table[trigger].trigger, sensor_trigger_table[trigger].handler); + trigger_enabled = true; } } else if (strcmp(argv[2], "off") == 0) { /* Clear the handler for the given trigger on this device */ @@ -1052,6 +1096,10 @@ static int cmd_trig_sensor(const struct shell *sh, size_t argc, char **argv) if (err) { shell_error(sh, "Error while setting trigger %d on device %s (%d)", trigger, argv[1], err); + } else { + shell_info(sh, "%s trigger idx=%d %s on device %s", + trigger_enabled ? "Enabled" : "Disabled", trigger, + sensor_trigger_table[trigger].name, argv[1]); } return err; diff --git a/drivers/sensor/silabs/si7006/si7006.c b/drivers/sensor/silabs/si7006/si7006.c index dc7c1b11ee5ae..86550a17f0d6a 100644 --- a/drivers/sensor/silabs/si7006/si7006.c +++ b/drivers/sensor/silabs/si7006/si7006.c @@ -13,12 +13,11 @@ #include #include #include -#include #include -#include #include #include #include "si7006.h" +#include LOG_MODULE_REGISTER(si7006, CONFIG_SENSOR_LOG_LEVEL); diff --git a/drivers/sensor/st/CMakeLists.txt b/drivers/sensor/st/CMakeLists.txt index 31b191490b5c5..b833043ae6c66 100644 --- a/drivers/sensor/st/CMakeLists.txt +++ b/drivers/sensor/st/CMakeLists.txt @@ -33,6 +33,7 @@ add_subdirectory_ifdef(CONFIG_LSM6DSV16X lsm6dsv16x) add_subdirectory_ifdef(CONFIG_LSM9DS0_GYRO lsm9ds0_gyro) add_subdirectory_ifdef(CONFIG_LSM9DS0_MFD lsm9ds0_mfd) add_subdirectory_ifdef(CONFIG_QDEC_STM32 qdec_stm32) +add_subdirectory_ifdef(CONFIG_STM32_DIGI_TEMP stm32_digi_temp) add_subdirectory_ifdef(CONFIG_STM32_TEMP stm32_temp) add_subdirectory_ifdef(CONFIG_STM32_VBAT stm32_vbat) add_subdirectory_ifdef(CONFIG_STM32_VREF stm32_vref) diff --git a/drivers/sensor/st/Kconfig b/drivers/sensor/st/Kconfig index bb1cbd6b6a09e..a3f03a36b668d 100644 --- a/drivers/sensor/st/Kconfig +++ b/drivers/sensor/st/Kconfig @@ -32,6 +32,7 @@ source "drivers/sensor/st/lsm6dsv16x/Kconfig" source "drivers/sensor/st/lsm9ds0_gyro/Kconfig" source "drivers/sensor/st/lsm9ds0_mfd/Kconfig" source "drivers/sensor/st/qdec_stm32/Kconfig" +source "drivers/sensor/st/stm32_digi_temp/Kconfig" source "drivers/sensor/st/stm32_temp/Kconfig" source "drivers/sensor/st/stm32_vbat/Kconfig" source "drivers/sensor/st/stm32_vref/Kconfig" diff --git a/drivers/sensor/st/hts221/hts221.c b/drivers/sensor/st/hts221/hts221.c index 677607c42a603..846cccc6409b1 100644 --- a/drivers/sensor/st/hts221/hts221.c +++ b/drivers/sensor/st/hts221/hts221.c @@ -191,8 +191,6 @@ int hts221_init(const struct device *dev) LOG_ERR("Failed to initialize interrupt."); return status; } -#else - LOG_INF("Cannot enable trigger without drdy-gpios"); #endif return 0; diff --git a/drivers/sensor/st/lis2dh/lis2dh_trigger.c b/drivers/sensor/st/lis2dh/lis2dh_trigger.c index 6afa8af839b1f..16b0ea52fb850 100644 --- a/drivers/sensor/st/lis2dh/lis2dh_trigger.c +++ b/drivers/sensor/st/lis2dh/lis2dh_trigger.c @@ -19,7 +19,7 @@ LOG_MODULE_DECLARE(lis2dh, CONFIG_SENSOR_LOG_LEVEL); #include "lis2dh.h" static const gpio_flags_t gpio_int_cfg[5] = { - GPIO_INT_EDGE, + GPIO_INT_EDGE_BOTH, GPIO_INT_EDGE_RISING, GPIO_INT_EDGE_FALLING, GPIO_INT_LEVEL_HIGH, diff --git a/drivers/sensor/st/lps22hh/lps22hh.c b/drivers/sensor/st/lps22hh/lps22hh.c index 01c698ba3c622..1ea4f2afb5b8e 100644 --- a/drivers/sensor/st/lps22hh/lps22hh.c +++ b/drivers/sensor/st/lps22hh/lps22hh.c @@ -39,15 +39,36 @@ static int lps22hh_sample_fetch(const struct device *dev, uint32_t raw_press; int16_t raw_temp; - __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); - - if (lps22hh_pressure_raw_get(ctx, &raw_press) < 0) { - LOG_DBG("Failed to read sample"); - return -EIO; - } - if (lps22hh_temperature_raw_get(ctx, &raw_temp) < 0) { - LOG_DBG("Failed to read sample"); - return -EIO; + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL + || chan == SENSOR_CHAN_PRESS + || chan == SENSOR_CHAN_AMBIENT_TEMP); + + switch (chan) { + case SENSOR_CHAN_PRESS: + if (lps22hh_pressure_raw_get(ctx, &raw_press) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + break; + case SENSOR_CHAN_AMBIENT_TEMP: + if (lps22hh_temperature_raw_get(ctx, &raw_temp) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + break; + case SENSOR_CHAN_ALL: + if (lps22hh_pressure_raw_get(ctx, &raw_press) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + if (lps22hh_temperature_raw_get(ctx, &raw_temp) < 0) { + LOG_DBG("Failed to read sample"); + return -EIO; + } + break; + default: + LOG_ERR("Unsupported sensor channel"); + return -ENOTSUP; } data->sample_press = raw_press; diff --git a/drivers/sensor/st/lps25hb/lps25hb.c b/drivers/sensor/st/lps25hb/lps25hb.c index 0ce9b8862a384..38291b114719e 100644 --- a/drivers/sensor/st/lps25hb/lps25hb.c +++ b/drivers/sensor/st/lps25hb/lps25hb.c @@ -69,9 +69,14 @@ static int lps25hb_sample_fetch(const struct device *dev, static inline void lps25hb_press_convert(struct sensor_value *val, int32_t raw_val) { - /* val = raw_val / 40960 */ + /* Pressure sensitivity is 4096 LSB/hPa */ + /* Also convert hPa into kPa */ val->val1 = raw_val / 40960; - val->val2 = ((int32_t)raw_val * 1000000 / 40960) % 1000000; + + /* For the decimal part use (3125 / 128) as a factor instead of + * (1000000 / 40960) to avoid int32 overflow + */ + val->val2 = (raw_val % 40960) * 3125 / 128; } static inline void lps25hb_temp_convert(struct sensor_value *val, diff --git a/drivers/sensor/st/lsm6dsl/lsm6dsl.c b/drivers/sensor/st/lsm6dsl/lsm6dsl.c index 0a0f35258045e..a29b18e8fea17 100644 --- a/drivers/sensor/st/lsm6dsl/lsm6dsl.c +++ b/drivers/sensor/st/lsm6dsl/lsm6dsl.c @@ -472,14 +472,12 @@ static int lsm6dsl_sample_fetch(const struct device *dev, static inline void lsm6dsl_accel_convert(struct sensor_value *val, int raw_val, float sensitivity) { - double dval; + int64_t dval; - /* Sensitivity is exposed in mg/LSB */ + /* Sensitivity is exposed in ug/LSB */ /* Convert to m/s^2 */ - dval = (double)(raw_val) * (double)sensitivity * SENSOR_G_DOUBLE / 1000; - val->val1 = (int32_t)dval; - val->val2 = (((int32_t)(dval * 1000)) % 1000) * 1000; - + dval = (int64_t)raw_val * sensitivity; + sensor_ug_to_ms2(dval, val); } static inline int lsm6dsl_accel_get_channel(enum sensor_channel chan, @@ -522,13 +520,12 @@ static int lsm6dsl_accel_channel_get(enum sensor_channel chan, static inline void lsm6dsl_gyro_convert(struct sensor_value *val, int raw_val, float sensitivity) { - double dval; + int64_t dval; - /* Sensitivity is exposed in mdps/LSB */ - /* Convert to rad/s */ - dval = (double)(raw_val * (double)sensitivity * SENSOR_DEG2RAD_DOUBLE / 1000); - val->val1 = (int32_t)dval; - val->val2 = (((int32_t)(dval * 1000)) % 1000) * 1000; + /* Sensitivity is exposed in udps/LSB */ + /* So, calculate value in 10 udps unit and then to rad/s */ + dval = (int64_t)raw_val * sensitivity / 10; + sensor_10udegrees_to_rad(dval, val); } static inline int lsm6dsl_gyro_get_channel(enum sensor_channel chan, diff --git a/drivers/sensor/st/lsm6dsl/lsm6dsl.h b/drivers/sensor/st/lsm6dsl/lsm6dsl.h index da176f4f6923f..524cc6bd314c6 100644 --- a/drivers/sensor/st/lsm6dsl/lsm6dsl.h +++ b/drivers/sensor/st/lsm6dsl/lsm6dsl.h @@ -553,14 +553,11 @@ #define LSM6DSL_REG_Z_OFS_USR 0x75 -/* Accel sensor sensitivity grain is 0.061 mg/LSB */ -#define SENSI_GRAIN_XL (61LL / 1000.0) - -/* Gyro sensor sensitivity grain is 4.375 mdps/LSB */ -#define SENSI_GRAIN_G (4375LL / 1000.0) -#define SENSOR_PI_DOUBLE (SENSOR_PI / 1000000.0) -#define SENSOR_DEG2RAD_DOUBLE (SENSOR_PI_DOUBLE / 180) -#define SENSOR_G_DOUBLE (SENSOR_G / 1000000.0) +/* Accel sensor sensitivity grain is 61 ug/LSB */ +#define SENSI_GRAIN_XL 61LL + +/* Gyro sensor sensitivity grain is 4375 udps/LSB */ +#define SENSI_GRAIN_G 4375LL #if CONFIG_LSM6DSL_ACCEL_FS == 0 #define LSM6DSL_ACCEL_FS_RUNTIME 1 diff --git a/drivers/sensor/st/stm32_digi_temp/CMakeLists.txt b/drivers/sensor/st/stm32_digi_temp/CMakeLists.txt new file mode 100644 index 0000000000000..1f155f3219ded --- /dev/null +++ b/drivers/sensor/st/stm32_digi_temp/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(stm32_digi_temp.c) diff --git a/drivers/sensor/st/stm32_digi_temp/Kconfig b/drivers/sensor/st/stm32_digi_temp/Kconfig new file mode 100644 index 0000000000000..e44814ee541f3 --- /dev/null +++ b/drivers/sensor/st/stm32_digi_temp/Kconfig @@ -0,0 +1,18 @@ +# STM32 digital temperature sensor configuration options + +# Copyright (c) 2024 Aurelien Jarno +# SPDX-License-Identifier: Apache-2.0 + +config STM32_DIGI_TEMP + bool "STM32 Digital Temperature Sensor" + default y + depends on DT_HAS_ST_STM32_DIGI_TEMP_ENABLED + depends on SOC_FAMILY_STM32 + help + Enable the driver for STM32 digital temperature sensor. This sensor + is different from the STM32 analog temperature sensor, which is read + by an ADC. While both drivers have similar code footprint, the analog + temperature driver also requires the ADC driver to be enabled. The + sensors differ in precision, accuracy and power consumption. Users + are encouraged to consult the datasheet to select the sensor that + best suits their needs. diff --git a/drivers/sensor/st/stm32_digi_temp/stm32_digi_temp.c b/drivers/sensor/st/stm32_digi_temp/stm32_digi_temp.c new file mode 100644 index 0000000000000..d862bb7a29a39 --- /dev/null +++ b/drivers/sensor/st/stm32_digi_temp/stm32_digi_temp.c @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2024 Aurelien Jarno + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT st_stm32_digi_temp + +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(stm32_digi_temp, CONFIG_SENSOR_LOG_LEVEL); + +/* Constants */ +#define ONE_MHZ 1000000 /* Hz */ +#define TS1_T0_VAL0 30 /* °C */ +#define TS1_T0_VAL1 130 /* °C */ +#define SAMPLING_TIME 15 /* best precision */ + +struct stm32_digi_temp_data { + struct k_sem sem_isr; + struct k_mutex mutex; + + /* Peripheral clock frequency */ + uint32_t pclk_freq; + /* Engineering value of the frequency measured at T0 in Hz */ + uint32_t t0_freq; + /* Engineering value of the T0 temperature in °C */ + uint16_t t0; + /* Engineering value of the ramp coefficient in Hz / °C */ + uint16_t ramp_coeff; + + /* Raw sensor value */ + uint16_t raw; +}; + +struct stm32_digi_temp_config { + /* DTS instance. */ + DTS_TypeDef *base; + /* Clock configuration. */ + struct stm32_pclken pclken; + /* Interrupt configuration. */ + void (*irq_config)(const struct device *dev); +}; + +static void stm32_digi_temp_isr(const struct device *dev) +{ + struct stm32_digi_temp_data *data = dev->data; + const struct stm32_digi_temp_config *cfg = dev->config; + DTS_TypeDef *dts = cfg->base; + + /* Clear interrupt */ + SET_BIT(dts->ICIFR, DTS_ICIFR_TS1_CITEF); + + /* Give semaphore */ + k_sem_give(&data->sem_isr); +} + +static int stm32_digi_temp_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + struct stm32_digi_temp_data *data = dev->data; + DTS_TypeDef *dts = cfg->base; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + k_mutex_lock(&data->mutex, K_FOREVER); + + /* Wait for the sensor to be ready (~40µS delay after enabling it) */ + while (READ_BIT(dts->SR, DTS_SR_TS1_RDY) == 0) { + k_yield(); + } + + /* Trigger a measurement */ + SET_BIT(dts->CFGR1, DTS_CFGR1_TS1_START); + CLEAR_BIT(dts->CFGR1, DTS_CFGR1_TS1_START); + + /* Wait for interrupt */ + k_sem_take(&data->sem_isr, K_FOREVER); + + /* Read value */ + data->raw = READ_REG(dts->DR); + + k_mutex_unlock(&data->mutex); + + return 0; +} + +static int stm32_digi_temp_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct stm32_digi_temp_data *data = dev->data; + float meas_freq, temp; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_DIE_TEMP) { + return -ENOTSUP; + } + + meas_freq = ((float)data->pclk_freq * SAMPLING_TIME) / data->raw; + temp = data->t0 + (meas_freq - data->t0_freq) / data->ramp_coeff; + + return sensor_value_from_float(val, temp); +} + +static void stm32_digi_temp_configure(const struct device *dev) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + struct stm32_digi_temp_data *data = dev->data; + DTS_TypeDef *dts = cfg->base; + int clk_div; + + /* Use the prescaler to obtain an internal frequency lower than 1 MHz. + * Allowed values are between 0 and 127. + */ + clk_div = MIN(DIV_ROUND_UP(data->pclk_freq, ONE_MHZ), 127); + MODIFY_REG(dts->CFGR1, DTS_CFGR1_HSREF_CLK_DIV_Msk, + clk_div << DTS_CFGR1_HSREF_CLK_DIV_Pos); + + /* Select PCLK as reference clock */ + MODIFY_REG(dts->CFGR1, DTS_CFGR1_REFCLK_SEL_Msk, + 0 << DTS_CFGR1_REFCLK_SEL_Pos); + + /* Select trigger */ + MODIFY_REG(dts->CFGR1, DTS_CFGR1_TS1_INTRIG_SEL_Msk, + 0 << DTS_CFGR1_TS1_INTRIG_SEL_Pos); + + /* Set sampling time */ + MODIFY_REG(dts->CFGR1, DTS_CFGR1_TS1_SMP_TIME_Msk, + SAMPLING_TIME << DTS_CFGR1_TS1_SMP_TIME_Pos); +} + +static void stm32_digi_temp_enable(const struct device *dev) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + DTS_TypeDef *dts = cfg->base; + + /* Enable the sensor */ + SET_BIT(dts->CFGR1, DTS_CFGR1_TS1_EN); + + /* Enable interrupt */ + SET_BIT(dts->ITENR, DTS_ITENR_TS1_ITEEN); +} + +#ifdef CONFIG_PM_DEVICE +static void stm32_digi_temp_disable(const struct device *dev) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + DTS_TypeDef *dts = cfg->base; + + /* Disable interrupt */ + CLEAR_BIT(dts->ITENR, DTS_ITENR_TS1_ITEEN); + + /* Disable the sensor */ + CLEAR_BIT(dts->CFGR1, DTS_CFGR1_TS1_EN); +} +#endif + +static int stm32_digi_temp_init(const struct device *dev) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + struct stm32_digi_temp_data *data = dev->data; + DTS_TypeDef *dts = cfg->base; + + /* enable clock for subsystem */ + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + + if (!device_is_ready(clk)) { + LOG_ERR("Clock control device not ready"); + return -ENODEV; + } + + if (clock_control_on(clk, (clock_control_subsys_t) &cfg->pclken) != 0) { + LOG_ERR("Could not enable DTS clock"); + return -EIO; + } + + /* Save the peripheral clock frequency in the data structure to avoid + * querying it for each call to the channel_get method. + */ + if (clock_control_get_rate(clk, (clock_control_subsys_t) &cfg->pclken, + &data->pclk_freq) < 0) { + LOG_ERR("Failed call clock_control_get_rate(pclken)"); + return -EIO; + } + + /* Save the calibration data in the data structure to avoid reading + * them for each call to the channel_get method, as this requires + * enabling the peripheral clock. + */ + data->ramp_coeff = dts->RAMPVALR & DTS_RAMPVALR_TS1_RAMP_COEFF; + data->t0_freq = (dts->T0VALR1 & DTS_T0VALR1_TS1_FMT0) * 100; /* 0.1 kHz -> Hz */ + + /* T0 temperature from the datasheet */ + switch (dts->T0VALR1 >> DTS_T0VALR1_TS1_T0_Pos) { + case 0: + data->t0 = TS1_T0_VAL0; + break; + case 1: + data->t0 = TS1_T0_VAL1; + break; + default: + LOG_ERR("Unknown T0 temperature value"); + return -EIO; + } + + /* Init mutex and semaphore */ + k_mutex_init(&data->mutex); + k_sem_init(&data->sem_isr, 0, 1); + + /* Configure and enable the sensor */ + cfg->irq_config(dev); + stm32_digi_temp_configure(dev); + stm32_digi_temp_enable(dev); + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static int stm32_digi_temp_pm_action(const struct device *dev, enum pm_device_action action) +{ + const struct stm32_digi_temp_config *cfg = dev->config; + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + int err; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + /* enable clock */ + err = clock_control_on(clk, (clock_control_subsys_t)&cfg->pclken); + if (err != 0) { + LOG_ERR("Could not enable DTS clock"); + return err; + } + /* Enable sensor */ + stm32_digi_temp_enable(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + /* Disable sensor */ + stm32_digi_temp_disable(dev); + /* Stop device clock */ + err = clock_control_off(clk, (clock_control_subsys_t)&cfg->pclken); + if (err != 0) { + LOG_ERR("Could not disable DTS clock"); + return err; + } + break; + default: + return -ENOTSUP; + } + + return 0; +} +#endif /* CONFIG_PM_DEVICE */ + +static const struct sensor_driver_api stm32_digi_temp_driver_api = { + .sample_fetch = stm32_digi_temp_sample_fetch, + .channel_get = stm32_digi_temp_channel_get, +}; + +#define STM32_DIGI_TEMP_INIT(index) \ +static void stm32_digi_temp_irq_config_func_##index(const struct device *dev) \ +{ \ + IRQ_CONNECT(DT_INST_IRQN(index), \ + DT_INST_IRQ(index, priority), \ + stm32_digi_temp_isr, DEVICE_DT_INST_GET(index), 0); \ + irq_enable(DT_INST_IRQN(index)); \ +} \ + \ +static struct stm32_digi_temp_data stm32_digi_temp_dev_data_##index; \ + \ +static const struct stm32_digi_temp_config stm32_digi_temp_dev_config_##index = { \ + .base = (DTS_TypeDef *)DT_INST_REG_ADDR(index), \ + .pclken = { \ + .enr = DT_INST_CLOCKS_CELL(index, bits), \ + .bus = DT_INST_CLOCKS_CELL(index, bus) \ + }, \ + .irq_config = stm32_digi_temp_irq_config_func_##index, \ +}; \ + \ +PM_DEVICE_DT_INST_DEFINE(index, stm32_digi_temp_pm_action); \ + \ +SENSOR_DEVICE_DT_INST_DEFINE(index, stm32_digi_temp_init, \ + PM_DEVICE_DT_INST_GET(index), \ + &stm32_digi_temp_dev_data_##index, \ + &stm32_digi_temp_dev_config_##index, \ + POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &stm32_digi_temp_driver_api); \ + +DT_INST_FOREACH_STATUS_OKAY(STM32_DIGI_TEMP_INIT) diff --git a/drivers/sensor/st/stm32_temp/stm32_temp.c b/drivers/sensor/st/stm32_temp/stm32_temp.c index 5e594b0fe0ce2..48abc493718a4 100644 --- a/drivers/sensor/st/stm32_temp/stm32_temp.c +++ b/drivers/sensor/st/stm32_temp/stm32_temp.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #if defined(CONFIG_SOC_SERIES_STM32H5X) #include @@ -74,6 +75,7 @@ static int stm32_temp_sample_fetch(const struct device *dev, enum sensor_channel } k_mutex_lock(&data->mutex, K_FOREVER); + pm_device_runtime_get(data->adc); rc = adc_channel_setup(data->adc, &data->adc_cfg); if (rc) { @@ -97,6 +99,7 @@ static int stm32_temp_sample_fetch(const struct device *dev, enum sensor_channel path &= ~LL_ADC_PATH_INTERNAL_TEMPSENSOR); unlock: + pm_device_runtime_put(data->adc); k_mutex_unlock(&data->mutex); return rc; @@ -149,7 +152,7 @@ static int stm32_temp_channel_get(const struct device *dev, enum sensor_channel temp += 25; #endif - return sensor_value_from_double(val, temp); + return sensor_value_from_float(val, temp); } static const struct sensor_driver_api stm32_temp_driver_api = { diff --git a/drivers/sensor/st/stm32_vbat/Kconfig b/drivers/sensor/st/stm32_vbat/Kconfig index 8f1c7e03875ac..f5430c91a6b74 100644 --- a/drivers/sensor/st/stm32_vbat/Kconfig +++ b/drivers/sensor/st/stm32_vbat/Kconfig @@ -7,6 +7,8 @@ config STM32_VBAT bool "STM32 Vbat Sensor" default y depends on DT_HAS_ST_STM32_VBAT_ENABLED - depends on ADC && (SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X) + depends on DT_HAS_ST_STM32_ADC_ENABLED + depends on SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X + select ADC help Enable driver for STM32 Vbat sensor and then also ADC diff --git a/drivers/sensor/st/stm32_vbat/stm32_vbat.c b/drivers/sensor/st/stm32_vbat/stm32_vbat.c index 8379670fab380..87942f4bfd205 100644 --- a/drivers/sensor/st/stm32_vbat/stm32_vbat.c +++ b/drivers/sensor/st/stm32_vbat/stm32_vbat.c @@ -9,6 +9,7 @@ #include #include #include +#include #include LOG_MODULE_REGISTER(stm32_vbat, CONFIG_SENSOR_LOG_LEVEL); @@ -45,6 +46,7 @@ static int stm32_vbat_sample_fetch(const struct device *dev, enum sensor_channel } k_mutex_lock(&data->mutex, K_FOREVER); + pm_device_runtime_get(data->adc); rc = adc_channel_setup(data->adc, &data->adc_cfg); @@ -67,6 +69,7 @@ static int stm32_vbat_sample_fetch(const struct device *dev, enum sensor_channel path &= ~LL_ADC_PATH_INTERNAL_VBAT); unlock: + pm_device_runtime_put(data->adc); k_mutex_unlock(&data->mutex); return rc; @@ -77,18 +80,16 @@ static int stm32_vbat_channel_get(const struct device *dev, enum sensor_channel { struct stm32_vbat_data *data = dev->data; const struct stm32_vbat_config *cfg = dev->config; - float voltage; + int32_t voltage; if (chan != SENSOR_CHAN_VOLTAGE) { return -ENOTSUP; } - /* Sensor value in millivolts */ - voltage = data->raw * adc_ref_internal(data->adc) / 0x0FFF; - /* considering the vbat input through a resistor bridge */ - voltage = voltage * cfg->ratio / 1000; /* value of SENSOR_CHAN_VOLTAGE in Volt */ + /* Sensor value in millivolts considering the vbat input through a resistor bridge */ + voltage = data->raw * adc_ref_internal(data->adc) * cfg->ratio / 0x0FFF; - return sensor_value_from_double(val, voltage); + return sensor_value_from_milli(val, voltage); } static const struct sensor_driver_api stm32_vbat_driver_api = { @@ -103,6 +104,11 @@ static int stm32_vbat_init(const struct device *dev) k_mutex_init(&data->mutex); + if (data->adc == NULL) { + LOG_ERR("ADC is not enabled"); + return -ENODEV; + } + if (!device_is_ready(data->adc)) { LOG_ERR("Device %s is not ready", data->adc->name); return -ENODEV; @@ -118,9 +124,13 @@ static int stm32_vbat_init(const struct device *dev) return 0; } +#define STM32_VBAT_GET_ADC_OR_NULL(inst) \ + COND_CODE_1(DT_NODE_HAS_STATUS(DT_INST_IO_CHANNELS_CTLR(inst), okay), \ + (DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst))), (NULL)) + #define STM32_VBAT_DEFINE(inst) \ static struct stm32_vbat_data stm32_vbat_dev_data_##inst = { \ - .adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)), \ + .adc = STM32_VBAT_GET_ADC_OR_NULL(inst), \ .adc_base = (ADC_TypeDef *)DT_REG_ADDR(DT_INST_IO_CHANNELS_CTLR(0)), \ .adc_cfg = { \ .gain = ADC_GAIN_1, \ @@ -138,6 +148,6 @@ static int stm32_vbat_init(const struct device *dev) SENSOR_DEVICE_DT_INST_DEFINE(inst, stm32_vbat_init, NULL, \ &stm32_vbat_dev_data_##inst, &stm32_vbat_dev_config_##inst, \ POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ - &stm32_vbat_driver_api); \ + &stm32_vbat_driver_api); DT_INST_FOREACH_STATUS_OKAY(STM32_VBAT_DEFINE) diff --git a/drivers/sensor/st/stm32_vref/Kconfig b/drivers/sensor/st/stm32_vref/Kconfig index 192cd3fd922e6..3e76dcd4f79d5 100644 --- a/drivers/sensor/st/stm32_vref/Kconfig +++ b/drivers/sensor/st/stm32_vref/Kconfig @@ -7,6 +7,7 @@ config STM32_VREF bool "STM32 VREF Sensor" default y depends on DT_HAS_ST_STM32_VREF_ENABLED - depends on ADC && (SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X) + depends on SOC_FAMILY_STM32 && !SOC_SERIES_STM32F1X + select ADC help Enable driver for STM32 Vref sensor. diff --git a/drivers/sensor/st/stm32_vref/stm32_vref.c b/drivers/sensor/st/stm32_vref/stm32_vref.c index 3532d2aeddd76..5db5a857167e9 100644 --- a/drivers/sensor/st/stm32_vref/stm32_vref.c +++ b/drivers/sensor/st/stm32_vref/stm32_vref.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #if defined(CONFIG_SOC_SERIES_STM32H5X) #include @@ -45,6 +46,7 @@ static int stm32_vref_sample_fetch(const struct device *dev, enum sensor_channel } k_mutex_lock(&data->mutex, K_FOREVER); + pm_device_runtime_get(data->adc); rc = adc_channel_setup(data->adc, &data->adc_cfg); if (rc) { @@ -71,6 +73,7 @@ static int stm32_vref_sample_fetch(const struct device *dev, enum sensor_channel unlock: + pm_device_runtime_put(data->adc); k_mutex_unlock(&data->mutex); return rc; @@ -81,7 +84,7 @@ static int stm32_vref_channel_get(const struct device *dev, enum sensor_channel { struct stm32_vref_data *data = dev->data; const struct stm32_vref_config *cfg = dev->config; - float vref; + int32_t vref; if (chan != SENSOR_CHAN_VOLTAGE) { return -ENOTSUP; @@ -112,14 +115,12 @@ static int stm32_vref_channel_get(const struct device *dev, enum sensor_channel #else vref = cfg->cal_mv * (*cfg->cal_addr) / data->raw; #endif /* CONFIG_SOC_SERIES_STM32H5X */ - /* millivolt to volt */ - vref /= 1000; #if defined(CONFIG_SOC_SERIES_STM32H5X) LL_ICACHE_Enable(); #endif /* CONFIG_SOC_SERIES_STM32H5X */ - return sensor_value_from_double(val, vref); + return sensor_value_from_milli(val, vref); } static const struct sensor_driver_api stm32_vref_driver_api = { diff --git a/drivers/sensor/tdk/icm42688/icm42688_decoder.c b/drivers/sensor/tdk/icm42688/icm42688_decoder.c index 3dc556ac61c7c..b71d06b7f3a6d 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_decoder.c +++ b/drivers/sensor/tdk/icm42688/icm42688_decoder.c @@ -178,7 +178,7 @@ static uint8_t icm42688_encode_channel(enum sensor_channel chan) return encode_bmask; } -int icm42688_encode(const struct device *dev, const enum sensor_channel *const channels, +int icm42688_encode(const struct device *dev, const struct sensor_chan_spec *const channels, const size_t num_channels, uint8_t *buf) { struct icm42688_dev_data *data = dev->data; @@ -187,7 +187,7 @@ int icm42688_encode(const struct device *dev, const enum sensor_channel *const c edata->channels = 0; for (int i = 0; i < num_channels; i++) { - edata->channels |= icm42688_encode_channel(channels[i]); + edata->channels |= icm42688_encode_channel(channels[i].chan_type); } edata->header.is_fifo = false; @@ -345,9 +345,8 @@ static uint32_t gyro_period_ns[] = { [ICM42688_GYRO_ODR_32000] = UINT32_C(1000000) / 32, }; -static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, - void *data_out) +static int icm42688_fifo_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct icm42688_fifo_data *edata = (const struct icm42688_fifo_data *)buffer; const uint8_t *buffer_end = buffer + sizeof(struct icm42688_fifo_data) + edata->fifo_count; @@ -356,7 +355,7 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann int count = 0; int rc; - if ((uintptr_t)buffer_end <= *fit || channel_idx != 0) { + if ((uintptr_t)buffer_end <= *fit || chan_spec.chan_idx != 0) { return 0; } @@ -388,7 +387,7 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann buffer = frame_end; continue; } - if (channel == SENSOR_CHAN_DIE_TEMP) { + if (chan_spec.chan_type == SENSOR_CHAN_DIE_TEMP) { struct sensor_q31_data *data = (struct sensor_q31_data *)data_out; data->shift = 9; @@ -401,7 +400,7 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann } data->readings[count].temperature = icm42688_read_temperature_from_packet(buffer); - } else if (IS_ACCEL(channel) && has_accel) { + } else if (IS_ACCEL(chan_spec.chan_type) && has_accel) { /* Decode accel */ struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)data_out; @@ -422,7 +421,7 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann buffer = frame_end; continue; } - } else if (IS_GYRO(channel) && has_gyro) { + } else if (IS_GYRO(chan_spec.chan_type) && has_gyro) { /* Decode gyro */ struct sensor_three_axis_data *data = (struct sensor_three_axis_data *)data_out; @@ -451,9 +450,8 @@ static int icm42688_fifo_decode(const uint8_t *buffer, enum sensor_channel chann return count; } -static int icm42688_one_shot_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, - void *data_out) +static int icm42688_one_shot_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct icm42688_encoded_data *edata = (const struct icm42688_encoded_data *)buffer; const struct icm42688_decoder_header *header = &edata->header; @@ -467,11 +465,11 @@ static int icm42688_one_shot_decode(const uint8_t *buffer, enum sensor_channel c if (*fit != 0) { return 0; } - if (max_count == 0 || channel_idx != 0) { + if (max_count == 0 || chan_spec.chan_idx != 0) { return -EINVAL; } - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -570,31 +568,31 @@ static int icm42688_one_shot_decode(const uint8_t *buffer, enum sensor_channel c } } -static int icm42688_decoder_decode(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint32_t *fit, uint16_t max_count, - void *data_out) +static int icm42688_decoder_decode(const uint8_t *buffer, struct sensor_chan_spec chan_spec, + uint32_t *fit, uint16_t max_count, void *data_out) { const struct icm42688_decoder_header *header = (const struct icm42688_decoder_header *)buffer; if (header->is_fifo) { - return icm42688_fifo_decode(buffer, channel, channel_idx, fit, max_count, data_out); + return icm42688_fifo_decode(buffer, chan_spec, fit, max_count, data_out); } - return icm42688_one_shot_decode(buffer, channel, channel_idx, fit, max_count, data_out); + return icm42688_one_shot_decode(buffer, chan_spec, fit, max_count, data_out); } -static int icm42688_decoder_get_frame_count(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint16_t *frame_count) +static int icm42688_decoder_get_frame_count(const uint8_t *buffer, + struct sensor_chan_spec chan_spec, + uint16_t *frame_count) { const struct icm42688_fifo_data *data = (const struct icm42688_fifo_data *)buffer; const struct icm42688_decoder_header *header = &data->header; - if (channel_idx != 0) { + if (chan_spec.chan_idx != 0) { return -ENOTSUP; } if (!header->is_fifo) { - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: @@ -643,10 +641,10 @@ static int icm42688_decoder_get_frame_count(const uint8_t *buffer, enum sensor_c return 0; } -static int icm42688_decoder_get_size_info(enum sensor_channel channel, size_t *base_size, +static int icm42688_decoder_get_size_info(struct sensor_chan_spec chan_spec, size_t *base_size, size_t *frame_size) { - switch (channel) { + switch (chan_spec.chan_type) { case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: diff --git a/drivers/sensor/tdk/icm42688/icm42688_decoder.h b/drivers/sensor/tdk/icm42688/icm42688_decoder.h index 499cf3d080155..9eadcbcecad57 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_decoder.h +++ b/drivers/sensor/tdk/icm42688/icm42688_decoder.h @@ -36,7 +36,7 @@ struct icm42688_encoded_data { int16_t readings[7]; }; -int icm42688_encode(const struct device *dev, const enum sensor_channel *const channels, +int icm42688_encode(const struct device *dev, const struct sensor_chan_spec *const channels, const size_t num_channels, uint8_t *buf); int icm42688_get_decoder(const struct device *dev, const struct sensor_decoder_api **decoder); diff --git a/drivers/sensor/tdk/icm42688/icm42688_emul.c b/drivers/sensor/tdk/icm42688/icm42688_emul.c index 5bf60aa4fd12c..41b6b11ea5f24 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_emul.c +++ b/drivers/sensor/tdk/icm42688/icm42688_emul.c @@ -295,15 +295,15 @@ static void icm42688_emul_get_gyro_ranges(const struct emul *target, q31_t *lowe *lower = -*upper; } -static int icm42688_emul_backend_get_sample_range(const struct emul *target, enum sensor_channel ch, - q31_t *lower, q31_t *upper, q31_t *epsilon, - int8_t *shift) +static int icm42688_emul_backend_get_sample_range(const struct emul *target, + struct sensor_chan_spec ch, q31_t *lower, + q31_t *upper, q31_t *epsilon, int8_t *shift) { if (!lower || !upper || !epsilon || !shift) { return -EINVAL; } - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_DIE_TEMP: /* degrees C = ([16-bit signed temp_data register] / 132.48) + 25 */ *shift = 9; @@ -328,7 +328,7 @@ static int icm42688_emul_backend_get_sample_range(const struct emul *target, enu return 0; } -static int icm42688_emul_backend_set_channel(const struct emul *target, enum sensor_channel ch, +static int icm42688_emul_backend_set_channel(const struct emul *target, struct sensor_chan_spec ch, const q31_t *value, int8_t shift) { if (!target || !target->data) { @@ -343,7 +343,7 @@ static int icm42688_emul_backend_set_channel(const struct emul *target, enum sen int64_t value_unshifted = shift < 0 ? ((int64_t)*value >> -shift) : ((int64_t)*value << shift); - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_DIE_TEMP: reg_addr = REG_TEMP_DATA1; reg_val = ((value_unshifted - (25 * Q31_SCALE)) * 13248) / (100 * Q31_SCALE); @@ -351,7 +351,7 @@ static int icm42688_emul_backend_set_channel(const struct emul *target, enum sen case SENSOR_CHAN_ACCEL_X: case SENSOR_CHAN_ACCEL_Y: case SENSOR_CHAN_ACCEL_Z: - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_ACCEL_X: reg_addr = REG_ACCEL_DATA_X1; break; @@ -370,7 +370,7 @@ static int icm42688_emul_backend_set_channel(const struct emul *target, enum sen case SENSOR_CHAN_GYRO_X: case SENSOR_CHAN_GYRO_Y: case SENSOR_CHAN_GYRO_Z: - switch (ch) { + switch (ch.chan_type) { case SENSOR_CHAN_GYRO_X: reg_addr = REG_GYRO_DATA_X1; break; diff --git a/drivers/sensor/tdk/icm42688/icm42688_rtio.c b/drivers/sensor/tdk/icm42688/icm42688_rtio.c index ccb9532ee45a2..b9e86c3d9a188 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_rtio.c +++ b/drivers/sensor/tdk/icm42688/icm42688_rtio.c @@ -43,10 +43,10 @@ static int icm42688_rtio_sample_fetch(const struct device *dev, int16_t readings return 0; } -static int icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +static void icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; - const enum sensor_channel *const channels = cfg->channels; + const struct sensor_chan_spec *const channels = cfg->channels; const size_t num_channels = cfg->count; uint32_t min_buf_len = sizeof(struct icm42688_encoded_data); int rc; @@ -59,7 +59,7 @@ static int icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev_ if (rc != 0) { LOG_ERR("Failed to get a read buffer of size %u bytes", min_buf_len); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } edata = (struct icm42688_encoded_data *)buf; @@ -71,24 +71,22 @@ static int icm42688_submit_one_shot(const struct device *dev, struct rtio_iodev_ if (rc != 0) { LOG_ERR("Failed to fetch samples"); rtio_iodev_sqe_err(iodev_sqe, rc); - return rc; + return; } rtio_iodev_sqe_ok(iodev_sqe, 0); - - return 0; } -int icm42688_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) +void icm42688_submit(const struct device *dev, struct rtio_iodev_sqe *iodev_sqe) { const struct sensor_read_config *cfg = iodev_sqe->sqe.iodev->data; if (!cfg->is_streaming) { - return icm42688_submit_one_shot(dev, iodev_sqe); + icm42688_submit_one_shot(dev, iodev_sqe); } else if (IS_ENABLED(CONFIG_ICM42688_STREAM)) { - return icm42688_submit_stream(dev, iodev_sqe); + icm42688_submit_stream(dev, iodev_sqe); } else { - return -ENOTSUP; + rtio_iodev_sqe_err(iodev_sqe, -ENOTSUP); } } diff --git a/drivers/sensor/tdk/icm42688/icm42688_rtio.h b/drivers/sensor/tdk/icm42688/icm42688_rtio.h index 888e8e95357ae..a4d12b82a1891 100644 --- a/drivers/sensor/tdk/icm42688/icm42688_rtio.h +++ b/drivers/sensor/tdk/icm42688/icm42688_rtio.h @@ -10,9 +10,9 @@ #include #include -int icm42688_submit(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); +void icm42688_submit(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); -int icm42688_submit_stream(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); +void icm42688_submit_stream(const struct device *sensor, struct rtio_iodev_sqe *iodev_sqe); void icm42688_fifo_event(const struct device *dev); diff --git a/drivers/sensor/ti/CMakeLists.txt b/drivers/sensor/ti/CMakeLists.txt index 6fae283ad4b67..3ea219ad0bcb3 100644 --- a/drivers/sensor/ti/CMakeLists.txt +++ b/drivers/sensor/ti/CMakeLists.txt @@ -5,8 +5,10 @@ add_subdirectory_ifdef(CONFIG_BQ274XX bq274xx) add_subdirectory_ifdef(CONFIG_FDC2X1X fdc2x1x) add_subdirectory_ifdef(CONFIG_INA219 ina219) +add_subdirectory_ifdef(CONFIG_INA226 ina226) add_subdirectory_ifdef(CONFIG_INA23X ina23x) add_subdirectory_ifdef(CONFIG_INA3221 ina3221) +add_subdirectory_ifdef(CONFIG_LM95234 lm95234) add_subdirectory_ifdef(CONFIG_OPT3001 opt3001) add_subdirectory_ifdef(CONFIG_TI_HDC ti_hdc) add_subdirectory_ifdef(CONFIG_TI_HDC20XX ti_hdc20xx) diff --git a/drivers/sensor/ti/Kconfig b/drivers/sensor/ti/Kconfig index d3b5569815911..00f6de6a94a46 100644 --- a/drivers/sensor/ti/Kconfig +++ b/drivers/sensor/ti/Kconfig @@ -5,8 +5,10 @@ source "drivers/sensor/ti/bq274xx/Kconfig" source "drivers/sensor/ti/fdc2x1x/Kconfig" source "drivers/sensor/ti/ina219/Kconfig" +source "drivers/sensor/ti/ina226/Kconfig" source "drivers/sensor/ti/ina23x/Kconfig" source "drivers/sensor/ti/ina3221/Kconfig" +source "drivers/sensor/ti/lm95234/Kconfig" source "drivers/sensor/ti/opt3001/Kconfig" source "drivers/sensor/ti/ti_hdc/Kconfig" source "drivers/sensor/ti/ti_hdc20xx/Kconfig" diff --git a/drivers/sensor/ti/ina226/CMakeLists.txt b/drivers/sensor/ti/ina226/CMakeLists.txt new file mode 100644 index 0000000000000..fd0e774e908e1 --- /dev/null +++ b/drivers/sensor/ti/ina226/CMakeLists.txt @@ -0,0 +1,6 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources_ifdef(CONFIG_INA226 ina226.c) diff --git a/drivers/sensor/ti/ina226/Kconfig b/drivers/sensor/ti/ina226/Kconfig new file mode 100644 index 0000000000000..f0e9cc75beeca --- /dev/null +++ b/drivers/sensor/ti/ina226/Kconfig @@ -0,0 +1,26 @@ +# INA226 Bidirectional Current/Power Monitor + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config INA226 + bool "INA226 Current/Power Monitor" + default y + depends on DT_HAS_TI_INA226_ENABLED + select I2C + help + Enable driver for INA226 Bidirectional Current/Power Monitor. + +config INA226_VSHUNT + bool "INA226 VShunt Measurement Enable" + depends on DT_HAS_TI_INA226_ENABLED + help + Enable shunt voltage measurement for INA226. + + This is the actual shunt voltage measured which is scaled within the + INA226 based upon the SHUNT_CAL register. This value is useful for + determining the measurement noise or debugging the SHUNT_CAL value. + + Note that enabling this option requires an extra I2C read when the + SENSOR_CHAN_ALL is selected. Hence, only enable this option if the + shunt voltage measurement is required. diff --git a/drivers/sensor/ti/ina226/ina226.c b/drivers/sensor/ti/ina226/ina226.c new file mode 100644 index 0000000000000..5f46b0322f064 --- /dev/null +++ b/drivers/sensor/ti/ina226/ina226.c @@ -0,0 +1,335 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* TODO: Add functionality for Trigger. */ + +#define DT_DRV_COMPAT ti_ina226 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* Device register addresses. */ +#define INA226_REG_CONFIG 0x00 +#define INA226_REG_SHUNT_VOLT 0x01 +#define INA226_REG_BUS_VOLT 0x02 +#define INA226_REG_POWER 0x03 +#define INA226_REG_CURRENT 0x04 +#define INA226_REG_CALIB 0x05 +#define INA226_REG_MASK 0x06 +#define INA226_REG_ALERT 0x07 +#define INA226_REG_MANUFACTURER_ID 0xFE +#define INA226_REG_DEVICE_ID 0xFF + +/* Device register values. */ +#define INA226_MANUFACTURER_ID 0x5449 +#define INA226_DEVICE_ID 0x2260 + +struct ina226_data { + const struct device *dev; + int16_t current; + uint16_t bus_voltage; + uint16_t power; +#ifdef CONFIG_INA226_VSHUNT + int16_t shunt_voltage; +#endif + enum sensor_channel chan; +}; + +struct ina226_config { + const struct i2c_dt_spec bus; + uint16_t config; + uint32_t current_lsb; + uint16_t cal; +}; + +LOG_MODULE_REGISTER(INA226, CONFIG_SENSOR_LOG_LEVEL); + +/** @brief Calibration scaling value (scaled by 10^-5) */ +#define INA226_CAL_SCALING 512ULL + +/** @brief The LSB value for the bus voltage register, in microvolts/LSB. */ +#define INA226_BUS_VOLTAGE_TO_uV(x) ((x) * 1250U) + +/** @brief The LSB value for the shunt voltage register, in microvolts/LSB. */ +#define INA226_SHUNT_VOLTAGE_TO_uV(x) ((x) * 2500U / 1000U) + +/** @brief Power scaling (need factor of 0.2) */ +#define INA226_POWER_TO_uW(x) ((x) * 25ULL) + + +int ina226_reg_read_16(const struct i2c_dt_spec *bus, uint8_t reg, uint16_t *val) +{ + uint8_t data[2]; + int ret; + + ret = i2c_burst_read_dt(bus, reg, data, sizeof(data)); + if (ret < 0) { + return ret; + } + + *val = sys_get_be16(data); + + return ret; +} + +int ina226_reg_write(const struct i2c_dt_spec *bus, uint8_t reg, uint16_t val) +{ + uint8_t tx_buf[3]; + + tx_buf[0] = reg; + sys_put_be16(val, &tx_buf[1]); + + return i2c_write_dt(bus, tx_buf, sizeof(tx_buf)); +} + +static void micro_s32_to_sensor_value(struct sensor_value *val, int32_t value_microX) +{ + val->val1 = value_microX / 1000000L; + val->val2 = value_microX % 1000000L; +} + +static int ina226_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + const struct ina226_data *data = dev->data; + const struct ina226_config *config = dev->config; + + switch (chan) { + case SENSOR_CHAN_VOLTAGE: + micro_s32_to_sensor_value(val, INA226_BUS_VOLTAGE_TO_uV(data->bus_voltage)); + break; + case SENSOR_CHAN_CURRENT: + /* see datasheet "Current and Power calculations" section */ + micro_s32_to_sensor_value(val, data->current * config->current_lsb); + break; + case SENSOR_CHAN_POWER: + /* power in uW is power_reg * current_lsb * 0.2 */ + micro_s32_to_sensor_value(val, + INA226_POWER_TO_uW((uint32_t)data->power * config->current_lsb)); + break; +#ifdef CONFIG_INA226_VSHUNT + case SENSOR_CHAN_VSHUNT: + micro_s32_to_sensor_value(val, INA226_SHUNT_VOLTAGE_TO_uV(data->shunt_voltage)); + break; +#endif /* CONFIG_INA226_VSHUNT */ + default: + return -ENOTSUP; + } + + return 0; +} + +static int ina226_read_data(const struct device *dev) +{ + struct ina226_data *data = dev->data; + const struct ina226_config *config = dev->config; + int ret; + + if ((data->chan == SENSOR_CHAN_ALL) || (data->chan == SENSOR_CHAN_VOLTAGE)) { + ret = ina226_reg_read_16(&config->bus, INA226_REG_BUS_VOLT, &data->bus_voltage); + if (ret < 0) { + LOG_ERR("Failed to read bus voltage"); + return ret; + } + } + + if ((data->chan == SENSOR_CHAN_ALL) || (data->chan == SENSOR_CHAN_CURRENT)) { + ret = ina226_reg_read_16(&config->bus, INA226_REG_CURRENT, &data->current); + if (ret < 0) { + LOG_ERR("Failed to read current"); + return ret; + } + } + + if ((data->chan == SENSOR_CHAN_ALL) || (data->chan == SENSOR_CHAN_POWER)) { + ret = ina226_reg_read_16(&config->bus, INA226_REG_POWER, &data->power); + if (ret < 0) { + LOG_ERR("Failed to read power"); + return ret; + } + } + +#ifdef CONFIG_INA226_VSHUNT + if ((data->chan == SENSOR_CHAN_ALL) || (data->chan == SENSOR_CHAN_VSHUNT)) { + ret = ina226_reg_read_16(&config->bus, INA226_REG_SHUNT_VOLT, &data->shunt_voltage); + if (ret < 0) { + LOG_ERR("Failed to read shunt voltage"); + return ret; + } + } +#endif /* CONFIG_INA226_VSHUNT */ + + return 0; +} + +static int ina226_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + struct ina226_data *data = dev->data; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_VOLTAGE + && chan != SENSOR_CHAN_CURRENT && chan != SENSOR_CHAN_POWER +#ifdef CONFIG_INA226_VSHUNT + && chan != SENSOR_CHAN_VSHUNT +#endif /* CONFIG_INA226_VSHUNT */ + ) { + return -ENOTSUP; + } + + data->chan = chan; + + return ina226_read_data(dev); +} + +static int ina226_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + const struct ina226_config *config = dev->config; + uint16_t data = val->val1; + + switch (attr) { + case SENSOR_ATTR_CONFIGURATION: + return ina226_reg_write(&config->bus, INA226_REG_CONFIG, data); + case SENSOR_ATTR_CALIBRATION: + return ina226_reg_write(&config->bus, INA226_REG_CALIB, data); + default: + LOG_ERR("INA226 attribute not supported."); + return -ENOTSUP; + } +} + +static int ina226_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + const struct ina226_config *config = dev->config; + uint16_t data; + int ret; + + switch (attr) { + case SENSOR_ATTR_CONFIGURATION: + ret = ina226_reg_read_16(&config->bus, INA226_REG_CONFIG, &data); + if (ret < 0) { + return ret; + } + break; + case SENSOR_ATTR_CALIBRATION: + ret = ina226_reg_read_16(&config->bus, INA226_REG_CALIB, &data); + if (ret < 0) { + return ret; + } + break; + default: + LOG_ERR("INA226 attribute not supported."); + return -ENOTSUP; + } + + val->val1 = data; + val->val2 = 0; + + return 0; +} + +static int ina226_calibrate(const struct device *dev) +{ + const struct ina226_config *config = dev->config; + int ret; + + ret = ina226_reg_write(&config->bus, INA226_REG_CALIB, config->cal); + if (ret < 0) { + return ret; + } + + return 0; +} + +static int ina226_init(const struct device *dev) +{ + struct ina226_data *data = dev->data; + const struct ina226_config *config = dev->config; + uint16_t id; + int ret; + + if (!i2c_is_ready_dt(&config->bus)) { + LOG_ERR("I2C bus %s is not ready", config->bus.bus->name); + return -ENODEV; + } + + data->dev = dev; + + ret = ina226_reg_read_16(&config->bus, INA226_REG_MANUFACTURER_ID, &id); + if (ret < 0) { + LOG_ERR("Failed to read manufacturer register."); + return ret; + } + + if (id != INA226_MANUFACTURER_ID) { + LOG_ERR("Manufacturer ID doesn't match."); + return -ENODEV; + } + + ret = ina226_reg_read_16(&config->bus, INA226_REG_DEVICE_ID, &id); + if (ret < 0) { + LOG_ERR("Failed to read device register."); + return ret; + } + + if (id != INA226_DEVICE_ID) { + LOG_ERR("Device ID doesn't match."); + return -ENODEV; + } + + ret = ina226_reg_write(&config->bus, INA226_REG_CONFIG, config->config); + if (ret < 0) { + LOG_ERR("Failed to write configuration register."); + return ret; + } + + ret = ina226_calibrate(dev); + if (ret < 0) { + LOG_ERR("Failed to write calibration register."); + return ret; + } + + return 0; +} + +static const struct sensor_driver_api ina226_driver_api = { + .attr_set = ina226_attr_set, + .attr_get = ina226_attr_get, + .sample_fetch = ina226_sample_fetch, + .channel_get = ina226_channel_get, +}; + +#define INA226_DRIVER_INIT(inst) \ + static struct ina226_data ina226_data_##inst; \ + static const struct ina226_config ina226_config_##inst = { \ + .bus = I2C_DT_SPEC_INST_GET(inst), \ + .current_lsb = DT_INST_PROP(inst, current_lsb_microamps), \ + .cal = INA226_CAL_SCALING * 10000000ULL / \ + (DT_INST_PROP(inst, current_lsb_microamps) * \ + DT_INST_PROP(inst, rshunt_micro_ohms)), \ + .config = (DT_INST_ENUM_IDX(inst, avg_count) << 9) | \ + (DT_INST_ENUM_IDX(inst, vbus_conversion_time_us) << 6) | \ + (DT_INST_ENUM_IDX(inst, vshunt_conversion_time_us) << 3) | \ + DT_INST_ENUM_IDX(inst, operating_mode), \ + }; \ + SENSOR_DEVICE_DT_INST_DEFINE(inst, \ + &ina226_init, \ + NULL, \ + &ina226_data_##inst, \ + &ina226_config_##inst, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &ina226_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(INA226_DRIVER_INIT) diff --git a/drivers/sensor/ti/lm95234/CMakeLists.txt b/drivers/sensor/ti/lm95234/CMakeLists.txt new file mode 100644 index 0000000000000..1eeeec6132b4d --- /dev/null +++ b/drivers/sensor/ti/lm95234/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(lm95234.c) diff --git a/drivers/sensor/ti/lm95234/Kconfig b/drivers/sensor/ti/lm95234/Kconfig new file mode 100644 index 0000000000000..e7e8528405d03 --- /dev/null +++ b/drivers/sensor/ti/lm95234/Kconfig @@ -0,0 +1,13 @@ +# LM95234 temperature sensor config + +# Copyright (c) 2024 Calian Advanced Technologies +# SPDX-License-Identifier: Apache-2.0 + +config LM95234 + bool "LM95234 Temperature Sensor" + default y + depends on DT_HAS_NATIONAL_LM95234_ENABLED + select I2C + help + Enable the driver for the LM95234 Quad Remote Diode and Local + Temperature Sensor with SMBus Interface. diff --git a/drivers/sensor/ti/lm95234/lm95234.c b/drivers/sensor/ti/lm95234/lm95234.c new file mode 100644 index 0000000000000..9beabc6da28d5 --- /dev/null +++ b/drivers/sensor/ti/lm95234/lm95234.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2024 Calian Advanced Technologies + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT national_lm95234 + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(LM95234, CONFIG_SENSOR_LOG_LEVEL); + +#define LM95234_REG_LOCAL_TEMP_SIGNED_MSB 0x10 +#define LM95234_REG_LOCAL_TEMP_SIGNED_LSB 0x20 +#define LM95234_REG_REMOTE_TEMP_1_SIGNED_MSB 0x11 +#define LM95234_REG_REMOTE_TEMP_1_SIGNED_LSB 0x21 +#define LM95234_REG_REMOTE_TEMP_2_SIGNED_MSB 0x12 +#define LM95234_REG_REMOTE_TEMP_2_SIGNED_LSB 0x22 +#define LM95234_REG_REMOTE_TEMP_3_SIGNED_MSB 0x13 +#define LM95234_REG_REMOTE_TEMP_3_SIGNED_LSB 0x23 +#define LM95234_REG_REMOTE_TEMP_4_SIGNED_MSB 0x14 +#define LM95234_REG_REMOTE_TEMP_4_SIGNED_LSB 0x24 +#define LM95234_REG_REMOTE_TEMP_1_UNSIGNED_MSB 0x19 +#define LM95234_REG_REMOTE_TEMP_1_UNSIGNED_LSB 0x29 +#define LM95234_REG_REMOTE_TEMP_2_UNSIGNED_MSB 0x1a +#define LM95234_REG_REMOTE_TEMP_2_UNSIGNED_LSB 0x2a +#define LM95234_REG_REMOTE_TEMP_3_UNSIGNED_MSB 0x1b +#define LM95234_REG_REMOTE_TEMP_3_UNSIGNED_LSB 0x2b +#define LM95234_REG_REMOTE_TEMP_4_UNSIGNED_MSB 0x1c +#define LM95234_REG_REMOTE_TEMP_4_UNSIGNED_LSB 0x2c +#define LM95234_REG_DIODE_MODEL_SELECT 0x30 +#define LM95234_REG_REMOTE_1_OFFSET 0x31 +#define LM95234_REG_REMOTE_2_OFFSET 0x32 +#define LM95234_REG_REMOTE_3_OFFSET 0x33 +#define LM95234_REG_REMOTE_4_OFFSET 0x34 +#define LM95234_REG_CONFIG 0x03 +#define LM95234_REG_CONV_RATE 0x04 +#define LM95234_REG_CHANNEL_CONV_ENABLE 0x05 +#define LM95234_REG_FILTER_SETTING 0x06 +#define LM95234_REG_ONESHOT 0x0f +#define LM95234_REG_COMMON_STATUS 0x02 +#define LM95234_REG_STATUS_1 0x07 +#define LM95234_REG_STATUS_2 0x08 +#define LM95234_REG_STATUS_3 0x09 +#define LM95234_REG_STATUS_4 0x0a +#define LM95234_REG_DIODE_MODEL_STATUS 0x38 +#define LM95234_REG_TCRIT1_MASK 0x0c +#define LM95234_REG_TCRIT2_MASK 0x0d +#define LM95234_REG_TCRIT3_MASK 0x0e +#define LM95234_REG_LOCAL_TCRIT_LIMIT 0x40 +#define LM95234_REG_REMOTE1_TCRIT1_LIMIT 0x41 +#define LM95234_REG_REMOTE2_TCRIT1_LIMIT 0x42 +#define LM95234_REG_REMOTE3_TCRIT_LIMIT 0x43 +#define LM95234_REG_REMOTE4_TCRIT_LIMIT 0x44 +#define LM95234_REG_REMOTE1_TCRIT23_LIMIT 0x49 +#define LM95234_REG_REMOTE2_TCRIT23_LIMIT 0x4a +#define LM95234_REG_COMMON_TCRIT_HYSTERESIS 0x5a +#define LM95234_REG_MANUF_ID 0xfe +#define LM95234_REG_REV_ID 0xff + +#define LM95234_MAN_ID 0x01 +#define LM95234_CHIP_ID 0x79 + +#define LM95234_CONFIG_STANDBY BIT(6) + +struct lm95234_data { + /** Temperatures in raw format read from sensor */ + int32_t local; + int32_t remote[4]; +}; + +struct lm95234_config { + struct i2c_dt_spec i2c; +}; + +static inline int lm95234_fetch_temp(const struct lm95234_config *cfg, struct lm95234_data *data, + enum sensor_channel chan, int32_t *output) +{ + int ret; + uint8_t val; + int32_t result = 0; + + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + uint16_t temp; + int offset = (chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1); + + ret = i2c_reg_read_byte_dt(&cfg->i2c, + LM95234_REG_REMOTE_TEMP_1_UNSIGNED_MSB + offset, &val); + if (ret) { + return ret; + } + temp = val << 8; + ret = i2c_reg_read_byte_dt(&cfg->i2c, + LM95234_REG_REMOTE_TEMP_1_UNSIGNED_LSB + offset, &val); + if (ret) { + return ret; + } + temp |= val; + result = temp; + } + + /* Read signed temperature if unsigned temperature is 0, or for local sensor */ + if (chan == SENSOR_CHAN_AMBIENT_TEMP || result == 0) { + int offset = chan == SENSOR_CHAN_AMBIENT_TEMP ? 0 : + (chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1 + 1); + int16_t temp; + + ret = i2c_reg_read_byte_dt(&cfg->i2c, + LM95234_REG_LOCAL_TEMP_SIGNED_MSB + offset, &val); + if (ret) { + return ret; + } + temp = val << 8; + ret = i2c_reg_read_byte_dt(&cfg->i2c, + LM95234_REG_LOCAL_TEMP_SIGNED_LSB + offset, &val); + if (ret) { + return ret; + } + temp |= val; + result = temp; + } + *output = result; + return 0; +} + +static int lm95234_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + struct lm95234_data *data = dev->data; + const struct lm95234_config *cfg = dev->config; + enum pm_device_state pm_state; + int ret; + + (void)pm_device_state_get(dev, &pm_state); + if (pm_state != PM_DEVICE_STATE_ACTIVE) { + ret = -EIO; + return ret; + } + + switch ((uint32_t)chan) { + case SENSOR_CHAN_ALL: + ret = lm95234_fetch_temp(cfg, data, SENSOR_CHAN_AMBIENT_TEMP, &data->local); + if (ret) + return ret; + for (int i = 0; i < ARRAY_SIZE(data->remote); i++) { + ret = lm95234_fetch_temp(cfg, data, + SENSOR_CHAN_LM95234_REMOTE_TEMP_1 + i, + &data->remote[i]); + if (ret) + return ret; + } + break; + case SENSOR_CHAN_AMBIENT_TEMP: + ret = lm95234_fetch_temp(cfg, data, chan, &data->local); + break; + case SENSOR_CHAN_LM95234_REMOTE_TEMP_1: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_2: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_3: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_4: + ret = lm95234_fetch_temp(cfg, data, chan, + &data->remote[chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1]); + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} + +static int lm95234_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct lm95234_data *data = dev->data; + int32_t raw_temp; + + switch ((uint32_t)chan) { + case SENSOR_CHAN_AMBIENT_TEMP: + raw_temp = data->local; + break; + case SENSOR_CHAN_LM95234_REMOTE_TEMP_1: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_2: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_3: + case SENSOR_CHAN_LM95234_REMOTE_TEMP_4: + raw_temp = data->remote[chan - SENSOR_CHAN_LM95234_REMOTE_TEMP_1]; + break; + default: + return -ENOTSUP; + } + + /* Raw data format is 8 bits integer, 5 bits fractional, 3 bits zero */ + val->val1 = raw_temp / 256; + val->val2 = (raw_temp % 256) * 1000000 / 256; + return 0; +} + +static const struct sensor_driver_api lm95234_driver_api = { + .sample_fetch = lm95234_sample_fetch, + .channel_get = lm95234_channel_get, +}; + +static int lm95234_init(const struct device *dev) +{ + const struct lm95234_config *cfg = dev->config; + int ret = 0; + uint8_t value, model_select, model_status; + + if (!i2c_is_ready_dt(&cfg->i2c)) { + LOG_ERR("I2C dev not ready"); + return -ENODEV; + } + + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_MANUF_ID, &value); + if (ret) { + LOG_ERR("Could not read manufacturer ID: %d", ret); + return ret; + } + if (value != LM95234_MAN_ID) { + LOG_ERR("Invalid manufacturer ID: %02x", value); + return -ENODEV; + } + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_REV_ID, &value); + if (ret) { + LOG_ERR("Could not read revision ID: %d", ret); + return ret; + } + if (value != LM95234_CHIP_ID) { + LOG_ERR("Invalid chip ID: %02x", value); + return -ENODEV; + } + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_CONFIG, &value); + if (ret) { + LOG_ERR("Could not read config: %d", ret); + return ret; + } + if (value & LM95234_CONFIG_STANDBY) { + value &= ~LM95234_CONFIG_STANDBY; + ret = i2c_reg_write_byte_dt(&cfg->i2c, LM95234_REG_CONFIG, value); + if (ret) { + LOG_ERR("Could not write config: %d", ret); + return ret; + } + } + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_DIODE_MODEL_SELECT, &model_select); + if (ret) { + LOG_ERR("Could not read diode model select: %d", ret); + return ret; + } + ret = i2c_reg_read_byte_dt(&cfg->i2c, LM95234_REG_DIODE_MODEL_STATUS, &model_status); + if (ret) { + LOG_ERR("Could not read diode model status: %d", ret); + return ret; + } + /** + * Check if any remote inputs have a 3904 transistor detected but are not configured + * as such. If so, configure them as 3904 transistors. + */ + if (model_select & model_status) { + model_select &= ~model_status; + ret = i2c_reg_write_byte_dt(&cfg->i2c, LM95234_REG_DIODE_MODEL_SELECT, + model_select); + if (ret) { + LOG_ERR("Could not write diode model select: %d", ret); + return ret; + } + } + +#ifdef CONFIG_PM_DEVICE_RUNTIME + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); + if (ret < 0 && ret != -ENOTSUP) { + LOG_ERR("Failed to enable runtime power management"); + return ret; + } +#endif + + return 0; +} + +#ifdef CONFIG_PM_DEVICE + +static int lm95234_pm_action(const struct device *dev, enum pm_device_action action) +{ + switch (action) { + case PM_DEVICE_ACTION_TURN_ON: + case PM_DEVICE_ACTION_RESUME: + case PM_DEVICE_ACTION_TURN_OFF: + case PM_DEVICE_ACTION_SUSPEND: + break; + default: + return -ENOTSUP; + } + + return 0; +} + +#endif + +#define LM95234_INST(inst) \ +static struct lm95234_data lm95234_data_##inst; \ +static const struct lm95234_config lm95234_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ +}; \ +PM_DEVICE_DT_INST_DEFINE(inst, lm95234_pm_action); \ +SENSOR_DEVICE_DT_INST_DEFINE(inst, lm95234_init, \ + PM_DEVICE_DT_INST_GET(inst), \ + &lm95234_data_##inst, \ + &lm95234_config_##inst, \ + POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, \ + &lm95234_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(LM95234_INST) diff --git a/drivers/sensor/ti/tmag5273/tmag5273.c b/drivers/sensor/ti/tmag5273/tmag5273.c index 0ef91725deef8..7c7cd92a25b0d 100644 --- a/drivers/sensor/ti/tmag5273/tmag5273.c +++ b/drivers/sensor/ti/tmag5273/tmag5273.c @@ -102,17 +102,17 @@ static int tmag5273_reset_device_status(const struct device *dev) /** * @brief checks for DIAG_FAIL errors and reads out the DEVICE_STATUS register if necessary * - * Prints a human readable representation to the log, if \c CONFIG_LOG is activated. - * - * @param drv_cfg[in] driver instance configuration - * @param device_status[out] DEVICE_STATUS register if DIAG_FAIL is set + * @param[in] drv_cfg driver instance configuration + * @param[out] device_status DEVICE_STATUS register if DIAG_FAIL is set * * @retval 0 on success - * @retval "!= 0" on error (see @ref i2c_reg_read_byte for error codes) + * @retval "!= 0" on error + * - \c -EIO on any set error device status bit + * - see @ref i2c_reg_read_byte for error codes * * @note - * If tmag5273_config.ignore_diag_fail is se - * - \a device_status will be always set to \c 0, + * If tmag5273_config.ignore_diag_fail is set + * - \a device_status will be always set to \c 0, * - the function always returns \c 0. */ static int tmag5273_check_device_status(const struct tmag5273_config *drv_cfg, @@ -144,23 +144,23 @@ static int tmag5273_check_device_status(const struct tmag5273_config *drv_cfg, } if ((*device_status & TMAG5273_VCC_UV_ER_MSK) == TMAG5273_VCC_UV_ERR) { - LOG_WRN("VCC undervoltage detected"); + LOG_ERR("VCC under voltage detected"); } #ifdef CONFIG_CRC if (drv_cfg->crc_enabled && ((*device_status & TMAG5273_OTP_CRC_ER_MSK) == TMAG5273_OTP_CRC_ERR)) { - LOG_WRN("OTP CRC error detected"); + LOG_ERR("OTP CRC error detected"); } #endif if ((*device_status & TMAG5273_INT_ER_MSK) == TMAG5273_INT_ERR) { - LOG_WRN("INT pin error detected"); + LOG_ERR("INT pin error detected"); } if ((*device_status & TMAG5273_OSC_ER_MSK) == TMAG5273_OSC_ERR) { - LOG_WRN("Oscillator error detected"); + LOG_ERR("Oscillator error detected"); } - return 0; + return -EIO; } /** @@ -689,11 +689,6 @@ static int tmag5273_sample_fetch(const struct device *dev, enum sensor_channel c return retval; } - if ((i2c_buffer[TMAG5273_REG_CONV_STATUS - TMAG5273_REG_RESULT_BEGIN] & - TMAG5273_DIAG_STATUS_MSK) == TMAG5273_DIAG_FAIL) { - return -EIO; - } - bool all_channels = (chan == SENSOR_CHAN_ALL); bool all_xyz = all_channels || (chan == SENSOR_CHAN_MAGN_XYZ); bool all_angle_magnitude = all_channels || ((int)chan == TMAG5273_CHAN_ANGLE_MAGNITUDE); @@ -1118,7 +1113,7 @@ static int tmag5273_init(const struct device *dev) return -EINVAL; } - tmag5273_check_device_status(drv_cfg, ®data); + (void)tmag5273_check_device_status(drv_cfg, ®data); retval = tmag5273_reset_device_status(dev); if (retval < 0) { diff --git a/drivers/sensor/ti/tmp112/Kconfig b/drivers/sensor/ti/tmp112/Kconfig index 19baeade7dcd3..c6ece4e4b8ce0 100644 --- a/drivers/sensor/ti/tmp112/Kconfig +++ b/drivers/sensor/ti/tmp112/Kconfig @@ -15,6 +15,8 @@ config TMP112 The TMP102 is compatible with the TMP112 but is less accurate and has been successfully tested with this driver. +if TMP112 + config TMP112_FULL_SCALE_RUNTIME bool "Allow to set extended mode at runtime" default y @@ -28,3 +30,5 @@ config TMP112_SAMPLING_FREQUENCY_RUNTIME help When set conversion rate can be set at runtime using sensor_attr_set with SENSOR_ATTR_SAMPLING_FREQUENCY + +endif # TMP112 diff --git a/drivers/sensor/tsic_xx6/CMakeLists.txt b/drivers/sensor/tsic_xx6/CMakeLists.txt new file mode 100644 index 0000000000000..968d4cfe796bd --- /dev/null +++ b/drivers/sensor/tsic_xx6/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_TSIC_XX6 tsic_xx6.c) diff --git a/drivers/sensor/tsic_xx6/Kconfig b/drivers/sensor/tsic_xx6/Kconfig new file mode 100644 index 0000000000000..761eae1d96363 --- /dev/null +++ b/drivers/sensor/tsic_xx6/Kconfig @@ -0,0 +1,11 @@ +# Copyright (c) 2024 Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +config TSIC_XX6 + bool "TSic xx6 driver" + default y + depends on DT_HAS_IST_TSIC_XX6_ENABLED + select PWM + select PWM_CAPTURE + help + Enable driver for TSic 206/306/316/506F/516/716. diff --git a/drivers/sensor/tsic_xx6/tsic_xx6.c b/drivers/sensor/tsic_xx6/tsic_xx6.c new file mode 100644 index 0000000000000..5470394a49ff9 --- /dev/null +++ b/drivers/sensor/tsic_xx6/tsic_xx6.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2024, Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ist_tsic_xx6 + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(TSIC_XX6, CONFIG_SENSOR_LOG_LEVEL); + +#define FRAME_BIT_PERIOD_US 125 + +enum { + FRAME_PARITIY_BIT_LSB, + FRAME_DATA_BIT_0, + FRAME_DATA_BIT_1, + FRAME_DATA_BIT_2, + FRAME_DATA_BIT_3, + FRAME_DATA_BIT_4, + FRAME_DATA_BIT_5, + FRAME_DATA_BIT_6, + FRAME_DATA_BIT_7, + FRAME_START_BIT_LSB, + /* Theres a single bit period between the two packets that is constant high. This bit will + * be part of the 2nd packet's start bit thus frame length is not affected. + */ + FRAME_PARITIY_BIT_MSB, + FRAME_DATA_BIT_8, + FRAME_DATA_BIT_9, + FRAME_DATA_BIT_10, + FRAME_DATA_BIT_11, + FRAME_DATA_BIT_12, + FRAME_DATA_BIT_13, + FRAME_ZERO_BIT_0, + FRAME_ZERO_BIT_1, + FRAME_START_BIT_MSB, + FRAME_READY_BIT, + FRAME_FLAGS, +}; + +struct tsic_xx6_config { + const struct pwm_dt_spec pwm; + const int8_t lower_temperature_limit; + const uint8_t higher_temperature_limit; + const uint8_t data_bits; +}; + +struct tsic_xx6_data { + uint64_t frame_cycles; + struct sensor_value val; + + ATOMIC_DEFINE(frame, FRAME_FLAGS); + uint32_t buf; + uint8_t buf_index; +}; + +static inline void tsic_xx6_buf_reset(struct tsic_xx6_data *data) +{ + data->buf_index = FRAME_START_BIT_MSB; +} + +static inline bool tsic_xx6_is_buf_reset(struct tsic_xx6_data *data) +{ + return data->buf_index == FRAME_START_BIT_MSB; +} + +static inline bool tsic_xx6_is_data_line_idle(struct tsic_xx6_data *data, uint64_t period_cycles) +{ + /* If the period is larger than two frames assume the data line has been idle */ + return period_cycles > data->frame_cycles * 2; +} + +static void tsic_xx6_pwm_callback(const struct device *dev, uint32_t channel, + uint32_t period_cycles, uint32_t pulse_cycles, int status, + void *user_data) +{ + const struct device *tsic_xx6_dev = user_data; + const struct tsic_xx6_config *config = tsic_xx6_dev->config; + struct tsic_xx6_data *data = tsic_xx6_dev->data; + uint32_t low_cycles; + bool val; + + if (dev != config->pwm.dev || channel != config->pwm.channel) { + return; + } + + if (status != 0) { + LOG_ERR("callback failed: %d", status); + return; + } + + if (!tsic_xx6_is_buf_reset(data) && tsic_xx6_is_data_line_idle(data, period_cycles)) { + LOG_ERR("unexpected data idle"); + tsic_xx6_buf_reset(data); + } + + /* + * Calculate low cycles: The sensor sends the pulse in the last part of the period. The PWM + * capture driver triggers on rising edge with normal polarity. Therefore only the low part + * of the frame bit is present. + */ + low_cycles = period_cycles - pulse_cycles; + + /* 25 % duty cycle is 0, 75 % duty cycle is 1 */ + val = low_cycles * 2 < data->frame_cycles; + WRITE_BIT(data->buf, data->buf_index, val); + + if (data->buf_index > 0) { + --data->buf_index; + } else { + WRITE_BIT(data->buf, FRAME_READY_BIT, 1); + (void)atomic_set(data->frame, data->buf); + tsic_xx6_buf_reset(data); + } +} + +static inline bool tsic_xx6_parity_check(uint8_t data, bool parity) +{ + bool data_parity = false; + size_t i; + + for (i = 0; i < 8; ++i) { + data_parity ^= FIELD_GET(BIT(i), data); + } + + return (parity ^ data_parity) == 0; +} + +static int tsic_xx6_get_data_bits(const struct tsic_xx6_config *config, uint16_t *data_bits, + uint32_t frame) +{ + uint8_t frame_data_bit_high = + config->data_bits == 14 ? FRAME_DATA_BIT_13 : FRAME_DATA_BIT_10; + uint8_t data_msb = FIELD_GET(GENMASK(frame_data_bit_high, FRAME_DATA_BIT_8), frame); + uint8_t data_lsb = FIELD_GET(GENMASK(FRAME_DATA_BIT_7, FRAME_DATA_BIT_0), frame); + bool parity_msb = FIELD_GET(BIT(FRAME_PARITIY_BIT_MSB), frame); + bool parity_lsb = BIT(FRAME_PARITIY_BIT_LSB) & frame; + + if (!tsic_xx6_parity_check(data_msb, parity_msb) || + !tsic_xx6_parity_check(data_lsb, parity_lsb)) { + return -EIO; + } + + *data_bits = data_msb << 8 | data_lsb; + + return 0; +} + +static void tsic_xx6_get_value(const struct tsic_xx6_config *config, struct tsic_xx6_data *data, + uint16_t data_bits) +{ + int64_t tmp; + + /* Apply the datasheet formula scaled to micro celcius */ + tmp = data_bits * (config->higher_temperature_limit - config->lower_temperature_limit); + tmp = tmp * 1000000 / (BIT(config->data_bits) - 1); + tmp += (int64_t)config->lower_temperature_limit * 1000000; + + data->val.val1 = tmp / 1000000; + data->val.val2 = tmp % 1000000; +} + +static int tsic_xx6_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + const struct tsic_xx6_config *config = dev->config; + struct tsic_xx6_data *data = dev->data; + uint32_t frame; + uint16_t data_bits; + int rc; + + if (chan != SENSOR_CHAN_ALL && chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + frame = atomic_and(data->frame, ~BIT(FRAME_READY_BIT)); + + if (FIELD_GET(BIT(FRAME_READY_BIT), frame) == 0) { + return -EBUSY; + } + + rc = tsic_xx6_get_data_bits(config, &data_bits, frame); + if (rc != 0) { + return rc; + } + + tsic_xx6_get_value(config, data, data_bits); + + return 0; +} + +static int tsic_xx6_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + struct tsic_xx6_data *data = dev->data; + + if (chan != SENSOR_CHAN_AMBIENT_TEMP) { + return -ENOTSUP; + } + + *val = data->val; + + return 0; +} + +static const struct sensor_driver_api tsic_xx6_driver_api = {.sample_fetch = tsic_xx6_sample_fetch, + .channel_get = tsic_xx6_channel_get}; + +static int tsic_xx6_get_frame_cycles(const struct tsic_xx6_config *config, uint64_t *frame_cycles) +{ + uint64_t tmp; + int rc; + + rc = pwm_get_cycles_per_sec(config->pwm.dev, config->pwm.channel, &tmp); + if (rc != 0) { + return rc; + } + + if (u64_mul_overflow(tmp, FRAME_BIT_PERIOD_US, &tmp)) { + return -ERANGE; + } + + *frame_cycles = tmp / USEC_PER_SEC; + + return 0; +} + +static int tsic_xx6_init(const struct device *dev) +{ + const struct tsic_xx6_config *config = dev->config; + struct tsic_xx6_data *data = dev->data; + int rc; + + if (!pwm_is_ready_dt(&config->pwm)) { + return -ENODEV; + } + + rc = tsic_xx6_get_frame_cycles(config, &data->frame_cycles); + if (rc != 0) { + return rc; + } + + rc = pwm_configure_capture(config->pwm.dev, config->pwm.channel, + config->pwm.flags | PWM_CAPTURE_TYPE_BOTH | + PWM_CAPTURE_MODE_CONTINUOUS, + tsic_xx6_pwm_callback, (void *)dev); + if (rc != 0) { + return rc; + } + + tsic_xx6_buf_reset(data); + + rc = pwm_enable_capture(config->pwm.dev, config->pwm.channel); + if (rc != 0) { + return rc; + } + + return 0; +} + +#define TSIC_XX6_DEVICE(n) \ + \ + static struct tsic_xx6_data tsic_xx6_data_##n; \ + \ + static const struct tsic_xx6_config tsic_xx6_config_##n = { \ + .pwm = PWM_DT_SPEC_INST_GET(n), \ + .lower_temperature_limit = (int8_t)DT_INST_PROP(n, lower_temperature_limit), \ + .higher_temperature_limit = DT_INST_PROP(n, higher_temperature_limit), \ + .data_bits = DT_INST_PROP(n, data_bits), \ + }; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(n, &tsic_xx6_init, NULL, &tsic_xx6_data_##n, \ + &tsic_xx6_config_##n, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &tsic_xx6_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(TSIC_XX6_DEVICE) diff --git a/drivers/sensor/veaa_x_3/CMakeLists.txt b/drivers/sensor/veaa_x_3/CMakeLists.txt new file mode 100644 index 0000000000000..07db16869425c --- /dev/null +++ b/drivers/sensor/veaa_x_3/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources(veaa_x_3.c) diff --git a/drivers/sensor/veaa_x_3/Kconfig b/drivers/sensor/veaa_x_3/Kconfig new file mode 100644 index 0000000000000..143618c6838aa --- /dev/null +++ b/drivers/sensor/veaa_x_3/Kconfig @@ -0,0 +1,18 @@ +# VEAA-X-3 configuration options + +# Copyright (c) 2024, Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +config VEAA_X_3 + bool "VEAA-X-3 pressure driver" + default y + depends on DT_HAS_FESTO_VEAA_X_3_ENABLED + depends on ADC + depends on DAC + help + Enable driver for Festo VEAA-X-3. + + The driver assumes that the maximum ADC value matches the maximum + output from the device, and that the maximum DAC value matches the + maximum input value for the device. External hardware is probably + required between the ADC/DAC and the device. diff --git a/drivers/sensor/veaa_x_3/veaa_x_3.c b/drivers/sensor/veaa_x_3/veaa_x_3.c new file mode 100644 index 0000000000000..c5935942069e7 --- /dev/null +++ b/drivers/sensor/veaa_x_3/veaa_x_3.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2024, Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + * + * Datasheet: + * https://www.festo.com/media/pim/620/D15000100140620.PDF + * + */ + +#define DT_DRV_COMPAT festo_veaa_x_3 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(veaa_x_3_sensor, CONFIG_SENSOR_LOG_LEVEL); + +struct veaa_x_3_data { + uint16_t adc_buf; +}; + +struct veaa_x_3_cfg { + const struct adc_dt_spec adc; + const struct device *dac; + const uint8_t dac_channel; + const uint8_t dac_resolution; + const uint16_t kpa_max; + const uint8_t kpa_min; +}; + +static uint16_t veaa_x_3_kpa_range(const struct veaa_x_3_cfg *cfg) +{ + return cfg->kpa_max - cfg->kpa_min; +} + +static int veaa_x_3_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + const struct veaa_x_3_cfg *cfg = dev->config; + uint32_t tmp; + + if (chan != SENSOR_CHAN_PRESS) { + return -ENOTSUP; + } + + switch ((enum sensor_attribute_veaa_x_3)attr) { + case SENSOR_ATTR_VEAA_X_3_SETPOINT: + if (val->val1 > cfg->kpa_max || val->val1 < cfg->kpa_min) { + LOG_ERR("%d kPa outside range", val->val1); + return -EINVAL; + } + + /* Convert from kPa to DAC value */ + tmp = val->val1 - cfg->kpa_min; + if (u32_mul_overflow(tmp, BIT(cfg->dac_resolution) - 1, &tmp)) { + LOG_ERR("kPa to DAC overflow"); + return -ERANGE; + } + tmp /= veaa_x_3_kpa_range(cfg); + + return dac_write_value(cfg->dac, cfg->dac_channel, tmp); + default: + return -ENOTSUP; + } +} + +static int veaa_x_3_attr_get(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, struct sensor_value *val) +{ + const struct veaa_x_3_cfg *cfg = dev->config; + + if (chan != SENSOR_CHAN_PRESS) { + return -ENOTSUP; + } + + switch ((enum sensor_attribute_veaa_x_3)attr) { + case SENSOR_ATTR_VEAA_X_3_RANGE: + val->val1 = cfg->kpa_min; + val->val2 = cfg->kpa_max; + return 0; + default: + return -ENOTSUP; + } +} + +static int veaa_x_3_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + int rc; + const struct veaa_x_3_cfg *cfg = dev->config; + struct veaa_x_3_data *data = dev->data; + struct adc_sequence sequence = { + .buffer = &data->adc_buf, + .buffer_size = sizeof(data->adc_buf), + }; + + if (chan != SENSOR_CHAN_PRESS && chan != SENSOR_CHAN_ALL) { + return -ENOTSUP; + } + + rc = adc_sequence_init_dt(&cfg->adc, &sequence); + if (rc != 0) { + return rc; + } + sequence.options = NULL; + sequence.buffer = &data->adc_buf; + sequence.buffer_size = sizeof(data->adc_buf); + sequence.calibrate = false; + + rc = adc_read_dt(&cfg->adc, &sequence); + if (rc != 0) { + return rc; + } + + return 0; +} + +static int veaa_x_3_channel_get(const struct device *dev, enum sensor_channel chan, + struct sensor_value *val) +{ + const struct veaa_x_3_cfg *cfg = dev->config; + struct veaa_x_3_data *data = dev->data; + const uint32_t max_adc_val = BIT(cfg->adc.resolution) - 1; + + if (chan != SENSOR_CHAN_PRESS) { + return -ENOTSUP; + } + + /* Convert from ADC value to kPa */ + if (u32_mul_overflow(data->adc_buf, veaa_x_3_kpa_range(cfg), &val->val1)) { + LOG_ERR("ADC to kPa overflow"); + return -ERANGE; + } + val->val2 = (val->val1 % max_adc_val) * 1000000 / max_adc_val; + val->val1 = (val->val1 / max_adc_val) + cfg->kpa_min; + + return 0; +} + +static const struct sensor_driver_api veaa_x_3_api_funcs = { + .attr_set = veaa_x_3_attr_set, + .attr_get = veaa_x_3_attr_get, + .sample_fetch = veaa_x_3_sample_fetch, + .channel_get = veaa_x_3_channel_get, +}; + +static int veaa_x_3_init(const struct device *dev) +{ + int rc; + const struct veaa_x_3_cfg *cfg = dev->config; + const struct dac_channel_cfg dac_cfg = { + .channel_id = cfg->dac_channel, + .resolution = cfg->dac_resolution, + .buffered = false, + }; + + LOG_DBG("Initializing %s with range %u-%u kPa", dev->name, cfg->kpa_min, cfg->kpa_max); + + if (!adc_is_ready_dt(&cfg->adc)) { + LOG_ERR("ADC not ready"); + return -ENODEV; + } + + rc = adc_channel_setup_dt(&cfg->adc); + if (rc != 0) { + LOG_ERR("%s setup failed: %d", cfg->adc.dev->name, rc); + return -ENODEV; + } + + if (!device_is_ready(cfg->dac)) { + LOG_ERR("DAC not ready"); + return -ENODEV; + } + + rc = dac_channel_setup(cfg->dac, &dac_cfg); + if (rc != 0) { + LOG_ERR("%s setup failed: %d", cfg->dac->name, rc); + return -ENODEV; + } + + return 0; +} + +#define VEAA_X_3_RANGE_KPA_INIT(n) \ + COND_CODE_1(DT_INST_ENUM_HAS_VALUE(n, pressure_range_type, d11), ({.max = 1000, min = 5}), \ + (COND_CODE_1(DT_INST_ENUM_HAS_VALUE(n, pressure_range_type, d9), \ + ({.max = 600, min = 3}), ({.max = 200, .min = 1})))) + +#define VEAA_X_3_TYPE_INIT(n) \ + COND_CODE_1(DT_INST_ENUM_HAS_VALUE(n, pressure_range_type, d11), \ + (.kpa_max = 1000, .kpa_min = 5), \ + (COND_CODE_1(DT_INST_ENUM_HAS_VALUE(n, pressure_range_type, d9), \ + (.kpa_max = 600, kpa_min = 3), (.kpa_max = 200, .kpa_min = 1)))) + +#define VEAA_X_3_INIT(n) \ + \ + static struct veaa_x_3_data veaa_x_3_data_##n; \ + \ + static const struct veaa_x_3_cfg veaa_x_3_cfg_##n = { \ + .adc = ADC_DT_SPEC_INST_GET(n), \ + .dac = DEVICE_DT_GET(DT_INST_PHANDLE(n, dac)), \ + .dac_channel = DT_INST_PROP(n, dac_channel_id), \ + .dac_resolution = DT_INST_PROP(n, dac_resolution), \ + VEAA_X_3_TYPE_INIT(n)}; \ + \ + SENSOR_DEVICE_DT_INST_DEFINE(n, veaa_x_3_init, NULL, &veaa_x_3_data_##n, \ + &veaa_x_3_cfg_##n, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, \ + &veaa_x_3_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(VEAA_X_3_INIT) diff --git a/drivers/sensor/vishay/vcnl36825t/vcnl36825t.c b/drivers/sensor/vishay/vcnl36825t/vcnl36825t.c index 940943950a45d..946f5e8ead4b0 100644 --- a/drivers/sensor/vishay/vcnl36825t/vcnl36825t.c +++ b/drivers/sensor/vishay/vcnl36825t/vcnl36825t.c @@ -454,6 +454,9 @@ static const struct sensor_driver_api vcnl36825t_driver_api = { DT_INST_PROP(inst, low_power) || (DT_INST_PROP(inst, measurement_period) <= \ VCNL36825T_PS_PERIOD_VALUE_MAX_MS), \ "measurement-period must be less/equal 80 ms with deactivated low-power mode"); \ + BUILD_ASSERT(!DT_INST_PROP(inst, low_power) || (DT_INST_ENUM_IDX(inst, operation_mode) == \ + VCNL36825T_OPERATION_MODE_AUTO), \ + "operation-mode \"force\" only available if low-power mode deactivated"); \ static struct vcnl36825t_data vcnl36825t_data_##inst; \ static const struct vcnl36825t_config vcnl36825t_config_##inst = { \ .i2c = I2C_DT_SPEC_INST_GET(inst), \ diff --git a/drivers/sensor/voltage_divider/Kconfig b/drivers/sensor/voltage_divider/Kconfig index 19027aa93615e..b89510c2b72b1 100644 --- a/drivers/sensor/voltage_divider/Kconfig +++ b/drivers/sensor/voltage_divider/Kconfig @@ -8,6 +8,6 @@ config VOLTAGE_DIVIDER bool "Voltage sensor driver" default y depends on DT_HAS_VOLTAGE_DIVIDER_ENABLED - depends on ADC + select ADC help Enable voltage sensor driver. diff --git a/drivers/sensor/voltage_divider/voltage.c b/drivers/sensor/voltage_divider/voltage.c index ef2b34c74b316..f10a6596222aa 100644 --- a/drivers/sensor/voltage_divider/voltage.c +++ b/drivers/sensor/voltage_divider/voltage.c @@ -17,14 +17,12 @@ LOG_MODULE_REGISTER(voltage, CONFIG_SENSOR_LOG_LEVEL); struct voltage_config { struct voltage_divider_dt_spec voltage; -#ifdef CONFIG_PM_DEVICE struct gpio_dt_spec gpio_power; -#endif }; struct voltage_data { struct adc_sequence sequence; - int16_t raw; + uint16_t raw; }; static int fetch(const struct device *dev, enum sensor_channel chan) @@ -49,7 +47,7 @@ static int get(const struct device *dev, enum sensor_channel chan, struct sensor { const struct voltage_config *config = dev->config; struct voltage_data *data = dev->data; - int32_t raw_val = data->raw; + int32_t raw_val; int32_t v_mv; int ret; @@ -59,6 +57,15 @@ static int get(const struct device *dev, enum sensor_channel chan, struct sensor return -ENOTSUP; } + if (config->voltage.port.channel_cfg.differential) { + raw_val = (int16_t)data->raw; + } else if (config->voltage.port.resolution < 16) { + /* Can be removed when issue #71119 is resolved */ + raw_val = (int16_t)data->raw; + } else { + raw_val = data->raw; + } + ret = adc_raw_to_millivolts_dt(&config->voltage.port, &raw_val); if (ret != 0) { LOG_ERR("raw_to_mv: %d", ret); @@ -90,8 +97,8 @@ static int pm_action(const struct device *dev, enum pm_device_action action) int ret; if (config->gpio_power.port == NULL) { - LOG_ERR("PM not supported"); - return -ENOTSUP; + /* No work to do */ + return 0; } switch (action) { @@ -126,7 +133,6 @@ static int voltage_init(const struct device *dev) return -ENODEV; } -#ifdef CONFIG_PM_DEVICE if (config->gpio_power.port != NULL) { if (!gpio_is_ready_dt(&config->gpio_power)) { LOG_ERR("Power GPIO is not ready"); @@ -138,7 +144,6 @@ static int voltage_init(const struct device *dev) LOG_ERR("failed to initialize GPIO for reset"); } } -#endif ret = adc_channel_setup_dt(&config->voltage.port); if (ret != 0) { @@ -158,18 +163,12 @@ static int voltage_init(const struct device *dev) return 0; } -#ifdef CONFIG_PM_DEVICE -#define POWER_GPIOS(inst) .gpio_power = GPIO_DT_SPEC_INST_GET_OR(inst, power_gpios, {0}), -#else -#define POWER_GPIOS(inst) -#endif - #define VOLTAGE_INIT(inst) \ static struct voltage_data voltage_##inst##_data; \ \ static const struct voltage_config voltage_##inst##_config = { \ .voltage = VOLTAGE_DIVIDER_DT_SPEC_GET(DT_DRV_INST(inst)), \ - POWER_GPIOS(inst) \ + .gpio_power = GPIO_DT_SPEC_INST_GET_OR(inst, power_gpios, {0}), \ }; \ \ PM_DEVICE_DT_INST_DEFINE(inst, pm_action); \ diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index ef0133a5ca105..dc3e4208ff4de 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -69,6 +69,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_EMUL uart_emul.c) zephyr_library_sources_ifdef(CONFIG_UART_NUMAKER uart_numaker.c) zephyr_library_sources_ifdef(CONFIG_UART_EFINIX_SAPPIHIRE uart_efinix_sapphire.c) zephyr_library_sources_ifdef(CONFIG_UART_SEDI uart_sedi.c) +zephyr_library_sources_ifdef(CONFIG_UART_MAX32 uart_max32.c) zephyr_library_sources_ifdef(CONFIG_UART_BCM2711_MU uart_bcm2711.c) zephyr_library_sources_ifdef(CONFIG_UART_INTEL_LW uart_intel_lw.c) zephyr_library_sources_ifdef(CONFIG_UART_RENESAS_RA uart_renesas_ra.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 91b79ce6dfad4..81329bfc6a821 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -150,130 +150,132 @@ config UART_ASYNC_TO_INT_DRIVEN_RX_TIMEOUT comment "Serial Drivers" -source "drivers/serial/Kconfig.b91" +rsource "Kconfig.b91" -source "drivers/serial/Kconfig.ns16550" +rsource "Kconfig.ns16550" -source "drivers/serial/Kconfig.mcux" +rsource "Kconfig.mcux" -source "drivers/serial/Kconfig.mcux_flexcomm" +rsource "Kconfig.mcux_flexcomm" -source "drivers/serial/Kconfig.mcux_iuart" +rsource "Kconfig.mcux_iuart" -source "drivers/serial/Kconfig.mcux_lpsci" +rsource "Kconfig.mcux_lpsci" -source "drivers/serial/Kconfig.mcux_lpuart" +rsource "Kconfig.mcux_lpuart" -source "drivers/serial/Kconfig.miv" +rsource "Kconfig.miv" -source "drivers/serial/Kconfig.imx" +rsource "Kconfig.imx" -source "drivers/serial/Kconfig.it8xxx2" +rsource "Kconfig.it8xxx2" -source "drivers/serial/Kconfig.stellaris" +rsource "Kconfig.stellaris" -source "drivers/serial/Kconfig.native_posix" +rsource "Kconfig.native_posix" -source "drivers/serial/Kconfig.usart_sam" +rsource "Kconfig.usart_sam" -source "drivers/serial/Kconfig.uart_sam" +rsource "Kconfig.uart_sam" -source "drivers/serial/Kconfig.stm32" +rsource "Kconfig.stm32" -source "drivers/serial/Kconfig.nrfx" +rsource "Kconfig.nrfx" -source "drivers/serial/Kconfig.altera_jtag" +rsource "Kconfig.altera_jtag" -source "drivers/serial/Kconfig.cc13xx_cc26xx" +rsource "Kconfig.cc13xx_cc26xx" -source "drivers/serial/Kconfig.cc32xx" +rsource "Kconfig.cc32xx" -source "drivers/serial/Kconfig.cmsdk_apb" +rsource "Kconfig.cmsdk_apb" -source "drivers/serial/Kconfig.sifive" +rsource "Kconfig.sifive" -source "drivers/serial/Kconfig.esp32" +rsource "Kconfig.esp32" -source "drivers/serial/Kconfig.gecko" +rsource "Kconfig.gecko" -source "drivers/serial/Kconfig.leuart_gecko" +rsource "Kconfig.leuart_gecko" -source "drivers/serial/Kconfig.msp432p4xx" +rsource "Kconfig.msp432p4xx" -source "drivers/serial/Kconfig.numicro" +rsource "Kconfig.numicro" -source "drivers/serial/Kconfig.sam0" +rsource "Kconfig.sam0" -source "drivers/serial/Kconfig.psoc6" +rsource "Kconfig.psoc6" -source "drivers/serial/Kconfig.pl011" +rsource "Kconfig.pl011" -source "drivers/serial/Kconfig.ql_usbserialport_s3b" +rsource "Kconfig.ql_usbserialport_s3b" -source "drivers/serial/Kconfig.rv32m1_lpuart" +rsource "Kconfig.rv32m1_lpuart" -source "drivers/serial/Kconfig.rpi_pico" +rsource "Kconfig.rpi_pico" -source "drivers/serial/Kconfig.litex" +rsource "Kconfig.litex" -source "drivers/serial/Kconfig.rtt" +rsource "Kconfig.rtt" -source "drivers/serial/Kconfig.bt" +rsource "Kconfig.bt" -source "drivers/serial/Kconfig.xlnx" +rsource "Kconfig.xlnx" -source "drivers/serial/Kconfig.xmc4xxx" +rsource "Kconfig.xmc4xxx" -source "drivers/serial/Kconfig.lpc11u6x" +rsource "Kconfig.lpc11u6x" -source "drivers/serial/Kconfig.npcx" +rsource "Kconfig.npcx" -source "drivers/serial/Kconfig.apbuart" +rsource "Kconfig.apbuart" -source "drivers/serial/Kconfig.rcar" +rsource "Kconfig.rcar" -source "drivers/serial/Kconfig.xec" +rsource "Kconfig.xec" -source "drivers/serial/Kconfig.gd32" +rsource "Kconfig.gd32" -source "drivers/serial/Kconfig.test" +rsource "Kconfig.test" -source "drivers/serial/Kconfig.neorv32" +rsource "Kconfig.neorv32" -source "drivers/serial/Kconfig.xen" +rsource "Kconfig.xen" -source "drivers/serial/Kconfig.ifx_cat1" +rsource "Kconfig.ifx_cat1" -source "drivers/serial/Kconfig.smartbond" +rsource "Kconfig.smartbond" -source "drivers/serial/Kconfig.nxp_s32" +rsource "Kconfig.nxp_s32" -source "drivers/serial/Kconfig.cdns" +rsource "Kconfig.cdns" -source "drivers/serial/Kconfig.opentitan" +rsource "Kconfig.opentitan" -source "drivers/serial/Kconfig.altera" +rsource "Kconfig.altera" -source "drivers/serial/Kconfig.hostlink" +rsource "Kconfig.hostlink" -source "drivers/serial/Kconfig.emul" +rsource "Kconfig.emul" -source "drivers/serial/Kconfig.native_tty" +rsource "Kconfig.native_tty" -source "drivers/serial/Kconfig.numaker" +rsource "Kconfig.numaker" -source "drivers/serial/Kconfig.efinix_sapphire" +rsource "Kconfig.efinix_sapphire" -source "drivers/serial/Kconfig.sedi" +rsource "Kconfig.sedi" -source "drivers/serial/Kconfig.bcm2711" +rsource "Kconfig.max32" -source "drivers/serial/Kconfig.intel_lw" +rsource "Kconfig.bcm2711" -source "drivers/serial/Kconfig.renesas_ra" +rsource "Kconfig.intel_lw" -source "drivers/serial/Kconfig.ene" +rsource "Kconfig.renesas_ra" -source "drivers/serial/Kconfig.rzt2m" +rsource "Kconfig.ene" + +rsource "Kconfig.rzt2m" endif # SERIAL diff --git a/drivers/serial/Kconfig.bt b/drivers/serial/Kconfig.bt index 500613d6208e8..214109759ae0b 100644 --- a/drivers/serial/Kconfig.bt +++ b/drivers/serial/Kconfig.bt @@ -11,3 +11,19 @@ config UART_BT help Enable the UART over NUS Bluetooth driver, which can be used to pipe serial data over Bluetooth LE GATT using NUS (Nordic UART Service). + +if UART_BT + +config UART_BT_WORKQUEUE_PRIORITY + int "UART NUS Work-queue Priority" + default MAIN_THREAD_PRIORITY + help + Select UART NUS Work-queue priority based on the application context. + +config UART_BT_WORKQUEUE_STACK_SIZE + int "UART NUS Work-queue Stack Size" + default 1024 + help + Set UART NUS Work-queue Stack-size based on the application context. + +endif diff --git a/drivers/serial/Kconfig.emul b/drivers/serial/Kconfig.emul index e61130a13c77e..dd243bade5f0b 100644 --- a/drivers/serial/Kconfig.emul +++ b/drivers/serial/Kconfig.emul @@ -8,6 +8,7 @@ config UART_EMUL default y depends on DT_HAS_ZEPHYR_UART_EMUL_ENABLED select SERIAL_SUPPORT_INTERRUPT + select SERIAL_SUPPORT_ASYNC select RING_BUFFER select EXPERIMENTAL help diff --git a/drivers/serial/Kconfig.esp32 b/drivers/serial/Kconfig.esp32 index f6fa5ac9d937e..8f7f35a630c0c 100644 --- a/drivers/serial/Kconfig.esp32 +++ b/drivers/serial/Kconfig.esp32 @@ -7,7 +7,7 @@ config UART_ESP32 depends on DT_HAS_ESPRESSIF_ESP32_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT - select SERIAL_SUPPORT_ASYNC if (SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32S3) + select SERIAL_SUPPORT_ASYNC if (SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32C6 || SOC_SERIES_ESP32S3) select GPIO_ESP32 help Enable the ESP32 UART. @@ -20,7 +20,7 @@ config SERIAL_ESP32_USB select SERIAL_SUPPORT_INTERRUPT help Enable the built-in USB serial interface present in some Espressif - MCUs like the ESP32-C3. + MCUs like ESP32-Cx. This driver uses the peripheral called USB Serial/JTAG Controller (USB_SERIAL_JTAG), which acts as a CDC-ACM interface towards the diff --git a/drivers/serial/Kconfig.max32 b/drivers/serial/Kconfig.max32 new file mode 100644 index 0000000000000..99b5c7b45ef50 --- /dev/null +++ b/drivers/serial/Kconfig.max32 @@ -0,0 +1,16 @@ +# MAX32 UART configuration + +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config UART_MAX32 + bool "MAX32 MCU serial driver" + default y + depends on DT_HAS_ADI_MAX32_UART_ENABLED + select SERIAL_HAS_DRIVER + select SERIAL_SUPPORT_INTERRUPT + select PINCTRL + help + This option enables the UART driver for MAX32 family of + processors. + Say y if you wish to use serial port on MAX32 MCU. diff --git a/drivers/serial/Kconfig.nrfx b/drivers/serial/Kconfig.nrfx index 158731404e63e..930dd00e3d869 100644 --- a/drivers/serial/Kconfig.nrfx +++ b/drivers/serial/Kconfig.nrfx @@ -31,7 +31,8 @@ config UART_NRFX_UARTE config UART_NRFX_UARTE_LEGACY_SHIM bool "Legacy UARTE shim" depends on UART_NRFX_UARTE - depends on !SOC_SERIES_NRF54LX && !SOC_SERIES_NRF54HX + depends on !SOC_SERIES_NRF54LX + depends on RISCV || !SOC_SERIES_NRF54HX # New shim takes more ROM. Until it is fixed use legacy shim. default y diff --git a/drivers/serial/Kconfig.nrfx_uart_instance b/drivers/serial/Kconfig.nrfx_uart_instance index b8a62084ce5fb..7f135d2f997c5 100644 --- a/drivers/serial/Kconfig.nrfx_uart_instance +++ b/drivers/serial/Kconfig.nrfx_uart_instance @@ -54,6 +54,7 @@ config UART_$(nrfx_uart_num)_NRF_HW_ASYNC depends on HAS_HW_NRF_UARTE$(nrfx_uart_num) depends on UART_ASYNC_API depends on UART_NRFX_UARTE_LEGACY_SHIM + depends on HAS_HW_NRF_PPI || HAS_HW_NRF_DPPIC select NRFX_PPI if HAS_HW_NRF_PPI select NRFX_DPPI if HAS_HW_NRF_DPPIC help @@ -76,6 +77,13 @@ config UART_$(nrfx_uart_num)_NRF_HW_ASYNC_TIMER int "Timer instance" depends on UART_$(nrfx_uart_num)_NRF_HW_ASYNC +config UART_$(nrfx_uart_num)_HAS_RX_CACHE_SECTION + def_bool $(dt_nodelabel_has_prop,uart$(nrfx_uart_num),memory-regions) + imply NRFX_UARTE_CONFIG_RX_CACHE_ENABLED + help + This helper symbol indicates the existence of a linker section which + can be dedicated to an RX cache buffer. + config UART_$(nrfx_uart_num)_TX_CACHE_SIZE int "TX cache buffer size" depends on !UART_NRFX_UARTE_LEGACY_SHIM @@ -87,7 +95,7 @@ config UART_$(nrfx_uart_num)_TX_CACHE_SIZE config UART_$(nrfx_uart_num)_RX_CACHE_SIZE int "RX cache buffer size" depends on !UART_NRFX_UARTE_LEGACY_SHIM - default 32 if $(dt_nodelabel_has_compat,shared_ram3x_region,$(DT_COMPAT_NORDIC_OWNED_MEMORY)) + default 32 if UART_$(nrfx_uart_num)_HAS_RX_CACHE_SECTION default 5 range 5 255 help diff --git a/drivers/serial/Kconfig.psoc6 b/drivers/serial/Kconfig.psoc6 index 66981e3766c40..4f0bb2c8fca0a 100644 --- a/drivers/serial/Kconfig.psoc6 +++ b/drivers/serial/Kconfig.psoc6 @@ -11,5 +11,6 @@ config UART_PSOC6 select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT select USE_INFINEON_UART + select PINCTRL help This option enables the SCB[UART] driver for PSoC-6 SoC family. diff --git a/drivers/serial/Kconfig.smartbond b/drivers/serial/Kconfig.smartbond index 5572b5ba18749..2ea73a37fa110 100644 --- a/drivers/serial/Kconfig.smartbond +++ b/drivers/serial/Kconfig.smartbond @@ -7,5 +7,6 @@ config UART_SMARTBOND depends on DT_HAS_RENESAS_SMARTBOND_UART_ENABLED select SERIAL_HAS_DRIVER select SERIAL_SUPPORT_INTERRUPT + select UART_INTERRUPT_DRIVEN if PM_DEVICE help Enable UART driver for Renesas SmartBond(tm) DA1469x series MCU. diff --git a/drivers/serial/serial_esp32_usb.c b/drivers/serial/serial_esp32_usb.c index 14e4b798a8f23..5b26ca00863ac 100644 --- a/drivers/serial/serial_esp32_usb.c +++ b/drivers/serial/serial_esp32_usb.c @@ -13,7 +13,7 @@ #include #include #include -#if defined(CONFIG_SOC_SERIES_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include #else #include @@ -22,7 +22,7 @@ #include #include -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t diff --git a/drivers/serial/uart_bt.c b/drivers/serial/uart_bt.c index ad450eea9aa23..9e4a4de593006 100644 --- a/drivers/serial/uart_bt.c +++ b/drivers/serial/uart_bt.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -14,6 +15,9 @@ #include LOG_MODULE_REGISTER(uart_nus, CONFIG_UART_LOG_LEVEL); +K_THREAD_STACK_DEFINE(nus_work_queue_stack, CONFIG_UART_BT_WORKQUEUE_STACK_SIZE); +static struct k_work_q nus_work_queue; + struct uart_bt_data { struct { struct bt_nus_inst *inst; @@ -47,7 +51,7 @@ static void bt_notif_enabled(bool enabled, void *ctx) LOG_DBG("%s() - %s", __func__, enabled ? "enabled" : "disabled"); if (!ring_buf_is_empty(dev_data->uart.tx_ringbuf)) { - k_work_reschedule(&dev_data->uart.tx_work, K_NO_WAIT); + k_work_reschedule_for_queue(&nus_work_queue, &dev_data->uart.tx_work, K_NO_WAIT); } } @@ -71,7 +75,7 @@ static void bt_received(struct bt_conn *conn, const void *data, uint16_t len, vo LOG_ERR("RX Ring buffer full. received: %d, added to queue: %d", len, put_len); } - k_work_submit(&dev_data->uart.cb_work); + k_work_submit_to_queue(&nus_work_queue, &dev_data->uart.cb_work); } static void cb_work_handler(struct k_work *work) @@ -113,7 +117,7 @@ static void tx_work_handler(struct k_work *work) } while (len > 0 && !err); if ((ring_buf_space_get(dev_data->uart.tx_ringbuf) > 0) && dev_data->uart.tx_irq_ena) { - k_work_submit(&dev_data->uart.cb_work); + k_work_submit_to_queue(&nus_work_queue, &dev_data->uart.cb_work); } } @@ -128,7 +132,7 @@ static int uart_bt_fifo_fill(const struct device *dev, const uint8_t *tx_data, i } if (atomic_get(&dev_data->bt.enabled)) { - k_work_reschedule(&dev_data->uart.tx_work, K_NO_WAIT); + k_work_reschedule_for_queue(&nus_work_queue, &dev_data->uart.tx_work, K_NO_WAIT); } return wrote; @@ -169,7 +173,7 @@ static void uart_bt_poll_out(const struct device *dev, unsigned char c) * data, so more than one byte is transmitted (e.g: when poll_out is * called inside a for-loop). */ - k_work_schedule(&dev_data->uart.tx_work, K_MSEC(1)); + k_work_schedule_for_queue(&nus_work_queue, &dev_data->uart.tx_work, K_MSEC(1)); } } @@ -191,7 +195,7 @@ static void uart_bt_irq_tx_enable(const struct device *dev) dev_data->uart.tx_irq_ena = true; if (uart_bt_irq_tx_ready(dev)) { - k_work_submit(&dev_data->uart.cb_work); + k_work_submit_to_queue(&nus_work_queue, &dev_data->uart.cb_work); } } @@ -219,7 +223,7 @@ static void uart_bt_irq_rx_enable(const struct device *dev) dev_data->uart.rx_irq_ena = true; - k_work_submit(&dev_data->uart.cb_work); + k_work_submit_to_queue(&nus_work_queue, &dev_data->uart.cb_work); } static void uart_bt_irq_rx_disable(const struct device *dev) @@ -267,6 +271,19 @@ static const struct uart_driver_api uart_bt_driver_api = { .irq_callback_set = uart_bt_irq_callback_set, }; +static int uart_bt_workqueue_init(void) +{ + k_work_queue_init(&nus_work_queue); + k_work_queue_start(&nus_work_queue, nus_work_queue_stack, + K_THREAD_STACK_SIZEOF(nus_work_queue_stack), + CONFIG_UART_BT_WORKQUEUE_PRIORITY, NULL); + + return 0; +} + +/** The work-queue is shared across all instances, hence we initialize it separatedly */ +SYS_INIT(uart_bt_workqueue_init, POST_KERNEL, CONFIG_SERIAL_INIT_PRIORITY); + static int uart_bt_init(const struct device *dev) { int err; diff --git a/drivers/serial/uart_emul.c b/drivers/serial/uart_emul.c index 2dc0f8495fdf1..2dc8029c7f911 100644 --- a/drivers/serial/uart_emul.c +++ b/drivers/serial/uart_emul.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2023 Fabian Blatz + * Copyright (c) 2024 grandcentrix GmbH * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,13 +23,10 @@ struct uart_emul_config { size_t latch_buffer_size; }; -struct uart_emul_work { - struct k_work work; - const struct device *dev; -}; - /* Device run time data */ struct uart_emul_data { + const struct device *dev; + struct uart_config cfg; int errors; @@ -44,10 +42,38 @@ struct uart_emul_data { #ifdef CONFIG_UART_INTERRUPT_DRIVEN bool rx_irq_en; bool tx_irq_en; - struct uart_emul_work irq_work; + struct k_work irq_work; + uart_irq_callback_user_data_t irq_cb; void *irq_cb_udata; #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +#ifdef CONFIG_UART_ASYNC_API + bool rx_async_en; + bool rx_stopping; + bool rx_release_on_timeout; + + struct k_work tx_work; + struct k_work rx_work; + struct k_work rx_disable_work; + struct k_work_delayable rx_timeout_work; + + uart_callback_t uart_callback; + void *callback_user_data; + + const uint8_t *tx_buf; + size_t tx_buf_len; + size_t tx_buf_offset; + + uint8_t *rx_buf; + size_t rx_buf_len; + size_t rx_buf_offset; + size_t rx_buf_data_len; + int32_t rx_buf_timeout; + + uint8_t *rx_buf_next; + size_t rx_buf_next_len; +#endif /* CONFIG_UART_ASYNC_API */ }; /* @@ -213,9 +239,8 @@ static int uart_emul_irq_rx_ready(const struct device *dev) static void uart_emul_irq_handler(struct k_work *work) { - struct uart_emul_work *uwork = CONTAINER_OF(work, struct uart_emul_work, work); - const struct device *dev = uwork->dev; - struct uart_emul_data *data = dev->data; + struct uart_emul_data *data = CONTAINER_OF(work, struct uart_emul_data, irq_work); + const struct device *dev = data->dev; uart_irq_callback_user_data_t cb = data->irq_cb; void *udata = data->irq_cb_udata; @@ -267,7 +292,7 @@ static void uart_emul_irq_tx_enable(const struct device *dev) } if (submit_irq_work) { - (void)k_work_submit_to_queue(&uart_emul_work_q, &data->irq_work.work); + (void)k_work_submit_to_queue(&uart_emul_work_q, &data->irq_work); } } @@ -282,7 +307,7 @@ static void uart_emul_irq_rx_enable(const struct device *dev) } if (submit_irq_work) { - (void)k_work_submit_to_queue(&uart_emul_work_q, &data->irq_work.work); + (void)k_work_submit_to_queue(&uart_emul_work_q, &data->irq_work); } } @@ -331,6 +356,497 @@ static int uart_emul_irq_update(const struct device *dev) } #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#ifdef CONFIG_UART_ASYNC_API +static void uart_emul_post_event(const struct device *dev, struct uart_event *evt) +{ + struct uart_emul_data *data = dev->data; + + if (!data->uart_callback) { + LOG_DBG("No async callback configured for uart_emul device %p", dev); + } + + data->uart_callback(dev, evt, data->callback_user_data); +} + +static void uart_emul_simple_event(const struct device *dev, enum uart_event_type type) +{ + uart_emul_post_event(dev, &(struct uart_event){.type = type}); +} + +static void uart_emul_async_switch_buf_nolock(struct uart_emul_data *data) +{ + data->rx_buf = data->rx_buf_next; + data->rx_buf_len = data->rx_buf_next_len; + data->rx_buf_offset = 0; + data->rx_buf_data_len = 0; + data->rx_buf_next = NULL; + data->rx_buf_next_len = 0; +} + +static void uart_emul_async_rx_timeout_handler(struct k_work *_work) +{ + struct k_work_delayable *work = k_work_delayable_from_work(_work); + struct uart_emul_data *data = CONTAINER_OF(work, struct uart_emul_data, rx_timeout_work); + const struct device *dev = data->dev; + + uint8_t *rx_buf; + size_t rx_buf_len; + size_t rx_buf_offset; + size_t rx_buf_data_len; + bool rx_en; + bool rx_buf_released = false; + bool rx_stopped = false; + + K_SPINLOCK(&data->rx_lock) { + rx_en = data->rx_async_en; + rx_buf = data->rx_buf; + rx_buf_len = data->rx_buf_len; + rx_buf_offset = data->rx_buf_offset; + rx_buf_data_len = data->rx_buf_data_len; + + data->rx_buf_offset += rx_buf_data_len; + data->rx_buf_data_len = 0; + + if (data->rx_buf_offset >= rx_buf_len || + (rx_buf_data_len > 0 && data->rx_release_on_timeout)) { + rx_buf_released = true; + uart_emul_async_switch_buf_nolock(data); + if (data->rx_buf == NULL) { + /* There was no second buffer scheduled, so stop receiving */ + rx_stopped = true; + data->rx_async_en = false; + } + } + } + + if (!rx_en || rx_buf == NULL || rx_buf_data_len == 0) { + return; + } + + struct uart_event rx_rdy_event = { + .type = UART_RX_RDY, + .data.rx = { + .buf = rx_buf, + .offset = rx_buf_offset, + .len = rx_buf_data_len, + }, + }; + + uart_emul_post_event(dev, &rx_rdy_event); + + if (rx_buf_released) { + struct uart_event rx_buf_released_event = { + .type = UART_RX_BUF_RELEASED, + .data.rx_buf.buf = rx_buf, + }; + + uart_emul_post_event(dev, &rx_buf_released_event); + } + if (rx_stopped) { + uart_emul_simple_event(dev, UART_RX_DISABLED); + } +} + +static void uart_emul_async_rx_handler(struct k_work *work) +{ + struct uart_emul_data *data = CONTAINER_OF(work, struct uart_emul_data, rx_work); + const struct device *dev = data->dev; + + bool rx_en = false; + bool empty = true; + + do { + bool rx_rdy = false; + bool buf_request = false; + + uint8_t *rx_buf = NULL; + size_t buf_len; + size_t offset; + size_t data_len; + + K_SPINLOCK(&data->rx_lock) { + rx_en = data->rx_async_en; + rx_buf = data->rx_buf; + buf_len = data->rx_buf_len; + offset = data->rx_buf_offset; + data_len = data->rx_buf_data_len; + empty = ring_buf_is_empty(data->rx_rb); + + if (!rx_en) { + K_SPINLOCK_BREAK; + } + + if (rx_buf == NULL) { + uart_emul_async_switch_buf_nolock(data); + rx_buf = data->rx_buf; + buf_len = data->rx_buf_len; + offset = data->rx_buf_offset; + data_len = data->rx_buf_data_len; + } + + if (rx_buf == NULL) { + /* During the last iteration the buffer was released but the + * application did not provide a new buffer. Stop RX and quit now. + */ + data->rx_async_en = false; + K_SPINLOCK_BREAK; + } + + if (empty) { + K_SPINLOCK_BREAK; + } + + buf_request = data_len == 0 && data->rx_buf_next == NULL; + + uint32_t read = ring_buf_get(data->rx_rb, &rx_buf[offset + data_len], + buf_len - (offset + data_len)); + data_len += read; + data->rx_buf_data_len = data_len; + + if (offset + data_len >= data->rx_buf_len) { + rx_rdy = true; + data->rx_buf = NULL; + data->rx_buf_len = 0; + data->rx_buf_offset = 0; + data->rx_buf_data_len = 0; + } + } + + if (!rx_en) { + break; + } + + if (rx_buf == NULL) { + uart_emul_simple_event(dev, UART_RX_DISABLED); + break; + } + + if (empty && data->rx_buf_timeout != SYS_FOREVER_US) { + (void)k_work_reschedule_for_queue(&uart_emul_work_q, &data->rx_timeout_work, + K_USEC(data->rx_buf_timeout)); + } + + if (buf_request) { + uart_emul_simple_event(dev, UART_RX_BUF_REQUEST); + } + + if (rx_rdy) { + struct uart_event rx_rdy_event = { + .type = UART_RX_RDY, + .data.rx = { + .buf = rx_buf, + .offset = offset, + .len = data_len, + }, + }; + + uart_emul_post_event(dev, &rx_rdy_event); + + struct uart_event rx_buf_released_event = { + .type = UART_RX_BUF_RELEASED, + .data.rx_buf.buf = rx_buf, + }; + + uart_emul_post_event(dev, &rx_buf_released_event); + } + } while (rx_en && !empty); +} + +static void uart_emul_async_tx_handler(struct k_work *work) +{ + struct uart_emul_data *data = CONTAINER_OF(work, struct uart_emul_data, tx_work); + const struct device *dev = data->dev; + const struct uart_emul_config *config = dev->config; + + uint32_t written; + + const uint8_t *tx_buf = NULL; + size_t tx_buf_len = 0; + size_t tx_buf_offset = 0; + bool tx_done = true; + + K_SPINLOCK(&data->tx_lock) { + tx_buf = data->tx_buf; + tx_buf_len = data->tx_buf_len; + tx_buf_offset = data->tx_buf_offset; + + if (!tx_buf) { + K_SPINLOCK_BREAK; + } + + written = ring_buf_put(data->tx_rb, &data->tx_buf[tx_buf_offset], + tx_buf_len - tx_buf_offset); + tx_done = written == (tx_buf_len - tx_buf_offset); + if (!tx_done) { + data->tx_buf_offset += written; + K_SPINLOCK_BREAK; + } + data->tx_buf = NULL; + data->tx_buf_len = 0; + data->tx_buf_offset = 0; + } + + if (!tx_buf) { + return; + } + + if (config->loopback && written) { + uint32_t loop_written = uart_emul_put_rx_data(dev, &tx_buf[tx_buf_offset], written); + + if (loop_written < written) { + LOG_WRN("Lost %" PRIu32 " bytes on loopback", written - loop_written); + } + } + if (data->tx_data_ready_cb) { + (data->tx_data_ready_cb)(dev, ring_buf_size_get(data->tx_rb), data->user_data); + } + + if ((config->loopback && written) || !written) { + /* When using the loopback fixture, just allow to drop all bytes in the ring buffer + * not consumed by tx_data_ready_cb(). + */ + + uint32_t flushed = uart_emul_flush_tx_data(dev); + + if (flushed) { + if (written) { + LOG_DBG("Flushed %" PRIu32 " unused bytes from tx buffer", flushed); + } else { + LOG_WRN("Flushed %" PRIu32 + " unused bytes from tx buffer to break out of infinite " + "loop! Consume or flush the bytes from the tx ring buffer " + "in your test case to prevent this!", + flushed); + } + } + } + + if (!tx_done) { + /* We are not done yet, yield back into workqueue. + * + * This would basically be an infinite loop when tx_data_ready_cb() does not consume + * the bytes in the tx ring buffer. + */ + k_work_submit_to_queue(&uart_emul_work_q, &data->tx_work); + return; + } + + struct uart_event tx_done_event = { + .type = UART_TX_DONE, + .data.tx = { + .buf = tx_buf, + .len = tx_buf_len, + }, + }; + + uart_emul_post_event(dev, &tx_done_event); +} + +static void uart_emul_rx_stop(const struct device *dev, struct uart_emul_data *data) +{ + uint8_t *rx_buf = NULL; + size_t rx_buf_offset = 0; + size_t rx_buf_data_len = 0; + + k_work_cancel_delayable(&data->rx_timeout_work); + + K_SPINLOCK(&data->rx_lock) { + if (!data->rx_async_en) { + K_SPINLOCK_BREAK; + } + rx_buf = data->rx_buf; + rx_buf_offset = data->rx_buf_offset; + rx_buf_data_len = data->rx_buf_data_len; + + data->rx_buf = NULL; + data->rx_buf_len = 0; + data->rx_buf_offset = 0; + data->rx_buf_data_len = 0; + data->rx_buf_next = NULL; + data->rx_buf_next_len = 0; + data->rx_async_en = false; + data->rx_stopping = false; + } + + if (rx_buf == NULL) { + return; + } + + if (rx_buf_data_len > 0) { + struct uart_event rx_rdy_event = { + .type = UART_RX_RDY, + .data.rx = { + .buf = rx_buf, + .offset = rx_buf_offset, + .len = rx_buf_data_len, + }, + }; + + uart_emul_post_event(dev, &rx_rdy_event); + } + + struct uart_event rx_buf_released_event = { + .type = UART_RX_BUF_RELEASED, + .data.rx_buf.buf = rx_buf, + }; + + uart_emul_post_event(dev, &rx_buf_released_event); + uart_emul_simple_event(dev, UART_RX_DISABLED); +} + +static void uart_emul_async_rx_disable_handler(struct k_work *work) +{ + struct uart_emul_data *data = CONTAINER_OF(work, struct uart_emul_data, rx_disable_work); + const struct device *dev = data->dev; + + uart_emul_rx_stop(dev, data); +} + +static int uart_emul_callback_set(const struct device *dev, uart_callback_t callback, + void *user_data) +{ + struct uart_emul_data *data = dev->data; + + data->uart_callback = callback; + data->callback_user_data = user_data; + + return 0; +} + +static int uart_emul_tx(const struct device *dev, const uint8_t *buf, size_t len, int32_t timeout) +{ + struct uart_emul_data *data = dev->data; + int ret = 0; + + K_SPINLOCK(&data->tx_lock) { + if (data->tx_buf) { + ret = -EBUSY; + K_SPINLOCK_BREAK; + } + + data->tx_buf = buf; + data->tx_buf_len = len; + data->tx_buf_offset = 0; + + k_work_submit_to_queue(&uart_emul_work_q, &data->tx_work); + } + + return ret; +} + +static int uart_emul_tx_abort(const struct device *dev) +{ + struct uart_emul_data *data = dev->data; + const uint8_t *tx_buf = NULL; + size_t tx_buf_sent; + + K_SPINLOCK(&data->tx_lock) { + tx_buf = data->tx_buf; + tx_buf_sent = data->tx_buf_offset; + + data->tx_buf = NULL; + data->tx_buf_len = 0; + data->tx_buf_offset = 0; + + k_work_cancel(&data->tx_work); + } + + if (!tx_buf) { + return -EFAULT; + } + + struct uart_event tx_aborted_event = { + .type = UART_TX_ABORTED, + .data.tx = { + .buf = tx_buf, + .len = tx_buf_sent, + }, + }; + + uart_emul_post_event(dev, &tx_aborted_event); + + return 0; +} + +static int uart_emul_rx_buf_rsp(const struct device *dev, uint8_t *buf, size_t len) +{ + struct uart_emul_data *data = dev->data; + int ret = 0; + + K_SPINLOCK(&data->rx_lock) { + if (!data->rx_async_en) { + ret = -EACCES; + K_SPINLOCK_BREAK; + } + + if (data->rx_buf_next != NULL) { + ret = -EBUSY; + K_SPINLOCK_BREAK; + } + + data->rx_buf_next = buf; + data->rx_buf_next_len = len; + } + + return ret; +} + +static int uart_emul_rx_enable(const struct device *dev, uint8_t *buf, size_t len, int32_t timeout) +{ + struct uart_emul_data *data = dev->data; + int ret = 0; + bool rx_stopping; + + K_SPINLOCK(&data->rx_lock) { + rx_stopping = data->rx_stopping; + k_work_cancel(&data->rx_disable_work); + } + + if (rx_stopping) { + uart_emul_rx_stop(dev, data); + } + + K_SPINLOCK(&data->rx_lock) { + if (data->rx_async_en) { + ret = -EBUSY; + K_SPINLOCK_BREAK; + } + + data->rx_async_en = true; + data->rx_buf = buf; + data->rx_buf_len = len; + data->rx_buf_timeout = timeout; + data->rx_buf_offset = 0; + data->rx_buf_data_len = 0; + data->rx_buf_next = NULL; + data->rx_buf_next_len = 0; + + if (!ring_buf_is_empty(data->rx_rb)) { + (void)k_work_submit_to_queue(&uart_emul_work_q, &data->rx_work); + } + } + + return ret; +} + +static int uart_emul_rx_disable(const struct device *dev) +{ + struct uart_emul_data *data = dev->data; + int ret = 0; + + K_SPINLOCK(&data->rx_lock) { + if (!data->rx_async_en) { + ret = -EFAULT; + K_SPINLOCK_BREAK; + } + data->rx_stopping = true; + k_work_submit_to_queue(&uart_emul_work_q, &data->rx_disable_work); + } + + return ret; +} +#endif /* CONFIG_UART_ASYNC_API */ + static const struct uart_driver_api uart_emul_api = { .poll_in = uart_emul_poll_in, .poll_out = uart_emul_poll_out, @@ -353,6 +869,14 @@ static const struct uart_driver_api uart_emul_api = { .irq_update = uart_emul_irq_update, .irq_is_pending = uart_emul_irq_is_pending, #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#ifdef CONFIG_UART_ASYNC_API + .callback_set = uart_emul_callback_set, + .tx = uart_emul_tx, + .tx_abort = uart_emul_tx_abort, + .rx_enable = uart_emul_rx_enable, + .rx_buf_rsp = uart_emul_rx_buf_rsp, + .rx_disable = uart_emul_rx_disable, +#endif /* CONFIG_UART_ASYNC_API */ }; void uart_emul_callback_tx_data_ready_set(const struct device *dev, @@ -364,17 +888,19 @@ void uart_emul_callback_tx_data_ready_set(const struct device *dev, drv_data->user_data = user_data; } -uint32_t uart_emul_put_rx_data(const struct device *dev, uint8_t *data, size_t size) +uint32_t uart_emul_put_rx_data(const struct device *dev, const uint8_t *data, size_t size) { struct uart_emul_data *drv_data = dev->data; uint32_t count; __unused bool empty; __unused bool irq_en; + __unused bool rx_en; K_SPINLOCK(&drv_data->rx_lock) { count = ring_buf_put(drv_data->rx_rb, data, size); empty = ring_buf_is_empty(drv_data->rx_rb); IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, (irq_en = drv_data->rx_irq_en;)); + IF_ENABLED(CONFIG_UART_ASYNC_API, (rx_en = drv_data->rx_async_en;)); } if (count < size) { @@ -383,7 +909,12 @@ uint32_t uart_emul_put_rx_data(const struct device *dev, uint8_t *data, size_t s IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, ( if (count > 0 && irq_en && !empty) { - (void)k_work_submit_to_queue(&uart_emul_work_q, &drv_data->irq_work.work); + (void)k_work_submit_to_queue(&uart_emul_work_q, &drv_data->irq_work); + } + )) + IF_ENABLED(CONFIG_UART_ASYNC_API, ( + if (count > 0 && rx_en && !empty) { + (void)k_work_submit_to_queue(&uart_emul_work_q, &drv_data->rx_work); } )) @@ -435,14 +966,16 @@ void uart_emul_set_errors(const struct device *dev, int errors) drv_data->errors |= errors; } +void uart_emul_set_release_buffer_on_timeout(const struct device *dev, bool release_on_timeout) +{ + __unused struct uart_emul_data *drv_data = dev->data; + + IF_ENABLED(CONFIG_UART_ASYNC_API, (drv_data->rx_release_on_timeout = release_on_timeout;)); +} + #define UART_EMUL_RX_FIFO_SIZE(inst) (DT_INST_PROP(inst, rx_fifo_size)) #define UART_EMUL_TX_FIFO_SIZE(inst) (DT_INST_PROP(inst, tx_fifo_size)) -#define UART_EMUL_IRQ_WORK_INIT(inst) \ - IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ - (.irq_work = {.dev = DEVICE_DT_INST_GET(inst), \ - .work = Z_WORK_INITIALIZER(uart_emul_irq_handler)},)) - #define DEFINE_UART_EMUL(inst) \ \ RING_BUF_DECLARE(uart_emul_##inst##_rx_rb, UART_EMUL_RX_FIFO_SIZE(inst)); \ @@ -453,9 +986,18 @@ void uart_emul_set_errors(const struct device *dev, int errors) .latch_buffer_size = DT_INST_PROP(inst, latch_buffer_size), \ }; \ static struct uart_emul_data uart_emul_data_##inst = { \ + .dev = DEVICE_DT_INST_GET(inst), \ .rx_rb = &uart_emul_##inst##_rx_rb, \ .tx_rb = &uart_emul_##inst##_tx_rb, \ - UART_EMUL_IRQ_WORK_INIT(inst) \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (.irq_work = Z_WORK_INITIALIZER(uart_emul_irq_handler),)) \ + IF_ENABLED(CONFIG_UART_ASYNC_API, \ + (.tx_work = Z_WORK_INITIALIZER(uart_emul_async_tx_handler), \ + .rx_timeout_work = Z_WORK_DELAYABLE_INITIALIZER( \ + uart_emul_async_rx_timeout_handler), \ + .rx_work = Z_WORK_INITIALIZER(uart_emul_async_rx_handler), \ + .rx_disable_work = Z_WORK_INITIALIZER( \ + uart_emul_async_rx_disable_handler),)) \ }; \ \ DEVICE_DT_INST_DEFINE(inst, NULL, NULL, &uart_emul_data_##inst, &uart_emul_cfg_##inst, \ diff --git a/drivers/serial/uart_esp32.c b/drivers/serial/uart_esp32.c index cb07de20adcb1..9bf0c3bb17cf1 100644 --- a/drivers/serial/uart_esp32.c +++ b/drivers/serial/uart_esp32.c @@ -25,6 +25,10 @@ #include #include #include +#elif defined(CONFIG_SOC_SERIES_ESP32C6) +#include +#include +#include #endif #ifdef CONFIG_UART_ASYNC_API #include @@ -43,19 +47,21 @@ #include #include -#ifndef CONFIG_SOC_SERIES_ESP32C3 -#include -#else +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include +#else +#include #endif + #include #include #include #include #include + LOG_MODULE_REGISTER(uart_esp32, CONFIG_UART_LOG_LEVEL); -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t @@ -67,6 +73,8 @@ struct uart_esp32_config { const clock_control_subsys_t clock_subsys; int irq_source; int irq_priority; + bool tx_invert; + bool rx_invert; #if CONFIG_UART_ASYNC_API const struct device *dma_dev; uint8_t tx_dma_channel; @@ -255,7 +263,7 @@ static int uart_esp32_configure(const struct device *dev, const struct uart_conf clock_control_on(config->clock_dev, config->clock_subsys); - uart_hal_set_sclk(&data->hal, UART_SCLK_APB); + uart_hal_set_sclk(&data->hal, UART_SCLK_DEFAULT); uart_hal_set_rxfifo_full_thr(&data->hal, UART_RX_FIFO_THRESH); uart_hal_set_txfifo_empty_thr(&data->hal, UART_TX_FIFO_THRESH); uart_hal_rxfifo_rst(&data->hal); @@ -328,6 +336,13 @@ static int uart_esp32_configure(const struct device *dev, const struct uart_conf uart_hal_set_rx_timeout(&data->hal, 0x16); + if (config->tx_invert) { + uart_hal_inverse_signal(&data->hal, UART_SIGNAL_TXD_INV); + } + + if (config->rx_invert) { + uart_hal_inverse_signal(&data->hal, UART_SIGNAL_RXD_INV); + } return 0; } @@ -879,7 +894,7 @@ static int uart_esp32_async_rx_disable(const struct device *dev) /*Release next buffer*/ if (data->async.rx_next_len) { evt.type = UART_RX_BUF_RELEASED; - evt.data.rx_buf.buf = data->async.rx_buf; + evt.data.rx_buf.buf = data->async.rx_next_buf; if (data->async.cb) { data->async.cb(dev, &evt, data->async.user_data); } @@ -1004,6 +1019,8 @@ static const DRAM_ATTR struct uart_driver_api uart_esp32_api = { .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(idx, offset), \ .irq_source = DT_INST_IRQN(idx), \ .irq_priority = UART_IRQ_PRIORITY, \ + .tx_invert = DT_INST_PROP_OR(idx, tx_invert, false), \ + .rx_invert = DT_INST_PROP_OR(idx, rx_invert, false), \ ESP_UART_DMA_INIT(idx)}; \ \ static struct uart_esp32_data uart_esp32_data_##idx = { \ diff --git a/drivers/serial/uart_handlers.c b/drivers/serial/uart_handlers.c index 954592aca28b7..24707bde75478 100644 --- a/drivers/serial/uart_handlers.c +++ b/drivers/serial/uart_handlers.c @@ -22,7 +22,7 @@ } UART_SIMPLE(err_check) -#include +#include static inline int z_vrfy_uart_poll_in(const struct device *dev, unsigned char *p_char) @@ -31,7 +31,7 @@ static inline int z_vrfy_uart_poll_in(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(p_char, sizeof(unsigned char))); return z_impl_uart_poll_in(dev, p_char); } -#include +#include static inline int z_vrfy_uart_poll_in_u16(const struct device *dev, uint16_t *p_u16) @@ -40,7 +40,7 @@ static inline int z_vrfy_uart_poll_in_u16(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(p_u16, sizeof(uint16_t))); return z_impl_uart_poll_in_u16(dev, p_u16); } -#include +#include static inline void z_vrfy_uart_poll_out(const struct device *dev, unsigned char out_char) @@ -48,7 +48,7 @@ static inline void z_vrfy_uart_poll_out(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_UART(dev, poll_out)); z_impl_uart_poll_out((const struct device *)dev, out_char); } -#include +#include static inline void z_vrfy_uart_poll_out_u16(const struct device *dev, uint16_t out_u16) @@ -56,7 +56,7 @@ static inline void z_vrfy_uart_poll_out_u16(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_UART(dev, poll_out)); z_impl_uart_poll_out_u16((const struct device *)dev, out_u16); } -#include +#include #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE static inline int z_vrfy_uart_config_get(const struct device *dev, @@ -67,7 +67,7 @@ static inline int z_vrfy_uart_config_get(const struct device *dev, return z_impl_uart_config_get(dev, cfg); } -#include +#include static inline int z_vrfy_uart_configure(const struct device *dev, const struct uart_config *cfg) @@ -77,7 +77,7 @@ static inline int z_vrfy_uart_configure(const struct device *dev, return z_impl_uart_configure(dev, cfg); } -#include +#include #endif #ifdef CONFIG_UART_ASYNC_API @@ -94,7 +94,7 @@ static inline int z_vrfy_uart_tx(const struct device *dev, const uint8_t *buf, K_OOPS(K_SYSCALL_MEMORY_READ(buf, len)); return z_impl_uart_tx(dev, buf, len, timeout); } -#include +#include #ifdef CONFIG_UART_WIDE_DATA static inline int z_vrfy_uart_tx_u16(const struct device *dev, @@ -105,11 +105,11 @@ static inline int z_vrfy_uart_tx_u16(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_ARRAY_READ(buf, len, sizeof(uint16_t))); return z_impl_uart_tx_u16(dev, buf, len, timeout); } -#include +#include #endif UART_SIMPLE(tx_abort); -#include +#include static inline int z_vrfy_uart_rx_enable(const struct device *dev, uint8_t *buf, @@ -119,7 +119,7 @@ static inline int z_vrfy_uart_rx_enable(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, len)); return z_impl_uart_rx_enable(dev, buf, len, timeout); } -#include +#include #ifdef CONFIG_UART_WIDE_DATA static inline int z_vrfy_uart_rx_enable_u16(const struct device *dev, @@ -130,11 +130,11 @@ static inline int z_vrfy_uart_rx_enable_u16(const struct device *dev, K_OOPS(K_SYSCALL_MEMORY_ARRAY_WRITE(buf, len, sizeof(uint16_t))); return z_impl_uart_rx_enable_u16(dev, buf, len, timeout); } -#include +#include #endif UART_SIMPLE(rx_disable); -#include +#include #endif /* CONFIG_UART_ASYNC_API */ #ifdef CONFIG_UART_INTERRUPT_DRIVEN @@ -146,14 +146,14 @@ UART_SIMPLE_VOID(irq_err_enable) UART_SIMPLE_VOID(irq_err_disable) UART_SIMPLE(irq_is_pending) UART_SIMPLE(irq_update) -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ #ifdef CONFIG_UART_LINE_CTRL @@ -164,7 +164,7 @@ static inline int z_vrfy_uart_line_ctrl_set(const struct device *dev, return z_impl_uart_line_ctrl_set((const struct device *)dev, ctrl, val); } -#include +#include static inline int z_vrfy_uart_line_ctrl_get(const struct device *dev, uint32_t ctrl, uint32_t *val) @@ -174,7 +174,7 @@ static inline int z_vrfy_uart_line_ctrl_get(const struct device *dev, return z_impl_uart_line_ctrl_get((const struct device *)dev, ctrl, (uint32_t *)val); } -#include +#include #endif /* CONFIG_UART_LINE_CTRL */ #ifdef CONFIG_UART_DRV_CMD @@ -184,5 +184,5 @@ static inline int z_vrfy_uart_drv_cmd(const struct device *dev, uint32_t cmd, K_OOPS(K_SYSCALL_DRIVER_UART(dev, drv_cmd)); return z_impl_uart_drv_cmd((const struct device *)dev, cmd, p); } -#include +#include #endif /* CONFIG_UART_DRV_CMD */ diff --git a/drivers/serial/uart_ifx_cat1.c b/drivers/serial/uart_ifx_cat1.c index 68222ec314cd6..c54bafa57251b 100644 --- a/drivers/serial/uart_ifx_cat1.c +++ b/drivers/serial/uart_ifx_cat1.c @@ -227,6 +227,10 @@ static int ifx_cat1_uart_configure(const struct device *dev, result = cyhal_uart_set_baud(&data->obj, cfg->baudrate, NULL); } + /* Set RTS/CTS flow control pins as NC so cyhal will skip initialization */ + data->obj.pin_cts = NC; + data->obj.pin_rts = NC; + /* Enable RTS/CTS flow control */ if ((result == CY_RSLT_SUCCESS) && cfg->flow_ctrl) { result = cyhal_uart_enable_flow_control(&data->obj, true, true); diff --git a/drivers/serial/uart_max32.c b/drivers/serial/uart_max32.c new file mode 100644 index 0000000000000..9d0ffadbea6b2 --- /dev/null +++ b/drivers/serial/uart_max32.c @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include + +#define DT_DRV_COMPAT adi_max32_uart + +LOG_MODULE_REGISTER(uart_max32, CONFIG_UART_LOG_LEVEL); + +struct max32_uart_config { + mxc_uart_regs_t *regs; + const struct pinctrl_dev_config *pctrl; + const struct device *clock; + struct max32_perclk perclk; + struct uart_config uart_conf; +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_config_func_t irq_config_func; +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +struct max32_uart_data { +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + uart_irq_callback_user_data_t cb; /* Interrupt callback */ + void *cb_data; /* Interrupt callback arg */ + uint32_t flags; /* Cached interrupt flags */ + uint32_t status; /* Cached status flags */ +#endif + struct uart_config conf; /* baudrate, stopbits, ... */ +}; + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN +static void uart_max32_isr(const struct device *dev); +#endif + +static void api_poll_out(const struct device *dev, unsigned char c) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_WriteCharacter(cfg->regs, c); +} + +static int api_poll_in(const struct device *dev, unsigned char *c) +{ + int val; + const struct max32_uart_config *cfg = dev->config; + + val = MXC_UART_ReadCharacterRaw(cfg->regs); + if (val >= 0) { + *c = (unsigned char)val; + } else { + return -1; + } + + return 0; +} + +static int api_err_check(const struct device *dev) +{ + int err = 0; + uint32_t flags; + const struct max32_uart_config *cfg = dev->config; + + flags = MXC_UART_GetFlags(cfg->regs); + + if (flags & ADI_MAX32_UART_ERROR_FRAMING) { + err |= UART_ERROR_FRAMING; + } + + if (flags & ADI_MAX32_UART_ERROR_PARITY) { + err |= UART_ERROR_PARITY; + } + + if (flags & ADI_MAX32_UART_ERROR_OVERRUN) { + err |= UART_ERROR_OVERRUN; + } + + return err; +} + +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + +static int api_configure(const struct device *dev, const struct uart_config *uart_cfg) +{ + int err; + const struct max32_uart_config *const cfg = dev->config; + mxc_uart_regs_t *regs = cfg->regs; + struct max32_uart_data *data = dev->data; + + /* + * Set parity + */ + if (data->conf.parity != uart_cfg->parity) { + mxc_uart_parity_t mxc_parity; + + switch (uart_cfg->parity) { + case UART_CFG_PARITY_NONE: + mxc_parity = ADI_MAX32_UART_CFG_PARITY_NONE; + break; + case UART_CFG_PARITY_ODD: + mxc_parity = ADI_MAX32_UART_CFG_PARITY_ODD; + break; + case UART_CFG_PARITY_EVEN: + mxc_parity = ADI_MAX32_UART_CFG_PARITY_EVEN; + break; + case UART_CFG_PARITY_MARK: +#if defined(ADI_MAX32_UART_CFG_PARITY_MARK) + mxc_parity = ADI_MAX32_UART_CFG_PARITY_MARK; + break; +#else + return -ENOTSUP; +#endif + case UART_CFG_PARITY_SPACE: +#if defined(ADI_MAX32_UART_CFG_PARITY_SPACE) + mxc_parity = ADI_MAX32_UART_CFG_PARITY_SPACE; + break; +#else + return -ENOTSUP; +#endif + default: + return -EINVAL; + } + + err = MXC_UART_SetParity(regs, mxc_parity); + if (err < 0) { + return -ENOTSUP; + } + /* incase of success keep configuration */ + data->conf.parity = uart_cfg->parity; + } + + /* + * Set stop bit + */ + if (data->conf.stop_bits != uart_cfg->stop_bits) { + if (uart_cfg->stop_bits == UART_CFG_STOP_BITS_1) { + err = MXC_UART_SetStopBits(regs, MXC_UART_STOP_1); + } else if (uart_cfg->stop_bits == UART_CFG_STOP_BITS_2) { + err = MXC_UART_SetStopBits(regs, MXC_UART_STOP_2); + } else { + return -ENOTSUP; + } + if (err < 0) { + return -ENOTSUP; + } + /* incase of success keep configuration */ + data->conf.stop_bits = uart_cfg->stop_bits; + } + + /* + * Set data bit + * Valid data for MAX32 is 5-6-7-8 + * Valid data for Zepyhr is 0-1-2-3 + * Added +5 to index match. + */ + if (data->conf.data_bits != uart_cfg->data_bits) { + err = MXC_UART_SetDataSize(regs, (5 + uart_cfg->data_bits)); + if (err < 0) { + return -ENOTSUP; + } + /* incase of success keep configuration */ + data->conf.data_bits = uart_cfg->data_bits; + } + + /* + * Set flow control + * Flow control not implemented yet so that only support no flow mode + */ + if (data->conf.flow_ctrl != uart_cfg->flow_ctrl) { + if (uart_cfg->flow_ctrl != UART_CFG_FLOW_CTRL_NONE) { + return -ENOTSUP; + } + data->conf.flow_ctrl = uart_cfg->flow_ctrl; + } + + /* + * Set baudrate + */ + if (data->conf.baudrate != uart_cfg->baudrate) { + err = Wrap_MXC_UART_SetFrequency(regs, uart_cfg->baudrate, cfg->perclk.clk_src); + if (err < 0) { + return -ENOTSUP; + } + /* In case of success keep configuration */ + data->conf.baudrate = uart_cfg->baudrate; + } + return 0; +} + +static int api_config_get(const struct device *dev, struct uart_config *uart_cfg) +{ + struct max32_uart_data *data = dev->data; + + /* copy configs from global setting */ + *uart_cfg = data->conf; + + return 0; +} + +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ + +static int uart_max32_init(const struct device *dev) +{ + int ret; + const struct max32_uart_config *const cfg = dev->config; + mxc_uart_regs_t *regs = cfg->regs; + + if (!device_is_ready(cfg->clock)) { + LOG_ERR("Clock control device not ready"); + return -ENODEV; + } + + ret = MXC_UART_Shutdown(regs); + if (ret) { + return ret; + } + + ret = clock_control_on(cfg->clock, (clock_control_subsys_t)&cfg->perclk); + if (ret != 0) { + LOG_ERR("Cannot enable UART clock"); + return ret; + } + + ret = pinctrl_apply_state(cfg->pctrl, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } + + ret = api_configure(dev, &cfg->uart_conf); + if (ret) { + return ret; + } + + ret = Wrap_MXC_UART_Init(regs); + if (ret) { + return ret; + } + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + /* Clear any pending UART RX/TX interrupts */ + MXC_UART_ClearFlags(regs, (ADI_MAX32_UART_INT_RX | ADI_MAX32_UART_INT_TX)); + cfg->irq_config_func(dev); +#endif + + return ret; +} + +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + +static int api_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + unsigned int num_tx = 0; + const struct max32_uart_config *cfg = dev->config; + + num_tx = MXC_UART_WriteTXFIFO(cfg->regs, (unsigned char *)tx_data, size); + + return (int)num_tx; +} + +static int api_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + unsigned int num_rx = 0; + const struct max32_uart_config *cfg = dev->config; + + num_rx = MXC_UART_ReadRXFIFO(cfg->regs, (unsigned char *)rx_data, size); + if (num_rx == 0) { + MXC_UART_ClearFlags(cfg->regs, ADI_MAX32_UART_INT_RX); + } + + return num_rx; +} + +static void api_irq_tx_enable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + unsigned int key; + + MXC_UART_EnableInt(cfg->regs, ADI_MAX32_UART_INT_TX | ADI_MAX32_UART_INT_TX_OEM); + + key = irq_lock(); + uart_max32_isr(dev); + irq_unlock(key); +} + +static void api_irq_tx_disable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_DisableInt(cfg->regs, ADI_MAX32_UART_INT_TX | ADI_MAX32_UART_INT_TX_OEM); +} + +static int api_irq_tx_ready(const struct device *dev) +{ + struct max32_uart_data *const data = dev->data; + + return ((data->flags & (ADI_MAX32_UART_INT_TX | ADI_MAX32_UART_INT_TX_OEM)) || + !(data->status & MXC_F_UART_STATUS_TX_FULL)); +} + +static void api_irq_rx_enable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_EnableInt(cfg->regs, ADI_MAX32_UART_INT_RX); +} + +static void api_irq_rx_disable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_DisableInt(cfg->regs, ADI_MAX32_UART_INT_RX); +} + +static int api_irq_tx_complete(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + if (MXC_UART_GetActive(cfg->regs) == E_BUSY) { + return 0; + } else { + return 1; /* transmission completed */ + } +} + +static int api_irq_rx_ready(const struct device *dev) +{ + struct max32_uart_data *const data = dev->data; + + return (data->flags & ADI_MAX32_UART_INT_RX); +} + +static void api_irq_err_enable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_EnableInt(cfg->regs, ADI_MAX32_UART_ERROR_INTERRUPTS); +} + +static void api_irq_err_disable(const struct device *dev) +{ + const struct max32_uart_config *cfg = dev->config; + + MXC_UART_DisableInt(cfg->regs, ADI_MAX32_UART_ERROR_INTERRUPTS); +} + +static int api_irq_is_pending(const struct device *dev) +{ + struct max32_uart_data *const data = dev->data; + + return (data->flags & (ADI_MAX32_UART_INT_RX | ADI_MAX32_UART_INT_TX)); +} + +static int api_irq_update(const struct device *dev) +{ + struct max32_uart_data *const data = dev->data; + const struct max32_uart_config *const cfg = dev->config; + + data->flags = MXC_UART_GetFlags(cfg->regs); + data->status = MXC_UART_GetStatus(cfg->regs); + + MXC_UART_ClearFlags(cfg->regs, data->flags); + + return 1; +} + +static void api_irq_callback_set(const struct device *dev, uart_irq_callback_user_data_t cb, + void *cb_data) +{ + struct max32_uart_data *const data = dev->data; + + data->cb = cb; + data->cb_data = cb_data; +} + +static void uart_max32_isr(const struct device *dev) +{ + struct max32_uart_data *data = dev->data; + + if (data->cb) { + data->cb(dev, data->cb_data); + } +} + +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ + +static const struct uart_driver_api uart_max32_driver_api = { + .poll_in = api_poll_in, + .poll_out = api_poll_out, + .err_check = api_err_check, +#ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE + .configure = api_configure, + .config_get = api_config_get, +#endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#ifdef CONFIG_UART_INTERRUPT_DRIVEN + .fifo_fill = api_fifo_fill, + .fifo_read = api_fifo_read, + .irq_tx_enable = api_irq_tx_enable, + .irq_tx_disable = api_irq_tx_disable, + .irq_tx_ready = api_irq_tx_ready, + .irq_rx_enable = api_irq_rx_enable, + .irq_rx_disable = api_irq_rx_disable, + .irq_tx_complete = api_irq_tx_complete, + .irq_rx_ready = api_irq_rx_ready, + .irq_err_enable = api_irq_err_enable, + .irq_err_disable = api_irq_err_disable, + .irq_is_pending = api_irq_is_pending, + .irq_update = api_irq_update, + .irq_callback_set = api_irq_callback_set, +#endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +}; + +#define MAX32_UART_INIT(_num) \ + PINCTRL_DT_INST_DEFINE(_num); \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (static void uart_max32_irq_init_##_num(const struct device *dev) \ + { \ + IF_ENABLED( \ + CONFIG_UART_INTERRUPT_DRIVEN, \ + (IRQ_CONNECT(DT_INST_IRQN(_num), DT_INST_IRQ(_num, priority), \ + uart_max32_isr, DEVICE_DT_INST_GET(_num), 0); \ + irq_enable(DT_INST_IRQN(_num)))); \ + })); \ + static const struct max32_uart_config max32_uart_config_##_num = { \ + .regs = (mxc_uart_regs_t *)DT_INST_REG_ADDR(_num), \ + .pctrl = PINCTRL_DT_INST_DEV_CONFIG_GET(_num), \ + .clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(_num)), \ + .perclk.bus = DT_INST_CLOCKS_CELL(_num, offset), \ + .perclk.bit = DT_INST_CLOCKS_CELL(_num, bit), \ + .perclk.clk_src = \ + DT_INST_PROP_OR(_num, clock_source, ADI_MAX32_PRPH_CLK_SRC_PCLK), \ + .uart_conf.baudrate = DT_INST_PROP_OR(_num, current_speed, 115200), \ + .uart_conf.parity = DT_INST_ENUM_IDX_OR(_num, parity, UART_CFG_PARITY_NONE), \ + .uart_conf.data_bits = DT_INST_ENUM_IDX_OR(_num, data_bits, UART_CFG_DATA_BITS_8), \ + .uart_conf.stop_bits = DT_INST_ENUM_IDX_OR(_num, stop_bits, UART_CFG_STOP_BITS_1), \ + .uart_conf.flow_ctrl = \ + DT_INST_PROP_OR(_num, hw_flow_control, UART_CFG_FLOW_CTRL_NONE), \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, \ + (.irq_config_func = uart_max32_irq_init_##_num,))}; \ + static struct max32_uart_data max32_uart_data##_num = { \ + IF_ENABLED(CONFIG_UART_INTERRUPT_DRIVEN, (.cb = NULL,))}; \ + DEVICE_DT_INST_DEFINE(_num, uart_max32_init, NULL, &max32_uart_data##_num, \ + &max32_uart_config_##_num, PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, (void *)&uart_max32_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MAX32_UART_INIT) diff --git a/drivers/serial/uart_mcux_flexcomm.c b/drivers/serial/uart_mcux_flexcomm.c index 8a95edbe3bb60..f39836bf847b7 100644 --- a/drivers/serial/uart_mcux_flexcomm.c +++ b/drivers/serial/uart_mcux_flexcomm.c @@ -1149,7 +1149,6 @@ DT_INST_FOREACH_STATUS_OKAY(UART_MCUX_FLEXCOMM_RX_TIMEOUT_FUNC); .head_block = \ &mcux_flexcomm_##n##_data.tx_data.active_block, \ .channel_direction = MEMORY_TO_PERIPHERAL, \ - .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, tx, channel), \ .dma_callback = mcux_flexcomm_uart_dma_tx_callback, \ .user_data = (void *)DEVICE_DT_INST_GET(n), \ }, \ @@ -1170,7 +1169,6 @@ DT_INST_FOREACH_STATUS_OKAY(UART_MCUX_FLEXCOMM_RX_TIMEOUT_FUNC); .head_block = \ &mcux_flexcomm_##n##_data.rx_data.active_block, \ .channel_direction = PERIPHERAL_TO_MEMORY, \ - .dma_slot = DT_INST_DMAS_CELL_BY_NAME(n, rx, channel), \ .dma_callback = mcux_flexcomm_uart_dma_rx_callback, \ .user_data = (void *)DEVICE_DT_INST_GET(n) \ }, \ diff --git a/drivers/serial/uart_mcux_lpuart.c b/drivers/serial/uart_mcux_lpuart.c index ea6b82ebc0e20..359944f477f8b 100644 --- a/drivers/serial/uart_mcux_lpuart.c +++ b/drivers/serial/uart_mcux_lpuart.c @@ -58,6 +58,9 @@ struct mcux_lpuart_config { uint8_t parity; bool rs485_de_active_low; bool loopback_en; + bool single_wire; + bool tx_invert; + bool rx_invert; #ifdef CONFIG_UART_MCUX_LPUART_ISR_SUPPORT void (*irq_config_func)(const struct device *dev); #endif @@ -711,10 +714,9 @@ static int mcux_lpuart_callback_set(const struct device *dev, uart_callback_t ca data->callback = NULL; data->cb_data = NULL; data->api_type = LPUART_ASYNC; - return mcux_lpuart_configure_async(dev); -#else - return 0; #endif + + return mcux_lpuart_configure_async(dev); } static int mcux_lpuart_tx(const struct device *dev, const uint8_t *buf, size_t len, @@ -1105,7 +1107,29 @@ static int mcux_lpuart_configure_init(const struct device *dev, const struct uar /* Set the LPUART into loopback mode */ config->base->CTRL |= LPUART_CTRL_LOOPS_MASK; config->base->CTRL &= ~LPUART_CTRL_RSRC_MASK; + } else if (config->single_wire) { + /* Enable the single wire / half-duplex mode, only possible when + * loopback is disabled. We need a critical section to prevent + * the UART firing an interrupt during mode switch + */ + unsigned int key = irq_lock(); + + config->base->CTRL |= (LPUART_CTRL_LOOPS_MASK | LPUART_CTRL_RSRC_MASK); + irq_unlock(key); + } else { +#ifdef LPUART_CTRL_TXINV + /* Only invert TX in full-duplex mode */ + if (config->tx_invert) { + config->base->CTRL |= LPUART_CTRL_TXINV(1); + } +#endif + } + +#ifdef LPUART_STAT_RXINV + if (config->rx_invert) { + config->base->STAT |= LPUART_STAT_RXINV(1); } +#endif /* update internal uart_config */ data->uart_config = *cfg; @@ -1126,6 +1150,9 @@ static int mcux_lpuart_configure(const struct device *dev, { const struct mcux_lpuart_config *config = dev->config; + /* Make sure that RSRC is de-asserted otherwise deinit will hang. */ + config->base->CTRL &= ~LPUART_CTRL_RSRC_MASK; + /* disable LPUART */ LPUART_Deinit(config->base); @@ -1330,6 +1357,9 @@ static const struct mcux_lpuart_config mcux_lpuart_##n##_config = { \ .parity = DT_INST_ENUM_IDX_OR(n, parity, UART_CFG_PARITY_NONE), \ .rs485_de_active_low = DT_INST_PROP(n, nxp_rs485_de_active_low), \ .loopback_en = DT_INST_PROP(n, nxp_loopback), \ + .single_wire = DT_INST_PROP(n, single_wire), \ + .rx_invert = DT_INST_PROP(n, rx_invert), \ + .tx_invert = DT_INST_PROP(n, tx_invert), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ MCUX_LPUART_IRQ_INIT(n) \ RX_DMA_CONFIG(n) \ diff --git a/drivers/serial/uart_native_tty.c b/drivers/serial/uart_native_tty.c index 8eb51bff5b873..4f2acc50b340b 100644 --- a/drivers/serial/uart_native_tty.c +++ b/drivers/serial/uart_native_tty.c @@ -90,7 +90,7 @@ static int native_tty_conv_to_bottom_cfg(struct native_tty_bottom_cfg *bottom_cf return -ENOTSUP; } - switch (cfg->data_bits) { + switch (cfg->stop_bits) { case UART_CFG_STOP_BITS_1: bottom_cfg->stop_bits = NTB_STOP_BITS_1; break; diff --git a/drivers/serial/uart_native_tty_bottom.c b/drivers/serial/uart_native_tty_bottom.c index cb8e4162a662c..279ebca410005 100644 --- a/drivers/serial/uart_native_tty_bottom.c +++ b/drivers/serial/uart_native_tty_bottom.c @@ -144,7 +144,7 @@ static inline void native_tty_stop_bits_set(struct termios *ter, * @brief Set the number of data bits in the termios structure * * @param ter - * @param stop_bits + * @param data_bits * */ static inline void native_tty_data_bits_set(struct termios *ter, diff --git a/drivers/serial/uart_nrfx_uarte.c b/drivers/serial/uart_nrfx_uarte.c index cc2c9b90594d8..990f4f3fb2ac6 100644 --- a/drivers/serial/uart_nrfx_uarte.c +++ b/drivers/serial/uart_nrfx_uarte.c @@ -25,12 +25,12 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #include /* Generalize PPI or DPPI channel management */ -#if defined(CONFIG_HAS_HW_NRF_PPI) +#if defined(PPI_PRESENT) #include #define gppi_channel_t nrf_ppi_channel_t #define gppi_channel_alloc nrfx_ppi_channel_alloc #define gppi_channel_enable nrfx_ppi_channel_enable -#elif defined(CONFIG_HAS_HW_NRF_DPPIC) +#elif defined(DPPI_PRESENT) #include #define gppi_channel_t uint8_t #define gppi_channel_alloc nrfx_dppi_channel_alloc @@ -39,39 +39,49 @@ LOG_MODULE_REGISTER(uart_nrfx_uarte, CONFIG_UART_LOG_LEVEL); #error "No PPI or DPPI" #endif +/* Execute macro f(x) for all instances. */ +#define UARTE_FOR_EACH_INSTANCE(f, sep, off_code) \ + NRFX_FOREACH_PRESENT(UARTE, f, sep, off_code, _) -#if (defined(CONFIG_HAS_HW_NRF_UARTE0) && \ - defined(CONFIG_UART_0_INTERRUPT_DRIVEN)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE1) && \ - defined(CONFIG_UART_1_INTERRUPT_DRIVEN)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE2) && \ - defined(CONFIG_UART_2_INTERRUPT_DRIVEN)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE3) && \ - defined(CONFIG_UART_3_INTERRUPT_DRIVEN)) +/* Determine if any instance is using interrupt driven API. */ +#define IS_INT_DRIVEN(unused, prefix, i, _) \ + (IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i) && \ + IS_ENABLED(CONFIG_UART_##prefix##i##_INTERRUPT_DRIVEN)) + +#if UARTE_FOR_EACH_INSTANCE(IS_INT_DRIVEN, (||), (0)) #define UARTE_INTERRUPT_DRIVEN 1 #endif -#if (defined(CONFIG_HAS_HW_NRF_UARTE0) && !defined(CONFIG_UART_0_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE1) && !defined(CONFIG_UART_1_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE2) && !defined(CONFIG_UART_2_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE3) && !defined(CONFIG_UART_3_ASYNC)) +/* Determine if any instance is not using asynchronous API. */ +#define IS_NOT_ASYNC(unused, prefix, i, _) \ + (IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i) && \ + !IS_ENABLED(CONFIG_UART_##prefix##i##_ASYNC)) + +#if UARTE_FOR_EACH_INSTANCE(IS_NOT_ASYNC, (||), (0)) #define UARTE_ANY_NONE_ASYNC 1 #endif -#if (defined(CONFIG_HAS_HW_NRF_UARTE0) && defined(CONFIG_UART_0_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE1) && defined(CONFIG_UART_1_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE2) && defined(CONFIG_UART_2_ASYNC)) || \ - (defined(CONFIG_HAS_HW_NRF_UARTE3) && defined(CONFIG_UART_3_ASYNC)) +/* Determine if any instance is using asynchronous API. */ +#define IS_ASYNC(unused, prefix, i, _) \ + (IS_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i) && \ + IS_ENABLED(CONFIG_UART_##prefix##i##_ASYNC)) + +#if UARTE_FOR_EACH_INSTANCE(IS_ASYNC, (||), (0)) #define UARTE_ANY_ASYNC 1 #endif -#if defined(CONFIG_UART_0_NRF_HW_ASYNC) || defined(CONFIG_UART_1_NRF_HW_ASYNC) || \ - defined(CONFIG_UART_2_NRF_HW_ASYNC) || defined(CONFIG_UART_3_NRF_HW_ASYNC) +/* Determine if any instance is using asynchronous API with HW byte counting. */ +#define IS_HW_ASYNC(unused, prefix, i, _) IS_ENABLED(CONFIG_UART_##prefix##i##_NRF_HW_ASYNC) + +#if UARTE_FOR_EACH_INSTANCE(IS_HW_ASYNC, (||), (0)) #define UARTE_HW_ASYNC 1 #endif -#if defined(CONFIG_UART_0_ENHANCED_POLL_OUT) || defined(CONFIG_UART_1_ENHANCED_POLL_OUT) || \ - defined(CONFIG_UART_2_ENHANCED_POLL_OUT) || defined(CONFIG_UART_3_ENHANCED_POLL_OUT) +/* Determine if any instance is using enhanced poll_out feature. */ +#define IS_ENHANCED_POLL_OUT(unused, prefix, i, _) \ + IS_ENABLED(CONFIG_UART_##prefix##i##_ENHANCED_POLL_OUT) + +#if UARTE_FOR_EACH_INSTANCE(IS_ENHANCED_POLL_OUT, (||), (0)) #define UARTE_ENHANCED_POLL_OUT 1 #endif @@ -506,6 +516,20 @@ static int wait_tx_ready(const struct device *dev) return key; } +#if defined(UARTE_ANY_ASYNC) || defined(CONFIG_PM_DEVICE) +static int pins_state_change(const struct device *dev, bool on) +{ + const struct uarte_nrfx_config *config = dev->config; + + if (config->flags & UARTE_CFG_FLAG_GPIO_MGMT) { + return pinctrl_apply_state(config->pcfg, + on ? PINCTRL_STATE_DEFAULT : PINCTRL_STATE_SLEEP); + } + + return 0; +} +#endif + #ifdef UARTE_ANY_ASYNC /* Using Macro instead of static inline function to handle NO_OPTIMIZATIONS case @@ -516,7 +540,7 @@ static int wait_tx_ready(const struct device *dev) #endif /* UARTE_ANY_ASYNC */ -static void uarte_enable(const struct device *dev, uint32_t mask) +static int uarte_enable(const struct device *dev, uint32_t mask) { #ifdef UARTE_ANY_ASYNC const struct uarte_nrfx_config *config = dev->config; @@ -524,8 +548,14 @@ static void uarte_enable(const struct device *dev, uint32_t mask) if (data->async) { bool disabled = data->async->low_power_mask == 0; + int ret; data->async->low_power_mask |= mask; + ret = pins_state_change(dev, true); + if (ret < 0) { + return ret; + } + if (HW_RX_COUNTING_ENABLED(data) && disabled) { const nrfx_timer_t *timer = &config->timer; @@ -538,6 +568,8 @@ static void uarte_enable(const struct device *dev, uint32_t mask) } #endif nrf_uarte_enable(get_uarte_instance(dev)); + + return 0; } /* At this point we should have irq locked and any previous transfer completed. @@ -561,7 +593,7 @@ static void tx_start(const struct device *dev, const uint8_t *buf, size_t len) nrf_uarte_event_clear(uarte, NRF_UARTE_EVENT_TXSTOPPED); if (config->flags & UARTE_CFG_FLAG_LOW_POWER) { - uarte_enable(dev, UARTE_LOW_POWER_TX); + (void)uarte_enable(dev, UARTE_LOW_POWER_TX); nrf_uarte_int_enable(uarte, NRF_UARTE_INT_TXSTOPPED_MASK); } @@ -843,6 +875,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, struct uarte_nrfx_data *data = dev->data; const struct uarte_nrfx_config *cfg = dev->config; NRF_UARTE_Type *uarte = get_uarte_instance(dev); + int ret = 0; if (cfg->disable_rx) { __ASSERT(false, "TX only UARTE instance"); @@ -896,7 +929,7 @@ static int uarte_nrfx_rx_enable(const struct device *dev, uint8_t *buf, if (cfg->flags & UARTE_CFG_FLAG_LOW_POWER) { unsigned int key = irq_lock(); - uarte_enable(dev, UARTE_LOW_POWER_RX); + ret = uarte_enable(dev, UARTE_LOW_POWER_RX); irq_unlock(key); } @@ -1269,6 +1302,10 @@ static void async_uart_release(const struct device *dev, uint32_t dir_mask) } uart_disable(dev); + int err = pins_state_change(dev, false); + + (void)err; + __ASSERT_NO_MSG(err == 0); } irq_unlock(key); @@ -1865,14 +1902,21 @@ static int uarte_nrfx_pm_action(const struct device *dev, const struct uarte_nrfx_config *cfg = dev->config; int ret; +#ifdef UARTE_ANY_ASYNC + /* If low power mode for asynchronous mode is used then there is nothing to do here. + * In low power mode UARTE is turned off whenever there is no activity. + */ + if (data->async && (cfg->flags & UARTE_CFG_FLAG_LOW_POWER)) { + return 0; + } +#endif + switch (action) { case PM_DEVICE_ACTION_RESUME: - if (cfg->flags & UARTE_CFG_FLAG_GPIO_MGMT) { - ret = pinctrl_apply_state(cfg->pcfg, - PINCTRL_STATE_DEFAULT); - if (ret < 0) { - return ret; - } + + ret = pins_state_change(dev, true); + if (ret < 0) { + return ret; } nrf_uarte_enable(uarte); @@ -1941,12 +1985,9 @@ static int uarte_nrfx_pm_action(const struct device *dev, wait_for_tx_stopped(dev); uart_disable(dev); - if (cfg->flags & UARTE_CFG_FLAG_GPIO_MGMT) { - ret = pinctrl_apply_state(cfg->pcfg, - PINCTRL_STATE_SLEEP); - if (ret < 0) { - return ret; - } + ret = pins_state_change(dev, false); + if (ret < 0) { + return ret; } break; @@ -2074,18 +2115,7 @@ static int uarte_nrfx_pm_action(const struct device *dev, DT_PHANDLE(UARTE(idx), memory_regions)))))), \ ()) -#ifdef CONFIG_HAS_HW_NRF_UARTE0 -UART_NRF_UARTE_DEVICE(0); -#endif - -#ifdef CONFIG_HAS_HW_NRF_UARTE1 -UART_NRF_UARTE_DEVICE(1); -#endif - -#ifdef CONFIG_HAS_HW_NRF_UARTE2 -UART_NRF_UARTE_DEVICE(2); -#endif +#define COND_UART_NRF_UARTE_DEVICE(unused, prefix, i, _) \ + IF_ENABLED(CONFIG_HAS_HW_NRF_UARTE##prefix##i, (UART_NRF_UARTE_DEVICE(prefix##i);)) -#ifdef CONFIG_HAS_HW_NRF_UARTE3 -UART_NRF_UARTE_DEVICE(3); -#endif +UARTE_FOR_EACH_INSTANCE(COND_UART_NRF_UARTE_DEVICE, (), ()) diff --git a/drivers/serial/uart_ns16550.c b/drivers/serial/uart_ns16550.c index 9b98ce8c52ec1..a9515d8c7a5cf 100644 --- a/drivers/serial/uart_ns16550.c +++ b/drivers/serial/uart_ns16550.c @@ -242,18 +242,18 @@ BUILD_ASSERT(IS_ENABLED(CONFIG_PCIE), "NS16550(s) in DT need CONFIG_PCIE"); #define MSR_RI 0x40 /* complement of ring signal */ #define MSR_DCD 0x80 /* complement of dcd */ -#define THR(dev) (get_port(dev) + REG_THR * reg_interval(dev)) -#define RDR(dev) (get_port(dev) + REG_RDR * reg_interval(dev)) -#define BRDL(dev) (get_port(dev) + REG_BRDL * reg_interval(dev)) -#define BRDH(dev) (get_port(dev) + REG_BRDH * reg_interval(dev)) -#define IER(dev) (get_port(dev) + REG_IER * reg_interval(dev)) -#define IIR(dev) (get_port(dev) + REG_IIR * reg_interval(dev)) -#define FCR(dev) (get_port(dev) + REG_FCR * reg_interval(dev)) -#define LCR(dev) (get_port(dev) + REG_LCR * reg_interval(dev)) -#define MDC(dev) (get_port(dev) + REG_MDC * reg_interval(dev)) -#define LSR(dev) (get_port(dev) + REG_LSR * reg_interval(dev)) -#define MSR(dev) (get_port(dev) + REG_MSR * reg_interval(dev)) -#define MDR1(dev) (get_port(dev) + REG_MDR1 * reg_interval(dev)) +#define THR(dev) (get_port(dev) + (REG_THR * reg_interval(dev))) +#define RDR(dev) (get_port(dev) + (REG_RDR * reg_interval(dev))) +#define BRDL(dev) (get_port(dev) + (REG_BRDL * reg_interval(dev))) +#define BRDH(dev) (get_port(dev) + (REG_BRDH * reg_interval(dev))) +#define IER(dev) (get_port(dev) + (REG_IER * reg_interval(dev))) +#define IIR(dev) (get_port(dev) + (REG_IIR * reg_interval(dev))) +#define FCR(dev) (get_port(dev) + (REG_FCR * reg_interval(dev))) +#define LCR(dev) (get_port(dev) + (REG_LCR * reg_interval(dev))) +#define MDC(dev) (get_port(dev) + (REG_MDC * reg_interval(dev))) +#define LSR(dev) (get_port(dev) + (REG_LSR * reg_interval(dev))) +#define MSR(dev) (get_port(dev) + (REG_MSR * reg_interval(dev))) +#define MDR1(dev) (get_port(dev) + (REG_MDR1 * reg_interval(dev))) #define DLF(dev) (get_port(dev) + REG_DLF) #define PCP(dev) (get_port(dev) + REG_PCP) diff --git a/drivers/serial/uart_ns16550.h b/drivers/serial/uart_ns16550.h deleted file mode 100644 index 97584c49ef179..0000000000000 --- a/drivers/serial/uart_ns16550.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2015 Intel Corporation. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * Header file for the NS16550 UART - */ - -#ifndef ZEPHYR_DRIVERS_SERIAL_UART_NS16550_H_ -#define ZEPHYR_DRIVERS_SERIAL_UART_NS16550_H_ - -#include - -#warning this header is deprecated, include instead - -#endif /* ZEPHYR_DRIVERS_SERIAL_UART_NS16550_H_ */ diff --git a/drivers/serial/uart_psoc6.c b/drivers/serial/uart_psoc6.c index 6bf09b22b7174..32c1d9e125f6b 100644 --- a/drivers/serial/uart_psoc6.c +++ b/drivers/serial/uart_psoc6.c @@ -12,12 +12,9 @@ * - Error handling is not implemented. * - The driver works only in polling mode, interrupt mode is not implemented. */ -#include -#include -#include -#include -#include #include +#include +#include #include "cy_syslib.h" #include "cy_sysclk.h" @@ -50,8 +47,7 @@ struct cypress_psoc6_config { #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_config_func_t irq_config_func; #endif - uint32_t num_pins; - struct soc_gpio_pin pins[]; + const struct pinctrl_dev_config *pcfg; }; #ifdef CONFIG_UART_INTERRUPT_DRIVEN @@ -104,9 +100,14 @@ static const cy_stc_scb_uart_config_t uartConfig = { */ static int uart_psoc6_init(const struct device *dev) { + int ret; const struct cypress_psoc6_config *config = dev->config; - soc_gpio_list_configure(config->pins, config->num_pins); + /* Configure dt provided device signals when available */ + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } /* Connect assigned divider to be a clock source for UART */ Cy_SysClk_PeriphAssignDivider(config->periph_id, @@ -344,14 +345,13 @@ static const struct uart_driver_api uart_psoc6_driver_api = { #endif #define CY_PSOC6_UART_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ CY_PSOC6_UART_DECL_DATA(n) \ CY_PSOC6_UART_IRQ_FUNC(n) \ static const struct cypress_psoc6_config cy_psoc6_uart##n##_config = { \ .base = (CySCB_Type *)DT_INST_REG_ADDR(n), \ .periph_id = DT_INST_PROP(n, peripheral_id), \ - \ - .num_pins = CY_PSOC6_DT_INST_NUM_PINS(n), \ - .pins = CY_PSOC6_DT_INST_PINS(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ \ CY_PSOC6_UART_IRQ_SET_FUNC(n) \ }; \ diff --git a/drivers/serial/uart_smartbond.c b/drivers/serial/uart_smartbond.c index 7d5ef34cc72db..8656ae8dc433d 100644 --- a/drivers/serial/uart_smartbond.c +++ b/drivers/serial/uart_smartbond.c @@ -7,13 +7,17 @@ #define DT_DRV_COMPAT renesas_smartbond_uart #include +#include #include #include +#include +#include #include #include #include #include #include +#include #define IIR_NO_INTR 1 #define IIR_THR_EMPTY 2 @@ -75,10 +79,29 @@ struct uart_smartbond_cfg { #ifdef CONFIG_UART_INTERRUPT_DRIVEN void (*irq_config_func)(const struct device *dev); #endif +#if CONFIG_PM_DEVICE + int rx_wake_timeout; + struct gpio_dt_spec rx_wake_gpio; + struct gpio_dt_spec dtr_gpio; +#endif +}; + +struct uart_smartbond_runtime_cfg { + uint32_t baudrate_cfg; + uint32_t lcr_reg_val; + uint8_t mcr_reg_val; + uint8_t ier_reg_val; +}; + +enum uart_smartbond_pm_policy_state_flag { + UART_SMARTBOND_PM_POLICY_STATE_RX_FLAG, + UART_SMARTBOND_PM_POLICY_STATE_DTR_FLAG, + UART_SMARTBOND_PM_POLICY_STATE_FLAG_COUNT, }; struct uart_smartbond_data { struct uart_config current_config; + struct uart_smartbond_runtime_cfg runtime_cfg; struct k_spinlock lock; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_callback_user_data_t callback; @@ -86,9 +109,44 @@ struct uart_smartbond_data { uint32_t flags; uint8_t rx_enabled; uint8_t tx_enabled; +#if CONFIG_PM_DEVICE + struct gpio_callback dtr_wake_cb; + const struct uart_smartbond_cfg *config; + struct gpio_callback rx_wake_cb; + int rx_wake_timeout; + struct k_work_delayable rx_timeout_work; + + ATOMIC_DEFINE(pm_policy_state_flag, UART_SMARTBOND_PM_POLICY_STATE_FLAG_COUNT); +#endif #endif }; +#if defined(CONFIG_PM_DEVICE) + +static void uart_smartbond_pm_policy_state_lock_get(struct uart_smartbond_data *data, int flag) +{ + if (atomic_test_and_set_bit(data->pm_policy_state_flag, flag) == 0) { + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +} + +static void uart_smartbond_pm_policy_state_lock_put(struct uart_smartbond_data *data, int flag) +{ + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, flag) == 1) { + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +} + +static void uart_smartbond_rx_refresh_timeout(struct k_work *work) +{ + struct uart_smartbond_data *data = CONTAINER_OF(work, struct uart_smartbond_data, + rx_timeout_work.work); + + uart_smartbond_pm_policy_state_lock_put(data, UART_SMARTBOND_PM_POLICY_STATE_RX_FLAG); +} + +#endif + static int uart_smartbond_poll_in(const struct device *dev, unsigned char *p_char) { const struct uart_smartbond_cfg *config = dev->config; @@ -122,14 +180,48 @@ static void uart_smartbond_poll_out(const struct device *dev, unsigned char out_ k_spin_unlock(&data->lock, key); } +static void apply_runtime_config(const struct device *dev) +{ + const struct uart_smartbond_cfg *config = dev->config; + struct uart_smartbond_data *data = dev->data; + k_spinlock_key_t key; + + key = k_spin_lock(&data->lock); + + CRG_COM->SET_CLK_COM_REG = config->periph_clock_config; + + config->regs->UART2_MCR_REG = data->runtime_cfg.mcr_reg_val; + config->regs->UART2_SRR_REG = UART2_UART2_SRR_REG_UART_UR_Msk | + UART2_UART2_SRR_REG_UART_RFR_Msk | + UART2_UART2_SRR_REG_UART_XFR_Msk; + + /* Configure baudrate */ + config->regs->UART2_LCR_REG |= UART2_UART2_LCR_REG_UART_DLAB_Msk; + config->regs->UART2_IER_DLH_REG = BAUDRATE_CFG_DLH(data->runtime_cfg.baudrate_cfg); + config->regs->UART2_RBR_THR_DLL_REG = BAUDRATE_CFG_DLL(data->runtime_cfg.baudrate_cfg); + config->regs->UART2_DLF_REG = BAUDRATE_CFG_DLF(data->runtime_cfg.baudrate_cfg); + config->regs->UART2_LCR_REG &= ~UART2_UART2_LCR_REG_UART_DLAB_Msk; + + /* Configure frame */ + config->regs->UART2_LCR_REG = data->runtime_cfg.lcr_reg_val; + + /* Enable hardware FIFO */ + config->regs->UART2_SFE_REG = UART2_UART2_SFE_REG_UART_SHADOW_FIFO_ENABLE_Msk; + + config->regs->UART2_SRT_REG = RX_FIFO_TRIG_1_CHAR; + config->regs->UART2_STET_REG = TX_FIFO_TRIG_1_2_FULL; + config->regs->UART2_IER_DLH_REG = data->runtime_cfg.ier_reg_val; + + k_spin_unlock(&data->lock, key); +} + static int uart_smartbond_configure(const struct device *dev, - const struct uart_config *cfg) + const struct uart_config *cfg) { const struct uart_smartbond_cfg *config = dev->config; struct uart_smartbond_data *data = dev->data; uint32_t baudrate_cfg = 0; - k_spinlock_key_t key; - uint32_t reg_val; + uint32_t lcr_reg_val; int err; int i; @@ -161,63 +253,44 @@ static int uart_smartbond_configure(const struct device *dev, return -ENOTSUP; } - key = k_spin_lock(&data->lock); - - CRG_COM->SET_CLK_COM_REG = config->periph_clock_config; - - config->regs->UART2_SRR_REG = UART2_UART2_SRR_REG_UART_UR_Msk | - UART2_UART2_SRR_REG_UART_RFR_Msk | - UART2_UART2_SRR_REG_UART_XFR_Msk; - - config->regs->UART2_LCR_REG |= UART2_UART2_LCR_REG_UART_DLAB_Msk; - config->regs->UART2_IER_DLH_REG = BAUDRATE_CFG_DLH(baudrate_cfg); - config->regs->UART2_RBR_THR_DLL_REG = BAUDRATE_CFG_DLL(baudrate_cfg); - config->regs->UART2_DLF_REG = BAUDRATE_CFG_DLF(baudrate_cfg); - config->regs->UART2_LCR_REG &= ~UART2_UART2_LCR_REG_UART_DLAB_Msk; - - /* Configure frame */ - - reg_val = 0; + /* Calculate frame configuration register value */ + lcr_reg_val = 0; switch (cfg->parity) { case UART_CFG_PARITY_NONE: break; case UART_CFG_PARITY_EVEN: - reg_val |= UART2_UART2_LCR_REG_UART_EPS_Msk; + lcr_reg_val |= UART2_UART2_LCR_REG_UART_EPS_Msk; /* no break */ case UART_CFG_PARITY_ODD: - reg_val |= UART2_UART2_LCR_REG_UART_PEN_Msk; + lcr_reg_val |= UART2_UART2_LCR_REG_UART_PEN_Msk; break; } if (cfg->stop_bits == UART_CFG_STOP_BITS_2) { - reg_val |= STOP_BITS_2 << UART2_UART2_LCR_REG_UART_STOP_Pos; + lcr_reg_val |= STOP_BITS_2 << UART2_UART2_LCR_REG_UART_STOP_Pos; } switch (cfg->data_bits) { case UART_CFG_DATA_BITS_6: - reg_val |= DATA_BITS_6 << UART2_UART2_LCR_REG_UART_DLS_Pos; + lcr_reg_val |= DATA_BITS_6 << UART2_UART2_LCR_REG_UART_DLS_Pos; break; case UART_CFG_DATA_BITS_7: - reg_val |= DATA_BITS_7 << UART2_UART2_LCR_REG_UART_DLS_Pos; + lcr_reg_val |= DATA_BITS_7 << UART2_UART2_LCR_REG_UART_DLS_Pos; break; case UART_CFG_DATA_BITS_8: - reg_val |= DATA_BITS_8 << UART2_UART2_LCR_REG_UART_DLS_Pos; + lcr_reg_val |= DATA_BITS_8 << UART2_UART2_LCR_REG_UART_DLS_Pos; break; } - config->regs->UART2_LCR_REG = reg_val; - - /* Enable hardware FIFO */ - config->regs->UART2_SFE_REG = UART2_UART2_SFE_REG_UART_SHADOW_FIFO_ENABLE_Msk; + data->runtime_cfg.baudrate_cfg = baudrate_cfg; + data->runtime_cfg.lcr_reg_val = lcr_reg_val; + data->runtime_cfg.mcr_reg_val = cfg->flow_ctrl ? UART2_UART2_MCR_REG_UART_AFCE_Msk : 0; - config->regs->UART2_SRT_REG = RX_FIFO_TRIG_1_CHAR; - config->regs->UART2_STET_REG = TX_FIFO_TRIG_1_2_FULL; + apply_runtime_config(dev); data->current_config = *cfg; - k_spin_unlock(&data->lock, key); - err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); if (err < 0) { return err; @@ -238,11 +311,103 @@ static int uart_smartbond_config_get(const struct device *dev, } #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ +#if CONFIG_PM_DEVICE + +static void uart_smartbond_wake_handler(const struct device *gpio, struct gpio_callback *cb, + uint32_t pins) +{ + struct uart_smartbond_data *data = CONTAINER_OF(cb, struct uart_smartbond_data, + rx_wake_cb); + + /* Disable interrupts on UART RX pin to avoid repeated interrupts. */ + (void)gpio_pin_interrupt_configure(gpio, (find_msb_set(pins) - 1), + GPIO_INT_DISABLE); + /* Refresh console expired time */ + if (data->rx_wake_timeout) { + + uart_smartbond_pm_policy_state_lock_get(data, + UART_SMARTBOND_PM_POLICY_STATE_RX_FLAG); + k_work_reschedule(&data->rx_timeout_work, K_MSEC(data->rx_wake_timeout)); + } +} + +static void uart_smartbond_dtr_handler(const struct device *gpio, struct gpio_callback *cb, + uint32_t pins) +{ + struct uart_smartbond_data *data = CONTAINER_OF(cb, struct uart_smartbond_data, + dtr_wake_cb); + int pin = find_lsb_set(pins) - 1; + + if (gpio_pin_get(gpio, pin) == 1) { + uart_smartbond_pm_policy_state_lock_put(data, + UART_SMARTBOND_PM_POLICY_STATE_DTR_FLAG); + } else { + uart_smartbond_pm_policy_state_lock_get(data, + UART_SMARTBOND_PM_POLICY_STATE_DTR_FLAG); + } +} + +#endif + static int uart_smartbond_init(const struct device *dev) { struct uart_smartbond_data *data = dev->data; + int ret = 0; + + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + +#ifdef CONFIG_PM_DEVICE + int rx_wake_timeout; + const struct uart_smartbond_cfg *config = dev->config; + const struct device *uart_console_dev = + DEVICE_DT_GET(DT_CHOSEN(zephyr_console)); + /* All uarts can have wake time specified in device tree to keep + * device awake after receiving data + */ + rx_wake_timeout = config->rx_wake_timeout; + if (dev == uart_console_dev) { +#ifdef CONFIG_UART_CONSOLE_INPUT_EXPIRED + /* For device configured as console wake time is taken from + * Kconfig same way it is configured for other platforms + */ + rx_wake_timeout = CONFIG_UART_CONSOLE_INPUT_EXPIRED_TIMEOUT; +#endif + } + /* If DTR pin is configured, use it for power management */ + if (config->dtr_gpio.port != NULL) { + gpio_init_callback(&data->dtr_wake_cb, uart_smartbond_dtr_handler, + BIT(config->dtr_gpio.pin)); + ret = gpio_add_callback(config->dtr_gpio.port, &data->dtr_wake_cb); + if (ret == 0) { + ret = gpio_pin_interrupt_configure_dt(&config->dtr_gpio, + GPIO_INT_MODE_EDGE | + GPIO_INT_TRIG_BOTH); + /* Check if DTR is already active (low), if so lock power state */ + if (gpio_pin_get(config->dtr_gpio.port, config->dtr_gpio.pin) == 0) { + uart_smartbond_pm_policy_state_lock_get(data, + UART_SMARTBOND_PM_POLICY_STATE_DTR_FLAG); + } + } + } + if (rx_wake_timeout > 0 && config->rx_wake_gpio.port != NULL) { + k_work_init_delayable(&data->rx_timeout_work, + uart_smartbond_rx_refresh_timeout); + gpio_init_callback(&data->rx_wake_cb, uart_smartbond_wake_handler, + BIT(config->rx_wake_gpio.pin)); + + ret = gpio_add_callback(config->rx_wake_gpio.port, &data->rx_wake_cb); + if (ret == 0) { + data->rx_wake_timeout = rx_wake_timeout; + } + } +#endif - return uart_smartbond_configure(dev, &data->current_config); + ret = uart_smartbond_configure(dev, &data->current_config); + if (ret < 0) { + da1469x_pd_release(MCU_PD_DOMAIN_COM); + } + + return ret; } #ifdef CONFIG_UART_INTERRUPT_DRIVEN @@ -316,6 +481,11 @@ static int uart_smartbond_fifo_read(const struct device *dev, uint8_t *rx_data, irq_rx_enable(dev); } +#ifdef CONFIG_PM_DEVICE + if (data->rx_wake_timeout) { + k_work_reschedule(&data->rx_timeout_work, K_MSEC(data->rx_wake_timeout)); + } +#endif k_spin_unlock(&data->lock, key); return num_rx; @@ -455,6 +625,60 @@ static void uart_smartbond_isr(const struct device *dev) } #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ +#ifdef CONFIG_PM_DEVICE +static int uart_disable(const struct device *dev) +{ + const struct uart_smartbond_cfg *config = dev->config; + struct uart_smartbond_data *data = dev->data; + + /* Store IER register in case UART will go to sleep */ + data->runtime_cfg.ier_reg_val = config->regs->UART2_IER_DLH_REG; + + if (config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_RFNE_Msk) { + return -EBUSY; + } + while (!(config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_TFE_Msk) || + (config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_BUSY_Msk)) { + /* Wait until FIFO is empty and UART finished tx */ + if (config->regs->UART2_USR_REG & UART2_UART2_USR_REG_UART_RFNE_Msk) { + return -EBUSY; + } + } + + CRG_COM->RESET_CLK_COM_REG = config->periph_clock_config; + da1469x_pd_release(MCU_PD_DOMAIN_COM); + + return 0; +} + +static int uart_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + const struct uart_smartbond_cfg *config; + int ret = 0; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + apply_runtime_config(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + config = dev->config; + ret = uart_disable(dev); + if (ret == 0 && config->rx_wake_gpio.port != NULL) { + ret = gpio_pin_interrupt_configure_dt(&config->rx_wake_gpio, + GPIO_INT_MODE_EDGE | + GPIO_INT_TRIG_LOW); + } + break; + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif /* CONFIG_PM_DEVICE */ + static const struct uart_driver_api uart_smartbond_driver_api = { .poll_in = uart_smartbond_poll_in, .poll_out = uart_smartbond_poll_out, @@ -494,6 +718,19 @@ static const struct uart_driver_api uart_smartbond_driver_api = { #define UART_SMARTBOND_CONFIGURE(id) #endif +#ifdef CONFIG_PM_DEVICE +#define UART_PM_WAKE_RX_TIMEOUT(n) \ + .rx_wake_timeout = (DT_INST_PROP_OR(n, rx_wake_timeout, 0)), +#define UART_PM_WAKE_RX_PIN(n) \ + .rx_wake_gpio = GPIO_DT_SPEC_INST_GET_OR(n, rx_wake_gpios, {0}), +#define UART_PM_WAKE_DTR_PIN(n) \ + .dtr_gpio = GPIO_DT_SPEC_INST_GET_OR(n, dtr_gpios, {0}), +#else +#define UART_PM_WAKE_RX_PIN(n) /* Not used */ +#define UART_PM_WAKE_RX_TIMEOUT(n) /* Not used */ +#define UART_PM_WAKE_DTR_PIN(n) /* Not used */ +#endif + #define UART_SMARTBOND_DEVICE(id) \ PINCTRL_DT_INST_DEFINE(id); \ static const struct uart_smartbond_cfg uart_smartbond_##id##_cfg = { \ @@ -501,6 +738,9 @@ static const struct uart_driver_api uart_smartbond_driver_api = { .periph_clock_config = DT_INST_PROP(id, periph_clock_config), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ .hw_flow_control_supported = DT_INST_PROP(id, hw_flow_control_supported), \ + UART_PM_WAKE_RX_TIMEOUT(id) \ + UART_PM_WAKE_RX_PIN(id) \ + UART_PM_WAKE_DTR_PIN(id) \ }; \ static struct uart_smartbond_data uart_smartbond_##id##_data = { \ .current_config = { \ @@ -516,9 +756,10 @@ static const struct uart_driver_api uart_smartbond_driver_api = { UART_SMARTBOND_CONFIGURE(id); \ return uart_smartbond_init(dev); \ } \ + PM_DEVICE_DT_INST_DEFINE(id, uart_smartbond_pm_action); \ DEVICE_DT_INST_DEFINE(id, \ uart_smartbond_##id##_init, \ - NULL, \ + PM_DEVICE_DT_INST_GET(id), \ &uart_smartbond_##id##_data, \ &uart_smartbond_##id##_cfg, \ PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \ diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index e79ba3bf0f3e9..10e5b310d8ff0 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 Open-RnD Sp. z o.o. * Copyright (c) 2016 Linaro Limited. + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -39,6 +40,12 @@ #include #endif /* CONFIG_PM */ +#ifdef CONFIG_DCACHE +#include +#include +#include +#endif /* CONFIG_DCACHE */ + #include #include LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL); @@ -119,6 +126,7 @@ static void uart_stm32_pm_policy_state_lock_put(const struct device *dev) static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t baud_rate) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; uint32_t clock_rate; @@ -141,7 +149,7 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba } #if HAS_LPUART - if (IS_LPUART_INSTANCE(config->usart)) { + if (IS_LPUART_INSTANCE(usart)) { uint32_t lpuartdiv; #ifdef USART_PRESC_PRESCALER uint8_t presc_idx; @@ -161,7 +169,7 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba presc_val = presc_idx << USART_PRESC_PRESCALER_Pos; - LL_LPUART_SetPrescaler(config->usart, presc_val); + LL_LPUART_SetPrescaler(usart, presc_val); #else lpuartdiv = lpuartdiv_calc(clock_rate, baud_rate); if (lpuartdiv < LPUART_BRR_MIN_VALUE || lpuartdiv > LPUART_BRR_MASK) { @@ -169,26 +177,26 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba return; } #endif /* USART_PRESC_PRESCALER */ - LL_LPUART_SetBaudRate(config->usart, + LL_LPUART_SetBaudRate(usart, clock_rate, #ifdef USART_PRESC_PRESCALER presc_val, #endif baud_rate); /* Check BRR is greater than or equal to 0x300 */ - __ASSERT(LL_LPUART_ReadReg(config->usart, BRR) >= 0x300U, + __ASSERT(LL_LPUART_ReadReg(usart, BRR) >= 0x300U, "BaudRateReg >= 0x300"); /* Check BRR is lower than or equal to 0xFFFFF */ - __ASSERT(LL_LPUART_ReadReg(config->usart, BRR) < 0x000FFFFFU, + __ASSERT(LL_LPUART_ReadReg(usart, BRR) < 0x000FFFFFU, "BaudRateReg < 0xFFFF"); } else { #endif /* HAS_LPUART */ #ifdef USART_CR1_OVER8 - LL_USART_SetOverSampling(config->usart, + LL_USART_SetOverSampling(usart, LL_USART_OVERSAMPLING_16); #endif - LL_USART_SetBaudRate(config->usart, + LL_USART_SetBaudRate(usart, clock_rate, #ifdef USART_PRESC_PRESCALER LL_USART_PRESCALER_DIV1, @@ -198,7 +206,7 @@ static inline void uart_stm32_set_baudrate(const struct device *dev, uint32_t ba #endif baud_rate); /* Check BRR is greater than or equal to 16d */ - __ASSERT(LL_USART_ReadReg(config->usart, BRR) >= 16, + __ASSERT(LL_USART_ReadReg(usart, BRR) >= 16, "BaudRateReg >= 16"); #if HAS_LPUART @@ -526,6 +534,7 @@ static int uart_stm32_configure(const struct device *dev, const struct uart_config *cfg) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; struct uart_config *uart_cfg = data->uart_cfg; const uint32_t parity = uart_stm32_cfg2ll_parity(cfg->parity); @@ -562,21 +571,21 @@ static int uart_stm32_configure(const struct device *dev, /* Driver supports only RTS/CTS and RS485 flow control */ if (!(cfg->flow_ctrl == UART_CFG_FLOW_CTRL_NONE || (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RTS_CTS && - IS_UART_HWFLOW_INSTANCE(config->usart)) + IS_UART_HWFLOW_INSTANCE(usart)) #if HAS_DRIVER_ENABLE || (cfg->flow_ctrl == UART_CFG_FLOW_CTRL_RS485 && - IS_UART_DRIVER_ENABLE_INSTANCE(config->usart)) + IS_UART_DRIVER_ENABLE_INSTANCE(usart)) #endif )) { return -ENOTSUP; } - LL_USART_Disable(config->usart); + LL_USART_Disable(usart); /* Set basic parameters, such as data-/stop-bit, parity, and baudrate */ uart_stm32_parameters_set(dev, cfg); - LL_USART_Enable(config->usart); + LL_USART_Enable(usart); /* Upon successful configuration, persist the syscall-passed * uart_config. @@ -612,37 +621,39 @@ static int uart_stm32_config_get(const struct device *dev, #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ typedef void (*poll_in_fn)( - const struct uart_stm32_config *config, + USART_TypeDef *usart, void *in); static int uart_stm32_poll_in_visitor(const struct device *dev, void *in, poll_in_fn get_fn) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; /* Clear overrun error flag */ - if (LL_USART_IsActiveFlag_ORE(config->usart)) { - LL_USART_ClearFlag_ORE(config->usart); + if (LL_USART_IsActiveFlag_ORE(usart)) { + LL_USART_ClearFlag_ORE(usart); } /* * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by * the uart_err_check function call (on errors flags clearing) */ - if (!LL_USART_IsActiveFlag_RXNE(config->usart)) { + if (!LL_USART_IsActiveFlag_RXNE(usart)) { return -1; } - get_fn(config, in); + get_fn(usart, in); return 0; } typedef void (*poll_out_fn)( - const struct uart_stm32_config *config, void *out); + USART_TypeDef *usart, void *out); static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, poll_out_fn set_fn) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; #ifdef CONFIG_PM struct uart_stm32_data *data = dev->data; #endif @@ -654,9 +665,9 @@ static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, pol * interlaced with the characters potentially send with interrupt transmission API */ while (1) { - if (LL_USART_IsActiveFlag_TXE(config->usart)) { + if (LL_USART_IsActiveFlag_TXE(usart)) { key = irq_lock(); - if (LL_USART_IsActiveFlag_TXE(config->usart)) { + if (LL_USART_IsActiveFlag_TXE(usart)) { break; } irq_unlock(key); @@ -679,22 +690,22 @@ static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, pol /* Enable TC interrupt so we can release suspend * constraint when done */ - LL_USART_EnableIT_TC(config->usart); + LL_USART_EnableIT_TC(usart); } #endif /* CONFIG_PM */ - set_fn(config, out); + set_fn(usart, out); irq_unlock(key); } -static void poll_in_u8(const struct uart_stm32_config *config, void *in) +static void poll_in_u8(USART_TypeDef *usart, void *in) { - *((unsigned char *)in) = (unsigned char)LL_USART_ReceiveData8(config->usart); + *((unsigned char *)in) = (unsigned char)LL_USART_ReceiveData8(usart); } -static void poll_out_u8(const struct uart_stm32_config *config, void *out) +static void poll_out_u8(USART_TypeDef *usart, void *out) { - LL_USART_TransmitData8(config->usart, *((uint8_t *)out)); + LL_USART_TransmitData8(usart, *((uint8_t *)out)); } static int uart_stm32_poll_in(const struct device *dev, unsigned char *c) @@ -709,14 +720,14 @@ static void uart_stm32_poll_out(const struct device *dev, unsigned char c) #ifdef CONFIG_UART_WIDE_DATA -static void poll_out_u9(const struct uart_stm32_config *config, void *out) +static void poll_out_u9(USART_TypeDef *usart, void *out) { - LL_USART_TransmitData9(config->usart, *((uint16_t *)out)); + LL_USART_TransmitData9(usart, *((uint16_t *)out)); } -static void poll_in_u9(const struct uart_stm32_config *config, void *in) +static void poll_in_u9(USART_TypeDef *usart, void *in) { - *((uint16_t *)in) = LL_USART_ReceiveData9(config->usart); + *((uint16_t *)in) = LL_USART_ReceiveData9(usart); } static int uart_stm32_poll_in_u16(const struct device *dev, uint16_t *in_u16) @@ -734,6 +745,7 @@ static void uart_stm32_poll_out_u16(const struct device *dev, uint16_t out_u16) static int uart_stm32_err_check(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; uint32_t err = 0U; /* Check for errors, then clear them. @@ -741,29 +753,29 @@ static int uart_stm32_err_check(const struct device *dev) * one is cleared. (e.g. F4X, F1X, and F2X). * The stm32 F4X, F1X, and F2X also reads the usart DR when clearing Errors */ - if (LL_USART_IsActiveFlag_ORE(config->usart)) { + if (LL_USART_IsActiveFlag_ORE(usart)) { err |= UART_ERROR_OVERRUN; } - if (LL_USART_IsActiveFlag_PE(config->usart)) { + if (LL_USART_IsActiveFlag_PE(usart)) { err |= UART_ERROR_PARITY; } - if (LL_USART_IsActiveFlag_FE(config->usart)) { + if (LL_USART_IsActiveFlag_FE(usart)) { err |= UART_ERROR_FRAMING; } - if (LL_USART_IsActiveFlag_NE(config->usart)) { + if (LL_USART_IsActiveFlag_NE(usart)) { err |= UART_ERROR_NOISE; } #if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT) - if (LL_USART_IsActiveFlag_LBD(config->usart)) { + if (LL_USART_IsActiveFlag_LBD(usart)) { err |= UART_BREAK; } if (err & UART_BREAK) { - LL_USART_ClearFlag_LBD(config->usart); + LL_USART_ClearFlag_LBD(usart); } #endif /* Clearing error : @@ -772,19 +784,19 @@ static int uart_stm32_err_check(const struct device *dev) * --> so is the RXNE flag also cleared ! */ if (err & UART_ERROR_OVERRUN) { - LL_USART_ClearFlag_ORE(config->usart); + LL_USART_ClearFlag_ORE(usart); } if (err & UART_ERROR_PARITY) { - LL_USART_ClearFlag_PE(config->usart); + LL_USART_ClearFlag_PE(usart); } if (err & UART_ERROR_FRAMING) { - LL_USART_ClearFlag_FE(config->usart); + LL_USART_ClearFlag_FE(usart); } if (err & UART_ERROR_NOISE) { - LL_USART_ClearFlag_NE(config->usart); + LL_USART_ClearFlag_NE(usart); } return err; @@ -800,28 +812,29 @@ static inline void __uart_stm32_get_clock(const struct device *dev) #ifdef CONFIG_UART_INTERRUPT_DRIVEN -typedef void (*fifo_fill_fn)(const struct uart_stm32_config *config, const void *tx_data, +typedef void (*fifo_fill_fn)(USART_TypeDef *usart, const void *tx_data, const uint8_t offset); static int uart_stm32_fifo_fill_visitor(const struct device *dev, const void *tx_data, int size, fifo_fill_fn fill_fn) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; uint8_t num_tx = 0U; unsigned int key; - if (!LL_USART_IsActiveFlag_TXE(config->usart)) { + if (!LL_USART_IsActiveFlag_TXE(usart)) { return num_tx; } /* Lock interrupts to prevent nested interrupts or thread switch */ key = irq_lock(); - while ((size - num_tx > 0) && LL_USART_IsActiveFlag_TXE(config->usart)) { + while ((size - num_tx > 0) && LL_USART_IsActiveFlag_TXE(usart)) { /* TXE flag will be cleared with byte write to DR|RDR register */ /* Send a character */ - fill_fn(config, tx_data, num_tx); + fill_fn(usart, tx_data, num_tx); num_tx++; } @@ -830,12 +843,12 @@ static int uart_stm32_fifo_fill_visitor(const struct device *dev, const void *tx return num_tx; } -static void fifo_fill_with_u8(const struct uart_stm32_config *config, +static void fifo_fill_with_u8(USART_TypeDef *usart, const void *tx_data, const uint8_t offset) { const uint8_t *data = (const uint8_t *)tx_data; /* Send a character (8bit) */ - LL_USART_TransmitData8(config->usart, data[offset]); + LL_USART_TransmitData8(usart, data[offset]); } static int uart_stm32_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) @@ -848,24 +861,25 @@ static int uart_stm32_fifo_fill(const struct device *dev, const uint8_t *tx_data fifo_fill_with_u8); } -typedef void (*fifo_read_fn)(const struct uart_stm32_config *config, void *rx_data, +typedef void (*fifo_read_fn)(USART_TypeDef *usart, void *rx_data, const uint8_t offset); static int uart_stm32_fifo_read_visitor(const struct device *dev, void *rx_data, const int size, fifo_read_fn read_fn) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; uint8_t num_rx = 0U; - while ((size - num_rx > 0) && LL_USART_IsActiveFlag_RXNE(config->usart)) { + while ((size - num_rx > 0) && LL_USART_IsActiveFlag_RXNE(usart)) { /* RXNE flag will be cleared upon read from DR|RDR register */ - read_fn(config, rx_data, num_rx); + read_fn(usart, rx_data, num_rx); num_rx++; /* Clear overrun error flag */ - if (LL_USART_IsActiveFlag_ORE(config->usart)) { - LL_USART_ClearFlag_ORE(config->usart); + if (LL_USART_IsActiveFlag_ORE(usart)) { + LL_USART_ClearFlag_ORE(usart); /* * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by * the uart_err_check function call (on errors flags clearing) @@ -876,12 +890,12 @@ static int uart_stm32_fifo_read_visitor(const struct device *dev, void *rx_data, return num_rx; } -static void fifo_read_with_u8(const struct uart_stm32_config *config, void *rx_data, +static void fifo_read_with_u8(USART_TypeDef *usart, void *rx_data, const uint8_t offset) { uint8_t *data = (uint8_t *)rx_data; - data[offset] = LL_USART_ReceiveData8(config->usart); + data[offset] = LL_USART_ReceiveData8(usart); } static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) @@ -896,13 +910,13 @@ static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, cons #ifdef CONFIG_UART_WIDE_DATA -static void fifo_fill_with_u16(const struct uart_stm32_config *config, +static void fifo_fill_with_u16(USART_TypeDef *usart, const void *tx_data, const uint8_t offset) { const uint16_t *data = (const uint16_t *)tx_data; /* Send a character (9bit) */ - LL_USART_TransmitData9(config->usart, data[offset]); + LL_USART_TransmitData9(usart, data[offset]); } static int uart_stm32_fifo_fill_u16(const struct device *dev, const uint16_t *tx_data, int size) @@ -915,12 +929,12 @@ static int uart_stm32_fifo_fill_u16(const struct device *dev, const uint16_t *tx fifo_fill_with_u16); } -static void fifo_read_with_u16(const struct uart_stm32_config *config, void *rx_data, +static void fifo_read_with_u16(USART_TypeDef *usart, void *rx_data, const uint8_t offset) { uint16_t *data = (uint16_t *)rx_data; - data[offset] = LL_USART_ReceiveData9(config->usart); + data[offset] = LL_USART_ReceiveData9(usart); } static int uart_stm32_fifo_read_u16(const struct device *dev, uint16_t *rx_data, const int size) @@ -1020,43 +1034,46 @@ static int uart_stm32_irq_rx_ready(const struct device *dev) static void uart_stm32_irq_err_enable(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; /* Enable FE, ORE interruptions */ - LL_USART_EnableIT_ERROR(config->usart); + LL_USART_EnableIT_ERROR(usart); #if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT) /* Enable Line break detection */ - if (IS_UART_LIN_INSTANCE(config->usart)) { - LL_USART_EnableIT_LBD(config->usart); + if (IS_UART_LIN_INSTANCE(usart)) { + LL_USART_EnableIT_LBD(usart); } #endif /* Enable parity error interruption */ - LL_USART_EnableIT_PE(config->usart); + LL_USART_EnableIT_PE(usart); } static void uart_stm32_irq_err_disable(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; /* Disable FE, ORE interruptions */ - LL_USART_DisableIT_ERROR(config->usart); + LL_USART_DisableIT_ERROR(usart); #if !defined(CONFIG_SOC_SERIES_STM32F0X) || defined(USART_LIN_SUPPORT) /* Disable Line break detection */ - if (IS_UART_LIN_INSTANCE(config->usart)) { - LL_USART_DisableIT_LBD(config->usart); + if (IS_UART_LIN_INSTANCE(usart)) { + LL_USART_DisableIT_LBD(usart); } #endif /* Disable parity error interruption */ - LL_USART_DisableIT_PE(config->usart); + LL_USART_DisableIT_PE(usart); } static int uart_stm32_irq_is_pending(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; - return ((LL_USART_IsActiveFlag_RXNE(config->usart) && - LL_USART_IsEnabledIT_RXNE(config->usart)) || - (LL_USART_IsActiveFlag_TC(config->usart) && - LL_USART_IsEnabledIT_TC(config->usart))); + return ((LL_USART_IsActiveFlag_RXNE(usart) && + LL_USART_IsEnabledIT_RXNE(usart)) || + (LL_USART_IsActiveFlag_TC(usart) && + LL_USART_IsEnabledIT_TC(usart))); } static int uart_stm32_irq_update(const struct device *dev) @@ -1217,17 +1234,18 @@ static void uart_stm32_isr(const struct device *dev) struct uart_stm32_data *data = dev->data; #if defined(CONFIG_PM) || defined(CONFIG_UART_ASYNC_API) const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; #endif #ifdef CONFIG_PM - if (LL_USART_IsEnabledIT_TC(config->usart) && - LL_USART_IsActiveFlag_TC(config->usart)) { + if (LL_USART_IsEnabledIT_TC(usart) && + LL_USART_IsActiveFlag_TC(usart)) { if (data->tx_poll_stream_on) { /* A poll stream transmission just completed, * allow system to suspend */ - LL_USART_DisableIT_TC(config->usart); + LL_USART_DisableIT_TC(usart); data->tx_poll_stream_on = false; uart_stm32_pm_policy_state_lock_put(dev); } @@ -1245,10 +1263,10 @@ static void uart_stm32_isr(const struct device *dev) #endif /* CONFIG_UART_INTERRUPT_DRIVEN */ #ifdef CONFIG_UART_ASYNC_API - if (LL_USART_IsEnabledIT_IDLE(config->usart) && - LL_USART_IsActiveFlag_IDLE(config->usart)) { + if (LL_USART_IsEnabledIT_IDLE(usart) && + LL_USART_IsActiveFlag_IDLE(usart)) { - LL_USART_ClearFlag_IDLE(config->usart); + LL_USART_ClearFlag_IDLE(usart); LOG_DBG("idle interrupt occurred"); @@ -1259,24 +1277,24 @@ static void uart_stm32_isr(const struct device *dev) async_timer_start(&data->dma_rx.timeout_work, data->dma_rx.timeout); } - } else if (LL_USART_IsEnabledIT_TC(config->usart) && - LL_USART_IsActiveFlag_TC(config->usart)) { + } else if (LL_USART_IsEnabledIT_TC(usart) && + LL_USART_IsActiveFlag_TC(usart)) { - LL_USART_DisableIT_TC(config->usart); + LL_USART_DisableIT_TC(usart); /* Generate TX_DONE event when transmission is done */ async_evt_tx_done(data); #ifdef CONFIG_PM uart_stm32_pm_policy_state_lock_put(dev); #endif - } else if (LL_USART_IsEnabledIT_RXNE(config->usart) && - LL_USART_IsActiveFlag_RXNE(config->usart)) { + } else if (LL_USART_IsEnabledIT_RXNE(usart) && + LL_USART_IsActiveFlag_RXNE(usart)) { #ifdef USART_SR_RXNE /* clear the RXNE flag, because Rx data was not read */ - LL_USART_ClearFlag_RXNE(config->usart); + LL_USART_ClearFlag_RXNE(usart); #else /* clear the RXNE by flushing the fifo, because Rx data was not read */ - LL_USART_RequestRxDataFlush(config->usart); + LL_USART_RequestRxDataFlush(usart); #endif /* USART_SR_RXNE */ } @@ -1286,12 +1304,12 @@ static void uart_stm32_isr(const struct device *dev) #if defined(CONFIG_PM) && defined(IS_UART_WAKEUP_FROMSTOP_INSTANCE) \ && defined(USART_CR3_WUFIE) - if (LL_USART_IsEnabledIT_WKUP(config->usart) && - LL_USART_IsActiveFlag_WKUP(config->usart)) { + if (LL_USART_IsEnabledIT_WKUP(usart) && + LL_USART_IsActiveFlag_WKUP(usart)) { - LL_USART_ClearFlag_WKUP(config->usart); + LL_USART_ClearFlag_WKUP(usart); #ifdef USART_ISR_REACK - while (LL_USART_IsActiveFlag_REACK(config->usart) == 0) { + while (LL_USART_IsActiveFlag_REACK(usart) == 0) { } #endif } @@ -1301,6 +1319,32 @@ static void uart_stm32_isr(const struct device *dev) #ifdef CONFIG_UART_ASYNC_API +#ifdef CONFIG_DCACHE +static bool buf_in_nocache(uintptr_t buf, size_t len_bytes) +{ + bool buf_within_nocache = false; + +#ifdef CONFIG_NOCACHE_MEMORY + buf_within_nocache = (buf >= ((uintptr_t)_nocache_ram_start)) && + ((buf + len_bytes - 1) <= ((uintptr_t)_nocache_ram_end)); + if (buf_within_nocache) { + return true; + } +#endif /* CONFIG_NOCACHE_MEMORY */ + + buf_within_nocache = mem_attr_check_buf( + (void *)buf, len_bytes, DT_MEM_ARM_MPU_RAM_NOCACHE) == 0; + if (buf_within_nocache) { + return true; + } + + buf_within_nocache = (buf >= ((uintptr_t)__rodata_region_start)) && + ((buf + len_bytes - 1) <= ((uintptr_t)__rodata_region_end)); + + return buf_within_nocache; +} +#endif /* CONFIG_DCACHE */ + static int uart_stm32_async_callback_set(const struct device *dev, uart_callback_t callback, void *user_data) @@ -1362,6 +1406,7 @@ static inline void uart_stm32_dma_rx_disable(const struct device *dev) static int uart_stm32_async_rx_disable(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; struct uart_event disabled_event = { .type = UART_RX_DISABLED @@ -1372,7 +1417,7 @@ static int uart_stm32_async_rx_disable(const struct device *dev) return -EFAULT; } - LL_USART_DisableIT_IDLE(config->usart); + LL_USART_DisableIT_IDLE(usart); uart_stm32_dma_rx_flush(dev); @@ -1396,7 +1441,7 @@ static int uart_stm32_async_rx_disable(const struct device *dev) data->rx_next_buffer_len = 0; /* When async rx is disabled, enable interruptible instance of uart to function normally */ - LL_USART_EnableIT_RXNE(config->usart); + LL_USART_EnableIT_RXNE(usart); LOG_DBG("rx: disabled"); @@ -1432,6 +1477,7 @@ void uart_stm32_dma_tx_cb(const struct device *dma_dev, void *user_data, static void uart_stm32_dma_replace_buffer(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; /* Replace the buffer and reload the DMA */ @@ -1454,7 +1500,7 @@ static void uart_stm32_dma_replace_buffer(const struct device *dev) dma_start(data->dma_rx.dma_dev, data->dma_rx.dma_channel); - LL_USART_ClearFlag_IDLE(config->usart); + LL_USART_ClearFlag_IDLE(usart); /* Request next buffer */ async_evt_rx_buf_request(data); @@ -1501,6 +1547,7 @@ static int uart_stm32_async_tx(const struct device *dev, const uint8_t *tx_data, size_t buf_size, int32_t timeout) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; int ret; @@ -1512,6 +1559,13 @@ static int uart_stm32_async_tx(const struct device *dev, return -EBUSY; } +#ifdef CONFIG_DCACHE + if (!buf_in_nocache((uintptr_t)tx_data, buf_size)) { + LOG_ERR("Tx buffer should be placed in a nocache memory region"); + return -EFAULT; + } +#endif /* CONFIG_DCACHE */ + data->dma_tx.buffer = (uint8_t *)tx_data; data->dma_tx.buffer_length = buf_size; data->dma_tx.timeout = timeout; @@ -1519,10 +1573,10 @@ static int uart_stm32_async_tx(const struct device *dev, LOG_DBG("tx: l=%d", data->dma_tx.buffer_length); /* Clear TC flag */ - LL_USART_ClearFlag_TC(config->usart); + LL_USART_ClearFlag_TC(usart); /* Enable TC interrupt so we can signal correct TX done */ - LL_USART_EnableIT_TC(config->usart); + LL_USART_EnableIT_TC(usart); /* set source address */ data->dma_tx.blk_cfg.source_address = (uint32_t)data->dma_tx.buffer; @@ -1560,6 +1614,7 @@ static int uart_stm32_async_rx_enable(const struct device *dev, uint8_t *rx_buf, size_t buf_size, int32_t timeout) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; int ret; @@ -1572,6 +1627,13 @@ static int uart_stm32_async_rx_enable(const struct device *dev, return -EBUSY; } +#ifdef CONFIG_DCACHE + if (!buf_in_nocache((uintptr_t)rx_buf, buf_size)) { + LOG_ERR("Rx buffer should be placed in a nocache memory region"); + return -EFAULT; + } +#endif /* CONFIG_DCACHE */ + data->dma_rx.offset = 0; data->dma_rx.buffer = rx_buf; data->dma_rx.buffer_length = buf_size; @@ -1579,7 +1641,7 @@ static int uart_stm32_async_rx_enable(const struct device *dev, data->dma_rx.timeout = timeout; /* Disable RX interrupts to let DMA to handle it */ - LL_USART_DisableIT_RXNE(config->usart); + LL_USART_DisableIT_RXNE(usart); data->dma_rx.blk_cfg.block_size = buf_size; data->dma_rx.blk_cfg.dest_address = (uint32_t)data->dma_rx.buffer; @@ -1599,9 +1661,9 @@ static int uart_stm32_async_rx_enable(const struct device *dev, /* Flush RX data buffer */ #ifdef USART_SR_RXNE - LL_USART_ClearFlag_RXNE(config->usart); + LL_USART_ClearFlag_RXNE(usart); #else - LL_USART_RequestRxDataFlush(config->usart); + LL_USART_RequestRxDataFlush(usart); #endif /* USART_SR_RXNE */ /* Enable RX DMA requests */ @@ -1610,10 +1672,10 @@ static int uart_stm32_async_rx_enable(const struct device *dev, /* Enable IRQ IDLE to define the end of a * RX DMA transaction. */ - LL_USART_ClearFlag_IDLE(config->usart); - LL_USART_EnableIT_IDLE(config->usart); + LL_USART_ClearFlag_IDLE(usart); + LL_USART_EnableIT_IDLE(usart); - LL_USART_EnableIT_ERROR(config->usart); + LL_USART_EnableIT_ERROR(usart); /* Request next buffer */ async_evt_rx_buf_request(data); @@ -1696,6 +1758,12 @@ static int uart_stm32_async_rx_buf_rsp(const struct device *dev, uint8_t *buf, } else if (!data->dma_rx.enabled) { err = -EACCES; } else { +#ifdef CONFIG_DCACHE + if (!buf_in_nocache((uintptr_t)buf, len)) { + LOG_ERR("Rx buffer should be placed in a nocache memory region"); + return -EFAULT; + } +#endif /* CONFIG_DCACHE */ data->rx_next_buffer = buf; data->rx_next_buffer_len = len; } @@ -1708,6 +1776,7 @@ static int uart_stm32_async_rx_buf_rsp(const struct device *dev, uint8_t *buf, static int uart_stm32_async_init(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; data->uart_dev = dev; @@ -1741,10 +1810,10 @@ static int uart_stm32_async_init(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32F4X) || \ defined(CONFIG_SOC_SERIES_STM32L1X) data->dma_rx.blk_cfg.source_address = - LL_USART_DMA_GetRegAddr(config->usart); + LL_USART_DMA_GetRegAddr(usart); #else data->dma_rx.blk_cfg.source_address = - LL_USART_DMA_GetRegAddr(config->usart, + LL_USART_DMA_GetRegAddr(usart, LL_USART_DMA_REG_DATA_RECEIVE); #endif @@ -1780,10 +1849,10 @@ static int uart_stm32_async_init(const struct device *dev) defined(CONFIG_SOC_SERIES_STM32F4X) || \ defined(CONFIG_SOC_SERIES_STM32L1X) data->dma_tx.blk_cfg.dest_address = - LL_USART_DMA_GetRegAddr(config->usart); + LL_USART_DMA_GetRegAddr(usart); #else data->dma_tx.blk_cfg.dest_address = - LL_USART_DMA_GetRegAddr(config->usart, + LL_USART_DMA_GetRegAddr(usart, LL_USART_DMA_REG_DATA_TRANSMIT); #endif @@ -1915,10 +1984,11 @@ static int uart_stm32_clocks_enable(const struct device *dev) static int uart_stm32_registers_configure(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; struct uart_stm32_data *data = dev->data; struct uart_config *uart_cfg = data->uart_cfg; - LL_USART_Disable(config->usart); + LL_USART_Disable(usart); if (!device_is_ready(config->reset.dev)) { LOG_ERR("reset controller not ready"); @@ -1929,55 +1999,54 @@ static int uart_stm32_registers_configure(const struct device *dev) (void)reset_line_toggle_dt(&config->reset); /* TX/RX direction */ - LL_USART_SetTransferDirection(config->usart, - LL_USART_DIRECTION_TX_RX); + LL_USART_SetTransferDirection(usart, LL_USART_DIRECTION_TX_RX); /* Set basic parameters, such as data-/stop-bit, parity, and baudrate */ uart_stm32_parameters_set(dev, uart_cfg); /* Enable the single wire / half-duplex mode */ if (config->single_wire) { - LL_USART_EnableHalfDuplex(config->usart); + LL_USART_EnableHalfDuplex(usart); } #ifdef LL_USART_TXRX_SWAPPED if (config->tx_rx_swap) { - LL_USART_SetTXRXSwap(config->usart, LL_USART_TXRX_SWAPPED); + LL_USART_SetTXRXSwap(usart, LL_USART_TXRX_SWAPPED); } #endif #ifdef LL_USART_RXPIN_LEVEL_INVERTED if (config->rx_invert) { - LL_USART_SetRXPinLevel(config->usart, LL_USART_RXPIN_LEVEL_INVERTED); + LL_USART_SetRXPinLevel(usart, LL_USART_RXPIN_LEVEL_INVERTED); } #endif #ifdef LL_USART_TXPIN_LEVEL_INVERTED if (config->tx_invert) { - LL_USART_SetTXPinLevel(config->usart, LL_USART_TXPIN_LEVEL_INVERTED); + LL_USART_SetTXPinLevel(usart, LL_USART_TXPIN_LEVEL_INVERTED); } #endif #if HAS_DRIVER_ENABLE if (config->de_enable) { - if (!IS_UART_DRIVER_ENABLE_INSTANCE(config->usart)) { + if (!IS_UART_DRIVER_ENABLE_INSTANCE(usart)) { LOG_ERR("%s does not support driver enable", dev->name); return -EINVAL; } uart_stm32_set_driver_enable(dev, true); - LL_USART_SetDEAssertionTime(config->usart, config->de_assert_time); - LL_USART_SetDEDeassertionTime(config->usart, config->de_deassert_time); + LL_USART_SetDEAssertionTime(usart, config->de_assert_time); + LL_USART_SetDEDeassertionTime(usart, config->de_deassert_time); if (config->de_invert) { - LL_USART_SetDESignalPolarity(config->usart, LL_USART_DE_POLARITY_LOW); + LL_USART_SetDESignalPolarity(usart, LL_USART_DE_POLARITY_LOW); } } #endif #ifdef USART_CR1_FIFOEN if (config->fifo_enable) { - LL_USART_EnableFIFO(config->usart); + LL_USART_EnableFIFO(usart); } #endif @@ -1989,11 +2058,11 @@ static int uart_stm32_registers_configure(const struct device *dev) * CONFIG_PM_DEVICE=y : Controlled by pm_device_wakeup_enable() */ #ifdef USART_CR3_WUFIE - LL_USART_SetWKUPType(config->usart, LL_USART_WAKEUP_ON_RXNE); - LL_USART_EnableIT_WKUP(config->usart); - LL_USART_ClearFlag_WKUP(config->usart); + LL_USART_SetWKUPType(usart, LL_USART_WAKEUP_ON_RXNE); + LL_USART_EnableIT_WKUP(usart); + LL_USART_ClearFlag_WKUP(usart); #endif - LL_USART_EnableInStopMode(config->usart); + LL_USART_EnableInStopMode(usart); if (config->wakeup_line != STM32_EXTI_LINE_NONE) { /* Prepare the WAKEUP with the expected EXTI line */ @@ -2002,17 +2071,17 @@ static int uart_stm32_registers_configure(const struct device *dev) } #endif /* CONFIG_PM */ - LL_USART_Enable(config->usart); + LL_USART_Enable(usart); #ifdef USART_ISR_TEACK /* Wait until TEACK flag is set */ - while (!(LL_USART_IsActiveFlag_TEACK(config->usart))) { + while (!(LL_USART_IsActiveFlag_TEACK(usart))) { } #endif /* !USART_ISR_TEACK */ #ifdef USART_ISR_REACK /* Wait until REACK flag is set */ - while (!(LL_USART_IsActiveFlag_REACK(config->usart))) { + while (!(LL_USART_IsActiveFlag_REACK(usart))) { } #endif /* !USART_ISR_REACK */ @@ -2067,21 +2136,22 @@ static int uart_stm32_init(const struct device *dev) static void uart_stm32_suspend_setup(const struct device *dev) { const struct uart_stm32_config *config = dev->config; + USART_TypeDef *usart = config->usart; #ifdef USART_ISR_BUSY /* Make sure that no USART transfer is on-going */ - while (LL_USART_IsActiveFlag_BUSY(config->usart) == 1) { + while (LL_USART_IsActiveFlag_BUSY(usart) == 1) { } #endif - while (LL_USART_IsActiveFlag_TC(config->usart) == 0) { + while (LL_USART_IsActiveFlag_TC(usart) == 0) { } #ifdef USART_ISR_REACK /* Make sure that USART is ready for reception */ - while (LL_USART_IsActiveFlag_REACK(config->usart) == 0) { + while (LL_USART_IsActiveFlag_REACK(usart) == 0) { } #endif /* Clear OVERRUN flag */ - LL_USART_ClearFlag_ORE(config->usart); + LL_USART_ClearFlag_ORE(usart); } static int uart_stm32_pm_action(const struct device *dev, diff --git a/drivers/smbus/smbus_handlers.c b/drivers/smbus/smbus_handlers.c index b9c45e76cf76b..77169fc662708 100644 --- a/drivers/smbus/smbus_handlers.c +++ b/drivers/smbus/smbus_handlers.c @@ -15,7 +15,7 @@ static inline int z_vrfy_smbus_configure(const struct device *dev, return z_impl_smbus_configure(dev, dev_config); } -#include +#include static inline int z_vrfy_smbus_get_config(const struct device *dev, uint32_t *dev_config) @@ -25,7 +25,7 @@ static inline int z_vrfy_smbus_get_config(const struct device *dev, return z_impl_smbus_get_config(dev, dev_config); } -#include +#include static inline int z_vrfy_smbus_quick(const struct device *dev, uint16_t addr, enum smbus_direction rw) @@ -34,7 +34,7 @@ static inline int z_vrfy_smbus_quick(const struct device *dev, uint16_t addr, return z_impl_smbus_quick(dev, addr, rw); } -#include +#include static inline int z_vrfy_smbus_byte_write(const struct device *dev, uint16_t addr, uint8_t byte) @@ -43,7 +43,7 @@ static inline int z_vrfy_smbus_byte_write(const struct device *dev, return z_impl_smbus_byte_write(dev, addr, byte); } -#include +#include static inline int z_vrfy_smbus_byte_read(const struct device *dev, uint16_t addr, uint8_t *byte) @@ -53,7 +53,7 @@ static inline int z_vrfy_smbus_byte_read(const struct device *dev, return z_impl_smbus_byte_read(dev, addr, byte); } -#include +#include static inline int z_vrfy_smbus_byte_data_write(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -63,7 +63,7 @@ static inline int z_vrfy_smbus_byte_data_write(const struct device *dev, return z_impl_smbus_byte_data_write(dev, addr, cmd, byte); } -#include +#include static inline int z_vrfy_smbus_byte_data_read(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -74,7 +74,7 @@ static inline int z_vrfy_smbus_byte_data_read(const struct device *dev, return z_impl_smbus_byte_data_read(dev, addr, cmd, byte); } -#include +#include static inline int z_vrfy_smbus_word_data_write(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -84,7 +84,7 @@ static inline int z_vrfy_smbus_word_data_write(const struct device *dev, return z_impl_smbus_word_data_write(dev, addr, cmd, word); } -#include +#include static inline int z_vrfy_smbus_word_data_read(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -95,7 +95,7 @@ static inline int z_vrfy_smbus_word_data_read(const struct device *dev, return z_impl_smbus_word_data_read(dev, addr, cmd, word); } -#include +#include static inline int z_vrfy_smbus_pcall(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -106,7 +106,7 @@ static inline int z_vrfy_smbus_pcall(const struct device *dev, return z_impl_smbus_pcall(dev, addr, cmd, send_word, recv_word); } -#include +#include static inline int z_vrfy_smbus_block_write(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -117,7 +117,7 @@ static inline int z_vrfy_smbus_block_write(const struct device *dev, return z_impl_smbus_block_write(dev, addr, cmd, count, buf); } -#include +#include static inline int z_vrfy_smbus_block_read(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -128,7 +128,7 @@ static inline int z_vrfy_smbus_block_read(const struct device *dev, return z_impl_smbus_block_read(dev, addr, cmd, count, buf); } -#include +#include static inline int z_vrfy_smbus_block_pcall(const struct device *dev, uint16_t addr, uint8_t cmd, @@ -142,7 +142,7 @@ static inline int z_vrfy_smbus_block_pcall(const struct device *dev, return z_impl_smbus_block_pcall(dev, addr, cmd, snd_count, snd_buf, rcv_count, rcv_buf); } -#include +#include static inline int z_vrfy_smbus_smbalert_remove_cb(const struct device *dev, struct smbus_callback *cb) @@ -151,7 +151,7 @@ static inline int z_vrfy_smbus_smbalert_remove_cb(const struct device *dev, return z_impl_smbus_smbalert_remove_cb(dev, cb); } -#include +#include static inline int z_vrfy_smbus_host_notify_remove_cb(const struct device *dev, struct smbus_callback *cb) @@ -160,4 +160,4 @@ static inline int z_vrfy_smbus_host_notify_remove_cb(const struct device *dev, return z_impl_smbus_host_notify_remove_cb(dev, cb); } -#include +#include diff --git a/drivers/spi/CMakeLists.txt b/drivers/spi/CMakeLists.txt index 840c9dcdc5f6d..07fb6a2455be6 100644 --- a/drivers/spi/CMakeLists.txt +++ b/drivers/spi/CMakeLists.txt @@ -45,6 +45,7 @@ zephyr_library_sources_ifdef(CONFIG_SPI_SMARTBOND spi_smartbond.c) zephyr_library_sources_ifdef(CONFIG_SPI_OPENTITAN spi_opentitan.c) zephyr_library_sources_ifdef(CONFIG_SPI_NUMAKER spi_numaker.c) zephyr_library_sources_ifdef(CONFIG_SPI_AMBIQ spi_ambiq.c) +zephyr_library_sources_ifdef(CONFIG_SPI_AMBIQ_BLEIF spi_ambiq_bleif.c) zephyr_library_sources_ifdef(CONFIG_SPI_RPI_PICO_PIO spi_rpi_pico_pio.c) zephyr_library_sources_ifdef(CONFIG_MSPI_AMBIQ mspi_ambiq.c) zephyr_library_sources_ifdef(CONFIG_SPI_MCHP_MSS spi_mchp_mss.c) @@ -55,3 +56,4 @@ zephyr_library_sources_ifdef(CONFIG_SPI_INFINEON_CAT1 spi_ifx_cat1.c) zephyr_library_sources_ifdef(CONFIG_SPI_SEDI spi_sedi.c) zephyr_library_sources_ifdef(CONFIG_SPI_NPCX_SPIP spi_npcx_spip.c) zephyr_library_sources_ifdef(CONFIG_SPI_GRLIB_SPIMCTRL spi_grlib_spimctrl.c) +zephyr_library_sources_ifdef(CONFIG_SPI_MAX32 spi_max32.c) diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9dc7908552f7e..b77b5a1e9ba27 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -156,4 +156,6 @@ source "drivers/spi/Kconfig.mchp_mss" source "drivers/spi/Kconfig.grlib_spimctrl" +source "drivers/spi/Kconfig.max32" + endif # SPI diff --git a/drivers/spi/Kconfig.ambiq b/drivers/spi/Kconfig.ambiq index 15eaf7463a46b..1a2499459881b 100644 --- a/drivers/spi/Kconfig.ambiq +++ b/drivers/spi/Kconfig.ambiq @@ -1,6 +1,7 @@ # Ambiq SDK SPI # # Copyright (c) 2023 Antmicro +# Copyright (c) 2024 Ambiq Micro Inc. # # SPDX-License-Identifier: Apache-2.0 # @@ -14,6 +15,19 @@ config SPI_AMBIQ help Enable driver for Ambiq SPI. +config SPI_AMBIQ_DMA + bool "AMBIQ APOLLO SPI DMA Support" + depends on SPI_AMBIQ + help + Enable DMA for Ambiq SPI. + +config SPI_DMA_TCB_BUFFER_SIZE + int "DMA Transfer Control Buffer size in words." + default 1024 + depends on SPI_AMBIQ_DMA + help + DMA Transfer Control Buffer size in words + config MSPI_AMBIQ bool "AMBIQ MSPI driver" default y @@ -22,3 +36,28 @@ config MSPI_AMBIQ select AMBIQ_HAL_USE_MSPI help Enable driver for Ambiq MSPI. + +config SPI_AMBIQ_BLEIF + bool "AMBIQ SPI-BLEIF driver" + default y + depends on DT_HAS_AMBIQ_SPI_BLEIF_ENABLED + select AMBIQ_HAL + select AMBIQ_HAL_USE_BLEIF + help + Enable driver for Ambiq Apollox Blue SOC (e.g. Apollo3 Blue) + which uses internal designed BLEIF module (different from the + general IOM module) for SPI transceiver. It is always used for + the Bluetooth HCI communication. + +if SPI_AMBIQ_BLEIF + +config SPI_AMBIQ_BLEIF_TIMING_TRACE + bool "Ambiq SPI-BLEIF timing trace" + help + The pins for the SPI transceiver are not exposed from the chips + and no need for user to confiugre them. But the chips design the + configurable BLEIF timing observation functions on other exposed + pins. The user can enable it to configure the pins for timing + trace purpose. + +endif # SPI_AMBIQ_BLEIF diff --git a/drivers/spi/Kconfig.max32 b/drivers/spi/Kconfig.max32 new file mode 100644 index 0000000000000..ca75a3725915d --- /dev/null +++ b/drivers/spi/Kconfig.max32 @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +config SPI_MAX32 + bool "MAX32 MCU SPI controller driver" + default y + depends on DT_HAS_ADI_MAX32_SPI_ENABLED + help + Enable SPI support on the MAX32 family of processors. + +if SPI_MAX32 + +config SPI_MAX32_INTERRUPT + bool "MAX32 MCU SPI Interrupt Support" + help + Enable interrupt support for MAX32 MCU SPI driver. + +endif # SPI_MAX32 diff --git a/drivers/spi/Kconfig.mcux_flexcomm b/drivers/spi/Kconfig.mcux_flexcomm index ff07a5ec03887..68ef16aa3e814 100644 --- a/drivers/spi/Kconfig.mcux_flexcomm +++ b/drivers/spi/Kconfig.mcux_flexcomm @@ -7,6 +7,7 @@ config SPI_MCUX_FLEXCOMM default y depends on DT_HAS_NXP_LPC_SPI_ENABLED select PINCTRL + select RESET help Enable support for mcux flexcomm spi driver. diff --git a/drivers/spi/Kconfig.psoc6 b/drivers/spi/Kconfig.psoc6 index 21b4bfe596bcd..5b7fe353d8190 100644 --- a/drivers/spi/Kconfig.psoc6 +++ b/drivers/spi/Kconfig.psoc6 @@ -8,5 +8,6 @@ config SPI_PSOC6 default y depends on DT_HAS_CYPRESS_PSOC6_SPI_ENABLED select USE_INFINEON_SPI + select PINCTRL help This option enables the SCB[SPI] driver for PSoC-6 SoC family. diff --git a/drivers/spi/Kconfig.smartbond b/drivers/spi/Kconfig.smartbond index 9c003eb915ddc..6198375003634 100644 --- a/drivers/spi/Kconfig.smartbond +++ b/drivers/spi/Kconfig.smartbond @@ -7,3 +7,13 @@ config SPI_SMARTBOND depends on DT_HAS_RENESAS_SMARTBOND_SPI_ENABLED help Enables SPI driver for Renesas SmartBond(tm) DA1469x series MCU. + +config SPI_SMARTBOND_DMA + bool "Renesas Smartbond(tm) SPI with DMA acceleration" + default y + depends on SPI_SMARTBOND + select DMA + help + Enables using the DMA engine instead of interrupt-driven + approach. This acceleration is available only for + asynchronous transfers. diff --git a/drivers/spi/spi_ambiq.c b/drivers/spi/spi_ambiq.c index 61d71e3f56716..3690816e205aa 100644 --- a/drivers/spi/spi_ambiq.c +++ b/drivers/spi/spi_ambiq.c @@ -28,20 +28,62 @@ struct spi_ambiq_config { uint32_t clock_freq; const struct pinctrl_dev_config *pcfg; ambiq_spi_pwr_func_t pwr_func; + void (*irq_config_func)(void); }; struct spi_ambiq_data { struct spi_context ctx; am_hal_iom_config_t iom_cfg; - void *IOMHandle; + void *iom_handler; + int inst_idx; }; -#define SPI_BASE (((const struct spi_ambiq_config *)(dev)->config)->base) -#define REG_STAT 0x248 -#define IDLE_STAT 0x4 -#define SPI_STAT(dev) (SPI_BASE + REG_STAT) +typedef void (*spi_context_update_trx)(struct spi_context *ctx, uint8_t dfs, uint32_t len); + #define SPI_WORD_SIZE 8 +#define SPI_CS_INDEX 3 + +#ifdef CONFIG_SPI_AMBIQ_DMA +static __aligned(32) struct { + __aligned(32) uint32_t buf[CONFIG_SPI_DMA_TCB_BUFFER_SIZE]; +} spi_dma_tcb_buf[DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT)] __attribute__((__section__(".nocache"))); + +static void spi_ambiq_callback(void *callback_ctxt, uint32_t status) +{ + const struct device *dev = callback_ctxt; + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + spi_context_complete(ctx, dev, (status == AM_HAL_STATUS_SUCCESS) ? 0 : -EIO); +} + +static void spi_ambiq_reset(const struct device *dev) +{ + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + /* cancel timed out transaction */ + am_hal_iom_disable(data->iom_handler); + /* NULL config to trigger reconfigure on next xfer */ + ctx->config = NULL; + /* signal any thread waiting on sync semaphore */ + spi_context_complete(ctx, dev, -ETIMEDOUT); + /* clean up for next xfer */ + k_sem_reset(&ctx->sync); +} +#endif + +static void spi_ambiq_isr(const struct device *dev) +{ + uint32_t ui32Status; + struct spi_ambiq_data *data = dev->data; + + am_hal_iom_interrupt_status_get(data->iom_handler, false, &ui32Status); + am_hal_iom_interrupt_clear(data->iom_handler, ui32Status); + am_hal_iom_interrupt_service(data->iom_handler, ui32Status); +} + static int spi_config(const struct device *dev, const struct spi_config *config) { struct spi_ambiq_data *data = dev->data; @@ -57,12 +99,7 @@ static int spi_config(const struct device *dev, const struct spi_config *config) return 0; } - if (config->operation & SPI_HALF_DUPLEX) { - LOG_ERR("Half-duplex not supported"); - return -ENOTSUP; - } - - if (SPI_WORD_SIZE_GET(config->operation) != 8) { + if (SPI_WORD_SIZE_GET(config->operation) != SPI_WORD_SIZE) { LOG_ERR("Word size must be %d", SPI_WORD_SIZE); return -ENOTSUP; } @@ -110,75 +147,224 @@ static int spi_config(const struct device *dev, const struct spi_config *config) return -ENOTSUP; } - data->iom_cfg.ui32ClockFreq = cfg->clock_freq; + /* Select slower of two: SPI bus frequency for SPI device or SPI master clock frequency */ + data->iom_cfg.ui32ClockFreq = + (config->frequency ? MIN(config->frequency, cfg->clock_freq) : cfg->clock_freq); ctx->config = config; +#ifdef CONFIG_SPI_AMBIQ_DMA + data->iom_cfg.pNBTxnBuf = spi_dma_tcb_buf[data->inst_idx].buf; + data->iom_cfg.ui32NBTxnBufLength = CONFIG_SPI_DMA_TCB_BUFFER_SIZE; +#endif + /* Disable IOM instance as it cannot be configured when enabled*/ - ret = am_hal_iom_disable(data->IOMHandle); + ret = am_hal_iom_disable(data->iom_handler); - ret = am_hal_iom_configure(data->IOMHandle, &data->iom_cfg); + ret = am_hal_iom_configure(data->iom_handler, &data->iom_cfg); - ret = am_hal_iom_enable(data->IOMHandle); + ret = am_hal_iom_enable(data->iom_handler); return ret; } -static int spi_ambiq_xfer(const struct device *dev, const struct spi_config *config) +static int spi_ambiq_xfer_half_duplex(const struct device *dev, am_hal_iom_dir_e dir, + am_hal_iom_transfer_t trans, bool cont) { struct spi_ambiq_data *data = dev->data; struct spi_context *ctx = &data->ctx; + bool is_last = false; + uint32_t rem_num, cur_num = 0; + size_t count = 0; int ret = 0; + spi_context_update_trx ctx_update; - am_hal_iom_transfer_t trans = {0}; - - if (ctx->tx_len) { - trans.ui64Instr = *ctx->tx_buf; - trans.ui32InstrLen = 1; - spi_context_update_tx(ctx, 1, 1); - - if (ctx->rx_buf != NULL) { - if (ctx->tx_len > 0) { - /* The instruction length can only be 0~5. */ - if (ctx->tx_len > 4) { - spi_context_complete(ctx, dev, 0); - return -ENOTSUP; + if (dir == AM_HAL_IOM_FULLDUPLEX) { + return -EINVAL; + } else if (dir == AM_HAL_IOM_RX) { + trans.eDirection = AM_HAL_IOM_RX; + count = ctx->rx_count; + ctx_update = spi_context_update_rx; + } else if (dir == AM_HAL_IOM_TX) { + trans.eDirection = AM_HAL_IOM_TX; + count = ctx->tx_count; + ctx_update = spi_context_update_tx; + } + /* Only instruction */ + if ((!count) && (trans.ui32InstrLen)) { + trans.bContinue = cont; +#ifdef CONFIG_SPI_AMBIQ_DMA + if (AM_HAL_STATUS_SUCCESS != + am_hal_iom_nonblocking_transfer(data->iom_handler, &trans, spi_ambiq_callback, + (void *)dev)) { + spi_ambiq_reset(dev); + return -EIO; + } + ret = spi_context_wait_for_completion(ctx); +#else + ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans); +#endif + } else { + for (size_t i = 0; i < count; i++) { + if (dir == AM_HAL_IOM_RX) { + rem_num = ctx->rx_len; + } else { + rem_num = ctx->tx_len; + } + while (rem_num) { + cur_num = (rem_num > AM_HAL_IOM_MAX_TXNSIZE_SPI) + ? AM_HAL_IOM_MAX_TXNSIZE_SPI + : rem_num; + if ((i == (count - 1)) && (cur_num == rem_num)) { + is_last = true; } - - /* Put the remaining TX data in instruction. */ - trans.ui32InstrLen += ctx->tx_len; - for (int i = 0; i < trans.ui32InstrLen - 1; i++) { - trans.ui64Instr = (trans.ui64Instr << 8) | (*ctx->tx_buf); - spi_context_update_tx(ctx, 1, 1); + trans.bContinue = (is_last == true) ? cont : true; + trans.ui32NumBytes = cur_num; + trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf; + trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf; +#ifdef CONFIG_SPI_AMBIQ_DMA + if (AM_HAL_STATUS_SUCCESS != + am_hal_iom_nonblocking_transfer( + data->iom_handler, &trans, + ((is_last == true) ? spi_ambiq_callback : NULL), + (void *)dev)) { + spi_ambiq_reset(dev); + return -EIO; + } + if (is_last) { + ret = spi_context_wait_for_completion(ctx); } +#else + ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans); +#endif + rem_num -= cur_num; + ctx_update(ctx, 1, cur_num); } + } + } - /* Set RX direction and hold CS to continue to receive data. */ - trans.eDirection = AM_HAL_IOM_RX; - trans.bContinue = true; - trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf; - trans.ui32NumBytes = ctx->rx_len; - ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); - } else if (ctx->tx_buf != NULL) { - /* Set TX direction to send data and release CS after transmission. */ + return ret; +} + +static int spi_ambiq_xfer_full_duplex(const struct device *dev, am_hal_iom_dir_e dir, + am_hal_iom_transfer_t trans, bool cont) +{ + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + bool trx_once = (ctx->tx_len == ctx->rx_len); + int ret = 0; + + if (dir != AM_HAL_IOM_FULLDUPLEX) { + return -EINVAL; + } + /* Tx and Rx length must be the same for am_hal_iom_spi_blocking_fullduplex */ + trans.eDirection = dir; + trans.ui32NumBytes = MIN(ctx->rx_len, ctx->tx_len); + trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf; + trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf; + trans.bContinue = (trx_once) ? cont : true; + spi_context_update_tx(ctx, 1, trans.ui32NumBytes); + spi_context_update_rx(ctx, 1, trans.ui32NumBytes); + + ret = am_hal_iom_spi_blocking_fullduplex(data->iom_handler, &trans); + + /* Transfer the remaining bytes */ + if (!trx_once) { + if (ctx->tx_len) { trans.eDirection = AM_HAL_IOM_TX; - trans.bContinue = false; trans.ui32NumBytes = ctx->tx_len; trans.pui32TxBuffer = (uint32_t *)ctx->tx_buf; - ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); + } else if (ctx->rx_len) { + trans.eDirection = AM_HAL_IOM_RX; + trans.ui32NumBytes = ctx->rx_len; + trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf; } + trans.bContinue = cont; + ret = am_hal_iom_blocking_transfer(data->iom_handler, &trans); + } + + return ret; +} + +static int spi_ambiq_fill_instruction(const struct device *dev, am_hal_iom_transfer_t *trans, + uint32_t len) +{ + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + int ret = 0; + + /* + * The instruction length can only be: + * 0~AM_HAL_IOM_MAX_OFFSETSIZE. + * split transaction if oversize + */ + if (trans->ui32InstrLen + len > AM_HAL_IOM_MAX_OFFSETSIZE) { + ret = spi_ambiq_xfer_half_duplex(dev, AM_HAL_IOM_TX, *trans, true); } else { - /* Set RX direction to receive data and release CS after transmission. */ - trans.ui64Instr = 0; - trans.ui32InstrLen = 0; - trans.eDirection = AM_HAL_IOM_RX; - trans.bContinue = false; - trans.pui32RxBuffer = (uint32_t *)ctx->rx_buf; - trans.ui32NumBytes = ctx->rx_len; - ret = am_hal_iom_blocking_transfer(data->IOMHandle, &trans); + trans->ui32InstrLen += len; + for (int i = 0; i < len; i++) { +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + trans->ui32Instr = (trans->ui32Instr << 8) | (*ctx->tx_buf); +#else + trans->ui64Instr = (trans->ui64Instr << 8) | (*ctx->tx_buf); +#endif + spi_context_update_tx(ctx, 1, 1); + } } + return ret; +} + +static int spi_ambiq_xfer(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + const struct spi_ambiq_config *cfg = dev->config; + struct spi_context *ctx = &data->ctx; + int ret = 0; + bool cont = (config->operation & SPI_HOLD_ON_CS) ? true : false; - spi_context_complete(ctx, dev, 0); + am_hal_iom_transfer_t trans = {0}; + /* TODO Need to get iom_nce from different nodes of spi */ +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + trans.uPeerInfo.ui32SpiChipSelect = cfg->pcfg->states->pins[SPI_CS_INDEX].iom_nce; +#else + trans.uPeerInfo.ui32SpiChipSelect = cfg->pcfg->states->pins[SPI_CS_INDEX].iom_nce % 4; +#endif + + /* There's data to send */ + if (spi_context_tx_on(ctx)) { + /* Always put the first byte to instuction */ + ret = spi_ambiq_fill_instruction(dev, &trans, 1); + /* There's data to Receive */ + if (spi_context_rx_on(ctx)) { + /* Regard the first tx_buf as cmd if there are more than one buffer */ + if (ctx->rx_count > 1) { + ret = spi_ambiq_fill_instruction(dev, &trans, ctx->tx_len); + /* Skip the cmd buffer for rx. */ + spi_context_update_rx(ctx, 1, ctx->rx_len); + } + if ((!(config->operation & SPI_HALF_DUPLEX)) && (spi_context_tx_on(ctx))) { + ret = spi_ambiq_xfer_full_duplex(dev, AM_HAL_IOM_FULLDUPLEX, trans, + cont); + } else { + ret = spi_ambiq_xfer_half_duplex(dev, AM_HAL_IOM_RX, trans, + cont); + } + } else { /* There's no data to Receive */ + /* Regard the first tx_buf as cmd if there are more than one buffer */ + if (ctx->tx_count > 1) { + ret = spi_ambiq_fill_instruction(dev, &trans, ctx->tx_len); + } + ret = spi_ambiq_xfer_half_duplex(dev, AM_HAL_IOM_TX, trans, cont); + } + } else { /* There's no data to send */ + ret = spi_ambiq_xfer_half_duplex(dev, AM_HAL_IOM_RX, trans, cont); + } + +#ifndef CONFIG_SPI_AMBIQ_DMA + if (!cont) { + spi_context_complete(ctx, dev, ret); + } +#endif return ret; } @@ -189,28 +375,39 @@ static int spi_ambiq_transceive(const struct device *dev, const struct spi_confi struct spi_ambiq_data *data = dev->data; int ret; + if (!tx_bufs && !rx_bufs) { + return 0; + } + + /* context setup */ + spi_context_lock(&data->ctx, false, NULL, NULL, config); + ret = spi_config(dev, config); if (ret) { + spi_context_release(&data->ctx, ret); return ret; } - if (!tx_bufs && !rx_bufs) { - return 0; - } - spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); ret = spi_ambiq_xfer(dev, config); + spi_context_release(&data->ctx, ret); + return ret; } static int spi_ambiq_release(const struct device *dev, const struct spi_config *config) { struct spi_ambiq_data *data = dev->data; + am_hal_iom_status_t iom_status; + + am_hal_iom_status_get(data->iom_handler, &iom_status); - if (!sys_read32(SPI_STAT(dev))) { + if ((iom_status.bStatIdle != IOM0_STATUS_IDLEST_IDLE) || + (iom_status.bStatCmdAct == IOM0_STATUS_CMDACT_ACTIVE) || + (iom_status.ui32NumPendTransactions)) { return -EBUSY; } @@ -228,14 +425,33 @@ static int spi_ambiq_init(const struct device *dev) { struct spi_ambiq_data *data = dev->data; const struct spi_ambiq_config *cfg = dev->config; - int ret; + int ret = 0; - ret = am_hal_iom_initialize((cfg->base - REG_IOM_BASEADDR) / cfg->size, &data->IOMHandle); + if (AM_HAL_STATUS_SUCCESS != + am_hal_iom_initialize((cfg->base - REG_IOM_BASEADDR) / cfg->size, &data->iom_handler)) { + LOG_ERR("Fail to initialize SPI\n"); + return -ENXIO; + } ret = cfg->pwr_func(); - ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + ret |= pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + LOG_ERR("Fail to config SPI pins\n"); + goto end; + } +#ifdef CONFIG_SPI_AMBIQ_DMA + am_hal_iom_interrupt_clear(data->iom_handler, AM_HAL_IOM_INT_CQUPD | AM_HAL_IOM_INT_ERR); + am_hal_iom_interrupt_enable(data->iom_handler, AM_HAL_IOM_INT_CQUPD | AM_HAL_IOM_INT_ERR); + cfg->irq_config_func(); +#endif +end: + if (ret < 0) { + am_hal_iom_uninitialize(data->iom_handler); + } else { + spi_context_unlock_unconditionally(&data->ctx); + } return ret; } @@ -249,14 +465,21 @@ static int spi_ambiq_init(const struct device *dev) k_busy_wait(PWRCTRL_MAX_WAIT_US); \ return 0; \ } \ + static void spi_irq_config_func_##n(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), spi_ambiq_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + }; \ static struct spi_ambiq_data spi_ambiq_data##n = { \ SPI_CONTEXT_INIT_LOCK(spi_ambiq_data##n, ctx), \ - SPI_CONTEXT_INIT_SYNC(spi_ambiq_data##n, ctx)}; \ + SPI_CONTEXT_INIT_SYNC(spi_ambiq_data##n, ctx), .inst_idx = n}; \ static const struct spi_ambiq_config spi_ambiq_config##n = { \ .base = DT_INST_REG_ADDR(n), \ .size = DT_INST_REG_SIZE(n), \ .clock_freq = DT_INST_PROP(n, clock_frequency), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .irq_config_func = spi_irq_config_func_##n, \ .pwr_func = pwr_on_ambiq_spi_##n}; \ DEVICE_DT_INST_DEFINE(n, spi_ambiq_init, NULL, &spi_ambiq_data##n, &spi_ambiq_config##n, \ POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, &spi_ambiq_driver_api); diff --git a/drivers/spi/spi_ambiq_bleif.c b/drivers/spi/spi_ambiq_bleif.c new file mode 100644 index 0000000000000..ceaf598455ded --- /dev/null +++ b/drivers/spi/spi_ambiq_bleif.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2024 Ambiq Micro Inc. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Some Ambiq Apollox Blue SOC (e.g. Apollo3 Blue) uses internal designed BLEIF module which is + * different from the general IOM module for SPI transceiver. The called HAL API will also be + * independent. This driver is implemented for the BLEIF module usage scenarios. + */ + +#define DT_DRV_COMPAT ambiq_spi_bleif + +#include +LOG_MODULE_REGISTER(spi_ambiq_bleif); + +#include +#include +#include +#include +#include +#include +#include "spi_context.h" +#include + +#define PWRCTRL_MAX_WAIT_US 5 + +typedef int (*ambiq_spi_pwr_func_t)(void); + +struct spi_ambiq_config { + uint32_t base; + int size; + const struct pinctrl_dev_config *pcfg; + ambiq_spi_pwr_func_t pwr_func; +}; + +struct spi_ambiq_data { + struct spi_context ctx; + am_hal_ble_config_t ble_cfg; + void *BLEhandle; +}; + +#define SPI_BASE (((const struct spi_ambiq_config *)(dev)->config)->base) +#define REG_STAT 0x268 +#define SPI_STAT(dev) (SPI_BASE + REG_STAT) +#define SPI_WORD_SIZE 8 + +static int spi_config(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &(data->ctx); + + int ret = 0; + + if (spi_context_configured(ctx, config)) { + /* Already configured. No need to do it again. */ + return 0; + } + + if (SPI_WORD_SIZE_GET(config->operation) != SPI_WORD_SIZE) { + LOG_ERR("Word size must be %d", SPI_WORD_SIZE); + return -ENOTSUP; + } + + if ((config->operation & SPI_LINES_MASK) != SPI_LINES_SINGLE) { + LOG_ERR("Only supports single mode"); + return -ENOTSUP; + } + + if (config->operation & SPI_LOCK_ON) { + LOG_ERR("Lock On not supported"); + return -ENOTSUP; + } + + if (config->operation & SPI_TRANSFER_LSB) { + LOG_ERR("LSB first not supported"); + return -ENOTSUP; + } + + if (config->operation & SPI_OP_MODE_SLAVE) { + LOG_ERR("Slave mode not supported"); + return -ENOTSUP; + } + if (config->operation & SPI_MODE_LOOP) { + LOG_ERR("Loopback mode not supported"); + return -ENOTSUP; + } + + /* We consider only the default configuration defined in HAL is tested and stable. */ + data->ble_cfg = am_hal_ble_default_config; + + ctx->config = config; + + ret = am_hal_ble_config(data->BLEhandle, &data->ble_cfg); + + return ret; +} + +static int spi_ambiq_xfer(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + int ret = 0; + + am_hal_ble_transfer_t trans = {0}; + + if (ctx->tx_len) { + trans.ui8Command = AM_HAL_BLE_WRITE; + trans.pui32Data = (uint32_t *)ctx->tx_buf; + trans.ui16Length = ctx->tx_len; + trans.bContinue = false; + } else { + trans.ui8Command = AM_HAL_BLE_READ; + trans.pui32Data = (uint32_t *)ctx->rx_buf; + trans.ui16Length = ctx->rx_len; + trans.bContinue = false; + } + + ret = am_hal_ble_blocking_transfer(data->BLEhandle, &trans); + spi_context_complete(ctx, dev, 0); + + return ret; +} + +static int spi_ambiq_transceive(const struct device *dev, const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs) +{ + struct spi_ambiq_data *data = dev->data; + int ret; + + ret = spi_config(dev, config); + + if (ret) { + return ret; + } + + if (!tx_bufs && !rx_bufs) { + return 0; + } + + spi_context_buffers_setup(&data->ctx, tx_bufs, rx_bufs, 1); + + ret = spi_ambiq_xfer(dev, config); + + return ret; +} + +static int spi_ambiq_release(const struct device *dev, const struct spi_config *config) +{ + struct spi_ambiq_data *data = dev->data; + + if (!sys_read32(SPI_STAT(dev))) { + return -EBUSY; + } + + spi_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static struct spi_driver_api spi_ambiq_driver_api = { + .transceive = spi_ambiq_transceive, + .release = spi_ambiq_release, +}; + +static int spi_ambiq_init(const struct device *dev) +{ + struct spi_ambiq_data *data = dev->data; + const struct spi_ambiq_config *cfg = dev->config; + int ret; + +#if defined(CONFIG_SPI_AMBIQ_BLEIF_TIMING_TRACE) + ret = pinctrl_apply_state(cfg->pcfg, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } +#endif /* CONFIG_SPI_AMBIQ_BLEIF_TIMING_TRACE */ + + ret = am_hal_ble_initialize((cfg->base - REG_BLEIF_BASEADDR) / cfg->size, &data->BLEhandle); + if (ret) { + return ret; + } + + ret = am_hal_ble_power_control(data->BLEhandle, AM_HAL_BLE_POWER_ACTIVE); + if (ret) { + return ret; + } + + ret = cfg->pwr_func(); + + return ret; +} + +#define AMBIQ_SPI_BLEIF_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ + static int pwr_on_ambiq_spi_##n(void) \ + { \ + uint32_t addr = DT_REG_ADDR(DT_INST_PHANDLE(n, ambiq_pwrcfg)) + \ + DT_INST_PHA(n, ambiq_pwrcfg, offset); \ + sys_write32((sys_read32(addr) | DT_INST_PHA(n, ambiq_pwrcfg, mask)), addr); \ + k_busy_wait(PWRCTRL_MAX_WAIT_US); \ + return 0; \ + } \ + static struct spi_ambiq_data spi_ambiq_data##n = { \ + SPI_CONTEXT_INIT_LOCK(spi_ambiq_data##n, ctx), \ + SPI_CONTEXT_INIT_SYNC(spi_ambiq_data##n, ctx)}; \ + static const struct spi_ambiq_config spi_ambiq_config##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .size = DT_INST_REG_SIZE(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .pwr_func = pwr_on_ambiq_spi_##n}; \ + DEVICE_DT_INST_DEFINE(n, spi_ambiq_init, NULL, &spi_ambiq_data##n, &spi_ambiq_config##n, \ + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, &spi_ambiq_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(AMBIQ_SPI_BLEIF_INIT) diff --git a/drivers/spi/spi_bitbang.c b/drivers/spi/spi_bitbang.c index cffd25abd9a0a..15ab576a139a8 100644 --- a/drivers/spi/spi_bitbang.c +++ b/drivers/spi/spi_bitbang.c @@ -177,22 +177,22 @@ static int spi_bitbang_transceive(const struct device *dev, k_busy_wait(wait_us); - /* first clock edge */ - gpio_pin_set_dt(&info->clk_gpio, !clock_state); - if (!loop && do_read && !cpha) { b = gpio_pin_get_dt(miso); } - k_busy_wait(wait_us); + /* first (leading) clock edge */ + gpio_pin_set_dt(&info->clk_gpio, !clock_state); - /* second clock edge */ - gpio_pin_set_dt(&info->clk_gpio, clock_state); + k_busy_wait(wait_us); if (!loop && do_read && cpha) { b = gpio_pin_get_dt(miso); } + /* second (trailing) clock edge */ + gpio_pin_set_dt(&info->clk_gpio, clock_state); + if (loop) { b = d; } diff --git a/drivers/spi/spi_esp32_spim.c b/drivers/spi/spi_esp32_spim.c index d209fd85b0486..229eff0007d72 100644 --- a/drivers/spi/spi_esp32_spim.c +++ b/drivers/spi/spi_esp32_spim.c @@ -17,10 +17,10 @@ LOG_MODULE_REGISTER(esp32_spi, CONFIG_SPI_LOG_LEVEL); #include #include #include -#ifndef CONFIG_SOC_SERIES_ESP32C3 -#include -#else +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include +#else +#include #endif #ifdef SOC_GDMA_SUPPORTED #include @@ -30,7 +30,7 @@ LOG_MODULE_REGISTER(esp32_spi, CONFIG_SPI_LOG_LEVEL); #include "spi_context.h" #include "spi_esp32_spim.h" -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t @@ -216,17 +216,35 @@ static int spi_esp32_init(const struct device *dev) int err; const struct spi_esp32_config *cfg = dev->config; struct spi_esp32_data *data = dev->data; + spi_hal_context_t *hal = &data->hal; if (!cfg->clock_dev) { return -EINVAL; } + if (!device_is_ready(cfg->clock_dev)) { + LOG_ERR("clock control device not ready"); + return -ENODEV; + } + + /* Enables SPI peripheral */ + err = clock_control_on(cfg->clock_dev, cfg->clock_subsys); + if (err < 0) { + LOG_ERR("Error enabling SPI clock"); + return err; + } + + spi_ll_master_init(hal->hw); + if (cfg->dma_enabled) { spi_esp32_init_dma(dev); } #ifdef CONFIG_SPI_ESP32_INTERRUPT - data->irq_line = esp_intr_alloc(cfg->irq_source, + spi_ll_disable_int(cfg->spi); + spi_ll_clear_int_stat(cfg->spi); + + esp_intr_alloc(cfg->irq_source, 0, (ISR_HANDLER)spi_esp32_isr, (void *)dev, @@ -285,19 +303,6 @@ static int IRAM_ATTR spi_esp32_configure(const struct device *dev, return 0; } - if (!device_is_ready(cfg->clock_dev)) { - LOG_ERR("clock control device not ready"); - return -ENODEV; - } - - /* enables SPI peripheral */ - if (clock_control_on(cfg->clock_dev, cfg->clock_subsys)) { - LOG_ERR("Could not enable SPI clock"); - return -EIO; - } - - spi_ll_master_init(hal->hw); - ctx->config = spi_cfg; if (spi_cfg->operation & SPI_HALF_DUPLEX) { @@ -372,10 +377,11 @@ static int IRAM_ATTR spi_esp32_configure(const struct device *dev, #endif /* - * Workaround for ESP32S3 and ESP32C3 SoC. This dummy transaction is needed to sync CLK and + * Workaround for ESP32S3 and ESP32Cx SoC. This dummy transaction is needed to sync CLK and * software controlled CS when SPI is in mode 3 */ -#if defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3) +#if defined(CONFIG_SOC_SERIES_ESP32S3) || defined(CONFIG_SOC_SERIES_ESP32C3) || \ + defined(CONFIG_SOC_SERIES_ESP32C6) if (ctx->num_cs_gpios && (hal_dev->mode & (SPI_MODE_CPOL | SPI_MODE_CPHA))) { spi_esp32_transfer(dev); } diff --git a/drivers/spi/spi_esp32_spim.h b/drivers/spi/spi_esp32_spim.h index b38c2aef8b318..03da08f6b3411 100644 --- a/drivers/spi/spi_esp32_spim.h +++ b/drivers/spi/spi_esp32_spim.h @@ -53,7 +53,6 @@ struct spi_esp32_data { spi_hal_dev_config_t dev_config; spi_hal_trans_config_t trans_config; uint8_t dfs; - int irq_line; lldesc_t dma_desc_tx; lldesc_t dma_desc_rx; uint32_t clock_source_hz; diff --git a/drivers/spi/spi_gecko.c b/drivers/spi/spi_gecko.c index d07485793b02f..3c79bdb4e2f1b 100644 --- a/drivers/spi/spi_gecko.c +++ b/drivers/spi/spi_gecko.c @@ -33,7 +33,10 @@ LOG_MODULE_REGISTER(spi_gecko); #define CLOCK_USART(id) _CONCAT(cmuClock_USART, id) #define GET_GECKO_USART_CLOCK(n) CLOCK_USART(DT_INST_PROP(n, peripheral_id)) #else -#if (USART_COUNT <= 2) +#if (USART_COUNT == 1) +#define CLOCK_USART(ref) (((ref) == USART0) ? cmuClock_USART0 \ + : -1) +#elif (USART_COUNT == 2) #define CLOCK_USART(ref) (((ref) == USART0) ? cmuClock_USART0 \ : ((ref) == USART1) ? cmuClock_USART1 \ : -1) @@ -81,6 +84,7 @@ struct spi_gecko_data { struct spi_gecko_config { USART_TypeDef *base; CMU_Clock_TypeDef clock; + uint32_t clock_frequency; #ifdef CONFIG_PINCTRL const struct pinctrl_dev_config *pcfg; #else @@ -101,6 +105,7 @@ static int spi_config(const struct device *dev, { const struct spi_gecko_config *gecko_config = dev->config; struct spi_gecko_data *data = dev->data; + uint32_t spi_frequency = CMU_ClockFreqGet(gecko_config->clock) / 2; if (config->operation & SPI_HALF_DUPLEX) { LOG_ERR("Half-duplex not supported"); @@ -138,6 +143,20 @@ static int spi_config(const struct device *dev, return -ENOTSUP; } + /* Set frequency to the minimum of what the device supports, what the + * user has configured the controller to, and the max frequency for the + * transaction. + */ + if (gecko_config->clock_frequency > spi_frequency) { + LOG_ERR("SPI clock-frequency too high"); + return -EINVAL; + } + spi_frequency = MIN(gecko_config->clock_frequency, spi_frequency); + if (config->frequency) { + spi_frequency = MIN(config->frequency, spi_frequency); + } + USART_BaudrateSyncSet(gecko_config->base, 0, spi_frequency); + /* Set Loopback */ if (config->operation & SPI_MODE_LOOP) { gecko_config->base->CTRL |= USART_CTRL_LOOPBK; @@ -377,7 +396,8 @@ static const struct spi_driver_api spi_gecko_api = { .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .base = (USART_TypeDef *) \ DT_INST_REG_ADDR(n), \ - .clock = GET_GECKO_USART_CLOCK(n) \ + .clock = GET_GECKO_USART_CLOCK(n), \ + .clock_frequency = DT_INST_PROP_OR(n, clock_frequency, 1000000) \ }; \ DEVICE_DT_INST_DEFINE(n, \ spi_gecko_init, \ @@ -398,6 +418,7 @@ static const struct spi_driver_api spi_gecko_api = { .base = (USART_TypeDef *) \ DT_INST_REG_ADDR(n), \ .clock = GET_GECKO_USART_CLOCK(n), \ + .clock_frequency = DT_INST_PROP_OR(n, clock_frequency, 1000000), \ .pin_rx = { DT_INST_PROP_BY_IDX(n, location_rx, 1), \ DT_INST_PROP_BY_IDX(n, location_rx, 2), \ gpioModeInput, 1}, \ diff --git a/drivers/spi/spi_handlers.c b/drivers/spi/spi_handlers.c index 68b362b5ed285..7d010a1e3e990 100644 --- a/drivers/spi/spi_handlers.c +++ b/drivers/spi/spi_handlers.c @@ -114,7 +114,7 @@ static inline int z_vrfy_spi_transceive(const struct device *dev, &tx_bufs_copy, &rx_bufs_copy); } -#include +#include static inline int z_vrfy_spi_release(const struct device *dev, const struct spi_config *config) @@ -123,4 +123,4 @@ static inline int z_vrfy_spi_release(const struct device *dev, K_OOPS(K_SYSCALL_DRIVER_SPI(dev, release)); return z_impl_spi_release((const struct device *)dev, config); } -#include +#include diff --git a/drivers/spi/spi_ll_stm32.c b/drivers/spi/spi_ll_stm32.c index 39ee5c2451ec6..70f42122cf4e1 100644 --- a/drivers/spi/spi_ll_stm32.c +++ b/drivers/spi/spi_ll_stm32.c @@ -20,6 +20,7 @@ LOG_MODULE_REGISTER(spi_ll_stm32); #include #include #include +#include #ifdef CONFIG_SPI_STM32_DMA #include #include @@ -82,6 +83,7 @@ static void spi_stm32_pm_policy_state_lock_get(const struct device *dev) if (IS_ENABLED(CONFIG_PM_S2RAM)) { pm_policy_state_lock_get(PM_STATE_SUSPEND_TO_RAM, PM_ALL_SUBSTATES); } + pm_device_runtime_get(dev); } } } @@ -93,6 +95,7 @@ static void spi_stm32_pm_policy_state_lock_put(const struct device *dev) if (data->pm_policy_state_on) { data->pm_policy_state_on = false; + pm_device_runtime_put(dev); pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_IDLE, PM_ALL_SUBSTATES); if (IS_ENABLED(CONFIG_PM_S2RAM)) { pm_policy_state_lock_put(PM_STATE_SUSPEND_TO_RAM, PM_ALL_SUBSTATES); @@ -119,31 +122,34 @@ static uint32_t bits2bytes(uint32_t bits) static __aligned(32) uint32_t dummy_rx_tx_buffer __nocache; /* This function is executed in the interrupt context */ -static void dma_callback(const struct device *dev, void *arg, +static void dma_callback(const struct device *dma_dev, void *arg, uint32_t channel, int status) { - /* arg directly holds the spi device */ - struct spi_stm32_data *data = arg; + ARG_UNUSED(dma_dev); + + /* arg holds SPI DMA data + * Passed in spi_stm32_dma_tx/rx_load() + */ + struct spi_stm32_data *spi_dma_data = arg; if (status < 0) { LOG_ERR("DMA callback error with channel %d.", channel); - data->status_flags |= SPI_STM32_DMA_ERROR_FLAG; + spi_dma_data->status_flags |= SPI_STM32_DMA_ERROR_FLAG; } else { /* identify the origin of this callback */ - if (channel == data->dma_tx.channel) { + if (channel == spi_dma_data->dma_tx.channel) { /* this part of the transfer ends */ - data->status_flags |= SPI_STM32_DMA_TX_DONE_FLAG; - } else if (channel == data->dma_rx.channel) { + spi_dma_data->status_flags |= SPI_STM32_DMA_TX_DONE_FLAG; + } else if (channel == spi_dma_data->dma_rx.channel) { /* this part of the transfer ends */ - data->status_flags |= SPI_STM32_DMA_RX_DONE_FLAG; + spi_dma_data->status_flags |= SPI_STM32_DMA_RX_DONE_FLAG; } else { - LOG_ERR("DMA callback channel %d is not valid.", - channel); - data->status_flags |= SPI_STM32_DMA_ERROR_FLAG; + LOG_ERR("DMA callback channel %d is not valid.", channel); + spi_dma_data->status_flags |= SPI_STM32_DMA_ERROR_FLAG; } } - k_sem_give(&data->status_sem); + k_sem_give(&spi_dma_data->status_sem); } static int spi_stm32_dma_tx_load(const struct device *dev, const uint8_t *buf, @@ -194,7 +200,7 @@ static int spi_stm32_dma_tx_load(const struct device *dev, const uint8_t *buf, /* direction is given by the DT */ stream->dma_cfg.head_block = blk_cfg; - /* give the client dev as arg, as the callback comes from the dma */ + /* give the dma channel data as arg, as the callback comes from the dma */ stream->dma_cfg.user_data = data; /* pass our client origin to the dma: data->dma_tx.dma_channel */ ret = dma_config(data->dma_tx.dma_dev, data->dma_tx.channel, @@ -460,7 +466,7 @@ static void spi_stm32_cs_control(const struct device *dev, bool on) LL_PWR_UnselectSUBGHZSPI_NSS(); } } -#endif +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_subghz) */ } static void spi_stm32_complete(const struct device *dev, int status) @@ -480,7 +486,7 @@ static void spi_stm32_complete(const struct device *dev, int status) } #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */ -#endif +#endif /* CONFIG_SPI_STM32_INTERRUPT */ #if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_fifo) @@ -488,7 +494,7 @@ static void spi_stm32_complete(const struct device *dev, int status) while (ll_func_rx_is_not_empty(spi)) { (void) LL_SPI_ReceiveData8(spi); } -#endif +#endif /* compat st_stm32_spi_fifo*/ if (LL_SPI_GetMode(spi) == LL_SPI_MODE_MASTER) { while (ll_func_spi_is_busy(spi)) { @@ -554,7 +560,7 @@ static void spi_stm32_isr(const struct device *dev) spi_stm32_complete(dev, err); } } -#endif +#endif /* CONFIG_SPI_STM32_INTERRUPT */ static int spi_stm32_configure(const struct device *dev, const struct spi_config *config) @@ -785,7 +791,7 @@ static int transceive(const struct device *dev, if (asynchronous) { return -ENOTSUP; } -#endif +#endif /* CONFIG_SPI_STM32_INTERRUPT */ spi_context_lock(&data->ctx, asynchronous, cb, userdata, config); @@ -821,7 +827,7 @@ static int transceive(const struct device *dev, while (ll_func_rx_is_not_empty(spi)) { (void) LL_SPI_ReceiveData8(spi); } -#endif +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_spi_fifo) */ LL_SPI_Enable(spi); @@ -839,13 +845,13 @@ static int transceive(const struct device *dev, } #endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) */ -#if CONFIG_SOC_SERIES_STM32H7X +#ifdef CONFIG_SOC_SERIES_STM32H7X /* * Add a small delay after enabling to prevent transfer stalling at high * system clock frequency (see errata sheet ES0392). */ k_busy_wait(WAIT_1US); -#endif +#endif /* CONFIG_SOC_SERIES_STM32H7X */ /* This is turned off in spi_stm32_complete(). */ spi_stm32_cs_control(dev, true); @@ -867,7 +873,7 @@ static int transceive(const struct device *dev, ll_func_enable_int_tx_empty(spi); ret = spi_context_wait_for_completion(&data->ctx); -#else +#else /* CONFIG_SPI_STM32_INTERRUPT */ do { ret = spi_stm32_shift_frames(cfg, data); } while (!ret && spi_stm32_transfer_ongoing(data)); @@ -880,7 +886,7 @@ static int transceive(const struct device *dev, } #endif /* CONFIG_SPI_SLAVE */ -#endif +#endif /* CONFIG_SPI_STM32_INTERRUPT */ end: spi_context_release(&data->ctx, ret); @@ -976,6 +982,7 @@ static int transceive_dma(const struct device *dev, struct spi_stm32_data *data = dev->data; SPI_TypeDef *spi = cfg->spi; int ret; + int err; if (!tx_bufs && !rx_bufs) { return 0; @@ -1059,7 +1066,7 @@ static int transceive_dma(const struct device *dev, #ifdef SPI_SR_FTLVL while (LL_SPI_GetTxFIFOLevel(spi) > 0) { } -#endif +#endif /* SPI_SR_FTLVL */ #ifdef CONFIG_SPI_STM32_ERRATA_BUSY WAIT_FOR(ll_func_spi_dma_busy(spi) != 0, @@ -1069,7 +1076,7 @@ static int transceive_dma(const struct device *dev, /* wait until spi is no more busy (spi TX fifo is really empty) */ while (ll_func_spi_dma_busy(spi) == 0) { } -#endif +#endif /* CONFIG_SPI_STM32_ERRATA_BUSY */ #if !DT_HAS_COMPAT_STATUS_OKAY(st_stm32h7_spi) /* toggle the DMA transfer request */ @@ -1092,8 +1099,14 @@ static int transceive_dma(const struct device *dev, LL_SPI_DisableDMAReq_TX(spi); LL_SPI_DisableDMAReq_RX(spi); - dma_stop(data->dma_rx.dma_dev, data->dma_rx.channel); - dma_stop(data->dma_tx.dma_dev, data->dma_tx.channel); + err = dma_stop(data->dma_rx.dma_dev, data->dma_rx.channel); + if (err) { + LOG_DBG("Rx dma_stop failed with error %d", err); + } + err = dma_stop(data->dma_tx.dma_dev, data->dma_tx.channel); + if (err) { + LOG_DBG("Tx dma_stop failed with error %d", err); + } #ifdef CONFIG_SPI_SLAVE if (spi_context_is_slave(&data->ctx) && !ret) { @@ -1156,7 +1169,7 @@ static inline bool spi_stm32_is_subghzspi(const struct device *dev) #else ARG_UNUSED(dev); return false; -#endif +#endif /* st_stm32_spi_subghz */ } static int spi_stm32_init(const struct device *dev) @@ -1198,7 +1211,7 @@ static int spi_stm32_init(const struct device *dev) #ifdef CONFIG_SPI_STM32_INTERRUPT cfg->irq_config(dev); -#endif +#endif /* CONFIG_SPI_STM32_INTERRUPT */ #ifdef CONFIG_SPI_STM32_DMA if ((data->dma_rx.dma_dev != NULL) && @@ -1224,7 +1237,7 @@ static int spi_stm32_init(const struct device *dev) spi_context_unlock_unconditionally(&data->ctx); - return 0; + return pm_device_runtime_enable(dev); } #ifdef CONFIG_PM_DEVICE @@ -1238,10 +1251,12 @@ static int spi_stm32_pm_action(const struct device *dev, switch (action) { case PM_DEVICE_ACTION_RESUME: - /* Set pins to active state */ - err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); - if (err < 0) { - return err; + if (!spi_stm32_is_subghzspi(dev)) { + /* Set pins to active state */ + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (err < 0) { + return err; + } } /* enable clock */ @@ -1255,21 +1270,24 @@ static int spi_stm32_pm_action(const struct device *dev, /* Stop device clock. */ err = clock_control_off(clk, (clock_control_subsys_t)&config->pclken[0]); if (err != 0) { - LOG_ERR("Could not enable SPI clock"); + LOG_ERR("Could not disable SPI clock"); return err; } - /* Move pins to sleep state */ - err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); - if ((err < 0) && (err != -ENOENT)) { - /* - * If returning -ENOENT, no pins where defined for sleep mode : - * Do not output on console (might sleep already) when going to sleep, - * "SPI pinctrl sleep state not available" - * and don't block PM suspend. - * Else return the error. - */ - return err; + if (!spi_stm32_is_subghzspi(dev)) { + /* Move pins to sleep state */ + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if ((err < 0) && (err != -ENOENT)) { + /* + * If returning -ENOENT, no pins where defined for sleep mode : + * Do not output on console (might sleep already) when going to + * sleep, + * "SPI pinctrl sleep state not available" + * and don't block PM suspend. + * Else return the error. + */ + return err; + } } break; default: @@ -1297,7 +1315,7 @@ static void spi_stm32_irq_config_func_##id(const struct device *dev) \ #define STM32_SPI_IRQ_HANDLER_DECL(id) #define STM32_SPI_IRQ_HANDLER_FUNC(id) #define STM32_SPI_IRQ_HANDLER(id) -#endif +#endif /* CONFIG_SPI_STM32_INTERRUPT */ #define SPI_DMA_CHANNEL_INIT(index, dir, dir_cap, src_dev, dest_dev) \ .dma_dev = DEVICE_DT_GET(STM32_DMA_CTLR(index, dir)), \ @@ -1325,7 +1343,7 @@ static void spi_stm32_irq_config_func_##id(const struct device *dev) \ STM32_DMA_FEATURES(index, dir)), \ -#if CONFIG_SPI_STM32_DMA +#ifdef CONFIG_SPI_STM32_DMA #define SPI_DMA_CHANNEL(id, dir, DIR, src, dest) \ .dma_##dir = { \ COND_CODE_1(DT_INST_DMAS_HAS_NAME(id, dir), \ @@ -1338,7 +1356,7 @@ static void spi_stm32_irq_config_func_##id(const struct device *dev) \ #else #define SPI_DMA_CHANNEL(id, dir, DIR, src, dest) #define SPI_DMA_STATUS_SEM(id) -#endif +#endif /* CONFIG_SPI_STM32_DMA */ #define SPI_SUPPORTS_FIFO(id) DT_INST_NODE_HAS_PROP(id, fifo_enable) #define SPI_GET_FIFO_PROP(id) DT_INST_PROP(id, fifo_enable) diff --git a/drivers/spi/spi_max32.c b/drivers/spi/spi_max32.c new file mode 100644 index 0000000000000..3dc6ecf18a4b4 --- /dev/null +++ b/drivers/spi/spi_max32.c @@ -0,0 +1,553 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT adi_max32_spi + +#include +#include +#include +#include +#include +#include +#include + +#include + +LOG_MODULE_REGISTER(spi_max32, CONFIG_SPI_LOG_LEVEL); +#include "spi_context.h" + +struct max32_spi_config { + mxc_spi_regs_t *regs; + const struct pinctrl_dev_config *pctrl; + const struct device *clock; + struct max32_perclk perclk; +#ifdef CONFIG_SPI_MAX32_INTERRUPT + void (*irq_config_func)(const struct device *dev); +#endif /* CONFIG_SPI_MAX32_INTERRUPT */ +}; + +/* Device run time data */ +struct max32_spi_data { + struct spi_context ctx; + const struct device *dev; + mxc_spi_req_t req; + uint8_t dummy[2]; +#ifdef CONFIG_SPI_ASYNC + struct k_work async_work; +#endif /* CONFIG_SPI_ASYNC */ +}; + +#ifdef CONFIG_SPI_MAX32_INTERRUPT +static void spi_max32_callback(mxc_spi_req_t *req, int error); +#endif /* CONFIG_SPI_MAX32_INTERRUPT */ + +static int spi_configure(const struct device *dev, const struct spi_config *config) +{ + int ret = 0; + const struct max32_spi_config *cfg = dev->config; + mxc_spi_regs_t *regs = cfg->regs; + struct max32_spi_data *data = dev->data; + + if (spi_context_configured(&data->ctx, config)) { + return 0; + } + + if (SPI_OP_MODE_GET(config->operation) & SPI_OP_MODE_SLAVE) { + return -ENOTSUP; + } + + int master_mode = 1; + int quad_mode = 0; + int num_slaves = 1; + int ss_polarity = (config->operation & SPI_CS_ACTIVE_HIGH) ? 1 : 0; + unsigned int spi_speed = (unsigned int)config->frequency; + + ret = Wrap_MXC_SPI_Init(regs, master_mode, quad_mode, num_slaves, ss_polarity, spi_speed); + if (ret) { + return ret; + } + + int cpol = (SPI_MODE_GET(config->operation) & SPI_MODE_CPOL) ? 1 : 0; + int cpha = (SPI_MODE_GET(config->operation) & SPI_MODE_CPHA) ? 1 : 0; + + if (cpol && cpha) { + ret = MXC_SPI_SetMode(regs, SPI_MODE_3); + } else if (cpha) { + ret = MXC_SPI_SetMode(regs, SPI_MODE_2); + } else if (cpol) { + ret = MXC_SPI_SetMode(regs, SPI_MODE_1); + } else { + ret = MXC_SPI_SetMode(regs, SPI_MODE_0); + } + if (ret) { + return ret; + } + + ret = MXC_SPI_SetDataSize(regs, SPI_WORD_SIZE_GET(config->operation)); + if (ret) { + return ret; + } + +#if defined(CONFIG_SPI_EXTENDED_MODES) + switch (config->operation & SPI_LINES_MASK) { + case SPI_LINES_QUAD: + ret = MXC_SPI_SetWidth(regs, SPI_WIDTH_QUAD); + break; + case SPI_LINES_DUAL: + ret = MXC_SPI_SetWidth(regs, SPI_WIDTH_DUAL); + break; + case SPI_LINES_OCTAL: + ret = -ENOTSUP; + break; + case SPI_LINES_SINGLE: + default: + ret = MXC_SPI_SetWidth(regs, SPI_WIDTH_STANDARD); + break; + } + + if (ret) { + return ret; + } +#endif + + data->ctx.config = config; + + return ret; +} + +static inline int spi_max32_get_dfs_shift(const struct spi_context *ctx) +{ + if (SPI_WORD_SIZE_GET(ctx->config->operation) < 9) { + return 0; + } + + return 1; +} + +static void spi_max32_setup(mxc_spi_regs_t *spi, mxc_spi_req_t *req) +{ + req->rxCnt = 0; + req->txCnt = 0; + + if (spi->ctrl0 & ADI_MAX32_SPI_CTRL_MASTER_MODE) { + MXC_SPI_SetSlave(spi, req->ssIdx); + } + + if (req->rxData && req->rxLen) { + MXC_SETFIELD(spi->ctrl1, MXC_F_SPI_CTRL1_RX_NUM_CHAR, + req->rxLen << MXC_F_SPI_CTRL1_RX_NUM_CHAR_POS); + spi->dma |= MXC_F_SPI_DMA_RX_FIFO_EN; + } else { + spi->ctrl1 &= ~MXC_F_SPI_CTRL1_RX_NUM_CHAR; + spi->dma &= ~MXC_F_SPI_DMA_RX_FIFO_EN; + } + + if (req->txLen) { + MXC_SETFIELD(spi->ctrl1, MXC_F_SPI_CTRL1_TX_NUM_CHAR, + req->txLen << MXC_F_SPI_CTRL1_TX_NUM_CHAR_POS); + spi->dma |= MXC_F_SPI_DMA_TX_FIFO_EN; + } else { + spi->ctrl1 &= ~MXC_F_SPI_CTRL1_TX_NUM_CHAR; + spi->dma &= ~MXC_F_SPI_DMA_TX_FIFO_EN; + } + + spi->dma |= (ADI_MAX32_SPI_DMA_TX_FIFO_CLEAR | ADI_MAX32_SPI_DMA_RX_FIFO_CLEAR); + spi->ctrl0 |= MXC_F_SPI_CTRL0_EN; + MXC_SPI_ClearFlags(spi); +} + +#ifndef CONFIG_SPI_MAX32_INTERRUPT +static int spi_max32_transceive_sync(mxc_spi_regs_t *spi, struct max32_spi_data *data, + uint8_t dfs_shift) +{ + int ret = 0; + mxc_spi_req_t *req = &data->req; + uint32_t remain, flags, tx_len, rx_len; + + MXC_SPI_ClearTXFIFO(spi); + MXC_SPI_ClearRXFIFO(spi); + + tx_len = req->txLen << dfs_shift; + rx_len = req->rxLen << dfs_shift; + do { + remain = tx_len - req->txCnt; + if (remain > 0) { + if (!data->req.txData) { + req->txCnt += MXC_SPI_WriteTXFIFO(spi, data->dummy, + MIN(remain, sizeof(data->dummy))); + } else { + req->txCnt += + MXC_SPI_WriteTXFIFO(spi, &req->txData[req->txCnt], remain); + } + if (!(spi->ctrl0 & MXC_F_SPI_CTRL0_START)) { + spi->ctrl0 |= MXC_F_SPI_CTRL0_START; + } + } + + if (req->rxCnt < rx_len) { + req->rxCnt += MXC_SPI_ReadRXFIFO(spi, &req->rxData[req->rxCnt], + rx_len - req->rxCnt); + } + } while ((req->txCnt < tx_len) || (req->rxCnt < rx_len)); + + do { + flags = MXC_SPI_GetFlags(spi); + } while (!(flags & ADI_MAX32_SPI_INT_FL_MST_DONE)); + MXC_SPI_ClearFlags(spi); + + return ret; +} +#endif /* CONFIG_SPI_MAX32_INTERRUPT */ + +static int spi_max32_transceive(const struct device *dev) +{ + int ret = 0; + const struct max32_spi_config *cfg = dev->config; + struct max32_spi_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + uint32_t len; + uint8_t dfs_shift; + + MXC_SPI_ClearTXFIFO(cfg->regs); + + dfs_shift = spi_max32_get_dfs_shift(ctx); + + len = spi_context_max_continuous_chunk(ctx); + data->req.txLen = len >> dfs_shift; + data->req.txData = (uint8_t *)ctx->tx_buf; + data->req.rxLen = len >> dfs_shift; + data->req.rxData = ctx->rx_buf; + + data->req.rxData = ctx->rx_buf; + data->req.rxLen = len >> dfs_shift; + if (!data->req.rxData) { + /* Pass a dummy buffer to HAL if receive buffer is NULL, otherwise + * corrupt data is read during subsequent transactions. + */ + data->req.rxData = data->dummy; + data->req.rxLen = 0; + } + data->req.spi = cfg->regs; + data->req.ssIdx = ctx->config->slave; + data->req.ssDeassert = 0; + data->req.txCnt = 0; + data->req.rxCnt = 0; + spi_max32_setup(cfg->regs, &data->req); +#ifdef CONFIG_SPI_MAX32_INTERRUPT + MXC_SPI_SetTXThreshold(cfg->regs, 1); + if (data->req.rxLen) { + MXC_SPI_SetRXThreshold(cfg->regs, 2); + MXC_SPI_EnableInt(cfg->regs, ADI_MAX32_SPI_INT_EN_RX_THD); + } + MXC_SPI_EnableInt(cfg->regs, ADI_MAX32_SPI_INT_EN_TX_THD | ADI_MAX32_SPI_INT_EN_MST_DONE); + + if (!data->req.txData) { + data->req.txCnt = + MXC_SPI_WriteTXFIFO(cfg->regs, data->dummy, MIN(len, sizeof(data->dummy))); + } else { + data->req.txCnt = MXC_SPI_WriteTXFIFO(cfg->regs, data->req.txData, len); + } + + MXC_SPI_StartTransmission(cfg->regs); +#else + ret = spi_max32_transceive_sync(cfg->regs, data, dfs_shift); + if (ret) { + ret = -EIO; + } else { + spi_context_update_tx(ctx, 1, len); + spi_context_update_rx(ctx, 1, len); + } +#endif + + return ret; +} + +static int transceive(const struct device *dev, const struct spi_config *config, + const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs, + bool async, spi_callback_t cb, void *userdata) +{ + int ret = 0; + const struct max32_spi_config *cfg = dev->config; + struct max32_spi_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + bool hw_cs_ctrl = true; + +#ifndef CONFIG_SPI_MAX32_INTERRUPT + if (async) { + return -ENOTSUP; + } +#endif + + spi_context_lock(ctx, async, cb, userdata, config); + + ret = spi_configure(dev, config); + if (ret != 0) { + spi_context_release(ctx, ret); + return -EIO; + } + + spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, 1); + + /* Check if CS GPIO exists */ + if (spi_cs_is_gpio(config)) { + hw_cs_ctrl = false; + } + MXC_SPI_HWSSControl(cfg->regs, hw_cs_ctrl); + + /* Assert the CS line if HW control disabled */ + if (!hw_cs_ctrl) { + spi_context_cs_control(ctx, true); + } else { + cfg->regs->ctrl0 = + (cfg->regs->ctrl0 & ~MXC_F_SPI_CTRL0_START) | MXC_F_SPI_CTRL0_SS_CTRL; + } + +#ifdef CONFIG_SPI_MAX32_INTERRUPT + do { + ret = spi_max32_transceive(dev); + if (!ret) { + ret = spi_context_wait_for_completion(ctx); + if (ret || async) { + break; + } + } else { + break; + } + } while ((spi_context_tx_on(ctx) || spi_context_rx_on(ctx))); +#else + do { + ret = spi_max32_transceive(dev); + if (ret) { + break; + } + } while (spi_context_tx_on(ctx) || spi_context_rx_on(ctx)); + +#endif /* CONFIG_SPI_MAX32_INTERRUPT */ + + /* Deassert the CS line if hw control disabled */ + if (!async) { + if (!hw_cs_ctrl) { + spi_context_cs_control(ctx, false); + } else { + cfg->regs->ctrl0 &= ~(MXC_F_SPI_CTRL0_START | MXC_F_SPI_CTRL0_SS_CTRL | + MXC_F_SPI_CTRL0_EN); + cfg->regs->ctrl0 |= MXC_F_SPI_CTRL0_EN; + } + } + + spi_context_release(ctx, ret); + + return ret; +} + +static int api_transceive(const struct device *dev, const struct spi_config *config, + const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs) +{ + return transceive(dev, config, tx_bufs, rx_bufs, false, NULL, NULL); +} + +#ifdef CONFIG_SPI_ASYNC +static int api_transceive_async(const struct device *dev, const struct spi_config *config, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, spi_callback_t cb, + void *userdata) +{ + return transceive(dev, config, tx_bufs, rx_bufs, true, cb, userdata); +} +#endif /* CONFIG_SPI_ASYNC */ + +#ifdef CONFIG_SPI_MAX32_INTERRUPT +static void spi_max32_callback(mxc_spi_req_t *req, int error) +{ + struct max32_spi_data *data = CONTAINER_OF(req, struct max32_spi_data, req); + struct spi_context *ctx = &data->ctx; + const struct device *dev = data->dev; + uint32_t len; + + len = spi_context_max_continuous_chunk(ctx); + spi_context_update_tx(ctx, 1, len); + spi_context_update_rx(ctx, 1, len); +#ifdef CONFIG_SPI_ASYNC + if (ctx->asynchronous && ((spi_context_tx_on(ctx) || spi_context_rx_on(ctx)))) { + k_work_submit(&data->async_work); + } else { + if (spi_cs_is_gpio(ctx->config)) { + spi_context_cs_control(ctx, false); + } else { + req->spi->ctrl0 &= ~(MXC_F_SPI_CTRL0_START | MXC_F_SPI_CTRL0_SS_CTRL | + MXC_F_SPI_CTRL0_EN); + req->spi->ctrl0 |= MXC_F_SPI_CTRL0_EN; + } + spi_context_complete(ctx, dev, error == E_NO_ERROR ? 0 : -EIO); + } +#else + spi_context_complete(ctx, dev, error == E_NO_ERROR ? 0 : -EIO); +#endif +} + +#ifdef CONFIG_SPI_ASYNC +void spi_max32_async_work_handler(struct k_work *work) +{ + struct max32_spi_data *data = CONTAINER_OF(work, struct max32_spi_data, async_work); + const struct device *dev = data->dev; + int ret; + + ret = spi_max32_transceive(dev); + if (ret) { + spi_context_complete(&data->ctx, dev, -EIO); + } +} +#endif /* CONFIG_SPI_ASYNC */ + +static void spi_max32_isr(const struct device *dev) +{ + const struct max32_spi_config *cfg = dev->config; + struct max32_spi_data *data = dev->data; + mxc_spi_req_t *req = &data->req; + mxc_spi_regs_t *spi = cfg->regs; + uint32_t flags, remain; + uint8_t dfs_shift = spi_max32_get_dfs_shift(&data->ctx); + + flags = MXC_SPI_GetFlags(spi); + MXC_SPI_ClearFlags(spi); + + remain = (req->txLen << dfs_shift) - req->txCnt; + if (flags & ADI_MAX32_SPI_INT_FL_TX_THD) { + if (remain) { + if (!data->req.txData) { + req->txCnt += MXC_SPI_WriteTXFIFO(cfg->regs, data->dummy, + MIN(remain, sizeof(data->dummy))); + } else { + req->txCnt += + MXC_SPI_WriteTXFIFO(spi, &req->txData[req->txCnt], remain); + } + } else { + MXC_SPI_DisableInt(spi, ADI_MAX32_SPI_INT_EN_TX_THD); + } + } + + remain = (req->rxLen << dfs_shift) - req->rxCnt; + if (remain) { + req->rxCnt += MXC_SPI_ReadRXFIFO(spi, &req->rxData[req->rxCnt], remain); + remain = (req->rxLen << dfs_shift) - req->rxCnt; + if (remain >= MXC_SPI_FIFO_DEPTH) { + MXC_SPI_SetRXThreshold(spi, 2); + } else { + MXC_SPI_SetRXThreshold(spi, remain); + } + } else { + MXC_SPI_DisableInt(spi, ADI_MAX32_SPI_INT_EN_RX_THD); + } + + if ((req->txLen == req->txCnt) && (req->rxLen == req->rxCnt)) { + MXC_SPI_DisableInt(spi, ADI_MAX32_SPI_INT_EN_TX_THD | ADI_MAX32_SPI_INT_EN_RX_THD); + if (flags & ADI_MAX32_SPI_INT_FL_MST_DONE) { + MXC_SPI_DisableInt(spi, ADI_MAX32_SPI_INT_EN_MST_DONE); + spi_max32_callback(req, 0); + } + } +} +#endif /* CONFIG_SPI_MAX32_INTERRUPT */ + +static int api_release(const struct device *dev, const struct spi_config *config) +{ + struct max32_spi_data *data = dev->data; + + if (!spi_context_configured(&data->ctx, config)) { + return -EINVAL; + } + + spi_context_unlock_unconditionally(&data->ctx); + + return 0; +} + +static int spi_max32_init(const struct device *dev) +{ + int ret = 0; + const struct max32_spi_config *const cfg = dev->config; + mxc_spi_regs_t *regs = cfg->regs; + struct max32_spi_data *data = dev->data; + + if (!device_is_ready(cfg->clock)) { + return -ENODEV; + } + + MXC_SPI_Shutdown(regs); + + ret = clock_control_on(cfg->clock, (clock_control_subsys_t)&cfg->perclk); + if (ret) { + return ret; + } + + ret = pinctrl_apply_state(cfg->pctrl, PINCTRL_STATE_DEFAULT); + if (ret) { + return ret; + } + + ret = spi_context_cs_configure_all(&data->ctx); + if (ret < 0) { + return ret; + } + + data->dev = dev; + +#ifdef CONFIG_SPI_MAX32_INTERRUPT + cfg->irq_config_func(dev); +#ifdef CONFIG_SPI_ASYNC + k_work_init(&data->async_work, spi_max32_async_work_handler); +#endif +#endif + + spi_context_unlock_unconditionally(&data->ctx); + + return ret; +} + +/* SPI driver APIs structure */ +static const struct spi_driver_api spi_max32_api = { + .transceive = api_transceive, +#ifdef CONFIG_SPI_ASYNC + .transceive_async = api_transceive_async, +#endif /* CONFIG_SPI_ASYNC */ + .release = api_release, +}; + +/* SPI driver registration */ +#ifdef CONFIG_SPI_MAX32_INTERRUPT +#define SPI_MAX32_CONFIG_IRQ_FUNC(n) .irq_config_func = spi_max32_irq_config_func_##n, + +#define SPI_MAX32_IRQ_CONFIG_FUNC(n) \ + static void spi_max32_irq_config_func_##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), DT_INST_IRQ(n, priority), spi_max32_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + irq_enable(DT_INST_IRQN(n)); \ + } +#else +#define SPI_MAX32_CONFIG_IRQ_FUNC(n) +#define SPI_MAX32_IRQ_CONFIG_FUNC(n) +#endif /* CONFIG_SPI_MAX32_INTERRUPT */ + +#define DEFINE_SPI_MAX32(_num) \ + PINCTRL_DT_INST_DEFINE(_num); \ + SPI_MAX32_IRQ_CONFIG_FUNC(_num) \ + static const struct max32_spi_config max32_spi_config_##_num = { \ + .regs = (mxc_spi_regs_t *)DT_INST_REG_ADDR(_num), \ + .pctrl = PINCTRL_DT_INST_DEV_CONFIG_GET(_num), \ + .clock = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(_num)), \ + .perclk.bus = DT_INST_CLOCKS_CELL(_num, offset), \ + .perclk.bit = DT_INST_CLOCKS_CELL(_num, bit), \ + SPI_MAX32_CONFIG_IRQ_FUNC(_num)}; \ + static struct max32_spi_data max32_spi_data_##_num = { \ + SPI_CONTEXT_INIT_LOCK(max32_spi_data_##_num, ctx), \ + SPI_CONTEXT_INIT_SYNC(max32_spi_data_##_num, ctx), \ + SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(_num), ctx)}; \ + DEVICE_DT_INST_DEFINE(_num, spi_max32_init, NULL, &max32_spi_data_##_num, \ + &max32_spi_config_##_num, PRE_KERNEL_2, CONFIG_SPI_INIT_PRIORITY, \ + &spi_max32_api); + +DT_INST_FOREACH_STATUS_OKAY(DEFINE_SPI_MAX32) diff --git a/drivers/spi/spi_mcux_flexcomm.c b/drivers/spi/spi_mcux_flexcomm.c index cb20fcea6e3be..411244c21a9aa 100644 --- a/drivers/spi/spi_mcux_flexcomm.c +++ b/drivers/spi/spi_mcux_flexcomm.c @@ -18,6 +18,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(spi_mcux_flexcomm, CONFIG_SPI_LOG_LEVEL); @@ -37,6 +38,7 @@ struct spi_mcux_config { uint32_t transfer_delay; uint32_t def_char; const struct pinctrl_dev_config *pincfg; + const struct reset_dt_spec reset; }; #ifdef CONFIG_SPI_MCUX_FLEXCOMM_DMA @@ -764,9 +766,19 @@ static int spi_mcux_release(const struct device *dev, static int spi_mcux_init(const struct device *dev) { - int err; const struct spi_mcux_config *config = dev->config; struct spi_mcux_data *data = dev->data; + int err = 0; + + if (!device_is_ready(config->reset.dev)) { + LOG_ERR("Reset device not ready"); + return -ENODEV; + } + + err = reset_line_toggle(config->reset.dev, config->reset.id); + if (err) { + return err; + } config->irq_config_func(dev); @@ -866,6 +878,7 @@ static void spi_mcux_config_func_##id(const struct device *dev) \ .transfer_delay = DT_INST_PROP_OR(id, transfer_delay, 0), \ .def_char = DT_INST_PROP_OR(id, def_char, 0), \ .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ + .reset = RESET_DT_SPEC_INST_GET(id), \ }; \ static struct spi_mcux_data spi_mcux_data_##id = { \ SPI_CONTEXT_INIT_LOCK(spi_mcux_data_##id, ctx), \ diff --git a/drivers/spi/spi_mcux_lpspi.c b/drivers/spi/spi_mcux_lpspi.c index 5432debd68a3e..0d5b7b27f4857 100644 --- a/drivers/spi/spi_mcux_lpspi.c +++ b/drivers/spi/spi_mcux_lpspi.c @@ -75,6 +75,7 @@ struct spi_mcux_data { #ifdef CONFIG_SPI_RTIO struct rtio *r; + struct mpsc io_q; struct rtio_iodev iodev; struct rtio_iodev_sqe *txn_head; struct rtio_iodev_sqe *txn_curr; @@ -702,7 +703,7 @@ static int spi_mcux_init(const struct device *dev) data->dt_spec.bus = dev; data->iodev.api = &spi_iodev_api; data->iodev.data = &data->dt_spec; - rtio_mpsc_init(&data->iodev.iodev_sq); + mpsc_init(&data->io_q); #endif err = pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); @@ -803,7 +804,7 @@ static void spi_mcux_iodev_next(const struct device *dev, bool completion) return; } - struct rtio_mpsc_node *next = rtio_mpsc_pop(&data->iodev.iodev_sq); + struct mpsc_node *next = mpsc_pop(&data->io_q); if (next != NULL) { struct rtio_iodev_sqe *next_sqe = CONTAINER_OF(next, struct rtio_iodev_sqe, q); @@ -832,7 +833,7 @@ static void spi_mcux_iodev_submit(const struct device *dev, { struct spi_mcux_data *data = dev->data; - rtio_mpsc_push(&data->iodev.iodev_sq, &iodev_sqe->q); + mpsc_push(&data->io_q, &iodev_sqe->q); spi_mcux_iodev_next(dev, false); } diff --git a/drivers/spi/spi_nrfx_spim.c b/drivers/spi/spi_nrfx_spim.c index 08012b389c55b..e1ce774af5229 100644 --- a/drivers/spi/spi_nrfx_spim.c +++ b/drivers/spi/spi_nrfx_spim.c @@ -5,8 +5,10 @@ */ #include +#include #include #include +#include #include #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 #include @@ -64,10 +66,28 @@ struct spi_nrfx_config { #endif uint32_t wake_pin; nrfx_gpiote_t wake_gpiote; +#ifdef CONFIG_DCACHE + uint32_t mem_attr; +#endif }; static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context); +static inline void finalize_spi_transaction(const struct device *dev, bool deactivate_cs) +{ + struct spi_nrfx_data *dev_data = dev->data; + const struct spi_nrfx_config *dev_config = dev->config; + void *reg = dev_config->spim.p_reg; + + if (deactivate_cs) { + spi_context_cs_control(&dev_data->ctx, false); + } + + if (NRF_SPIM_IS_320MHZ_SPIM(reg) && !(dev_data->ctx.config->operation & SPI_HOLD_ON_CS)) { + nrfy_spim_disable(reg); + } +} + static inline uint32_t get_nrf_spim_frequency(uint32_t frequency) { /* Get the highest supported frequency not exceeding the requested one. @@ -193,7 +213,7 @@ static int configure(const struct device *dev, } result = nrfx_spim_init(&dev_config->spim, &config, - event_handler, dev_data); + event_handler, (void *)dev); if (result != NRFX_SUCCESS) { LOG_ERR("Failed to initialize nrfx driver: %08x", result); return -EIO; @@ -298,6 +318,8 @@ static void finish_transaction(const struct device *dev, int error) spi_context_complete(ctx, dev, error); dev_data->busy = false; + + finalize_spi_transaction(dev, true); } static void transfer_next_chunk(const struct device *dev) @@ -328,6 +350,11 @@ static void transfer_next_chunk(const struct device *dev) } memcpy(dev_data->tx_buffer, tx_buf, chunk_len); +#ifdef CONFIG_DCACHE + if (dev_config->mem_attr & DT_MEM_CACHEABLE) { + sys_cache_data_flush_range(dev_data->tx_buffer, chunk_len); + } +#endif tx_buf = dev_data->tx_buffer; } @@ -377,7 +404,11 @@ static void transfer_next_chunk(const struct device *dev) static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context) { - struct spi_nrfx_data *dev_data = p_context; + const struct device *dev = p_context; + struct spi_nrfx_data *dev_data = dev->data; +#ifdef CONFIG_DCACHE + const struct spi_nrfx_config *dev_config = dev->config; +#endif if (p_event->type == NRFX_SPIM_EVENT_DONE) { /* Chunk length is set to 0 when a transaction is aborted @@ -395,6 +426,11 @@ static void event_handler(const nrfx_spim_evt_t *p_event, void *p_context) if (spi_context_rx_buf_on(&dev_data->ctx) && p_event->xfer_desc.p_rx_buffer != NULL && p_event->xfer_desc.p_rx_buffer != dev_data->ctx.rx_buf) { +#ifdef CONFIG_DCACHE + if (dev_config->mem_attr & DT_MEM_CACHEABLE) { + sys_cache_data_invd_range(dev_data->rx_buffer, dev_data->chunk_len); + } +#endif (void)memcpy(dev_data->ctx.rx_buf, dev_data->rx_buffer, dev_data->chunk_len); @@ -417,6 +453,7 @@ static int transceive(const struct device *dev, { struct spi_nrfx_data *dev_data = dev->data; const struct spi_nrfx_config *dev_config = dev->config; + void *reg = dev_config->spim.p_reg; int error; spi_context_lock(&dev_data->ctx, asynchronous, cb, userdata, spi_cfg); @@ -439,6 +476,9 @@ static int transceive(const struct device *dev, } spi_context_buffers_setup(&dev_data->ctx, tx_bufs, rx_bufs, 1); + if (NRF_SPIM_IS_320MHZ_SPIM(reg)) { + nrfy_spim_enable(reg); + } spi_context_cs_control(&dev_data->ctx, true); transfer_next_chunk(dev); @@ -467,9 +507,9 @@ static int transceive(const struct device *dev, #ifdef CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58 anomaly_58_workaround_clear(dev_data); #endif + } else if (error) { + finalize_spi_transaction(dev, true); } - - spi_context_cs_control(&dev_data->ctx, false); } spi_context_release(&dev_data->ctx, error); @@ -511,6 +551,7 @@ static int spi_nrfx_release(const struct device *dev, } spi_context_unlock_unconditionally(&dev_data->ctx); + finalize_spi_transaction(dev, false); return 0; } @@ -612,6 +653,7 @@ static int spi_nrfx_init(const struct device *dev) #define SPIM(idx) DT_NODELABEL(spi##idx) #define SPIM_PROP(idx, prop) DT_PROP(SPIM(idx), prop) #define SPIM_HAS_PROP(idx, prop) DT_NODE_HAS_PROP(SPIM(idx), prop) +#define SPIM_MEM_REGION(idx) DT_PHANDLE(SPIM(idx), memory_regions) #define SPI_NRFX_SPIM_EXTENDED_CONFIG(idx) \ IF_ENABLED(NRFX_SPIM_EXTENDED_ENABLED, \ @@ -621,6 +663,13 @@ static int spi_nrfx_init(const struct device *dev) ()) \ )) +#define SPIM_GET_MEM_ATTR(idx) \ + COND_CODE_1(SPIM_HAS_PROP(idx, memory_regions), \ + (COND_CODE_1(DT_NODE_HAS_PROP(SPIM_MEM_REGION(idx), zephyr_memory_attr), \ + (DT_PROP(SPIM_MEM_REGION(idx), zephyr_memory_attr)), \ + (0))), \ + (0)) + #define SPI_NRFX_SPIM_DEFINE(idx) \ NRF_DT_CHECK_NODE_HAS_PINCTRL_SLEEP(SPIM(idx)); \ static void irq_connect##idx(void) \ @@ -669,6 +718,8 @@ static int spi_nrfx_init(const struct device *dev) .wake_pin = NRF_DT_GPIOS_TO_PSEL_OR(SPIM(idx), wake_gpios, \ WAKE_PIN_NOT_USED), \ .wake_gpiote = WAKE_GPIOTE_INSTANCE(SPIM(idx)), \ + IF_ENABLED(CONFIG_DCACHE, \ + (.mem_attr = SPIM_GET_MEM_ATTR(idx),)) \ }; \ BUILD_ASSERT(!SPIM_HAS_PROP(idx, wake_gpios) || \ !(DT_GPIO_FLAGS(SPIM(idx), wake_gpios) & GPIO_ACTIVE_LOW),\ @@ -685,7 +736,7 @@ static int spi_nrfx_init(const struct device *dev) #define SPIM_MEMORY_SECTION(idx) \ COND_CODE_1(SPIM_HAS_PROP(idx, memory_regions), \ (__attribute__((__section__(LINKER_DT_NODE_REGION_NAME( \ - DT_PHANDLE(SPIM(idx), memory_regions)))))), \ + SPIM_MEM_REGION(idx)))))), \ ()) #ifdef CONFIG_HAS_HW_NRF_SPIM0 diff --git a/drivers/spi/spi_psoc6.c b/drivers/spi/spi_psoc6.c index 7b6a30d3a6540..817c94899b274 100644 --- a/drivers/spi/spi_psoc6.c +++ b/drivers/spi/spi_psoc6.c @@ -31,8 +31,7 @@ struct spi_psoc6_config { CySCB_Type *base; uint32_t periph_id; void (*irq_config_func)(const struct device *dev); - uint32_t num_pins; - struct soc_gpio_pin pins[]; + const struct pinctrl_dev_config *pcfg; }; struct spi_psoc6_transfer { @@ -377,7 +376,12 @@ static int spi_psoc6_init(const struct device *dev) const struct spi_psoc6_config *config = dev->config; struct spi_psoc6_data *data = dev->data; - soc_gpio_list_configure(config->pins, config->num_pins); + + /* Configure dt provided device signals when available */ + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } Cy_SysClk_PeriphAssignDivider(config->periph_id, CY_SYSCLK_DIV_8_BIT, @@ -408,12 +412,12 @@ static const struct spi_driver_api spi_psoc6_driver_api = { }; #define SPI_PSOC6_DEVICE_INIT(n) \ + PINCTRL_DT_INST_DEFINE(n); \ static void spi_psoc6_spi##n##_irq_cfg(const struct device *port); \ static const struct spi_psoc6_config spi_psoc6_config_##n = { \ .base = (CySCB_Type *)DT_INST_REG_ADDR(n), \ .periph_id = DT_INST_PROP(n, peripheral_id), \ - .num_pins = CY_PSOC6_DT_INST_NUM_PINS(n), \ - .pins = CY_PSOC6_DT_INST_PINS(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .irq_config_func = spi_psoc6_spi##n##_irq_cfg, \ }; \ static struct spi_psoc6_data spi_psoc6_dev_data_##n = { \ diff --git a/drivers/spi/spi_sam.c b/drivers/spi/spi_sam.c index 7cb6e8dc90c6f..fb42cb6a55373 100644 --- a/drivers/spi/spi_sam.c +++ b/drivers/spi/spi_sam.c @@ -53,6 +53,7 @@ struct spi_sam_data { #ifdef CONFIG_SPI_RTIO struct rtio *r; /* context for thread calls */ + struct mpsc io_q; struct rtio_iodev iodev; struct rtio_iodev_sqe *txn_head; struct rtio_iodev_sqe *txn_curr; @@ -691,7 +692,7 @@ static void spi_sam_iodev_next(const struct device *dev, bool completion) return; } - struct rtio_mpsc_node *next = rtio_mpsc_pop(&data->iodev.iodev_sq); + struct mpsc_node *next = mpsc_pop(&data->io_q); if (next != NULL) { struct rtio_iodev_sqe *next_sqe = CONTAINER_OF(next, struct rtio_iodev_sqe, q); @@ -736,7 +737,7 @@ static void spi_sam_iodev_submit(const struct device *dev, { struct spi_sam_data *data = dev->data; - rtio_mpsc_push(&data->iodev.iodev_sq, &iodev_sqe->q); + mpsc_push(&data->io_q, &iodev_sqe->q); spi_sam_iodev_next(dev, false); } #endif @@ -866,7 +867,7 @@ static int spi_sam_init(const struct device *dev) data->dt_spec.bus = dev; data->iodev.api = &spi_iodev_api; data->iodev.data = &data->dt_spec; - rtio_mpsc_init(&data->iodev.iodev_sq); + mpsc_init(&data->io_q); #endif spi_context_unlock_unconditionally(&data->ctx); diff --git a/drivers/spi/spi_smartbond.c b/drivers/spi/spi_smartbond.c index 7f44c0f29aaf0..f067da9c0a098 100644 --- a/drivers/spi/spi_smartbond.c +++ b/drivers/spi/spi_smartbond.c @@ -15,26 +15,91 @@ LOG_MODULE_REGISTER(spi_smartbond); #include #include #include +#include +#include +#include +#include +#include #include +#include -#define DIVN_CLK 32000000 /* divN_clk 32MHz */ -#define SCLK_FREQ_2MHZ (DIVN_CLK / 14) /* 2.285714MHz*/ -#define SCLK_FREQ_4MHZ (DIVN_CLK / 8) /* 4MHz */ -#define SCLK_FREQ_8MHZ (DIVN_CLK / 4) /* 8MHz */ -#define SCLK_FREQ_16MHZ (DIVN_CLK / 2) /* 16MHz */ +#define DIVN_CLK 32000000 /* DIVN clock: fixed @32MHz */ +#define SCLK_FREQ_2MHZ (DIVN_CLK / 14) /* 2.285714 MHz*/ +#define SCLK_FREQ_4MHZ (DIVN_CLK / 8) /* 4 MHz */ +#define SCLK_FREQ_8MHZ (DIVN_CLK / 4) /* 8 MHz */ +#define SCLK_FREQ_16MHZ (DIVN_CLK / 2) /* 16 MHz */ + +enum spi_smartbond_transfer { + SPI_SMARTBOND_TRANSFER_TX_ONLY, + SPI_SMARTBOND_TRANSFER_RX_ONLY, + SPI_SMARTBOND_TRANSFER_TX_RX, + SPI_SMARTBOND_TRANSFER_NONE +}; + +enum spi_smartbond_dma_channel { + SPI_SMARTBOND_DMA_TX_CHANNEL, + SPI_SMARTBOND_DMA_RX_CHANNEL +}; + +enum spi_smartbond_fifo_mode { + /* Bi-directional mode */ + SPI_SMARTBOND_FIFO_MODE_TX_RX, + /* TX FIFO single depth, no flow control */ + SPI_SMARTBOND_FIFO_MODE_RX_ONLY, + /* RX FIFO single depth, no flow control */ + SPI_SMARTBOND_FIFO_MODE_TX_ONLY, + SPI_SMARTBOND_FIFO_NONE +}; struct spi_smartbond_cfg { SPI_Type *regs; int periph_clock_config; const struct pinctrl_dev_config *pcfg; +#ifdef CONFIG_SPI_SMARTBOND_DMA + int tx_dma_chan; + int rx_dma_chan; + uint8_t tx_slot_mux; + uint8_t rx_slot_mux; + const struct device *tx_dma_ctrl; + const struct device *rx_dma_ctrl; +#endif }; struct spi_smartbond_data { struct spi_context ctx; uint8_t dfs; + +#if defined(CONFIG_PM_DEVICE) + ATOMIC_DEFINE(pm_policy_state_flag, 1); + uint32_t spi_ctrl_reg; +#endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA + struct dma_config tx_dma_cfg; + struct dma_config rx_dma_cfg; + struct dma_block_config tx_dma_block_cfg; + struct dma_block_config rx_dma_block_cfg; + struct k_sem rx_dma_sync; + struct k_sem tx_dma_sync; + + ATOMIC_DEFINE(dma_channel_atomic_flag, 2); + +#endif + +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) + size_t rx_len; + size_t tx_len; + size_t transferred; + enum spi_smartbond_transfer transfer_mode; +#endif }; +#define SPI_CTRL_REG_SET_FIELD(_field, _var, _val) \ + (_var) = \ + (((_var) & ~SPI_SPI_CTRL_REG_ ## _field ## _Msk) | \ + (((_val) << SPI_SPI_CTRL_REG_ ## _field ## _Pos) & SPI_SPI_CTRL_REG_ ## _field ## _Msk)) + static inline void spi_smartbond_enable(const struct spi_smartbond_cfg *cfg, bool enable) { if (enable) { @@ -52,6 +117,60 @@ static inline bool spi_smartbond_isenabled(const struct spi_smartbond_cfg *cfg) (!(cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_RST_Msk)); } +static inline void spi_smartbond_write_word(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + struct spi_smartbond_data *data = dev->data; + + /* + * No need to typecast the register address as the controller will automatically + * generate the necessary clock cycles based on the data size. + */ + switch (data->dfs) { + case 1: + cfg->regs->SPI_RX_TX_REG = *(uint8_t *)data->ctx.tx_buf; + break; + case 2: + cfg->regs->SPI_RX_TX_REG = sys_get_le16(data->ctx.tx_buf); + break; + case 4: + cfg->regs->SPI_RX_TX_REG = sys_get_le32(data->ctx.tx_buf); + break; + } +} + +static inline void spi_smartbond_write_dummy(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + cfg->regs->SPI_RX_TX_REG = 0x0; +} + +static inline void spi_smartbond_read_word(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + struct spi_smartbond_data *data = dev->data; + + switch (data->dfs) { + case 1: + *(uint8_t *)data->ctx.rx_buf = cfg->regs->SPI_RX_TX_REG; + break; + case 2: + sys_put_le16((uint16_t)cfg->regs->SPI_RX_TX_REG, data->ctx.rx_buf); + break; + case 4: + sys_put_le32(cfg->regs->SPI_RX_TX_REG, data->ctx.rx_buf); + break; + } +} + +static inline void spi_smartbond_read_discard(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + (void)cfg->regs->SPI_RX_TX_REG; +} + static inline int spi_smartbond_set_speed(const struct spi_smartbond_cfg *cfg, const uint32_t frequency) { @@ -106,6 +225,31 @@ static inline int spi_smartbond_set_word_size(const struct spi_smartbond_cfg *cf return 0; } +static inline void spi_smartbond_pm_policy_state_lock_get(struct spi_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) + if (atomic_test_and_set_bit(data->pm_policy_state_flag, 0) == 0) { + /* + * Prevent the SoC from entering the normal sleep state as PDC does not support + * waking up the application core following SPI events. + */ + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + +static inline void spi_smartbond_pm_policy_state_lock_put(struct spi_smartbond_data *data) +{ +#if defined(CONFIG_PM_DEVICE) + if (atomic_test_and_clear_bit(data->pm_policy_state_flag, 0) == 1) { + /* + * Allow the SoC to enter the normal sleep state once SPI transactions are done. + */ + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +#endif +} + static int spi_smartbond_configure(const struct spi_smartbond_cfg *cfg, struct spi_smartbond_data *data, const struct spi_config *spi_cfg) @@ -113,6 +257,9 @@ static int spi_smartbond_configure(const struct spi_smartbond_cfg *cfg, int rc; if (spi_context_configured(&data->ctx, spi_cfg)) { +#ifdef CONFIG_PM_DEVICE + spi_smartbond_enable(cfg, true); +#endif return 0; } @@ -172,6 +319,732 @@ static int spi_smartbond_configure(const struct spi_smartbond_cfg *cfg, return 0; } +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) +static inline void spi_smartbond_isr_set_status(const struct device *dev, bool status) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + if (status) { + cfg->regs->SPI_CTRL_REG |= SPI_SPI_CTRL_REG_SPI_MINT_Msk; + } else { + cfg->regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_MINT_Msk; + } +} + +static inline bool spi_smartbond_is_busy(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + return (cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_BUSY_Msk); +} + +static inline void spi_smartbond_clear_interrupt(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + cfg->regs->SPI_CLEAR_INT_REG = 0x1; +} + +/* 0 = No RX data available, 1 = data has been transmitted and received */ +static inline bool spi_smartbond_is_rx_data(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + return (cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_INT_BIT_Msk); +} + +static inline uint8_t spi_smartbond_get_fifo_mode(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + return ((cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_FIFO_MODE_Msk) >> + SPI_SPI_CTRL_REG_SPI_FIFO_MODE_Pos); +} + +static void spi_smartbond_set_fifo_mode(const struct device *dev, enum spi_smartbond_fifo_mode mode) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + bool is_enabled = spi_smartbond_isenabled(cfg); + enum spi_smartbond_fifo_mode current_mode = spi_smartbond_get_fifo_mode(dev); + uint32_t spi_ctrl_reg = cfg->regs->SPI_CTRL_REG; + +#ifdef CONFIG_SPI_SMARTBOND_DMA + struct spi_smartbond_data *data = dev->data; +#endif + + if ((current_mode != mode) +#ifdef CONFIG_SPI_SMARTBOND_DMA + || (data->dfs == 4) +#endif + ) { + if (current_mode != SPI_SMARTBOND_FIFO_MODE_RX_ONLY) { + while (spi_smartbond_is_busy(dev)) { + ; + } + } + /* Controller should be disabled when FIFO mode is updated */ + cfg->regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_ON_Msk; + +#ifdef CONFIG_SPI_SMARTBOND_DMA + /* + * Workaround for the controller that cannot generate DMA requests + * for 4-byte bus length. + */ + if (data->dfs == 4) { + mode = SPI_SMARTBOND_FIFO_NONE; + } +#endif + SPI_CTRL_REG_SET_FIELD(SPI_FIFO_MODE, spi_ctrl_reg, mode); + + + if (mode != SPI_SMARTBOND_FIFO_NONE) { + SPI_CTRL_REG_SET_FIELD(SPI_DMA_TXREQ_MODE, spi_ctrl_reg, 0); + } else { + SPI_CTRL_REG_SET_FIELD(SPI_DMA_TXREQ_MODE, spi_ctrl_reg, 1); + } + + if (is_enabled) { + SPI_CTRL_REG_SET_FIELD(SPI_ON, spi_ctrl_reg, 1); + } + + cfg->regs->SPI_CTRL_REG = spi_ctrl_reg; + } +} + +static int spi_smartbond_transfer_mode_get(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + if (spi_context_rx_buf_on(ctx) || spi_context_tx_buf_on(ctx)) { + /* + * Check only buffers' length as it might happen that current buffer is NULL. + * In such a case the context should be updated and a dummy write/read should + * take place. + */ + if (ctx->rx_len || ctx->tx_len) { + spi_smartbond_set_fifo_mode(dev, SPI_SMARTBOND_FIFO_MODE_TX_RX); + return SPI_SMARTBOND_TRANSFER_TX_RX; + } + + if (!spi_context_rx_buf_on(ctx)) { + spi_smartbond_set_fifo_mode(dev, SPI_SMARTBOND_FIFO_MODE_TX_ONLY); + return SPI_SMARTBOND_TRANSFER_TX_ONLY; + } + + if (!spi_context_tx_buf_on(ctx)) { + /* + * Use the TX/RX mode with TX being dummy. Using the RX only mode + * is a bit tricky as the controller should generate clock cycles + * automatically and immediately after the ISR is enabled. + */ + spi_smartbond_set_fifo_mode(dev, SPI_SMARTBOND_FIFO_MODE_TX_RX); + return SPI_SMARTBOND_TRANSFER_RX_ONLY; + } + } + + /* Return waiting updating the fifo mode */ + return SPI_SMARTBOND_TRANSFER_NONE; +} + +static inline void spi_smartbond_transfer_mode_check_and_update(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + + data->transfer_mode = spi_smartbond_transfer_mode_get(dev); +} +#endif + +#ifdef CONFIG_SPI_ASYNC +static inline bool spi_smartbond_is_tx_full(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + return (cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_TXH_Msk); +} + +static void spi_smartbond_write(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + while (spi_context_tx_buf_on(ctx)) { + /* Check if TX FIFO is full as otherwise undefined data should be transmitted. */ + if (spi_smartbond_is_tx_full(dev)) { + spi_smartbond_clear_interrupt(dev); + break; + } + /* Send to TX FIFO and update buffer pointer. */ + spi_smartbond_write_word(dev); + spi_context_update_tx(ctx, data->dfs, 1); + + /* + * It might happen that a NULL buffer with a non-zero length is provided. + * In that case, the bytes should be consumed. + */ + if (ctx->rx_len && !ctx->rx_buf) { + spi_smartbond_read_discard(dev); + spi_context_update_rx(ctx, data->dfs, 1); + } + } +} + +static void spi_smartbond_transfer(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + while (data->rx_len) { + /* Zero means that RX FIFO or register is empty */ + if (!spi_smartbond_is_rx_data(dev)) { + break; + } + + if (ctx->rx_buf) { + spi_smartbond_read_word(dev); + } else { + spi_smartbond_read_discard(dev); + } + spi_context_update_rx(ctx, data->dfs, 1); + + spi_smartbond_clear_interrupt(dev); + + data->rx_len--; + data->transferred++; + } + + while (data->tx_len) { + /* Check if TX FIFO is full as otherwise undefined data should be transmitted. */ + if (spi_smartbond_is_tx_full(dev)) { + break; + } + + if (ctx->tx_buf) { + spi_smartbond_write_word(dev); + } else { + spi_smartbond_write_dummy(dev); + } + spi_context_update_tx(ctx, data->dfs, 1); + + data->tx_len--; + } +} + +static void spi_smartbond_read(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + while (spi_context_rx_buf_on(ctx)) { + /* Zero means that RX FIFO or register is empty */ + if (!spi_smartbond_is_rx_data(dev)) { + break; + } + + spi_smartbond_read_word(dev); + spi_context_update_rx(ctx, data->dfs, 1); + spi_smartbond_clear_interrupt(dev); + } + + /* Perform dummy access to generate the required clock cycles */ + while (data->tx_len) { + if (spi_smartbond_is_tx_full(dev)) { + break; + } + spi_smartbond_write_dummy(dev); + + data->tx_len--; + } +} + +static void spi_smartbond_isr_trigger(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + data->transfer_mode = spi_smartbond_transfer_mode_get(dev); + + switch (data->transfer_mode) { + case SPI_SMARTBOND_TRANSFER_RX_ONLY: + data->tx_len = spi_context_total_rx_len(ctx); + spi_smartbond_read(dev); + break; + case SPI_SMARTBOND_TRANSFER_TX_ONLY: + spi_smartbond_write(dev); + break; + case SPI_SMARTBOND_TRANSFER_TX_RX: + /* + * Each sub-transfer in the descriptor list should be exercised + * separately as it might happen that a buffer is NULL with + * non-zero length. + */ + data->rx_len = spi_context_max_continuous_chunk(ctx); + data->tx_len = data->rx_len; + spi_smartbond_transfer(dev); + break; + case SPI_SMARTBOND_TRANSFER_NONE: + __fallthrough; + default: + __ASSERT_MSG_INFO("Invalid transfer mode"); + break; + } + + spi_smartbond_isr_set_status(dev, true); +} + +static int spi_smartbond_transceive_async(const struct device *dev, + const struct spi_config *spi_cfg, + const struct spi_buf_set *tx_bufs, + const struct spi_buf_set *rx_bufs, spi_callback_t cb, + void *userdata) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + int rc; + + spi_context_lock(ctx, true, cb, userdata, spi_cfg); + + rc = spi_smartbond_configure(cfg, data, spi_cfg); + if (rc == 0) { + spi_smartbond_pm_policy_state_lock_get(data); + spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, data->dfs); + spi_context_cs_control(ctx, true); + + /* + * PM constraints will be released within ISR once all transfers + * are exercised along with de-asserting the #CS line. + */ + spi_smartbond_isr_trigger(dev); + } + /* + * Context will actually be released when \sa spi_context_complete + * is called. + */ + spi_context_release(ctx, rc); + + return rc; +} +#endif + +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) +static void spi_smartbond_isr(void *args) +{ +#ifdef CONFIG_SPI_ASYNC + struct device *dev = args; + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + switch (data->transfer_mode) { + case SPI_SMARTBOND_TRANSFER_RX_ONLY: + spi_smartbond_read(dev); + break; + case SPI_SMARTBOND_TRANSFER_TX_ONLY: + spi_smartbond_write(dev); + break; + case SPI_SMARTBOND_TRANSFER_TX_RX: + /* Exersice the type of the next sub-transfer */ + if (!data->rx_len && !data->tx_len) { + spi_smartbond_transfer_mode_check_and_update(dev); + + if (data->transfer_mode == SPI_SMARTBOND_TRANSFER_RX_ONLY) { + data->tx_len = spi_context_total_rx_len(ctx) - data->transferred; + /* Clear in case another truncated transfer should be executed */ + data->transferred = 0; + spi_smartbond_read(dev); + } else if (data->transfer_mode == SPI_SMARTBOND_TRANSFER_TX_ONLY) { + spi_smartbond_write(dev); + } else if (data->transfer_mode == SPI_SMARTBOND_TRANSFER_TX_RX) { + data->rx_len = spi_context_max_continuous_chunk(ctx); + data->tx_len = data->rx_len; + spi_smartbond_transfer(dev); + } + } else { + spi_smartbond_transfer(dev); + } + break; + case SPI_SMARTBOND_TRANSFER_NONE: + __fallthrough; + default: + __ASSERT_MSG_INFO("Invalid transfer mode"); + break; + } + + /* All buffers have been exercised, signal completion */ + if (!spi_context_tx_buf_on(ctx) && !spi_context_rx_buf_on(ctx)) { + spi_smartbond_isr_set_status(dev, false); + + /* Mark completion to trigger callback function */ + spi_context_complete(ctx, dev, 0); + + spi_context_cs_control(ctx, false); + spi_smartbond_pm_policy_state_lock_put(data); + } +#endif +} +#endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA +static uint32_t spi_smartbond_read_dummy_buf; + +/* + * Should be used to flush the RX FIFO in case a transaction is requested + * with NULL pointer and non-zero length. In such a case, data will be + * shifted into the RX FIFO (regardless of whether or not the RX mode is + * disabled) which should then be flushed. Otherwise, a next read operation + * will result in fetching old bytes. + */ +static void spi_smartbond_flush_rx_fifo(const struct device *dev) +{ + while (spi_smartbond_is_busy(dev)) { + }; + while (spi_smartbond_is_rx_data(dev)) { + spi_smartbond_read_discard(dev); + spi_smartbond_clear_interrupt(dev); + } +} + +static int spi_smartbond_dma_tx_channel_request(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + + if (!atomic_test_and_set_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_TX_CHANNEL)) { + if (dma_request_channel(config->tx_dma_ctrl, (void *)&config->tx_dma_chan) < 0) { + atomic_clear_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_TX_CHANNEL); + return -EIO; + } + } + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static void spi_smartbond_dma_tx_channel_release(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + + if (atomic_test_and_clear_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_TX_CHANNEL)) { + dma_release_channel(config->tx_dma_ctrl, config->tx_dma_chan); + } +} +#endif + +static int spi_smartbond_dma_rx_channel_request(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + + if (!atomic_test_and_set_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_RX_CHANNEL)) { + if (dma_request_channel(config->rx_dma_ctrl, (void *)&config->rx_dma_chan) < 0) { + atomic_clear_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_RX_CHANNEL); + return -EIO; + } + } + + return 0; +} + +#ifdef CONFIG_PM_DEVICE +static void spi_smartbond_dma_rx_channel_release(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + + if (atomic_test_and_clear_bit(data->dma_channel_atomic_flag, + SPI_SMARTBOND_DMA_RX_CHANNEL)) { + dma_release_channel(config->rx_dma_ctrl, config->rx_dma_chan); + } +} +#endif + +static void spi_smartbond_tx_dma_cb(const struct device *dma, void *arg, + uint32_t id, int status) +{ + const struct device *dev = arg; + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + if (status < 0) { + LOG_WRN("DMA transfer did not complete"); + } + + spi_context_update_tx(ctx, data->dfs, data->tx_len); + k_sem_give(&data->tx_dma_sync); +} + +static void spi_smartbond_rx_dma_cb(const struct device *dma, void *arg, + uint32_t id, int status) +{ + const struct device *dev = arg; + struct spi_smartbond_data *data = dev->data; + struct spi_context *ctx = &data->ctx; + + if (status < 0) { + LOG_WRN("DMA transfer did not complete"); + } + + spi_context_update_rx(ctx, data->dfs, data->rx_len); + k_sem_give(&data->rx_dma_sync); +} + +#ifdef CONFIG_PM_DEVICE +static void spi_smartbond_dma_deconfig(const struct device *dev) +{ + const struct spi_smartbond_cfg *config = dev->config; + + dma_stop(config->rx_dma_ctrl, config->rx_dma_chan); + dma_stop(config->tx_dma_ctrl, config->tx_dma_chan); + + spi_smartbond_dma_rx_channel_release(dev); + spi_smartbond_dma_tx_channel_release(dev); +} +#endif + +static int spi_smartbond_dma_config(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + struct dma_config *tx = &data->tx_dma_cfg; + struct dma_config *rx = &data->rx_dma_cfg; + struct dma_block_config *tx_block = &data->tx_dma_block_cfg; + struct dma_block_config *rx_block = &data->rx_dma_block_cfg; + + /* + * DMA RX should be assigned an even number and + * DMA TX should be assigned the right next + * channel (odd number). + */ + if (!(config->tx_dma_chan & 0x1) || + (config->rx_dma_chan & 0x1) || + (config->tx_dma_chan != (config->rx_dma_chan + 1))) { + LOG_ERR("Invalid RX/TX channel selection"); + return -EINVAL; + } + + if (config->tx_slot_mux != config->rx_slot_mux) { + LOG_ERR("TX/RX DMA slots mismatch"); + return -EINVAL; + } + + if (!device_is_ready(config->tx_dma_ctrl) || + !device_is_ready(config->rx_dma_ctrl)) { + LOG_ERR("TX/RX DMA device is not ready"); + return -ENODEV; + } + + if (spi_smartbond_dma_tx_channel_request(dev) < 0) { + LOG_ERR("TX DMA channel is already occupied"); + return -EIO; + } + + if (spi_smartbond_dma_rx_channel_request(dev) < 0) { + LOG_ERR("RX DMA channel is already occupied"); + return -EIO; + } + + tx->channel_direction = MEMORY_TO_PERIPHERAL; + tx->dma_callback = spi_smartbond_tx_dma_cb; + tx->user_data = (void *)dev; + tx->block_count = 1; + tx->head_block = &data->tx_dma_block_cfg; + tx->error_callback_dis = 1; + tx->dma_slot = config->tx_slot_mux; + tx->channel_priority = 2; + + /* Burst mode is not using when DREQ is one */ + tx->source_burst_length = 1; + tx->dest_burst_length = 1; + /* Source and destination data size should reflect DFS value */ + tx->source_data_size = 0; + tx->dest_data_size = 0; + + /* Do not change */ + tx_block->dest_addr_adj = 0x2; + /* Incremental */ + tx_block->source_addr_adj = 0x0; + tx_block->dest_address = (uint32_t)&config->regs->SPI_RX_TX_REG; + + /* + * To be filled when a transaction is requested and + * should reflect the total number of bytes. + */ + tx_block->block_size = 0; + /* Should reflect the TX buffer */ + tx_block->source_address = 0; + + rx->channel_direction = PERIPHERAL_TO_MEMORY; + rx->dma_callback = spi_smartbond_rx_dma_cb; + rx->user_data = (void *)dev; + rx->block_count = 1; + rx->head_block = &data->rx_dma_block_cfg; + rx->error_callback_dis = 1; + rx->dma_slot = config->rx_slot_mux; + rx->channel_priority = 2; + + /* Burst mode is not using when DREQ is one */ + rx->source_burst_length = 1; + rx->dest_burst_length = 1; + /* Source and destination data size should reflect DFS value */ + rx->source_data_size = 0; + rx->dest_data_size = 0; + + /* Do not change */ + rx_block->source_addr_adj = 0x2; + /* Incremenetal */ + rx_block->dest_addr_adj = 0x0; + rx_block->source_address = (uint32_t)&config->regs->SPI_RX_TX_REG; + + /* + * To be filled when a transaction is requested and + * should reflect the total number of bytes. + */ + rx_block->block_size = 0; + /* Should reflect the RX buffer */ + rx_block->dest_address = 0; + + return 0; +} + +static int spi_smartbond_dma_trigger(const struct device *dev) +{ + struct spi_smartbond_data *data = dev->data; + const struct spi_smartbond_cfg *config = dev->config; + struct spi_context *ctx = &data->ctx; + struct dma_config *tx = &data->tx_dma_cfg; + struct dma_config *rx = &data->rx_dma_cfg; + struct dma_block_config *tx_block = &data->tx_dma_block_cfg; + struct dma_block_config *rx_block = &data->rx_dma_block_cfg; + + rx->source_data_size = data->dfs; + rx->dest_data_size = data->dfs; + tx->source_data_size = data->dfs; + tx->dest_data_size = data->dfs; + + data->transfer_mode = spi_smartbond_transfer_mode_get(dev); + do { + switch (data->transfer_mode) { + case SPI_SMARTBOND_TRANSFER_RX_ONLY: + spi_smartbond_flush_rx_fifo(dev); + + data->rx_len = spi_context_max_continuous_chunk(ctx); + data->tx_len = data->rx_len; + + rx_block->block_size = data->rx_len * data->dfs; + tx_block->block_size = rx_block->block_size; + + rx_block->dest_address = (uint32_t)ctx->rx_buf; + rx_block->dest_addr_adj = 0x0; + tx_block->source_address = (uint32_t)&spi_smartbond_read_dummy_buf; + /* Non-incremental */ + tx_block->source_addr_adj = 0x2; + + if (dma_config(config->tx_dma_ctrl, config->tx_dma_chan, tx) < 0) { + LOG_ERR("TX DMA configuration failed"); + return -EINVAL; + } + if (dma_config(config->rx_dma_ctrl, config->rx_dma_chan, rx) < 0) { + LOG_ERR("RX DMA configuration failed"); + return -EINVAL; + } + dma_start(config->rx_dma_ctrl, config->rx_dma_chan); + dma_start(config->tx_dma_ctrl, config->tx_dma_chan); + + /* Wait for the current DMA transfer to complete */ + k_sem_take(&data->tx_dma_sync, K_FOREVER); + k_sem_take(&data->rx_dma_sync, K_FOREVER); + break; + case SPI_SMARTBOND_TRANSFER_TX_ONLY: + spi_smartbond_flush_rx_fifo(dev); + + data->tx_len = spi_context_max_continuous_chunk(ctx); + data->rx_len = data->tx_len; + + tx_block->block_size = data->tx_len * data->dfs; + tx_block->source_address = (uint32_t)ctx->tx_buf; + tx_block->source_addr_adj = 0x0; + + if (dma_config(config->tx_dma_ctrl, config->tx_dma_chan, tx) < 0) { + LOG_ERR("TX DMA configuration failed"); + return -EINVAL; + } + dma_start(config->tx_dma_ctrl, config->tx_dma_chan); + + /* Wait for the current DMA transfer to complete */ + k_sem_take(&data->tx_dma_sync, K_FOREVER); + break; + case SPI_SMARTBOND_TRANSFER_TX_RX: + spi_smartbond_flush_rx_fifo(dev); + + data->rx_len = spi_context_max_continuous_chunk(ctx); + data->tx_len = data->rx_len; + /* + * DMA block size represents total number of bytes whilist, + * context length is divided by the data size (dfs). + */ + tx_block->block_size = data->tx_len * data->dfs; + rx_block->block_size = tx_block->block_size; + + if (ctx->tx_buf) { + tx_block->source_address = (uint32_t)ctx->tx_buf; + tx_block->source_addr_adj = 0x0; + } else { + tx_block->source_address = (uint32_t)&spi_smartbond_read_dummy_buf; + tx_block->source_addr_adj = 0x2; + } + + if (ctx->rx_buf) { + rx_block->dest_address = (uint32_t)ctx->rx_buf; + rx_block->dest_addr_adj = 0x0; + } else { + rx_block->dest_address = (uint32_t)&spi_smartbond_read_dummy_buf; + rx_block->dest_addr_adj = 0x2; + } + + if (dma_config(config->tx_dma_ctrl, config->tx_dma_chan, tx) < 0) { + LOG_ERR("TX DMA configuration failed"); + return -EINVAL; + } + if (dma_config(config->rx_dma_ctrl, config->rx_dma_chan, rx) < 0) { + LOG_ERR("RX DMA configuration failed"); + return -EINVAL; + } + dma_start(config->rx_dma_ctrl, config->rx_dma_chan); + dma_start(config->tx_dma_ctrl, config->tx_dma_chan); + + k_sem_take(&data->tx_dma_sync, K_FOREVER); + k_sem_take(&data->rx_dma_sync, K_FOREVER); + + /* + * Regardless of whether or not the RX FIFO is enabled, received + * bytes are pushed into it. As such, the RXI FIFO should be + * flushed so that a next read access retrives the correct bytes + * and not old ones. + */ + if (!ctx->rx_buf) { + spi_smartbond_flush_rx_fifo(dev); + } + break; + case SPI_SMARTBOND_TRANSFER_NONE: + __fallthrough; + default: + __ASSERT_MSG_INFO("Invalid transfer mode"); + break; + } + + spi_smartbond_transfer_mode_check_and_update(dev); + } while (data->transfer_mode != SPI_SMARTBOND_TRANSFER_NONE); + + return 0; +} +#endif + static int spi_smartbond_transceive(const struct device *dev, const struct spi_config *spi_cfg, const struct spi_buf_set *tx_bufs, const struct spi_buf_set *rx_bufs) @@ -179,50 +1052,57 @@ static int spi_smartbond_transceive(const struct device *dev, const struct spi_c const struct spi_smartbond_cfg *cfg = dev->config; struct spi_smartbond_data *data = dev->data; struct spi_context *ctx = &data->ctx; - uint32_t bitmask; int rc; + spi_smartbond_pm_policy_state_lock_get(data); + spi_context_lock(&data->ctx, false, NULL, NULL, spi_cfg); + rc = spi_smartbond_configure(cfg, data, spi_cfg); if (rc == 0) { spi_context_buffers_setup(ctx, tx_bufs, rx_bufs, data->dfs); spi_context_cs_control(ctx, true); - bitmask = ~((~0UL) << SPI_WORD_SIZE_GET(data->ctx.config->operation)); +#ifdef CONFIG_SPI_SMARTBOND_DMA + rc = spi_smartbond_dma_trigger(dev); + /* Mark completion to trigger callback function */ + spi_context_complete(ctx, dev, 0); +#else while (spi_context_tx_buf_on(ctx) || spi_context_rx_buf_on(ctx)) { if (spi_context_tx_buf_on(ctx)) { - cfg->regs->SPI_RX_TX_REG = (*(uint32_t *)ctx->tx_buf) & bitmask; + spi_smartbond_write_word(dev); spi_context_update_tx(ctx, data->dfs, 1); } else { - cfg->regs->SPI_RX_TX_REG = 0UL; + spi_smartbond_write_dummy(dev); } while (!(cfg->regs->SPI_CTRL_REG & SPI_SPI_CTRL_REG_SPI_INT_BIT_Msk)) { }; if (spi_context_rx_buf_on(ctx)) { - (*(uint32_t *)ctx->rx_buf) = cfg->regs->SPI_RX_TX_REG & bitmask; + spi_smartbond_read_word(dev); spi_context_update_rx(ctx, data->dfs, 1); } else { - (void)cfg->regs->SPI_RX_TX_REG; + spi_smartbond_read_discard(dev); + /* + * It might happen that a NULL buffer with a non-zero length + * is provided. In that case, the bytes should be consumed. + */ + if (ctx->rx_len) { + spi_context_update_rx(ctx, data->dfs, 1); + } } cfg->regs->SPI_CLEAR_INT_REG = 1UL; } +#endif + + spi_context_cs_control(ctx, false); } - spi_context_cs_control(ctx, false); spi_context_release(&data->ctx, rc); + spi_smartbond_pm_policy_state_lock_put(data); + return rc; } -#ifdef CONFIG_SPI_ASYNC -static int spi_smartbond_transceive_async(const struct device *dev, - const struct spi_config *spi_cfg, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs, spi_callback_t cb, - void *userdata) -{ - return -ENOTSUP; -} -#endif static int spi_smartbond_release(const struct device *dev, const struct spi_config *spi_cfg) { @@ -247,7 +1127,7 @@ static const struct spi_driver_api spi_smartbond_driver_api = { .release = spi_smartbond_release, }; -static int spi_smartbond_init(const struct device *dev) +static int spi_smartbond_resume(const struct device *dev) { const struct spi_smartbond_cfg *cfg = dev->config; struct spi_smartbond_data *data = dev->data; @@ -268,24 +1148,190 @@ static int spi_smartbond_init(const struct device *dev) return rc; } +#ifdef CONFIG_SPI_SMARTBOND_DMA + rc = spi_smartbond_dma_config(dev); + if (rc < 0) { + LOG_ERR("Failed to configure DMA"); + return rc; + } +#endif + spi_context_unlock_unconditionally(&data->ctx); return 0; } +#if defined(CONFIG_PM_DEVICE) +static int spi_smartbond_suspend(const struct device *dev) +{ + int ret; + const struct spi_smartbond_cfg *config = dev->config; + struct spi_smartbond_data *data = dev->data; + + data->spi_ctrl_reg = config->regs->SPI_CTRL_REG; + /* Disable the SPI digital block */ + config->regs->SPI_CTRL_REG &= ~SPI_SPI_CTRL_REG_SPI_EN_CTRL_Msk; + /* Gate SPI clocking */ + CRG_COM->RESET_CLK_COM_REG = config->periph_clock_config; + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_SLEEP); + if (ret < 0) { + LOG_WRN("Failed to configure the SPI pins to inactive state"); + } + +#ifdef CONFIG_SPI_SMARTBOND_DMA + spi_smartbond_dma_deconfig(dev); +#endif + + return ret; +} + +static int spi_smartbond_pm_action(const struct device *dev, + enum pm_device_action action) +{ + int ret; + + switch (action) { + case PM_DEVICE_ACTION_RESUME: + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + ret = spi_smartbond_resume(dev); + break; + case PM_DEVICE_ACTION_SUSPEND: + ret = spi_smartbond_suspend(dev); + da1469x_pd_release(MCU_PD_DOMAIN_COM); + break; + default: + ret = -ENOTSUP; + } + + return ret; +} +#endif + +#define SPI_SMARTBOND_ISR_CONNECT \ + IRQ_CONNECT(DT_IRQN(DT_NODELABEL(spi)), DT_IRQ(DT_NODELABEL(spi), priority), \ + spi_smartbond_isr, DEVICE_DT_GET(DT_NODELABEL(spi)), 0); \ + irq_enable(DT_IRQN(DT_NODELABEL(spi))); + +#define SPI2_SMARTBOND_ISR_CONNECT \ + IRQ_CONNECT(DT_IRQN(DT_NODELABEL(spi2)), DT_IRQ(DT_NODELABEL(spi2), priority), \ + spi_smartbond_isr, DEVICE_DT_GET(DT_NODELABEL(spi2)), 0); \ + irq_enable(DT_IRQN(DT_NODELABEL(spi2))); + +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) +static int spi_smartbond_isr_connect(const struct device *dev) +{ + const struct spi_smartbond_cfg *cfg = dev->config; + + switch ((uint32_t)cfg->regs) { + case (uint32_t)SPI: + COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(spi), okay), + (SPI_SMARTBOND_ISR_CONNECT), (NULL)); + break; + case (uint32_t)SPI2: + COND_CODE_1(DT_NODE_HAS_STATUS(DT_NODELABEL(spi2), okay), + (SPI2_SMARTBOND_ISR_CONNECT), (NULL)); + break; + default: + return -EINVAL; + } + + return 0; +} +#endif + +static int spi_smartbond_init(const struct device *dev) +{ + int ret; + struct spi_smartbond_data *data = dev->data; + +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) + data->transfer_mode = SPI_SMARTBOND_TRANSFER_NONE; +#endif +#ifdef CONFIG_SPI_SMARTBOND_DMA + k_sem_init(&data->tx_dma_sync, 0, 1); + k_sem_init(&data->rx_dma_sync, 0, 1); +#endif + +#ifdef CONFIG_PM_DEVICE_RUNTIME + /* Make sure device state is marked as suspended */ + pm_device_init_suspended(dev); + + ret = pm_device_runtime_enable(dev); + +#else + da1469x_pd_acquire(MCU_PD_DOMAIN_COM); + ret = spi_smartbond_resume(dev); +#endif + spi_context_unlock_unconditionally(&data->ctx); + +#if defined(CONFIG_SPI_ASYNC) || defined(CONFIG_SPI_SMARTBOND_DMA) + ret = spi_smartbond_isr_connect(dev); +#endif + + return ret; +} + +#ifdef CONFIG_SPI_SMARTBOND_DMA +#define SPI_SMARTBOND_DMA_TX_INIT(id) \ + .tx_dma_chan = DT_INST_DMAS_CELL_BY_NAME(id, tx, channel), \ + .tx_slot_mux = (uint8_t)DT_INST_DMAS_CELL_BY_NAME(id, tx, config), \ + .tx_dma_ctrl = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(id, tx)), +#else +#define SPI_SMARTBOND_DMA_TX_INIT(id) +#endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA +#define SPI_SMARTBOND_DMA_RX_INIT(id) \ + .rx_dma_chan = DT_INST_DMAS_CELL_BY_NAME(id, rx, channel), \ + .rx_slot_mux = (uint8_t)DT_INST_DMAS_CELL_BY_NAME(id, rx, config), \ + .rx_dma_ctrl = DEVICE_DT_GET(DT_INST_DMAS_CTLR_BY_NAME(id, rx)), +#else +#define SPI_SMARTBOND_DMA_RX_INIT(id) +#endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA +#define SPI_SMARTBOND_DMA_TX_INVALIDATE(id) \ + .tx_dma_chan = 255, \ + .tx_slot_mux = 255, \ + .tx_dma_ctrl = NULL, +#else +#define SPI_SMARTBOND_DMA_TX_INVALIDATE(id) +#endif + +#ifdef CONFIG_SPI_SMARTBOND_DMA +#define SPI_SMARTBOND_DMA_RX_INVALIDATE(id) \ + .rx_dma_chan = 255, \ + .rx_slot_mux = 255, \ + .rx_dma_ctrl = NULL, +#else +#define SPI_SMARTBOND_DMA_RX_INVALIDATE(id) +#endif + #define SPI_SMARTBOND_DEVICE(id) \ PINCTRL_DT_INST_DEFINE(id); \ static const struct spi_smartbond_cfg spi_smartbond_##id##_cfg = { \ .regs = (SPI_Type *)DT_INST_REG_ADDR(id), \ .periph_clock_config = DT_INST_PROP(id, periph_clock_config), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(id), \ + COND_CODE_1(DT_INST_DMAS_HAS_NAME(id, tx), \ + (SPI_SMARTBOND_DMA_TX_INIT(id)), \ + (SPI_SMARTBOND_DMA_TX_INVALIDATE(id))) \ + COND_CODE_1(DT_INST_DMAS_HAS_NAME(id, rx), \ + (SPI_SMARTBOND_DMA_RX_INIT(id)), \ + (SPI_SMARTBOND_DMA_RX_INVALIDATE(id))) \ }; \ static struct spi_smartbond_data spi_smartbond_##id##_data = { \ SPI_CONTEXT_INIT_LOCK(spi_smartbond_##id##_data, ctx), \ SPI_CONTEXT_INIT_SYNC(spi_smartbond_##id##_data, ctx), \ SPI_CONTEXT_CS_GPIOS_INITIALIZE(DT_DRV_INST(id), ctx)}; \ - DEVICE_DT_INST_DEFINE(id, spi_smartbond_init, NULL, &spi_smartbond_##id##_data, \ - &spi_smartbond_##id##_cfg, POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ + PM_DEVICE_DT_INST_DEFINE(id, spi_smartbond_pm_action); \ + DEVICE_DT_INST_DEFINE(id, \ + spi_smartbond_init, \ + PM_DEVICE_DT_INST_GET(id), \ + &spi_smartbond_##id##_data, \ + &spi_smartbond_##id##_cfg, \ + POST_KERNEL, CONFIG_SPI_INIT_PRIORITY, \ &spi_smartbond_driver_api); DT_INST_FOREACH_STATUS_OKAY(SPI_SMARTBOND_DEVICE) diff --git a/drivers/timer/CMakeLists.txt b/drivers/timer/CMakeLists.txt index c44acda2ae6c6..ac5bac6c244ad 100644 --- a/drivers/timer/CMakeLists.txt +++ b/drivers/timer/CMakeLists.txt @@ -6,6 +6,7 @@ zephyr_library_sources_ifdef(CONFIG_ALTERA_AVALON_TIMER altera_avalon_timer_hal. zephyr_library_sources_ifdef(CONFIG_AMBIQ_STIMER_TIMER ambiq_stimer.c) zephyr_library_sources_ifdef(CONFIG_APIC_TIMER apic_timer.c) zephyr_library_sources_ifdef(CONFIG_APIC_TSC_DEADLINE_TIMER apic_tsc.c) +zephyr_library_sources_ifdef(CONFIG_APIC_TIMER_TSC apic_tsc.c) zephyr_library_sources_ifdef(CONFIG_ARCV2_TIMER arcv2_timer0.c) zephyr_library_sources_ifdef(CONFIG_ARM_ARCH_TIMER arm_arch_timer.c) zephyr_library_sources_ifdef(CONFIG_INTEL_ADSP_TIMER intel_adsp_timer.c) @@ -31,6 +32,8 @@ zephyr_library_sources_ifdef(CONFIG_RISCV_MACHINE_TIMER riscv_machine_timer.c) zephyr_library_sources_ifdef(CONFIG_RV32M1_LPTMR_TIMER rv32m1_lptmr_timer.c) zephyr_library_sources_ifdef(CONFIG_SAM0_RTC_TIMER sam0_rtc_timer.c) zephyr_library_sources_ifdef(CONFIG_STM32_LPTIM_TIMER stm32_lptim_timer.c) +zephyr_library_sources_ifdef(CONFIG_TI_DM_TIMER ti_dmtimer.c) zephyr_library_sources_ifdef(CONFIG_XLNX_PSTTC_TIMER xlnx_psttc_timer.c) zephyr_library_sources_ifdef(CONFIG_XTENSA_TIMER xtensa_sys_timer.c) zephyr_library_sources_ifdef(CONFIG_SMARTBOND_TIMER smartbond_timer.c) +zephyr_library_sources_ifdef(CONFIG_MTK_ADSP_TIMER mtk_adsp_timer.c) diff --git a/drivers/timer/Kconfig b/drivers/timer/Kconfig index 2ddfe321e77e4..3343f78d79ce0 100644 --- a/drivers/timer/Kconfig +++ b/drivers/timer/Kconfig @@ -92,8 +92,10 @@ source "drivers/timer/Kconfig.rv32m1_lptmr" source "drivers/timer/Kconfig.sam0_rtc" source "drivers/timer/Kconfig.smartbond" source "drivers/timer/Kconfig.stm32_lptim" +source "drivers/timer/Kconfig.ti_dm_timer" source "drivers/timer/Kconfig.xlnx_psttc" source "drivers/timer/Kconfig.xtensa" +source "drivers/timer/Kconfig.mtk_adsp" endmenu diff --git a/drivers/timer/Kconfig.esp32 b/drivers/timer/Kconfig.esp32 index 0d45987c726db..4dd289287e205 100644 --- a/drivers/timer/Kconfig.esp32 +++ b/drivers/timer/Kconfig.esp32 @@ -5,10 +5,11 @@ config ESP32_SYS_TIMER bool "ESP32 sys-timer support (ESP32Cx series)" - depends on SOC_SERIES_ESP32C3 + depends on SOC_SERIES_ESP32C3 || SOC_SERIES_ESP32C6 default y select TICKLESS_CAPABLE select TIMER_HAS_64BIT_CYCLE_COUNTER + select SYSTEM_TIMER_HAS_DISABLE_SUPPORT help This option enables the system timer driver for the Espressif ESP32Cx and provides the standard "system clock driver" interface. diff --git a/drivers/timer/Kconfig.mcux_lptmr b/drivers/timer/Kconfig.mcux_lptmr index 8879cb3b558c4..851c49ebbfb6f 100644 --- a/drivers/timer/Kconfig.mcux_lptmr +++ b/drivers/timer/Kconfig.mcux_lptmr @@ -6,11 +6,21 @@ config MCUX_LPTMR_TIMER bool "MCUX LPTMR timer" default y - depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED + depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED || \ + MCUX_KINETIS_LPTMR depends on !COUNTER_MCUX_LPTMR - depends on PM select SYSTEM_TIMER_HAS_DISABLE_SUPPORT help This module implements a kernel device driver for the NXP MCUX Low Power Timer (LPTMR) and provides the standard "system clock driver" interfaces. + +config MCUX_KINETIS_LPTMR + bool + default y + depends on DT_HAS_NXP_KINETIS_LPTMR_ENABLED + select DEPRECATED + help + The compatible string "nxp,kinetis-lptmr" should + be swiched to "nxp,lptmr" in DT. The former will + be removed eventually. diff --git a/drivers/timer/Kconfig.mtk_adsp b/drivers/timer/Kconfig.mtk_adsp new file mode 100644 index 0000000000000..d3b7501e3071e --- /dev/null +++ b/drivers/timer/Kconfig.mtk_adsp @@ -0,0 +1,11 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +config MTK_ADSP_TIMER + bool "MediaTek Audio DSP timer" + select TICKLESS_CAPABLE + select TIMER_HAS_64BIT_CYCLE_COUNTER + select SYSTEM_CLOCK_LOCK_FREE_COUNT + help + MediaTek MT81xx Audio DSPs have a 13 Mhz wall clock timer + for system time that is independent of CPU speed. diff --git a/drivers/timer/Kconfig.nrf_grtc b/drivers/timer/Kconfig.nrf_grtc index 0436c071fa200..b136f65425236 100644 --- a/drivers/timer/Kconfig.nrf_grtc +++ b/drivers/timer/Kconfig.nrf_grtc @@ -41,9 +41,20 @@ config NRF_GRTC_TIMER_CLOCK_MANAGEMENT the GRTC. Usually this is only needed by the processor that is starting the SYSCOUNTER, but can be shared by multiple processors in the system. -config NRF_GRTC_SLEEP_MINIMUM_LATENCY +config NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY int default 1000 depends on NRF_GRTC_SLEEP_ALLOWED + help + The value (in us) ensures that the wakeup event will not fire + too early. In other words, applying SYSCOUNTER sleep state for less than + NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY period makes no sense. + +config NRF_GRTC_TIMER_AUTO_KEEP_ALIVE + bool + default y if NRF_GRTC_START_SYSCOUNTER + help + This feature prevents the SYSCOUNTER from sleeping when any core is in + active state. endif # NRF_GRTC_TIMER diff --git a/drivers/timer/Kconfig.ti_dm_timer b/drivers/timer/Kconfig.ti_dm_timer new file mode 100644 index 0000000000000..42b86e5c6ef8f --- /dev/null +++ b/drivers/timer/Kconfig.ti_dm_timer @@ -0,0 +1,13 @@ +# Copyright (C) 2023 BeagleBoard.org Foundation +# Copyright (C) 2023 S Prashanth +# +# SPDX-License-Identifier: Apache-2.0 + +config TI_DM_TIMER + bool "TI Dual-Mode Timer" + default y + depends on DT_HAS_TI_AM654_TIMER_ENABLED + select TICKLESS_CAPABLE + help + This module implements a kernel device driver for TI Dual-Mode timer. This + driver provides system tick interface. diff --git a/drivers/timer/Kconfig.x86 b/drivers/timer/Kconfig.x86 index ea6d4a216b7d4..436439838f6eb 100644 --- a/drivers/timer/Kconfig.x86 +++ b/drivers/timer/Kconfig.x86 @@ -26,10 +26,10 @@ config HPET_TIMER config APIC_TIMER bool "Local APIC timer" select LOAPIC - select TICKLESS_CAPABLE + select TIMER_HAS_64BIT_CYCLE_COUNTER select SYSTEM_CLOCK_LOCK_FREE_COUNT help - Use the x86 local APIC in one-shot mode as the system time + Use the x86 local APIC in periodic mode as the system time source. NOTE: this probably isn't what you want except on older or idiosyncratic hardware (or environments like qemu without complete APIC emulation). Modern hardware will work @@ -51,6 +51,19 @@ config APIC_TSC_DEADLINE_TIMER choice for any x86 device with invariant TSC and TSC deadline capability. +config APIC_TIMER_TSC + bool "Local APIC timer using TSC time source" + depends on !SMP + select LOAPIC + select TICKLESS_CAPABLE + select TIMER_HAS_64BIT_CYCLE_COUNTER + help + If your CPU supports invariant TSC but no TSC deadline capability + then this choice will rely on the TSC as time source and the + local APIC in one-shot mode as the timeout event source. + You must know the ratio of the TSC frequency to the local APIC + timer frequency. + endchoice if APIC_TIMER @@ -66,14 +79,7 @@ config APIC_TIMER_IRQ user-configurable and almost certainly should be managed via a different mechanism. -config APIC_TIMER_TSC - bool "Use invariant TSC for sys_clock_cycle_get_32()" - select TIMER_HAS_64BIT_CYCLE_COUNTER - help - If your CPU supports invariant TSC, and you know the ratio of the - TSC frequency to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC (the local APIC - timer frequency), then enable this for a much faster and more - accurate sys_clock_cycle_get_32(). +endif # APIC_TIMER if APIC_TIMER_TSC @@ -87,11 +93,9 @@ config APIC_TIMER_TSC_M endif # APIC_TIMER_TSC -endif # APIC_TIMER - config APIC_TIMER_IRQ_PRIORITY int "Local APIC timer interrupt priority" - depends on APIC_TIMER || APIC_TSC_DEADLINE_TIMER + depends on APIC_TIMER || APIC_TSC_DEADLINE_TIMER || APIC_TIMER_TSC default 4 help This option specifies the interrupt priority used by the diff --git a/drivers/timer/ambiq_stimer.c b/drivers/timer/ambiq_stimer.c index e2c9d9976f471..e0cfa948aa13d 100644 --- a/drivers/timer/ambiq_stimer.c +++ b/drivers/timer/ambiq_stimer.c @@ -35,12 +35,41 @@ const int32_t z_sys_timer_irq_for_test = TIMER_IRQ; #endif -/* Value of STIMER counter when the previous kernel tick was announced */ -static atomic_t g_last_count; +/* Elapsed ticks since the previous kernel tick was announced, It will get accumulated every time + * stimer_isr is triggered, or sys_clock_set_timeout/sys_clock_elapsed API is called. + * It will be cleared after sys_clock_announce is called,. + */ +static uint32_t g_tick_elapsed; + +/* Value of STIMER counter when the previous timer API is called, this value is + * aligned to tick boundary. It is updated along with the g_tick_elapsed value. + */ +static uint32_t g_last_time_stamp; /* Spinlock to sync between Compare ISR and update of Compare register */ static struct k_spinlock g_lock; +static void update_tick_counter(void) +{ + /* Read current cycle count. */ + uint32_t now = am_hal_stimer_counter_get(); + + /* If current cycle count is smaller than the last time stamp, a counter overflow happened. + * We need to extend the current counter value to 64 bits and add it with 0xFFFFFFFF + * to get the correct elapsed cycles. + */ + uint64_t now_64 = (g_last_time_stamp <= now) ? (uint64_t)now : (uint64_t)now + COUNTER_MAX; + + /* Get elapsed cycles */ + uint32_t elapsed_cycle = (now_64 - g_last_time_stamp); + + /* Get elapsed ticks. */ + uint32_t dticks = elapsed_cycle / CYC_PER_TICK; + + g_last_time_stamp += dticks * CYC_PER_TICK; + g_tick_elapsed += dticks; +} + static void stimer_isr(const void *arg) { ARG_UNUSED(arg); @@ -52,22 +81,34 @@ static void stimer_isr(const void *arg) k_spinlock_key_t key = k_spin_lock(&g_lock); - uint32_t now = am_hal_stimer_counter_get(); - uint32_t dticks = (uint32_t)((now - g_last_count) / CYC_PER_TICK); - - g_last_count += dticks * CYC_PER_TICK; + /*Calculate the elapsed ticks based on the current cycle count*/ + update_tick_counter(); if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - uint32_t next = g_last_count + CYC_PER_TICK; - if ((int32_t)(next - now) < MIN_DELAY) { - next += CYC_PER_TICK; - } - am_hal_stimer_compare_delta_set(0, next - g_last_count); + /* Get the counter value to trigger the next tick interrupt. */ + uint64_t next = (uint64_t)g_last_time_stamp + CYC_PER_TICK; + + /* Read current cycle count. */ + uint32_t now = am_hal_stimer_counter_get(); + + /* If current cycle count is smaller than the last time stamp, a counter + * overflow happened. We need to extend the current counter value to 64 bits + * and add 0xFFFFFFFF to get the correct elapsed cycles. + */ + uint64_t now_64 = (g_last_time_stamp <= now) ? (uint64_t)now + : (uint64_t)now + COUNTER_MAX; + + uint32_t delta = (now_64 + MIN_DELAY < next) ? (next - now_64) : MIN_DELAY; + + /* Set delta. */ + am_hal_stimer_compare_delta_set(0, delta); } k_spin_unlock(&g_lock, key); - sys_clock_announce(dticks); + + sys_clock_announce(g_tick_elapsed); + g_tick_elapsed = 0; } } @@ -79,17 +120,40 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) return; } - if (ticks == K_TICKS_FOREVER) { - return; - } - - ticks = MIN(MAX_TICKS, ticks); - /* If tick is 0, set delta cyc to MIN_DELAY to trigger tick isr asap */ - uint32_t cyc = MAX(ticks * CYC_PER_TICK, MIN_DELAY); + /* Adjust the ticks to the range of [1, MAX_TICKS]. */ + ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks; + ticks = CLAMP(ticks, 1, (int32_t)MAX_TICKS); k_spinlock_key_t key = k_spin_lock(&g_lock); - am_hal_stimer_compare_delta_set(0, cyc); + /* Update the internal tick counter*/ + update_tick_counter(); + + /* Get current hardware counter value.*/ + uint32_t now = am_hal_stimer_counter_get(); + + /* last: the last recorded counter value. + * now_64: current counter value. Extended to uint64_t to easy the handing of hardware + * counter overflow. + * next: counter values where to trigger the scheduled timeout. + * last < now_64 < next + */ + uint64_t last = (uint64_t)g_last_time_stamp; + uint64_t now_64 = (g_last_time_stamp <= now) ? (uint64_t)now : (uint64_t)now + COUNTER_MAX; + uint64_t next = now_64 + ticks * CYC_PER_TICK; + + uint32_t gap = next - last; + uint32_t gap_aligned = (gap / CYC_PER_TICK) * CYC_PER_TICK; + uint64_t next_aligned = last + gap_aligned; + + uint32_t delta = next_aligned - now_64; + + if (delta <= MIN_DELAY) { + /*If the delta value is smaller than MIN_DELAY, trigger a interrupt immediately*/ + am_hal_stimer_int_set(AM_HAL_STIMER_INT_COMPAREA); + } else { + am_hal_stimer_compare_delta_set(0, delta); + } k_spin_unlock(&g_lock, key); } @@ -101,10 +165,10 @@ uint32_t sys_clock_elapsed(void) } k_spinlock_key_t key = k_spin_lock(&g_lock); - uint32_t ret = (am_hal_stimer_counter_get() - g_last_count) / CYC_PER_TICK; - + update_tick_counter(); k_spin_unlock(&g_lock, key); - return ret; + + return g_tick_elapsed; } uint32_t sys_clock_cycle_get_32(void) @@ -115,7 +179,6 @@ uint32_t sys_clock_cycle_get_32(void) static int stimer_init(void) { uint32_t oldCfg; - k_spinlock_key_t key = k_spin_lock(&g_lock); oldCfg = am_hal_stimer_config(AM_HAL_STIMER_CFG_FREEZE); @@ -126,9 +189,7 @@ static int stimer_init(void) am_hal_stimer_config((oldCfg & ~(AM_HAL_STIMER_CFG_FREEZE | STIMER_STCFG_CLKSEL_Msk)) | AM_HAL_STIMER_XTAL_32KHZ | AM_HAL_STIMER_CFG_COMPARE_A_ENABLE); #endif - g_last_count = am_hal_stimer_counter_get(); - - k_spin_unlock(&g_lock, key); + g_last_time_stamp = am_hal_stimer_counter_get(); NVIC_ClearPendingIRQ(TIMER_IRQ); IRQ_CONNECT(TIMER_IRQ, 0, stimer_isr, 0, 0); diff --git a/drivers/timer/apic_timer.c b/drivers/timer/apic_timer.c index cf28acb04d93e..2c16ba749000b 100644 --- a/drivers/timer/apic_timer.c +++ b/drivers/timer/apic_timer.c @@ -10,18 +10,14 @@ #include #include -BUILD_ASSERT(!IS_ENABLED(CONFIG_SMP), "APIC timer doesn't support SMP"); +BUILD_ASSERT(!IS_ENABLED(CONFIG_TICKLESS_KERNEL), "this is a tickfull driver"); /* * Overview: * * This driver enables the local APIC as the Zephyr system timer. It supports - * both legacy ("tickful") mode as well as TICKLESS_KERNEL. The driver will - * work with any APIC that has the ARAT "always running APIC timer" feature - * (CPUID 0x06, EAX bit 2); for the more accurate sys_clock_cycle_get_32(), - * the invariant TSC feature (CPUID 0x80000007: EDX bit 8) is also required. - * (Ultimately systems with invariant TSCs should use a TSC-based driver, - * and the TSC-related parts should be stripped from this implementation.) + * legacy ("tickful") mode only. The driver will work with any APIC that has + * the ARAT "always running APIC timer" feature (CPUID 0x06, EAX bit 2). * * Configuration: * @@ -31,15 +27,6 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_SMP), "APIC timer doesn't support SMP"); * * CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC= must contain the frequency seen * by the local APIC timer block (before it gets to the timer divider). - * - * CONFIG_APIC_TIMER_TSC=y enables the more accurate TSC-based cycle counter - * for sys_clock_cycle_get_32(). This also requires the next options be set. - * - * CONFIG_APIC_TIMER_TSC_N= - * CONFIG_APIC_TIMER_TSC_M= - * When CONFIG_APIC_TIMER_TSC=y, these are set to indicate the ratio of - * the TSC frequency to CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC. This can be - * found via CPUID 0x15 (n = EBX, m = EAX) on most CPUs. */ /* These should be merged into include/drivers/interrupt_controller/loapic.h. */ @@ -47,139 +34,24 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_SMP), "APIC timer doesn't support SMP"); #define DCR_DIVIDER_MASK 0x0000000F /* divider bits */ #define DCR_DIVIDER 0x0000000B /* divide by 1 */ #define LVT_MODE_MASK 0x00060000 /* timer mode bits */ -#define LVT_MODE 0x00000000 /* one-shot */ +#define LVT_MODE 0x00020000 /* periodic mode */ #if defined(CONFIG_TEST) const int32_t z_sys_timer_irq_for_test = CONFIG_APIC_TIMER_IRQ; #endif -/* - * CYCLES_PER_TICK must always be at least '2', otherwise MAX_TICKS - * will overflow int32_t, which is how 'ticks' are currently represented. - */ #define CYCLES_PER_TICK \ (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC / CONFIG_SYS_CLOCK_TICKS_PER_SEC) -BUILD_ASSERT(CYCLES_PER_TICK >= 2, "APIC timer: bad CYCLES_PER_TICK"); - -/* max number of ticks we can load into the timer in one shot */ - -#define MAX_TICKS (0xFFFFFFFFU / CYCLES_PER_TICK) - -/* - * The spinlock protects all access to the local APIC timer registers, - * as well as 'total_cycles', 'last_announcement', and 'cached_icr'. - * - * One important invariant that must be observed: `total_cycles` + `cached_icr` - * is always an integral multiple of CYCLE_PER_TICK; this is, timer interrupts - * are only ever scheduled to occur at tick boundaries. - */ - -static struct k_spinlock lock; -static uint64_t total_cycles; -static uint32_t cached_icr = CYCLES_PER_TICK; +BUILD_ASSERT(CYCLES_PER_TICK >= 1, "APIC timer: bad CYCLES_PER_TICK"); -#ifdef CONFIG_TICKLESS_KERNEL - -static uint64_t last_announcement; /* last time we called sys_clock_announce() */ - -void sys_clock_set_timeout(int32_t n, bool idle) -{ - ARG_UNUSED(idle); - - uint32_t ccr; - int full_ticks; /* number of complete ticks we'll wait */ - uint32_t full_cycles; /* full_ticks represented as cycles */ - uint32_t partial_cycles; /* number of cycles to first tick boundary */ - - if (n < 1) { - full_ticks = 0; - } else if ((n == K_TICKS_FOREVER) || (n > MAX_TICKS)) { - full_ticks = MAX_TICKS - 1; - } else { - full_ticks = n - 1; - } - - full_cycles = full_ticks * CYCLES_PER_TICK; - - /* - * There's a wee race condition here. The timer may expire while - * we're busy reprogramming it; an interrupt will be queued at the - * local APIC and the ISR will be called too early, roughly right - * after we unlock, and not because the count we just programmed has - * counted down. Luckily this situation is easy to detect, which is - * why the ISR actually checks to be sure the CCR is 0 before acting. - */ - - k_spinlock_key_t key = k_spin_lock(&lock); - - ccr = x86_read_loapic(LOAPIC_TIMER_CCR); - total_cycles += (cached_icr - ccr); - partial_cycles = CYCLES_PER_TICK - (total_cycles % CYCLES_PER_TICK); - cached_icr = full_cycles + partial_cycles; - x86_write_loapic(LOAPIC_TIMER_ICR, cached_icr); - - k_spin_unlock(&lock, key); -} - -uint32_t sys_clock_elapsed(void) -{ - uint32_t ccr; - uint32_t ticks; - - k_spinlock_key_t key = k_spin_lock(&lock); - ccr = x86_read_loapic(LOAPIC_TIMER_CCR); - ticks = total_cycles - last_announcement; - ticks += cached_icr - ccr; - k_spin_unlock(&lock, key); - ticks /= CYCLES_PER_TICK; - - return ticks; -} +static volatile uint64_t total_cycles; static void isr(const void *arg) { ARG_UNUSED(arg); - uint32_t cycles; - int32_t ticks; - - k_spinlock_key_t key = k_spin_lock(&lock); - - /* - * If we get here and the CCR isn't zero, then this interrupt is - * stale: it was queued while sys_clock_set_timeout() was setting - * a new counter. Just ignore it. See above for more info. - */ - - if (x86_read_loapic(LOAPIC_TIMER_CCR) != 0) { - k_spin_unlock(&lock, key); - return; - } - - /* Restart the timer as early as possible to minimize drift... */ - x86_write_loapic(LOAPIC_TIMER_ICR, MAX_TICKS * CYCLES_PER_TICK); - - cycles = cached_icr; - cached_icr = MAX_TICKS * CYCLES_PER_TICK; - total_cycles += cycles; - ticks = (total_cycles - last_announcement) / CYCLES_PER_TICK; - last_announcement = total_cycles; - k_spin_unlock(&lock, key); - sys_clock_announce(ticks); -} - -#else - -static void isr(const void *arg) -{ - ARG_UNUSED(arg); - - k_spinlock_key_t key = k_spin_lock(&lock); total_cycles += CYCLES_PER_TICK; - x86_write_loapic(LOAPIC_TIMER_ICR, cached_icr); - k_spin_unlock(&lock, key); - sys_clock_announce(1); } @@ -188,36 +60,32 @@ uint32_t sys_clock_elapsed(void) return 0U; } -#endif /* CONFIG_TICKLESS_KERNEL */ - -#ifdef CONFIG_APIC_TIMER_TSC - -uint32_t sys_clock_cycle_get_32(void) +uint64_t sys_clock_cycle_get_64(void) { - uint64_t tsc = z_tsc_read(); - uint32_t cycles; - - cycles = (tsc * CONFIG_APIC_TIMER_TSC_M) / CONFIG_APIC_TIMER_TSC_N; - return cycles; + uint32_t ccr_1st, ccr_2nd; + uint64_t cycles; + + /* + * We may race with CCR reaching 0 and reloading, and the interrupt + * handler updating total_cycles. Let's make sure we sample everything + * away from this roll-over transition by ensuring consecutive CCR + * values are descending so we're sure the enclosed (volatile) + * total_cycles sample and CCR value are coherent with each other. + */ + do { + ccr_1st = x86_read_loapic(LOAPIC_TIMER_CCR); + cycles = total_cycles; + ccr_2nd = x86_read_loapic(LOAPIC_TIMER_CCR); + } while (ccr_2nd > ccr_1st); + + return cycles + (CYCLES_PER_TICK - ccr_2nd); } -#else - uint32_t sys_clock_cycle_get_32(void) { - uint32_t ret; - uint32_t ccr; - - k_spinlock_key_t key = k_spin_lock(&lock); - ccr = x86_read_loapic(LOAPIC_TIMER_CCR); - ret = total_cycles + (cached_icr - ccr); - k_spin_unlock(&lock, key); - - return ret; + return (uint32_t)sys_clock_cycle_get_64(); } -#endif - static int sys_clock_driver_init(void) { uint32_t val; @@ -239,7 +107,7 @@ static int sys_clock_driver_init(void) CONFIG_APIC_TIMER_IRQ_PRIORITY, isr, 0, 0); - x86_write_loapic(LOAPIC_TIMER_ICR, cached_icr); + x86_write_loapic(LOAPIC_TIMER_ICR, CYCLES_PER_TICK); irq_enable(CONFIG_APIC_TIMER_IRQ); return 0; diff --git a/drivers/timer/apic_tsc.c b/drivers/timer/apic_tsc.c index 59b0017375c3d..0c617a01ca789 100644 --- a/drivers/timer/apic_tsc.c +++ b/drivers/timer/apic_tsc.c @@ -2,18 +2,82 @@ * Copyright (c) 2021 Intel Corporation * SPDX-License-Identifier: Apache-2.0 */ + +#include /* Header provided by the toolchain. */ + #include +#include #include #include #include #include #include +/* + * This driver is selected when either CONFIG_APIC_TIMER_TSC or + * CONFIG_APIC_TSC_DEADLINE_TIMER is selected. The later is preferred over + * the former when the TSC deadline comparator is available. + */ +BUILD_ASSERT((!IS_ENABLED(CONFIG_APIC_TIMER_TSC) && + IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER)) || + (!IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER) && + IS_ENABLED(CONFIG_APIC_TIMER_TSC)), + "one of CONFIG_APIC_TIMER_TSC or CONFIG_APIC_TSC_DEADLINE_TIMER must be set"); + +/* + * If the TSC deadline comparator is not supported then the ICR in one-shot + * mode is used as a fallback method to trigger the next timeout interrupt. + * Those config symbols must then be defined: + * + * CONFIG_APIC_TIMER_TSC_N= + * CONFIG_APIC_TIMER_TSC_M= + * + * These are set to indicate the ratio of the TSC frequency to the local + * APIC timer frequency. This can be found via CPUID 0x15 (n = EBX, m = EAX) + * on most CPUs. + */ +#ifdef CONFIG_APIC_TIMER_TSC +#define APIC_TIMER_TSC_M CONFIG_APIC_TIMER_TSC_M +#define APIC_TIMER_TSC_N CONFIG_APIC_TIMER_TSC_N +#else +#define APIC_TIMER_TSC_M 1 +#define APIC_TIMER_TSC_N 1 +#endif + #define IA32_TSC_DEADLINE_MSR 0x6e0 #define IA32_TSC_ADJUST_MSR 0x03b -#define CYC_PER_TICK (CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \ - / (uint64_t) CONFIG_SYS_CLOCK_TICKS_PER_SEC) +#define CYC_PER_TICK (uint32_t)(CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC \ + / CONFIG_SYS_CLOCK_TICKS_PER_SEC) + +/* the unsigned long cast limits divisors to native CPU register width */ +#define cycle_diff_t unsigned long +#define CYCLE_DIFF_MAX (~(cycle_diff_t)0) + +/* + * We have two constraints on the maximum number of cycles we can wait for. + * + * 1) sys_clock_announce() accepts at most INT32_MAX ticks. + * + * 2) The number of cycles between two reports must fit in a cycle_diff_t + * variable before converting it to ticks. + * + * Then: + * + * 3) Pick the smallest between (1) and (2). + * + * 4) Take into account some room for the unavoidable IRQ servicing latency. + * Let's use 3/4 of the max range. + * + * Finally let's add the LSB value to the result so to clear out a bunch of + * consecutive set bits coming from the original max values to produce a + * nicer literal for assembly generation. + */ +#define CYCLES_MAX_1 ((uint64_t)INT32_MAX * (uint64_t)CYC_PER_TICK) +#define CYCLES_MAX_2 ((uint64_t)CYCLE_DIFF_MAX) +#define CYCLES_MAX_3 MIN(CYCLES_MAX_1, CYCLES_MAX_2) +#define CYCLES_MAX_4 (CYCLES_MAX_3 / 2 + CYCLES_MAX_3 / 4) +#define CYCLES_MAX (CYCLES_MAX_4 + LSB_GET(CYCLES_MAX_4)) struct apic_timer_lvt { uint8_t vector : 8; @@ -24,7 +88,9 @@ struct apic_timer_lvt { }; static struct k_spinlock lock; -static uint64_t last_announce; +static uint64_t last_cycle; +static uint64_t last_tick; +static uint32_t last_elapsed; static union { uint32_t val; struct apic_timer_lvt lvt; } lvt_reg; static ALWAYS_INLINE uint64_t rdtsc(void) @@ -35,41 +101,74 @@ static ALWAYS_INLINE uint64_t rdtsc(void) return lo + (((uint64_t)hi) << 32); } +static inline void wrmsr(int32_t msr, uint64_t val) +{ + uint32_t hi = (uint32_t) (val >> 32); + uint32_t lo = (uint32_t) val; + + __asm__ volatile("wrmsr" :: "d"(hi), "a"(lo), "c"(msr)); +} + +static void set_trigger(uint64_t deadline) +{ + if (IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER)) { + wrmsr(IA32_TSC_DEADLINE_MSR, deadline); + } else { + /* use the timer ICR to trigger next interrupt */ + uint64_t curr_cycle = rdtsc(); + uint64_t delta_cycles = deadline - MIN(deadline, curr_cycle); + uint64_t icr = (delta_cycles * APIC_TIMER_TSC_M) / APIC_TIMER_TSC_N; + + /* cap icr to 32 bits, and not zero */ + icr = CLAMP(icr, 1, UINT32_MAX); + x86_write_loapic(LOAPIC_TIMER_ICR, icr); + } +} + static void isr(const void *arg) { ARG_UNUSED(arg); + k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t ticks = (rdtsc() - last_announce) / CYC_PER_TICK; + uint64_t curr_cycle = rdtsc(); + uint64_t delta_cycles = curr_cycle - last_cycle; + uint32_t delta_ticks = (cycle_diff_t)delta_cycles / CYC_PER_TICK; - last_announce += ticks * CYC_PER_TICK; - k_spin_unlock(&lock, key); - sys_clock_announce(ticks); + last_cycle += (cycle_diff_t)delta_ticks * CYC_PER_TICK; + last_tick += delta_ticks; + last_elapsed = 0; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - sys_clock_set_timeout(1, false); - } -} + uint64_t next_cycle = last_cycle + CYC_PER_TICK; -static inline void wrmsr(int32_t msr, uint64_t val) -{ - uint32_t hi = (uint32_t) (val >> 32); - uint32_t lo = (uint32_t) val; + set_trigger(next_cycle); + } - __asm__ volatile("wrmsr" :: "d"(hi), "a"(lo), "c"(msr)); + k_spin_unlock(&lock, key); + sys_clock_announce(delta_ticks); } void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); - uint64_t now = rdtsc(); - k_spinlock_key_t key = k_spin_lock(&lock); - uint64_t expires = now + MAX(ticks - 1, 0) * CYC_PER_TICK; + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + return; + } - expires = last_announce + (((expires - last_announce + CYC_PER_TICK - 1) - / CYC_PER_TICK) * CYC_PER_TICK); + k_spinlock_key_t key = k_spin_lock(&lock); + uint64_t next_cycle; + + if (ticks == K_TICKS_FOREVER) { + next_cycle = last_cycle + CYCLES_MAX; + } else { + next_cycle = (last_tick + last_elapsed + ticks) * CYC_PER_TICK; + if ((next_cycle - last_cycle) > CYCLES_MAX) { + next_cycle = last_cycle + CYCLES_MAX; + } + } - /* The second condition is to catch the wraparound. + /* * Interpreted strictly, the IA SDM description of the * TSC_DEADLINE MSR implies that it will trigger an immediate * interrupt if we try to set an expiration across the 64 bit @@ -77,21 +176,28 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) * real hardware it requires more than a century of uptime, * but this is cheap and safe. */ - if (ticks == K_TICKS_FOREVER || expires < last_announce) { - expires = UINT64_MAX; + if (next_cycle < last_cycle) { + next_cycle = UINT64_MAX; } + set_trigger(next_cycle); - wrmsr(IA32_TSC_DEADLINE_MSR, expires); k_spin_unlock(&lock, key); } uint32_t sys_clock_elapsed(void) { + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + return 0; + } + k_spinlock_key_t key = k_spin_lock(&lock); - uint32_t ret = (rdtsc() - last_announce) / CYC_PER_TICK; + uint64_t curr_cycle = rdtsc(); + uint64_t delta_cycles = curr_cycle - last_cycle; + uint32_t delta_ticks = (cycle_diff_t)delta_cycles / CYC_PER_TICK; + last_elapsed = delta_ticks; k_spin_unlock(&lock, key); - return ret; + return delta_ticks; } uint32_t sys_clock_cycle_get_32(void) @@ -149,40 +255,49 @@ void smp_timer_init(void) irq_enable(timer_irq()); } -static inline void cpuid(uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) -{ - __asm__ volatile("cpuid" - : "=b"(*ebx), "=c"(*ecx), "=d"(*edx) - : "a"(*eax), "c"(*ecx)); -} - static int sys_clock_driver_init(void) { #ifdef CONFIG_ASSERT uint32_t eax, ebx, ecx, edx; - eax = 1; ecx = 0; - cpuid(&eax, &ebx, &ecx, &edx); - __ASSERT((ecx & BIT(24)) != 0, "No TSC Deadline support"); + if (IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER)) { + ecx = 0; /* prevent compiler warning */ + __get_cpuid(CPUID_BASIC_INFO_1, &eax, &ebx, &ecx, &edx); + __ASSERT((ecx & BIT(24)) != 0, "No TSC Deadline support"); + } - eax = 0x80000007; ecx = 0; - cpuid(&eax, &ebx, &ecx, &edx); + edx = 0; /* prevent compiler warning */ + __get_cpuid(0x80000007, &eax, &ebx, &ecx, &edx); __ASSERT((edx & BIT(8)) != 0, "No Invariant TSC support"); - eax = 7; ecx = 0; - cpuid(&eax, &ebx, &ecx, &edx); - __ASSERT((ebx & BIT(1)) != 0, "No TSC_ADJUST MSR support"); + if (IS_ENABLED(CONFIG_SMP)) { + ebx = 0; /* prevent compiler warning */ + __get_cpuid_count(CPUID_EXTENDED_FEATURES_LVL, 0, &eax, &ebx, &ecx, &edx); + __ASSERT((ebx & BIT(1)) != 0, "No TSC_ADJUST MSR support"); + } #endif - clear_tsc_adjust(); + if (IS_ENABLED(CONFIG_SMP)) { + clear_tsc_adjust(); + } /* Timer interrupt number is runtime-fetched, so can't use * static IRQ_CONNECT() */ irq_connect_dynamic(timer_irq(), CONFIG_APIC_TIMER_IRQ_PRIORITY, isr, 0, 0); + if (IS_ENABLED(CONFIG_APIC_TIMER_TSC)) { + uint32_t timer_conf; + + timer_conf = x86_read_loapic(LOAPIC_TIMER_CONFIG); + timer_conf &= ~0x0f; /* clear divider bits */ + timer_conf |= 0x0b; /* divide by 1 */ + x86_write_loapic(LOAPIC_TIMER_CONFIG, timer_conf); + } + lvt_reg.val = x86_read_loapic(LOAPIC_TIMER); - lvt_reg.lvt.mode = TSC_DEADLINE; + lvt_reg.lvt.mode = IS_ENABLED(CONFIG_APIC_TSC_DEADLINE_TIMER) ? + TSC_DEADLINE : ONE_SHOT; lvt_reg.lvt.masked = 0; x86_write_loapic(LOAPIC_TIMER, lvt_reg.val); @@ -193,12 +308,12 @@ static int sys_clock_driver_init(void) */ __asm__ volatile("mfence" ::: "memory"); - last_announce = rdtsc(); - irq_enable(timer_irq()); - + last_tick = rdtsc() / CYC_PER_TICK; + last_cycle = last_tick * CYC_PER_TICK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - sys_clock_set_timeout(1, false); + set_trigger(last_cycle + CYC_PER_TICK); } + irq_enable(timer_irq()); return 0; } diff --git a/drivers/timer/esp32_sys_timer.c b/drivers/timer/esp32_sys_timer.c index 040807299116e..2eeb71d1524e2 100644 --- a/drivers/timer/esp32_sys_timer.c +++ b/drivers/timer/esp32_sys_timer.c @@ -5,9 +5,7 @@ */ #include #include -#include -#include -#include + #include #include #include @@ -136,6 +134,13 @@ uint64_t sys_clock_cycle_get_64(void) return get_systimer_alarm(); } +void sys_clock_disable(void) +{ + systimer_ll_enable_alarm(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, false); + systimer_ll_enable_alarm_int(systimer_hal.dev, SYSTIMER_ALARM_OS_TICK_CORE0, false); + systimer_hal_deinit(&systimer_hal); +} + static int sys_clock_driver_init(void) { @@ -156,5 +161,5 @@ static int sys_clock_driver_init(void) return 0; } -SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_1, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/intel_adsp_timer.c b/drivers/timer/intel_adsp_timer.c index d1f37b123c2c2..2636e506bfe0a 100644 --- a/drivers/timer/intel_adsp_timer.c +++ b/drivers/timer/intel_adsp_timer.c @@ -212,7 +212,6 @@ void smp_timer_init(void) { } -/* Runs on core 0 only */ static int sys_clock_driver_init(void) { uint64_t curr = count(); @@ -224,14 +223,11 @@ static int sys_clock_driver_init(void) return 0; } -#ifdef CONFIG_PM - -void sys_clock_idle_exit(void) +/* Runs on core 0 only */ +void intel_adsp_clock_soft_off_exit(void) { - sys_clock_driver_init(); + (void)sys_clock_driver_init(); } -#endif - SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/mcux_lptmr_timer.c b/drivers/timer/mcux_lptmr_timer.c index e91c11112ff9c..930058f4ea40a 100644 --- a/drivers/timer/mcux_lptmr_timer.c +++ b/drivers/timer/mcux_lptmr_timer.c @@ -4,7 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#if DT_HAS_COMPAT_STATUS_OKAY(nxp_kinetis_lptmr) #define DT_DRV_COMPAT nxp_kinetis_lptmr +#else +#define DT_DRV_COMPAT nxp_lptmr +#endif #include #include diff --git a/drivers/timer/mtk_adsp_timer.c b/drivers/timer/mtk_adsp_timer.c new file mode 100644 index 0000000000000..7a6c06d9e61ac --- /dev/null +++ b/drivers/timer/mtk_adsp_timer.c @@ -0,0 +1,180 @@ +/* Copyright 2023 The ChromiumOS Authors + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include + +#define OSTIMER64_BASE DT_REG_ADDR(DT_NODELABEL(ostimer64)) +#define OSTIMER_BASE DT_REG_ADDR(DT_NODELABEL(ostimer0)) + +/* + * This device has a LOT of timer hardware. There are SIX + * instantiated devices, with THREE different interfaces! Not + * including the three Xtensa CCOUNT timers! + * + * In practice only "ostimer0" is used as an interrupt source by the + * original SOF code, and the "ostimer64" and "platform" timers + * reflect the same underlying clock (though they're different + * counters with different values). There is also a "ptimer" device, + * which is unused by SOF and not exercised by this driver. + * + * The driver architecture itself is sort of a hybrid of what other + * Zephyr drivers use: there is no (or at least no documented) + * comparator facility. The "ostimer64" is used as the system clock, + * which is a 13 MHz 64 bit up-counter. But timeout interrupts are + * delivered by ostimers[0], which is a 32 bit (!) down-counter (!!) + * running at twice (!!!) the rate: 26MHz. Testing shows they're + * slaved the same underlying clock -- they don't skew relative to + * each other. + */ +struct mtk_ostimer { + unsigned int con; + unsigned int rst; + unsigned int cur; + unsigned int irq_ack; +}; + +struct mtk_ostimer64 { + unsigned int con; + unsigned int init_l; + unsigned int init_h; + unsigned int cur_l; + unsigned int cur_h; + unsigned int tval_h; + unsigned int irq_ack; +}; + +#define OSTIMER64 (*(volatile struct mtk_ostimer64 *)OSTIMER64_BASE) + +#define OSTIMERS ((volatile struct mtk_ostimer *)OSTIMER_BASE) + +#define OSTIMER_CON_ENABLE BIT(0) +#define OSTIMER_CON_CLKSRC_MASK 0x30 +#define OSTIMER_CON_CLKSRC_32K 0x00 /* 32768 Hz */ +#define OSTIMER_CON_CLKSRC_26M 0x10 /* 26 MHz */ +#define OSTIMER_CON_CLKSRC_BCLK 0x20 /* CPU speed, 720 MHz */ +#define OSTIMER_CON_CLKSRC_PCLK 0x30 /* ~312 MHz experimentally */ + +#define OSTIMER_IRQ_ACK_ENABLE BIT(4) /* read = status, write = enable */ +#define OSTIMER_IRQ_ACK_CLEAR BIT(5) + +#define OST64_HZ 13000000U +#define OST_HZ 26000000U +#define OST64_PER_TICK (OST64_HZ / CONFIG_SYS_CLOCK_TICKS_PER_SEC) +#define OST_PER_TICK (OST_HZ / CONFIG_SYS_CLOCK_TICKS_PER_SEC) + +#define MAX_TICKS ((0xffffffffU - OST_PER_TICK) / OST_PER_TICK) +#define CYC64_MAX (0xffffffff - OST64_PER_TICK) + +static struct k_spinlock lock; + +static uint64_t last_announce; + +uint32_t sys_clock_cycle_get_32(void) +{ + return OSTIMER64.cur_l; +} + +uint64_t sys_clock_cycle_get_64(void) +{ + uint32_t l, h0, h1; + + do { + h0 = OSTIMER64.cur_h; + l = OSTIMER64.cur_l; + h1 = OSTIMER64.cur_h; + } while (h0 != h1); + + return (((uint64_t)h0) << 32) | l; +} + +void sys_clock_set_timeout(int32_t ticks, bool idle) +{ + /* Compute desired expiration time */ + uint64_t now = sys_clock_cycle_get_64(); + uint64_t end = now + CLAMP(ticks - 1, 0, MAX_TICKS) * OST64_PER_TICK; + uint32_t dt = (uint32_t)MIN(end - last_announce, CYC64_MAX); + + /* Round up to tick boundary */ + dt = ((dt + OST64_PER_TICK - 1) / OST64_PER_TICK) * OST64_PER_TICK; + + /* Convert to "fast" OSTIMER[0] cycles! */ + uint32_t cyc = 2 * (dt - (uint32_t)(now - last_announce)); + + /* Writes to RST need to be done when the device is disabled, + * and automatically reset CUR (which reads zero while disabled) + */ + OSTIMERS[0].con &= ~OSTIMER_CON_ENABLE; + OSTIMERS[0].rst = cyc; + OSTIMERS[0].irq_ack |= OSTIMER_IRQ_ACK_CLEAR; + OSTIMERS[0].irq_ack |= OSTIMER_IRQ_ACK_ENABLE; + OSTIMERS[0].con |= OSTIMER_CON_ENABLE; +} + +uint32_t sys_clock_elapsed(void) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + uint32_t ret; + + ret = (uint32_t)((sys_clock_cycle_get_64() - last_announce) + / OST64_PER_TICK); + k_spin_unlock(&lock, key); + return ret; +} + +static void timer_isr(__maybe_unused void *arg) +{ + /* Note: no locking. As it happens, on MT8195/8186/8188 all + * Zephyr-usable interrupts are delivered at the same level. + * So we can't be preempted and there's actually no need to + * take a spinlock here. But ideally we should verify/detect + * this instead of trusting blindly; this is fragile if future + * devices add nested interrupts. + */ + uint64_t dcyc = sys_clock_cycle_get_64() - last_announce; + uint64_t ticks = dcyc / OST64_PER_TICK; + + /* Leave the device disabled after clearing the interrupt, + * sys_clock_set_timeout() is responsible for turning it back + * on. + */ + OSTIMERS[0].irq_ack |= OSTIMER_IRQ_ACK_CLEAR; + OSTIMERS[0].con &= ~OSTIMER_CON_ENABLE; + OSTIMERS[0].irq_ack &= ~OSTIMER_IRQ_ACK_ENABLE; + + last_announce += ticks * OST64_PER_TICK; + sys_clock_announce(ticks); + + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + sys_clock_set_timeout(1, false); + } +} + +static int mtk_adsp_timer_init(void) +{ + IRQ_CONNECT(DT_IRQN(DT_NODELABEL(ostimer0)), 0, timer_isr, 0, 0); + irq_enable(DT_IRQN(DT_NODELABEL(ostimer0))); + + /* Disable all timers */ + for (int i = 0; i < 4; i++) { + OSTIMERS[i].con &= ~OSTIMER_CON_ENABLE; + OSTIMERS[i].irq_ack |= OSTIMER_IRQ_ACK_CLEAR; + OSTIMERS[i].irq_ack &= ~OSTIMER_IRQ_ACK_ENABLE; + } + + /* Set them up to use the same clock. Note that OSTIMER64 has + * a built-in divide by two (or it's configurable and I don't + * know the register) and exposes a 13 MHz counter! + */ + OSTIMERS[0].con = ((OSTIMERS[0].con & ~OSTIMER_CON_CLKSRC_MASK) + | OSTIMER_CON_CLKSRC_26M); + OSTIMERS[0].con |= OSTIMER_CON_ENABLE; + + /* Clock is free running and survives reset, doesn't start at zero */ + last_announce = sys_clock_cycle_get_64(); + + return 0; +} + +SYS_INIT(mtk_adsp_timer_init, PRE_KERNEL_2, CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/timer/nrf_grtc_timer.c b/drivers/timer/nrf_grtc_timer.c index 98faa4e231cc1..8c1c927b142ea 100644 --- a/drivers/timer/nrf_grtc_timer.c +++ b/drivers/timer/nrf_grtc_timer.c @@ -29,12 +29,6 @@ #define CHAN_COUNT NRFX_GRTC_CONFIG_NUM_OF_CC_CHANNELS #define EXT_CHAN_COUNT (CHAN_COUNT - 1) -/* The reset value of waketime is 1, which doesn't seem to work. - * It's being looked into, but for the time being use 4. - * Timeout must always be higher than waketime, so setting that to 5. - */ -#define WAKETIME (4) -#define TIMEOUT (WAKETIME + 1) #ifndef GRTC_SYSCOUNTERL_VALUE_Msk #define GRTC_SYSCOUNTERL_VALUE_Msk GRTC_SYSCOUNTER_SYSCOUNTERL_VALUE_Msk @@ -55,8 +49,7 @@ #define MAX_CYCLES (MAX_TICKS * CYC_PER_TICK) -/* The maximum SYSCOUNTERVALID settling time equals 1x32k cycles + 20x1MHz cycles. */ -#define GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US 51 +#define LFCLK_FREQUENCY_HZ 32768 #if defined(CONFIG_TEST) const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE); @@ -65,7 +58,7 @@ const int32_t z_sys_timer_irq_for_test = DT_IRQN(GRTC_NODE); static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_context); static struct k_spinlock lock; -static uint64_t last_count; +static uint64_t last_count; /* Time (SYSCOUNTER value) @last sys_clock_announce() */ static atomic_t int_mask; static uint8_t ext_channels_allocated; static nrfx_grtc_channel_t system_clock_channel_data = { @@ -78,36 +71,6 @@ static nrfx_grtc_channel_t system_clock_channel_data = { __ASSERT_NO_MSG((NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK & (1UL << (chan))) && \ ((chan) != system_clock_channel_data.channel)) -static inline void grtc_active_set(void) -{ -#if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1) - nrfy_grtc_sys_counter_active_set(NRF_GRTC, true); - while (!nrfy_grtc_sys_conter_ready_check(NRF_GRTC)) { - } -#else - nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, true); - k_busy_wait(GRTC_SYSCOUNTERVALID_SETTLE_MAX_TIME_US); -#endif -} - -static inline void grtc_wakeup(void) -{ - if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { - grtc_active_set(); - } -} - -static inline void grtc_sleep(void) -{ - if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { -#if defined(NRF_GRTC_HAS_SYSCOUNTER_ARRAY) && (NRF_GRTC_HAS_SYSCOUNTER_ARRAY == 1) - nrfy_grtc_sys_counter_active_set(NRF_GRTC, false); -#else - nrfy_grtc_sys_counter_active_state_request_set(NRF_GRTC, false); -#endif - } -} - static inline uint64_t counter_sub(uint64_t a, uint64_t b) { return (a - b); @@ -116,10 +79,7 @@ static inline uint64_t counter_sub(uint64_t a, uint64_t b) static inline uint64_t counter(void) { uint64_t now; - - grtc_wakeup(); nrfx_grtc_syscounter_get(&now); - grtc_sleep(); return now; } @@ -137,19 +97,29 @@ static inline int get_comparator(uint32_t chan, uint64_t *cc) return 0; } -static void system_timeout_set(uint64_t value) +/* + * Program a new callback microseconds in the future + */ +static void system_timeout_set_relative(uint64_t value) { if (value <= NRF_GRTC_SYSCOUNTER_CCADD_MASK) { - grtc_wakeup(); nrfx_grtc_syscounter_cc_relative_set(&system_clock_channel_data, value, true, NRFX_GRTC_CC_RELATIVE_SYSCOUNTER); - grtc_sleep(); } else { nrfx_grtc_syscounter_cc_absolute_set(&system_clock_channel_data, value + counter(), true); } } +/* + * Program a new callback in the absolute time given by + */ +static void system_timeout_set_abs(uint64_t value) +{ + nrfx_grtc_syscounter_cc_absolute_set(&system_clock_channel_data, value, + true); +} + static bool compare_int_lock(int32_t chan) { atomic_val_t prev = atomic_and(&int_mask, ~BIT(chan)); @@ -177,17 +147,19 @@ static void sys_clock_timeout_handler(int32_t id, uint64_t cc_val, void *p_conte if (unlikely(now < cc_val)) { return; } + + dticks = counter_sub(cc_val, last_count) / CYC_PER_TICK; + + last_count += dticks * CYC_PER_TICK; + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { /* protection is not needed because we are in the GRTC interrupt * so it won't get preempted by the interrupt. */ - system_timeout_set(CYC_PER_TICK); + system_timeout_set_abs(last_count + CYC_PER_TICK); } - dticks = counter_sub(now, last_count) / CYC_PER_TICK; - - last_count += dticks * CYC_PER_TICK; - sys_clock_announce(IS_ENABLED(CONFIG_TICKLESS_KERNEL) ? (int32_t)dticks : (dticks > 0)); + sys_clock_announce((int32_t)dticks); } int32_t z_nrf_grtc_timer_chan_alloc(void) @@ -318,18 +290,21 @@ uint64_t z_nrf_grtc_timer_get_ticks(k_timeout_t t) int64_t curr_tick; int64_t result; int64_t abs_ticks; + int64_t grtc_ticks; curr_time = counter(); curr_tick = sys_clock_tick_get(); + grtc_ticks = t.ticks * CYC_PER_TICK; abs_ticks = Z_TICK_ABS(t.ticks); if (abs_ticks < 0) { /* relative timeout */ - return (t.ticks > (int64_t)COUNTER_SPAN) ? -EINVAL : (curr_time + t.ticks); + return (grtc_ticks > (int64_t)COUNTER_SPAN) ? + -EINVAL : (curr_time + grtc_ticks); } /* absolute timeout */ - result = abs_ticks - curr_tick; + result = (abs_ticks - curr_tick) * CYC_PER_TICK; if (result > (int64_t)COUNTER_SPAN) { return -EINVAL; @@ -369,6 +344,7 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time) */ uint64_t capt_time; + nrfx_err_t result; IS_CHANNEL_ALLOWED_ASSERT(chan); @@ -379,8 +355,10 @@ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time) */ return -EBUSY; } - - capt_time = nrfy_grtc_sys_counter_cc_get(NRF_GRTC, chan); + result = nrfx_grtc_syscounter_cc_value_read(chan, &capt_time); + if (result != NRFX_SUCCESS) { + return -EPERM; + } __ASSERT_NO_MSG(capt_time < COUNTER_SPAN); @@ -395,16 +373,23 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) nrfx_err_t err_code; static uint8_t systemoff_channel; uint64_t now = counter(); + nrfx_grtc_sleep_config_t sleep_cfg; /* Minimum time that ensures valid execution of system-off procedure. */ - uint32_t minimum_latency_us = nrfy_grtc_waketime_get(NRF_GRTC) + - nrfy_grtc_timeout_get(NRF_GRTC) + - CONFIG_NRF_GRTC_SLEEP_MINIMUM_LATENCY; + uint32_t minimum_latency_us; uint32_t chan; int ret; + nrfx_grtc_sleep_configuration_get(&sleep_cfg); + minimum_latency_us = (sleep_cfg.waketime + sleep_cfg.timeout) * + USEC_PER_SEC / LFCLK_FREQUENCY_HZ + + CONFIG_NRF_GRTC_SYSCOUNTER_SLEEP_MINIMUM_LATENCY; + sleep_cfg.auto_mode = false; + nrfx_grtc_sleep_configure(&sleep_cfg); + if (minimum_latency_us > wake_time_us) { return -EINVAL; } + k_spinlock_key_t key = k_spin_lock(&lock); err_code = nrfx_grtc_channel_alloc(&systemoff_channel); @@ -413,7 +398,9 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) return -ENOMEM; } (void)nrfx_grtc_syscounter_cc_int_disable(systemoff_channel); - ret = compare_set(systemoff_channel, now + wake_time_us, NULL, NULL); + ret = compare_set(systemoff_channel, + now + wake_time_us * sys_clock_hw_cycles_per_sec() / USEC_PER_SEC, NULL, + NULL); if (ret < 0) { k_spin_unlock(&lock, key); return ret; @@ -429,7 +416,7 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) } /* Make sure that wake_time_us was not triggered yet. */ - if (nrfy_grtc_sys_counter_compare_event_check(NRF_GRTC, systemoff_channel)) { + if (nrfx_grtc_syscounter_compare_event_check(systemoff_channel)) { k_spin_unlock(&lock, key); return -EINVAL; } @@ -440,7 +427,7 @@ int z_nrf_grtc_wakeup_prepare(uint64_t wake_time_us) MAX_CC_LATCH_WAIT_TIME_US; k_busy_wait(wait_time); #if NRF_GRTC_HAS_CLKSEL - nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFXO); + nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFXO); #endif k_spin_unlock(&lock, key); return 0; @@ -481,16 +468,9 @@ static int sys_clock_driver_init(void) #if defined(CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) && \ (defined(NRF_GRTC_HAS_CLKSEL) && (NRF_GRTC_HAS_CLKSEL == 1)) /* Use System LFCLK as the low-frequency clock source. */ - nrfy_grtc_clksel_set(NRF_GRTC, NRF_GRTC_CLKSEL_LFCLK); + nrfx_grtc_clock_source_set(NRF_GRTC_CLKSEL_LFCLK); #endif -#if defined(CONFIG_NRF_GRTC_START_SYSCOUNTER) - /* SYSCOUNTER needs to be turned off before initialization. */ - nrfy_grtc_sys_counter_set(NRF_GRTC, false); - nrfy_grtc_timeout_set(NRF_GRTC, TIMEOUT); - nrfy_grtc_waketime_set(NRF_GRTC, WAKETIME); -#endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */ - IRQ_CONNECT(DT_IRQN(GRTC_NODE), DT_IRQ(GRTC_NODE, priority), nrfx_isr, nrfx_grtc_irq_handler, 0); @@ -504,9 +484,6 @@ static int sys_clock_driver_init(void) if (err_code != NRFX_SUCCESS) { return err_code == NRFX_ERROR_NO_MEM ? -ENOMEM : -EPERM; } - if (IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { - nrfy_grtc_sys_counter_auto_mode_set(NRF_GRTC, false); - } #else err_code = nrfx_grtc_channel_alloc(&system_clock_channel_data.channel); if (err_code != NRFX_SUCCESS) { @@ -514,13 +491,9 @@ static int sys_clock_driver_init(void) } #endif /* CONFIG_NRF_GRTC_START_SYSCOUNTER */ - if (!IS_ENABLED(CONFIG_NRF_GRTC_SLEEP_ALLOWED)) { - grtc_active_set(); - } - int_mask = NRFX_GRTC_CONFIG_ALLOWED_CC_CHANNELS_MASK; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { - system_timeout_set(CYC_PER_TICK); + system_timeout_set_relative(CYC_PER_TICK); } #if defined(CONFIG_CLOCK_CONTROL_NRF) @@ -540,34 +513,23 @@ static int sys_clock_driver_init(void) void sys_clock_set_timeout(int32_t ticks, bool idle) { ARG_UNUSED(idle); - uint64_t cyc, off, now; if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { return; } - ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : MIN(MAX_TICKS, MAX(ticks - 1, 0)); - - now = counter(); + ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : MIN(MAX_TICKS, MAX(ticks, 0)); - /* Round up to the next tick boundary */ - off = (now - last_count) + (CYC_PER_TICK - 1); - off = (off / CYC_PER_TICK) * CYC_PER_TICK; + uint64_t delta_time = ticks * CYC_PER_TICK; - /* Get the offset with respect to now */ - off -= (now - last_count); + uint64_t target_time = counter() + delta_time; - /* Add the offset to get to the next tick boundary */ - cyc = (uint64_t)ticks * CYC_PER_TICK + off; - - /* Due to elapsed time the calculation above might produce a - * duration that laps the counter. Don't let it. + /* Rounded down target_time to the tick boundary + * (but not less than one tick after the last) */ - if (cyc > MAX_CYCLES) { - cyc = MAX_CYCLES; - } + target_time = MAX((target_time - last_count)/CYC_PER_TICK, 1)*CYC_PER_TICK + last_count; - system_timeout_set(cyc == 0 ? 1 : cyc); + system_timeout_set_abs(target_time); } #if defined(CONFIG_NRF_GRTC_TIMER_APP_DEFINED_INIT) diff --git a/drivers/timer/smartbond_timer.c b/drivers/timer/smartbond_timer.c index 4ab03f5d956e0..ceef22ce5fa2f 100644 --- a/drivers/timer/smartbond_timer.c +++ b/drivers/timer/smartbond_timer.c @@ -5,6 +5,8 @@ */ #include +#include +#include #include #include #include @@ -17,6 +19,10 @@ #define TICK_TO_CYC(tick) k_ticks_to_cyc_ceil32(tick) #define CYC_TO_TICK(cyc) k_cyc_to_ticks_ceil32(cyc) #define MAX_TICKS (((COUNTER_SPAN / 2) - CYC_PER_TICK) / (CYC_PER_TICK)) +#define SMARTBOND_CLOCK_CONTROLLER DEVICE_DT_GET(DT_NODELABEL(osc)) +/* Margin values are based on DA1469x characterization data */ +#define RC32K_FREQ_POSITIVE_MARGIN_DUE_TO_VOLTAGE (675) +#define RC32K_FREQ_MARGIN_DUE_TO_TEMPERATURE (450) static uint32_t last_timer_val_reg; static uint32_t timer_val_31_24; @@ -25,6 +31,19 @@ static uint32_t last_isr_val; static uint32_t last_isr_val_rounded; static uint32_t announced_ticks; +static uint32_t get_rc32k_max_frequency(void) +{ + /* According to DA1469x datasheet */ + uint32_t r32k_frequency = 37000; + + clock_control_get_rate(SMARTBOND_CLOCK_CONTROLLER, + (clock_control_subsys_t)SMARTBOND_CLK_RC32K, &r32k_frequency); + + r32k_frequency += RC32K_FREQ_POSITIVE_MARGIN_DUE_TO_VOLTAGE + + RC32K_FREQ_MARGIN_DUE_TO_TEMPERATURE; + return r32k_frequency; +} + static void set_reload(uint32_t val) { TIMER2->TIMER2_RELOAD_REG = val & TIMER2_TIMER2_RELOAD_REG_TIM_RELOAD_Msk; @@ -88,11 +107,20 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) uint32_t watchdog_expire_ticks; if (CRG_TOP->CLK_RCX_REG & CRG_TOP_CLK_RCX_REG_RCX_ENABLE_Msk) { - watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG * 21 * - CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000; + /* + * When LP clock is RCX, the watchdog is clocked by RCX clock + * divided by 320. + */ + watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG * 320; } else { + /* + * When LP clock is not RCX, the watchdog is clocked by RC32K + * divided by 320. In this case watchdog value to LP clock + * ticks must be calculated according to XTAL32K frequency and + * RC32K maximum frequency. + */ watchdog_expire_ticks = SYS_WDOG->WATCHDOG_REG * - CONFIG_SYS_CLOCK_TICKS_PER_SEC / 100; + CONFIG_SYS_CLOCK_TICKS_PER_SEC / (get_rc32k_max_frequency() / 320); } if (watchdog_expire_ticks - 2 < ticks) { ticks = watchdog_expire_ticks - 2; @@ -108,6 +136,18 @@ void sys_clock_set_timeout(int32_t ticks, bool idle) target_val = ((target_val + CYC_PER_TICK - 1) / CYC_PER_TICK) * CYC_PER_TICK; set_reload(target_val); + + /* + * If time was so small that it already fired or should fire + * just now, mark interrupt as pending to avoid losing timer event. + * Condition is true when target_val (point in time that should be + * used for wakeup) is behind timer value or is equal to it. + * In that case we don't know if reload value was set in time or + * not but time expired anyway so make sure that interrupt is pending. + */ + if ((int32_t)(target_val - timer_val_32_noupdate() - 1) < 0) { + NVIC_SetPendingIRQ(TIMER2_IRQn); + } } uint32_t sys_clock_elapsed(void) diff --git a/drivers/timer/stm32_lptim_timer.c b/drivers/timer/stm32_lptim_timer.c index c94be66b80e11..90c75fb709ce9 100644 --- a/drivers/timer/stm32_lptim_timer.c +++ b/drivers/timer/stm32_lptim_timer.c @@ -550,14 +550,21 @@ static int sys_clock_driver_init(void) return 0; } -void sys_clock_idle_exit(void) +void stm32_clock_control_standby_exit(void) { #ifdef CONFIG_STM32_LPTIM_STDBY_TIMER if (clock_control_get_status(clk_ctrl, (clock_control_subsys_t) &lptim_clk[0]) != CLOCK_CONTROL_STATUS_ON) { sys_clock_driver_init(); - } else if (timeout_stdby) { + } +#endif /* CONFIG_STM32_LPTIM_STDBY_TIMER */ +} + +void sys_clock_idle_exit(void) +{ +#ifdef CONFIG_STM32_LPTIM_STDBY_TIMER + if (timeout_stdby) { cycle_t missed_lptim_cnt; uint32_t stdby_timer_diff, stdby_timer_post, dticks; uint64_t stdby_timer_us; diff --git a/drivers/timer/ti_dmtimer.c b/drivers/timer/ti_dmtimer.c new file mode 100644 index 0000000000000..7b04b92788a21 --- /dev/null +++ b/drivers/timer/ti_dmtimer.c @@ -0,0 +1,167 @@ +/* Copyright (C) 2023 BeagleBoard.org Foundation + * Copyright (C) 2023 S Prashanth + * Copyright (c) 2024 Texas Instruments Incorporated + * Andrew Davis + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define DT_DRV_COMPAT ti_am654_timer + +#define TIMER_BASE_ADDR DT_INST_REG_ADDR(0) + +#define TIMER_IRQ_NUM DT_INST_IRQN(0) +#define TIMER_IRQ_PRIO DT_INST_IRQ(0, priority) +#define TIMER_IRQ_FLAGS DT_INST_IRQ(0, flags) + +#define CYC_PER_TICK ((uint32_t)(sys_clock_hw_cycles_per_sec() \ + / CONFIG_SYS_CLOCK_TICKS_PER_SEC)) + +#define MAX_TICKS ((k_ticks_t)(UINT32_MAX / CYC_PER_TICK) - 1) + +static struct k_spinlock lock; + +static uint32_t last_cycle; + +#define TI_DM_TIMER_READ(reg) sys_read32(TIMER_BASE_ADDR + TI_DM_TIMER_ ## reg) + +#define TI_DM_TIMER_MASK(reg) TI_DM_TIMER_ ## reg ## _MASK +#define TI_DM_TIMER_SHIFT(reg) TI_DM_TIMER_ ## reg ## _SHIFT +#define TI_DM_TIMER_WRITE(data, reg, bits) \ + ti_dm_timer_write_masks(data, \ + TIMER_BASE_ADDR + TI_DM_TIMER_ ## reg, \ + TI_DM_TIMER_MASK(reg ## _ ## bits), \ + TI_DM_TIMER_SHIFT(reg ## _ ## bits)) + +static void ti_dm_timer_write_masks(uint32_t data, uint32_t reg, uint32_t mask, uint32_t shift) +{ + uint32_t reg_val; + + reg_val = sys_read32(reg); + reg_val = (reg_val & ~(mask)) | (data << shift); + sys_write32(reg_val, reg); +} + +static void ti_dmtimer_isr(void *data) +{ + /* If no pending event */ + if (!TI_DM_TIMER_READ(IRQSTATUS)) + return; + + k_spinlock_key_t key = k_spin_lock(&lock); + + uint32_t curr_cycle = TI_DM_TIMER_READ(TCRR); + uint32_t delta_cycles = curr_cycle - last_cycle; + uint32_t delta_ticks = delta_cycles / CYC_PER_TICK; + + last_cycle = curr_cycle; + + /* ACK match interrupt */ + TI_DM_TIMER_WRITE(1, IRQSTATUS, MAT_IT_FLAG); + + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + /* Setup next match time */ + uint64_t next_cycle = curr_cycle + CYC_PER_TICK; + + TI_DM_TIMER_WRITE(next_cycle, TMAR, COMPARE_VALUE); + } + + k_spin_unlock(&lock, key); + + sys_clock_announce(delta_ticks); +} + +void sys_clock_set_timeout(int32_t ticks, bool idle) +{ + ARG_UNUSED(idle); + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + /* Not supported on tickful kernels */ + return; + } + + ticks = (ticks == K_TICKS_FOREVER) ? MAX_TICKS : ticks; + ticks = CLAMP(ticks, 1, (int32_t)MAX_TICKS); + + k_spinlock_key_t key = k_spin_lock(&lock); + + /* Setup next match time */ + uint32_t curr_cycle = TI_DM_TIMER_READ(TCRR); + uint32_t next_cycle = curr_cycle + (ticks * CYC_PER_TICK); + + TI_DM_TIMER_WRITE(next_cycle, TMAR, COMPARE_VALUE); + + k_spin_unlock(&lock, key); +} + +uint32_t sys_clock_cycle_get_32(void) +{ + k_spinlock_key_t key = k_spin_lock(&lock); + + uint32_t curr_cycle = TI_DM_TIMER_READ(TCRR); + + k_spin_unlock(&lock, key); + + return curr_cycle; +} + +unsigned int sys_clock_elapsed(void) +{ + if (!IS_ENABLED(CONFIG_TICKLESS_KERNEL)) { + /* Always return 0 for tickful kernel system */ + return 0; + } + + k_spinlock_key_t key = k_spin_lock(&lock); + + uint32_t curr_cycle = TI_DM_TIMER_READ(TCRR); + uint32_t delta_cycles = curr_cycle - last_cycle; + uint32_t delta_ticks = delta_cycles / CYC_PER_TICK; + + k_spin_unlock(&lock, key); + + return delta_ticks; +} + +static int sys_clock_driver_init(void) +{ + last_cycle = 0; + + IRQ_CONNECT(TIMER_IRQ_NUM, TIMER_IRQ_PRIO, ti_dmtimer_isr, NULL, TIMER_IRQ_FLAGS); + + /* Select autoreload mode */ + TI_DM_TIMER_WRITE(1, TCLR, AR); + + /* Enable match interrupt */ + TI_DM_TIMER_WRITE(1, IRQENABLE_SET, MAT_EN_FLAG); + + /* Load timer counter value */ + TI_DM_TIMER_WRITE(0, TCRR, TIMER_COUNTER); + + /* Load timer load value */ + TI_DM_TIMER_WRITE(0, TLDR, LOAD_VALUE); + + /* Load timer compare value */ + TI_DM_TIMER_WRITE(CYC_PER_TICK, TMAR, COMPARE_VALUE); + + /* Enable compare mode */ + TI_DM_TIMER_WRITE(1, TCLR, CE); + + /* Start the timer */ + TI_DM_TIMER_WRITE(1, TCLR, ST); + + irq_enable(TIMER_IRQ_NUM); + + return 0; +} + +SYS_INIT(sys_clock_driver_init, PRE_KERNEL_2, + CONFIG_SYSTEM_CLOCK_INIT_PRIORITY); diff --git a/drivers/usb/common/usb_dwc2_hw.h b/drivers/usb/common/usb_dwc2_hw.h index f216a423968d5..b137a526ede0f 100644 --- a/drivers/usb/common/usb_dwc2_hw.h +++ b/drivers/usb/common/usb_dwc2_hw.h @@ -190,32 +190,81 @@ USB_DWC2_SET_FIELD_DEFINE(grstctl_txfnum, GRSTCTL_TXFNUM) #define USB_DWC2_GINTMSK 0x0018UL #define USB_DWC2_GINTSTS_WKUPINT_POS 31UL #define USB_DWC2_GINTSTS_WKUPINT BIT(USB_DWC2_GINTSTS_WKUPINT_POS) +#define USB_DWC2_GINTSTS_SESSREQINT_POS 30UL +#define USB_DWC2_GINTSTS_SESSREQINT BIT(USB_DWC2_GINTSTS_SESSREQINT_POS) +#define USB_DWC2_GINTSTS_DISCONNINT_POS 29UL +#define USB_DWC2_GINTSTS_DISCONNINT BIT(USB_DWC2_GINTSTS_DISCONNINT_POS) +#define USB_DWC2_GINTSTS_CONIDSTSCHNG_POS 28UL +#define USB_DWC2_GINTSTS_CONIDSTSCHNG BIT(USB_DWC2_GINTSTS_CONIDSTSCHNG_POS) +#define USB_DWC2_GINTSTS_LPM_INT_POS 27UL +#define USB_DWC2_GINTSTS_LPM_INT BIT(USB_DWC2_GINTSTS_LPM_INT_POS) +#define USB_DWC2_GINTSTS_HCHINT_POS 25UL +#define USB_DWC2_GINTSTS_HCHINT BIT(USB_DWC2_GINTSTS_HCHINT_POS) +#define USB_DWC2_GINTSTS_PRTINT_POS 24UL +#define USB_DWC2_GINTSTS_PRTINT BIT(USB_DWC2_GINTSTS_PRTINT_POS) +#define USB_DWC2_GINTSTS_RESETDET_POS 23UL +#define USB_DWC2_GINTSTS_RESETDET BIT(USB_DWC2_GINTSTS_RESETDET_POS) +#define USB_DWC2_GINTSTS_FETSUSP_POS 22UL +#define USB_DWC2_GINTSTS_FETSUSP BIT(USB_DWC2_GINTSTS_FETSUSP_POS) +#define USB_DWC2_GINTSTS_INCOMPIP_POS 21UL +#define USB_DWC2_GINTSTS_INCOMPIP BIT(USB_DWC2_GINTSTS_INCOMPIP_POS) +#define USB_DWC2_GINTSTS_INCOMPISOIN_POS 20UL +#define USB_DWC2_GINTSTS_INCOMPISOIN BIT(USB_DWC2_GINTSTS_INCOMPISOIN_POS) #define USB_DWC2_GINTSTS_OEPINT_POS 19UL #define USB_DWC2_GINTSTS_OEPINT BIT(USB_DWC2_GINTSTS_OEPINT_POS) #define USB_DWC2_GINTSTS_IEPINT_POS 18UL #define USB_DWC2_GINTSTS_IEPINT BIT(USB_DWC2_GINTSTS_IEPINT_POS) +#define USB_DWC2_GINTSTS_EPMIS_POS 17UL +#define USB_DWC2_GINTSTS_EPMIS BIT(USB_DWC2_GINTSTS_EPMIS_POS) +#define USB_DWC2_GINTSTS_RSTRDONEINT_POS 16UL +#define USB_DWC2_GINTSTS_RSTRDONEINT BIT(USB_DWC2_GINTSTS_RSTRDONEINT_POS) +#define USB_DWC2_GINTSTS_EOPF_POS 15UL +#define USB_DWC2_GINTSTS_EOPF BIT(USB_DWC2_GINTSTS_EOPF_POS) +#define USB_DWC2_GINTSTS_ISOOUTDROP_POS 14UL +#define USB_DWC2_GINTSTS_ISOOUTDROP BIT(USB_DWC2_GINTSTS_ISOOUTDROP_POS) #define USB_DWC2_GINTSTS_ENUMDONE_POS 13UL #define USB_DWC2_GINTSTS_ENUMDONE BIT(USB_DWC2_GINTSTS_ENUMDONE_POS) #define USB_DWC2_GINTSTS_USBRST_POS 12UL #define USB_DWC2_GINTSTS_USBRST BIT(USB_DWC2_GINTSTS_USBRST_POS) #define USB_DWC2_GINTSTS_USBSUSP_POS 11UL #define USB_DWC2_GINTSTS_USBSUSP BIT(USB_DWC2_GINTSTS_USBSUSP_POS) +#define USB_DWC2_GINTSTS_ERLYSUSP_POS 10UL +#define USB_DWC2_GINTSTS_ERLYSUSP BIT(USB_DWC2_GINTSTS_ERLYSUSP_POS) +#define USB_DWC2_GINTSTS_GOUTNAKEFF_POS 7UL +#define USB_DWC2_GINTSTS_GOUTNAKEFF BIT(USB_DWC2_GINTSTS_GOUTNAKEFF_POS) +#define USB_DWC2_GINTSTS_GINNAKEFF_POS 6UL +#define USB_DWC2_GINTSTS_GINNAKEFF BIT(USB_DWC2_GINTSTS_GINNAKEFF_POS) +#define USB_DWC2_GINTSTS_NPTXFEMP_POS 5UL +#define USB_DWC2_GINTSTS_NPTXFEMP BIT(USB_DWC2_GINTSTS_NPTXFEMP_POS) #define USB_DWC2_GINTSTS_RXFLVL_POS 4UL #define USB_DWC2_GINTSTS_RXFLVL BIT(USB_DWC2_GINTSTS_RXFLVL_POS) #define USB_DWC2_GINTSTS_SOF_POS 3UL #define USB_DWC2_GINTSTS_SOF BIT(USB_DWC2_GINTSTS_SOF_POS) #define USB_DWC2_GINTSTS_OTGINT_POS 2UL #define USB_DWC2_GINTSTS_OTGINT BIT(USB_DWC2_GINTSTS_OTGINT_POS) +#define USB_DWC2_GINTSTS_MODEMIS_POS 1UL +#define USB_DWC2_GINTSTS_MODEMIS BIT(USB_DWC2_GINTSTS_MODEMIS_POS) +#define USB_DWC2_GINTSTS_CURMOD_POS 0UL +#define USB_DWC2_GINTSTS_CURMOD BIT(USB_DWC2_GINTSTS_CURMOD_POS) /* Status read and pop registers */ #define USB_DWC2_GRXSTSR 0x001CUL #define USB_DWC2_GRXSTSP 0x0020UL +#define USB_DWC2_GRXSTSR_FN_POS 21UL +#define USB_DWC2_GRXSTSR_FN_MASK (0xFUL << USB_DWC2_GRXSTSR_FN_POS) #define USB_DWC2_GRXSTSR_PKTSTS_POS 17UL #define USB_DWC2_GRXSTSR_PKTSTS_MASK (0xFUL << USB_DWC2_GRXSTSR_PKTSTS_POS) +#define USB_DWC2_GRXSTSR_PKTSTS_GLOBAL_OUT_NAK 1 #define USB_DWC2_GRXSTSR_PKTSTS_OUT_DATA 2 #define USB_DWC2_GRXSTSR_PKTSTS_OUT_DATA_DONE 3 #define USB_DWC2_GRXSTSR_PKTSTS_SETUP_DONE 4 #define USB_DWC2_GRXSTSR_PKTSTS_SETUP 6 +#define USB_DWC2_GRXSTSR_DPID_POS 15UL +#define USB_DWC2_GRXSTSR_DPID_MASK (0x3UL << USB_DWC2_GRXSTSR_DPID_POS) +#define USB_DWC2_GRXSTSR_DPID_DATA0 0 +#define USB_DWC2_GRXSTSR_DPID_DATA2 1 +#define USB_DWC2_GRXSTSR_DPID_DATA1 2 +#define USB_DWC2_GRXSTSR_DPID_MDATA 3 #define USB_DWC2_GRXSTSR_BCNT_POS 4UL #define USB_DWC2_GRXSTSR_BCNT_MASK (0x000007FFUL << USB_DWC2_GRXSTSR_BCNT_POS) #define USB_DWC2_GRXSTSR_EPNUM_POS 0UL @@ -223,6 +272,7 @@ USB_DWC2_SET_FIELD_DEFINE(grstctl_txfnum, GRSTCTL_TXFNUM) #define USB_DWC2_GRXSTSR_CHNUM_POS 0UL #define USB_DWC2_GRXSTSR_CHNUM_MASK 0x0000000FUL +USB_DWC2_GET_FIELD_DEFINE(grxstsp_fn, GRXSTSR_FN) USB_DWC2_GET_FIELD_DEFINE(grxstsp_pktsts, GRXSTSR_PKTSTS) USB_DWC2_GET_FIELD_DEFINE(grxstsp_bcnt, GRXSTSR_BCNT) USB_DWC2_GET_FIELD_DEFINE(grxstsp_epnum, GRXSTSR_EPNUM) @@ -456,6 +506,8 @@ USB_DWC2_GET_FIELD_DEFINE(dsts_enumspd, DSTS_ENUMSPD) #define USB_DWC2_DEPCTL_EPENA BIT(USB_DWC2_DEPCTL_EPENA_POS) #define USB_DWC2_DEPCTL_EPDIS_POS 30UL #define USB_DWC2_DEPCTL_EPDIS BIT(USB_DWC2_DEPCTL_EPDIS_POS) +#define USB_DWC2_DEPCTL_SETD1PID_POS 29UL +#define USB_DWC2_DEPCTL_SETD1PID BIT(USB_DWC2_DEPCTL_SETD1PID_POS) #define USB_DWC2_DEPCTL_SETD0PID_POS 28UL #define USB_DWC2_DEPCTL_SETD0PID BIT(USB_DWC2_DEPCTL_SETD0PID_POS) #define USB_DWC2_DEPCTL_SNAK_POS 27UL @@ -472,6 +524,10 @@ USB_DWC2_GET_FIELD_DEFINE(dsts_enumspd, DSTS_ENUMSPD) #define USB_DWC2_DEPCTL_EPTYPE_BULK 2 #define USB_DWC2_DEPCTL_EPTYPE_ISO 1 #define USB_DWC2_DEPCTL_EPTYPE_CONTROL 0 +#define USB_DWC2_DEPCTL_NAKSTS_POS 17UL +#define USB_DWC2_DEPCTL_NAKSTS BIT(USB_DWC2_DEPCTL_NAKSTS_POS) +#define USB_DWC2_DEPCTL_DPID_POS 16UL +#define USB_DWC2_DEPCTL_DPID BIT(USB_DWC2_DEPCTL_DPID_POS) #define USB_DWC2_DEPCTL_USBACTEP_POS 15UL #define USB_DWC2_DEPCTL_USBACTEP BIT(USB_DWC2_DEPCTL_USBACTEP_POS) #define USB_DWC2_DEPCTL0_MPS_POS 0UL diff --git a/drivers/usb/device/Kconfig b/drivers/usb/device/Kconfig index ad2432998c437..f110d7df2f1d3 100644 --- a/drivers/usb/device/Kconfig +++ b/drivers/usb/device/Kconfig @@ -229,6 +229,17 @@ config USB_NATIVE_POSIX help Native Posix USB Device Controller Driver. +DT_ZEPHYR_UDC0 := $(dt_nodelabel_path,zephyr_udc0) +DT_ZEPHYR_UDC0_HS_SPEED := $(dt_node_str_prop_equals,$(DT_ZEPHYR_UDC0),maximum-speed,high-speed) + +config USB_NATIVE_POSIX_HS + bool "High speed support" + select USB_DC_HAS_HS_SUPPORT + depends on USB_NATIVE_POSIX + default y if "$(DT_ZEPHYR_UDC0_HS_SPEED)" + help + Enable high speed support in the Native Posix USB device controller driver. + module = USB_DRIVER module-str = usb driver source "subsys/logging/Kconfig.template.log_config" diff --git a/drivers/usb/device/usb_dc_it82xx2.c b/drivers/usb/device/usb_dc_it82xx2.c index e453144473c0b..3cf17e7f08a83 100644 --- a/drivers/usb/device/usb_dc_it82xx2.c +++ b/drivers/usb/device/usb_dc_it82xx2.c @@ -82,7 +82,6 @@ enum it82xx2_transaction_types { /* ENDPOINT[3..0]_CONTROL_REG */ #define ENDPOINT_EN BIT(0) -#define ENDPOINT_RDY BIT(1) #define EP_SEND_STALL BIT(3) enum it82xx2_ep_status { @@ -195,8 +194,7 @@ static struct usb_it82xx2_regs *it82xx2_get_usb_regs(void) static void it82xx2_enable_sof_int(bool enable) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; if (enable) { @@ -257,12 +255,13 @@ static void it8xxx2_usb_dc_wuc_init(const struct device *dev) IRQ_CONNECT(IT8XXX2_WU90_IRQ, 0, it82xx2_wu90_isr, 0, 0); } -static int it82xx2_usb_fifo_ctrl(uint8_t ep) +static int it82xx2_usb_fifo_ctrl(const uint8_t ep, const bool clear) { - struct usb_it82xx2_regs *const usb_regs = (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); volatile uint8_t *ep_fifo_ctrl = usb_regs->fifo_regs[EP_EXT_REGS_BX].fifo_ctrl.ep_fifo_ctrl; uint8_t ep_idx = USB_EP_GET_IDX(ep); uint8_t fifon_ctrl = (ep_fifo_res[ep_idx % FIFO_NUM] - 1) * 2; + unsigned int key; int ret = 0; if (ep_idx == 0) { @@ -270,6 +269,13 @@ static int it82xx2_usb_fifo_ctrl(uint8_t ep) return -EINVAL; } + key = irq_lock(); + if (clear) { + ep_fifo_ctrl[fifon_ctrl] = 0x0; + ep_fifo_ctrl[fifon_ctrl + 1] = 0x0; + goto out; + } + if (USB_EP_DIR_IS_IN(ep) && udata0.ep_data[ep_idx].ep_status == EP_CONFIG_IN) { if (ep_idx < 8) { ep_fifo_ctrl[fifon_ctrl] = BIT(ep_idx); @@ -290,14 +296,15 @@ static int it82xx2_usb_fifo_ctrl(uint8_t ep) ret = -EINVAL; } +out: + irq_unlock(key); return ret; } static volatile void *it82xx2_get_ext_ctrl(int ep_idx, enum it82xx2_ep_ctrl ctrl) { uint8_t idx; - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); union epn0n1_extend_ctrl_reg *epn0n1_ext_ctrl = usb_regs->fifo_regs[EP_EXT_REGS_9X].ext_4_15.epn0n1_ext_ctrl; struct epn_ext_ctrl_regs *ext_ctrl = @@ -314,12 +321,14 @@ static volatile void *it82xx2_get_ext_ctrl(int ep_idx, enum it82xx2_ep_ctrl ctrl static int it82xx2_usb_extend_ep_ctrl(uint8_t ep, enum it82xx2_ep_ctrl ctrl, bool enable) { - struct usb_it82xx2_regs *const usb_regs = (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; struct epn_ext_ctrl_regs *ext_ctrl = usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; union epn_extend_ctrl1_reg *epn_ext_ctrl1 = NULL; union epn0n1_extend_ctrl_reg *epn0n1_ext_ctrl = NULL; uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint8_t ep_fifo = (ep_idx > 0) ? (ep_fifo_res[ep_idx % FIFO_NUM]) : 0; if (!IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { return -EINVAL; @@ -408,10 +417,14 @@ static int it82xx2_usb_extend_ep_ctrl(uint8_t ep, enum it82xx2_ep_ctrl ctrl, boo } break; case EP_READY_ENABLE: + unsigned int key; int idx = ((ep_idx - 4) % 3) + 1; + key = irq_lock(); (enable) ? (ext_ctrl[idx].epn_ext_ctrl2 |= BIT((ep_idx - 4) / 3)) : (ext_ctrl[idx].epn_ext_ctrl2 &= ~BIT((ep_idx - 4) / 3)); + ep_regs[ep_fifo].ep_ctrl.fields.ready_bit = enable; + irq_unlock(key); break; default: LOG_ERR("Unknown control type 0x%x", ctrl); @@ -423,8 +436,7 @@ static int it82xx2_usb_extend_ep_ctrl(uint8_t ep, enum it82xx2_ep_ctrl ctrl, boo static int it82xx2_usb_ep_ctrl(uint8_t ep, enum it82xx2_ep_ctrl ctrl, bool enable) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; uint8_t ep_idx = USB_EP_GET_IDX(ep); @@ -448,7 +460,11 @@ static int it82xx2_usb_ep_ctrl(uint8_t ep, enum it82xx2_ep_ctrl ctrl, bool enabl ep_regs[ep_idx].ep_ctrl.fields.enable_bit = enable; break; case EP_READY_ENABLE: + unsigned int key; + + key = irq_lock(); ep_regs[ep_idx].ep_ctrl.fields.ready_bit = enable; + irq_unlock(key); break; case EP_DATA_SEQ_1: ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = enable; @@ -485,8 +501,7 @@ static int it82xx2_usb_set_ep_ctrl(uint8_t ep, enum it82xx2_ep_ctrl ctrl, bool e static int it82xx2_usb_dc_ip_init(void) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); /* Reset Device Controller */ usb_regs->host_device_control = RESET_CORE; @@ -524,8 +539,7 @@ static int it82xx2_usb_dc_attach_init(void) /* Check the condition that SETUP_TOKEN following OUT_TOKEN and return it */ static bool it82xx2_check_setup_following_out(void) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; @@ -536,8 +550,7 @@ static bool it82xx2_check_setup_following_out(void) static inline void it82xx2_handler_setup(uint8_t fifo_idx, uint8_t ep_ctrl) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; uint8_t ep_idx = fifo_idx; @@ -578,34 +591,19 @@ static inline void it82xx2_handler_setup(uint8_t fifo_idx, uint8_t ep_ctrl) /* Set ready bit to no-data control in */ if (udata0.no_data_ctrl) { - ep_regs[fifo_idx].ep_ctrl.fields.ready_bit = 1; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); udata0.no_data_ctrl = false; } } -static inline void it82xx2_handler_in(uint8_t fifo_idx, uint8_t ep_ctrl) +static inline void it82xx2_handler_in(const uint8_t ep_idx, const uint8_t ep_ctrl) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; - volatile struct epn_ext_ctrl_regs *epn_ext_ctrl = - usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; - uint8_t ep_idx; - if (fifo_idx != 0) { - if (!udata0.fifo_ready[fifo_idx - 1]) { - return; - } - - ep_idx = (epn_ext_ctrl[fifo_idx].epn_ext_ctrl2 & COMPLETED_TRANS) >> 4; - if (ep_idx == 0 || udata0.ep_data[ep_idx].ep_status != EP_CONFIG_IN) { - return; - } - udata0.fifo_ready[fifo_idx - 1] = false; - } else { - ep_idx = 0; + if (ep_idx == 0) { if (ep_ctrl & EP_SEND_STALL) { - ep_regs[fifo_idx].ep_ctrl.fields.send_stall_bit = 0; + ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit = 0; udata0.st_state = STALL_SEND; LOG_DBG("Clear Stall Bit"); return; @@ -644,36 +642,25 @@ static inline void it82xx2_handler_in(uint8_t fifo_idx, uint8_t ep_ctrl) udata0.ep_data[ep_idx].cb_in(ep_idx | USB_EP_DIR_IN, USB_DC_EP_DATA_IN); } - if (fifo_idx != 0) { - k_sem_give(&udata0.fifo_sem[fifo_idx - 1]); + if (ep_idx != 0) { + uint8_t ep_fifo = ep_fifo_res[ep_idx % FIFO_NUM]; + + /* clear fifo ctrl registers when IN transaction is completed */ + it82xx2_usb_fifo_ctrl(ep_idx, true); + k_sem_give(&udata0.fifo_sem[ep_fifo - 1]); } else { if (udata0.st_state == DIN_ST && udata0.ep_data[ep_idx].remaining == 0) { - ep_regs[fifo_idx].ep_ctrl.fields.ready_bit = 1; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); } } } -static inline void it82xx2_handler_out(uint8_t fifo_idx) +static inline void it82xx2_handler_out(const uint8_t ep_idx) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; - volatile struct epn_ext_ctrl_regs *epn_ext_ctrl = - usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; - uint8_t ep_idx; - - if (fifo_idx != 0) { - if (!udata0.fifo_ready[fifo_idx - 1]) { - return; - } - ep_idx = (epn_ext_ctrl[fifo_idx].epn_ext_ctrl2 & COMPLETED_TRANS) >> 4; - if (ep_idx == 0 || udata0.ep_data[ep_idx].ep_status != EP_CONFIG_OUT) { - return; - } - udata0.fifo_ready[fifo_idx - 1] = false; - } else { - ep_idx = 0; + if (ep_idx == 0) { /* ep0 wrong enter check */ if (udata0.st_state >= STATUS_ST) { return; @@ -695,45 +682,150 @@ static inline void it82xx2_handler_out(uint8_t fifo_idx) udata0.ep_data[ep_idx].cb_out(ep_idx, USB_DC_EP_DATA_OUT); } - if (fifo_idx == 0) { + if (ep_idx == 0) { /* SETUP_TOKEN follow OUT_TOKEN */ if (it82xx2_check_setup_following_out()) { udata0.last_token = udata0.now_token; udata0.now_token = SETUP_TOKEN; udata0.st_state = SETUP_ST; - ep_regs[fifo_idx].ep_ctrl.fields.outdata_sequence_bit = 1; + ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = 1; udata0.ep_data[ep_idx].cb_out(ep_idx | USB_EP_DIR_OUT, USB_DC_EP_SETUP); if (udata0.no_data_ctrl) { - ep_regs[fifo_idx].ep_ctrl.fields.ready_bit = 1; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); udata0.no_data_ctrl = false; } } } } +static bool get_extend_enable_bit(const uint8_t ep_idx) +{ + union epn_extend_ctrl1_reg *epn_ext_ctrl1 = NULL; + bool enable; + + epn_ext_ctrl1 = (union epn_extend_ctrl1_reg *)it82xx2_get_ext_ctrl(ep_idx, EP_ENABLE); + if (((ep_idx - 4) / 3 == 0)) { + enable = (epn_ext_ctrl1->fields.epn0_enable_bit != 0); + } else if (((ep_idx - 4) / 3 == 1)) { + enable = (epn_ext_ctrl1->fields.epn3_enable_bit != 0); + } else if (((ep_idx - 4) / 3 == 2)) { + enable = (epn_ext_ctrl1->fields.epn6_enable_bit != 0); + } else { + enable = (epn_ext_ctrl1->fields.epn9_enable_bit != 0); + } + + return enable; +} + +static bool get_extend_ready_bit(const uint8_t ep_idx) +{ + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); + struct epn_ext_ctrl_regs *ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; + int idx = ((ep_idx - 4) % 3) + 1; + + return ((ext_ctrl[idx].epn_ext_ctrl2 & BIT((ep_idx - 4) / 3)) != 0); +} + +static uint16_t get_fifo_ctrl(const uint8_t fifo_idx) +{ + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); + volatile uint8_t *ep_fifo_ctrl = usb_regs->fifo_regs[EP_EXT_REGS_BX].fifo_ctrl.ep_fifo_ctrl; + uint8_t fifon_ctrl = (fifo_idx - 1) * 2; + + if (fifo_idx == 0) { + LOG_ERR("Invalid fifo_idx 0x%x", fifo_idx); + return 0; + } + + return (ep_fifo_ctrl[fifon_ctrl + 1] << 8 | ep_fifo_ctrl[fifon_ctrl]); +} + +static bool it82xx2_usb_fake_token(const uint8_t ep_idx, uint8_t *token_type) +{ + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + bool is_fake = false; + bool enable_bit, ready_bit; + uint8_t ep_fifo = (ep_idx > 0) ? (ep_fifo_res[ep_idx % FIFO_NUM]) : 0; + + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + enable_bit = get_extend_enable_bit(ep_idx); + ready_bit = get_extend_ready_bit(ep_idx); + } else { + enable_bit = (ep_regs[ep_idx].ep_ctrl.fields.enable_bit != 0); + ready_bit = (ep_regs[ep_idx].ep_ctrl.fields.ready_bit != 0); + } + + /* The enable bit is set and the ready bit is cleared if the + * transaction is completed. + */ + if (!enable_bit || ready_bit) { + return true; + } + + *token_type = ep_regs[ep_fifo].ep_transtype_sts & DC_ALL_TRANS; + + if (ep_idx == 0) { + return false; + } + + switch (*token_type) { + case DC_IN_TRANS: + if (get_fifo_ctrl(ep_fifo) != BIT(ep_idx) || + udata0.ep_data[ep_idx].ep_status != EP_CONFIG_IN) { + is_fake = true; + } + break; + case DC_OUTDATA_TRANS: + if (!udata0.fifo_ready[ep_fifo - 1] || + udata0.ep_data[ep_idx].ep_status != EP_CONFIG_OUT) { + is_fake = true; + } else { + udata0.fifo_ready[ep_fifo - 1] = false; + } + break; + case DC_SETUP_TRANS: + __fallthrough; + default: + is_fake = true; + break; + } + + return is_fake; +} + static void it82xx2_usb_dc_trans_done(void) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct epn_ext_ctrl_regs *epn_ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; for (uint8_t fifo_idx = 0; fifo_idx < 4; fifo_idx++) { uint8_t ep_ctrl = ep_regs[fifo_idx].ep_ctrl.value; + uint8_t ep_idx, token_type; - /* check ready bit ,will be 0 when trans done */ - if ((ep_ctrl & ENDPOINT_EN) && !(ep_ctrl & ENDPOINT_RDY)) { - switch (ep_regs[fifo_idx].ep_transtype_sts & DC_ALL_TRANS) { + if (fifo_idx == 0) { + ep_idx = 0; + } else { + ep_idx = (epn_ext_ctrl[fifo_idx].epn_ext_ctrl2 & COMPLETED_TRANS) >> 4; + if (ep_idx == 0) { + continue; + } + } + + if (!it82xx2_usb_fake_token(ep_idx, &token_type)) { + switch (token_type) { case DC_SETUP_TRANS: - if (fifo_idx == 0) { - it82xx2_handler_setup(fifo_idx, ep_ctrl); - } + it82xx2_handler_setup(fifo_idx, ep_ctrl); break; case DC_IN_TRANS: - it82xx2_handler_in(fifo_idx, ep_ctrl); + it82xx2_handler_in(ep_idx, ep_ctrl); break; case DC_OUTDATA_TRANS: - it82xx2_handler_out(fifo_idx); + it82xx2_handler_out(ep_idx); break; default: break; @@ -744,8 +836,7 @@ static void it82xx2_usb_dc_trans_done(void) static void it82xx2_usb_dc_isr(void) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); uint8_t status = usb_regs->dc_interrupt_status & usb_regs->dc_interrupt_mask; /* mask non enable int */ @@ -782,8 +873,7 @@ static void suspended_check_handler(struct k_work *item) struct usb_it82xx2_data *udata = CONTAINER_OF(dwork, struct usb_it82xx2_data, check_suspended_work); - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); if (usb_regs->dc_interrupt_status & DC_SOF_RECEIVED) { usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; @@ -818,8 +908,7 @@ static void suspended_check_handler(struct k_work *item) int usb_dc_attach(void) { int ret; - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); if (udata0.attached) { LOG_DBG("Already Attached"); @@ -867,8 +956,7 @@ int usb_dc_attach(void) int usb_dc_detach(void) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); if (!udata0.attached) { LOG_DBG("Already Detached"); @@ -887,8 +975,7 @@ int usb_dc_detach(void) int usb_dc_reset(void) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; @@ -1002,7 +1089,7 @@ int usb_dc_ep_configure(const struct usb_dc_ep_cfg_data *const cfg) udata0.ep_data[ep_idx].ep_status = EP_CONFIG_IN; } else { udata0.ep_data[ep_idx].ep_status = EP_CONFIG_OUT; - it82xx2_usb_fifo_ctrl(cfg->ep_addr); + it82xx2_usb_fifo_ctrl(cfg->ep_addr, false); } switch (cfg->ep_type) { @@ -1093,8 +1180,7 @@ int usb_dc_ep_disable(uint8_t ep) int usb_dc_ep_set_stall(const uint8_t ep) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; uint8_t ep_idx = USB_EP_GET_IDX(ep); @@ -1109,7 +1195,7 @@ int usb_dc_ep_set_stall(const uint8_t ep) if (ep_idx == 0) { uint32_t idx = 0; - ep_regs[ep_idx].ep_ctrl.fields.ready_bit = 1; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); /* polling if stall send for 3ms */ while (idx < 198 && !(ep_regs[ep_idx].ep_status & DC_STALL_SENT)) { @@ -1166,8 +1252,7 @@ int usb_dc_ep_halt(uint8_t ep) int usb_dc_ep_flush(uint8_t ep) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; uint8_t ep_idx = USB_EP_GET_IDX(ep); @@ -1189,11 +1274,9 @@ int usb_dc_ep_flush(uint8_t ep) int usb_dc_ep_write(uint8_t ep, const uint8_t *buf, uint32_t data_len, uint32_t *ret_bytes) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); - struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; - + unsigned int key; uint8_t ep_idx = USB_EP_GET_IDX(ep); uint8_t ep_fifo = (ep_idx > 0) ? (ep_fifo_res[ep_idx % FIFO_NUM]) : 0; @@ -1213,7 +1296,8 @@ int usb_dc_ep_write(uint8_t ep, const uint8_t *buf, } } else { k_sem_take(&udata0.fifo_sem[ep_fifo - 1], K_FOREVER); - it82xx2_usb_fifo_ctrl(ep); + key = irq_lock(); + it82xx2_usb_fifo_ctrl(ep, false); } if (data_len > udata0.ep_data[ep_idx].mps) { @@ -1238,14 +1322,9 @@ int usb_dc_ep_write(uint8_t ep, const uint8_t *buf, LOG_DBG("Write %d Packets to TX FIFO(%d)", data_len, ep_idx); } - if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { - it82xx2_usb_extend_ep_ctrl(ep_idx, EP_READY_ENABLE, true); - } - - ep_regs[ep_fifo].ep_ctrl.fields.ready_bit = 1; - - if (ep_fifo > EP0) { - udata0.fifo_ready[ep_fifo - 1] = true; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); + if (ep_idx != 0) { + irq_unlock(key); } LOG_DBG("Set EP%d Ready(%d)", ep_idx, __LINE__); @@ -1257,8 +1336,7 @@ int usb_dc_ep_write(uint8_t ep, const uint8_t *buf, int usb_dc_ep_read(uint8_t ep, uint8_t *buf, uint32_t max_data_len, uint32_t *read_bytes) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; @@ -1274,20 +1352,25 @@ int usb_dc_ep_read(uint8_t ep, uint8_t *buf, uint32_t max_data_len, LOG_WRN("fifo_%d error status: 0x%02x", ep_fifo, ep_regs[ep_fifo].ep_status); } - if (max_data_len == 0) { - - *read_bytes = 0; + rx_fifo_len = (uint16_t)ff_regs[ep_fifo].ep_rx_fifo_dcnt_lsb + + (((uint16_t)ff_regs[ep_fifo].ep_rx_fifo_dcnt_msb) << 8); - if (ep_idx > 0) { - ep_regs[ep_idx].ep_ctrl.fields.ready_bit = 1; + if (!buf && !max_data_len) { + /* + * When both buffer and max data to read are zero return + * the available data length in buffer. + */ + if (read_bytes) { + *read_bytes = rx_fifo_len; } + if (ep_idx > 0 && !rx_fifo_len) { + udata0.fifo_ready[ep_fifo - 1] = true; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); + } return 0; } - rx_fifo_len = (uint16_t)ff_regs[ep_fifo].ep_rx_fifo_dcnt_lsb + - (((uint16_t)ff_regs[ep_fifo].ep_rx_fifo_dcnt_msb) << 8); - if (ep_idx == 0) { /* Prevent wrong read_bytes cause memory error * if EP0 is in OUT status stage @@ -1331,11 +1414,8 @@ int usb_dc_ep_read(uint8_t ep, uint8_t *buf, uint32_t max_data_len, } if (ep_fifo > EP0) { - ep_regs[ep_fifo].ep_ctrl.fields.ready_bit = 1; - if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { - it82xx2_usb_extend_ep_ctrl(ep_idx, EP_READY_ENABLE, true); - } udata0.fifo_ready[ep_fifo - 1] = true; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); } else if (udata0.now_token == SETUP_TOKEN) { if (!(buf[0] & USB_EP_DIR_MASK)) { /* request type: host-to-device transfer direction */ @@ -1343,7 +1423,7 @@ int usb_dc_ep_read(uint8_t ep, uint8_t *buf, uint32_t max_data_len, if (buf[6] != 0 || buf[7] != 0) { /* set status IN after data OUT */ ep_regs[0].ep_ctrl.fields.outdata_sequence_bit = 1; - ep_regs[0].ep_ctrl.fields.ready_bit = 1; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); } else { /* no_data_ctrl status */ udata0.no_data_ctrl = true; @@ -1358,8 +1438,7 @@ int usb_dc_ep_read(uint8_t ep, uint8_t *buf, uint32_t max_data_len, int usb_dc_ep_read_wait(uint8_t ep, uint8_t *buf, uint32_t max_data_len, uint32_t *read_bytes) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; @@ -1400,10 +1479,6 @@ int usb_dc_ep_read_wait(uint8_t ep, uint8_t *buf, uint32_t max_data_len, int usb_dc_ep_read_continue(uint8_t ep) { - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); - struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; - uint8_t ep_idx = USB_EP_GET_IDX(ep); uint8_t ep_fifo = (ep_idx > 0) ? (ep_fifo_res[ep_idx % FIFO_NUM]) : 0; @@ -1417,11 +1492,8 @@ int usb_dc_ep_read_continue(uint8_t ep) return -EINVAL; } - if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { - it82xx2_usb_extend_ep_ctrl(ep_idx, EP_READY_ENABLE, true); - } - ep_regs[ep_fifo].ep_ctrl.fields.ready_bit = 1; udata0.fifo_ready[ep_fifo - 1] = true; + it82xx2_usb_set_ep_ctrl(ep_idx, EP_READY_ENABLE, true); LOG_DBG("EP(%d) Read Continue", ep_idx); return 0; } @@ -1447,8 +1519,7 @@ int usb_dc_ep_mps(const uint8_t ep) int usb_dc_wakeup_request(void) { int ret; - struct usb_it82xx2_regs *const usb_regs = - (struct usb_it82xx2_regs *)it82xx2_get_usb_regs(); + struct usb_it82xx2_regs *const usb_regs = it82xx2_get_usb_regs(); if (udata0.suspended) { diff --git a/drivers/usb/device/usb_dc_mcux.c b/drivers/usb/device/usb_dc_mcux.c index e36eba8918252..d62662063eec3 100644 --- a/drivers/usb/device/usb_dc_mcux.c +++ b/drivers/usb/device/usb_dc_mcux.c @@ -89,7 +89,9 @@ BUILD_ASSERT(NUM_INSTS <= 1, "Only one USB device supported"); #elif DT_NODE_HAS_STATUS(DT_NODELABEL(usbfs), okay) #define CONTROLLER_ID kUSB_ControllerLpcIp3511Fs0 #endif /* LPC55s69 */ -#elif defined(CONFIG_SOC_SERIES_IMXRT11XX) || defined(CONFIG_SOC_SERIES_IMXRT10XX) +#elif defined(CONFIG_SOC_SERIES_IMXRT11XX) || \ + defined(CONFIG_SOC_SERIES_IMXRT10XX) || \ + defined(CONFIG_SOC_SERIES_MCXNX4X) #if DT_NODE_HAS_STATUS(DT_NODELABEL(usb1), okay) #define CONTROLLER_ID kUSB_ControllerEhci0 #elif DT_NODE_HAS_STATUS(DT_NODELABEL(usb2), okay) diff --git a/drivers/usb/device/usb_dc_native_posix.c b/drivers/usb/device/usb_dc_native_posix.c index c74dad9b35deb..d806d3513ef67 100644 --- a/drivers/usb/device/usb_dc_native_posix.c +++ b/drivers/usb/device/usb_dc_native_posix.c @@ -26,7 +26,11 @@ LOG_MODULE_REGISTER(native_posix); #define USBIP_IN_EP_NUM 8 #define USBIP_OUT_EP_NUM 8 +#ifdef CONFIG_USB_NATIVE_POSIX_HS +#define USBIP_MAX_PACKET_SIZE 512 +#else /* CONFIG_USB_NATIVE_POSIX_HS */ #define USBIP_MAX_PACKET_SIZE 64 +#endif /* !CONFIG_USB_NATIVE_POSIX_HS */ K_KERNEL_STACK_MEMBER(thread_stack, CONFIG_ARCH_POSIX_RECOMMENDED_STACK_SIZE); static struct k_thread thread; diff --git a/drivers/usb/device/usb_dc_native_posix_adapt.c b/drivers/usb/device/usb_dc_native_posix_adapt.c index f62b6242491bf..14ede80fec0cf 100644 --- a/drivers/usb/device/usb_dc_native_posix_adapt.c +++ b/drivers/usb/device/usb_dc_native_posix_adapt.c @@ -127,7 +127,11 @@ static void fill_device(struct devlist_device *dev, const uint8_t *desc) dev->busnum = htonl(1); dev->devnum = htonl(2); - dev->speed = htonl(2); + if (IS_ENABLED(CONFIG_USB_NATIVE_POSIX_HS)) { + dev->speed = htonl(3); + } else { + dev->speed = htonl(2); + } dev->idVendor = htons(dev_dsc->idVendor); dev->idProduct = htons(dev_dsc->idProduct); diff --git a/drivers/usb/device/usb_dc_rpi_pico.c b/drivers/usb/device/usb_dc_rpi_pico.c index bb99fa365b285..c6623727c1e2a 100644 --- a/drivers/usb/device/usb_dc_rpi_pico.c +++ b/drivers/usb/device/usb_dc_rpi_pico.c @@ -787,7 +787,7 @@ int usb_dc_ep_read_wait(uint8_t ep, uint8_t *data, } LOG_DBG("ep 0x%02x, %u bytes, %u+%u, %p", ep, max_data_len, ep_state->read_offset, - read_count, data); + read_count, (void *)data); if (data) { read_count = MIN(read_count, max_data_len); diff --git a/drivers/usb/device/usb_dc_stm32.c b/drivers/usb/device/usb_dc_stm32.c index ad9c6ac520cab..dbfd359f10bbc 100644 --- a/drivers/usb/device/usb_dc_stm32.c +++ b/drivers/usb/device/usb_dc_stm32.c @@ -265,27 +265,26 @@ static int usb_dc_stm32_clock_enable(void) #endif /* RCC_CFGR_OTGFSPRE / RCC_CFGR_USBPRE */ -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) +#if USB_OTG_HS_ULPI_PHY +#if defined(CONFIG_SOC_SERIES_STM32H7X) + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); +#else LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_OTGHSULPI); - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC); -#elif defined(CONFIG_SOC_SERIES_STM32H7X) -#if !USB_OTG_HS_ULPI_PHY - /* Disable ULPI interface (for external high-speed PHY) clock in sleep - * mode. - */ - LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); #endif -#else /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) */ -#if !USB_OTG_HS_ULPI_PHY - /* Disable ULPI interface (for external high-speed PHY) clock in low - * power mode. It is disabled by default in run power mode, no need to - * disable it. +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) /* USB_OTG_HS_ULPI_PHY */ + /* Disable ULPI interface (for external high-speed PHY) clock in sleep/low-power mode. It is + * disabled by default in run power mode, no need to disable it. */ +#if defined(CONFIG_SOC_SERIES_STM32H7X) + LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); +#else LL_AHB1_GRP1_DisableClockLowPower(LL_AHB1_GRP1_PERIPH_OTGHSULPI); +#endif + +#if USB_OTG_HS_EMB_PHY + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC); +#endif #endif /* USB_OTG_HS_ULPI_PHY */ -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) */ -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) */ return 0; } @@ -884,7 +883,7 @@ int usb_dc_ep_read_wait(uint8_t ep, uint8_t *data, uint32_t max_data_len, read_count = ep_state->read_count; LOG_DBG("ep 0x%02x, %u bytes, %u+%u, %p", ep, max_data_len, - ep_state->read_offset, read_count, data); + ep_state->read_offset, read_count, (void *)data); if (!USB_EP_DIR_IS_OUT(ep)) { /* check if OUT ep */ LOG_ERR("Wrong endpoint direction: 0x%02x", ep); diff --git a/drivers/usb/udc/CMakeLists.txt b/drivers/usb/udc/CMakeLists.txt index ebca5f6427753..6004729d373fc 100644 --- a/drivers/usb/udc/CMakeLists.txt +++ b/drivers/usb/udc/CMakeLists.txt @@ -12,3 +12,6 @@ zephyr_library_sources_ifdef(CONFIG_UDC_KINETIS udc_kinetis.c) zephyr_library_sources_ifdef(CONFIG_UDC_SKELETON udc_skeleton.c) zephyr_library_sources_ifdef(CONFIG_UDC_VIRTUAL udc_virtual.c) zephyr_library_sources_ifdef(CONFIG_UDC_STM32 udc_stm32.c) +zephyr_library_sources_ifdef(CONFIG_UDC_IT82XX2 udc_it82xx2.c) +zephyr_library_sources_ifdef(CONFIG_UDC_NXP_EHCI udc_mcux_ehci.c) +zephyr_library_sources_ifdef(CONFIG_UDC_NXP_IP3511 udc_mcux_ip3511.c) diff --git a/drivers/usb/udc/Kconfig b/drivers/usb/udc/Kconfig index 5b19a3385ad9f..b4d1df0114ad6 100644 --- a/drivers/usb/udc/Kconfig +++ b/drivers/usb/udc/Kconfig @@ -53,5 +53,7 @@ source "drivers/usb/udc/Kconfig.kinetis" source "drivers/usb/udc/Kconfig.skeleton" source "drivers/usb/udc/Kconfig.virtual" source "drivers/usb/udc/Kconfig.stm32" +source "drivers/usb/udc/Kconfig.it82xx2" +source "drivers/usb/udc/Kconfig.mcux" endif # UDC_DRIVER diff --git a/drivers/usb/udc/Kconfig.dwc2 b/drivers/usb/udc/Kconfig.dwc2 index c05aed352665b..a1a1c9d22cece 100644 --- a/drivers/usb/udc/Kconfig.dwc2 +++ b/drivers/usb/udc/Kconfig.dwc2 @@ -5,6 +5,8 @@ config UDC_DWC2 bool "DWC2 USB device controller driver" default y depends on DT_HAS_SNPS_DWC2_ENABLED + select NRFS if NRFS_HAS_VBUS_DETECTOR_SERVICE + select NRFS_VBUS_DETECTOR_SERVICE_ENABLED if NRFS_HAS_VBUS_DETECTOR_SERVICE help DWC2 USB device controller driver. diff --git a/drivers/usb/udc/Kconfig.it82xx2 b/drivers/usb/udc/Kconfig.it82xx2 new file mode 100644 index 0000000000000..649b2531d10db --- /dev/null +++ b/drivers/usb/udc/Kconfig.it82xx2 @@ -0,0 +1,27 @@ +# Copyright (c) 2023 ITE Corporation. +# SPDX-License-Identifier: Apache-2.0 + +config UDC_IT82XX2 + bool "IT82XX2 USB device controller driver" + default y + depends on DT_HAS_ITE_IT82XX2_USB_ENABLED + help + IT82xx2 USB device controller driver. + +if UDC_IT82XX2 + +config UDC_IT82xx2_EVENT_COUNT + int "UDC IT82xx2 event count" + range 4 64 + default 8 + help + IT82xx2 event count. + +config UDC_IT82xx2_STACK_SIZE + int "IT82xx2 UDC driver internal thread stack size" + default 1024 + help + Size of the stack used in the driver for IT82xx2 USBD ISR event + handling. + +endif # UDC_IT82XX2 diff --git a/drivers/usb/udc/Kconfig.mcux b/drivers/usb/udc/Kconfig.mcux new file mode 100644 index 0000000000000..f36eab115b0c6 --- /dev/null +++ b/drivers/usb/udc/Kconfig.mcux @@ -0,0 +1,17 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config UDC_NXP_EHCI + bool "NXP MCUX USB EHCI Device controller driver" + default y + depends on DT_HAS_NXP_EHCI_ENABLED + select NOCACHE_MEMORY if HAS_MCUX_CACHE && CPU_HAS_DCACHE + help + NXP MCUX USB Device Controller Driver for EHCI. + +config UDC_NXP_IP3511 + bool "NXP MCUX USB IP3511 Device controller driver" + default y + depends on DT_HAS_NXP_LPCIP3511_ENABLED + help + NXP MCUX USB Device Controller Driver for KHCI. diff --git a/drivers/usb/udc/udc_common.c b/drivers/usb/udc/udc_common.c index 90a73d592307c..eeed077ebc47a 100644 --- a/drivers/usb/udc/udc_common.c +++ b/drivers/usb/udc/udc_common.c @@ -175,10 +175,6 @@ int udc_submit_event(const struct device *dev, .dev = dev, }; - if (!udc_is_initialized(dev)) { - return -EPERM; - } - return data->event_cb(dev, &drv_evt); } diff --git a/drivers/usb/udc/udc_dwc2.c b/drivers/usb/udc/udc_dwc2.c index 0c1463e979801..e97001ca9c352 100644 --- a/drivers/usb/udc/udc_dwc2.c +++ b/drivers/usb/udc/udc_dwc2.c @@ -6,7 +6,6 @@ #include "udc_common.h" #include "udc_dwc2.h" -#include "udc_dwc2_vendor_quirks.h" #include #include @@ -22,6 +21,7 @@ #include LOG_MODULE_REGISTER(udc_dwc2, CONFIG_UDC_DRIVER_LOG_LEVEL); +#include "udc_dwc2_vendor_quirks.h" enum dwc2_drv_event_type { /* Trigger next transfer, must not be used for control OUT */ @@ -54,12 +54,6 @@ K_MSGQ_DEFINE(drv_msgq, sizeof(struct dwc2_drv_event), /* TX FIFO0 depth in 32-bit words (used by control IN endpoint) */ #define UDC_DWC2_FIFO0_DEPTH 16U -/* Number of endpoints supported by the driver. - * This must be equal to or greater than the number supported by the hardware. - * (FIXME) - */ -#define UDC_DWC2_DRV_EP_NUM 8 - /* Get Data FIFO access register */ #define UDC_DWC2_EP_FIFO(base, idx) ((mem_addr_t)base + 0x1000 * (idx + 1)) @@ -75,7 +69,7 @@ struct udc_dwc2_data { uint32_t max_pktcnt; uint32_t tx_len[16]; unsigned int dynfifosizing : 1; - /* Number of endpoints in addition to control endpoint */ + /* Number of endpoints including control endpoint */ uint8_t numdeveps; /* Number of IN endpoints including control endpoint */ uint8_t ineps; @@ -265,6 +259,7 @@ static int dwc2_tx_fifo_write(const struct device *dev, mem_addr_t dieptsiz_reg = (mem_addr_t)&base->in_ep[ep_idx].dieptsiz; /* TODO: use dwc2_get_dxepctl_reg() */ mem_addr_t diepctl_reg = (mem_addr_t)&base->in_ep[ep_idx].diepctl; + mem_addr_t diepint_reg = (mem_addr_t)&base->in_ep[ep_idx].diepint; uint32_t max_xfersize, max_pktcnt, pktcnt, spcavail; const size_t d = sizeof(uint32_t); @@ -327,6 +322,8 @@ static int dwc2_tx_fifo_write(const struct device *dev, /* Clear NAK and set endpoint enable */ sys_set_bits(diepctl_reg, USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_CNAK); + /* Clear IN Endpoint NAK Effective interrupt in case it was set */ + sys_write32(USB_DWC2_DIEPINT_INEPNAKEFF, diepint_reg); /* FIFO access is always in 32-bit words */ @@ -355,7 +352,7 @@ static inline int dwc2_read_fifo(const struct device *dev, const uint8_t ep, struct net_buf *const buf, const size_t size) { struct usb_dwc2_reg *const base = dwc2_get_base(dev); - size_t len = MIN(size, net_buf_tailroom(buf)); + size_t len = buf ? MIN(size, net_buf_tailroom(buf)) : 0; const size_t d = sizeof(uint32_t); /* FIFO access is always in 32-bit words */ @@ -395,7 +392,7 @@ static void dwc2_prep_rx(const struct device *dev, doeptsiz = (1 << USB_DWC2_DOEPTSIZ0_PKTCNT_POS) | cfg->mps; if (cfg->addr == USB_CONTROL_EP_OUT) { - doeptsiz |= (1 << USB_DWC2_DOEPTSIZ0_SUPCNT_POS); + doeptsiz |= (3 << USB_DWC2_DOEPTSIZ0_SUPCNT_POS); } sys_write32(doeptsiz, doeptsiz_reg); @@ -472,7 +469,10 @@ static int dwc2_handle_evt_setup(const struct device *dev) /* Allocate and feed buffer for data OUT stage */ LOG_DBG("s:%p|feed for -out-", buf); - err = dwc2_ctrl_feed_dout(dev, udc_data_stage_length(buf)); + /* Allocate at least 8 bytes in case the host decides to send + * SETUP DATA instead of OUT DATA packet. + */ + err = dwc2_ctrl_feed_dout(dev, MAX(udc_data_stage_length(buf), 8)); if (err == -ENOMEM) { err = udc_submit_ep_event(dev, buf, err); } @@ -656,7 +656,7 @@ static void dwc2_on_bus_reset(const struct device *dev) } } - sys_write32(0UL, (mem_addr_t)&base->doepmsk); + sys_write32(USB_DWC2_DOEPINT_SETUP, (mem_addr_t)&base->doepmsk); sys_set_bits((mem_addr_t)&base->gintmsk, USB_DWC2_GINTSTS_RXFLVL); sys_set_bits((mem_addr_t)&base->diepmsk, USB_DWC2_DIEPINT_XFERCOMPL); @@ -674,13 +674,19 @@ static void dwc2_handle_enumdone(const struct device *dev) priv->enumspd = usb_dwc2_get_dsts_enumspd(dsts); } -static inline int dwc2_read_fifo_setup(const struct device *dev) +static inline int dwc2_read_fifo_setup(const struct device *dev, uint8_t ep, + const size_t size) { struct usb_dwc2_reg *const base = dwc2_get_base(dev); struct udc_dwc2_data *const priv = udc_get_private(dev); + size_t offset; /* FIFO access is always in 32-bit words */ + if (size != 8) { + LOG_ERR("%d bytes SETUP", size); + } + /* * We store the setup packet temporarily in the driver's private data * because there is always a race risk after the status stage OUT @@ -688,8 +694,16 @@ static inline int dwc2_read_fifo_setup(const struct device *dev) * bottom-half processing because the events arrive in a queue and * there will be a next net_buf for the setup packet. */ - sys_put_le32(sys_read32(UDC_DWC2_EP_FIFO(base, 0)), priv->setup); - sys_put_le32(sys_read32(UDC_DWC2_EP_FIFO(base, 0)), &priv->setup[4]); + for (offset = 0; offset < MIN(size, 8); offset += 4) { + sys_put_le32(sys_read32(UDC_DWC2_EP_FIFO(base, ep)), + &priv->setup[offset]); + } + + /* On protocol error simply discard extra data */ + while (offset < size) { + sys_read32(UDC_DWC2_EP_FIFO(base, ep)); + offset += 4; + } return 0; } @@ -712,26 +726,23 @@ static inline void dwc2_handle_rxflvl(const struct device *dev) switch (pktsts) { case USB_DWC2_GRXSTSR_PKTSTS_SETUP: - evt.type = DWC2_DRV_EVT_SETUP; - - __ASSERT(evt.bcnt == 8, "Incorrect setup packet length"); - dwc2_read_fifo_setup(dev); - - k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); + dwc2_read_fifo_setup(dev, evt.ep, evt.bcnt); break; case USB_DWC2_GRXSTSR_PKTSTS_OUT_DATA: evt.type = DWC2_DRV_EVT_DOUT; ep_cfg = udc_get_ep_cfg(dev, evt.ep); buf = udc_buf_peek(dev, ep_cfg->addr); + + /* RxFIFO data must be retrieved even when buf is NULL */ + dwc2_read_fifo(dev, evt.ep, buf, evt.bcnt); + if (buf == NULL) { LOG_ERR("No buffer for ep 0x%02x", ep_cfg->addr); udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); break; } - dwc2_read_fifo(dev, USB_CONTROL_EP_OUT, buf, evt.bcnt); - if (net_buf_tailroom(buf) && evt.bcnt == ep_cfg->mps) { dwc2_prep_rx(dev, ep_cfg, 0); } else { @@ -740,9 +751,13 @@ static inline void dwc2_handle_rxflvl(const struct device *dev) break; case USB_DWC2_GRXSTSR_PKTSTS_OUT_DATA_DONE: - case USB_DWC2_GRXSTSR_PKTSTS_SETUP_DONE: LOG_DBG("RX pktsts DONE"); break; + case USB_DWC2_GRXSTSR_PKTSTS_SETUP_DONE: + LOG_DBG("SETUP pktsts DONE"); + case USB_DWC2_GRXSTSR_PKTSTS_GLOBAL_OUT_NAK: + LOG_DBG("Global OUT NAK"); + break; default: break; } @@ -819,7 +834,6 @@ static inline void dwc2_handle_oepint(const struct device *dev) doepmsk = sys_read32((mem_addr_t)&base->doepmsk); daint = sys_read32((mem_addr_t)&base->daint); - /* No OUT interrupt expected in FIFO mode, just clear interrupt */ for (uint8_t n = 0U; n < n_max; n++) { mem_addr_t doepint_reg = (mem_addr_t)&base->out_ep[n].doepint; uint32_t doepint; @@ -832,6 +846,16 @@ static inline void dwc2_handle_oepint(const struct device *dev) sys_write32(status, doepint_reg); LOG_DBG("ep 0x%02x interrupt status: 0x%x", n, status); + + if (status & USB_DWC2_DOEPINT_SETUP) { + struct dwc2_drv_event evt = { + .type = DWC2_DRV_EVT_SETUP, + .ep = USB_CONTROL_EP_OUT, + .bcnt = 8, + }; + + k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); + } } } @@ -865,13 +889,13 @@ static void udc_dwc2_isr_handler(const struct device *dev) sys_write32(USB_DWC2_GINTSTS_USBRST, gintsts_reg); dwc2_on_bus_reset(dev); LOG_DBG("USB Reset interrupt"); - udc_submit_event(dev, UDC_EVT_RESET, 0); } if (int_status & USB_DWC2_GINTSTS_ENUMDONE) { /* Clear and handle Enumeration Done interrupt. */ sys_write32(USB_DWC2_GINTSTS_ENUMDONE, gintsts_reg); dwc2_handle_enumdone(dev); + udc_submit_event(dev, UDC_EVT_RESET, 0); } if (int_status & USB_DWC2_GINTSTS_USBSUSP) { @@ -888,67 +912,23 @@ static void udc_dwc2_isr_handler(const struct device *dev) udc_submit_event(dev, UDC_EVT_RESUME, 0); } - if (int_status & USB_DWC2_GINTSTS_RXFLVL) { - /* Handle RxFIFO Non-Empty interrupt */ - dwc2_handle_rxflvl(dev); - } - if (int_status & USB_DWC2_GINTSTS_IEPINT) { /* Handle IN Endpoints interrupt */ dwc2_handle_iepint(dev); } + if (int_status & USB_DWC2_GINTSTS_RXFLVL) { + /* Handle RxFIFO Non-Empty interrupt */ + dwc2_handle_rxflvl(dev); + } + if (int_status & USB_DWC2_GINTSTS_OEPINT) { /* Handle OUT Endpoints interrupt */ dwc2_handle_oepint(dev); } } - if (config->quirks != NULL && config->quirks->irq_clear != NULL) { - config->quirks->irq_clear(dev); - } -} - -static int udc_dwc2_ep_enqueue(const struct device *dev, - struct udc_ep_config *const cfg, - struct net_buf *const buf) -{ - struct dwc2_drv_event evt = { - .ep = cfg->addr, - .type = DWC2_DRV_EVT_XFER, - }; - - LOG_DBG("%p enqueue %x %p", dev, cfg->addr, buf); - udc_buf_put(cfg, buf); - - if (!cfg->stat.halted) { - k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); - } - - return 0; -} - -static int udc_dwc2_ep_dequeue(const struct device *dev, - struct udc_ep_config *const cfg) -{ - unsigned int lock_key; - struct net_buf *buf; - - lock_key = irq_lock(); - - if (USB_EP_DIR_IS_IN(cfg->addr)) { - dwc2_flush_tx_fifo(dev, USB_EP_GET_IDX(cfg->addr)); - } - - buf = udc_buf_get_all(dev, cfg->addr); - if (buf) { - udc_submit_ep_event(dev, buf, -ECONNABORTED); - } - - irq_unlock(lock_key); - LOG_DBG("dequeue ep 0x%02x", cfg->addr); - - return 0; + (void)dwc2_quirk_irq_clear(dev); } static void dwc2_unset_unused_fifo(const struct device *dev) @@ -956,7 +936,7 @@ static void dwc2_unset_unused_fifo(const struct device *dev) struct udc_dwc2_data *const priv = udc_get_private(dev); struct udc_ep_config *tmp; - for (uint8_t i = priv->ineps; i > 0; i--) { + for (uint8_t i = priv->ineps - 1U; i > 0; i--) { tmp = udc_get_ep_cfg(dev, i | USB_EP_DIR_IN); if (tmp->stat.enabled && (priv->txf_set & BIT(i))) { @@ -1094,8 +1074,8 @@ static int dwc2_ep_control_enable(const struct device *dev, return 0; } -static int udc_dwc2_ep_enable(const struct device *dev, - struct udc_ep_config *const cfg) +static int udc_dwc2_ep_activate(const struct device *dev, + struct udc_ep_config *const cfg) { struct usb_dwc2_reg *const base = dwc2_get_base(dev); struct udc_dwc2_data *const priv = udc_get_private(dev); @@ -1168,7 +1148,7 @@ static int udc_dwc2_ep_enable(const struct device *dev, for (uint8_t i = 1U; i < priv->ineps; i++) { LOG_DBG("DIEPTXF%u %08x DIEPCTL%u %08x", - i, sys_read32((mem_addr_t)base->dieptxf[i - 1U]), i, dxepctl); + i, sys_read32((mem_addr_t)&base->dieptxf[i - 1U]), i, dxepctl); } return 0; @@ -1199,8 +1179,141 @@ static int dwc2_unset_dedicated_fifo(const struct device *dev, return 0; } -static int udc_dwc2_ep_disable(const struct device *dev, - struct udc_ep_config *const cfg) +static void dwc2_wait_for_bit(const struct device *dev, + mem_addr_t addr, uint32_t bit) +{ + k_timepoint_t timeout = sys_timepoint_calc(K_MSEC(100)); + + /* This could potentially be converted to use proper synchronization + * primitives instead of busy looping, but the number of interrupt bits + * this function can be waiting for is rather high. + * + * Busy looping is most likely fine unless profiling shows otherwise. + */ + while (!(sys_read32(addr) & bit)) { + if (dwc2_quirk_is_phy_clk_off(dev)) { + /* No point in waiting, because the bit can only be set + * when the PHY is actively clocked. + */ + return; + } + + if (sys_timepoint_expired(timeout)) { + LOG_ERR("Timeout waiting for bit 0x%08X at 0x%08X", + bit, (uint32_t)addr); + return; + } + } +} + +/* Disabled IN endpoint means that device will send NAK (isochronous: ZLP) after + * receiving IN token from host even if there is packet available in TxFIFO. + * Disabled OUT endpoint means that device will NAK (isochronous: discard data) + * incoming OUT data (or HS PING) even if there is space available in RxFIFO. + * + * Set stall parameter to true if caller wants to send STALL instead of NAK. + */ +static void udc_dwc2_ep_disable(const struct device *dev, + struct udc_ep_config *const cfg, bool stall) +{ + struct usb_dwc2_reg *const base = dwc2_get_base(dev); + uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + mem_addr_t dxepctl_reg; + uint32_t dxepctl; + + dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr); + dxepctl = sys_read32(dxepctl_reg); + + if (dxepctl & USB_DWC2_DEPCTL_NAKSTS) { + /* Endpoint already sends forced NAKs. STALL if necessary. */ + if (stall) { + dxepctl |= USB_DWC2_DEPCTL_STALL; + sys_write32(dxepctl, dxepctl_reg); + } + + return; + } + + if (USB_EP_DIR_IS_OUT(cfg->addr)) { + mem_addr_t dctl_reg, gintsts_reg, doepint_reg; + uint32_t dctl; + + dctl_reg = (mem_addr_t)&base->dctl; + gintsts_reg = (mem_addr_t)&base->gintsts; + doepint_reg = (mem_addr_t)&base->out_ep[ep_idx].doepint; + + dctl = sys_read32(dctl_reg); + + if (sys_read32(gintsts_reg) & USB_DWC2_GINTSTS_GOUTNAKEFF) { + LOG_ERR("GOUTNAKEFF already active"); + } else { + dctl |= USB_DWC2_DCTL_SGOUTNAK; + sys_write32(dctl, dctl_reg); + dctl &= ~USB_DWC2_DCTL_SGOUTNAK; + } + + dwc2_wait_for_bit(dev, gintsts_reg, USB_DWC2_GINTSTS_GOUTNAKEFF); + + /* The application cannot disable control OUT endpoint 0. */ + if (ep_idx != 0) { + dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS; + } + + if (stall) { + /* For OUT endpoints STALL is set instead of SNAK */ + dxepctl |= USB_DWC2_DEPCTL_STALL; + } else { + dxepctl |= USB_DWC2_DEPCTL_SNAK; + } + sys_write32(dxepctl, dxepctl_reg); + + if (ep_idx != 0) { + dwc2_wait_for_bit(dev, doepint_reg, USB_DWC2_DOEPINT_EPDISBLD); + } + + /* Clear Endpoint Disabled interrupt */ + sys_write32(USB_DWC2_DIEPINT_EPDISBLD, doepint_reg); + + dctl |= USB_DWC2_DCTL_CGOUTNAK; + sys_write32(dctl, dctl_reg); + } else { + mem_addr_t diepint_reg; + + diepint_reg = (mem_addr_t)&base->in_ep[ep_idx].diepint; + + dxepctl |= USB_DWC2_DEPCTL_SNAK; + if (stall) { + /* For IN endpoints STALL is set in addition to SNAK */ + dxepctl |= USB_DWC2_DEPCTL_STALL; + } + sys_write32(dxepctl, dxepctl_reg); + + dwc2_wait_for_bit(dev, diepint_reg, USB_DWC2_DIEPINT_INEPNAKEFF); + + dxepctl |= USB_DWC2_DEPCTL_EPENA | USB_DWC2_DEPCTL_EPDIS; + sys_write32(dxepctl, dxepctl_reg); + + dwc2_wait_for_bit(dev, diepint_reg, USB_DWC2_DIEPINT_EPDISBLD); + + /* Clear Endpoint Disabled interrupt */ + sys_write32(USB_DWC2_DIEPINT_EPDISBLD, diepint_reg); + + /* TODO: Read DIEPTSIZn here? Programming Guide suggest it to + * let application know how many bytes of interrupted transfer + * were transferred to the host. + */ + + dwc2_flush_tx_fifo(dev, ep_idx); + } + + udc_ep_set_busy(dev, cfg->addr, false); +} + +/* Deactivated endpoint means that there will be a bus timeout when the host + * tries to access the endpoint. + */ +static int udc_dwc2_ep_deactivate(const struct device *dev, + struct udc_ep_config *const cfg) { uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); mem_addr_t dxepctl_reg; @@ -1212,7 +1325,11 @@ static int udc_dwc2_ep_disable(const struct device *dev, if (dxepctl & USB_DWC2_DEPCTL_USBACTEP) { LOG_DBG("Disable ep 0x%02x DxEPCTL%u %x", cfg->addr, ep_idx, dxepctl); - dxepctl |= USB_DWC2_DEPCTL_EPDIS | USB_DWC2_DEPCTL_SNAK; + + udc_dwc2_ep_disable(dev, cfg, false); + + dxepctl = sys_read32(dxepctl_reg); + dxepctl &= ~USB_DWC2_DEPCTL_USBACTEP; } else { LOG_WRN("ep 0x%02x is not active DxEPCTL%u %x", cfg->addr, ep_idx, dxepctl); @@ -1225,6 +1342,15 @@ static int udc_dwc2_ep_disable(const struct device *dev, sys_write32(dxepctl, dxepctl_reg); dwc2_set_epint(dev, cfg, false); + if (cfg->addr == USB_CONTROL_EP_OUT) { + struct net_buf *buf = udc_buf_get_all(dev, cfg->addr); + + /* Release the buffer allocated in dwc2_ctrl_feed_dout() */ + if (buf) { + net_buf_unref(buf); + } + } + return 0; } @@ -1233,7 +1359,7 @@ static int udc_dwc2_ep_set_halt(const struct device *dev, { uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); - sys_set_bits(dwc2_get_dxepctl_reg(dev, cfg->addr), USB_DWC2_DEPCTL_STALL); + udc_dwc2_ep_disable(dev, cfg, true); LOG_DBG("Set halt ep 0x%02x", cfg->addr); if (ep_idx != 0) { @@ -1246,11 +1372,64 @@ static int udc_dwc2_ep_set_halt(const struct device *dev, static int udc_dwc2_ep_clear_halt(const struct device *dev, struct udc_ep_config *const cfg) { - sys_clear_bits(dwc2_get_dxepctl_reg(dev, cfg->addr), USB_DWC2_DEPCTL_STALL); + mem_addr_t dxepctl_reg = dwc2_get_dxepctl_reg(dev, cfg->addr); + uint32_t dxepctl; + struct dwc2_drv_event evt = { + .ep = cfg->addr, + .type = DWC2_DRV_EVT_XFER, + }; + + dxepctl = sys_read32(dxepctl_reg); + dxepctl &= ~USB_DWC2_DEPCTL_STALL; + dxepctl |= USB_DWC2_DEPCTL_SETD0PID; + sys_write32(dxepctl, dxepctl_reg); LOG_DBG("Clear halt ep 0x%02x", cfg->addr); cfg->stat.halted = false; + /* Resume queued transfers if any */ + if (udc_buf_peek(dev, cfg->addr)) { + k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); + } + + return 0; +} + +static int udc_dwc2_ep_enqueue(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + struct dwc2_drv_event evt = { + .ep = cfg->addr, + .type = DWC2_DRV_EVT_XFER, + }; + + LOG_DBG("%p enqueue %x %p", dev, cfg->addr, buf); + udc_buf_put(cfg, buf); + + if (!cfg->stat.halted) { + k_msgq_put(&drv_msgq, &evt, K_NO_WAIT); + } + + return 0; +} + +static int udc_dwc2_ep_dequeue(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *buf; + + udc_dwc2_ep_disable(dev, cfg, false); + + buf = udc_buf_get_all(dev, cfg->addr); + if (buf) { + udc_submit_ep_event(dev, buf, -ECONNABORTED); + } + + udc_ep_set_busy(dev, cfg->addr, false); + + LOG_DBG("dequeue ep 0x%02x", cfg->addr); + return 0; } @@ -1324,30 +1503,6 @@ static enum udc_bus_speed udc_dwc2_device_speed(const struct device *dev) } } -static int udc_dwc2_enable(const struct device *dev) -{ - struct usb_dwc2_reg *const base = dwc2_get_base(dev); - mem_addr_t dctl_reg = (mem_addr_t)&base->dctl; - - /* Disable soft disconnect */ - sys_clear_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON); - LOG_DBG("Enable device %p", base); - - return 0; -} - -static int udc_dwc2_disable(const struct device *dev) -{ - struct usb_dwc2_reg *const base = dwc2_get_base(dev); - mem_addr_t dctl_reg = (mem_addr_t)&base->dctl; - - /* Enable soft disconnect */ - sys_set_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON); - LOG_DBG("Disable device %p", dev); - - return 0; -} - static int dwc2_core_soft_reset(const struct device *dev) { struct usb_dwc2_reg *const base = dwc2_get_base(dev); @@ -1386,7 +1541,7 @@ static int dwc2_core_soft_reset(const struct device *dev) return 0; } -static int udc_dwc2_init(const struct device *dev) +static int udc_dwc2_init_controller(const struct device *dev) { const struct udc_dwc2_config *const config = dev->config; struct udc_dwc2_data *const priv = udc_get_private(dev); @@ -1399,19 +1554,6 @@ static int udc_dwc2_init(const struct device *dev) uint32_t ghwcfg4; int ret; - if (config->quirks != NULL && config->quirks->clk_enable != NULL) { - LOG_DBG("Enable vendor clock"); - ret = config->quirks->clk_enable(dev); - if (ret) { - return ret; - } - } - - ret = dwc2_init_pinctrl(dev); - if (ret) { - return ret; - } - ret = dwc2_core_soft_reset(dev); if (ret) { return ret; @@ -1441,10 +1583,10 @@ static int udc_dwc2_init(const struct device *dev) } /* Get the number or endpoints and IN endpoints we can use later */ - priv->numdeveps = usb_dwc2_get_ghwcfg2_numdeveps(ghwcfg2); - priv->ineps = usb_dwc2_get_ghwcfg4_ineps(ghwcfg4); - LOG_DBG("Number of endpoints (NUMDEVEPS) %u", priv->numdeveps); - LOG_DBG("Number of IN endpoints (INEPS) %u", priv->ineps); + priv->numdeveps = usb_dwc2_get_ghwcfg2_numdeveps(ghwcfg2) + 1U; + priv->ineps = usb_dwc2_get_ghwcfg4_ineps(ghwcfg4) + 1U; + LOG_DBG("Number of endpoints (NUMDEVEPS + 1) %u", priv->numdeveps); + LOG_DBG("Number of IN endpoints (INEPS + 1) %u", priv->ineps); LOG_DBG("Number of periodic IN endpoints (NUMDEVPERIOEPS) %u", usb_dwc2_get_ghwcfg4_numdevperioeps(ghwcfg4)); @@ -1551,30 +1693,53 @@ static int udc_dwc2_init(const struct device *dev) USB_DWC2_GINTSTS_SOF, (mem_addr_t)&base->gintmsk); + return 0; +} - /* Call vendor-specific function to enable peripheral */ - if (config->quirks != NULL && config->quirks->pwr_on != NULL) { - LOG_DBG("Enable vendor power"); - ret = config->quirks->pwr_on(dev); - if (ret) { - return ret; - } +static int udc_dwc2_enable(const struct device *dev) +{ + const struct udc_dwc2_config *const config = dev->config; + struct usb_dwc2_reg *const base = dwc2_get_base(dev); + int err; + + err = dwc2_quirk_pre_enable(dev); + if (err) { + LOG_ERR("Quirk pre enable failed %d", err); + return err; + } + + err = udc_dwc2_init_controller(dev); + if (err) { + return err; + } + + err = dwc2_quirk_post_enable(dev); + if (err) { + LOG_ERR("Quirk post enable failed %d", err); + return err; } /* Enable global interrupt */ sys_set_bits((mem_addr_t)&base->gahbcfg, USB_DWC2_GAHBCFG_GLBINTRMASK); config->irq_enable_func(dev); + /* Disable soft disconnect */ + sys_clear_bits((mem_addr_t)&base->dctl, USB_DWC2_DCTL_SFTDISCON); + LOG_DBG("Enable device %p", base); + return 0; } -static int udc_dwc2_shutdown(const struct device *dev) +static int udc_dwc2_disable(const struct device *dev) { const struct udc_dwc2_config *const config = dev->config; - struct usb_dwc2_reg *const base = config->base; + struct usb_dwc2_reg *const base = dwc2_get_base(dev); + mem_addr_t dctl_reg = (mem_addr_t)&base->dctl; + int err; - config->irq_disable_func(dev); - sys_clear_bits((mem_addr_t)&base->gahbcfg, USB_DWC2_GAHBCFG_GLBINTRMASK); + /* Enable soft disconnect */ + sys_set_bits(dctl_reg, USB_DWC2_DCTL_SFTDISCON); + LOG_DBG("Disable device %p", dev); if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) { LOG_DBG("Failed to disable control endpoint"); @@ -1586,6 +1751,41 @@ static int udc_dwc2_shutdown(const struct device *dev) return -EIO; } + config->irq_disable_func(dev); + sys_clear_bits((mem_addr_t)&base->gahbcfg, USB_DWC2_GAHBCFG_GLBINTRMASK); + + err = dwc2_quirk_disable(dev); + if (err) { + LOG_ERR("Quirk disable failed %d", err); + return err; + } + + return 0; +} + +static int udc_dwc2_init(const struct device *dev) +{ + int ret; + + ret = dwc2_quirk_init(dev); + if (ret) { + LOG_ERR("Quirk init failed %d", ret); + return ret; + } + + return dwc2_init_pinctrl(dev); +} + +static int udc_dwc2_shutdown(const struct device *dev) +{ + int ret; + + ret = dwc2_quirk_shutdown(dev); + if (ret) { + LOG_ERR("Quirk shutdown failed %d", ret); + return ret; + } + return 0; } @@ -1594,6 +1794,8 @@ static int dwc2_driver_preinit(const struct device *dev) const struct udc_dwc2_config *config = dev->config; struct udc_data *data = dev->data; uint16_t mps = 1023; + uint32_t numdeveps; + uint32_t ineps; int err; k_mutex_init(&data->mutex); @@ -1601,49 +1803,93 @@ static int dwc2_driver_preinit(const struct device *dev) data->caps.rwup = true; data->caps.addr_before_status = true; data->caps.mps0 = UDC_MPS0_64; - if (config->speed_idx == 2) { - data->caps.hs = true; + + (void)dwc2_quirk_caps(dev); + if (data->caps.hs) { mps = 1024; } - for (int i = 0; i < config->num_of_eps; i++) { - config->ep_cfg_out[i].caps.out = 1; + /* + * At this point, we cannot or do not want to access the hardware + * registers to get GHWCFGn values. For now, we will use devicetree to + * get GHWCFGn values and use them to determine the number and type of + * configured endpoints in the hardware. This can be considered a + * workaround, and we may change the upper layer internals to avoid it + * in the future. + */ + ineps = usb_dwc2_get_ghwcfg4_ineps(config->ghwcfg4) + 1U; + numdeveps = usb_dwc2_get_ghwcfg2_numdeveps(config->ghwcfg2) + 1U; + LOG_DBG("Number of endpoints (NUMDEVEPS + 1) %u", numdeveps); + LOG_DBG("Number of IN endpoints (INEPS + 1) %u", ineps); + + for (uint32_t i = 0, n = 0; i < numdeveps; i++) { + uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir(config->ghwcfg1, i); + + if (epdir != USB_DWC2_GHWCFG1_EPDIR_OUT && + epdir != USB_DWC2_GHWCFG1_EPDIR_BDIR) { + continue; + } + if (i == 0) { - config->ep_cfg_out[i].caps.control = 1; - config->ep_cfg_out[i].caps.mps = 64; + config->ep_cfg_out[n].caps.control = 1; + config->ep_cfg_out[n].caps.mps = 64; } else { - config->ep_cfg_out[i].caps.bulk = 1; - config->ep_cfg_out[i].caps.interrupt = 1; - config->ep_cfg_out[i].caps.iso = 1; - config->ep_cfg_out[i].caps.mps = mps; + config->ep_cfg_out[n].caps.bulk = 1; + config->ep_cfg_out[n].caps.interrupt = 1; + config->ep_cfg_out[n].caps.iso = 1; + config->ep_cfg_out[n].caps.mps = mps; } - config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; - err = udc_register_ep(dev, &config->ep_cfg_out[i]); + config->ep_cfg_out[n].caps.out = 1; + config->ep_cfg_out[n].addr = USB_EP_DIR_OUT | i; + + LOG_DBG("Register ep 0x%02x (%u)", i, n); + err = udc_register_ep(dev, &config->ep_cfg_out[n]); if (err != 0) { LOG_ERR("Failed to register endpoint"); return err; } + + n++; + /* Also check the number of desired OUT endpoints in devicetree. */ + if (n >= config->num_out_eps) { + break; + } } - for (int i = 0; i < config->num_of_eps; i++) { - config->ep_cfg_in[i].caps.in = 1; + for (uint32_t i = 0, n = 0; i < numdeveps; i++) { + uint32_t epdir = usb_dwc2_get_ghwcfg1_epdir(config->ghwcfg1, i); + + if (epdir != USB_DWC2_GHWCFG1_EPDIR_IN && + epdir != USB_DWC2_GHWCFG1_EPDIR_BDIR) { + continue; + } + if (i == 0) { - config->ep_cfg_in[i].caps.control = 1; - config->ep_cfg_in[i].caps.mps = 64; + config->ep_cfg_in[n].caps.control = 1; + config->ep_cfg_in[n].caps.mps = 64; } else { - config->ep_cfg_in[i].caps.bulk = 1; - config->ep_cfg_in[i].caps.interrupt = 1; - config->ep_cfg_in[i].caps.iso = 1; - config->ep_cfg_in[i].caps.mps = mps; + config->ep_cfg_in[n].caps.bulk = 1; + config->ep_cfg_in[n].caps.interrupt = 1; + config->ep_cfg_in[n].caps.iso = 1; + config->ep_cfg_in[n].caps.mps = mps; } - config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i; - err = udc_register_ep(dev, &config->ep_cfg_in[i]); + config->ep_cfg_in[n].caps.in = 1; + config->ep_cfg_in[n].addr = USB_EP_DIR_IN | i; + + LOG_DBG("Register ep 0x%02x (%u)", USB_EP_DIR_IN | i, n); + err = udc_register_ep(dev, &config->ep_cfg_in[n]); if (err != 0) { LOG_ERR("Failed to register endpoint"); return err; } + + n++; + /* Also check the number of desired IN endpoints in devicetree. */ + if (n >= MIN(ineps, config->num_in_eps)) { + break; + } } config->make_thread(dev); @@ -1672,8 +1918,8 @@ static const struct udc_api udc_dwc2_api = { .set_address = udc_dwc2_set_address, .test_mode = udc_dwc2_test_mode, .host_wakeup = udc_dwc2_host_wakeup, - .ep_enable = udc_dwc2_ep_enable, - .ep_disable = udc_dwc2_ep_disable, + .ep_enable = udc_dwc2_ep_activate, + .ep_disable = udc_dwc2_ep_deactivate, .ep_set_halt = udc_dwc2_ep_set_halt, .ep_clear_halt = udc_dwc2_ep_clear_halt, .ep_enqueue = udc_dwc2_ep_enqueue, @@ -1751,19 +1997,23 @@ static const struct udc_api udc_dwc2_api = { irq_disable(DT_INST_IRQN(n)); \ } \ \ - static struct udc_ep_config ep_cfg_out[UDC_DWC2_DRV_EP_NUM]; \ - static struct udc_ep_config ep_cfg_in[UDC_DWC2_DRV_EP_NUM]; \ + static struct udc_ep_config ep_cfg_out[DT_INST_PROP(n, num_out_eps)]; \ + static struct udc_ep_config ep_cfg_in[DT_INST_PROP(n, num_in_eps)]; \ \ static const struct udc_dwc2_config udc_dwc2_config_##n = { \ - .num_of_eps = UDC_DWC2_DRV_EP_NUM, \ - .ep_cfg_in = ep_cfg_out, \ - .ep_cfg_out = ep_cfg_in, \ + .num_out_eps = DT_INST_PROP(n, num_out_eps), \ + .num_in_eps = DT_INST_PROP(n, num_in_eps), \ + .ep_cfg_in = ep_cfg_in, \ + .ep_cfg_out = ep_cfg_out, \ .make_thread = udc_dwc2_make_thread_##n, \ .base = (struct usb_dwc2_reg *)UDC_DWC2_DT_INST_REG_ADDR(n), \ .pcfg = UDC_DWC2_PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ .irq_enable_func = udc_dwc2_irq_enable_func_##n, \ .irq_disable_func = udc_dwc2_irq_disable_func_##n, \ .quirks = UDC_DWC2_VENDOR_QUIRK_GET(n), \ + .ghwcfg1 = DT_INST_PROP(n, ghwcfg1), \ + .ghwcfg2 = DT_INST_PROP(n, ghwcfg2), \ + .ghwcfg4 = DT_INST_PROP(n, ghwcfg4), \ }; \ \ static struct udc_dwc2_data udc_priv_##n = { \ diff --git a/drivers/usb/udc/udc_dwc2.h b/drivers/usb/udc/udc_dwc2.h index 11d8178c135b0..07cd71bcb9c85 100644 --- a/drivers/usb/udc/udc_dwc2.h +++ b/drivers/usb/udc/udc_dwc2.h @@ -14,19 +14,30 @@ /* Vendor quirks per driver instance */ struct dwc2_vendor_quirks { - int (*clk_enable)(const struct device *dev); - int (*clk_disable)(const struct device *dev); - int (*pwr_on)(const struct device *dev); - int (*pwr_off)(const struct device *dev); + /* Called at the beginning of udc_dwc2_init() */ + int (*init)(const struct device *dev); + /* Called on udc_dwc2_enable() before the controller is initialized */ + int (*pre_enable)(const struct device *dev); + /* Called on udc_dwc2_enable() after the controller is initialized */ + int (*post_enable)(const struct device *dev); + /* Called at the end of udc_dwc2_disable() */ + int (*disable)(const struct device *dev); + /* Called at the end of udc_dwc2_shutdown() */ + int (*shutdown)(const struct device *dev); + /* Called at the end of IRQ handling */ int (*irq_clear)(const struct device *dev); + /* Called on driver pre-init */ + int (*caps)(const struct device *dev); + /* Called while waiting for bits that require PHY to be clocked */ + int (*is_phy_clk_off)(const struct device *dev); }; /* Driver configuration per instance */ struct udc_dwc2_config { - size_t num_of_eps; + size_t num_in_eps; + size_t num_out_eps; struct udc_ep_config *ep_cfg_in; struct udc_ep_config *ep_cfg_out; - int speed_idx; struct usb_dwc2_reg *const base; /* Pointer to pin control configuration or NULL */ struct pinctrl_dev_config *const pcfg; @@ -35,6 +46,31 @@ struct udc_dwc2_config { void (*make_thread)(const struct device *dev); void (*irq_enable_func)(const struct device *dev); void (*irq_disable_func)(const struct device *dev); + uint32_t ghwcfg1; + uint32_t ghwcfg2; + uint32_t ghwcfg4; }; +#define DWC2_QUIRK_FUNC_DEFINE(fname) \ +static inline int dwc2_quirk_##fname(const struct device *dev) \ +{ \ + const struct udc_dwc2_config *const config = dev->config; \ + struct dwc2_vendor_quirks *quirks = config->quirks; \ + \ + if (quirks != NULL && config->quirks->fname != NULL) { \ + return quirks->fname(dev); \ + } \ + \ + return 0; \ +} + +DWC2_QUIRK_FUNC_DEFINE(init) +DWC2_QUIRK_FUNC_DEFINE(pre_enable) +DWC2_QUIRK_FUNC_DEFINE(post_enable) +DWC2_QUIRK_FUNC_DEFINE(disable) +DWC2_QUIRK_FUNC_DEFINE(shutdown) +DWC2_QUIRK_FUNC_DEFINE(irq_clear) +DWC2_QUIRK_FUNC_DEFINE(caps) +DWC2_QUIRK_FUNC_DEFINE(is_phy_clk_off) + #endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_H */ diff --git a/drivers/usb/udc/udc_dwc2_vendor_quirks.h b/drivers/usb/udc/udc_dwc2_vendor_quirks.h index 104cb5cb8474f..57ff4c4de0441 100644 --- a/drivers/usb/udc/udc_dwc2_vendor_quirks.h +++ b/drivers/usb/udc/udc_dwc2_vendor_quirks.h @@ -11,13 +11,14 @@ #include #include +#include + +#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg) + #include #include - #include -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg) - struct usb_dw_stm32_clk { const struct device *const dev; const struct stm32_pclken *const pclken; @@ -26,7 +27,7 @@ struct usb_dw_stm32_clk { #define DT_DRV_COMPAT snps_dwc2 -static inline int clk_enable_stm32f4_fsotg(const struct usb_dw_stm32_clk *const clk) +static inline int stm32f4_fsotg_enable_clk(const struct usb_dw_stm32_clk *const clk) { int ret; @@ -59,7 +60,7 @@ static inline int clk_enable_stm32f4_fsotg(const struct usb_dw_stm32_clk *const return clock_control_on(clk->dev, (void *)&clk->pclken[0]); } -static inline int pwr_on_stm32f4_fsotg(const struct device *dev) +static inline int stm32f4_fsotg_enable_phy(const struct device *dev) { const struct udc_dwc2_config *const config = dev->config; mem_addr_t ggpio_reg = (mem_addr_t)&config->base->ggpio; @@ -69,6 +70,16 @@ static inline int pwr_on_stm32f4_fsotg(const struct device *dev) return 0; } +static inline int stm32f4_fsotg_disable_phy(const struct device *dev) +{ + const struct udc_dwc2_config *const config = dev->config; + mem_addr_t ggpio_reg = (mem_addr_t)&config->base->ggpio; + + sys_clear_bits(ggpio_reg, USB_DWC2_GGPIO_STM32_PWRDWN | USB_DWC2_GGPIO_STM32_VBDEN); + + return 0; +} + #define QUIRK_STM32F4_FSOTG_DEFINE(n) \ static const struct stm32_pclken pclken_##n[] = STM32_DT_INST_CLOCKS(n);\ \ @@ -78,14 +89,15 @@ static inline int pwr_on_stm32f4_fsotg(const struct device *dev) .pclken_len = DT_INST_NUM_CLOCKS(n), \ }; \ \ - static int clk_enable_stm32f4_fsotg_##n(const struct device *dev) \ + static int stm32f4_fsotg_enable_clk_##n(const struct device *dev) \ { \ - return clk_enable_stm32f4_fsotg(&stm32f4_clk_##n); \ + return stm32f4_fsotg_enable_clk(&stm32f4_clk_##n); \ } \ \ struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ - .clk_enable = clk_enable_stm32f4_fsotg_##n, \ - .pwr_on = pwr_on_stm32f4_fsotg, \ + .pre_enable = stm32f4_fsotg_enable_clk_##n, \ + .post_enable = stm32f4_fsotg_enable_phy, \ + .disable = stm32f4_fsotg_disable_phy, \ .irq_clear = NULL, \ }; @@ -96,6 +108,164 @@ DT_INST_FOREACH_STATUS_OKAY(QUIRK_STM32F4_FSOTG_DEFINE) #endif /*DT_HAS_COMPAT_STATUS_OKAY(st_stm32f4_fsotg) */ +#if DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) + +#define DT_DRV_COMPAT snps_dwc2 + +#include +#include + +#define USBHS_DT_WRAPPER_REG_ADDR(n) UINT_TO_POINTER(DT_INST_REG_ADDR_BY_NAME(n, wrapper)) + +/* + * On USBHS, we cannot access the DWC2 register until VBUS is detected and + * valid. If the user tries to force usbd_enable() and the corresponding + * udc_enable() without a "VBUS ready" notification, the event wait will block + * until a valid VBUS signal is detected. + */ +static K_EVENT_DEFINE(usbhs_events); +#define USBHS_VBUS_READY BIT(0) + +static void usbhs_vbus_handler(nrfs_usb_evt_t const *p_evt, void *const context) +{ + const struct device *dev = context; + + switch (p_evt->type) { + case NRFS_USB_EVT_VBUS_STATUS_CHANGE: + LOG_DBG("USBHS new status, pll_ok = %d vreg_ok = %d vbus_detected = %d", + p_evt->usbhspll_ok, p_evt->vregusb_ok, p_evt->vbus_detected); + + if (p_evt->usbhspll_ok && p_evt->vregusb_ok && p_evt->vbus_detected) { + k_event_post(&usbhs_events, USBHS_VBUS_READY); + udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); + } else { + k_event_set_masked(&usbhs_events, 0, USBHS_VBUS_READY); + udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0); + } + + break; + case NRFS_USB_EVT_REJECT: + LOG_ERR("Request rejected"); + break; + default: + LOG_ERR("Unknown event type 0x%x", p_evt->type); + break; + } +} + +static inline int usbhs_enable_nrfs_service(const struct device *dev) +{ + nrfs_err_t nrfs_err; + int err; + + err = nrfs_backend_wait_for_connection(K_MSEC(1000)); + if (err) { + LOG_INF("NRFS backend connection timeout"); + return err; + } + + nrfs_err = nrfs_usb_init(usbhs_vbus_handler); + if (nrfs_err != NRFS_SUCCESS) { + LOG_ERR("Failed to init NRFS VBUS handler: %d", nrfs_err); + return -EIO; + } + + nrfs_err = nrfs_usb_enable_request((void *)dev); + if (nrfs_err != NRFS_SUCCESS) { + LOG_ERR("Failed to enable NRFS VBUS service: %d", nrfs_err); + return -EIO; + } + + return 0; +} + +static inline int usbhs_enable_core(const struct device *dev) +{ + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + + if (!k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_NO_WAIT)) { + LOG_WRN("VBUS is not ready, block udc_enable()"); + k_event_wait(&usbhs_events, USBHS_VBUS_READY, false, K_FOREVER); + } + + wrapper->ENABLE = USBHS_ENABLE_PHY_Msk | USBHS_ENABLE_CORE_Msk; + wrapper->TASKS_START = 1UL; + + /* Enable interrupts */ + wrapper->INTENSET = 1UL; + + return 0; +} + +static inline int usbhs_disable_core(const struct device *dev) +{ + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + + /* Disable interrupts */ + wrapper->INTENCLR = 1UL; + + wrapper->ENABLE = 0UL; + wrapper->TASKS_START = 1UL; + + return 0; +} + +static inline int usbhs_disable_nrfs_service(const struct device *dev) +{ + nrfs_err_t nrfs_err; + + nrfs_err = nrfs_usb_disable_request((void *)dev); + if (nrfs_err != NRFS_SUCCESS) { + LOG_ERR("Failed to disable NRFS VBUS service: %d", nrfs_err); + return -EIO; + } + + nrfs_usb_uninit(); + + return 0; +} + +static inline int usbhs_irq_clear(const struct device *dev) +{ + NRF_USBHS_Type *wrapper = USBHS_DT_WRAPPER_REG_ADDR(0); + + wrapper->EVENTS_CORE = 0UL; + + return 0; +} + +static inline int usbhs_init_caps(const struct device *dev) +{ + struct udc_data *data = dev->data; + + data->caps.can_detect_vbus = true; + data->caps.hs = true; + + return 0; +} + +static inline int usbhs_is_phy_clk_off(const struct device *dev) +{ + return !k_event_test(&usbhs_events, USBHS_VBUS_READY); +} + +#define QUIRK_NRF_USBHS_DEFINE(n) \ + struct dwc2_vendor_quirks dwc2_vendor_quirks_##n = { \ + .init = usbhs_enable_nrfs_service, \ + .pre_enable = usbhs_enable_core, \ + .disable = usbhs_disable_core, \ + .shutdown = usbhs_disable_nrfs_service, \ + .irq_clear = usbhs_irq_clear, \ + .caps = usbhs_init_caps, \ + .is_phy_clk_off = usbhs_is_phy_clk_off, \ + }; + +DT_INST_FOREACH_STATUS_OKAY(QUIRK_NRF_USBHS_DEFINE) + +#undef DT_DRV_COMPAT + +#endif /*DT_HAS_COMPAT_STATUS_OKAY(nordic_nrf_usbhs) */ + /* Add next vendor quirks definition above this line */ #endif /* ZEPHYR_DRIVERS_USB_UDC_DWC2_VENDOR_QUIRKS_H */ diff --git a/drivers/usb/udc/udc_it82xx2.c b/drivers/usb/udc/udc_it82xx2.c new file mode 100644 index 0000000000000..70209f11e1770 --- /dev/null +++ b/drivers/usb/udc/udc_it82xx2.c @@ -0,0 +1,1477 @@ +/* + * Copyright (c) 2023 ITE Technology Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "udc_common.h" + +#include +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(udc_it82xx2, CONFIG_UDC_DRIVER_LOG_LEVEL); + +#define DT_DRV_COMPAT ite_it82xx2_usb + +#define IT8XXX2_IS_EXTEND_ENDPOINT(n) (USB_EP_GET_IDX(n) >= 4) + +/* Shared FIFO number including FIFO_1/2/3 */ +#define SHARED_FIFO_NUM 3 + +/* The related definitions of the register dc_line_status: 0x51 */ +#define RX_LINE_STATE_MASK (RX_LINE_FULL_SPD | RX_LINE_LOW_SPD) +#define RX_LINE_LOW_SPD 0x02 +#define RX_LINE_FULL_SPD 0x01 +#define RX_LINE_RESET 0x00 + +#define DC_ADDR_NULL 0x00 +#define DC_ADDR_MASK 0x7F + +/* EPN Extend Control 2 Register Mask Definition */ +#define COMPLETED_TRANS 0xF0 + +/* The related definitions of the register EP STATUS: + * 0x41/0x45/0x49/0x4D + */ +#define EP_STATUS_ERROR 0x0F + +/* ENDPOINT[3..0]_CONTROL_REG */ +#define ENDPOINT_EN BIT(0) +#define ENDPOINT_RDY BIT(1) + +/* The bit definitions of the register EP RX/TX FIFO Control: + * EP_RX_FIFO_CONTROL: 0X64/0x84/0xA4/0xC4 + * EP_TX_FIFO_CONTROL: 0X74/0x94/0xB4/0xD4 + */ +#define FIFO_FORCE_EMPTY BIT(0) + +/* The bit definitions of the register Host/Device Control: 0XE0 */ +#define RESET_CORE BIT(1) + +/* ENDPOINT[3..0]_STATUS_REG */ +#define DC_STALL_SENT BIT(5) + +/* DC_INTERRUPT_STATUS_REG */ +#define DC_TRANS_DONE BIT(0) +#define DC_RESET_EVENT BIT(2) +#define DC_SOF_RECEIVED BIT(3) +#define DC_NAK_SENT_INT BIT(4) + +/* DC_CONTROL_REG */ +#define DC_GLOBAL_ENABLE BIT(0) +#define DC_TX_LINE_STATE_DM BIT(1) +#define DC_DIRECT_CONTROL BIT(3) +#define DC_FULL_SPEED_LINE_POLARITY BIT(4) +#define DC_FULL_SPEED_LINE_RATE BIT(5) +#define DC_CONNECT_TO_HOST BIT(6) /* internal pull-up */ + +/* Bit [1:0] represents the TRANSACTION_TYPE as follows: */ +enum it82xx2_transaction_types { + DC_SETUP_TRANS = 0, + DC_IN_TRANS, + DC_OUTDATA_TRANS, + DC_ALL_TRANS +}; + +enum it82xx2_event_type { + IT82xx2_EVT_XFER, + IT82xx2_EVT_SETUP_TOKEN, + IT82xx2_EVT_OUT_TOKEN, + IT82xx2_EVT_IN_TOKEN, +}; + +struct it82xx2_ep_event { + sys_snode_t node; + const struct device *dev; + uint8_t ep; + enum it82xx2_event_type event; +}; + +K_MSGQ_DEFINE(evt_msgq, sizeof(struct it82xx2_ep_event), + CONFIG_UDC_IT82xx2_EVENT_COUNT, sizeof(uint32_t)); + +struct usb_it8xxx2_wuc { + /* WUC control device structure */ + const struct device *dev; + /* WUC pin mask */ + uint8_t mask; +}; + +struct it82xx2_data { + const struct device *dev; + + struct k_fifo fifo; + struct k_work_delayable suspended_work; + + struct k_thread thread_data; + struct k_sem suspended_sem; + + /* FIFO_1/2/3 ready status */ + bool fifo_ready[SHARED_FIFO_NUM]; + + /* FIFO_1/2/3 semaphore */ + struct k_sem fifo_sem[SHARED_FIFO_NUM]; + + /* Record if the previous transaction of endpoint0 is STALL */ + bool stall_is_sent; +}; + +struct usb_it82xx2_config { + struct usb_it82xx2_regs *const base; + const struct pinctrl_dev_config *pcfg; + const struct usb_it8xxx2_wuc wuc; + uint8_t usb_irq; + uint8_t wu_irq; + struct udc_ep_config *ep_cfg_in; + struct udc_ep_config *ep_cfg_out; + void (*make_thread)(const struct device *dev); +}; + +enum it82xx2_ep_ctrl { + EP_IN_DIRECTION_SET, + EP_IOS_ENABLE, + EP_ENABLE, + EP_DATA_SEQ_1, + EP_DATA_SEQ_TOGGLE, + EP_READY_ENABLE, +}; + +static inline void ep_set_halt(const struct device *dev, const uint8_t ep_idx, const bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + union epn0n1_extend_ctrl_reg *ext_ctrl; + uint8_t idx = (ep_idx - 4) / 2; + + ext_ctrl = usb_regs->fifo_regs[EP_EXT_REGS_9X].ext_4_15.epn0n1_ext_ctrl; + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + if (ep_idx % 2) { + ext_ctrl[idx].fields.epn1_send_stall_bit = enable; + } else { + ext_ctrl[idx].fields.epn0_send_stall_bit = enable; + } + } else { + ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit = enable; + } +} + +static volatile void *it82xx2_get_ext_ctrl(const struct device *dev, const uint8_t ep_idx, + const enum it82xx2_ep_ctrl ctrl) +{ + uint8_t idx; + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + union epn0n1_extend_ctrl_reg *epn0n1_ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_9X].ext_4_15.epn0n1_ext_ctrl; + struct epn_ext_ctrl_regs *ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; + + if (ctrl == EP_IN_DIRECTION_SET || ctrl == EP_ENABLE) { + idx = ((ep_idx - 4) % 3) + 1; + return &ext_ctrl[idx].epn_ext_ctrl1; + } + + idx = (ep_idx - 4) / 2; + return &epn0n1_ext_ctrl[idx]; +} + +static int it82xx2_usb_extend_ep_ctrl(const struct device *dev, const uint8_t ep, + const enum it82xx2_ep_ctrl ctrl, const bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct epn_ext_ctrl_regs *ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; + volatile union epn_extend_ctrl1_reg *epn_ext_ctrl1 = NULL; + volatile union epn0n1_extend_ctrl_reg *epn0n1_ext_ctrl = NULL; + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (ctrl == EP_IN_DIRECTION_SET || ctrl == EP_ENABLE) { + epn_ext_ctrl1 = it82xx2_get_ext_ctrl(dev, ep_idx, ctrl); + } else { + epn0n1_ext_ctrl = it82xx2_get_ext_ctrl(dev, ep_idx, ctrl); + } + + switch (ctrl) { + case EP_IOS_ENABLE: + if (ep_idx % 2) { + epn0n1_ext_ctrl->fields.epn1_iso_enable_bit = enable; + } else { + epn0n1_ext_ctrl->fields.epn0_iso_enable_bit = enable; + } + break; + case EP_DATA_SEQ_1: + if (ep_idx % 2) { + epn0n1_ext_ctrl->fields.epn1_outdata_sequence_bit = enable; + } else { + epn0n1_ext_ctrl->fields.epn0_outdata_sequence_bit = enable; + } + break; + case EP_DATA_SEQ_TOGGLE: + if (!enable) { + break; + } + if (ep_idx % 2) { + if (epn0n1_ext_ctrl->fields.epn1_outdata_sequence_bit) { + epn0n1_ext_ctrl->fields.epn1_outdata_sequence_bit = 0; + } else { + epn0n1_ext_ctrl->fields.epn1_outdata_sequence_bit = 1; + } + } else { + if (epn0n1_ext_ctrl->fields.epn0_outdata_sequence_bit) { + epn0n1_ext_ctrl->fields.epn0_outdata_sequence_bit = 0; + } else { + epn0n1_ext_ctrl->fields.epn0_outdata_sequence_bit = 1; + } + } + break; + case EP_IN_DIRECTION_SET: + if (((ep_idx - 4) / 3 == 0)) { + epn_ext_ctrl1->fields.epn0_direction_bit = enable; + } else if (((ep_idx - 4) / 3 == 1)) { + epn_ext_ctrl1->fields.epn3_direction_bit = enable; + } else if (((ep_idx - 4) / 3 == 2)) { + epn_ext_ctrl1->fields.epn6_direction_bit = enable; + } else if (((ep_idx - 4) / 3 == 3)) { + epn_ext_ctrl1->fields.epn9_direction_bit = enable; + } else { + LOG_ERR("Invalid endpoint 0x%x for control type 0x%x", ep, ctrl); + return -EINVAL; + } + break; + case EP_ENABLE: + if (((ep_idx - 4) / 3 == 0)) { + epn_ext_ctrl1->fields.epn0_enable_bit = enable; + } else if (((ep_idx - 4) / 3 == 1)) { + epn_ext_ctrl1->fields.epn3_enable_bit = enable; + } else if (((ep_idx - 4) / 3 == 2)) { + epn_ext_ctrl1->fields.epn6_enable_bit = enable; + } else if (((ep_idx - 4) / 3 == 3)) { + epn_ext_ctrl1->fields.epn9_enable_bit = enable; + } else { + LOG_ERR("Invalid endpoint 0x%x for control type 0x%x", ep, ctrl); + return -EINVAL; + } + break; + case EP_READY_ENABLE: + int idx = ((ep_idx - 4) % 3) + 1; + + (enable) ? (ext_ctrl[idx].epn_ext_ctrl2 |= BIT((ep_idx - 4) / 3)) + : (ext_ctrl[idx].epn_ext_ctrl2 &= ~BIT((ep_idx - 4) / 3)); + break; + default: + LOG_ERR("Unknown control type 0x%x", ctrl); + return -EINVAL; + } + + return 0; +} + +static int it82xx2_usb_ep_ctrl(const struct device *dev, uint8_t ep, enum it82xx2_ep_ctrl ctrl, + bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + return -EINVAL; + } + + switch (ctrl) { + case EP_IN_DIRECTION_SET: + ep_regs[ep_idx].ep_ctrl.fields.direction_bit = enable; + break; + case EP_IOS_ENABLE: + ep_regs[ep_idx].ep_ctrl.fields.iso_enable_bit = enable; + break; + case EP_ENABLE: + ep_regs[ep_idx].ep_ctrl.fields.enable_bit = enable; + break; + case EP_READY_ENABLE: + ep_regs[ep_idx].ep_ctrl.fields.ready_bit = enable; + break; + case EP_DATA_SEQ_1: + ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = enable; + break; + case EP_DATA_SEQ_TOGGLE: + if (!enable) { + break; + } + if (ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit) { + ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = 0; + } else { + ep_regs[ep_idx].ep_ctrl.fields.outdata_sequence_bit = 1; + } + break; + default: + LOG_ERR("Unknown control type 0x%x", ctrl); + return -EINVAL; + } + return 0; +} + +static int it82xx2_usb_set_ep_ctrl(const struct device *dev, uint8_t ep, enum it82xx2_ep_ctrl ctrl, + bool enable) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + int ret = 0; + + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + ret = it82xx2_usb_extend_ep_ctrl(dev, ep, ctrl, enable); + } else { + ret = it82xx2_usb_ep_ctrl(dev, ep, ctrl, enable); + } + return ret; +} + +/* Standby(deep doze) mode enable/disable */ +static void it82xx2_enable_standby_state(bool enable) +{ + if (enable) { + pm_policy_state_lock_put(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } else { + pm_policy_state_lock_get(PM_STATE_STANDBY, PM_ALL_SUBSTATES); + } +} + +/* Wake-up interrupt (USB D+) Enable/Disable */ +static void it82xx2_enable_wu_irq(const struct device *dev, bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + + /* Clear pending interrupt */ + it8xxx2_wuc_clear_status(config->wuc.dev, config->wuc.mask); + + if (enable) { + irq_enable(config->wu_irq); + } else { + irq_disable(config->wu_irq); + } +} + +static void it82xx2_wu_isr(const void *arg) +{ + const struct device *dev = arg; + + it82xx2_enable_wu_irq(dev, false); + it82xx2_enable_standby_state(false); + LOG_DBG("USB D+ (WU) Triggered"); +} + +static void it8xxx2_usb_dc_wuc_init(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + + /* Initializing the WUI */ + it8xxx2_wuc_set_polarity(config->wuc.dev, config->wuc.mask, WUC_TYPE_EDGE_FALLING); + it8xxx2_wuc_clear_status(config->wuc.dev, config->wuc.mask); + + /* Enabling the WUI */ + it8xxx2_wuc_enable(config->wuc.dev, config->wuc.mask); + + /* Connect WU (USB D+) interrupt but make it disabled initially */ + irq_connect_dynamic(config->wu_irq, 0, it82xx2_wu_isr, dev, 0); +} + +/* The ep_fifo_res[ep_idx % SHARED_FIFO_NUM] where the SHARED_FIFO_NUM is 3 represents the + * EP mapping because when (ep_idx % SHARED_FIFO_NUM) is 3, it actually means the EP0. + */ +static const uint8_t ep_fifo_res[SHARED_FIFO_NUM] = {3, 1, 2}; + +static int it82xx2_usb_fifo_ctrl(const struct device *dev, uint8_t ep) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + volatile uint8_t *ep_fifo_ctrl = usb_regs->fifo_regs[EP_EXT_REGS_BX].fifo_ctrl.ep_fifo_ctrl; + uint8_t fifon_ctrl = (ep_fifo_res[ep_idx % SHARED_FIFO_NUM] - 1) * 2; + int ret = 0; + + if (ep_idx == 0) { + LOG_ERR("Invalid endpoint 0x%x", ep); + return -EINVAL; + } + + if (USB_EP_DIR_IS_IN(ep)) { + if (ep_idx < 8) { + ep_fifo_ctrl[fifon_ctrl] = BIT(ep_idx); + ep_fifo_ctrl[fifon_ctrl + 1] = 0x0; + } else { + ep_fifo_ctrl[fifon_ctrl] = 0x0; + ep_fifo_ctrl[fifon_ctrl + 1] = BIT(ep_idx - 8); + } + } else if (USB_EP_DIR_IS_OUT(ep)) { + if (ep_idx < 8) { + ep_fifo_ctrl[fifon_ctrl] |= BIT(ep_idx); + } else { + ep_fifo_ctrl[fifon_ctrl + 1] |= BIT(ep_idx - 8); + } + } else { + LOG_ERR("Failed to set fifo control register for ep 0x%x", ep); + ret = -EINVAL; + } + + return ret; +} + +static void it82xx2_event_submit(const struct device *dev, const uint8_t ep, + const enum it82xx2_event_type event) +{ + struct it82xx2_ep_event evt; + + evt.dev = dev; + evt.ep = ep; + evt.event = event; + k_msgq_put(&evt_msgq, &evt, K_NO_WAIT); +} + +static int it82xx2_ep_enqueue(const struct device *dev, struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + udc_buf_put(cfg, buf); + + it82xx2_event_submit(dev, cfg->addr, IT82xx2_EVT_XFER); + return 0; +} + +static int it82xx2_ep_dequeue(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + struct net_buf *buf; + unsigned int lock_key; + uint8_t fifo_idx; + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + lock_key = irq_lock(); + if (USB_EP_DIR_IS_IN(cfg->addr)) { + ff_regs[fifo_idx].ep_tx_fifo_ctrl = FIFO_FORCE_EMPTY; + } else { + ff_regs[fifo_idx].ep_rx_fifo_ctrl = FIFO_FORCE_EMPTY; + } + irq_unlock(lock_key); + + buf = udc_buf_get_all(dev, cfg->addr); + if (buf) { + udc_submit_ep_event(dev, buf, -ECONNABORTED); + } + + udc_ep_set_busy(dev, cfg->addr, false); + + return 0; +} + +static inline void ctrl_ep_stall_workaround(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct gctrl_it8xxx2_regs *const gctrl_regs = GCTRL_IT8XXX2_REGS_BASE; + struct it82xx2_data *priv = udc_get_private(dev); + unsigned int lock_key; + uint32_t idx = 0; + + priv->stall_is_sent = true; + lock_key = irq_lock(); + ep_set_halt(dev, 0, true); + it82xx2_usb_set_ep_ctrl(dev, 0, EP_READY_ENABLE, true); + + /* It82xx2 does not support clearing the STALL bit by hardware; instead, the STALL bit need + * to be cleared by firmware. The SETUP token will be STALLed, which isn't compliant to + * USB specification, if firmware clears the STALL bit too late. Due to this hardware + * limitations, device controller polls to check if the stall bit has been transmitted for + * 3ms and then disables it after responsing STALLed. + */ + while (idx < 198 && !(ep_regs[0].ep_status & DC_STALL_SENT)) { + /* wait 15.15us */ + gctrl_regs->GCTRL_WNCKR = 0; + idx++; + } + + if (idx < 198) { + ep_set_halt(dev, 0, false); + } + irq_unlock(lock_key); +} + +static int it82xx2_ep_set_halt(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + + if (ep_idx == 0) { + ctrl_ep_stall_workaround(dev); + } else { + ep_set_halt(dev, ep_idx, true); + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_READY_ENABLE, true); + } + + LOG_DBG("Endpoint 0x%x is halted", cfg->addr); + + return 0; +} + +static int it82xx2_ep_clear_halt(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + + ep_set_halt(dev, ep_idx, false); + + LOG_DBG("Endpoint 0x%x clear halted", cfg->addr); + + return 0; +} + +static int it82xx2_ep_enable(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + + /* Configure endpoint */ + if (ep_idx != 0) { + if (USB_EP_DIR_IS_IN(cfg->addr)) { + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_IN_DIRECTION_SET, true); + } else { + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_IN_DIRECTION_SET, false); + it82xx2_usb_fifo_ctrl(dev, cfg->addr); + } + + switch (cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) { + case USB_EP_TYPE_BULK: + __fallthrough; + case USB_EP_TYPE_INTERRUPT: + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_IOS_ENABLE, false); + break; + case USB_EP_TYPE_ISO: + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_IOS_ENABLE, true); + break; + case USB_EP_TYPE_CONTROL: + __fallthrough; + default: + return -ENOTSUP; + } + } + + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + uint8_t fifo_idx; + + fifo_idx = ep_fifo_res[ep_idx % SHARED_FIFO_NUM]; + it82xx2_usb_set_ep_ctrl(dev, fifo_idx, EP_ENABLE, true); + } + + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_ENABLE, true); + + LOG_DBG("Endpoint 0x%02x is enabled", cfg->addr); + + return 0; +} + +static int it82xx2_ep_disable(const struct device *dev, struct udc_ep_config *const cfg) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(cfg->addr); + + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_ENABLE, false); + + LOG_DBG("Endpoint 0x%02x is disabled", cfg->addr); + + return 0; +} + +static int it82xx2_host_wakeup(const struct device *dev) +{ + struct it82xx2_data *priv = udc_get_private(dev); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + int ret; + + if (udc_is_suspended(dev)) { + usb_regs->dc_control = DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | + DC_FULL_SPEED_LINE_RATE | DC_DIRECT_CONTROL | + DC_TX_LINE_STATE_DM | DC_CONNECT_TO_HOST; + + /* The remote wakeup device must hold the resume signal for */ + /* at least 1 ms but for no more than 15 ms */ + k_msleep(2); + + usb_regs->dc_control = DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | + DC_FULL_SPEED_LINE_RATE | DC_CONNECT_TO_HOST; + + ret = k_sem_take(&priv->suspended_sem, K_MSEC(500)); + if (ret < 0) { + LOG_ERR("Failed to wake up host"); + } + } + + return 0; +} + +static int it82xx2_set_address(const struct device *dev, const uint8_t addr) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + usb_regs->dc_address = addr & DC_ADDR_MASK; + + LOG_DBG("Set usb address 0x%02x", addr); + + return 0; +} + +static int it82xx2_usb_dc_ip_init(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + /* reset usb controller */ + usb_regs->host_device_control = RESET_CORE; + k_msleep(1); + usb_regs->port0_misc_control &= ~(PULL_DOWN_EN); + usb_regs->port1_misc_control &= ~(PULL_DOWN_EN); + + /* clear reset bit */ + usb_regs->host_device_control = 0; + + usb_regs->dc_interrupt_status = DC_TRANS_DONE | DC_RESET_EVENT | DC_SOF_RECEIVED; + + usb_regs->dc_interrupt_mask = 0x00; + usb_regs->dc_interrupt_mask = DC_TRANS_DONE | DC_RESET_EVENT | DC_SOF_RECEIVED; + + usb_regs->dc_address = DC_ADDR_NULL; + + return 0; +} + +static void it82xx2_enable_sof_int(const struct device *dev, bool enable) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; + if (enable) { + usb_regs->dc_interrupt_mask |= DC_SOF_RECEIVED; + } else { + usb_regs->dc_interrupt_mask &= ~DC_SOF_RECEIVED; + } +} + +void it82xx2_dc_reset(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + struct it82xx2_data *priv = udc_get_private(dev); + + for (uint8_t ep_idx = 0; ep_idx < 4; ep_idx++) { + ff_regs[ep_idx].ep_rx_fifo_ctrl = FIFO_FORCE_EMPTY; + ff_regs[ep_idx].ep_tx_fifo_ctrl = FIFO_FORCE_EMPTY; + } + + ep_regs[0].ep_ctrl.value = ENDPOINT_EN; + usb_regs->dc_address = DC_ADDR_NULL; + usb_regs->dc_interrupt_status = DC_NAK_SENT_INT | DC_SOF_RECEIVED; + + priv->fifo_ready[0] = false; + priv->fifo_ready[1] = false; + priv->fifo_ready[2] = false; + k_sem_give(&priv->fifo_sem[0]); + k_sem_give(&priv->fifo_sem[1]); + k_sem_give(&priv->fifo_sem[2]); +} + +static int it82xx2_xfer_in_data(const struct device *dev, uint8_t ep, struct net_buf *buf) +{ + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + struct it82xx2_data *priv = udc_get_private(dev); + struct udc_ep_config *ep_cfg = udc_get_ep_cfg(dev, ep); + uint8_t fifo_idx; + size_t len; + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + if (ep_idx == 0) { + ff_regs[ep_idx].ep_tx_fifo_ctrl = FIFO_FORCE_EMPTY; + } else { + k_sem_take(&priv->fifo_sem[fifo_idx - 1], K_FOREVER); + it82xx2_usb_fifo_ctrl(dev, ep); + } + + len = MIN(buf->len, ep_cfg->mps); + + for (size_t i = 0; i < len; i++) { + ff_regs[fifo_idx].ep_tx_fifo_data = buf->data[i]; + } + + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + it82xx2_usb_extend_ep_ctrl(dev, ep_idx, EP_READY_ENABLE, true); + } + it82xx2_usb_set_ep_ctrl(dev, fifo_idx, EP_READY_ENABLE, true); + + if (ep_idx != 0) { + priv->fifo_ready[fifo_idx - 1] = true; + } + + LOG_DBG("Writed %d packets to endpoint%d tx fifo", buf->len, ep_idx); + + return 0; +} + +static int it82xx2_xfer_out_data(const struct device *dev, uint8_t ep, struct net_buf *buf) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint8_t fifo_idx; + size_t len; + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + if (ep_regs[fifo_idx].ep_status & EP_STATUS_ERROR) { + LOG_WRN("endpoint%d error status 0x%02x", ep_idx, ep_regs[fifo_idx].ep_status); + return -EINVAL; + } + + len = (uint16_t)ff_regs[fifo_idx].ep_rx_fifo_dcnt_lsb + + (((uint16_t)ff_regs[fifo_idx].ep_rx_fifo_dcnt_msb) << 8); + + len = MIN(net_buf_tailroom(buf), len); + uint8_t *data_ptr = net_buf_tail(buf); + + for (size_t idx = 0; idx < len; idx++) { + data_ptr[idx] = ff_regs[fifo_idx].ep_rx_fifo_data; + } + + net_buf_add(buf, len); + + return 0; +} + +static int work_handler_xfer_continue(const struct device *dev, uint8_t ep, struct net_buf *buf) +{ + int ret = 0; + + if (USB_EP_DIR_IS_OUT(ep)) { + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + struct it82xx2_data *priv = udc_get_private(dev); + uint8_t fifo_idx; + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + it82xx2_usb_set_ep_ctrl(dev, ep_idx, EP_READY_ENABLE, true); + if (IT8XXX2_IS_EXTEND_ENDPOINT(ep_idx)) { + it82xx2_usb_set_ep_ctrl(dev, fifo_idx, EP_READY_ENABLE, true); + } + if (ep_idx != 0) { + priv->fifo_ready[fifo_idx - 1] = true; + } + } else { + ret = it82xx2_xfer_in_data(dev, ep, buf); + } + + return ret; +} + +static int work_handler_xfer_next(const struct device *dev, uint8_t ep) +{ + struct net_buf *buf; + + buf = udc_buf_peek(dev, ep); + if (buf == NULL) { + return -ENODATA; + } + + return work_handler_xfer_continue(dev, ep, buf); +} + +/* + * Allocate buffer and initiate a new control OUT transfer, + * use successive buffer descriptor when next is true. + */ +static int it82xx2_ctrl_feed_dout(const struct device *dev, const size_t length) +{ + struct udc_ep_config *cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + struct net_buf *buf; + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, length); + if (buf == NULL) { + return -ENOMEM; + } + udc_buf_put(cfg, buf); + + it82xx2_usb_set_ep_ctrl(dev, 0, EP_READY_ENABLE, true); + + return 0; +} + +static bool it82xx2_fake_token(const struct device *dev, uint8_t ep, uint8_t token_type) +{ + struct it82xx2_data *priv = udc_get_private(dev); + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + uint8_t fifo_idx; + bool is_fake = true; + + if (ep_idx == 0) { + switch (token_type) { + case DC_IN_TRANS: + if (priv->stall_is_sent) { + return true; + } + is_fake = !udc_ctrl_stage_is_data_in(dev) && + !udc_ctrl_stage_is_status_in(dev) && + !udc_ctrl_stage_is_no_data(dev); + break; + case DC_OUTDATA_TRANS: + is_fake = !udc_ctrl_stage_is_data_out(dev) && + !udc_ctrl_stage_is_status_out(dev); + break; + default: + LOG_ERR("Invalid token type"); + break; + } + } else { + fifo_idx = ep_fifo_res[ep_idx % SHARED_FIFO_NUM]; + + if (!priv->fifo_ready[fifo_idx - 1]) { + is_fake = true; + } else { + priv->fifo_ready[fifo_idx - 1] = false; + is_fake = false; + } + } + + return is_fake; +} + +static inline int work_handler_in(const struct device *dev, uint8_t ep) +{ + struct it82xx2_data *priv = udc_get_private(dev); + struct udc_ep_config *ep_cfg; + struct net_buf *buf; + uint8_t fifo_idx; + int err = 0; + + if (it82xx2_fake_token(dev, ep, DC_IN_TRANS)) { + return 0; + } + + if (ep != USB_CONTROL_EP_IN) { + fifo_idx = ep_fifo_res[USB_EP_GET_IDX(ep) % SHARED_FIFO_NUM]; + k_sem_give(&priv->fifo_sem[fifo_idx - 1]); + } + + buf = udc_buf_peek(dev, ep); + if (buf == NULL) { + return -ENODATA; + } + ep_cfg = udc_get_ep_cfg(dev, ep); + + net_buf_pull(buf, MIN(buf->len, ep_cfg->mps)); + + it82xx2_usb_set_ep_ctrl(dev, ep, EP_DATA_SEQ_TOGGLE, true); + + if (buf->len) { + work_handler_xfer_continue(dev, ep, buf); + return 0; + } + + if (udc_ep_buf_has_zlp(buf)) { + work_handler_xfer_continue(dev, ep, buf); + udc_ep_buf_clear_zlp(buf); + return 0; + } + + buf = udc_buf_get(dev, ep); + if (buf == NULL) { + return -ENODATA; + } + + udc_ep_set_busy(dev, ep, false); + + if (ep == USB_CONTROL_EP_IN) { + if (udc_ctrl_stage_is_status_in(dev) || udc_ctrl_stage_is_no_data(dev)) { + /* Status stage finished, notify upper layer */ + udc_ctrl_submit_status(dev, buf); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (udc_ctrl_stage_is_status_out(dev)) { + /* + * IN transfer finished, release buffer, + * Feed control OUT buffer for status stage. + */ + net_buf_unref(buf); + return it82xx2_ctrl_feed_dout(dev, 0U); + } + return err; + } + + return udc_submit_ep_event(dev, buf, 0); +} + +static inline int work_handler_setup(const struct device *dev, uint8_t ep) +{ + struct it82xx2_data *priv = udc_get_private(dev); + struct net_buf *buf; + int err = 0; + + if (udc_ctrl_stage_is_status_out(dev)) { + /* out -> setup */ + buf = udc_buf_get(dev, USB_CONTROL_EP_OUT); + if (buf) { + udc_ep_set_busy(dev, USB_CONTROL_EP_OUT, false); + net_buf_unref(buf); + } + } + + if (udc_ctrl_stage_is_status_in(dev) || udc_ctrl_stage_is_no_data(dev)) { + /* in -> setup */ + work_handler_in(dev, USB_CONTROL_EP_IN); + } + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, sizeof(struct usb_setup_packet)); + if (buf == NULL) { + LOG_ERR("Failed to allocate buffer"); + return -ENOMEM; + } + + udc_ep_buf_set_setup(buf); + it82xx2_xfer_out_data(dev, ep, buf); + if (buf->len != sizeof(struct usb_setup_packet)) { + LOG_DBG("buffer length %d read from chip", buf->len); + net_buf_unref(buf); + return 0; + } + + priv->stall_is_sent = false; + LOG_HEXDUMP_DBG(buf->data, buf->len, "setup:"); + + udc_ctrl_update_stage(dev, buf); + + it82xx2_usb_set_ep_ctrl(dev, ep, EP_DATA_SEQ_1, true); + + if (udc_ctrl_stage_is_data_out(dev)) { + /* Allocate and feed buffer for data OUT stage */ + LOG_DBG("s:%p|feed for -out-", buf); + err = it82xx2_ctrl_feed_dout(dev, udc_data_stage_length(buf)); + if (err == -ENOMEM) { + err = udc_submit_ep_event(dev, buf, err); + } + } else if (udc_ctrl_stage_is_data_in(dev)) { + udc_ctrl_submit_s_in_status(dev); + } else { + udc_ctrl_submit_s_status(dev); + } + + return err; +} + +static inline int work_handler_out(const struct device *dev, uint8_t ep) +{ + struct net_buf *buf; + int err = 0; + + const uint8_t ep_idx = USB_EP_GET_IDX(ep); + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + struct udc_ep_config *ep_cfg; + uint8_t fifo_idx; + size_t len; + + if (it82xx2_fake_token(dev, ep, DC_OUTDATA_TRANS)) { + return 0; + } + + buf = udc_buf_get(dev, ep); + if (buf == NULL) { + return -ENODATA; + } + + udc_ep_set_busy(dev, ep, false); + + fifo_idx = ep_idx > 0 ? ep_fifo_res[ep_idx % SHARED_FIFO_NUM] : 0; + len = (uint16_t)ff_regs[fifo_idx].ep_rx_fifo_dcnt_lsb + + (((uint16_t)ff_regs[fifo_idx].ep_rx_fifo_dcnt_msb) << 8); + + if (ep == USB_CONTROL_EP_OUT) { + if (udc_ctrl_stage_is_status_out(dev) && len != 0) { + LOG_DBG("Handle early setup token"); + /* Notify upper layer */ + udc_ctrl_submit_status(dev, buf); + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + return 0; + } + } + + ep_cfg = udc_get_ep_cfg(dev, ep); + if (len > ep_cfg->mps) { + LOG_ERR("Failed to handle this packet due to the packet size"); + return -ENOBUFS; + } + + it82xx2_xfer_out_data(dev, ep, buf); + + if (ep == USB_CONTROL_EP_OUT) { + if (udc_ctrl_stage_is_status_out(dev)) { + /* Status stage finished, notify upper layer */ + udc_ctrl_submit_status(dev, buf); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (udc_ctrl_stage_is_status_in(dev)) { + it82xx2_usb_set_ep_ctrl(dev, ep, EP_DATA_SEQ_1, true); + err = udc_ctrl_submit_s_out_status(dev, buf); + } + } else { + err = udc_submit_ep_event(dev, buf, 0); + } + + return err; +} + +static void xfer_work_handler(const struct device *dev) +{ + while (true) { + struct it82xx2_ep_event evt; + int err = 0; + + k_msgq_get(&evt_msgq, &evt, K_FOREVER); + + switch (evt.event) { + case IT82xx2_EVT_SETUP_TOKEN: + err = work_handler_setup(evt.dev, evt.ep); + break; + case IT82xx2_EVT_IN_TOKEN: + err = work_handler_in(evt.dev, evt.ep); + break; + case IT82xx2_EVT_OUT_TOKEN: + err = work_handler_out(evt.dev, evt.ep); + break; + case IT82xx2_EVT_XFER: + break; + default: + LOG_ERR("Unknown event type 0x%x", evt.event); + err = -EINVAL; + break; + } + + if (err) { + udc_submit_event(evt.dev, UDC_EVT_ERROR, err); + } + + if (evt.ep != USB_CONTROL_EP_OUT && !udc_ep_is_busy(evt.dev, evt.ep)) { + if (work_handler_xfer_next(evt.dev, evt.ep) == 0) { + udc_ep_set_busy(evt.dev, evt.ep, true); + } + } + } +} + +static inline bool it82xx2_check_ep0_stall(const struct device *dev, const uint8_t ep_idx, + const uint8_t transtype) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct it82xx2_usb_ep_fifo_regs *ff_regs = usb_regs->fifo_regs; + + if (ep_idx != 0) { + return false; + } + + /* Check if the stall bit is set */ + if (ep_regs[ep_idx].ep_ctrl.fields.send_stall_bit) { + ep_set_halt(dev, ep_idx, false); + if (transtype == DC_SETUP_TRANS) { + ff_regs[ep_idx].ep_rx_fifo_ctrl = FIFO_FORCE_EMPTY; + } + LOG_ERR("Cleared stall bit"); + return true; + } + + /* Check if the IN transaction is STALL */ + if ((transtype == DC_IN_TRANS) && (ep_regs[ep_idx].ep_status & DC_STALL_SENT)) { + return true; + } + + return false; +} + +static void it82xx2_usb_xfer_done(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_usb_ep_regs *ep_regs = usb_regs->usb_ep_regs; + struct epn_ext_ctrl_regs *epn_ext_ctrl = + usb_regs->fifo_regs[EP_EXT_REGS_DX].ext_0_3.epn_ext_ctrl; + + for (uint8_t fifo_idx = 0; fifo_idx < 4; fifo_idx++) { + uint8_t ep, ep_idx, ep_ctrl, transtype; + + ep_ctrl = ep_regs[fifo_idx].ep_ctrl.value; + transtype = ep_regs[fifo_idx].ep_transtype_sts & DC_ALL_TRANS; + + if (!(ep_ctrl & ENDPOINT_EN) || (ep_ctrl & ENDPOINT_RDY)) { + continue; + } + + if (fifo_idx == 0) { + ep_idx = 0; + if (it82xx2_check_ep0_stall(dev, ep_idx, transtype)) { + continue; + } + } else { + ep_idx = (epn_ext_ctrl[fifo_idx].epn_ext_ctrl2 & COMPLETED_TRANS) >> 4; + if (ep_idx == 0) { + continue; + } + } + + switch (transtype) { + case DC_SETUP_TRANS: + /* SETUP transaction done */ + if (ep_idx != 0) { + break; + } + it82xx2_event_submit(dev, ep_idx, IT82xx2_EVT_SETUP_TOKEN); + break; + case DC_IN_TRANS: + /* IN transaction done */ + ep = USB_EP_DIR_IN | ep_idx; + it82xx2_event_submit(dev, ep, IT82xx2_EVT_IN_TOKEN); + break; + case DC_OUTDATA_TRANS: + /* OUT transaction done */ + ep = USB_EP_DIR_OUT | ep_idx; + it82xx2_event_submit(dev, ep, IT82xx2_EVT_OUT_TOKEN); + break; + default: + LOG_ERR("Unknown transaction type"); + break; + } + } +} + +static void it82xx2_usb_dc_isr(const void *arg) +{ + const struct device *dev = arg; + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_data *priv = udc_get_private(dev); + + uint8_t status = usb_regs->dc_interrupt_status & + usb_regs->dc_interrupt_mask; /* mask non enable int */ + + /* reset event */ + if (status & DC_RESET_EVENT) { + if ((usb_regs->dc_line_status & RX_LINE_STATE_MASK) == RX_LINE_RESET) { + it82xx2_dc_reset(dev); + usb_regs->dc_interrupt_status = DC_RESET_EVENT; + + udc_submit_event(dev, UDC_EVT_RESET, 0); + return; + } + usb_regs->dc_interrupt_status = DC_RESET_EVENT; + } + + /* sof received */ + if (status & DC_SOF_RECEIVED) { + it82xx2_enable_sof_int(dev, false); + k_work_reschedule(&priv->suspended_work, K_MSEC(5)); + } + + /* transaction done */ + if (status & DC_TRANS_DONE) { + /* clear interrupt before new transaction */ + usb_regs->dc_interrupt_status = DC_TRANS_DONE; + if (udc_is_suspended(dev) && udc_is_enabled(dev)) { + udc_set_suspended(dev, false); + udc_submit_event(dev, UDC_EVT_RESUME, 0); + k_sem_give(&priv->suspended_sem); + } + it82xx2_usb_xfer_done(dev); + return; + } +} + +static void suspended_handler(struct k_work *item) +{ + struct k_work_delayable *dwork = k_work_delayable_from_work(item); + struct it82xx2_data *priv = CONTAINER_OF(dwork, struct it82xx2_data, suspended_work); + const struct device *dev = priv->dev; + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + if (usb_regs->dc_interrupt_status & DC_SOF_RECEIVED) { + usb_regs->dc_interrupt_status = DC_SOF_RECEIVED; + if (udc_is_suspended(dev) && udc_is_enabled(dev)) { + udc_set_suspended(dev, false); + udc_submit_event(dev, UDC_EVT_RESUME, 0); + k_sem_give(&priv->suspended_sem); + } + k_work_reschedule(&priv->suspended_work, K_MSEC(5)); + return; + } + + it82xx2_enable_sof_int(dev, true); + + if (!udc_is_suspended(dev) && udc_is_enabled(dev)) { + udc_set_suspended(dev, true); + udc_submit_event(dev, UDC_EVT_SUSPEND, 0); + it82xx2_enable_wu_irq(dev, true); + it82xx2_enable_standby_state(true); + + k_sem_reset(&priv->suspended_sem); + } +} + +static int it82xx2_enable(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + struct it82xx2_data *priv = udc_get_private(dev); + + k_sem_init(&priv->suspended_sem, 0, 1); + k_work_init_delayable(&priv->suspended_work, suspended_handler); + + /* Initialize FIFO ready status */ + priv->fifo_ready[0] = false; + priv->fifo_ready[1] = false; + priv->fifo_ready[2] = false; + + /* Initialize FIFO semaphore */ + k_sem_init(&priv->fifo_sem[0], 1, 1); + k_sem_init(&priv->fifo_sem[1], 1, 1); + k_sem_init(&priv->fifo_sem[2], 1, 1); + + usb_regs->dc_control = DC_GLOBAL_ENABLE | DC_FULL_SPEED_LINE_POLARITY | + DC_FULL_SPEED_LINE_RATE | DC_CONNECT_TO_HOST; + + /* Enable USB D+ and USB interrupts */ + it82xx2_enable_wu_irq(dev, true); + irq_enable(config->usb_irq); + + return 0; +} + +static int it82xx2_disable(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct usb_it82xx2_regs *const usb_regs = config->base; + + irq_disable(config->usb_irq); + + /* stop pull-up D+ D-*/ + usb_regs->dc_control &= ~DC_CONNECT_TO_HOST; + + return 0; +} + +static int it82xx2_init(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct gctrl_it8xxx2_regs *const gctrl_regs = GCTRL_IT8XXX2_REGS_BASE; + int ret; + + /* + * Disable USB debug path , prevent CPU enter + * JTAG mode and then reset by USB command. + */ + gctrl_regs->GCTRL_MCCR &= ~(IT8XXX2_GCTRL_MCCR_USB_EN); + gctrl_regs->gctrl_pmer2 |= IT8XXX2_GCTRL_PMER2_USB_PAD_EN; + + it82xx2_usb_dc_ip_init(dev); + + ret = udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, USB_EP_TYPE_CONTROL, + config->ep_cfg_out[0].caps.mps, 0); + if (ret) { + LOG_ERR("Failed to enable ep 0x%02x", USB_CONTROL_EP_OUT); + return ret; + } + + ret = udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, USB_EP_TYPE_CONTROL, + config->ep_cfg_in[0].caps.mps, 0); + if (ret) { + LOG_ERR("Failed to enable ep 0x%02x", USB_CONTROL_EP_IN); + return ret; + } + return 0; +} + +static int it82xx2_shutdown(const struct device *dev) +{ + if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) { + LOG_ERR("Failed to disable control endpoint"); + return -EIO; + } + + if (udc_ep_disable_internal(dev, USB_CONTROL_EP_IN)) { + LOG_ERR("Failed to disable control endpoint"); + return -EIO; + } + + return 0; +} + +static int it82xx2_lock(const struct device *dev) +{ + return udc_lock_internal(dev, K_FOREVER); +} + +static int it82xx2_unlock(const struct device *dev) +{ + return udc_unlock_internal(dev); +} + +static const struct udc_api it82xx2_api = { + .ep_enqueue = it82xx2_ep_enqueue, + .ep_dequeue = it82xx2_ep_dequeue, + .ep_set_halt = it82xx2_ep_set_halt, + .ep_clear_halt = it82xx2_ep_clear_halt, + .ep_try_config = NULL, + .ep_enable = it82xx2_ep_enable, + .ep_disable = it82xx2_ep_disable, + .host_wakeup = it82xx2_host_wakeup, + .set_address = it82xx2_set_address, + .enable = it82xx2_enable, + .disable = it82xx2_disable, + .init = it82xx2_init, + .shutdown = it82xx2_shutdown, + .lock = it82xx2_lock, + .unlock = it82xx2_unlock, +}; + +static int it82xx2_usb_driver_preinit(const struct device *dev) +{ + const struct usb_it82xx2_config *config = dev->config; + struct udc_data *data = dev->data; + struct it82xx2_data *priv = udc_get_private(dev); + int err; + + k_mutex_init(&data->mutex); + k_fifo_init(&priv->fifo); + + err = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (err < 0) { + LOG_ERR("Failed to configure usb pins"); + return err; + } + + for (int i = 0; i < MAX_NUM_ENDPOINTS; i++) { + config->ep_cfg_out[i].caps.out = 1; + if (i == 0) { + config->ep_cfg_out[i].caps.control = 1; + config->ep_cfg_out[i].caps.mps = USB_CONTROL_EP_MPS; + } else if ((i % 3) == 2) { + config->ep_cfg_out[i].caps.bulk = 1; + config->ep_cfg_out[i].caps.interrupt = 1; + config->ep_cfg_out[i].caps.iso = 1; + config->ep_cfg_out[i].caps.mps = 64; + } + + config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; + err = udc_register_ep(dev, &config->ep_cfg_out[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + for (int i = 0; i < MAX_NUM_ENDPOINTS; i++) { + config->ep_cfg_in[i].caps.in = 1; + if (i == 0) { + config->ep_cfg_in[i].caps.control = 1; + config->ep_cfg_in[i].caps.mps = USB_CONTROL_EP_MPS; + } else if ((i % 3) != 2) { + config->ep_cfg_in[i].caps.bulk = 1; + config->ep_cfg_in[i].caps.interrupt = 1; + config->ep_cfg_in[i].caps.iso = 1; + config->ep_cfg_in[i].caps.mps = 64; + } + + config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i; + err = udc_register_ep(dev, &config->ep_cfg_in[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + data->caps.rwup = true; + data->caps.mps0 = UDC_MPS0_64; + + priv->dev = dev; + + config->make_thread(dev); + + /* Initializing WU (USB D+) */ + it8xxx2_usb_dc_wuc_init(dev); + + /* Connect USB interrupt */ + irq_connect_dynamic(config->usb_irq, 0, it82xx2_usb_dc_isr, dev, 0); + + return 0; +} + +#define IT82xx2_USB_DEVICE_DEFINE(n) \ + K_KERNEL_STACK_DEFINE(udc_it82xx2_stack_##n, CONFIG_UDC_IT82xx2_STACK_SIZE); \ + \ + static void udc_it82xx2_thread_##n(void *dev, void *arg1, void *arg2) \ + { \ + ARG_UNUSED(arg1); \ + ARG_UNUSED(arg2); \ + xfer_work_handler(dev); \ + } \ + \ + static void udc_it82xx2_make_thread_##n(const struct device *dev) \ + { \ + struct it82xx2_data *priv = udc_get_private(dev); \ + \ + k_thread_create(&priv->thread_data, udc_it82xx2_stack_##n, \ + K_THREAD_STACK_SIZEOF(udc_it82xx2_stack_##n), \ + udc_it82xx2_thread_##n, (void *)dev, NULL, NULL, K_PRIO_COOP(8), \ + 0, K_NO_WAIT); \ + k_thread_name_set(&priv->thread_data, dev->name); \ + } \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static struct udc_ep_config ep_cfg_out[MAX_NUM_ENDPOINTS]; \ + static struct udc_ep_config ep_cfg_in[MAX_NUM_ENDPOINTS]; \ + \ + static struct usb_it82xx2_config udc_cfg_##n = { \ + .base = (struct usb_it82xx2_regs *)DT_INST_REG_ADDR(n), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + .wuc = {.dev = IT8XXX2_DEV_WUC(0, n), .mask = IT8XXX2_DEV_WUC_MASK(0, n)}, \ + .usb_irq = DT_INST_IRQ_BY_IDX(n, 0, irq), \ + .wu_irq = DT_INST_IRQ_BY_IDX(n, 1, irq), \ + .ep_cfg_in = ep_cfg_out, \ + .ep_cfg_out = ep_cfg_in, \ + .make_thread = udc_it82xx2_make_thread_##n, \ + }; \ + \ + static struct it82xx2_data priv_data_##n = {}; \ + \ + static struct udc_data udc_data_##n = { \ + .mutex = Z_MUTEX_INITIALIZER(udc_data_##n.mutex), \ + .priv = &priv_data_##n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, it82xx2_usb_driver_preinit, NULL, &udc_data_##n, &udc_cfg_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &it82xx2_api); + +DT_INST_FOREACH_STATUS_OKAY(IT82xx2_USB_DEVICE_DEFINE) diff --git a/drivers/usb/udc/udc_mcux_ehci.c b/drivers/usb/udc/udc_mcux_ehci.c new file mode 100644 index 0000000000000..e5e56adb46907 --- /dev/null +++ b/drivers/usb/udc/udc_mcux_ehci.c @@ -0,0 +1,929 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT nxp_ehci + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "udc_common.h" +#include "usb.h" +#include "usb_device_config.h" +#include "usb_device_mcux_drv_port.h" +#include "usb_device_ehci.h" +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED +#include "usb_phy.h" +#endif + +#include +LOG_MODULE_REGISTER(udc_mcux, CONFIG_UDC_DRIVER_LOG_LEVEL); + +/* + * There is no real advantage to change control endpoint size + * but we can use it for testing UDC driver API and higher layers. + */ +#define USB_MCUX_MPS0 UDC_MPS0_64 +#define USB_MCUX_EP0_SIZE 64 + +#define PRV_DATA_HANDLE(_handle) CONTAINER_OF(_handle, struct udc_mcux_data, mcux_device) + +struct udc_mcux_config { + const usb_device_controller_interface_struct_t *mcux_if; + void (*irq_enable_func)(const struct device *dev); + void (*irq_disable_func)(const struct device *dev); + size_t num_of_eps; + struct udc_ep_config *ep_cfg_in; + struct udc_ep_config *ep_cfg_out; + uintptr_t base; + const struct pinctrl_dev_config *pincfg; +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED + usb_phy_config_struct_t *phy_config; +#endif +}; + +struct udc_mcux_data { + const struct device *dev; + usb_device_struct_t mcux_device; + uint8_t controller_id; /* 0xFF is invalid value */ +}; + +/* TODO: implement the cache maintenance + * solution1: Use the non-cached buf to do memcpy before/after giving buffer to usb controller. + * solution2: Use cache API to flush/invalid cache. but it needs the given buffer is + * cache line size aligned and the buffer range cover multiple of cache line size block. + * Need to change the usb stack to implement it, will try to implement it later. + */ +#if defined(CONFIG_NOCACHE_MEMORY) +K_HEAP_DEFINE_NOCACHE(mcux_packet_alloc_pool, USB_DEVICE_CONFIG_ENDPOINTS * 2u * 1024u); + +/* allocate non-cached buffer for usb */ +static void *udc_mcux_nocache_alloc(uint32_t size) +{ + void *p = (void *)k_heap_alloc(&mcux_packet_alloc_pool, size, K_NO_WAIT); + + if (p != NULL) { + (void)memset(p, 0, size); + } + + return p; +} + +/* free the allocated non-cached buffer */ +static void udc_mcux_nocache_free(void *p) +{ + if (p == NULL) { + return; + } + k_heap_free(&mcux_packet_alloc_pool, p); +} +#endif + +static int udc_mcux_control(const struct device *dev, usb_device_control_type_t command, + void *param) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + status = mcux_if->deviceControl(priv->mcux_device.controllerHandle, + command, param); + + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + return 0; +} + +/* If ep is busy, return busy. Otherwise feed the buf to controller */ +static int udc_mcux_ep_feed(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status = kStatus_USB_Success; + uint8_t *data; + uint32_t len; + unsigned int key; + usb_device_endpoint_status_struct_t ep_status; + + ep_status.endpointAddress = cfg->addr; + udc_mcux_control(dev, kUSB_DeviceControlGetEndpointStatus, &ep_status); + if (ep_status.endpointStatus == kUSB_DeviceEndpointStateStalled) { + return -EACCES; /* stalled */ + } + + key = irq_lock(); + if (!udc_ep_is_busy(dev, cfg->addr)) { + udc_ep_set_busy(dev, cfg->addr, true); + irq_unlock(key); + + if (USB_EP_DIR_IS_OUT(cfg->addr)) { + len = net_buf_tailroom(buf); +#if defined(CONFIG_NOCACHE_MEMORY) + data = (len == 0 ? NULL : udc_mcux_nocache_alloc(len)); +#else + data = net_buf_tail(buf); +#endif + status = mcux_if->deviceRecv(priv->mcux_device.controllerHandle, + cfg->addr, data, len); + } else { + len = buf->len; +#if defined(CONFIG_NOCACHE_MEMORY) + data = (len == 0 ? NULL : udc_mcux_nocache_alloc(len)); + memcpy(data, buf->data, len); +#else + data = buf->data; +#endif + status = mcux_if->deviceSend(priv->mcux_device.controllerHandle, + cfg->addr, data, len); + } + + key = irq_lock(); + if (status != kStatus_USB_Success) { + udc_ep_set_busy(dev, cfg->addr, false); + } + irq_unlock(key); + } else { + irq_unlock(key); + return -EBUSY; + } + + return (status == kStatus_USB_Success ? 0 : -EIO); +} + +/* return success if the ep is busy or stalled. */ +static int udc_mcux_ep_try_feed(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *feed_buf; + + feed_buf = udc_buf_peek(dev, cfg->addr); + if (feed_buf) { + int ret = udc_mcux_ep_feed(dev, cfg, feed_buf); + + return ((ret == -EBUSY || ret == -EACCES || ret == 0) ? 0 : -EIO); + } + + return 0; +} + +/* + * Allocate buffer and initiate a new control OUT transfer. + */ +static int udc_mcux_ctrl_feed_dout(const struct device *dev, + const size_t length) +{ + struct net_buf *buf; + struct udc_ep_config *cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + int ret; + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, length); + if (buf == NULL) { + return -ENOMEM; + } + + net_buf_put(&cfg->fifo, buf); + + ret = udc_mcux_ep_feed(dev, cfg, buf); + + if (ret) { + net_buf_unref(buf); + return ret; + } + + return 0; +} + +static int udc_mcux_handler_setup(const struct device *dev, struct usb_setup_packet *setup) +{ + int err; + struct net_buf *buf; + + LOG_DBG("setup packet"); + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, + sizeof(struct usb_setup_packet)); + if (buf == NULL) { + LOG_ERR("Failed to allocate for setup"); + return -EIO; + } + + udc_ep_buf_set_setup(buf); + memcpy(buf->data, setup, 8); + net_buf_add(buf, 8); + + if (setup->RequestType.type == USB_REQTYPE_TYPE_STANDARD && + setup->RequestType.direction == USB_REQTYPE_DIR_TO_DEVICE && + setup->bRequest == USB_SREQ_SET_ADDRESS && + setup->wLength == 0) { + udc_mcux_control(dev, kUSB_DeviceControlPreSetDeviceAddress, + &setup->wValue); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (!buf->len) { + return -EIO; + } + + if (udc_ctrl_stage_is_data_out(dev)) { + /* Allocate and feed buffer for data OUT stage */ + LOG_DBG("s:%p|feed for -out-", buf); + err = udc_mcux_ctrl_feed_dout(dev, udc_data_stage_length(buf)); + if (err == -ENOMEM) { + err = udc_submit_ep_event(dev, buf, err); + } + } else if (udc_ctrl_stage_is_data_in(dev)) { + err = udc_ctrl_submit_s_in_status(dev); + } else { + err = udc_ctrl_submit_s_status(dev); + } + + return err; +} + +static int udc_mcux_handler_ctrl_out(const struct device *dev, struct net_buf *buf, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err = 0; + uint32_t len; + + len = MIN(net_buf_tailroom(buf), mcux_len); +#if defined(CONFIG_NOCACHE_MEMORY) + memcpy(net_buf_tail(buf), mcux_buf, len); + udc_mcux_nocache_free(mcux_buf); +#endif + net_buf_add(buf, len); + if (udc_ctrl_stage_is_status_out(dev)) { + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + /* Status stage finished, notify upper layer */ + err = udc_ctrl_submit_status(dev, buf); + } else { + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + } + + if (udc_ctrl_stage_is_status_in(dev)) { + err = udc_ctrl_submit_s_out_status(dev, buf); + } + + return err; +} + +static int udc_mcux_handler_ctrl_in(const struct device *dev, struct net_buf *buf, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err = 0; + uint32_t len; + + len = MIN(buf->len, mcux_len); + buf->data += len; + buf->len -= len; +#if defined(CONFIG_NOCACHE_MEMORY) + udc_mcux_nocache_free(mcux_buf); +#endif + + if (udc_ctrl_stage_is_status_in(dev) || + udc_ctrl_stage_is_no_data(dev)) { + /* Status stage finished, notify upper layer */ + err = udc_ctrl_submit_status(dev, buf); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (udc_ctrl_stage_is_status_out(dev)) { + /* + * IN transfer finished, release buffer, + * control OUT buffer should be already fed. + */ + net_buf_unref(buf); + err = udc_mcux_ctrl_feed_dout(dev, 0u); + } + + return err; +} + +static int udc_mcux_handler_non_ctrl_in(const struct device *dev, uint8_t ep, + struct net_buf *buf, uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + uint32_t len; + + len = MIN(buf->len, mcux_len); + buf->data += len; + buf->len -= len; + +#if defined(CONFIG_NOCACHE_MEMORY) + udc_mcux_nocache_free(mcux_buf); +#endif + err = udc_submit_ep_event(dev, buf, 0); + udc_mcux_ep_try_feed(dev, udc_get_ep_cfg(dev, ep)); + + return err; +} + +static int udc_mcux_handler_non_ctrl_out(const struct device *dev, uint8_t ep, + struct net_buf *buf, uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + uint32_t len; + + len = MIN(net_buf_tailroom(buf), mcux_len); +#if defined(CONFIG_NOCACHE_MEMORY) + memcpy(net_buf_tail(buf), mcux_buf, len); +#endif + net_buf_add(buf, len); + +#if defined(CONFIG_NOCACHE_MEMORY) + udc_mcux_nocache_free(mcux_buf); +#endif + err = udc_submit_ep_event(dev, buf, 0); + udc_mcux_ep_try_feed(dev, udc_get_ep_cfg(dev, ep)); + + return err; +} + +static int udc_mcux_handler_out(const struct device *dev, uint8_t ep, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + struct net_buf *buf; + unsigned int key; + + buf = udc_buf_get(dev, ep); + + key = irq_lock(); + udc_ep_set_busy(dev, ep, false); + irq_unlock(key); + + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + + if (ep == USB_CONTROL_EP_OUT) { + err = udc_mcux_handler_ctrl_out(dev, buf, mcux_buf, mcux_len); + } else { + err = udc_mcux_handler_non_ctrl_out(dev, ep, buf, mcux_buf, mcux_len); + } + + return err; +} + +/* return true - zlp is feed; false - no zlp */ +static bool udc_mcux_handler_zlt(const struct device *dev, uint8_t ep, struct net_buf *buf, + uint16_t mcux_len) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + + /* The whole transfer is already done by MCUX controller driver. */ + if (mcux_len >= buf->len) { + if (udc_ep_buf_has_zlp(buf)) { + usb_status_t status; + + udc_ep_buf_clear_zlp(buf); + status = mcux_if->deviceRecv(priv->mcux_device.controllerHandle, + ep, NULL, 0); + if (status != kStatus_USB_Success) { + udc_submit_event(dev, UDC_EVT_ERROR, -EIO); + return false; + } + return true; + } + } + + return false; +} + +static int udc_mcux_handler_in(const struct device *dev, uint8_t ep, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + struct net_buf *buf; + unsigned int key; + + buf = udc_buf_peek(dev, ep); + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + + if (udc_mcux_handler_zlt(dev, ep, buf, mcux_len)) { + return 0; + } + + buf = udc_buf_get(dev, ep); + + key = irq_lock(); + udc_ep_set_busy(dev, ep, false); + irq_unlock(key); + + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + if (ep == USB_CONTROL_EP_IN) { + err = udc_mcux_handler_ctrl_in(dev, buf, mcux_buf, mcux_len); + } else { + err = udc_mcux_handler_non_ctrl_in(dev, ep, buf, mcux_buf, mcux_len); + } + + return err; +} + +/* NXP MCUX controller driver notify transfers/status through this interface */ +usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg) +{ + usb_device_callback_message_struct_t *mcux_msg = msg; + uint8_t ep; + usb_device_notification_t mcux_notify; + struct udc_mcux_data *priv; + const struct device *dev; + usb_status_t mcux_status = kStatus_USB_Success; + int err = 0; + + if ((NULL == msg) || (NULL == handle)) { + return kStatus_USB_InvalidHandle; + } + + mcux_notify = (usb_device_notification_t)mcux_msg->code; + priv = (struct udc_mcux_data *)(PRV_DATA_HANDLE(handle)); + dev = priv->dev; + + switch (mcux_notify) { + case kUSB_DeviceNotifyBusReset: + struct udc_ep_config *cfg; + + udc_mcux_control(dev, kUSB_DeviceControlSetDefaultStatus, NULL); + cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + if (cfg->stat.enabled) { + udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT); + } + cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN); + if (cfg->stat.enabled) { + udc_ep_disable_internal(dev, USB_CONTROL_EP_IN); + } + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, + USB_EP_TYPE_CONTROL, + USB_MCUX_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } + + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, + USB_EP_TYPE_CONTROL, + USB_MCUX_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } + udc_submit_event(dev, UDC_EVT_RESET, 0); + break; + case kUSB_DeviceNotifyError: + udc_submit_event(dev, UDC_EVT_ERROR, -EIO); + break; + case kUSB_DeviceNotifySuspend: + udc_set_suspended(dev, true); + udc_submit_event(dev, UDC_EVT_SUSPEND, 0); + break; + case kUSB_DeviceNotifyResume: + udc_set_suspended(dev, false); + udc_submit_event(dev, UDC_EVT_RESUME, 0); + break; + case kUSB_DeviceNotifyLPMSleep: + break; + case kUSB_DeviceNotifyDetach: + udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0); + break; + case kUSB_DeviceNotifyAttach: + udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); + break; + default: + ep = mcux_msg->code; + if (mcux_msg->isSetup) { + struct usb_setup_packet *setup = + (struct usb_setup_packet *)mcux_msg->buffer; + + err = udc_mcux_handler_setup(dev, setup); + } else if (USB_EP_DIR_IS_IN(ep)) { + err = udc_mcux_handler_in(dev, ep, mcux_msg->buffer, mcux_msg->length); + } else { + err = udc_mcux_handler_out(dev, ep, mcux_msg->buffer, mcux_msg->length); + } + + break; + } + + if (unlikely(err)) { + udc_submit_event(dev, UDC_EVT_ERROR, err); + mcux_status = kStatus_USB_Error; + } + return mcux_status; +} + +static void udc_mcux_isr(const struct device *dev) +{ + struct udc_mcux_data *priv = udc_get_private(dev); + + USB_DeviceEhciIsrFunction((void *)(&priv->mcux_device)); +} + +/* Return actual USB device speed */ +static enum udc_bus_speed udc_mcux_device_speed(const struct device *dev) +{ + int err; + uint8_t mcux_speed; + + err = udc_mcux_control(dev, kUSB_DeviceControlGetSpeed, &mcux_speed); + if (err) { + /* + * In the current version of all NXP USB device drivers, + * no error is returned if the parameter is correct. + */ + return UDC_BUS_SPEED_FS; + } + + switch (mcux_speed) { + case USB_SPEED_HIGH: + return UDC_BUS_SPEED_HS; + case USB_SPEED_LOW: + __ASSERT(false, "Low speed mode not supported"); + __fallthrough; + case USB_SPEED_FULL: + __fallthrough; + default: + return UDC_BUS_SPEED_FS; + } +} + +static int udc_mcux_ep_enqueue(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + udc_buf_put(cfg, buf); + if (cfg->stat.halted) { + LOG_DBG("ep 0x%02x halted", cfg->addr); + return 0; + } + + return udc_mcux_ep_try_feed(dev, cfg); +} + +static int udc_mcux_ep_dequeue(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *buf; + unsigned int key; + + cfg->stat.halted = false; + buf = udc_buf_get_all(dev, cfg->addr); + if (buf) { + udc_submit_ep_event(dev, buf, -ECONNABORTED); + } + + key = irq_lock(); + udc_ep_set_busy(dev, cfg->addr, false); + irq_unlock(key); + + return 0; +} + +static int udc_mcux_ep_set_halt(const struct device *dev, + struct udc_ep_config *const cfg) +{ + return udc_mcux_control(dev, kUSB_DeviceControlEndpointStall, &cfg->addr); +} + +static int udc_mcux_ep_clear_halt(const struct device *dev, + struct udc_ep_config *const cfg) +{ + (void)udc_mcux_control(dev, kUSB_DeviceControlEndpointUnstall, &cfg->addr); + /* transfer is enqueued after stalled */ + return udc_mcux_ep_try_feed(dev, cfg); +} + +static int udc_mcux_ep_enable(const struct device *dev, + struct udc_ep_config *const cfg) +{ + usb_device_endpoint_init_struct_t ep_init; + + LOG_DBG("Enable ep 0x%02x", cfg->addr); + + ep_init.zlt = 0U; + ep_init.interval = cfg->interval; + ep_init.endpointAddress = cfg->addr; + ep_init.maxPacketSize = cfg->mps; + + switch (cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) { + case USB_EP_TYPE_CONTROL: + ep_init.transferType = USB_ENDPOINT_CONTROL; + break; + case USB_EP_TYPE_BULK: + ep_init.transferType = USB_ENDPOINT_BULK; + break; + case USB_EP_TYPE_INTERRUPT: + ep_init.transferType = USB_ENDPOINT_INTERRUPT; + break; + case USB_EP_TYPE_ISO: + ep_init.transferType = USB_ENDPOINT_ISOCHRONOUS; + break; + default: + return -EINVAL; + } + + return udc_mcux_control(dev, kUSB_DeviceControlEndpointInit, &ep_init); +} + +static int udc_mcux_ep_disable(const struct device *dev, + struct udc_ep_config *const cfg) +{ + LOG_DBG("Disable ep 0x%02x", cfg->addr); + + return udc_mcux_control(dev, kUSB_DeviceControlEndpointDeinit, &cfg->addr); +} + +static int udc_mcux_host_wakeup(const struct device *dev) +{ + return -ENOTSUP; +} + +static int udc_mcux_set_address(const struct device *dev, const uint8_t addr) +{ + uint8_t temp_addr = addr; + + return udc_mcux_control(dev, kUSB_DeviceControlSetDeviceAddress, &temp_addr); +} + +static int udc_mcux_enable(const struct device *dev) +{ + return udc_mcux_control(dev, kUSB_DeviceControlRun, NULL); +} + +static int udc_mcux_disable(const struct device *dev) +{ + return udc_mcux_control(dev, kUSB_DeviceControlStop, NULL); +} + +static int udc_mcux_init(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + if (priv->controller_id == 0xFFu) { + return -ENOMEM; + } + +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED + if (config->phy_config != NULL) { + USB_EhciPhyInit(priv->controller_id, 0u, + (usb_phy_config_struct_t *)&config->phy_config); + } +#endif + + /* Init MCUX USB device driver. */ + status = mcux_if->deviceInit(priv->controller_id, + &priv->mcux_device, &(priv->mcux_device.controllerHandle)); + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + /* enable USB interrupt */ + config->irq_enable_func(dev); + + LOG_DBG("Initialized USB controller %x", (uint32_t)config->base); + + return 0; +} + +static int udc_mcux_shutdown(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + /* Disable interrupt */ + config->irq_disable_func(dev); + + /* De-init MCUX USB device driver. */ + status = mcux_if->deviceDeinit(priv->mcux_device.controllerHandle); + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + return 0; +} + +static int udc_mcux_lock(const struct device *dev) +{ + return udc_lock_internal(dev, K_FOREVER); +} + +static int udc_mcux_unlock(const struct device *dev) +{ + return udc_unlock_internal(dev); +} + +static inline void udc_mcux_get_hal_driver_id(struct udc_mcux_data *priv, + const struct udc_mcux_config *config) +{ + /* + * MCUX USB controller drivers use an ID to tell the HAL drivers + * which controller is being used. This part of the code converts + * the base address to the ID value. + */ +#ifdef USBHS_STACK_BASE_ADDRS + uintptr_t usb_base_addrs[] = USBHS_STACK_BASE_ADDRS; +#else + uintptr_t usb_base_addrs[] = USBHS_BASE_ADDRS; +#endif + + /* get the right controller id */ + priv->controller_id = 0xFFu; /* invalid value */ + for (uint8_t i = 0; i < ARRAY_SIZE(usb_base_addrs); i++) { + if (usb_base_addrs[i] == config->base) { + priv->controller_id = kUSB_ControllerEhci0 + i; + break; + } + } +} + +static int udc_mcux_driver_preinit(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + struct udc_data *data = dev->data; + struct udc_mcux_data *priv = data->priv; + int err; + + udc_mcux_get_hal_driver_id(priv, config); + if (priv->controller_id == 0xFFu) { + return -ENOMEM; + } + + k_mutex_init(&data->mutex); + + for (int i = 0; i < config->num_of_eps; i++) { + config->ep_cfg_out[i].caps.out = 1; + if (i == 0) { + config->ep_cfg_out[i].caps.control = 1; + config->ep_cfg_out[i].caps.mps = 64; + } else { + config->ep_cfg_out[i].caps.bulk = 1; + config->ep_cfg_out[i].caps.interrupt = 1; + config->ep_cfg_out[i].caps.iso = 1; + config->ep_cfg_out[i].caps.mps = 1024; + } + + config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; + err = udc_register_ep(dev, &config->ep_cfg_out[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + for (int i = 0; i < config->num_of_eps; i++) { + config->ep_cfg_in[i].caps.in = 1; + if (i == 0) { + config->ep_cfg_in[i].caps.control = 1; + config->ep_cfg_in[i].caps.mps = 64; + } else { + config->ep_cfg_in[i].caps.bulk = 1; + config->ep_cfg_in[i].caps.interrupt = 1; + config->ep_cfg_in[i].caps.iso = 1; + config->ep_cfg_in[i].caps.mps = 1024; + } + + config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i; + err = udc_register_ep(dev, &config->ep_cfg_in[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + /* Requires udc_mcux_host_wakeup() implementation */ + data->caps.rwup = false; + data->caps.mps0 = USB_MCUX_MPS0; + data->caps.hs = true; + priv->dev = dev; + + pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + + return 0; +} + +static const struct udc_api udc_mcux_api = { + .device_speed = udc_mcux_device_speed, + .ep_enqueue = udc_mcux_ep_enqueue, + .ep_dequeue = udc_mcux_ep_dequeue, + .ep_set_halt = udc_mcux_ep_set_halt, + .ep_clear_halt = udc_mcux_ep_clear_halt, + .ep_try_config = NULL, + .ep_enable = udc_mcux_ep_enable, + .ep_disable = udc_mcux_ep_disable, + .host_wakeup = udc_mcux_host_wakeup, + .set_address = udc_mcux_set_address, + .enable = udc_mcux_enable, + .disable = udc_mcux_disable, + .init = udc_mcux_init, + .shutdown = udc_mcux_shutdown, + .lock = udc_mcux_lock, + .unlock = udc_mcux_unlock, +}; + +/* EHCI device driver interface */ +static const usb_device_controller_interface_struct_t udc_mcux_if = { + USB_DeviceEhciInit, USB_DeviceEhciDeinit, USB_DeviceEhciSend, + USB_DeviceEhciRecv, USB_DeviceEhciCancel, USB_DeviceEhciControl +}; + +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED +#define UDC_MCUX_PHY_DEFINE(n) \ +static usb_phy_config_struct_t phy_config_##n = { \ + .D_CAL = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_d_cal, 0), \ + .TXCAL45DP = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_cal_45_dp_ohms, 0), \ + .TXCAL45DM = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_cal_45_dm_ohms, 0), \ +} + +#define UDC_MCUX_PHY_DEFINE_OR(n) \ + COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), phy_handle), \ + (UDC_MCUX_PHY_DEFINE(n)), ()) + +#define UDC_MCUX_PHY_CFG_PTR_OR_NULL(n) \ + .phy_config = COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), phy_handle), \ + (&phy_config_##n), (NULL)) +#else +#define UDC_MCUX_PHY_DEFINE_OR(n) +#define UDC_MCUX_PHY_CFG_PTR_OR_NULL(n) +#endif + +#define USB_MCUX_EHCI_DEVICE_DEFINE(n) \ + UDC_MCUX_PHY_DEFINE_OR(n); \ + \ + static void udc_irq_enable_func##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + udc_mcux_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static void udc_irq_disable_func##n(const struct device *dev) \ + { \ + irq_disable(DT_INST_IRQN(n)); \ + } \ + \ + static struct udc_ep_config \ + ep_cfg_out##n[DT_INST_PROP(n, num_bidir_endpoints)]; \ + static struct udc_ep_config \ + ep_cfg_in##n[DT_INST_PROP(n, num_bidir_endpoints)]; \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static struct udc_mcux_config priv_config_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .irq_enable_func = udc_irq_enable_func##n, \ + .irq_disable_func = udc_irq_disable_func##n, \ + .num_of_eps = DT_INST_PROP(n, num_bidir_endpoints), \ + .ep_cfg_in = ep_cfg_in##n, \ + .ep_cfg_out = ep_cfg_out##n, \ + .mcux_if = &udc_mcux_if, \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + UDC_MCUX_PHY_CFG_PTR_OR_NULL(n), \ + }; \ + \ + static struct udc_mcux_data priv_data_##n = { \ + }; \ + \ + static struct udc_data udc_data_##n = { \ + .mutex = Z_MUTEX_INITIALIZER(udc_data_##n.mutex), \ + .priv = &priv_data_##n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, udc_mcux_driver_preinit, NULL, \ + &udc_data_##n, &priv_config_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &udc_mcux_api); + +DT_INST_FOREACH_STATUS_OKAY(USB_MCUX_EHCI_DEVICE_DEFINE) diff --git a/drivers/usb/udc/udc_mcux_ip3511.c b/drivers/usb/udc/udc_mcux_ip3511.c new file mode 100644 index 0000000000000..d3b257e80e75a --- /dev/null +++ b/drivers/usb/udc/udc_mcux_ip3511.c @@ -0,0 +1,890 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT nxp_lpcip3511 + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "udc_common.h" +#include "usb.h" +#include "usb_device_config.h" +#include "usb_device_mcux_drv_port.h" +#include "usb_device_lpcip3511.h" +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED +#include "usb_phy.h" +#endif + +#include +LOG_MODULE_REGISTER(udc_mcux, CONFIG_UDC_DRIVER_LOG_LEVEL); + +/* + * There is no real advantage to change control endpoint size + * but we can use it for testing UDC driver API and higher layers. + */ +#define USB_MCUX_MPS0 UDC_MPS0_64 +#define USB_MCUX_EP0_SIZE 64 + +#define PRV_DATA_HANDLE(_handle) CONTAINER_OF(_handle, struct udc_mcux_data, mcux_device) + +struct udc_mcux_config { + const usb_device_controller_interface_struct_t *mcux_if; + void (*irq_enable_func)(const struct device *dev); + void (*irq_disable_func)(const struct device *dev); + size_t num_of_eps; + struct udc_ep_config *ep_cfg_in; + struct udc_ep_config *ep_cfg_out; + uintptr_t base; + const struct pinctrl_dev_config *pincfg; +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED + usb_phy_config_struct_t *phy_config; +#endif +}; + +struct udc_mcux_data { + const struct device *dev; + usb_device_struct_t mcux_device; + uint8_t controller_id; /* 0xFF is invalid value */ +}; + +static int udc_mcux_control(const struct device *dev, usb_device_control_type_t command, + void *param) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + status = mcux_if->deviceControl(priv->mcux_device.controllerHandle, + command, param); + + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + return 0; +} + +/* If ep is busy, return busy. Otherwise feed the buf to controller */ +static int udc_mcux_ep_feed(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status = kStatus_USB_Success; + uint8_t *data; + uint32_t len; + unsigned int key; + usb_device_endpoint_status_struct_t ep_status; + + ep_status.endpointAddress = cfg->addr; + udc_mcux_control(dev, kUSB_DeviceControlGetEndpointStatus, &ep_status); + if (ep_status.endpointStatus == kUSB_DeviceEndpointStateStalled) { + return -EACCES; /* stalled */ + } + + key = irq_lock(); + if (!udc_ep_is_busy(dev, cfg->addr)) { + udc_ep_set_busy(dev, cfg->addr, true); + irq_unlock(key); + + if (USB_EP_DIR_IS_OUT(cfg->addr)) { + len = net_buf_tailroom(buf); + data = net_buf_tail(buf); + status = mcux_if->deviceRecv(priv->mcux_device.controllerHandle, + cfg->addr, data, len); + } else { + len = buf->len; + data = buf->data; + status = mcux_if->deviceSend(priv->mcux_device.controllerHandle, + cfg->addr, data, len); + } + + key = irq_lock(); + if (status != kStatus_USB_Success) { + udc_ep_set_busy(dev, cfg->addr, false); + } + irq_unlock(key); + } else { + irq_unlock(key); + return -EBUSY; + } + + return (status == kStatus_USB_Success ? 0 : -EIO); +} + +/* return success if the ep is busy or stalled. */ +static int udc_mcux_ep_try_feed(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *feed_buf; + + feed_buf = udc_buf_peek(dev, cfg->addr); + if (feed_buf) { + int ret = udc_mcux_ep_feed(dev, cfg, feed_buf); + + return ((ret == -EBUSY || ret == -EACCES || ret == 0) ? 0 : -EIO); + } + + return 0; +} + +/* + * Allocate buffer and initiate a new control OUT transfer. + */ +static int udc_mcux_ctrl_feed_dout(const struct device *dev, + const size_t length) +{ + struct net_buf *buf; + struct udc_ep_config *cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + int ret; + + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, length); + if (buf == NULL) { + return -ENOMEM; + } + + net_buf_put(&cfg->fifo, buf); + + ret = udc_mcux_ep_feed(dev, cfg, buf); + + if (ret) { + net_buf_unref(buf); + return ret; + } + + return 0; +} + +static int udc_mcux_handler_setup(const struct device *dev, struct usb_setup_packet *setup) +{ + int err; + struct net_buf *buf; + + LOG_DBG("setup packet"); + buf = udc_ctrl_alloc(dev, USB_CONTROL_EP_OUT, + sizeof(struct usb_setup_packet)); + if (buf == NULL) { + LOG_ERR("Failed to allocate for setup"); + return -EIO; + } + + udc_ep_buf_set_setup(buf); + memcpy(buf->data, setup, 8); + net_buf_add(buf, 8); + + if (setup->RequestType.type == USB_REQTYPE_TYPE_STANDARD && + setup->RequestType.direction == USB_REQTYPE_DIR_TO_DEVICE && + setup->bRequest == USB_SREQ_SET_ADDRESS && + setup->wLength == 0) { + udc_mcux_control(dev, kUSB_DeviceControlPreSetDeviceAddress, + &setup->wValue); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (!buf->len) { + return -EIO; + } + + if (udc_ctrl_stage_is_data_out(dev)) { + /* Allocate and feed buffer for data OUT stage */ + LOG_DBG("s:%p|feed for -out-", buf); + err = udc_mcux_ctrl_feed_dout(dev, udc_data_stage_length(buf)); + if (err == -ENOMEM) { + err = udc_submit_ep_event(dev, buf, err); + } + } else if (udc_ctrl_stage_is_data_in(dev)) { + err = udc_ctrl_submit_s_in_status(dev); + } else { + err = udc_ctrl_submit_s_status(dev); + } + + return err; +} + +static int udc_mcux_handler_ctrl_out(const struct device *dev, struct net_buf *buf, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err = 0; + uint32_t len; + + len = MIN(net_buf_tailroom(buf), mcux_len); + net_buf_add(buf, len); + if (udc_ctrl_stage_is_status_out(dev)) { + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + /* Status stage finished, notify upper layer */ + err = udc_ctrl_submit_status(dev, buf); + } else { + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + } + + if (udc_ctrl_stage_is_status_in(dev)) { + err = udc_ctrl_submit_s_out_status(dev, buf); + } + + return err; +} + +static int udc_mcux_handler_ctrl_in(const struct device *dev, struct net_buf *buf, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err = 0; + uint32_t len; + + len = MIN(buf->len, mcux_len); + buf->data += len; + buf->len -= len; + + if (udc_ctrl_stage_is_status_in(dev) || + udc_ctrl_stage_is_no_data(dev)) { + /* Status stage finished, notify upper layer */ + err = udc_ctrl_submit_status(dev, buf); + } + + /* Update to next stage of control transfer */ + udc_ctrl_update_stage(dev, buf); + + if (udc_ctrl_stage_is_status_out(dev)) { + /* + * IN transfer finished, release buffer, + * control OUT buffer should be already fed. + */ + net_buf_unref(buf); + err = udc_mcux_ctrl_feed_dout(dev, 0u); + } + + return err; +} + +static int udc_mcux_handler_non_ctrl_in(const struct device *dev, uint8_t ep, + struct net_buf *buf, uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + uint32_t len; + + len = MIN(buf->len, mcux_len); + buf->data += len; + buf->len -= len; + + err = udc_submit_ep_event(dev, buf, 0); + udc_mcux_ep_try_feed(dev, udc_get_ep_cfg(dev, ep)); + + return err; +} + +static int udc_mcux_handler_non_ctrl_out(const struct device *dev, uint8_t ep, + struct net_buf *buf, uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + uint32_t len; + + len = MIN(net_buf_tailroom(buf), mcux_len); + net_buf_add(buf, len); + + err = udc_submit_ep_event(dev, buf, 0); + udc_mcux_ep_try_feed(dev, udc_get_ep_cfg(dev, ep)); + + return err; +} + +static int udc_mcux_handler_out(const struct device *dev, uint8_t ep, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + struct net_buf *buf; + unsigned int key; + + buf = udc_buf_get(dev, ep); + + key = irq_lock(); + udc_ep_set_busy(dev, ep, false); + irq_unlock(key); + + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + + if (ep == USB_CONTROL_EP_OUT) { + err = udc_mcux_handler_ctrl_out(dev, buf, mcux_buf, mcux_len); + } else { + err = udc_mcux_handler_non_ctrl_out(dev, ep, buf, mcux_buf, mcux_len); + } + + return err; +} + +/* return true - zlp is feed; false - no zlp */ +static bool udc_mcux_handler_zlt(const struct device *dev, uint8_t ep, struct net_buf *buf, + uint16_t mcux_len) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + + /* The whole transfer is already done by MCUX controller driver. */ + if (mcux_len >= buf->len) { + if (udc_ep_buf_has_zlp(buf)) { + usb_status_t status; + + udc_ep_buf_clear_zlp(buf); + status = mcux_if->deviceRecv(priv->mcux_device.controllerHandle, + ep, NULL, 0); + if (status != kStatus_USB_Success) { + udc_submit_event(dev, UDC_EVT_ERROR, -EIO); + return false; + } + return true; + } + } + + return false; +} + +static int udc_mcux_handler_in(const struct device *dev, uint8_t ep, + uint8_t *mcux_buf, uint16_t mcux_len) +{ + int err; + struct net_buf *buf; + unsigned int key; + + buf = udc_buf_peek(dev, ep); + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + + if (udc_mcux_handler_zlt(dev, ep, buf, mcux_len)) { + return 0; + } + + buf = udc_buf_get(dev, ep); + + key = irq_lock(); + udc_ep_set_busy(dev, ep, false); + irq_unlock(key); + + if (buf == NULL) { + udc_submit_event(dev, UDC_EVT_ERROR, -ENOBUFS); + return -ENOBUFS; + } + if (ep == USB_CONTROL_EP_IN) { + err = udc_mcux_handler_ctrl_in(dev, buf, mcux_buf, mcux_len); + } else { + err = udc_mcux_handler_non_ctrl_in(dev, ep, buf, mcux_buf, mcux_len); + } + + return err; +} + +/* NXP MCUX controller driver notify transfers/status through this interface */ +usb_status_t USB_DeviceNotificationTrigger(void *handle, void *msg) +{ + usb_device_callback_message_struct_t *mcux_msg = msg; + uint8_t ep; + usb_device_notification_t mcux_notify; + struct udc_mcux_data *priv; + const struct device *dev; + usb_status_t mcux_status = kStatus_USB_Success; + int err = 0; + + if ((NULL == msg) || (NULL == handle)) { + return kStatus_USB_InvalidHandle; + } + + mcux_notify = (usb_device_notification_t)mcux_msg->code; + priv = (struct udc_mcux_data *)(PRV_DATA_HANDLE(handle)); + dev = priv->dev; + + switch (mcux_notify) { + case kUSB_DeviceNotifyBusReset: + struct udc_ep_config *cfg; + + udc_mcux_control(dev, kUSB_DeviceControlSetDefaultStatus, NULL); + cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_OUT); + if (cfg->stat.enabled) { + udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT); + } + cfg = udc_get_ep_cfg(dev, USB_CONTROL_EP_IN); + if (cfg->stat.enabled) { + udc_ep_disable_internal(dev, USB_CONTROL_EP_IN); + } + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, + USB_EP_TYPE_CONTROL, + USB_MCUX_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } + + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, + USB_EP_TYPE_CONTROL, + USB_MCUX_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } + udc_submit_event(dev, UDC_EVT_RESET, 0); + break; + case kUSB_DeviceNotifyError: + udc_submit_event(dev, UDC_EVT_ERROR, -EIO); + break; + case kUSB_DeviceNotifySuspend: + udc_set_suspended(dev, true); + udc_submit_event(dev, UDC_EVT_SUSPEND, 0); + break; + case kUSB_DeviceNotifyResume: + udc_set_suspended(dev, false); + udc_submit_event(dev, UDC_EVT_RESUME, 0); + break; + case kUSB_DeviceNotifyLPMSleep: + break; + case kUSB_DeviceNotifyDetach: + udc_submit_event(dev, UDC_EVT_VBUS_REMOVED, 0); + break; + case kUSB_DeviceNotifyAttach: + udc_submit_event(dev, UDC_EVT_VBUS_READY, 0); + break; + default: + ep = mcux_msg->code; + if (mcux_msg->isSetup) { + struct usb_setup_packet *setup = + (struct usb_setup_packet *)mcux_msg->buffer; + + err = udc_mcux_handler_setup(dev, setup); + } else if (USB_EP_DIR_IS_IN(ep)) { + err = udc_mcux_handler_in(dev, ep, mcux_msg->buffer, mcux_msg->length); + } else { + err = udc_mcux_handler_out(dev, ep, mcux_msg->buffer, mcux_msg->length); + } + + break; + } + + if (unlikely(err)) { + udc_submit_event(dev, UDC_EVT_ERROR, err); + mcux_status = kStatus_USB_Error; + } + return mcux_status; +} + +static void udc_mcux_isr(const struct device *dev) +{ + struct udc_mcux_data *priv = udc_get_private(dev); + + USB_DeviceLpcIp3511IsrFunction((void *)(&priv->mcux_device)); +} + +/* Return actual USB device speed */ +static enum udc_bus_speed udc_mcux_device_speed(const struct device *dev) +{ + int err; + uint8_t mcux_speed; + + err = udc_mcux_control(dev, kUSB_DeviceControlGetSpeed, &mcux_speed); + if (err) { + /* + * In the current version of all NXP USB device drivers, + * no error is returned if the parameter is correct. + */ + return UDC_BUS_SPEED_FS; + } + + switch (mcux_speed) { + case USB_SPEED_HIGH: + return UDC_BUS_SPEED_HS; + case USB_SPEED_LOW: + __ASSERT(false, "Low speed mode not supported"); + __fallthrough; + case USB_SPEED_FULL: + __fallthrough; + default: + return UDC_BUS_SPEED_FS; + } +} + +static int udc_mcux_ep_enqueue(const struct device *dev, + struct udc_ep_config *const cfg, + struct net_buf *const buf) +{ + udc_buf_put(cfg, buf); + if (cfg->stat.halted) { + LOG_DBG("ep 0x%02x halted", cfg->addr); + return 0; + } + + return udc_mcux_ep_try_feed(dev, cfg); +} + +static int udc_mcux_ep_dequeue(const struct device *dev, + struct udc_ep_config *const cfg) +{ + struct net_buf *buf; + unsigned int key; + + cfg->stat.halted = false; + buf = udc_buf_get_all(dev, cfg->addr); + if (buf) { + udc_submit_ep_event(dev, buf, -ECONNABORTED); + } + + key = irq_lock(); + udc_ep_set_busy(dev, cfg->addr, false); + irq_unlock(key); + + return 0; +} + +static int udc_mcux_ep_set_halt(const struct device *dev, + struct udc_ep_config *const cfg) +{ + return udc_mcux_control(dev, kUSB_DeviceControlEndpointStall, &cfg->addr); +} + +static int udc_mcux_ep_clear_halt(const struct device *dev, + struct udc_ep_config *const cfg) +{ + (void)udc_mcux_control(dev, kUSB_DeviceControlEndpointUnstall, &cfg->addr); + /* transfer is enqueued after stalled */ + return udc_mcux_ep_try_feed(dev, cfg); +} + +static int udc_mcux_ep_enable(const struct device *dev, + struct udc_ep_config *const cfg) +{ + usb_device_endpoint_init_struct_t ep_init; + + LOG_DBG("Enable ep 0x%02x", cfg->addr); + + ep_init.zlt = 0U; + ep_init.interval = cfg->interval; + ep_init.endpointAddress = cfg->addr; + ep_init.maxPacketSize = cfg->mps; + + switch (cfg->attributes & USB_EP_TRANSFER_TYPE_MASK) { + case USB_EP_TYPE_CONTROL: + ep_init.transferType = USB_ENDPOINT_CONTROL; + break; + case USB_EP_TYPE_BULK: + ep_init.transferType = USB_ENDPOINT_BULK; + break; + case USB_EP_TYPE_INTERRUPT: + ep_init.transferType = USB_ENDPOINT_INTERRUPT; + break; + case USB_EP_TYPE_ISO: + ep_init.transferType = USB_ENDPOINT_ISOCHRONOUS; + break; + default: + return -EINVAL; + } + + return udc_mcux_control(dev, kUSB_DeviceControlEndpointInit, &ep_init); +} + +static int udc_mcux_ep_disable(const struct device *dev, + struct udc_ep_config *const cfg) +{ + LOG_DBG("Disable ep 0x%02x", cfg->addr); + + return udc_mcux_control(dev, kUSB_DeviceControlEndpointDeinit, &cfg->addr); +} + +static int udc_mcux_host_wakeup(const struct device *dev) +{ + return -ENOTSUP; +} + +static int udc_mcux_set_address(const struct device *dev, const uint8_t addr) +{ + uint8_t temp_addr = addr; + + return udc_mcux_control(dev, kUSB_DeviceControlSetDeviceAddress, &temp_addr); +} + +static int udc_mcux_enable(const struct device *dev) +{ + return udc_mcux_control(dev, kUSB_DeviceControlRun, NULL); +} + +static int udc_mcux_disable(const struct device *dev) +{ + return udc_mcux_control(dev, kUSB_DeviceControlStop, NULL); +} + +static int udc_mcux_init(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + if (priv->controller_id == 0xFFu) { + return -ENOMEM; + } + +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED + if (config->phy_config != NULL) { + USB_EhciPhyInit(priv->controller_id, 0u, + (usb_phy_config_struct_t *)&config->phy_config); + } +#endif + + /* Init MCUX USB device driver. */ + status = mcux_if->deviceInit(priv->controller_id, + &priv->mcux_device, &(priv->mcux_device.controllerHandle)); + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + /* enable USB interrupt */ + config->irq_enable_func(dev); + + LOG_DBG("Initialized USB controller %x", (uint32_t)config->base); + + return 0; +} + +static int udc_mcux_shutdown(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + const usb_device_controller_interface_struct_t *mcux_if = config->mcux_if; + struct udc_mcux_data *priv = udc_get_private(dev); + usb_status_t status; + + /* Disable interrupt */ + config->irq_disable_func(dev); + + /* De-init MCUX USB device driver. */ + status = mcux_if->deviceDeinit(priv->mcux_device.controllerHandle); + if (status != kStatus_USB_Success) { + return -ENOMEM; + } + + return 0; +} + +static int udc_mcux_lock(const struct device *dev) +{ + return udc_lock_internal(dev, K_FOREVER); +} + +static int udc_mcux_unlock(const struct device *dev) +{ + return udc_unlock_internal(dev); +} + +static inline void udc_mcux_get_hal_driver_id(struct udc_mcux_data *priv, + const struct udc_mcux_config *config) +{ + /* + * MCUX USB controller drivers use an ID to tell the HAL drivers + * which controller is being used. This part of the code converts + * the base address to the ID value. + */ +#ifdef USB_BASE_ADDRS + uintptr_t ip3511_fs_base[] = USB_BASE_ADDRS; +#endif +#ifdef USBHSD_BASE_ADDRS + uintptr_t ip3511_hs_base[] = USBHSD_BASE_ADDRS; +#endif + + /* get the right controller id */ + priv->controller_id = 0xFFu; /* invalid value */ +#ifdef USB_BASE_ADDRS + for (uint8_t i = 0; i < ARRAY_SIZE(ip3511_fs_base); i++) { + if (ip3511_fs_base[i] == config->base) { + priv->controller_id = kUSB_ControllerLpcIp3511Fs0 + i; + break; + } + } +#endif + +#ifdef USBHSD_BASE_ADDRS + if (priv->controller_id == 0xFF) { + for (uint8_t i = 0; i < ARRAY_SIZE(ip3511_hs_base); i++) { + if (ip3511_hs_base[i] == config->base) { + priv->controller_id = kUSB_ControllerLpcIp3511Hs0 + i; + break; + } + } + } +#endif +} + +static int udc_mcux_driver_preinit(const struct device *dev) +{ + const struct udc_mcux_config *config = dev->config; + struct udc_data *data = dev->data; + struct udc_mcux_data *priv = data->priv; + int err; + + udc_mcux_get_hal_driver_id(priv, config); + if (priv->controller_id == 0xFFu) { + return -ENOMEM; + } + + k_mutex_init(&data->mutex); + + for (int i = 0; i < config->num_of_eps; i++) { + config->ep_cfg_out[i].caps.out = 1; + if (i == 0) { + config->ep_cfg_out[i].caps.control = 1; + config->ep_cfg_out[i].caps.mps = 64; + } else { + config->ep_cfg_out[i].caps.bulk = 1; + config->ep_cfg_out[i].caps.interrupt = 1; + config->ep_cfg_out[i].caps.iso = 1; + config->ep_cfg_out[i].caps.mps = 1024; + } + + config->ep_cfg_out[i].addr = USB_EP_DIR_OUT | i; + err = udc_register_ep(dev, &config->ep_cfg_out[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + for (int i = 0; i < config->num_of_eps; i++) { + config->ep_cfg_in[i].caps.in = 1; + if (i == 0) { + config->ep_cfg_in[i].caps.control = 1; + config->ep_cfg_in[i].caps.mps = 64; + } else { + config->ep_cfg_in[i].caps.bulk = 1; + config->ep_cfg_in[i].caps.interrupt = 1; + config->ep_cfg_in[i].caps.iso = 1; + config->ep_cfg_in[i].caps.mps = 1024; + } + + config->ep_cfg_in[i].addr = USB_EP_DIR_IN | i; + err = udc_register_ep(dev, &config->ep_cfg_in[i]); + if (err != 0) { + LOG_ERR("Failed to register endpoint"); + return err; + } + } + + /* Requires udc_mcux_host_wakeup() implementation */ + data->caps.rwup = false; + data->caps.mps0 = USB_MCUX_MPS0; + if ((priv->controller_id == kUSB_ControllerLpcIp3511Hs0) || + (priv->controller_id == kUSB_ControllerLpcIp3511Hs1)) { + data->caps.hs = true; + } + priv->dev = dev; + + pinctrl_apply_state(config->pincfg, PINCTRL_STATE_DEFAULT); + + return 0; +} + +static const struct udc_api udc_mcux_api = { + .device_speed = udc_mcux_device_speed, + .ep_enqueue = udc_mcux_ep_enqueue, + .ep_dequeue = udc_mcux_ep_dequeue, + .ep_set_halt = udc_mcux_ep_set_halt, + .ep_clear_halt = udc_mcux_ep_clear_halt, + .ep_try_config = NULL, + .ep_enable = udc_mcux_ep_enable, + .ep_disable = udc_mcux_ep_disable, + .host_wakeup = udc_mcux_host_wakeup, + .set_address = udc_mcux_set_address, + .enable = udc_mcux_enable, + .disable = udc_mcux_disable, + .init = udc_mcux_init, + .shutdown = udc_mcux_shutdown, + .lock = udc_mcux_lock, + .unlock = udc_mcux_unlock, +}; + +/* IP3511 device driver interface */ +static const usb_device_controller_interface_struct_t udc_mcux_if = { + USB_DeviceLpc3511IpInit, USB_DeviceLpc3511IpDeinit, USB_DeviceLpc3511IpSend, + USB_DeviceLpc3511IpRecv, USB_DeviceLpc3511IpCancel, USB_DeviceLpc3511IpControl +}; + +#ifdef CONFIG_DT_HAS_NXP_USBPHY_ENABLED +#define UDC_MCUX_PHY_DEFINE(n) \ +static usb_phy_config_struct_t phy_config_##n = { \ + .D_CAL = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_d_cal, 0), \ + .TXCAL45DP = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_cal_45_dp_ohms, 0), \ + .TXCAL45DM = DT_PROP_OR(DT_INST_PHANDLE(n, phy_handle), tx_cal_45_dm_ohms, 0), \ +} + +#define UDC_MCUX_PHY_DEFINE_OR(n) \ + COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), phy_handle), \ + (UDC_MCUX_PHY_DEFINE(n)), ()) + +#define UDC_MCUX_PHY_CFG_PTR_OR_NULL(n) \ + .phy_config = COND_CODE_1(DT_NODE_HAS_PROP(DT_DRV_INST(n), phy_handle), \ + (&phy_config_##n), (NULL)) +#else +#define UDC_MCUX_PHY_DEFINE_OR(n) +#define UDC_MCUX_PHY_CFG_PTR_OR_NULL(n) +#endif + +#define USB_MCUX_IP3511_DEVICE_DEFINE(n) \ + UDC_MCUX_PHY_DEFINE_OR(n); \ + \ + static void udc_irq_enable_func##n(const struct device *dev) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(n), \ + DT_INST_IRQ(n, priority), \ + udc_mcux_isr, \ + DEVICE_DT_INST_GET(n), 0); \ + \ + irq_enable(DT_INST_IRQN(n)); \ + } \ + \ + static void udc_irq_disable_func##n(const struct device *dev) \ + { \ + irq_disable(DT_INST_IRQN(n)); \ + } \ + \ + static struct udc_ep_config \ + ep_cfg_out##n[DT_INST_PROP(n, num_bidir_endpoints)]; \ + static struct udc_ep_config \ + ep_cfg_in##n[DT_INST_PROP(n, num_bidir_endpoints)]; \ + \ + PINCTRL_DT_INST_DEFINE(n); \ + \ + static struct udc_mcux_config priv_config_##n = { \ + .base = DT_INST_REG_ADDR(n), \ + .irq_enable_func = udc_irq_enable_func##n, \ + .irq_disable_func = udc_irq_disable_func##n, \ + .num_of_eps = DT_INST_PROP(n, num_bidir_endpoints), \ + .ep_cfg_in = ep_cfg_in##n, \ + .ep_cfg_out = ep_cfg_out##n, \ + .mcux_if = &udc_mcux_if, \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(n), \ + UDC_MCUX_PHY_CFG_PTR_OR_NULL(n), \ + }; \ + \ + static struct udc_mcux_data priv_data_##n = { \ + }; \ + \ + static struct udc_data udc_data_##n = { \ + .mutex = Z_MUTEX_INITIALIZER(udc_data_##n.mutex), \ + .priv = &priv_data_##n, \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, udc_mcux_driver_preinit, NULL, \ + &udc_data_##n, &priv_config_##n, \ + POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ + &udc_mcux_api); + +DT_INST_FOREACH_STATUS_OKAY(USB_MCUX_IP3511_DEVICE_DEFINE) diff --git a/drivers/usb/udc/udc_nrf.c b/drivers/usb/udc/udc_nrf.c index d4ecc130587c4..f02dfcdc308b8 100644 --- a/drivers/usb/udc/udc_nrf.c +++ b/drivers/usb/udc/udc_nrf.c @@ -470,14 +470,14 @@ static void udc_nrf_power_handler(nrfx_power_usb_evt_t pwr_evt) switch (pwr_evt) { case NRFX_POWER_USB_EVT_DETECTED: LOG_DBG("POWER event detected"); + udc_submit_event(udc_nrf_dev, UDC_EVT_VBUS_READY, 0); break; case NRFX_POWER_USB_EVT_READY: - LOG_INF("POWER event ready"); - udc_submit_event(udc_nrf_dev, UDC_EVT_VBUS_READY, 0); + LOG_DBG("POWER event ready"); nrf_usbd_common_start(true); break; case NRFX_POWER_USB_EVT_REMOVED: - LOG_INF("POWER event removed"); + LOG_DBG("POWER event removed"); udc_submit_event(udc_nrf_dev, UDC_EVT_VBUS_REMOVED, 0); break; default: @@ -631,9 +631,26 @@ static int udc_nrf_host_wakeup(const struct device *dev) static int udc_nrf_enable(const struct device *dev) { + unsigned int key; int ret; - nrf_usbd_common_enable(); + ret = nrf_usbd_common_init(usbd_event_handler); + if (ret != NRFX_SUCCESS) { + LOG_ERR("nRF USBD driver initialization failed"); + return -EIO; + } + + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, + USB_EP_TYPE_CONTROL, UDC_NRF_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } + + if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, + USB_EP_TYPE_CONTROL, UDC_NRF_EP0_SIZE, 0)) { + LOG_ERR("Failed to enable control endpoint"); + return -EIO; + } sys_notify_init_spinwait(&hfxo_cli.notify); ret = onoff_request(hfxo_mgr, &hfxo_cli); @@ -642,6 +659,11 @@ static int udc_nrf_enable(const struct device *dev) return ret; } + /* Disable interrupts until USBD is enabled */ + key = irq_lock(); + nrf_usbd_common_enable(); + irq_unlock(key); + return 0; } @@ -651,6 +673,18 @@ static int udc_nrf_disable(const struct device *dev) nrf_usbd_common_disable(); + if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) { + LOG_ERR("Failed to disable control endpoint"); + return -EIO; + } + + if (udc_ep_disable_internal(dev, USB_CONTROL_EP_IN)) { + LOG_ERR("Failed to disable control endpoint"); + return -EIO; + } + + nrf_usbd_common_uninit(); + ret = onoff_cancel_or_release(hfxo_mgr, &hfxo_cli); if (ret < 0) { LOG_ERR("Failed to stop HFXO %d", ret); @@ -663,7 +697,6 @@ static int udc_nrf_disable(const struct device *dev) static int udc_nrf_init(const struct device *dev) { const struct udc_nrf_config *cfg = dev->config; - int ret; hfxo_mgr = z_nrf_clock_control_get_onoff(cfg->clock); @@ -683,25 +716,7 @@ static int udc_nrf_init(const struct device *dev) (void)nrfx_power_init(&cfg->pwr); nrfx_power_usbevt_init(&cfg->evt); - ret = nrf_usbd_common_init(usbd_event_handler); - if (ret != NRFX_SUCCESS) { - LOG_ERR("nRF USBD driver initialization failed"); - return -EIO; - } - nrfx_power_usbevt_enable(); - if (udc_ep_enable_internal(dev, USB_CONTROL_EP_OUT, - USB_EP_TYPE_CONTROL, UDC_NRF_EP0_SIZE, 0)) { - LOG_ERR("Failed to enable control endpoint"); - return -EIO; - } - - if (udc_ep_enable_internal(dev, USB_CONTROL_EP_IN, - USB_EP_TYPE_CONTROL, UDC_NRF_EP0_SIZE, 0)) { - LOG_ERR("Failed to enable control endpoint"); - return -EIO; - } - LOG_INF("Initialized"); return 0; @@ -711,18 +726,7 @@ static int udc_nrf_shutdown(const struct device *dev) { LOG_INF("shutdown"); - if (udc_ep_disable_internal(dev, USB_CONTROL_EP_OUT)) { - LOG_ERR("Failed to disable control endpoint"); - return -EIO; - } - - if (udc_ep_disable_internal(dev, USB_CONTROL_EP_IN)) { - LOG_ERR("Failed to disable control endpoint"); - return -EIO; - } - nrfx_power_usbevt_disable(); - nrf_usbd_common_uninit(); nrfx_power_usbevt_uninit(); #ifdef CONFIG_HAS_HW_NRF_USBREG irq_disable(USBREGULATOR_IRQn); @@ -794,6 +798,7 @@ static int udc_nrf_driver_init(const struct device *dev) data->caps.rwup = true; data->caps.out_ack = true; data->caps.mps0 = UDC_NRF_MPS0; + data->caps.can_detect_vbus = true; return 0; } diff --git a/drivers/usb/udc/udc_stm32.c b/drivers/usb/udc/udc_stm32.c index 1e75fe49d7097..157902a121640 100644 --- a/drivers/usb/udc/udc_stm32.c +++ b/drivers/usb/udc/udc_stm32.c @@ -353,6 +353,16 @@ void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum) } } +#if DT_INST_NODE_HAS_PROP(0, disconnect_gpios) +void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) +{ + struct gpio_dt_spec usb_disconnect = GPIO_DT_SPEC_INST_GET(0, disconnect_gpios); + + gpio_pin_configure_dt(&usb_disconnect, + state ? GPIO_OUTPUT_ACTIVE : GPIO_OUTPUT_INACTIVE); +} +#endif + static void udc_stm32_irq(const struct device *dev) { const struct udc_stm32_data *priv = udc_get_private(dev); @@ -974,33 +984,31 @@ static int priv_clock_enable(void) #endif /* RCC_CFGR_OTGFSPRE / RCC_CFGR_USBPRE */ -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) +#if USB_OTG_HS_ULPI_PHY +#if defined(CONFIG_SOC_SERIES_STM32H7X) + LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); +#else LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_OTGHSULPI); - LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC); -#elif defined(CONFIG_SOC_SERIES_STM32H7X) -#if !USB_OTG_HS_ULPI_PHY - /* Disable ULPI interface (for external high-speed PHY) clock in sleep - * mode. +#endif +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) /* USB_OTG_HS_ULPI_PHY */ + /* Disable ULPI interface (for external high-speed PHY) clock in sleep/low-power mode. It is + * disabled by default in run power mode, no need to disable it. */ +#if defined(CONFIG_SOC_SERIES_STM32H7X) LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB1OTGHSULPI); +#else + LL_AHB1_GRP1_DisableClockLowPower(LL_AHB1_GRP1_PERIPH_OTGHSULPI); +#endif /* defined(CONFIG_SOC_SERIES_STM32H7X) */ + +#if USB_OTG_HS_EMB_PHY + LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_OTGPHYC); #endif -#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otgfs) +#elif defined(CONFIG_SOC_SERIES_STM32H7X) && DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otgfs) /* The USB2 controller only works in FS mode, but the ULPI clock needs * to be disabled in sleep mode for it to work. */ LL_AHB1_GRP1_DisableClockSleep(LL_AHB1_GRP1_PERIPH_USB2OTGHSULPI); -#endif -#else /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) */ -#if !USB_OTG_HS_ULPI_PHY - /* Disable ULPI interface (for external high-speed PHY) clock in low - * power mode. It is disabled by default in run power mode, no need to - * disable it. - */ - LL_AHB1_GRP1_DisableClockLowPower(LL_AHB1_GRP1_PERIPH_OTGHSULPI); #endif /* USB_OTG_HS_ULPI_PHY */ -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_usbphyc) */ -#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_stm32_otghs) */ return 0; } diff --git a/drivers/video/CMakeLists.txt b/drivers/video/CMakeLists.txt index 0b279de38134f..2e52d1f66ea88 100644 --- a/drivers/video/CMakeLists.txt +++ b/drivers/video/CMakeLists.txt @@ -5,8 +5,11 @@ zephyr_library() zephyr_library_sources(video_common.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_MCUX_CSI video_mcux_csi.c) +zephyr_library_sources_ifdef(CONFIG_VIDEO_MCUX_MIPI_CSI2RX video_mcux_mipi_csi2rx.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_SW_GENERATOR video_sw_generator.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_MT9M114 mt9m114.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_OV7725 ov7725.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_OV2640 ov2640.c) zephyr_library_sources_ifdef(CONFIG_VIDEO_STM32_DCMI video_stm32_dcmi.c) +zephyr_library_sources_ifdef(CONFIG_VIDEO_OV5640 ov5640.c) +zephyr_library_sources_ifdef(CONFIG_VIDEO_OV7670 ov7670.c) diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 8a489cc4be6bd..d6a6bd3ccce66 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -33,6 +33,8 @@ config VIDEO_BUFFER_POOL_ALIGN source "drivers/video/Kconfig.mcux_csi" +source "drivers/video/Kconfig.mcux_mipi_csi2rx" + source "drivers/video/Kconfig.sw_generator" source "drivers/video/Kconfig.mt9m114" @@ -43,4 +45,8 @@ source "drivers/video/Kconfig.ov2640" source "drivers/video/Kconfig.stm32_dcmi" +source "drivers/video/Kconfig.ov5640" + +source "drivers/video/Kconfig.ov7670" + endif # VIDEO diff --git a/drivers/video/Kconfig.mcux_csi b/drivers/video/Kconfig.mcux_csi index 18adaab4c50e3..0f1263f041c31 100644 --- a/drivers/video/Kconfig.mcux_csi +++ b/drivers/video/Kconfig.mcux_csi @@ -6,7 +6,6 @@ config VIDEO_MCUX_CSI bool "NXP MCUX CMOS Sensor Interface (CSI) driver" default y - depends on HAS_MCUX_CSI depends on DT_HAS_NXP_IMX_CSI_ENABLED config VIDEO_MCUX_CSI_INIT_PRIORITY diff --git a/drivers/video/Kconfig.mcux_mipi_csi2rx b/drivers/video/Kconfig.mcux_mipi_csi2rx new file mode 100644 index 0000000000000..f9bf2f19f1efe --- /dev/null +++ b/drivers/video/Kconfig.mcux_mipi_csi2rx @@ -0,0 +1,10 @@ +# NXP MIPI CSI-2 Rx driver configuration option + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config VIDEO_MCUX_MIPI_CSI2RX + bool "NXP MIPI CSI-2 Rx driver" + default y + depends on DT_HAS_NXP_MIPI_CSI2RX_ENABLED + select VIDEO_MCUX_CSI diff --git a/drivers/video/Kconfig.ov5640 b/drivers/video/Kconfig.ov5640 new file mode 100644 index 0000000000000..950079dd35507 --- /dev/null +++ b/drivers/video/Kconfig.ov5640 @@ -0,0 +1,12 @@ +# OV5640 + +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config VIDEO_OV5640 + bool "OV5640 CMOS digital image sensor" + select I2C + depends on DT_HAS_OVTI_OV5640_ENABLED + default y + help + Enable driver for OV5640 CMOS digital image sensor device diff --git a/drivers/video/Kconfig.ov7670 b/drivers/video/Kconfig.ov7670 new file mode 100644 index 0000000000000..9a2a1d70f3d90 --- /dev/null +++ b/drivers/video/Kconfig.ov7670 @@ -0,0 +1,10 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +config VIDEO_OV7670 + bool "OV7670 CMOS digital image sensor" + select I2C + depends on DT_HAS_OVTI_OV7670_ENABLED + default y + help + Enable driver for OV7670 CMOS digital image sensor device. diff --git a/drivers/video/ov5640.c b/drivers/video/ov5640.c new file mode 100644 index 0000000000000..7c76c7b88c93c --- /dev/null +++ b/drivers/video/ov5640.c @@ -0,0 +1,698 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ovti_ov5640 + +#include +#include +#include +#include +#include + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(ov5640); + +#include + +#define CHIP_ID_REG 0x300a +#define CHIP_ID_VAL 0x5640 + +#define SYS_CTRL0_REG 0x3008 +#define SYS_CTRL0_SW_PWDN 0x42 +#define SYS_CTRL0_SW_PWUP 0x02 +#define SYS_CTRL0_SW_RST 0x82 + +#define SYS_RESET00_REG 0x3000 +#define SYS_RESET02_REG 0x3002 +#define SYS_CLK_ENABLE00_REG 0x3004 +#define SYS_CLK_ENABLE02_REG 0x3006 +#define IO_MIPI_CTRL00_REG 0x300e +#define SYSTEM_CONTROL1_REG 0x302e +#define SCCB_SYS_CTRL1_REG 0x3103 +#define TIMING_TC_REG20_REG 0x3820 +#define TIMING_TC_REG21_REG 0x3821 +#define HZ5060_CTRL01_REG 0x3c01 +#define ISP_CTRL01_REG 0x5001 + +#define SC_PLL_CTRL0_REG 0x3034 +#define SC_PLL_CTRL1_REG 0x3035 +#define SC_PLL_CTRL2_REG 0x3036 +#define SC_PLL_CTRL3_REG 0x3037 +#define SYS_ROOT_DIV_REG 0x3108 +#define PCLK_PERIOD_REG 0x4837 + +#define AEC_CTRL00_REG 0x3a00 +#define AEC_CTRL0F_REG 0x3a0f +#define AEC_CTRL10_REG 0x3a10 +#define AEC_CTRL11_REG 0x3a11 +#define AEC_CTRL1B_REG 0x3a1b +#define AEC_CTRL1E_REG 0x3a1e +#define AEC_CTRL1F_REG 0x3a1f + +#define BLC_CTRL01_REG 0x4001 +#define BLC_CTRL04_REG 0x4004 +#define BLC_CTRL05_REG 0x4005 + +#define AWB_CTRL00_REG 0x5180 +#define AWB_CTRL01_REG 0x5181 +#define AWB_CTRL02_REG 0x5182 +#define AWB_CTRL03_REG 0x5183 +#define AWB_CTRL04_REG 0x5184 +#define AWB_CTRL05_REG 0x5185 +#define AWB_CTRL17_REG 0x5191 +#define AWB_CTRL18_REG 0x5192 +#define AWB_CTRL19_REG 0x5193 +#define AWB_CTRL20_REG 0x5194 +#define AWB_CTRL21_REG 0x5195 +#define AWB_CTRL22_REG 0x5196 +#define AWB_CTRL23_REG 0x5197 +#define AWB_CTRL30_REG 0x519e + +#define SDE_CTRL0_REG 0x5580 +#define SDE_CTRL3_REG 0x5583 +#define SDE_CTRL4_REG 0x5584 +#define SDE_CTRL9_REG 0x5589 +#define SDE_CTRL10_REG 0x558a +#define SDE_CTRL11_REG 0x558b + +#define DEFAULT_MIPI_CHANNEL 0 + +#define OV5640_RESOLUTION_PARAM_NUM 24 + +struct ov5640_config { + struct i2c_dt_spec i2c; + struct gpio_dt_spec reset_gpio; + struct gpio_dt_spec powerdown_gpio; +}; + +struct ov5640_data { + struct video_format fmt; +}; + +struct ov5640_reg { + uint16_t addr; + uint8_t val; +}; + +struct ov5640_mipi_clock_config { + uint8_t pllCtrl1; + uint8_t pllCtrl2; +}; + +struct ov5640_resolution_config { + uint16_t width; + uint16_t height; + const struct ov5640_reg *res_params; + const struct ov5640_mipi_clock_config mipi_pclk; +}; + +static const struct ov5640_reg ov5640InitParams[] = { + /* Power down */ + {SYS_CTRL0_REG, SYS_CTRL0_SW_PWDN}, + + /* System setting. */ + {SCCB_SYS_CTRL1_REG, 0x13}, + {SCCB_SYS_CTRL1_REG, 0x03}, + {SYS_RESET00_REG, 0x00}, + {SYS_CLK_ENABLE00_REG, 0xff}, + {SYS_RESET02_REG, 0x1c}, + {SYS_CLK_ENABLE02_REG, 0xc3}, + {SYSTEM_CONTROL1_REG, 0x08}, + {0x3618, 0x00}, + {0x3612, 0x29}, + {0x3708, 0x64}, + {0x3709, 0x52}, + {0x370c, 0x03}, + {TIMING_TC_REG20_REG, 0x41}, + {TIMING_TC_REG21_REG, 0x07}, + {0x3630, 0x36}, + {0x3631, 0x0e}, + {0x3632, 0xe2}, + {0x3633, 0x12}, + {0x3621, 0xe0}, + {0x3704, 0xa0}, + {0x3703, 0x5a}, + {0x3715, 0x78}, + {0x3717, 0x01}, + {0x370b, 0x60}, + {0x3705, 0x1a}, + {0x3905, 0x02}, + {0x3906, 0x10}, + {0x3901, 0x0a}, + {0x3731, 0x12}, + {0x3600, 0x08}, + {0x3601, 0x33}, + {0x302d, 0x60}, + {0x3620, 0x52}, + {0x371b, 0x20}, + {0x471c, 0x50}, + {0x3a13, 0x43}, + {0x3a18, 0x00}, + {0x3a19, 0x7c}, + {0x3635, 0x13}, + {0x3636, 0x03}, + {0x3634, 0x40}, + {0x3622, 0x01}, + {HZ5060_CTRL01_REG, 0x00}, + {AEC_CTRL00_REG, 0x58}, + {BLC_CTRL01_REG, 0x02}, + {BLC_CTRL04_REG, 0x02}, + {BLC_CTRL05_REG, 0x1a}, + {ISP_CTRL01_REG, 0xa3}, + + /* AEC */ + {AEC_CTRL0F_REG, 0x30}, + {AEC_CTRL10_REG, 0x28}, + {AEC_CTRL1B_REG, 0x30}, + {AEC_CTRL1E_REG, 0x26}, + {AEC_CTRL11_REG, 0x60}, + {AEC_CTRL1F_REG, 0x14}, + + /* AWB */ + {AWB_CTRL00_REG, 0xff}, + {AWB_CTRL01_REG, 0xf2}, + {AWB_CTRL02_REG, 0x00}, + {AWB_CTRL03_REG, 0x14}, + {AWB_CTRL04_REG, 0x25}, + {AWB_CTRL05_REG, 0x24}, + {0x5186, 0x09}, + {0x5187, 0x09}, + {0x5188, 0x09}, + {0x5189, 0x88}, + {0x518a, 0x54}, + {0x518b, 0xee}, + {0x518c, 0xb2}, + {0x518d, 0x50}, + {0x518e, 0x34}, + {0x518f, 0x6b}, + {0x5190, 0x46}, + {AWB_CTRL17_REG, 0xf8}, + {AWB_CTRL18_REG, 0x04}, + {AWB_CTRL19_REG, 0x70}, + {AWB_CTRL20_REG, 0xf0}, + {AWB_CTRL21_REG, 0xf0}, + {AWB_CTRL22_REG, 0x03}, + {AWB_CTRL23_REG, 0x01}, + {0x5198, 0x04}, + {0x5199, 0x6c}, + {0x519a, 0x04}, + {0x519b, 0x00}, + {0x519c, 0x09}, + {0x519d, 0x2b}, + {AWB_CTRL30_REG, 0x38}, + + /* Color Matrix */ + {0x5381, 0x1e}, + {0x5382, 0x5b}, + {0x5383, 0x08}, + {0x5384, 0x0a}, + {0x5385, 0x7e}, + {0x5386, 0x88}, + {0x5387, 0x7c}, + {0x5388, 0x6c}, + {0x5389, 0x10}, + {0x538a, 0x01}, + {0x538b, 0x98}, + + /* Sharp */ + {0x5300, 0x08}, + {0x5301, 0x30}, + {0x5302, 0x10}, + {0x5303, 0x00}, + {0x5304, 0x08}, + {0x5305, 0x30}, + {0x5306, 0x08}, + {0x5307, 0x16}, + {0x5309, 0x08}, + {0x530a, 0x30}, + {0x530b, 0x04}, + {0x530c, 0x06}, + + /* Gamma */ + {0x5480, 0x01}, + {0x5481, 0x08}, + {0x5482, 0x14}, + {0x5483, 0x28}, + {0x5484, 0x51}, + {0x5485, 0x65}, + {0x5486, 0x71}, + {0x5487, 0x7d}, + {0x5488, 0x87}, + {0x5489, 0x91}, + {0x548a, 0x9a}, + {0x548b, 0xaa}, + {0x548c, 0xb8}, + {0x548d, 0xcd}, + {0x548e, 0xdd}, + {0x548f, 0xea}, + {0x5490, 0x1d}, + + /* UV adjust. */ + {SDE_CTRL0_REG, 0x02}, + {SDE_CTRL3_REG, 0x40}, + {SDE_CTRL4_REG, 0x10}, + {SDE_CTRL9_REG, 0x10}, + {SDE_CTRL10_REG, 0x00}, + {SDE_CTRL11_REG, 0xf8}, + + /* Lens correction. */ + {0x5800, 0x23}, + {0x5801, 0x14}, + {0x5802, 0x0f}, + {0x5803, 0x0f}, + {0x5804, 0x12}, + {0x5805, 0x26}, + {0x5806, 0x0c}, + {0x5807, 0x08}, + {0x5808, 0x05}, + {0x5809, 0x05}, + {0x580a, 0x08}, + {0x580b, 0x0d}, + {0x580c, 0x08}, + {0x580d, 0x03}, + {0x580e, 0x00}, + {0x580f, 0x00}, + {0x5810, 0x03}, + {0x5811, 0x09}, + {0x5812, 0x07}, + {0x5813, 0x03}, + {0x5814, 0x00}, + {0x5815, 0x01}, + {0x5816, 0x03}, + {0x5817, 0x08}, + {0x5818, 0x0d}, + {0x5819, 0x08}, + {0x581a, 0x05}, + {0x581b, 0x06}, + {0x581c, 0x08}, + {0x581d, 0x0e}, + {0x581e, 0x29}, + {0x581f, 0x17}, + {0x5820, 0x11}, + {0x5821, 0x11}, + {0x5822, 0x15}, + {0x5823, 0x28}, + {0x5824, 0x46}, + {0x5825, 0x26}, + {0x5826, 0x08}, + {0x5827, 0x26}, + {0x5828, 0x64}, + {0x5829, 0x26}, + {0x582a, 0x24}, + {0x582b, 0x22}, + {0x582c, 0x24}, + {0x582d, 0x24}, + {0x582e, 0x06}, + {0x582f, 0x22}, + {0x5830, 0x40}, + {0x5831, 0x42}, + {0x5832, 0x24}, + {0x5833, 0x26}, + {0x5834, 0x24}, + {0x5835, 0x22}, + {0x5836, 0x22}, + {0x5837, 0x26}, + {0x5838, 0x44}, + {0x5839, 0x24}, + {0x583a, 0x26}, + {0x583b, 0x28}, + {0x583c, 0x42}, + {0x583d, 0xce}, + {0x5000, 0xa7}, +}; + +static const struct ov5640_reg ov5640_low_res_params[] = { + {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0x04}, {0x3804, 0x0a}, + {0x3805, 0x3f}, {0x3806, 0x07}, {0x3807, 0x9b}, {0x3808, 0x02}, {0x3809, 0x80}, + {0x380a, 0x01}, {0x380b, 0xe0}, {0x380c, 0x07}, {0x380d, 0x68}, {0x380e, 0x03}, + {0x380f, 0xd8}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x06}, + {0x3814, 0x31}, {0x3815, 0x31}, {0x3824, 0x02}, {0x460c, 0x22}}; + +static const struct ov5640_reg ov5640_720p_res_params[] = { + {0x3800, 0x00}, {0x3801, 0x00}, {0x3802, 0x00}, {0x3803, 0xfa}, {0x3804, 0x0a}, + {0x3805, 0x3f}, {0x3806, 0x06}, {0x3807, 0xa9}, {0x3808, 0x05}, {0x3809, 0x00}, + {0x380a, 0x02}, {0x380b, 0xd0}, {0x380c, 0x07}, {0x380d, 0x64}, {0x380e, 0x02}, + {0x380f, 0xe4}, {0x3810, 0x00}, {0x3811, 0x10}, {0x3812, 0x00}, {0x3813, 0x04}, + {0x3814, 0x31}, {0x3815, 0x31}, {0x3824, 0x04}, {0x460c, 0x20}}; + +static const struct ov5640_resolution_config resolutionParams[] = { + {.width = 640, + .height = 480, + .res_params = ov5640_low_res_params, + .mipi_pclk = { + .pllCtrl1 = 0x14, + .pllCtrl2 = 0x38, + }}, + {.width = 1280, + .height = 720, + .res_params = ov5640_720p_res_params, + .mipi_pclk = { + .pllCtrl1 = 0x21, + .pllCtrl2 = 0x54, + }}, +}; + +#define OV5640_VIDEO_FORMAT_CAP(width, height, format) \ + { \ + .pixelformat = (format), .width_min = (width), .width_max = (width), \ + .height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \ + } + +static const struct video_format_cap fmts[] = { + OV5640_VIDEO_FORMAT_CAP(1280, 720, VIDEO_PIX_FMT_RGB565), + OV5640_VIDEO_FORMAT_CAP(1280, 720, VIDEO_PIX_FMT_YUYV), + OV5640_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_RGB565), + OV5640_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_YUYV), + {0}}; + +static int ov5640_read_reg(const struct i2c_dt_spec *spec, const uint16_t addr, void *val, + const uint8_t val_size) +{ + int ret; + struct i2c_msg msg[2]; + uint8_t addr_buf[2]; + + if (val_size > 4) { + return -ENOTSUP; + } + + addr_buf[1] = addr & 0xFF; + addr_buf[0] = addr >> 8; + msg[0].buf = addr_buf; + msg[0].len = 2U; + msg[0].flags = I2C_MSG_WRITE; + + msg[1].buf = (uint8_t *)val; + msg[1].len = val_size; + msg[1].flags = I2C_MSG_READ | I2C_MSG_STOP | I2C_MSG_RESTART; + + ret = i2c_transfer_dt(spec, msg, 2); + if (ret) { + return ret; + } + + switch (val_size) { + case 4: + *(uint32_t *)val = sys_be32_to_cpu(*(uint32_t *)val); + break; + case 2: + *(uint16_t *)val = sys_be16_to_cpu(*(uint16_t *)val); + break; + case 1: + break; + default: + return -ENOTSUP; + } + + return 0; +} + +static int ov5640_write_reg(const struct i2c_dt_spec *spec, const uint16_t addr, const uint8_t val) +{ + uint8_t addr_buf[2]; + struct i2c_msg msg[2]; + + addr_buf[1] = addr & 0xFF; + addr_buf[0] = addr >> 8; + msg[0].buf = addr_buf; + msg[0].len = 2U; + msg[0].flags = I2C_MSG_WRITE; + + msg[1].buf = (uint8_t *)&val; + msg[1].len = 1; + msg[1].flags = I2C_MSG_WRITE | I2C_MSG_STOP; + + return i2c_transfer_dt(spec, msg, 2); +} + +static int ov5640_modify_reg(const struct i2c_dt_spec *spec, const uint16_t addr, + const uint8_t mask, const uint8_t val) +{ + uint8_t regVal = 0; + int ret = ov5640_read_reg(spec, addr, ®Val, sizeof(regVal)); + + if (ret) { + return ret; + } + + return ov5640_write_reg(spec, addr, (regVal & ~mask) | (val & mask)); +} + +static int ov5640_write_multi_regs(const struct i2c_dt_spec *spec, const struct ov5640_reg *regs, + const uint32_t num_regs) +{ + int ret; + + for (int i = 0; i < num_regs; i++) { + ret = ov5640_write_reg(spec, regs[i].addr, regs[i].val); + if (ret) { + return ret; + } + } + + return 0; +} + +static int ov5640_set_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + struct ov5640_data *drv_data = dev->data; + const struct ov5640_config *cfg = dev->config; + int ret; + int i; + + for (i = 0; i < ARRAY_SIZE(fmts); ++i) { + if (fmt->pixelformat == fmts[i].pixelformat && fmt->width >= fmts[i].width_min && + fmt->width <= fmts[i].width_max && fmt->height >= fmts[i].height_min && + fmt->height <= fmts[i].height_max) { + break; + } + } + + if (i == ARRAY_SIZE(fmts)) { + LOG_ERR("Unsupported pixel format or resolution"); + return -ENOTSUP; + } + + if (!memcmp(&drv_data->fmt, fmt, sizeof(drv_data->fmt))) { + return 0; + } + + drv_data->fmt = *fmt; + + /* Set resolution parameters */ + for (i = 0; i < ARRAY_SIZE(resolutionParams); i++) { + if (fmt->width == resolutionParams[i].width && + fmt->height == resolutionParams[i].height) { + ret = ov5640_write_multi_regs(&cfg->i2c, resolutionParams[i].res_params, + OV5640_RESOLUTION_PARAM_NUM); + if (ret) { + LOG_ERR("Unable to set resolution parameters"); + return ret; + } + break; + } + } + + /* Set pixel format, default to VIDEO_PIX_FMT_RGB565 */ + struct ov5640_reg fmt_params[2] = { + {0x4300, 0x6f}, + {0x501f, 0x01}, + }; + + if (fmt->pixelformat == VIDEO_PIX_FMT_YUYV) { + fmt_params[0].val = 0x3f; + fmt_params[1].val = 0x00; + } + + ret = ov5640_write_multi_regs(&cfg->i2c, fmt_params, ARRAY_SIZE(fmt_params)); + if (ret) { + LOG_ERR("Unable to set pixel format"); + return ret; + } + + /* Configure MIPI pixel clock */ + ret |= ov5640_modify_reg(&cfg->i2c, SC_PLL_CTRL0_REG, 0x0f, 0x08); + ret |= ov5640_modify_reg(&cfg->i2c, SC_PLL_CTRL1_REG, 0xff, + resolutionParams[i].mipi_pclk.pllCtrl1); + ret |= ov5640_modify_reg(&cfg->i2c, SC_PLL_CTRL2_REG, 0xff, + resolutionParams[i].mipi_pclk.pllCtrl2); + ret |= ov5640_modify_reg(&cfg->i2c, SC_PLL_CTRL3_REG, 0x1f, 0x13); + ret |= ov5640_modify_reg(&cfg->i2c, SYS_ROOT_DIV_REG, 0x3f, 0x01); + ret |= ov5640_write_reg(&cfg->i2c, PCLK_PERIOD_REG, 0x0a); + if (ret) { + LOG_ERR("Unable to configure MIPI pixel clock"); + return ret; + } + + return 0; +} + +static int ov5640_get_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + struct ov5640_data *drv_data = dev->data; + + *fmt = drv_data->fmt; + + return 0; +} + +static int ov5640_get_caps(const struct device *dev, enum video_endpoint_id ep, + struct video_caps *caps) +{ + caps->format_caps = fmts; + return 0; +} + +static int ov5640_stream_start(const struct device *dev) +{ + const struct ov5640_config *cfg = dev->config; + /* Power up MIPI PHY HS Tx & LP Rx in 2 data lanes mode */ + int ret = ov5640_write_reg(&cfg->i2c, IO_MIPI_CTRL00_REG, 0x45); + + if (ret) { + LOG_ERR("Unable to power up MIPI PHY"); + return ret; + } + return ov5640_write_reg(&cfg->i2c, SYS_CTRL0_REG, SYS_CTRL0_SW_PWUP); +} + +static int ov5640_stream_stop(const struct device *dev) +{ + const struct ov5640_config *cfg = dev->config; + /* Power down MIPI PHY HS Tx & LP Rx */ + int ret = ov5640_write_reg(&cfg->i2c, IO_MIPI_CTRL00_REG, 0x40); + + if (ret) { + LOG_ERR("Unable to power down MIPI PHY"); + return ret; + } + return ov5640_write_reg(&cfg->i2c, SYS_CTRL0_REG, SYS_CTRL0_SW_PWDN); +} + +static const struct video_driver_api ov5640_driver_api = { + .set_format = ov5640_set_fmt, + .get_format = ov5640_get_fmt, + .get_caps = ov5640_get_caps, + .stream_start = ov5640_stream_start, + .stream_stop = ov5640_stream_stop, +}; + +static int ov5640_init(const struct device *dev) +{ + const struct ov5640_config *cfg = dev->config; + struct video_format fmt; + uint16_t chip_id; + int ret; + + if (!device_is_ready(cfg->i2c.bus)) { + LOG_ERR("Bus device is not ready"); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&cfg->reset_gpio)) { + LOG_ERR("%s: device %s is not ready", dev->name, cfg->reset_gpio.port->name); + return -ENODEV; + } + + if (!gpio_is_ready_dt(&cfg->powerdown_gpio)) { + LOG_ERR("%s: device %s is not ready", dev->name, cfg->powerdown_gpio.port->name); + return -ENODEV; + } + + /* Power up sequence */ + if (cfg->powerdown_gpio.port != NULL) { + ret = gpio_pin_configure_dt(&cfg->powerdown_gpio, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } + + if (cfg->reset_gpio.port != NULL) { + ret = gpio_pin_configure_dt(&cfg->reset_gpio, GPIO_OUTPUT_ACTIVE); + if (ret) { + return ret; + } + } + + k_sleep(K_MSEC(5)); + + if (cfg->powerdown_gpio.port != NULL) { + gpio_pin_set_dt(&cfg->powerdown_gpio, 0); + } + + k_sleep(K_MSEC(1)); + + if (cfg->reset_gpio.port != NULL) { + gpio_pin_set_dt(&cfg->reset_gpio, 0); + } + + k_sleep(K_MSEC(20)); + + /* Software reset */ + ret = ov5640_write_reg(&cfg->i2c, SYS_CTRL0_REG, SYS_CTRL0_SW_RST); + if (ret) { + LOG_ERR("Unable to perform software reset"); + return -EIO; + } + + k_sleep(K_MSEC(5)); + + /* Initialize register values */ + ret = ov5640_write_multi_regs(&cfg->i2c, ov5640InitParams, ARRAY_SIZE(ov5640InitParams)); + if (ret) { + LOG_ERR("Unable to initialize the sensor"); + return -EIO; + } + + /* Set virtual channel */ + ret = ov5640_modify_reg(&cfg->i2c, 0x4814, 3U << 6, (uint8_t)(DEFAULT_MIPI_CHANNEL) << 6); + if (ret) { + LOG_ERR("Unable to set virtual channel"); + return -EIO; + } + + /* Check sensor chip id */ + ret = ov5640_read_reg(&cfg->i2c, CHIP_ID_REG, &chip_id, sizeof(chip_id)); + if (ret) { + LOG_ERR("Unable to read sensor chip ID, ret = %d", ret); + return -ENODEV; + } + + if (chip_id != CHIP_ID_VAL) { + LOG_ERR("Wrong chip ID: %04x (expected %04x)", chip_id, CHIP_ID_VAL); + return -ENODEV; + } + + /* Set default format to 720p RGB565 */ + fmt.pixelformat = VIDEO_PIX_FMT_RGB565; + fmt.width = 1280; + fmt.height = 720; + fmt.pitch = fmt.width * 2; + ret = ov5640_set_fmt(dev, VIDEO_EP_OUT, &fmt); + if (ret) { + LOG_ERR("Unable to configure default format"); + return -EIO; + } + + return 0; +} + +#define OV5640_INIT(n) \ + static struct ov5640_data ov5640_data_##n; \ + \ + static const struct ov5640_config ov5640_cfg_##n = { \ + .i2c = I2C_DT_SPEC_INST_GET(n), \ + .reset_gpio = GPIO_DT_SPEC_INST_GET_OR(n, reset_gpios, {0}), \ + .powerdown_gpio = GPIO_DT_SPEC_INST_GET_OR(n, powerdown_gpios, {0}), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &ov5640_init, NULL, &ov5640_data_##n, &ov5640_cfg_##n, \ + POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &ov5640_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(OV5640_INIT) diff --git a/drivers/video/ov7670.c b/drivers/video/ov7670.c new file mode 100644 index 0000000000000..96cb3f860db1f --- /dev/null +++ b/drivers/video/ov7670.c @@ -0,0 +1,488 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT ovti_ov7670 + +#include +#include +#include + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(ov7670); + +/* Initialization register structure */ +struct ov7670_reg { + uint8_t reg; + uint8_t cmd; +}; + +struct ov7670_config { + struct i2c_dt_spec bus; +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + struct gpio_dt_spec reset; +#endif +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(pwdn_gpios) + struct gpio_dt_spec pwdn; +#endif +}; + +struct ov7670_data { + struct video_format fmt; +}; + +/* OV7670 registers */ +#define OV7670_PID 0x0A +#define OV7670_COM7 0x12 +#define OV7670_MVFP 0x1E +#define OV7670_COM10 0x15 +#define OV7670_COM12 0x3C +#define OV7670_BRIGHT 0x55 +#define OV7670_CLKRC 0x11 +#define OV7670_SCALING_PCLK_DIV 0x73 +#define OV7670_COM14 0x3E +#define OV7670_DBLV 0x6B +#define OV7670_SCALING_XSC 0x70 +#define OV7670_SCALING_YSC 0x71 +#define OV7670_COM2 0x09 +#define OV7670_SCALING_PCLK_DELAY 0xA2 +#define OV7670_BD50MAX 0xA5 +#define OV7670_BD60MAX 0xAB +#define OV7670_HAECC7 0xAA +#define OV7670_COM3 0x0C +#define OV7670_COM4 0x0D +#define OV7670_COM6 0x0F +#define OV7670_COM11 0x3B +#define OV7670_EDGE 0x3F +#define OV7670_DNSTH 0x4C +#define OV7670_DM_LNL 0x92 +#define OV7670_DM_LNH 0x93 +#define OV7670_COM15 0x40 +#define OV7670_TSLB 0x3A +#define OV7670_COM13 0x3D +#define OV7670_MANU 0x67 +#define OV7670_MANV 0x68 +#define OV7670_HSTART 0x17 +#define OV7670_HSTOP 0x18 +#define OV7670_VSTRT 0x19 +#define OV7670_VSTOP 0x1A +#define OV7670_HREF 0x32 +#define OV7670_VREF 0x03 +#define OV7670_SCALING_DCWCTR 0x72 +#define OV7670_GAIN 0x00 +#define OV7670_AECHH 0x07 +#define OV7670_AECH 0x10 +#define OV7670_COM8 0x13 +#define OV7670_COM9 0x14 +#define OV7670_AEW 0x24 +#define OV7670_AEB 0x25 +#define OV7670_VPT 0x26 +#define OV7670_AWBC1 0x43 +#define OV7670_AWBC2 0x44 +#define OV7670_AWBC3 0x45 +#define OV7670_AWBC4 0x46 +#define OV7670_AWBC5 0x47 +#define OV7670_AWBC6 0x48 +#define OV7670_MTX1 0x4F +#define OV7670_MTX2 0x50 +#define OV7670_MTX3 0x51 +#define OV7670_MTX4 0x52 +#define OV7670_MTX5 0x53 +#define OV7670_MTX6 0x54 +#define OV7670_LCC1 0x62 +#define OV7670_LCC2 0x63 +#define OV7670_LCC3 0x64 +#define OV7670_LCC4 0x65 +#define OV7670_LCC5 0x66 +#define OV7670_LCC6 0x94 +#define OV7670_LCC7 0x95 +#define OV7670_SLOP 0x7A +#define OV7670_GAM1 0x7B +#define OV7670_GAM2 0x7C +#define OV7670_GAM3 0x7D +#define OV7670_GAM4 0x7E +#define OV7670_GAM5 0x7F +#define OV7670_GAM6 0x80 +#define OV7670_GAM7 0x81 +#define OV7670_GAM8 0x82 +#define OV7670_GAM9 0x83 +#define OV7670_GAM10 0x84 +#define OV7670_GAM11 0x85 +#define OV7670_GAM12 0x86 +#define OV7670_GAM13 0x87 +#define OV7670_GAM14 0x88 +#define OV7670_GAM15 0x89 +#define OV7670_HAECC1 0x9F +#define OV7670_HAECC2 0xA0 +#define OV7670_HSYEN 0x31 +#define OV7670_HAECC3 0xA6 +#define OV7670_HAECC4 0xA7 +#define OV7670_HAECC5 0xA8 +#define OV7670_HAECC6 0xA9 + +/* OV7670 definitions */ +#define OV7670_PROD_ID 0x76 + +#define OV7670_VIDEO_FORMAT_CAP(width, height, format) \ + { \ + .pixelformat = (format), .width_min = (width), .width_max = (width), \ + .height_min = (height), .height_max = (height), .width_step = 0, .height_step = 0 \ + } + +static const struct video_format_cap fmts[] = { + OV7670_VIDEO_FORMAT_CAP(176, 144, VIDEO_PIX_FMT_RGB565), /* QCIF */ + OV7670_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_RGB565), /* QVGA */ + OV7670_VIDEO_FORMAT_CAP(352, 288, VIDEO_PIX_FMT_RGB565), /* CIF */ + OV7670_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_RGB565), /* VGA */ + OV7670_VIDEO_FORMAT_CAP(176, 144, VIDEO_PIX_FMT_YUYV), /* QCIF */ + OV7670_VIDEO_FORMAT_CAP(320, 240, VIDEO_PIX_FMT_YUYV), /* QVGA */ + OV7670_VIDEO_FORMAT_CAP(352, 288, VIDEO_PIX_FMT_YUYV), /* CIF */ + OV7670_VIDEO_FORMAT_CAP(640, 480, VIDEO_PIX_FMT_YUYV), /* VGA */ + {0}}; + +/* This initialization table is based on the MCUX SDK driver for the OV7670 */ +static const struct ov7670_reg ov7670_init_regtbl[] = { + {OV7670_MVFP, 0x20}, /* MVFP: Mirror/VFlip,Normal image */ + + /* configure the output timing */ + /* PCLK does not toggle during horizontal blank, one PCLK, one pixel */ + {OV7670_COM10, 0x20}, /* COM10 */ + {OV7670_COM12, 0x00}, /* COM12,No HREF when VSYNC is low */ + /* Brightness Control, with signal -128 to +128, 0x00 is middle value */ + {OV7670_BRIGHT, 0x2f}, + + /* Internal clock pre-scalar,F(internal clock) = F(input clock)/(Bit[5:0]+1) */ + {OV7670_CLKRC, 0x81}, /* Clock Div, Input/(n+1), bit6 set to 1 to disable divider */ + + /* SCALING_PCLK_DIV, */ + {OV7670_SCALING_PCLK_DIV, 0x00}, /* 0: Enable clock divider,010: Divided by 4 */ + /* Common Control 14,Bit[4]: DCW and scaling PCLK enable,Bit[3]: Manual scaling */ + {OV7670_COM14, 0x00}, + + /* DBLV,Bit[7:6]: PLL control */ + /* 0:Bypass PLL.,40: Input clock x4 , 80: Input clock x6 ,C0: Input clock x8 */ + {OV7670_DBLV, 0x40}, + + /* test pattern, useful in some case */ + {OV7670_SCALING_XSC, 0x0}, + {OV7670_SCALING_YSC, 0}, + + /* Output Drive Capability */ + {OV7670_COM2, 0x00}, /* Common Control 2, Output Drive Capability: 1x */ + {OV7670_SCALING_PCLK_DELAY, 0x02}, + {OV7670_BD50MAX, 0x05}, + {OV7670_BD60MAX, 0x07}, + {OV7670_HAECC7, 0x94}, + + {OV7670_COM3, 0x00}, + {OV7670_COM4, 0x00}, + {OV7670_COM6, 0x4b}, + {OV7670_COM11, 0x9F}, /* Night mode */ + {OV7670_EDGE, 0x04}, /* Edge Enhancement Adjustment */ + {OV7670_DNSTH, 0x00}, /* De-noise Strength */ + + {OV7670_DM_LNL, 0x00}, + {OV7670_DM_LNH, 0x00}, + + /* reserved */ + {0x16, 0x02}, + {0x21, 0x02}, + {0x22, 0x91}, + {0x29, 0x07}, + {0x35, 0x0b}, + {0x33, 0x0b}, + {0x37, 0x1d}, + {0x38, 0x71}, + {0x39, 0x2a}, + {0x0e, 0x61}, + {0x56, 0x40}, + {0x57, 0x80}, + {0x69, 0x00}, + {0x74, 0x19}, + + /* display , need retain */ + {OV7670_COM15, 0xD0}, /* Common Control 15 */ + {OV7670_TSLB, 0x0C}, /* Line Buffer Test Option */ + {OV7670_COM13, 0x80}, /* Common Control 13 */ + {OV7670_MANU, 0x11}, /* Manual U Value */ + {OV7670_MANV, 0xFF}, /* Manual V Value */ + /* config the output window data, this can be configed later */ + {OV7670_HSTART, 0x16}, /* HSTART */ + {OV7670_HSTOP, 0x04}, /* HSTOP */ + {OV7670_VSTRT, 0x02}, /* VSTRT */ + {OV7670_VSTOP, 0x7a}, /* VSTOP */ + {OV7670_HREF, 0x80}, /* HREF */ + {OV7670_VREF, 0x0a}, /* VREF */ + + /* DCW Control, */ + {OV7670_SCALING_DCWCTR, 0x11}, + + /* AGC/AEC - Automatic Gain Control/Automatic exposure Control */ + {OV7670_GAIN, 0x00}, /* AGC */ + {OV7670_AECHH, 0x3F}, /* Exposure Value */ + {OV7670_AECH, 0xFF}, + {OV7670_COM8, 0x66}, + {OV7670_COM9, 0x21}, /* limit the max gain */ + {OV7670_AEW, 0x75}, + {OV7670_AEB, 0x63}, + {OV7670_VPT, 0xA5}, + /* Automatic white balance control */ + {OV7670_AWBC1, 0x14}, + {OV7670_AWBC2, 0xf0}, + {OV7670_AWBC3, 0x34}, + {OV7670_AWBC4, 0x58}, + {OV7670_AWBC5, 0x28}, + {OV7670_AWBC6, 0x3a}, + /* Matrix Coefficient */ + {OV7670_MTX1, 0x80}, + {OV7670_MTX2, 0x80}, + {OV7670_MTX3, 0x00}, + {OV7670_MTX4, 0x22}, + {OV7670_MTX5, 0x5e}, + {OV7670_MTX6, 0x80}, + /* AWB Control */ + {0x59, 0x88}, + {0x5a, 0x88}, + {0x5b, 0x44}, + {0x5c, 0x67}, + {0x5d, 0x49}, + {0x5e, 0x0e}, + {0x6c, 0x0a}, + {0x6d, 0x55}, + {0x6e, 0x11}, + {0x6f, 0x9f}, + /* Lens Correction Option */ + {OV7670_LCC1, 0x00}, + {OV7670_LCC2, 0x00}, + {OV7670_LCC3, 0x04}, + {OV7670_LCC4, 0x20}, + {OV7670_LCC5, 0x05}, + {OV7670_LCC6, 0x04}, /* effective only when LCC5[2] is high */ + {OV7670_LCC7, 0x08}, /* effective only when LCC5[2] is high */ + /* Gamma Curve, needn't config */ + {OV7670_SLOP, 0x20}, + {OV7670_GAM1, 0x1c}, + {OV7670_GAM2, 0x28}, + {OV7670_GAM3, 0x3c}, + {OV7670_GAM4, 0x55}, + {OV7670_GAM5, 0x68}, + {OV7670_GAM6, 0x76}, + {OV7670_GAM7, 0x80}, + {OV7670_GAM8, 0x88}, + {OV7670_GAM9, 0x8f}, + {OV7670_GAM10, 0x96}, + {OV7670_GAM11, 0xa3}, + {OV7670_GAM12, 0xaf}, + {OV7670_GAM13, 0xc4}, + {OV7670_GAM14, 0xd7}, + {OV7670_GAM15, 0xe8}, + /* Histogram-based AEC/AGC Control */ + {OV7670_HAECC1, 0x78}, + {OV7670_HAECC2, 0x68}, + {OV7670_HSYEN, 0xff}, + {0xa1, 0x03}, + {OV7670_HAECC3, 0xdf}, + {OV7670_HAECC4, 0xdf}, + {OV7670_HAECC5, 0xf0}, + {OV7670_HAECC6, 0x90}, + /* Automatic black Level Compensation */ + {0xb0, 0x84}, + {0xb1, 0x0c}, + {0xb2, 0x0e}, + {0xb3, 0x82}, + {0xb8, 0x0a}, +}; + +static int ov7670_get_caps(const struct device *dev, enum video_endpoint_id ep, + struct video_caps *caps) +{ + caps->format_caps = fmts; + return 0; +} + +static int ov7670_set_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + const struct ov7670_config *config = dev->config; + struct ov7670_data *data = dev->data; + uint8_t com7 = 0U; + uint8_t i = 0U; + + if (fmt->pixelformat != VIDEO_PIX_FMT_RGB565 && fmt->pixelformat != VIDEO_PIX_FMT_YUYV) { + LOG_ERR("Only RGB565 and YUYV supported!"); + return -ENOTSUP; + } + + if (!memcmp(&data->fmt, fmt, sizeof(data->fmt))) { + /* nothing to do */ + return 0; + } + + memcpy(&data->fmt, fmt, sizeof(data->fmt)); + + if (fmt->pixelformat == VIDEO_PIX_FMT_RGB565) { + com7 |= 0x4; + } + + /* Set output resolution */ + while (fmts[i].pixelformat) { + if (fmts[i].width_min == fmt->width && fmts[i].height_min == fmt->height && + fmts[i].pixelformat == fmt->pixelformat) { + /* Set output format */ + switch (fmts[i].width_min) { + case 176: /* QCIF */ + com7 |= BIT(3); + break; + case 320: /* QVGA */ + com7 |= BIT(4); + break; + case 352: /* CIF */ + com7 |= BIT(5); + break; + default: /* VGA */ + break; + } + /* Program COM7 to set format */ + return i2c_reg_write_byte_dt(&config->bus, OV7670_COM7, com7); + } + i++; + } + LOG_ERR("Unsupported format"); + return -ENOTSUP; +} + +static int ov7670_get_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + struct ov7670_data *data = dev->data; + + if (fmt == NULL) { + return -EINVAL; + } + memcpy(fmt, &data->fmt, sizeof(data->fmt)); + return 0; +} + +static int ov7670_init(const struct device *dev) +{ + const struct ov7670_config *config = dev->config; + int ret, i; + uint8_t pid; + struct video_format fmt; + const struct ov7670_reg *reg; + + if (!i2c_is_ready_dt(&config->bus)) { + /* I2C device is not ready, return */ + return -ENODEV; + } + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(pwdn_gpios) + /* Power up camera module */ + if (config->pwdn.port != NULL) { + if (!gpio_is_ready_dt(&config->pwdn)) { + return -ENODEV; + } + ret = gpio_pin_configure_dt(&config->pwdn, GPIO_OUTPUT_INACTIVE); + if (ret < 0) { + LOG_ERR("Could not clear power down pin: %d", ret); + return ret; + } + } +#endif +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) + /* Reset camera module */ + if (config->reset.port != NULL) { + if (!gpio_is_ready_dt(&config->reset)) { + return -ENODEV; + } + ret = gpio_pin_configure_dt(&config->reset, GPIO_OUTPUT); + if (ret < 0) { + LOG_ERR("Could not set reset pin: %d", ret); + return ret; + } + /* Reset is active low, has 1ms settling time*/ + gpio_pin_set_dt(&config->reset, 0); + k_msleep(1); + gpio_pin_set_dt(&config->reset, 1); + k_msleep(1); + } +#endif + + /* + * Read product ID from camera. This camera implements the SCCB, + * spec- which *should* be I2C compatible, but in practice does + * not seem to respond when I2C repeated start commands are used. + * To work around this, use a write then a read to interface with + * registers. + */ + uint8_t cmd = OV7670_PID; + + ret = i2c_write_dt(&config->bus, &cmd, sizeof(cmd)); + if (ret < 0) { + LOG_ERR("Could not request product ID: %d", ret); + return ret; + } + ret = i2c_read_dt(&config->bus, &pid, sizeof(pid)); + if (ret < 0) { + LOG_ERR("Could not read product ID: %d", ret); + return ret; + } + + if (pid != OV7670_PROD_ID) { + LOG_ERR("Incorrect product ID: 0x%02X", pid); + return -ENODEV; + } + + /* Set default camera format (QVGA, YUYV) */ + fmt.pixelformat = VIDEO_PIX_FMT_YUYV; + fmt.width = 640; + fmt.height = 480; + fmt.pitch = fmt.width * 2; + ret = ov7670_set_fmt(dev, VIDEO_EP_OUT, &fmt); + if (ret < 0) { + return ret; + } + + /* Write initialization values to OV7670 */ + for (i = 0; i < ARRAY_SIZE(ov7670_init_regtbl); i++) { + reg = &ov7670_init_regtbl[i]; + ret = i2c_reg_write_byte_dt(&config->bus, reg->reg, reg->cmd); + if (ret < 0) { + return ret; + } + } + + return 0; +} + +static const struct video_driver_api ov7670_api = { + .set_format = ov7670_set_fmt, + .get_format = ov7670_get_fmt, + .get_caps = ov7670_get_caps, +}; + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(reset_gpios) +#define OV7670_RESET_GPIO(inst) .reset = GPIO_DT_SPEC_INST_GET_OR(inst, reset_gpios, {}), +#else +#define OV7670_RESET_GPIO(inst) +#endif + +#if DT_ANY_INST_HAS_PROP_STATUS_OKAY(pwdn_gpios) +#define OV7670_PWDN_GPIO(inst) .pwdn = GPIO_DT_SPEC_INST_GET_OR(inst, pwdn_gpios, {}), +#else +#define OV7670_PWDN_GPIO(inst) +#endif + +#define OV7670_INIT(inst) \ + const struct ov7670_config ov7670_config_##inst = {.bus = I2C_DT_SPEC_INST_GET(inst), \ + OV7670_RESET_GPIO(inst) \ + OV7670_PWDN_GPIO(inst)}; \ + struct ov7670_data ov7670_data_##inst; \ + \ + DEVICE_DT_INST_DEFINE(inst, ov7670_init, NULL, &ov7670_data_##inst, &ov7670_config_##inst, \ + POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, &ov7670_api); + +DT_INST_FOREACH_STATUS_OKAY(OV7670_INIT) diff --git a/drivers/video/video_mcux_csi.c b/drivers/video/video_mcux_csi.c index 1e7117c4393e3..2e8e4d505084a 100644 --- a/drivers/video/video_mcux_csi.c +++ b/drivers/video/video_mcux_csi.c @@ -20,7 +20,7 @@ struct video_mcux_csi_config { CSI_Type *base; - const struct device *sensor_dev; + const struct device *source_dev; const struct pinctrl_dev_config *pincfg; }; @@ -30,7 +30,6 @@ struct video_mcux_csi_data { csi_handle_t csi_handle; struct k_fifo fifo_in; struct k_fifo fifo_out; - uint32_t pixelformat; struct k_poll_signal *signal; }; @@ -45,13 +44,15 @@ static inline unsigned int video_pix_fmt_bpp(uint32_t pixelformat) case VIDEO_PIX_FMT_RGB565: case VIDEO_PIX_FMT_YUYV: return 2; + case VIDEO_PIX_FMT_XRGB32: + case VIDEO_PIX_FMT_XYUV32: + return 4; default: return 0; } } -static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, - status_t status, void *user_data) +static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, status_t status, void *user_data) { struct video_mcux_csi_data *data = user_data; const struct device *dev = data->dev; @@ -66,8 +67,7 @@ static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, return; } - status = CSI_TransferGetFullBuffer(config->base, &(data->csi_handle), - &buffer_addr); + status = CSI_TransferGetFullBuffer(config->base, &(data->csi_handle), &buffer_addr); if (status != kStatus_Success) { result = VIDEO_BUF_ERROR; goto done; @@ -116,25 +116,62 @@ static void __frame_done_cb(CSI_Type *base, csi_handle_t *handle, return; } -static int video_mcux_csi_set_fmt(const struct device *dev, - enum video_endpoint_id ep, +#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX) +K_HEAP_DEFINE(csi_heap, 1000); +static struct video_format_cap *fmts; +/* + * On i.MX RT11xx SoCs which have MIPI CSI-2 Rx, image data from the camera sensor after passing + * through the pipeline (MIPI CSI-2 Rx --> Video Mux --> CSI) will be implicitly converted to a + * 32-bits pixel format. For example, an input in RGB565 or YUYV (2-bytes format) will become a + * XRGB32 or XYUV32 (4-bytes format) respectively, at the output of the CSI. + */ +static inline void video_pix_fmt_convert(struct video_format *fmt, bool isGetFmt) +{ + switch (fmt->pixelformat) { + case VIDEO_PIX_FMT_XRGB32: + fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XRGB32 : VIDEO_PIX_FMT_RGB565; + break; + case VIDEO_PIX_FMT_XYUV32: + fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XYUV32 : VIDEO_PIX_FMT_YUYV; + break; + case VIDEO_PIX_FMT_RGB565: + fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XRGB32 : VIDEO_PIX_FMT_RGB565; + break; + case VIDEO_PIX_FMT_YUYV: + fmt->pixelformat = isGetFmt ? VIDEO_PIX_FMT_XYUV32 : VIDEO_PIX_FMT_YUYV; + break; + } + + fmt->pitch = fmt->width * video_pix_fmt_bpp(fmt->pixelformat); +} +#endif + +static int video_mcux_csi_set_fmt(const struct device *dev, enum video_endpoint_id ep, struct video_format *fmt) { const struct video_mcux_csi_config *config = dev->config; struct video_mcux_csi_data *data = dev->data; unsigned int bpp = video_pix_fmt_bpp(fmt->pixelformat); status_t ret; + struct video_format format = *fmt; if (!bpp || ep != VIDEO_EP_OUT) { return -EINVAL; } - data->pixelformat = fmt->pixelformat; data->csi_config.bytesPerPixel = bpp; data->csi_config.linePitch_Bytes = fmt->pitch; +#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX) + if (fmt->pixelformat != VIDEO_PIX_FMT_XRGB32 && fmt->pixelformat != VIDEO_PIX_FMT_XYUV32) { + return -ENOTSUP; + } + video_pix_fmt_convert(&format, false); + data->csi_config.dataBus = kCSI_DataBus24Bit; +#else + data->csi_config.dataBus = kCSI_DataBus8Bit; +#endif data->csi_config.polarityFlags = kCSI_HsyncActiveHigh | kCSI_DataLatchOnRisingEdge; data->csi_config.workMode = kCSI_GatedClockMode; /* use VSYNC, HSYNC, and PIXCLK */ - data->csi_config.dataBus = kCSI_DataBus8Bit; data->csi_config.useExtVsync = true; data->csi_config.height = fmt->height; data->csi_config.width = fmt->width; @@ -144,42 +181,36 @@ static int video_mcux_csi_set_fmt(const struct device *dev, return -EIO; } - ret = CSI_TransferCreateHandle(config->base, &data->csi_handle, - __frame_done_cb, data); + ret = CSI_TransferCreateHandle(config->base, &data->csi_handle, __frame_done_cb, data); if (ret != kStatus_Success) { return -EIO; } - if (config->sensor_dev && video_set_format(config->sensor_dev, ep, fmt)) { + if (config->source_dev && video_set_format(config->source_dev, ep, &format)) { return -EIO; } return 0; } -static int video_mcux_csi_get_fmt(const struct device *dev, - enum video_endpoint_id ep, +static int video_mcux_csi_get_fmt(const struct device *dev, enum video_endpoint_id ep, struct video_format *fmt) { - struct video_mcux_csi_data *data = dev->data; const struct video_mcux_csi_config *config = dev->config; if (fmt == NULL || ep != VIDEO_EP_OUT) { return -EINVAL; } - if (config->sensor_dev && !video_get_format(config->sensor_dev, ep, fmt)) { - /* align CSI with sensor fmt */ + if (config->source_dev && !video_get_format(config->source_dev, ep, fmt)) { +#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX) + video_pix_fmt_convert(fmt, true); +#endif + /* align CSI with source fmt */ return video_mcux_csi_set_fmt(dev, ep, fmt); } - - fmt->pixelformat = data->pixelformat; - fmt->height = data->csi_config.height; - fmt->width = data->csi_config.width; - fmt->pitch = data->csi_config.linePitch_Bytes; - - return 0; + return -EIO; } static int video_mcux_csi_stream_start(const struct device *dev) @@ -193,7 +224,7 @@ static int video_mcux_csi_stream_start(const struct device *dev) return -EIO; } - if (config->sensor_dev && video_stream_start(config->sensor_dev)) { + if (config->source_dev && video_stream_start(config->source_dev)) { return -EIO; } @@ -206,7 +237,7 @@ static int video_mcux_csi_stream_stop(const struct device *dev) struct video_mcux_csi_data *data = dev->data; status_t ret; - if (config->sensor_dev && video_stream_stop(config->sensor_dev)) { + if (config->source_dev && video_stream_stop(config->source_dev)) { return -EIO; } @@ -218,10 +249,7 @@ static int video_mcux_csi_stream_stop(const struct device *dev) return 0; } - -static int video_mcux_csi_flush(const struct device *dev, - enum video_endpoint_id ep, - bool cancel) +static int video_mcux_csi_flush(const struct device *dev, enum video_endpoint_id ep, bool cancel) { const struct video_mcux_csi_config *config = dev->config; struct video_mcux_csi_data *data = dev->data; @@ -237,16 +265,14 @@ static int video_mcux_csi_flush(const struct device *dev, } else { /* Flush driver output queue */ do { - ret = CSI_TransferGetFullBuffer(config->base, - &(data->csi_handle), + ret = CSI_TransferGetFullBuffer(config->base, &(data->csi_handle), &buffer_addr); } while (ret == kStatus_Success); while ((vbuf = k_fifo_get(&data->fifo_in, K_NO_WAIT))) { k_fifo_put(&data->fifo_out, vbuf); if (IS_ENABLED(CONFIG_POLL) && data->signal) { - k_poll_signal_raise(data->signal, - VIDEO_BUF_ABORTED); + k_poll_signal_raise(data->signal, VIDEO_BUF_ABORTED); } } } @@ -254,8 +280,7 @@ static int video_mcux_csi_flush(const struct device *dev, return 0; } -static int video_mcux_csi_enqueue(const struct device *dev, - enum video_endpoint_id ep, +static int video_mcux_csi_enqueue(const struct device *dev, enum video_endpoint_id ep, struct video_buffer *vbuf) { const struct video_mcux_csi_config *config = dev->config; @@ -281,10 +306,8 @@ static int video_mcux_csi_enqueue(const struct device *dev, return 0; } -static int video_mcux_csi_dequeue(const struct device *dev, - enum video_endpoint_id ep, - struct video_buffer **vbuf, - k_timeout_t timeout) +static int video_mcux_csi_dequeue(const struct device *dev, enum video_endpoint_id ep, + struct video_buffer **vbuf, k_timeout_t timeout) { struct video_mcux_csi_data *data = dev->data; @@ -300,38 +323,33 @@ static int video_mcux_csi_dequeue(const struct device *dev, return 0; } -static inline int video_mcux_csi_set_ctrl(const struct device *dev, - unsigned int cid, - void *value) +static inline int video_mcux_csi_set_ctrl(const struct device *dev, unsigned int cid, void *value) { const struct video_mcux_csi_config *config = dev->config; int ret = -ENOTSUP; - /* Forward to sensor dev if any */ - if (config->sensor_dev) { - ret = video_set_ctrl(config->sensor_dev, cid, value); + /* Forward to source dev if any */ + if (config->source_dev) { + ret = video_set_ctrl(config->source_dev, cid, value); } return ret; } -static inline int video_mcux_csi_get_ctrl(const struct device *dev, - unsigned int cid, - void *value) +static inline int video_mcux_csi_get_ctrl(const struct device *dev, unsigned int cid, void *value) { const struct video_mcux_csi_config *config = dev->config; int ret = -ENOTSUP; - /* Forward to sensor dev if any */ - if (config->sensor_dev) { - ret = video_get_ctrl(config->sensor_dev, cid, value); + /* Forward to source dev if any */ + if (config->source_dev) { + ret = video_get_ctrl(config->source_dev, cid, value); } return ret; } -static int video_mcux_csi_get_caps(const struct device *dev, - enum video_endpoint_id ep, +static int video_mcux_csi_get_caps(const struct device *dev, enum video_endpoint_id ep, struct video_caps *caps) { const struct video_mcux_csi_config *config = dev->config; @@ -341,15 +359,43 @@ static int video_mcux_csi_get_caps(const struct device *dev, return -EINVAL; } - /* Just forward to sensor dev for now */ - if (config->sensor_dev) { - err = video_get_caps(config->sensor_dev, ep, caps); + /* Just forward to source dev for now */ + if (config->source_dev) { + err = video_get_caps(config->source_dev, ep, caps); +#if defined(CONFIG_VIDEO_MCUX_MIPI_CSI2RX) + /* + * On i.MX RT11xx SoCs which have MIPI CSI-2 Rx, image data from the camera sensor + * after passing through the pipeline (MIPI CSI-2 Rx --> Video Mux --> CSI) will be + * implicitly converted to a 32-bits pixel format. For example, an input in RGB565 + * or YUYV (2-bytes format) will become an XRGB32 or XYUV32 (4-bytes format) + * respectively, at the output of the CSI. So, we change the pixel formats of the + * source caps to reflect this. + */ + int ind = 0; + + while (caps->format_caps[ind].pixelformat) { + ind++; + } + k_heap_free(&csi_heap, fmts); + fmts = k_heap_alloc(&csi_heap, (ind + 1) * sizeof(struct video_format_cap), + K_FOREVER); + + for (int i = 0; i <= ind; i++) { + memcpy(&fmts[i], &caps->format_caps[i], sizeof(fmts[i])); + if (fmts[i].pixelformat == VIDEO_PIX_FMT_RGB565) { + fmts[i].pixelformat = VIDEO_PIX_FMT_XRGB32; + } else if (fmts[i].pixelformat == VIDEO_PIX_FMT_YUYV) { + fmts[i].pixelformat = VIDEO_PIX_FMT_XYUV32; + } + } + caps->format_caps = fmts; +#endif } /* NXP MCUX CSI request at least 2 buffer before starting */ caps->min_vbuf_count = 2; - /* no sensor dev */ + /* no source dev */ return err; } @@ -371,10 +417,10 @@ static int video_mcux_csi_init(const struct device *dev) CSI_GetDefaultConfig(&data->csi_config); - /* check if there is any sensor device (video ctrl device) + /* check if there is any source device (video ctrl device) * the device is not yet initialized so we only check if it exists */ - if (config->sensor_dev == NULL) { + if (config->source_dev == NULL) { return -ENODEV; } @@ -387,8 +433,7 @@ static int video_mcux_csi_init(const struct device *dev) } #ifdef CONFIG_POLL -static int video_mcux_csi_set_signal(const struct device *dev, - enum video_endpoint_id ep, +static int video_mcux_csi_set_signal(const struct device *dev, enum video_endpoint_id ep, struct k_poll_signal *signal) { struct video_mcux_csi_data *data = dev->data; @@ -424,7 +469,7 @@ PINCTRL_DT_INST_DEFINE(0); static const struct video_mcux_csi_config video_mcux_csi_config_0 = { .base = (CSI_Type *)DT_INST_REG_ADDR(0), - .sensor_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, sensor)), + .source_dev = DEVICE_DT_GET(DT_INST_PHANDLE(0, source)), .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(0), }; @@ -434,8 +479,7 @@ static int video_mcux_csi_init_0(const struct device *dev) { struct video_mcux_csi_data *data = dev->data; - IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), - video_mcux_csi_isr, NULL, 0); + IRQ_CONNECT(DT_INST_IRQN(0), DT_INST_IRQ(0, priority), video_mcux_csi_isr, NULL, 0); irq_enable(DT_INST_IRQN(0)); @@ -449,9 +493,7 @@ static int video_mcux_csi_init_0(const struct device *dev) * necessary since the clock to the camera is provided by the * CSI peripheral. */ -DEVICE_DT_INST_DEFINE(0, &video_mcux_csi_init_0, - NULL, &video_mcux_csi_data_0, - &video_mcux_csi_config_0, - POST_KERNEL, CONFIG_VIDEO_MCUX_CSI_INIT_PRIORITY, - &video_mcux_csi_driver_api); +DEVICE_DT_INST_DEFINE(0, &video_mcux_csi_init_0, NULL, &video_mcux_csi_data_0, + &video_mcux_csi_config_0, POST_KERNEL, CONFIG_VIDEO_MCUX_CSI_INIT_PRIORITY, + &video_mcux_csi_driver_api); #endif diff --git a/drivers/video/video_mcux_mipi_csi2rx.c b/drivers/video/video_mcux_mipi_csi2rx.c new file mode 100644 index 0000000000000..6d9dc5729edc3 --- /dev/null +++ b/drivers/video/video_mcux_mipi_csi2rx.c @@ -0,0 +1,218 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT nxp_mipi_csi2rx + +#include + +#include +#include + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(mipi_csi); + +/* + * Two data lanes are set by default as 2-lanes camera sensors are + * more common and more performant but single lane is also supported. + */ +#define DEFAULT_MIPI_CSI_NUM_LANES 2 +#define DEFAULT_CAMERA_FRAME_RATE 30 + +struct mipi_csi2rx_config { + const MIPI_CSI2RX_Type *base; + const struct device *sensor_dev; +}; + +struct mipi_csi2rx_data { + csi2rx_config_t csi2rxConfig; +}; + +static int mipi_csi2rx_set_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + const struct mipi_csi2rx_config *config = dev->config; + struct mipi_csi2rx_data *drv_data = dev->data; + csi2rx_config_t csi2rxConfig = {0}; + uint8_t i = 0; + + /* + * Initialize the MIPI CSI2 + * + * From D-PHY specification, the T-HSSETTLE should in the range of 85ns+6*UI to 145ns+10*UI + * UI is Unit Interval, equal to the duration of any HS state on the Clock Lane + * + * T-HSSETTLE = csi2rxConfig.tHsSettle_EscClk * (Tperiod of RxClkInEsc) + * + * csi2rxConfig.tHsSettle_EscClk setting for camera: + * + * Resolution | frame rate | T_HS_SETTLE + * ============================================= + * 720P | 30 | 0x12 + * --------------------------------------------- + * 720P | 15 | 0x17 + * --------------------------------------------- + * VGA | 30 | 0x1F + * --------------------------------------------- + * VGA | 15 | 0x24 + * --------------------------------------------- + * QVGA | 30 | 0x1F + * --------------------------------------------- + * QVGA | 15 | 0x24 + * --------------------------------------------- + */ + static const uint32_t csi2rxHsSettle[][4] = { + { + 1280, + 720, + 30, + 0x12, + }, + { + 1280, + 720, + 15, + 0x17, + }, + { + 640, + 480, + 30, + 0x1F, + }, + { + 640, + 480, + 15, + 0x24, + }, + { + 320, + 240, + 30, + 0x1F, + }, + { + 320, + 240, + 15, + 0x24, + }, + }; + + csi2rxConfig.laneNum = DEFAULT_MIPI_CSI_NUM_LANES; + + for (i = 0; i < ARRAY_SIZE(csi2rxHsSettle); i++) { + if ((fmt->width == csi2rxHsSettle[i][0]) && (fmt->height == csi2rxHsSettle[i][1]) && + (DEFAULT_CAMERA_FRAME_RATE == csi2rxHsSettle[i][2])) { + csi2rxConfig.tHsSettle_EscClk = csi2rxHsSettle[i][3]; + break; + } + } + + if (i == ARRAY_SIZE(csi2rxHsSettle)) { + LOG_ERR("Unsupported resolution"); + return -ENOTSUP; + } + + drv_data->csi2rxConfig = csi2rxConfig; + + if (video_set_format(config->sensor_dev, ep, fmt)) { + return -EIO; + } + + return 0; +} + +static int mipi_csi2rx_get_fmt(const struct device *dev, enum video_endpoint_id ep, + struct video_format *fmt) +{ + const struct mipi_csi2rx_config *config = dev->config; + + if (fmt == NULL || ep != VIDEO_EP_OUT) { + return -EINVAL; + } + + if (video_get_format(config->sensor_dev, ep, fmt)) { + return -EIO; + } + + return 0; +} + +static int mipi_csi2rx_stream_start(const struct device *dev) +{ + const struct mipi_csi2rx_config *config = dev->config; + struct mipi_csi2rx_data *drv_data = dev->data; + + CSI2RX_Init((MIPI_CSI2RX_Type *)config->base, &drv_data->csi2rxConfig); + + if (video_stream_start(config->sensor_dev)) { + return -EIO; + } + + return 0; +} + +static int mipi_csi2rx_stream_stop(const struct device *dev) +{ + const struct mipi_csi2rx_config *config = dev->config; + + if (video_stream_stop(config->sensor_dev)) { + return -EIO; + } + + CSI2RX_Deinit((MIPI_CSI2RX_Type *)config->base); + + return 0; +} + +static int mipi_csi2rx_get_caps(const struct device *dev, enum video_endpoint_id ep, + struct video_caps *caps) +{ + const struct mipi_csi2rx_config *config = dev->config; + + if (ep != VIDEO_EP_OUT) { + return -EINVAL; + } + + /* Just forward to sensor dev for now */ + return video_get_caps(config->sensor_dev, ep, caps); +} + +static const struct video_driver_api mipi_csi2rx_driver_api = { + .get_caps = mipi_csi2rx_get_caps, + .get_format = mipi_csi2rx_get_fmt, + .set_format = mipi_csi2rx_set_fmt, + .stream_start = mipi_csi2rx_stream_start, + .stream_stop = mipi_csi2rx_stream_stop, +}; + +static int mipi_csi2rx_init(const struct device *dev) +{ + const struct mipi_csi2rx_config *config = dev->config; + + /* Check if there is any sensor device */ + if (!device_is_ready(config->sensor_dev)) { + return -ENODEV; + } + + return 0; +} + +#define MIPI_CSI2RX_INIT(n) \ + static struct mipi_csi2rx_data mipi_csi2rx_data_##n; \ + \ + static const struct mipi_csi2rx_config mipi_csi2rx_config_##n = { \ + .base = (MIPI_CSI2RX_Type *)DT_INST_REG_ADDR(n), \ + .sensor_dev = DEVICE_DT_GET(DT_INST_PHANDLE(n, sensor)), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(n, &mipi_csi2rx_init, NULL, &mipi_csi2rx_data_##n, \ + &mipi_csi2rx_config_##n, POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY, \ + &mipi_csi2rx_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(MIPI_CSI2RX_INIT) diff --git a/drivers/virtualization/virt_ivshmem.c b/drivers/virtualization/virt_ivshmem.c index f620ab473f9e0..bce1dd4c42885 100644 --- a/drivers/virtualization/virt_ivshmem.c +++ b/drivers/virtualization/virt_ivshmem.c @@ -219,9 +219,9 @@ static bool ivshmem_configure(const struct device *dev) LOG_ERR("Invalid state table size %zu", state_table_size); return false; } - z_phys_map((uint8_t **)&data->state_table_shmem, - shmem_phys_addr, state_table_size, - K_MEM_CACHE_WB | K_MEM_PERM_USER); + k_mem_map_phys_bare((uint8_t **)&data->state_table_shmem, + shmem_phys_addr, state_table_size, + K_MEM_CACHE_WB | K_MEM_PERM_USER); /* R/W section (optional) */ cap_pos = vendor_cap + IVSHMEM_CFG_RW_SECTION_SZ / 4; @@ -229,9 +229,10 @@ static bool ivshmem_configure(const struct device *dev) size_t rw_section_offset = state_table_size; LOG_INF("RW section size 0x%zX", data->rw_section_size); if (data->rw_section_size > 0) { - z_phys_map((uint8_t **)&data->rw_section_shmem, - shmem_phys_addr + rw_section_offset, data->rw_section_size, - K_MEM_CACHE_WB | K_MEM_PERM_RW | K_MEM_PERM_USER); + k_mem_map_phys_bare((uint8_t **)&data->rw_section_shmem, + shmem_phys_addr + rw_section_offset, + data->rw_section_size, + K_MEM_CACHE_WB | K_MEM_PERM_RW | K_MEM_PERM_USER); } /* Output sections */ @@ -249,8 +250,8 @@ static bool ivshmem_configure(const struct device *dev) if (i == regs->id) { flags |= K_MEM_PERM_RW; } - z_phys_map((uint8_t **)&data->output_section_shmem[i], - phys_addr, data->output_section_size, flags); + k_mem_map_phys_bare((uint8_t **)&data->output_section_shmem[i], + phys_addr, data->output_section_size, flags); } data->size = output_section_offset + @@ -273,9 +274,9 @@ static bool ivshmem_configure(const struct device *dev) data->size = mbar_shmem.size; - z_phys_map((uint8_t **)&data->shmem, - shmem_phys_addr, data->size, - K_MEM_CACHE_WB | K_MEM_PERM_RW | K_MEM_PERM_USER); + k_mem_map_phys_bare((uint8_t **)&data->shmem, + shmem_phys_addr, data->size, + K_MEM_CACHE_WB | K_MEM_PERM_RW | K_MEM_PERM_USER); } if (msi_x_bar_present) { diff --git a/drivers/virtualization/virt_ivshmem_handlers.c b/drivers/virtualization/virt_ivshmem_handlers.c index 821ab16f30407..4f22a4dadd8b4 100644 --- a/drivers/virtualization/virt_ivshmem_handlers.c +++ b/drivers/virtualization/virt_ivshmem_handlers.c @@ -16,7 +16,7 @@ static inline size_t z_vrfy_ivshmem_get_mem(const struct device *dev, return z_impl_ivshmem_get_mem(dev, memmap); } -#include +#include static inline uint32_t z_vrfy_ivshmem_get_id(const struct device *dev) { @@ -24,7 +24,7 @@ static inline uint32_t z_vrfy_ivshmem_get_id(const struct device *dev) return z_impl_ivshmem_get_id(dev); } -#include +#include static inline uint16_t z_vrfy_ivshmem_get_vectors(const struct device *dev) { @@ -32,7 +32,7 @@ static inline uint16_t z_vrfy_ivshmem_get_vectors(const struct device *dev) return z_impl_ivshmem_get_vectors(dev); } -#include +#include static inline int z_vrfy_ivshmem_int_peer(const struct device *dev, uint32_t peer_id, uint16_t vector) @@ -41,7 +41,7 @@ static inline int z_vrfy_ivshmem_int_peer(const struct device *dev, return z_impl_ivshmem_int_peer(dev, peer_id, vector); } -#include +#include static inline int z_vrfy_ivshmem_register_handler(const struct device *dev, struct k_poll_signal *signal, @@ -52,7 +52,7 @@ static inline int z_vrfy_ivshmem_register_handler(const struct device *dev, return z_impl_ivshmem_register_handler(dev, signal, vector); } -#include +#include #ifdef CONFIG_IVSHMEM_V2 @@ -64,7 +64,7 @@ static inline size_t z_vrfy_ivshmem_get_rw_mem_section(const struct device *dev, return z_impl_ivshmem_get_rw_mem_section(dev, memmap); } -#include +#include static inline size_t z_vrfy_ivshmem_get_output_mem_section(const struct device *dev, uint32_t peer_id, @@ -75,7 +75,7 @@ static inline size_t z_vrfy_ivshmem_get_output_mem_section(const struct device * return z_impl_ivshmem_get_output_mem_section(dev, peer_id, memmap); } -#include +#include static inline uint32_t z_vrfy_ivshmem_get_state(const struct device *dev, uint32_t peer_id) @@ -84,7 +84,7 @@ static inline uint32_t z_vrfy_ivshmem_get_state(const struct device *dev, return z_impl_ivshmem_get_state(dev, peer_id); } -#include +#include static inline int z_vrfy_ivshmem_set_state(const struct device *dev, uint32_t state) @@ -93,7 +93,7 @@ static inline int z_vrfy_ivshmem_set_state(const struct device *dev, return z_impl_ivshmem_set_state(dev, state); } -#include +#include static inline uint32_t z_vrfy_ivshmem_get_max_peers(const struct device *dev) { @@ -101,7 +101,7 @@ static inline uint32_t z_vrfy_ivshmem_get_max_peers(const struct device *dev) return z_impl_ivshmem_get_max_peers(dev); } -#include +#include static inline uint16_t z_vrfy_ivshmem_get_protocol(const struct device *dev) { @@ -109,7 +109,7 @@ static inline uint16_t z_vrfy_ivshmem_get_protocol(const struct device *dev) return z_impl_ivshmem_get_protocol(dev); } -#include +#include static inline int z_vrfy_ivshmem_enable_interrupts(const struct device *dev, bool enable) @@ -118,6 +118,6 @@ static inline int z_vrfy_ivshmem_enable_interrupts(const struct device *dev, return z_impl_ivshmem_enable_interrupts(dev, enable); } -#include +#include #endif /* CONFIG_IVSHMEM_V2 */ diff --git a/drivers/w1/w1_handlers.c b/drivers/w1/w1_handlers.c index f2299705a269b..db2fb4ee18721 100644 --- a/drivers/w1/w1_handlers.c +++ b/drivers/w1/w1_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_w1_reset_bus(const struct device *dev) return z_impl_w1_reset_bus((const struct device *)dev); } -#include +#include static inline int z_vrfy_w1_read_bit(const struct device *dev) { @@ -21,7 +21,7 @@ static inline int z_vrfy_w1_read_bit(const struct device *dev) return z_impl_w1_read_bit((const struct device *)dev); } -#include +#include static inline int z_vrfy_w1_write_bit(const struct device *dev, bool bit) { @@ -29,7 +29,7 @@ static inline int z_vrfy_w1_write_bit(const struct device *dev, bool bit) return z_impl_w1_write_bit((const struct device *)dev, bit); } -#include +#include static inline int z_vrfy_w1_read_byte(const struct device *dev) { @@ -37,7 +37,7 @@ static inline int z_vrfy_w1_read_byte(const struct device *dev) return z_impl_w1_read_byte((const struct device *)dev); } -#include +#include static inline int z_vrfy_w1_write_byte(const struct device *dev, uint8_t byte) { @@ -45,7 +45,7 @@ static inline int z_vrfy_w1_write_byte(const struct device *dev, uint8_t byte) return z_impl_w1_write_byte((const struct device *)dev, (uint8_t)byte); } -#include +#include static inline int z_vrfy_w1_read_block(const struct device *dev, uint8_t *buffer, size_t len) @@ -56,7 +56,7 @@ static inline int z_vrfy_w1_read_block(const struct device *dev, return z_impl_w1_read_block((const struct device *)dev, (uint8_t *)buffer, (size_t)len); } -#include +#include static inline int z_vrfy_w1_write_block(const struct device *dev, const uint8_t *buffer, size_t len) @@ -67,7 +67,7 @@ static inline int z_vrfy_w1_write_block(const struct device *dev, return z_impl_w1_write_block((const struct device *)dev, (const uint8_t *)buffer, (size_t)len); } -#include +#include static inline int z_vrfy_w1_change_bus_lock(const struct device *dev, bool lock) { @@ -75,7 +75,7 @@ static inline int z_vrfy_w1_change_bus_lock(const struct device *dev, bool lock) return z_impl_w1_change_bus_lock((const struct device *)dev, lock); } -#include +#include static inline int z_vrfy_w1_configure(const struct device *dev, enum w1_settings_type type, uint32_t value) @@ -84,7 +84,7 @@ static inline int z_vrfy_w1_configure(const struct device *dev, return z_impl_w1_configure(dev, type, value); } -#include +#include static inline size_t z_vrfy_w1_get_slave_count(const struct device *dev) { @@ -92,7 +92,7 @@ static inline size_t z_vrfy_w1_get_slave_count(const struct device *dev) return z_impl_w1_get_slave_count((const struct device *)dev); } -#include +#include #if CONFIG_W1_NET static inline int z_vrfy_w1_search_bus(const struct device *dev, @@ -112,5 +112,5 @@ static inline int z_vrfy_w1_search_bus(const struct device *dev, (void *)user_data); } -#include +#include #endif /* CONFIG_W1_NET */ diff --git a/drivers/w1/w1_zephyr_gpio.c b/drivers/w1/w1_zephyr_gpio.c index 1954436897585..bcab363494801 100644 --- a/drivers/w1/w1_zephyr_gpio.c +++ b/drivers/w1/w1_zephyr_gpio.c @@ -289,7 +289,7 @@ static int w1_gpio_init(const struct device *dev) if (gpio_is_ready_dt(spec)) { int ret = gpio_pin_configure_dt(spec, GPIO_OUTPUT_INACTIVE | GPIO_OPEN_DRAIN | - GPIO_PULL_UP); + GPIO_INPUT); if (ret < 0) { LOG_ERR("Failed to configure GPIO port %s pin %d", spec->port->name, spec->pin); diff --git a/drivers/watchdog/CMakeLists.txt b/drivers/watchdog/CMakeLists.txt index cfec0ef05fe5c..41f56d637dbba 100644 --- a/drivers/watchdog/CMakeLists.txt +++ b/drivers/watchdog/CMakeLists.txt @@ -15,6 +15,7 @@ zephyr_library_sources_ifdef(CONFIG_WDOG_CMSDK_APB wdt_cmsdk_apb.c) zephyr_library_sources_ifdef(CONFIG_WDT_CC32XX wdt_cc32xx.c) zephyr_library_sources_ifdef(CONFIG_WDT_CC13XX_CC26XX wdt_cc13xx_cc26xx.c) zephyr_library_sources_ifdef(CONFIG_WDT_ESP32 wdt_esp32.c) +zephyr_library_sources_ifdef(CONFIG_WDT_XT_ESP32 xt_wdt_esp32.c) zephyr_library_sources_ifdef(CONFIG_WDT_GECKO wdt_gecko.c) zephyr_library_sources_ifdef(CONFIG_WDT_ITE_IT8XXX2 wdt_ite_it8xxx2.c) zephyr_library_sources_ifdef(CONFIG_WDT_MCUX_IMX_WDOG wdt_mcux_imx_wdog.c) diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 96cc4a61e0d2c..4a3982ba15d1d 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -11,8 +11,12 @@ menuconfig WATCHDOG if WATCHDOG +config HAS_WDT_DISABLE_AT_BOOT + bool + config WDT_DISABLE_AT_BOOT bool "Disable at boot" + depends on HAS_WDT_DISABLE_AT_BOOT help Disable watchdog at Zephyr system startup. diff --git a/drivers/watchdog/Kconfig.andes_atcwdt200 b/drivers/watchdog/Kconfig.andes_atcwdt200 index b4160c7bf242d..f942da491bae6 100644 --- a/drivers/watchdog/Kconfig.andes_atcwdt200 +++ b/drivers/watchdog/Kconfig.andes_atcwdt200 @@ -9,6 +9,7 @@ config WDT_ANDES_ATCWDT200 bool "Andes Watchdog driver" default y depends on DT_HAS_ANDESTECH_ATCWDT200_ENABLED + select HAS_WDT_DISABLE_AT_BOOT select COUNTER help Enable driver for the Andes Watchdog driver. diff --git a/drivers/watchdog/Kconfig.cc13xx_cc26xx b/drivers/watchdog/Kconfig.cc13xx_cc26xx index 4590c944a4b85..2ea45787f0307 100644 --- a/drivers/watchdog/Kconfig.cc13xx_cc26xx +++ b/drivers/watchdog/Kconfig.cc13xx_cc26xx @@ -5,6 +5,7 @@ config WDT_CC13XX_CC26XX bool "Watchdog Driver for CC13xx / CC26xx family of MCUs" default y depends on DT_HAS_TI_CC13XX_CC26XX_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable watchdog for CC13xx / CC26xx family of MCUs diff --git a/drivers/watchdog/Kconfig.cc32xx b/drivers/watchdog/Kconfig.cc32xx index 01734a4cdc8f0..a6a581fdfc759 100644 --- a/drivers/watchdog/Kconfig.cc32xx +++ b/drivers/watchdog/Kconfig.cc32xx @@ -5,6 +5,7 @@ config WDT_CC32XX bool "Watchdog Driver for cc32xx family of MCUs" default y depends on DT_HAS_TI_CC32XX_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Watchdog for cc32xx family of MCUs diff --git a/drivers/watchdog/Kconfig.dw b/drivers/watchdog/Kconfig.dw index a3fb726ddd838..ba35465af1326 100644 --- a/drivers/watchdog/Kconfig.dw +++ b/drivers/watchdog/Kconfig.dw @@ -7,5 +7,6 @@ config WDT_DW bool "Synopsys DesignWare Watchdog driver" default y depends on DT_HAS_SNPS_DESIGNWARE_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Synopsys DesignWare Watchdog driver. diff --git a/drivers/watchdog/Kconfig.ene b/drivers/watchdog/Kconfig.ene index 114c69b4c2b72..425b5bb63acfe 100644 --- a/drivers/watchdog/Kconfig.ene +++ b/drivers/watchdog/Kconfig.ene @@ -5,5 +5,6 @@ config WDT_ENE_KB1200 bool "ENE KB1200 watchdog driver" default y depends on DT_HAS_ENE_KB1200_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help This option enables the KB1200 watchdog driver. diff --git a/drivers/watchdog/Kconfig.esp32 b/drivers/watchdog/Kconfig.esp32 index 68eb9e5577935..26bf28c264784 100644 --- a/drivers/watchdog/Kconfig.esp32 +++ b/drivers/watchdog/Kconfig.esp32 @@ -7,5 +7,13 @@ config WDT_ESP32 bool "ESP32 Watchdog (WDT) Driver" default y depends on DT_HAS_ESPRESSIF_ESP32_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT + help + Enable WDT driver for ESP32. + +config WDT_XT_ESP32 + bool "ESP32 Watchdog for External 32K Crystal Driver" + default y + depends on DT_HAS_ESPRESSIF_ESP32_XT_WDT_ENABLED help Enable WDT driver for ESP32. diff --git a/drivers/watchdog/Kconfig.gd32 b/drivers/watchdog/Kconfig.gd32 index 29da540738951..7d149f17b50ae 100644 --- a/drivers/watchdog/Kconfig.gd32 +++ b/drivers/watchdog/Kconfig.gd32 @@ -5,6 +5,7 @@ config FWDGT_GD32 bool "GD32 Free watchdog timer (FWDGT) driver" default y depends on DT_HAS_GD_GD32_FWDGT_ENABLED + select HAS_WDT_DISABLE_AT_BOOT select USE_GD32_FWDGT help Enable the Free watchdog timer (FWDGT) driver for GD32 SoCs. diff --git a/drivers/watchdog/Kconfig.gecko b/drivers/watchdog/Kconfig.gecko index 15b99e0b8b228..55fbd7b8e1755 100644 --- a/drivers/watchdog/Kconfig.gecko +++ b/drivers/watchdog/Kconfig.gecko @@ -9,7 +9,7 @@ config WDT_GECKO bool "Gecko series Watchdog (WDOG) Driver" default y depends on DT_HAS_SILABS_GECKO_WDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT select SOC_GECKO_WDOG - default y help Enable WDOG driver for Silicon Labs Gecko MCUs. diff --git a/drivers/watchdog/Kconfig.it8xxx2 b/drivers/watchdog/Kconfig.it8xxx2 index 1ef3ad194494d..e042ded8b47ec 100644 --- a/drivers/watchdog/Kconfig.it8xxx2 +++ b/drivers/watchdog/Kconfig.it8xxx2 @@ -5,6 +5,7 @@ config WDT_ITE_IT8XXX2 bool "ITE it8xxx2 Watchdog Timer (WDT) driver" default y depends on DT_HAS_ITE_IT8XXX2_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help This option enables the Watchdog Timer driver for ITE it8xxx2. This driver supports only one channel that id is 0 and 16-bits diff --git a/drivers/watchdog/Kconfig.npcx b/drivers/watchdog/Kconfig.npcx index 8d25067be8c22..f69a70c8db571 100644 --- a/drivers/watchdog/Kconfig.npcx +++ b/drivers/watchdog/Kconfig.npcx @@ -7,17 +7,17 @@ config WDT_NPCX bool "Nuvoton NPCX embedded controller (EC) Watchdog Timer driver" default y depends on DT_HAS_NUVOTON_NPCX_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help This option enables the Watchdog Timer driver for NPCX family of processors. Say y if you wish to use watchdog on NPCX MCU. -config WDT_NPCX_DELAY_CYCLES - int "Number of delay cycles before generating watchdog event/signal" +config WDT_NPCX_WARNING_LEADING_TIME_MS + int "Milliseconds before generating watchdog event/signal" depends on WDT_NPCX - range 1 255 - default 10 + default 500 help This option defines the window in which a watchdog event must be - handled, in units of 31ms. After this time window, the watchdog reset - triggers immediately. + handled. After this time window, the watchdog reset triggers + immediately. diff --git a/drivers/watchdog/Kconfig.nrfx b/drivers/watchdog/Kconfig.nrfx index 2967fe8648901..61f42d8ff3167 100644 --- a/drivers/watchdog/Kconfig.nrfx +++ b/drivers/watchdog/Kconfig.nrfx @@ -11,7 +11,11 @@ config WDT_NRFX select NRFX_WDT1 if HAS_HW_NRF_WDT1 select NRFX_WDT30 if HAS_HW_NRF_WDT30 select NRFX_WDT31 if HAS_HW_NRF_WDT31 + select NRFX_WDT010 if HAS_HW_NRF_WDT010 + select NRFX_WDT011 if HAS_HW_NRF_WDT011 select NRFX_WDT130 if HAS_HW_NRF_WDT130 + select NRFX_WDT131 if HAS_HW_NRF_WDT131 + select NRFX_WDT132 if HAS_HW_NRF_WDT132 help Enable support for nrfx WDT driver for nRF MCU series. diff --git a/drivers/watchdog/Kconfig.rpi_pico b/drivers/watchdog/Kconfig.rpi_pico index 2c99d50fdd1e2..a48d1c49fef1b 100644 --- a/drivers/watchdog/Kconfig.rpi_pico +++ b/drivers/watchdog/Kconfig.rpi_pico @@ -5,6 +5,7 @@ config WDT_RPI_PICO bool "Raspberry Pi Pico Watchdog driver" default y depends on DT_HAS_RASPBERRYPI_PICO_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT config WDT_RPI_PICO_INITIAL_TIMEOUT int "Default watchdog timeout in us" diff --git a/drivers/watchdog/Kconfig.sam b/drivers/watchdog/Kconfig.sam index 9cfd452532423..3556a46ff8726 100644 --- a/drivers/watchdog/Kconfig.sam +++ b/drivers/watchdog/Kconfig.sam @@ -7,5 +7,6 @@ config WDT_SAM bool "Atmel SAM MCU Family Watchdog (WDT) Driver" default y depends on DT_HAS_ATMEL_SAM_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable WDT driver for Atmel SAM MCUs. diff --git a/drivers/watchdog/Kconfig.sam0 b/drivers/watchdog/Kconfig.sam0 index 381a5347b9c5a..a7ac15c68a218 100644 --- a/drivers/watchdog/Kconfig.sam0 +++ b/drivers/watchdog/Kconfig.sam0 @@ -7,5 +7,6 @@ config WDT_SAM0 bool "Atmel SAM0 series Watchdog (WDT) Driver" default y depends on DT_HAS_ATMEL_SAM0_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable WDT driver for Atmel SAM0 MCUs. diff --git a/drivers/watchdog/Kconfig.sifive b/drivers/watchdog/Kconfig.sifive index 79623237b3750..43357cc7e0808 100644 --- a/drivers/watchdog/Kconfig.sifive +++ b/drivers/watchdog/Kconfig.sifive @@ -7,5 +7,6 @@ config WDT_SIFIVE bool "SiFive Watchdog (WDT) Driver" default y depends on DT_HAS_SIFIVE_WDT_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help This option enables WDT driver for SiFive Freedom. diff --git a/drivers/watchdog/Kconfig.smartbond b/drivers/watchdog/Kconfig.smartbond index 5cf82ba5514e2..9978a8332cbbe 100644 --- a/drivers/watchdog/Kconfig.smartbond +++ b/drivers/watchdog/Kconfig.smartbond @@ -7,6 +7,7 @@ config WDT_SMARTBOND bool "Watchdog Driver for Smartbond family of MCUs" default y depends on DT_HAS_RENESAS_SMARTBOND_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable watchdog driver for Smartbond line of MCUs diff --git a/drivers/watchdog/Kconfig.stm32 b/drivers/watchdog/Kconfig.stm32 index af5a964f9a698..87ace6ba59bc0 100644 --- a/drivers/watchdog/Kconfig.stm32 +++ b/drivers/watchdog/Kconfig.stm32 @@ -9,6 +9,7 @@ config IWDG_STM32 bool "Independent Watchdog (IWDG) Driver for STM32 family of MCUs" default y depends on DT_HAS_ST_STM32_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable IWDG driver for STM32 line of MCUs diff --git a/drivers/watchdog/Kconfig.tco b/drivers/watchdog/Kconfig.tco index 2e479e37efd9f..7439ffbc8918c 100644 --- a/drivers/watchdog/Kconfig.tco +++ b/drivers/watchdog/Kconfig.tco @@ -7,5 +7,6 @@ config WDT_TCO bool "Intel TCO Watchdog driver" default y depends on DT_HAS_INTEL_TCO_WDT_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable support for Intel TCO WDT driver. diff --git a/drivers/watchdog/Kconfig.xec b/drivers/watchdog/Kconfig.xec index 7de929517005d..78e6bb616ae33 100644 --- a/drivers/watchdog/Kconfig.xec +++ b/drivers/watchdog/Kconfig.xec @@ -7,5 +7,6 @@ config WDT_XEC bool "Microchip XEC series Watchdog Timer (WDT) driver" default y depends on DT_HAS_MICROCHIP_XEC_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable WDT driver for Microchip XEC MCU series. diff --git a/drivers/watchdog/Kconfig.xmc4xxx b/drivers/watchdog/Kconfig.xmc4xxx index 8c18d06da0d24..de677089d4d07 100644 --- a/drivers/watchdog/Kconfig.xmc4xxx +++ b/drivers/watchdog/Kconfig.xmc4xxx @@ -7,6 +7,7 @@ config WDT_XMC4XXX bool "Infineon XMC4xxx MCU Family Watchdog (WDT) Driver" default y depends on DT_HAS_INFINEON_XMC4XXX_WATCHDOG_ENABLED + select HAS_WDT_DISABLE_AT_BOOT help Enable WDT driver for Infineon XMC4xxx MCUs. diff --git a/drivers/watchdog/wdt_ambiq.c b/drivers/watchdog/wdt_ambiq.c index 5e3cf663b8e18..91929c91e20ff 100644 --- a/drivers/watchdog/wdt_ambiq.c +++ b/drivers/watchdog/wdt_ambiq.c @@ -35,10 +35,13 @@ static void wdt_ambiq_isr(void *arg) const struct device *dev = (const struct device *)arg; struct wdt_ambiq_data *data = dev->data; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_wdt_int_clear(); +#else uint32_t status; - am_hal_wdt_interrupt_status_get(AM_HAL_WDT_MCU, &status, false); am_hal_wdt_interrupt_clear(AM_HAL_WDT_MCU, status); +#endif if (data->callback) { data->callback(dev, 0); @@ -51,6 +54,25 @@ static int wdt_ambiq_setup(const struct device *dev, uint8_t options) struct wdt_ambiq_data *data = dev->data; am_hal_wdt_config_t cfg; +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + uint32_t ui32ClockSource = AM_HAL_WDT_LFRC_CLK_DEFAULT; + + if (dev_cfg->clk_freq == 128) { + ui32ClockSource = AM_HAL_WDT_LFRC_CLK_128HZ; + } else if (dev_cfg->clk_freq == 16) { + ui32ClockSource = AM_HAL_WDT_LFRC_CLK_16HZ; + } else if (dev_cfg->clk_freq == 1) { + ui32ClockSource = AM_HAL_WDT_LFRC_CLK_1HZ; + } + cfg.ui32Config = ui32ClockSource | _VAL2FLD(WDT_CFG_RESEN, data->reset) | + AM_HAL_WDT_ENABLE_INTERRUPT; + cfg.ui16InterruptCount = data->timeout; + cfg.ui16ResetCount = data->timeout; + am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_LFRC_START, 0); + am_hal_wdt_init(&cfg); + am_hal_wdt_int_enable(); + am_hal_wdt_start(); +#else if (dev_cfg->clk_freq == 128) { cfg.eClockSource = AM_HAL_WDT_128HZ; } else if (dev_cfg->clk_freq == 16) { @@ -68,7 +90,7 @@ static int wdt_ambiq_setup(const struct device *dev, uint8_t options) am_hal_wdt_config(AM_HAL_WDT_MCU, &cfg); am_hal_wdt_interrupt_enable(AM_HAL_WDT_MCU, AM_HAL_WDT_INTERRUPT_MCU); am_hal_wdt_start(AM_HAL_WDT_MCU, false); - +#endif return 0; } @@ -76,8 +98,11 @@ static int wdt_ambiq_disable(const struct device *dev) { ARG_UNUSED(dev); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_wdt_halt(); +#else am_hal_wdt_stop(AM_HAL_WDT_MCU); - +#endif return 0; } @@ -114,7 +139,11 @@ static int wdt_ambiq_feed(const struct device *dev, int channel_id) ARG_UNUSED(dev); ARG_UNUSED(channel_id); +#if defined(CONFIG_SOC_SERIES_APOLLO3X) + am_hal_wdt_restart(); +#else am_hal_wdt_restart(AM_HAL_WDT_MCU); +#endif LOG_DBG("Fed the watchdog"); return 0; diff --git a/drivers/watchdog/wdt_andes_atcwdt200.c b/drivers/watchdog/wdt_andes_atcwdt200.c index 5fca002680502..899f2cfac51b3 100644 --- a/drivers/watchdog/wdt_andes_atcwdt200.c +++ b/drivers/watchdog/wdt_andes_atcwdt200.c @@ -332,14 +332,14 @@ static int wdt_atcwdt200_init(const struct device *dev) ret = syscon_write_reg(syscon_dev, SMU_RESET_REGLO, ((uint32_t)((unsigned long) - Z_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY)))); + K_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY)))); if (ret < 0) { return -EINVAL; } ret = syscon_write_reg(syscon_dev, SMU_RESET_REGHI, ((uint32_t)((uint64_t)((unsigned long) - Z_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY)) >> 32))); + K_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY)) >> 32))); if (ret < 0) { return -EINVAL; } diff --git a/drivers/watchdog/wdt_esp32.c b/drivers/watchdog/wdt_esp32.c index 460f130c1b5f5..f5ef51fad0271 100644 --- a/drivers/watchdog/wdt_esp32.c +++ b/drivers/watchdog/wdt_esp32.c @@ -7,7 +7,11 @@ #define DT_DRV_COMPAT espressif_esp32_watchdog /* Include esp-idf headers first to avoid redefining BIT() macro */ +#if defined(CONFIG_SOC_SERIES_ESP32C6) +#include +#else #include +#endif #include #include #include @@ -15,17 +19,17 @@ #include #include #include -#ifndef CONFIG_SOC_SERIES_ESP32C3 -#include -#else +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #include +#else +#include #endif #include #include LOG_MODULE_REGISTER(wdt_esp32, CONFIG_WDT_LOG_LEVEL); -#ifdef CONFIG_SOC_SERIES_ESP32C3 +#if defined(CONFIG_SOC_SERIES_ESP32C3) || defined(CONFIG_SOC_SERIES_ESP32C6) #define ISR_HANDLER isr_handler_t #else #define ISR_HANDLER intr_handler_t diff --git a/drivers/watchdog/wdt_handlers.c b/drivers/watchdog/wdt_handlers.c index 2ac872f1379d7..727b51251eee5 100644 --- a/drivers/watchdog/wdt_handlers.c +++ b/drivers/watchdog/wdt_handlers.c @@ -13,7 +13,7 @@ static inline int z_vrfy_wdt_setup(const struct device *dev, uint8_t options) return z_impl_wdt_setup(dev, options); } -#include +#include static inline int z_vrfy_wdt_disable(const struct device *dev) { @@ -21,7 +21,7 @@ static inline int z_vrfy_wdt_disable(const struct device *dev) return z_impl_wdt_disable(dev); } -#include +#include static inline int z_vrfy_wdt_feed(const struct device *dev, int channel_id) { @@ -29,4 +29,4 @@ static inline int z_vrfy_wdt_feed(const struct device *dev, int channel_id) return z_impl_wdt_feed(dev, channel_id); } -#include +#include diff --git a/drivers/watchdog/wdt_iwdg_stm32.c b/drivers/watchdog/wdt_iwdg_stm32.c index bafd8f579df6c..6c6846abf61fa 100644 --- a/drivers/watchdog/wdt_iwdg_stm32.c +++ b/drivers/watchdog/wdt_iwdg_stm32.c @@ -99,6 +99,8 @@ static int iwdg_stm32_setup(const struct device *dev, uint8_t options) #endif #if defined(CONFIG_SOC_SERIES_STM32H7X) LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_IWDG1_STOP); +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) + LL_DBGMCU_APB4_GRP1_FreezePeriph(LL_DBGMCU_APB4_GRP1_IWDG_STOP); #else LL_DBGMCU_APB1_GRP1_FreezePeriph(LL_DBGMCU_APB1_GRP1_IWDG_STOP); #endif diff --git a/drivers/watchdog/wdt_npcx.c b/drivers/watchdog/wdt_npcx.c index 482bbd1c7334b..31aadd86345a1 100644 --- a/drivers/watchdog/wdt_npcx.c +++ b/drivers/watchdog/wdt_npcx.c @@ -46,10 +46,13 @@ LOG_MODULE_REGISTER(wdt_npcx, CONFIG_WDT_LOG_LEVEL); #define NPCX_WDT_CLK LFCLK /* - * Maximum watchdog window time. Since the watchdog counter is 8-bits, maximum - * time supported by npcx watchdog is 256 * (32 * 32) / 32768 = 8 sec. + * Maximum watchdog window time. Keep the timer and watchdog clock prescaler + * (TWCP) to 0x5. Since the watchdog counter is 8-bits, maximum time supported + * by npcx watchdog is 256 * (32 * 32768) / 32768 = 8192 sec. + * The maximum time supported of T0OUT is 65536 * 32 / 32768 = 64 sec. + * Thus, the maximum time of watchdog set here is 64 sec. */ -#define NPCX_WDT_MAX_WND_TIME 8000UL +#define NPCX_WDT_MAX_WND_TIME 64000UL /* * Minimum watchdog window time. Ensure we have waited at least 3 watchdog @@ -139,7 +142,7 @@ static void wdt_t0out_isr(const struct device *dev, struct npcx_wui *wui) ARG_UNUSED(wui); LOG_DBG("WDT reset will issue after %d delay cycle! WUI(%d %d %d)", - CONFIG_WDT_NPCX_DELAY_CYCLES, wui->table, wui->group, wui->bit); + CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS, wui->table, wui->group, wui->bit); /* Handle watchdog event here. */ if (data->cb) { @@ -208,6 +211,9 @@ static int wdt_npcx_setup(const struct device *dev, uint8_t options) struct twd_reg *const inst = HAL_INSTANCE(dev); const struct wdt_npcx_config *const config = dev->config; struct wdt_npcx_data *const data = dev->data; + uint32_t wd_cnt, pre_scal; + uint8_t wdcp; + int rv; /* Disable irq of t0-out expired event first */ @@ -242,9 +248,24 @@ static int wdt_npcx_setup(const struct device *dev, uint8_t options) inst->TWDT0 = MAX(DIV_ROUND_UP(data->timeout * NPCX_WDT_CLK, 32 * 1000) - 1, 1); - /* Configure 8-bit watchdog counter */ - inst->WDCNT = MIN(DIV_ROUND_UP(data->timeout, 32) + - CONFIG_WDT_NPCX_DELAY_CYCLES, 0xff); + /* Configure 8-bit watchdog counter + * Change the prescaler of watchdog clock for larger timeout + */ + wd_cnt = DIV_ROUND_UP((data->timeout + CONFIG_WDT_NPCX_WARNING_LEADING_TIME_MS) * + NPCX_WDT_CLK, + 32 * 1000); + + pre_scal = DIV_ROUND_UP(wd_cnt, 255); + + /* + * Find the smallest power of 2 greater than or equal to the + * prescaler + */ + wdcp = LOG2(pre_scal - 1) + 1; + pre_scal = 1 << wdcp; + + inst->WDCP = wdcp; + inst->WDCNT = wd_cnt / pre_scal; LOG_DBG("WDT setup: TWDT0, WDCNT are %d, %d", inst->TWDT0, inst->WDCNT); @@ -265,12 +286,14 @@ static int wdt_npcx_disable(const struct device *dev) const struct wdt_npcx_config *const config = dev->config; struct wdt_npcx_data *const data = dev->data; struct twd_reg *const inst = HAL_INSTANCE(dev); + uint16_t min_wnd_t; /* * Ensure we have waited at least 3 watchdog ticks before * stopping watchdog */ - while (k_uptime_get() - data->last_watchdog_touch < NPCX_WDT_MIN_WND_TIME) { + min_wnd_t = DIV_ROUND_UP(3 * NPCX_WDT_CLK, 32 * (1 << inst->WDCP)); + while (k_uptime_get() - data->last_watchdog_touch < min_wnd_t) { continue; } diff --git a/drivers/watchdog/wdt_nrfx.c b/drivers/watchdog/wdt_nrfx.c index 57b4dba828c7f..1c23c9452b41a 100644 --- a/drivers/watchdog/wdt_nrfx.c +++ b/drivers/watchdog/wdt_nrfx.c @@ -60,7 +60,9 @@ static int wdt_nrf_disable(const struct device *dev) { #if NRFX_WDT_HAS_STOP const struct wdt_nrfx_config *config = dev->config; + struct wdt_nrfx_data *data = dev->data; nrfx_err_t err_code; + int channel_id; err_code = nrfx_wdt_stop(&config->wdt); @@ -69,6 +71,13 @@ static int wdt_nrf_disable(const struct device *dev) return -EFAULT; } + nrfx_wdt_channels_free(&config->wdt); + + for (channel_id = 0; channel_id < data->m_allocated_channels; channel_id++) { + data->m_callbacks[channel_id] = NULL; + } + data->m_allocated_channels = 0; + return 0; #else ARG_UNUSED(dev); @@ -220,6 +229,22 @@ WDT_NRFX_WDT_DEVICE(30); WDT_NRFX_WDT_DEVICE(31); #endif +#ifdef CONFIG_HAS_HW_NRF_WDT010 +WDT_NRFX_WDT_DEVICE(010); +#endif + +#ifdef CONFIG_HAS_HW_NRF_WDT011 +WDT_NRFX_WDT_DEVICE(011); +#endif + #ifdef CONFIG_HAS_HW_NRF_WDT130 WDT_NRFX_WDT_DEVICE(130); #endif + +#ifdef CONFIG_HAS_HW_NRF_WDT131 +WDT_NRFX_WDT_DEVICE(131); +#endif + +#ifdef CONFIG_HAS_HW_NRF_WDT132 +WDT_NRFX_WDT_DEVICE(132); +#endif diff --git a/drivers/watchdog/xt_wdt_esp32.c b/drivers/watchdog/xt_wdt_esp32.c new file mode 100644 index 0000000000000..7e0141d02664c --- /dev/null +++ b/drivers/watchdog/xt_wdt_esp32.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#define DT_DRV_COMPAT espressif_esp32_xt_wdt + +#include +#include +#include + +#include +#include +#include +#include + +#ifndef CONFIG_SOC_SERIES_ESP32C3 +#include +#else +#include +#endif +#include +#include + +LOG_MODULE_REGISTER(xt_wdt_esp32, CONFIG_WDT_LOG_LEVEL); + +#ifdef CONFIG_SOC_SERIES_ESP32C3 +#define ISR_HANDLER isr_handler_t +#else +#define ISR_HANDLER intr_handler_t +#endif + +#define ESP32_XT_WDT_MAX_TIMEOUT 255 + +struct esp32_xt_wdt_data { + xt_wdt_hal_context_t hal; + wdt_callback_t callback; + uint32_t timeout; +}; + +struct esp32_xt_wdt_config { + const struct device *clock_dev; + const clock_control_subsys_t clock_subsys; + int irq_source; +}; + +static int esp32_xt_wdt_setup(const struct device *dev, uint8_t options) +{ + ARG_UNUSED(options); + struct esp32_xt_wdt_data *data = dev->data; + + xt_wdt_hal_config_t xt_wdt_hal_config = { + .timeout = data->timeout, + }; + + xt_wdt_hal_init(&data->hal, &xt_wdt_hal_config); + xt_wdt_hal_enable(&data->hal, true); + + return 0; +} + +static int esp32_xt_wdt_disable(const struct device *dev) +{ + struct esp32_xt_wdt_data *data = dev->data; + + xt_wdt_hal_enable(&data->hal, false); + + return 0; +} + +static int esp32_xt_wdt_feed(const struct device *dev, int channel_id) +{ + ARG_UNUSED(dev); + ARG_UNUSED(channel_id); + + return -ENOSYS; +} + +static int esp32_xt_wdt_install_timeout(const struct device *dev, + const struct wdt_timeout_cfg *cfg) +{ + struct esp32_xt_wdt_data *data = dev->data; + + if (cfg->window.min != 0U || cfg->window.max == 0U || + cfg->window.max >= ESP32_XT_WDT_MAX_TIMEOUT) { + LOG_ERR("Invalid timeout configuration"); + return -EINVAL; + } + + data->timeout = cfg->window.max; + data->callback = cfg->callback; + + return 0; +} + +static void esp32_xt_wdt_isr(void *arg) +{ + const struct device *dev = (const struct device *)arg; + const struct esp32_xt_wdt_config *cfg = dev->config; + struct esp32_xt_wdt_data *data = dev->data; + struct esp32_clock_config clk_cfg = {0}; + uint32_t status = REG_READ(RTC_CNTL_INT_ST_REG); + + REG_WRITE(RTC_CNTL_INT_CLR_REG, status); + + clk_cfg.rtc.rtc_slow_clock_src = ESP32_RTC_SLOW_CLK_SRC_RC_SLOW; + + clock_control_configure(cfg->clock_dev, + (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW, + &clk_cfg); + + if (data->callback != NULL) { + data->callback(dev, 0); + } +} + +static int esp32_xt_wdt_init(const struct device *dev) +{ + const struct esp32_xt_wdt_config *cfg = dev->config; + struct esp32_xt_wdt_data *data = dev->data; + xt_wdt_hal_config_t xt_wdt_hal_config = { + .timeout = ESP32_XT_WDT_MAX_TIMEOUT, + }; + + xt_wdt_hal_init(&data->hal, &xt_wdt_hal_config); + xt_wdt_hal_enable_backup_clk(&data->hal, + ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ/1000); + + int err = esp_intr_alloc(cfg->irq_source, 0, (ISR_HANDLER)esp32_xt_wdt_isr, (void *)dev, + NULL); + if (err) { + LOG_ERR("Failed to register ISR\n"); + return -EFAULT; + } + + REG_WRITE(RTC_CNTL_INT_ENA_REG, 0); + REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX); + + return 0; +} + +static const struct wdt_driver_api esp32_xt_wdt_api = { + .setup = esp32_xt_wdt_setup, + .disable = esp32_xt_wdt_disable, + .install_timeout = esp32_xt_wdt_install_timeout, + .feed = esp32_xt_wdt_feed +}; + +static struct esp32_xt_wdt_data esp32_xt_wdt_data0; + +static struct esp32_xt_wdt_config esp32_xt_wdt_config0 = { + .clock_dev = DEVICE_DT_GET(DT_INST_CLOCKS_CTLR(0)), + .clock_subsys = (clock_control_subsys_t)DT_INST_CLOCKS_CELL(0, offset), + .irq_source = DT_INST_IRQN(0), +}; + +DEVICE_DT_DEFINE(DT_NODELABEL(xt_wdt), + &esp32_xt_wdt_init, + NULL, + &esp32_xt_wdt_data0, + &esp32_xt_wdt_config0, + POST_KERNEL, + CONFIG_KERNEL_INIT_PRIORITY_DEVICE, + &esp32_xt_wdt_api); + +#if !(defined(CONFIG_SOC_SERIES_ESP32S2) || \ + defined(CONFIG_SOC_SERIES_ESP32S3) || \ + defined(CONFIG_SOC_SERIES_ESP32C3)) +#error "XT WDT is not supported" +#else +BUILD_ASSERT((DT_PROP(DT_INST(0, espressif_esp32_rtc), slow_clk_src) == + ESP32_RTC_SLOW_CLK_SRC_XTAL32K) || + (DT_PROP(DT_INST(0, espressif_esp32_rtc), slow_clk_src) == + ESP32_RTC_SLOW_CLK_32K_EXT_OSC), + "XT WDT is only supported with XTAL32K or 32K_EXT_OSC as slow clock source"); +#endif diff --git a/drivers/wifi/esp32/Kconfig.esp32 b/drivers/wifi/esp32/Kconfig.esp32 index 2efbbba1ce551..2805f5b2ce48f 100644 --- a/drivers/wifi/esp32/Kconfig.esp32 +++ b/drivers/wifi/esp32/Kconfig.esp32 @@ -9,12 +9,6 @@ menuconfig WIFI_ESP32 select NET_L2_WIFI_MGMT select WIFI_USE_NATIVE_NETWORKING select MBEDTLS - select MBEDTLS_ENTROPY_ENABLED - select MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - select MBEDTLS_ECP_ALL_ENABLED - select MBEDTLS_ECDH_C - select MBEDTLS_ECDSA_C - select MBEDTLS_ECP_C select THREAD_STACK_INFO select DYNAMIC_THREAD select DYNAMIC_THREAD_ALLOC @@ -275,7 +269,7 @@ config ESP32_WIFI_MBEDTLS_CRYPTO select MBEDTLS_PKCS5_C select MBEDTLS_PK_WRITE_C select MBEDTLS_CIPHER_MODE_CTR_ENABLED - select MBEDTLS_MAC_CMAC_ENABLED + select MBEDTLS_CMAC select MBEDTLS_ZEPHYR_ENTROPY help Select this option to use MbedTLS crypto APIs which utilize hardware acceleration. diff --git a/drivers/wifi/esp32/src/esp_wifi_drv.c b/drivers/wifi/esp32/src/esp_wifi_drv.c index 5c17f1b4dd6bc..1ebb3a03760df 100644 --- a/drivers/wifi/esp32/src/esp_wifi_drv.c +++ b/drivers/wifi/esp32/src/esp_wifi_drv.c @@ -182,6 +182,10 @@ static void scan_done_handler(void) strncpy(res.ssid, ap_list_buffer[k].ssid, ssid_len); res.rssi = ap_list_buffer[k].rssi; res.channel = ap_list_buffer[k].primary; + + memcpy(res.mac, ap_list_buffer[k].bssid, WIFI_MAC_ADDR_LEN); + res.mac_length = WIFI_MAC_ADDR_LEN; + switch (ap_list_buffer[k].authmode) { case WIFI_AUTH_OPEN: res.security = WIFI_SECURITY_TYPE_NONE; diff --git a/drivers/wifi/esp_at/esp.c b/drivers/wifi/esp_at/esp.c index 2261a11f714a1..ff32e3884efa2 100644 --- a/drivers/wifi/esp_at/esp.c +++ b/drivers/wifi/esp_at/esp.c @@ -256,7 +256,7 @@ MODEM_CMD_DEFINE(on_cmd_cipstamac) static int esp_pull_quoted(char **str, char *str_end, char **unquoted) { if (**str != '"') { - return -EBADMSG; + return -EAGAIN; } (*str)++; diff --git a/drivers/wifi/infineon/Kconfig.airoc b/drivers/wifi/infineon/Kconfig.airoc index a3eac53862d54..319253378d318 100644 --- a/drivers/wifi/infineon/Kconfig.airoc +++ b/drivers/wifi/infineon/Kconfig.airoc @@ -116,11 +116,11 @@ choice CYW4373_MODULE config CYW4373_STERLING_LWB5PLUS bool "STERLING-LWB5plus" help - Laird Sterling LWB5+ 802.11ac / Bluetooth 5.0 M.2 Carrier Board + Ezurio Sterling LWB5+ 802.11ac / Bluetooth 5.0 M.2 Carrier Board (E-Type Key w/ SDIO/UART) Detailed information about Type Sterling LWB5+ module you can find on - https://www.lairdconnect.com/wireless-modules/wifi-modules-bluetooth/sterling-lwb5-plus-wifi-5-bluetooth-5-module + https://www.ezurio.com/wireless-modules/wifi-modules-bluetooth/sterling-lwb5-plus-wifi-5-bluetooth-5-module endchoice choice CYW43439_MODULE diff --git a/drivers/wifi/simplelink/Kconfig.simplelink b/drivers/wifi/simplelink/Kconfig.simplelink index f2c5ccacbab31..c325a50f2cd4e 100644 --- a/drivers/wifi/simplelink/Kconfig.simplelink +++ b/drivers/wifi/simplelink/Kconfig.simplelink @@ -9,6 +9,7 @@ menuconfig WIFI_SIMPLELINK select WIFI_OFFLOAD select NET_L2_WIFI_MGMT select FDTABLE + select POSIX_SEMAPHORES if WIFI_SIMPLELINK diff --git a/dts/arm/adi/max32/max32655-pinctrl.dtsi b/dts/arm/adi/max32/max32655-pinctrl.dtsi new file mode 100644 index 0000000000000..c336e402afcc7 --- /dev/null +++ b/dts/arm/adi/max32/max32655-pinctrl.dtsi @@ -0,0 +1,407 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + pinctrl: pin-controller@40008000 { + + /omit-if-no-ref/ uart0a_rx_p0_0: uart0a_rx_p0_0 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_tx_p0_1: uart0a_tx_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0a_ioa_p0_2: tmr0a_ioa_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_cts_p0_2: uart0b_cts_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ ext_clk_p0_3: ext_clk_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_rts_p0_3: uart0b_rts_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0_ss0_p0_4: spi0_ss0_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_ioan_p0_4: tmr0b_ioan_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0_mosi_p0_5: spi0_mosi_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_iobn_p0_5: tmr0b_iobn_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0_miso_p0_6: spi0_miso_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_io_p0_6: owm_io_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0_sck_p0_7: spi0_sck_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_pe_p0_7: owm_pe_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0_sdio2_p0_8: spi0_sdio2_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_ioa_p0_8: tmr0b_ioa_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0_sdio3_p0_9: spi0_sdio3_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_iob_p0_9: tmr0b_iob_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0_scl_p0_10: i2c0_scl_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0_ss2_p0_10: spi0_ss2_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0_sda_p0_11: i2c0_sda_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0_ss1_p0_11: spi0_ss1_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rx_p0_12: uart1a_rx_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_ioan_p0_12: tmr1b_ioan_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_tx_p0_13: uart1a_tx_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_iobn_p0_13: tmr1b_iobn_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1a_ioa_p0_14: tmr1a_ioa_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_cts_p0_14: uart1b_cts_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1a_iob_p0_15: tmr1a_iob_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_rts_p0_15: uart1b_rts_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1_scl_p0_16: i2c1_scl_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ pt2_p0_16: pt2_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1_sda_p0_17: i2c1_sda_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ pt3_p0_17: pt3_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ pt0_p0_18: pt0_p0_18 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_io_p0_18: owm_io_p0_18 { + pinmux = ; + }; + + /omit-if-no-ref/ pt1_p0_19: pt1_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_pe_p0_19: owm_pe_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_ss0_p0_20: spi1_ss0_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_ioa_p0_20: tmr1b_ioa_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_mosi_p0_21: spi1_mosi_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_iob_p0_21: tmr1b_iob_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_miso_p0_22: spi1_miso_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_ioan_p0_22: tmr1b_ioan_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_sck_p0_23: spi1_sck_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_iobn_p0_23: tmr1b_iobn_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_sdio2_p0_24: spi1_sdio2_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_ioa_p0_24: tmr2b_ioa_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_sdio3_p0_25: spi1_sdio3_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_iob_p0_25: tmr2b_iob_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2a_ioa_p0_26: tmr2a_ioa_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_ss1_p0_26: spi1_ss1_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2a_iob_p0_27: tmr2a_iob_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_ss2_p0_27: spi1_ss2_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ swdio_p0_28: swdio_p0_28 { + pinmux = ; + }; + + /omit-if-no-ref/ swclk_p0_29: swclk_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2_scl_p0_30: i2c2_scl_p0_30 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_cts_p0_30: uart2b_cts_p0_30 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2_sda_p0_31: i2c2_sda_p0_31 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_rts_p0_31: uart2b_rts_p0_31 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rx_p1_0: uart2a_rx_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tck_p1_0: rv_tck_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_tx_p1_1: uart2a_tx_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tms_p1_1: rv_tms_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s_sck_p1_2: i2s_sck_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdi_p1_2: rv_tdi_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s_ws_p1_3: i2s_ws_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdo_p1_3: rv_tdo_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s_sdi_p1_4: i2s_sdi_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3b_ioa_p1_4: tmr3b_ioa_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s_sdo_p1_5: i2s_sdo_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3b_iob_p1_5: tmr3b_iob_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_ioa_p1_6: tmr3a_ioa_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl2_p1_6: ble_ant_ctrl2_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_iob_p1_7: tmr3a_iob_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl3_p1_7: ble_ant_ctrl3_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctr_p1_8: ble_ant_ctr_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ rxev0l0_p1_8: rxev0l0_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctr_p1_9: ble_ant_ctr_p1_9 { + pinmux = ; + }; + + /omit-if-no-ref/ txev0l1_p1_9: txev0l1_p1_9 { + pinmux = ; + }; + + /omit-if-no-ref/ ain0_p2_0: ain0_p2_0 { + pinmux = ; + }; + + /omit-if-no-ref/ ain1_p2_1: ain1_p2_1 { + pinmux = ; + }; + + /omit-if-no-ref/ ain2_p2_2: ain2_p2_2 { + pinmux = ; + }; + + /omit-if-no-ref/ ain3_p2_3: ain3_p2_3 { + pinmux = ; + }; + + /omit-if-no-ref/ ain4_p2_4: ain4_p2_4 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0b_ioa_p2_4: lptmr0b_ioa_p2_4 { + pinmux = ; + }; + + /omit-if-no-ref/ ain5_p2_5: ain5_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1b_ioa_p2_5: lptmr1b_ioa_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ ain6_p2_6: ain6_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0_clk_p2_6: lptmr0_clk_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuartb_rx_p2_6: lpuartb_rx_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ ain7_p2_7: ain7_p2_7 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1_clk_p2_7: lptmr1_clk_p2_7 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuartb_tx_p2_7: lpuartb_tx_p2_7 { + pinmux = ; + }; + + /omit-if-no-ref/ pdown_p3_0: pdown_p3_0 { + pinmux = ; + }; + + /omit-if-no-ref/ wakeup_p3_0: wakeup_p3_0 { + pinmux = ; + }; + + /omit-if-no-ref/ sqwout_p3_1: sqwout_p3_1 { + pinmux = ; + }; + + /omit-if-no-ref/ wakeup_p3_1: wakeup_p3_1 { + pinmux = ; + }; + + }; + }; +}; diff --git a/dts/arm/adi/max32/max32655.dtsi b/dts/arm/adi/max32/max32655.dtsi new file mode 100644 index 0000000000000..feacd93f09d87 --- /dev/null +++ b/dts/arm/adi/max32/max32655.dtsi @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&pinctrl { + reg = <0x40008000 0x2400>; + + gpio2: gpio@40080400 { + reg = <0x40080400 0x200>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <26 0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 0>; + status = "disabled"; + }; + + gpio3: gpio@40080600 { + reg = <0x40080600 0x200>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <54 0>; + status = "disabled"; + }; +}; + +/* MAX32655 extra peripherals. */ +/ { + soc { + sram1: memory@20008000 { + compatible = "mmio-sram"; + reg = <0x20008000 DT_SIZE_K(32)>; + }; + + sram2: memory@20010000 { + compatible = "mmio-sram"; + reg = <0x20010000 DT_SIZE_K(48)>; + }; + + sram3: memory@2001c000 { + compatible = "mmio-sram"; + reg = <0x2001c000 DT_SIZE_K(16)>; + }; + + uart3: serial@40081400 { + compatible = "adi,max32-uart"; + reg = <0x40081400 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 4>; + clock-source = ; + interrupts = <88 0>; + status = "disabled"; + }; + }; +}; diff --git a/dts/arm/adi/max32/max32672-pinctrl.dtsi b/dts/arm/adi/max32/max32672-pinctrl.dtsi new file mode 100644 index 0000000000000..bbc737cc4d3cd --- /dev/null +++ b/dts/arm/adi/max32/max32672-pinctrl.dtsi @@ -0,0 +1,522 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + pinctrl: pin-controller@40008000 { + + /omit-if-no-ref/ swdio_p0_0: swdio_p0_0 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ia_p0_0: tmr0c_ia_p0_0 { + pinmux = ; + }; + + /omit-if-no-ref/ swdclk_p0_1: swdclk_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_oa_p0_1: tmr0c_oa_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_miso_p0_2: spi0a_miso_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_rx_p0_2: uart1b_rx_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ia_p0_2: tmr1c_ia_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_mosi_p0_3: spi0a_mosi_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_tx_p0_3: uart1b_tx_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_oa_p0_3: tmr1c_oa_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_sck_p0_4: spi0a_sck_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_cts_p0_4: uart1b_cts_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_ia_p0_4: tmr2c_ia_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_ss0_p0_5: spi0a_ss0_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_rts_p0_5: uart1b_rts_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_oa_p0_5: tmr2c_oa_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ hfx_clk_out_p0_5: hfx_clk_out_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_scl_p0_6: i2c0a_scl_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0b_ia_p0_6: lptmr0b_ia_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0c_ss1_p0_6: spi0c_ss1_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ qea_p0_6: qea_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_sda_p0_7: i2c0a_sda_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0b_oa_p0_7: lptmr0b_oa_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0c_ss2_p0_7: spi0c_ss2_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ qeb_p0_7: qeb_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_rx_p0_8: uart0a_rx_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sdo_p0_8: i2s0a_sdo_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ia_p0_8: tmr0c_ia_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ ain0_p0_8: ain0_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_tx_p0_9: uart0a_tx_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_lrclk_p0_9: i2s0a_lrclk_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_oa_p0_9: tmr0c_oa_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_n_p0_9: ain_c0_n_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_cts_p0_10: uart0a_cts_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_bcllk_p0_10: i2s0a_bcllk_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ia_p0_10: tmr1c_ia_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_n_p0_10: ain_c0_n_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_rts_p0_11: uart0a_rts_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sdi_p0_11: i2s0a_sdi_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_oa_p0_11: tmr1c_oa_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_n_p0_11: ain_c0_n_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_scl_p0_12: i2c1a_scl_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ ext_clk2_p0_12: ext_clk2_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_ia_p0_12: tmr2c_ia_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_p_p0_12: ain_c0_p_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_sda_p0_13: i2c1a_sda_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ cal32k_p0_13: cal32k_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_oa_p0_13: tmr2c_oa_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_p_p0_13: ain_c0_p_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_miso_p0_14: spi1a_miso_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_rx_p0_14: uart2b_rx_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ia_p0_14: tmr3c_ia_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_p_p0_14: ain_c0_p_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_mosi_p0_15: spi1a_mosi_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_tx_p0_15: uart2b_tx_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_oa_p0_15: tmr3c_oa_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ ain_c0_p_p0_15: ain_c0_p_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_sck_p0_16: spi1a_sck_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_cts_p0_16: uart2b_cts_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ia_p0_16: tmr0c_ia_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ ain8_p0_16: ain8_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_ss0_p0_17: spi1a_ss0_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2b_rts_p0_17: uart2b_rts_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_oa_p0_17: tmr0c_oa_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ ain9_p0_17: ain9_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2a_scl_p0_18: i2c2a_scl_p0_18 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ia_p0_18: tmr1c_ia_p0_18 { + pinmux = ; + }; + + /omit-if-no-ref/ ain10_p0_18: ain10_p0_18 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2a_sda_p0_19: i2c2a_sda_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_oa_p0_19: tmr1c_oa_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ ain11_p0_19: ain11_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ cm4_rx_p0_20: cm4_rx_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_ia_p0_20: tmr2c_ia_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ cm4_tx_p0_21: cm4_tx_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_oa_p0_21: tmr2c_oa_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1a_ia_p0_22: lptmr1a_ia_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_b_p0_22: adc_trig_b_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ia_p0_22: tmr0c_ia_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1a_oa_p0_23: lptmr1a_oa_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0c_ss3_p0_23: spi0c_ss3_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ qei_p0_23: qei_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0a_cts_p0_24: lpuart0a_cts_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_rx_p0_24: uart0b_rx_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sd0_p0_24: i2s0a_sd0_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ qes_p0_24: qes_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0a_rts_p0_25: lpuart0a_rts_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_tx_p0_25: uart0b_tx_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_lrclk_p0_25: i2s0a_lrclk_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ qmatch_p0_25: qmatch_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0a_rx_p0_26: lpuart0a_rx_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_cts_p0_26: uart0b_cts_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_bclk_p0_26: i2s0c_bclk_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ qdir_p0_26: qdir_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0a_tx_p0_27: lpuart0a_tx_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_rts_p0_27: uart0b_rts_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_sdi_p0_27: i2s0c_sdi_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ qerr_p0_27: qerr_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rx_p0_28: uart1a_rx_p0_28 { + pinmux = ; + }; + + /omit-if-no-ref/ ext_clk1_p0_28: ext_clk1_p0_28 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ia_p0_28: tmr3c_ia_p0_28 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_tx_p0_29: uart1a_tx_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1_ss0_p0_29: spi1_ss0_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_oa_p0_29: tmr3c_oa_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_d_p0_29: adc_trig_d_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_cts_p0_30: uart1a_cts_p0_30 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ia_p0_30: tmr3c_ia_p0_30 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rts_p0_31: uart1a_rts_p0_31 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_oa_p0_31: tmr3c_oa_p0_31 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ia_p1_0: tmr1c_ia_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_miso_p1_1: spi2a_miso_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_rx_p1_1: uart0b_rx_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_oa_p1_1: tmr3c_oa_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_mosi_p1_2: spi2a_mosi_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_tx_p1_2: uart0b_tx_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ia_p1_2: tmr3c_ia_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ div_clk_out_p1_2: div_clk_out_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_sck_p1_3: spi2a_sck_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_cts_p1_3: uart0b_cts_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_ss0_p1_4: spi2a_ss0_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_rts_p1_4: uart0b_rts_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_oa_p1_4: tmr0c_oa_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_d_p1_4: adc_trig_d_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rx_p1_5: uart2a_rx_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_tx_p1_6: uart2a_tx_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_cts_p1_7: uart2a_cts_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rts_p1_8: uart2a_rts_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_oa_p1_9: tmr1c_oa_p1_9 { + pinmux = ; + }; + }; + }; +}; diff --git a/dts/arm/adi/max32/max32672.dtsi b/dts/arm/adi/max32/max32672.dtsi new file mode 100644 index 0000000000000..0845075cccaa8 --- /dev/null +++ b/dts/arm/adi/max32/max32672.dtsi @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&sram0 { + reg = <0x20000000 DT_SIZE_K(16)>; +}; + +&clk_inro { + clock-frequency = ; +}; + +/delete-node/ &clk_iso; + +/* MAX32672 extra peripherals. */ +/ { + soc { + sram1: memory@20004000 { + compatible = "mmio-sram"; + reg = <0x20004000 DT_SIZE_K(16)>; + }; + + sram2: memory@20008000 { + compatible = "mmio-sram"; + reg = <0x20008000 DT_SIZE_K(64)>; + }; + + sram3: memory@20018000 { + compatible = "mmio-sram"; + reg = <0x20018000 DT_SIZE_K(64)>; + }; + + sram4: memory@20028000 { + compatible = "mmio-sram"; + reg = <0x20028000 DT_SIZE_K(4)>; + }; + + sram5: memory@20029000 { + compatible = "mmio-sram"; + reg = <0x20029000 DT_SIZE_K(4)>; + }; + + sram6: memory@2002a000 { + compatible = "mmio-sram"; + reg = <0x2002a000 DT_SIZE_K(16)>; + }; + + sram7: memory@2002e000 { + compatible = "mmio-sram"; + reg = <0x2002e000 DT_SIZE_K(16)>; + }; + + flc1: flash_controller@40029400 { + compatible = "adi,max32-flash-controller"; + reg = <0x40029400 0x400>; + + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + flash1: flash@10080000 { + compatible = "soc-nv-flash"; + reg = <0x10080000 DT_SIZE_K(512)>; + write-block-size = <16>; + erase-block-size = <8192>; + }; + }; + + uart3: serial@40145000 { + compatible = "adi,max32-uart"; + reg = <0x40145000 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 2>; + clock-source = ; + interrupts = <88 0>; + status = "disabled"; + }; + }; +}; diff --git a/dts/arm/adi/max32/max32680-pinctrl.dtsi b/dts/arm/adi/max32/max32680-pinctrl.dtsi new file mode 100644 index 0000000000000..525666cb14c9d --- /dev/null +++ b/dts/arm/adi/max32/max32680-pinctrl.dtsi @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + pinctrl: pin-controller@40008000 { + + /omit-if-no-ref/ uart0a_rx_p0_0: uart0a_rx_p0_0 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_tx_p0_1: uart0a_tx_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0a_ioa_p0_2: tmr0a_ioa_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0b_cts_p0_2: uart0b_cts_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ ext_clk_p0_3: ext_clk_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_ss0_p0_4: spi0a_ss0_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_ioan_p0_4: tmr0b_ioan_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_mosi_p0_5: spi0a_mosi_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_iobn_p0_5: tmr0b_iobn_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_miso_p0_6: spi0a_miso_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_io_p0_6: owm_io_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_sck_p0_7: spi0a_sck_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_pe_p0_7: owm_pe_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_sdio2_p0_8: spi0a_sdio2_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_ioa_p0_8: tmr0b_ioa_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_sdio3_p0_9: spi0a_sdio3_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_iob_p0_9: tmr0b_iob_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_scl_p0_10: i2c0a_scl_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_ss2_p0_10: spi0b_ss2_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_sda_p0_11: i2c0a_sda_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_ss1_p0_11: spi0b_ss1_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rx_p0_12: uart1a_rx_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_ioa_p0_12: tmr1b_ioa_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_tx_p0_13: uart1a_tx_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_iobn_p0_13: tmr1b_iobn_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1a_ioa_p0_14: tmr1a_ioa_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_cts_p0_14: uart1b_cts_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1a_iob_p0_15: tmr1a_iob_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1b_rts_p0_15: uart1b_rts_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_scl_p0_16: i2c1a_scl_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ pt2_p0_16: pt2_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_sda_p0_17: i2c1a_sda_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ pt3_p0_17: pt3_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_sdio2_p0_24: spi1a_sdio2_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_ioa_p0_24: tmr2b_ioa_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ adc0_rdy_p0_24: adc0_rdy_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_sdio3_p0_25: spi1a_sdio3_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_iob_p0_25: tmr2b_iob_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ adc1_rdy_p0_25: adc1_rdy_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2a_ioa_p0_26: tmr2a_ioa_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1b_ss1_p0_26: spi1b_ss1_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2a_iob_p0_27: tmr2a_iob_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1b_ss2_p0_27: spi1b_ss2_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ swdio_p0_28: swdio_p0_28 { + pinmux = ; + }; + + /omit-if-no-ref/ swclk_p0_29: swclk_p0_29 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rx_p1_0: uart2a_rx_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tck_p1_0: rv_tck_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_tx_p1_1: uart2a_tx_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tms_p1_1: rv_tms_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sck_p1_2: i2s0a_sck_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdi_p1_2: rv_tdi_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_lrclk_p1_3: i2s0a_lrclk_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdo_p1_3: rv_tdo_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sdi_p1_4: i2s0a_sdi_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3b_ioa_p1_4: tmr3b_ioa_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0a_sdo_p1_5: i2s0a_sdo_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3b_iob_p1_5: tmr3b_iob_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_ioa_p1_6: tmr3a_ioa_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl2_p1_6: ble_ant_ctrl2_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_iob_p1_7: tmr3a_iob_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl3_p1_7: ble_ant_ctrl3_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ ain12_p2_4: ain12_p2_4 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0b_ioa_p2_4: lptmr0b_ioa_p2_4 { + pinmux = ; + }; + + /omit-if-no-ref/ ain13_p2_5: ain13_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1b_ioa_p2_5: lptmr1b_ioa_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0_clk_p2_6: lptmr0_clk_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuartb_r_p2_6: lpuartb_r_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ x_p2_6: x_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1_clk_p2_7: lptmr1_clk_p2_7 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuartb_tx_p2_7: lpuartb_tx_p2_7 { + pinmux = ; + }; + }; + }; +}; diff --git a/dts/arm/adi/max32/max32680.dtsi b/dts/arm/adi/max32/max32680.dtsi new file mode 100644 index 0000000000000..47c883b50b2bd --- /dev/null +++ b/dts/arm/adi/max32/max32680.dtsi @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&pinctrl { + reg = <0x40008000 0x2400>; + + gpio2: gpio@40080400 { + reg = <0x40080400 0x200>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <26 0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 0>; + status = "disabled"; + }; + + gpio3: gpio@40080600 { + reg = <0x40080600 0x200>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <54 0>; + status = "disabled"; + }; +}; + +/ { + soc { + sram1: memory@20008000 { + compatible = "mmio-sram"; + reg = <0x20008000 DT_SIZE_K(32)>; + }; + + sram2: memory@20010000 { + compatible = "mmio-sram"; + reg = <0x20010000 DT_SIZE_K(48)>; + }; + + sram3: memory@2001c000 { + compatible = "mmio-sram"; + reg = <0x2001c000 DT_SIZE_K(16)>; + }; + + uart3: serial@40081400 { + compatible = "adi,max32-uart"; + reg = <0x40081400 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 4>; + clock-source = ; + interrupts = <88 0>; + status = "disabled"; + }; + }; +}; diff --git a/dts/arm/adi/max32/max32690-pinctrl.dtsi b/dts/arm/adi/max32/max32690-pinctrl.dtsi new file mode 100644 index 0000000000000..18fab74ba2fcb --- /dev/null +++ b/dts/arm/adi/max32/max32690-pinctrl.dtsi @@ -0,0 +1,771 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + pinctrl: pin-controller@40008000 { + + /omit-if-no-ref/ spixr_sdio0_p0_1: spixr_sdio0_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sdio0_p0_1: spixf_sdio0_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2c_tx_p0_1: uart2c_tx_p0_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_sdio2_p0_2: spixr_sdio2_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sdio2_p0_2: spixf_sdio2_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2c_cts_p0_2: uart2c_cts_p0_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_sck_p0_3: spixr_sck_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sck_p0_3: spixf_sck_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2c_rts_p0_3: uart2c_rts_p0_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_sdio3_p0_4: spixr_sdio3_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sdio3_p0_4: spixf_sdio3_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ioa_p0_4: tmr0c_ioa_p0_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_sdio1_p0_5: spixr_sdio1_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_sdio1_p0_5: spixf_sdio1_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_iob_p0_5: tmr2c_iob_p0_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spixr_ss0_p0_6: spixr_ss0_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ spixf_ss0_p0_6: spixf_ss0_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2c_rx_p0_6: uart2c_rx_p0_6 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_pe_p0_7: owm_pe_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_ioa_p0_7: tmr1b_ioa_p0_7 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_io_p0_8: owm_io_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1b_iob_p0_8: tmr1b_iob_p0_8 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_clk_ext_p0_9: adc_clk_ext_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_ioan_p0_9: tmr0c_ioan_p0_9 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_a_p0_10: adc_trig_a_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0c_iobn_p0_10: tmr0c_iobn_p0_10 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_sda_p0_11: i2c1a_sda_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ioan_p0_11: tmr1c_ioan_p0_11 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_scl_p0_12: i2c1a_scl_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_iobn_p0_12: tmr1c_iobn_p0_12 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_ss1_p0_13: spi3a_ss1_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_ioa_p0_13: tmr0b_ioa_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2c_sda_p0_13: i2c2c_sda_p0_13 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_ss2_p0_14: spi3a_ss2_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr0b_iob_p0_14: tmr0b_iob_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2c_scl_p0_14: i2c2c_scl_p0_14 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_sdio3_p0_15: spi3a_sdio3_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_ioa_p0_15: tmr1c_ioa_p0_15 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_sck_p0_16: spi3a_sck_p0_16 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_sdio2_p0_17: spi3a_sdio2_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr1c_iob_p0_17: tmr1c_iob_p0_17 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_ss0_p0_19: spi3a_ss0_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tck_p0_19: rv_tck_p0_19 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_miso_p0_20: spi3a_miso_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tms_p0_20: rv_tms_p0_20 { + pinmux = ; + }; + + /omit-if-no-ref/ spi3a_mosi_p0_21: spi3a_mosi_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdi_p0_21: rv_tdi_p0_21 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0a_ss0_p0_22: spi0a_ss0_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ rv_tdo_p0_22: rv_tdo_p0_22 { + pinmux = ; + }; + + /omit-if-no-ref/ pt15_p0_23: pt15_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_clkext_p0_23: i2s0b_clkext_p0_23 { + pinmux = ; + }; + + /omit-if-no-ref/ rxev0_p0_24: rxev0_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_sck_p0_24: i2s0b_sck_p0_24 { + pinmux = ; + }; + + /omit-if-no-ref/ txevo_p0_25: txevo_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_sdi_p0_25: i2s0b_sdi_p0_25 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_sdo_p0_26: i2s0b_sdo_p0_26 { + pinmux = ; + }; + + /omit-if-no-ref/ erfo_clk_out_p0_27: erfo_clk_out_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0b_ws_p0_27: i2s0b_ws_p0_27 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_sda_p0_30: i2c0a_sda_p0_30 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_scl_p0_31: i2c0a_scl_p0_31 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_ss0_p1_0: spi4a_ss0_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_trig_b_p1_0: adc_trig_b_p1_0 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_mosi_p1_1: spi4a_mosi_p1_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_miso_p1_2: spi4a_miso_p1_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_sck_p1_3: spi4a_sck_p1_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_sdio2_p1_4: spi4a_sdio2_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_ioa_p1_4: tmr2b_ioa_p1_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_sdio3_p1_5: spi4a_sdio3_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2b_iob_p1_5: tmr2b_iob_p1_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_ss1_p1_6: spi4a_ss1_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ pt0_p1_6: pt0_p1_6 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_cts_p1_7: uart2a_cts_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ pt1_p1_7: pt1_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2c_sda_p1_7: i2c2c_sda_p1_7 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rts_p1_8: uart2a_rts_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ pt2_p1_8: pt2_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c2c_scl_p1_8: i2c2c_scl_p1_8 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_rx_p1_9: uart2a_rx_p1_9 { + pinmux = ; + }; + + /omit-if-no-ref/ pt3_p1_9: pt3_p1_9 { + pinmux = ; + }; + + /omit-if-no-ref/ uart2a_tx_p1_10: uart2a_tx_p1_10 { + pinmux = ; + }; + + /omit-if-no-ref/ pt4_p1_10: pt4_p1_10 { + pinmux = ; + }; + + /omit-if-no-ref/ spi4a_ss2_p1_11: spi4a_ss2_p1_11 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_cs0n_p1_11: hyp_cs0n_p1_11 { + pinmux = ; + }; + + /omit-if-no-ref/ pt5_p1_12: pt5_p1_12 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d0_p1_12: hyp_d0_p1_12 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_ioa_p1_13: tmr3a_ioa_p1_13 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d4_p1_13: hyp_d4_p1_13 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3a_iob_p1_14: tmr3a_iob_p1_14 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_rwds_p1_14: hyp_rwds_p1_14 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d1_p1_15: hyp_d1_p1_15 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d5_p1_16: hyp_d5_p1_16 { + pinmux = ; + }; + + /omit-if-no-ref/ pt9_p1_17: pt9_p1_17 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_cs1n_p1_17: hyp_cs1n_p1_17 { + pinmux = ; + }; + + /omit-if-no-ref/ pt6_p1_18: pt6_p1_18 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d6_p1_18: hyp_d6_p1_18 { + pinmux = ; + }; + + /omit-if-no-ref/ pt7_p1_19: pt7_p1_19 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d2_p1_19: hyp_d2_p1_19 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d3_p1_20: hyp_d3_p1_20 { + pinmux = ; + }; + + /omit-if-no-ref/ pt8_p1_21: pt8_p1_21 { + pinmux = ; + }; + + /omit-if-no-ref/ hyp_d7_p1_21: hyp_d7_p1_21 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_ss0_p1_23: spi1a_ss0_p1_23 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_ss2_p1_24: spi1a_ss2_p1_24 { + pinmux = ; + }; + + /omit-if-no-ref/ can0b_rx_p1_24: can0b_rx_p1_24 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_ss1_p1_25: spi1a_ss1_p1_25 { + pinmux = ; + }; + + /omit-if-no-ref/ can0b_tx_p1_25: can0b_tx_p1_25 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_sck_p1_26: spi1a_sck_p1_26 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_ss2_p1_27: spi2a_ss2_p1_27 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_miso_p1_28: spi1a_miso_p1_28 { + pinmux = ; + }; + + /omit-if-no-ref/ can1b_rx_p1_28: can1b_rx_p1_28 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1a_mosi_p1_29: spi1a_mosi_p1_29 { + pinmux = ; + }; + + /omit-if-no-ref/ can1b_tx_p1_29: can1b_tx_p1_29 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_pe_p1_30: owm_pe_p1_30 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1b_sdio2_p1_30: spi1b_sdio2_p1_30 { + pinmux = ; + }; + + /omit-if-no-ref/ owm_io_p1_31: owm_io_p1_31 { + pinmux = ; + }; + + /omit-if-no-ref/ spi1b_sdio3_p1_31: spi1b_sdio3_p1_31 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_ss1_p2_1: spi2a_ss1_p2_1 { + pinmux = ; + }; + + /omit-if-no-ref/ pt10_p2_1: pt10_p2_1 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_sck_p2_2: spi2a_sck_p2_2 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_miso_p2_3: spi2a_miso_p2_3 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_mosi_p2_4: spi2a_mosi_p2_4 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2a_ss0_p2_5: spi2a_ss0_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ pt11_p2_5: pt11_p2_5 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2b_sdio2_p2_6: spi2b_sdio2_p2_6 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_sda_p2_7: i2c0a_sda_p2_7 { + pinmux = ; + }; + + /omit-if-no-ref/ spi2b_sdio3_p2_7: spi2b_sdio3_p2_7 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c0a_scl_p2_8: i2c0a_scl_p2_8 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_cts_p2_9: uart0a_cts_p2_9 { + pinmux = ; + }; + + /omit-if-no-ref/ pt12_p2_9: pt12_p2_9 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_rts_p2_10: uart0a_rts_p2_10 { + pinmux = ; + }; + + /omit-if-no-ref/ pt14_p2_10: pt14_p2_10 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_rx_p2_11: uart0a_rx_p2_11 { + pinmux = ; + }; + + /omit-if-no-ref/ pt13_p2_11: pt13_p2_11 { + pinmux = ; + }; + + /omit-if-no-ref/ uart0a_tx_p2_12: uart0a_tx_p2_12 { + pinmux = ; + }; + + /omit-if-no-ref/ pt15_p2_12: pt15_p2_12 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_cts_p2_13: uart1a_cts_p2_13 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rx_p2_14: uart1a_rx_p2_14 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_rts_p2_15: uart1a_rts_p2_15 { + pinmux = ; + }; + + /omit-if-no-ref/ adc_hw_trig_c_p2_15: adc_hw_trig_c_p2_15 { + pinmux = ; + }; + + /omit-if-no-ref/ uart1a_tx_p2_16: uart1a_tx_p2_16 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_sda_p2_17: i2c1a_sda_p2_17 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl1_p2_17: ble_ant_ctrl1_p2_17 { + pinmux = ; + }; + + /omit-if-no-ref/ i2c1a_scl_p2_18: i2c1a_scl_p2_18 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl0_p2_18: ble_ant_ctrl0_p2_18 { + pinmux = ; + }; + + /omit-if-no-ref/ pt5_p2_20: pt5_p2_20 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl2_p2_20: ble_ant_ctrl2_p2_20 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_ioa_p2_20: tmr2c_ioa_p2_20 { + pinmux = ; + }; + + /omit-if-no-ref/ pt7_p2_21: pt7_p2_21 { + pinmux = ; + }; + + /omit-if-no-ref/ ble_ant_ctrl3_p2_21: ble_ant_ctrl3_p2_21 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr2c_iob_p2_21: tmr2c_iob_p2_21 { + pinmux = ; + }; + + /omit-if-no-ref/ pt8_p2_22: pt8_p2_22 { + pinmux = ; + }; + + /omit-if-no-ref/ can0b_rx_p2_22: can0b_rx_p2_22 { + pinmux = ; + }; + + /omit-if-no-ref/ pt6_p2_23: pt6_p2_23 { + pinmux = ; + }; + + /omit-if-no-ref/ can0b_tx_p2_23: can0b_tx_p2_23 { + pinmux = ; + }; + + /omit-if-no-ref/ pt10_p2_24: pt10_p2_24 { + pinmux = ; + }; + + /omit-if-no-ref/ can1b_rx_p2_24: can1b_rx_p2_24 { + pinmux = ; + }; + + /omit-if-no-ref/ pt11_p2_25: pt11_p2_25 { + pinmux = ; + }; + + /omit-if-no-ref/ can1b_tx_p2_25: can1b_tx_p2_25 { + pinmux = ; + }; + + /omit-if-no-ref/ pt12_p2_26: pt12_p2_26 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_ss1_p2_26: spi0b_ss1_p2_26 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_ws_p2_26: i2s0c_ws_p2_26 { + pinmux = ; + }; + + /omit-if-no-ref/ pt13_p2_27: pt13_p2_27 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_miso_p2_27: spi0b_miso_p2_27 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_sdi_p2_27: i2s0c_sdi_p2_27 { + pinmux = ; + }; + + /omit-if-no-ref/ pt14_p2_28: pt14_p2_28 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_mosi_p2_28: spi0b_mosi_p2_28 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_sdo_p2_28: i2s0c_sdo_p2_28 { + pinmux = ; + }; + + /omit-if-no-ref/ pt0_p2_29: pt0_p2_29 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_sck_p2_29: spi0b_sck_p2_29 { + pinmux = ; + }; + + /omit-if-no-ref/ i2s0c_sck_p2_29: i2s0c_sck_p2_29 { + pinmux = ; + }; + + /omit-if-no-ref/ pt1_p2_30: pt1_p2_30 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_sdio2_p2_30: spi0b_sdio2_p2_30 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_ioa_p2_30: tmr3c_ioa_p2_30 { + pinmux = ; + }; + + /omit-if-no-ref/ pt2_p2_31: pt2_p2_31 { + pinmux = ; + }; + + /omit-if-no-ref/ spi0b_sdio3_p2_31: spi0b_sdio3_p2_31 { + pinmux = ; + }; + + /omit-if-no-ref/ tmr3c_iob_p2_31: tmr3c_iob_p2_31 { + pinmux = ; + }; + + /omit-if-no-ref/ ain0_p3_0: ain0_p3_0 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0b_rx_p3_0: lpuart0b_rx_p3_0 { + pinmux = ; + }; + + /omit-if-no-ref/ ain1_p3_1: ain1_p3_1 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0b_tx_p3_1: lpuart0b_tx_p3_1 { + pinmux = ; + }; + + /omit-if-no-ref/ ain2_p3_2: ain2_p3_2 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0b_cts_p3_2: lpuart0b_cts_p3_2 { + pinmux = ; + }; + + /omit-if-no-ref/ ain3_p3_3: ain3_p3_3 { + pinmux = ; + }; + + /omit-if-no-ref/ lpuart0b_rts_p3_3: lpuart0b_rts_p3_3 { + pinmux = ; + }; + + /omit-if-no-ref/ ain4_p3_4: ain4_p3_4 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr0b_ioa_p3_4: lptmr0b_ioa_p3_4 { + pinmux = ; + }; + + /omit-if-no-ref/ ain5_p3_5: ain5_p3_5 { + pinmux = ; + }; + + /omit-if-no-ref/ ain6_p3_6: ain6_p3_6 { + pinmux = ; + }; + + /omit-if-no-ref/ ain7_p3_7: ain7_p3_7 { + pinmux = ; + }; + + /omit-if-no-ref/ lptmr1b_ioa_p3_7: lptmr1b_ioa_p3_7 { + pinmux = ; + }; + + }; + }; +}; diff --git a/dts/arm/adi/max32/max32690.dtsi b/dts/arm/adi/max32/max32690.dtsi new file mode 100644 index 0000000000000..a0dac1573a70c --- /dev/null +++ b/dts/arm/adi/max32/max32690.dtsi @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +&clk_ipo { + clock-frequency = ; +}; + +&sram0 { + reg = <0x20000000 DT_SIZE_K(128)>; +}; + +&flash0 { + reg = <0x10000000 DT_SIZE_M(3)>; + erase-block-size = <16384>; +}; + +&gcr { + /delete-property/ sysclk-prescaler; +}; + +&pinctrl { + reg = <0x40008000 0x3220>; + + gpio2: gpio@4000a000 { + reg = <0x4000a000 0x1000>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <26 0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 2>; + status = "disabled"; + }; + + gpio3: gpio@40080400 { + reg = <0x40080400 0x200>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <58 0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 0>; + status = "disabled"; + }; + + gpio4: gpio@4000c000 { + reg = <0x4000c000 0x20>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <54 0>; + status = "disabled"; + }; +}; + +/* MAX32690 extra peripherals. */ +/ { + soc { + sram1: memory@20020000 { + compatible = "mmio-sram"; + reg = <0x20020000 DT_SIZE_K(128)>; + }; + + sram2: memory@20040000 { + compatible = "mmio-sram"; + reg = <0x20040000 DT_SIZE_K(128)>; + }; + + sram3: memory@20060000 { + compatible = "mmio-sram"; + reg = <0x20060000 DT_SIZE_K(128)>; + }; + + sram4: memory@20080000 { + compatible = "mmio-sram"; + reg = <0x20080000 DT_SIZE_K(128)>; + }; + + sram5: memory@200a0000 { + compatible = "mmio-sram"; + reg = <0x200a0000 DT_SIZE_K(128)>; + }; + + sram6: memory@200c0000 { + compatible = "mmio-sram"; + reg = <0x200c0000 DT_SIZE_K(64)>; + }; + + sram7: memory@200d0000 { + compatible = "mmio-sram"; + reg = <0x200d0000 DT_SIZE_K(64)>; + }; + + flc1: flash_controller@40029400 { + compatible = "adi,max32-flash-controller"; + reg = <0x40029400 0x400>; + + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + flash1: flash@10080000 { + compatible = "soc-nv-flash"; + reg = <0x10080000 DT_SIZE_K(256)>; + write-block-size = <16>; + erase-block-size = <16384>; + }; + }; + + spi0: spi@40046000 { + compatible = "adi,max32-spi"; + reg = <0x40046000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 6>; + interrupts = <16 0>; + status = "disabled"; + }; + + spi1: spi@40047000 { + compatible = "adi,max32-spi"; + reg = <0x40047000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 7>; + interrupts = <17 0>; + status = "disabled"; + }; + + spi2: spi@40048000 { + compatible = "adi,max32-spi"; + reg = <0x40048000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 8>; + interrupts = <18 0>; + status = "disabled"; + }; + + spi3: spi@400be000 { + compatible = "adi,max32-spi"; + reg = <0x400be000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS1 16>; + interrupts = <56 0>; + status = "disabled"; + }; + + spi4: spi@400be400 { + compatible = "adi,max32-spi"; + reg = <0x400be400 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS1 17>; + interrupts = <105 0>; + status = "disabled"; + }; + + uart3: serial@40081400 { + compatible = "adi,max32-uart"; + reg = <0x40081400 0x400>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS2 4>; + clock-source = ; + interrupts = <88 0>; + status = "disabled"; + }; + }; +}; diff --git a/dts/arm/adi/max32/max32xxx.dtsi b/dts/arm/adi/max32/max32xxx.dtsi new file mode 100644 index 0000000000000..9db02fc449834 --- /dev/null +++ b/dts/arm/adi/max32/max32xxx.dtsi @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include + +/ { + chosen { + zephyr,flash-controller = &flc0; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m4f"; + reg = <0>; + }; + }; + + clocks { + clk_ipo: clk_ipo { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "disabled"; + }; + + clk_iso: clk_iso { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "disabled"; + }; + + clk_inro: clk_inro { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "disabled"; + }; + + clk_ibro: clk_ibro { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <7372800>; + status = "disabled"; + }; + + clk_ertco: clk_ertco { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + status = "disabled"; + }; + + clk_erfo: clk_erfo { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + status = "disabled"; + }; + }; + + soc { + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(32)>; + }; + + flc0: flash_controller@40029000 { + compatible = "flash-controller"; + reg = <0x40029000 0x400>; + + #address-cells = <1>; + #size-cells = <1>; + status = "okay"; + + flash0: flash@10000000 { + compatible = "soc-nv-flash"; + reg = <0x10000000 DT_SIZE_K(512)>; + write-block-size = <16>; + erase-block-size = <8192>; + }; + }; + + gcr: clock-controller@40000000 { + reg = <0x40000000 0x400>; + compatible = "adi,max32-gcr"; + #clock-cells = <2>; + clocks = <&clk_ipo>; + sysclk-prescaler = <1>; + status = "okay"; + }; + + i2c0: i2c0@4001d000 { + compatible = "adi,max32-i2c"; + reg = <0x4001d000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = ; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 13>; + interrupts = <13 0>; + status = "disabled"; + }; + + i2c1: i2c1@4001e000 { + compatible = "adi,max32-i2c"; + reg = <0x4001e000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = ; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 28>; + interrupts = <36 0>; + status = "disabled"; + }; + + i2c2: i2c2@4001f000 { + compatible = "adi,max32-i2c"; + reg = <0x4001f000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = ; + clocks = <&gcr ADI_MAX32_CLOCK_BUS1 24>; + interrupts = <62 0>; + status = "disabled"; + }; + + pinctrl: pin-controller@40008000 { + compatible = "adi,max32-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x40008000 0x2000>; + + gpio0: gpio@40008000 { + reg = <0x40008000 0x1000>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 0>; + interrupts = <24 0>; + status = "disabled"; + }; + + gpio1: gpio@40009000 { + reg = <0x40009000 0x1000>; + compatible = "adi,max32-gpio"; + gpio-controller; + #gpio-cells = <2>; + interrupts = <25 0>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 1>; + status = "disabled"; + }; + }; + + uart0: serial@40042000 { + compatible = "adi,max32-uart"; + reg = <0x40042000 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 9>; + clock-source = ; + interrupts = <14 0>; + status = "disabled"; + }; + + uart1: serial@40043000 { + compatible = "adi,max32-uart"; + reg = <0x40043000 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS0 10>; + clock-source = ; + interrupts = <15 0>; + status = "disabled"; + }; + + uart2: serial@40044000 { + compatible = "adi,max32-uart"; + reg = <0x40044000 0x1000>; + clocks = <&gcr ADI_MAX32_CLOCK_BUS1 1>; + clock-source = ; + interrupts = <34 0>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi index 1f151efc9a1ab..ae1028ab4a1f3 100644 --- a/dts/arm/ambiq/ambiq_apollo3_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3_blue.dtsi @@ -25,12 +25,6 @@ }; }; - /* Flash region */ - flash0: flash@C000 { - compatible = "soc-nv-flash"; - reg = <0x0000C000 0xF4000>; - }; - /* TCM */ tcm: tcm@10000000 { compatible = "zephyr,memory-region"; @@ -47,6 +41,20 @@ soc { compatible = "ambiq,apollo3-blue", "ambiq,apollo3x", "simple-bus"; + flash: flash-controller@c000 { + compatible = "ambiq,flash-controller"; + reg = <0x0000c000 0xf4000>; + + #address-cells = <1>; + #size-cells = <1>; + + /* Flash region */ + flash0: flash@c000 { + compatible = "soc-nv-flash"; + reg = <0x0000c000 0xf4000>; + }; + }; + pwrcfg: pwrcfg@40021000 { compatible = "ambiq,pwrctrl"; reg = <0x40021000 0x400>; @@ -62,8 +70,73 @@ counter0: counter@40008000 { compatible = "ambiq,counter"; - reg = <0x40008000 0x80>; + reg = <0x40008000 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter1: counter@40008020 { + compatible = "ambiq,counter"; + reg = <0x40008020 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter2: counter@40008040 { + compatible = "ambiq,counter"; + reg = <0x40008040 0x20>; interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter3: counter@40008060 { + compatible = "ambiq,counter"; + reg = <0x40008060 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter4: counter@40008080 { + compatible = "ambiq,counter"; + reg = <0x40008080 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter5: counter@400080a0 { + compatible = "ambiq,counter"; + reg = <0x400080A0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter6: counter@400080c0 { + compatible = "ambiq,counter"; + reg = <0x400080C0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter7: counter@400080e0 { + compatible = "ambiq,counter"; + reg = <0x400080E0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; status = "disabled"; }; @@ -87,7 +160,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x100>; }; - iom0: iom@50004000 { + spi0: spi@50004000 { reg = <0x50004000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -96,7 +169,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x2>; }; - iom1: iom@50005000 { + spi1: spi@50005000 { reg = <0x50005000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -105,7 +178,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x4>; }; - iom2: iom@50006000 { + spi2: spi@50006000 { reg = <0x50006000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -114,7 +187,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x8>; }; - iom3: iom@50007000 { + spi3: spi@50007000 { reg = <0x50007000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -123,7 +196,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x10>; }; - iom4: iom@50008000 { + spi4: spi@50008000 { reg = <0x50008000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -132,7 +205,61 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x20>; }; - iom5: iom@50009000 { + spi5: spi@50009000 { + reg = <0x50009000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <11 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x40>; + }; + + i2c0: i2c@50004000 { + reg = <0x50004000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <6 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x2>; + }; + + i2c1: i2c@50005000 { + reg = <0x50005000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <7 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x4>; + }; + + i2c2: i2c@50006000 { + reg = <0x50006000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x8>; + }; + + i2c3: i2c@50007000 { + reg = <0x50007000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <9 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x10>; + }; + + i2c4: i2c@50008000 { + reg = <0x50008000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <10 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x20>; + }; + + i2c5: i2c@50009000 { reg = <0x50009000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -151,9 +278,60 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x800>; }; + bleif: bleif@5000c000 { + compatible = "ambiq,spi-bleif"; + reg = <0x5000c000 0x414>; + interrupts = <12 1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x8000>; + + bt_hci_apollo: bt-hci@0 { + compatible = "ambiq,bt-hci-spi"; + reg = <0>; + }; + }; + pinctrl: pin-controller@40010000 { compatible = "ambiq,apollo3-pinctrl"; reg = <0x40010000 0x800>; + #address-cells = <1>; + #size-cells = <0>; + + gpio: gpio@40010000 { + compatible = "ambiq,gpio"; + gpio-map-mask = <0xffffffe0 0xffffffc0>; + gpio-map-pass-thru = <0x1f 0x3f>; + gpio-map = < + 0x00 0x0 &gpio0_31 0x0 0x0 + 0x20 0x0 &gpio32_63 0x0 0x0 + >; + reg = <0x40010000>; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <0>; + ranges; + + gpio0_31: gpio0_31@0 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + interrupts = <13 0>; + status = "disabled"; + }; + + gpio32_63: gpio32_63@20 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x20>; + interrupts = <13 0>; + status = "disabled"; + ngpios = <18>; + }; + }; }; wdt0: watchdog@40024000 { diff --git a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi index a95b7e6945b35..afaf69692dd5a 100644 --- a/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo3p_blue.dtsi @@ -25,12 +25,6 @@ }; }; - /* Flash region */ - flash0: flash@C000 { - compatible = "soc-nv-flash"; - reg = <0x0000C000 0x1F4000>; - }; - /* TCM */ tcm: tcm@10000000 { compatible = "zephyr,memory-region"; @@ -47,6 +41,20 @@ soc { compatible = "ambiq,apollo3p-blue", "ambiq,apollo3x", "simple-bus"; + flash: flash-controller@c000 { + compatible = "ambiq,flash-controller"; + reg = <0x0000c000 0x1f4000>; + + #address-cells = <1>; + #size-cells = <1>; + + /* Flash region */ + flash0: flash@c000 { + compatible = "soc-nv-flash"; + reg = <0x0000c000 0x1f4000>; + }; + }; + pwrcfg: pwrcfg@40021000 { compatible = "ambiq,pwrctrl"; reg = <0x40021000 0x400>; @@ -62,8 +70,73 @@ counter0: counter@40008000 { compatible = "ambiq,counter"; - reg = <0x40008000 0x80>; + reg = <0x40008000 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter1: counter@40008020 { + compatible = "ambiq,counter"; + reg = <0x40008020 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter2: counter@40008040 { + compatible = "ambiq,counter"; + reg = <0x40008040 0x20>; interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter3: counter@40008060 { + compatible = "ambiq,counter"; + reg = <0x40008060 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter4: counter@40008080 { + compatible = "ambiq,counter"; + reg = <0x40008080 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter5: counter@400080a0 { + compatible = "ambiq,counter"; + reg = <0x400080A0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter6: counter@400080c0 { + compatible = "ambiq,counter"; + reg = <0x400080C0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; + status = "disabled"; + }; + + counter7: counter@400080e0 { + compatible = "ambiq,counter"; + reg = <0x400080E0 0x20>; + interrupts = <14 0>; + clock-frequency = ; + clk-source = <2>; status = "disabled"; }; @@ -87,7 +160,61 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x100>; }; - iom0: iom@50004000 { + spi0: spi@50004000 { + reg = <0x50004000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <6 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x2>; + }; + + spi1: spi@50005000 { + reg = <0x50005000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <7 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x4>; + }; + + spi2: spi@50006000 { + reg = <0x50006000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <8 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x8>; + }; + + spi3: spi@50007000 { + reg = <0x50007000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <9 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x10>; + }; + + spi4: spi@50008000 { + reg = <0x50008000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <10 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x20>; + }; + + spi5: spi@50009000 { + reg = <0x50009000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + interrupts = <11 0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x40>; + }; + + i2c0: i2c@50004000 { reg = <0x50004000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -96,7 +223,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x2>; }; - iom1: iom@50005000 { + i2c1: i2c@50005000 { reg = <0x50005000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -105,7 +232,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x4>; }; - iom2: iom@50006000 { + i2c2: i2c@50006000 { reg = <0x50006000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -114,7 +241,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x8>; }; - iom3: iom@50007000 { + i2c3: i2c@50007000 { reg = <0x50007000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -123,7 +250,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x10>; }; - iom4: iom@50008000 { + i2c4: i2c@50008000 { reg = <0x50008000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -132,7 +259,7 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x20>; }; - iom5: iom@50009000 { + i2c5: i2c@50009000 { reg = <0x50009000 0x1000>; #address-cells = <1>; #size-cells = <0>; @@ -171,9 +298,70 @@ ambiq,pwrcfg = <&pwrcfg 0x8 0x2000>; }; + bleif: bleif@5000c000 { + compatible = "ambiq,spi-bleif"; + reg = <0x5000c000 0x414>; + interrupts = <12 1>; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + ambiq,pwrcfg = <&pwrcfg 0x8 0x8000>; + + bt_hci_apollo: bt-hci@0 { + compatible = "ambiq,bt-hci-spi"; + reg = <0>; + }; + }; + pinctrl: pin-controller@40010000 { compatible = "ambiq,apollo3-pinctrl"; reg = <0x40010000 0x800>; + #address-cells = <1>; + #size-cells = <0>; + + gpio: gpio@40010000 { + compatible = "ambiq,gpio"; + gpio-map-mask = <0xffffffe0 0xffffffc0>; + gpio-map-pass-thru = <0x1f 0x3f>; + gpio-map = < + 0x00 0x0 &gpio0_31 0x0 0x0 + 0x20 0x0 &gpio32_63 0x0 0x0 + 0x40 0x0 &gpio64_95 0x0 0x0 + >; + reg = <0x40010000>; + #gpio-cells = <2>; + #address-cells = <1>; + #size-cells = <0>; + ranges; + + gpio0_31: gpio0_31@0 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + interrupts = <13 0>; + status = "disabled"; + }; + + gpio32_63: gpio32_63@20 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x20>; + interrupts = <13 0>; + status = "disabled"; + }; + + gpio64_95: gpio64_95@40 { + compatible = "ambiq,gpio-bank"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x40>; + interrupts = <13 0>; + status = "disabled"; + ngpios = <10>; + }; + }; }; wdt0: watchdog@40024000 { diff --git a/dts/arm/ambiq/ambiq_apollo4p.dtsi b/dts/arm/ambiq/ambiq_apollo4p.dtsi index a3abd1093e936..b7ce6461e359e 100644 --- a/dts/arm/ambiq/ambiq_apollo4p.dtsi +++ b/dts/arm/ambiq/ambiq_apollo4p.dtsi @@ -22,13 +22,35 @@ cpu0: cpu@0 { compatible = "arm,cortex-m4f"; reg = <0>; + cpu-power-states = <&idle &suspend_to_ram>; }; - }; + power-states { + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + /* + * As Apollo4 datasheet, run_to_sleep and sleep_to_run + * transition time are both lower than 1us, but + * considering the software overhead we set a + * bigger value. + */ + min-residency-us = <100>; + exit-latency-us = <5>; + }; - /* MRAM region */ - flash0: flash@18000 { - compatible = "soc-nv-flash"; - reg = <0x00018000 0x1e8000>; + suspend_to_ram: suspend_to_ram { + compatible = "zephyr,power-state"; + power-state-name = "suspend-to-ram"; + /* + * As Apollo4 datasheet, run_to_deepsleep transition + * time is lower than 1us and deepsleep_to_run + * transition time is about 25us, but considering + * the software overhead, we set a bigger value. + */ + min-residency-us = <2000>; + exit-latency-us = <125>; + }; + }; }; /* TCM */ @@ -47,6 +69,20 @@ soc { compatible = "ambiq,apollo4p", "ambiq,apollo4x", "simple-bus"; + flash: flash-controller@18000 { + compatible = "ambiq,flash-controller"; + reg = <0x00018000 0x1e8000>; + + #address-cells = <1>; + #size-cells = <1>; + + /* Flash region */ + flash0: flash@18000 { + compatible = "soc-nv-flash"; + reg = <0x00018000 0x1e8000>; + }; + }; + pwrcfg: pwrcfg@40021000 { compatible = "ambiq,pwrctrl"; reg = <0x40021000 0x400>; @@ -60,10 +96,12 @@ status = "okay"; }; - counter0: counter@40008000 { + counter0: counter@40008200 { compatible = "ambiq,counter"; - reg = <0x40008000 0x80>; + reg = <0x40008200 0x20>; interrupts = <67 0>; + clock-frequency = ; + clk-source = <1>; status = "disabled"; }; diff --git a/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi b/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi index dfc2f59de3d70..9656eadc98445 100644 --- a/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi +++ b/dts/arm/ambiq/ambiq_apollo4p_blue.dtsi @@ -78,10 +78,12 @@ status = "okay"; }; - counter0: counter@40008000 { + counter0: counter@40008200 { compatible = "ambiq,counter"; - reg = <0x40008000 0x80>; + reg = <0x40008200 0x20>; interrupts = <67 0>; + clock-frequency = ; + clk-source = <1>; status = "disabled"; }; @@ -172,7 +174,7 @@ status = "disabled"; ambiq,pwrcfg = <&pwrcfg 0x4 0x20>; - bt-hci@0 { + bt_hci_apollo: bt-hci@0 { compatible = "ambiq,bt-hci-spi"; reg = <0>; irq-gpios = <&gpio32_63 21 GPIO_ACTIVE_HIGH>; diff --git a/dts/arm/cypress/psoc6-pinctrl.dtsi b/dts/arm/cypress/psoc6-pinctrl.dtsi deleted file mode 100644 index 526f74eea036c..0000000000000 --- a/dts/arm/cypress/psoc6-pinctrl.dtsi +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2021 ATL Electronics - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include "pinctrl_cypress_psoc6.h" - -/ { - soc { - pinctrl@40310000 { - /* instance, signal, port, pin, hsiom [, flag1, ... ] */ - DT_CYPRESS_HSIOM(spi0, mosi, 0, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi0, miso, 0, 3, act_8, input-enable); - DT_CYPRESS_HSIOM(spi0, clk, 0, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi0, sel0, 0, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi0, sel1, 0, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi0, sel2, 0, 1, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, mosi, 10, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, miso, 10, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi1, clk, 10, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, sel0, 10, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, sel1, 10, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, sel2, 10, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi1, sel3, 10, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, mosi, 9, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, miso, 9, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi2, clk, 9, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, sel0, 9, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, sel1, 9, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, sel2, 9, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi2, sel3, 9, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, mosi, 6, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, miso, 6, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi3, clk, 6, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, sel0, 6, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, sel1, 7, 7, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, sel2, 8, 7, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi3, sel3, 5, 7, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, mosi, 7, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, miso, 7, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi4, clk, 7, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel0, 7, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel1, 7, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel2, 7, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel3, 7, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, mosi, 8, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, miso, 8, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi4, clk, 8, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel0, 8, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel1, 8, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel2, 8, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi4, sel3, 8, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, mosi, 5, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, miso, 5, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi5, clk, 5, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel0, 5, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel1, 5, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel2, 5, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel3, 5, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, mosi, 11, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, miso, 11, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi5, clk, 11, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel0, 11, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel1, 11, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel2, 11, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi5, sel3, 11, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, mosi, 6, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, miso, 6, 5, act_8, input-enable); - DT_CYPRESS_HSIOM(spi6, clk, 6, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel0, 6, 7, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, mosi, 12, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, miso, 12, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi6, clk, 12, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel0, 12, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel1, 12, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel2, 12, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel3, 12, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, mosi, 13, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, miso, 13, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi6, clk, 13, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel0, 13, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel1, 13, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel2, 13, 5, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi6, sel3, 13, 6, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, mosi, 1, 0, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, miso, 1, 1, act_8, input-enable); - DT_CYPRESS_HSIOM(spi7, clk, 1, 2, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, sel0, 1, 3, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, sel1, 1, 4, act_8, drive-push-pull); - DT_CYPRESS_HSIOM(spi7, sel2, 1, 5, act_8, drive-push-pull); - - DT_CYPRESS_HSIOM(uart0, rx, 0, 2, act_6, input-enable); - DT_CYPRESS_HSIOM(uart0, tx, 0, 3, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart0, rts, 0, 4, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart0, cts, 0, 5, act_6, input-enable); - DT_CYPRESS_HSIOM(uart1, rx, 10, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart1, tx, 10, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart1, rts, 10, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart1, cts, 10, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart2, rx, 9, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart2, tx, 9, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart2, rts, 9, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart2, cts, 9, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart3, rx, 6, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart3, tx, 6, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart3, rts, 6, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart3, cts, 6, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart4, rx, 7, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart4, tx, 7, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart4, rts, 7, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart4, cts, 7, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart4, rx, 8, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart4, tx, 8, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart4, rts, 8, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart4, cts, 8, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart5, rx, 5, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart5, tx, 5, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart5, rts, 5, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart5, cts, 5, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart5, rx, 11, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart5, tx, 11, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart5, rts, 11, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart5, cts, 11, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, rx, 6, 4, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, tx, 6, 5, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, rts, 6, 6, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, cts, 6, 7, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, rx, 12, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, tx, 12, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, rts, 12, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, cts, 12, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, rx, 13, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart6, tx, 13, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, rts, 13, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart6, cts, 13, 3, act_6, input-enable); - DT_CYPRESS_HSIOM(uart7, rx, 1, 0, act_6, input-enable); - DT_CYPRESS_HSIOM(uart7, tx, 1, 1, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart7, rts, 1, 2, act_6, drive-push-pull); - DT_CYPRESS_HSIOM(uart7, cts, 1, 3, act_6, input-enable); - }; - }; -}; diff --git a/dts/arm/gd/gd32f4xx/gd32f4xx.dtsi b/dts/arm/gd/gd32f4xx/gd32f4xx.dtsi index f2e35e981e427..260115cb8a675 100644 --- a/dts/arm/gd/gd32f4xx/gd32f4xx.dtsi +++ b/dts/arm/gd/gd32f4xx/gd32f4xx.dtsi @@ -107,7 +107,7 @@ uart4: usart@40005000 { compatible = "gd,gd32-usart"; reg = <0x40005000 0x400>; - interrupts = <52 0>; + interrupts = <53 0>; clocks = <&cctl GD32_CLOCK_UART4>; resets = <&rctl GD32_RESET_UART4>; status = "disabled"; diff --git a/dts/arm/cypress/pinctrl_cypress_psoc6.h b/dts/arm/infineon/cat1a/legacy/pinctrl_cypress_psoc6.h similarity index 100% rename from dts/arm/cypress/pinctrl_cypress_psoc6.h rename to dts/arm/infineon/cat1a/legacy/pinctrl_cypress_psoc6.h diff --git a/dts/arm/infineon/cat1a/legacy/psoc6-pinctrl.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6-pinctrl.dtsi new file mode 100644 index 0000000000000..2f06ed2269fcb --- /dev/null +++ b/dts/arm/infineon/cat1a/legacy/psoc6-pinctrl.dtsi @@ -0,0 +1,721 @@ +/* + * Copyright (c) 2021 ATL Electronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + soc { + + pinctrl: pinctrl@40310000 { + /* scb_i2c_scl */ + /omit-if-no-ref/ p0_2_scb0_i2c_scl: p0_2_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_scb7_i2c_scl: p1_0_scb7_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_i2c_scl: p5_0_scb5_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_i2c_scl: p6_0_scb3_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb8_i2c_scl: p6_0_scb8_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_i2c_scl: p6_4_scb6_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb8_i2c_scl: p6_4_scb8_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_i2c_scl: p7_0_scb4_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_i2c_scl: p8_0_scb4_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_i2c_scl: p9_0_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_i2c_scl: p10_0_scb1_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_i2c_scl: p11_0_scb5_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_i2c_scl: p12_0_scb6_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_i2c_scl: p13_0_scb6_i2c_scl { + pinmux = ; + }; + + /* scb_i2c_sda */ + /omit-if-no-ref/ p0_3_scb0_i2c_sda: p0_3_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb7_i2c_sda: p1_1_scb7_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_i2c_sda: p5_1_scb5_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_i2c_sda: p6_1_scb3_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb8_i2c_sda: p6_1_scb8_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_i2c_sda: p6_5_scb6_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb8_i2c_sda: p6_5_scb8_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_i2c_sda: p7_1_scb4_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_i2c_sda: p8_1_scb4_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_i2c_sda: p9_1_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_i2c_sda: p10_1_scb1_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_i2c_sda: p11_1_scb5_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_i2c_sda: p12_1_scb6_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_i2c_sda: p13_1_scb6_i2c_sda { + pinmux = ; + }; + + /* scb_spi_m_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_m_clk: p0_4_scb0_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_scb5_spi_m_clk: p5_2_scb5_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb3_spi_m_clk: p6_2_scb3_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb8_spi_m_clk: p6_2_scb8_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb6_spi_m_clk: p6_6_scb6_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb8_spi_m_clk: p6_6_scb8_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_scb4_spi_m_clk: p7_2_scb4_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_scb4_spi_m_clk: p8_2_scb4_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_scb2_spi_m_clk: p9_2_scb2_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_scb1_spi_m_clk: p10_2_scb1_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_scb5_spi_m_clk: p11_2_scb5_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_scb6_spi_m_clk: p12_2_scb6_spi_m_clk { + pinmux = ; + }; + + /* scb_spi_m_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_m_miso: p0_3_scb0_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb7_spi_m_miso: p1_1_scb7_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_spi_m_miso: p5_1_scb5_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_spi_m_miso: p6_1_scb3_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb8_spi_m_miso: p6_1_scb8_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_spi_m_miso: p6_5_scb6_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb8_spi_m_miso: p6_5_scb8_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_spi_m_miso: p7_1_scb4_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_spi_m_miso: p8_1_scb4_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_spi_m_miso: p9_1_scb2_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_spi_m_miso: p10_1_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_spi_m_miso: p11_1_scb5_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_spi_m_miso: p12_1_scb6_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_spi_m_miso: p13_1_scb6_spi_m_miso { + pinmux = ; + }; + + /* scb_spi_m_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_m_mosi: p0_2_scb0_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_scb7_spi_m_mosi: p1_0_scb7_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_spi_m_mosi: p5_0_scb5_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_spi_m_mosi: p6_0_scb3_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb8_spi_m_mosi: p6_0_scb8_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_spi_m_mosi: p6_4_scb6_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb8_spi_m_mosi: p6_4_scb8_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_spi_m_mosi: p7_0_scb4_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_spi_m_mosi: p8_0_scb4_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_spi_m_mosi: p9_0_scb2_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_spi_m_mosi: p10_0_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_spi_m_mosi: p11_0_scb5_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_spi_m_mosi: p12_0_scb6_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_spi_m_mosi: p13_0_scb6_spi_m_mosi { + pinmux = ; + }; + + /* scb_spi_m_select0 */ + /omit-if-no-ref/ p0_5_scb0_spi_m_select0: p0_5_scb0_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_scb5_spi_m_select0: p5_3_scb5_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb3_spi_m_select0: p6_3_scb3_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb8_spi_m_select0: p6_3_scb8_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb6_spi_m_select0: p6_7_scb6_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb8_spi_m_select0: p6_7_scb8_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_scb4_spi_m_select0: p7_3_scb4_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_scb4_spi_m_select0: p8_3_scb4_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_scb2_spi_m_select0: p9_3_scb2_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_scb1_spi_m_select0: p10_3_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_scb5_spi_m_select0: p11_3_scb5_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_scb6_spi_m_select0: p12_3_scb6_spi_m_select0 { + pinmux = ; + }; + + /* scb_spi_m_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_m_select1: p0_0_scb0_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p1_4_scb7_spi_m_select1: p1_4_scb7_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_scb5_spi_m_select1: p5_4_scb5_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p7_4_scb4_spi_m_select1: p7_4_scb4_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p7_7_scb3_spi_m_select1: p7_7_scb3_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_scb4_spi_m_select1: p8_4_scb4_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p10_4_scb1_spi_m_select1: p10_4_scb1_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p11_4_scb5_spi_m_select1: p11_4_scb5_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p12_4_scb6_spi_m_select1: p12_4_scb6_spi_m_select1 { + pinmux = ; + }; + + /* scb_spi_m_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_m_select2: p0_1_scb0_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p1_5_scb7_spi_m_select2: p1_5_scb7_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_scb5_spi_m_select2: p5_5_scb5_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p7_5_scb4_spi_m_select2: p7_5_scb4_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_scb4_spi_m_select2: p8_5_scb4_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_scb3_spi_m_select2: p8_7_scb3_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p10_5_scb1_spi_m_select2: p10_5_scb1_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p11_5_scb5_spi_m_select2: p11_5_scb5_spi_m_select2 { + pinmux = ; + }; + + /* scb_spi_m_select3 */ + /omit-if-no-ref/ p5_6_scb5_spi_m_select3: p5_6_scb5_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_scb3_spi_m_select3: p5_7_scb3_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p7_6_scb4_spi_m_select3: p7_6_scb4_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_scb4_spi_m_select3: p8_6_scb4_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p10_6_scb1_spi_m_select3: p10_6_scb1_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p11_6_scb5_spi_m_select3: p11_6_scb5_spi_m_select3 { + pinmux = ; + }; + + /* scb_spi_s_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_s_clk: p0_4_scb0_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_scb5_spi_s_clk: p5_2_scb5_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb3_spi_s_clk: p6_2_scb3_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb8_spi_s_clk: p6_2_scb8_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb6_spi_s_clk: p6_6_scb6_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb8_spi_s_clk: p6_6_scb8_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_scb4_spi_s_clk: p7_2_scb4_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_scb4_spi_s_clk: p8_2_scb4_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_scb2_spi_s_clk: p9_2_scb2_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_scb1_spi_s_clk: p10_2_scb1_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_scb5_spi_s_clk: p11_2_scb5_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_scb6_spi_s_clk: p12_2_scb6_spi_s_clk { + pinmux = ; + }; + + /* scb_spi_s_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_s_miso: p0_3_scb0_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb7_spi_s_miso: p1_1_scb7_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_spi_s_miso: p5_1_scb5_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_spi_s_miso: p6_1_scb3_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb8_spi_s_miso: p6_1_scb8_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_spi_s_miso: p6_5_scb6_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb8_spi_s_miso: p6_5_scb8_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_spi_s_miso: p7_1_scb4_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_spi_s_miso: p8_1_scb4_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_spi_s_miso: p9_1_scb2_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_spi_s_miso: p10_1_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_spi_s_miso: p11_1_scb5_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_spi_s_miso: p12_1_scb6_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_spi_s_miso: p13_1_scb6_spi_s_miso { + pinmux = ; + }; + + /* scb_spi_s_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_s_mosi: p0_2_scb0_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_scb7_spi_s_mosi: p1_0_scb7_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_spi_s_mosi: p5_0_scb5_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_spi_s_mosi: p6_0_scb3_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb8_spi_s_mosi: p6_0_scb8_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_spi_s_mosi: p6_4_scb6_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb8_spi_s_mosi: p6_4_scb8_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_spi_s_mosi: p7_0_scb4_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_spi_s_mosi: p8_0_scb4_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_spi_s_mosi: p9_0_scb2_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_spi_s_mosi: p10_0_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_spi_s_mosi: p11_0_scb5_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_spi_s_mosi: p12_0_scb6_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_spi_s_mosi: p13_0_scb6_spi_s_mosi { + pinmux = ; + }; + + /* scb_spi_s_select0 */ + /omit-if-no-ref/ p0_5_scb0_spi_s_select0: p0_5_scb0_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_scb5_spi_s_select0: p5_3_scb5_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb3_spi_s_select0: p6_3_scb3_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb8_spi_s_select0: p6_3_scb8_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb6_spi_s_select0: p6_7_scb6_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb8_spi_s_select0: p6_7_scb8_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_scb4_spi_s_select0: p7_3_scb4_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_scb4_spi_s_select0: p8_3_scb4_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_scb2_spi_s_select0: p9_3_scb2_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_scb1_spi_s_select0: p10_3_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_scb5_spi_s_select0: p11_3_scb5_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_scb6_spi_s_select0: p12_3_scb6_spi_s_select0 { + pinmux = ; + }; + + /* scb_spi_s_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_s_select1: p0_0_scb0_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p1_4_scb7_spi_s_select1: p1_4_scb7_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_scb5_spi_s_select1: p5_4_scb5_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p7_4_scb4_spi_s_select1: p7_4_scb4_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p7_7_scb3_spi_s_select1: p7_7_scb3_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_scb4_spi_s_select1: p8_4_scb4_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p10_4_scb1_spi_s_select1: p10_4_scb1_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p11_4_scb5_spi_s_select1: p11_4_scb5_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p12_4_scb6_spi_s_select1: p12_4_scb6_spi_s_select1 { + pinmux = ; + }; + + /* scb_spi_s_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_s_select2: p0_1_scb0_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p1_5_scb7_spi_s_select2: p1_5_scb7_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_scb5_spi_s_select2: p5_5_scb5_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p7_5_scb4_spi_s_select2: p7_5_scb4_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_scb4_spi_s_select2: p8_5_scb4_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_scb3_spi_s_select2: p8_7_scb3_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p10_5_scb1_spi_s_select2: p10_5_scb1_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p11_5_scb5_spi_s_select2: p11_5_scb5_spi_s_select2 { + pinmux = ; + }; + + /* scb_spi_s_select3 */ + /omit-if-no-ref/ p5_6_scb5_spi_s_select3: p5_6_scb5_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_scb3_spi_s_select3: p5_7_scb3_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p7_6_scb4_spi_s_select3: p7_6_scb4_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_scb4_spi_s_select3: p8_6_scb4_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p10_6_scb1_spi_s_select3: p10_6_scb1_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p11_6_scb5_spi_s_select3: p11_6_scb5_spi_s_select3 { + pinmux = ; + }; + + /* scb_uart_cts */ + /omit-if-no-ref/ p0_5_scb0_uart_cts: p0_5_scb0_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_scb5_uart_cts: p5_3_scb5_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb3_uart_cts: p6_3_scb3_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb6_uart_cts: p6_7_scb6_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_scb4_uart_cts: p7_3_scb4_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_scb4_uart_cts: p8_3_scb4_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_scb2_uart_cts: p9_3_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_scb1_uart_cts: p10_3_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_scb5_uart_cts: p11_3_scb5_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_scb6_uart_cts: p12_3_scb6_uart_cts { + pinmux = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p0_4_scb0_uart_rts: p0_4_scb0_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_scb5_uart_rts: p5_2_scb5_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb3_uart_rts: p6_2_scb3_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb6_uart_rts: p6_6_scb6_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_scb4_uart_rts: p7_2_scb4_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_scb4_uart_rts: p8_2_scb4_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_scb2_uart_rts: p9_2_scb2_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_scb1_uart_rts: p10_2_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_scb5_uart_rts: p11_2_scb5_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_scb6_uart_rts: p12_2_scb6_uart_rts { + pinmux = ; + }; + + /* scb_uart_rx */ + /omit-if-no-ref/ p0_2_scb0_uart_rx: p0_2_scb0_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_scb7_uart_rx: p1_0_scb7_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_uart_rx: p5_0_scb5_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_uart_rx: p6_0_scb3_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_uart_rx: p6_4_scb6_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_uart_rx: p7_0_scb4_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_uart_rx: p8_0_scb4_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_uart_rx: p9_0_scb2_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_uart_rx: p10_0_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_uart_rx: p11_0_scb5_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_uart_rx: p12_0_scb6_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_uart_rx: p13_0_scb6_uart_rx { + pinmux = ; + }; + + /* scb_uart_tx */ + /omit-if-no-ref/ p0_3_scb0_uart_tx: p0_3_scb0_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb7_uart_tx: p1_1_scb7_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_uart_tx: p5_1_scb5_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_uart_tx: p6_1_scb3_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_uart_tx: p6_5_scb6_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_uart_tx: p7_1_scb4_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_uart_tx: p8_1_scb4_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_uart_tx: p9_1_scb2_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_uart_tx: p10_1_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_uart_tx: p11_1_scb5_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_uart_tx: p12_1_scb6_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_uart_tx: p13_1_scb6_uart_tx { + pinmux = ; + }; + }; + }; +}; diff --git a/dts/arm/cypress/psoc6.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6.dtsi similarity index 99% rename from dts/arm/cypress/psoc6.dtsi rename to dts/arm/infineon/cat1a/legacy/psoc6.dtsi index a6ab61e9949dd..ad9fef2e0fdef 100644 --- a/dts/arm/cypress/psoc6.dtsi +++ b/dts/arm/infineon/cat1a/legacy/psoc6.dtsi @@ -67,7 +67,7 @@ soc { pinctrl@40310000 { - compatible = "cypress,psoc6-pinctrl"; + compatible = "infineon,cat1-pinctrl"; #address-cells = <1>; #size-cells = <1>; ranges = <0x40310000 0x40310000 0x2024>; diff --git a/dts/arm/cypress/psoc6_cm0.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6_cm0.dtsi similarity index 99% rename from dts/arm/cypress/psoc6_cm0.dtsi rename to dts/arm/infineon/cat1a/legacy/psoc6_cm0.dtsi index c4221dc1ad0bb..7a9d44ab17e95 100644 --- a/dts/arm/cypress/psoc6_cm0.dtsi +++ b/dts/arm/infineon/cat1a/legacy/psoc6_cm0.dtsi @@ -5,7 +5,7 @@ */ #include -#include +#include / { cpus { diff --git a/dts/arm/cypress/psoc6_cm4.dtsi b/dts/arm/infineon/cat1a/legacy/psoc6_cm4.dtsi similarity index 84% rename from dts/arm/cypress/psoc6_cm4.dtsi rename to dts/arm/infineon/cat1a/legacy/psoc6_cm4.dtsi index c2693b610095b..35e866413c610 100644 --- a/dts/arm/cypress/psoc6_cm4.dtsi +++ b/dts/arm/infineon/cat1a/legacy/psoc6_cm4.dtsi @@ -5,7 +5,7 @@ */ #include -#include +#include / { cpus { diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6016BZI_F04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6016BZI_F04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6016BZI_F04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6016BZI_F04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6036BZI_F04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6036BZI_F04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6036BZI_F04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6036BZI_F04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6116BZI_F54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6116BZI_F54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6116BZI_F54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6116BZI_F54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6117BZI_F34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6117BZI_F34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6117BZI_F34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6117BZI_F34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6117FDI_F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6117FDI_F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6117FDI_F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6117FDI_F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6117WI_F34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6117WI_F34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6117WI_F34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6117WI_F34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6136BZI_F14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6136BZI_F14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6136BZI_F14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6136BZI_F14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6136BZI_F34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6136BZI_F34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6136BZI_F34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6136BZI_F34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6136FDI_F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6136FDI_F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6136FDI_F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6136FDI_F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6136FTI_F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6136FTI_F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6136FTI_F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6136FTI_F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137BZI_F54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137BZI_F54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137FDI_F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137FDI_F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137FDI_F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137FDI_F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6137WI_F54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6137WI_F54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6137WI_F54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6137WI_F54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F82.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F82.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F82.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F82.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F83.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F83.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F83.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F83.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F92.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F92.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F92.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F92.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F93.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F93.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144AZI_S4F93.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144AZI_S4F93.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F82.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F82.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F82.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F82.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F92.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F92.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6144LQI_S4F92.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6144LQI_S4F92.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F72.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F72.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145AZI_S3F72.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145AZI_S3F72.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F11.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F11.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F11.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F11.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F41.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F41.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F41.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F41.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F71.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F71.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145FNI_S3F71.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145FNI_S3F71.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F72.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F72.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6145LQI_S3F72.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6145LQI_S3F72.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148AZI_S2F44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148AZI_S2F44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148AZI_S2F44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148AZI_S2F44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148BZI_S2F44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148BZI_S2F44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148BZI_S2F44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148BZI_S2F44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148FNI_S2F43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148FNI_S2F43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148FNI_S2F43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148FNI_S2F43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148LQI_S2F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148LQI_S2F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148LQI_S2F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148LQI_S2F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6148LQI_S2F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6148LQI_S2F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6148LQI_S2F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6148LQI_S2F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AAZI_S2F44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AAZI_S2F44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614ABZI_S2F04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614ABZI_S2F04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614ABZI_S2F04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614ABZI_S2F04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614ABZI_S2F44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614ABZI_S2F44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614ABZI_S2F44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614ABZI_S2F44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AFNI_S2F03.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AFNI_S2F03.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AFNI_S2F03.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AFNI_S2F03.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614AFNI_S2F43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614AFNI_S2F43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614AFNI_S2F43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614AFNI_S2F43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614ALQI_S2F02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614ALQI_S2F02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614ALQI_S2F02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614ALQI_S2F02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C614ALQI_S2F42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C614ALQI_S2F42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C614ALQI_S2F42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C614ALQI_S2F42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D82.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D82.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D82.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D82.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D83.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D83.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D83.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D83.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D92.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D92.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D92.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D92.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D93.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D93.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244AZI_S4D93.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244AZI_S4D93.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D82.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D82.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D82.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D82.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D92.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D92.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6244LQI_S4D92.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6244LQI_S4D92.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D72.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D72.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245AZI_S3D72.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245AZI_S3D72.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D11.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D11.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D11.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D11.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D41.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D41.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D41.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D41.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D71.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D71.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245FNI_S3D71.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245FNI_S3D71.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D12.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D12.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D12.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D12.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D62.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D62.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D62.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D62.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D72.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D72.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6245LQI_S3D72.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6245LQI_S3D72.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6246BZI_D04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6246BZI_D04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6246BZI_D04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6246BZI_D04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BFI_D54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BFI_D54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BFI_D54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BFI_D54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BZI_AUD54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BZI_AUD54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BZI_AUD54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BZI_AUD54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247BZI_D54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247BZI_D54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D32.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D32.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D32.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D32.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D52.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D52.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247FDI_D52.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247FDI_D52.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247FTI_D52.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247FTI_D52.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247FTI_D52.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247FTI_D52.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6247WI_D54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6247WI_D54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6247WI_D54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6247WI_D54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248AZI_S2D14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248AZI_S2D14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248AZI_S2D14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248AZI_S2D14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248AZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248AZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248AZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248AZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248BZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248BZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248BZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248BZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248FNI_S2D43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248FNI_S2D43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248FNI_S2D43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248FNI_S2D43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248LQI_S2D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248LQI_S2D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248LQI_S2D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248LQI_S2D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6248LQI_S2D42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6248LQI_S2D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6248LQI_S2D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6248LQI_S2D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624AAZI_S2D14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624AAZI_S2D14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624AAZI_S2D14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624AAZI_S2D14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624AAZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624AAZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624AAZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624AAZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D44A0.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D44A0.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ABZI_S2D44A0.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ABZI_S2D44A0.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624AFNI_S2D43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624AFNI_S2D43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624AFNI_S2D43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624AFNI_S2D43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ALQI_S2D02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ALQI_S2D02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ALQI_S2D02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ALQI_S2D02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C624ALQI_S2D42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C624ALQI_S2D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C624ALQI_S2D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C624ALQI_S2D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF03.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF03.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF03.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF03.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6316BZI_BLF54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6316BZI_BLF54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLD13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLD13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLD13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLD13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLD14.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLD14.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLD14.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLD14.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLF03.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLF03.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLF03.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLF03.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLF04.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLF04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BLF04.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BLF04.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BUD13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BUD13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336BZI_BUD13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336BZI_BUD13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336LQI_BLF02.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336LQI_BLF02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336LQI_BLF02.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336LQI_BLF02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6336LQI_BLF42.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6336LQI_BLF42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6336LQI_BLF42.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6336LQI_BLF42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6337BZI_BLF13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6337BZI_BLF13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6337BZI_BLF13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6337BZI_BLF13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD33.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD33.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD33.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD33.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD34.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD34.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD34.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD34.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD44.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD44.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD54.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BLD54.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BLD54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD33.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD33.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD33.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD33.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347BZI_BUD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347BZI_BUD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD33.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD33.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD33.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD33.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BLD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BLD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD13.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD13.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD13.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD13.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD33.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD33.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD33.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD33.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD43.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD43.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD43.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD43.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD53.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347FMI_BUD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347FMI_BUD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CY8C6347LQI_BLD52.dtsi b/dts/arm/infineon/cat1a/mpns/CY8C6347LQI_BLD52.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CY8C6347LQI_BLD52.dtsi rename to dts/arm/infineon/cat1a/mpns/CY8C6347LQI_BLD52.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB06445LQI_S3D42.dtsi b/dts/arm/infineon/cat1a/mpns/CYB06445LQI_S3D42.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB06445LQI_S3D42.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB06445LQI_S3D42.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB06447BZI_BLD53.dtsi b/dts/arm/infineon/cat1a/mpns/CYB06447BZI_BLD53.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB06447BZI_BLD53.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB06447BZI_BLD53.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB06447BZI_BLD54.dtsi b/dts/arm/infineon/cat1a/mpns/CYB06447BZI_BLD54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB06447BZI_BLD54.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB06447BZI_BLD54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB06447BZI_D54.dtsi b/dts/arm/infineon/cat1a/mpns/CYB06447BZI_D54.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB06447BZI_D54.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB06447BZI_D54.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYB0644ABZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CYB0644ABZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYB0644ABZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CYB0644ABZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYBLE_416045_02.dtsi b/dts/arm/infineon/cat1a/mpns/CYBLE_416045_02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYBLE_416045_02.dtsi rename to dts/arm/infineon/cat1a/mpns/CYBLE_416045_02.dtsi diff --git a/dts/arm/infineon/psoc6/mpns/CYS0644ABZI_S2D44.dtsi b/dts/arm/infineon/cat1a/mpns/CYS0644ABZI_S2D44.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/mpns/CYS0644ABZI_S2D44.dtsi rename to dts/arm/infineon/cat1a/mpns/CYS0644ABZI_S2D44.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.104-m-csp-ble-usb.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.104-m-csp-ble.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.104-m-csp-ble.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.104-m-csp-ble.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.104-m-csp-ble.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.116-bga-ble.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.116-bga-ble.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.116-bga-ble.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.116-bga-ble.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.116-bga-usb.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.116-bga-usb.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.116-bga-usb.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.116-bga-usb.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.124-bga-sip.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.124-bga-sip.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.124-bga-sip.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.124-bga-sip.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.124-bga.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.124-bga.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.124-bga.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.124-bga.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.43-smt.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.43-smt.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.43-smt.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.43-smt.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.68-qfn-ble.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.68-qfn-ble.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.68-qfn-ble.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.68-qfn-ble.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.80-wlcsp.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.80-wlcsp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.80-wlcsp.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.80-wlcsp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi b/dts/arm/infineon/cat1a/psoc6_01/psoc6_01.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_01/psoc6_01.dtsi rename to dts/arm/infineon/cat1a/psoc6_01/psoc6_01.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.100-wlcsp.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.100-wlcsp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_02/psoc6_02.100-wlcsp.dtsi rename to dts/arm/infineon/cat1a/psoc6_02/psoc6_02.100-wlcsp.dtsi diff --git a/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.124-bga.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.124-bga.dtsi new file mode 100644 index 0000000000000..aa1cd9a0c93f7 --- /dev/null +++ b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.124-bga.dtsi @@ -0,0 +1,969 @@ +/* + * Copyright (c) 2022 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "psoc6_02.dtsi" + +/ { + soc { + pinctrl: pinctrl@40300000 { + /* scb_i2c_scl */ + /omit-if-no-ref/ p0_2_scb0_i2c_scl: p0_2_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_scb7_i2c_scl: p1_0_scb7_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p2_0_scb1_i2c_scl: p2_0_scb1_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p2_4_scb9_i2c_scl: p2_4_scb9_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb2_i2c_scl: p3_0_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb7_i2c_scl: p4_0_scb7_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_i2c_scl: p5_0_scb5_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_scb10_i2c_scl: p5_4_scb10_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_i2c_scl: p6_0_scb3_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb8_i2c_scl: p6_0_scb8_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_i2c_scl: p6_4_scb6_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb8_i2c_scl: p6_4_scb8_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_i2c_scl: p7_0_scb4_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_i2c_scl: p8_0_scb4_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_scb11_i2c_scl: p8_4_scb11_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_i2c_scl: p9_0_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_i2c_scl: p10_0_scb1_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_i2c_scl: p11_0_scb5_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_i2c_scl: p12_0_scb6_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_i2c_scl: p13_0_scb6_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p13_4_scb12_i2c_scl: p13_4_scb12_i2c_scl { + pinmux = ; + }; + + /* scb_i2c_sda */ + /omit-if-no-ref/ p0_3_scb0_i2c_sda: p0_3_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb7_i2c_sda: p1_1_scb7_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p2_1_scb1_i2c_sda: p2_1_scb1_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p2_5_scb9_i2c_sda: p2_5_scb9_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_i2c_sda: p3_1_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb7_i2c_sda: p4_1_scb7_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_i2c_sda: p5_1_scb5_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_scb10_i2c_sda: p5_5_scb10_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_i2c_sda: p6_1_scb3_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb8_i2c_sda: p6_1_scb8_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_i2c_sda: p6_5_scb6_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb8_i2c_sda: p6_5_scb8_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_i2c_sda: p7_1_scb4_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_i2c_sda: p8_1_scb4_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_scb11_i2c_sda: p8_5_scb11_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_i2c_sda: p9_1_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_i2c_sda: p10_1_scb1_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_i2c_sda: p11_1_scb5_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_i2c_sda: p12_1_scb6_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_i2c_sda: p13_1_scb6_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p13_5_scb12_i2c_sda: p13_5_scb12_i2c_sda { + pinmux = ; + }; + + /* scb_uart_cts */ + /omit-if-no-ref/ p0_5_scb0_uart_cts: p0_5_scb0_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb7_uart_cts: p1_3_scb7_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p2_3_scb1_uart_cts: p2_3_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p2_7_scb9_uart_cts: p2_7_scb9_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_uart_cts: p3_3_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_scb5_uart_cts: p5_3_scb5_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_scb10_uart_cts: p5_7_scb10_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_scb3_uart_cts: p6_3_scb3_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_scb6_uart_cts: p6_7_scb6_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_scb4_uart_cts: p7_3_scb4_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_scb4_uart_cts: p8_3_scb4_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_scb11_uart_cts: p8_7_scb11_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_scb2_uart_cts: p9_3_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_scb1_uart_cts: p10_3_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_scb5_uart_cts: p11_3_scb5_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_scb6_uart_cts: p12_3_scb6_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p13_3_scb6_uart_cts: p13_3_scb6_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p13_7_scb12_uart_cts: p13_7_scb12_uart_cts { + pinmux = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p0_4_scb0_uart_rts: p0_4_scb0_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb7_uart_rts: p1_2_scb7_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p2_2_scb1_uart_rts: p2_2_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p2_6_scb9_uart_rts: p2_6_scb9_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_uart_rts: p3_2_scb2_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_scb5_uart_rts: p5_2_scb5_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p5_6_scb10_uart_rts: p5_6_scb10_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_scb3_uart_rts: p6_2_scb3_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_scb6_uart_rts: p6_6_scb6_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_scb4_uart_rts: p7_2_scb4_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_scb4_uart_rts: p8_2_scb4_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_scb11_uart_rts: p8_6_scb11_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_scb2_uart_rts: p9_2_scb2_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_scb1_uart_rts: p10_2_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_scb5_uart_rts: p11_2_scb5_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_scb6_uart_rts: p12_2_scb6_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p13_2_scb6_uart_rts: p13_2_scb6_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p13_6_scb12_uart_rts: p13_6_scb12_uart_rts { + pinmux = ; + }; + + /* scb_uart_rx */ + /omit-if-no-ref/ p0_2_scb0_uart_rx: p0_2_scb0_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_scb7_uart_rx: p1_0_scb7_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p2_0_scb1_uart_rx: p2_0_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p2_4_scb9_uart_rx: p2_4_scb9_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb2_uart_rx: p3_0_scb2_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb7_uart_rx: p4_0_scb7_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb5_uart_rx: p5_0_scb5_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_scb10_uart_rx: p5_4_scb10_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_scb3_uart_rx: p6_0_scb3_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_scb6_uart_rx: p6_4_scb6_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_scb4_uart_rx: p7_0_scb4_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_scb4_uart_rx: p8_0_scb4_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_scb11_uart_rx: p8_4_scb11_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_scb2_uart_rx: p9_0_scb2_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_scb1_uart_rx: p10_0_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_scb5_uart_rx: p11_0_scb5_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_scb6_uart_rx: p12_0_scb6_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_scb6_uart_rx: p13_0_scb6_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p13_4_scb12_uart_rx: p13_4_scb12_uart_rx { + pinmux = ; + }; + + /* scb_uart_tx */ + /omit-if-no-ref/ p0_3_scb0_uart_tx: p0_3_scb0_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb7_uart_tx: p1_1_scb7_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p2_1_scb1_uart_tx: p2_1_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p2_5_scb9_uart_tx: p2_5_scb9_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_uart_tx: p3_1_scb2_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb7_uart_tx: p4_1_scb7_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb5_uart_tx: p5_1_scb5_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_scb10_uart_tx: p5_5_scb10_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_scb3_uart_tx: p6_1_scb3_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_scb6_uart_tx: p6_5_scb6_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_scb4_uart_tx: p7_1_scb4_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_scb4_uart_tx: p8_1_scb4_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_scb11_uart_tx: p8_5_scb11_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_scb2_uart_tx: p9_1_scb2_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_scb1_uart_tx: p10_1_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_scb5_uart_tx: p11_1_scb5_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_scb6_uart_tx: p12_1_scb6_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_scb6_uart_tx: p13_1_scb6_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p13_5_scb12_uart_tx: p13_5_scb12_uart_tx { + pinmux = ; + }; + + /* tcpwm_line */ + /omit-if-no-ref/ p0_0_tcpwm0_line: p0_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_0_tcpwm1_line: p0_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_2_tcpwm0_line: p0_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_2_tcpwm1_line: p0_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_tcpwm0_line: p0_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_tcpwm1_line: p0_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_tcpwm0_line: p1_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_0_tcpwm1_line: p1_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_tcpwm0_line: p1_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_tcpwm1_line: p1_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_4_tcpwm0_line: p1_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p1_4_tcpwm1_line: p1_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_0_tcpwm0_line: p2_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_0_tcpwm1_line: p2_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_2_tcpwm0_line: p2_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_2_tcpwm1_line: p2_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_4_tcpwm0_line: p2_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_4_tcpwm1_line: p2_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_6_tcpwm0_line: p2_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p2_6_tcpwm1_line: p2_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_tcpwm0_line: p3_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_tcpwm1_line: p3_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_tcpwm0_line: p3_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_tcpwm1_line: p3_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_tcpwm0_line: p3_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_tcpwm1_line: p3_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_tcpwm0_line: p4_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_tcpwm1_line: p4_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_tcpwm0_line: p5_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_tcpwm1_line: p5_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_tcpwm0_line: p5_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_2_tcpwm1_line: p5_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_tcpwm0_line: p5_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_4_tcpwm1_line: p5_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_6_tcpwm0_line: p5_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p5_6_tcpwm1_line: p5_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_tcpwm0_line: p6_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_0_tcpwm1_line: p6_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_tcpwm0_line: p6_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_2_tcpwm1_line: p6_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_tcpwm0_line: p6_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_4_tcpwm1_line: p6_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_tcpwm0_line: p6_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p6_6_tcpwm1_line: p6_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_tcpwm0_line: p7_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_0_tcpwm1_line: p7_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_tcpwm0_line: p7_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_2_tcpwm1_line: p7_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_4_tcpwm0_line: p7_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_4_tcpwm1_line: p7_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_6_tcpwm0_line: p7_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p7_6_tcpwm1_line: p7_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_tcpwm0_line: p8_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_0_tcpwm1_line: p8_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_tcpwm0_line: p8_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_2_tcpwm1_line: p8_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_tcpwm0_line: p8_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_4_tcpwm1_line: p8_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_tcpwm0_line: p8_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p8_6_tcpwm1_line: p8_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_tcpwm0_line: p9_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_0_tcpwm1_line: p9_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_tcpwm0_line: p9_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_2_tcpwm1_line: p9_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_4_tcpwm0_line: p9_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_4_tcpwm1_line: p9_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_6_tcpwm0_line: p9_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p9_6_tcpwm1_line: p9_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_tcpwm0_line: p10_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_0_tcpwm1_line: p10_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_tcpwm0_line: p10_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_2_tcpwm1_line: p10_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_4_tcpwm0_line: p10_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_4_tcpwm1_line: p10_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_6_tcpwm0_line: p10_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p10_6_tcpwm1_line: p10_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_tcpwm0_line: p11_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_0_tcpwm1_line: p11_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_tcpwm0_line: p11_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_2_tcpwm1_line: p11_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_4_tcpwm0_line: p11_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p11_4_tcpwm1_line: p11_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_tcpwm0_line: p12_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_0_tcpwm1_line: p12_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_tcpwm0_line: p12_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_2_tcpwm1_line: p12_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_4_tcpwm0_line: p12_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_4_tcpwm1_line: p12_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_6_tcpwm0_line: p12_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p12_6_tcpwm1_line: p12_6_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_tcpwm0_line: p13_0_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_0_tcpwm1_line: p13_0_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_2_tcpwm0_line: p13_2_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_2_tcpwm1_line: p13_2_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_4_tcpwm0_line: p13_4_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_4_tcpwm1_line: p13_4_tcpwm1_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_6_tcpwm0_line: p13_6_tcpwm0_line { + pinmux = ; + }; + /omit-if-no-ref/ p13_6_tcpwm1_line: p13_6_tcpwm1_line { + pinmux = ; + }; + + /* tcpwm_line_compl */ + /omit-if-no-ref/ p0_1_tcpwm0_line_compl: p0_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_1_tcpwm1_line_compl: p0_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_3_tcpwm0_line_compl: p0_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_3_tcpwm1_line_compl: p0_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_tcpwm0_line_compl: p0_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_tcpwm1_line_compl: p0_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_tcpwm0_line_compl: p1_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_tcpwm1_line_compl: p1_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_tcpwm0_line_compl: p1_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_tcpwm1_line_compl: p1_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_5_tcpwm0_line_compl: p1_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p1_5_tcpwm1_line_compl: p1_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_1_tcpwm0_line_compl: p2_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_1_tcpwm1_line_compl: p2_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_3_tcpwm0_line_compl: p2_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_3_tcpwm1_line_compl: p2_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_5_tcpwm0_line_compl: p2_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_5_tcpwm1_line_compl: p2_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_7_tcpwm0_line_compl: p2_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p2_7_tcpwm1_line_compl: p2_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_tcpwm0_line_compl: p3_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_tcpwm1_line_compl: p3_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_tcpwm0_line_compl: p3_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_tcpwm1_line_compl: p3_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_tcpwm0_line_compl: p3_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_tcpwm1_line_compl: p3_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_tcpwm0_line_compl: p4_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_tcpwm1_line_compl: p4_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_tcpwm0_line_compl: p5_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_tcpwm1_line_compl: p5_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_tcpwm0_line_compl: p5_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_3_tcpwm1_line_compl: p5_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_tcpwm0_line_compl: p5_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_5_tcpwm1_line_compl: p5_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_tcpwm0_line_compl: p5_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p5_7_tcpwm1_line_compl: p5_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_tcpwm0_line_compl: p6_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_1_tcpwm1_line_compl: p6_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_tcpwm0_line_compl: p6_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_3_tcpwm1_line_compl: p6_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_tcpwm0_line_compl: p6_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_5_tcpwm1_line_compl: p6_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_tcpwm0_line_compl: p6_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p6_7_tcpwm1_line_compl: p6_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_tcpwm0_line_compl: p7_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_1_tcpwm1_line_compl: p7_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_tcpwm0_line_compl: p7_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_3_tcpwm1_line_compl: p7_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_5_tcpwm0_line_compl: p7_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_5_tcpwm1_line_compl: p7_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_7_tcpwm0_line_compl: p7_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p7_7_tcpwm1_line_compl: p7_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_tcpwm0_line_compl: p8_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_1_tcpwm1_line_compl: p8_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_tcpwm0_line_compl: p8_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_3_tcpwm1_line_compl: p8_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_tcpwm0_line_compl: p8_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_5_tcpwm1_line_compl: p8_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_tcpwm0_line_compl: p8_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p8_7_tcpwm1_line_compl: p8_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_tcpwm0_line_compl: p9_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_1_tcpwm1_line_compl: p9_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_tcpwm0_line_compl: p9_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_3_tcpwm1_line_compl: p9_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_5_tcpwm0_line_compl: p9_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_5_tcpwm1_line_compl: p9_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_7_tcpwm0_line_compl: p9_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p9_7_tcpwm1_line_compl: p9_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_tcpwm0_line_compl: p10_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_1_tcpwm1_line_compl: p10_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_tcpwm0_line_compl: p10_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_3_tcpwm1_line_compl: p10_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_5_tcpwm0_line_compl: p10_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_5_tcpwm1_line_compl: p10_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_7_tcpwm0_line_compl: p10_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p10_7_tcpwm1_line_compl: p10_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_tcpwm0_line_compl: p11_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_1_tcpwm1_line_compl: p11_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_tcpwm0_line_compl: p11_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_3_tcpwm1_line_compl: p11_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_5_tcpwm0_line_compl: p11_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p11_5_tcpwm1_line_compl: p11_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_tcpwm0_line_compl: p12_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_1_tcpwm1_line_compl: p12_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_tcpwm0_line_compl: p12_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_3_tcpwm1_line_compl: p12_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_5_tcpwm0_line_compl: p12_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_5_tcpwm1_line_compl: p12_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_7_tcpwm0_line_compl: p12_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p12_7_tcpwm1_line_compl: p12_7_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_tcpwm0_line_compl: p13_1_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_1_tcpwm1_line_compl: p13_1_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_3_tcpwm0_line_compl: p13_3_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_3_tcpwm1_line_compl: p13_3_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_5_tcpwm0_line_compl: p13_5_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_5_tcpwm1_line_compl: p13_5_tcpwm1_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_7_tcpwm0_line_compl: p13_7_tcpwm0_line_compl { + pinmux = ; + }; + /omit-if-no-ref/ p13_7_tcpwm1_line_compl: p13_7_tcpwm1_line_compl { + pinmux = ; + }; + + }; + }; +}; diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.128-tqfp.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.128-tqfp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_02/psoc6_02.128-tqfp.dtsi rename to dts/arm/infineon/cat1a/psoc6_02/psoc6_02.128-tqfp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.68-qfn.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.68-qfn.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_02/psoc6_02.68-qfn.dtsi rename to dts/arm/infineon/cat1a/psoc6_02/psoc6_02.68-qfn.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi b/dts/arm/infineon/cat1a/psoc6_02/psoc6_02.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_02/psoc6_02.dtsi rename to dts/arm/infineon/cat1a/psoc6_02/psoc6_02.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.100-tqfp.dtsi b/dts/arm/infineon/cat1a/psoc6_03/psoc6_03.100-tqfp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_03/psoc6_03.100-tqfp.dtsi rename to dts/arm/infineon/cat1a/psoc6_03/psoc6_03.100-tqfp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.49-wlcsp.dtsi b/dts/arm/infineon/cat1a/psoc6_03/psoc6_03.49-wlcsp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_03/psoc6_03.49-wlcsp.dtsi rename to dts/arm/infineon/cat1a/psoc6_03/psoc6_03.49-wlcsp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.68-qfn.dtsi b/dts/arm/infineon/cat1a/psoc6_03/psoc6_03.68-qfn.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_03/psoc6_03.68-qfn.dtsi rename to dts/arm/infineon/cat1a/psoc6_03/psoc6_03.68-qfn.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi b/dts/arm/infineon/cat1a/psoc6_03/psoc6_03.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_03/psoc6_03.dtsi rename to dts/arm/infineon/cat1a/psoc6_03/psoc6_03.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.64-tqfp-epad.dtsi b/dts/arm/infineon/cat1a/psoc6_04/psoc6_04.64-tqfp-epad.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_04/psoc6_04.64-tqfp-epad.dtsi rename to dts/arm/infineon/cat1a/psoc6_04/psoc6_04.64-tqfp-epad.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.68-qfn.dtsi b/dts/arm/infineon/cat1a/psoc6_04/psoc6_04.68-qfn.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_04/psoc6_04.68-qfn.dtsi rename to dts/arm/infineon/cat1a/psoc6_04/psoc6_04.68-qfn.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.80-tqfp.dtsi b/dts/arm/infineon/cat1a/psoc6_04/psoc6_04.80-tqfp.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_04/psoc6_04.80-tqfp.dtsi rename to dts/arm/infineon/cat1a/psoc6_04/psoc6_04.80-tqfp.dtsi diff --git a/dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi b/dts/arm/infineon/cat1a/psoc6_04/psoc6_04.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/psoc6_04/psoc6_04.dtsi rename to dts/arm/infineon/cat1a/psoc6_04/psoc6_04.dtsi diff --git a/dts/arm/infineon/psoc6/system_clocks.dtsi b/dts/arm/infineon/cat1a/system_clocks.dtsi similarity index 100% rename from dts/arm/infineon/psoc6/system_clocks.dtsi rename to dts/arm/infineon/cat1a/system_clocks.dtsi diff --git a/dts/arm/infineon/cat1b/cyw20829/clock_source_def.h b/dts/arm/infineon/cat1b/cyw20829/clock_source_def.h new file mode 100644 index 0000000000000..26921d08235d8 --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/clock_source_def.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2024, Cypress Semiconductor + * SPDX-License-Identifier: Apache-2.0 + */ + +#define CLK_SOURCE_IHO +#define CLK_SOURCE_PILO diff --git a/dts/arm/infineon/cat1b/cyw20829/cyw20829.40-qfn.dtsi b/dts/arm/infineon/cat1b/cyw20829/cyw20829.40-qfn.dtsi new file mode 100644 index 0000000000000..aff1340f79712 --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/cyw20829.40-qfn.dtsi @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "cyw20829.dtsi" + +/ { + soc { + + pinctrl: pinctrl@40400000 { + /* scb_i2c_scl */ + /omit-if-no-ref/ p1_2_scb2_i2c_scl: p1_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_i2c_scl: p3_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_i2c_scl: p4_0_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_i2c_scl: p5_0_scb2_i2c_scl { + pinmux = ; + }; + + /* scb_i2c_sda */ + /omit-if-no-ref/ p1_3_scb2_i2c_sda: p1_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_i2c_sda: p3_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_i2c_sda: p4_1_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb2_i2c_sda: p5_1_scb2_i2c_sda { + pinmux = ; + }; + + /* scb_spi_m_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_m_clk: p0_4_scb0_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_m_clk: p1_1_scb1_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_m_clk: p3_1_scb1_spi_m_clk { + pinmux = ; + }; + + /* scb_spi_m_miso */ + /omit-if-no-ref/ p1_3_scb1_spi_m_miso: p1_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_m_miso: p3_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_m_miso: p4_1_scb0_spi_m_miso { + pinmux = ; + }; + + /* scb_spi_m_mosi */ + /omit-if-no-ref/ p1_2_scb1_spi_m_mosi: p1_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_m_mosi: p3_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_m_mosi: p4_0_scb0_spi_m_mosi { + pinmux = ; + }; + + /* scb_spi_m_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_m_select0: p1_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_m_select0: p5_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_m_select0: p5_1_scb0_spi_m_select0 { + pinmux = ; + }; + + /* scb_spi_m_select1 */ + /omit-if-no-ref/ p0_5_scb1_spi_m_select1: p0_5_scb1_spi_m_select1 { + pinmux = ; + }; + + /* scb_spi_m_select2 */ + /omit-if-no-ref/ p0_4_scb1_spi_m_select2: p0_4_scb1_spi_m_select2 { + pinmux = ; + }; + + /* scb_spi_m_select3 */ + + /* scb_spi_s_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_s_clk: p0_4_scb0_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_s_clk: p1_1_scb1_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_s_clk: p3_1_scb1_spi_s_clk { + pinmux = ; + }; + + /* scb_spi_s_miso */ + /omit-if-no-ref/ p1_3_scb1_spi_s_miso: p1_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_s_miso: p3_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_s_miso: p4_1_scb0_spi_s_miso { + pinmux = ; + }; + + /* scb_spi_s_mosi */ + /omit-if-no-ref/ p1_2_scb1_spi_s_mosi: p1_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_s_mosi: p3_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_s_mosi: p4_0_scb0_spi_s_mosi { + pinmux = ; + }; + + /* scb_spi_s_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_s_select0: p1_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_s_select0: p5_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_s_select0: p5_1_scb0_spi_s_select0 { + pinmux = ; + }; + + /* scb_spi_s_select1 */ + /omit-if-no-ref/ p0_5_scb1_spi_s_select1: p0_5_scb1_spi_s_select1 { + pinmux = ; + }; + + /* scb_spi_s_select2 */ + /omit-if-no-ref/ p0_4_scb1_spi_s_select2: p0_4_scb1_spi_s_select2 { + pinmux = ; + }; + + /* scb_spi_s_select3 */ + + /* scb_uart_cts */ + /omit-if-no-ref/ p1_0_scb1_uart_cts: p1_0_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb2_uart_cts: p4_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_uart_cts: p5_0_scb2_uart_cts { + pinmux = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p1_1_scb1_uart_rts: p1_1_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_uart_rts: p3_1_scb2_uart_rts { + pinmux = ; + }; + + /* scb_uart_rx */ + /omit-if-no-ref/ p1_2_scb1_uart_rx: p1_2_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_uart_rx: p3_2_scb2_uart_rx { + pinmux = ; + }; + + /* scb_uart_tx */ + /omit-if-no-ref/ p1_3_scb1_uart_tx: p1_3_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_uart_tx: p3_3_scb2_uart_tx { + pinmux = ; + }; + + }; + }; +}; + +&gpio_prt0 { + ngpios = <2>; +}; +&gpio_prt1 { + ngpios = <4>; +}; +&gpio_prt3 { + ngpios = <3>; +}; +&gpio_prt5 { + ngpios = <2>; +}; diff --git a/dts/arm/infineon/cat1b/cyw20829/cyw20829.56-qfn.dtsi b/dts/arm/infineon/cat1b/cyw20829/cyw20829.56-qfn.dtsi new file mode 100644 index 0000000000000..a94c9744b9e9d --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/cyw20829.56-qfn.dtsi @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "cyw20829.dtsi" + +/ { + + soc { + + pinctrl: pinctrl@40400000 { + /* scb_i2c_scl */ + /omit-if-no-ref/ p0_2_scb0_i2c_scl: p0_2_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb2_i2c_scl: p1_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_i2c_scl: p3_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_i2c_scl: p4_0_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_i2c_scl: p5_0_scb2_i2c_scl { + pinmux = ; + }; + + /* scb_i2c_sda */ + /omit-if-no-ref/ p0_3_scb0_i2c_sda: p0_3_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb2_i2c_sda: p1_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_i2c_sda: p3_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_i2c_sda: p4_1_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb2_i2c_sda: p5_1_scb2_i2c_sda { + pinmux = ; + }; + + /* scb_spi_m_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_m_clk: p0_4_scb0_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_m_clk: p1_1_scb1_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_m_clk: p3_1_scb1_spi_m_clk { + pinmux = ; + }; + + /* scb_spi_m_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_m_miso: p0_3_scb0_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb1_spi_m_miso: p1_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_m_miso: p3_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_m_miso: p4_1_scb0_spi_m_miso { + pinmux = ; + }; + + /* scb_spi_m_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_m_mosi: p0_2_scb0_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb1_spi_m_mosi: p1_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_m_mosi: p3_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_m_mosi: p4_0_scb0_spi_m_mosi { + pinmux = ; + }; + + /* scb_spi_m_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_m_select0: p1_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb1_spi_m_select0: p3_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_m_select0: p5_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_m_select0: p5_1_scb0_spi_m_select0 { + pinmux = ; + }; + + /* scb_spi_m_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_m_select1: p0_0_scb0_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_scb1_spi_m_select1: p0_5_scb1_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p3_6_scb1_spi_m_select1: p3_6_scb1_spi_m_select1 { + pinmux = ; + }; + + /* scb_spi_m_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_m_select2: p0_1_scb0_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_scb1_spi_m_select2: p0_4_scb1_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_scb1_spi_m_select2: p3_5_scb1_spi_m_select2 { + pinmux = ; + }; + + /* scb_spi_m_select3 */ + /omit-if-no-ref/ p0_3_scb1_spi_m_select3: p0_3_scb1_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_scb1_spi_m_select3: p3_4_scb1_spi_m_select3 { + pinmux = ; + }; + + /* scb_spi_s_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_s_clk: p0_4_scb0_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_s_clk: p1_1_scb1_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_s_clk: p3_1_scb1_spi_s_clk { + pinmux = ; + }; + + /* scb_spi_s_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_s_miso: p0_3_scb0_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb1_spi_s_miso: p1_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_s_miso: p3_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_s_miso: p4_1_scb0_spi_s_miso { + pinmux = ; + }; + + /* scb_spi_s_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_s_mosi: p0_2_scb0_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb1_spi_s_mosi: p1_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_s_mosi: p3_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_s_mosi: p4_0_scb0_spi_s_mosi { + pinmux = ; + }; + + /* scb_spi_s_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_s_select0: p1_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb1_spi_s_select0: p3_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_s_select0: p5_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_s_select0: p5_1_scb0_spi_s_select0 { + pinmux = ; + }; + + /* scb_spi_s_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_s_select1: p0_0_scb0_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_scb1_spi_s_select1: p0_5_scb1_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p3_6_scb1_spi_s_select1: p3_6_scb1_spi_s_select1 { + pinmux = ; + }; + + /* scb_spi_s_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_s_select2: p0_1_scb0_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_scb1_spi_s_select2: p0_4_scb1_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_scb1_spi_s_select2: p3_5_scb1_spi_s_select2 { + pinmux = ; + }; + + /* scb_spi_s_select3 */ + /omit-if-no-ref/ p0_3_scb1_spi_s_select3: p0_3_scb1_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_scb1_spi_s_select3: p3_4_scb1_spi_s_select3 { + pinmux = ; + }; + + /* scb_uart_cts */ + /omit-if-no-ref/ p1_0_scb1_uart_cts: p1_0_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb2_uart_cts: p3_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb2_uart_cts: p4_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_uart_cts: p5_0_scb2_uart_cts { + pinmux = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p1_1_scb1_uart_rts: p1_1_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_uart_rts: p3_1_scb2_uart_rts { + pinmux = ; + }; + + /* scb_uart_rx */ + /omit-if-no-ref/ p1_2_scb1_uart_rx: p1_2_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_uart_rx: p3_2_scb2_uart_rx { + pinmux = ; + }; + + /* scb_uart_tx */ + /omit-if-no-ref/ p1_3_scb1_uart_tx: p1_3_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_uart_tx: p3_3_scb2_uart_tx { + pinmux = ; + }; + + }; + }; +}; diff --git a/dts/arm/infineon/cat1b/cyw20829/cyw20829.77-bga.dtsi b/dts/arm/infineon/cat1b/cyw20829/cyw20829.77-bga.dtsi new file mode 100644 index 0000000000000..6975188c56167 --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/cyw20829.77-bga.dtsi @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "cyw20829.dtsi" + +/ { + soc { + + pinctrl: pinctrl@40400000 { + /* scb_i2c_scl */ + /omit-if-no-ref/ p0_2_scb0_i2c_scl: p0_2_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb2_i2c_scl: p1_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_i2c_scl: p3_2_scb2_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_i2c_scl: p4_0_scb0_i2c_scl { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_i2c_scl: p5_0_scb2_i2c_scl { + pinmux = ; + }; + + /* scb_i2c_sda */ + /omit-if-no-ref/ p0_3_scb0_i2c_sda: p0_3_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb2_i2c_sda: p1_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_i2c_sda: p3_3_scb2_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_i2c_sda: p4_1_scb0_i2c_sda { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb2_i2c_sda: p5_1_scb2_i2c_sda { + pinmux = ; + }; + + /* scb_spi_m_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_m_clk: p0_4_scb0_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_m_clk: p1_1_scb1_spi_m_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_m_clk: p3_1_scb1_spi_m_clk { + pinmux = ; + }; + + /* scb_spi_m_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_m_miso: p0_3_scb0_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb1_spi_m_miso: p1_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_m_miso: p3_3_scb1_spi_m_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_m_miso: p4_1_scb0_spi_m_miso { + pinmux = ; + }; + + /* scb_spi_m_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_m_mosi: p0_2_scb0_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb1_spi_m_mosi: p1_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_m_mosi: p3_2_scb1_spi_m_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_m_mosi: p4_0_scb0_spi_m_mosi { + pinmux = ; + }; + + /* scb_spi_m_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_m_select0: p1_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb1_spi_m_select0: p3_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_m_select0: p5_0_scb1_spi_m_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_m_select0: p5_1_scb0_spi_m_select0 { + pinmux = ; + }; + + /* scb_spi_m_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_m_select1: p0_0_scb0_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_scb1_spi_m_select1: p0_5_scb1_spi_m_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p3_6_scb1_spi_m_select1: p3_6_scb1_spi_m_select1 { + pinmux = ; + }; + + /* scb_spi_m_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_m_select2: p0_1_scb0_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_scb1_spi_m_select2: p0_4_scb1_spi_m_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_scb1_spi_m_select2: p3_5_scb1_spi_m_select2 { + pinmux = ; + }; + + /* scb_spi_m_select3 */ + /omit-if-no-ref/ p0_3_scb1_spi_m_select3: p0_3_scb1_spi_m_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_scb1_spi_m_select3: p3_4_scb1_spi_m_select3 { + pinmux = ; + }; + + /* scb_spi_s_clk */ + /omit-if-no-ref/ p0_4_scb0_spi_s_clk: p0_4_scb0_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p1_1_scb1_spi_s_clk: p1_1_scb1_spi_s_clk { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb1_spi_s_clk: p3_1_scb1_spi_s_clk { + pinmux = ; + }; + + /* scb_spi_s_miso */ + /omit-if-no-ref/ p0_3_scb0_spi_s_miso: p0_3_scb0_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p1_3_scb1_spi_s_miso: p1_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb1_spi_s_miso: p3_3_scb1_spi_s_miso { + pinmux = ; + }; + /omit-if-no-ref/ p4_1_scb0_spi_s_miso: p4_1_scb0_spi_s_miso { + pinmux = ; + }; + + /* scb_spi_s_mosi */ + /omit-if-no-ref/ p0_2_scb0_spi_s_mosi: p0_2_scb0_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p1_2_scb1_spi_s_mosi: p1_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb1_spi_s_mosi: p3_2_scb1_spi_s_mosi { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb0_spi_s_mosi: p4_0_scb0_spi_s_mosi { + pinmux = ; + }; + + /* scb_spi_s_select0 */ + /omit-if-no-ref/ p1_0_scb1_spi_s_select0: p1_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb1_spi_s_select0: p3_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb1_spi_s_select0: p5_0_scb1_spi_s_select0 { + pinmux = ; + }; + /omit-if-no-ref/ p5_1_scb0_spi_s_select0: p5_1_scb0_spi_s_select0 { + pinmux = ; + }; + + /* scb_spi_s_select1 */ + /omit-if-no-ref/ p0_0_scb0_spi_s_select1: p0_0_scb0_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p0_5_scb1_spi_s_select1: p0_5_scb1_spi_s_select1 { + pinmux = ; + }; + /omit-if-no-ref/ p3_6_scb1_spi_s_select1: p3_6_scb1_spi_s_select1 { + pinmux = ; + }; + + /* scb_spi_s_select2 */ + /omit-if-no-ref/ p0_1_scb0_spi_s_select2: p0_1_scb0_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p0_4_scb1_spi_s_select2: p0_4_scb1_spi_s_select2 { + pinmux = ; + }; + /omit-if-no-ref/ p3_5_scb1_spi_s_select2: p3_5_scb1_spi_s_select2 { + pinmux = ; + }; + + /* scb_spi_s_select3 */ + /omit-if-no-ref/ p0_3_scb1_spi_s_select3: p0_3_scb1_spi_s_select3 { + pinmux = ; + }; + /omit-if-no-ref/ p3_4_scb1_spi_s_select3: p3_4_scb1_spi_s_select3 { + pinmux = ; + }; + + /* scb_uart_cts */ + /omit-if-no-ref/ p1_0_scb1_uart_cts: p1_0_scb1_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p3_0_scb2_uart_cts: p3_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p4_0_scb2_uart_cts: p4_0_scb2_uart_cts { + pinmux = ; + }; + /omit-if-no-ref/ p5_0_scb2_uart_cts: p5_0_scb2_uart_cts { + pinmux = ; + }; + + /* scb_uart_rts */ + /omit-if-no-ref/ p1_1_scb1_uart_rts: p1_1_scb1_uart_rts { + pinmux = ; + }; + /omit-if-no-ref/ p3_1_scb2_uart_rts: p3_1_scb2_uart_rts { + pinmux = ; + }; + + /* scb_uart_rx */ + /omit-if-no-ref/ p1_2_scb1_uart_rx: p1_2_scb1_uart_rx { + pinmux = ; + }; + /omit-if-no-ref/ p3_2_scb2_uart_rx: p3_2_scb2_uart_rx { + pinmux = ; + }; + + /* scb_uart_tx */ + /omit-if-no-ref/ p1_3_scb1_uart_tx: p1_3_scb1_uart_tx { + pinmux = ; + }; + /omit-if-no-ref/ p3_3_scb2_uart_tx: p3_3_scb2_uart_tx { + pinmux = ; + }; + + }; + }; +}; diff --git a/dts/arm/infineon/cat1b/cyw20829/cyw20829.dtsi b/dts/arm/infineon/cat1b/cyw20829/cyw20829.dtsi new file mode 100644 index 0000000000000..c0a59722e2f8b --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/cyw20829.dtsi @@ -0,0 +1,300 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m33"; + reg = <0>; + }; + }; + + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(244)>; + }; + + sram_bootstrap: memory@2003D000 { + compatible = "zephyr,memory-region", "mmio-sram"; + zephyr,memory-region = "BOOTSTRAP_RAM"; + reg = <0x2003D000 DT_SIZE_K(12)>; + }; + + soc { + pinctrl: pinctrl@40400000 { + compatible = "infineon,cat1-pinctrl"; + reg = <0x40400000 0x20000>; + }; + + hsiom: hsiom@40400000 { + compatible = "infineon,cat1-hsiom"; + reg = <0x40400000 0x4000>; + interrupts = <7 6>, <6 6>; + status = "disabled"; + }; + + gpio_prt0: gpio@40410000 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410000 0x80>; + interrupts = <0 6>; + gpio-controller; + ngpios = <6>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt1: gpio@40410080 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410080 0x80>; + interrupts = <1 6>; + gpio-controller; + ngpios = <7>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt2: gpio@40410100 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410100 0x80>; + interrupts = <2 6>; + gpio-controller; + ngpios = <6>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt3: gpio@40410180 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410180 0x80>; + interrupts = <3 6>; + gpio-controller; + ngpios = <8>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt4: gpio@40410200 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410200 0x80>; + interrupts = <4 6>; + gpio-controller; + ngpios = <2>; + status = "disabled"; + #gpio-cells = <2>; + }; + gpio_prt5: gpio@40410280 { + compatible = "infineon,cat1-gpio"; + reg = <0x40410280 0x80>; + interrupts = <5 6>; + gpio-controller; + ngpios = <3>; + status = "disabled"; + #gpio-cells = <2>; + }; + + ipc0: ipc@401d0000 { + compatible = "infineon,cat1-ipc"; + reg = <0x401d0000 0x10000>; + status = "disabled"; + #ipc-config-cells = <3>; + }; + + scb0: scb@40590000 { + compatible = "infineon,cat1-scb"; + reg = <0x40590000 0xfd0>; + interrupts = <8 6>; + status = "disabled"; + }; + scb1: scb@405a0000 { + compatible = "infineon,cat1-scb"; + reg = <0x405a0000 0xfd0>; + interrupts = <17 6>; + status = "disabled"; + }; + scb2: scb@405b0000 { + compatible = "infineon,cat1-scb"; + reg = <0x405b0000 0xfd0>; + interrupts = <18 6>; + status = "disabled"; + }; + + watchdog0: watchdog@4020c000 { + compatible = "infineon,cat1-watchdog"; + reg = <0x4020c000 0x10>; + interrupts = <15 6>; + status = "disabled"; + }; + + mcwdt0: mcwdt@4020d000 { + compatible = "infineon,cat1-lp-timer"; + reg = <0x4020d000 0x40>; + interrupts = <9 6>; + status = "disabled"; + }; + + counter0_0: counter@404a0000 { + compatible = "infineon,cat1-counter"; + reg = <0x404a0000 0x80>; + interrupts = <42 6>; + resolution = <32>; + status = "disabled"; + }; + counter0_1: counter@404a0080 { + compatible = "infineon,cat1-counter"; + reg = <0x404a0080 0x80>; + interrupts = <43 6>; + resolution = <32>; + status = "disabled"; + }; + counter1_0: counter@404a8000 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8000 0x80>; + interrupts = <44 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_1: counter@404a8080 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8080 0x80>; + interrupts = <45 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_2: counter@404a8100 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8100 0x80>; + interrupts = <46 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_3: counter@404a8180 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8180 0x80>; + interrupts = <47 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_4: counter@404a8200 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8200 0x80>; + interrupts = <48 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_5: counter@404a8280 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8280 0x80>; + interrupts = <49 6>; + resolution = <16>; + status = "disabled"; + }; + counter1_6: counter@404a8300 { + compatible = "infineon,cat1-counter"; + reg = <0x404a8300 0x80>; + interrupts = <50 6>; + resolution = <16>; + status = "disabled"; + }; + + pwm0_0: pwm@404a0000 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a0000 0x80>; + interrupts = <42 6>; + resolution = <32>; + status = "disabled"; + }; + pwm0_1: pwm@404a0080 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a0080 0x80>; + interrupts = <43 6>; + resolution = <32>; + status = "disabled"; + }; + pwm1_0: pwm@404a8000 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8000 0x80>; + interrupts = <44 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_1: pwm@404a8080 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8080 0x80>; + interrupts = <45 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_2: pwm@404a8100 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8100 0x80>; + interrupts = <46 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_3: pwm@404a8180 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8180 0x80>; + interrupts = <47 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_4: pwm@404a8200 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8200 0x80>; + interrupts = <48 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_5: pwm@404a8280 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8280 0x80>; + interrupts = <49 6>; + resolution = <16>; + status = "disabled"; + }; + pwm1_6: pwm@404a8300 { + compatible = "infineon,cat1-pwm"; + reg = <0x404a8300 0x80>; + interrupts = <50 6>; + resolution = <16>; + status = "disabled"; + }; + + dma0: dw@40180000 { + #dma-cells = <1>; + compatible = "infineon,cat1-dma"; + reg = <0x40180000 0x10000>; + dma-channels = <16>; + interrupts = <19 6>, /* CH0 */ + <20 6>, /* CH1 */ + <21 6>, /* CH2 */ + <22 6>, /* CH3 */ + <23 6>, /* CH4 */ + <24 6>, /* CH5 */ + <25 6>, /* CH6 */ + <26 6>, /* CH7 */ + <27 6>, /* CH8 */ + <28 6>, /* CH9 */ + <29 6>, /* CH10 */ + <30 6>, /* CH11 */ + <31 6>, /* CH12 */ + <32 6>, /* CH13 */ + <33 6>, /* CH14 */ + <34 6>; /* CH15 */ + status = "disabled"; + }; + bluetooth: btss@42000000 { + compatible = "infineon,cyw208xx-hci"; + reg = <0x42000000 0x6186A0>; + interrupts = <16 6>; + status = "disabled"; + }; + + }; +}; diff --git a/dts/arm/infineon/cat1b/cyw20829/system_clocks.dtsi b/dts/arm/infineon/cat1b/cyw20829/system_clocks.dtsi new file mode 100644 index 0000000000000..b40054d67a36a --- /dev/null +++ b/dts/arm/infineon/cat1b/cyw20829/system_clocks.dtsi @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "clock_source_def.h" +/ { + clocks { + /* iho */ + clk_iho: clk_iho { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <48000000>; + status = "okay"; + }; + + /* imo */ + clk_imo: clk_imo { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <8000000>; + status = "okay"; + }; + + /* fll */ + fll0: fll0 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <96000000>; + status = "okay"; + }; + + /* path mux0 */ + path_mux0: path_mux0 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_iho>; + status = "disabled"; + }; + + /* path mux1 */ + path_mux1: path_mux1 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_iho>; + status = "disabled"; + }; + + /* path mux2 */ + path_mux2: path_mux2 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_iho>; + status = "disabled"; + }; + + /* path mux3 */ + path_mux3: path_mux3 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clocks = <&clk_imo>; + status = "disabled"; + }; + + /* clk_hf0 */ + clk_hf0: clk_hf0 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clocks = <&fll0>; + status = "disabled"; + }; + + /* clk_hf1 */ + clk_hf1: clk_hf1 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clocks = <&fll0>; + status = "disabled"; + }; + + /* clk_hf2 */ + clk_hf2: clk_hf2 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <1>; + clocks = <&path_mux2>; + status = "disabled"; + }; + + /* clk_hf3 */ + clk_hf3: clk_hf3 { + #clock-cells = <0>; + compatible = "fixed-factor-clock"; + clock-div = <2>; + clocks = <&path_mux1>; + status = "disabled"; + }; + + }; + +}; diff --git a/dts/arm/infineon/cat1b/mpns/CYW20829A0KML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW20829A0KML.dtsi new file mode 100644 index 0000000000000..d1fc0a7c02689 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW20829A0KML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.40-qfn.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW20829A0LKML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW20829A0LKML.dtsi new file mode 100644 index 0000000000000..05ea3e26ed06f --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW20829A0LKML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.56-qfn.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW20829B0KML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW20829B0KML.dtsi new file mode 100644 index 0000000000000..d1fc0a7c02689 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW20829B0KML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.40-qfn.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW20829B0LKML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW20829B0LKML.dtsi new file mode 100644 index 0000000000000..d3ba211c22435 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW20829B0LKML.dtsi @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "../cyw20829/cyw20829.56-qfn.dtsi" + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/dts/arm/infineon/cat1b/mpns/CYW89829A0KML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW89829A0KML.dtsi new file mode 100644 index 0000000000000..d1fc0a7c02689 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW89829A0KML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.40-qfn.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW89829B01MKSBG.dtsi b/dts/arm/infineon/cat1b/mpns/CYW89829B01MKSBG.dtsi new file mode 100644 index 0000000000000..363ad188050f2 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW89829B01MKSBG.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.77-bga.dtsi" diff --git a/dts/arm/infineon/cat1b/mpns/CYW89829B0KML.dtsi b/dts/arm/infineon/cat1b/mpns/CYW89829B0KML.dtsi new file mode 100644 index 0000000000000..d1fc0a7c02689 --- /dev/null +++ b/dts/arm/infineon/cat1b/mpns/CYW89829B0KML.dtsi @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2023 Cypress Semiconductor Corporation (an Infineon company) or + * an affiliate of Cypress Semiconductor Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "../cyw20829/cyw20829.40-qfn.dtsi" diff --git a/dts/arm/infineon/xmc4500_F100x1024-intc.dtsi b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-intc.dtsi similarity index 100% rename from dts/arm/infineon/xmc4500_F100x1024-intc.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-intc.dtsi diff --git a/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-pinctrl.dtsi similarity index 99% rename from dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-pinctrl.dtsi index 4506e0c995fc9..d5eb1ba0039f9 100644 --- a/dts/arm/infineon/xmc4500_F100x1024-pinctrl.dtsi +++ b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024-pinctrl.dtsi @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include &pinctrl { diff --git a/dts/arm/infineon/xmc4500_F100x1024.dtsi b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024.dtsi similarity index 97% rename from dts/arm/infineon/xmc4500_F100x1024.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4500_F100x1024.dtsi index d368e397ea3c3..ff64b9bd9c19d 100644 --- a/dts/arm/infineon/xmc4500_F100x1024.dtsi +++ b/dts/arm/infineon/cat3/xmc/xmc4500_F100x1024.dtsi @@ -6,7 +6,7 @@ */ #include -#include +#include / { psram1: memory@10000000 { diff --git a/dts/arm/infineon/xmc4700_F144x2048-intc.dtsi b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-intc.dtsi similarity index 100% rename from dts/arm/infineon/xmc4700_F144x2048-intc.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-intc.dtsi diff --git a/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-pinctrl.dtsi similarity index 99% rename from dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-pinctrl.dtsi index e6bab488049d0..b40ba24a8a5c7 100644 --- a/dts/arm/infineon/xmc4700_F144x2048-pinctrl.dtsi +++ b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048-pinctrl.dtsi @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include #include &pinctrl { diff --git a/dts/arm/infineon/xmc4700_F144x2048.dtsi b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048.dtsi similarity index 98% rename from dts/arm/infineon/xmc4700_F144x2048.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4700_F144x2048.dtsi index ad8e1ea641357..7a1d6f4db6e69 100644 --- a/dts/arm/infineon/xmc4700_F144x2048.dtsi +++ b/dts/arm/infineon/cat3/xmc/xmc4700_F144x2048.dtsi @@ -5,7 +5,7 @@ */ #include -#include +#include / { psram1: memory@1ffe8000 { diff --git a/dts/arm/infineon/xmc4xxx.dtsi b/dts/arm/infineon/cat3/xmc/xmc4xxx.dtsi similarity index 100% rename from dts/arm/infineon/xmc4xxx.dtsi rename to dts/arm/infineon/cat3/xmc/xmc4xxx.dtsi diff --git a/dts/arm/intel_socfpga_std/socfpga.dtsi b/dts/arm/intel_socfpga_std/socfpga.dtsi index 7e1f37267d5ce..ad36609bfa1b2 100644 --- a/dts/arm/intel_socfpga_std/socfpga.dtsi +++ b/dts/arm/intel_socfpga_std/socfpga.dtsi @@ -227,6 +227,11 @@ reg = <0xffb30000 0xffff>; interrupts = <0 127 4 IRQ_DEFAULT_PRIORITY>; interrupt-parent = <&intc>; + num-out-eps = <16>; + num-in-eps = <16>; + ghwcfg1 = <0x00000000>; + ghwcfg2 = <0x208ffc90>; + ghwcfg4 = <0xfe0f0020>; status = "disabled"; }; @@ -235,6 +240,11 @@ reg = <0xffb40000 0xffff>; interrupts = <0 128 4 IRQ_DEFAULT_PRIORITY>; interrupt-parent = <&intc>; + num-out-eps = <16>; + num-in-eps = <16>; + ghwcfg1 = <0x00000000>; + ghwcfg2 = <0x208ffc90>; + ghwcfg4 = <0xfe0f0020>; status = "okay"; }; diff --git a/dts/arm/nordic/nrf51822.dtsi b/dts/arm/nordic/nrf51822.dtsi index b64de1d4985c8..11cc9eff2f9e8 100644 --- a/dts/arm/nordic/nrf51822.dtsi +++ b/dts/arm/nordic/nrf51822.dtsi @@ -5,6 +5,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci_controller; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -73,6 +74,11 @@ reg = <0x40001000 0x1000>; interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; + + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52805.dtsi b/dts/arm/nordic/nrf52805.dtsi index c5a184d5e288c..36213c186526c 100644 --- a/dts/arm/nordic/nrf52805.dtsi +++ b/dts/arm/nordic/nrf52805.dtsi @@ -9,6 +9,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci_controller; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -86,6 +87,14 @@ interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; ble-2mbps-supported; + + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52810.dtsi b/dts/arm/nordic/nrf52810.dtsi index 1ca4a9ea378a3..18b2e430943da 100644 --- a/dts/arm/nordic/nrf52810.dtsi +++ b/dts/arm/nordic/nrf52810.dtsi @@ -5,6 +5,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci_controller; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -90,6 +91,14 @@ interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; ble-2mbps-supported; + + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52811.dtsi b/dts/arm/nordic/nrf52811.dtsi index 63b8567658773..12615364cef37 100644 --- a/dts/arm/nordic/nrf52811.dtsi +++ b/dts/arm/nordic/nrf52811.dtsi @@ -9,6 +9,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci_controller; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -102,6 +103,14 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52820.dtsi b/dts/arm/nordic/nrf52820.dtsi index f93e449b0b2cc..21bb88aa99ce5 100644 --- a/dts/arm/nordic/nrf52820.dtsi +++ b/dts/arm/nordic/nrf52820.dtsi @@ -10,6 +10,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci_controller; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -98,6 +99,14 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + /* Note: In the nRF Connect SDK another Bluetooth controller + * is added and set as the default. + */ + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52832.dtsi b/dts/arm/nordic/nrf52832.dtsi index 13ee05226b76f..f467c5fc5c000 100644 --- a/dts/arm/nordic/nrf52832.dtsi +++ b/dts/arm/nordic/nrf52832.dtsi @@ -5,6 +5,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci_controller; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -90,6 +91,14 @@ interrupts = <1 NRF_DEFAULT_IRQ_PRIORITY>; status = "okay"; ble-2mbps-supported; + + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52833.dtsi b/dts/arm/nordic/nrf52833.dtsi index f22cb36bc14a4..1a27a14447bbf 100644 --- a/dts/arm/nordic/nrf52833.dtsi +++ b/dts/arm/nordic/nrf52833.dtsi @@ -9,6 +9,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci_controller; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -97,6 +98,14 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf52840.dtsi b/dts/arm/nordic/nrf52840.dtsi index 4cfb7abc511ef..5d209533a1ae9 100644 --- a/dts/arm/nordic/nrf52840.dtsi +++ b/dts/arm/nordic/nrf52840.dtsi @@ -5,6 +5,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci_controller; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -92,6 +93,14 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "okay"; + }; }; uart0: uart@40002000 { diff --git a/dts/arm/nordic/nrf5340_cpuapp_ipc.dtsi b/dts/arm/nordic/nrf5340_cpuapp_ipc.dtsi index 9dc8f70a7d0ce..f5cda20e9613f 100644 --- a/dts/arm/nordic/nrf5340_cpuapp_ipc.dtsi +++ b/dts/arm/nordic/nrf5340_cpuapp_ipc.dtsi @@ -11,4 +11,9 @@ ipc0: ipc0 { mbox-names = "tx", "rx"; role = "host"; status = "okay"; + + bt_hci_ipc0: bt_hci_ipc0 { + compatible = "zephyr,bt-hci-ipc"; + status = "okay"; + }; }; diff --git a/dts/arm/nordic/nrf5340_cpunet.dtsi b/dts/arm/nordic/nrf5340_cpunet.dtsi index 8a95b3e99850a..77b77759b2205 100644 --- a/dts/arm/nordic/nrf5340_cpunet.dtsi +++ b/dts/arm/nordic/nrf5340_cpunet.dtsi @@ -9,6 +9,7 @@ / { chosen { + zephyr,bt-hci = &bt_hci_controller; zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; }; @@ -100,6 +101,14 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "okay"; + }; }; rng: random@41009000 { diff --git a/dts/arm/nordic/nrf54h20_cpuapp.dtsi b/dts/arm/nordic/nrf54h20_cpuapp.dtsi index 9d011019f4afe..1cfa3dddb553a 100644 --- a/dts/arm/nordic/nrf54h20_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54h20_cpuapp.dtsi @@ -11,6 +11,8 @@ systick: &cpuapp_systick {}; nvic: &cpuapp_nvic {}; cpuppr_vevif: &cpuppr_vevif_remote {}; cpusys_vevif: &cpusys_vevif_remote {}; +wdt010: &cpuapp_wdt010 {}; +wdt011: &cpuapp_wdt011 {}; /delete-node/ &cpuppr; /delete-node/ &cpurad; diff --git a/dts/arm/nordic/nrf54h20_cpurad.dtsi b/dts/arm/nordic/nrf54h20_cpurad.dtsi index 2a62845dc8917..b426d660f3dc0 100644 --- a/dts/arm/nordic/nrf54h20_cpurad.dtsi +++ b/dts/arm/nordic/nrf54h20_cpurad.dtsi @@ -11,6 +11,8 @@ systick: &cpurad_systick {}; nvic: &cpurad_nvic {}; cpuppr_vevif: &cpuppr_vevif_remote {}; cpusys_vevif: &cpusys_vevif_remote {}; +wdt010: &cpurad_wdt010 {}; +wdt011: &cpurad_wdt011 {}; /delete-node/ &cpuapp; /delete-node/ &cpuapp_peripherals; @@ -48,7 +50,7 @@ cpusys_vevif: &cpusys_vevif_remote {}; }; &grtc { - owned-channels = <7 8 9 10 11 12 13 14>; + owned-channels = <7 8 9 10 11 12 13 14 15>; child-owned-channels = <8 9 10 11 12>; nonsecure-channels = <8 9 10 11 12>; interrupts = <109 NRF_DEFAULT_IRQ_PRIORITY>, diff --git a/dts/arm/nordic/nrf54l15_cpuapp.dtsi b/dts/arm/nordic/nrf54l15_cpuapp.dtsi index 6a4f5fcae239e..551d344f8426a 100644 --- a/dts/arm/nordic/nrf54l15_cpuapp.dtsi +++ b/dts/arm/nordic/nrf54l15_cpuapp.dtsi @@ -17,6 +17,10 @@ cpuflpr_vevif: &cpuflpr_vevif_remote {}; /delete-node/ &cpuflpr_clic; / { + chosen { + zephyr,bt-hci = &bt_hci_controller; + }; + soc { compatible = "simple-bus"; interrupt-parent = <&cpuapp_nvic>; @@ -29,14 +33,22 @@ cpuflpr_vevif: &cpuflpr_vevif_remote {}; }; }; +&bt_hci_controller { + status = "okay"; +}; + &cpuapp_ppb { compatible = "simple-bus"; ranges; }; &grtc { +#ifdef USE_NON_SECURE_ADDRESS_MAP + interrupts = <227 NRF_DEFAULT_IRQ_PRIORITY>, +#else interrupts = <228 NRF_DEFAULT_IRQ_PRIORITY>, - <229 NRF_DEFAULT_IRQ_PRIORITY>; /* reserved for Zero Latency IRQs */ +#endif + <229 NRF_DEFAULT_IRQ_PRIORITY>; /* reserved for Zero Latency IRQs */ }; &gpiote20 { diff --git a/dts/arm/nuvoton/m2l31x.dtsi b/dts/arm/nuvoton/m2l31x.dtsi index 1ebbd9118a074..b3cbd6c997b5d 100644 --- a/dts/arm/nuvoton/m2l31x.dtsi +++ b/dts/arm/nuvoton/m2l31x.dtsi @@ -18,6 +18,10 @@ zephyr,flash-controller = &rmc; }; + aliases { + rtc = &rtc; + }; + cpus { #address-cells = <1>; #size-cells = <0>; @@ -40,6 +44,7 @@ compatible = "nuvoton,numaker-scc"; reg = <0x40000200 0x100>; #clock-cells = <0>; + lxt = "enable"; clk-pclkdiv = <(NUMAKER_CLK_PCLKDIV_APB0DIV_DIV2 | NUMAKER_CLK_PCLKDIV_APB1DIV_DIV2)>; core-clock = ; @@ -320,6 +325,75 @@ status = "disabled"; #io-channel-cells = <1>; }; + + rtc: rtc@40041000 { + compatible = "nuvoton,numaker-rtc"; + reg = <0x40041000 0x138>; + interrupts = <6 0>; + oscillator = "lxt"; + clocks = <&pcc NUMAKER_RTC_MODULE 0 0>; + alarms-count = <1>; + }; + + epwm0: epwm@40058000 { + compatible = "nuvoton,numaker-pwm"; + reg = <0x40058000 0x37c>; + interrupts = <25 0>, <26 0>, <27 0>; + interrupt-names = "pair0", "pair1", "pair2"; + resets = <&rst NUMAKER_EPWM0_RST>; + prescaler = <19>; + clocks = <&pcc NUMAKER_EPWM0_MODULE NUMAKER_CLK_CLKSEL2_EPWM0SEL_PCLK0 0>; + #pwm-cells = <3>; + status = "disabled"; + }; + + epwm1: epwm@40059000 { + compatible = "nuvoton,numaker-pwm"; + reg = <0x40059000 0x37c>; + interrupts = <29 0>, <30 0>, <31 0>; + interrupt-names = "pair0", "pair1", "pair2"; + resets = <&rst NUMAKER_EPWM1_RST>; + prescaler = <19>; + clocks = <&pcc NUMAKER_EPWM1_MODULE NUMAKER_CLK_CLKSEL2_EPWM1SEL_PCLK1 0>; + #pwm-cells = <3>; + status = "disabled"; + }; + + canfd0: canfd@40020000 { + compatible = "nuvoton,numaker-canfd"; + reg = <0x40020000 0x200>, <0x40020200 0x1800>; + reg-names = "m_can", "message_ram"; + interrupts = <112 0>, <113 0>; + interrupt-names = "int0", "int1"; + resets = <&rst NUMAKER_CANFD0_RST>; + clocks = <&pcc NUMAKER_CANFD0_MODULE + NUMAKER_CLK_CLKSEL0_CANFD0SEL_HCLK + NUMAKER_CLK_CLKDIV5_CANFD0(1)>; + bosch,mram-cfg = <0x0 12 10 3 3 3 3 3>; + status = "disabled"; + }; + + canfd1: canfd@40024000 { + compatible = "nuvoton,numaker-canfd"; + reg = <0x40024000 0x200>, <0x40024200 0x1800>; + reg-names = "m_can", "message_ram"; + interrupts = <114 0>, <115 0>; + interrupt-names = "int0", "int1"; + resets = <&rst NUMAKER_CANFD1_RST>; + clocks = <&pcc NUMAKER_CANFD1_MODULE + NUMAKER_CLK_CLKSEL0_CANFD1SEL_HCLK + NUMAKER_CLK_CLKDIV5_CANFD1(1)>; + bosch,mram-cfg = <0x0 12 10 3 3 3 3 3>; + status = "disabled"; + }; + + wwdt: watchdog@40096000 { + compatible = "nuvoton,numaker-wwdt"; + reg = <0x40096000 0x10>; + interrupts = <9 0>; + clocks = <&pcc NUMAKER_WWDT_MODULE NUMAKER_CLK_CLKSEL1_WWDTSEL_LIRC 0>; + status = "disabled"; + }; }; }; diff --git a/dts/arm/nuvoton/npcx/npcx4/npcx4-pinctrl.dtsi b/dts/arm/nuvoton/npcx/npcx4/npcx4-pinctrl.dtsi index af45fa59ddb08..ec9979c707725 100644 --- a/dts/arm/nuvoton/npcx/npcx4/npcx4-pinctrl.dtsi +++ b/dts/arm/nuvoton/npcx/npcx4/npcx4-pinctrl.dtsi @@ -30,6 +30,22 @@ dev-ctl = <0x0 6 1 0x01>; }; + /omit-if-no-ref/ sio_clk_sel_96m: devctl3-sio-clk_sel-96m { + dev-ctl = <0x4 6 2 0x00>; + }; + + /omit-if-no-ref/ sio_clk_sel_100: devctl3-sio-clk_sel-100m { + dev-ctl = <0x4 6 2 0x01>; + }; + + /omit-if-no-ref/ sio_clk_sel_120m: devctl3-sio-clk_sel-120m { + dev-ctl = <0x4 6 2 0x02>; + }; + + /omit-if-no-ref/ sio_clk_sel_90m: devctl3-sio-clk_sel-90m { + dev-ctl = <0x4 6 2 0x03>; + }; + /* Prebuild nodes for peripheral device's pin-muxing and pad properties */ /* Flash Interface Unit (FIU) */ /omit-if-no-ref/ fiu_ext_io0_io1_clk_cs_gpa4_96_a2_a0: periph-fiu-ext { diff --git a/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi b/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi index 2b219c48edecb..35a40411835d4 100644 --- a/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi +++ b/dts/arm/nuvoton/npcx/npcx7/npcx7-pinctrl.dtsi @@ -22,6 +22,14 @@ dev-ctl = <0x0 6 1 0x01>; }; + /omit-if-no-ref/ sio_full_ck48: devctl4-sio-full-ck48 { + dev-ctl = <0x6 3 1 0x00>; + }; + + /omit-if-no-ref/ sio_full_ck50: devctl4-sio-full-ck50 { + dev-ctl = <0x6 3 1 0x01>; + }; + /* Prebuild nodes for peripheral device's pin-muxing and pad properties */ /* Flash Interface Unit (FIU) */ /omit-if-no-ref/ fiu_ext_io0_io1_clk_cs_gpa4_96_a2_a0: periph-fiu-ext { diff --git a/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi b/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi index 2ba0b78fdda29..583b5352fad7d 100644 --- a/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi +++ b/dts/arm/nuvoton/npcx/npcx9/npcx9-pinctrl.dtsi @@ -23,6 +23,14 @@ dev-ctl = <0x0 6 1 0x01>; }; + /omit-if-no-ref/ sio_full_ck48: devctl4-sio-full-ck48 { + dev-ctl = <0x6 3 1 0x00>; + }; + + /omit-if-no-ref/ sio_full_ck50: devctl4-sio-full-ck50 { + dev-ctl = <0x6 3 1 0x01>; + }; + /* Prebuild nodes for peripheral device's pin-muxing and pad properties */ /* Flash Interface Unit (FIU) */ /omit-if-no-ref/ fiu_ext_io0_io1_clk_cs_gpa4_96_a2_a0: periph-fiu-ext { diff --git a/dts/arm/nxp/nxp_imx6sx_m4.dtsi b/dts/arm/nxp/nxp_imx6sx_m4.dtsi index 4a6d606c25374..ce34a247b80e0 100644 --- a/dts/arm/nxp/nxp_imx6sx_m4.dtsi +++ b/dts/arm/nxp/nxp_imx6sx_m4.dtsi @@ -29,9 +29,10 @@ }; }; - tcml:memory@1fff8000 { + /* TCML 0x1fff8000 is aliased at 0 */ + tcml:memory@0 { compatible = "nxp,imx-itcm"; - reg = <0x1fff8000 DT_SIZE_K(32)>; + reg = <0x00000000 DT_SIZE_K(32)>; }; tcmu:memory@20000000 { diff --git a/dts/arm/nxp/nxp_imx7d_m4.dtsi b/dts/arm/nxp/nxp_imx7d_m4.dtsi index 9b7ed2aed5acc..b127c8eda4f5b 100644 --- a/dts/arm/nxp/nxp_imx7d_m4.dtsi +++ b/dts/arm/nxp/nxp_imx7d_m4.dtsi @@ -56,9 +56,10 @@ reg = <0x20200000 DT_SIZE_K(128)>; }; - ocram_s_code: code@20180000 { + /* OCRAM_S 0x20180000 is aliased at 0 */ + ocram_s_code: code@0 { compatible = "nxp,imx-code-bus"; - reg = <0x20180000 DT_SIZE_K(32)>; + reg = <0x00000000 DT_SIZE_K(32)>; }; ocram_s_sys: memory@180000 { diff --git a/dts/arm/nxp/nxp_k22fn512.dtsi b/dts/arm/nxp/nxp_k22fn512.dtsi new file mode 100644 index 0000000000000..76244b94d597b --- /dev/null +++ b/dts/arm/nxp/nxp_k22fn512.dtsi @@ -0,0 +1,11 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&flash0 { + reg = <0 DT_SIZE_K(512)>; +}; diff --git a/dts/arm/nxp/nxp_ke17z.dtsi b/dts/arm/nxp/nxp_ke17z.dtsi new file mode 100644 index 0000000000000..a7d3cd7f583fe --- /dev/null +++ b/dts/arm/nxp/nxp_ke17z.dtsi @@ -0,0 +1,50 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/delete-node/ &sram_l; +/delete-node/ &sram_u; + +/ { + chosen { + zephyr,flash-controller = &ftfa; + }; + + /* Fix sram_l and sram_u, they have different addr and size on KE17Z */ + sram_l: memory@1fffc000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x1fffc000 DT_SIZE_K(16)>; + zephyr,memory-region = "SRAML"; + }; + + sram_u: memory@20000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(32)>; + zephyr,memory-region = "SRAMU"; + }; + + soc{ + /* Remove ftfe, it doesn't exist on KE17Z */ + /delete-node/ ftfe; + + ftfa: flash-controller@40020000 { + compatible = "nxp,kinetis-ftfa"; + reg = <0x40020000 0x1000>; + interrupts = <5 0>; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 DT_SIZE_K(256)>; + erase-block-size = ; + write-block-size = <8>; + }; + }; + }; +}; diff --git a/dts/arm/nxp/nxp_ke17z512.dtsi b/dts/arm/nxp/nxp_ke17z512.dtsi new file mode 100644 index 0000000000000..f5bf211fe341d --- /dev/null +++ b/dts/arm/nxp/nxp_ke17z512.dtsi @@ -0,0 +1,47 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/delete-node/ &sram_l; +/delete-node/ &sram_u; + +/ { + /* Fix sram_l and sram_u, they have different addr and size on KE17Z512 */ + sram_l: memory@1fff8000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x1fff8000 DT_SIZE_K(32)>; + zephyr,memory-region = "SRAML"; + }; + + sram_u: memory@20000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(64)>; + zephyr,memory-region = "SRAMU"; + }; + + soc { + /* Fix flash, it has different size on KE17Z512 */ + /delete-node/ ftfe; + + ftfe: flash-controller@40020000 { + compatible = "nxp,kinetis-ftfe"; + reg = <0x40020000 0x1000>; + interrupts = <5 0>; + interrupt-names = "command-complete"; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 DT_SIZE_K(512)>; + erase-block-size = ; + write-block-size = <8>; + }; + }; + }; +}; diff --git a/dts/arm/nxp/nxp_ke1xf.dtsi b/dts/arm/nxp/nxp_ke1xf.dtsi index 6d2bacf26ea46..6aff4315889ad 100644 --- a/dts/arm/nxp/nxp_ke1xf.dtsi +++ b/dts/arm/nxp/nxp_ke1xf.dtsi @@ -284,12 +284,13 @@ }; lptmr0: lptmr@40040000 { - compatible = "nxp,kinetis-lptmr"; + compatible = "nxp,lptmr"; reg = <0x40040000 0x1000>; interrupts = <58 0>; clock-frequency = <128000>; prescaler = <1>; clk-source = <1>; + resolution = <16>; }; wdog: watchdog@40052000 { diff --git a/dts/arm/nxp/nxp_ke1xz.dtsi b/dts/arm/nxp/nxp_ke1xz.dtsi new file mode 100644 index 0000000000000..9623d5a337353 --- /dev/null +++ b/dts/arm/nxp/nxp_ke1xz.dtsi @@ -0,0 +1,260 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "armv6-m.dtsi" +#include +#include +#include +#include + +/ { + chosen { + zephyr,flash-controller = &ftfe; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-m0+"; + clock-frequency = <48000000>; + reg = <0>; + }; + }; + + sram_l: memory@1fffe000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x1FFFE000 DT_SIZE_K(8)>; + zephyr,memory-region = "SRAML"; + }; + + sram_u: memory@20000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(24)>; + zephyr,memory-region = "SRAMU"; + }; + + pinctrl: pinctrl { + compatible = "nxp,kinetis-pinctrl"; + }; + + soc { + scg: scg@40064000 { + sosc-mode = ; + compatible = "nxp,kinetis-scg"; + reg = <0x40064000 0x1000>; + #clock-cells = <1>; + + sirc_clk: sirc_clk { + compatible = "fixed-clock"; + clock-frequency = <8000000>; + #clock-cells = <0>; + }; + + firc_clk: firc_clk { + compatible = "fixed-clock"; + clock-frequency = <48000000>; + #clock-cells = <0>; + }; + + core_clk: core_clk { + compatible = "fixed-factor-clock"; + clocks = <&firc_clk>; + clock-div = <1>; + #clock-cells = <0>; + }; + + bus_clk: bus_clk { + compatible = "fixed-factor-clock"; + clocks = <&core_clk>; + clock-div = <4>; + #clock-cells = <0>; + }; + + sircdiv2_clk: sircdiv2_clk { + compatible = "fixed-factor-clock"; + clocks = <&sirc_clk>; + clock-div = <2>; + #clock-cells = <0>; + }; + + fircdiv2_clk: fircdiv2_clk { + compatible = "fixed-factor-clock"; + clocks = <&firc_clk>; + clock-div = <1>; + #clock-cells = <0>; + }; + }; + + pcc: pcc@40065000 { + compatible = "nxp,kinetis-pcc"; + reg = <0x40065000 0x1000>; + #clock-cells = <2>; + }; + + ftfe: flash-controller@40020000 { + compatible = "nxp,kinetis-ftfe"; + reg = <0x40020000 0x1000>; + interrupts = <5 0>; + interrupt-names = "command-complete"; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + reg = <0 DT_SIZE_K(256)>; + erase-block-size = ; + write-block-size = <8>; + }; + }; + + lpuart0: uart@4006a000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4006a000 0x1000>; + interrupts = <12 0>; + clocks = <&pcc 0x1a8 KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; + + lpuart1: uart@4006b000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4006b000 0x1000>; + interrupts = <13 0>; + clocks = <&pcc 0x1ac KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; + + lpuart2: uart@4006c000 { + compatible = "nxp,kinetis-lpuart"; + reg = <0x4006c000 0x1000>; + interrupts = <14 0>; + clocks = <&pcc 0x1b0 KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; + + porta: pinmux@40049000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x40049000 0x1000>; + clocks = <&pcc 0x124 KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + portb: pinmux@4004a000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x4004a000 0x1000>; + clocks = <&pcc 0x128 KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + portc: pinmux@4004b000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x4004b000 0x1000>; + clocks = <&pcc 0x12c KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + portd: pinmux@4004c000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x4004c000 0x1000>; + clocks = <&pcc 0x130 KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + porte: pinmux@4004d000 { + compatible = "nxp,kinetis-pinmux"; + reg = <0x4004d000 0x1000>; + clocks = <&pcc 0x134 KINETIS_PCC_SRC_NONE_OR_EXT>; + }; + + gpios0: gpios0@400ff000 { + compatible = "nxp,gpio-cluster"; + interrupts = <7 2>; + reg = <0x400ff000 0x200>; + ranges = <0x0 0x400ff000 0x200>; + #address-cells = <1>; + #size-cells = <1>; + + gpioa: gpio@400ff000 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0x0 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&porta>; + }; + + gpioe: gpio@400ff100 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0x100 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&porte>; + }; + }; + + gpios1: gpios1@400ff040 { + compatible = "nxp,gpio-cluster"; + interrupts = <26 2>; + reg = <0x400ff040 0x200>; + ranges = <0x40 0x400ff040 0x200>; + #address-cells = <1>; + #size-cells = <1>; + + gpiob: gpio@400ff040 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0x40 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&portb>; + }; + + gpioc: gpio@400ff080 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0x80 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&portc>; + }; + + gpiod: gpio@400ff0c0 { + compatible = "nxp,kinetis-gpio"; + status = "disabled"; + reg = <0xc0 0x40>; + gpio-controller; + #gpio-cells = <2>; + nxp,kinetis-port = <&portd>; + }; + }; + + lpi2c0: i2c@40066000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40066000 0x1000>; + interrupts = <8 0>; + clocks = <&pcc 0x198 KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; + + lpi2c1: i2c@40067000 { + compatible = "nxp,imx-lpi2c"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40067000 0x1000>; + interrupts = <9 0>; + clocks = <&pcc 0x19c KINETIS_PCC_SRC_FIRC_ASYNC>; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <2>; +}; diff --git a/dts/arm/nxp/nxp_lpc51u68.dtsi b/dts/arm/nxp/nxp_lpc51u68.dtsi index 964e863485ba9..69c0070a18273 100644 --- a/dts/arm/nxp/nxp_lpc51u68.dtsi +++ b/dts/arm/nxp/nxp_lpc51u68.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include / { cpus { @@ -26,6 +27,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x40000000 0x4000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; sram0:memory@20000000 { @@ -35,7 +40,7 @@ sramx:memory@4000000 { compatible = "mmio-sram"; - reg = <0x40000000 DT_SIZE_K(32)>; + reg = <0x04000000 DT_SIZE_K(32)>; }; flash0: flash@0 { @@ -54,22 +59,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@4008c000 { compatible = "nxp,lpc-gpio"; reg = <0x4008c000 0x2484>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; + + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x4008C000 0x2484>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; }; pint: pint@40004000 { @@ -88,6 +98,7 @@ reg = <0x40086000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -96,6 +107,7 @@ reg = <0x40087000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -104,6 +116,7 @@ reg = <0x40088000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -112,6 +125,7 @@ reg = <0x40089000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -120,6 +134,7 @@ reg = <0x4008a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -128,6 +143,7 @@ reg = <0x40096000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -136,6 +152,7 @@ reg = <0x40097000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -144,6 +161,7 @@ reg = <0x40098000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; diff --git a/dts/arm/nxp/nxp_lpc54xxx.dtsi b/dts/arm/nxp/nxp_lpc54xxx.dtsi index a5befec1257f0..922a93e19ab31 100644 --- a/dts/arm/nxp/nxp_lpc54xxx.dtsi +++ b/dts/arm/nxp/nxp_lpc54xxx.dtsi @@ -9,6 +9,7 @@ #include #include #include +#include / { aliases{ @@ -41,6 +42,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x40000000 0x4000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; /* @@ -109,22 +114,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@4008c000 { compatible = "nxp,lpc-gpio"; reg = <0x4008c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; + + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + reg = <0>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x4008C000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + reg = <1>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; }; pint: pint@40004000 { @@ -151,6 +161,7 @@ reg = <0x40086000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -159,6 +170,7 @@ reg = <0x40087000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -167,6 +179,7 @@ reg = <0x40088000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -175,6 +188,7 @@ reg = <0x40089000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -183,6 +197,7 @@ reg = <0x4008a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -191,6 +206,7 @@ reg = <0x40096000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -199,6 +215,7 @@ reg = <0x40097000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -207,6 +224,7 @@ reg = <0x40098000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; }; diff --git a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi index c2f8295e57578..60888d4ea0f7b 100644 --- a/dts/arm/nxp/nxp_lpc55S0x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S0x_common.dtsi @@ -8,6 +8,7 @@ #include #include #include +#include / { cpus { @@ -68,6 +69,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x4000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -112,22 +117,26 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; }; pint: pint@4000 { @@ -147,6 +156,7 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -155,6 +165,7 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -163,6 +174,7 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -171,6 +183,7 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -179,6 +192,7 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -187,6 +201,7 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -195,6 +210,7 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -203,6 +219,7 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; @@ -211,6 +228,7 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -222,6 +240,7 @@ interrupts = <43 0>, <44 0>; interrupt-names = "int0", "int1"; clocks = <&syscon MCUX_MCAN_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 7)>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; status = "disabled"; }; diff --git a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi index 05ad85196be8f..636f419f77a57 100644 --- a/dts/arm/nxp/nxp_lpc55S1x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S1x_common.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include / { cpus { @@ -35,13 +36,15 @@ #size-cells = <1>; sramx: memory@4000000 { - compatible = "mmio-sram"; + compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x4000000 DT_SIZE_K(16)>; + zephyr,memory-region = "SRAMX"; }; sram0: memory@20000000 { - compatible = "mmio-sram"; + compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x20000000 DT_SIZE_K(32)>; + zephyr,memory-region = "SRAM0"; }; sram1: memory@20008000 { @@ -73,6 +76,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x4000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -117,22 +124,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + reg = <0>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + reg = <1>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; }; pint: pint@4000 { @@ -152,6 +164,7 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -160,6 +173,7 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -168,6 +182,7 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -176,6 +191,7 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -184,6 +200,7 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -192,6 +209,7 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -200,6 +218,7 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -208,6 +227,7 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; @@ -217,6 +237,7 @@ interrupts = <43 0>, <44 0>; interrupt-names = "int0", "int1"; clocks = <&syscon MCUX_MCAN_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 7)>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; status = "disabled"; }; @@ -226,6 +247,7 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi index 5a5e435083309..bb29407288c3c 100644 --- a/dts/arm/nxp/nxp_lpc55S2x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S2x_common.dtsi @@ -12,6 +12,7 @@ #include #include #include +#include / { aliases { @@ -88,6 +89,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x1000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -126,22 +131,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; + + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; }; pint: pint@4000 { @@ -179,6 +189,7 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; status = "disabled"; }; @@ -187,6 +198,7 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; status = "disabled"; }; @@ -195,6 +207,7 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; status = "disabled"; }; @@ -203,6 +216,7 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; status = "disabled"; }; @@ -211,6 +225,7 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; status = "disabled"; }; @@ -219,6 +234,7 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; status = "disabled"; }; @@ -227,6 +243,7 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; status = "disabled"; }; @@ -235,6 +252,7 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; status = "disabled"; }; @@ -249,6 +267,7 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi index 311ad16e3ace2..3b2c079b37ecf 100644 --- a/dts/arm/nxp/nxp_lpc55S3x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S3x_common.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { cpus { @@ -73,6 +74,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x1000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -112,30 +117,33 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x278c>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + reg = <0x8c000 0x2488>; + #address-cells = <1>; + #size-cells = <0>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x278c>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; - }; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; - gpio2: gpio@2 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x278c>; - gpio-controller; - #gpio-cells = <2>; - port = <2>; + gpio2: gpio@2 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <2>; + }; }; dma0: dma-controller@82000 { @@ -179,6 +187,7 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; dmas = <&dma0 4>, <&dma0 5>; dma-names = "rx", "tx"; status = "disabled"; @@ -189,6 +198,7 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; dmas = <&dma0 6>, <&dma0 7>; dma-names = "rx", "tx"; status = "disabled"; @@ -199,6 +209,7 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; dmas = <&dma0 10>, <&dma0 11>; dma-names = "rx", "tx"; status = "disabled"; @@ -209,6 +220,7 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; dmas = <&dma0 8>, <&dma0 9>; dma-names = "rx", "tx"; status = "disabled"; @@ -219,6 +231,7 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; dmas = <&dma0 12>, <&dma0 13>; dma-names = "rx", "tx"; status = "disabled"; @@ -229,6 +242,7 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; dmas = <&dma0 14>, <&dma0 15>; dma-names = "rx", "tx"; status = "disabled"; @@ -239,6 +253,7 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; dmas = <&dma0 16>, <&dma0 17>; dma-names = "rx", "tx"; status = "disabled"; @@ -249,6 +264,7 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; dmas = <&dma0 18>, <&dma0 19>; dma-names = "rx", "tx"; status = "disabled"; @@ -259,6 +275,7 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; dmas = <&dma0 2>, <&dma0 3>; dma-names = "rx", "tx"; status = "disabled"; @@ -318,6 +335,7 @@ interrupts = <43 0>, <44 0>; interrupt-names = "int0", "int1"; clocks = <&syscon MCUX_MCAN_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 7)>; bosch,mram-cfg = <0x0 15 15 8 8 0 15 15>; status = "disabled"; }; diff --git a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi index 3178e05a54eb1..07883ab825305 100644 --- a/dts/arm/nxp/nxp_lpc55S6x_common.dtsi +++ b/dts/arm/nxp/nxp_lpc55S6x_common.dtsi @@ -13,6 +13,7 @@ #include #include #include +#include / { aliases { @@ -113,6 +114,10 @@ compatible = "nxp,lpc-syscon"; reg = <0x0 0x1000>; #clock-cells = <1>; + reset: reset { + compatible = "nxp,lpc-syscon-reset"; + #reset-cells = <1>; + }; }; iap: flash-controller@34000 { @@ -156,22 +161,27 @@ }; }; - gpio0: gpio@0 { + gpio: gpio@8c000 { compatible = "nxp,lpc-gpio"; reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x8c000 0x2488>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + reg = <0>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; + + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + reg = <1>; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + }; }; pint: pint@4000 { @@ -214,6 +224,7 @@ compatible = "nxp,lpc-mailbox"; reg = <0x8b000 0xEC>; interrupts = <31 0>; + resets = <&reset NXP_SYSCON_RESET(0, 26)>; status = "disabled"; }; @@ -222,6 +233,9 @@ reg = <0x86000 0x1000>; interrupts = <14 0>; clocks = <&syscon MCUX_FLEXCOMM0_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 11)>; + dmas = <&dma0 4>, <&dma0 5>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -230,6 +244,9 @@ reg = <0x87000 0x1000>; interrupts = <15 0>; clocks = <&syscon MCUX_FLEXCOMM1_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 12)>; + dmas = <&dma0 6 &dma0 7>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -238,6 +255,9 @@ reg = <0x88000 0x1000>; interrupts = <16 0>; clocks = <&syscon MCUX_FLEXCOMM2_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 13)>; + dmas = <&dma0 10 &dma0 11>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -246,6 +266,9 @@ reg = <0x89000 0x1000>; interrupts = <17 0>; clocks = <&syscon MCUX_FLEXCOMM3_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 14)>; + dmas = <&dma0 8 &dma0 9>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -254,6 +277,9 @@ reg = <0x8a000 0x1000>; interrupts = <18 0>; clocks = <&syscon MCUX_FLEXCOMM4_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 15)>; + dmas = <&dma0 12 &dma0 13>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -262,6 +288,9 @@ reg = <0x96000 0x1000>; interrupts = <19 0>; clocks = <&syscon MCUX_FLEXCOMM5_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 16)>; + dmas = <&dma0 14 &dma0 15>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -270,6 +299,9 @@ reg = <0x97000 0x1000>; interrupts = <20 0>; clocks = <&syscon MCUX_FLEXCOMM6_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 17)>; + dmas = <&dma0 16 &dma0 17>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -278,6 +310,9 @@ reg = <0x98000 0x1000>; interrupts = <21 0>; clocks = <&syscon MCUX_FLEXCOMM7_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 18)>; + dmas = <&dma0 18 &dma0 19>; + dma-names = "rx", "tx"; status = "disabled"; }; @@ -300,6 +335,9 @@ reg = <0x9f000 0x1000>; interrupts = <59 0>; clocks = <&syscon MCUX_HS_SPI_CLK>; + resets = <&reset NXP_SYSCON_RESET(2, 28)>; + dmas = <&dma0 2 &dma0 3>; + dma-names = "rx", "tx"; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -352,6 +390,12 @@ status = "disabled"; }; + usbphy1: usbphy@38000 { + compatible = "nxp,usbphy"; + reg = <0x38000 0x1000>; + status = "disabled"; + }; + ctimer0: ctimer@8000 { compatible = "nxp,lpc-ctimer"; reg = <0x8000 0x1000>; @@ -429,6 +473,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&syscon MCUX_MRT_CLK>; + resets = <&reset NXP_SYSCON_RESET(1, 0)>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_mcxn94x_common.dtsi b/dts/arm/nxp/nxp_mcxn94x_common.dtsi index ad7d25a8ec72b..c14a6f2698e84 100644 --- a/dts/arm/nxp/nxp_mcxn94x_common.dtsi +++ b/dts/arm/nxp/nxp_mcxn94x_common.dtsi @@ -572,7 +572,8 @@ compatible = "soc-nv-flash"; reg = <0 DT_SIZE_M(2)>; erase-block-size = <8192>; - write-block-size = <16>; + /* MCXN94x ROM Flash API supports writing of 128B pages. */ + write-block-size = <128>; }; }; @@ -786,6 +787,135 @@ input = <0>; prescale = <0>; }; + + usdhc0: usdhc@109000 { + compatible = "nxp,imx-usdhc"; + reg = <0x109000 0x1000>; + interrupts = <61 0>; + status = "disabled"; + clocks = <&syscon MCUX_USDHC1_CLK>; + max-bus-freq = <52000000>; + min-bus-freq = <400000>; + }; + + vref: vref@111000 { + compatible = "nxp,vref"; + regulator-name = "mcxn94x-vref"; + reg = <0x111000 0x14>; + status = "disabled"; + nxp,buffer-startup-delay-us = <400>; + nxp,bandgap-startup-time-us = <20>; + regulator-min-microvolt = <1000000>; + regulator-max-microvolt = <2100000>; + }; + + lpadc0: lpadc@10d000 { + compatible = "nxp,lpc-lpadc"; + reg = <0x10d000 0x1000>; + interrupts = <45 0>; + status = "disabled"; + clk-divider = <1>; + clk-source = <0>; + voltage-ref= <1>; + calibration-average = <128>; + power-level = <0>; + offset-value-a = <0>; + offset-value-b = <0>; + #io-channel-cells = <1>; + clocks = <&syscon MCUX_LPADC1_CLK>; + nxp,reference-supply = <&vref>; + }; + + lpadc1: lpadc@10e000 { + compatible = "nxp,lpc-lpadc"; + reg = <0x10e000 0x1000>; + interrupts = <46 0>; + status = "disabled"; + clk-divider = <1>; + clk-source = <0>; + voltage-ref= <0>; + calibration-average = <128>; + power-level = <1>; + offset-value-a = <0>; + offset-value-b = <0>; + #io-channel-cells = <1>; + clocks = <&syscon MCUX_LPADC2_CLK>; + }; + + usb1: usbd@10b000 { + compatible = "nxp,ehci"; + reg = <0x10b000 0x1000>; + interrupts = <67 0>; + interrupt-names = "usb_otg"; + num-bidir-endpoints = <8>; + status = "disabled"; + }; + + lpcmp0: lpcmp@51000 { + compatible = "nxp,lpcmp"; + reg = <0x51000 0x1000>; + interrupts = <109 0>; + status = "disabled"; + #io-channel-cells = <2>; + }; + + lpcmp1: lpcmp@52000 { + compatible = "nxp,lpcmp"; + reg = <0x52000 0x1000>; + interrupts = <110 0>; + status = "disabled"; + #io-channel-cells = <2>; + }; + + lpcmp2: lpcmp@53000 { + compatible = "nxp,lpcmp"; + reg = <0x53000 0x1000>; + interrupts = <111 0>; + status = "disabled"; + #io-channel-cells = <2>; + }; + + flexcan0: can@d4000 { + compatible = "nxp,flexcan"; + reg = <0xd4000 0x4000>; + interrupts = <62 0>; + interrupt-names = "common"; + clocks = <&syscon MCUX_FLEXCAN0_CLK>; + clk-source = <0>; + status = "disabled"; + }; + + flexcan1: can@d8000 { + compatible = "nxp,flexcan"; + reg = <0xd8000 0x4000>; + interrupts = <63 0>; + interrupt-names = "common"; + clocks = <&syscon MCUX_FLEXCAN1_CLK>; + clk-source = <0>; + status = "disabled"; + }; + + lptmr0: lptmr@4a000 { + compatible = "nxp,lptmr"; + reg = <0x4a000 0x1000>; + interrupts = <143 0>; + clock-frequency = <16000>; + prescaler = <1>; + clk-source = <1>; + resolution = <32>; + }; + + flexio0: flexio@105000 { + compatible = "nxp,flexio"; + reg = <0x105000 0x1000>; + status = "disabled"; + interrupts = <105 0>; + clocks = <&syscon MCUX_FLEXIO0_CLK>; + flexio0_lcd: flexio0-lcd { + compatible = "nxp,mipi-dbi-flexio-lcdif"; + status = "disabled"; + }; + }; }; &systick { diff --git a/dts/arm/nxp/nxp_rt1040.dtsi b/dts/arm/nxp/nxp_rt1040.dtsi index 70dd0b0d4ad28..888d4eb1bd9c6 100644 --- a/dts/arm/nxp/nxp_rt1040.dtsi +++ b/dts/arm/nxp/nxp_rt1040.dtsi @@ -11,7 +11,7 @@ }; &sysclk { - clock-frequency = <500000000>; + clock-frequency = <528000000>; }; &ccm { @@ -20,10 +20,13 @@ }; arm-podf { - clock-div = <2>; + clock-div = <1>; }; }; +&gpt2 { + gptfreq = <33000000>; +}; / { soc { diff --git a/dts/arm/nxp/nxp_rt1060.dtsi b/dts/arm/nxp/nxp_rt1060.dtsi index ccd92ef7e50ef..8d308a27509f4 100644 --- a/dts/arm/nxp/nxp_rt1060.dtsi +++ b/dts/arm/nxp/nxp_rt1060.dtsi @@ -50,7 +50,7 @@ /* i.MX rt1060 has a second Ethernet controller. */ enet2: ethernet@402d4000 { compatible = "nxp,enet"; - reg = <0x402D8000 0x628>; + reg = <0x402d4000 0x628>; clocks = <&ccm IMX_CCM_ENET_CLK 0 0>; enet2_mac: ethernet { compatible = "nxp,enet-mac"; diff --git a/dts/arm/nxp/nxp_rt10xx.dtsi b/dts/arm/nxp/nxp_rt10xx.dtsi index 6c827e7ce7fa7..df04eff6841bd 100644 --- a/dts/arm/nxp/nxp_rt10xx.dtsi +++ b/dts/arm/nxp/nxp_rt10xx.dtsi @@ -297,6 +297,15 @@ #clock-cells = <0>; }; + sys-pll { + compatible = "nxp,imx-ccm-fnpll"; + loop-div = <22>; + numerator = <0>; + denominator = <1>; + src = <0>; + #clock-cells = <0>; + }; + #clock-cells = <3>; }; @@ -826,6 +835,18 @@ status = "disabled"; }; + usbphy1: usbphy@400d9000 { + compatible = "nxp,usbphy"; + reg = <0x400D9000 0x1000>; + status = "disabled"; + }; + + usbphy2: usbphy@400da000 { + compatible = "nxp,usbphy"; + reg = <0x400DA000 0x1000>; + status = "disabled"; + }; + usdhc1: usdhc@402c0000 { compatible = "nxp,imx-usdhc"; reg = <0x402c0000 0x4000>; diff --git a/dts/arm/nxp/nxp_rt1160.dtsi b/dts/arm/nxp/nxp_rt1160.dtsi new file mode 100644 index 0000000000000..1794204a80f30 --- /dev/null +++ b/dts/arm/nxp/nxp_rt1160.dtsi @@ -0,0 +1,11 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Configure ARM PLL to 600MHz */ +&arm_pll { + clock-mult = <100>; + clock-div = <4>; +}; diff --git a/dts/arm/nxp/nxp_rt1170.dtsi b/dts/arm/nxp/nxp_rt1170.dtsi new file mode 100644 index 0000000000000..555225b94fd93 --- /dev/null +++ b/dts/arm/nxp/nxp_rt1170.dtsi @@ -0,0 +1,11 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Configure ARM PLL to 996MHz */ +&arm_pll { + clock-mult = <83>; + clock-div = <2>; +}; diff --git a/dts/arm/nxp/nxp_rt11xx.dtsi b/dts/arm/nxp/nxp_rt11xx.dtsi index 03611213830ae..c9c126f5173ed 100644 --- a/dts/arm/nxp/nxp_rt11xx.dtsi +++ b/dts/arm/nxp/nxp_rt11xx.dtsi @@ -164,11 +164,55 @@ clocks = <&ccm IMX_CCM_GPT_CLK 0x45 0>; }; + qtmr1: qtmr@4015c000 { + compatible = "nxp,qtmr-pwm"; + reg = <0x4015c000 0x4000>; + interrupts = <171 0>; + status = "disabled"; + clocks = <&ccm IMX_CCM_QTMR1_CLK 0x0 0>; + }; + + qtmr2: qtmr@40160000 { + compatible = "nxp,qtmr-pwm"; + reg = <0x40160000 0x4000>; + interrupts = <172 0>; + status = "disabled"; + clocks = <&ccm IMX_CCM_QTMR2_CLK 0x0 0>; + }; + + qtmr3: qtmr@40164000 { + compatible = "nxp,qtmr-pwm"; + reg = <0x40164000 0x4000>; + interrupts = <173 0>; + status = "disabled"; + clocks = <&ccm IMX_CCM_QTMR3_CLK 0x0 0>; + }; + + qtmr4: qtmr@40168000 { + compatible = "nxp,qtmr-pwm"; + reg = <0x40168000 0x4000>; + interrupts = <174 0>; + status = "disabled"; + clocks = <&ccm IMX_CCM_QTMR4_CLK 0x0 0>; + }; + ccm: ccm@40cc0000 { compatible = "nxp,imx-ccm-rev2"; reg = <0x40cc0000 0x4000>; #clock-cells = <3>; + + /* + * ARM PLL is an integer PLL, with an input clock + * of 24MHz. The PLL features a loop divider and + * post divider. The output frequency is calculated + * as Fout = 24MHz * (clock-mult / clock-div) + */ + arm_pll: arm-pll { + compatible = "fixed-factor-clock"; + #clock-cells = <0>; + }; + }; gpio1: gpio@4012c000 { @@ -732,22 +776,30 @@ }; }; - /* - * enet1g peripheral to use with kinetis-ethernet (eth_mcux) driver - * just like the enet peripheral (i.e. only 10/100Mbit for now) - */ enet1g: ethernet@40420000 { - compatible = "nxp,kinetis-ethernet"; + compatible = "nxp,enet1g"; reg = <0x40420000 0x628>; - interrupts = <141 0>; - interrupt-names = "COMMON"; + clocks = <&ccm IMX_CCM_ENET1G_CLK 0 0>; status = "disabled"; - phy-addr = <1>; - ptp1g: ptp { - compatible = "nxp,kinetis-ptp"; + enet1g_mac: ethernet { + compatible = "nxp,enet-mac"; + interrupts = <141 0>; + interrupt-names = "COMMON"; + nxp,mdio = <&enet1g_mdio>; + nxp,ptp-clock = <&enet1g_ptp_clock>; + status = "disabled"; + }; + enet1g_mdio: mdio { + compatible = "nxp,enet-mdio"; status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + enet1g_ptp_clock: ptp_clock { + compatible = "nxp,enet-ptp-clock"; interrupts = <142 0>; - interrupt-names = "IEEE1588_TMR"; + status = "disabled"; + clocks = <&ccm IMX_CCM_ENET_PLL 0 0>; }; }; @@ -808,6 +860,35 @@ reg = <0x40800000 0x4000>; interrupts = <56 1>; status = "disabled"; + source = <&mipi_csi2rx>; + + port { + csi_ep_in: endpoint { + remote-endpoint = <&mipi_csi2rx_ep_out>; + }; + }; + }; + + mipi_csi2rx: mipi_csi2rx@40810000 { + compatible = "nxp,mipi-csi2rx"; + reg = <0x40810000 0x200>; + status = "disabled"; + + ports { + #address-cells = <1>; + #size-cells = <0>; + + port@0 { + reg = <0>; + mipi_csi2rx_ep_out: endpoint { + remote-endpoint = <&csi_ep_in>; + }; + }; + + port@1 { + reg = <1>; + }; + }; }; flexcan1: can@400c4000 { diff --git a/dts/arm/nxp/nxp_rt5xx_common.dtsi b/dts/arm/nxp/nxp_rt5xx_common.dtsi index fc6714b951e0c..63954b3904dbe 100644 --- a/dts/arm/nxp/nxp_rt5xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt5xx_common.dtsi @@ -13,6 +13,7 @@ #include #include #include +#include / { chosen { @@ -115,6 +116,7 @@ */ clkctl0: clkctl@1000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x1000 0x1000>; #clock-cells = <1>; @@ -129,72 +131,85 @@ }; clkctl1: clkctl@21000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x21000 0x1000>; #clock-cells = <1>; }; + rstctl0: reset@0 { + compatible = "nxp,rstctl"; + reg = <0x0 0x80>; + #reset-cells = <1>; + }; + + rstctl1: reset@20000 { + compatible = "nxp,rstctl"; + reg = <0x20000 0x80>; + #reset-cells = <1>; + }; + uuid: uuid@2f50 { compatible = "nxp,lpc-uid"; reg = <0x2f50 0x10>; }; - gpio0: gpio@0 { + gpio: gpio@100000 { compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + reg = <0x100000 0x2784>; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; - }; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio2: gpio@2 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <2>; - }; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; - gpio3: gpio@3 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <3>; - }; + gpio2: gpio@2 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <2>; + }; - gpio4: gpio@4 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <4>; - }; + gpio3: gpio@3 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <3>; + }; - gpio5: gpio@5 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <5>; - }; + gpio4: gpio@4 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <4>; + }; - gpio6: gpio@6 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <6>; + gpio5: gpio@5 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <5>; + }; + + gpio6: gpio@6 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <6>; + }; }; pint: pint@25000 { @@ -214,6 +229,7 @@ reg = <0x106000 0x1000>; interrupts = <14 0>; clocks = <&clkctl1 MCUX_FLEXCOMM0_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 8)>; status = "disabled"; }; @@ -222,6 +238,7 @@ reg = <0x107000 0x1000>; interrupts = <15 0>; clocks = <&clkctl1 MCUX_FLEXCOMM1_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 9)>; status = "disabled"; }; @@ -230,6 +247,7 @@ reg = <0x108000 0x1000>; interrupts = <16 0>; clocks = <&clkctl1 MCUX_FLEXCOMM2_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 10)>; status = "disabled"; }; @@ -238,6 +256,7 @@ reg = <0x109000 0x1000>; interrupts = <17 0>; clocks = <&clkctl1 MCUX_FLEXCOMM3_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 11)>; status = "disabled"; }; @@ -246,6 +265,7 @@ reg = <0x122000 0x1000>; interrupts = <18 0>; clocks = <&clkctl1 MCUX_FLEXCOMM4_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 12)>; status = "disabled"; }; @@ -254,6 +274,7 @@ reg = <0x123000 0x1000>; interrupts = <19 0>; clocks = <&clkctl1 MCUX_FLEXCOMM5_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 13)>; status = "disabled"; }; @@ -262,6 +283,7 @@ reg = <0x124000 0x1000>; interrupts = <43 0>; clocks = <&clkctl1 MCUX_FLEXCOMM6_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 14)>; status = "disabled"; }; @@ -270,6 +292,7 @@ reg = <0x125000 0x1000>; interrupts = <44 0>; clocks = <&clkctl1 MCUX_FLEXCOMM7_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 15)>; status = "disabled"; }; @@ -278,6 +301,7 @@ reg = <0x127000 0x1000>; interrupts = <21 0>; clocks = <&clkctl1 MCUX_PMIC_I2C_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 23)>; status = "disabled"; }; @@ -286,6 +310,7 @@ reg = <0x209000 0x1000>; interrupts = <60 0>; clocks = <&clkctl1 MCUX_FLEXCOMM8_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 16)>; status = "disabled"; }; @@ -294,6 +319,7 @@ reg = <0x20a000 0x1000>; interrupts = <61 0>; clocks = <&clkctl1 MCUX_FLEXCOMM9_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 17)>; status = "disabled"; }; @@ -302,6 +328,7 @@ reg = <0x20b000 0x1000>; interrupts = <62 0>; clocks = <&clkctl1 MCUX_FLEXCOMM10_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 18)>; status = "disabled"; }; @@ -310,6 +337,7 @@ reg = <0x20c000 0x1000>; interrupts = <63 0>; clocks = <&clkctl1 MCUX_FLEXCOMM11_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 19)>; status = "disabled"; }; @@ -318,6 +346,7 @@ reg = <0x20d000 0x1000>; interrupts = <64 0>; clocks = <&clkctl1 MCUX_FLEXCOMM12_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 20)>; status = "disabled"; }; @@ -326,6 +355,7 @@ reg = <0x20e000 0x1000>; interrupts = <65 0>; clocks = <&clkctl1 MCUX_FLEXCOMM13_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 21)>; status = "disabled"; }; @@ -349,6 +379,7 @@ reg = <0x126000 0x1000>; interrupts = <20 0>; clocks = <&clkctl1 MCUX_HS_SPI_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 22)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -359,6 +390,7 @@ reg = <0x128000 0x1000>; interrupts = <66 0>; clocks = <&clkctl1 MCUX_HS_SPI1_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 24)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -656,6 +688,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&clkctl1 MCUX_MRT_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(2, 8)>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_rt6xx_common.dtsi b/dts/arm/nxp/nxp_rt6xx_common.dtsi index 800d61bd13855..9cd910e16ded3 100644 --- a/dts/arm/nxp/nxp_rt6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rt6xx_common.dtsi @@ -11,6 +11,7 @@ #include #include #include +#include / { chosen { @@ -99,6 +100,7 @@ */ clkctl0: clkctl@1000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x1000 0x1000>; #clock-cells = <1>; @@ -113,64 +115,78 @@ }; clkctl1: clkctl@21000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x21000 0x1000>; #clock-cells = <1>; }; + rstctl0: reset@0 { + compatible = "nxp,rstctl"; + reg = <0x0 0x80>; + #reset-cells = <1>; + }; + + rstctl1: reset@20000 { + compatible = "nxp,rstctl"; + reg = <0x20000 0x80>; + #reset-cells = <1>; + }; + uuid: uuid@2f50 { compatible = "nxp,lpc-uid"; reg = <0x2f50 0x10>; }; - gpio0: gpio@0 { + gpio: gpio@100000 { compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - }; + reg = <0x100000 0x2784>; + #address-cells = <1>; + #size-cells = <0>; - gpio1: gpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - int-source = "pint"; - gpio-controller; - #gpio-cells = <2>; - port = <1>; - }; + gpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + }; - gpio2: gpio@2 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <2>; - }; + gpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + int-source = "pint"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + }; - gpio3: gpio@3 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <3>; - }; + gpio2: gpio@2 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <2>; + }; - gpio4: gpio@4 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <4>; - }; + gpio3: gpio@3 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <3>; + }; - gpio7: gpio@7 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x1000>; - gpio-controller; - #gpio-cells = <2>; - port = <7>; + gpio4: gpio@4 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <4>; + }; + + gpio7: gpio@7 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <7>; + }; }; pint: pint@25000 { @@ -190,6 +206,7 @@ reg = <0x106000 0x1000>; interrupts = <14 0>; clocks = <&clkctl1 MCUX_FLEXCOMM0_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 8)>; status = "disabled"; }; @@ -198,6 +215,7 @@ reg = <0x107000 0x1000>; interrupts = <15 0>; clocks = <&clkctl1 MCUX_FLEXCOMM1_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 9)>; status = "disabled"; }; @@ -206,6 +224,7 @@ reg = <0x108000 0x1000>; interrupts = <16 0>; clocks = <&clkctl1 MCUX_FLEXCOMM2_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 10)>; status = "disabled"; }; @@ -214,6 +233,7 @@ reg = <0x109000 0x1000>; interrupts = <17 0>; clocks = <&clkctl1 MCUX_FLEXCOMM3_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 11)>; status = "disabled"; }; @@ -222,6 +242,7 @@ reg = <0x122000 0x1000>; interrupts = <18 0>; clocks = <&clkctl1 MCUX_FLEXCOMM4_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 12)>; status = "disabled"; }; @@ -230,6 +251,7 @@ reg = <0x123000 0x1000>; interrupts = <19 0>; clocks = <&clkctl1 MCUX_FLEXCOMM5_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 13)>; status = "disabled"; }; @@ -238,6 +260,7 @@ reg = <0x124000 0x1000>; interrupts = <43 0>; clocks = <&clkctl1 MCUX_FLEXCOMM6_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 14)>; status = "disabled"; }; @@ -246,6 +269,7 @@ reg = <0x125000 0x1000>; interrupts = <44 0>; clocks = <&clkctl1 MCUX_FLEXCOMM7_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 15)>; status = "disabled"; }; @@ -254,6 +278,7 @@ reg = <0x127000 0x1000>; interrupts = <21 0>; clocks = <&clkctl1 MCUX_PMIC_I2C_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 23)>; status = "disabled"; }; @@ -265,6 +290,12 @@ status = "disabled"; }; + usbphy: usbphy@13b000 { + compatible = "nxp,usbphy"; + reg = <0x13b000 0x1000>; + status = "disabled"; + }; + hs_lspi: spi@126000 { compatible = "nxp,lpc-spi"; /* Enabling cs-gpios below will allow using GPIO CS, @@ -276,6 +307,7 @@ reg = <0x126000 0x1000>; interrupts = <20 0>; clocks = <&clkctl1 MCUX_HS_SPI_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 22)>; status = "disabled"; #address-cells = <1>; #size-cells = <0>; @@ -470,6 +502,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&clkctl1 MCUX_MRT_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(2, 8)>; #address-cells = <1>; #size-cells = <0>; diff --git a/dts/arm/nxp/nxp_rw6xx_common.dtsi b/dts/arm/nxp/nxp_rw6xx_common.dtsi index d78879e107a4d..86bb92eb6b048 100644 --- a/dts/arm/nxp/nxp_rw6xx_common.dtsi +++ b/dts/arm/nxp/nxp_rw6xx_common.dtsi @@ -9,15 +9,20 @@ #include #include #include +#include +#include +#include / { chosen { zephyr,entropy = &trng; + zephyr,bt-hci = &hci; }; cpus { #address-cells = <1>; #size-cells = <0>; + cpu-power-states = <&idle &suspend>; cpu0: cpu@0 { compatible = "arm,cortex-m33f"; @@ -30,7 +35,38 @@ reg = <0xe000ed90 0x40>; }; }; + + power-states { + /* Idle mode maps to Power Mode 1 */ + idle: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <0>; + exit-latency-us = <0>; + }; + /* Suspend mode maps to Power Mode 2 */ + suspend: suspend { + compatible = "nxp,pdcfg-power", "zephyr,power-state"; + power-state-name = "suspend-to-idle"; + min-residency-us = <500>; + exit-latency-us = <120>; + deep-sleep-config = <0x180000>, + <0x0>, + <0x4>, + <0x100>, + <0x0>; + }; + }; + }; + + smu1: sram@41380000 { + ranges = <0x0 0x41380000 DT_SIZE_K(510)>; + }; + + smu2: sram@443C0000 { + ranges = <0x0 0x443C0000 DT_SIZE_K(140)>; }; + }; &sram { @@ -48,11 +84,36 @@ }; }; +&smu1 { + #address-cells = <1>; + #size-cells = <1>; + + smu1_data: memory@0 { + compatible = "zephyr,memory-region","mmio-sram"; + reg = <0x0 DT_SIZE_K(510)>; + zephyr,memory-region = "SMU1"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; + }; +}; + +&smu2 { + #address-cells = <1>; + #size-cells = <1>; + + smu2_data: memory@0 { + compatible = "zephyr,memory-region","mmio-sram"; + reg = <0x0 DT_SIZE_K(140)>; + zephyr,memory-region = "SMU2"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM) )>; + }; +}; + &peripheral { #address-cells = <1>; #size-cells = <1>; clkctl0: clkctl@1000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x1000 0x1000>; #clock-cells = <1>; @@ -65,11 +126,24 @@ }; clkctl1: clkctl@21000 { + /* FIXME This chip does NOT have a syscon */ compatible = "nxp,lpc-syscon"; reg = <0x21000 0x1000>; #clock-cells = <1>; }; + rstctl0: reset@0 { + compatible = "nxp,rstctl"; + reg = <0x0 0x80>; + #reset-cells = <1>; + }; + + rstctl1: reset@20000 { + compatible = "nxp,rstctl"; + reg = <0x20000 0x80>; + #reset-cells = <1>; + }; + pmu: pmu@31000 { reg = <0x31000 0x130>; compatible = "nxp,rw-pmu"; @@ -90,22 +164,27 @@ clk-divider = <1>; }; - hsgpio0: hsgpio@0 { + hsgpio: hsgpio@100000 { compatible = "nxp,lpc-gpio"; reg = <0x100000 0x4000>; - gpio-controller; - #gpio-cells = <2>; - port = <0>; - int-source = "pint"; - }; + #address-cells = <1>; + #size-cells = <0>; - hsgpio1: hsgpio@1 { - compatible = "nxp,lpc-gpio"; - reg = <0x100000 0x4000>; - gpio-controller; - #gpio-cells = <2>; - port = <1>; - int-source = "pint"; + hsgpio0: gpio@0 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <0>; + int-source = "pint"; + }; + + hsgpio1: gpio@1 { + compatible = "nxp,lpc-gpio-port"; + gpio-controller; + #gpio-cells = <2>; + reg = <1>; + int-source = "pint"; + }; }; usb_otg: usbotg@145000 { @@ -122,6 +201,7 @@ reg = <0x106000 0x1000>; interrupts = <14 0>; clocks = <&clkctl1 MCUX_FLEXCOMM0_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 8)>; dmas = <&dma0 0>, <&dma0 1>; dma-names = "rx", "tx"; status = "disabled"; @@ -132,6 +212,7 @@ reg = <0x107000 0x1000>; interrupts = <15 0>; clocks = <&clkctl1 MCUX_FLEXCOMM1_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 9)>; dmas = <&dma0 2>, <&dma0 3>; dma-names = "rx", "tx"; status = "disabled"; @@ -142,6 +223,7 @@ reg = <0x108000 0x1000>; interrupts = <16 0>; clocks = <&clkctl1 MCUX_FLEXCOMM2_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 10)>; dmas = <&dma0 4>, <&dma0 5>; dma-names = "rx", "tx"; status = "disabled"; @@ -152,6 +234,7 @@ reg = <0x109000 0x1000>; interrupts = <17 0>; clocks = <&clkctl1 MCUX_FLEXCOMM3_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 11)>; dmas = <&dma0 6>, <&dma0 7>; dma-names = "rx", "tx"; status = "disabled"; @@ -162,6 +245,7 @@ reg = <0x126000 0x2000>; interrupts = <20 0>; clocks = <&clkctl1 MCUX_FLEXCOMM14_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(0, 22)>; dmas = <&dma0 26>, <&dma0 27>; dma-names = "rx", "tx"; status = "disabled"; @@ -266,6 +350,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&clkctl1 MCUX_MRT_CLK>; + resets = <&rstctl1 NXP_SYSCON_RESET(2, 8)>; #address-cells = <1>; #size-cells = <0>; @@ -298,6 +383,7 @@ num-channels = <4>; num-bits = <24>; clocks = <&clkctl1 MCUX_FREEMRT_CLK>; + resets = <&rstctl0 NXP_SYSCON_RESET(2, 26)>; #address-cells = <1>; #size-cells = <0>; @@ -361,6 +447,75 @@ }; }; + gau { + ranges = <>; + #address-cells = <1>; + #size-cells = <1>; + + adc0: gau_adc0@38000 { + compatible = "nxp,gau-adc"; + reg = <0x38000 0x100>; + interrupts = <112 0>; + status = "disabled"; + #io-channel-cells = <1>; + }; + + adc1: gau_adc1@38100 { + compatible = "nxp,gau-adc"; + reg = <0x38100 0x100>; + interrupts = <111 0>; + status = "disabled"; + #io-channel-cells = <1>; + }; + + dac0: dac@38200 { + compatible = "nxp,gau-dac"; + reg = <0x38200 0x30>; + interrupts = <108 0>; + status = "disabled"; + #io-channel-cells = <0>; + }; + }; + + os_timer: timers@13b000 { + compatible = "nxp,os-timer"; + reg = <0x13b000 0x1000>; + interrupts = <41 0>; + status = "disabled"; + }; + + hci: hci_ble { + compatible = "nxp,hci-ble"; + /* first index is the hci interrupt, the second is the wake up done interrupt */ + interrupts = <90 2>, <82 2>; + interrupt-names = "hci_int", "wakeup_int"; + }; + + enet: enet@138000 { + compatible = "nxp,enet"; + reg = <0x138000 0x700>; + clocks = <&clkctl1 MCUX_ENET_CLK>; + enet_mac: ethernet { + compatible = "nxp,enet-mac"; + interrupts = <115 0>; + interrupt-names = "COMMON"; + nxp,mdio = <&enet_mdio>; + nxp,ptp-clock = <&enet_ptp_clock>; + status = "disabled"; + }; + enet_mdio: mdio { + compatible = "nxp,enet-mdio"; + status = "disabled"; + #address-cells = <1>; + #size-cells = <0>; + }; + enet_ptp_clock: ptp-clock { + compatible = "nxp,enet-ptp-clock"; + interrupts = <116 0>; + status = "disabled"; + clocks = <&clkctl1 MCUX_ENET_PLL>; + }; + }; }; &flexspi { diff --git a/dts/arm/nxp/nxp_s32k344_m7.dtsi b/dts/arm/nxp/nxp_s32k344_m7.dtsi index 0289b24f42ea6..fa6b2b1e43de0 100644 --- a/dts/arm/nxp/nxp_s32k344_m7.dtsi +++ b/dts/arm/nxp/nxp_s32k344_m7.dtsi @@ -828,6 +828,20 @@ }; }; + flexio0: flexio@40324000 { + compatible = "nxp,flexio"; + reg = <0x40324000 0x4000>; + interrupts = <139 0>; + clocks = <&clock NXP_S32_FLEXIO0_CLK>; + status = "disabled"; + + flexio0_pwm { + compatible = "nxp,flexio-pwm"; + #pwm-cells = <3>; + status = "disabled"; + }; + }; + lcu0: lcu@40098000 { compatible = "nxp,s32-lcu"; reg = <0x40098000 0x4000>; diff --git a/dts/arm/renesas/smartbond/da1469x.dtsi b/dts/arm/renesas/smartbond/da1469x.dtsi index eed1abc33ee79..05f250935f32f 100644 --- a/dts/arm/renesas/smartbond/da1469x.dtsi +++ b/dts/arm/renesas/smartbond/da1469x.dtsi @@ -46,7 +46,6 @@ rc32k: rc32k { compatible = "renesas,smartbond-lp-osc"; clock-frequency = ; - calibration-interval = <1>; #clock-cells = <0>; status = "okay"; }; @@ -60,9 +59,8 @@ rcx: rcx { compatible = "renesas,smartbond-lp-osc"; clock-frequency = ; - calibration-interval = <1>; #clock-cells = <0>; - status = "disabled"; + status = "okay"; }; rc32m: rc32m { compatible = "fixed-clock"; @@ -97,7 +95,7 @@ }; lp_clk: lp_clk { compatible = "renesas,smartbond-lp-clk"; - clock-src = <&rc32k>; + clock-src = <&rcx>; status = "okay"; }; @@ -153,6 +151,14 @@ compatible = "mmio-sram"; }; + psram: memory@32000000 { + compatible = "zephyr,memory-region"; + device_type = "memory"; + reg = <0x32000000 DT_SIZE_K(32768)>; + zephyr,memory-region = "PSRAM"; + status = "disabled"; + }; + qspif: memory@16000000 { compatible = "zephyr,memory-region"; reg = <0x16000000 DT_SIZE_K(32768)>; @@ -272,6 +278,7 @@ reg = <0x50020100 0x100>; periph-clock-config = <0x02>; interrupts = <6 0>; + hw-flow-control-supported; status = "disabled"; }; @@ -280,6 +287,7 @@ reg = <0x50020200 0x100>; periph-clock-config = <0x08>; interrupts = <7 0>; + hw-flow-control-supported; status = "disabled"; }; @@ -378,7 +386,18 @@ status = "disabled"; dma-channels = <8>; block-count = <1>; - #dma-cells = <0>; + #dma-cells = <2>; + }; + + memc: qspic2@34000000 { + compatible = "renesas,smartbond-nor-psram"; + reg = <0x34000000 0x48>; + status = "disabled"; + }; + + bt_hci_da1469x: bt_hci_da1469x { + compatible = "renesas,bt-hci-da1469x"; + status = "disabled"; }; }; }; diff --git a/dts/arm/silabs/efr32bg2x.dtsi b/dts/arm/silabs/efr32bg2x.dtsi index 70df9708d116a..9cd0618cd41c9 100644 --- a/dts/arm/silabs/efr32bg2x.dtsi +++ b/dts/arm/silabs/efr32bg2x.dtsi @@ -224,6 +224,11 @@ #io-channel-cells = <1>; }; }; + + bt_hci_silabs: bt_hci_silabs { + compatible = "silabs,bt-hci"; + status = "disabled"; + }; }; / { diff --git a/dts/arm/silabs/efr32mg.dtsi b/dts/arm/silabs/efr32mg.dtsi index cfbbde48af9b1..a7926f6710f6b 100644 --- a/dts/arm/silabs/efr32mg.dtsi +++ b/dts/arm/silabs/efr32mg.dtsi @@ -234,6 +234,11 @@ }; }; + bt_hci_silabs: bt_hci_silabs { + compatible = "silabs,bt-hci"; + status = "disabled"; + }; + pinctrl: pin-controller { /* Pin controller is a "virtual" device since SiLabs SoCs do pin * control in a distributed way (GPIO registers and PSEL diff --git a/dts/arm/silabs/efr32mg24.dtsi b/dts/arm/silabs/efr32mg24.dtsi index 860cedddeda5f..b92100c85a567 100644 --- a/dts/arm/silabs/efr32mg24.dtsi +++ b/dts/arm/silabs/efr32mg24.dtsi @@ -213,6 +213,12 @@ #io-channel-cells = <1>; }; }; + + + bt_hci_silabs: bt_hci_silabs { + compatible = "silabs,bt-hci"; + status = "disabled"; + }; }; / { diff --git a/dts/arm/silabs/efr32xg13p.dtsi b/dts/arm/silabs/efr32xg13p.dtsi index 96d9c6493d18d..3444eb6e391f4 100644 --- a/dts/arm/silabs/efr32xg13p.dtsi +++ b/dts/arm/silabs/efr32xg13p.dtsi @@ -181,6 +181,11 @@ }; }; + bt_hci_silabs: bt_hci_silabs { + compatible = "silabs,bt-hci"; + status = "disabled"; + }; + pinctrl: pin-controller { /* Pin controller is a "virtual" device since SiLabs SoCs do pin * control in a distributed way (GPIO registers and PSEL diff --git a/dts/arm/st/c0/stm32c0.dtsi b/dts/arm/st/c0/stm32c0.dtsi index fd37b14b5f93b..f7e58c7b69919 100644 --- a/dts/arm/st/c0/stm32c0.dtsi +++ b/dts/arm/st/c0/stm32c0.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2023 Benjamin Björnsson + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -154,6 +155,8 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <1>; + alrm-exti-line = <19>; status = "disabled"; }; diff --git a/dts/arm/st/f0/stm32f0.dtsi b/dts/arm/st/f0/stm32f0.dtsi index 0371ac75ac6e1..5f25181e6578a 100644 --- a/dts/arm/st/f0/stm32f0.dtsi +++ b/dts/arm/st/f0/stm32f0.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2017 RnDity Sp. z o.o. * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -210,6 +211,8 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; interrupts = <2 0>; prescaler = <32768>; + alarms-count = <1>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/f2/stm32f2.dtsi b/dts/arm/st/f2/stm32f2.dtsi index 9c91375691984..8af21aaa46804 100644 --- a/dts/arm/st/f2/stm32f2.dtsi +++ b/dts/arm/st/f2/stm32f2.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 qianfan Zhao * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -202,6 +203,8 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; interrupts = <41 0>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/f3/stm32f3.dtsi b/dts/arm/st/f3/stm32f3.dtsi index 725ed0eacb622..07ed6f9dc2606 100644 --- a/dts/arm/st/f3/stm32f3.dtsi +++ b/dts/arm/st/f3/stm32f3.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2017 I-SENSE group of ICCS * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -410,6 +411,8 @@ clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; interrupts = <41 0>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/f4/stm32f4.dtsi b/dts/arm/st/f4/stm32f4.dtsi index 231c8b988f886..b69d32d6cf301 100644 --- a/dts/arm/st/f4/stm32f4.dtsi +++ b/dts/arm/st/f4/stm32f4.dtsi @@ -2,6 +2,7 @@ * Copyright (c) 2017 Linaro Limited * Copyright (c) 2019 Centaur Analytics, Inc * Copyright (c) 2022 Valerio Setti + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -515,6 +516,8 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/f7/stm32f7.dtsi b/dts/arm/st/f7/stm32f7.dtsi index 600f959b4fd85..439bc560a7d5e 100644 --- a/dts/arm/st/f7/stm32f7.dtsi +++ b/dts/arm/st/f7/stm32f7.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2018 Yurii Hamann * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,10 +45,10 @@ }; }; - quadspi_memory: memory@90000000 { + quadspi_memory: memory-placeholder@90000000 { compatible = "zephyr,memory-region", "mmio-sram"; reg = <0x90000000 DT_SIZE_M(256)>; - zephyr,memory-region = "QSPI"; + zephyr,memory-region = "QSPI_PLACEHOLDER"; zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_EXTMEM) )>; }; @@ -713,7 +714,8 @@ num-bidir-endpoints = <9>; ram-size = <4096>; maximum-speed = "full-speed"; - clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x20000000>; + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x20000000>, + <&rcc STM32_SRC_PLL_Q CK48M_SEL(0)>; phys = <&otghs_fs_phy>; status = "disabled"; }; @@ -724,6 +726,8 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/g0/stm32g0.dtsi b/dts/arm/st/g0/stm32g0.dtsi index bfa023d027d3e..ca4e3d47d8a91 100644 --- a/dts/arm/st/g0/stm32g0.dtsi +++ b/dts/arm/st/g0/stm32g0.dtsi @@ -1,6 +1,6 @@ /* * Copyright (c) 2019 Philippe Retornaz - * Copyright (c) 2019 ST Microelectronics + * Copyright (c) 2019-2024 STMicroelectronics * Copyright (c) 2019 Centaur Analytics, Inc * Copyright (C) 2020 Framework Computer LLC * Copyright (c) 2021 G-Technologies Sdn. Bhd. @@ -189,7 +189,21 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <19>; status = "disabled"; + + /* In STM32G0, the backup registers are defined as part of the TAMP + * peripheral. This peripheral is not implemented in Zephyr yet, however, + * the reference manual states that tamp_pclk is connected to rtc_pclk. + * It makes sense to have BBRAM instantiated as a child of RTC, so that + * the driver can verify that its parent device (RTC) is ready. + */ + bbram: backup_regs { + compatible = "st,stm32-bbram"; + st,backup-regs = <5>; + status = "disabled"; + }; }; iwdg: watchdog@40003000 { diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index 1450efbee3835..8cba3a5802153 100644 --- a/dts/arm/st/g4/stm32g4.dtsi +++ b/dts/arm/st/g4/stm32g4.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2021 The Chromium OS Authors * Copyright (c) 2019 Richard Osterloh + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -598,6 +599,8 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/h5/stm32h5.dtsi b/dts/arm/st/h5/stm32h5.dtsi index cd19d329e60f4..9b2e14209af10 100644 --- a/dts/arm/st/h5/stm32h5.dtsi +++ b/dts/arm/st/h5/stm32h5.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -308,6 +308,8 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; @@ -528,6 +530,54 @@ status = "disabled"; }; + i2s1: i2s@40013000 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40013000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>, + <&rcc STM32_SRC_PLL1_Q SPI1_SEL(0)>; + dmas = <&gpdma1 0 7 (STM32_DMA_PERIPH_TX |STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH) + &gpdma1 1 6 (STM32_DMA_PERIPH_RX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH)>; + dma-names = "tx", "rx"; + interrupts = <55 3>; + status = "disabled"; + }; + + i2s2: i2s@40003800 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>, + <&rcc STM32_SRC_PLL1_Q SPI2_SEL(0)>; + dmas = <&gpdma1 2 9 (STM32_DMA_PERIPH_TX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH) + &gpdma1 3 8 (STM32_DMA_PERIPH_RX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH)>; + dma-names = "tx", "rx"; + interrupts = <56 3>; + status = "disabled"; + }; + + i2s3: i2s@40003c00 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00008000>, + <&rcc STM32_SRC_PLL1_Q SPI3_SEL(0)>; + dmas = <&gpdma1 4 11 (STM32_DMA_PERIPH_TX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH) + &gpdma1 5 10 (STM32_DMA_PERIPH_RX | STM32_DMA_16BITS | \ + STM32_DMA_PRIORITY_HIGH)>; + dma-names = "tx", "rx"; + interrupts = <57 3>; + status = "disabled"; + }; + usb: usb@40016000 { compatible = "st,stm32-usb"; reg = <0x40016000 0x400>; diff --git a/dts/arm/st/h5/stm32h533.dtsi b/dts/arm/st/h5/stm32h533.dtsi new file mode 100644 index 0000000000000..bd781b87cd9cd --- /dev/null +++ b/dts/arm/st/h5/stm32h533.dtsi @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include + +/ { + soc { + compatible = "st,stm32h533", "st,stm32h5", "simple-bus"; + + gpiof: gpio@42021400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x42021400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000080>; + }; + }; +}; diff --git a/dts/arm/st/h5/stm32h533Xe.dtsi b/dts/arm/st/h5/stm32h533Xe.dtsi new file mode 100644 index 0000000000000..7b3b530f6a7ef --- /dev/null +++ b/dts/arm/st/h5/stm32h533Xe.dtsi @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include + +/ { + sram1: memory@20000000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(128)>; + zephyr,memory-region = "SRAM1"; + }; + + sram2: memory@20040000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20040000 DT_SIZE_K(80)>; + zephyr,memory-region = "SRAM2"; + }; + + sram3: memory@20050000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x20050000 DT_SIZE_K(64)>; + zephyr,memory-region = "SRAM3"; + }; + + soc { + flash-controller@40022000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(512)>; + }; + }; + }; +}; diff --git a/dts/arm/st/h5/stm32h562.dtsi b/dts/arm/st/h5/stm32h562.dtsi index a4acfcb8ee9c0..bab82009a1f59 100644 --- a/dts/arm/st/h5/stm32h562.dtsi +++ b/dts/arm/st/h5/stm32h562.dtsi @@ -6,6 +6,8 @@ #include #include +/* keep both header files for compatibility */ +#include / { clocks { @@ -54,6 +56,14 @@ }; }; + backup_sram: memory@40036400 { + compatible = "zephyr,memory-region", "st,stm32-backup-sram"; + reg = <0x40036400 DT_SIZE_K(4)>; + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x10000000>; + zephyr,memory-region = "BACKUP_SRAM"; + status = "disabled"; + }; + lptim3: timers@44004800 { compatible = "st,stm32-lptim"; clocks = <&rcc STM32_CLOCK_BUS_APB3 0x1000>; @@ -65,12 +75,12 @@ status = "disabled"; }; - lptim4: timers@44004C00 { + lptim4: timers@44004c00 { compatible = "st,stm32-lptim"; clocks = <&rcc STM32_CLOCK_BUS_APB3 0x2000>; #address-cells = <1>; #size-cells = <0>; - reg = <0x44004C00 0x400>; + reg = <0x44004c00 0x400>; interrupts = <128 1>; interrupt-names = "wakeup"; status = "disabled"; @@ -143,6 +153,15 @@ status = "disabled"; }; + usart6: serial@40006400 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40006400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x02000000>; + resets = <&rctl STM32_RESET(APB1L, 25U)>; + interrupts = <85 0>; + status = "disabled"; + }; + usart10: serial@40006800 { compatible = "st,stm32-usart", "st,stm32-uart"; reg = <0x40006800 0x400>; @@ -224,11 +243,11 @@ status = "disabled"; }; - octospi1: octospi@47001400 { - compatible = "st,stm32-ospi"; + xspi1: xspi@47001400 { + compatible = "st,stm32-xspi"; reg = <0x47001400 0x400>; interrupts = <78 0>; - clock-names = "ospix", "ospi-ker"; + clock-names = "xspix", "xspi-ker"; clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00100000>, <&rcc STM32_SRC_PLL1_Q OCTOSPI1_SEL(1)>; #address-cells = <1>; @@ -357,6 +376,69 @@ }; }; + timers15: timers@40014000 { + compatible = "st,stm32-timers"; + reg = <0x40014000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00010000>; + resets = <&rctl STM32_RESET(APB2, 16U)>; + interrupts = <71 0>; + interrupt-names = "global"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers16: timers@40014400 { + compatible = "st,stm32-timers"; + reg = <0x40014400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00020000>; + resets = <&rctl STM32_RESET(APB2, 17U)>; + interrupts = <72 0>; + interrupt-names = "global"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers17: timers@40014800 { + compatible = "st,stm32-timers"; + reg = <0x40014800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00040000>; + resets = <&rctl STM32_RESET(APB2, 18U)>; + interrupts = <73 0>; + interrupt-names = "global"; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + aes: aes@420c0000 { compatible = "st,stm32-aes"; reg = <0x420c0000 0x400>; diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index f3a24e2718fc8..c9b8d5e4f968d 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -2,6 +2,7 @@ * Copyright (c) 2019 Linaro Limited * Copyright (c) 2019 Centaur Analytics, Inc * Copyright (c) 2020 Teslabs Engineering S.L. + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -352,6 +353,8 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00010000>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/h7/stm32h723.dtsi b/dts/arm/st/h7/stm32h723.dtsi index 662ecef5da94d..05e596974982c 100644 --- a/dts/arm/st/h7/stm32h723.dtsi +++ b/dts/arm/st/h7/stm32h723.dtsi @@ -177,6 +177,15 @@ status = "disabled"; }; }; + + digi_die_temp: digi_dietemp@58006800 { + compatible = "st,stm32-digi-temp"; + reg = <0x58006800 0x400>; + interrupts = <147 0>; + interrupt-names = "digi_temp"; + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x04000000>; + status = "disabled"; + }; }; /* D1 domain, AXI SRAM (128KB with shared ITCM 192KB as `TCM_AXI_SHARED` is `000`) */ diff --git a/dts/arm/st/h7/stm32h7_dualcore.dtsi b/dts/arm/st/h7/stm32h7_dualcore.dtsi index 591d68b791630..1ba052502ac15 100644 --- a/dts/arm/st/h7/stm32h7_dualcore.dtsi +++ b/dts/arm/st/h7/stm32h7_dualcore.dtsi @@ -17,9 +17,10 @@ soc { mailbox: mailbox@58026400 { - compatible = "st,stm32-hsem-mailbox"; + compatible = "st,stm32-hsem-mailbox", "st,mbox-stm32-hsem"; reg = <0x58026400 0x400>; clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x02000000>; + #mbox-cells = <1>; status = "disabled"; }; }; diff --git a/dts/arm/st/h7/stm32h7a3.dtsi b/dts/arm/st/h7/stm32h7a3.dtsi index 68f7d82969f54..a9a570e07abaf 100644 --- a/dts/arm/st/h7/stm32h7a3.dtsi +++ b/dts/arm/st/h7/stm32h7a3.dtsi @@ -97,6 +97,15 @@ health-test-magic = <0x17590abc>; health-test-config = <0x72ac>; }; + + digi_die_temp: digi_dietemp@58006800 { + compatible = "st,stm32-digi-temp"; + reg = <0x58006800 0x400>; + interrupts = <147 0>; + interrupt-names = "digi_temp"; + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x04000000>; + status = "disabled"; + }; }; /* System data RAM accessible over AXI bus: AXI SRAM1 in CD domain */ diff --git a/dts/arm/st/h7rs/stm32h7r3.dtsi b/dts/arm/st/h7rs/stm32h7r3.dtsi new file mode 100644 index 0000000000000..57a2c057b92d8 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7r3.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + soc { + + compatible = "st,stm32h7r3", "st,stm32h7rs", "simple-bus"; + + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7r3X8.dtsi b/dts/arm/st/h7rs/stm32h7r3X8.dtsi new file mode 100644 index 0000000000000..5bdb944644816 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7r3X8.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +/ { + soc { + flash-controller@52002000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7r7.dtsi b/dts/arm/st/h7rs/stm32h7r7.dtsi new file mode 100644 index 0000000000000..bdc347798c8ca --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7r7.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * STM32H7R7 line contains the same peripherals as STM32H7R3. + */ +/ { + soc { + compatible = "st,stm32h7r7", "st,stm32h7rs", "simple-bus"; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7r7X8.dtsi b/dts/arm/st/h7rs/stm32h7r7X8.dtsi new file mode 100644 index 0000000000000..3755e88f26bbf --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7r7X8.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +/ { + soc { + flash-controller@52002000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7rs.dtsi b/dts/arm/st/h7rs/stm32h7rs.dtsi new file mode 100644 index 0000000000000..35432a9b91510 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7rs.dtsi @@ -0,0 +1,796 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * STM32H7RS line contains has many common peripherals with STM32H7. + */ + +/ { + chosen { + zephyr,entropy = &rng; + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-m7"; + reg = <0>; + #address-cells = <1>; + #size-cells = <1>; + + mpu: mpu@e000ed90 { + compatible = "arm,armv7m-mpu"; + reg = <0xe000ed90 0x40>; + }; + }; + }; + + /* System data RAM accessible over AXI bus: AXI SRAM1 in CD domain */ + sram0: memory@24000000 { + compatible = "mmio-sram"; + reg = <0x24000000 DT_SIZE_K(128)>; + }; + + /* System data RAM accessible over AHB bus: SRAM1 in D2 domain */ + sram1: memory@30000000 { + reg = <0x30000000 DT_SIZE_K(16)>; + compatible = "zephyr,memory-region", "mmio-sram"; + zephyr,memory-region = "SRAM1"; + }; + + /* System data RAM accessible over AHB bus: SRAM2 in D2 domain */ + sram2: memory@30004000 { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x30004000 DT_SIZE_K(16)>; + zephyr,memory-region = "SRAM2"; + }; + + dtcm: memory@20000000 { + compatible = "zephyr,memory-region", "arm,dtcm"; + reg = <0x20000000 DT_SIZE_K(128)>; + zephyr,memory-region = "DTCM"; + }; + + itcm: memory@0 { + compatible = "zephyr,memory-region", "arm,itcm"; + reg = <0x00000000 DT_SIZE_K(64)>; + zephyr,memory-region = "ITCM"; + }; + + ext_memory: memory@70000000 { + compatible = "zephyr,memory-region"; + reg = <0x70000000 DT_SIZE_M(256)>; + zephyr,memory-region = "EXTMEM"; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_EXTMEM) )>; + }; + + clocks { + #address-cells = <1>; + #size-cells = <0>; + + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "st,stm32-hse-clock"; + status = "disabled"; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "st,stm32h7-hsi-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_hsi48: clk-hsi48 { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_csi: clk-csi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "st,stm32-lse-clock"; + clock-frequency = <32768>; + driving-capability = <0>; + status = "disabled"; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = ; + status = "disabled"; + }; + + pll: pll@0 { + #clock-cells = <0>; + compatible = "st,stm32h7rs-pll-clock"; + reg = <0>; + status = "disabled"; + }; + + pll2: pll@1 { + #clock-cells = <0>; + compatible = "st,stm32h7rs-pll-clock"; + reg = <1>; + status = "disabled"; + }; + + pll3: pll@2 { + #clock-cells = <0>; + compatible = "st,stm32h7rs-pll-clock"; + reg = <2>; + status = "disabled"; + }; + + perck: perck { + #clock-cells = <0>; + compatible = "st,stm32-clock-mux"; + status = "disabled"; + }; + }; + + soc { + flash: flash-controller@52002000 { + compatible = "st,stm32-flash-controller", "st,stm32h7-flash-controller"; + reg = <0x52002000 0x400>; + interrupts = <8 0>; + clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00000100>; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@8000000 { + compatible = "st,stm32-nv-flash", "soc-nv-flash"; + write-block-size = <32>; + erase-block-size = ; + /* maximum erase time for a 8K sector */ + max-erase-time = <3>; + }; + }; + + rcc: rcc@58024400 { + compatible = "st,stm32h7rs-rcc"; + #clock-cells = <2>; + reg = <0x58024400 0x400>; + + rctl: reset-controller { + compatible = "st,stm32-rcc-rctl"; + #reset-cells = <1>; + }; + }; + + exti: interrupt-controller@58000000 { + compatible = "st,stm32h7rs-exti", "st,stm32-exti"; + interrupt-controller; + #interrupt-cells = <1>; + #address-cells = <1>; + reg = <0x58000000 0x400>; + /* SBS for interrupt */ + num-lines = <16>; + interrupts = <16 0>, <17 0>, <18 0>, <19 0>, + <20 0>, <21 0>, <22 0>, <23 0>, + <24 0>, <25 0>, <26 0>, <27 0>, + <28 0>, <29 0>, <30 0>, <31 0>; + interrupt-names = "line0", "line1", "line2", "line3", + "line4", "line5", "line6", "line7", + "line8", "line9", "line10", "line11", + "line12", "line13", "line14", "line15"; + line-ranges = <0 1>, <1 1>, <2 1>, <3 1>, + <4 1>, <5 1>, <6 1>, <7 1>, + <8 1>, <9 1>, <10 1>, <11 1>, + <12 1>, <13 1>, <14 1>, <15 1>; + }; + + pinctrl: pin-controller@58020000 { + compatible = "st,stm32-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x58020000 0x2400>; + + gpioa: gpio@58020000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58020000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000001>; + }; + + gpiob: gpio@58020400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58020400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000002>; + }; + + gpioc: gpio@58020800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58020800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000004>; + }; + + gpiod: gpio@58020C00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58020C00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000008>; + }; + + gpioe: gpio@58021000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58021000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000010>; + }; + + gpiof: gpio@58021400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58021400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000020>; + }; + + gpiog: gpio@58021800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58021800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000040>; + }; + + gpioh: gpio@58021c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58021c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00000080>; + }; + + gpiom: gpio@58023000 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58023000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00001000>; + }; + + gpion: gpio@58023400 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58023400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00002000>; + }; + + gpioo: gpio@58023800 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58023800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00004000>; + }; + + gpiop: gpio@58023c00 { + compatible = "st,stm32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x58023c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB4 0x00008000>; + }; + }; + + usart1: serial@42001000 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x42001000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000010>; + resets = <&rctl STM32_RESET(APB2, 4U)>; + interrupts = <82 0>; + status = "disabled"; + }; + usart2: serial@40004400 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40004400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00020000>; + resets = <&rctl STM32_RESET(APB1L, 17U)>; + interrupts = <83 0>; + status = "disabled"; + }; + usart3: serial@40004800 { + compatible = "st,stm32-usart", "st,stm32-uart"; + reg = <0x40004800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00040000>; + resets = <&rctl STM32_RESET(APB1L, 18U)>; + interrupts = <84 0>; + status = "disabled"; + }; + uart4: serial@40004c00 { + compatible ="st,stm32-uart"; + reg = <0x40004c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00080000>; + resets = <&rctl STM32_RESET(APB1L, 19U)>; + interrupts = <85 0>; + status = "disabled"; + }; + uart5: serial@40005000 { + compatible = "st,stm32-uart"; + reg = <0x40005000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00100000>; + resets = <&rctl STM32_RESET(APB1L, 20U)>; + interrupts = <86 0>; + status = "disabled"; + }; + uart7: serial@40007800 { + compatible = "st,stm32-uart"; + reg = <0x40007800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x40000000>; + resets = <&rctl STM32_RESET(APB1L, 30U)>; + interrupts = <87 0>; + status = "disabled"; + }; + uart8: serial@40007c00 { + compatible = "st,stm32-uart"; + reg = <0x40007c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x80000000>; + resets = <&rctl STM32_RESET(APB1L, 31U)>; + interrupts = <88 0>; + status = "disabled"; + }; + + lpuart1: serial@58000c00 { + compatible = "st,stm32-lpuart", "st,stm32-uart"; + reg = <0x58000c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB4 0x00000008>; + resets = <&rctl STM32_RESET(APB4, 3U)>; + interrupts = <131 0>; + status = "disabled"; + }; + + i2c1: i2c@40005400 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40005400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00200000>; + interrupts = <76 0>, <77 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + i2c2: i2c@40005800 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40005800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00400000>; + interrupts = <78 0>, <79 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + i2c3: i2c@40005c00 { + compatible = "st,stm32-i2c-v2"; + clock-frequency = ; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40005c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00800000>; + interrupts = <80 0>, <81 0>; + interrupt-names = "event", "error"; + status = "disabled"; + }; + + spi1: spi@42003000 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x42003000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>, + <&rcc STM32_SRC_PLL1_Q SPI1_SEL(0)>; + interrupts = <58 0>; + status = "disabled"; + }; + + spi2: spi@40003800 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00004000>, + <&rcc STM32_SRC_PLL1_Q SPI23_SEL(0)>; + interrupts = <59 0>; + status = "disabled"; + }; + + spi3: spi@40003c00 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40003c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00008000>, + <&rcc STM32_SRC_PLL1_Q SPI23_SEL(0)>; + interrupts = <60 0>; + status = "disabled"; + }; + + spi4: spi@42003400 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x42003400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00002000>; + interrupts = <61 0>; + status = "disabled"; + }; + + spi5: spi@42005000 { + compatible = "st,stm32h7-spi", "st,stm32-spi-fifo", "st,stm32-spi"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x42005000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00100000>; + interrupts = <62 0>; + status = "disabled"; + }; + + i2s1: i2s@40013000 { + compatible = "st,stm32h7-i2s", "st,stm32-i2s"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40013000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00001000>, + <&rcc STM32_SRC_PLL1_Q SPI1_SEL(0)>; + interrupts = <35 3>; + status = "disabled"; + }; + + iwdg: iwdg1: watchdog@58004800 { + compatible = "st,stm32-watchdog"; + reg = <0x58004800 0x400>; + interrupts = <3 0>; + status = "disabled"; + }; + + wwdg: wwdg1: watchdog@40002c00 { + compatible = "st,stm32-window-watchdog"; + reg = <0x40002c00 0x1000>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000800>; + interrupts = <4 7>; + status = "disabled"; + }; + + timers1: timers@42000000 { + compatible = "st,stm32-timers"; + reg = <0x42000000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00000001>; + resets = <&rctl STM32_RESET(APB2, 0U)>; + interrupts = <47 0>, <48 0>, <49 0>, <50 0>; + interrupt-names = "brk", "up", "trgcom", "cc"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + }; + + timers2: timers@40000000 { + compatible = "st,stm32-timers"; + reg = <0x40000000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000001>; + resets = <&rctl STM32_RESET(APB1L, 0U)>; + interrupts = <51 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers3: timers@40000400 { + compatible = "st,stm32-timers"; + reg = <0x40000400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000002>; + resets = <&rctl STM32_RESET(APB1L, 1U)>; + interrupts = <52 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers4: timers@40000800 { + compatible = "st,stm32-timers"; + reg = <0x40000800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000004>; + resets = <&rctl STM32_RESET(APB1L, 2U)>; + interrupts = <53 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers5: timers@40000c00 { + compatible = "st,stm32-timers"; + reg = <0x40000c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000008>; + resets = <&rctl STM32_RESET(APB1L, 3U)>; + interrupts = <54 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers6: timers@40001000 { + compatible = "st,stm32-timers"; + reg = <0x40001000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000010>; + resets = <&rctl STM32_RESET(APB1L, 4U)>; + interrupts = <55 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers7: timers@40001400 { + compatible = "st,stm32-timers"; + reg = <0x40001400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000020>; + resets = <&rctl STM32_RESET(APB1L, 5U)>; + interrupts = <56 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers9: timers@42004c00 { + compatible = "st,stm32-timers"; + reg = <0x42004c00 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00080000>; + resets = <&rctl STM32_RESET(APB2, 19U)>; + interrupts = <57 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers15: timers@42004000 { + compatible = "st,stm32-timers"; + reg = <0x42004000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB2 0x00010000>; + resets = <&rctl STM32_RESET(APB2, 16U)>; + interrupts = <116 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers16: timers@42004400 { + compatible = "st,stm32-timers"; + reg = <0x42004400 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00020000>; + resets = <&rctl STM32_RESET(APB2, 17U)>; + interrupts = <117 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + timers17: timers@42004800 { + compatible = "st,stm32-timers"; + reg = <0x42004800 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00040000>; + resets = <&rctl STM32_RESET(APB2, 18U)>; + interrupts = <118 0>; + interrupt-names = "global"; + st,prescaler = <0>; + status = "disabled"; + + pwm { + compatible = "st,stm32-pwm"; + status = "disabled"; + #pwm-cells = <3>; + }; + + counter { + compatible = "st,stm32-counter"; + status = "disabled"; + }; + }; + + lptim1: timers@40002400 { + compatible = "st,stm32-lptim"; + clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000200>; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x40002400 0x400>; + interrupts = <119 1>; + interrupt-names = "wakeup"; + status = "disabled"; + }; + + adc1: adc@40022000 { + compatible = "st,stm32-adc"; + reg = <0x40022000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x00000020>; + interrupts = <38 0>; + status = "disabled"; + #io-channel-cells = <1>; + resolutions = ; + sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; + }; + + adc2: adc@40022100 { + compatible = "st,stm32-adc"; + reg = <0x40022100 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB1 0x00000020>; + interrupts = <38 0>; + status = "disabled"; + #io-channel-cells = <1>; + resolutions = ; + sampling-times = <3 7 13 25 48 93 248 641>; + st,adc-sequencer = ; + }; + + rng: rng@48020000 { + compatible = "st,stm32-rng"; + reg = <0x48020000 0x400>; + clocks = <&rcc STM32_CLOCK_BUS_AHB3 0x00000001>; + interrupts = <37 0>; + status = "disabled"; + }; + }; + + die_temp: dietemp { + compatible = "st,stm32-temp-cal"; + ts-cal1-addr = <0x08FFF814>; + ts-cal2-addr = <0x08FFF818>; + ts-cal1-temp = <30>; + ts-cal2-temp = <130>; + ts-cal-vrefanalog = <3300>; + ts-cal-resolution = <12>; + io-channels = <&adc1 16>; + status = "disabled"; + }; + + vbat: vbat { + compatible = "st,stm32-vbat"; + ratio = <4>; + status = "disabled"; + io-channels = <&adc2 16>; + }; + + vref: vref { + compatible = "st,stm32-vref"; + vrefint-cal-addr = <0x08fff810>; + vrefint-cal-mv = <3300>; + status = "disabled"; + io-channels = <&adc1 17>; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <4>; +}; diff --git a/dts/arm/st/h7rs/stm32h7s3.dtsi b/dts/arm/st/h7rs/stm32h7s3.dtsi new file mode 100644 index 0000000000000..f1d490266b7dd --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7s3.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * STM32H7S3 line contains the same peripherals as STM32H7R3. + */ +/ { + soc { + compatible = "st,stm32h7s3", "st,stm32h7rs", "simple-bus"; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7s3X8.dtsi b/dts/arm/st/h7rs/stm32h7s3X8.dtsi new file mode 100644 index 0000000000000..4eca0e58ab2c7 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7s3X8.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +/ { + soc { + flash-controller@52002000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7s7.dtsi b/dts/arm/st/h7rs/stm32h7s7.dtsi new file mode 100644 index 0000000000000..7566df2cfe9c8 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7s7.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* + * STM32H7S7 line contains the same peripherals as STM32H7R7. + */ +/ { + soc { + compatible = "st,stm32h7s7", "st,stm32h7rs", "simple-bus"; + }; +}; diff --git a/dts/arm/st/h7rs/stm32h7s7X8.dtsi b/dts/arm/st/h7rs/stm32h7s7X8.dtsi new file mode 100644 index 0000000000000..2c31b66b586e3 --- /dev/null +++ b/dts/arm/st/h7rs/stm32h7s7X8.dtsi @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +/ { + soc { + flash-controller@52002000 { + flash0: flash@8000000 { + reg = <0x08000000 DT_SIZE_K(64)>; + }; + }; + }; +}; diff --git a/dts/arm/st/l0/stm32l0.dtsi b/dts/arm/st/l0/stm32l0.dtsi index 91d290d0d0807..f515f9c3166bf 100644 --- a/dts/arm/st/l0/stm32l0.dtsi +++ b/dts/arm/st/l0/stm32l0.dtsi @@ -97,6 +97,8 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { diff --git a/dts/arm/st/l1/stm32l1.dtsi b/dts/arm/st/l1/stm32l1.dtsi index 1f6f0644819cc..3816489f42ffc 100644 --- a/dts/arm/st/l1/stm32l1.dtsi +++ b/dts/arm/st/l1/stm32l1.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2019 Linaro Ltd. * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -118,6 +119,8 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/l4/stm32l4.dtsi b/dts/arm/st/l4/stm32l4.dtsi index 7dcabdf877cd7..03e7734f75942 100644 --- a/dts/arm/st/l4/stm32l4.dtsi +++ b/dts/arm/st/l4/stm32l4.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2017 Linaro Limited * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,6 +17,7 @@ #include #include #include +#include #include / { @@ -380,6 +382,8 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <18>; status = "disabled"; }; @@ -466,6 +470,39 @@ <&rcc STM32_SRC_MSI CLK48_SEL(3)>; status = "disabled"; }; + + pwr: power@40007000 { + compatible = "st,stm32-pwr"; + reg = <0x40007000 0x400>; /* PWR register bank */ + status = "disabled"; + + wkup-pins-nb = <5>; /* 5 system wake-up pins */ + wkup-pins-pol; + wkup-pins-pupd; + + #address-cells = <1>; + #size-cells = <0>; + + wkup-pin@1 { + reg = <0x1>; + }; + + wkup-pin@2 { + reg = <0x2>; + }; + + wkup-pin@3 { + reg = <0x3>; + }; + + wkup-pin@4 { + reg = <0x4>; + }; + + wkup-pin@5 { + reg = <0x5>; + }; + }; }; die_temp: dietemp { diff --git a/dts/arm/st/l4/stm32l4r5Xi.dtsi b/dts/arm/st/l4/stm32l4r5Xi.dtsi index 9154d8820f8be..5da6f035e7693 100644 --- a/dts/arm/st/l4/stm32l4r5Xi.dtsi +++ b/dts/arm/st/l4/stm32l4r5Xi.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Pushpal Sidhu + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,3 +17,25 @@ }; }; }; + +&pwr { + wkup-pin@1 { + wkup-gpios = <&gpioa 0 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@2 { + wkup-gpios = <&gpioc 13 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@3 { + wkup-gpios = <&gpioe 6 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@4 { + wkup-gpios = <&gpioa 2 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@5 { + wkup-gpios = <&gpioc 5 STM32_PWR_WKUP_PIN_SRC_0>; + }; +}; diff --git a/dts/arm/st/l5/stm32l5.dtsi b/dts/arm/st/l5/stm32l5.dtsi index f9c37b33cd8c5..d4f7a7f000b0a 100644 --- a/dts/arm/st/l5/stm32l5.dtsi +++ b/dts/arm/st/l5/stm32l5.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2021 The Chromium OS Authors * Copyright (c) 2020 Linaro Limited + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -460,6 +461,8 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; }; diff --git a/dts/arm/st/mp1/stm32mp157.dtsi b/dts/arm/st/mp1/stm32mp157.dtsi index 2eec4faa4da30..97e72c7cb59f4 100644 --- a/dts/arm/st/mp1/stm32mp157.dtsi +++ b/dts/arm/st/mp1/stm32mp157.dtsi @@ -61,8 +61,8 @@ reg = <0x5000d000 0x400>; num-lines = <16>; interrupts = <6 0>, <7 0>, <8 0>, <9 0>, - <10 0>, <23 0>, <40 0>, <42 0>, - <64 0>, <65 0>, <66 0>, <67 0>, + <10 0>, <23 0>, <64 0>, <65 0>, + <66 0>, <67 0>, <40 0>, <42 0>, <76 0>, <77 0>, <121 0>, <127 0>; interrupt-names = "line0", "line1", "line2", "line3", "line4", "line5", "line6", "line7", diff --git a/dts/arm/st/u5/stm32u5.dtsi b/dts/arm/st/u5/stm32u5.dtsi index bd9bb445858d1..4a7f2a1fe4387 100644 --- a/dts/arm/st/u5/stm32u5.dtsi +++ b/dts/arm/st/u5/stm32u5.dtsi @@ -2,6 +2,7 @@ * Copyright (c) 2021 The Chromium OS Authors * Copyright (c) 2021 Linaro Limited * Copyright (c) 2023 PSICONTROL nv + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -18,6 +19,7 @@ #include #include #include +#include #include / { @@ -475,6 +477,7 @@ interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB3 0x00200000>; prescaler = <32768>; + alarms-count = <2>; status = "disabled"; }; @@ -839,6 +842,76 @@ }; }; + pwr: power@46020800 { + compatible = "st,stm32-pwr"; + reg = <0x46020800 0x400>; /* PWR register bank */ + status = "disabled"; + + wkup-pins-nb = <8>; /* 8 system wake-up pins */ + wkup-pin-srcs = <3>; /* 3 gpio sources associated with each wkup pin */ + wkup-pins-pol; + wkup-pins-pupd; + + #address-cells = <1>; + #size-cells = <0>; + + wkup-pin@1 { + reg = <0x1>; + wkup-gpios = <&gpioa 0 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpiob 2 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpioe 4 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@2 { + reg = <0x2>; + wkup-gpios = <&gpioa 4 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioc 13 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpioe 5 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@3 { + reg = <0x3>; + wkup-gpios = <&gpioe 6 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 1 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpiob 6 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@4 { + reg = <0x4>; + wkup-gpios = <&gpioa 2 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpiob 1 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpiob 7 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@5 { + reg = <0x5>; + wkup-gpios = <&gpioc 5 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 3 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpiob 8 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@6 { + reg = <0x6>; + wkup-gpios = <&gpiob 5 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 5 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpioe 7 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@7 { + reg = <0x7>; + wkup-gpios = <&gpiob 15 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 6 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpioe 8 STM32_PWR_WKUP_PIN_SRC_2>; + }; + + wkup-pin@8 { + reg = <0x8>; + wkup-gpios = <&gpiof 2 STM32_PWR_WKUP_PIN_SRC_0>, + <&gpioa 7 STM32_PWR_WKUP_PIN_SRC_1>, + <&gpiob 10 STM32_PWR_WKUP_PIN_SRC_2>; + }; + }; + }; swj_port: swj_port { diff --git a/dts/arm/st/wb/stm32wb.dtsi b/dts/arm/st/wb/stm32wb.dtsi index d76f2f243f743..fa0c3304fe287 100644 --- a/dts/arm/st/wb/stm32wb.dtsi +++ b/dts/arm/st/wb/stm32wb.dtsi @@ -1,6 +1,7 @@ /* * Copyright (c) 2019 Linaro Limited * Copyright (c) 2019 Centaur Analytics, Inc + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,12 +16,14 @@ #include #include #include +#include #include / { chosen { zephyr,entropy = &rng; zephyr,flash-controller = &flash; + zephyr,bt-hci = &ble_rf; }; cpus { @@ -285,6 +288,8 @@ interrupts = <41 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; bbram: backup_regs { @@ -509,6 +514,29 @@ interrupts = <51 0>; status = "disabled"; }; + + pwr: power@58000400 { + compatible = "st,stm32-pwr"; + reg = <0x58000400 0x400>; /* PWR register bank */ + status = "disabled"; + + wkup-pins-nb = <5>; /* 5 system wake-up pins */ + wkup-pins-pol; + wkup-pins-pupd; + + #address-cells = <1>; + #size-cells = <0>; + + wkup-pin@1 { + reg = <0x1>; + wkup-gpios = <&gpioa 0 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@4 { + reg = <0x4>; + wkup-gpios = <&gpioa 2 STM32_PWR_WKUP_PIN_SRC_0>; + }; + }; }; die_temp: dietemp { diff --git a/dts/arm/st/wb/stm32wb55Xg.dtsi b/dts/arm/st/wb/stm32wb55Xg.dtsi index 91592e8778df3..c3a7d391e7752 100644 --- a/dts/arm/st/wb/stm32wb55Xg.dtsi +++ b/dts/arm/st/wb/stm32wb55Xg.dtsi @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Linaro Limited + * Copyright (c) 2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -19,3 +20,20 @@ }; }; }; + +&pwr { + wkup-pin@2 { + reg = <0x2>; + wkup-gpios = <&gpioc 13 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@3 { + reg = <0x3>; + wkup-gpios = <&gpioc 12 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@5 { + reg = <0x5>; + wkup-gpios = <&gpioc 5 STM32_PWR_WKUP_PIN_SRC_0>; + }; +}; diff --git a/dts/arm/st/wba/stm32wba.dtsi b/dts/arm/st/wba/stm32wba.dtsi index 38a76023cfc43..5b402ae9501c5 100644 --- a/dts/arm/st/wba/stm32wba.dtsi +++ b/dts/arm/st/wba/stm32wba.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023 STMicroelectronics + * Copyright (c) 2023-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -23,6 +23,7 @@ zephyr,entropy = &rng; zephyr,flash-controller = &flash; st,lptim-stdby-timer = &rtc; + zephyr,bt-hci = &bt_hci_wba; }; cpus { @@ -212,6 +213,7 @@ reg = <0x46007800 0x400>; interrupts = <2 0>; clocks = <&rcc STM32_CLOCK_BUS_APB7 0x00200000>; + alarms-count = <2>; status = "disabled"; }; @@ -471,6 +473,11 @@ }; }; + bt_hci_wba: bt_hci_wba { + compatible = "st,hci-stm32wba"; + status = "okay"; + }; + swj_port: swj_port { compatible = "swj-connector"; pinctrl-0 = <&debug_jtms_swdio_pa13 &debug_jtck_swclk_pa14 diff --git a/dts/arm/st/wl/stm32wl.dtsi b/dts/arm/st/wl/stm32wl.dtsi index 5e69ef4f3b786..fae199c6f6302 100644 --- a/dts/arm/st/wl/stm32wl.dtsi +++ b/dts/arm/st/wl/stm32wl.dtsi @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020 STMicroelectronics + * Copyright (c) 2020-2024 STMicroelectronics * * SPDX-License-Identifier: Apache-2.0 */ @@ -15,6 +15,7 @@ #include #include #include +#include #include / { @@ -29,7 +30,7 @@ cpu0: cpu@0 { device_type = "cpu"; - compatible = "arm,cortex-m4f"; + compatible = "arm,cortex-m4"; reg = <0>; cpu-power-states = <&stop0 &stop1 &stop2>; }; @@ -206,6 +207,8 @@ interrupts = <42 0>; clocks = <&rcc STM32_CLOCK_BUS_APB1 0x00000400>; prescaler = <32768>; + alarms-count = <2>; + alrm-exti-line = <17>; status = "disabled"; /* In STM32WL, the backup registers are defined as part of the TAMP @@ -496,6 +499,34 @@ dma-requests= <38>; status = "disabled"; }; + + pwr: power@58000400 { + compatible = "st,stm32-pwr"; + reg = <0x58000400 0x400>; /* PWR register bank */ + status = "disabled"; + + wkup-pins-nb = <3>; /* 3 system wake-up pins */ + wkup-pins-pol; + wkup-pins-pupd; + + #address-cells = <1>; + #size-cells = <0>; + + wkup-pin@1 { + reg = <0x1>; + wkup-gpios = <&gpioa 0 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@2 { + reg = <0x2>; + wkup-gpios = <&gpioc 13 STM32_PWR_WKUP_PIN_SRC_0>; + }; + + wkup-pin@3 { + reg = <0x3>; + wkup-gpios = <&gpiob 3 STM32_PWR_WKUP_PIN_SRC_0>; + }; + }; }; die_temp: dietemp { diff --git a/dts/arm/ti/cc13xx_cc26xx.dtsi b/dts/arm/ti/cc13xx_cc26xx.dtsi index 5c67e9df3f4e9..3cdf6b5d57892 100644 --- a/dts/arm/ti/cc13xx_cc26xx.dtsi +++ b/dts/arm/ti/cc13xx_cc26xx.dtsi @@ -105,7 +105,7 @@ pwm0: pwm { compatible = "ti,cc13xx-cc26xx-timer-pwm"; - #pwm-cells = <1>; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -119,7 +119,7 @@ pwm1: pwm { compatible = "ti,cc13xx-cc26xx-timer-pwm"; - #pwm-cells = <1>; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -133,7 +133,7 @@ pwm2: pwm { compatible = "ti,cc13xx-cc26xx-timer-pwm"; - #pwm-cells = <1>; + #pwm-cells = <3>; status = "disabled"; }; }; @@ -147,7 +147,7 @@ pwm3: pwm { compatible = "ti,cc13xx-cc26xx-timer-pwm"; - #pwm-cells = <1>; + #pwm-cells = <3>; status = "disabled"; }; }; diff --git a/dts/arm64/broadcom/bcm2712.dtsi b/dts/arm64/broadcom/bcm2712.dtsi index a31e8b21d14bd..9249cb3622c0b 100644 --- a/dts/arm64/broadcom/bcm2712.dtsi +++ b/dts/arm64/broadcom/bcm2712.dtsi @@ -73,6 +73,7 @@ reg = <0x10 0x7d001000 0x200>; interrupts = ; + interrupt-names = "irq_121"; clocks = <&clk_uart>; status = "disabled"; }; diff --git a/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi b/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi index 9fdfa1d27f345..5913da254486c 100644 --- a/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi +++ b/dts/arm64/nxp/nxp_mimx8mp_a53.dtsi @@ -124,6 +124,37 @@ status = "disabled"; }; + enet: enet@30be0000 { + compatible = "nxp,enet1g"; + reg = <0x30be0000 DT_SIZE_K(64)>; + clocks = <&ccm IMX_CCM_ENET_CLK 0 0>; + rdc = ; + status = "disabled"; + + enet_mac: ethernet { + compatible = "nxp,enet-mac"; + interrupts = ; + interrupt-names = "COMMON"; + interrupt-parent = <&gic>; + nxp,mdio = <&enet_mdio>; + nxp,ptp-clock = <&enet_ptp_clock>; + status = "disabled"; + }; + enet_mdio: mdio { + compatible = "nxp,enet-mdio"; + #address-cells = <1>; + #size-cells = <0>; + status = "disabled"; + }; + enet_ptp_clock: ptp_clock { + compatible = "nxp,enet-ptp-clock"; + interrupts = ; + interrupt-parent = <&gic>; + clocks = <&ccm IMX_CCM_ENET_PLL 0 0>; + status = "disabled"; + }; + }; + iomuxc: iomuxc@30330000 { compatible = "nxp,imx-iomuxc"; reg = <0x30330000 DT_SIZE_K(64)>; diff --git a/dts/arm64/nxp/nxp_mimx93_a55.dtsi b/dts/arm64/nxp/nxp_mimx93_a55.dtsi index 0192e62a3502b..defcb2dc32687 100644 --- a/dts/arm64/nxp/nxp_mimx93_a55.dtsi +++ b/dts/arm64/nxp/nxp_mimx93_a55.dtsi @@ -10,6 +10,7 @@ #include #include #include +#include #include / { diff --git a/dts/bindings/adc/lltc,ltc2451.yaml b/dts/bindings/adc/lltc,ltc2451.yaml index b68f127337f7b..a3707e2c54903 100644 --- a/dts/bindings/adc/lltc,ltc2451.yaml +++ b/dts/bindings/adc/lltc,ltc2451.yaml @@ -10,7 +10,11 @@ include: i2c-device.yaml properties: conversion-speed: type: int + default: 60 enum: - 30 - 60 - description: Set conversion speed in Hz + description: | + Set conversion speed in Hz + Default value corresponds to the default value of the register + To specify channel 2 and 4 = 0b001010 = 10 diff --git a/dts/bindings/adc/nordic,nrf-saadc.yaml b/dts/bindings/adc/nordic,nrf-saadc.yaml index f41cf2c048e87..ebb3a889692fc 100644 --- a/dts/bindings/adc/nordic,nrf-saadc.yaml +++ b/dts/bindings/adc/nordic,nrf-saadc.yaml @@ -5,7 +5,7 @@ description: Nordic Semiconductor nRF family SAADC node compatible: "nordic,nrf-saadc" -include: adc-controller.yaml +include: ["adc-controller.yaml", "memory-region.yaml"] properties: reg: diff --git a/dts/bindings/adc/nxp,gau-adc.yaml b/dts/bindings/adc/nxp,gau-adc.yaml new file mode 100644 index 0000000000000..7f5c5767d78ab --- /dev/null +++ b/dts/bindings/adc/nxp,gau-adc.yaml @@ -0,0 +1,55 @@ +# Copyright 2022 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP GAU GPADC. + +compatible: "nxp,gau-adc" + +include: + - name: base.yaml + - name: adc-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + nxp,clock-divider: + type: int + description: | + Clock divider from 1 to 32. + Default is 1 which is reset value. + default: 1 + + nxp,power-mode: + type: string + description: | + Current bias. + Default is "full-bias" because it is the reset value. + enum: + - "full-bias" + - "half-bias" + default: "full-bias" + + nxp,input-buffer: + type: boolean + description: Enable use of the input buffer + + nxp,calibration-voltage: + type: string + enum: + - "internal" + - "external" + default: "internal" + description: | + Use external calibration voltage. + Default is "internal" because it is the reset value. + + "#io-channel-cells": + const: 1 + +io-channel-cells: + - input diff --git a/dts/bindings/arm/nordic,nrf-resetinfo.yaml b/dts/bindings/arm/nordic,nrf-resetinfo.yaml new file mode 100644 index 0000000000000..c8585e5897e50 --- /dev/null +++ b/dts/bindings/arm/nordic,nrf-resetinfo.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic RESETINFO (Reset Information) + +compatible: "nordic,nrf-resetinfo" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/arm/nxp,lpc-flexcomm.yaml b/dts/bindings/arm/nxp,lpc-flexcomm.yaml index ffc27753c3dce..57121b489ae25 100644 --- a/dts/bindings/arm/nxp,lpc-flexcomm.yaml +++ b/dts/bindings/arm/nxp,lpc-flexcomm.yaml @@ -5,7 +5,7 @@ description: LPC Flexcomm node compatible: "nxp,lpc-flexcomm" -include: [base.yaml, pinctrl-device.yaml] +include: [base.yaml, pinctrl-device.yaml, reset-device.yaml] properties: reg: diff --git a/dts/bindings/base/pm.yaml b/dts/bindings/base/pm.yaml index 0776170d8f205..50c016d07bd12 100644 --- a/dts/bindings/base/pm.yaml +++ b/dts/bindings/base/pm.yaml @@ -30,3 +30,8 @@ properties: description: | Automatically configure the device for runtime power management after the init function runs. + + zephyr,disabling-power-states: + type: phandles + description: | + List of power states that will disable this device power. diff --git a/dts/bindings/base/zephyr,memory-attr.yaml b/dts/bindings/base/zephyr,memory-attr.yaml deleted file mode 100644 index 1a5611b5258e4..0000000000000 --- a/dts/bindings/base/zephyr,memory-attr.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (c) 2023, Carlo Caione -# SPDX-License-Identifier: Apache-2.0 - -include: [base.yaml] - -properties: - zephyr,memory-region-mpu: - type: string - deprecated: true - description: | - Signify that this node should result in a dedicated MPU region. - Deprecated in favor of 'zephyr,memory-attr'. - - zephyr,memory-attr: - type: int - description: | - Attribute or set of attributes (bitmask) for the memory region. See - 'include/zephyr/dt-bindings/memory-attr/memory-attr.h' for a - comprehensive list with description of possible values. - - reg: - required: true diff --git a/dts/bindings/base/zephyr,memory-common.yaml b/dts/bindings/base/zephyr,memory-common.yaml new file mode 100644 index 0000000000000..f2ccbdb3c412c --- /dev/null +++ b/dts/bindings/base/zephyr,memory-common.yaml @@ -0,0 +1,30 @@ +# Copyright (c) 2023, Carlo Caione +# SPDX-License-Identifier: Apache-2.0 + +include: [base.yaml] + +properties: + zephyr,memory-region: + type: string + description: | + Signify that this node should result in a dedicated linker script + memory region in the final executable. The region address and size + is taken from the property, while the name is the value of + this property. + + zephyr,memory-region-mpu: + type: string + deprecated: true + description: | + Signify that this node should result in a dedicated MPU region. + Deprecated in favor of 'zephyr,memory-attr'. + + zephyr,memory-attr: + type: int + description: | + Attribute or set of attributes (bitmask) for the memory region. See + 'include/zephyr/dt-bindings/memory-attr/memory-attr.h' for a + comprehensive list with description of possible values. + + reg: + required: true diff --git a/dts/bindings/base/zephyr,memory-region.yaml b/dts/bindings/base/zephyr,memory-region.yaml index 60308af7173a4..1d9486de8b3ee 100644 --- a/dts/bindings/base/zephyr,memory-region.yaml +++ b/dts/bindings/base/zephyr,memory-region.yaml @@ -5,14 +5,8 @@ description: Compatible for devices resulting in linker memory regions compatible: "zephyr,memory-region" -include: [base.yaml, "zephyr,memory-attr.yaml"] +include: [base.yaml, "zephyr,memory-common.yaml"] properties: zephyr,memory-region: - type: string required: true - description: | - Signify that this node should result in a dedicated linker script - memory region in the final executable. The region address and size - is taken from the property, while the name is the value of - this property. diff --git a/dts/bindings/bluetooth/ambiq,bt-hci-spi.yaml b/dts/bindings/bluetooth/ambiq,bt-hci-spi.yaml index 42df66d218094..cbaabb318c1b5 100644 --- a/dts/bindings/bluetooth/ambiq,bt-hci-spi.yaml +++ b/dts/bindings/bluetooth/ambiq,bt-hci-spi.yaml @@ -7,6 +7,8 @@ description: | compatible: "ambiq,bt-hci-spi" +include: bt-hci.yaml + properties: reg: type: array @@ -30,3 +32,9 @@ properties: controller. The host needs to enable XO32MHz when receiving low to high edge interrupts and disable XO32MHz when receiving high to low edge interrupts. + + bt-hci-name: + default: "ambiq hci" + + bt-hci-bus: + default: "BT_HCI_BUS_SPI" diff --git a/dts/bindings/bluetooth/bt-hci.yaml b/dts/bindings/bluetooth/bt-hci.yaml new file mode 100644 index 0000000000000..e53b9022e9069 --- /dev/null +++ b/dts/bindings/bluetooth/bt-hci.yaml @@ -0,0 +1,28 @@ +# Common fields for Bluetooth HCI devices + +include: base.yaml + +properties: + bt-hci-name: + type: string + description: Name of the HCI transport + bt-hci-bus: + type: string + description: Bus of the transport + enum: + - "BT_HCI_BUS_VIRTUAL" + - "BT_HCI_BUS_USB" + - "BT_HCI_BUS_PCCARD" + - "BT_HCI_BUS_UART" + - "BT_HCI_BUS_RS232" + - "BT_HCI_BUS_PCI" + - "BT_HCI_BUS_SDIO" + - "BT_HCI_BUS_SPI" + - "BT_HCI_BUS_I2C" + - "BT_HCI_BUS_IPM" + bt-hci-quirks: + type: string-array + description: HCI device quirks + bt-hci-vs-ext: + type: boolean + description: Zephyr HCI vendor extensions are supported diff --git a/dts/bindings/bluetooth/espressif,esp32-bt-hci.yaml b/dts/bindings/bluetooth/espressif,esp32-bt-hci.yaml new file mode 100644 index 0000000000000..e095fcd9510a4 --- /dev/null +++ b/dts/bindings/bluetooth/espressif,esp32-bt-hci.yaml @@ -0,0 +1,13 @@ +description: Bluetooth HCI for Espressif ESP32 + +compatible: "espressif,esp32-bt-hci" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "BT ESP32" + bt-hci-bus: + default: "BT_HCI_BUS_IPM" + bt-hci-quirks: + default: ["BT_HCI_QUIRK_NO_AUTO_DLE"] diff --git a/dts/bindings/bluetooth/infineon,cat1-bless-hci.yaml b/dts/bindings/bluetooth/infineon,cat1-bless-hci.yaml index 0d38855c00edb..80671e581350e 100644 --- a/dts/bindings/bluetooth/infineon,cat1-bless-hci.yaml +++ b/dts/bindings/bluetooth/infineon,cat1-bless-hci.yaml @@ -8,8 +8,14 @@ description: | compatible: "infineon,cat1-bless-hci" -include: base.yaml +include: bt-hci.yaml properties: + bt-hci-name: + default: "PSoC 6 BLESS" + bt-hci-bus: + default: "BT_HCI_BUS_VIRTUAL" + bt-hci-quirks: + default: ["BT_HCI_QUIRK_NO_RESET"] interrupts: required: true diff --git a/dts/bindings/bluetooth/infineon,cyw208xx-hci.yaml b/dts/bindings/bluetooth/infineon,cyw208xx-hci.yaml new file mode 100644 index 0000000000000..be3cb559be4b3 --- /dev/null +++ b/dts/bindings/bluetooth/infineon,cyw208xx-hci.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Cypress Semiconductor Corporation (an Infineon company) or +# an affiliate of Cypress Semiconductor Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: | + Bluetooth module that uses Infineon CYW208XX HCI bluetooth interface + + NOTE: + cyw920829 requires fetch binary files of Bluetooth controller firmware. + To fetch Binary Blobs: west blobs fetch hal_infineon + +compatible: "infineon,cyw208xx-hci" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "CYW208XX" + bt-hci-bus: + default: "BT_HCI_BUS_VIRTUAL" diff --git a/dts/bindings/bluetooth/nxp,bt-hci-uart.yaml b/dts/bindings/bluetooth/nxp,bt-hci-uart.yaml new file mode 100644 index 0000000000000..362c540507255 --- /dev/null +++ b/dts/bindings/bluetooth/nxp,bt-hci-uart.yaml @@ -0,0 +1,50 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + Bluetooth module that uses NXP's Bluetooth Module (e.g. Murata 2EL) + +compatible: "nxp,bt-hci-uart" + +include: base.yaml + +properties: + sdio-reset-gpios: + type: phandle-array + required: true + + w-disable-gpios: + type: phandle-array + required: true + + hci-operation-speed: + type: int + description: | + HCI UART baudrate for feature operation. If not defined + bus/current-speed will be used as default. + + hw-flow-control: + type: boolean + description: Set to enable RTS/CTS flow control for HCI. + + fw-download-primary-speed: + type: int + description: | + HCI UART primary baudrate for FW download operation. + If not defined bus/current-speed will be used as default. + + fw-download-primary-flowcontrol: + type: boolean + description: | + Flow control setting for primary speed. + + fw-download-secondary-speed: + type: int + description: | + HCI UART secondary baudrate for FW download operation. + If not defined bus/current-speed will be used as default. + + fw-download-secondary-flowcontrol: + type: boolean + description: | + Flow control setting for secondary speed. diff --git a/dts/bindings/bluetooth/nxp,hci-ble.yaml b/dts/bindings/bluetooth/nxp,hci-ble.yaml new file mode 100644 index 0000000000000..f2c05c2fda1d9 --- /dev/null +++ b/dts/bindings/bluetooth/nxp,hci-ble.yaml @@ -0,0 +1,16 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP BLE HCI information + +compatible: "nxp,hci-ble" + +include: bt-hci.yaml + +properties: + interrupts: + required: true + bt-hci-name: + default: "BT NXP" + bt-hci-bus: + default: "BT_HCI_BUS_IPM" diff --git a/dts/bindings/bluetooth/renesas,bt-hci-da1469x.yaml b/dts/bindings/bluetooth/renesas,bt-hci-da1469x.yaml new file mode 100644 index 0000000000000..cd66b0119538b --- /dev/null +++ b/dts/bindings/bluetooth/renesas,bt-hci-da1469x.yaml @@ -0,0 +1,11 @@ +description: Bluetooth HCI for Renesas DA1469x + +compatible: "renesas,bt-hci-da1469x" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "BT DA1469x" + bt-hci-bus: + default: "BT_HCI_BUS_IPM" diff --git a/dts/bindings/bluetooth/silabs,bt-hci.yaml b/dts/bindings/bluetooth/silabs,bt-hci.yaml new file mode 100644 index 0000000000000..9dc5b67947c58 --- /dev/null +++ b/dts/bindings/bluetooth/silabs,bt-hci.yaml @@ -0,0 +1,13 @@ +description: Bluetooth HCI on Silabs boards + +compatible: "silabs,bt-hci" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "sl:bt" + bt-hci-bus: + default: "BT_HCI_BUS_VIRTUAL" + bt-hci-quirks: + default: ["BT_HCI_QUIRK_NO_RESET"] diff --git a/dts/bindings/bluetooth/st,hci-spi-v1.yaml b/dts/bindings/bluetooth/st,hci-spi-v1.yaml index 3784c88ded047..020a796af85f0 100644 --- a/dts/bindings/bluetooth/st,hci-spi-v1.yaml +++ b/dts/bindings/bluetooth/st,hci-spi-v1.yaml @@ -6,3 +6,7 @@ description: STMicroelectronics SPI protocol V1 compatible with BlueNRG-MS devic compatible: "st,hci-spi-v1" include: zephyr,bt-hci-spi.yaml + +properties: + bt-hci-quirks: + default: ["BT_HCI_QUIRK_NO_RESET"] diff --git a/dts/bindings/bluetooth/st,hci-spi-v2.yaml b/dts/bindings/bluetooth/st,hci-spi-v2.yaml index 36b25eae76894..97b62dc90bd82 100644 --- a/dts/bindings/bluetooth/st,hci-spi-v2.yaml +++ b/dts/bindings/bluetooth/st,hci-spi-v2.yaml @@ -6,3 +6,7 @@ description: STMicroelectronics SPI protocol V2 compatible with BlueNRG-1 and su compatible: "st,hci-spi-v2" include: zephyr,bt-hci-spi.yaml + +properties: + bt-hci-quirks: + default: ["BT_HCI_QUIRK_NO_RESET"] diff --git a/dts/bindings/bluetooth/st,hci-stm32wba.yaml b/dts/bindings/bluetooth/st,hci-stm32wba.yaml new file mode 100644 index 0000000000000..ea7c8dbbcc735 --- /dev/null +++ b/dts/bindings/bluetooth/st,hci-stm32wba.yaml @@ -0,0 +1,11 @@ +description: Bluetooth HCI driver for ST STM32WBA + +compatible: "st,hci-stm32wba" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "BT IPM" + bt-hci-bus: + default: "BT_HCI_BUS_IPM" diff --git a/dts/bindings/bluetooth/st,stm32wb-ble-rf.yaml b/dts/bindings/bluetooth/st,stm32wb-ble-rf.yaml index 51b46cbff1738..f1903de684000 100644 --- a/dts/bindings/bluetooth/st,stm32wb-ble-rf.yaml +++ b/dts/bindings/bluetooth/st,stm32wb-ble-rf.yaml @@ -6,8 +6,12 @@ description: | compatible: "st,stm32wb-rf" -include: base.yaml +include: bt-hci.yaml properties: - clocks: - required: true + clocks: + required: true + bt-hci-name: + default: "BT IPM" + bt-hci-bus: + default: "BT_HCI_BUS_IPM" diff --git a/dts/bindings/bluetooth/zephyr,bt-hci-3wire-uart.yaml b/dts/bindings/bluetooth/zephyr,bt-hci-3wire-uart.yaml new file mode 100644 index 0000000000000..d2a5f62c2137d --- /dev/null +++ b/dts/bindings/bluetooth/zephyr,bt-hci-3wire-uart.yaml @@ -0,0 +1,13 @@ +# UART Bluetooth HCI device + +description: Bluetooth HCI behind a 3-Wire UART device (H:5) + +compatible: "zephyr,bt-hci-3wire-uart" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "H:5" + bt-hci-bus: + default: "BT_HCI_BUS_UART" diff --git a/dts/bindings/bluetooth/zephyr,bt-hci-ipc.yaml b/dts/bindings/bluetooth/zephyr,bt-hci-ipc.yaml new file mode 100644 index 0000000000000..88780827ce47e --- /dev/null +++ b/dts/bindings/bluetooth/zephyr,bt-hci-ipc.yaml @@ -0,0 +1,17 @@ +description: Bluetooth HCI using the IPC subsystem + +compatible: "zephyr,bt-hci-ipc" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "IPC" + bt-hci-bus: + default: "BT_HCI_BUS_IPM" + bt-hci-quirks: + default: ["BT_HCI_QUIRK_NO_AUTO_DLE"] + bt-hci-ipc-name: + type: string + default: "nrf_bt_hci" + description: IPC endpoint name diff --git a/dts/bindings/bluetooth/zephyr,bt-hci-ll-sw-split.yaml b/dts/bindings/bluetooth/zephyr,bt-hci-ll-sw-split.yaml new file mode 100644 index 0000000000000..f53cf49e90e05 --- /dev/null +++ b/dts/bindings/bluetooth/zephyr,bt-hci-ll-sw-split.yaml @@ -0,0 +1,13 @@ +description: Bluetooth HCI provided by the native Zephyr Bluetooth Controller + +compatible: "zephyr,bt-hci-ll-sw-split" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "Controller" + bt-hci-bus: + default: "BT_HCI_BUS_VIRTUAL" + bt-hci-quirks: + default: ["BT_HCI_QUIRK_NO_AUTO_DLE"] diff --git a/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml b/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml index 50d0e311461b5..0447e69d5f19f 100644 --- a/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml +++ b/dts/bindings/bluetooth/zephyr,bt-hci-spi.yaml @@ -7,7 +7,7 @@ description: | compatible: "zephyr,bt-hci-spi" -include: spi-device.yaml +include: [spi-device.yaml, bt-hci.yaml] properties: irq-gpios: @@ -35,3 +35,9 @@ properties: resulting in an ignored transaction that then needs to be performed a second time. The default of 20uS was chosen as the lowest delay that reliably eliminated double transactions between a nRF9160 host and a nRF52832 controller. + + bt-hci-name: + default: "SPI" + + bt-hci-bus: + default: "BT_HCI_BUS_SPI" diff --git a/dts/bindings/bluetooth/zephyr,bt-hci-uart.yaml b/dts/bindings/bluetooth/zephyr,bt-hci-uart.yaml new file mode 100644 index 0000000000000..d14f8e3035648 --- /dev/null +++ b/dts/bindings/bluetooth/zephyr,bt-hci-uart.yaml @@ -0,0 +1,13 @@ +# UART Bluetooth HCI device + +description: Bluetooth HCI behind a UART device (H:4) + +compatible: "zephyr,bt-hci-uart" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "H:4" + bt-hci-bus: + default: "BT_HCI_BUS_UART" diff --git a/dts/bindings/bluetooth/zephyr,bt-hci-userchan.yaml b/dts/bindings/bluetooth/zephyr,bt-hci-userchan.yaml new file mode 100644 index 0000000000000..124a298353275 --- /dev/null +++ b/dts/bindings/bluetooth/zephyr,bt-hci-userchan.yaml @@ -0,0 +1,11 @@ +description: Bluetooth HCI provided by a Linux HCI user channel socket + +compatible: "zephyr,bt-hci-userchan" + +include: bt-hci.yaml + +properties: + bt-hci-name: + default: "HCI User Channel" + bt-hci-bus: + default: "BT_HCI_BUS_UART" diff --git a/dts/bindings/can/can-controller.yaml b/dts/bindings/can/can-controller.yaml index adc738d7319f2..e2825b6e6763b 100644 --- a/dts/bindings/can/can-controller.yaml +++ b/dts/bindings/can/can-controller.yaml @@ -5,9 +5,17 @@ include: base.yaml properties: bus-speed: type: int - required: true + deprecated: true description: | - Initial bitrate in bit/s. + Deprecated. This property has been renamed to bitrate. + + Initial bitrate in bit/s. If this is unset, the initial bitrate is set to + CONFIG_CAN_DEFAULT_BITRATE. + bitrate: + type: int + description: | + Initial bitrate in bit/s. If this is unset, the initial bitrate is set to + CONFIG_CAN_DEFAULT_BITRATE. sample-point: type: int description: | diff --git a/dts/bindings/can/can-fd-controller.yaml b/dts/bindings/can/can-fd-controller.yaml index 46fab559d2a03..ea357b832240e 100644 --- a/dts/bindings/can/can-fd-controller.yaml +++ b/dts/bindings/can/can-fd-controller.yaml @@ -5,9 +5,17 @@ include: can-controller.yaml properties: bus-speed-data: type: int - required: true + deprecated: true description: | - Initial data phase bitrate in bit/s. + Deprecated. This property has been renamed to bitrate-data. + + Initial data phase bitrate in bit/s. If this is unset, the initial data phase bitrate is set + to CONFIG_CAN_DEFAULT_BITRATE_DATA. + bitrate-data: + type: int + description: | + Initial data phase bitrate in bit/s. If this is unset, the initial data phase bitrate is set + to CONFIG_CAN_DEFAULT_BITRATE_DATA. sample-point-data: type: int description: | diff --git a/dts/bindings/can/microchip,mcp251xfd.yaml b/dts/bindings/can/microchip,mcp251xfd.yaml index e435076059475..168314547eff5 100644 --- a/dts/bindings/can/microchip,mcp251xfd.yaml +++ b/dts/bindings/can/microchip,mcp251xfd.yaml @@ -19,8 +19,6 @@ description: | reg = <0x0>; osc-freq = <40000000>; - bus-speed = <125000>; - bus-speed-data = <1000000>; }; }; diff --git a/dts/bindings/can/nordic,nrf-can.yaml b/dts/bindings/can/nordic,nrf-can.yaml new file mode 100644 index 0000000000000..a17f82a14c8e0 --- /dev/null +++ b/dts/bindings/can/nordic,nrf-can.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Nordic CAN (Controller Area Network) + +compatible: "nordic,nrf-can" + +include: + - base.yaml + - pinctrl-device.yaml + - bosch,m_can-base.yaml + +properties: + reg: + required: true + + clocks: + required: true + + pinctrl-0: + required: true diff --git a/dts/bindings/can/nxp,flexcan-fd.yaml b/dts/bindings/can/nxp,flexcan-fd.yaml index f55eb780c2d6e..ce65192812374 100644 --- a/dts/bindings/can/nxp,flexcan-fd.yaml +++ b/dts/bindings/can/nxp,flexcan-fd.yaml @@ -15,8 +15,6 @@ description: | interrupt-names = "common"; clocks = <&ccm IMX_CCM_CAN_CLK 0x84 6>; clk-source = <2>; - bus-speed = <125000>; - bus-speed-data = <1000000>; pinctrl-0 = <&pinmux_flexcan3>; pinctrl-names = "default"; diff --git a/dts/bindings/can/nxp,flexcan.yaml b/dts/bindings/can/nxp,flexcan.yaml index 736382d68bd0e..045c09974fcdd 100644 --- a/dts/bindings/can/nxp,flexcan.yaml +++ b/dts/bindings/can/nxp,flexcan.yaml @@ -13,7 +13,6 @@ description: | interrupt-names = "warning", "error", "wake-up", "mb-0-15"; clocks = <&scg KINETIS_SCG_BUS_CLK>; clk-source = <1>; - bus-speed = <125000>; pinctrl-0 = <&pinmux_flexcan0>; pinctrl-names = "default"; diff --git a/dts/bindings/can/nxp,lpc-mcan.yaml b/dts/bindings/can/nxp,lpc-mcan.yaml index 48aef0031396c..bd735c88561e6 100644 --- a/dts/bindings/can/nxp,lpc-mcan.yaml +++ b/dts/bindings/can/nxp,lpc-mcan.yaml @@ -2,7 +2,7 @@ description: NXP LPC SoC series MCAN CAN FD controller compatible: "nxp,lpc-mcan" -include: ["bosch,m_can-base.yaml", pinctrl-device.yaml] +include: ["bosch,m_can-base.yaml", pinctrl-device.yaml, "reset-device.yaml"] properties: reg: diff --git a/dts/bindings/can/ti,tcan4x5x.yaml b/dts/bindings/can/ti,tcan4x5x.yaml index 5c74989093ca0..75b115d697cee 100644 --- a/dts/bindings/can/ti,tcan4x5x.yaml +++ b/dts/bindings/can/ti,tcan4x5x.yaml @@ -16,8 +16,6 @@ description: | reset-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>; int-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; bosch,mram-cfg = <0x0 15 15 5 5 0 10 10>; - bus-speed = <125000>; - bus-speed-data = <1000000>; status = "okay"; can-transceiver { diff --git a/dts/bindings/can/zephyr,can-loopback.yaml b/dts/bindings/can/zephyr,can-loopback.yaml index 531c6d965bf8c..af93433bf041b 100644 --- a/dts/bindings/can/zephyr,can-loopback.yaml +++ b/dts/bindings/can/zephyr,can-loopback.yaml @@ -5,4 +5,4 @@ description: Zephyr emulated CAN loopback controller compatible: "zephyr,can-loopback" -include: can-controller.yaml +include: can-fd-controller.yaml diff --git a/dts/bindings/can/zephyr,native-linux-can.yaml b/dts/bindings/can/zephyr,native-linux-can.yaml index 4175617403b34..b854984ece08a 100644 --- a/dts/bindings/can/zephyr,native-linux-can.yaml +++ b/dts/bindings/can/zephyr,native-linux-can.yaml @@ -5,7 +5,7 @@ description: Zephyr CAN driver using Linux SocketCAN compatible: "zephyr,native-linux-can" -include: can-controller.yaml +include: can-fd-controller.yaml properties: host-interface: diff --git a/dts/bindings/charger/maxim,max20335-charger.yaml b/dts/bindings/charger/maxim,max20335-charger.yaml index 3fe44c92908f1..00fc9c41f11b3 100644 --- a/dts/bindings/charger/maxim,max20335-charger.yaml +++ b/dts/bindings/charger/maxim,max20335-charger.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: Maxim MAX20335 battery charger diff --git a/dts/bindings/clock/adi,max32-gcr.yaml b/dts/bindings/clock/adi,max32-gcr.yaml new file mode 100644 index 0000000000000..be8049542293b --- /dev/null +++ b/dts/bindings/clock/adi,max32-gcr.yaml @@ -0,0 +1,36 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: MAX32 Global Control + +compatible: "adi,max32-gcr" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 2 + + sysclk-prescaler: + type: int + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 32 + - 64 + - 128 + + description: | + SYSCLK prescaler. Defines actual core clock frequency SYSCLK + based on system frequency input. Some MAX32xxx devices does not + support this feature, check your device user guide before using it. + +clock-cells: + - offset + - bit diff --git a/dts/bindings/clock/espressif,esp32-rtc.yaml b/dts/bindings/clock/espressif,esp32-rtc.yaml index e30b027a46660..c5ba502398327 100644 --- a/dts/bindings/clock/espressif,esp32-rtc.yaml +++ b/dts/bindings/clock/espressif,esp32-rtc.yaml @@ -11,14 +11,32 @@ properties: reg: required: true - xtal-freq: + fast-clk-src: type: int required: true - description: Value of the external XTAL connected to ESP32. - - xtal-div: + description: | + RTC fast clock source. + - 0: ESP32_RTC_FAST_CLK_SRC_XTAL_D2 - Main XTAL divided by 2 (C3/S3) + ESP32_RTC_FAST_CLK_SRC_XTAL_D4 Main XTAL divided by 4 (ESP32/S2) + - 1: ESP32_RTC_FAST_CLK_SRC_RC_FAST - 8 MHz + enum: + - 0 + - 1 + + slow-clk-src: type: int - description: Divisor value for XTAL Clock, CPU_CLK = XTAL_FREQ / xtal-div + required: true + description: | + RTC slow clock source. Default to + - 0: ESP32_RTC_SLOW_CLK_SRC_RC_SLOW - 136 KHz (C3/S3) - 90 kHz (S2) - 150 kHz (ESP32) + - 1: ESP32_RTC_SLOW_CLK_SRC_XTAL32K - 32,768U KHz + - 2: ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 - 17,5 MHz + - 9: ESP32_RTC_SLOW_CLK_32K_EXT_OSC - External 32k oscillator connected to 32K_XP pin + enum: + - 0 + - 1 + - 2 + - 9 "#clock-cells": const: 1 diff --git a/dts/bindings/clock/mediatek,mt8195_cpuclk.yaml b/dts/bindings/clock/mediatek,mt8195_cpuclk.yaml new file mode 100644 index 0000000000000..ea85d99580a1c --- /dev/null +++ b/dts/bindings/clock/mediatek,mt8195_cpuclk.yaml @@ -0,0 +1,16 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +description: MediaTek Audio DSP CPU Frequency Control +compatible: "mediatek,mt8195_cpuclk" +properties: + freqs_mhz: + type: array + description: Available frequencies in ascending order + required: true + reg: + type: array + cg_reg: + type: int + pll_ctrl_reg: + type: int diff --git a/dts/bindings/clock/nordic,nrf-auxpll.yaml b/dts/bindings/clock/nordic,nrf-auxpll.yaml new file mode 100644 index 0000000000000..6eec285f39eb7 --- /dev/null +++ b/dts/bindings/clock/nordic,nrf-auxpll.yaml @@ -0,0 +1,92 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic Auxiliary PLL (Phase Locked Loop) + + The output frequency (f_out) of the auxiliary PLL is calculated as follows: + + f_out = ((R + A * 2^(-16)) * f_src) / B + + where: + + - A: nordic,frequency + - B: nordic,outdiv + - R: nordic,range (3=low, 4=mid, 5=high, 6=statichigh) + - f_src: Source frequency, given by clocks + +compatible: "nordic,nrf-auxpll" + +include: + - base.yaml + - clock-controller.yaml + - nordic-nrf-ficr-client.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + required: true + + "#clock-cells": + const: 0 + + nordic,ficrs: + required: true + + nordic,frequency: + type: int + required: true + description: | + Value used to set the fractional PLL divider ratio (can be set between + divider ratios 4 to 5). Valid values range from 0 to 65535. + + nordic,out-div: + type: int + enum: + - 1 + - 2 + - 3 + - 4 + - 6 + - 8 + - 12 + - 16 + description: PLL output divider. + + nordic,out-drive: + type: int + required: true + enum: + - 0 + - 1 + - 2 + - 3 + description: Output buffer drive strength. + + nordic,current-tune: + type: int + required: true + description: Constant current tune for the ring oscillator + + nordic,sdm-disable: + type: boolean + description: Disable sigma-delta modulator + + nordic,dither-disable: + type: boolean + description: Disable dither in sigma-delta modulator + + nordic,range: + type: string + required: true + enum: + - "low" + - "mid" + - "high" + - "statichigh" + description: PLL loop divider range diff --git a/dts/bindings/clock/nordic,nrf-hsfll.yaml b/dts/bindings/clock/nordic,nrf-hsfll.yaml index 3614d80870fa0..f1077dbc4f0e9 100644 --- a/dts/bindings/clock/nordic,nrf-hsfll.yaml +++ b/dts/bindings/clock/nordic,nrf-hsfll.yaml @@ -57,9 +57,3 @@ properties: - 368000000 - 384000000 - 400000000 - - nordic,ficrs: - required: true - - nordic,ficr-names: - required: true diff --git a/dts/bindings/clock/nxp,imx-ccm-fnpll.yaml b/dts/bindings/clock/nxp,imx-ccm-fnpll.yaml new file mode 100644 index 0000000000000..cd18246823c89 --- /dev/null +++ b/dts/bindings/clock/nxp,imx-ccm-fnpll.yaml @@ -0,0 +1,38 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + i.MX CCM Fractional PLL. Output frequency is given by the following + formula: Fout = Fin * (loop-div + (numerator/denominator) + +compatible: "nxp,imx-ccm-fnpll" + +include: [clock-controller.yaml, base.yaml] + +properties: + "#clock-cells": + const: 0 + + loop-div: + type: int + required: true + description: | + Loop divider. Divides PLL feedback loop (effectively multiplying output + frequency) + + numerator: + type: int + required: true + description: | + Numerator of PLL multiplier fraction + + denominator: + type: int + required: true + description: | + Denominator of PLL multiplier fraction + + src: + type: int + required: true + description: Sets source for PLL input. SOC specific. diff --git a/dts/bindings/clock/renesas,smartbond-lp-osc.yaml b/dts/bindings/clock/renesas,smartbond-lp-osc.yaml index 0aa82f773e5f2..45c3c56e47277 100644 --- a/dts/bindings/clock/renesas,smartbond-lp-osc.yaml +++ b/dts/bindings/clock/renesas,smartbond-lp-osc.yaml @@ -13,16 +13,6 @@ include: - clock-frequency properties: - calibration-interval: - type: int - default: 1 - description: | - Time in seconds between calibration of low power clock RCX or RC32K. - For XTAL32K this value is not used. - If set to 0 calibration will not be performed. This can be applied - when XTAL32K is enabled for low power clock and RCX or RC32K is used - for watchdog and strict timing is not required. - settle-time: type: int default: 8000 diff --git a/dts/bindings/clock/st,stm32f3-rcc.yaml b/dts/bindings/clock/st,stm32f3-rcc.yaml index ca0e57dc7193e..64851cdaf59da 100644 --- a/dts/bindings/clock/st,stm32f3-rcc.yaml +++ b/dts/bindings/clock/st,stm32f3-rcc.yaml @@ -31,6 +31,7 @@ properties: ADC 1 and 2 prescaler - 0: Disables the clock so the ADC can use AHB clock (synchronous mode) - Other values n: The ADC can use the PLL clock divided by n + On STM32F37x, only 2/4/6/8 are allowed. adc34-prescaler: type: int diff --git a/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml b/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml new file mode 100644 index 0000000000000..cb2980dd39c5a --- /dev/null +++ b/dts/bindings/clock/st,stm32h7rs-pll-clock.yaml @@ -0,0 +1,40 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + PLL node binding for STM32H7RS devices + + It can be used to describe 3 different PLLs: PLL1 (Main PLL), PLL2 and PLL3. + + These PLLs could take one of clk_hse, clk_hsi or clk_csi as input clock, with + an input frequency from 1 to 16 MHz. PLLM factor is used to set the input + clock in this acceptable range. + + Each PLL can have up to 5 output clocks and for each output clock, the + frequency can be computed with the following formulae: + + f(PLL_Px) = f(VCOx clock) / PLLPx -> pllx_p_ck ((pll1_p_ck : sys_ck)) + f(PLL_Qx) = f(VCOx clock) / PLLQx -> pllx_q_ck + f(PLL_Rx) = f(VCOx clock) / PLLRx -> pllx_r_ck + f(PLL_Sx) = f(VCOx clock) / PLLSx -> pllx_s_ck + f(PLL_Tx) = f(VCOx clock) / PLLTx -> pllx_t_ck (only for PLL2) + + with f(VCOx clock) = f(REFx_CK) × (PLLNx / PLLMx) + + +compatible: "st,stm32h7rs-pll-clock" + +include: st,stm32h7-pll-clock.yaml + +properties: + div-s: + type: int + description: | + PLL division factor for pllx_s_ck : valid for PLL1, 2, 3 + Valid range: 1 - 8 + + div-t: + type: int + description: | + PLL division factor for pllx_t_ck : valid for PLL2 + Valid range: 1 - 8 diff --git a/dts/bindings/clock/st,stm32h7rs-rcc.yaml b/dts/bindings/clock/st,stm32h7rs-rcc.yaml new file mode 100644 index 0000000000000..780c84564f447 --- /dev/null +++ b/dts/bindings/clock/st,stm32h7rs-rcc.yaml @@ -0,0 +1,135 @@ +# Copyright (c) 2024, STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 Reset and Clock controller node for STM32H7RS devices + This node is in charge of system clock ('SYSCLK') source selection and + System Clock Generation. + + Configuring STM32 Reset and Clock controller node: + + System clock source should be selected amongst the clock nodes available in "clocks" + node (typically 'clk_hse, clk_csi', 'pll', ...). + As part of this node configuration, SYSCLK frequency should also be defined, using + "clock-frequency" property. + Last, bus clocks (typically HCLK, PCLK1, PCLK2) should be configured using matching + prescaler properties. + Here is an example of correctly configured rcc node: + &rcc { + clocks = <&pll>; /* Set pll as SYSCLK source */ + clock-frequency = ; /* SYSCLK runs at 280MHz */ + dcpre = <1>; + hpre = <1>; + ppre1 = <1>; + ppre2 = <1>; + ppre4 = <1>; + ppre5 = <1>; + } + + Confere st,stm32-rcc binding for information about domain clocks configuration. + +compatible: "st,stm32h7rs-rcc" + +include: [clock-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#clock-cells": + const: 2 + + clock-frequency: + required: true + type: int + description: | + default frequency in Hz for clock output + + dcpre: + type: int + required: true + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 64 + - 128 + - 256 + - 512 + description: | + CPU clock prescaler. Sets a HCLK frequency (feeding Cortex-M Systick) + lower than SYSCLK frequency (actual core frequency). + Zephyr doesn't make a difference today between these two clocks. + Changing this prescaler is not allowed until it is made possible to + use them independently in Zephyr clock subsystem. + + hpre: + type: int + required: true + description: | + peripheral clock to the Bus Matrix APB (1/2/4/5) and AHB(1/2/3/4/5) peripheral + divider of the CPU clock by this prescaler (BMPRE register) + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + - 64 + - 128 + - 256 + - 512 + + ppre1: + type: int + required: true + description: | + APB1 peripheral prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + + ppre2: + type: int + required: true + description: | + APB2 peripheral prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + + ppre4: + type: int + required: true + description: | + APB4 peripheral prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + + ppre5: + type: int + required: true + description: | + APB5 peripheral prescaler + enum: + - 1 + - 2 + - 4 + - 8 + - 16 + +clock-cells: + - bus + - bits diff --git a/dts/bindings/counter/ambiq,counter.yaml b/dts/bindings/counter/ambiq,counter.yaml index 7ae915c4d2155..63399c06cae7c 100644 --- a/dts/bindings/counter/ambiq,counter.yaml +++ b/dts/bindings/counter/ambiq,counter.yaml @@ -13,3 +13,13 @@ properties: interrupts: required: true + + clock-frequency: + type: int + required: true + description: Counter clock frequency + + clk-source: + type: int + required: true + description: Counter clock source diff --git a/dts/bindings/counter/espressif,esp32-rtc-timer.yaml b/dts/bindings/counter/espressif,esp32-rtc-timer.yaml index 86d5cd6887630..a8bc1c1165f01 100644 --- a/dts/bindings/counter/espressif,esp32-rtc-timer.yaml +++ b/dts/bindings/counter/espressif,esp32-rtc-timer.yaml @@ -15,11 +15,4 @@ description: | include: base.yaml -properties: - slow-clk-freq: - description: | - The slow clock input frequency for the RTC Timer. - type: int - required: true - compatible: "espressif,esp32-rtc-timer" diff --git a/dts/bindings/counter/nxp,kinetis-lptmr.yaml b/dts/bindings/counter/nxp,kinetis-lptmr.yaml new file mode 100644 index 0000000000000..0188b103b1c20 --- /dev/null +++ b/dts/bindings/counter/nxp,kinetis-lptmr.yaml @@ -0,0 +1,8 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: Deprecated compatible for NXP LPTMR + +compatible: "nxp,kinetis-lptmr" + +include: nxp,lptmr.yaml diff --git a/dts/bindings/counter/nxp,lptmr.yaml b/dts/bindings/counter/nxp,lptmr.yaml new file mode 100644 index 0000000000000..d44fcb5ef5443 --- /dev/null +++ b/dts/bindings/counter/nxp,lptmr.yaml @@ -0,0 +1,36 @@ +# Copyright (c) 2020 Vestas Wind Systems A/S +# SPDX-License-Identifier: Apache-2.0 + +description: NXP LPTMR + +compatible: "nxp,lptmr" + +include: rtc.yaml + +properties: + reg: + required: true + + clock-frequency: + required: true + + prescaler: + required: true + + clk-source: + type: int + required: true + description: Prescaler clock source (0 to 3) + + input-pin: + type: int + description: Pulse counter input pin (0 to 3). + + active-low: + type: boolean + description: Pulse counter input pin is active-low + + resolution: + type: int + required: true + description: Represents the width of the timer in bits. diff --git a/dts/bindings/counter/nxp,mrt.yaml b/dts/bindings/counter/nxp,mrt.yaml index e9e05b6c5b5b0..18e4543cfe3db 100644 --- a/dts/bindings/counter/nxp,mrt.yaml +++ b/dts/bindings/counter/nxp,mrt.yaml @@ -5,7 +5,7 @@ description: NXP Multirate Timer compatible: "nxp,mrt" -include: base.yaml +include: [base.yaml, reset-device.yaml] properties: reg: diff --git a/dts/bindings/cpu/espressif,riscv.yaml b/dts/bindings/cpu/espressif,riscv.yaml index a93894cd946ff..374d51c6a2fd6 100644 --- a/dts/bindings/cpu/espressif,riscv.yaml +++ b/dts/bindings/cpu/espressif,riscv.yaml @@ -9,5 +9,24 @@ include: riscv,cpus.yaml properties: clock-source: + required: true type: int - description: cpu clock source + description: | + Defines the CPU clock source, each corresponding to different frequencies: + - 0: ESP32_CPU_CLK_SRC_XTAL - Uses the external crystal clock typically at 40 MHz. + - 1: ESP32_CPU_CLK_SRC_PLL - Utilizes an internal PLL which operates at either + 320 MHz or 480 MHz. + - 2: ESP32_CPU_CLK_SRC_RC_FAST - Employs an internal fast RC oscillator with + frequency of 17.5 MHz. + enum: + - 0 + - 1 + - 2 + + xtal-freq: + required: true + type: int + description: Value of the external XTAL connected to ESP32. This is typically 40 MHz. + enum: + - 40000000 + - 32000000 diff --git a/dts/bindings/cpu/espressif,xtensa-lx6.yaml b/dts/bindings/cpu/espressif,xtensa-lx6.yaml new file mode 100644 index 0000000000000..24dd830cb010d --- /dev/null +++ b/dts/bindings/cpu/espressif,xtensa-lx6.yaml @@ -0,0 +1,34 @@ +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: Espressif Xtensa CPU + +compatible: "espressif,xtensa-lx6" + +include: cdns,tensilica-xtensa-lx6.yaml + +properties: + clock-source: + required: true + type: int + description: | + Defines the CPU clock source, each corresponding to different frequencies: + - 0: ESP32_CPU_CLK_SRC_XTAL - Uses the external crystal clock typically at 40 MHz. + - 1: ESP32_CPU_CLK_SRC_PLL - Utilizes an internal PLL which operates at either + 320 MHz or 480 MHz. + - 2: ESP32_CPU_CLK_SRC_RC_FAST - Employs an internal fast RC oscillator with + frequency of 17.5 MHz. 8 MHz for ESP32S2. + - 3: APLL_CLK - 16 Mhz ~ 128 MHz + enum: + - 0 + - 1 + - 2 + - 3 + + xtal-freq: + type: int + required: true + description: Value of the external XTAL connected to ESP32. + enum: + - 40000000 + - 32000000 diff --git a/dts/bindings/cpu/espressif,xtensa-lx7.yaml b/dts/bindings/cpu/espressif,xtensa-lx7.yaml new file mode 100644 index 0000000000000..33c6503122bb8 --- /dev/null +++ b/dts/bindings/cpu/espressif,xtensa-lx7.yaml @@ -0,0 +1,34 @@ +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: Espressif Xtensa CPU + +compatible: "espressif,xtensa-lx7" + +include: cdns,tensilica-xtensa-lx7.yaml + +properties: + clock-source: + type: int + required: true + description: | + Defines the CPU clock source, each corresponding to different frequencies: + - 0: ESP32_CPU_CLK_SRC_XTAL - Uses the external crystal clock typically at 40 MHz. + - 1: ESP32_CPU_CLK_SRC_PLL - Utilizes an internal PLL which operates at either + 320 MHz or 480 MHz. + - 2: ESP32_CPU_CLK_SRC_RC_FAST - Employs an internal fast RC oscillator with + frequency of 17.5 MHz. 8 MHz for ESP32S2. + - 3: APLL_CLK - 16 Mhz ~ 128 MHz (ESP32S2 Only) + enum: + - 0 + - 1 + - 2 + - 3 + + xtal-freq: + type: int + required: true + description: Value of the external XTAL connected to ESP32. + enum: + - 40000000 + - 32000000 diff --git a/dts/bindings/cpu/qemu,riscv-virt.yaml b/dts/bindings/cpu/qemu,riscv-virt.yaml new file mode 100644 index 0000000000000..c4c5a8b174eca --- /dev/null +++ b/dts/bindings/cpu/qemu,riscv-virt.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 + +description: QEMU RISC-V virt machine CPU node + +compatible: "qemu,riscv-virt" + +include: riscv,cpus.yaml diff --git a/dts/bindings/dac/nxp,gau-dac.yaml b/dts/bindings/dac/nxp,gau-dac.yaml new file mode 100644 index 0000000000000..e151d2fdbe3d5 --- /dev/null +++ b/dts/bindings/dac/nxp,gau-dac.yaml @@ -0,0 +1,45 @@ +# Copyright 2023 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP GAU DAC + +compatible: "nxp,gau-dac" + +include: dac-controller.yaml + +properties: + nxp,dac-reference: + type: string + enum: + - "internal" + - "external" + default: "internal" + description: | + DAC reference select. + Default is "internal" because that is the reset value. + + nxp,output-voltage-range: + type: string + enum: + - "small" + - "medium" + - "large" + default: "large" + description: | + See specific platform Reference Manual for equations describing the options. + Default is large because that is the reset value. + + nxp,conversion-rate: + type: string + enum: + - "62.5K" + - "125K" + - "250K" + - "500K" + default: "62.5K" + description: | + DAC conversion rate. + Default is "62.5K" because that is the reset value. + + "#io-channel-cells": + const: 0 diff --git a/dts/bindings/display/galaxycore,gc9x01x.yaml b/dts/bindings/display/galaxycore,gc9x01x.yaml index bc85c652b0635..7867de55a0dea 100644 --- a/dts/bindings/display/galaxycore,gc9x01x.yaml +++ b/dts/bindings/display/galaxycore,gc9x01x.yaml @@ -29,23 +29,9 @@ description: | compatible: "galaxycore,gc9x01x" -include: [spi-device.yaml, display-controller.yaml, lcd-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml, lcd-controller.yaml] properties: - reset-gpios: - type: phandle-array - description: | - RESET pin of the GC9X01X. - If connected directly the MCU pin should be configured - as active low. - - cmd-data-gpios: - type: phandle-array - required: true - description: | - Data/Command pin of the GC9X01X is to be configured - high(1) for data, low(0) for command. - orientation: type: string default: "normal" diff --git a/dts/bindings/display/ilitek,ili9xxx-common.yaml b/dts/bindings/display/ilitek,ili9xxx-common.yaml index 802250002d604..6a657399140e6 100644 --- a/dts/bindings/display/ilitek,ili9xxx-common.yaml +++ b/dts/bindings/display/ilitek,ili9xxx-common.yaml @@ -28,6 +28,7 @@ properties: - 270 description: Display rotation (CW) in degrees. + If not defined, rotation is off by default. display-inversion: type: boolean diff --git a/dts/bindings/display/sitronix,st7735r.yaml b/dts/bindings/display/sitronix,st7735r.yaml index 90ead2b8731d8..bc94281e82923 100644 --- a/dts/bindings/display/sitronix,st7735r.yaml +++ b/dts/bindings/display/sitronix,st7735r.yaml @@ -5,26 +5,9 @@ description: ST7735R/ST7735S 160x128 (max) display controller compatible: "sitronix,st7735r" -include: [spi-device.yaml, display-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml] properties: - reset-gpios: - type: phandle-array - description: RESET pin. - - The RESET pin of ST7735R is active low. - If connected directly the MCU pin should be configured - as active low. - - cmd-data-gpios: - type: phandle-array - required: true - description: D/CX pin. - - The D/CX pin of ST7735R is active low (transmission command byte). - If connected directly the MCU pin should be configured - as active low. - x-offset: type: int required: true diff --git a/dts/bindings/display/sitronix,st7789v.yaml b/dts/bindings/display/sitronix,st7789v.yaml index ec72e18d7f977..9b503eb86bafa 100644 --- a/dts/bindings/display/sitronix,st7789v.yaml +++ b/dts/bindings/display/sitronix,st7789v.yaml @@ -6,29 +6,9 @@ description: ST7789V 320x240 display controller compatible: "sitronix,st7789v" -include: [spi-device.yaml, display-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml] properties: - reset-gpios: - type: phandle-array - description: | - RESET pin. - - The RESET pin of ST7789V is active low. - If connected directly the MCU pin should be configured - as active low. - - cmd-data-gpios: - type: phandle-array - description: | - D/CX pin. If configured, 4-lines serial interface is used, otherwise - 3-lines serial interface is used and a D/CX bit (9-bit) is added to - the protocol. - - The D/CX pin of ST7789V is active low (transmission command byte). - If connected directly the MCU pin should be configured - as active low. - x-offset: type: int required: true @@ -115,3 +95,6 @@ properties: type: uint8-array required: true description: RGB Interface Control Parameter + + mipi-mode: + required: true diff --git a/dts/bindings/display/sitronix,st7796s.yaml b/dts/bindings/display/sitronix,st7796s.yaml index 8f67fe81e4158..1c0117235083c 100644 --- a/dts/bindings/display/sitronix,st7796s.yaml +++ b/dts/bindings/display/sitronix,st7796s.yaml @@ -104,3 +104,12 @@ properties: - "2-dot" description: | Display inversion control mode. + + rgb-is-inverted: + type: boolean + description: | + Inverting color format order (RGB->BGR or BGR->RGB) + In the case of enabling this option, API reports pixel-format in capabilities + as the inverted value of the RGB pixel-format specified in MADCTL. + This option is convenient for supporting displays with bugs + where the actual color is different from the pixel format of MADCTL. diff --git a/dts/bindings/display/solomon,ssd16xx-common.yaml b/dts/bindings/display/solomon,ssd16xx-common.yaml index dd5b651e8feaf..343f9a9c69b48 100644 --- a/dts/bindings/display/solomon,ssd16xx-common.yaml +++ b/dts/bindings/display/solomon,ssd16xx-common.yaml @@ -3,35 +3,13 @@ description: SSD16XX EPD display controller -include: [spi-device.yaml, display-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml] properties: softstart: type: uint8-array description: Booster soft start values - orientation-flipped: - type: boolean - description: Last column address is mapped to first segment - - reset-gpios: - type: phandle-array - required: true - description: RESET pin. - - The RESET pin of SSD16XX is active low. - If connected directly the MCU pin should be configured - as active low. - - dc-gpios: - type: phandle-array - required: true - description: DC pin. - - The DC pin of SSD16XX is active low (transmission command byte). - If connected directly the MCU pin should be configured - as active low. - busy-gpios: type: phandle-array required: true @@ -49,6 +27,18 @@ properties: an external temperature sensor is connected to the controller. The value selects which sensor should be used. + rotation: + type: int + default: 0 + enum: + - 0 + - 90 + - 180 + - 270 + description: + Display rotation (CW) in degrees. + If not defined, rotation is off by default. + child-binding: description: | Child nodes describe refresh profiles. Each refresh profile diff --git a/dts/bindings/display/ultrachip,uc81xx-common.yaml b/dts/bindings/display/ultrachip,uc81xx-common.yaml index b2c8a4de35c13..20819d8c9fb01 100644 --- a/dts/bindings/display/ultrachip,uc81xx-common.yaml +++ b/dts/bindings/display/ultrachip,uc81xx-common.yaml @@ -1,30 +1,13 @@ # Copyright (c) 2022 Andreas Sandberg # Copyright (c) 2020, Phytec Messtechnik GmbH +# Copyright 2024 NXP # SPDX-License-Identifier: Apache-2.0 description: UltraChip UC81xx EPD display controller common properties -include: [spi-device.yaml, display-controller.yaml] +include: [mipi-dbi-spi-device.yaml, display-controller.yaml] properties: - reset-gpios: - type: phandle-array - required: true - description: RESET pin. - - The RESET pin of UC81xx is active low. - If connected directly the MCU pin should be configured - as active low. - - dc-gpios: - type: phandle-array - required: true - description: DC pin. - - The DC pin of UC81xx is active low (transmission command byte). - If connected directly the MCU pin should be configured - as active low. - busy-gpios: type: phandle-array required: true diff --git a/dts/bindings/dma/intel,sedi-dma.yaml b/dts/bindings/dma/intel,sedi-dma.yaml new file mode 100644 index 0000000000000..8e708cc232f73 --- /dev/null +++ b/dts/bindings/dma/intel,sedi-dma.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2023 Intel Corporation +# +# SPDX-License-Identifier: Apache-2.0 + +description: Intel SEDI DMA controller. + +compatible: "intel,sedi-dma" + +include: dma-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + peripheral-id: + type: int + description: Peripheral Instance ID + required: true diff --git a/dts/bindings/dma/intel,sedi_dma.yaml b/dts/bindings/dma/intel,sedi_dma.yaml deleted file mode 100644 index 3fe1036c00c9f..0000000000000 --- a/dts/bindings/dma/intel,sedi_dma.yaml +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2023 Intel Corporation -# -# SPDX-License-Identifier: Apache-2.0 - -description: Intel SEDI DMA controller. - -compatible: "intel,sedi_dma" - -include: dma-controller.yaml - -properties: - reg: - required: true - - interrupts: - required: true - - peripheral-id: - type: int - description: Peripheral Instance ID - required: true diff --git a/dts/bindings/dma/raspberrypi,pico-dma.yaml b/dts/bindings/dma/raspberrypi,pico-dma.yaml index 35960fbca7fe9..10263958b1372 100644 --- a/dts/bindings/dma/raspberrypi,pico-dma.yaml +++ b/dts/bindings/dma/raspberrypi,pico-dma.yaml @@ -2,7 +2,7 @@ # SPDX-License-Identifier: Apache-2.0 description: | - Raspberry Pi Pico GPIO + Raspberry Pi Pico DMA channel: Select channel for data transmitting @@ -30,7 +30,7 @@ properties: irq0-channels: type: uint8-array - default: [0, 2, 4, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30] + default: [0, 2, 4, 6, 8, 10] description: Channels list that uses the irq0 "#dma-cells": diff --git a/dts/bindings/dma/renesas,smartbond-dma.yaml b/dts/bindings/dma/renesas,smartbond-dma.yaml index 0845df7746324..388efb236ebf0 100644 --- a/dts/bindings/dma/renesas,smartbond-dma.yaml +++ b/dts/bindings/dma/renesas,smartbond-dma.yaml @@ -19,3 +19,14 @@ properties: type: int const: 1 description: Number of block counts supported + + "#dma-cells": + const: 2 + +# - #dma-cells : Must be <2>. +# channel: dma channel to be reserved +# config: peripheral's dma request line. Valid values are defined in dt-bindings/dma/dma_smartbond.h + +dma-cells: + - channel + - config diff --git a/dts/bindings/ethernet/ethernet-controller.yaml b/dts/bindings/ethernet/ethernet-controller.yaml index 8823459d3a9eb..bb4fa794152be 100644 --- a/dts/bindings/ethernet/ethernet-controller.yaml +++ b/dts/bindings/ethernet/ethernet-controller.yaml @@ -36,3 +36,4 @@ properties: - "mii" - "rmii" - "gmii" + - "rgmii" diff --git a/dts/bindings/ethernet/microchip,ksz8081.yaml b/dts/bindings/ethernet/microchip,ksz8081.yaml index 83a6be9f72d99..7667fca85314b 100644 --- a/dts/bindings/ethernet/microchip,ksz8081.yaml +++ b/dts/bindings/ethernet/microchip,ksz8081.yaml @@ -8,15 +8,13 @@ compatible: "microchip,ksz8081" include: ethernet-phy.yaml properties: - mc,reset-gpio: + reset-gpios: type: phandle-array - specifier-space: gpio description: GPIO connected to PHY reset signal pin. Reset is active low. - mc,interrupt-gpio: + int-gpios: type: phandle-array - specifier-space: gpio description: GPIO for interrupt signal indicating PHY state change. - mc,interface-type: + microchip,interface-type: type: string required: true description: Which type of phy connection the phy is set up for diff --git a/dts/bindings/ethernet/nxp,enet-mac.yaml b/dts/bindings/ethernet/nxp,enet-mac.yaml index cf8ca151e46c1..b6b7aaff10ad4 100644 --- a/dts/bindings/ethernet/nxp,enet-mac.yaml +++ b/dts/bindings/ethernet/nxp,enet-mac.yaml @@ -26,6 +26,17 @@ properties: nxp,unique-mac: type: boolean description: | - Use unique silicon ID to use UAA MAC. + Use part of the unique silicon ID to generate the MAC. This property will be overridden if the node has zephyr,random-mac-address or local-mac-address also. + This option is intended for cases where a very low likelihood + that the mac address is the same as another on the network + is sufficient, such as, testing, bringup, demos, etc. + The first 3 bytes will be the freescale OUI and the next + 3 bytes will come from the chip's unique ID. + + nxp,fused-mac: + type: boolean + description: | + Use the MAC address from fuse shadow register. + Not all platforms have a fusable MAC address. diff --git a/dts/bindings/ethernet/nxp,enet.yaml b/dts/bindings/ethernet/nxp,enet.yaml index f98af9f002b50..23e234bb7ae7a 100644 --- a/dts/bindings/ethernet/nxp,enet.yaml +++ b/dts/bindings/ethernet/nxp,enet.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP ENET IP Module diff --git a/dts/bindings/ethernet/nxp,enet1g.yaml b/dts/bindings/ethernet/nxp,enet1g.yaml new file mode 100644 index 0000000000000..4c7e99ab72d2e --- /dev/null +++ b/dts/bindings/ethernet/nxp,enet1g.yaml @@ -0,0 +1,19 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP ENET1G IP Module + +compatible: "nxp,enet1g" + +include: ["base.yaml"] + +properties: + reg: + required: true + + clocks: + required: true + + rdc: + type: int + description: Set the RDC(Resource Domain Controller) domain permission for this peripheral diff --git a/dts/bindings/ethernet/realtek,rtl8211f.yaml b/dts/bindings/ethernet/realtek,rtl8211f.yaml new file mode 100644 index 0000000000000..1f8cc22e71db3 --- /dev/null +++ b/dts/bindings/ethernet/realtek,rtl8211f.yaml @@ -0,0 +1,16 @@ +# Copyright 2023-2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: Realtek RTL8211F Ethernet PHY device + +compatible: "realtek,rtl8211f" + +include: ethernet-phy.yaml + +properties: + reset-gpios: + type: phandle-array + description: GPIO connected to PHY reset signal pin. Reset is active low. + int-gpios: + type: phandle-array + description: GPIO for interrupt signal indicating PHY state change. diff --git a/dts/bindings/flash_controller/st,stm32-ospi-nor.yaml b/dts/bindings/flash_controller/st,stm32-ospi-nor.yaml index cdcb0b9d80089..0330240c79777 100644 --- a/dts/bindings/flash_controller/st,stm32-ospi-nor.yaml +++ b/dts/bindings/flash_controller/st,stm32-ospi-nor.yaml @@ -32,6 +32,9 @@ properties: reset-gpios: type: phandle-array description: RESETn pin + reset-gpios-duration: + type: int + description: The duration (in ms) for the flash memory reset pulse spi-bus-width: type: int required: true diff --git a/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml b/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml new file mode 100644 index 0000000000000..7aee7040f6b08 --- /dev/null +++ b/dts/bindings/flash_controller/st,stm32-xspi-nor.yaml @@ -0,0 +1,62 @@ +# Copyright (c) 2021 - 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 XSPI Flash controller supporting the JEDEC CFI interface + + Representation of a serial flash on a xspi bus: + + mx25lm51245: xspi-nor-flash@70000000 { + compatible = "st,stm32-xspi-nor"; + reg = <0x70000000 DT_SIZE_M(64)>; /* 512 Mbits */ + data-mode = ; /* access on 8 data lines */ + data-rate = ; /* access in DTR */ + ospi-max-frequency = ; + status = "okay"; + }; + +compatible: "st,stm32-xspi-nor" + +include: + - name: st,stm32-ospi-nor.yaml + property-blocklist: + - spi-bus-width + - data-rate +properties: + spi-bus-width: + type: int + required: true + description: | + The width of XSPI bus to which flash memory is connected. + + Possible values are : + - XSPI_SPI_MODE <1> = SPI mode on 1 data line + - XSPI_DUAL_MODE <2> = Dual mode on 2 data lines + - XSPI_QUAD_MODE <4> = Quad mode on 4 data lines + - XSPI_OCTO_MODE <8> = Octo mode on 8 data lines + enum: + - 1 + - 2 + - 4 + - 8 + data-rate: + type: int + required: true + description: | + The SPI data Rate is STR or DTR + + Possible values are : + - XSPI_STR_TRANSFER <1> = Single Rate Transfer + - XSPI_DTR_TRANSFER <2> = Dual Rate Transfer (only with XSPI_OCTO_MODE) + enum: + - 1 + - 2 + + ncs-line: + type: int + default: 1 + enum: + - 1 + - 2 + description: | + Specifies which nCS line of the XSPI IO Manager is connected to the Flash. diff --git a/dts/bindings/gnss/zephyr,gnss-emul.yaml b/dts/bindings/gnss/zephyr,gnss-emul.yaml new file mode 100644 index 0000000000000..eb7d9eec8acc3 --- /dev/null +++ b/dts/bindings/gnss/zephyr,gnss-emul.yaml @@ -0,0 +1,6 @@ +# Copyright (c) 2024 Trackunit Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Zephyr emulated GNSS device + +compatible: "zephyr,gnss-emul" diff --git a/dts/bindings/gpio/adi,adp5585-gpio.yaml b/dts/bindings/gpio/adi,adp5585-gpio.yaml new file mode 100644 index 0000000000000..bb27d2facb61e --- /dev/null +++ b/dts/bindings/gpio/adi,adp5585-gpio.yaml @@ -0,0 +1,30 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: ADP5585 GPIO Controller + +compatible: "adi,adp5585-gpio" + +include: gpio-controller.yaml + +properties: + "#gpio-cells": + const: 2 + + ngpios: + const: 13 + description: | + Number of GPIOs available on port expander. + + gpio-reserved-ranges: + required: true + const: [5, 3] + description: | + Ranges of GPIOs reserved unavailable on port expander. + The ADP5585 has 10 GPIO lines divided in 2 groups. GPIO number + 5, 6, 7 is reserved. That's to say, GPIO R0~R4 occupy line + number 0~4, GPIO C0~C4 occupy line number 8~12. + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/adi,max32-gpio.yaml b/dts/bindings/gpio/adi,max32-gpio.yaml new file mode 100644 index 0000000000000..d903ff70cae10 --- /dev/null +++ b/dts/bindings/gpio/adi,max32-gpio.yaml @@ -0,0 +1,19 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: MAX32 GPIO + +compatible: "adi,max32-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/adi,sdp-120.yaml b/dts/bindings/gpio/adi,sdp-120.yaml new file mode 100644 index 0000000000000..02d1249cdd5aa --- /dev/null +++ b/dts/bindings/gpio/adi,sdp-120.yaml @@ -0,0 +1,74 @@ +# Copyright (c) 2024 Analog Devices Inc. +# Copyright (c) 2024 Baylibre, SAS + +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO pins exposed on a Analog devices SDP interface. + + 120-pin SDP interface: + + 1 VIN NC 120 + 2 NC NC 119 + 3 GND GND 118 + 4 GND GND 117 + 5 USB_VBUS VIO 116 + 6 GND GND 115 + 7 PAR_D23 PAR_D22 114 + 8 PAR_D21 PAR_D20 113 + 9 PAR_D19 PAR_D18 112 + 10 PAR_D17 PAR_D16 111 + 11 GND PAR_D15 110 + 12 PAR_D14 GND 109 + 13 PAR_D13 PAR_D12 108 + 14 PAR_D11 PAR_D10 107 + 15 PAR_D9 PAR_D8 106 + 16 PAR_D7 PAR_D6 105 + 17 GND GND 104 + 18 PAR_D5 PAR_D4 103 + 19 PAR_D3 PAR_D2 102 + 20 PAR_D1 PAR_D0 101 + 21 PAR_RD_N PAR_WR_N 100 + 22 PAR_CS_N PAR_INT 99 + 23 GND GND 98 + 24 PAR_A3 PAR_A2 97 + 25 PAR_A1 PAR_A0 96 + 26 PAR_FS3 PAR_FS2 95 + 27 PAR_FS1 PAR_CLK 94 + 28 GND GND 93 + 29 SPORT_TDV0 SPORT_RSCLK 92 + 30 SPORT_TDV1 SPORT_DR0 91 + 31 SPORT_DR1 SPORT_RFS 90 + 32 SPORT_DT1 SPORT_TFS 89 + 33 SPI_D2 SPORT_DT0 88 + 34 SPI_D3 SPORT_TSCLK 87 + 35 SERIAL_INT GND 86 + 36 GND SPI_SEL_A_N 85 + 37 SPI_SEL_B_N SPI_MOSI 84 + 38 SPI_SEL_C_N SPI_MISO 83 + 39 SPI_SEL1/SPI_SS_N SPI_CLK 82 + 40 GND GND 81 + 41 SDA_1 SDA_0 80 + 42 SCL_1 SCL_0 79 + 43 GPIO0 GPIO1 78 + 44 GPIO2 GPIO3 77 + 45 GPIO4 GPIO5 76 + 46 GND GND 75 + 47 GPIO6 GPIO7 74 + 48 TMR_A TMR_B 73 + 49 TMR_C TMR_D 72 + 50 NC CLKOUT 71 + 51 NC NC 70 + 52 GND GND 69 + 53 NC NC 68 + 54 NC NC 67 + 55 NC NC 66 + 56 EEPROM_A0 WAKE_N 65 + 57 RESET_OUT_N SLEEP_N 64 + 58 GND GND 63 + 59 UART_RX UART_TX 62 + 60 RESET_IN_N BMODE1 61 + +compatible: "adi,sdp-120" + +include: [gpio-nexus.yaml, base.yaml] diff --git a/dts/bindings/gpio/brcm,iproc-gpio.yaml b/dts/bindings/gpio/brcm,iproc-gpio.yaml new file mode 100644 index 0000000000000..11543d6fe7393 --- /dev/null +++ b/dts/bindings/gpio/brcm,iproc-gpio.yaml @@ -0,0 +1,29 @@ +# Copyright 2020 Broadcom +# SPDX-License-Identifier: Apache-2.0 + +description: Broadcom iProc GPIO Controller + +compatible: "brcm,iproc-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + description: | + Define the base and range of the I/O address space that contains SoC + GPIO/PINCONF controller registers + + ngpios: + required: true + description: Total number of in-use slots in GPIO controller + + interrupts: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/nxp,cam-44pins-connector.yaml b/dts/bindings/gpio/nxp,cam-44pins-connector.yaml new file mode 100644 index 0000000000000..f929b71581fb0 --- /dev/null +++ b/dts/bindings/gpio/nxp,cam-44pins-connector.yaml @@ -0,0 +1,33 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO pins exposed on NXP 44-pin board-to-board camera connector. + The connector layout is depicted below: + + 42 GND GND 41 + 2 AF_GND AGND 1 + 4 AF_VCC STROBE 3 + 6 VCMSINK SDA 5 + 8 AVDD SCL 7 + 10 GPIO1 RESETB 9 + 12 GPIO0 PCLK 11 + 14 FREX VSYNC 13 + 16 MIPI_CSI_DP1/D9 HREF 15 + 18 MIPI_CSI_DN1/D8 PWDN 17 + 20 DGND MIPI_CSI_DP1/D9 19 + 22 MIPI_CSI_CLKP/D7 MIPI_CSI_DN1/D8 21 + 24 MIPI_CSI_CLKN/D6 MIPI_CSI_CLKP/D7 23 + 26 DGND MIPI_CSI_CLKN/D6 25 + 28 MIPI_CSI_DP0/D5 MIPI_CSI_DP0/D5 27 + 30 MIPI_CSI_DN0/D4 MIPI_CSI_DN0/D4 29 + 32 DGND D3 31 + 34 XCLK D2 33 + 36 DVDD D1 35 + 38 DOVDD D0 37 + 40 DGND DGND 39 + 44 AF_GND GND 43 + +compatible: "nxp,cam-44pins-connector" + +include: [gpio-nexus.yaml, base.yaml] diff --git a/dts/bindings/gpio/nxp,gpio-cluster.yaml b/dts/bindings/gpio/nxp,gpio-cluster.yaml new file mode 100644 index 0000000000000..73f5de72ea2cd --- /dev/null +++ b/dts/bindings/gpio/nxp,gpio-cluster.yaml @@ -0,0 +1,9 @@ +description: A group of GPIOs that share an interrupt. + +compatible: "nxp,gpio-cluster" + +include: [base.yaml] + +properties: + interrupts: + required: true diff --git a/dts/bindings/gpio/nxp,i2c-tsc-fpc.yaml b/dts/bindings/gpio/nxp,i2c-tsc-fpc.yaml new file mode 100644 index 0000000000000..077f6701961a0 --- /dev/null +++ b/dts/bindings/gpio/nxp,i2c-tsc-fpc.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + + +compatible: "nxp,i2c-tsc-fpc" + +description: | + GPIO pins exposed on NXP LCD touch controller interface. These pins are + exposed on a 6 pin flexible printed cable connector. The pins have the + following assignments: + + Pin Number Usage + 1 VDD + 2 LCD touch reset + 3 LCD touch interrupt + 4 LCD touch controller I2C SCL + 5 LCD touch controller I2C SDA + 6 GND + +include: [gpio-nexus.yaml, base.yaml] diff --git a/dts/bindings/gpio/nxp,lpc-gpio-port.yaml b/dts/bindings/gpio/nxp,lpc-gpio-port.yaml new file mode 100644 index 0000000000000..43cdec363b44b --- /dev/null +++ b/dts/bindings/gpio/nxp,lpc-gpio-port.yaml @@ -0,0 +1,34 @@ +# Copyright 2019-2022, 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: LPC GPIO port device. + +compatible: "nxp,lpc-gpio-port" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#gpio-cells": + const: 2 + + int-source: + type: string + default: "none" + enum: + - "pint" + - "int-a" + - "int-b" + - "none" + description: | + Interrupt source for the gpio port. For ports that can use the PINT + as an interrupt source for their pins (typically ports 0 and 1), + this can be set to PINT. Otherwise, the property should be set to "int-a" + or "int-b" if interrupt support is desired, and the appropriate IRQ number + should set for the device. + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/gpio/nxp,lpc-gpio.yaml b/dts/bindings/gpio/nxp,lpc-gpio.yaml index 52716cba7de63..19b31bc284ca4 100644 --- a/dts/bindings/gpio/nxp,lpc-gpio.yaml +++ b/dts/bindings/gpio/nxp,lpc-gpio.yaml @@ -1,48 +1,23 @@ -# Copyright (c) 2019-22, NXP +# Copyright 2024 NXP # SPDX-License-Identifier: Apache-2.0 +# This binding is for the gpio device, +# which has multiple ports that share the same +# base address. It is the ports that are +# functionally gpio devices. + description: LPC GPIO node compatible: "nxp,lpc-gpio" -include: [gpio-controller.yaml, base.yaml] +include: base.yaml properties: reg: required: true - "#gpio-cells": - const: 2 - - port: - type: int - required: true - description: The GPIO port this node describes - enum: - - 0 - - 1 - - 2 - - 3 - - 4 - - 5 - - 6 - - 7 - - int-source: - type: string - default: "none" - enum: - - "pint" - - "int-a" - - "int-b" - - "none" - description: | - Interrupt source for the gpio port. For ports that can use the PINT - as an interrupt source for their pins (typically ports 0 and 1), - this can be set to PINT. Otherwise, the property should be set to "int-a" - or "int-b" if interrupt support is desired, and the appropriate IRQ number - should set for the device. + "#address-cells": + const: 1 -gpio-cells: - - pin - - flags + "#size-cells": + const: 0 diff --git a/dts/bindings/gpio/nxp,parallel-lcd-connector.yaml b/dts/bindings/gpio/nxp,parallel-lcd-connector.yaml new file mode 100644 index 0000000000000..c1d8e8657e2ff --- /dev/null +++ b/dts/bindings/gpio/nxp,parallel-lcd-connector.yaml @@ -0,0 +1,33 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + + +compatible: "nxp,parallel-lcd-connector" + +description: | + GPIO pins exposed on NXP LCD interface. These pins are + exposed on a 40 pin flexible printed cable connector. The pins have the + following assignments: + + FPC Pin Function + 1 LED backlight cathode + 2 LED backlight anode + 3 GND + 4 VDD (3v3) + 5-7 GND + 8-12 LCD D11-D15 + 13-14 GND + 15-20 LCD D5-D10 + 21-23 GND + 24-28 LCD D0-D4 + 29 GND + 30 LCD CLK + 31 LCD DISP + 32 LCD HSYNC + 33 LCD VSYNC + 34 LCD DE + 35 NC + 36 GND + 37-40 NC + +include: [gpio-nexus.yaml, base.yaml] diff --git a/dts/bindings/gpio/sparkfun,micromod-gpio.yaml b/dts/bindings/gpio/sparkfun,micromod-gpio.yaml new file mode 100644 index 0000000000000..ae0c290aee3ef --- /dev/null +++ b/dts/bindings/gpio/sparkfun,micromod-gpio.yaml @@ -0,0 +1,51 @@ +# Copyright (c) 2024 Jerónimo Agulló +# SPDX-License-Identifier: Apache-2.0 + +description: | + GPIO pins exposed on micromod headers. + + The micromod standard leverages the M.2 connector with 76 pins for + swap between a myriad of supported boards and carriers. + + The micromod standard consists of two lanes with the following + supported buses: + * An 6-pin Power Supply header. No pins on this header are exposed + by this binding. + * Reset, Boot pins and SWD pins not exposed by this binding. + * 2 UART buses. First with RTS and CTS pins, while the 2nd with only + RX and TX pins. Neither of them are exposed by this binding. + * 2 i2c buses. Only the corresponding interrupt pin is exposed by + this binding. + * 2 SPI buses not exposed by this binding. Only SPI CS control pin + is exposed by this binding. + * Audio line not exposed by this binding. + * 2 analog pins (A0 and A1). + * 2 digital pins (D0 and D1). + * 12 General purpose pins (G0 - G11). + + This binding provides a nexus mapping for the analog, digital and + general purpose gpios in the order depicted below: + + - 00 -> A0 PIN 34 + - 01 -> A1 PIN 38 + - 02 -> D0 PIN 10 + - 03 -> D1/CAM_TRIG PIN 18 + - 04 -> I2C_INT# PIN 16 + - 05 -> G0/BUS0 PIN 40 + - 06 -> G1/BUS1 PIN 42 + - 07 -> G2/BUS2 PIN 44 + - 08 -> G3/BUS3 PIN 46 + - 09 -> G4/BUS4 PIN 48 + - 10 -> G5/BUS5 PIN 73 + - 11 -> G6/BUS6 PIN 71 + - 12 -> G7/BUS7 PIN 69 + - 13 -> G8 PIN 67 + - 14 -> G9/ADC_D-/CAM_HSYNC PIN 65 + - 15 -> G10/ADC_D+/CAM_VSYNC PIN 63 + - 16 -> G11/SWO PIN 8 + - 17 -> SPI_CS PIN 55 + + +compatible: "sparkfun,micromod-gpio" + +include: [gpio-nexus.yaml, base.yaml] diff --git a/dts/bindings/gpio/zephyr,gpio-emul.yaml b/dts/bindings/gpio/zephyr,gpio-emul.yaml index b1810ef26991c..fc2b09cd8390e 100644 --- a/dts/bindings/gpio/zephyr,gpio-emul.yaml +++ b/dts/bindings/gpio/zephyr,gpio-emul.yaml @@ -8,9 +8,6 @@ compatible: "zephyr,gpio-emul" include: [gpio-controller.yaml, base.yaml] properties: - reg: - required: true - rising-edge: description: Enables support for rising edge interrupt detection type: boolean diff --git a/dts/bindings/i2c/adi,max32-i2c.yaml b/dts/bindings/i2c/adi,max32-i2c.yaml new file mode 100644 index 0000000000000..2b1c81de0c70b --- /dev/null +++ b/dts/bindings/i2c/adi,max32-i2c.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: ADI MAX32 I2C + +compatible: "adi,max32-i2c" + +include: [i2c-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + clocks: + required: true + + interrupts: + required: true diff --git a/dts/bindings/i2c/brcm,iproc-i2c.yaml b/dts/bindings/i2c/brcm,iproc-i2c.yaml new file mode 100644 index 0000000000000..343674488f49d --- /dev/null +++ b/dts/bindings/i2c/brcm,iproc-i2c.yaml @@ -0,0 +1,16 @@ +# Copyright 2020 Broadcom +# Copyright 2024 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +description: Broadcom iProc I2C controller + +compatible: "brcm,iproc-i2c" + +include: i2c-controller.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/dts/bindings/i2c/litex,i2c.yaml b/dts/bindings/i2c/litex,i2c.yaml index acb9032bd4eb7..04af4f9858def 100644 --- a/dts/bindings/i2c/litex,i2c.yaml +++ b/dts/bindings/i2c/litex,i2c.yaml @@ -13,3 +13,6 @@ include: i2c-controller.yaml properties: reg: required: true + + clock-frequency: + required: true diff --git a/dts/bindings/input/futaba,sbus.yaml b/dts/bindings/input/futaba,sbus.yaml new file mode 100644 index 0000000000000..574c7ef7ff809 --- /dev/null +++ b/dts/bindings/input/futaba,sbus.yaml @@ -0,0 +1,70 @@ +# Copyright (c) 2024 NXP Semiconductors +# SPDX-License-Identifier: Apache-2.0 + +description: | + SBUS input driver using + This driver implements the SBUS protocol used on RC radio's + to send out analogue joystick and switches output. + SBUS is an single-wire inverted serial protocol to either you need to + to the rx-invert feature of your serial driver or use an external signal inverter. + The driver binds this to the Zephyr input system using INPUT_EV_CODES. + + The following examples defines a a binding of 2 joysticks and a button using 5 channels. + + &lpuart6 { + status = "okay"; + + sbus { + compatible = "futaba,sbus"; + right_stick_x { + channel = <1>; + type = ; + zephyr,code = ; + }; + right_stick_y { + channel = <2>; + type = ; + zephyr,code = ; + }; + left_stick_x { + channel = <3>; + type = ; + zephyr,code = ; + }; + left_stick_y { + channel = <4>; + type = ; + zephyr,code = ; + }; + kill_switch { + channel = <5>; + type = ; + zephyr,code = ; + }; + }; + }; + +compatible: "futaba,sbus" + +include: [base.yaml, uart-device.yaml] + +child-binding: + description: | + SBUS Channel to input-event-code binding + INPUT_EV_ABS & INPUT_EV_MSC gives raw input value + INPUT_EV_KEY emulates a key + properties: + channel: + type: int + required: true + description: | + SBUS input channel + Valid range: 1 - 16 + type: + type: int + required: true + description: Input event types see INPUT_EV_CODES + zephyr,code: + type: int + required: true + description: Code to emit. diff --git a/dts/bindings/interrupt-controller/litex,vexriscv-intc0.yaml b/dts/bindings/interrupt-controller/litex,vexriscv-intc0.yaml new file mode 100644 index 0000000000000..3d1fd43deb7d6 --- /dev/null +++ b/dts/bindings/interrupt-controller/litex,vexriscv-intc0.yaml @@ -0,0 +1,24 @@ +# Copyright (c) 2018 - 2019 Antmicro +# SPDX-License-Identifier: Apache-2.0 + +description: LiteX VexRiscV interrupt controller + +compatible: "litex,vexriscv-intc0" + +include: [interrupt-controller.yaml, base.yaml] + +properties: + reg: + required: true + + riscv,max-priority: + type: int + description: maximum interrupt priority + required: true + + "#interrupt-cells": + const: 2 + +interrupt-cells: + - irq + - priority diff --git a/dts/bindings/interrupt-controller/mediatek,adsp_intc.yaml b/dts/bindings/interrupt-controller/mediatek,adsp_intc.yaml new file mode 100644 index 0000000000000..03f5941d36395 --- /dev/null +++ b/dts/bindings/interrupt-controller/mediatek,adsp_intc.yaml @@ -0,0 +1,33 @@ +# Copyright 2023 The ChromiumOS Authors +# SPDX-License-Identifier: Apache-2.0 + +description: MediaTek MT8xxx Audio DSP Interrupt Controller + +compatible: "mediatek,adsp_intc" + +include: [interrupt-controller.yaml, base.yaml] + +properties: + reg: + required: true + + interrupts: + required: true + + "#interrupt-cells": + const: 3 + + status-reg: + description: Register address of interrupt-is-signaled bits + type: int + required: true + + mask: + description: Mask of valid interrupt bits + type: int + required: true + +interrupt-cells: + - irq + - sense + - priority diff --git a/dts/bindings/interrupt-controller/st,stm32h7rs-exti.yaml b/dts/bindings/interrupt-controller/st,stm32h7rs-exti.yaml new file mode 100644 index 0000000000000..1e441fb47b80b --- /dev/null +++ b/dts/bindings/interrupt-controller/st,stm32h7rs-exti.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2024, STMicroelectronics + +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 controller + This compatible stands for the stm32H7RS interrupt-controller block + with two dedicated Rising and Falling interrupt pending registers + +compatible: "st,stm32h7rs-exti" + +include: st,stm32-exti.yaml diff --git a/dts/bindings/interrupt-controller/vexriscv-intc0.yaml b/dts/bindings/interrupt-controller/vexriscv-intc0.yaml deleted file mode 100644 index e370a774c5a63..0000000000000 --- a/dts/bindings/interrupt-controller/vexriscv-intc0.yaml +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) 2018 - 2019 Antmicro -# SPDX-License-Identifier: Apache-2.0 - -description: LiteX VexRiscV interrupt controller - -compatible: "vexriscv-intc0" - -include: [interrupt-controller.yaml, base.yaml] - -properties: - reg: - required: true - - riscv,max-priority: - type: int - description: maximum interrupt priority - required: true - - "#interrupt-cells": - const: 2 - -interrupt-cells: - - irq - - priority diff --git a/dts/bindings/ipm/nxp,lpc-mailbox.yaml b/dts/bindings/ipm/nxp,lpc-mailbox.yaml index 12f99a8338667..14e96d7e0db21 100644 --- a/dts/bindings/ipm/nxp,lpc-mailbox.yaml +++ b/dts/bindings/ipm/nxp,lpc-mailbox.yaml @@ -5,7 +5,7 @@ description: LPC MAILBOX compatible: "nxp,lpc-mailbox" -include: base.yaml +include: [base.yaml, reset-device.yaml] properties: reg: diff --git a/dts/bindings/ipm/st,stm32-hsem-mailbox.yaml b/dts/bindings/ipm/st,stm32-hsem-mailbox.yaml index 813ca865f97b3..c8df24f2572cf 100644 --- a/dts/bindings/ipm/st,stm32-hsem-mailbox.yaml +++ b/dts/bindings/ipm/st,stm32-hsem-mailbox.yaml @@ -13,3 +13,11 @@ properties: interrupts: required: true + + "#mbox-cells": + type: int + description: | + Dummy property for device tree compatibility with MBOX driver. + +mbox-cells: + - channel diff --git a/dts/bindings/led/issi,is31fl3194.yaml b/dts/bindings/led/issi,is31fl3194.yaml new file mode 100644 index 0000000000000..4d07a36d7a4aa --- /dev/null +++ b/dts/bindings/led/issi,is31fl3194.yaml @@ -0,0 +1,74 @@ +# Copyright (c) 2024 Arduino SA +# SPDX-License-Identifier: Apache-2.0 + +description: | + IS31FL3194 3-channel LED driver with programmable pattern sequencing + + This driver supports single-channel and RGB LEDs. For single channel LEDs, + the led_set_brightness() API can be used to set the brightness of each LED. + For RGB LEDs, the led_set_color() API can be used to set the red, green and + blue components; the driver takes care of routing to the outputs described + by the color-mapping property. + + The LED_SHELL application can be used for testing. + + The following defines a single RGB LED in the is31fl3194 DT node: + + is31fl3194@53 { + compatible = "issi,is31fl3194"; + reg = <0x53>; + + led_0 { + label = "RGB LED"; + color-mapping = + , + , + ; + }; + }; + + The following example defines three single-channel LEDs in the is31fl3194 DT node: + + is31fl3194@53 { + compatible = "issi,is31fl3194"; + reg = <0x53>; + + led_0 { + label = "RED LED"; + color-mapping = ; + }; + + led_1 { + label = "GREEN LED"; + color-mapping = ; + }; + + led_2 { + label = "BLUE LED"; + color-mapping = ; + }; + }; + + +compatible: "issi,is31fl3194" + +include: ["i2c-device.yaml", "led-controller.yaml"] + +child-binding: + properties: + label: + required: true + + color-mapping: + required: true + + current-limit: + type: int + enum: + - 10 + - 20 + - 30 + - 40 + required: true + description: | + The current limit for the LED in mA. diff --git a/dts/bindings/led_strip/apa,apa102.yaml b/dts/bindings/led_strip/apa,apa102.yaml index 0a6e6a00a0de4..2d3b7b665294e 100644 --- a/dts/bindings/led_strip/apa,apa102.yaml +++ b/dts/bindings/led_strip/apa,apa102.yaml @@ -2,4 +2,4 @@ description: APA102 SPI LED strip compatible: "apa,apa102" -include: spi-device.yaml +include: [spi-device.yaml, led-strip.yaml] diff --git a/dts/bindings/led_strip/greeled,lpd8803.yaml b/dts/bindings/led_strip/greeled,lpd8803.yaml index 6baca4898d68c..7a7dc8158c279 100644 --- a/dts/bindings/led_strip/greeled,lpd8803.yaml +++ b/dts/bindings/led_strip/greeled,lpd8803.yaml @@ -5,4 +5,4 @@ description: GreeLed LPD8803 SPI LED strip compatible: "greeled,lpd8803" -include: spi-device.yaml +include: [spi-device.yaml, led-strip.yaml] diff --git a/dts/bindings/led_strip/greeled,lpd8806.yaml b/dts/bindings/led_strip/greeled,lpd8806.yaml index 0a0f0e9f6ee74..971155b210d65 100644 --- a/dts/bindings/led_strip/greeled,lpd8806.yaml +++ b/dts/bindings/led_strip/greeled,lpd8806.yaml @@ -5,4 +5,4 @@ description: GreeLed LPD8806 SPI LED strip compatible: "greeled,lpd8806" -include: spi-device.yaml +include: [spi-device.yaml, led-strip.yaml] diff --git a/dts/bindings/led_strip/led-strip.yaml b/dts/bindings/led_strip/led-strip.yaml new file mode 100644 index 0000000000000..f8ffb62e68314 --- /dev/null +++ b/dts/bindings/led_strip/led-strip.yaml @@ -0,0 +1,24 @@ +# Copyright (c) 2019, Linaro Limited +# Copyright (c) 2019, Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Common fields for LED strips + +properties: + chain-length: + type: int + required: true + description: | + The number of devices in the daisy-chain. + + color-mapping: + type: array + required: true + description: | + Channel to color mapping (or pixel order). + + For example a GRB channel to color mapping would be + + color-mapping = ; diff --git a/dts/bindings/led_strip/ti,tlc5971.yaml b/dts/bindings/led_strip/ti,tlc5971.yaml index 2da4f234e64fa..de66dd7d2af28 100644 --- a/dts/bindings/led_strip/ti,tlc5971.yaml +++ b/dts/bindings/led_strip/ti,tlc5971.yaml @@ -6,7 +6,8 @@ description: | Driver bindings for daisy chains of a TLC5971 devices using a single device tree node. Length of daisy chains in pixels is defined by the chain-length - property. + property. Note: chain-length must be a multiple of 4. A single TLC5971 device + supports 4 RGB LEDs. The color order of the TLC5971 is BGR. Applications can provide custom mappings using the color-mapping property. @@ -28,23 +29,4 @@ description: | compatible: "ti,tlc5971" -include: spi-device.yaml - -properties: - chain-length: - type: int - required: true - description: | - The number of RGB LEDs in the daisy-chain. - Must be multiple of 4. A single TLC5971 device supports 4 RGB LEDs. - - color-mapping: - type: array - required: true - description: | - Channel to color mapping (or pixel order). - For example a BGR channel to color mapping would be - - color-mapping = ; +include: [spi-device.yaml, led-strip.yaml] diff --git a/dts/bindings/led_strip/ti,tlc59731.yaml b/dts/bindings/led_strip/ti,tlc59731.yaml new file mode 100644 index 0000000000000..596bee98d165d --- /dev/null +++ b/dts/bindings/led_strip/ti,tlc59731.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Javad Rahimipetroudi +# SPDX-License-Identifier: Apache-2.0 + +compatible: "ti,tlc59731" +description: TLC59731 RGB LED Controller +include: [led-strip.yaml] + +properties: + gpios: + required: true + type: phandle-array + description: | + GPIO to send command data to the controller. diff --git a/dts/bindings/led_strip/ws2812.yaml b/dts/bindings/led_strip/ws2812.yaml index ff594a862cd64..6b8e59b7e9e7e 100644 --- a/dts/bindings/led_strip/ws2812.yaml +++ b/dts/bindings/led_strip/ws2812.yaml @@ -34,25 +34,9 @@ description: | property. The pixel order depends on the model and it can be configured using the color-mapping property. -properties: - chain-length: - type: int - required: true - description: | - The number of devices in the daisy-chain. - - color-mapping: - type: array - required: true - description: | - Channel to color mapping (or pixel order). - - For example a GRB channel to color mapping would be - - color-mapping = ; +include: led-strip.yaml +properties: reset-delay: type: int default: 8 diff --git a/dts/bindings/lora/reyax,rylrxxx.yaml b/dts/bindings/lora/reyax,rylrxxx.yaml new file mode 100644 index 0000000000000..e04a78f7ac491 --- /dev/null +++ b/dts/bindings/lora/reyax,rylrxxx.yaml @@ -0,0 +1,13 @@ +# Copyright (c) 2024 David Ullmann +# SPDX-License-Identifier: Apache-2.0 + +description: Reyax lora module with AT-command serial interface + +compatible: "reyax,rylrxxx" + +include: uart-device.yaml + +properties: + reset-gpios: + type: phandle-array + required: true diff --git a/dts/bindings/mbox/st,mbox-stm32-hsem.yaml b/dts/bindings/mbox/st,mbox-stm32-hsem.yaml new file mode 100644 index 0000000000000..50226f3118242 --- /dev/null +++ b/dts/bindings/mbox/st,mbox-stm32-hsem.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Celina Sophie Kalus +# SPDX-License-Identifier: Apache-2.0 + +description: STM32 HSEM MBOX + +compatible: "st,mbox-stm32-hsem" + +include: [base.yaml, mailbox-controller.yaml] + +properties: + clocks: + required: true + + interrupts: + required: true + +mbox-cells: + - channel diff --git a/dts/bindings/memory-controllers/renesas,smartbond-nor-psram.yaml b/dts/bindings/memory-controllers/renesas,smartbond-nor-psram.yaml new file mode 100644 index 0000000000000..f55e064683bde --- /dev/null +++ b/dts/bindings/memory-controllers/renesas,smartbond-nor-psram.yaml @@ -0,0 +1,260 @@ +# Copyright (c) 2023 Renesas Electronics Corporation +# SPDX-License-Identifier: Apache-2.0 + +description: Renesas Smartbond(tm) NOR/PSRAM controller + +include: base.yaml + +compatible: "renesas,smartbond-nor-psram" + +properties: + reg: + required: true + + is-ram: + type: boolean + description: | + If present, the memory controller will be configured to drive PSRAM devices. + + dev-size: + type: int + required: true + description: | + Memory size/capacity in bits. + + dev-type: + type: int + required: true + description: | + Device type, part of device ID, used to verify the memory device used. + + dev-density: + type: int + required: true + description: | + Device density, part of device ID, used to verify the memory device used. + [7:0] should reflect the density value itself and [15:8] should reflect + the mask that should be applied to the returned device ID value. + This is because part of its byte value might contain invalid bits. + + dev-id: + type: int + required: true + description: | + Manufacturer ID, part of device ID, used to verify the memory device used. + + reset-delay-us: + type: int + required: true + description: | + Time in microseconds (us) the memory device can accept the next command following a SW reset. + + read-cs-idle-min-ns: + type: int + required: true + description: | + Min. time, in nanoseconds, the #CS line should remain inactive between + the transmission of two different instructions. + + erase-cs-idle-min-ns: + type: int + description: | + Min. time, in nanoseconds, the #CS line should remain inactive after the execution + of a write enable, erase, erase suspend or erase resume instruction. This setting + is not used if is-ram property is present. + + enter-qpi-cmd: + type: int + description: | + Command to enter the QPI mode supported by a memory device + (should be transmitted in single bus mode). + + exit-qpi-cmd: + type: int + description: | + Command to exit the QPI mode supported by a memory device + (should be transmitted in quad bus mode). + + enter-qpi-mode: + type: boolean + description: | + If present, the memory device will enter the QPI mode which typically reflects that + all bytes be sent in quad bus mode. It's a pre-requisite that read and write + commands, that should be read-cmd and write-cmd respectively, reflect the QPI mode. + + read-cmd: + type: int + default: 0x03 + description: | + Read command for single/burst read accesses in auto mode. Default value is the opcode + for single mode which is supported by all memory devices. + + write-cmd: + type: int + default: 0x02 + description: | + Write command for single/burst write accesses in auto mode. Default value is the opcode + for single mode which is supported by all memory devices. + + clock-mode: + type: string + enum: + - "spi-mode0" + - "spi-mode3" + default: "spi-mode0" + description: | + Clock mode when #CS is idle/inactive + + - Mode0: #CLK is low when #CS is inactive + - Mode3: #CLK is high when #CS is inactive + + Mode0 is selected by default as it should be supported by all memory devices. + + addr-range: + type: string + enum: + - "addr-range-24bit" + - "addr-range-32bit" + default: "addr-range-24bit" + description: | + Address size to use in auto mode. In 24-bit mode up to 16MB can be + accessed whilst in 32-bit mode up to 32MB can be accessed which is + the max. address space supported by QSPICx. Default value is 24-bit + mode which is supported by all memory devices. + + clock-div: + type: int + description: | + Clock divider for QSPIC2 controller. The clock path of + this block is always DIV1 which reflects the current + system clock. + + tcem-max-us: + type: int + description: | + If a non zero value is applied, then Tcem should be taken into + consideration by QSPIC2 so that it can split a burst read/write + access in case the total time exceeds the defined value + (at the cost of extra cycles required for re-sending the instruction, + address and dummy bytes, if any). This setting is meaningful only if + is-ram is present. This value reflects the max. time in microseconds + the #CS line can be driven low in a write/read burst access + (required for the auto-refresh mechanism, when supported). + + dummy-bytes-count: + type: string + required: true + enum: + - "dummy-bytes-count0" + - "dummy-bytes-count1" + - "dummy-bytes-count2" + - "dummy-bytes-count4" + description: | + Number of dummy bytes to send for single/burst read access in auto mode. + + extra-byte-enable: + type: boolean + description: | + If present, the extra byte will be sent after the dummy bytes, if any. + This should be useful if 3 dummy bytes are required. In such a case, + dummy-bytes-count should be set to 2. + + extra-byte: + type: int + description: | + Extra byte to be sent, if extra-byte-enable is present. + + rx-addr-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the address phase for single/burst + read accesses in auto mode. Default value is single mode which should be + supported by all memory devices. + + rx-inst-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the instruction phase for single/burst + read accesses in auto mode. Default value is single mode which should be + supported by all memory devices. + + rx-data-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the data phase for single/burst + read accesses in auto mode. Default value is single mode which should + be supported by all memory devices. + + rx-dummy-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the dummy bytes phase for single/burst + read accesses in auto mode. The single mode should be supported by all + memory devices. + + rx-extra-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + description: | + Describes the mode of SPI bus during the extra byte phase for single/burst + read accesses in auto mode. Default value is single mode which should be + supported by all memory devices. + + tx-addr-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the address phase for single/burst + write accesses in auto mode. Default value is single mode which should + be supported by all memory devices. + + tx-inst-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the instruction phase for single/burst + write accesses in auto mode. The single mode should be supported by all + memory devices. + + tx-data-mode: + type: string + enum: + - "single-spi" + - "dual-spi" + - "quad-spi" + default: "single-spi" + description: | + Describes the mode of SPI bus during the data phase for single/burst + write accesses in auto mode. Default value is single mode which should + be supported by all memory devices. diff --git a/dts/bindings/mfd/adi,adp5585.yaml b/dts/bindings/mfd/adi,adp5585.yaml new file mode 100644 index 0000000000000..9d2456b6a83b5 --- /dev/null +++ b/dts/bindings/mfd/adi,adp5585.yaml @@ -0,0 +1,19 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: Analog ADP5585 GPIO/keypad/PWM chip + +compatible: "adi,adp5585" + +include: i2c-device.yaml + +properties: + reset-gpios: + type: phandle-array + description: RESET pin + + nint-gpios: + type: phandle-array + description: | + Connection for the NINT signal. This signal is active-low when + produced by adp5585 GPIO node. diff --git a/dts/bindings/mipi-dbi/mipi-dbi-device.yaml b/dts/bindings/mipi-dbi/mipi-dbi-device.yaml index 4f68fadf73151..2cadb4d3a425c 100644 --- a/dts/bindings/mipi-dbi/mipi-dbi-device.yaml +++ b/dts/bindings/mipi-dbi/mipi-dbi-device.yaml @@ -19,6 +19,18 @@ properties: the concordance list (see dt-bindings/mipi_dbi/mipi_dbi.h) 1 MIPI_DBI_MODE_SPI_3WIRE 2 MIPI_DBI_MODE_SPI_4WIRE + 3 MIPI_DBI_MODE_6800_BUS_16_BIT + 4 MIPI_DBI_MODE_6800_BUS_9_BIT + 5 MIPI_DBI_MODE_6800_BUS_8_BIT + 6 MIPI_DBI_MODE_8080_BUS_16_BIT + 7 MIPI_DBI_MODE_8080_BUS_9_BIT + 8 MIPI_DBI_MODE_8080_BUS_8_BIT enum: - 1 - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 diff --git a/dts/bindings/mipi-dbi/nxp,mipi-dbi-flexio-lcdif.yaml b/dts/bindings/mipi-dbi/nxp,mipi-dbi-flexio-lcdif.yaml new file mode 100644 index 0000000000000..25851966505d9 --- /dev/null +++ b/dts/bindings/mipi-dbi/nxp,mipi-dbi-flexio-lcdif.yaml @@ -0,0 +1,63 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP FlexIO LCD controller + +compatible: "nxp,mipi-dbi-flexio-lcdif" + +include: [mipi-dbi-controller.yaml, base.yaml, pinctrl-device.yaml] + +properties: + shifters-count: + type: int + required: true + description: | + Number of FlexIO shifters needed. + + timers-count: + type: int + required: true + description: | + Number of FlexIO timers needed. + + enwr-pin: + type: int + required: true + description: | + Pin select for WR(8080 mode), EN(6800 mode). + + rd-pin: + type: int + description: | + Pin select for RD(8080 mode), not used in 6800 mode. + + data-pin-start: + type: int + required: true + description: | + Start index of the data pin. + + cs-gpios: + type: phandle-array + required: true + description: | + CS Pin + GPIO to drive the CS pin. + + rs-gpios: + type: phandle-array + required: true + description: | + RS Pin + GPIO to drive the RS pin. + + rdwr-gpios: + type: phandle-array + description: | + RDWR Pin + GPIO to drive the RDWR pin. This is required for Motorola 68K bus. + + reset-gpios: + type: phandle-array + description: | + Reset GPIO pin. diff --git a/dts/bindings/misc/zephyr,swdp-gpio.yaml b/dts/bindings/misc/zephyr,swdp-gpio.yaml new file mode 100644 index 0000000000000..c6d6aa55e7fa8 --- /dev/null +++ b/dts/bindings/misc/zephyr,swdp-gpio.yaml @@ -0,0 +1,102 @@ +# Copyright (c) 2019 Phytec Messtechnik GmbH +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + This is a representation of the Serial Wire Debug Port interface + implementation by GPIO bit-banging. + + Schematic using dual-supply bus transceiver and separate dout and dnoe pins + + VCC_3V3 VCC_REF + ^ ^ + | +-------------+ | + +-------|vcca vccb|-----+ + | | + clk-gpios -------|a b|-------------- SWD CLK + | | + noe-gpios -------|dir gnd|-----+ + +-------------+ | + 74LVC1T45 v + GND + + + VCC_3V3 VCC_REF + ^ ^ + | +-------------+ | + +-------|vcca vccb|-----+ + | | + dio-gpios -------|a b|------------*- SWD DIO + | | | + +-------|dir gnd|-----+ | + | +-------------+ | | + v 74LVC1T45 v | + GND GND | + | + | + VCC_3V3 VCC_REF | + ^ ^ | + | +-------------+ | | + +-------|vcca vccb|-----+ | + | | | + dout-gpios -------|a b|------------+ + | | + dnoe-gpios -------|dir gnd|-----+ + +-------------+ | + 74LVC1T45 v + GND + + Direct connection using only dio pin for SWD DIO. + + clk-gpios ------------------------------------ SWD CLK + + dio-gpios ------------------------------------ SWD DIO + + Of course, bidirectional bus transceiver between dio and SWD DIO can also be + used together with noe pin to enable/disable transceivers. + +compatible: "zephyr,swdp-gpio" + +include: base.yaml + +properties: + clk-gpios: + type: phandle-array + required: true + description: GPIO pin used for SWCLK output + + dio-gpios: + type: phandle-array + required: true + description: | + GPIO pin used for SWDIO input. This pin is also used for the SWDIO output + if separate output pin is not defined. + + dout-gpios: + type: phandle-array + description: | + Optional GPIO pin used for SWDIO output. + + dnoe-gpios: + type: phandle-array + description: | + GPIO pin used to disable the SWDIO output buffer behind optional + pin dout-gpios. + + noe-gpios: + type: phandle-array + description: | + Optional pin to disable all bus transceivers if any are present. + + reset-gpios: + type: phandle-array + description: | + Optional GPIO pin used for RESET output. + + port-write-cycles: + type: int + required: true + description: | + Number of processor cycles for I/O Port write operations.For example, the + GPIO clock may be different from the CPU clock. This can usually be + found in the SoC documentation. diff --git a/dts/bindings/modem/zephyr,gsm-ppp.yaml b/dts/bindings/modem/zephyr,gsm-ppp.yaml deleted file mode 100644 index 768173d62707f..0000000000000 --- a/dts/bindings/modem/zephyr,gsm-ppp.yaml +++ /dev/null @@ -1,8 +0,0 @@ -# Copyright (c) 2021 G-Technologies Sdn. Bhd. -# SPDX-License-Identifier: Apache-2.0 - -description: GSM PPP modem - -compatible: "zephyr,gsm-ppp" - -include: uart-device.yaml diff --git a/dts/bindings/mtd/atmel,at24.yaml b/dts/bindings/mtd/atmel,at24.yaml index da3369ec623c5..b9dda41cc802a 100644 --- a/dts/bindings/mtd/atmel,at24.yaml +++ b/dts/bindings/mtd/atmel,at24.yaml @@ -2,7 +2,36 @@ # Copyright (c) 2018, Nordic Semiconductor # SPDX-License-Identifier: Apache-2.0 -description: Atmel AT24 (or compatible) I2C EEPROM +description: | + I2C EEPROMs compatible with Atmel's AT24 family + + There are multiple vendors manufacturing I2C EEPROMs compatible with the programming model of the + Atmel AT24. + + Examples of compatible EEPROM families: + - Microchip AT24xxx + - ST M24xxx + + Each of these can be represented by a set of common parameters (EEPROM size, page size, address + width, and timeout) available from the datasheet of the specific EEPROM. The compatible string for + these can list the specific EEPROM vendor and model along with the vendor EEPROM family as long as + the least-specific compatible entry is "atmel,at24". + + Example devicetree node describing a ST M24M01 EEPROM on the i2c0 bus: + + &i2c0 { + status = "okay"; + clock-frequency = ; + + eeprom@56 { + compatible = "st,m24m01", "st,m24xxx", "atmel,at24"; + reg = <0x56>; + size = ; + pagesize = <256>; + address-width = <16>; + timeout = <5>; + }; + }; compatible: "atmel,at24" diff --git a/dts/bindings/mtd/atmel,at25.yaml b/dts/bindings/mtd/atmel,at25.yaml index 9b1977e8dc136..7c887dd1768e8 100644 --- a/dts/bindings/mtd/atmel,at25.yaml +++ b/dts/bindings/mtd/atmel,at25.yaml @@ -1,7 +1,36 @@ # Copyright (c) 2019 Vestas Wind Systems A/S # SPDX-License-Identifier: Apache-2.0 -description: Atmel AT25 (or compatible) SPI EEPROM +description: | + SPI EEPROMs compatible with Atmel's AT25 family + + There are multiple vendors manufacturing SPI EEPROMs compatible with the programming model of the + Atmel AT25. + + Examples of compatible EEPROM families: + - Microchip AT25xxx + - ST M95xxx + + Each of these can be represented by a set of common parameters (EEPROM size, page size, address + width, and timeout) available from the datasheet of the specific EEPROM. The compatible string for + these can list the specific EEPROM vendor and model along with the vendor EEPROM family as long as + the least-specific compatible entry is "atmel,at25". + + Example devicetree node describing a ST M95256 EEPROM on the spi0 bus: + + &spi0 { + status = "okay"; + + eeprom@1 { + compatible = "st,m95256", "st,m95xxx", "atmel,at25"; + reg = <0x1>; + size = ; + pagesize = <64>; + address-width = <16>; + spi-max-frequency = ; + timeout = <5>; + }; + }; compatible: "atmel,at25" diff --git a/dts/bindings/mtd/zephyr,i2c-target-eeprom.yaml b/dts/bindings/mtd/zephyr,i2c-target-eeprom.yaml index c6dcfbfec52bb..ff465b8cef4d6 100644 --- a/dts/bindings/mtd/zephyr,i2c-target-eeprom.yaml +++ b/dts/bindings/mtd/zephyr,i2c-target-eeprom.yaml @@ -5,3 +5,11 @@ description: Zephyr I2C target EEPROM compatible: "zephyr,i2c-target-eeprom" include: ["eeprom-base.yaml", i2c-device.yaml] + +properties: + address-width: + type: int + enum: [8, 16] + description: | + Number of address bits used to address the EEPROM. If not specified + the EEPROM is assumed to have a 8-bit address. diff --git a/dts/bindings/ospi/st,stm32-ospi.yaml b/dts/bindings/ospi/st,stm32-ospi.yaml index aaac4141455f0..b1666d67d91ec 100644 --- a/dts/bindings/ospi/st,stm32-ospi.yaml +++ b/dts/bindings/ospi/st,stm32-ospi.yaml @@ -119,3 +119,48 @@ properties: Note: You might need to enable the OCTOSPI I/O manager clock to use the property. Please refer to Reference Manual. The clock can be enabled in the devicetree. + + clk-port: + type: int + enum: + - 1 + - 2 + description: | + Specifies which port of the OCTOSPI IO Manager is used for the clk pin. + + If absent, then n is used where `n` is the OSPI + instance number. + + Note: You might need to enable the OCTOSPI I/O manager clock to use the + property. Please refer to Reference Manual. + The clock can be enabled in the devicetree. + + dqs-port: + type: int + enum: + - 1 + - 2 + description: | + Specifies which port of the OCTOSPI IO Manager is used for the dqs pin. + + If absent, then n is used where `n` is the OSPI + instance number. + + Note: You might need to enable the OCTOSPI I/O manager clock to use the + property. Please refer to Reference Manual. + The clock can be enabled in the devicetree. + + ncs-port: + type: int + enum: + - 1 + - 2 + description: | + Specifies which port of the OCTOSPI IO Manager is used for the ncs pin. + + If absent, then n is used where `n` is the OSPI + instance number. + + Note: You might need to enable the OCTOSPI I/O manager clock to use the + property. Please refer to Reference Manual. + The clock can be enabled in the devicetree. diff --git a/dts/bindings/pinctrl/adi,max32-pinctrl.yaml b/dts/bindings/pinctrl/adi,max32-pinctrl.yaml new file mode 100644 index 0000000000000..d40926ca772b9 --- /dev/null +++ b/dts/bindings/pinctrl/adi,max32-pinctrl.yaml @@ -0,0 +1,90 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + MAX32 Pin controller Node + Based on pincfg-node.yaml binding. + + Note: `bias-disable` are default pin configurations. + +compatible: "adi,max32-pinctrl" + +include: base.yaml + +properties: + reg: + required: true + + +child-binding: + description: | + Base binding configuration for ADI MAX32xxx MCUs + + include: + - name: pincfg-node.yaml + property-allowlist: + - bias-disable + - bias-pull-down + - bias-pull-up + - output-low + - output-high + - input-enable + - output-enable + - power-source + - drive-strength + + properties: + pinmux: + required: true + type: int + description: | + Integer array, represents gpio pin number and mux setting. + These defines are calculated as: (pin<<8 | port<<4 | function<<0) + With: + - port: The gpio port index (0, 1, ...) + - pin: The pin offset within the port (0, 1, 2, ...) + - function: The function number, can be: + * 0 : GPIO + * 1 : Alternate Function 1 + * 2 : Alternate Function 2 + * 3 : Alternate Function 3 + * 4 : Alternate Function 4 + In case selected pin function is GPIO, pin is statically configured as + a plain input/output GPIO. Default configuration is input. Output value + can be configured by adding 'ouptut-low' or 'output-high' properties + to the pin configuration. + + To simplify the usage, macro is available to generate "pinmux" field. + This macro is available here: + -include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h + Some examples of macro usage: + P0.9 set as alernate function 1 + { + pinmux = ; + }; + P0.9 set as alernate function 2 + { + pinmux = ; + }; + P0.9 set as GPIO output high + { + pinmux = ; + output-high; + }; + power-source: + enum: [0, 1] + description: | + GPIO Supply Voltage Select, Selects the voltage rail used for the pin. + 0 or MAX32_VSEL_VDDIO + 1 or MAX32_VSEL_VDDIOH + drive-strength: + default: 0 + enum: [0, 1, 2, 3] + description: | + There are 4 drive strength mode. + Mode 0: 1mA + Mode 1: 2mA + Mode 2: 4mA + Mode 3: 8mA + Default GPIO output drive strength is mode 0 for MAX32 MCUs. + For more information please take a look device user guide, datasheet. diff --git a/dts/bindings/pinctrl/cypress,psoc6-pinctrl.yaml b/dts/bindings/pinctrl/cypress,psoc6-pinctrl.yaml deleted file mode 100644 index 8914f873f81f2..0000000000000 --- a/dts/bindings/pinctrl/cypress,psoc6-pinctrl.yaml +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright (c) 2020, Linaro Limited -# Copyright (c) 2021, ATL Electronics -# SPDX-License-Identifier: Apache-2.0 - -description: | - Cypress PSoC-6 Pinctrl container node - - The Cypress PSoC-6 pins implements following pin configuration option: - - * bias-pull-up - * bias-pull-down - * drive-open-drain - * drive-open-source - * drive-push-pull (strong) - * input-enable (input-buffer) - - These options define devicetree flags that are converted to SoC flags at - CY_PSOC6_PIN_FLAGS(). - -compatible: "cypress,psoc6-pinctrl" - -include: base.yaml - -properties: - "#address-cells": - required: true - const: 1 - "#size-cells": - required: true - const: 1 - -child-binding: - description: cypress pins - - include: pincfg-node.yaml - - properties: - "cypress,pins": - type: phandle-array diff --git a/dts/bindings/pinctrl/ite,it8xxx2-pinctrl.yaml b/dts/bindings/pinctrl/ite,it8xxx2-pinctrl.yaml index 01a1c758a9c55..40c688a0b8b47 100644 --- a/dts/bindings/pinctrl/ite,it8xxx2-pinctrl.yaml +++ b/dts/bindings/pinctrl/ite,it8xxx2-pinctrl.yaml @@ -96,3 +96,16 @@ child-binding: enum: - "3v3" - "1v8" + + drive-strength: + type: string + description: | + We can configure this property to drive a high or low current selection. + If this property is not configured, it is the default setting. + According to the SPEC, the default drive current selection varies from + different pins. + Define the high level 0b: 8mA + low level 1b: 4mA or 2mA + enum: + - "high" + - "low" diff --git a/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml b/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml index 4474f9b089faf..3ff6200ee3919 100644 --- a/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml +++ b/dts/bindings/pinctrl/nuvoton,numaker-pinctrl.yaml @@ -83,3 +83,6 @@ child-binding: Set the speed of a pin. This setting effectively limits the slew rate of the output signal. Hardware default configuration is low. Fast slew rate could support fast speed pins, like as SPI CLK up to 50MHz. + digital-path-disable: + type: boolean + description: disable digital path on a pin. diff --git a/dts/bindings/power/st,stm32-pwr.yaml b/dts/bindings/power/st,stm32-pwr.yaml new file mode 100644 index 0000000000000..84b67104dac7d --- /dev/null +++ b/dts/bindings/power/st,stm32-pwr.yaml @@ -0,0 +1,67 @@ +# Copyright (c) 2023 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: STM32 power controller + +compatible: "st,stm32-pwr" + +include: base.yaml + +properties: + reg: + required: true + + wkup-pins-nb: + type: int + description: | + Max nbr of system wake-up pins. + For example wkup-pins-nb = <8>; on the stm32u5 + + wkup-pin-srcs: + type: int + description: | + Number of wake-up GPIO sources to select from for each wake-up pin. + If not specified, that means there is only 1 GPIO source for each + wake-up pin. + + For example, each wake-up pin on STM32U5 is associated with + 4 wake-up sources, 3 of them correspond to GPIOs. + + wkup-pins-pol: + type: boolean + description: | + True if SoC has a wake-up pins polarity config register + + wkup-pins-pupd: + type: boolean + description: | + True if SoC has pull-up/down config register(s) for GPIO ports + that are associated with wake-up pins. + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + +child-binding: + description: | + STM32 wake-up pin node. + + All nodes using this binding must be named "wkup-pin@[index]" + index starts from 1 + + properties: + reg: + type: array + required: true + description: Wake-up pin identifier, same as "index" in node name + + wkup-gpios: + type: phandle-array + description: | + Specifies the GPIOs, if any, that are associated with the wake-up pin. + + For example, for GPIO B2 associated with wakeup source 1 on wake-up + pin 1 on STM32U5 SoCs: + wkup-gpios = <&gpiob 2 STM32_PWR_WKUP_PIN_SRC_1>, <...>; diff --git a/dts/bindings/power/zephyr,power-state.yaml b/dts/bindings/power/zephyr,power-state.yaml index 5c645306b58a1..4fe22d1c5dba0 100644 --- a/dts/bindings/power/zephyr,power-state.yaml +++ b/dts/bindings/power/zephyr,power-state.yaml @@ -31,3 +31,9 @@ properties: type: int description: | Worst case latency in microseconds required to exit the idle state. + zephyr,pm-device-disabled: + type: boolean + description: | + Disable system managed device power management for this state. When set, + the power management subsystem will not suspend devices before entering + this state. diff --git a/dts/bindings/pwm/nxp,flexio-pwm.yaml b/dts/bindings/pwm/nxp,flexio-pwm.yaml new file mode 100644 index 0000000000000..44e33d5589c60 --- /dev/null +++ b/dts/bindings/pwm/nxp,flexio-pwm.yaml @@ -0,0 +1,47 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP Flexio PWM controller. + Each flexio timer can be used for generating one pwm pulse. + The two PWM modes supported by flexio are chosen based on the selected polarity - + Dual 8-bit counters PWM mode and Dual 8-bit counters PWM Low mode. + +compatible: "nxp,flexio-pwm" + +include: [pwm-controller.yaml, pinctrl-device.yaml, base.yaml] + +properties: + pinctrl-0: + required: true + + pinctrl-names: + required: true + + "#pwm-cells": + const: 3 + +pwm-cells: + - channel + - period + - flags + +child-binding: + description: | + Flexio PWM channel configuration. + + properties: + pin-id: + type: int + required: true + description: | + pin-id should be populated with number 'n' specified in the + FXIO_D data pin of your board's schematic. + + prescaler: + type: int + description: | + The clock divider for internal counter prescaler. + - 1: Divide by 1 + - 16: Divide by 16 + - 256: Divide by 256 + enum: [1, 16, 256] diff --git a/dts/bindings/pwm/nxp,qtmr-pwm.yaml b/dts/bindings/pwm/nxp,qtmr-pwm.yaml new file mode 100644 index 0000000000000..587c32e3c4a7d --- /dev/null +++ b/dts/bindings/pwm/nxp,qtmr-pwm.yaml @@ -0,0 +1,23 @@ +# Copyright (c) 2024, NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP QTMR PWM + +compatible: "nxp,qtmr-pwm" + +include: [pwm-controller.yaml, pinctrl-device.yaml, base.yaml] + +properties: + prescaler: + type: int + required: true + description: prescale factor from the qtmr clock. + enum: [1, 2, 4, 8, 16, 32, 64, 128] + + "#pwm-cells": + const: 3 + +pwm-cells: + - channel + - period + - flags diff --git a/dts/bindings/pwm/ti,cc13xx-cc26xx-timer-pwm.yaml b/dts/bindings/pwm/ti,cc13xx-cc26xx-timer-pwm.yaml index c63fc7ac1d78f..bc33465b1188e 100644 --- a/dts/bindings/pwm/ti,cc13xx-cc26xx-timer-pwm.yaml +++ b/dts/bindings/pwm/ti,cc13xx-cc26xx-timer-pwm.yaml @@ -69,4 +69,6 @@ properties: required: true pwm-cells: -- period + - channel + - period + - flags diff --git a/dts/bindings/qspi/st,stm32-qspi.yaml b/dts/bindings/qspi/st,stm32-qspi.yaml index 04aa6e4d02083..f656bd90586ef 100644 --- a/dts/bindings/qspi/st,stm32-qspi.yaml +++ b/dts/bindings/qspi/st,stm32-qspi.yaml @@ -59,12 +59,22 @@ properties: For example dma-names = "tx_rx"; + dual-flash: + type: boolean + description: | + configuration to enable the dual flash mode of the QSPI peripheral + where two external quad SPI Flash memories (FLASH 1 and FLASH 2) are used + in order to send/receive 8 bits (or 16 bits in DDR mode) every cycle, + effectively doubling the throughput as well as the capacity. + When true, the Flash ID number is useless. + flash-id: type: int description: | - FLash ID number. This number, if defined, helps to select the right - QSPI GPIO banks (defined as 'quadspi_bk[12]' in pinctrl property) + Flash ID number. This number, if defined, helps to select the right + QSPI GPIO banks (defined as 'quadspi_bk[1/2]' in pinctrl property) to communicate with flash memory. + Valid only if the is not set. For example flash-id = <2>; diff --git a/dts/bindings/regulator/adi,adp5360-regulator.yaml b/dts/bindings/regulator/adi,adp5360-regulator.yaml index e54a305e80f89..05d173826029b 100644 --- a/dts/bindings/regulator/adi,adp5360-regulator.yaml +++ b/dts/bindings/regulator/adi,adp5360-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Analog Devices ADP3560 PMIC diff --git a/dts/bindings/regulator/cirrus,cp9314.yaml b/dts/bindings/regulator/cirrus,cp9314.yaml index c5b3c973b44e6..9718c20b39145 100644 --- a/dts/bindings/regulator/cirrus,cp9314.yaml +++ b/dts/bindings/regulator/cirrus,cp9314.yaml @@ -1,5 +1,5 @@ # Copyright (c) 2024 Cirrus Logic, Inc. -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Cirrus CP9314 Buck Switched Cap DC/DC Converter diff --git a/dts/bindings/regulator/maxim,max20335-regulator.yaml b/dts/bindings/regulator/maxim,max20335-regulator.yaml index d23a1fdf1c1ef..90324568172c2 100644 --- a/dts/bindings/regulator/maxim,max20335-regulator.yaml +++ b/dts/bindings/regulator/maxim,max20335-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Grinn -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Maxim MAX20335 PMIC diff --git a/dts/bindings/regulator/nordic,npm1100.yaml b/dts/bindings/regulator/nordic,npm1100.yaml index b70523cfadd37..bf1a77a2ac83d 100644 --- a/dts/bindings/regulator/nordic,npm1100.yaml +++ b/dts/bindings/regulator/nordic,npm1100.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Nordic nPM1100 PMIC diff --git a/dts/bindings/regulator/nordic,npm1300-regulator.yaml b/dts/bindings/regulator/nordic,npm1300-regulator.yaml index e0fc28ff8be4e..cdb0999b23a96 100644 --- a/dts/bindings/regulator/nordic,npm1300-regulator.yaml +++ b/dts/bindings/regulator/nordic,npm1300-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Nordic nPM1300 PMIC diff --git a/dts/bindings/regulator/nordic,npm6001-regulator.yaml b/dts/bindings/regulator/nordic,npm6001-regulator.yaml index 378f6c0a8ecd1..731ebe828c3b4 100644 --- a/dts/bindings/regulator/nordic,npm6001-regulator.yaml +++ b/dts/bindings/regulator/nordic,npm6001-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2022 Nordic Semiconductor ASA -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Nordic nPM6001 PMIC diff --git a/dts/bindings/regulator/nxp,pca9420.yaml b/dts/bindings/regulator/nxp,pca9420.yaml index 2e4584d0a67dc..10e48a13348d0 100644 --- a/dts/bindings/regulator/nxp,pca9420.yaml +++ b/dts/bindings/regulator/nxp,pca9420.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2021 NXP -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | NXP PCA9420 PMIC diff --git a/dts/bindings/regulator/nxp,vref.yaml b/dts/bindings/regulator/nxp,vref.yaml index e3466ad29d5e0..8d5acb1f2bc25 100644 --- a/dts/bindings/regulator/nxp,vref.yaml +++ b/dts/bindings/regulator/nxp,vref.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 NXP +# Copyright 2023-2024 NXP # SPDX-License-Identifier: Apache-2.0 description: NXP VREF SOC peripheral @@ -20,12 +20,6 @@ properties: reg: required: true - nxp,ground-select: - type: string - enum: - - "VREFL3V" # 0 - - "VSSA" # 1 - nxp,buffer-startup-delay-us: type: int required: true diff --git a/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml b/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml index 2034ccd2c0fae..2dc1c7d0e891e 100644 --- a/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml +++ b/dts/bindings/regulator/raspberrypi,core-supply-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 TOKITA Hiroshi -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | RaspberryPi Pico core supply regurator diff --git a/dts/bindings/regulator/renesas,da1469x-regulator.yaml b/dts/bindings/regulator/renesas,da1469x-regulator.yaml index 2537b7e09d7da..d8a064a179f5d 100644 --- a/dts/bindings/regulator/renesas,da1469x-regulator.yaml +++ b/dts/bindings/regulator/renesas,da1469x-regulator.yaml @@ -1,5 +1,5 @@ # Copyright (c), 2023 Renesas Electronics Corporation -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | Renesas Smartbond(tm) LDO and DCDC regulators diff --git a/dts/bindings/regulator/x-powers,axp192-regulator.yaml b/dts/bindings/regulator/x-powers,axp192-regulator.yaml index 9072e80727b35..5fcbda2c8471e 100644 --- a/dts/bindings/regulator/x-powers,axp192-regulator.yaml +++ b/dts/bindings/regulator/x-powers,axp192-regulator.yaml @@ -1,6 +1,6 @@ # Copyright (c), 2021 NXP # Copyright (c), 2023 Martin Kiepfer -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 description: | AXP192 PMIC diff --git a/dts/bindings/reset/nxp,lpc-syscon-reset.yaml b/dts/bindings/reset/nxp,lpc-syscon-reset.yaml new file mode 100644 index 0000000000000..df4e01c2a2e63 --- /dev/null +++ b/dts/bindings/reset/nxp,lpc-syscon-reset.yaml @@ -0,0 +1,15 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: LPC SYSCON Peripheral reset controller + +compatible: "nxp,lpc-syscon-reset" + +include: [reset-controller.yaml] + +properties: + "#reset-cells": + const: 1 + +reset-cells: + - id diff --git a/dts/bindings/reset/nxp,rstctl.yaml b/dts/bindings/reset/nxp,rstctl.yaml new file mode 100644 index 0000000000000..04a1a48d043b6 --- /dev/null +++ b/dts/bindings/reset/nxp,rstctl.yaml @@ -0,0 +1,18 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP RSTCTL Peripheral reset controller + +compatible: "nxp,rstctl" + +include: [reset-controller.yaml, base.yaml] + +properties: + reg: + required: true + + "#reset-cells": + const: 1 + +reset-cells: + - id diff --git a/dts/bindings/reset/reset-controller.yaml b/dts/bindings/reset/reset-controller.yaml index eddf52c376ada..6a2cf5e10d3d6 100644 --- a/dts/bindings/reset/reset-controller.yaml +++ b/dts/bindings/reset/reset-controller.yaml @@ -7,4 +7,6 @@ properties: "#reset-cells": type: int required: true - description: Number of cells in reset property + description: | + Number of cells in reset property. There must be a cell + named "id" to use the reset_dt_spec macros. diff --git a/dts/bindings/riscv/litex,soc-controller.yaml b/dts/bindings/riscv/litex,soc-controller.yaml new file mode 100644 index 0000000000000..3b78aae8df15d --- /dev/null +++ b/dts/bindings/riscv/litex,soc-controller.yaml @@ -0,0 +1,12 @@ +# Copyright 2024 Vogl Electronic GmbH +# SPDX-License-Identifier: Apache-2.0 + +description: LiteX SoC Controller driver + +compatible: "litex,soc-controller" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/rtc/microcrystal,rv3028.yaml b/dts/bindings/rtc/microcrystal,rv3028.yaml new file mode 100644 index 0000000000000..6ca549c860e1c --- /dev/null +++ b/dts/bindings/rtc/microcrystal,rv3028.yaml @@ -0,0 +1,54 @@ +# Copyright (c) 2024 ANITRA system s.r.o. +# SPDX-License-Identifier: Apache-2.0 + +description: Micro Crystal RV3028 RTC + +compatible: "microcrystal,rv3028" + +include: + - name: rtc-device.yaml + - name: i2c-device.yaml + +properties: + clkout-frequency: + type: int + enum: + - 32768 + - 8192 + - 1024 + - 64 + - 32 + - 1 + description: | + Frequency of the CLKOUT signal in Hertz (Hz). If omitted, the CLKOUT pin is LOW. + + backup-switch-mode: + type: string + required: true + enum: + - disabled + - direct + - level + description: | + Automatic backup switchover function selection: + - disabled: The switchover function is disabled - only one power supply available (VDD) + - direct: Direct Switching Mode (DSM): when VDD < VBACKUP, switchover occurs from VDD to + VBACKUP without requiring VDD to drop below VTH:LSM (2.0 V) + - level: Level Switching Mode (LSM): when VDD < VTH:LSM (2.0 V) AND VBACKUP > VTH:LSM, + switchover occurs from VDD to VBACKUP + + trickle-resistor-ohms: + type: int + enum: + - 3000 + - 5000 + - 9000 + - 15000 + description: | + Enable the trickle charger with provided current-limiting resistance in ohms. The trickle + charger allows a battery or supercapacitor connected to VBACKUP to be charged. + + int-gpios: + type: phandle-array + description: | + GPIO connected to the RV3028 INT interrupt output. This signal is open-drain, active low. diff --git a/dts/bindings/rtc/nxp,kinetis-lptmr.yaml b/dts/bindings/rtc/nxp,kinetis-lptmr.yaml deleted file mode 100644 index f16451fc0a35a..0000000000000 --- a/dts/bindings/rtc/nxp,kinetis-lptmr.yaml +++ /dev/null @@ -1,31 +0,0 @@ -# Copyright (c) 2020 Vestas Wind Systems A/S -# SPDX-License-Identifier: Apache-2.0 - -description: Kinetis LPTMR - -compatible: "nxp,kinetis-lptmr" - -include: rtc.yaml - -properties: - reg: - required: true - - clock-frequency: - required: true - - prescaler: - required: true - - clk-source: - type: int - required: true - description: Prescaler clock source (0 to 3) - - input-pin: - type: int - description: Pulse counter input pin (0 to 3). - - active-low: - type: boolean - description: Pulse counter input pin is active-low diff --git a/dts/bindings/rtc/st,stm32-rtc.yaml b/dts/bindings/rtc/st,stm32-rtc.yaml index dcfd2a49276b1..d368410b6ee6e 100644 --- a/dts/bindings/rtc/st,stm32-rtc.yaml +++ b/dts/bindings/rtc/st,stm32-rtc.yaml @@ -1,11 +1,14 @@ # Copyright (c) 2018, Workaround GmbH +# Copyright (c) 2024 STMicroelectronics # SPDX-License-Identifier: Apache-2.0 description: STM32 RTC compatible: "st,stm32-rtc" -include: rtc.yaml +include: + - rtc.yaml + - rtc-device.yaml properties: reg: @@ -18,3 +21,19 @@ properties: enum: - 1 - 512 + + alarms-count: + description: | + Number of alarms supported by STM32 RTC device. + Most of STM32 MCU series have 2 RTC alarms, A & B. + Defaults to 0 when not declared in devicetree. + + alrm-exti-line: + type: int + description: | + Number of the Extended Interrupts and Event Controller (EXTI) interrupt + line connected to the RTC Alarm event. + Not required, since RTC Alarm interrupt could be routed directly to Nested + Vectored Interrupt Controller (NVIC) and to Power Control (PWR) wake-up + pins on some series. + Valid range: 0 - 31 diff --git a/dts/bindings/sensor/festo,veaa-x-3.yaml b/dts/bindings/sensor/festo,veaa-x-3.yaml new file mode 100644 index 0000000000000..38529ab240d29 --- /dev/null +++ b/dts/bindings/sensor/festo,veaa-x-3.yaml @@ -0,0 +1,40 @@ +# Copyright (c) 2024 Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +description: | + Festo VEAA proportional pressure regulator using 3/3-way valve. + Only voltage controlled valve is supported. + +compatible: "festo,veaa-x-3" + +include: sensor-device.yaml + +properties: + io-channels: + type: phandle-array + required: true + description: | + ADC used to get the actual value: + <&adc_node channel> + dac: + type: phandle + required: true + description: | + DAC used to set the setpoint value: + <&dac_node channel resolution buffered> + dac-channel-id: + type: int + required: true + dac-resolution: + type: int + required: true + pressure-range-type: + type: string + enum: ["D2", "D9", "D11"] + required: true + description: | + The device pressure range type. + | Type | Range [kPa] | + | D11 | 5-1000 | + | D9 | 3-600 | + | D2 | 1-200 | diff --git a/dts/bindings/sensor/ist,tsic-xx6.yaml b/dts/bindings/sensor/ist,tsic-xx6.yaml new file mode 100644 index 0000000000000..d6ee88b8079b7 --- /dev/null +++ b/dts/bindings/sensor/ist,tsic-xx6.yaml @@ -0,0 +1,40 @@ +# Copyright (c) 2024, Vitrolife A/S +# SPDX-License-Identifier: Apache-2.0 + +description: | + TSic xx6 temperature sensor. + https://www.ist-ag.com/sites/default/files/downloads/ATTSic_E.pdf + + Example: + tsic_716: tsic_716 { + status = "okay"; + compatible = "ist,tsic-xx6"; + pwms = <&pwm2 1 PWM_USEC(5) PWM_POLARITY_NORMAL>; + data-bits = <14>; + lower-temperature-limit = <(-10)>; + higher-temperature-limit = <60>; + }; + +compatible: "ist,tsic-xx6" + +properties: + pwms: + required: true + type: phandle-array + description: Reference to a PWM instance with PWM capture support. + + lower-temperature-limit: + required: true + type: int + description: Lowest temperature supported by the device in celcius degrees. + + higher-temperature-limit: + required: true + type: int + description: Highest temperature supported by the device in celcius degrees. + + data-bits: + required: true + type: int + description: Data bits per reading. + enum: [11, 14] diff --git a/dts/bindings/sensor/maxim,ds18s20.yaml b/dts/bindings/sensor/maxim,ds18s20.yaml new file mode 100644 index 0000000000000..1e42cd80a9d05 --- /dev/null +++ b/dts/bindings/sensor/maxim,ds18s20.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024, Fredrik Gihl +# SPDX-License-Identifier: Apache-2.0 + +description: Maxim 1-Wire ds18s20 temperature sensor + +compatible: "maxim,ds18s20" + +include: [sensor-device.yaml, w1-slave.yaml] diff --git a/dts/bindings/sensor/national,lm95234.yaml b/dts/bindings/sensor/national,lm95234.yaml new file mode 100644 index 0000000000000..a13577aca8f06 --- /dev/null +++ b/dts/bindings/sensor/national,lm95234.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Calian Advanced Technologies +# SPDX-License-Identifier: Apache-2.0 + +description: LM95234 Quad Remote Diode and Local Temperature Sensor with SMBus Interface + +compatible: "national,lm95234" + +include: [sensor-device.yaml, i2c-device.yaml] diff --git a/dts/bindings/sensor/nordic,nrf-temp-nrfs.yaml b/dts/bindings/sensor/nordic,nrf-temp-nrfs.yaml new file mode 100644 index 0000000000000..2a77552b3bfef --- /dev/null +++ b/dts/bindings/sensor/nordic,nrf-temp-nrfs.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + Nordic nRF family temperature sensor accessed via nRF Services (nrfs) + +compatible: "nordic,nrf-temp-nrfs" + +include: base.yaml diff --git a/dts/bindings/sensor/nxp,lpcmp.yaml b/dts/bindings/sensor/nxp,lpcmp.yaml new file mode 100644 index 0000000000000..8412159563263 --- /dev/null +++ b/dts/bindings/sensor/nxp,lpcmp.yaml @@ -0,0 +1,73 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: NXP low-power analog comparator (LPCMP) + +compatible: "nxp,lpcmp" + +include: [sensor-device.yaml, pinctrl-device.yaml] + +properties: + interrupts: + required: true + + reg: + required: true + + enable-output-pin: + type: boolean + description: | + Decide whether to enable the comparator is available in selected pin. + + use-unfiltered-output: + type: boolean + description: | + Decide whether to use the unfiltered output. + + enable-output-invert: + type: boolean + description: | + Decide whether to invert the comparator output. + + hysteresis-level: + type: int + enum: + - 0 + - 1 + - 2 + - 3 + default: 0 + description: | + LPCMP hysteresis mode. + The default corresponds to the reset value of the register field. + + power-level: + type: string + enum: + - "low" + - "high" + - "nano" + default: "low" + description: | + LPCMP power mode. + The default corresponds to the reset value of the register field. + + function-clock: + type: string + enum: + - "Reserved" + - "FRO_16K" + - "XTAL32K" + - "CMP_CLOCK" + default: "Reserved" + description: | + LPCMP function clock. + The default corresponds to the reset value of the register field. + + "#io-channel-cells": + type: int + const: 2 + +io-channel-cells: + - positive + - negative diff --git a/dts/bindings/sensor/sensirion,shtcx.yaml b/dts/bindings/sensor/sensirion,shtcx.yaml index e0d90c6a929a7..d4a2cfcc2d302 100644 --- a/dts/bindings/sensor/sensirion,shtcx.yaml +++ b/dts/bindings/sensor/sensirion,shtcx.yaml @@ -1,24 +1,30 @@ # Copyright (c) 2021, Thomas Stranger # SPDX-License-Identifier: Apache-2.0 -description: Sensirion SHTCx humidity and temperature sensor +description: | + Sensirion SHTCx humidity and temperature sensor + + Additionally use "sensirion,shtc1" or "sensirion,shtc3" compatibles + such that a generic driver can consider chip specific behaviour. + + Example device tree node describing a Sensirion SHTC3 Sensor on the i2c0 bus: + + &i2c0 { + status = "okay"; + clock-frequency = ; + shtc3@70 { + compatible = "sensirion,shtc3", "sensirion,shtcx"; + reg = <0x70>; + measure-mode = "normal"; + clock-stretching; + }; + }; compatible: "sensirion,shtcx" include: [sensor-device.yaml, i2c-device.yaml] properties: - chip: - type: string - required: true - description: | - Specifies which chip exactly is used. This is necessary to get exact - timing information and supported command set. - SHTC3 has an additional sleep mode that is entered between measurements. - enum: - - "shtc1" - - "shtc3" - measure-mode: type: string required: true diff --git a/dts/bindings/sensor/st,lis2dh-common.yaml b/dts/bindings/sensor/st,lis2dh-common.yaml index 1988a7c1deb5e..e4c41f586d513 100644 --- a/dts/bindings/sensor/st,lis2dh-common.yaml +++ b/dts/bindings/sensor/st,lis2dh-common.yaml @@ -34,7 +34,7 @@ properties: The default of 0 is the most common situation to avoid multiple interrupts to be triggered by same event. - - 0 # LIS2DH_DT_GPIO_INT_EDGE + - 0 # LIS2DH_DT_GPIO_INT_EDGE_BOTH - 1 # LIS2DH_DT_GPIO_INT_EDGE_RISING - 2 # LIS2DH_DT_GPIO_INT_EDGE_FALLING - 3 # LIS2DH_DT_GPIO_INT_LEVEL_HIGH @@ -51,7 +51,7 @@ properties: The default of 0 is the most common situation to avoid multiple interrupts to be triggered by same event. - - 0 # LIS2DH_DT_GPIO_INT_EDGE + - 0 # LIS2DH_DT_GPIO_INT_EDGE_BOTH - 1 # LIS2DH_DT_GPIO_INT_EDGE_RISING - 2 # LIS2DH_DT_GPIO_INT_EDGE_FALLING - 3 # LIS2DH_DT_GPIO_INT_LEVEL_HIGH diff --git a/dts/bindings/sensor/st,stm32-digi-temp.yaml b/dts/bindings/sensor/st,stm32-digi-temp.yaml new file mode 100644 index 0000000000000..4faba85246dd2 --- /dev/null +++ b/dts/bindings/sensor/st,stm32-digi-temp.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024, Aurelien Jarno +# SPDX-License-Identifier: Apache-2.0 + +description: STM32 family Digital Temperature Sensor node + +compatible: "st,stm32-digi-temp" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true + + clocks: + required: true diff --git a/dts/bindings/sensor/ti,ina226.yaml b/dts/bindings/sensor/ti,ina226.yaml new file mode 100644 index 0000000000000..0752e2902d573 --- /dev/null +++ b/dts/bindings/sensor/ti,ina226.yaml @@ -0,0 +1,73 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + TI INA226 Bidirectional Current and Power Monitor. + The file should be included in the + DeviceTree as it provides macros that can be used for initializing the + configuration registers. + +compatible: "ti,ina226" + +include: [sensor-device.yaml, i2c-device.yaml] + +properties: + avg-count: + type: int + description: | + Number of samples to average (applies to all inputs). + Default is the power-on reset value. + default: 1 + enum: [1, 4, 16, 64, 128, 256, 512, 1024] + + vbus-conversion-time-us: + type: int + description: | + Vbus conversion time in microseconds. + Default is the power-on reset value. + default: 1100 + enum: [140, 204, 332, 588, 1100, 2116, 4156, 8244] + + vshunt-conversion-time-us: + type: int + description: | + Vshunt conversion time in microseconds. + Default is the power-on reset value. + default: 1100 + enum: [140, 204, 332, 588, 1100, 2116, 4156, 8244] + + operating-mode: + type: string + description: | + Selects mode of operation. + Default is the power-on reset value. + default: "Shunt and Bus, Continuous" + enum: + - "Power-Down (or Shutdown)" + - "Shunt Voltage, Triggered" + - "Bus Voltage, Triggered" + - "Shunt and Bus, Triggered" + - "Power-Down (or Shutdown)" + - "Shunt Voltage, Continuous" + - "Bus Voltage, Continuous" + - "Shunt and Bus, Continuous" + + current-lsb-microamps: + type: int + required: true + description: | + Current LSB value in microAmpere. + This value gives the measurement resolution for current measurement. + Formula: current-lsb [μA] = maximum expected current [μA] / 2^15 + Higher resolution means lower range of current measurement, vice versa. + + For example, if maximum expected current is 15 [A]: + then, current-lsb [μA] = 15000000 [μA] / 2^15 ~= 457.763 [μA]. + + Note: rounded values may be used for convenience, e.g. 500uA/LSB. + + rshunt-micro-ohms: + type: int + required: true + description: | + Shunt resistor value in micro-ohms. diff --git a/dts/bindings/sensor/vishay,vcnl36825t.yaml b/dts/bindings/sensor/vishay,vcnl36825t.yaml index b1188b3d77e15..03ea6f4510c1d 100644 --- a/dts/bindings/sensor/vishay,vcnl36825t.yaml +++ b/dts/bindings/sensor/vishay,vcnl36825t.yaml @@ -21,6 +21,8 @@ properties: Defaults to sensor reset value. + Note: "force"-mode only available if low-power mode inactive. + measurement-period: type: int default: 40 diff --git a/dts/bindings/serial/adi,max32-uart.yaml b/dts/bindings/serial/adi,max32-uart.yaml new file mode 100644 index 0000000000000..c79543cf6b88e --- /dev/null +++ b/dts/bindings/serial/adi,max32-uart.yaml @@ -0,0 +1,36 @@ +# Copyright (c) 2023-2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: MAX32 UART + +include: [uart-controller.yaml, pinctrl-device.yaml] + +compatible: "adi,max32-uart" + +properties: + reg: + required: true + + clocks: + required: true + + interrupts: + required: true + + pinctrl: + type: phandles + + clock-source: + type: int + enum: [0, 1, 2, 3, 4, 5] + description: | + Clock source to be used by the UART peripheral. The following options + are available: + - 0: "ADI_MAX32_PRPH_CLK_SRC_PCLK" Peripheral clock + - 1: "ADI_MAX32_PRPH_CLK_SRC_EXTCLK" External Clock + - 2: "ADI_MAX32_PRPH_CLK_SRC_IBRO" Internal Baud Rate Oscillator + - 3: "ADI_MAX32_PRPH_CLK_SRC_ERFO" External Radio Frequency Oscillator + - 4: "ADI_MAX32_PRPH_CLK_SRC_ERTCO" External Real-Time Clock Oscillator + - 5: "ADI_MAX32_PRPH_CLK_SRC_INRO" Internal Ring Oscillator + The target device might not support all option please take a look on + target device user guide diff --git a/dts/bindings/serial/cypress,psoc6-uart.yaml b/dts/bindings/serial/cypress,psoc6-uart.yaml index 543975ab7c8c2..6cf83bce61790 100644 --- a/dts/bindings/serial/cypress,psoc6-uart.yaml +++ b/dts/bindings/serial/cypress,psoc6-uart.yaml @@ -6,7 +6,7 @@ description: Cypress SCB[UART] compatible: "cypress,psoc6-uart" -include: uart-controller.yaml +include: [uart-controller.yaml, pinctrl-device.yaml] properties: reg: diff --git a/dts/bindings/serial/espressif,esp32-uart.yaml b/dts/bindings/serial/espressif,esp32-uart.yaml index 313d9039a5b54..49026309f34d3 100644 --- a/dts/bindings/serial/espressif,esp32-uart.yaml +++ b/dts/bindings/serial/espressif,esp32-uart.yaml @@ -2,7 +2,7 @@ description: ESP32 UART compatible: "espressif,esp32-uart" -include: [uart-controller.yaml, pinctrl-device.yaml] +include: [uart-controller.yaml, uart-controller-pin-inversion.yaml, pinctrl-device.yaml] properties: reg: diff --git a/dts/bindings/serial/nordic,nrf-uart-common.yaml b/dts/bindings/serial/nordic,nrf-uart-common.yaml index fa68a195cd687..b985b7bc96309 100644 --- a/dts/bindings/serial/nordic,nrf-uart-common.yaml +++ b/dts/bindings/serial/nordic,nrf-uart-common.yaml @@ -17,6 +17,7 @@ properties: if CONFIG_PINCTRL is enabled). current-speed: + required: true description: | Initial baud rate setting for UART. Only a fixed set of baud rates are selectable on these devices. diff --git a/dts/bindings/serial/nxp,kinetis-lpuart.yaml b/dts/bindings/serial/nxp,kinetis-lpuart.yaml index 1b8f540072253..b17723ff5ade4 100644 --- a/dts/bindings/serial/nxp,kinetis-lpuart.yaml +++ b/dts/bindings/serial/nxp,kinetis-lpuart.yaml @@ -2,7 +2,7 @@ description: Kinetis LPUART compatible: "nxp,kinetis-lpuart" -include: [uart-controller.yaml, pinctrl-device.yaml] +include: [uart-controller.yaml, uart-controller-pin-inversion.yaml, pinctrl-device.yaml] properties: reg: @@ -15,6 +15,14 @@ properties: disconnected, and transmitter output is internally connected to the receiver input. + single-wire: + type: boolean + description: | + Enable the single wire half-duplex communication. + Using this mode, TX and RX lines are internally connected and + only TX pin is used afterwards and should be configured. + RX/TX conflicts must be handled on user side. + nxp,rs485-mode: type: boolean description: | diff --git a/dts/bindings/serial/renesas,smartbond-uart.yaml b/dts/bindings/serial/renesas,smartbond-uart.yaml index 4b2a2b973c2d9..428eb0ca76e3d 100644 --- a/dts/bindings/serial/renesas,smartbond-uart.yaml +++ b/dts/bindings/serial/renesas,smartbond-uart.yaml @@ -38,3 +38,24 @@ properties: hw-flow-control-supported: type: boolean description: Set to indicate RTS/CTS flow control is supported. + + rx-wake-gpios: + type: phandle-array + description: GPIO configured as wake source + + rx-wake-timeout: + type: int + description: | + Time to prevent UART entering sleep mode after receiving data (ms) + + dtr-gpios: + type: phandle-array + description: | + DTR pin specification. DTR pin when active tells that the driver that there + is active client on the other side of serial line. + The device driver does not use DTR for hardware flow control. + When device is connected to computer serial converter usually asserts DTR + line when serial port is opened and ready for communication. + This line can be used in Smartbond(tm) driver to detect remote client presence. + If client is not present the device can disable UART, allowing for + power system management to enter more efficient power levels. diff --git a/dts/bindings/serial/st,stm32-uart-base.yaml b/dts/bindings/serial/st,stm32-uart-base.yaml index f84b4def05718..37b6e66762bd6 100644 --- a/dts/bindings/serial/st,stm32-uart-base.yaml +++ b/dts/bindings/serial/st,stm32-uart-base.yaml @@ -10,6 +10,7 @@ include: - clock-frequency - name: pinctrl-device.yaml - name: reset-device.yaml + - name: uart-controller-pin-inversion.yaml properties: reg: @@ -37,18 +38,6 @@ properties: description: Swap the TX and RX pins. Used in case of a cross wired connection. - tx-invert: - type: boolean - description: | - Invert the binary logic of tx pin. When enabled, physical logic levels are inverted and - we use 1=Low, 0=High instead of 1=High, 0=Low. - - rx-invert: - type: boolean - description: | - Invert the binary logic of rx pin. When enabled, physical logic levels are inverted and - we use 1=Low, 0=High instead of 1=High, 0=Low. - pinctrl-0: required: true diff --git a/dts/bindings/serial/uart-controller-pin-inversion.yaml b/dts/bindings/serial/uart-controller-pin-inversion.yaml new file mode 100644 index 0000000000000..706109417e5cc --- /dev/null +++ b/dts/bindings/serial/uart-controller-pin-inversion.yaml @@ -0,0 +1,16 @@ +# Copyright (c) 2024 Croxel, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: Pin Inversion fields for UART controllers + +properties: + tx-invert: + type: boolean + description: | + Invert the binary logic of tx pin. When enabled, physical logic levels are inverted and + we use 1=Low, 0=High instead of 1=High, 0=Low. + rx-invert: + type: boolean + description: | + Invert the binary logic of rx pin. When enabled, physical logic levels are inverted and + we use 1=Low, 0=High instead of 1=High, 0=Low. diff --git a/dts/bindings/spi/adi,max32-spi.yaml b/dts/bindings/spi/adi,max32-spi.yaml new file mode 100644 index 0000000000000..12bc88b105a1e --- /dev/null +++ b/dts/bindings/spi/adi,max32-spi.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: ADI MAX32 SPI + +include: + - name: spi-controller.yaml + - name: pinctrl-device.yaml + +compatible: "adi,max32-spi" + +properties: + reg: + required: true + + interrupts: + required: true + + pinctrl-0: + type: phandles + required: true diff --git a/dts/bindings/spi/ambiq,spi-bleif.yaml b/dts/bindings/spi/ambiq,spi-bleif.yaml new file mode 100644 index 0000000000000..2be2ee1b9f8a2 --- /dev/null +++ b/dts/bindings/spi/ambiq,spi-bleif.yaml @@ -0,0 +1,18 @@ +# Copyright (c) 2024 Ambiq Micro Inc. +# SPDX-License-Identifier: Apache-2.0 + +description: | + This binding gives a representation of SPI controller in some Ambiq + Apollox Blue SOC (e.g. Apollo3 Blue) which uses BLEIF module for SPI + transceiver. + +compatible: "ambiq,spi-bleif" + +include: [spi-controller.yaml, pinctrl-device.yaml, ambiq-pwrcfg.yaml] + +properties: + reg: + required: true + + ambiq,pwrcfg: + required: true diff --git a/dts/bindings/spi/cypress,psoc6-spi.yaml b/dts/bindings/spi/cypress,psoc6-spi.yaml index 81a12f44ec5db..bebdc53d314b1 100644 --- a/dts/bindings/spi/cypress,psoc6-spi.yaml +++ b/dts/bindings/spi/cypress,psoc6-spi.yaml @@ -5,7 +5,7 @@ description: Cypress SBC[SPI] compatible: "cypress,psoc6-spi" -include: spi-controller.yaml +include: [spi-controller.yaml, pinctrl-device.yaml] properties: reg: diff --git a/dts/bindings/test/vnd,memory-attr.yaml b/dts/bindings/test/vnd,memory-attr.yaml index 0303d255c5472..8696279859db1 100644 --- a/dts/bindings/test/vnd,memory-attr.yaml +++ b/dts/bindings/test/vnd,memory-attr.yaml @@ -5,4 +5,4 @@ description: Test memory and memory attributes compatible: "vnd,memory-attr" -include: [base.yaml, "zephyr,memory-attr.yaml"] +include: [base.yaml, "zephyr,memory-common.yaml"] diff --git a/dts/bindings/timer/nordic,nrf-timer.yaml b/dts/bindings/timer/nordic,nrf-timer.yaml index 8a961f34f8834..9f8395003a85c 100644 --- a/dts/bindings/timer/nordic,nrf-timer.yaml +++ b/dts/bindings/timer/nordic,nrf-timer.yaml @@ -24,10 +24,20 @@ properties: interrupts: required: true + max-frequency: + type: int + default: 16000000 + description: | + Maximum timer frequency in Hz. + + The default value is 16MHz which was the maximum frequency for all nRF TIMER peripherals + up to the nRF54 series, and still remains the most typical maximum frequency for nRF54 + TIMERs. + prescaler: type: int required: true - description: Prescaler value determines frequency (base_frequency/2^prescaler) + description: Prescaler value determines frequency (max-frequency/2^prescaler) zli: type: boolean diff --git a/dts/bindings/timer/ti,am654-dmtimer.yaml b/dts/bindings/timer/ti,am654-dmtimer.yaml new file mode 100644 index 0000000000000..f2fc8167aba51 --- /dev/null +++ b/dts/bindings/timer/ti,am654-dmtimer.yaml @@ -0,0 +1,16 @@ +# Copyright (C) 2023 BeagleBoard.org Foundation +# Copyright (C) 2023 S Prashanth +# SPDX-License-Identifier: Apache-2.0 + +description: TI Dual-Mode Timer + +compatible: "ti,am654-timer" + +include: base.yaml + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/dts/bindings/usb/nxp,ehci.yaml b/dts/bindings/usb/nxp,ehci.yaml index cf72a69545c9f..8f1569e2060e7 100644 --- a/dts/bindings/usb/nxp,ehci.yaml +++ b/dts/bindings/usb/nxp,ehci.yaml @@ -6,3 +6,7 @@ description: NXP EHCI USB device mode compatible: nxp,ehci include: "nxp,mcux-usbd.yaml" + +properties: + phy_handle: + type: phandle diff --git a/dts/bindings/usb/nxp,lpcip3511.yaml b/dts/bindings/usb/nxp,lpcip3511.yaml index 70ea118883722..3c799e493907d 100644 --- a/dts/bindings/usb/nxp,lpcip3511.yaml +++ b/dts/bindings/usb/nxp,lpcip3511.yaml @@ -6,3 +6,7 @@ description: NXP LPCIP3511 USB device mode compatible: nxp,lpcip3511 include: "nxp,mcux-usbd.yaml" + +properties: + phy_handle: + type: phandle diff --git a/dts/bindings/usb/nxp,usbphy.yaml b/dts/bindings/usb/nxp,usbphy.yaml new file mode 100644 index 0000000000000..0b1f143dde245 --- /dev/null +++ b/dts/bindings/usb/nxp,usbphy.yaml @@ -0,0 +1,33 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: | + NXP USB high speed phy that is used on NXP RTxxxx, RTxxx, MCX, LPC and Kinetis + platforms if high speed usb is supported on these platforms. + Note: Only some LPC plafforms use it (like: LPC55S69, LPC55S28 and LPC55S16 etc). + +compatible: "nxp,usbphy" + +include: base.yaml + +properties: + tx-d-cal: + type: int + required: true + description: | + It is board level's value that is used to trim the nominal 17.78mA + current source for the High Speed TX drivers on USB_DP and USB_DM. + + tx-cal-45-dp-ohms: + type: int + required: true + description: | + It is board level's value that is used to trim the nominal 17.78mA + current source for the High Speed TX drivers on USB_DP and USB_DM. + + tx-cal-45-dm-ohms: + type: int + required: true + description: | + It is board level's value that is used to trim the nominal 17.78mA + current source for the High Speed TX drivers on USB_DP and USB_DM. diff --git a/dts/bindings/usb/snps,dwc2.yaml b/dts/bindings/usb/snps,dwc2.yaml index 8af55448780f8..d5b0167f26b32 100644 --- a/dts/bindings/usb/snps,dwc2.yaml +++ b/dts/bindings/usb/snps,dwc2.yaml @@ -18,3 +18,36 @@ properties: phys: type: phandle + + num-in-eps: + type: int + required: true + description: | + Number of configured OUT endpoints including control endpoint. + + num-out-eps: + type: int + required: true + description: | + Number of configured IN endpoints including control endpoint. + + ghwcfg1: + type: int + required: true + description: | + Value of the GHWCFG1 register. It is used to determine available endpoint + types during driver pre-initialization. + + ghwcfg2: + type: int + required: true + description: | + Value of the GHWCFG2 register. It is used to determine available endpoint + types during driver pre-initialization. + + ghwcfg4: + type: int + required: true + description: | + Value of the GHWCFG4 register. It is used to determine available endpoint + types during driver pre-initialization. diff --git a/dts/bindings/usb/zephyr,hid-device.yaml b/dts/bindings/usb/zephyr,hid-device.yaml new file mode 100644 index 0000000000000..2d20b450986b6 --- /dev/null +++ b/dts/bindings/usb/zephyr,hid-device.yaml @@ -0,0 +1,58 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: Bindings for HID device + +compatible: "zephyr,hid-device" + +include: base.yaml + +properties: + interface-name: + type: string + description: | + HID device name. When this property is present, a USB device will use it + as the string descriptor of the interface. + + protocol-code: + type: string + description: | + This property corresponds to the protocol codes defined in Chapter 4.3 + of the HID specification. Only boot devices are required to set one of + the protocols, keyboard or mouse. For non-boot devices, this property is + not required or can be set to none. + - none: Device does not support the boot interface + - keyboard: Device supports boot interface and keyboard protocol + - mouse: Device supports boot interface and mouse protocol + enum: + - none + - keyboard + - mouse + + in-report-size: + type: int + required: true + description: | + The size of the longest input report that the HID device can generate. + This property is used to determine the buffer length used for transfers. + + in-polling-period-us: + type: int + required: true + description: | + Input or output type reports polling period in microseconds. For USB full + speed this could be clamped to 1ms or 255ms depending on the value. + + out-report-size: + type: int + description: | + The size of the longest output report that the HID device can generate. + When this property is present, a USB device will use out pipe for output + reports, otherwise control pipe will be used for output reports. + + out-polling-period-us: + type: int + description: | + Output type reports polling period in microseconds. For USB full + speed this could be clamped to 1ms or 255ms depending on the value. + This option is only effective if the out-report-size property is defined. diff --git a/dts/bindings/vendor-prefixes.txt b/dts/bindings/vendor-prefixes.txt index 21920433fc7f1..f6152d693646c 100644 --- a/dts/bindings/vendor-prefixes.txt +++ b/dts/bindings/vendor-prefixes.txt @@ -111,6 +111,7 @@ broadmobi Shanghai Broadmobi Communication Technology Co.,Ltd. bticino Bticino International buffalo Buffalo, Inc. bur B&R Industrial Automation GmbH +bytesatwork bytesatwork AG calaosystems CALAO Systems SAS calxeda Calxeda canaan Canaan, Inc. @@ -224,6 +225,7 @@ evervision Evervision Electronics Co. Ltd. exar Exar Corporation excito Excito ezchip EZchip Semiconductor +ezurio Ezurio facebook Facebook (deprecated, use meta) fairphone Fairphone B.V. fanke FANKE Technology Co., Ltd. @@ -232,6 +234,7 @@ fastrax Fastrax Oy fcs Fairchild Semiconductor feixin Shenzhen Feixin Photoelectic Co., Ltd feiyang Shenzhen Fly Young Technology Co.,LTD. +festo Festo SE & Co. KG fii Foxconn Industrial Internet fintek Feature Integration Technology Inc. firefly Firefly @@ -242,6 +245,7 @@ friendlyarm Guangzhou FriendlyARM Computer Tech Co., Ltd fsl Freescale Semiconductor ftdi Future Technology Devices International Ltd. fujitsu Fujitsu Ltd. +futaba Futaba Corporation gaisler Gaisler galaxycore Galaxycore, Inc. gardena GARDENA GmbH @@ -321,6 +325,7 @@ isee ISEE 2007 S.L. isentek Isentek Inc. isil Intersil issi Integrated Silicon Solutions Inc. +ist Innovative Sensor Technology IST AG ite ITE Tech. Inc. itead ITEAD Intelligent Systems Co.Ltd ivo InfoVision Optoelectronics Kunshan Co. Ltd. @@ -351,7 +356,6 @@ kvg Kverneland Group kyo Kyocera Corporation lacie LaCie laird Laird PLC -lairdconnect Laird Connectivity lamobo Ketai Huajie Technology Co., Ltd. lantiq Lantiq Semiconductor lattice Lattice Semiconductor @@ -364,6 +368,7 @@ lg LG Corporation lgphilips LG Display libretech Shenzhen Libre Technology Co., Ltd licheepi Lichee Pi +lilygo Lilygo Shenzhen Xinyuan Electronic Technology Co., Ltd linaro Linaro Limited linksprite LinkSprite Technologies, Inc. linksys Belkin International, Inc. (Linksys) @@ -497,7 +502,7 @@ pda Precision Design Associates, Inc. pericom Pericom Technology Inc. pervasive Pervasive Displays, Inc. phicomm PHICOMM Co., Ltd. -phytec PHYTEC Messtechnik GmbH +phytec PHYTEC picochip Picochip Ltd pine64 Pine64 pineriver Shenzhen PineRiver Designs Co., Ltd. @@ -549,6 +554,7 @@ renode Antmicro's open source simulation and virtual development framework rervision Shenzhen Rervision Technology Co., Ltd. revotics Revolution Robotics, Inc. (Revotics) rex iMX6 Rex Project +reyax Reyax Technology Co., Ltd. richtek Richtek Technology Corporation ricoh Ricoh Co. Ltd. rikomagic Rikomagic Tech Corp. Ltd diff --git a/dts/bindings/video/nxp,imx-csi.yaml b/dts/bindings/video/nxp,imx-csi.yaml index d2553d6891184..bf7fd01eeaadd 100644 --- a/dts/bindings/video/nxp,imx-csi.yaml +++ b/dts/bindings/video/nxp,imx-csi.yaml @@ -14,7 +14,8 @@ properties: interrupts: required: true - sensor: + source: required: true type: phandle - description: phandle of connected sensor device + description: the connected source device, + e.g., a mipi csi or a camera sensor diff --git a/dts/bindings/video/nxp,mipi-csi2rx.yaml b/dts/bindings/video/nxp,mipi-csi2rx.yaml new file mode 100644 index 0000000000000..1726d63b3299e --- /dev/null +++ b/dts/bindings/video/nxp,mipi-csi2rx.yaml @@ -0,0 +1,17 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +description: NXP MIPI CSI-2 Rx interface + +compatible: "nxp,mipi-csi2rx" + +include: [base.yaml] + +properties: + sensor: + required: true + type: phandle + description: the connected camera sensor diff --git a/dts/bindings/video/ovti,ov5640.yaml b/dts/bindings/video/ovti,ov5640.yaml new file mode 100644 index 0000000000000..eecb0e3d3192b --- /dev/null +++ b/dts/bindings/video/ovti,ov5640.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: OV5640 CMOS video sensor + +compatible: "ovti,ov5640" + +include: i2c-device.yaml + +properties: + reset-gpios: + type: phandle-array + description: | + The RESETB pin is asserted to cause a hard reset. The sensor + receives this as an active-low signal. + powerdown-gpios: + type: phandle-array + description: | + The PWDN pin is asserted to disable the sensor. The sensor + receives this as an active-high signal. diff --git a/dts/bindings/video/ovti,ov7670.yaml b/dts/bindings/video/ovti,ov7670.yaml new file mode 100644 index 0000000000000..4b8fa88f1170b --- /dev/null +++ b/dts/bindings/video/ovti,ov7670.yaml @@ -0,0 +1,20 @@ +# Copyright 2024 NXP +# SPDX-License-Identifier: Apache-2.0 + +description: OV7670 CMOS video sensor + +compatible: "ovti,ov7670" + +properties: + reset-gpios: + type: phandle-array + description: | + The RESETn pin is asserted to disable the sensor causing a hard + reset. The sensor receives this as an active-low signal. + pwdn-gpios: + type: phandle-array + description: | + The PWDN pin is asserted to power down the sensor. The sensor + receives this as an active high signal + +include: i2c-device.yaml diff --git a/dts/bindings/w1/zephyr,w1-gpio.yaml b/dts/bindings/w1/zephyr,w1-gpio.yaml index 46f4e684e01b7..d3b796f25c67f 100644 --- a/dts/bindings/w1/zephyr,w1-gpio.yaml +++ b/dts/bindings/w1/zephyr,w1-gpio.yaml @@ -19,6 +19,12 @@ description: | - w1 is pin 13 on gpio0. The gpio is active when the pin is high, is configured as an open-drain, and has a pull-up resistor. + Implementation details: + - Most drivers require the selected gpio to support open drain, this enables onewire + devices to lower the signal when the SOC set the signal high. + - Ensure pullup is strong enough (4.7K according to the specification). Standard pullup in + SOC are usually weak, and may not be strong enough. + compatible: "zephyr,w1-gpio" include: [w1-master.yaml] diff --git a/dts/bindings/watchdog/espressif,esp32-xt-wdt.yaml b/dts/bindings/watchdog/espressif,esp32-xt-wdt.yaml new file mode 100644 index 0000000000000..c20a4234cabc0 --- /dev/null +++ b/dts/bindings/watchdog/espressif,esp32-xt-wdt.yaml @@ -0,0 +1,17 @@ +# Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. +# SPDX-License-Identifier: Apache-2.0 + +description: | + This watchdog timer can detect oscillation failure of the RTC_SLOW_CLK_SRC_XTAL32K. + When such a failure is detected the hardware automatically switch to + ESP32_RTC_SLOW_CLK_SRC_RC_SLOW. + + This feature is only available for ESP32S2,ESP32C3 and ESP32S3. + +compatible: "espressif,esp32-xt-wdt" + +include: base.yaml + +properties: + reg: + required: true diff --git a/dts/bindings/xspi/st,stm32-xspi.yaml b/dts/bindings/xspi/st,stm32-xspi.yaml new file mode 100644 index 0000000000000..388c3d20bca1c --- /dev/null +++ b/dts/bindings/xspi/st,stm32-xspi.yaml @@ -0,0 +1,9 @@ +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 XSPI device representation. Enabling a stm32 xspi node in a board + +compatible: "st,stm32-xspi" + +include: st,stm32-ospi.yaml diff --git a/dts/common/nordic/nrf54h20.dtsi b/dts/common/nordic/nrf54h20.dtsi index 75d112b85e2c8..a0f088be07fd8 100644 --- a/dts/common/nordic/nrf54h20.dtsi +++ b/dts/common/nordic/nrf54h20.dtsi @@ -8,12 +8,8 @@ #include #include - -/* Domain IDs. Can be used to specify channel links in IPCT nodes. */ -#define NRF_DOMAIN_ID_APPLICATION 2 -#define NRF_DOMAIN_ID_RADIOCORE 3 -#define NRF_DOMAIN_ID_GLOBALFAST 12 -#define NRF_DOMAIN_ID_GLOBALSLOW 13 +#include +#include /delete-node/ &sw_pwm; @@ -78,6 +74,10 @@ #address-cells = <1>; #size-cells = <1>; + suit_storage_partition: memory@e1eb000 { + reg = <0xe1eb000 DT_SIZE_K(24)>; + }; + cpurad_uicr_ext: memory@e1ff000 { reg = <0xe1ff000 DT_SIZE_K(2)>; }; @@ -88,6 +88,12 @@ }; clocks { + hfxo: hfxo { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = ; + }; + fll16m: fll16m { compatible = "fixed-clock"; #clock-cells = <0>; @@ -168,6 +174,30 @@ interrupts = <64 NRF_DEFAULT_IRQ_PRIORITY>, <65 NRF_DEFAULT_IRQ_PRIORITY>; }; + + cpuapp_wdt010: watchdog@14000 { + compatible = "nordic,nrf-wdt"; + reg = <0x14000 0x1000>; + status = "disabled"; + interrupts = <20 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + cpuapp_wdt011: watchdog@15000 { + compatible = "nordic,nrf-wdt"; + reg = <0x15000 0x1000>; + status = "disabled"; + interrupts = <21 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + cpuapp_resetinfo: resetinfo@1e000 { + compatible = "nordic,nrf-resetinfo"; + reg = <0x1e000 0x1000>; + }; + + cpuapp_ieee802154: ieee802154 { + compatible = "nordic,nrf-ieee802154"; + status = "disabled"; + }; }; cpurad_peripherals: peripheral@53000000 { @@ -188,6 +218,25 @@ nordic,ficr-names = "vsup", "coarse", "fine"; }; + cpurad_wdt010: watchdog@13000 { + compatible = "nordic,nrf-wdt"; + reg = <0x13000 0x1000>; + status = "disabled"; + interrupts = <19 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + cpurad_wdt011: watchdog@14000 { + compatible = "nordic,nrf-wdt"; + reg = <0x14000 0x1000>; + status = "disabled"; + interrupts = <20 NRF_DEFAULT_IRQ_PRIORITY>; + }; + + cpurad_resetinfo: resetinfo@1e000 { + compatible = "nordic,nrf-resetinfo"; + reg = <0x1e000 0x1000>; + }; + dppic020: dppic@22000 { compatible = "nordic,nrf-dppic-local"; reg = <0x22000 0x1000>; @@ -217,6 +266,7 @@ cc-num = <8>; interrupts = <40 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; @@ -227,6 +277,7 @@ cc-num = <8>; interrupts = <41 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; @@ -237,6 +288,7 @@ cc-num = <8>; interrupts = <42 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; @@ -301,15 +353,20 @@ ranges = <0x0 0x5f000000 0x1000000>; usbhs: usbhs@86000 { - compatible = "snps,dwc2"; + compatible = "nordic,nrf-usbhs", "snps,dwc2"; reg = <0x86000 0x1000>, <0x2f700000 0x40000>; reg-names = "wrapper", "core"; interrupts = <134 NRF_DEFAULT_IRQ_PRIORITY>; + num-in-eps = <8>; + num-out-eps = <10>; + ghwcfg1 = <0xaa555000>; + ghwcfg2 = <0x22abfc72>; + ghwcfg4 = <0x1e10aa60>; status = "disabled"; }; exmif: spi@95000 { - compatible = "nordic,nrf-exmif", "snps,designware-spi"; + compatible = "nordic,nrf-exmif"; #address-cells = <1>; #size-cells = <0>; reg = <0x95000 0x500 0x95500 0xb00>; @@ -339,6 +396,22 @@ #mbox-cells = <1>; }; + canpll: clock-controller@8c2000{ + compatible = "nordic,nrf-auxpll"; + reg = <0x8c2000 0x1000>; + interrupts = <194 NRF_DEFAULT_IRQ_PRIORITY>; + clocks = <&hfxo>; + #clock-cells = <0>; + nordic,ficrs = <&ficr NRF_FICR_TRIM_GLOBAL_CANPLL_TRIM_CTUNE>; + nordic,frequency = <0>; + nordic,out-div = <2>; + nordic,out-drive = <0>; + nordic,current-tune = <6>; + nordic,sdm-disable; + nordic,range = "high"; + status = "disabled"; + }; + cpusys_vevif_remote: mailbox@8c8000 { compatible = "nordic,nrf-vevif-remote"; reg = <0x8c8000 0x1000>; @@ -356,6 +429,16 @@ global-domain-id = <12>; }; + can120: can@8d8000 { + compatible = "nordic,nrf-can"; + reg = <0x8d8000 0x400>, <0x2fbef800 0x800>, <0x2fbe8000 0x7800>; + reg-names = "wrapper", "m_can", "message_ram"; + interrupts = <216 NRF_DEFAULT_IRQ_PRIORITY>; + clocks = <&canpll>; + bosch,mram-cfg = <0x0 28 8 3 3 0 1 1>; + status = "disabled"; + }; + dppic120: dppic@8e1000 { compatible = "nordic,nrf-dppic-global"; reg = <0x8e1000 0x1000>; @@ -369,6 +452,7 @@ cc-num = <6>; interrupts = <226 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; @@ -379,6 +463,7 @@ cc-num = <6>; interrupts = <227 NRF_DEFAULT_IRQ_PRIORITY>; max-bit-width = <32>; + max-frequency = ; prescaler = <0>; }; @@ -576,6 +661,14 @@ status = "disabled"; }; + adc: adc@982000 { + compatible = "nordic,nrf-saadc"; + reg = <0x982000 0x1000>; + interrupts = <386 NRF_DEFAULT_IRQ_PRIORITY>; + status = "disabled"; + #io-channel-cells = <1>; + }; + comp: comparator@983000 { compatible = "nordic,nrf-comp"; reg = <0x983000 0x1000>; @@ -1042,4 +1135,9 @@ #address-cells = <1>; }; }; + + temp_nrfs: temp { + compatible = "nordic,nrf-temp-nrfs"; + status = "disabled"; + }; }; diff --git a/dts/common/nordic/nrf54l15.dtsi b/dts/common/nordic/nrf54l15.dtsi index 76dc4903f5552..122e4fdf42aaf 100644 --- a/dts/common/nordic/nrf54l15.dtsi +++ b/dts/common/nordic/nrf54l15.dtsi @@ -104,11 +104,14 @@ #address-cells = <1>; #size-cells = <1>; +#ifdef USE_NON_SECURE_ADDRESS_MAP + /* intentionally empty because UICR is hardware fixed to Secure */ +#else uicr: uicr@ffd000 { compatible = "nordic,nrf-uicr"; reg = <0xffd000 0x1000>; }; - +#endif ficr: ficr@ffc000 { compatible = "nordic,nrf-ficr"; reg = <0xffc000 0x1000>; @@ -131,10 +134,17 @@ ranges = <0x0 0x2002f000 0x11000>; }; +#ifdef USE_NON_SECURE_ADDRESS_MAP + global_peripherals: peripheral@40000000 { + #address-cells = <1>; + #size-cells = <1>; + ranges = <0x0 0x40000000 0x10000000>; +#else global_peripherals: peripheral@50000000 { #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0x50000000 0x10000000>; +#endif dppic00: dppic@42000 { compatible = "nordic,nrf-dppic"; @@ -212,6 +222,7 @@ cc-num = <6>; max-bit-width = <32>; interrupts = <85 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; prescaler = <0>; }; @@ -228,6 +239,7 @@ cc-num = <8>; max-bit-width = <32>; interrupts = <133 NRF_DEFAULT_IRQ_PRIORITY>; + max-frequency = ; prescaler = <0>; }; @@ -252,6 +264,14 @@ compatible = "nordic,nrf-ieee802154"; status = "disabled"; }; + + /* Note: In the nRF Connect SDK the SoftDevice Controller + * is added and set as the default Bluetooth Controller. + */ + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "disabled"; + }; }; dppic20: dppic@c2000 { @@ -565,12 +585,16 @@ status = "disabled"; }; +#ifdef USE_NON_SECURE_ADDRESS_MAP + /* intentionally empty because WDT30 is hardware fixed to Secure */ +#else wdt30: watchdog@108000 { compatible = "nordic,nrf-wdt"; reg = <0x108000 0x620>; interrupts = <264 NRF_DEFAULT_IRQ_PRIORITY>; status = "disabled"; }; +#endif wdt31: watchdog@109000 { compatible = "nordic,nrf-wdt"; diff --git a/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi index 6ad2f61286692..71b703114c36b 100644 --- a/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi +++ b/dts/riscv/espressif/esp32c3/esp32c3_common.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -23,6 +24,7 @@ zephyr,canbus = &twai; zephyr,entropy = &trng0; zephyr,flash-controller = &flash; + zephyr,bt-hci = &esp32_bt_hci; }; cpus { @@ -35,6 +37,9 @@ riscv,isa = "rv32imc_zicsr"; reg = <0>; cpu-power-states = <&light_sleep &deep_sleep>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; power-states { @@ -64,6 +69,11 @@ status = "disabled"; }; + esp32_bt_hci: esp32_bt_hci { + compatible = "espressif,esp32-bt-hci"; + status = "disabled"; + }; + soc { #address-cells = <1>; #size-cells = <1>; @@ -95,17 +105,28 @@ rtc: rtc@60008000 { compatible = "espressif,esp32-rtc"; reg = <0x60008000 0x1000>; - xtal-freq = ; + fast-clk-src = ; + slow-clk-src = ; #clock-cells = <1>; status = "okay"; + }; - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; + xt_wdt: xt_wdt@60008004 { + compatible = "espressif,esp32-xt-wdt"; + reg = <0x60008004 0x4>; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + rtc_timer: rtc_timer@60008004 { + reg = <0x60008004 0xC>; + compatible = "espressif,esp32-rtc-timer"; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; }; flash: flash-controller@60002000 { diff --git a/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi new file mode 100644 index 0000000000000..0edf5bf95a3db --- /dev/null +++ b/dts/riscv/espressif/esp32c6/esp32c6_common.dtsi @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + chosen { + zephyr,flash-controller = &flash; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "espressif,riscv"; + riscv,isa = "rv32imac_zicsr"; + reg = <0>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; + }; + }; + + pinctrl: pin-controller { + compatible = "espressif,esp32-pinctrl"; + status = "okay"; + }; + + soc { + #address-cells = <1>; + #size-cells = <1>; + compatible = "simple-bus"; + ranges; + + sram0: memory@40800000 { + compatible = "mmio-sram"; + reg = <0x40800000 0x50000>; + }; + + intc: interrupt-controller@60010000 { + compatible = "espressif,esp32-intc"; + #address-cells = <0>; + #interrupt-cells = <1>; + interrupt-controller; + reg = <0x60010000 DT_SIZE_K(4)>; + status = "okay"; + }; + + systimer0: systimer@6000a000 { + compatible = "espressif,esp32-systimer"; + reg = <0x6000A000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; + }; + + rtc: rtc@600b000 { + compatible = "espressif,esp32-rtc"; + reg = <0x600B000 DT_SIZE_K(1)>; + fast-clk-src = ; + slow-clk-src = ; + #clock-cells = <1>; + status = "okay"; + + }; + + rtc_timer: rtc_timer@600b0c00 { + compatible = "espressif,esp32-rtc-timer"; + reg = <0x600B0C00 DT_SIZE_K(1)>; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + spi2: spi@60081000 { + compatible = "espressif,esp32-spi"; + reg = <0x60081000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_SPI2_MODULE>; + dma-clk = ; + dma-host = <0>; + status = "disabled"; + }; + + wdt0: watchdog@60008048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x60008048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG0_MODULE>; + status = "disabled"; + }; + + wdt1: watchdog@60009048 { + compatible = "espressif,esp32-watchdog"; + reg = <0x60009048 0x20>; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_TIMG1_MODULE>; + status = "disabled"; + }; + + flash: flash-controller@60002000 { + compatible = "espressif,esp32-flash-controller"; + reg = <0x60002000 0x1000>; + + #address-cells = <1>; + #size-cells = <1>; + + flash0: flash@0 { + compatible = "soc-nv-flash"; + erase-block-size = <4096>; + write-block-size = <4>; + }; + }; + + gpio0: gpio@60091000 { + compatible = "espressif,esp32-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x60091000 DT_SIZE_K(4)>; + interrupts = ; + interrupt-parent = <&intc>; + ngpios = <30>; /* 0..29 */ + }; + + uart0: uart@60000000 { + compatible = "espressif,esp32-uart"; + reg = <0x60000000 DT_SIZE_K(4)>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART0_MODULE>; + }; + + uart1: uart@60001000 { + compatible = "espressif,esp32-uart"; + reg = <0x60001000 DT_SIZE_K(4)>; + status = "disabled"; + interrupts = ; + interrupt-parent = <&intc>; + clocks = <&rtc ESP32_UART1_MODULE>; + current-speed = <115200>; + }; + + ledc0: ledc@60007000 { + compatible = "espressif,esp32-ledc"; + pwm-controller; + #pwm-cells = <3>; + reg = <0x60007000 0x1000>; + clocks = <&rtc ESP32_LEDC_MODULE>; + status = "disabled"; + }; + }; + +}; diff --git a/dts/riscv/espressif/esp32c6/esp32c6_wroom_n4.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_wroom_n4.dtsi new file mode 100644 index 0000000000000..062bb06621ca8 --- /dev/null +++ b/dts/riscv/espressif/esp32c6/esp32c6_wroom_n4.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #include "esp32c6_common.dtsi" + +/* 4MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(4)>; +}; diff --git a/dts/riscv/espressif/esp32c6/esp32c6_wroom_n8.dtsi b/dts/riscv/espressif/esp32c6/esp32c6_wroom_n8.dtsi new file mode 100644 index 0000000000000..71af7e15320ed --- /dev/null +++ b/dts/riscv/espressif/esp32c6/esp32c6_wroom_n8.dtsi @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + + #include "esp32c6_common.dtsi" + +/* 8MB flash */ +&flash0 { + reg = <0x0 DT_SIZE_M(8)>; +}; diff --git a/dts/riscv/ite/it81202dx.dtsi b/dts/riscv/ite/it81202dx.dtsi new file mode 100644 index 0000000000000..73f577d814a46 --- /dev/null +++ b/dts/riscv/ite/it81202dx.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + sram0: memory@80100000 { + compatible = "mmio-sram"; + reg = <0x80100000 DT_SIZE_K(128)>; + }; + }; +}; diff --git a/dts/riscv/ite/it81302dx.dtsi b/dts/riscv/ite/it81302dx.dtsi new file mode 100644 index 0000000000000..73f577d814a46 --- /dev/null +++ b/dts/riscv/ite/it81302dx.dtsi @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 ITE Corporation. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + soc { + sram0: memory@80100000 { + compatible = "mmio-sram"; + reg = <0x80100000 DT_SIZE_K(128)>; + }; + }; +}; diff --git a/dts/riscv/ite/it81xx2.dtsi b/dts/riscv/ite/it81xx2.dtsi index 252ddfe120bfd..53dd3b0cdc935 100644 --- a/dts/riscv/ite/it81xx2.dtsi +++ b/dts/riscv/ite/it81xx2.dtsi @@ -61,7 +61,8 @@ pinctrla: pinctrl@f01610 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01610 8>; /* GPCR */ + reg = <0x00f01610 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -80,7 +81,8 @@ pinctrlb: pinctrl@f01618 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01618 8>; /* GPCR */ + reg = <0x00f01618 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = <0xf016f5 0xf016f5 NO_FUNC NO_FUNC NO_FUNC NO_FUNC NO_FUNC 0xf01600>; func3-en-mask = <0x01 0x02 0 0 @@ -99,7 +101,8 @@ pinctrlc: pinctrl@f01620 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01620 8>; /* GPCR */ + reg = <0x00f01620 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0x10 @@ -118,7 +121,8 @@ pinctrld: pinctrl@f01628 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01628 8>; /* GPCR */ + reg = <0x00f01628 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -137,7 +141,8 @@ pinctrle: pinctrl@f01630 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01630 8>; /* GPCR */ + reg = <0x00f01630 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = <0xf02032 NO_FUNC NO_FUNC NO_FUNC NO_FUNC 0xf016f0 NO_FUNC 0xf02032>; func3-en-mask = <0x01 0 0 0 @@ -156,7 +161,8 @@ pinctrlf: pinctrl@f01638 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01638 8>; /* GPCR */ + reg = <0x00f01638 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0x02 0x02 @@ -175,7 +181,8 @@ pinctrlg: pinctrl@f01640 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01640 8>; /* GPCR */ + reg = <0x00f01640 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = <0xf016f0 0xf016f0 0xf016f0 NO_FUNC NO_FUNC NO_FUNC 0xf016f0 NO_FUNC>; func3-en-mask = <0x20 0x08 0x10 0 @@ -194,7 +201,8 @@ pinctrlh: pinctrl@f01648 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01648 8>; /* GPCR */ + reg = <0x00f01648 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0x20 0x20 0 @@ -217,7 +225,8 @@ pinctrli: pinctrl@f01650 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01650 8>; /* GPCR */ + reg = <0x00f01650 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -236,7 +245,8 @@ pinctrlj: pinctrl@f01658 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01658 8>; /* GPCR */ + reg = <0x00f01658 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = <0xf016f4 NO_FUNC 0xf016f4 0xf016f4 0xf016f0 0xf016f0 NO_FUNC NO_FUNC>; func3-en-mask = <0x01 0 0x01 0x02 @@ -255,7 +265,8 @@ pinctrlk: pinctrl@f01690 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01690 8>; /* GPCR */ + reg = <0x00f01690 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -274,7 +285,8 @@ pinctrll: pinctrl@f01698 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01698 8>; /* GPCR */ + reg = <0x00f01698 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -293,7 +305,8 @@ pinctrlm: pinctrl@f016a0 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016a0 8>; /* GPCR */ + reg = <0x00f016a0 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 diff --git a/dts/riscv/ite/it82xx2.dtsi b/dts/riscv/ite/it82xx2.dtsi index a9ab8b206cf05..4e5bae980b6b7 100644 --- a/dts/riscv/ite/it82xx2.dtsi +++ b/dts/riscv/ite/it82xx2.dtsi @@ -447,7 +447,8 @@ pinctrla: pinctrl@f01660 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01660 8>; /* GPCR */ + reg = <0x00f01660 8 /* GPCR */ + 0x00f03e30 1>; /* PDSCA */ func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -466,7 +467,8 @@ pinctrlb: pinctrl@f01668 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01668 8>; /* GPCR */ + reg = <0x00f01668 8 /* GPCR */ + 0x00f03e31 1>; /* PDSCB */ func3-gcr = <0xf03e15 0xf03e15 0xf03e11 NO_FUNC NO_FUNC 0xf03e11 NO_FUNC NO_FUNC>; func3-en-mask = <0x01 0x02 0x20 0 @@ -489,7 +491,8 @@ pinctrlc: pinctrl@f01670 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01670 8>; /* GPCR */ + reg = <0x00f01670 8 /* GPCR */ + 0x00f03e32 1>; /* PDSCC */ func3-gcr = ; func3-en-mask = <0 0 0 0x10 @@ -508,7 +511,8 @@ pinctrld: pinctrl@f01678 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01678 8>; /* GPCR */ + reg = <0x00f01678 8 /* GPCR */ + 0x00f03e33 1>; /* PDSCD */ func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -527,7 +531,8 @@ pinctrle: pinctrl@f01680 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01680 8>; /* GPCR */ + reg = <0x00f01680 8 /* GPCR */ + 0x00f03e34 1>; /* PDSCE */ func3-gcr = ; func3-en-mask = <0 0x20 0x20 0 @@ -550,7 +555,8 @@ pinctrlf: pinctrl@f01688 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01688 8>; /* GPCR */ + reg = <0x00f01688 8 /* GPCR */ + 0x00f03e35 1>; /* PDSCF */ func3-gcr = <0xf03e15 0xf03e15 0xf03e10 0xf03e10 NO_FUNC NO_FUNC 0xf03e11 NO_FUNC>; func3-en-mask = <0x04 0x08 0x02 0x02 @@ -569,7 +575,8 @@ pinctrlg: pinctrl@f01690 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01690 8>; /* GPCR */ + reg = <0x00f01690 8 /* GPCR */ + 0x00f03e36 1>; /* PDSCG */ func3-gcr = <0xf03e10 0xf03e10 0xf03e10 NO_FUNC NO_FUNC NO_FUNC 0xf03e10 NO_FUNC>; func3-en-mask = <0x20 0x08 0x10 0 @@ -588,7 +595,8 @@ pinctrlh: pinctrl@f01698 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f01698 8>; /* GPCR */ + reg = <0x00f01698 8 /* GPCR */ + 0x00f03e37 1>; /* PDSCH */ func3-gcr = ; func3-en-mask = <0 0x20 0x20 0 @@ -607,7 +615,8 @@ pinctrli: pinctrl@f016a0 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016a0 8>; /* GPCR */ + reg = <0x00f016a0 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -626,7 +635,8 @@ pinctrlj: pinctrl@f016a8 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016a8 8>; /* GPCR */ + reg = <0x00f016a8 8 /* GPCR */ + 0x00f03e39 1>; /* PDSCJ */ func3-gcr = <0xf03e14 NO_FUNC 0xf03e14 0xf03e14 0xf03e10 0xf03e10 NO_FUNC NO_FUNC>; func3-en-mask = <0x01 0 0x01 0x02 @@ -645,7 +655,8 @@ pinctrlk: pinctrl@f016b0 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016b0 8>; /* GPCR */ + reg = <0x00f016b0 8 /* GPCR */ + 0x00f03e3A 1>; /* PDSCK */ func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -664,7 +675,8 @@ pinctrll: pinctrl@f016b8 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016b8 8>; /* GPCR */ + reg = <0x00f016b8 8 /* GPCR */ + 0x00f03e3B 1>; /* PDSCL */ func3-gcr = ; func3-en-mask = <0 0 0 0 @@ -683,7 +695,8 @@ pinctrlm: pinctrl@f016c0 { compatible = "ite,it8xxx2-pinctrl-func"; - reg = <0x00f016c0 8>; /* GPCR */ + reg = <0x00f016c0 8 /* GPCR */ + NO_FUNC 1>; func3-gcr = ; func3-en-mask = <0 0 0 0 diff --git a/dts/riscv/openisa/rv32m1.dtsi b/dts/riscv/openisa/rv32m1.dtsi index afbc7c41c23a0..cb234eba99827 100644 --- a/dts/riscv/openisa/rv32m1.dtsi +++ b/dts/riscv/openisa/rv32m1.dtsi @@ -524,5 +524,10 @@ write-block-size = <8>; }; }; + + bt_hci_controller: bt_hci_controller { + compatible = "zephyr,bt-hci-ll-sw-split"; + status = "disabled"; + }; }; }; diff --git a/dts/riscv/qemu/virt-riscv.dtsi b/dts/riscv/qemu/virt-riscv.dtsi new file mode 100644 index 0000000000000..8329a1ec62b8c --- /dev/null +++ b/dts/riscv/qemu/virt-riscv.dtsi @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2020 Cobham Gaisler AB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This file is based on: + * qemu-system-riscv32 -machine virt,dumpdtb=virt.dtb -smp 8 -m 256 + * dtc virt.dtb > virt.dtsi + */ + +/dts-v1/; + +/ { + #address-cells = < 0x01 >; + #size-cells = < 0x01 >; + compatible = "riscv-virtio"; + model = "riscv-virtio,qemu"; + + flash@20000000 { + bank-width = < 0x04 >; + reg = < 0x20000000 0x2000000 0x22000000 0x2000000 >; + compatible = "cfi-flash"; + }; + + uart0: uart@10000000 { + interrupts = < 0x0a 1 >; + interrupt-parent = < &plic >; + clock-frequency = < 0x384000 >; + reg = < 0x10000000 0x100 >; + compatible = "ns16550"; + reg-shift = < 0 >; + }; + + cpus { + #address-cells = < 0x01 >; + #size-cells = < 0x00 >; + + cpu@0 { + device_type = "cpu"; + reg = < 0x00 >; + status = "okay"; + compatible = "qemu,riscv-virt", "riscv"; + + hlic0: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = < 0x01 >; + interrupt-controller; + }; + }; + + cpu@1 { + device_type = "cpu"; + reg = < 0x01 >; + status = "okay"; + compatible = "qemu,riscv-virt", "riscv"; + + hlic1: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = < 0x01 >; + interrupt-controller; + }; + }; + + cpu@2 { + device_type = "cpu"; + reg = < 0x02 >; + status = "okay"; + compatible = "qemu,riscv-virt", "riscv"; + + hlic2: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = < 0x01 >; + interrupt-controller; + }; + }; + + cpu@3 { + device_type = "cpu"; + reg = < 0x03 >; + status = "okay"; + compatible = "qemu,riscv-virt", "riscv"; + + hlic3: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = < 0x01 >; + interrupt-controller; + }; + }; + + cpu@4 { + device_type = "cpu"; + reg = < 0x04 >; + status = "okay"; + compatible = "qemu,riscv-virt", "riscv"; + + hlic4: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = < 0x01 >; + interrupt-controller; + }; + }; + + cpu@5 { + device_type = "cpu"; + reg = < 0x05 >; + status = "okay"; + compatible = "qemu,riscv-virt", "riscv"; + + hlic5: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = < 0x01 >; + interrupt-controller; + }; + }; + + cpu@6 { + device_type = "cpu"; + reg = < 0x06 >; + status = "okay"; + compatible = "qemu,riscv-virt", "riscv"; + + hlic6: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = < 0x01 >; + interrupt-controller; + }; + }; + + cpu@7 { + device_type = "cpu"; + reg = < 0x07 >; + status = "okay"; + compatible = "qemu,riscv-virt", "riscv"; + + hlic7: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + #interrupt-cells = < 0x01 >; + interrupt-controller; + }; + }; + }; + + ram0: memory@80000000 { + device_type = "memory"; + reg = < 0x80000000 0x10000000 >; + }; + + soc { + #address-cells = < 0x01 >; + #size-cells = < 0x01 >; + compatible = "simple-bus"; + ranges; + + plic: interrupt-controller@c000000 { + riscv,max-priority = <7>; + riscv,ndev = < 1024 >; + reg = <0x0c000000 0x04000000>; + interrupts-extended = < + &hlic0 0x0b &hlic0 0x09 + &hlic1 0x0b &hlic1 0x09 + &hlic2 0x0b &hlic2 0x09 + &hlic3 0x0b &hlic3 0x09 + &hlic4 0x0b &hlic4 0x09 + &hlic5 0x0b &hlic5 0x09 + &hlic6 0x0b &hlic6 0x09 + &hlic7 0x0b &hlic7 0x09 + >; + interrupt-controller; + compatible = "sifive,plic-1.0.0"; + #address-cells = < 0x00 >; + #interrupt-cells = < 0x02 >; + }; + + clint@2000000 { + compatible = "sifive,clint0"; + reg = <0x2000000 0x10000>; + interrupts-extended = <&hlic0 0x03 &hlic0 0x07 + &hlic1 0x03 &hlic1 0x07 + &hlic2 0x03 &hlic2 0x07 + &hlic3 0x03 &hlic3 0x07 + &hlic4 0x03 &hlic4 0x07 + &hlic5 0x03 &hlic5 0x07 + &hlic6 0x03 &hlic6 0x07 + &hlic7 0x03 &hlic7 0x07>; + }; + }; +}; diff --git a/dts/riscv/qemu/virt-riscv32.dtsi b/dts/riscv/qemu/virt-riscv32.dtsi new file mode 100644 index 0000000000000..25d769d5183a9 --- /dev/null +++ b/dts/riscv/qemu/virt-riscv32.dtsi @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + cpus { + cpu@0 { + riscv,isa = "rv32gc"; + }; + + cpu@1 { + riscv,isa = "rv32gc"; + }; + + cpu@2 { + riscv,isa = "rv32gc"; + }; + + cpu@3 { + riscv,isa = "rv32gc"; + }; + + cpu@4 { + riscv,isa = "rv32gc"; + }; + + cpu@5 { + riscv,isa = "rv32gc"; + }; + + cpu@6 { + riscv,isa = "rv32gc"; + }; + + cpu@7 { + riscv,isa = "rv32gc"; + }; + }; +}; diff --git a/dts/riscv/qemu/virt-riscv64.dtsi b/dts/riscv/qemu/virt-riscv64.dtsi new file mode 100644 index 0000000000000..936f0a1881526 --- /dev/null +++ b/dts/riscv/qemu/virt-riscv64.dtsi @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Antmicro + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include + +/ { + cpus { + cpu@0 { + riscv,isa = "rv64gc"; + }; + + cpu@1 { + riscv,isa = "rv64gc"; + }; + + cpu@2 { + riscv,isa = "rv64gc"; + }; + + cpu@3 { + riscv,isa = "rv64gc"; + }; + + cpu@4 { + riscv,isa = "rv64gc"; + }; + + cpu@5 { + riscv,isa = "rv64gc"; + }; + + cpu@6 { + riscv,isa = "rv64gc"; + }; + + cpu@7 { + riscv,isa = "rv64gc"; + }; + }; +}; diff --git a/dts/riscv/riscv32-litex-vexriscv.dtsi b/dts/riscv/riscv32-litex-vexriscv.dtsi index 8013decbafdfe..6ae55a82016b5 100644 --- a/dts/riscv/riscv32-litex-vexriscv.dtsi +++ b/dts/riscv/riscv32-litex-vexriscv.dtsi @@ -4,6 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ + #include + / { #address-cells = <1>; #size-cells = <1>; @@ -18,7 +20,7 @@ cpus { #address-cells = <1>; #size-cells = <0>; - cpu@0 { + cpu0: cpu@0 { clock-frequency = <100000000>; compatible = "litex,vexriscv-standard", "riscv"; device_type = "cpu"; @@ -32,8 +34,17 @@ #size-cells = <1>; compatible = "litex,vexriscv"; ranges; + ctrl0: soc_controller@e0000000 { + compatible = "litex,soc-controller"; + reg = <0xe0000000 0x4 + 0xe0000004 0x4 + 0xe0000008 0x4>; + reg-names = "reset", + "scratch", + "bus_errors"; + }; intc0: interrupt-controller@bc0 { - compatible = "vexriscv-intc0"; + compatible = "litex,vexriscv-intc0"; #address-cells = <0>; #interrupt-cells = <2>; interrupt-controller; @@ -161,6 +172,7 @@ compatible = "litex,i2c"; reg = <0xe0005000 0x4 0xe0005004 0x4>; reg-names = "write", "read"; + clock-frequency = ; #address-cells = <1>; #size-cells = <0>; status = "disabled"; diff --git a/dts/riscv/virt.dtsi b/dts/riscv/virt.dtsi deleted file mode 100644 index 20873731c6e9d..0000000000000 --- a/dts/riscv/virt.dtsi +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2020 Cobham Gaisler AB - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/* - * This file is based on: - * qemu-system-riscv32 -machine virt,dumpdtb=virt.dtb -smp 8 -m 256 - * dtc virt.dtb > virt.dtsi - */ - -/dts-v1/; - -/ { - #address-cells = < 0x01 >; - #size-cells = < 0x01 >; - compatible = "riscv-virtio"; - model = "riscv-virtio,qemu"; - - flash@20000000 { - bank-width = < 0x04 >; - reg = < 0x20000000 0x2000000 0x22000000 0x2000000 >; - compatible = "cfi-flash"; - }; - - uart0: uart@10000000 { - interrupts = < 0x0a 1 >; - interrupt-parent = < &plic >; - clock-frequency = < 0x384000 >; - reg = < 0x10000000 0x100 >; - compatible = "ns16550"; - reg-shift = < 0 >; - }; - - cpus { - #address-cells = < 0x01 >; - #size-cells = < 0x00 >; - - cpu@0 { - device_type = "cpu"; - reg = < 0x00 >; - status = "okay"; - compatible = "riscv"; - - hlic0: interrupt-controller { - compatible = "riscv,cpu-intc"; - #address-cells = <0>; - #interrupt-cells = < 0x01 >; - interrupt-controller; - }; - }; - - cpu@1 { - device_type = "cpu"; - reg = < 0x01 >; - status = "okay"; - compatible = "riscv"; - - hlic1: interrupt-controller { - compatible = "riscv,cpu-intc"; - #address-cells = <0>; - #interrupt-cells = < 0x01 >; - interrupt-controller; - }; - }; - - cpu@2 { - device_type = "cpu"; - reg = < 0x02 >; - status = "okay"; - compatible = "riscv"; - - hlic2: interrupt-controller { - compatible = "riscv,cpu-intc"; - #address-cells = <0>; - #interrupt-cells = < 0x01 >; - interrupt-controller; - }; - }; - - cpu@3 { - device_type = "cpu"; - reg = < 0x03 >; - status = "okay"; - compatible = "riscv"; - - hlic3: interrupt-controller { - compatible = "riscv,cpu-intc"; - #address-cells = <0>; - #interrupt-cells = < 0x01 >; - interrupt-controller; - }; - }; - - cpu@4 { - device_type = "cpu"; - reg = < 0x04 >; - status = "okay"; - compatible = "riscv"; - - hlic4: interrupt-controller { - compatible = "riscv,cpu-intc"; - #address-cells = <0>; - #interrupt-cells = < 0x01 >; - interrupt-controller; - }; - }; - - cpu@5 { - device_type = "cpu"; - reg = < 0x05 >; - status = "okay"; - compatible = "riscv"; - - hlic5: interrupt-controller { - compatible = "riscv,cpu-intc"; - #address-cells = <0>; - #interrupt-cells = < 0x01 >; - interrupt-controller; - }; - }; - - cpu@6 { - device_type = "cpu"; - reg = < 0x06 >; - status = "okay"; - compatible = "riscv"; - - hlic6: interrupt-controller { - compatible = "riscv,cpu-intc"; - #address-cells = <0>; - #interrupt-cells = < 0x01 >; - interrupt-controller; - }; - }; - - cpu@7 { - device_type = "cpu"; - reg = < 0x07 >; - status = "okay"; - compatible = "riscv"; - - hlic7: interrupt-controller { - compatible = "riscv,cpu-intc"; - #address-cells = <0>; - #interrupt-cells = < 0x01 >; - interrupt-controller; - }; - }; - }; - - ram0: memory@80000000 { - device_type = "memory"; - reg = < 0x80000000 0x10000000 >; - }; - - soc { - #address-cells = < 0x01 >; - #size-cells = < 0x01 >; - compatible = "simple-bus"; - ranges; - - plic: interrupt-controller@c000000 { - riscv,max-priority = <7>; - riscv,ndev = < 1024 >; - reg = <0x0c000000 0x04000000>; - interrupts-extended = < - &hlic0 0x0b &hlic0 0x09 - &hlic1 0x0b &hlic1 0x09 - &hlic2 0x0b &hlic2 0x09 - &hlic3 0x0b &hlic3 0x09 - &hlic4 0x0b &hlic4 0x09 - &hlic5 0x0b &hlic5 0x09 - &hlic6 0x0b &hlic6 0x09 - &hlic7 0x0b &hlic7 0x09 - >; - interrupt-controller; - compatible = "sifive,plic-1.0.0"; - #address-cells = < 0x00 >; - #interrupt-cells = < 0x02 >; - }; - - clint@2000000 { - compatible = "sifive,clint0"; - reg = <0x2000000 0x10000>; - interrupts-extended = <&hlic0 0x03 &hlic0 0x07 - &hlic1 0x03 &hlic1 0x07 - &hlic2 0x03 &hlic2 0x07 - &hlic3 0x03 &hlic3 0x07 - &hlic4 0x03 &hlic4 0x07 - &hlic5 0x03 &hlic5 0x07 - &hlic6 0x03 &hlic6 0x07 - &hlic7 0x03 &hlic7 0x07>; - }; - }; -}; diff --git a/dts/x86/intel/intel_ish5.dtsi b/dts/x86/intel/intel_ish5.dtsi index 5f2ef6a1960c3..81abf748b9342 100644 --- a/dts/x86/intel/intel_ish5.dtsi +++ b/dts/x86/intel/intel_ish5.dtsi @@ -189,7 +189,7 @@ }; dma0: dma@10100000 { - compatible = "intel,sedi_dma"; + compatible = "intel,sedi-dma"; #dma-cells = <2>; dma-channels = <8>; peripheral-id = <0>; diff --git a/dts/xtensa/espressif/esp32/esp32_common.dtsi b/dts/xtensa/espressif/esp32/esp32_common.dtsi index 82a92ed00a878..ae348b1288fb2 100644 --- a/dts/xtensa/espressif/esp32/esp32_common.dtsi +++ b/dts/xtensa/espressif/esp32/esp32_common.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -18,6 +19,7 @@ zephyr,canbus = &twai; zephyr,entropy = &trng0; zephyr,flash-controller = &flash; + zephyr,bt-hci = &esp32_bt_hci; }; cpus { @@ -26,15 +28,21 @@ cpu0: cpu@0 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx6"; + compatible = "espressif,xtensa-lx6"; reg = <0>; cpu-power-states = <&light_sleep &deep_sleep>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; cpu1: cpu@1 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx6"; + compatible = "espressif,xtensa-lx6"; reg = <1>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; power-states { @@ -59,6 +67,11 @@ status = "disabled"; }; + esp32_bt_hci: esp32_bt_hci { + compatible = "espressif,esp32-bt-hci"; + status = "disabled"; + }; + eth: eth { compatible = "espressif,esp32-eth"; interrupts = ; @@ -107,17 +120,20 @@ rtc: rtc@3ff48000 { compatible = "espressif,esp32-rtc"; reg = <0x3ff48000 0x0D8>; - xtal-freq = ; + fast-clk-src = ; + slow-clk-src = ; #clock-cells = <1>; status = "okay"; - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; + }; + + rtc_timer: rtc_timer@3ff48004 { + reg = <0x3ff48004 0xC>; + compatible = "espressif,esp32-rtc-timer"; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; }; flash: flash-controller@3ff42000 { diff --git a/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi index 1bb8c000ed59f..a855bd0df97b8 100644 --- a/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi +++ b/dts/xtensa/espressif/esp32s2/esp32s2_common.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -32,9 +33,12 @@ cpu0: cpu@0 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx7"; + compatible = "espressif,xtensa-lx7"; reg = <0>; cpu-power-states = <&light_sleep &deep_sleep>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; power-states { @@ -59,6 +63,11 @@ status = "disabled"; }; + esp32_bt_hci: esp32_bt_hci { + compatible = "espressif,esp32-bt-hci"; + status = "disabled"; + }; + pinctrl: pin-controller { compatible = "espressif,esp32-pinctrl"; status = "okay"; @@ -86,17 +95,28 @@ rtc: rtc@3f408000 { compatible = "espressif,esp32-rtc"; reg = <0x3f408000 0x0D8>; - xtal-freq = ; + fast-clk-src = ; + slow-clk-src = ; #clock-cells = <1>; status = "okay"; + }; - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; + xt_wdt: xt_wdt@3f408004 { + compatible = "espressif,esp32-xt-wdt"; + reg = <0x3f408004 0x4>; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + rtc_timer: rtc_timer@3f408004 { + reg = <0x3f408004 0xC>; + compatible = "espressif,esp32-rtc-timer"; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "okay"; }; flash: flash-controller@3f402000 { diff --git a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi index b02d38410ada1..2b571a6596087 100644 --- a/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi +++ b/dts/xtensa/espressif/esp32s3/esp32s3_common.dtsi @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ #include +#include #include #include #include @@ -30,15 +31,21 @@ cpu0: cpu@0 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx7"; + compatible = "espressif,xtensa-lx7"; reg = <0>; cpu-power-states = <&light_sleep &deep_sleep>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; cpu1: cpu@1 { device_type = "cpu"; - compatible = "cdns,tensilica-xtensa-lx7"; + compatible = "espressif,xtensa-lx7"; reg = <1>; + clock-source = ; + clock-frequency = ; + xtal-freq = ; }; power-states { @@ -63,6 +70,11 @@ status = "disabled"; }; + esp32_bt_hci: esp32_bt_hci { + compatible = "espressif,esp32-bt-hci"; + status = "disabled"; + }; + pinctrl: pin-controller { compatible = "espressif,esp32-pinctrl"; status = "okay"; @@ -100,17 +112,28 @@ rtc: rtc@60021000 { compatible = "espressif,esp32-rtc"; reg = <0x60021000 0x2000>; - xtal-freq = ; + fast-clk-src = ; + slow-clk-src = ; #clock-cells = <1>; status = "okay"; + }; - rtc_timer: rtc_timer { - compatible = "espressif,esp32-rtc-timer"; - slow-clk-freq = ; - interrupts = ; - interrupt-parent = <&intc>; - status = "okay"; - }; + xt_wdt: xt_wdt@60021004 { + compatible = "espressif,esp32-xt-wdt"; + reg = <0x60021004 0x4>; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; + }; + + rtc_timer: rtc_timer@60008004 { + reg = <0x60008004 0xC>; + compatible = "espressif,esp32-rtc-timer"; + clocks = <&rtc ESP32_MODULE_MAX>; + interrupts = ; + interrupt-parent = <&intc>; + status = "disabled"; }; flash: flash-controller@60002000 { diff --git a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi index d9595311a974a..7c2050b109fda 100644 --- a/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace15_mtpm.dtsi @@ -25,14 +25,14 @@ device_type = "cpu"; compatible = "cdns,tensilica-xtensa-lx7"; reg = <1>; - cpu-power-states = <&d0i3 &d3>; + cpu-power-states = <&d3>; }; cpu2: cpu@2 { device_type = "cpu"; compatible = "cdns,tensilica-xtensa-lx7"; reg = <2>; - cpu-power-states = <&d0i3 &d3>; + cpu-power-states = <&d3>; }; power-states { @@ -111,6 +111,21 @@ soc { + l1ccap: l1ccap@1fe80080 { + compatible = "intel,adsp-l1ccap"; + reg = <0x1fe80080 0x4>; + }; + + l1ccfg: l1ccfg@1fe80084 { + compatible = "intel,adsp-l1ccfg"; + reg = <0x1fe80084 0x4>; + }; + + l1pcfg: l1pcfg@1fe80088 { + compatible = "intel,adsp-l1pcfg"; + reg = <0x1fe80088 0x4>; + }; + lsbpm: lsbpm@71d80 { compatible = "intel,adsp-lsbpm"; reg = <0x71d80 0x0008>; diff --git a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi index e3462c834d193..c26d2b815fe0a 100644 --- a/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi +++ b/dts/xtensa/intel/intel_adsp_ace20_lnl.dtsi @@ -130,6 +130,21 @@ soc { + l1ccap: l1ccap@1fe80080 { + compatible = "intel,adsp-l1ccap"; + reg = <0x1fe80080 0x4>; + }; + + l1ccfg: l1ccfg@1fe80084 { + compatible = "intel,adsp-l1ccfg"; + reg = <0x1fe80084 0x4>; + }; + + l1pcfg: l1pcfg@1fe80088 { + compatible = "intel,adsp-l1pcfg"; + reg = <0x1fe80088 0x4>; + }; + lsbpm: lsbpm@71d80 { compatible = "intel,adsp-lsbpm"; reg = <0x71d80 0x0008>; diff --git a/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi new file mode 100644 index 0000000000000..11930481baad7 --- /dev/null +++ b/dts/xtensa/intel/intel_adsp_ace30_ptl.dtsi @@ -0,0 +1,710 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <0>; + cpu-power-states = <&d0i3 &d3>; + i-cache-line-size = <64>; + d-cache-line-size = <64>; + }; + + cpu1: cpu@1 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <1>; + cpu-power-states = <&d0i3 &d3>; + }; + + cpu2: cpu@2 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <2>; + cpu-power-states = <&d0i3 &d3>; + }; + + cpu3: cpu@3 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <3>; + cpu-power-states = <&d0i3 &d3>; + }; + + cpu4: cpu@4 { + device_type = "cpu"; + compatible = "cdns,tensilica-xtensa-lx7"; + reg = <4>; + cpu-power-states = <&d0i3 &d3>; + }; + }; + + power-states { + d0i3: idle { + compatible = "zephyr,power-state"; + power-state-name = "runtime-idle"; + min-residency-us = <200>; + exit-latency-us = <100>; + }; + /* PM_STATE_SOFT_OFF can be entered only by calling pm_state_force. + * The procedure is triggered by IPC from the HOST (SET_DX). + */ + d3: off { + compatible = "zephyr,power-state"; + power-state-name = "soft-off"; + min-residency-us = <0>; + exit-latency-us = <0>; + status = "disabled"; + }; + }; + + sram0: memory@a0020000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0xa0020000 DT_SIZE_K(4608)>; + }; + + sram0virtual: virtualmemory@a0020000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0xa0020000 DT_SIZE_K(8192)>; + }; + + sram1: memory@a0000000 { + device_type = "memory"; + compatible = "mmio-sram"; + reg = <0xa0000000 DT_SIZE_K(64)>; + }; + + sysclk: system-clock { + compatible = "fixed-clock"; + clock-frequency = <38400000>; + #clock-cells = <0>; + }; + + clkctl: clkctl { + compatible = "intel,adsp-shim-clkctl"; + adsp-clkctl-clk-wovcro = <0>; + adsp-clkctl-clk-ipll = <1>; + adsp-clkctl-freq-enc = <0xc 0x4>; + adsp-clkctl-freq-mask = <0x0 0x0>; + adsp-clkctl-freq-default = <1>; + adsp-clkctl-freq-lowest = <0>; + wovcro-supported; + }; + + audioclk: audio-clock { + compatible = "fixed-clock"; + clock-frequency = <24576000>; + #clock-cells = <0>; + }; + + pllclk: pll-clock { + compatible = "fixed-clock"; + clock-frequency = <96000000>; + #clock-cells = <0>; + }; + + IMR1: memory@A1000000 { + compatible = "intel,adsp-imr"; + reg = <0xA1000000 DT_SIZE_M(16)>; + block-size = <0x1000>; + zephyr,memory-region = "IMR1"; + }; + + soc { + l1ccap: l1ccap@3fe80080 { + compatible = "intel,adsp-l1ccap"; + reg = <0x3fe80080 0x4>; + }; + + l1ccfg: l1ccfg@3fe80084 { + compatible = "intel,adsp-l1ccfg"; + reg = <0x3fe80084 0x4>; + }; + + l1pcfg: l1pcfg@3fe80088 { + compatible = "intel,adsp-l1pcfg"; + reg = <0x3fe80088 0x4>; + }; + + lsbpm: lsbpm@71d80 { + compatible = "intel,adsp-lsbpm"; + reg = <0x71d80 0x0008>; + }; + + hsbpm: hsbpm@17a800 { + compatible = "intel,adsp-hsbpm"; + reg = <0x17a800 0x0008>; + }; + + core_intc: core_intc@0 { + compatible = "cdns,xtensa-core-intc"; + reg = <0x00 0x400>; + interrupt-controller; + #interrupt-cells = <3>; + }; + + hdamlddmic: hdamlddmic@cc0 { + compatible = "intel,adsp-hda-dmic-cap"; + reg = <0xcc0 0x40>; + status = "okay"; + }; + + dmic0: dai-dmic0@10100 { + compatible = "intel,dai-dmic"; + reg = <0x10100 0x8000>; + shim = <0x10000>; + fifo = <0x0008>; + interrupts = <0x08 0 0>; + interrupt-parent = <&ace_intc>; + power-domain = <&hub_ulp_domain>; + }; + + dmic1: dai-dmic1@10100 { + compatible = "intel,dai-dmic"; + reg = <0x10100 0x8000>; + shim = <0x10000>; + fifo = <0x0108>; + interrupts = <0x08 0 0>; + interrupt-parent = <&ace_intc>; + power-domain = <&hub_ulp_domain>; + }; + + dmicvss: dmicvss@16000 { + compatible = "intel,adsp-dmic-vss"; + reg = <0x16000 0x2000>; + status = "okay"; + }; + + /* + * FIXME this is modeling individual alh channels/instances + * with node labels, which has problems. A better representation + * is discussed here: + * + * https://github.com/zephyrproject-rtos/zephyr/pull/50287#discussion_r974591009 + */ + alh0: alh0@24400 { + compatible = "intel,alh-dai"; + reg = <0x00024400 0x00024600>; + status = "okay"; + }; + + alh1: alh1@24400 { + compatible = "intel,alh-dai"; + reg = <0x00024400 0x00024600>; + status = "okay"; + }; + + sspbase: ssp_base@28000 { + compatible = "intel,ssp-sspbase"; + reg = <0x28000 0x1000>; + }; + + hdamlssp: hdamlssp@d00 { + compatible = "intel,adsp-hda-ssp-cap"; + reg = <0xD00 0x40>; + status = "okay"; + }; + + ssp0: ssp@28100 { + compatible = "intel,ssp"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x00028100 0x1000 + 0x00079C00 0x200>; + interrupts = <0x00 0 0>; + interrupt-parent = <&ace_intc>; + dmas = <&hda_link_out 1 + &hda_link_in 1>; + dma-names = "tx", "rx"; + ssp-index = <0>; + power-domain = <&io0_domain>; + status = "okay"; + + ssp00: ssp@0 { + compatible = "intel,ssp-dai"; + reg = <0x0>; + status = "okay"; + }; + + ssp01: ssp@1 { + compatible = "intel,ssp-dai"; + reg = <0x1>; + status = "okay"; + }; + + ssp02: ssp@2 { + compatible = "intel,ssp-dai"; + reg = <0x2>; + status = "okay"; + }; + + ssp03: ssp@3 { + compatible = "intel,ssp-dai"; + reg = <0x3>; + status = "okay"; + }; + + ssp04: ssp@4 { + compatible = "intel,ssp-dai"; + reg = <0x4>; + status = "okay"; + }; + + ssp05: ssp@5 { + compatible = "intel,ssp-dai"; + reg = <0x5>; + status = "okay"; + }; + + ssp06: ssp@6 { + compatible = "intel,ssp-dai"; + reg = <0x6>; + status = "okay"; + }; + + ssp07: ssp@7 { + compatible = "intel,ssp-dai"; + reg = <0x7>; + status = "okay"; + }; + }; + + ssp1: ssp@29100 { + compatible = "intel,ssp"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x00029100 0x1000 + 0x00079C00 0x200>; + interrupts = <0x01 0 0>; + interrupt-parent = <&ace_intc>; + dmas = <&hda_link_out 2 + &hda_link_in 2>; + dma-names = "tx", "rx"; + ssp-index = <1>; + power-domain = <&io0_domain>; + status = "okay"; + + ssp10: ssp@10 { + compatible = "intel,ssp-dai"; + reg = <0x10>; + status = "okay"; + }; + + ssp11: ssp@11 { + compatible = "intel,ssp-dai"; + reg = <0x11>; + status = "okay"; + }; + + ssp12: ssp@12 { + compatible = "intel,ssp-dai"; + reg = <0x12>; + status = "okay"; + }; + + ssp13: ssp@13 { + compatible = "intel,ssp-dai"; + reg = <0x13>; + status = "okay"; + }; + + ssp14: ssp@14 { + compatible = "intel,ssp-dai"; + reg = <0x14>; + status = "okay"; + }; + + ssp15: ssp@15 { + compatible = "intel,ssp-dai"; + reg = <0x15>; + status = "okay"; + }; + + ssp16: ssp@16 { + compatible = "intel,ssp-dai"; + reg = <0x16>; + status = "okay"; + }; + + ssp17: ssp@17 { + compatible = "intel,ssp-dai"; + reg = <0x17>; + status = "okay"; + }; + }; + + ssp2: ssp@2a100 { + compatible = "intel,ssp"; + #address-cells = <1>; + #size-cells = <0>; + reg = <0x0002a100 0x1000 + 0x00079C00 0x200>; + interrupts = <0x02 0 0>; + interrupt-parent = <&ace_intc>; + dmas = <&hda_link_out 3 + &hda_link_in 3>; + dma-names = "tx", "rx"; + ssp-index = <2>; + power-domain = <&io0_domain>; + status = "okay"; + + ssp20: ssp@20 { + compatible = "intel,ssp-dai"; + reg = <0x20>; + status = "okay"; + }; + + ssp21: ssp@21 { + compatible = "intel,ssp-dai"; + reg = <0x21>; + status = "okay"; + }; + + ssp22: ssp@22 { + compatible = "intel,ssp-dai"; + reg = <0x22>; + status = "okay"; + }; + + ssp23: ssp@23 { + compatible = "intel,ssp-dai"; + reg = <0x23>; + status = "okay"; + }; + + ssp24: ssp@24 { + compatible = "intel,ssp-dai"; + reg = <0x24>; + status = "okay"; + }; + + ssp25: ssp@25 { + compatible = "intel,ssp-dai"; + reg = <0x25>; + status = "okay"; + }; + + ssp26: ssp@26 { + compatible = "intel,ssp-dai"; + reg = <0x26>; + status = "okay"; + }; + + ssp27: ssp@27 { + compatible = "intel,ssp-dai"; + reg = <0x27>; + status = "okay"; + }; + }; + + mem_window0: mem_window@70200 { + compatible = "intel,adsp-mem-window"; + reg = <0x70200 0x8>; + offset = <0x4000>; + memory = <&sram0>; + initialize; + read-only; + }; + + mem_window1: mem_window@70208 { + compatible = "intel,adsp-mem-window"; + reg = <0x70208 0x8>; + memory = <&sram0>; + }; + + mem_window2: mem_window@70210 { + compatible = "intel,adsp-mem-window"; + reg = <0x70210 0x8>; + memory = <&sram0>; + }; + + mem_window3: mem_window@70218 { + compatible = "intel,adsp-mem-window"; + reg = <0x70218 0x8>; + memory = <&sram0>; + read-only; + }; + + adsp_idc: ace_idc@92000 { + compatible = "intel,adsp-idc"; + reg = <0x92000 0x0400>; + interrupts = <24 0 0>; + interrupt-parent = <&ace_intc>; + }; + + dfpmcch: dfpmcch@71ac0 { + compatible = "intel,adsp-dfpmcch"; + reg = <0x00071ac0 0x40>; + }; + + dfpmccu: dfpmccu@71b00 { + compatible = "intel,adsp-dfpmccu"; + reg = <0x71b00 0x100>; + + hub_ulp_domain: hub_ulp_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <15>; + }; + hub_hp_domain: hub_hpp_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <6>; + }; + io0_domain: io0_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <8>; + }; + io1_domain: io1_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <9>; + }; + io2_domain: io2_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <10>; + }; + io3_domain: io3_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <11>; + }; + hst_domain: hst_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <5>; + }; + ml0_domain: ml0_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <12>; + }; + ml1_domain: ml1_domain { + compatible = "intel,adsp-power-domain"; + bit-position = <13>; + }; + }; + + shim: shim@71f00 { + compatible = "intel,cavs-shim"; + reg = <0x71f00 0x100>; + }; + + tts: tts@72000 { + compatible = "intel,adsp-tts"; + reg = <0x72000 0x70>; + status = "okay"; + }; + + ace_rtc_counter: ace_rtc_counter@72008 { + compatible = "intel,ace-rtc-counter"; + reg = <0x72008 0x0064>; + }; + + ace_timestamp: ace_timestamp@72040 { + compatible = "intel,ace-timestamp"; + reg = <0x72040 0x0032>; + }; + + ace_art_counter: ace_art_counter@72058 { + compatible = "intel,ace-art-counter"; + reg = <0x72058 0x0064>; + }; + + hda_host_out: dma@72800 { + compatible = "intel,adsp-hda-host-out"; + #dma-cells = <1>; + reg = <0x00072800 0x40>; + dma-channels = <9>; + dma-buf-addr-alignment = <128>; + dma-buf-size-alignment = <32>; + dma-copy-alignment = <32>; + power-domain = <&hst_domain>; + interrupts = <13 0 0>; + interrupt-parent = <&ace_intc>; + status = "okay"; + }; + + hda_host_in: dma@72c00 { + compatible = "intel,adsp-hda-host-in"; + #dma-cells = <1>; + reg = <0x00072c00 0x40>; + dma-channels = <11>; + dma-buf-addr-alignment = <128>; + dma-buf-size-alignment = <32>; + dma-copy-alignment = <32>; + power-domain = <&hst_domain>; + interrupts = <12 0 0>; + interrupt-parent = <&ace_intc>; + status = "okay"; + }; + + adsp_host_ipc: ace_host_ipc@73000 { + compatible = "intel,adsp-host-ipc"; + status = "okay"; + reg = <0x73000 0x30>; + interrupts = <0 0 0>; + interrupt-parent = <&ace_intc>; + }; + + hda_link_out: dma@79400 { + compatible = "intel,adsp-hda-link-out"; + #dma-cells = <1>; + reg = <0x00079400 0x40>; + dma-channels = <9>; + dma-buf-addr-alignment = <128>; + dma-buf-size-alignment = <32>; + dma-copy-alignment = <32>; + power-domain = <&io0_domain>; + status = "okay"; + }; + + hda_link_in: dma@79800 { + compatible = "intel,adsp-hda-link-in"; + #dma-cells = <1>; + reg = <0x00079800 0x40>; + dma-channels = <11>; + dma-buf-addr-alignment = <128>; + dma-buf-size-alignment = <32>; + dma-copy-alignment = <32>; + power-domain = <&io0_domain>; + status = "okay"; + }; + + /* This is actually an array of per-core designware + * controllers, but the special setup and extra + * masking layer makes it easier for MTL to handle + * this internally. + */ + ace_intc: ace_intc@94000 { + compatible = "intel,ace-intc"; + reg = <0x94000 0xc00>; + interrupt-controller; + #interrupt-cells = <3>; + interrupts = <4 0 0>; + num-irqs = <28>; + interrupt-parent = <&core_intc>; + }; + + tlb: tlb@17e000 { + compatible = "intel,adsp-mtl-tlb"; + reg = <0x17e000 0x1000>; + paddr-size = <12>; + exec-bit-idx = <14>; + write-bit-idx= <15>; + }; + + timer: timer { + compatible = "intel,adsp-timer"; + syscon = <&tts>; + }; + }; + + hdas { + #address-cells = <1>; + #size-cells = <0>; + + hda0: hda@0 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0>; + }; + hda1: hda@1 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <1>; + }; + hda2: hda@2 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <2>; + }; + hda3: hda@3 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <3>; + }; + hda4: hda@4 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <4>; + }; + hda5: hda@5 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <5>; + }; + hda6: hda@6 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <6>; + }; + hda7: hda@7 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <7>; + }; + hda8: hda@8 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <8>; + }; + hda9: hda@9 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <9>; + }; + hda10: hda@a { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0a>; + }; + hda11: hda@b { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0b>; + }; + hda12: hda@c { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0c>; + }; + hda13: hda@d { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0d>; + }; + hda14: hda@e { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0e>; + }; + hda15: hda@f { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x0f>; + }; + hda16: hda@10 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x10>; + }; + hda17: hda@11 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x11>; + }; + hda18: hda@12 { + compatible = "intel,hda-dai"; + status = "okay"; + reg = <0x12>; + }; + }; +}; diff --git a/include/zephyr/app_memory/app_memdomain.h b/include/zephyr/app_memory/app_memdomain.h index 08e28982ad632..d53a3d2266a27 100644 --- a/include/zephyr/app_memory/app_memdomain.h +++ b/include/zephyr/app_memory/app_memdomain.h @@ -128,16 +128,16 @@ struct z_app_region { extern char Z_APP_START(name)[]; \ extern char Z_APP_SIZE(name)[]; \ struct k_mem_partition name = { \ - .start = (uintptr_t) &Z_APP_START(name), \ - .size = (size_t) &Z_APP_SIZE(name), \ + .start = (uintptr_t) &Z_APP_START(name)[0], \ + .size = (size_t) &Z_APP_SIZE(name)[0], \ .attr = K_MEM_PARTITION_P_RW_U_RW \ }; \ extern char Z_APP_BSS_START(name)[]; \ extern char Z_APP_BSS_SIZE(name)[]; \ Z_GENERIC_SECTION(.app_regions.name) \ const struct z_app_region name##_region = { \ - .bss_start = &Z_APP_BSS_START(name), \ - .bss_size = (size_t) &Z_APP_BSS_SIZE(name) \ + .bss_start = &Z_APP_BSS_START(name)[0], \ + .bss_size = (size_t) &Z_APP_BSS_SIZE(name)[0] \ }; \ Z_APPMEM_PLACEHOLDER(name) #else diff --git a/include/zephyr/app_memory/mem_domain.h b/include/zephyr/app_memory/mem_domain.h index ece13e3bdc29e..8fe75eb33d931 100644 --- a/include/zephyr/app_memory/mem_domain.h +++ b/include/zephyr/app_memory/mem_domain.h @@ -126,7 +126,7 @@ struct k_mem_partition; * @retval -EINVAL if invalid parameters supplied * @retval -ENOMEM if insufficient memory */ -extern int k_mem_domain_init(struct k_mem_domain *domain, uint8_t num_parts, +int k_mem_domain_init(struct k_mem_domain *domain, uint8_t num_parts, struct k_mem_partition *parts[]); /** @@ -156,7 +156,7 @@ extern int k_mem_domain_init(struct k_mem_domain *domain, uint8_t num_parts, * @retval -EINVAL if invalid parameters supplied * @retval -ENOSPC if no free partition slots available */ -extern int k_mem_domain_add_partition(struct k_mem_domain *domain, +int k_mem_domain_add_partition(struct k_mem_domain *domain, struct k_mem_partition *part); /** @@ -171,7 +171,7 @@ extern int k_mem_domain_add_partition(struct k_mem_domain *domain, * @retval -EINVAL if invalid parameters supplied * @retval -ENOENT if no matching partition found */ -extern int k_mem_domain_remove_partition(struct k_mem_domain *domain, +int k_mem_domain_remove_partition(struct k_mem_domain *domain, struct k_mem_partition *part); /** @@ -185,7 +185,7 @@ extern int k_mem_domain_remove_partition(struct k_mem_domain *domain, * * @return 0 if successful, fails otherwise. */ -extern int k_mem_domain_add_thread(struct k_mem_domain *domain, +int k_mem_domain_add_thread(struct k_mem_domain *domain, k_tid_t thread); #ifdef __cplusplus diff --git a/include/zephyr/arch/arc/v2/exception.h b/include/zephyr/arch/arc/v2/exception.h index 553024fa3a8c6..f606cf1ea9a7c 100644 --- a/include/zephyr/arch/arc/v2/exception.h +++ b/include/zephyr/arch/arc/v2/exception.h @@ -18,11 +18,6 @@ extern "C" { #endif -#ifdef _ASMLANGUAGE -#else -typedef struct _irq_stack_frame z_arch_esf_t; -#endif - #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/arc/v2/linker.ld b/include/zephyr/arch/arc/v2/linker.ld index a7751d961194e..c65aa5a648412 100644 --- a/include/zephyr/arch/arc/v2/linker.ld +++ b/include/zephyr/arch/arc/v2/linker.ld @@ -81,6 +81,10 @@ SECTIONS { #include +#ifdef CONFIG_LLEXT +#include +#endif + GROUP_START(ROMABLE_REGION) SECTION_PROLOGUE(_TEXT_SECTION_NAME,,ALIGN(1024)) { diff --git a/include/zephyr/arch/arc/v2/mpu/arc_core_mpu.h b/include/zephyr/arch/arc/v2/mpu/arc_core_mpu.h index ad36a22eb771e..8e3e02a67ced1 100644 --- a/include/zephyr/arch/arc/v2/mpu/arc_core_mpu.h +++ b/include/zephyr/arch/arc/v2/mpu/arc_core_mpu.h @@ -88,7 +88,7 @@ void arc_core_mpu_remove_mem_domain(struct k_mem_domain *mem_domain); void arc_core_mpu_remove_mem_partition(struct k_mem_domain *domain, uint32_t partition_id); int arc_core_mpu_get_max_domain_partition_regions(void); -int arc_core_mpu_buffer_validate(void *addr, size_t size, int write); +int arc_core_mpu_buffer_validate(const void *addr, size_t size, int write); #endif diff --git a/include/zephyr/arch/arch_inlines.h b/include/zephyr/arch/arch_inlines.h index 4e1cd149dfb4d..0f32159e2f1bf 100644 --- a/include/zephyr/arch/arch_inlines.h +++ b/include/zephyr/arch/arch_inlines.h @@ -12,7 +12,7 @@ #ifndef ZEPHYR_INCLUDE_ARCH_INLINES_H_ #define ZEPHYR_INCLUDE_ARCH_INLINES_H_ -#if defined(CONFIG_X86) || defined(CONFIG_X86_64) +#if defined(CONFIG_X86) #include #elif defined(CONFIG_ARM) #include @@ -32,8 +32,6 @@ #include #elif defined(CONFIG_SPARC) #include -#else -#error "Unknown Architecture" #endif #endif /* ZEPHYR_INCLUDE_ARCH_INLINES_H_ */ diff --git a/include/zephyr/arch/arch_interface.h b/include/zephyr/arch/arch_interface.h index d7ff2f2cad2db..ae51b4a375999 100644 --- a/include/zephyr/arch/arch_interface.h +++ b/include/zephyr/arch/arch_interface.h @@ -39,6 +39,7 @@ extern "C" { #endif /* NOTE: We cannot pull in kernel.h here, need some forward declarations */ +struct arch_esf; struct k_thread; struct k_mem_domain; @@ -46,6 +47,8 @@ typedef struct z_thread_stack_element k_thread_stack_t; typedef void (*k_thread_entry_t)(void *p1, void *p2, void *p3); +__deprecated typedef struct arch_esf z_arch_esf_t; + /** * @defgroup arch-timing Architecture timing APIs * @ingroup arch-interface @@ -491,10 +494,18 @@ static inline uint32_t arch_proc_id(void); /** * Broadcast an interrupt to all CPUs * - * This will invoke z_sched_ipi() on other CPUs in the system. + * This will invoke z_sched_ipi() on all other CPUs in the system. */ -void arch_sched_ipi(void); +void arch_sched_broadcast_ipi(void); +/** + * Direct IPIs to the specified CPUs + * + * This will invoke z_sched_ipi() on the CPUs identified by @a cpu_bitmap. + * + * @param cpu_bitmap A bitmap indicating which CPUs need the IPI + */ +void arch_sched_directed_ipi(uint32_t cpu_bitmap); int arch_smp_init(void); @@ -783,7 +794,7 @@ int arch_mem_domain_partition_add(struct k_mem_domain *domain, * * @return nonzero if the permissions don't match. */ -int arch_buffer_validate(void *addr, size_t size, int write); +int arch_buffer_validate(const void *addr, size_t size, int write); /** * Get the optimal virtual region alignment to optimize the MMU table layout @@ -1240,6 +1251,33 @@ bool arch_pcie_msi_vector_connect(msi_vector_t *vector, */ void arch_spin_relax(void); +/** + * stack_trace_callback_fn - Callback for @ref arch_stack_walk + * @param cookie Caller supplied pointer handed back by @ref arch_stack_walk + * @param addr The stack entry address to consume + * + * @return True, if the entry was consumed or skipped. False, if there is no space left to store + */ +typedef bool (*stack_trace_callback_fn)(void *cookie, unsigned long addr); + +/** + * @brief Architecture-specific function to walk the stack + * + * @param callback_fn Callback which is invoked by the architecture code for each entry. + * @param cookie Caller supplied pointer which is handed back to @a callback_fn + * @param thread Pointer to a k_thread struct, can be NULL + * @param esf Pointer to an arch_esf struct, can be NULL + * + * ============ ======= ============================================ + * thread esf + * ============ ======= ============================================ + * thread NULL Stack trace from thread (can be _current) + * thread esf Stack trace starting on esf + * ============ ======= ============================================ + */ +void arch_stack_walk(stack_trace_callback_fn callback_fn, void *cookie, + const struct k_thread *thread, const struct arch_esf *esf); + #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/include/zephyr/arch/arm/cortex_a_r/exception.h b/include/zephyr/arch/arm/cortex_a_r/exception.h index 3bef647566d3c..cd8377bc3a70c 100644 --- a/include/zephyr/arch/arm/cortex_a_r/exception.h +++ b/include/zephyr/arch/arm/cortex_a_r/exception.h @@ -54,7 +54,7 @@ struct __extra_esf_info { }; #endif /* CONFIG_EXTRA_EXCEPTION_INFO */ -struct __esf { +struct arch_esf { #if defined(CONFIG_EXTRA_EXCEPTION_INFO) struct __extra_esf_info extra_info; #endif @@ -75,8 +75,6 @@ struct __esf { extern uint32_t z_arm_coredump_fault_sp; -typedef struct __esf z_arch_esf_t; - extern void z_arm_exc_exit(bool fatal); #ifdef __cplusplus diff --git a/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld b/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld index 947c18de31349..cffe2f3856e00 100644 --- a/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_a_r/scripts/linker.ld @@ -98,6 +98,10 @@ SECTIONS { #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. diff --git a/include/zephyr/arch/arm/cortex_m/exception.h b/include/zephyr/arch/arm/cortex_m/exception.h index a9896cea1e4ed..2deed9bdf832d 100644 --- a/include/zephyr/arch/arm/cortex_m/exception.h +++ b/include/zephyr/arch/arm/cortex_m/exception.h @@ -98,7 +98,7 @@ struct __extra_esf_info { }; #endif /* CONFIG_EXTRA_EXCEPTION_INFO */ -struct __esf { +struct arch_esf { struct __basic_sf { sys_define_gpr_with_alias(a1, r0); sys_define_gpr_with_alias(a2, r1); @@ -119,8 +119,6 @@ struct __esf { extern uint32_t z_arm_coredump_fault_sp; -typedef struct __esf z_arch_esf_t; - extern void z_arm_exc_exit(void); #ifdef __cplusplus diff --git a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld index 6d5ba15ee6e82..094e4a5303f97 100644 --- a/include/zephyr/arch/arm/cortex_m/scripts/linker.ld +++ b/include/zephyr/arch/arm/cortex_m/scripts/linker.ld @@ -26,6 +26,14 @@ #endif #define RAMABLE_REGION RAM +/* Region of the irq vectors and boot-vector SP/PC */ +#if defined(CONFIG_ROMSTART_RELOCATION_ROM) +#define ROMSTART_ADDR CONFIG_ROMSTART_REGION_ADDRESS +#define ROMSTART_SIZE (CONFIG_ROMSTART_REGION_SIZE * 1K) +#else +#define ROMSTART_REGION ROMABLE_REGION +#endif + #if !defined(CONFIG_XIP) && (CONFIG_FLASH_SIZE == 0) #define ROM_ADDR RAM_ADDR #else @@ -85,6 +93,9 @@ _region_min_align = 4; MEMORY { +#if defined(CONFIG_ROMSTART_RELOCATION_ROM) + ROMSTART_REGION (rx) : ORIGIN = ROMSTART_ADDR, LENGTH = ROMSTART_SIZE +#endif FLASH (rx) : ORIGIN = ROM_ADDR, LENGTH = ROM_SIZE RAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE #if defined(CONFIG_LINKER_DEVNULL_MEMORY) @@ -102,6 +113,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. @@ -129,7 +144,7 @@ SECTIONS */ #include - } GROUP_LINK_IN(ROMABLE_REGION) + } GROUP_LINK_IN(ROMSTART_REGION) #ifdef CONFIG_CODE_DATA_RELOCATION diff --git a/include/zephyr/arch/arm/gdbstub.h b/include/zephyr/arch/arm/gdbstub.h index e8e606d7def80..55fceff173d10 100644 --- a/include/zephyr/arch/arm/gdbstub.h +++ b/include/zephyr/arch/arm/gdbstub.h @@ -64,7 +64,7 @@ struct gdb_ctx { unsigned int registers[GDB_NUM_REGS]; }; -void z_gdb_entry(z_arch_esf_t *esf, unsigned int exc_cause); +void z_gdb_entry(struct arch_esf *esf, unsigned int exc_cause); #endif diff --git a/include/zephyr/arch/arm64/arm_mem.h b/include/zephyr/arch/arm64/arm_mem.h index 110f85a24caa6..4f81376caf7f2 100644 --- a/include/zephyr/arch/arm64/arm_mem.h +++ b/include/zephyr/arch/arm64/arm_mem.h @@ -7,7 +7,7 @@ #define ZEPHYR_INCLUDE_ARCH_ARM64_ARM_MEM_H_ /* - * Define ARM specific memory flags used by z_phys_map() + * Define ARM specific memory flags used by k_mem_map_phys_bare() * followed public definitions in include/kernel/mm.h. */ /* For ARM64, K_MEM_CACHE_NONE is nGnRnE. */ diff --git a/include/zephyr/arch/arm64/exception.h b/include/zephyr/arch/arm64/exception.h index 4ccdc41f19cf7..a1348f608e3b9 100644 --- a/include/zephyr/arch/arm64/exception.h +++ b/include/zephyr/arch/arm64/exception.h @@ -24,7 +24,7 @@ extern "C" { #endif -struct __esf { +struct arch_esf { uint64_t x0; uint64_t x1; uint64_t x2; @@ -47,7 +47,7 @@ struct __esf { uint64_t lr; uint64_t spsr; uint64_t elr; -#ifdef CONFIG_ARM64_ENABLE_FRAME_POINTER +#ifdef CONFIG_FRAME_POINTER uint64_t fp; #endif #ifdef CONFIG_ARM64_SAFE_EXCEPTION_STACK @@ -55,8 +55,6 @@ struct __esf { #endif } __aligned(16); -typedef struct __esf z_arch_esf_t; - #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/arm64/scripts/linker.ld b/include/zephyr/arch/arm64/scripts/linker.ld index 5a8e1404a98ae..b360e4417bbe7 100644 --- a/include/zephyr/arch/arm64/scripts/linker.ld +++ b/include/zephyr/arch/arm64/scripts/linker.ld @@ -14,6 +14,7 @@ #include #include +#include #include #include @@ -66,6 +67,7 @@ MEMORY { FLASH (rx) : ORIGIN = ROM_ADDR, LENGTH = ROM_SIZE RAM (wx) : ORIGIN = RAM_ADDR, LENGTH = RAM_SIZE + LINKER_DT_REGIONS() /* Used by and documented in include/linker/intlist.ld */ IDT_LIST (wx) : ORIGIN = 0xFFFF8000, LENGTH = 32K } @@ -77,6 +79,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to 'arm-zephyr-elf-ld --verbose', * before text section. @@ -329,6 +335,8 @@ SECTIONS /DISCARD/ : { *(.note.GNU-stack) } + /* Sections generated from 'zephyr,memory-region' nodes */ + LINKER_DT_SECTIONS() /* Must be last in romable region */ SECTION_PROLOGUE(.last_section,,) diff --git a/include/zephyr/arch/common/pm_s2ram.h b/include/zephyr/arch/common/pm_s2ram.h index 16443f2d105fd..451794a53a246 100644 --- a/include/zephyr/arch/common/pm_s2ram.h +++ b/include/zephyr/arch/common/pm_s2ram.h @@ -7,7 +7,6 @@ * * @brief public S2RAM APIs. * @defgroup pm_s2ram S2RAM APIs - * @ingroup subsys_pm * @{ */ @@ -57,6 +56,30 @@ typedef int (*pm_s2ram_system_off_fn_t)(void); */ int arch_pm_s2ram_suspend(pm_s2ram_system_off_fn_t system_off); +/** + * @brief Mark that core is entering suspend-to-RAM state. + * + * Function is called when system state is stored to RAM, just before going to system + * off. + * + * Default implementation is setting a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING + * allows custom implementation. + */ +void pm_s2ram_mark_set(void); + +/** + * @brief Check suspend-to-RAM marking and clear its state. + * + * Function is used to determine if resuming after suspend-to-RAM shall be performed + * or standard boot code shall be executed. + * + * Default implementation is checking a magic word in RAM. CONFIG_PM_S2RAM_CUSTOM_MARKING + * allows custom implementation. + * + * @retval true if marking is found which indicates resuming after suspend-to-RAM. + * @retval false if marking is not found which indicates standard boot. + */ +bool pm_s2ram_mark_check_and_clear(void); /** * @} */ diff --git a/include/zephyr/arch/cpu.h b/include/zephyr/arch/cpu.h index 11abe8df8c0b5..1e107512fa2a4 100644 --- a/include/zephyr/arch/cpu.h +++ b/include/zephyr/arch/cpu.h @@ -31,8 +31,6 @@ #include #elif defined(CONFIG_SPARC) #include -#else -#error "Unknown Architecture" #endif #endif /* ZEPHYR_INCLUDE_ARCH_CPU_H_ */ diff --git a/include/zephyr/arch/exception.h b/include/zephyr/arch/exception.h new file mode 100644 index 0000000000000..074a5e0b0d71c --- /dev/null +++ b/include/zephyr/arch/exception.h @@ -0,0 +1,35 @@ +/* exception.h - automatically selects the correct exception.h file to include */ + +/* + * Copyright (c) 2024 Meta Platforms + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_EXCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_EXCEPTION_H_ + +#if defined(CONFIG_X86_64) +#include +#elif defined(CONFIG_X86) +#include +#elif defined(CONFIG_ARM64) +#include +#elif defined(CONFIG_ARM) +#include +#elif defined(CONFIG_ARC) +#include +#elif defined(CONFIG_NIOS2) +#include +#elif defined(CONFIG_RISCV) +#include +#elif defined(CONFIG_XTENSA) +#include +#elif defined(CONFIG_MIPS) +#include +#elif defined(CONFIG_ARCH_POSIX) +#include +#elif defined(CONFIG_SPARC) +#include +#endif + +#endif /* ZEPHYR_INCLUDE_ARCH_EXCEPTION_H_ */ diff --git a/include/zephyr/arch/mips/exception.h b/include/zephyr/arch/mips/exception.h index d4403f1d5995e..f33af4c4387d8 100644 --- a/include/zephyr/arch/mips/exception.h +++ b/include/zephyr/arch/mips/exception.h @@ -17,7 +17,7 @@ extern "C" { #endif -struct __esf { +struct arch_esf { unsigned long ra; /* return address */ unsigned long gp; /* global pointer */ @@ -50,8 +50,6 @@ struct __esf { unsigned long cause; }; -typedef struct __esf z_arch_esf_t; - #ifdef __cplusplus } #endif diff --git a/include/zephyr/arch/mips/linker.ld b/include/zephyr/arch/mips/linker.ld index cbff890822c72..f7479c23e36b5 100644 --- a/include/zephyr/arch/mips/linker.ld +++ b/include/zephyr/arch/mips/linker.ld @@ -46,6 +46,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + SECTION_PROLOGUE(_VECTOR_SECTION_NAME,,) { . = ALIGN(0x1000); diff --git a/include/zephyr/arch/nios2/arch.h b/include/zephyr/arch/nios2/arch.h index 7df7ae9a91aa8..5369f690b5d37 100644 --- a/include/zephyr/arch/nios2/arch.h +++ b/include/zephyr/arch/nios2/arch.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -99,34 +100,11 @@ static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key) void arch_irq_enable(unsigned int irq); void arch_irq_disable(unsigned int irq); -struct __esf { - uint32_t ra; /* return address r31 */ - uint32_t r1; /* at */ - uint32_t r2; /* return value */ - uint32_t r3; /* return value */ - uint32_t r4; /* register args */ - uint32_t r5; /* register args */ - uint32_t r6; /* register args */ - uint32_t r7; /* register args */ - uint32_t r8; /* Caller-saved general purpose */ - uint32_t r9; /* Caller-saved general purpose */ - uint32_t r10; /* Caller-saved general purpose */ - uint32_t r11; /* Caller-saved general purpose */ - uint32_t r12; /* Caller-saved general purpose */ - uint32_t r13; /* Caller-saved general purpose */ - uint32_t r14; /* Caller-saved general purpose */ - uint32_t r15; /* Caller-saved general purpose */ - uint32_t estatus; - uint32_t instr; /* Instruction being executed when exc occurred */ -}; - -typedef struct __esf z_arch_esf_t; - FUNC_NORETURN void z_SysFatalErrorHandler(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); FUNC_NORETURN void z_NanoFatalErrorHandler(unsigned int reason, - const z_arch_esf_t *esf); + const struct arch_esf *esf); enum nios2_exception_cause { NIOS2_EXCEPTION_UNKNOWN = -1, diff --git a/include/zephyr/arch/nios2/exception.h b/include/zephyr/arch/nios2/exception.h new file mode 100644 index 0000000000000..223fa583114e6 --- /dev/null +++ b/include/zephyr/arch/nios2/exception.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_NIOS2_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_NIOS2_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct arch_esf { + uint32_t ra; /* return address r31 */ + uint32_t r1; /* at */ + uint32_t r2; /* return value */ + uint32_t r3; /* return value */ + uint32_t r4; /* register args */ + uint32_t r5; /* register args */ + uint32_t r6; /* register args */ + uint32_t r7; /* register args */ + uint32_t r8; /* Caller-saved general purpose */ + uint32_t r9; /* Caller-saved general purpose */ + uint32_t r10; /* Caller-saved general purpose */ + uint32_t r11; /* Caller-saved general purpose */ + uint32_t r12; /* Caller-saved general purpose */ + uint32_t r13; /* Caller-saved general purpose */ + uint32_t r14; /* Caller-saved general purpose */ + uint32_t r15; /* Caller-saved general purpose */ + uint32_t estatus; + uint32_t instr; /* Instruction being executed when exc occurred */ +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_NIOS2_EXPCEPTION_H_ */ diff --git a/include/zephyr/arch/nios2/linker.ld b/include/zephyr/arch/nios2/linker.ld index f7ba64088fc6e..d65805ba7cf1e 100644 --- a/include/zephyr/arch/nios2/linker.ld +++ b/include/zephyr/arch/nios2/linker.ld @@ -85,6 +85,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * .plt and .iplt are here according to * 'nios2-zephyr-elf-ld --verbose', before text section. diff --git a/include/zephyr/arch/posix/arch.h b/include/zephyr/arch/posix/arch.h index 83aceb1c14ba1..7dbfb6b386450 100644 --- a/include/zephyr/arch/posix/arch.h +++ b/include/zephyr/arch/posix/arch.h @@ -22,6 +22,7 @@ #include #include +#include #include #include #include /* Each board must define this */ @@ -38,12 +39,6 @@ extern "C" { #define ARCH_STACK_PTR_ALIGN 4 #endif -struct __esf { - uint32_t dummy; /*maybe we will want to add something someday*/ -}; - -typedef struct __esf z_arch_esf_t; - extern uint32_t sys_clock_cycle_get_32(void); static inline uint32_t arch_k_cycle_get_32(void) diff --git a/include/zephyr/arch/posix/exception.h b/include/zephyr/arch/posix/exception.h new file mode 100644 index 0000000000000..6c7962aa05799 --- /dev/null +++ b/include/zephyr/arch/posix/exception.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2010-2014 Wind River Systems, Inc. + * Copyright (c) 2017 Oticon A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_POSIX_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_POSIX_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct arch_esf { + uint32_t dummy; /*maybe we will want to add something someday*/ +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_POSIX_EXPCEPTION_H_ */ diff --git a/include/zephyr/arch/posix/linker.ld b/include/zephyr/arch/posix/linker.ld index 06dfb3254f172..0943546c0c7b0 100644 --- a/include/zephyr/arch/posix/linker.ld +++ b/include/zephyr/arch/posix/linker.ld @@ -21,6 +21,10 @@ SECTIONS { +#ifdef CONFIG_LLEXT +#include +#endif + SECTION_PROLOGUE(rom_start,,) { /* Located in generated directory. This file is populated by the diff --git a/include/zephyr/arch/riscv/arch.h b/include/zephyr/arch/riscv/arch.h index e7dcfbef3aed1..4cdedb700d326 100644 --- a/include/zephyr/arch/riscv/arch.h +++ b/include/zephyr/arch/riscv/arch.h @@ -48,12 +48,12 @@ */ #ifdef CONFIG_PMP_POWER_OF_TWO_ALIGNMENT #define Z_RISCV_STACK_GUARD_SIZE \ - Z_POW2_CEIL(MAX(sizeof(z_arch_esf_t) + CONFIG_PMP_STACK_GUARD_MIN_SIZE, \ + Z_POW2_CEIL(MAX(sizeof(struct arch_esf) + CONFIG_PMP_STACK_GUARD_MIN_SIZE, \ Z_RISCV_STACK_PMP_ALIGN)) #define ARCH_KERNEL_STACK_OBJ_ALIGN Z_RISCV_STACK_GUARD_SIZE #else #define Z_RISCV_STACK_GUARD_SIZE \ - ROUND_UP(sizeof(z_arch_esf_t) + CONFIG_PMP_STACK_GUARD_MIN_SIZE, \ + ROUND_UP(sizeof(struct arch_esf) + CONFIG_PMP_STACK_GUARD_MIN_SIZE, \ Z_RISCV_STACK_PMP_ALIGN) #define ARCH_KERNEL_STACK_OBJ_ALIGN Z_RISCV_STACK_PMP_ALIGN #endif diff --git a/include/zephyr/arch/riscv/atomic.h b/include/zephyr/arch/riscv/atomic.h new file mode 100644 index 0000000000000..986e4c2f8d822 --- /dev/null +++ b/include/zephyr/arch/riscv/atomic.h @@ -0,0 +1,149 @@ +/** + * Copyright (c) 2024 NextSilicon + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_RISCV_ATOMIC_H_ +#define ZEPHYR_INCLUDE_ARCH_RISCV_ATOMIC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* The standard RISC-V atomic-instruction extension, "A", specifies + * the number of instructions that atomically read-modify-write memory, + * which RISC-V harts should support in order to synchronise harts + * running in the same memory space. This is the subset of RISC-V + * atomic-instructions not present in atomic_builtin.h file. + */ + +#ifdef CONFIG_64BIT +static ALWAYS_INLINE atomic_val_t atomic_swap(const atomic_t *target, atomic_val_t newval) +{ + atomic_val_t ret; + + __asm__ volatile("amoswap.d.aq %0, %1, %2" + : "=r"(ret) + : "r"(newval), "A"(*target) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE atomic_val_t atomic_max(atomic_t *target, atomic_val_t value) +{ + atomic_val_t ret; + + __asm__ volatile("amomax.d.aq %0, %1, %2" + : "=r"(ret) + : "r"(value), "A"(*target) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE atomic_val_t atomic_min(atomic_t *target, atomic_val_t value) +{ + atomic_val_t ret; + + __asm__ volatile("amomin.d.aq %0, %1, %2" + : "=r"(ret) + : "r"(value), "A"(*target) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE atomic_val_t atomic_maxu(unsigned long *target, unsigned long value) +{ + unsigned long ret; + + __asm__ volatile("amomaxu.d.aq %0, %1, %2" + : "=r"(ret) + : "r"(value), "A"(*target) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE atomic_val_t atomic_minu(unsigned long *target, unsigned long value) +{ + unsigned long ret; + + __asm__ volatile("amominu.d.aq %0, %1, %2" + : "=r"(ret) + : "r"(value), "A"(*target) + : "memory"); + + return ret; +} + +#else + +static ALWAYS_INLINE atomic_val_t atomic_swap(const atomic_t *target, atomic_val_t newval) +{ + atomic_val_t ret; + + __asm__ volatile("amoswap.w.aq %0, %1, %2" + : "=r"(ret) + : "r"(newval), "A"(*target) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE atomic_val_t atomic_max(atomic_t *target, atomic_val_t value) +{ + atomic_val_t ret; + + __asm__ volatile("amomax.w.aq %0, %1, %2" + : "=r"(ret) + : "r"(value), "A"(*target) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE atomic_val_t atomic_min(atomic_t *target, atomic_val_t value) +{ + atomic_val_t ret; + + __asm__ volatile("amomin.w.aq %0, %1, %2" + : "=r"(ret) + : "r"(value), "A"(*target) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE unsigned long atomic_maxu(unsigned long *target, unsigned long value) +{ + unsigned long ret; + + __asm__ volatile("amomaxu.w.aq %0, %1, %2" + : "=r"(ret) + : "r"(value), "A"(*target) + : "memory"); + + return ret; +} + +static ALWAYS_INLINE unsigned long atomic_minu(unsigned long *target, unsigned long value) +{ + unsigned long ret; + + __asm__ volatile("amominu.w.aq %0, %1, %2" + : "=r"(ret) + : "r"(value), "A"(*target) + : "memory"); + + return ret; +} + +#endif /* CONFIG_64BIT */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_ARCH_RISCV_ATOMIC_H_ */ diff --git a/include/zephyr/arch/riscv/common/linker.ld b/include/zephyr/arch/riscv/common/linker.ld index ccb16cc2c670b..5b996bc48d57f 100644 --- a/include/zephyr/arch/riscv/common/linker.ld +++ b/include/zephyr/arch/riscv/common/linker.ld @@ -55,13 +55,18 @@ #elif DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_flash), jedec_spi_nor) /* For jedec,spi-nor we expect the spi controller to memory map the flash - * and for that mapping to be the second register property of the spi - * controller. + * and for that mapping to be on the register with the name flash_mmap and if a register with that + * name doesn't exists, we expect it to be in the second register property of the spi controller. */ #define SPI_CTRL DT_PARENT(DT_CHOSEN(zephyr_flash)) -#define ROM_BASE (DT_REG_ADDR_BY_IDX(SPI_CTRL, 1) + FLASH_LOAD_OFFSET) +#define FLASH_MMAP_NAME flash_mmap +#define ROM_BASE \ + (DT_REG_ADDR_BY_NAME_OR(SPI_CTRL, FLASH_MMAP_NAME, DT_REG_ADDR_BY_IDX(SPI_CTRL, 1)) + \ + FLASH_LOAD_OFFSET) #ifndef ROM_SIZE -#define ROM_SIZE (DT_REG_SIZE_BY_IDX(SPI_CTRL, 1) - ROM_END_OFFSET) +#define ROM_SIZE \ + (DT_REG_SIZE_BY_NAME_OR(SPI_CTRL, FLASH_MMAP_NAME, DT_REG_SIZE_BY_IDX(SPI_CTRL, 1)) - \ + ROM_END_OFFSET) #endif #else /* Use Kconfig to cover the remaining cases */ @@ -122,6 +127,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /* * The .plt and .iplt are here according to * 'riscv32-zephyr-elf-ld --verbose', before text section. diff --git a/include/zephyr/arch/riscv/error.h b/include/zephyr/arch/riscv/error.h index a7c3e02b48297..208eafadbe502 100644 --- a/include/zephyr/arch/riscv/error.h +++ b/include/zephyr/arch/riscv/error.h @@ -42,7 +42,7 @@ extern "C" { __syscall void user_fault(unsigned int reason); -#include +#include #ifdef __cplusplus } diff --git a/include/zephyr/arch/riscv/exception.h b/include/zephyr/arch/riscv/exception.h index 644df2cd1fbf9..097776227bb47 100644 --- a/include/zephyr/arch/riscv/exception.h +++ b/include/zephyr/arch/riscv/exception.h @@ -48,7 +48,7 @@ struct soc_esf { #if defined(CONFIG_RISCV_SOC_HAS_ISR_STACKING) SOC_ISR_STACKING_ESF_DECLARE; #else -struct __esf { +struct arch_esf { unsigned long ra; /* return address */ unsigned long t0; /* Caller-saved temporary register */ @@ -87,7 +87,6 @@ struct __esf { } __aligned(16); #endif /* CONFIG_RISCV_SOC_HAS_ISR_STACKING */ -typedef struct __esf z_arch_esf_t; #ifdef CONFIG_RISCV_SOC_CONTEXT_SAVE typedef struct soc_esf soc_esf_t; #endif diff --git a/include/zephyr/arch/sparc/arch.h b/include/zephyr/arch/sparc/arch.h index df3c40e4ba4a3..c1d87682f39bb 100644 --- a/include/zephyr/arch/sparc/arch.h +++ b/include/zephyr/arch/sparc/arch.h @@ -14,6 +14,7 @@ #ifndef ZEPHYR_INCLUDE_ARCH_SPARC_ARCH_H_ #define ZEPHYR_INCLUDE_ARCH_SPARC_ARCH_H_ +#include #include #include #include @@ -107,19 +108,6 @@ static inline uint64_t arch_k_cycle_get_64(void) return sys_clock_cycle_get_64(); } -struct __esf { - uint32_t out[8]; - uint32_t global[8]; - uint32_t psr; - uint32_t pc; - uint32_t npc; - uint32_t wim; - uint32_t tbr; - uint32_t y; -}; - -typedef struct __esf z_arch_esf_t; - #define ARCH_EXCEPT(reason_p) \ do { \ register uint32_t _g1 __asm__("g1") = reason_p; \ diff --git a/include/zephyr/arch/sparc/exception.h b/include/zephyr/arch/sparc/exception.h new file mode 100644 index 0000000000000..a2d3fae52e203 --- /dev/null +++ b/include/zephyr/arch/sparc/exception.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019-2020 Cobham Gaisler AB + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_SPARC_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_SPARC_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct arch_esf { + uint32_t out[8]; + uint32_t global[8]; + uint32_t psr; + uint32_t pc; + uint32_t npc; + uint32_t wim; + uint32_t tbr; + uint32_t y; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_SPARC_EXPCEPTION_H_ */ diff --git a/include/zephyr/arch/sparc/linker.ld b/include/zephyr/arch/sparc/linker.ld index 725339ef0b7cd..ccf333d4863c4 100644 --- a/include/zephyr/arch/sparc/linker.ld +++ b/include/zephyr/arch/sparc/linker.ld @@ -23,6 +23,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + __rom_region_start = .; SECTION_PROLOGUE(_TEXT_SECTION_NAME,,) diff --git a/include/zephyr/arch/syscall.h b/include/zephyr/arch/syscall.h index 5b41561b68190..966f6003098ba 100644 --- a/include/zephyr/arch/syscall.h +++ b/include/zephyr/arch/syscall.h @@ -9,12 +9,10 @@ #ifndef ZEPHYR_INCLUDE_ARCH_SYSCALL_H_ #define ZEPHYR_INCLUDE_ARCH_SYSCALL_H_ -#if defined(CONFIG_X86) #if defined(CONFIG_X86_64) #include -#else +#elif defined(CONFIG_X86) #include -#endif #elif defined(CONFIG_ARM64) #include #elif defined(CONFIG_ARM) diff --git a/include/zephyr/arch/x86/arch.h b/include/zephyr/arch/x86/arch.h index f7e75b3aab615..61036288671c8 100644 --- a/include/zephyr/arch/x86/arch.h +++ b/include/zephyr/arch/x86/arch.h @@ -219,7 +219,7 @@ static ALWAYS_INLINE int sys_test_and_clear_bit(mem_addr_t addr, extern unsigned char _irq_to_interrupt_vector[]; #define Z_IRQ_TO_INTERRUPT_VECTOR(irq) \ - ((unsigned int) _irq_to_interrupt_vector[irq]) + ((unsigned int) _irq_to_interrupt_vector[(irq)]) #endif /* _ASMLANGUAGE */ @@ -244,10 +244,10 @@ extern "C" { #ifndef _ASMLANGUAGE -extern void arch_irq_enable(unsigned int irq); -extern void arch_irq_disable(unsigned int irq); +void arch_irq_enable(unsigned int irq); +void arch_irq_disable(unsigned int irq); -extern uint32_t sys_clock_cycle_get_32(void); +uint32_t sys_clock_cycle_get_32(void); __pinned_func static inline uint32_t arch_k_cycle_get_32(void) @@ -255,7 +255,7 @@ static inline uint32_t arch_k_cycle_get_32(void) return sys_clock_cycle_get_32(); } -extern uint64_t sys_clock_cycle_get_64(void); +uint64_t sys_clock_cycle_get_64(void); __pinned_func static inline uint64_t arch_k_cycle_get_64(void) diff --git a/include/zephyr/arch/x86/ia32/arch.h b/include/zephyr/arch/x86/ia32/arch.h index 8e85ccaea111f..b82e0db0f1733 100644 --- a/include/zephyr/arch/x86/ia32/arch.h +++ b/include/zephyr/arch/x86/ia32/arch.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -250,7 +251,7 @@ static inline void arch_irq_direct_pm(void) { if (_kernel.idle) { _kernel.idle = 0; - z_pm_save_idle_exit(); + pm_system_resume(); } } @@ -266,8 +267,8 @@ static inline void arch_irq_direct_pm(void) * tracing/tracing.h cannot be included here due to circular dependency */ #if defined(CONFIG_TRACING) -extern void sys_trace_isr_enter(void); -extern void sys_trace_isr_exit(void); +void sys_trace_isr_enter(void); +void sys_trace_isr_exit(void); #endif static inline void arch_isr_direct_header(void) @@ -287,7 +288,7 @@ static inline void arch_isr_direct_header(void) * cannot be referenced from a public header, so we move it to an * external function. */ -extern void arch_isr_direct_footer_swap(unsigned int key); +void arch_isr_direct_footer_swap(unsigned int key); static inline void arch_isr_direct_footer(int swap) { @@ -333,53 +334,6 @@ static inline void arch_isr_direct_footer(int swap) static inline int name##_body(void) #endif /* !CONFIG_X86_KPTI */ -/** - * @brief Exception Stack Frame - * - * A pointer to an "exception stack frame" (ESF) is passed as an argument - * to exception handlers registered via nanoCpuExcConnect(). As the system - * always operates at ring 0, only the EIP, CS and EFLAGS registers are pushed - * onto the stack when an exception occurs. - * - * The exception stack frame includes the volatile registers (EAX, ECX, and - * EDX) as well as the 5 non-volatile registers (EDI, ESI, EBX, EBP and ESP). - * Those registers are pushed onto the stack by _ExcEnt(). - */ - -typedef struct nanoEsf { -#ifdef CONFIG_GDBSTUB - unsigned int ss; - unsigned int gs; - unsigned int fs; - unsigned int es; - unsigned int ds; -#endif - unsigned int esp; - unsigned int ebp; - unsigned int ebx; - unsigned int esi; - unsigned int edi; - unsigned int edx; - unsigned int eax; - unsigned int ecx; - unsigned int errorCode; - unsigned int eip; - unsigned int cs; - unsigned int eflags; -} z_arch_esf_t; - -extern unsigned int z_x86_exception_vector; - -struct _x86_syscall_stack_frame { - uint32_t eip; - uint32_t cs; - uint32_t eflags; - - /* These are only present if cs = USER_CODE_SEG */ - uint32_t esp; - uint32_t ss; -}; - static ALWAYS_INLINE unsigned int arch_irq_lock(void) { unsigned int key; diff --git a/include/zephyr/arch/x86/ia32/exception.h b/include/zephyr/arch/x86/ia32/exception.h new file mode 100644 index 0000000000000..de618f4e01d43 --- /dev/null +++ b/include/zephyr/arch/x86/ia32/exception.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2010-2014 Wind River Systems, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_X86_IA32_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_X86_IA32_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Exception Stack Frame + * + * A pointer to an "exception stack frame" (ESF) is passed as an argument + * to exception handlers registered via nanoCpuExcConnect(). As the system + * always operates at ring 0, only the EIP, CS and EFLAGS registers are pushed + * onto the stack when an exception occurs. + * + * The exception stack frame includes the volatile registers (EAX, ECX, and + * EDX) as well as the 5 non-volatile registers (EDI, ESI, EBX, EBP and ESP). + * Those registers are pushed onto the stack by _ExcEnt(). + */ + +struct arch_esf { +#ifdef CONFIG_GDBSTUB + unsigned int ss; + unsigned int gs; + unsigned int fs; + unsigned int es; + unsigned int ds; +#endif + unsigned int esp; + unsigned int ebp; + unsigned int ebx; + unsigned int esi; + unsigned int edi; + unsigned int edx; + unsigned int eax; + unsigned int ecx; + unsigned int errorCode; + unsigned int eip; + unsigned int cs; + unsigned int eflags; +}; + +extern unsigned int z_x86_exception_vector; + +struct _x86_syscall_stack_frame { + uint32_t eip; + uint32_t cs; + uint32_t eflags; + + /* These are only present if cs = USER_CODE_SEG */ + uint32_t esp; + uint32_t ss; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_X86_IA32_EXPCEPTION_H_ */ diff --git a/include/zephyr/arch/x86/ia32/linker.ld b/include/zephyr/arch/x86/ia32/linker.ld index a0e2f5c6732eb..5994379eeefc8 100644 --- a/include/zephyr/arch/x86/ia32/linker.ld +++ b/include/zephyr/arch/x86/ia32/linker.ld @@ -38,13 +38,13 @@ */ #include -#include +#include #include #include #include -#if defined(CONFIG_XIP) || defined(Z_VM_KERNEL) +#if defined(CONFIG_XIP) || defined(K_MEM_IS_VM_KERNEL) #define ROMABLE_REGION ROM #define RAMABLE_REGION RAM #else @@ -68,7 +68,7 @@ #define MMU_PAGE_ALIGN_PERM #endif -epoint = Z_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY); +epoint = K_MEM_PHYS_ADDR(CONFIG_KERNEL_ENTRY); ENTRY(epoint) /* SECTIONS definitions */ @@ -77,6 +77,10 @@ SECTIONS #include +#ifdef CONFIG_LLEXT +#include +#endif + /DISCARD/ : { *(.plt) @@ -417,43 +421,10 @@ SECTIONS _app_smem_num_words = _app_smem_size >> 2; #endif /* CONFIG_USERSPACE */ - SECTION_PROLOGUE(_BSS_SECTION_NAME, (NOLOAD),) - { - MMU_PAGE_ALIGN_PERM -#if !defined(CONFIG_USERSPACE) - _image_ram_start = .; -#endif - /* - * For performance, BSS section is forced to be both 4 byte aligned and - * a multiple of 4 bytes. - */ - . = ALIGN(4); - __kernel_ram_start = .; - __bss_start = .; - - *(.bss) - *(".bss.*") - *(COMMON) - *(".kernel_bss.*") - - /* - * As memory is cleared in words only, it is simpler to ensure the BSS - * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. - */ - . = ALIGN(4); - __bss_end = .; - } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) - - __bss_num_words = (__bss_end - __bss_start) >> 2; - -#include - - MMU_PAGE_ALIGN_PERM - - SECTION_DATA_PROLOGUE(_DATA_SECTION_NAME,,) { + MMU_PAGE_ALIGN_PERM __data_region_start = .; __data_start = .; @@ -503,6 +474,39 @@ SECTIONS MMU_PAGE_ALIGN __data_region_end = .; + SECTION_PROLOGUE(_BSS_SECTION_NAME, (NOLOAD),) + { + MMU_PAGE_ALIGN_PERM +#if !defined(CONFIG_USERSPACE) + _image_ram_start = .; +#endif + /* + * For performance, BSS section is forced to be both 4 byte aligned and + * a multiple of 4 bytes. + */ + . = ALIGN(4); + __kernel_ram_start = .; + __bss_start = .; + + *(.bss) + *(".bss.*") + *(COMMON) + *(".kernel_bss.*") + + /* + * As memory is cleared in words only, it is simpler to ensure the BSS + * section ends on a 4 byte boundary. This wastes a maximum of 3 bytes. + */ + . = ALIGN(4); + __bss_end = .; + } GROUP_NOLOAD_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + + __bss_num_words = (__bss_end - __bss_start) >> 2; + +#include + + MMU_PAGE_ALIGN_PERM + /* All unused memory also owned by the kernel for heaps */ __kernel_ram_end = KERNEL_BASE_ADDR + KERNEL_RAM_SIZE; __kernel_ram_size = __kernel_ram_end - __kernel_ram_start; diff --git a/include/zephyr/arch/x86/intel64/arch.h b/include/zephyr/arch/x86/intel64/arch.h index c176e4e0bb0ba..86de01297f472 100644 --- a/include/zephyr/arch/x86/intel64/arch.h +++ b/include/zephyr/arch/x86/intel64/arch.h @@ -6,6 +6,7 @@ #ifndef ZEPHYR_INCLUDE_ARCH_X86_INTEL64_ARCH_H_ #define ZEPHYR_INCLUDE_ARCH_X86_INTEL64_ARCH_H_ +#include #include #include #if defined(CONFIG_PCIE) && !defined(_ASMLANGUAGE) @@ -52,61 +53,6 @@ static ALWAYS_INLINE unsigned int arch_irq_lock(void) return (unsigned int) key; } -/* - * the exception stack frame - */ - -struct x86_esf { -#ifdef CONFIG_EXCEPTION_DEBUG - /* callee-saved */ - unsigned long rbx; - unsigned long r12; - unsigned long r13; - unsigned long r14; - unsigned long r15; -#endif /* CONFIG_EXCEPTION_DEBUG */ - unsigned long rbp; - - /* Caller-saved regs */ - unsigned long rax; - unsigned long rcx; - unsigned long rdx; - unsigned long rsi; - unsigned long rdi; - unsigned long r8; - unsigned long r9; - unsigned long r10; - /* Must be aligned 16 bytes from the end of this struct due to - * requirements of 'fxsave (%rsp)' - */ - char fxsave[X86_FXSAVE_SIZE]; - unsigned long r11; - - /* Pushed by CPU or assembly stub */ - unsigned long vector; - unsigned long code; - unsigned long rip; - unsigned long cs; - unsigned long rflags; - unsigned long rsp; - unsigned long ss; -}; - -typedef struct x86_esf z_arch_esf_t; - -struct x86_ssf { - unsigned long rip; - unsigned long rflags; - unsigned long r10; - unsigned long r9; - unsigned long r8; - unsigned long rdx; - unsigned long rsi; - char fxsave[X86_FXSAVE_SIZE]; - unsigned long rdi; - unsigned long rsp; -}; - #define ARCH_EXCEPT(reason_p) do { \ __asm__ volatile( \ "movq %[reason], %%rax\n\t" \ diff --git a/include/zephyr/arch/x86/intel64/exception.h b/include/zephyr/arch/x86/intel64/exception.h new file mode 100644 index 0000000000000..55c7cc2b4ee84 --- /dev/null +++ b/include/zephyr/arch/x86/intel64/exception.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2019 Intel Corp. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ARCH_X86_INTEL64_EXPCEPTION_H_ +#define ZEPHYR_INCLUDE_ARCH_X86_INTEL64_EXPCEPTION_H_ + +#ifndef _ASMLANGUAGE +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * the exception stack frame + */ + +struct arch_esf { +#ifdef CONFIG_EXCEPTION_DEBUG + /* callee-saved */ + unsigned long rbx; + unsigned long r12; + unsigned long r13; + unsigned long r14; + unsigned long r15; +#endif /* CONFIG_EXCEPTION_DEBUG */ + unsigned long rbp; + + /* Caller-saved regs */ + unsigned long rax; + unsigned long rcx; + unsigned long rdx; + unsigned long rsi; + unsigned long rdi; + unsigned long r8; + unsigned long r9; + unsigned long r10; + /* Must be aligned 16 bytes from the end of this struct due to + * requirements of 'fxsave (%rsp)' + */ + char fxsave[X86_FXSAVE_SIZE]; + unsigned long r11; + + /* Pushed by CPU or assembly stub */ + unsigned long vector; + unsigned long code; + unsigned long rip; + unsigned long cs; + unsigned long rflags; + unsigned long rsp; + unsigned long ss; +}; + +struct x86_ssf { + unsigned long rip; + unsigned long rflags; + unsigned long r10; + unsigned long r9; + unsigned long r8; + unsigned long rdx; + unsigned long rsi; + char fxsave[X86_FXSAVE_SIZE]; + unsigned long rdi; + unsigned long rsp; +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _ASMLANGUAGE */ + +#endif /* ZEPHYR_INCLUDE_ARCH_X86_INTEL64_EXPCEPTION_H_ */ diff --git a/include/zephyr/arch/x86/intel64/linker.ld b/include/zephyr/arch/x86/intel64/linker.ld index 8949b94e657fd..1bc014570c638 100644 --- a/include/zephyr/arch/x86/intel64/linker.ld +++ b/include/zephyr/arch/x86/intel64/linker.ld @@ -236,4 +236,7 @@ SECTIONS .shstrtab 0 : { *(.shstrtab) } #endif +#ifdef CONFIG_LLEXT + #include +#endif } diff --git a/include/zephyr/arch/x86/memory.ld b/include/zephyr/arch/x86/memory.ld index c9ede2b9d2329..3e2c0b6935275 100644 --- a/include/zephyr/arch/x86/memory.ld +++ b/include/zephyr/arch/x86/memory.ld @@ -39,7 +39,7 @@ * the same as its physical location, although an identity mapping for RAM * is still supported by setting CONFIG_KERNEL_VM_BASE=CONFIG_SRAM_BASE_ADDRESS. */ -#ifdef Z_VM_KERNEL +#ifdef K_MEM_IS_VM_KERNEL #define KERNEL_BASE_ADDR (CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_OFFSET) #define KERNEL_RAM_SIZE (CONFIG_KERNEL_VM_SIZE - CONFIG_KERNEL_VM_OFFSET) #define PHYS_RAM_AVAIL (PHYS_RAM_SIZE - CONFIG_SRAM_OFFSET) @@ -87,7 +87,7 @@ MEMORY * or copied into physical RAM by a loader (MMU) */ ROM (rx) : ORIGIN = PHYS_LOAD_ADDR, LENGTH = FLASH_ROM_SIZE -#elif defined(Z_VM_KERNEL) +#elif defined(K_MEM_IS_VM_KERNEL) ROM (rx) : ORIGIN = PHYS_LOAD_ADDR, LENGTH = PHYS_RAM_AVAIL #endif /* Linear address range to link the kernel. If non-XIP, everything is diff --git a/include/zephyr/arch/x86/multiboot.h b/include/zephyr/arch/x86/multiboot.h index 9a951a0150f08..66c312e48e242 100644 --- a/include/zephyr/arch/x86/multiboot.h +++ b/include/zephyr/arch/x86/multiboot.h @@ -40,7 +40,7 @@ extern struct multiboot_info multiboot_info; #ifdef CONFIG_MULTIBOOT_INFO -extern void z_multiboot_init(struct multiboot_info *info_pa); +void z_multiboot_init(struct multiboot_info *info_pa); #else diff --git a/include/zephyr/arch/xtensa/arch.h b/include/zephyr/arch/xtensa/arch.h index 0b29df511b7fa..41072c5c8320e 100644 --- a/include/zephyr/arch/xtensa/arch.h +++ b/include/zephyr/arch/xtensa/arch.h @@ -79,7 +79,7 @@ struct arch_mem_domain { * * @param reason_p Reason for exception. */ -extern void xtensa_arch_except(int reason_p); +void xtensa_arch_except(int reason_p); /** * @brief Generate kernel oops. @@ -89,7 +89,7 @@ extern void xtensa_arch_except(int reason_p); * @param reason_p Reason for exception. * @param ssf Stack pointer. */ -extern void xtensa_arch_kernel_oops(int reason_p, void *ssf); +void xtensa_arch_kernel_oops(int reason_p, void *ssf); #ifdef CONFIG_USERSPACE @@ -114,10 +114,10 @@ extern void xtensa_arch_kernel_oops(int reason_p, void *ssf); __syscall void xtensa_user_fault(unsigned int reason); -#include +#include /* internal routine documented in C file, needed by IRQ_CONNECT() macro */ -extern void z_irq_priority_set(uint32_t irq, uint32_t prio, uint32_t flags); +void z_irq_priority_set(uint32_t irq, uint32_t prio, uint32_t flags); #define ARCH_IRQ_CONNECT(irq_p, priority_p, isr_p, isr_param_p, flags_p) \ { \ @@ -237,7 +237,7 @@ static inline bool arch_mem_coherent(void *ptr) * @param is_core0 True if this is called while executing on * CPU core #0. */ -extern void arch_xtensa_mmu_post_init(bool is_core0); +void arch_xtensa_mmu_post_init(bool is_core0); #endif #ifdef __cplusplus diff --git a/include/zephyr/arch/xtensa/arch_inlines.h b/include/zephyr/arch/xtensa/arch_inlines.h index 4e7b52002768a..e8ceb3c973399 100644 --- a/include/zephyr/arch/xtensa/arch_inlines.h +++ b/include/zephyr/arch/xtensa/arch_inlines.h @@ -11,7 +11,7 @@ #ifndef _ASMLANGUAGE #include -#include +#include /** * @brief Read a special register. diff --git a/include/zephyr/arch/xtensa/exception.h b/include/zephyr/arch/xtensa/exception.h index 51a5d5aef9036..acc6d4a30413b 100644 --- a/include/zephyr/arch/xtensa/exception.h +++ b/include/zephyr/arch/xtensa/exception.h @@ -25,7 +25,9 @@ extern "C" { * register windows are in use. This isn't a struct type, it just * matches the register/stack-unit width. */ -typedef int z_arch_esf_t; +struct arch_esf { + int dummy; +}; #endif diff --git a/include/zephyr/arch/xtensa/irq.h b/include/zephyr/arch/xtensa/irq.h index 938ab7b2303c2..3df8639ac737a 100644 --- a/include/zephyr/arch/xtensa/irq.h +++ b/include/zephyr/arch/xtensa/irq.h @@ -160,7 +160,7 @@ static ALWAYS_INLINE bool arch_irq_unlocked(unsigned int key) * * @return True if interrupt is enabled, false otherwise. */ -extern int xtensa_irq_is_enabled(unsigned int irq); +int xtensa_irq_is_enabled(unsigned int irq); #include diff --git a/include/zephyr/arch/xtensa/xtensa_mmu.h b/include/zephyr/arch/xtensa/xtensa_mmu.h index d4deca40b311b..91da6a4f65688 100644 --- a/include/zephyr/arch/xtensa/xtensa_mmu.h +++ b/include/zephyr/arch/xtensa/xtensa_mmu.h @@ -123,6 +123,16 @@ extern int xtensa_soc_mmu_ranges_num; */ void xtensa_mmu_init(void); +/** + * @brief Re-initialize hardware MMU. + * + * This configures the MMU hardware when the cpu lost context and has + * re-started. + * + * It assumes that the page table is already created and accessible in memory. + */ +void xtensa_mmu_reinit(void); + /** * @brief Tell other processors to flush TLBs. * diff --git a/include/zephyr/bluetooth/audio/aics.h b/include/zephyr/bluetooth/audio/aics.h index dbaf7383e652c..a554c1503959a 100644 --- a/include/zephyr/bluetooth/audio/aics.h +++ b/include/zephyr/bluetooth/audio/aics.h @@ -12,6 +12,9 @@ * * @defgroup bt_gatt_aics Audio Input Control Service (AICS) * + * @since 2.6 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * @@ -23,9 +26,11 @@ * automatically handle any changes to that. If out of date, the client implementation will * autonomously read the change counter value when executing a write request. * - * [Experimental] Users should note that the APIs can change as a part of ongoing development. */ +#include +#include +#include #include #ifdef __cplusplus diff --git a/include/zephyr/bluetooth/audio/audio.h b/include/zephyr/bluetooth/audio/audio.h index 4274279890039..f847ef35bc397 100644 --- a/include/zephyr/bluetooth/audio/audio.h +++ b/include/zephyr/bluetooth/audio/audio.h @@ -18,14 +18,21 @@ * @{ */ -#include +#include +#include +#include + +#include +#include +#include #include #include +#include #include #include -#include -#include - +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -41,6 +48,14 @@ extern "C" { #define BT_AUDIO_BROADCAST_CODE_SIZE 16 +/** The minimum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */ +#define BT_AUDIO_BROADCAST_NAME_LEN_MIN 4 +/** The maximum size of a Broadcast Name as defined by Bluetooth Assigned Numbers */ +#define BT_AUDIO_BROADCAST_NAME_LEN_MAX 128 + +/** Size of the stream language value, e.g. "eng" */ +#define BT_AUDIO_LANG_SIZE 3 + /** * @brief Codec capability types * @@ -373,11 +388,12 @@ enum bt_audio_metadata_type { /** UTF-8 encoded title or summary of stream content */ BT_AUDIO_METADATA_TYPE_PROGRAM_INFO = 0x03, - /** @brief Stream language + /** @brief Language * * 3 octet lower case language code defined by ISO 639-3 + * Possible values can be found at https://iso639-3.sil.org/code_tables/639/data */ - BT_AUDIO_METADATA_TYPE_STREAM_LANG = 0x04, + BT_AUDIO_METADATA_TYPE_LANG = 0x04, /** Array of 8-bit CCID values */ BT_AUDIO_METADATA_TYPE_CCID_LIST = 0x05, @@ -631,6 +647,15 @@ struct bt_audio_codec_cfg { int bt_audio_data_parse(const uint8_t ltv[], size_t size, bool (*func)(struct bt_data *data, void *user_data), void *user_data); +/** + * @brief Function to get the number of channels from the channel allocation + * + * @param chan_allocation The channel allocation + * + * @return The number of channels + */ +uint8_t bt_audio_get_chan_count(enum bt_audio_location chan_allocation); + /** @brief Audio Capability type */ enum bt_audio_dir { BT_AUDIO_DIR_SINK = 0x01, @@ -702,60 +727,95 @@ enum { /** @brief Codec QoS structure. */ struct bt_audio_codec_qos { - /** QoS PHY */ - uint8_t phy; - - /** QoS Framing */ - enum bt_audio_codec_qos_framing framing; - - /** QoS Retransmission Number */ - uint8_t rtn; - - /** QoS SDU */ - uint16_t sdu; - -#if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_UNICAST) /** - * @brief QoS Transport Latency + * @brief Presentation Delay in microseconds * - * Not used for the @kconfig{CONFIG_BT_BAP_BROADCAST_SINK} role. - */ - uint16_t latency; -#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE || CONFIG_BT_BAP_UNICAST */ - - /** QoS Frame Interval */ - uint32_t interval; - - /** @brief QoS Presentation Delay in microseconds + * This value can be changed up and until bt_bap_stream_qos() has been called. + * Once a stream has been QoS configured, modifying this field does not modify the value. + * It is however possible to modify this field and call bt_bap_stream_qos() again to update + * the value, assuming that the stream is in the correct state. * - * Value range 0 to @ref BT_AUDIO_PD_MAX. + * Value range 0 to @ref BT_AUDIO_PD_MAX. */ uint32_t pd; -#if defined(CONFIG_BT_ISO_TEST_PARAMS) - /** @brief Maximum PDU size - * - * Maximum size, in octets, of the payload from link layer to link - * layer. + /** + * @brief Connected Isochronous Group (CIG) parameters * - * Value range @ref BT_ISO_PDU_MIN to @ref BT_ISO_PDU_MAX. + * The fields in this struct affect the value sent to the controller via HCI + * when creating the CIG. Once the group has been created with + * bt_bap_unicast_group_create(), modifying these fields will not affect the group. */ - uint16_t max_pdu; + struct { + /** QoS Framing */ + enum bt_audio_codec_qos_framing framing; + + /** + * @brief PHY + * + * Allowed values are @ref BT_AUDIO_CODEC_QOS_1M, @ref BT_AUDIO_CODEC_QOS_2M and + * @ref BT_AUDIO_CODEC_QOS_CODED. + */ + uint8_t phy; + + /** + * @brief Retransmission Number + * + * This a recommendation to the controller, and the actual retransmission number + * may be different than this. + */ + uint8_t rtn; + + /** + * @brief Maximum SDU size + * + * Value range @ref BT_ISO_MIN_SDU to @ref BT_ISO_MAX_SDU. + */ + uint16_t sdu; - /** @brief Burst number - * - * Value range @ref BT_ISO_BN_MIN to @ref BT_ISO_BN_MAX. - */ - uint8_t burst_number; +#if defined(CONFIG_BT_BAP_BROADCAST_SOURCE) || defined(CONFIG_BT_BAP_UNICAST) + /** + * @brief Maximum Transport Latency + * + * Not used for the @kconfig{CONFIG_BT_BAP_BROADCAST_SINK} role. + */ + uint16_t latency; +#endif /* CONFIG_BT_BAP_BROADCAST_SOURCE || CONFIG_BT_BAP_UNICAST */ - /** @brief Number of subevents - * - * Maximum number of subevents in each CIS or BIS event. - * - * Value range @ref BT_ISO_NSE_MIN to @ref BT_ISO_NSE_MAX. - */ - uint8_t num_subevents; + /** + * @brief SDU Interval + * + * Value range @ref BT_ISO_SDU_INTERVAL_MIN to @ref BT_ISO_SDU_INTERVAL_MAX + */ + uint32_t interval; + +#if defined(CONFIG_BT_ISO_TEST_PARAMS) + /** + * @brief Maximum PDU size + * + * Maximum size, in octets, of the payload from link layer to link layer. + * + * Value range @ref BT_ISO_PDU_MIN to @ref BT_ISO_PDU_MAX. + */ + uint16_t max_pdu; + + /** + * @brief Burst number + * + * Value range @ref BT_ISO_BN_MIN to @ref BT_ISO_BN_MAX. + */ + uint8_t burst_number; + + /** + * @brief Number of subevents + * + * Maximum number of subevents in each CIS or BIS event. + * + * Value range @ref BT_ISO_NSE_MIN to @ref BT_ISO_NSE_MAX. + */ + uint8_t num_subevents; #endif /* CONFIG_BT_ISO_TEST_PARAMS */ + }; }; /** @@ -931,24 +991,29 @@ int bt_audio_codec_cfg_get_frame_dur(const struct bt_audio_codec_cfg *codec_cfg) int bt_audio_codec_cfg_set_frame_dur(struct bt_audio_codec_cfg *codec_cfg, enum bt_audio_codec_cfg_frame_dur frame_dur); -/** @brief Extract channel allocation from BT codec config +/** + * @brief Extract channel allocation from BT codec config * - * The value returned is a bit field representing one or more audio locations as - * specified by @ref bt_audio_location - * Shall match one or more of the bits set in BT_PAC_SNK_LOC/BT_PAC_SRC_LOC. + * The value returned is a bit field representing one or more audio locations as + * specified by @ref bt_audio_location + * Shall match one or more of the bits set in BT_PAC_SNK_LOC/BT_PAC_SRC_LOC. * - * Up to the configured @ref BT_AUDIO_CODEC_CAP_TYPE_CHAN_COUNT number of channels can be present. + * Up to the configured @ref BT_AUDIO_CODEC_CAP_TYPE_CHAN_COUNT number of channels can be present. * - * @param codec_cfg The codec configuration to extract data from. - * @param chan_allocation Pointer to the variable to store the extracted value in. + * @param codec_cfg The codec configuration to extract data from. + * @param chan_allocation Pointer to the variable to store the extracted value in. + * @param fallback_to_default If true this function will provide the default value of + * @ref BT_AUDIO_LOCATION_MONO_AUDIO if the type is not found when @p codec_cfg.id is @ref + * BT_HCI_CODING_FORMAT_LC3. * - * @retval 0 if value is found and stored in the pointer provided - * @retval -EINVAL if arguments are invalid - * @retval -ENODATA if not found - * @retval -EBADMSG if found value has invalid size or value + * @retval 0 if value is found and stored in the pointer provided + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value */ int bt_audio_codec_cfg_get_chan_allocation(const struct bt_audio_codec_cfg *codec_cfg, - enum bt_audio_location *chan_allocation); + enum bt_audio_location *chan_allocation, + bool fallback_to_default); /** * @brief Set the channel allocation of a codec configuration. @@ -967,7 +1032,7 @@ int bt_audio_codec_cfg_set_chan_allocation(struct bt_audio_codec_cfg *codec_cfg, * * The overall SDU size will be octets_per_frame * blocks_per_sdu. * - * The Bluetooth specificationa are not clear about this value - it does not state that + * The Bluetooth specifications are not clear about this value - it does not state that * the codec shall use this SDU size only. A codec like LC3 supports variable bit-rate * (per SDU) hence it might be allowed for an encoder to reduce the frame size below this * value. @@ -996,26 +1061,25 @@ int bt_audio_codec_cfg_get_octets_per_frame(const struct bt_audio_codec_cfg *cod int bt_audio_codec_cfg_set_octets_per_frame(struct bt_audio_codec_cfg *codec_cfg, uint16_t octets_per_frame); -/** @brief Extract number of audio frame blockss in each SDU from BT codec config +/** + * @brief Extract number of audio frame blocks in each SDU from BT codec config * - * The overall SDU size will be octets_per_frame * frame_blocks_per_sdu * number-of-channels. + * The overall SDU size will be octets_per_frame * frame_blocks_per_sdu * number-of-channels. * - * If this value is not present a default value of 1 shall be used. + * If this value is not present a default value of 1 shall be used. * - * A frame block is one or more frames that represents data for the same period of time but - * for different channels. If the stream have two audio channels and this value is two - * there will be four frames in the SDU. + * A frame block is one or more frames that represents data for the same period of time but + * for different channels. If the stream have two audio channels and this value is two + * there will be four frames in the SDU. * - * @param codec_cfg The codec configuration to extract data from. - * @param fallback_to_default If true this function will return the default value of 1 - * if the type is not found. In this case the function will only fail if a NULL - * pointer is provided. + * @param codec_cfg The codec configuration to extract data from. + * @param fallback_to_default If true this function will return the default value of 1 + * if the type is not found when @p codec_cfg.id is @ref BT_HCI_CODING_FORMAT_LC3. * - * @retval The count of codec frames in each SDU if value is found else of @p fallback_to_default - * is true then the value 1 is returned if frames per sdu is not found. - * @retval -EINVAL if arguments are invalid - * @retval -ENODATA if not found - * @retval -EBADMSG if found value has invalid size or value + * @retval The count of codec frame blocks in each SDU. + * @retval -EINVAL if arguments are invalid + * @retval -ENODATA if not found + * @retval -EBADMSG if found value has invalid size or value */ int bt_audio_codec_cfg_get_frame_blocks_per_sdu(const struct bt_audio_codec_cfg *codec_cfg, bool fallback_to_default); @@ -1119,18 +1183,23 @@ int bt_audio_codec_cfg_meta_set_val(struct bt_audio_codec_cfg *codec_cfg, */ int bt_audio_codec_cfg_meta_unset_val(struct bt_audio_codec_cfg *codec_cfg, enum bt_audio_metadata_type type); -/** @brief Extract preferred contexts +/** + * @brief Extract preferred contexts * - * See @ref BT_AUDIO_METADATA_TYPE_PREF_CONTEXT for more information about this value. + * See @ref BT_AUDIO_METADATA_TYPE_PREF_CONTEXT for more information about this value. * - * @param codec_cfg The codec data to search in. + * @param codec_cfg The codec data to search in. + * @param fallback_to_default If true this function will provide the default value of + * @ref BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED if the type is not found when @p codec_cfg.id is + * @ref BT_HCI_CODING_FORMAT_LC3. * * @retval The preferred context type if positive or 0 * @retval -EINVAL if arguments are invalid * @retval -ENODATA if not found * @retval -EBADMSG if found value has invalid size */ -int bt_audio_codec_cfg_meta_get_pref_context(const struct bt_audio_codec_cfg *codec_cfg); +int bt_audio_codec_cfg_meta_get_pref_context(const struct bt_audio_codec_cfg *codec_cfg, + bool fallback_to_default); /** * @brief Set the preferred context of a codec configuration metadata. @@ -1199,31 +1268,33 @@ int bt_audio_codec_cfg_meta_get_program_info(const struct bt_audio_codec_cfg *co int bt_audio_codec_cfg_meta_set_program_info(struct bt_audio_codec_cfg *codec_cfg, const uint8_t *program_info, size_t program_info_len); -/** @brief Extract stream language +/** @brief Extract language * - * See @ref BT_AUDIO_METADATA_TYPE_STREAM_LANG for more information about this value. + * See @ref BT_AUDIO_METADATA_TYPE_LANG for more information about this value. * - * @param codec_cfg The codec data to search in. + * @param[in] codec_cfg The codec data to search in. + * @param[out] lang Pointer to the language bytes (of length BT_AUDIO_LANG_SIZE) * - * @retval The stream language if positive or 0 + * @retval The language if positive or 0 * @retval -EINVAL if arguments are invalid * @retval -ENODATA if not found * @retval -EBADMSG if found value has invalid size */ -int bt_audio_codec_cfg_meta_get_stream_lang(const struct bt_audio_codec_cfg *codec_cfg); +int bt_audio_codec_cfg_meta_get_lang(const struct bt_audio_codec_cfg *codec_cfg, + const uint8_t **lang); /** - * @brief Set the stream language of a codec configuration metadata. + * @brief Set the language of a codec configuration metadata. * * @param codec_cfg The codec configuration to set data for. - * @param stream_lang The 24-bit stream language to set. + * @param lang The 24-bit language to set. * * @retval The data_len of @p codec_cfg on success * @retval -EINVAL if arguments are invalid * @retval -ENOMEM if the new value could not set or added due to memory */ -int bt_audio_codec_cfg_meta_set_stream_lang(struct bt_audio_codec_cfg *codec_cfg, - uint32_t stream_lang); +int bt_audio_codec_cfg_meta_set_lang(struct bt_audio_codec_cfg *codec_cfg, + const uint8_t lang[BT_AUDIO_LANG_SIZE]); /** @brief Extract CCID list * @@ -1524,13 +1595,16 @@ int bt_audio_codec_cap_set_frame_dur(struct bt_audio_codec_cap *codec_cap, * @brief Extract the frequency from a codec capability. * * @param codec_cap The codec capabilities to extract data from. + * @param fallback_to_default If true this function will provide the default value of 1 + * if the type is not found when @p codec_cap.id is @ref BT_HCI_CODING_FORMAT_LC3. * - * @retval Bitfield of supported channel counts if 0 or positive + * @retval Number of supported channel counts if 0 or positive * @retval -EINVAL if arguments are invalid * @retval -ENODATA if not found * @retval -EBADMSG if found value has invalid size or value */ -int bt_audio_codec_cap_get_supported_audio_chan_counts(const struct bt_audio_codec_cap *codec_cap); +int bt_audio_codec_cap_get_supported_audio_chan_counts(const struct bt_audio_codec_cap *codec_cap, + bool fallback_to_default); /** * @brief Set the channel count of a codec capability. @@ -1578,13 +1652,16 @@ int bt_audio_codec_cap_set_octets_per_frame( * @brief Extract the maximum codec frames per SDU from a codec capability. * * @param codec_cap The codec capabilities to extract data from. + * @param fallback_to_default If true this function will provide the default value of 1 + * if the type is not found when @p codec_cap.id is @ref BT_HCI_CODING_FORMAT_LC3. * * @retval Maximum number of codec frames per SDU supported * @retval -EINVAL if arguments are invalid * @retval -ENODATA if not found * @retval -EBADMSG if found value has invalid size or value */ -int bt_audio_codec_cap_get_max_codec_frames_per_sdu(const struct bt_audio_codec_cap *codec_cap); +int bt_audio_codec_cap_get_max_codec_frames_per_sdu(const struct bt_audio_codec_cap *codec_cap, + bool fallback_to_default); /** * @brief Set the maximum codec frames per SDU of a codec capability. @@ -1722,31 +1799,33 @@ int bt_audio_codec_cap_meta_get_program_info(const struct bt_audio_codec_cap *co int bt_audio_codec_cap_meta_set_program_info(struct bt_audio_codec_cap *codec_cap, const uint8_t *program_info, size_t program_info_len); -/** @brief Extract stream language +/** @brief Extract language * - * See @ref BT_AUDIO_METADATA_TYPE_STREAM_LANG for more information about this value. + * See @ref BT_AUDIO_METADATA_TYPE_LANG for more information about this value. * - * @param codec_cap The codec data to search in. + * @param[in] codec_cap The codec data to search in. + * @param[out] lang Pointer to the language bytes (of length BT_AUDIO_LANG_SIZE) * - * @retval The stream language if positive or 0 + * @retval 0 On success * @retval -EINVAL if arguments are invalid * @retval -ENODATA if not found * @retval -EBADMSG if found value has invalid size */ -int bt_audio_codec_cap_meta_get_stream_lang(const struct bt_audio_codec_cap *codec_cap); +int bt_audio_codec_cap_meta_get_lang(const struct bt_audio_codec_cap *codec_cap, + const uint8_t **lang); /** - * @brief Set the stream language of a codec capability metadata. + * @brief Set the language of a codec capability metadata. * * @param codec_cap The codec capability to set data for. - * @param stream_lang The 24-bit stream language to set. + * @param lang The 24-bit language to set. * * @retval The data_len of @p codec_cap on success * @retval -EINVAL if arguments are invalid * @retval -ENOMEM if the new value could not set or added due to memory */ -int bt_audio_codec_cap_meta_set_stream_lang(struct bt_audio_codec_cap *codec_cap, - uint32_t stream_lang); +int bt_audio_codec_cap_meta_set_lang(struct bt_audio_codec_cap *codec_cap, + const uint8_t lang[BT_AUDIO_LANG_SIZE]); /** @brief Extract CCID list * diff --git a/include/zephyr/bluetooth/audio/bap.h b/include/zephyr/bluetooth/audio/bap.h index 08a2a642eb029..1ee66b59170f6 100644 --- a/include/zephyr/bluetooth/audio/bap.h +++ b/include/zephyr/bluetooth/audio/bap.h @@ -2,7 +2,7 @@ * @brief Header for Bluetooth BAP. * * Copyright (c) 2020 Bose Corporation - * Copyright (c) 2021-2023 Nordic Semiconductor ASA + * Copyright (c) 2021-2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -17,9 +17,17 @@ * @{ */ -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -410,6 +418,9 @@ struct bt_bap_ep_info { * otherwise NULL */ struct bt_bap_ep *paired_ep; + + /** Pointer to the preferred QoS settings associated with the endpoint */ + const struct bt_audio_codec_qos_pref *qos_pref; }; /** @@ -712,20 +723,43 @@ int bt_bap_stream_metadata(struct bt_bap_stream *stream, const uint8_t meta[], s */ int bt_bap_stream_disable(struct bt_bap_stream *stream); +/** + * @brief Connect unicast audio stream + * + * This procedure is used by a unicast client to connect the connected isochronous stream (CIS) + * associated with the audio stream. If two audio streams share a CIS, then this only needs to be + * done once for those streams. This can only be done for streams in the QoS configured or enabled + * states. + * + * The bt_bap_stream_ops.connected() callback will be called on the streams once this has finished. + * + * This shall only be called for unicast streams, and only as the unicast client + * (@kconfig{CONFIG_BT_BAP_UNICAST_CLIENT}). + * + * @param stream Stream object + * + * @retval 0 in case of success + * @retval -EINVAL if the stream, endpoint, ISO channel or connection is NULL + * @retval -EBADMSG if the stream or ISO channel is in an invalid state for connection + * @retval -EOPNOTSUPP if the role of the stream is not @ref BT_HCI_ROLE_CENTRAL + * @retval -EALREADY if the ISO channel is already connecting or connected + * @retval -EBUSY if another ISO channel is connecting + * @retval -ENOEXEC if otherwise rejected by the ISO layer + */ +int bt_bap_stream_connect(struct bt_bap_stream *stream); + /** * @brief Start Audio Stream * * This procedure is used by a unicast client or unicast server to make a stream start streaming. * - * For the unicast client, this will connect the CIS for the stream before - * sending the start command. + * For the unicast client, this will send the receiver start ready command to the unicast server for + * @ref BT_AUDIO_DIR_SOURCE ASEs. The CIS is required to be connected first by + * bt_bap_stream_connect() before the command can be sent. * - * For the unicast server, this will put a @ref BT_AUDIO_DIR_SINK stream into the streaming state if - * the CIS is connected (initialized by the unicast client). If the CIS is not connected yet, the - * stream will go into the streaming state as soon as the CIS is connected. - * @ref BT_AUDIO_DIR_SOURCE streams will go into the streaming state when the unicast client sends - * the Receiver Start Ready operation, which will trigger the @ref bt_bap_unicast_server_cb.start() - * callback. + * For the unicast server, this will execute the receiver start ready command on the unicast server + * for @ref BT_AUDIO_DIR_SINK ASEs. If the CIS is not connected yet, the stream will go into the + * streaming state as soon as the CIS is connected. * * This shall only be called for unicast streams. * @@ -1406,6 +1440,16 @@ struct bt_bap_base_subgroup_bis { */ const struct bt_bap_base *bt_bap_base_get_base_from_ad(const struct bt_data *ad); +/** + * @brief Get the size of a BASE + * + * @param base The BASE pointer + * + * @retval -EINVAL if arguments are invalid + * @retval The size of the BASE + */ +int bt_bap_base_get_size(const struct bt_bap_base *base); + /** * @brief Get the presentation delay value of a BASE * @@ -2101,11 +2145,9 @@ struct bt_bap_broadcast_assistant_cb { * @brief Callback function for when a receive state is removed. * * @param conn The connection to the Broadcast Audio Scan Service server. - * @param err Error value. 0 on success, GATT error on fail. * @param src_id The receive state. */ - void (*recv_state_removed)(struct bt_conn *conn, int err, - uint8_t src_id); + void (*recv_state_removed)(struct bt_conn *conn, uint8_t src_id); /** * @brief Callback function for bt_bap_broadcast_assistant_scan_start(). diff --git a/include/zephyr/bluetooth/audio/bap_lc3_preset.h b/include/zephyr/bluetooth/audio/bap_lc3_preset.h index d31c47fd4fb79..7ba6af250a216 100644 --- a/include/zephyr/bluetooth/audio/bap_lc3_preset.h +++ b/include/zephyr/bluetooth/audio/bap_lc3_preset.h @@ -10,6 +10,7 @@ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_BAP_LC3_PRESET_ #include +#include /** Struct to hold a BAP defined LC3 preset */ struct bt_bap_lc3_preset { diff --git a/include/zephyr/bluetooth/audio/cap.h b/include/zephyr/bluetooth/audio/cap.h index 9c785b87e9843..afc1ca9018ef0 100644 --- a/include/zephyr/bluetooth/audio/cap.h +++ b/include/zephyr/bluetooth/audio/cap.h @@ -12,19 +12,25 @@ * * @defgroup bt_cap Common Audio Profile (CAP) * + * @since 3.2 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ +#include +#include #include -#include -#include #include #include +#include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -63,14 +69,16 @@ struct bt_cap_initiator_cb { * @param conn The connection pointer supplied to * bt_cap_initiator_unicast_discover(). * @param err 0 if Common Audio Service was found else -ENODATA. + * @param member Pointer to the set member. NULL if err != 0. * @param csis_inst The Coordinated Set Identification Service if * Common Audio Service was found and includes a * Coordinated Set Identification Service. * NULL on error or if remote device does not include - * Coordinated Set Identification Service. + * Coordinated Set Identification Service. NULL if err != 0. */ void (*unicast_discovery_complete)( struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst); /** @@ -294,6 +302,16 @@ struct bt_cap_unicast_audio_stop_param { */ int bt_cap_initiator_register_cb(const struct bt_cap_initiator_cb *cb); +/** + * @brief Unregister Common Audio Profile Initiator callbacks + * + * @param cb The callback structure that was previously registered. + * + * @retval 0 Success + * @retval -EINVAL @p cb is NULL or @p cb was not registered + */ +int bt_cap_initiator_unregister_cb(const struct bt_cap_initiator_cb *cb); + /** * @brief Setup and start unicast audio streams for a set of devices. * @@ -676,13 +694,15 @@ struct bt_cap_commander_cb { * @param conn The connection pointer supplied to * bt_cap_initiator_unicast_discover(). * @param err 0 if Common Audio Service was found else -ENODATA. + * @param member Pointer to the set member. NULL if err != 0. * @param csis_inst The Coordinated Set Identification Service if * Common Audio Service was found and includes a * Coordinated Set Identification Service. * NULL on error or if remote device does not include - * Coordinated Set Identification Service. + * Coordinated Set Identification Service. NULL if err != 0. */ void (*discovery_complete)(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst); #if defined(CONFIG_BT_VCP_VOL_CTLR) diff --git a/include/zephyr/bluetooth/audio/csip.h b/include/zephyr/bluetooth/audio/csip.h index a302a69886729..7b8d8d2631fe4 100644 --- a/include/zephyr/bluetooth/audio/csip.h +++ b/include/zephyr/bluetooth/audio/csip.h @@ -12,13 +12,23 @@ * * @defgroup bt_gatt_csip Coordinated Set Identification Profile (CSIP) * + * @since 3.0 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * * - * [Experimental] Users should note that the APIs can change as a part of ongoing development. */ +#include +#include +#include + +#include +#include #include +#include +#include +#include #ifdef __cplusplus extern "C" { @@ -43,7 +53,7 @@ extern "C" { #define BT_CSIP_READ_SIRK_REQ_RSP_OOB_ONLY 0x03 /** Size of the Set Identification Resolving Key (SIRK) */ -#define BT_CSIP_SET_SIRK_SIZE 16 +#define BT_CSIP_SIRK_SIZE 16 /** Size of the Resolvable Set Identifier (RSI) */ #define BT_CSIP_RSI_SIZE 6 @@ -122,7 +132,7 @@ struct bt_csip_set_member_register_param { * This shall be unique between different sets, and shall be the same * for each set member for each set. */ - uint8_t set_sirk[BT_CSIP_SET_SIRK_SIZE]; + uint8_t sirk[BT_CSIP_SIRK_SIZE]; /** * @brief Boolean to set whether the set is lockable by clients @@ -203,8 +213,8 @@ int bt_csip_set_member_unregister(struct bt_csip_set_member_svc_inst *svc_inst); * @param svc_inst Pointer to the registered Coordinated Set Identification Service. * @param sirk The new SIRK. */ -int bt_csip_set_member_set_sirk(struct bt_csip_set_member_svc_inst *svc_inst, - const uint8_t sirk[BT_CSIP_SET_SIRK_SIZE]); +int bt_csip_set_member_sirk(struct bt_csip_set_member_svc_inst *svc_inst, + const uint8_t sirk[BT_CSIP_SIRK_SIZE]); /** * @brief Get the SIRK of a service instance @@ -213,7 +223,7 @@ int bt_csip_set_member_set_sirk(struct bt_csip_set_member_svc_inst *svc_inst, * @param[out] sirk Array to store the SIRK in. */ int bt_csip_set_member_get_sirk(struct bt_csip_set_member_svc_inst *svc_inst, - uint8_t sirk[BT_CSIP_SET_SIRK_SIZE]); + uint8_t sirk[BT_CSIP_SIRK_SIZE]); /** * @brief Generate the Resolvable Set Identifier (RSI) value. @@ -247,10 +257,10 @@ struct bt_csip_set_coordinator_set_info { /** * @brief The 16 octet set Set Identity Resolving Key (SIRK) * - * The Set SIRK may not be exposed by the server over Bluetooth, and + * The SIRK may not be exposed by the server over Bluetooth, and * may require an out-of-band solution. */ - uint8_t set_sirk[BT_CSIP_SET_SIRK_SIZE]; + uint8_t sirk[BT_CSIP_SIRK_SIZE]; /** * @brief The size of the set @@ -313,6 +323,21 @@ typedef void (*bt_csip_set_coordinator_discover_cb)( */ int bt_csip_set_coordinator_discover(struct bt_conn *conn); +/** + * @brief Get the set member from a connection pointer + * + * Get the Coordinated Set Identification Profile Set Coordinator pointer from a connection pointer. + * Only Set Coordinators that have been initiated via bt_csip_set_coordinator_discover() can be + * retrieved. + * + * @param conn Connection pointer. + * + * @retval Pointer to a Coordinated Set Identification Profile Set Coordinator instance + * @retval NULL if @p conn is NULL or if the connection has not done discovery yet + */ +struct bt_csip_set_coordinator_set_member * +bt_csip_set_coordinator_set_member_by_conn(const struct bt_conn *conn); + /** * @typedef bt_csip_set_coordinator_lock_set_cb * @brief Callback for locking a set across one or more devices @@ -381,12 +406,12 @@ struct bt_csip_set_coordinator_cb { /** * @brief Check if advertising data indicates a set member * - * @param set_sirk The SIRK of the set to check against - * @param data The advertising data + * @param sirk The SIRK of the set to check against + * @param data The advertising data * * @return true if the advertising data indicates a set member, false otherwise */ -bool bt_csip_set_coordinator_is_set_member(const uint8_t set_sirk[BT_CSIP_SET_SIRK_SIZE], +bool bt_csip_set_coordinator_is_set_member(const uint8_t sirk[BT_CSIP_SIRK_SIZE], struct bt_data *data); /** diff --git a/include/zephyr/bluetooth/audio/gmap_lc3_preset.h b/include/zephyr/bluetooth/audio/gmap_lc3_preset.h index e5a22936c741e..5e50de243e7fd 100644 --- a/include/zephyr/bluetooth/audio/gmap_lc3_preset.h +++ b/include/zephyr/bluetooth/audio/gmap_lc3_preset.h @@ -9,7 +9,9 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_GMAP_LC3_PRESET_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_GMAP_LC3_PRESET_ +#include #include +#include /* GMAP LC3 unicast presets defined by table 3.16 in the GMAP v1.0 specification */ diff --git a/include/zephyr/bluetooth/audio/has.h b/include/zephyr/bluetooth/audio/has.h index 46be03e72ef2e..7bd20aec89e3a 100644 --- a/include/zephyr/bluetooth/audio/has.h +++ b/include/zephyr/bluetooth/audio/has.h @@ -12,20 +12,22 @@ * * @defgroup bt_has Hearing Access Service (HAS) * + * @since 3.1 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * * The Hearing Access Service is used to identify a hearing aid and optionally * to control hearing aid presets. - * - * [Experimental] Users should note that the APIs can change as a part of - * ongoing development. */ -#include +#include +#include #include #include +#include #ifdef __cplusplus extern "C" { @@ -63,7 +65,7 @@ enum bt_has_properties { BT_HAS_PROP_AVAILABLE = BIT(1), }; -/** Hearing Aid device capablilities */ +/** Hearing Aid device capabilities */ enum bt_has_capabilities { BT_HAS_PRESET_SUPPORT = BIT(0), }; diff --git a/include/zephyr/bluetooth/audio/mcc.h b/include/zephyr/bluetooth/audio/mcc.h index f67eb76831810..fb71f011db96e 100644 --- a/include/zephyr/bluetooth/audio/mcc.h +++ b/include/zephyr/bluetooth/audio/mcc.h @@ -5,11 +5,11 @@ * * @defgroup bt_gatt_mcc Media Control Client (MCC) * + * @since 3.0 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ /* @@ -22,6 +22,7 @@ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_MCC_ #include +#include #include #include @@ -407,7 +408,7 @@ typedef void (*bt_mcc_read_content_control_id_cb)(struct bt_conn *conn, typedef void (*bt_mcc_otc_obj_selected_cb)(struct bt_conn *conn, int err); /** - * @brief Callback function for bt_mcc_otc_read_object_meatadata() + * @brief Callback function for bt_mcc_otc_read_object_metadata() * * Called when object metadata is read * diff --git a/include/zephyr/bluetooth/audio/mcs.h b/include/zephyr/bluetooth/audio/mcs.h index b234131281e4d..5212905497c27 100644 --- a/include/zephyr/bluetooth/audio/mcs.h +++ b/include/zephyr/bluetooth/audio/mcs.h @@ -12,17 +12,18 @@ * * @defgroup bt_mcs Media Control Service (MCS) * + * @since 3.0 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. - * * Definitions and types related to the Media Control Service and Media Control * Profile specifications. */ #include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/media_proxy.h b/include/zephyr/bluetooth/audio/media_proxy.h index 34e3e7126f699..16bb978bfcc48 100644 --- a/include/zephyr/bluetooth/audio/media_proxy.h +++ b/include/zephyr/bluetooth/audio/media_proxy.h @@ -11,6 +11,9 @@ * * @defgroup bt_media_proxy Media Proxy * + * @since 3.0 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * @@ -31,15 +34,13 @@ * application, or it may be a Media Control Service relaying requests * from a remote Media Control Client. There may be either local or * remote control, or both, or even multiple instances of each. - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ #include #include #include +#include /* TODO: Remove dependency on mcs.h */ #include "mcs.h" diff --git a/include/zephyr/bluetooth/audio/micp.h b/include/zephyr/bluetooth/audio/micp.h index 27359ca7ffa5d..0fe9a7af681f5 100644 --- a/include/zephyr/bluetooth/audio/micp.h +++ b/include/zephyr/bluetooth/audio/micp.h @@ -12,16 +12,18 @@ * * @defgroup bt_gatt_micp Microphone Control Profile (MICP) * + * @since 2.7 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ #include #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/pacs.h b/include/zephyr/bluetooth/audio/pacs.h index 6db4d34b0a285..74f401d7bd54f 100644 --- a/include/zephyr/bluetooth/audio/pacs.h +++ b/include/zephyr/bluetooth/audio/pacs.h @@ -10,7 +10,11 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_PACS_H_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_PACS_H_ +#include + #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/pbp.h b/include/zephyr/bluetooth/audio/pbp.h index acc53adb5ad5d..d218720895d34 100644 --- a/include/zephyr/bluetooth/audio/pbp.h +++ b/include/zephyr/bluetooth/audio/pbp.h @@ -12,15 +12,19 @@ * * @defgroup bt_pbp Public Broadcast Profile (PBP) * + * @since 3.5 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ -#include #include +#include +#include +#include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/tbs.h b/include/zephyr/bluetooth/audio/tbs.h index 523efc4264fc1..49039a7ff6145 100644 --- a/include/zephyr/bluetooth/audio/tbs.h +++ b/include/zephyr/bluetooth/audio/tbs.h @@ -14,6 +14,7 @@ #include #include +#include /* Call States */ #define BT_TBS_CALL_STATE_INCOMING 0x00 diff --git a/include/zephyr/bluetooth/audio/tmap.h b/include/zephyr/bluetooth/audio/tmap.h index 4bcdbb0a5bfc8..1c8e8ccb8921d 100644 --- a/include/zephyr/bluetooth/audio/tmap.h +++ b/include/zephyr/bluetooth/audio/tmap.h @@ -9,8 +9,10 @@ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TMAP_ #define ZEPHYR_INCLUDE_BLUETOOTH_AUDIO_TMAP_ +#include #include #include +#include /** Call Gateway (CG) supported */ #define BT_TMAP_CG_SUPPORTED \ diff --git a/include/zephyr/bluetooth/audio/vcp.h b/include/zephyr/bluetooth/audio/vcp.h index 15d91fae330e2..755ee12d065ab 100644 --- a/include/zephyr/bluetooth/audio/vcp.h +++ b/include/zephyr/bluetooth/audio/vcp.h @@ -12,17 +12,19 @@ * * @defgroup bt_gatt_vcp Volume Control Profile (VCP) * + * @since 2.7 + * @version 0.8.0 + * * @ingroup bluetooth * @{ - * - * [Experimental] Users should note that the APIs can change - * as a part of ongoing development. */ #include #include #include +#include +#include #ifdef __cplusplus extern "C" { diff --git a/include/zephyr/bluetooth/audio/vocs.h b/include/zephyr/bluetooth/audio/vocs.h index d34e6bcd16e9d..8b6a51d8d64b4 100644 --- a/include/zephyr/bluetooth/audio/vocs.h +++ b/include/zephyr/bluetooth/audio/vocs.h @@ -12,6 +12,9 @@ * * @defgroup bt_gatt_vocs Volume Offset Control Service (VOCS) * + * @since 2.6 + * @version 0.8.0 + * * @ingroup bluetooth * @{ * @@ -22,8 +25,6 @@ * Note that the API abstracts away the change counter in the volume offset control state and will * automatically handle any changes to that. If out of date, the client implementation will * autonomously read the change counter value when executing a write request. - * - * [Experimental] Users should note that the APIs can change as a part of ongoing development. */ #include diff --git a/include/zephyr/bluetooth/bluetooth.h b/include/zephyr/bluetooth/bluetooth.h index 364514fc343cd..202d29eb9caa2 100644 --- a/include/zephyr/bluetooth/bluetooth.h +++ b/include/zephyr/bluetooth/bluetooth.h @@ -231,6 +231,15 @@ int bt_enable(bt_ready_cb_t cb); * * Disable Bluetooth. Can't be called before bt_enable has completed. * + * This API will clear all configured identities and keys that are not persistently + * stored with @kconfig{CONFIG_BT_SETTINGS}. These can be restored + * with settings_load() before reenabling the stack. + * + * This API does _not_ clear previously registered callbacks + * like @ref bt_le_scan_cb_register and @ref bt_conn_cb_register. + * That is, the application shall not re-register them when + * the Bluetooth subsystem is re-enabled later. + * * Close and release HCI resources. Result is architecture dependent. * * @return Zero on success or (negative) error code otherwise. @@ -912,6 +921,12 @@ struct bt_le_per_adv_param { BT_GAP_ADV_FAST_INT_MIN_2, \ BT_GAP_ADV_FAST_INT_MAX_2, NULL) +/** This is the recommended default for connectable advertisers. + */ +#define BT_LE_ADV_CONN_ONE_TIME \ + BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, \ + BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, NULL) + /** * @deprecated This macro will be removed in the near future, see * https://github.com/zephyrproject-rtos/zephyr/issues/71686 @@ -1807,8 +1822,11 @@ int bt_le_per_adv_sync_delete(struct bt_le_per_adv_sync *per_adv_sync); * such as synced, terminated and when data is received. * * @param cb Callback struct. Must point to memory that remains valid. + * + * @retval 0 Success. + * @retval -EEXIST if @p cb was already registered. */ -void bt_le_per_adv_sync_cb_register(struct bt_le_per_adv_sync_cb *cb); +int bt_le_per_adv_sync_cb_register(struct bt_le_per_adv_sync_cb *cb); /** * @brief Enables receiving periodic advertising reports for a sync. @@ -2294,8 +2312,11 @@ int bt_le_scan_stop(void); * API was used to start the scanner. * * @param cb Callback struct. Must point to memory that remains valid. + * + * @retval 0 Success. + * @retval -EEXIST if @p cb was already registered. */ -void bt_le_scan_cb_register(struct bt_le_scan_cb *cb); +int bt_le_scan_cb_register(struct bt_le_scan_cb *cb); /** * @brief Unregister scanner packet callbacks. diff --git a/include/zephyr/bluetooth/buf.h b/include/zephyr/bluetooth/buf.h index 7429547ee410d..b373ab5bd911c 100644 --- a/include/zephyr/bluetooth/buf.h +++ b/include/zephyr/bluetooth/buf.h @@ -68,7 +68,7 @@ struct bt_buf_data { /** Helper to calculate needed buffer size for HCI ISO packets. */ #define BT_BUF_ISO_SIZE(size) BT_BUF_SIZE(BT_HCI_ISO_HDR_SIZE + \ - BT_HCI_ISO_TS_DATA_HDR_SIZE + \ + BT_HCI_ISO_SDU_TS_HDR_SIZE + \ (size)) /** Data size needed for HCI ACL RX buffers */ diff --git a/include/zephyr/bluetooth/classic/a2dp-codec.h b/include/zephyr/bluetooth/classic/a2dp-codec.h deleted file mode 100644 index 3da36420dcd21..0000000000000 --- a/include/zephyr/bluetooth/classic/a2dp-codec.h +++ /dev/null @@ -1,115 +0,0 @@ -/** @file - * @brief Advance Audio Distribution Profile - SBC Codec header. - */ -/* - * SPDX-License-Identifier: Apache-2.0 - * Copyright (c) 2015-2016 Intel Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -#ifndef ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ -#define ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @name Sampling Frequency - * @{ - */ -#define A2DP_SBC_SAMP_FREQ_16000 BIT(7) /**< 16 kHz */ -#define A2DP_SBC_SAMP_FREQ_32000 BIT(6) /**< 32 kHz */ -#define A2DP_SBC_SAMP_FREQ_44100 BIT(5) /**< 44.1 kHz */ -#define A2DP_SBC_SAMP_FREQ_48000 BIT(4) /**< 48 kHz */ -/** @} */ - -/** - * @name Channel Mode - * @{ - */ -#define A2DP_SBC_CH_MODE_MONO BIT(3) /**< Mono */ -#define A2DP_SBC_CH_MODE_DUAL BIT(2) /**< Dual Channel */ -#define A2DP_SBC_CH_MODE_STREO BIT(1) /**< Stereo */ -#define A2DP_SBC_CH_MODE_JOINT BIT(0) /**< Joint Stereo */ -/** @} */ - -/** - * @name Block Length - * @{ - */ -#define A2DP_SBC_BLK_LEN_4 BIT(7) /**< 4 blocks */ -#define A2DP_SBC_BLK_LEN_8 BIT(6) /**< 8 blocks */ -#define A2DP_SBC_BLK_LEN_12 BIT(5) /**< 12 blocks */ -#define A2DP_SBC_BLK_LEN_16 BIT(4) /**< 16 blocks */ -/** @} */ - -/** - * @name Subbands - * @{ - */ -#define A2DP_SBC_SUBBAND_4 BIT(3) /**< 4 subbands */ -#define A2DP_SBC_SUBBAND_8 BIT(2) /**< 8 subbands */ -/** @} */ - -/** - * @name Bit pool Allocation Method - * @{ - */ -#define A2DP_SBC_ALLOC_MTHD_SNR BIT(1) /**< Allocate based on loudness of the subband signal */ -#define A2DP_SBC_ALLOC_MTHD_LOUDNESS BIT(0) /**< Allocate based on the signal-to-noise ratio */ -/** @} */ - -/** - * Gets the sampling rate from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_SAMP_FREQ(preset) ((preset->config[0] >> 4) & 0x0f) -/** - * Gets the channel mode from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_CHAN_MODE(preset) ((preset->config[0]) & 0x0f) -/** - * Gets the block length from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_BLK_LEN(preset) ((preset->config[1] >> 4) & 0x0f) -/** - * Gets the number subbands from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_SUB_BAND(preset) ((preset->config[1] >> 2) & 0x03) -/** - * Gets the bitpool allocation method from a codec preset - * @param preset Codec preset - */ -#define BT_A2DP_SBC_ALLOC_MTHD(preset) ((preset->config[1]) & 0x03) - -/** @brief SBC Codec */ -struct bt_a2dp_codec_sbc_params { - /** First two octets of configuration */ - uint8_t config[2]; - /** Minimum Bitpool Value */ - uint8_t min_bitpool; - /** Maximum Bitpool Value */ - uint8_t max_bitpool; -} __packed; - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ */ diff --git a/include/zephyr/bluetooth/classic/a2dp.h b/include/zephyr/bluetooth/classic/a2dp.h index a065012280289..540899c2197b2 100644 --- a/include/zephyr/bluetooth/classic/a2dp.h +++ b/include/zephyr/bluetooth/classic/a2dp.h @@ -4,6 +4,7 @@ /* * Copyright (c) 2015-2016 Intel Corporation + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,19 +13,262 @@ #include +#include +#include #include #ifdef __cplusplus extern "C" { #endif -/** @brief Stream Structure */ -struct bt_a2dp_stream { - /* TODO */ +#define BT_A2DP_STREAM_BUF_RESERVE (12u + BT_L2CAP_BUF_SIZE(0)) + +/** SBC IE length */ +#define BT_A2DP_SBC_IE_LENGTH (4u) +/** MPEG1,2 IE length */ +#define BT_A2DP_MPEG_1_2_IE_LENGTH (4u) +/** MPEG2,4 IE length */ +#define BT_A2DP_MPEG_2_4_IE_LENGTH (6u) +/** The max IE (Codec Info Element) length */ +#define A2DP_MAX_IE_LENGTH (8U) + +/** @brief define the audio endpoint + * @param _role BT_AVDTP_SOURCE or BT_AVDTP_SINK. + * @param _codec value of enum bt_a2dp_codec_id. + * @param _capability the codec capability. + */ +#define BT_A2DP_EP_INIT(_role, _codec, _capability)\ +{\ + .codec_type = _codec,\ + .sep = {.sep_info = {.media_type = BT_AVDTP_AUDIO, .tsep = _role}},\ + .codec_cap = _capability,\ + .stream = NULL,\ +} + +/** @brief define the audio sink endpoint + * @param _codec value of enum bt_a2dp_codec_id. + * @param _capability the codec capability. + */ +#define BT_A2DP_SINK_EP_INIT(_codec, _capability)\ +BT_A2DP_EP_INIT(BT_AVDTP_SINK, _codec, _capability) + +/** @brief define the audio source endpoint + * @param _codec value of enum bt_a2dp_codec_id. + * @param _capability the codec capability. + */ +#define BT_A2DP_SOURCE_EP_INIT(_codec, _capability)\ +BT_A2DP_EP_INIT(BT_AVDTP_SOURCE, _codec, _capability) + +/** @brief define the SBC sink endpoint that can be used as + * bt_a2dp_register_endpoint's parameter. + * + * SBC is mandatory as a2dp specification, BT_A2DP_SBC_SINK_EP_DEFAULT + * is more convenient for user to register SBC endpoint. + * + * @param _freq sbc codec frequency. + * for example: A2DP_SBC_SAMP_FREQ_44100 | A2DP_SBC_SAMP_FREQ_48000 + * @param _ch_mode sbc codec channel mode. + * for example: A2DP_SBC_CH_MODE_MONO | A2DP_SBC_CH_MODE_STREO + * @param _blk_len sbc codec block length. + * for example: A2DP_SBC_BLK_LEN_16 + * @param _subband sbc codec subband. + * for example: A2DP_SBC_SUBBAND_8 + * @param _alloc_mthd sbc codec allocate method. + * for example: A2DP_SBC_ALLOC_MTHD_LOUDNESS + * @param _min_bitpool sbc codec min bit pool. for example: 18 + * @param _max_bitpool sbc codec max bit pool. for example: 35 + * @ + */ +#define BT_A2DP_SBC_SINK_EP(_name, _freq, _ch_mode, _blk_len, _subband,\ +_alloc_mthd, _min_bitpool, _max_bitpool)\ +static struct bt_a2dp_codec_ie bt_a2dp_ep_cap_ie##_name =\ +{.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {_freq | _ch_mode,\ +_blk_len | _subband | _alloc_mthd, _min_bitpool, _max_bitpool}};\ +static struct bt_a2dp_ep _name = BT_A2DP_SINK_EP_INIT(BT_A2DP_SBC,\ +(&bt_a2dp_ep_cap_ie##_name)) + +/** @brief define the SBC source endpoint that can be used as bt_a2dp_register_endpoint's + * parameter. + * + * SBC is mandatory as a2dp specification, BT_A2DP_SBC_SOURCE_EP_DEFAULT + * is more convenient for user to register SBC endpoint. + * + * @param _name the endpoint variable name. + * @param _freq sbc codec frequency. + * for example: A2DP_SBC_SAMP_FREQ_44100 | A2DP_SBC_SAMP_FREQ_48000 + * @param _ch_mode sbc codec channel mode. + * for example: A2DP_SBC_CH_MODE_MONO | A2DP_SBC_CH_MODE_STREO + * @param _blk_len sbc codec block length. + * for example: A2DP_SBC_BLK_LEN_16 + * @param _subband sbc codec subband. + * for example: A2DP_SBC_SUBBAND_8 + * @param _alloc_mthd sbc codec allocate method. + * for example: A2DP_SBC_ALLOC_MTHD_LOUDNESS + * @param _min_bitpool sbc codec min bit pool. for example: 18 + * @param _max_bitpool sbc codec max bit pool. for example: 35 + */ +#define BT_A2DP_SBC_SOURCE_EP(_name, _freq, _ch_mode, _blk_len, _subband,\ +_alloc_mthd, _min_bitpool, _max_bitpool)\ +static struct bt_a2dp_codec_ie bt_a2dp_ep_cap_ie##_name =\ +{.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {_freq | _ch_mode,\ +_blk_len | _subband | _alloc_mthd, _min_bitpool, _max_bitpool}};\ +static struct bt_a2dp_ep _name = BT_A2DP_SOURCE_EP_INIT(BT_A2DP_SBC,\ +&bt_a2dp_ep_cap_ie##_name) + +/** @brief define the default SBC sink endpoint that can be used as + * bt_a2dp_register_endpoint's parameter. + * + * SBC is mandatory as a2dp specification, BT_A2DP_SBC_SINK_EP_DEFAULT + * is more convenient for user to register SBC endpoint. + * + * @param _name the endpoint variable name. + */ +#define BT_A2DP_SBC_SINK_EP_DEFAULT(_name)\ +static struct bt_a2dp_codec_ie bt_a2dp_ep_cap_ie##_name =\ +{.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {A2DP_SBC_SAMP_FREQ_44100 |\ +A2DP_SBC_SAMP_FREQ_48000 | A2DP_SBC_CH_MODE_MONO | A2DP_SBC_CH_MODE_STREO |\ +A2DP_SBC_CH_MODE_JOINT, A2DP_SBC_BLK_LEN_16 |\ +A2DP_SBC_SUBBAND_8 | A2DP_SBC_ALLOC_MTHD_LOUDNESS, 18U, 35U}};\ +static struct bt_a2dp_ep _name = BT_A2DP_SINK_EP_INIT(BT_A2DP_SBC,\ +&bt_a2dp_ep_cap_ie##_name) + +/** @brief define the default SBC source endpoint that can be used as bt_a2dp_register_endpoint's + * parameter. + * + * SBC is mandatory as a2dp specification, BT_A2DP_SBC_SOURCE_EP_DEFAULT + * is more convenient for user to register SBC endpoint. + * + * @param _name the endpoint variable name. + */ +#define BT_A2DP_SBC_SOURCE_EP_DEFAULT(_name)\ +static struct bt_a2dp_codec_ie bt_a2dp_ep_cap_ie##_name =\ +{.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {A2DP_SBC_SAMP_FREQ_44100 | \ +A2DP_SBC_SAMP_FREQ_48000 | A2DP_SBC_CH_MODE_MONO | A2DP_SBC_CH_MODE_STREO | \ +A2DP_SBC_CH_MODE_JOINT, A2DP_SBC_BLK_LEN_16 | A2DP_SBC_SUBBAND_8 | A2DP_SBC_ALLOC_MTHD_LOUDNESS,\ +18U, 35U},};\ +static struct bt_a2dp_ep _name = BT_A2DP_SOURCE_EP_INIT(BT_A2DP_SBC,\ +&bt_a2dp_ep_cap_ie##_name) + +/** @brief define the SBC default configuration. + * + * @param _freq_cfg sbc codec frequency. + * for example: A2DP_SBC_SAMP_FREQ_44100 + * @param _ch_mode_cfg sbc codec channel mode. + * for example: A2DP_SBC_CH_MODE_JOINT + * @param _blk_len_cfg sbc codec block length. + * for example: A2DP_SBC_BLK_LEN_16 + * @param _subband_cfg sbc codec subband. + * for example: A2DP_SBC_SUBBAND_8 + * @param _alloc_mthd_cfg sbc codec allocate method. + * for example: A2DP_SBC_ALLOC_MTHD_LOUDNESS + * @param _min_bitpool_cfg sbc codec min bit pool. for example: 18 + * @param _max_bitpool_cfg sbc codec max bit pool. for example: 35 + */ +#define BT_A2DP_SBC_EP_CFG(_name, _freq_cfg, _ch_mode_cfg, _blk_len_cfg, _subband_cfg,\ +_alloc_mthd_cfg, _min_bitpool_cfg, _max_bitpool_cfg)\ +static struct bt_a2dp_codec_ie bt_a2dp_codec_ie##_name = {\ +.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {_freq_cfg | _ch_mode_cfg,\ +_blk_len_cfg | _subband_cfg | _alloc_mthd_cfg, _min_bitpool_cfg, _max_bitpool_cfg},};\ +struct bt_a2dp_codec_cfg _name = {.codec_config = &bt_a2dp_codec_ie##_name,} + +/** @brief define the SBC default configuration. + * + * @param _freq_cfg the frequency to configure the remote same codec type endpoint. + */ +#define BT_A2DP_SBC_EP_CFG_DEFAULT(_name, _freq_cfg)\ +static struct bt_a2dp_codec_ie bt_a2dp_codec_ie##_name = {\ +.len = BT_A2DP_SBC_IE_LENGTH, .codec_ie = {_freq_cfg | A2DP_SBC_CH_MODE_JOINT,\ +A2DP_SBC_BLK_LEN_16 | A2DP_SBC_SUBBAND_8 | A2DP_SBC_ALLOC_MTHD_LOUDNESS, 18U, 35U},};\ +struct bt_a2dp_codec_cfg _name = {.codec_config = &bt_a2dp_codec_ie##_name,} + +/** + * @brief A2DP error code + */ +enum bt_a2dp_err_code { + /** Media Codec Type is not valid */ + BT_A2DP_INVALID_CODEC_TYPE = 0xC1, + /** Media Codec Type is not supported */ + BT_A2DP_NOT_SUPPORTED_CODEC_TYPE = 0xC2, + /** Sampling Frequency is not valid or multiple values have been selected */ + BT_A2DP_INVALID_SAMPLING_FREQUENCY = 0xC3, + /** Sampling Frequency is not supported */ + BT_A2DP_NOT_SUPPORTED_SAMPLING_FREQUENCY = 0xC4, + /** Channel Mode is not valid or multiple values have been selected */ + BT_A2DP_INVALID_CHANNEL_MODE = 0xC5, + /** Channel Mode is not supported */ + BT_A2DP_NOT_SUPPORTED_CHANNEL_MODE = 0xC6, + /** None or multiple values have been selected for Number of Subbands */ + BT_A2DP_INVALID_SUBBANDS = 0xC7, + /** Number of Subbands is not supported */ + BT_A2DP_NOT_SUPPORTED_SUBBANDS = 0xC8, + /** None or multiple values have been selected for Allocation Method */ + BT_A2DP_INVALID_ALLOCATION_METHOD = 0xC9, + /** Allocation Method is not supported */ + BT_A2DP_NOT_SUPPORTED_ALLOCATION_METHOD = 0xCA, + /** Minimum Bitpool Value is not valid */ + BT_A2DP_INVALID_MINIMUM_BITPOOL_VALUE = 0xCB, + /** Minimum Bitpool Value is not supported */ + BT_A2DP_NOT_SUPPORTED_MINIMUM_BITPOOL_VALUE = 0xCC, + /** Maximum Bitpool Value is not valid */ + BT_A2DP_INVALID_MAXIMUM_BITPOOL_VALUE = 0xCD, + /** Maximum Bitpool Value is not supported */ + BT_A2DP_NOT_SUPPORTED_MAXIMUM_BITPOOL_VALUE = 0xCE, + /** None or multiple values have been selected for Layer */ + BT_A2DP_INVALID_LAYER = 0xCF, + /** Layer is not supported */ + BT_A2DP_NOT_SUPPORTED_LAYER = 0xD0, + /** CRC is not supported */ + BT_A2DP_NOT_SUPPORTED_CRC = 0xD1, + /** MPF-2 is not supported */ + BT_A2DP_NOT_SUPPORTED_MPF = 0xD2, + /** VBR is not supported */ + BT_A2DP_NOT_SUPPORTED_VBR = 0xD3, + /** None or multiple values have been selected for Bit Rate */ + BT_A2DP_INVALID_BIT_RATE = 0xD4, + /** Bit Rate is not supported */ + BT_A2DP_NOT_SUPPORTED_BIT_RATE = 0xD5, + /** Either 1) Object type is not valid or + * 2) None or multiple values have been selected for Object Type + */ + BT_A2DP_INVALID_OBJECT_TYPE = 0xD6, + /** Object Type is not supported */ + BT_A2DP_NOT_SUPPORTED_OBJECT_TYPE = 0xD7, + /** Either 1) Channels is not valid or + * 2) None or multiple values have been selected for Channels + */ + BT_A2DP_INVALID_CHANNELS = 0xD8, + /** Channels is not supported */ + BT_A2DP_NOT_SUPPORTED_CHANNELS = 0xD9, + /** Version is not valid */ + BT_A2DP_INVALID_VERSION = 0xDA, + /** Version is not supported */ + BT_A2DP_NOT_SUPPORTED_VERSION = 0xDB, + /** Maximum SUL is not acceptable for the Decoder in the SNK */ + BT_A2DP_NOT_SUPPORTED_MAXIMUM_SUL = 0xDC, + /** None or multiple values have been selected for Block Length */ + BT_A2DP_INVALID_BLOCK_LENGTH = 0xDD, + /** The requested CP Type is not supported */ + BT_A2DP_INVALID_CP_TYPE = 0xE0, + /** The format of Content Protection Service Capability/Content + * Protection Scheme Dependent Data is not correct + */ + BT_A2DP_INVALID_CP_FORMAT = 0xE1, + /** The codec parameter is invalid. + * Used if a more specific error code does not exist for the codec in use + */ + BT_A2DP_INVALID_CODEC_PARAMETER = 0xE2, + /** The codec parameter is not supported. + * Used if a more specific error code does not exist for the codec in use + */ + BT_A2DP_NOT_SUPPORTED_CODEC_PARAMETER = 0xE3, + /** Combination of Object Type and DRC is invalid */ + BT_A2DP_INVALID_DRC = 0xE4, + /** DRC is not supported */ + BT_A2DP_NOT_SUPPORTED_DRC = 0xE5, }; -/** @brief Codec ID */ -enum bt_a2dp_codec_id { +/** @brief Codec Type */ +enum bt_a2dp_codec_type { /** Codec SBC */ BT_A2DP_SBC = 0x00, /** Codec MPEG-1 */ @@ -37,52 +281,266 @@ enum bt_a2dp_codec_id { BT_A2DP_VENDOR = 0xff }; -/** @brief Preset for the endpoint */ -struct bt_a2dp_preset { - /** Length of preset */ +/** @brief A2DP structure */ +struct bt_a2dp; + +/* Internal to pass build */ +struct bt_a2dp_stream; + +/** @brief codec information elements for the endpoint */ +struct bt_a2dp_codec_ie { + /** Length of codec_cap */ uint8_t len; - /** Preset */ - uint8_t preset[0]; + /** codec information element */ + uint8_t codec_ie[A2DP_MAX_IE_LENGTH]; +}; + +/** @brief The endpoint configuration */ +struct bt_a2dp_codec_cfg { + /** The media codec configuration content */ + struct bt_a2dp_codec_ie *codec_config; }; /** @brief Stream End Point */ -struct bt_a2dp_endpoint { - /** Code ID */ - uint8_t codec_id; - /** Stream End Point Information */ - struct bt_avdtp_seid_lsep info; - /** Pointer to preset codec chosen */ - struct bt_a2dp_preset *preset; +struct bt_a2dp_ep { + /** Code Type @ref bt_a2dp_codec_type */ + uint8_t codec_type; /** Capabilities */ - struct bt_a2dp_preset *caps; + struct bt_a2dp_codec_ie *codec_cap; + /** AVDTP Stream End Point Identifier */ + struct bt_avdtp_sep sep; + /* Internally used stream object pointer */ + struct bt_a2dp_stream *stream; }; -/** @brief Stream End Point Media Type */ -enum MEDIA_TYPE { - /** Audio Media Type */ - BT_A2DP_AUDIO = 0x00, - /** Video Media Type */ - BT_A2DP_VIDEO = 0x01, - /** Multimedia Media Type */ - BT_A2DP_MULTIMEDIA = 0x02 +struct bt_a2dp_ep_info { + /** Code Type @ref bt_a2dp_codec_type */ + uint8_t codec_type; + /** Codec capabilities, if SBC, use function of a2dp_codec_sbc.h to parse it */ + struct bt_a2dp_codec_ie codec_cap; + /** Stream End Point Information */ + struct bt_avdtp_sep_info sep_info; }; -/** @brief Stream End Point Role */ -enum ROLE_TYPE { - /** Source Role */ - BT_A2DP_SOURCE = 0, - /** Sink Role */ - BT_A2DP_SINK = 1 +/** @brief Helper enum to be used as return value of bt_a2dp_discover_ep_cb. + * The value informs the caller to perform further pending actions or stop them. + */ +enum { + BT_A2DP_DISCOVER_EP_STOP = 0, + BT_A2DP_DISCOVER_EP_CONTINUE, }; -/** @brief A2DP structure */ -struct bt_a2dp; +/** @typedef bt_a2dp_discover_ep_cb + * + * @brief Called when a stream endpoint is discovered. + * + * A function of this type is given by the user to the bt_a2dp_discover_param + * object. It'll be called on each valid stream endpoint discovery completion. + * When no more endpoint then NULL is passed to the user. Otherwise user can get + * valid endpoint information from parameter info, user can set parameter ep to + * get the endpoint after the callback is return. + * The returned function value allows the user to control retrieving follow-up + * endpoints if any. If the user doesn't want to read more endpoints since + * current found endpoints fulfill its requirements then should return + * BT_A2DP_DISCOVER_EP_STOP. Otherwise returned value means + * more subcall iterations are allowable. + * + * @param a2dp a2dp connection object identifying a2dp connection to queried remote. + * @param info Object pointing to the information of the callbacked endpoint. + * @param ep If the user want to use this found endpoint, user can set value to it + * to get the ednpoint that can be used futher in other A2DP APIs. It is NULL if info + * is NULL (no more endpoint is found). + * + * @return BT_A2DP_DISCOVER_EP_STOP in case of no more need to continue discovery + * for next endpoint. By returning BT_A2DP_DISCOVER_EP_STOP user allows this + * discovery continuation. + */ +typedef uint8_t (*bt_a2dp_discover_ep_cb)(struct bt_a2dp *a2dp, + struct bt_a2dp_ep_info *info, struct bt_a2dp_ep **ep); + +struct bt_a2dp_discover_param { + /** discover callback */ + bt_a2dp_discover_ep_cb cb; + /** The discovered endpoint info that is callbacked by cb */ + struct bt_a2dp_ep_info info; + /** The max count of remote endpoints that can be got, + * it save endpoint info internally. + */ + struct bt_avdtp_sep_info *seps_info; + /** The max count of seps (strem endpoint) that can be got in this call route */ + uint8_t sep_count; +}; + +/** @brief The connecting callback */ +struct bt_a2dp_cb { + /** @brief A a2dp connection has been established. + * + * This callback notifies the application of a a2dp connection. + * It means the AVDTP L2CAP connection. + * In case the err parameter is non-zero it means that the + * connection establishment failed. + * + * @param a2dp a2dp connection object. + * @param err error code. + */ + void (*connected)(struct bt_a2dp *a2dp, int err); + /** @brief A a2dp connection has been disconnected. + * + * This callback notifies the application that a a2dp connection + * has been disconnected. + * + * @param a2dp a2dp connection object. + */ + void (*disconnected)(struct bt_a2dp *a2dp); + /** + * @brief Endpoint config request callback + * + * The callback is called whenever an endpoint is requested to be + * configured. + * + * @param a2dp a2dp connection object. + * @param[in] ep Local Audio Endpoint being configured. + * @param[in] codec_cfg Codec configuration. + * @param[out] stream Pointer to stream that will be configured for the endpoint. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*config_req)(struct bt_a2dp *a2dp, struct bt_a2dp_ep *ep, + struct bt_a2dp_codec_cfg *codec_cfg, struct bt_a2dp_stream **stream, + uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_config() + * + * Called when the codec configure operation is completed. + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*config_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief stream establishment request callback + * + * The callback is called whenever an stream is requested to be + * established (open cmd and create the stream l2cap channel). + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*establish_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_establish() + * + * Called when the establishment operation is completed. + * (open cmd and create the stream l2cap channel). + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*establish_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief stream release request callback + * + * The callback is called whenever an stream is requested to be + * released (release cmd and release the l2cap channel) + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*release_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_release() + * + * Called when the release operation is completed. + * (release cmd and release the l2cap channel) + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*release_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief stream start request callback + * + * The callback is called whenever an stream is requested to be + * started. + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*start_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_start() + * + * Called when the start operation is completed. + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*start_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief Endpoint suspend request callback + * + * The callback is called whenever an stream is requested to be + * suspended. + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*suspend_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_suspend() + * + * Called when the suspend operation is completed. + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*suspend_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); + /** + * @brief Endpoint config request callback + * + * The callback is called whenever an endpoint is requested to be + * reconfigured. + * + * @param[in] stream Pointer to stream object. + * @param[out] rsp_err_code give the error code if response error. + * bt_a2dp_err_code or bt_avdtp_err_code + * + * @return 0 in case of success or negative value in case of error. + */ + int (*reconfig_req)(struct bt_a2dp_stream *stream, uint8_t *rsp_err_code); + /** @brief Callback function for bt_a2dp_stream_reconfig() + * + * Called when the reconfig operation is completed. + * + * @param[in] stream Pointer to stream object. + * @param[in] rsp_err_code the remote responsed error code + * bt_a2dp_err_code or bt_avdtp_err_code + */ + void (*reconfig_rsp)(struct bt_a2dp_stream *stream, uint8_t rsp_err_code); +}; /** @brief A2DP Connect. * * This function is to be called after the conn parameter is obtained by * performing a GAP procedure. The API is to be used to establish A2DP * connection between devices. + * This function only establish AVDTP L2CAP Signaling connection. + * After connection success, the callback that is registered by + * bt_a2dp_register_connect_callback is called. * * @param conn Pointer to bt_conn structure. * @@ -91,20 +549,242 @@ struct bt_a2dp; */ struct bt_a2dp *bt_a2dp_connect(struct bt_conn *conn); -/** @brief Endpoint Registration. +/** @brief disconnect l2cap a2dp + * + * This function close AVDTP L2CAP Signaling connection. + * It closes the AVDTP L2CAP Media connection too if it is established. * - * This function is used for registering the stream end points. The user has - * to take care of allocating the memory, the preset pointer and then pass the - * required arguments. Also, only one sep can be registered at a time. + * @param a2dp The a2dp instance. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_disconnect(struct bt_a2dp *a2dp); + +/** @brief Endpoint Registration. * - * @param endpoint Pointer to bt_a2dp_endpoint structure. + * @param ep Pointer to bt_a2dp_ep structure. * @param media_type Media type that the Endpoint is. * @param role Role of Endpoint. * * @return 0 in case of success and error code in case of error. */ -int bt_a2dp_register_endpoint(struct bt_a2dp_endpoint *endpoint, - uint8_t media_type, uint8_t role); +int bt_a2dp_register_ep(struct bt_a2dp_ep *ep, uint8_t media_type, uint8_t role); + +/** @brief register callback. + * + * The cb is called when bt_a2dp_connect is called or it is operated by remote device. + * + * @param cb The callback function. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_register_cb(struct bt_a2dp_cb *cb); + +/** @brief Discover remote endpoints. + * + * @param a2dp The a2dp instance. + * @param param the discover used param. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_discover(struct bt_a2dp *a2dp, struct bt_a2dp_discover_param *param); + +/** @brief A2DP Stream */ +struct bt_a2dp_stream { + /** local endpoint */ + struct bt_a2dp_ep *local_ep; + /** remote endpoint */ + struct bt_a2dp_ep *remote_ep; + /** remote endpoint's Stream End Point ID */ + uint8_t remote_ep_id; + /** Audio stream operations */ + struct bt_a2dp_stream_ops *ops; + /** the a2dp connection */ + struct bt_a2dp *a2dp; + /** the stream current configuration */ + struct bt_a2dp_codec_ie codec_config; +}; + +/** @brief The stream endpoint related operations */ +struct bt_a2dp_stream_ops { + /** + * @brief Stream configured callback + * + * The callback is called whenever an Audio Stream has been configured. + * + * @param stream Stream object that has been configured. + */ + void (*configured)(struct bt_a2dp_stream *stream); + /** + * @brief Stream establishment callback + * + * The callback is called whenever an Audio Stream has been established. + * + * @param stream Stream object that has been established. + */ + void (*established)(struct bt_a2dp_stream *stream); + /** + * @brief Stream release callback + * + * The callback is called whenever an Audio Stream has been released. + * + * @param stream Stream object that has been released. + */ + void (*released)(struct bt_a2dp_stream *stream); + /** + * @brief Stream start callback + * + * The callback is called whenever an Audio Stream has been started. + * + * @param stream Stream object that has been started. + */ + void (*started)(struct bt_a2dp_stream *stream); + /** + * @brief Stream suspend callback + * + * The callback is called whenever an Audio Stream has been suspended. + * + * @param stream Stream object that has been suspended. + */ + void (*suspended)(struct bt_a2dp_stream *stream); + /** + * @brief Stream reconfigured callback + * + * The callback is called whenever an Audio Stream has been reconfigured. + * + * @param stream Stream object that has been reconfigured. + */ + void (*reconfigured)(struct bt_a2dp_stream *stream); +#if defined(CONFIG_BT_A2DP_SINK) + /** @brief the media streaming data, only for sink + * + * @param buf the data buf + * @param seq_num the seqence number + * @param ts the time stamp + */ + void (*recv)(struct bt_a2dp_stream *stream, + struct net_buf *buf, uint16_t seq_num, uint32_t ts); +#endif +#if defined(CONFIG_BT_A2DP_SOURCE) + /** + * @brief Stream audio HCI sent callback + * + * This callback will be called once the controller marks the SDU + * as completed. When the controller does so is implementation + * dependent. It could be after the SDU is enqueued for transmission, + * or after it is sent on air or flushed. + * + * This callback is only used if the ISO data path is HCI. + * + * @param stream Stream object. + */ + void (*sent)(struct bt_a2dp_stream *stream); +#endif +}; + +/** + * @brief Register Audio callbacks for a stream. + * + * Register Audio callbacks for a stream. + * + * @param stream Stream object. + * @param ops Stream operations structure. + */ +void bt_a2dp_stream_cb_register(struct bt_a2dp_stream *stream, struct bt_a2dp_stream_ops *ops); + +/** @brief configure endpoint. + * + * bt_a2dp_discover can be used to find remote's endpoints. + * This function to configure the selected endpoint that is found by + * bt_a2dp_discover. + * This function sends AVDTP_SET_CONFIGURATION. + * + * @param a2dp The a2dp instance. + * @param stream Stream object. + * @param local_ep The configured endpoint that is registered. + * @param remote_ep The remote endpoint. + * @param config The config to configure the endpoint. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_config(struct bt_a2dp *a2dp, struct bt_a2dp_stream *stream, + struct bt_a2dp_ep *local_ep, struct bt_a2dp_ep *remote_ep, + struct bt_a2dp_codec_cfg *config); + +/** @brief establish a2dp streamer. + * + * This function sends the AVDTP_OPEN command and create the l2cap channel. + * + * @param stream The stream object. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_establish(struct bt_a2dp_stream *stream); + +/** @brief release a2dp streamer. + * + * This function sends the AVDTP_CLOSE command and release the l2cap channel. + * + * @param stream The stream object. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_release(struct bt_a2dp_stream *stream); + +/** @brief start a2dp streamer. + * + * This function sends the AVDTP_START command. + * + * @param stream The stream object. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_start(struct bt_a2dp_stream *stream); + +/** @brief suspend a2dp streamer. + * + * This function sends the AVDTP_SUSPEND command. + * + * @param stream The stream object. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_suspend(struct bt_a2dp_stream *stream); + +/** @brief re-configure a2dp streamer + * + * This function sends the AVDTP_RECONFIGURE command. + * + * @param stream The stream object. + * @param config The config to configure the stream. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_reconfig(struct bt_a2dp_stream *stream, struct bt_a2dp_codec_cfg *config); + +/** @brief get the stream l2cap mtu + * + * @param stream The stream object. + * + * @return mtu value + */ +uint32_t bt_a2dp_get_mtu(struct bt_a2dp_stream *stream); + +#if defined(CONFIG_BT_A2DP_SOURCE) +/** @brief send a2dp media data + * + * Only A2DP source side can call this function. + * + * @param stream The stream object. + * @param buf The data. + * @param seq_num The sequence number. + * @param ts The time stamp. + * + * @return 0 in case of success and error code in case of error. + */ +int bt_a2dp_stream_send(struct bt_a2dp_stream *stream, struct net_buf *buf, + uint16_t seq_num, uint32_t ts); +#endif #ifdef __cplusplus } diff --git a/include/zephyr/bluetooth/classic/a2dp_codec_sbc.h b/include/zephyr/bluetooth/classic/a2dp_codec_sbc.h new file mode 100644 index 0000000000000..1a96c914324c9 --- /dev/null +++ b/include/zephyr/bluetooth/classic/a2dp_codec_sbc.h @@ -0,0 +1,124 @@ +/** @file + * @brief Advance Audio Distribution Profile - SBC Codec header. + */ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2015-2016 Intel Corporation + * Copyright (c) 2021 NXP + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Sampling Frequency */ +#define A2DP_SBC_SAMP_FREQ_16000 BIT(7) +#define A2DP_SBC_SAMP_FREQ_32000 BIT(6) +#define A2DP_SBC_SAMP_FREQ_44100 BIT(5) +#define A2DP_SBC_SAMP_FREQ_48000 BIT(4) + +/* Channel Mode */ +#define A2DP_SBC_CH_MODE_MONO BIT(3) +#define A2DP_SBC_CH_MODE_DUAL BIT(2) +#define A2DP_SBC_CH_MODE_STREO BIT(1) +#define A2DP_SBC_CH_MODE_JOINT BIT(0) + +/* Block Length */ +#define A2DP_SBC_BLK_LEN_4 BIT(7) +#define A2DP_SBC_BLK_LEN_8 BIT(6) +#define A2DP_SBC_BLK_LEN_12 BIT(5) +#define A2DP_SBC_BLK_LEN_16 BIT(4) + +/* Subbands */ +#define A2DP_SBC_SUBBAND_4 BIT(3) +#define A2DP_SBC_SUBBAND_8 BIT(2) + +/* Allocation Method */ +#define A2DP_SBC_ALLOC_MTHD_SNR BIT(1) +#define A2DP_SBC_ALLOC_MTHD_LOUDNESS BIT(0) + +#define BT_A2DP_SBC_SAMP_FREQ(cap) ((cap->config[0] >> 4) & 0x0f) +#define BT_A2DP_SBC_CHAN_MODE(cap) ((cap->config[0]) & 0x0f) +#define BT_A2DP_SBC_BLK_LEN(cap) ((cap->config[1] >> 4) & 0x0f) +#define BT_A2DP_SBC_SUB_BAND(cap) ((cap->config[1] >> 2) & 0x03) +#define BT_A2DP_SBC_ALLOC_MTHD(cap) ((cap->config[1]) & 0x03) + +/** @brief SBC Codec */ +struct bt_a2dp_codec_sbc_params { + /** First two octets of configuration */ + uint8_t config[2]; + /** Minimum Bitpool Value */ + uint8_t min_bitpool; + /** Maximum Bitpool Value */ + uint8_t max_bitpool; +} __packed; + +/** If the F bit is set to 0, this field indicates the number of frames contained + * in this packet. If the F bit is set to 1, this field indicates the number + * of remaining fragments, including the current fragment. + * Therefore, the last counter value shall be one. + */ +#define BT_A2DP_SBC_MEDIA_HDR_NUM_FRAMES_GET(hdr) FIELD_GET(GENMASK(3, 0), (hdr)) +/** Set to 1 for the last packet of a fragmented SBC frame, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_L_GET(hdr) FIELD_GET(BIT(5), (hdr)) +/** Set to 1 for the starting packet of a fragmented SBC frame, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_S_GET(hdr) FIELD_GET(BIT(6), (hdr)) +/** Set to 1 if the SBC frame is fragmented, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_F_GET(hdr) FIELD_GET(BIT(7), (hdr)) + +/** If the F bit is set to 0, this field indicates the number of frames contained + * in this packet. If the F bit is set to 1, this field indicates the number + * of remaining fragments, including the current fragment. + * Therefore, the last counter value shall be one. + */ +#define BT_A2DP_SBC_MEDIA_HDR_NUM_FRAMES_SET(hdr, val)\ + hdr = ((hdr) & ~GENMASK(3, 0)) | FIELD_PREP(GENMASK(3, 0), (val)) +/** Set to 1 for the last packet of a fragmented SBC frame, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_L_SET(hdr, val)\ + hdr = ((hdr) & ~BIT(5)) | FIELD_PREP(BIT(5), (val)) +/** Set to 1 for the starting packet of a fragmented SBC frame, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_S_SET(hdr, val)\ + hdr = ((hdr) & ~BIT(6)) | FIELD_PREP(BIT(6), (val)) +/** Set to 1 if the SBC frame is fragmented, otherwise set to 0. */ +#define BT_A2DP_SBC_MEDIA_HDR_F_SET(hdr, val)\ + hdr = ((hdr) & ~BIT(7)) | FIELD_PREP(BIT(7), (val)) + +#define BT_A2DP_SBC_MEDIA_HDR_ENCODE(num_frames, l, s, f)\ + FIELD_PREP(GENMASK(3, 0), num_frames) | FIELD_PREP(BIT(5), l) |\ + FIELD_PREP(BIT(6), s) | FIELD_PREP(BIT(7), f) + +/** @brief get channel num of a2dp sbc config. + * + * @param sbc_codec The a2dp sbc parameter. + * + * @return the channel num. + */ +uint8_t bt_a2dp_sbc_get_channel_num(struct bt_a2dp_codec_sbc_params *sbc_codec); + +/** @brief get sample rate of a2dp sbc config. + * + * @param sbc_codec The a2dp sbc parameter. + * + * @return the sample rate. + */ +uint32_t bt_a2dp_sbc_get_sampling_frequency(struct bt_a2dp_codec_sbc_params *sbc_codec); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_A2DP_CODEC_H_ */ diff --git a/include/zephyr/bluetooth/classic/avdtp.h b/include/zephyr/bluetooth/classic/avdtp.h index 396025814b806..cfd419239783e 100644 --- a/include/zephyr/bluetooth/classic/avdtp.h +++ b/include/zephyr/bluetooth/classic/avdtp.h @@ -4,49 +4,137 @@ /* * Copyright (c) 2015-2016 Intel Corporation + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_BLUETOOTH_AVDTP_H_ #define ZEPHYR_INCLUDE_BLUETOOTH_AVDTP_H_ -#include - #ifdef __cplusplus extern "C" { #endif -/** @brief AVDTP SEID Information */ -struct bt_avdtp_seid_info { - /** Stream End Point ID */ - uint8_t id:6; +/** + * @brief AVDTP error code + */ +enum bt_avdtp_err_code { + /** The response is success, it is not from avdtp spec. */ + BT_AVDTP_SUCCESS = 0x00, + /** The request is time out without response, it is not from avdtp spec. */ + BT_AVDTP_TIME_OUT = 0xFF, + /** The request packet header format error */ + BT_AVDTP_BAD_HEADER_FORMAT = 0x01, + /** The request packet length is not match the assumed length */ + BT_AVDTP_BAD_LENGTH = 0x11, + /** The requested command indicates an invalid ACP SEID (not addressable) */ + BT_AVDTP_BAD_ACP_SEID = 0x12, + /** The SEP is in use */ + BT_AVDTP_SEP_IN_USE = 0x13, + /** The SEP is not in use */ + BT_AVDTP_SEP_NOT_IN_USE = 0x14, + /** The value of Service Category in the request packet is not defined in AVDTP */ + BT_AVDTP_BAD_SERV_CATEGORY = 0x17, + /** The requested command has an incorrect payload format */ + BT_AVDTP_BAD_PAYLOAD_FORMAT = 0x18, + /** The requested command is not supported by the device */ + BT_AVDTP_NOT_SUPPORTED_COMMAND = 0x19, + /** The reconfigure command is an attempt to reconfigure a transport service codec_cap + * of the SEP. Reconfigure is only permitted for application service codec_cap + */ + BT_AVDTP_INVALID_CAPABILITIES = 0x1A, + /** The requested Recovery Type is not defined in AVDTP */ + BT_AVDTP_BAD_RECOVERY_TYPE = 0x22, + /** The format of Media Transport Capability is not correct */ + BT_AVDTP_BAD_MEDIA_TRANSPORT_FORMAT = 0x23, + /** The format of Recovery Service Capability is not correct */ + BT_AVDTP_BAD_RECOVERY_FORMAT = 0x25, + /** The format of Header Compression Service Capability is not correct */ + BT_AVDTP_BAD_ROHC_FORMAT = 0x26, + /** The format of Content Protection Service Capability is not correct */ + BT_AVDTP_BAD_CP_FORMAT = 0x27, + /** The format of Multiplexing Service Capability is not correct */ + BT_AVDTP_BAD_MULTIPLEXING_FORMAT = 0x28, + /** Configuration not supported */ + BT_AVDTP_UNSUPPORTED_CONFIGURAION = 0x29, + /** Indicates that the ACP state machine is in an invalid state in order to process the + * signal. This also includes the situation when an INT receives a request for the + * same command that it is currently expecting a response + */ + BT_AVDTP_BAD_STATE = 0x31, +}; + +/** @brief Stream End Point Type */ +enum bt_avdtp_sep_type { + /** Source Role */ + BT_AVDTP_SOURCE = 0, + /** Sink Role */ + BT_AVDTP_SINK = 1 +}; + +/** @brief Stream End Point Media Type */ +enum bt_avdtp_media_type { + /** Audio Media Type */ + BT_AVDTP_AUDIO = 0x00, + /** Video Media Type */ + BT_AVDTP_VIDEO = 0x01, + /** Multimedia Media Type */ + BT_AVDTP_MULTIMEDIA = 0x02 +}; + +/** @brief AVDTP stream endpoint information. + * Don't need to care endianness because it is not used for data parsing. + */ +struct bt_avdtp_sep_info { /** End Point usage status */ uint8_t inuse:1; + /** Stream End Point ID that is the identifier of the stream endpoint */ + uint8_t id:6; /** Reserved */ - uint8_t rfa0:1; - /** Media-type of the End Point */ - uint8_t media_type:4; - /** TSEP of the End Point */ - uint8_t tsep:1; - /** Reserved */ - uint8_t rfa1:3; -} __packed; + uint8_t reserved:1; + /** Stream End-point Type that indicates if the stream end-point is SNK or SRC */ + enum bt_avdtp_sep_type tsep; + /** Media-type of the End Point + * Only @ref BT_AVDTP_AUDIO is supported now. + */ + enum bt_avdtp_media_type media_type; +}; -/** @brief AVDTP Local SEP*/ -struct bt_avdtp_seid_lsep { - /** Stream End Point information */ - struct bt_avdtp_seid_info sep; - /** Pointer to next local Stream End Point structure */ - struct bt_avdtp_seid_lsep *next; +/** @brief service category Type */ +enum bt_avdtp_service_category { + /** Media Transport */ + BT_AVDTP_SERVICE_MEDIA_TRANSPORT = 0x01, + /** Reporting */ + BT_AVDTP_SERVICE_REPORTING = 0x02, + /** Recovery */ + BT_AVDTP_SERVICE_MEDIA_RECOVERY = 0x03, + /** Content Protection */ + BT_AVDTP_SERVICE_CONTENT_PROTECTION = 0x04, + /** Header Compression */ + BT_AVDTP_SERVICE_HEADER_COMPRESSION = 0x05, + /** Multiplexing */ + BT_AVDTP_SERVICE_MULTIPLEXING = 0x06, + /** Media Codec */ + BT_AVDTP_SERVICE_MEDIA_CODEC = 0x07, + /** Delay Reporting */ + BT_AVDTP_SERVICE_DELAY_REPORTING = 0x08, }; -/** @brief AVDTP Stream */ -struct bt_avdtp_stream { - struct bt_l2cap_br_chan chan; /* Transport Channel*/ - struct bt_avdtp_seid_info lsep; /* Configured Local SEP */ - struct bt_avdtp_seid_info rsep; /* Configured Remote SEP*/ - uint8_t state; /* current state of the stream */ - struct bt_avdtp_stream *next; +/** @brief AVDTP Stream End Point */ +struct bt_avdtp_sep { + /** Stream End Point information */ + struct bt_avdtp_sep_info sep_info; + /** Media Transport Channel*/ + struct bt_l2cap_br_chan chan; + /** the endpoint media data */ + void (*media_data_cb)(struct bt_avdtp_sep *sep, + struct net_buf *buf); + /** avdtp session */ + struct bt_avdtp *session; + /** SEP state */ + uint8_t state; + /* Internally used list node */ + sys_snode_t _node; }; #ifdef __cplusplus diff --git a/include/zephyr/bluetooth/classic/hfp_ag.h b/include/zephyr/bluetooth/classic/hfp_ag.h new file mode 100644 index 0000000000000..6e5173d9fa4c1 --- /dev/null +++ b/include/zephyr/bluetooth/classic/hfp_ag.h @@ -0,0 +1,298 @@ +/** @file + * @brief Handsfree Profile Audio Gateway handling. + */ + +/* + * Copyright (c) 2015-2016 Intel Corporation + * Copyright 2023-2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_BLUETOOTH_HFP_AG_H_ +#define ZEPHYR_INCLUDE_BLUETOOTH_HFP_AG_H_ + +/** + * @brief Hands Free Profile - Audio Gateway (HFP-AG) + * @defgroup bt_hfp_ag Hands Free Profile - Audio Gateway (HFP-AG) + * @ingroup bluetooth + * @{ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* HFP AG Indicators */ +enum bt_hfp_ag_indicator { + BT_HFP_AG_SERVICE_IND = 0, /* Service availability indicator */ + BT_HFP_AG_CALL_IND = 1, /* call status indicator */ + BT_HFP_AG_CALL_SETUP_IND = 2, /* Call set up status indicator */ + BT_HFP_AG_CALL_HELD_IND = 3, /* Call hold status indicator */ + BT_HFP_AG_SIGNAL_IND = 4, /* Signal strength indicator */ + BT_HFP_AG_ROAM_IND = 5, /* Roaming status indicator */ + BT_HFP_AG_BATTERY_IND = 6, /* Battery change indicator */ + BT_HFP_AG_IND_MAX /* Indicator MAX value */ +}; + +/* HFP CODEC */ +#define BT_HFP_AG_CODEC_CVSD 0x01 +#define BT_HFP_AG_CODEC_MSBC 0x02 +#define BT_HFP_AG_CODEC_LC3_SWB 0x03 + +struct bt_hfp_ag; + +/** @brief HFP profile AG application callback */ +struct bt_hfp_ag_cb { + /** HF AG connected callback to application + * + * If this callback is provided it will be called whenever the + * AG connection completes. + * + * @param ag HFP AG object. + */ + void (*connected)(struct bt_hfp_ag *ag); + /** HF disconnected callback to application + * + * If this callback is provided it will be called whenever the + * connection gets disconnected, including when a connection gets + * rejected or cancelled or any error in SLC establishment. + * + * @param ag HFP AG object. + */ + void (*disconnected)(struct bt_hfp_ag *ag); + /** HF SCO/eSCO connected Callback + * + * If this callback is provided it will be called whenever the + * SCO/eSCO connection completes. + * + * @param ag HFP AG object. + * @param sco_conn SCO/eSCO Connection object. + */ + void (*sco_connected)(struct bt_hfp_ag *ag, struct bt_conn *sco_conn); + /** HF SCO/eSCO disconnected Callback + * + * If this callback is provided it will be called whenever the + * SCO/eSCO connection gets disconnected. + * + * @param ag HFP AG object. + * @param sco_conn SCO/eSCO Connection object. + */ + void (*sco_disconnected)(struct bt_hfp_ag *ag); + + /** HF memory dialing request Callback + * + * If this callback is provided it will be called whenever a + * new call is requested with memory dialing from HFP unit. + * Get the phone number according to the given AG memory location. + * + * @param ag HFP AG object. + * @param location AG memory location + * @param number Dailing number + * + * @return 0 in case of success or negative value in case of error. + */ + int (*memory_dial)(struct bt_hfp_ag *ag, const char *location, char **number); + + /** HF outgoing Callback + * + * If this callback is provided it will be called whenever a + * new call is outgoing. + * + * @param ag HFP AG object. + * @param number Dailing number + */ + void (*outgoing)(struct bt_hfp_ag *ag, const char *number); + + /** HF incoming Callback + * + * If this callback is provided it will be called whenever a + * new call is incoming. + * + * @param ag HFP AG object. + * @param number Incoming number + */ + void (*incoming)(struct bt_hfp_ag *ag, const char *number); + + /** HF ringing Callback + * + * If this callback is provided it will be called whenever the + * call is in the ringing + * + * @param ag HFP AG object. + * @param in_bond true - in-bond ringing, false - No in-bond ringing + */ + void (*ringing)(struct bt_hfp_ag *ag, bool in_band); + + /** HF call accept Callback + * + * If this callback is provided it will be called whenever the + * call is accepted. + * + * @param ag HFP AG object. + */ + void (*accept)(struct bt_hfp_ag *ag); + + /** HF call reject Callback + * + * If this callback is provided it will be called whenever the + * call is rejected. + * + * @param ag HFP AG object. + */ + void (*reject)(struct bt_hfp_ag *ag); + + /** HF call terminate Callback + * + * If this callback is provided it will be called whenever the + * call is terminated. + * + * @param ag HFP AG object. + */ + void (*terminate)(struct bt_hfp_ag *ag); + + /** Supported codec Ids callback + * + * If this callback is provided it will be called whenever the + * supported codec ids are updated. + * + * @param ag HFP AG object. + */ + void (*codec)(struct bt_hfp_ag *ag, uint32_t ids); +}; + +/** @brief Register HFP AG profile + * + * Register Handsfree profile AG callbacks to monitor the state and get the + * required HFP details to display. + * + * @param cb callback structure. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_register(struct bt_hfp_ag_cb *cb); + +/** @brief Create the hfp ag session + * + * Create the hfp ag session + * + * @param conn ACL connection object. + * @param ag Created HFP AG object. + * @param channel Peer rfcomm channel to be connected. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_connect(struct bt_conn *conn, struct bt_hfp_ag **ag, uint8_t channel); + +/** @brief Disconnect the hfp ag session + * + * Disconnect the hfp ag session + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_disconnect(struct bt_hfp_ag *ag); + +/** @brief Notify HFP Unit of an incoming call + * + * Notify HFP Unit of an incoming call. + * + * @param ag HFP AG object. + * @param number Dailing number. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_incoming(struct bt_hfp_ag *ag, const char *number); + +/** @brief Reject the incoming call + * + * Reject the incoming call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_reject(struct bt_hfp_ag *ag); + +/** @brief Accept the incoming call + * + * Accept the incoming call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_accept(struct bt_hfp_ag *ag); + +/** @brief Terminate the active/hold call + * + * Terminate the active/hold call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_terminate(struct bt_hfp_ag *ag); + +/** @brief Dial a call + * + * Dial a call. + * + * @param ag HFP AG object. + * @param number Dailing number. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_outgoing(struct bt_hfp_ag *ag, const char *number); + +/** @brief Notify HFP Unit that the remote starts ringing + * + * Notify HFP Unit that the remote starts ringing. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_ringing(struct bt_hfp_ag *ag); + +/** @brief Notify HFP Unit that the remote rejects the call + * + * Notify HFP Unit that the remote rejects the call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_reject(struct bt_hfp_ag *ag); + +/** @brief Notify HFP Unit that the remote accepts the call + * + * Notify HFP Unit that the remote accepts the call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_accept(struct bt_hfp_ag *ag); + +/** @brief Notify HFP Unit that the remote terminates the active/hold call + * + * Notify HFP Unit that the remote terminates the active/hold call. + * + * @param ag HFP AG object. + * + * @return 0 in case of success or negative value in case of error. + */ +int bt_hfp_ag_remote_terminate(struct bt_hfp_ag *ag); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_BLUETOOTH_HFP_HF_H_ */ diff --git a/include/zephyr/bluetooth/classic/rfcomm.h b/include/zephyr/bluetooth/classic/rfcomm.h index 5664506931c82..1d3056643bd0b 100644 --- a/include/zephyr/bluetooth/classic/rfcomm.h +++ b/include/zephyr/bluetooth/classic/rfcomm.h @@ -66,10 +66,9 @@ struct bt_rfcomm_dlc_ops { /** DLC sent callback * * @param dlc The dlc which has sent data. - * @param buf Buffer containing data has been sent. * @param err Sent result. */ - void (*sent)(struct bt_rfcomm_dlc *dlc, struct net_buf *buf, int err); + void (*sent)(struct bt_rfcomm_dlc *dlc, int err); }; /** @brief Role of RFCOMM session and dlc. Used only by internal APIs @@ -104,7 +103,9 @@ struct bt_rfcomm_dlc { /* Stack & kernel data for TX thread */ struct k_thread tx_thread; - K_KERNEL_STACK_MEMBER(stack, 256); +#if defined(CONFIG_BT_RFCOMM_DLC_STACK_SIZE) + K_KERNEL_STACK_MEMBER(stack, CONFIG_BT_RFCOMM_DLC_STACK_SIZE); +#endif /* CONFIG_BT_RFCOMM_DLC_STACK_SIZE */ }; struct bt_rfcomm_server { diff --git a/include/zephyr/bluetooth/conn.h b/include/zephyr/bluetooth/conn.h index ca8a7bb3fb941..32c9aa9f11e4f 100644 --- a/include/zephyr/bluetooth/conn.h +++ b/include/zephyr/bluetooth/conn.h @@ -515,6 +515,57 @@ struct bt_conn_le_tx_power_report { int8_t delta; }; +/** @brief Path Loss zone that has been entered. + * + * The path loss zone that has been entered in the most recent LE Path Loss Monitoring + * Threshold Change event as documented in Core Spec. Version 5.4 Vol.4, Part E, 7.7.65.32. + * + * @note BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE has been added to notify when path loss becomes + * unavailable. + */ +enum bt_conn_le_path_loss_zone { + /** Low path loss zone entered. */ + BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_LOW, + /** Middle path loss zone entered. */ + BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_MIDDLE, + /** High path loss zone entered. */ + BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH, + /** Path loss has become unavailable. */ + BT_CONN_LE_PATH_LOSS_ZONE_UNAVAILABLE, +}; + +BUILD_ASSERT(BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_LOW == BT_HCI_LE_ZONE_ENTERED_LOW); +BUILD_ASSERT(BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_MIDDLE == BT_HCI_LE_ZONE_ENTERED_MIDDLE); +BUILD_ASSERT(BT_CONN_LE_PATH_LOSS_ZONE_ENTERED_HIGH == BT_HCI_LE_ZONE_ENTERED_HIGH); + +/** @brief LE Path Loss Monitoring Threshold Change Report Structure. */ +struct bt_conn_le_path_loss_threshold_report { + + /** Path Loss zone as documented in Core Spec. Version 5.4 Vol.4, Part E, 7.7.65.32. */ + enum bt_conn_le_path_loss_zone zone; + + /** Current path loss (dB). */ + uint8_t path_loss; +}; + +/** @brief LE Path Loss Monitoring Parameters Structure as defined in Core Spec. Version 5.4 + * Vol.4, Part E, 7.8.119 LE Set Path Loss Reporting Parameters command. + */ +struct bt_conn_le_path_loss_reporting_param { + /** High threshold for the path loss (dB). */ + uint8_t high_threshold; + /** Hysteresis value for the high threshold (dB). */ + uint8_t high_hysteresis; + /** Low threshold for the path loss (dB). */ + uint8_t low_threshold; + /** Hysteresis value for the low threshold (dB). */ + uint8_t low_hysteresis; + /** Minimum time in number of connection events to be observed once the + * path loss crosses the threshold before an event is generated. + */ + uint16_t min_time_spent; +}; + /** @brief Passkey Keypress Notification type * * The numeric values are the same as in the Core specification for Pairing @@ -601,6 +652,34 @@ int bt_conn_le_set_tx_power_report_enable(struct bt_conn *conn, bool local_enable, bool remote_enable); +/** @brief Set Path Loss Monitoring Parameters. + * + * Change the configuration for path loss threshold change events for a given conn handle. + * + * @note To use this API @kconfig{CONFIG_BT_PATH_LOSS_MONITORING} must be set. + * + * @param conn Connection object. + * @param param Path Loss Monitoring parameters + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_le_set_path_loss_mon_param(struct bt_conn *conn, + const struct bt_conn_le_path_loss_reporting_param *param); + +/** @brief Enable or Disable Path Loss Monitoring. + * + * Enable or disable Path Loss Monitoring, which will decide whether Path Loss Threshold events + * are sent from the controller to the host. + * + * @note To use this API @kconfig{CONFIG_BT_PATH_LOSS_MONITORING} must be set. + * + * @param conn Connection Object. + * @param enable Enable/disable path loss reporting. + * + * @return Zero on success or (negative) error code on failure. + */ +int bt_conn_le_set_path_loss_mon_enable(struct bt_conn *conn, bool enable); + /** @brief Update the connection parameters. * * If the local device is in the peripheral role then updating the connection @@ -768,7 +847,8 @@ struct bt_conn_le_create_param { * This uses the General Connection Establishment procedure. * * The application must disable explicit scanning before initiating - * a new LE connection. + * a new LE connection if @kconfig{CONFIG_BT_SCAN_AND_INITIATE_IN_PARALLEL} + * is not enabled. * * @param[in] peer Remote address. * @param[in] create_param Create connection parameters. @@ -1154,7 +1234,22 @@ struct bt_conn_cb { const struct bt_conn_le_tx_power_report *report); #endif /* CONFIG_BT_TRANSMIT_POWER_CONTROL */ - struct bt_conn_cb *_next; +#if defined(CONFIG_BT_PATH_LOSS_MONITORING) + /** @brief LE Path Loss Threshold event. + * + * This callback notifies the application that there has been a path loss threshold + * crossing or reporting the initial path loss threshold zone after using + * @ref bt_conn_le_set_path_loss_mon_enable. + * + * @param conn Connection object. + * @param report Path loss threshold report. + */ + void (*path_loss_threshold_report)(struct bt_conn *conn, + const struct bt_conn_le_path_loss_threshold_report *report); +#endif /* CONFIG_BT_PATH_LOSS_MONITORING */ + + /** @internal Internally used field for list handling */ + sys_snode_t _node; }; /** @brief Register connection callbacks. @@ -1162,8 +1257,11 @@ struct bt_conn_cb { * Register callbacks to monitor the state of connections. * * @param cb Callback struct. Must point to memory that remains valid. + * + * @retval 0 Success. + * @retval -EEXIST if @p cb was already registered. */ -void bt_conn_cb_register(struct bt_conn_cb *cb); +int bt_conn_cb_register(struct bt_conn_cb *cb); /** * @brief Unregister connection callbacks. diff --git a/include/zephyr/bluetooth/gatt.h b/include/zephyr/bluetooth/gatt.h index 5f50a4c802d66..e1c42be9fcd1c 100644 --- a/include/zephyr/bluetooth/gatt.h +++ b/include/zephyr/bluetooth/gatt.h @@ -169,6 +169,7 @@ typedef ssize_t (*bt_gatt_attr_write_func_t)(struct bt_conn *conn, struct bt_gatt_attr { /** Attribute UUID */ const struct bt_uuid *uuid; + /** Attribute read callback */ bt_gatt_attr_read_func_t read; /** Attribute write callback */ bt_gatt_attr_write_func_t write; diff --git a/include/zephyr/bluetooth/hci.h b/include/zephyr/bluetooth/hci.h index 258f86519b61a..7dfcb2275270f 100644 --- a/include/zephyr/bluetooth/hci.h +++ b/include/zephyr/bluetooth/hci.h @@ -20,6 +20,20 @@ extern "C" { #endif +/** Converts a HCI error to string. + * + * The error codes are described in the Bluetooth Core specification, + * Vol 1, Part F, Section 2. + * + * The HCI documentation found in Vol 4, Part E, + * describes when the different error codes are used. + * + * See also the defined BT_HCI_ERR_* macros. + * + * @return The string representation of the HCI error code. + */ +const char *bt_hci_err_to_str(uint8_t hci_err); + /** Allocate a HCI command buffer. * * This function allocates a new buffer for a HCI command. It is given @@ -97,6 +111,15 @@ int bt_hci_get_conn_handle(const struct bt_conn *conn, uint16_t *conn_handle); */ int bt_hci_get_adv_handle(const struct bt_le_ext_adv *adv, uint8_t *adv_handle); +/** @brief Get periodic advertising sync handle. + * + * @param sync Periodic advertising sync set. + * @param sync_handle Place to store the periodic advertising sync handle. + * + * @return 0 on success or negative error value on failure. + */ +int bt_hci_get_adv_sync_handle(const struct bt_le_per_adv_sync *sync, uint16_t *sync_handle); + /** @brief Obtain the version string given a core version number. * * The core version of a controller can be obtained by issuing diff --git a/include/zephyr/bluetooth/hci_types.h b/include/zephyr/bluetooth/hci_types.h index f1ebf0c7d3eb7..1aa5aa915a3e8 100644 --- a/include/zephyr/bluetooth/hci_types.h +++ b/include/zephyr/bluetooth/hci_types.h @@ -108,17 +108,17 @@ struct bt_hci_acl_hdr { #define bt_iso_pkt_flags(h) ((h) >> 14) #define bt_iso_pkt_len_pack(h, f) (((h) & BIT_MASK(12)) | ((f) << 14)) -struct bt_hci_iso_data_hdr { +struct bt_hci_iso_sdu_hdr { uint16_t sn; uint16_t slen; /* 12 bit len, 2 bit RFU, 2 bit packet status */ } __packed; -#define BT_HCI_ISO_DATA_HDR_SIZE 4 +#define BT_HCI_ISO_SDU_HDR_SIZE 4 -struct bt_hci_iso_ts_data_hdr { +struct bt_hci_iso_sdu_ts_hdr { uint32_t ts; - struct bt_hci_iso_data_hdr data; + struct bt_hci_iso_sdu_hdr sdu; } __packed; -#define BT_HCI_ISO_TS_DATA_HDR_SIZE 8 +#define BT_HCI_ISO_SDU_TS_HDR_SIZE 8 /* Bluetooth spec v5.4 Vol 4, Part E - 5.4.5 HCI ISO Data Packets */ struct bt_hci_iso_hdr { @@ -276,8 +276,17 @@ struct bt_hci_cmd_hdr { #define BT_FEAT_LE_ISO(feat) (BT_FEAT_LE_CIS(feat) | \ BT_FEAT_LE_BIS(feat)) -/* LE States */ -#define BT_LE_STATES_PER_CONN_ADV(states) (states & 0x0000004000000000) +/* LE States. See Core_v5.4, Vol 4, Part E, Section 7.8.27 */ +#define BT_LE_STATES_PER_CONN_ADV(states) (states & BIT64_MASK(38)) + +#if defined(CONFIG_BT_SCAN_AND_INITIATE_IN_PARALLEL) +/* Both passive and active scanner can be run in parallel with initiator. */ +#define BT_LE_STATES_SCAN_INIT(states) ((states) & BIT64_MASK(22) && \ + (states) & BIT64_MASK(23)) + +#else +#define BT_LE_STATES_SCAN_INIT(states) 0 +#endif /* Bonding/authentication types */ #define BT_HCI_NO_BONDING 0x00 @@ -567,6 +576,66 @@ struct bt_hci_rp_write_conn_accept_timeout { #define BT_BREDR_SCAN_INQUIRY 0x01 #define BT_BREDR_SCAN_PAGE 0x02 +#define BT_COD(major_service, major_device, minor_device) \ + (((uint32_t)major_service << 13) | ((uint32_t)major_device << 8) | \ + ((uint32_t)minor_device << 2)) +#define BT_COD_VALID(cod) ((0 == (cod[0] & (BIT(0) | BIT(1)))) ? true : false) +#define BT_COD_MAJOR_SERVICE_CLASSES(cod) \ + ((((uint32_t)cod[2] & 0xFF) >> 5) | (((uint32_t)cod[1] & 0xD0) >> 5)) +#define BT_COD_MAJOR_DEVICE_CLASS(cod) ((((uint32_t)cod[1]) & 0x1FUL)) +#define BT_COD_MINOR_DEVICE_CLASS(cod) (((((uint32_t)cod[0]) & 0xFF) >> 2)) + +#define BT_COD_MAJOR_MISC 0x00 +#define BT_COD_MAJOR_COMPUTER 0x01 +#define BT_COD_MAJOR_PHONE 0x02 +#define BT_COD_MAJOR_LAN_NETWORK_AP 0x03 +#define BT_COD_MAJOR_AUDIO_VIDEO 0x04 +#define BT_COD_MAJOR_PERIPHERAL 0x05 +#define BT_COD_MAJOR_IMAGING 0x06 +#define BT_COD_MAJOR_WEARABLE 0x07 +#define BT_COD_MAJOR_TOY 0x08 +#define BT_COD_MAJOR_HEALTH 0x09 +#define BT_COD_MAJOR_UNCATEGORIZED 0x1F + +/* Minor Device Class field - Computer Major Class */ +#define BT_COD_MAJOR_COMPUTER_MINOR_UNCATEGORIZED 0x00 +#define BT_COD_MAJOR_COMPUTER_MINOR_DESKTOP 0x01 +#define BT_COD_MAJOR_COMPUTER_MINOR_SERVER_CLASS_COMPUTER 0x02 +#define BT_COD_MAJOR_COMPUTER_MINOR_LAPTOP 0x03 +#define BT_COD_MAJOR_COMPUTER_MINOR_HANDHELD_PC_PDA 0x04 +#define BT_COD_MAJOR_COMPUTER_MINOR_PALM_SIZE_PC_PDA 0x05 +#define BT_COD_MAJOR_COMPUTER_MINOR_WEARABLE_COMPUTER 0x06 +#define BT_COD_MAJOR_COMPUTER_MINOR_TABLET 0x07 + +/* Minor Device Class field - Phone Major Class */ +#define BT_COD_MAJOR_PHONE_MINOR_UNCATEGORIZED 0x00 +#define BT_COD_MAJOR_PHONE_MINOR_CELLULAR 0x01 +#define BT_COD_MAJOR_PHONE_MINOR_CORDLESS 0x02 +#define BT_COD_MAJOR_PHONE_MINOR_SMARTPHONE 0x03 +#define BT_COD_MAJOR_PHONE_MINOR_WIRED_MODEM_VOICE_GATEWAY 0x04 +#define BT_COD_MAJOR_PHONE_MINOR_ISDN 0x05 + +/* Minor Device Class field - Audio/Video Major Class */ +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_UNCATEGORIZED 0x00 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_WEARABLE_HEADSET 0x01 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_HANDS_FREE 0x02 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_RFU 0x03 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_MICROPHONE 0x04 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_LOUDSPEAKER 0x05 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_HEADPHONES 0x06 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_PORTABLE_AUDIO 0x07 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_CAR_AUDIO 0x08 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_SET_TOP_BOX 0x09 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_HIFI_AUDIO 0x0A +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VCR 0x0B +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VIDEO_CAMERA 0x0C +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_CAMCORDER 0x0D +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VIDEO_MONITOR 0x0E +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VIDEO_DISPLAY_LOUDSPEAKER 0x0F +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_VIDEO_CONFERENCING 0x10 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_RFU2 0x11 +#define BT_COD_MAJOR_AUDIO_VIDEO_MINOR_GAME_TOY 0x12 + #define BT_HCI_OP_WRITE_CLASS_OF_DEVICE BT_OP(BT_OGF_BASEBAND, 0x0024) /* 0x0c24 */ struct bt_hci_cp_write_class_of_device { uint8_t class_of_device[3]; @@ -615,6 +684,26 @@ struct bt_hci_cp_le_set_tx_power_report_enable { uint8_t remote_enable; } __packed; +struct bt_hci_cp_le_set_path_loss_reporting_parameters { + uint16_t handle; + uint8_t high_threshold; + uint8_t high_hysteresis; + uint8_t low_threshold; + uint8_t low_hysteresis; + uint16_t min_time_spent; +} __packed; + +struct bt_hci_cp_le_set_path_loss_reporting_enable { + uint16_t handle; + uint8_t enable; +} __packed; + +#define BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_PARAMETERS BT_OP(BT_OGF_LE, 0x0078) /* 0x2078 */ + +#define BT_HCI_LE_PATH_LOSS_REPORTING_DISABLE 0x00 +#define BT_HCI_LE_PATH_LOSS_REPORTING_ENABLE 0x01 +#define BT_HCI_OP_LE_SET_PATH_LOSS_REPORTING_ENABLE BT_OP(BT_OGF_LE, 0x0079) /* 0x2079 */ + #define BT_HCI_CTL_TO_HOST_FLOW_DISABLE 0x00 #define BT_HCI_CTL_TO_HOST_FLOW_ENABLE 0x01 #define BT_HCI_OP_SET_CTL_TO_HOST_FLOW BT_OP(BT_OGF_BASEBAND, 0x0031) /* 0x0c31 */ @@ -2960,6 +3049,18 @@ struct bt_hci_evt_le_req_peer_sca_complete { uint8_t sca; } __packed; +#define BT_HCI_LE_ZONE_ENTERED_LOW 0x0 +#define BT_HCI_LE_ZONE_ENTERED_MIDDLE 0x1 +#define BT_HCI_LE_ZONE_ENTERED_HIGH 0x2 +#define BT_HCI_LE_PATH_LOSS_UNAVAILABLE 0xFF + +#define BT_HCI_EVT_LE_PATH_LOSS_THRESHOLD 0x20 +struct bt_hci_evt_le_path_loss_threshold { + uint16_t handle; + uint8_t current_path_loss; + uint8_t zone_entered; +} __packed; + /** Reason for Transmit power reporting. */ /* Local Transmit power changed. */ diff --git a/include/zephyr/bluetooth/hci_vs.h b/include/zephyr/bluetooth/hci_vs.h index 3561e20e9aa58..dabbe2902eaf9 100644 --- a/include/zephyr/bluetooth/hci_vs.h +++ b/include/zephyr/bluetooth/hci_vs.h @@ -451,7 +451,7 @@ struct bt_hci_evt_mesh_scanning_report { struct bt_hci_evt_mesh_scan_report reports[0]; } __packed; -struct net_buf *hci_vs_err_stack_frame(unsigned int reason, const z_arch_esf_t *esf); +struct net_buf *hci_vs_err_stack_frame(unsigned int reason, const struct arch_esf *esf); struct net_buf *hci_vs_err_trace(const char *file, uint32_t line, uint64_t pc); struct net_buf *hci_vs_err_assert(const char *file, uint32_t line); diff --git a/include/zephyr/bluetooth/iso.h b/include/zephyr/bluetooth/iso.h index f7bb3900e7649..a8166a5605132 100644 --- a/include/zephyr/bluetooth/iso.h +++ b/include/zephyr/bluetooth/iso.h @@ -14,6 +14,10 @@ /** * @brief Isochronous channels (ISO) * @defgroup bt_iso Isochronous channels (ISO) + * + * @since 2.3 + * @version 0.8.0 + * * @ingroup bluetooth * @{ */ @@ -156,7 +160,7 @@ struct bt_iso_chan { struct bt_iso_chan_qos *qos; /** Channel state */ enum bt_iso_state state; -#if defined(CONFIG_BT_SMP) || defined(__DOXYGEN__) +#if (defined(CONFIG_BT_SMP) && defined(CONFIG_BT_ISO_UNICAST)) || defined(__DOXYGEN__) /** @brief The required security level of the channel * * This value can be set as the central before connecting a CIS @@ -167,7 +171,7 @@ struct bt_iso_chan { * Only available when @kconfig{CONFIG_BT_SMP} is enabled. */ bt_security_t required_sec_level; -#endif /* CONFIG_BT_SMP */ +#endif /* CONFIG_BT_SMP && CONFIG_BT_ISO_UNICAST */ /** Node used internally by the stack */ sys_snode_t node; }; diff --git a/include/zephyr/bluetooth/l2cap.h b/include/zephyr/bluetooth/l2cap.h index 02bb706f87068..f471c9253794b 100644 --- a/include/zephyr/bluetooth/l2cap.h +++ b/include/zephyr/bluetooth/l2cap.h @@ -157,8 +157,6 @@ struct bt_l2cap_le_endpoint { uint16_t mtu; /** Endpoint Maximum PDU payload Size */ uint16_t mps; - /** Endpoint initial credits */ - uint16_t init_credits; /** Endpoint credits */ atomic_t credits; }; @@ -192,13 +190,9 @@ struct bt_l2cap_le_chan { * L2CAP_LE_CREDIT_BASED_CONNECTION_REQ/RSP or L2CAP_CONFIGURATION_REQ. */ struct bt_l2cap_le_endpoint tx; -#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL) - /** Channel Transmission queue */ + /** Channel Transmission queue (for SDUs) */ struct k_fifo tx_queue; - /** Channel Pending Transmission buffer */ - struct net_buf *tx_buf; - /** Channel Transmission work */ - struct k_work_delayable tx_work; +#if defined(CONFIG_BT_L2CAP_DYNAMIC_CHANNEL) /** Segment SDU packet from upper layer */ struct net_buf *_sdu; uint16_t _sdu_len; @@ -220,6 +214,13 @@ struct bt_l2cap_le_chan { struct k_work_delayable rtx_work; struct k_work_sync rtx_sync; #endif + + /** @internal To be used with @ref bt_conn.upper_data_ready */ + sys_snode_t _pdu_ready; + /** @internal To be used with @ref bt_conn.upper_data_ready */ + atomic_t _pdu_ready_lock; + /** @internal Holds the length of the current PDU/segment */ + size_t _pdu_remaining; }; /** @@ -262,6 +263,13 @@ struct bt_l2cap_br_chan { /* Response Timeout eXpired (RTX) timer */ struct k_work_delayable rtx_work; struct k_work_sync rtx_sync; + + /** @internal To be used with @ref bt_conn.upper_data_ready */ + sys_snode_t _pdu_ready; + /** @internal To be used with @ref bt_conn.upper_data_ready */ + atomic_t _pdu_ready_lock; + /** @internal Queue of net bufs not yet sent to lower layer */ + struct k_fifo _pdu_tx_queue; }; /** @brief L2CAP Channel operations structure. */ @@ -599,6 +607,7 @@ int bt_l2cap_chan_disconnect(struct bt_l2cap_chan *chan); * @return -EINVAL if `buf` or `chan` is NULL. * @return -EINVAL if `chan` is not either BR/EDR or LE credit-based. * @return -EINVAL if buffer doesn't have enough bytes reserved to fit header. + * @return -EINVAL if buffer's reference counter != 1 * @return -EMSGSIZE if `buf` is larger than `chan`'s MTU. * @return -ENOTCONN if underlying conn is disconnected. * @return -ESHUTDOWN if L2CAP channel is disconnected. diff --git a/include/zephyr/bluetooth/testing.h b/include/zephyr/bluetooth/testing.h index 58aae9726ffa1..74806a53a6df1 100644 --- a/include/zephyr/bluetooth/testing.h +++ b/include/zephyr/bluetooth/testing.h @@ -53,8 +53,11 @@ struct bt_test_cb { /** Register callbacks for Bluetooth testing purposes * * @param cb bt_test_cb callback structure + * + * @retval 0 Success. + * @retval -EEXIST if @p cb was already registered. */ -void bt_test_cb_register(struct bt_test_cb *cb); +int bt_test_cb_register(struct bt_test_cb *cb); /** Unregister callbacks for Bluetooth testing purposes * diff --git a/include/zephyr/bluetooth/uuid.h b/include/zephyr/bluetooth/uuid.h index f430fc7edf5bf..8568ebb254d2c 100644 --- a/include/zephyr/bluetooth/uuid.h +++ b/include/zephyr/bluetooth/uuid.h @@ -4120,12 +4120,11 @@ struct bt_uuid_128 { /** * @brief Set Identity Resolving Key value */ -#define BT_UUID_CSIS_SET_SIRK_VAL 0x2b84 +#define BT_UUID_CSIS_SIRK_VAL 0x2b84 /** * @brief Set Identity Resolving Key */ -#define BT_UUID_CSIS_SET_SIRK \ - BT_UUID_DECLARE_16(BT_UUID_CSIS_SET_SIRK_VAL) +#define BT_UUID_CSIS_SIRK BT_UUID_DECLARE_16(BT_UUID_CSIS_SIRK_VAL) /** * @brief Set size value */ diff --git a/include/zephyr/cache.h b/include/zephyr/cache.h index f5547f64afde2..9dbadb8d4ee8e 100644 --- a/include/zephyr/cache.h +++ b/include/zephyr/cache.h @@ -550,7 +550,7 @@ static ALWAYS_INLINE void sys_cache_flush(void *addr, size_t size) } #endif -#include +#include #ifdef __cplusplus } #endif diff --git a/include/zephyr/data/json.h b/include/zephyr/data/json.h index b8b386d968ac0..07393109009a3 100644 --- a/include/zephyr/data/json.h +++ b/include/zephyr/data/json.h @@ -45,6 +45,7 @@ enum json_tokens { JSON_TOK_FLOAT = '1', JSON_TOK_OPAQUE = '2', JSON_TOK_OBJ_ARRAY = '3', + JSON_TOK_ENCODED_OBJ = '4', JSON_TOK_TRUE = 't', JSON_TOK_FALSE = 'f', JSON_TOK_NULL = 'n', @@ -191,11 +192,9 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = (sizeof(#field_name_) - 1), \ .type = JSON_TOK_OBJECT_START, \ .offset = offsetof(struct_, field_name_), \ - { \ - .object = { \ - .sub_descr = sub_descr_, \ - .sub_descr_len = ARRAY_SIZE(sub_descr_), \ - }, \ + .object = { \ + .sub_descr = sub_descr_, \ + .sub_descr_len = ARRAY_SIZE(sub_descr_), \ }, \ } @@ -277,12 +276,10 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(#field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ - elem_type_,), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ + elem_type_,), \ + .n_elements = (max_len_), \ }, \ } @@ -328,13 +325,11 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(#field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ - JSON_TOK_OBJECT_START, \ - Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ + JSON_TOK_OBJECT_START, \ + Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \ + .n_elements = (max_len_), \ }, \ } @@ -389,15 +384,13 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(#field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR( \ - struct_, len_field_, JSON_TOK_ARRAY_START, \ - Z_JSON_DESCR_ARRAY( \ - elem_descr_, \ - 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR( \ + struct_, len_field_, JSON_TOK_ARRAY_START, \ + Z_JSON_DESCR_ARRAY( \ + elem_descr_, \ + 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \ + .n_elements = (max_len_), \ }, \ } @@ -426,15 +419,13 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(#json_field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, struct_field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR( \ - struct_, len_field_, JSON_TOK_ARRAY_START, \ - Z_JSON_DESCR_ARRAY( \ - elem_descr_, \ - 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR( \ + struct_, len_field_, JSON_TOK_ARRAY_START, \ + Z_JSON_DESCR_ARRAY( \ + elem_descr_, \ + 1 + ZERO_OR_COMPILE_ERROR(elem_descr_len_ == 1))), \ + .n_elements = (max_len_), \ }, \ } @@ -483,11 +474,9 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = (sizeof(json_field_name_) - 1), \ .type = JSON_TOK_OBJECT_START, \ .offset = offsetof(struct_, struct_field_name_), \ - { \ - .object = { \ - .sub_descr = sub_descr_, \ - .sub_descr_len = ARRAY_SIZE(sub_descr_), \ - }, \ + .object = { \ + .sub_descr = sub_descr_, \ + .sub_descr_len = ARRAY_SIZE(sub_descr_), \ }, \ } @@ -516,12 +505,10 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(json_field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, struct_field_name_), \ - { \ - .array = { \ - .element_descr = \ - Z_JSON_ELEMENT_DESCR(struct_, len_field_, elem_type_,), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = \ + Z_JSON_ELEMENT_DESCR(struct_, len_field_, elem_type_,), \ + .n_elements = (max_len_), \ }, \ } @@ -575,13 +562,11 @@ typedef int (*json_append_bytes_t)(const char *bytes, size_t len, .field_name_len = sizeof(json_field_name_) - 1, \ .type = JSON_TOK_ARRAY_START, \ .offset = offsetof(struct_, struct_field_name_), \ - { \ - .array = { \ - .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ - JSON_TOK_OBJECT_START, \ - Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \ - .n_elements = (max_len_), \ - }, \ + .array = { \ + .element_descr = Z_JSON_ELEMENT_DESCR(struct_, len_field_, \ + JSON_TOK_OBJECT_START, \ + Z_JSON_DESCR_OBJ(elem_descr_, elem_descr_len_)), \ + .n_elements = (max_len_), \ }, \ } diff --git a/include/zephyr/debug/coredump.h b/include/zephyr/debug/coredump.h index 740ef4776b8d5..f61f4e94a38b7 100644 --- a/include/zephyr/debug/coredump.h +++ b/include/zephyr/debug/coredump.h @@ -11,6 +11,19 @@ #include #include +/* + * Define COREDUMP_*_STR as public to allow coredump_backend_other to re-use + * these strings if necessary + */ +#define COREDUMP_BEGIN_STR "BEGIN#" +#define COREDUMP_END_STR "END#" +#define COREDUMP_ERROR_STR "ERROR CANNOT DUMP#" + +/* + * Need to prefix coredump strings to make it easier to parse + * as log module adds its own prefixes. + */ +#define COREDUMP_PREFIX_STR "#CD:" /** * @file @@ -219,7 +232,7 @@ struct coredump_backend_api { coredump_backend_cmd_t cmd; }; -void coredump(unsigned int reason, const z_arch_esf_t *esf, +void coredump(unsigned int reason, const struct arch_esf *esf, struct k_thread *thread); void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr); void coredump_buffer_output(uint8_t *buf, size_t buflen); @@ -229,34 +242,34 @@ int coredump_cmd(enum coredump_cmd_id cmd_id, void *arg); #else -void coredump(unsigned int reason, const z_arch_esf_t *esf, - struct k_thread *thread) +static inline void coredump(unsigned int reason, const struct arch_esf *esf, + struct k_thread *thread) { ARG_UNUSED(reason); ARG_UNUSED(esf); ARG_UNUSED(thread); } -void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr) +static inline void coredump_memory_dump(uintptr_t start_addr, uintptr_t end_addr) { ARG_UNUSED(start_addr); ARG_UNUSED(end_addr); } -void coredump_buffer_output(uint8_t *buf, size_t buflen) +static inline void coredump_buffer_output(uint8_t *buf, size_t buflen) { ARG_UNUSED(buf); ARG_UNUSED(buflen); } -int coredump_query(enum coredump_query_id query_id, void *arg) +static inline int coredump_query(enum coredump_query_id query_id, void *arg) { ARG_UNUSED(query_id); ARG_UNUSED(arg); return -ENOTSUP; } -int coredump_cmd(enum coredump_cmd_id query_id, void *arg) +static inline int coredump_cmd(enum coredump_cmd_id query_id, void *arg) { ARG_UNUSED(query_id); ARG_UNUSED(arg); @@ -266,7 +279,7 @@ int coredump_cmd(enum coredump_cmd_id query_id, void *arg) #endif /* CONFIG_DEBUG_COREDUMP */ /** - * @fn void coredump(unsigned int reason, const z_arch_esf_t *esf, struct k_thread *thread); + * @fn void coredump(unsigned int reason, const struct arch_esf *esf, struct k_thread *thread); * @brief Perform coredump. * * Normally, this is called inside z_fatal_error() to generate coredump diff --git a/include/zephyr/debug/mipi_stp_decoder.h b/include/zephyr/debug/mipi_stp_decoder.h new file mode 100644 index 0000000000000..85b08af6419c4 --- /dev/null +++ b/include/zephyr/debug/mipi_stp_decoder.h @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DEBUG_MIPI_STP_DECODER_H__ +#define ZEPHYR_INCLUDE_DEBUG_MIPI_STP_DECODER_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup mipi_stp_decoder_apis STP Decoder API + * @ingroup coresight_apis + * @{ + */ + +/** @brief STPv2 opcodes. */ +enum mipi_stp_decoder_ctrl_type { + STP_DATA4 = 1, + STP_DATA8 = 2, + STP_DATA16 = 4, + STP_DATA32 = 8, + STP_DATA64 = 16, + STP_DECODER_NULL = 128, + STP_DECODER_MASTER, + STP_DECODER_MERROR, + STP_DECODER_CHANNEL, + STP_DECODER_VERSION, + STP_DECODER_FREQ, + STP_DECODER_GERROR, + STP_DECODER_FLAG, + STP_DECODER_ASYNC, + STP_DECODER_NOT_SUPPORTED, +}; + +/** @brief Convert type to a string literal. + * + * @param _type type + * @return String literal. + */ +#define STP_DECODER_TYPE2STR(_type) \ + _type == STP_DATA4 ? "DATA4" : (\ + _type == STP_DATA8 ? "DATA8" : (\ + _type == STP_DATA16 ? "DATA16" : (\ + _type == STP_DATA32 ? "DATA32" : (\ + _type == STP_DATA64 ? "DATA64" : (\ + _type == STP_DECODER_NULL ? "NULL" : (\ + _type == STP_DECODER_MASTER ? "MASTER" : (\ + _type == STP_DECODER_MERROR ? "MERROR" : (\ + _type == STP_DECODER_CHANNEL ? "CHANNEL" : (\ + _type == STP_DECODER_VERSION ? "VERSION" : (\ + _type == STP_DECODER_FREQ ? "FREQ" : (\ + _type == STP_DECODER_GERROR ? "GERROR" : (\ + _type == STP_DECODER_FLAG ? "FLAG" : (\ + _type == STP_DECODER_ASYNC ? "ASYNC" : (\ + "Unknown")))))))))))))) + +/** @brief Union with data associated with a given STP opcode. */ +union mipi_stp_decoder_data { + /** ID - used for master and channel. */ + uint16_t id; + + /** Frequency. */ + uint64_t freq; + + /** Version. */ + uint32_t ver; + + /** Error code. */ + uint32_t err; + + /** Dummy. */ + uint32_t dummy; + + /** Data. */ + uint64_t data; +}; + +/** @brief Callback signature. + * + * Callback is called whenever an element from STPv2 stream is decoded. + * + * @note Callback is called with interrupts locked. + * + * @param type Type. See @ref mipi_stp_decoder_ctrl_type. + * @param data Data. Data associated with a given @p type. + * @param ts Timestamp. Present if not NULL. + * @param marked Set to true if opcode was marked. + */ +typedef void (*mipi_stp_decoder_cb)(enum mipi_stp_decoder_ctrl_type type, + union mipi_stp_decoder_data data, + uint64_t *ts, bool marked); + +/** @brief Decoder configuration. */ +struct mipi_stp_decoder_config { + /** Indicates that decoder start in out of sync state. */ + bool start_out_of_sync; + + /** Callback. */ + mipi_stp_decoder_cb cb; +}; + +/** @brief Initialize the decoder. + * + * @param config Configuration. + * + * @retval 0 On successful initialization. + * @retval negative On failure. + */ +int mipi_stp_decoder_init(const struct mipi_stp_decoder_config *config); + +/** @brief Decode STPv2 stream. + * + * Function decodes the stream and calls the callback for every decoded element. + * + * @param data Data. + * @param len Data length. + * + * @retval 0 On successful decoding. + * @retval negative On failure. + */ +int mipi_stp_decoder_decode(const uint8_t *data, size_t len); + +/** @brief Indicate synchronization loss. + * + * If detected, then decoder starts to look for ASYNC marker and drops all data + * until ASYNC is found. Synchronization can be lost when there is data loss (e.g. + * due to overflow). + */ +void mipi_stp_decoder_sync_loss(void); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DEBUG_MIPI_STP_DECODER_H__ */ diff --git a/include/zephyr/debug/symtab.h b/include/zephyr/debug/symtab.h new file mode 100644 index 0000000000000..41bf0b1b0c414 --- /dev/null +++ b/include/zephyr/debug/symtab.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DEBUG_SYMTAB_H_ +#define ZEPHYR_INCLUDE_DEBUG_SYMTAB_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @defgroup symtab_apis Symbol Table API + * @{ + */ + +/** + * @cond INTERNAL_HIDDEN + */ + +struct z_symtab_entry { + const uint32_t offset; + const char *const name; +}; + +/** + * INTERNAL_HIDDEN @endcond + */ + +struct symtab_info { + /* Absolute address of the first symbol */ + const uintptr_t first_addr; + /* Number of symbol entries */ + const uint32_t length; + /* Symbol entries */ + const struct z_symtab_entry *const entries; +}; + +/** + * @brief Get the pointer to the symbol table. + * + * @return Pointer to the symbol table. + */ +const struct symtab_info *const symtab_get(void); + +/** + * @brief Find the symbol name with a binary search + * + * @param[in] addr Address of the symbol to find + * @param[out] offset Offset of the symbol from the nearest symbol. If the symbol can't be found, + * this will be 0. + * + * @return Name of the nearest symbol if found, otherwise "?" is returned. + */ +const char *const symtab_find_symbol_name(uintptr_t addr, uint32_t *offset); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DEBUG_SYMTAB_H_ */ diff --git a/include/zephyr/debug/tracing.h b/include/zephyr/debug/tracing.h deleted file mode 100644 index 28d438daf812e..0000000000000 --- a/include/zephyr/debug/tracing.h +++ /dev/null @@ -1,12 +0,0 @@ - /* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_DEBUG_TRACING_H -#define ZEPHYR_INCLUDE_DEBUG_TRACING_H -#warning "This header file has moved, include instead." - -#include -#endif diff --git a/include/zephyr/device.h b/include/zephyr/device.h index d2f2244cc0b8f..4f8c9a260a7d8 100644 --- a/include/zephyr/device.h +++ b/include/zephyr/device.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -25,7 +26,7 @@ extern "C" { * @brief Device Model * @defgroup device_model Device Model * @since 1.0 - * @version 1.0.0 + * @version 1.1.0 * @{ */ @@ -96,7 +97,7 @@ typedef int16_t device_handle_t; * size. * * The ordinal used in this name can be mapped to the path by - * examining zephyr/include/generated/devicetree_generated.h. + * examining zephyr/include/generated/zephyr/devicetree_generated.h. */ #define Z_DEVICE_DT_DEV_ID(node_id) _CONCAT(dts_ord_, DT_DEP_ORD(node_id)) @@ -386,6 +387,9 @@ struct device_state { struct pm_device_base; struct pm_device; struct pm_device_isr; +#if defined(CONFIG_DEVICE_DT_METADATA) || defined(__DOXYGEN__) +struct device_dt_metadata; +#endif #ifdef CONFIG_DEVICE_DEPS_DYNAMIC #define Z_DEVICE_DEPS_CONST @@ -418,6 +422,10 @@ struct device { */ Z_DEVICE_DEPS_CONST device_handle_t *deps; #endif /* CONFIG_DEVICE_DEPS */ +#if defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS) || defined(__DOXYGEN__) + struct pm_state_constraint const *pm_constraints; + size_t pm_constraints_size; +#endif /* CONFIG_PM */ #if defined(CONFIG_PM_DEVICE) || defined(__DOXYGEN__) /** * Reference to the device PM resources (only available if @@ -429,6 +437,9 @@ struct device { struct pm_device_isr *pm_isr; }; #endif +#if defined(CONFIG_DEVICE_DT_METADATA) || defined(__DOXYGEN__) + const struct device_dt_metadata *dt_meta; +#endif /* CONFIG_DEVICE_DT_METADATA */ }; /** @@ -729,22 +740,6 @@ __syscall const struct device *device_get_binding(const char *name); */ size_t z_device_get_all_static(const struct device **devices); -/** - * @brief Verify that a device is ready for use. - * - * This is the implementation underlying device_is_ready(), without the overhead - * of a syscall wrapper. - * - * @param dev pointer to the device in question. - * - * @retval true If the device is ready for use. - * @retval false If the device is not ready for use or if a NULL device pointer - * is passed as argument. - * - * @see device_is_ready() - */ -bool z_device_is_ready(const struct device *dev); - /** * @brief Verify that a device is ready for use. * @@ -763,11 +758,6 @@ bool z_device_is_ready(const struct device *dev); */ __syscall bool device_is_ready(const struct device *dev); -static inline bool z_impl_device_is_ready(const struct device *dev) -{ - return z_device_is_ready(dev); -} - /** * @brief Initialize a device. * @@ -887,6 +877,156 @@ __syscall int device_init(const struct device *dev); #endif /* CONFIG_DEVICE_DEPS */ +#if defined(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS) || defined(__DOXYGEN__) + +/** + * @brief Synthesize the name of the object that holds a device pm constraint. + * + * @param dev_id Device identifier. + */ +#define Z_DEVICE_PM_CONSTRAINTS_NAME(dev_id) _CONCAT(__devicepmconstraints_, dev_id) + +/** + * @brief initialize a device pm constraint with information from devicetree. + * + * @param node_id Node identifier. + */ +#define Z_PM_STATE_CONSTRAINT_DT_INIT(node_id) \ + { \ + .state = PM_STATE_DT_INIT(node_id), \ + .substate_id = DT_PROP_OR(node_id, substate_id, 0), \ + } + +#define Z_PM_STATE_FROM_DT_DEVICE(i, node_id) \ + COND_CODE_1(DT_NODE_HAS_STATUS(DT_PHANDLE_BY_IDX(node_id, \ + zephyr_disabling_power_states, i), okay), \ + (Z_PM_STATE_CONSTRAINT_DT_INIT(DT_PHANDLE_BY_IDX(node_id, \ + zephyr_disabling_power_states, i)),), ()) + +/** + * @brief Helper macro to generate a list of device pm constraints. + */ +#define Z_PM_STATE_CONSTRAINTS_FROM_DT_DEVICE(node_id) \ + { \ + LISTIFY(DT_PROP_LEN_OR(node_id, zephyr_disabling_power_states, 0), \ + Z_PM_STATE_FROM_DT_DEVICE, (), node_id) \ + } + +/** + * @brief Define device pm constraints. + * + * Defines a list of `pm_state_constraint` for a specific device from its + * devicetree definition. + * + * This information tell us which power states would cause power loss + * and intended to be used by a device to set power state constraints when + * it is in the middle of an operation. + */ +#define Z_DEVICE_PM_CONSTRAINTS_DEFINE(node_id, dev_id, ...) \ + Z_DECL_ALIGN(struct pm_state_constraint) \ + Z_DEVICE_PM_CONSTRAINTS_NAME(dev_id)[] = \ + Z_PM_STATE_CONSTRAINTS_FROM_DT_DEVICE(node_id); + +#endif /* CONFIG_PM_POLICY_DEVICE_CONSTRAINTS */ + +#if defined(CONFIG_DEVICE_DT_METADATA) || defined(__DOXYGEN__) +/** + * @brief Devicetree node labels associated with a device + */ +struct device_dt_nodelabels { + /* @brief number of elements in the nodelabels array */ + size_t num_nodelabels; + /* @brief array of node labels as strings, exactly as they + * appear in the final devicetree + */ + const char *nodelabels[]; +}; + +/** + * @brief Devicetree metadata associated with a device + * + * This is currently limited to node labels, but the structure is + * generic enough to be extended later without requiring breaking + * changes. + */ +struct device_dt_metadata { + /** + * @brief Node labels associated with the device + * @see device_get_dt_nodelabels() + */ + const struct device_dt_nodelabels *nl; +}; + +/** + * @brief Get a @ref device reference from a devicetree node label. + * + * If: + * + * 1. a device was defined from a devicetree node, for example + * with DEVICE_DT_DEFINE() or another similar macro, and + * 2. that devicetree node has @p nodelabel as one of its node labels, and + * 3. the device initialized successfully at boot time, + * + * then this function returns a pointer to the device. Otherwise, it + * returns NULL. + * + * @param nodelabel a devicetree node label + * @return a device reference for a device created from a node with that + * node label, or NULL if either no such device exists or the device + * failed to initialize + */ +__syscall const struct device *device_get_by_dt_nodelabel(const char *nodelabel); + +/** + * @brief Get the devicetree node labels associated with a device + * @param dev device whose metadata to look up + * @return information about the devicetree node labels + */ +static inline const struct device_dt_nodelabels * +device_get_dt_nodelabels(const struct device *dev) +{ + return dev->dt_meta->nl; +} + +/** + * @brief Maximum devicetree node label length. + * + * The maximum length is set so that device_get_by_dt_nodelabel() can + * be used from userspace. + */ +#define Z_DEVICE_MAX_NODELABEL_LEN Z_DEVICE_MAX_NAME_LEN + +/** + * @brief Name of the identifier for a device's DT metadata structure + * @param dev_id device identifier + */ +#define Z_DEVICE_DT_METADATA_NAME_GET(dev_id) UTIL_CAT(__dev_dt_meta_, dev_id) + +/** + * @brief Name of the identifier for the array of node label strings + * saved for a device. + */ +#define Z_DEVICE_DT_NODELABELS_NAME_GET(dev_id) UTIL_CAT(__dev_dt_nodelabels_, dev_id) + +/** + * @brief Initialize an entry in the device DT node label lookup table + * + * Allocates and initializes a struct device_dt_metadata in the + * appropriate iterable section for use finding devices. + */ +#define Z_DEVICE_DT_METADATA_DEFINE(node_id, dev_id) \ + static const struct device_dt_nodelabels \ + Z_DEVICE_DT_NODELABELS_NAME_GET(dev_id) = { \ + .num_nodelabels = DT_NUM_NODELABELS(node_id), \ + .nodelabels = DT_NODELABEL_STRING_ARRAY(node_id), \ + }; \ + \ + static const struct device_dt_metadata \ + Z_DEVICE_DT_METADATA_NAME_GET(dev_id) = { \ + .nl = &Z_DEVICE_DT_NODELABELS_NAME_GET(dev_id), \ + }; +#endif /* CONFIG_DEVICE_DT_METADATA */ + /** * @brief Init sub-priority of the device * @@ -925,16 +1065,24 @@ __syscall int device_init(const struct device *dev); * @param api_ Reference to device API ops. * @param state_ Reference to device state. * @param deps_ Reference to device dependencies. + * @param dev_id_ Device identifier token, as passed to Z_DEVICE_BASE_DEFINE */ -#define Z_DEVICE_INIT(name_, pm_, data_, config_, api_, state_, deps_) \ - { \ - .name = name_, \ - .config = (config_), \ - .api = (api_), \ - .state = (state_), \ - .data = (data_), \ - IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ - IF_ENABLED(CONFIG_PM_DEVICE, ({ .pm_base = (pm_),})) /**/ \ +#define Z_DEVICE_INIT(name_, pm_, data_, config_, api_, state_, deps_, \ + constraints_size_, constraints_, dev_id_) \ + { \ + .name = name_, \ + .config = (config_), \ + .api = (api_), \ + .state = (state_), \ + .data = (data_), \ + IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \ + IF_ENABLED(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS, \ + (.pm_constraints = (constraints_),)) \ + IF_ENABLED(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS, \ + (.pm_constraints_size = (constraints_size_),)) \ + IF_ENABLED(CONFIG_PM_DEVICE, ({ .pm_base = (pm_),})) /**/ \ + IF_ENABLED(CONFIG_DEVICE_DT_METADATA, \ + (.dt_meta = &Z_DEVICE_DT_METADATA_NAME_GET(dev_id_),)) \ } /** @@ -963,13 +1111,14 @@ __syscall int device_init(const struct device *dev); * @param ... Optional dependencies, manually specified. */ #define Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, prio, api, state, \ - deps) \ + deps, constraints) \ COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \ COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (), (const)) \ STRUCT_SECTION_ITERABLE_NAMED_ALTERNATE( \ device, COND_CODE_1(Z_DEVICE_IS_MUTABLE(node_id), (device_mutable), (device)), \ Z_DEVICE_SECTION_NAME(level, prio), DEVICE_NAME_GET(dev_id)) = \ - Z_DEVICE_INIT(name, pm, data, config, api, state, deps) + Z_DEVICE_INIT(name, pm, data, config, api, state, deps, \ + DT_PROP_LEN_OR(node_id, zephyr_disabling_power_states, 0), constraints, dev_id) /* deprecated device initialization levels */ #define Z_DEVICE_LEVEL_DEPRECATED_EARLY \ @@ -1047,20 +1196,26 @@ __syscall int device_init(const struct device *dev); * @param state Reference to device state. * @param ... Optional dependencies, manually specified. */ -#define Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \ - level, prio, api, state, ...) \ - Z_DEVICE_NAME_CHECK(name); \ - \ - IF_ENABLED(CONFIG_DEVICE_DEPS, \ - (Z_DEVICE_DEPS_DEFINE(node_id, dev_id, __VA_ARGS__);)) \ - \ - Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \ - prio, api, state, Z_DEVICE_DEPS_NAME(dev_id)); \ - \ - COND_CODE_1(DEVICE_DT_DEFER(node_id), \ - (Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, \ - init_fn)), \ - (Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn, \ +#define Z_DEVICE_DEFINE(node_id, dev_id, name, init_fn, pm, data, config, \ + level, prio, api, state, ...) \ + Z_DEVICE_NAME_CHECK(name); \ + \ + IF_ENABLED(CONFIG_DEVICE_DEPS, \ + (Z_DEVICE_DEPS_DEFINE(node_id, dev_id, __VA_ARGS__);)) \ + \ + IF_ENABLED(CONFIG_PM_POLICY_DEVICE_CONSTRAINTS, \ + (Z_DEVICE_PM_CONSTRAINTS_DEFINE(node_id, dev_id, __VA_ARGS__);))\ + \ + IF_ENABLED(CONFIG_DEVICE_DT_METADATA, \ + (Z_DEVICE_DT_METADATA_DEFINE(node_id, dev_id);)) \ + \ + Z_DEVICE_BASE_DEFINE(node_id, dev_id, name, pm, data, config, level, \ + prio, api, state, Z_DEVICE_DEPS_NAME(dev_id), \ + Z_DEVICE_PM_CONSTRAINTS_NAME(dev_id)); \ + COND_CODE_1(DEVICE_DT_DEFER(node_id), \ + (Z_DEFER_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, \ + init_fn)), \ + (Z_DEVICE_INIT_ENTRY_DEFINE(node_id, dev_id, init_fn, \ level, prio))); /** @@ -1085,6 +1240,6 @@ DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_DEVICE_DECLARE_INTERNAL) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DEVICE_H_ */ diff --git a/include/zephyr/devicetree.h b/include/zephyr/devicetree.h index eb28dea874aca..349e5836fbce5 100644 --- a/include/zephyr/devicetree.h +++ b/include/zephyr/devicetree.h @@ -16,7 +16,7 @@ #ifndef DEVICETREE_H #define DEVICETREE_H -#include +#include #include #if !defined(_LINKER) && !defined(_ASMLANGUAGE) @@ -29,7 +29,7 @@ * @brief devicetree.h API * @defgroup devicetree Devicetree * @since 2.2 - * @version 1.0.0 + * @version 1.1.0 * @{ * @} */ @@ -593,6 +593,33 @@ #define DT_SAME_NODE(node_id1, node_id2) \ (DT_DEP_ORD(node_id1) == (DT_DEP_ORD(node_id2))) +/** + * @brief Get a devicetree node's node labels as an array of strings + * + * Example devicetree fragment: + * + * @code{.dts} + * foo: bar: node@deadbeef {}; + * @endcode + * + * Example usage: + * + * @code{.c} + * DT_NODELABEL_STRING_ARRAY(DT_NODELABEL(foo)) + * @endcode + * + * This expands to: + * + * @code{.c} + * { "foo", "bar", } + * @endcode + * + * @param node_id node identifier + * @return an array initializer for an array of the node's node labels as strings + */ +#define DT_NODELABEL_STRING_ARRAY(node_id) \ + { DT_FOREACH_NODELABEL(node_id, DT_NODELABEL_STRING_ARRAY_ENTRY_INTERNAL) } + /** * @} */ @@ -2202,6 +2229,20 @@ #define DT_REG_HAS_IDX(node_id, idx) \ IS_ENABLED(DT_CAT4(node_id, _REG_IDX_, idx, _EXISTS)) +/** + * @brief Is @p name a valid register block name? + * + * If this returns 1, then DT_REG_ADDR_BY_NAME(node_id, name) or + * DT_REG_SIZE_BY_NAME(node_id, name) are valid. + * If it returns 0, it is an error to use those macros with name @p name. + * @param node_id node identifier + * @param name name to check + * @return 1 if @p name is a valid register block name, + * 0 otherwise. + */ +#define DT_REG_HAS_NAME(node_id, name) \ + IS_ENABLED(DT_CAT4(node_id, _REG_NAME_, name, _EXISTS)) + /** * @brief Get the base address of the register block at index @p idx * @param node_id node identifier @@ -2264,6 +2305,18 @@ #define DT_REG_ADDR_BY_NAME(node_id, name) \ DT_CAT4(node_id, _REG_NAME_, name, _VAL_ADDRESS) +/** + * @brief Like DT_REG_ADDR_BY_NAME(), but with a fallback to @p default_value + * @param node_id node identifier + * @param name lowercase-and-underscores register specifier name + * @param default_value a fallback value to expand to + * @return address of the register block specified by name if present, + * @p default_value otherwise + */ +#define DT_REG_ADDR_BY_NAME_OR(node_id, name, default_value) \ + COND_CODE_1(DT_REG_HAS_NAME(node_id, name), \ + (DT_REG_ADDR_BY_NAME(node_id, name)), (default_value)) + /** * @brief 64-bit version of DT_REG_ADDR_BY_NAME() * @@ -2288,6 +2341,19 @@ #define DT_REG_SIZE_BY_NAME(node_id, name) \ DT_CAT4(node_id, _REG_NAME_, name, _VAL_SIZE) +/** + * @brief Like DT_REG_SIZE_BY_NAME(), but with a fallback to @p default_value + * @param node_id node identifier + * @param name lowercase-and-underscores register specifier name + * @param default_value a fallback value to expand to + * @return size of the register block specified by name if present, + * @p default_value otherwise + */ +#define DT_REG_SIZE_BY_NAME_OR(node_id, name, default_value) \ + COND_CODE_1(DT_REG_HAS_NAME(node_id, name), \ + (DT_REG_SIZE_BY_NAME(node_id, name)), (default_value)) + + /** * @} */ @@ -2308,6 +2374,32 @@ */ #define DT_NUM_IRQS(node_id) DT_CAT(node_id, _IRQ_NUM) +/** + * @brief Get the number of node labels that a node has + * + * Example devicetree fragment: + * + * @code{.dts} + * / { + * foo {}; + * bar: bar@1000 {}; + * baz: baz2: baz@2000 {}; + * }; + * @endcode + * + * Example usage: + * + * @code{.c} + * DT_NUM_NODELABELS(DT_PATH(foo)) // 0 + * DT_NUM_NODELABELS(DT_NODELABEL(bar)) // 1 + * DT_NUM_NODELABELS(DT_NODELABEL(baz)) // 2 + * @endcode + * + * @param node_id node identifier + * @return number of node labels that the node has + */ +#define DT_NUM_NODELABELS(node_id) DT_CAT(node_id, _NODELABEL_NUM) + /** * @brief Get the interrupt level for the node * @@ -3162,6 +3254,86 @@ compat)(fn, __VA_ARGS__)), \ ()) +/** + * @brief Invokes @p fn for each node label of a given node + * + * The order of the node labels in this macro's expansion matches + * the order in the final devicetree, with duplicates removed. + * + * Node labels are passed to @p fn as tokens. Note that devicetree + * node labels are always valid C tokens (see "6.2 Labels" in + * Devicetree Specification v0.4 for details). The node labels are + * passed as tokens to @p fn as-is, without any lowercasing or + * conversion of special characters to underscores. + * + * Example devicetree fragment: + * + * @code{.dts} + * foo: bar: FOO: node@deadbeef {}; + * @endcode + * + * Example usage: + * + * @code{.c} + * int foo = 1; + * int bar = 2; + * int FOO = 3; + * + * #define FN(nodelabel) + nodelabel + * int sum = 0 DT_FOREACH_NODELABEL(DT_NODELABEL(foo), FN) + * @endcode + * + * This expands to: + * + * @code{.c} + * int sum = 0 + 1 + 2 + 3; + * @endcode + * + * @param node_id node identifier whose node labels to use + * @param fn macro which will be passed each node label in order + */ +#define DT_FOREACH_NODELABEL(node_id, fn) DT_CAT(node_id, _FOREACH_NODELABEL)(fn) + +/** + * @brief Invokes @p fn for each node label of a given node with + * multiple arguments. + * + * This is like DT_FOREACH_NODELABEL() except you can also pass + * additional arguments to @p fn. + * + * Example devicetree fragment: + * + * @code{.dts} + * foo: bar: node@deadbeef {}; + * @endcode + * + * Example usage: + * + * @code{.c} + * int foo = 0; + * int bar = 1; + * + * #define VAR_PLUS(nodelabel, to_add) int nodelabel ## _added = nodelabel + to_add; + * + * DT_FOREACH_NODELABEL_VARGS(DT_NODELABEL(foo), VAR_PLUS, 1) + * @endcode + * + * This expands to: + * + * @code{.c} + * int foo = 0; + * int bar = 1; + * int foo_added = foo + 1; + * int bar_added = bar + 1; + * @endcode + * + * @param node_id node identifier whose node labels to use + * @param fn macro which will be passed each node label in order + * @param ... additional arguments to pass to @p fn + */ +#define DT_FOREACH_NODELABEL_VARGS(node_id, fn, ...) \ + DT_CAT(node_id, _FOREACH_NODELABEL_VARGS)(fn, __VA_ARGS__) + /** * @} */ @@ -3289,7 +3461,7 @@ * @param status okay or disabled as a token, not a string */ #define DT_NODE_HAS_COMPAT_STATUS(node_id, compat, status) \ - DT_NODE_HAS_COMPAT(node_id, compat) && DT_NODE_HAS_STATUS(node_id, status) + UTIL_AND(DT_NODE_HAS_COMPAT(node_id, compat), DT_NODE_HAS_STATUS(node_id, status)) /** * @brief Does a devicetree node have a property? @@ -3484,6 +3656,26 @@ #define DT_INST_CHILD_NUM_STATUS_OKAY(inst) \ DT_CHILD_NUM_STATUS_OKAY(DT_DRV_INST(inst)) +/** + * @brief Get a string array of DT_DRV_INST(inst)'s node labels + * + * Equivalent to DT_NODELABEL_STRING_ARRAY(DT_DRV_INST(inst)). + * + * @param inst instance number + * @return an array initializer for an array of the instance's node labels as strings + */ +#define DT_INST_NODELABEL_STRING_ARRAY(inst) DT_NODELABEL_STRING_ARRAY(DT_DRV_INST(inst)) + +/** + * @brief Get the number of node labels by instance number + * + * Equivalent to DT_NUM_NODELABELS(DT_DRV_INST(inst)). + * + * @param inst instance number + * @return the number of node labels that the node with that instance number has + */ +#define DT_INST_NUM_NODELABELS(inst) DT_NUM_NODELABELS(DT_DRV_INST(inst)) + /** * @brief Call @p fn on all child nodes of DT_DRV_INST(inst). * @@ -3915,6 +4107,15 @@ */ #define DT_INST_REG_HAS_IDX(inst, idx) DT_REG_HAS_IDX(DT_DRV_INST(inst), idx) +/** + * @brief is @p name a valid register block name on a `DT_DRV_COMPAT` instance? + * @param inst instance number + * @param name name to check + * @return 1 if @p name is a valid register block name, + * 0 otherwise. + */ +#define DT_INST_REG_HAS_NAME(inst, name) DT_REG_HAS_NAME(DT_DRV_INST(inst), name) + /** * @brief Get a `DT_DRV_COMPAT` instance's idx-th register block's address * @param inst instance number @@ -3941,6 +4142,17 @@ #define DT_INST_REG_ADDR_BY_NAME(inst, name) \ DT_REG_ADDR_BY_NAME(DT_DRV_INST(inst), name) +/** + * @brief Like DT_INST_REG_ADDR_BY_NAME(), but with a fallback to @p default_value + * @param inst instance number + * @param name lowercase-and-underscores register specifier name + * @param default_value a fallback value to expand to + * @return address of the register block specified by name if present, + * @p default_value otherwise + */ +#define DT_INST_REG_ADDR_BY_NAME_OR(inst, name, default_value) \ + DT_REG_ADDR_BY_NAME_OR(DT_DRV_INST(inst), name, default_value) + /** * @brief 64-bit version of DT_INST_REG_ADDR_BY_NAME() * @@ -3965,6 +4177,17 @@ #define DT_INST_REG_SIZE_BY_NAME(inst, name) \ DT_REG_SIZE_BY_NAME(DT_DRV_INST(inst), name) +/** + * @brief Like DT_INST_REG_SIZE_BY_NAME(), but with a fallback to @p default_value + * @param inst instance number + * @param name lowercase-and-underscores register specifier name + * @param default_value a fallback value to expand to + * @return size of the register block specified by name if present, + * @p default_value otherwise + */ +#define DT_INST_REG_SIZE_BY_NAME_OR(inst, name, default_value) \ + DT_REG_SIZE_BY_NAME_OR(DT_DRV_INST(inst), name, default_value) + /** * @brief Get a `DT_DRV_COMPAT`'s (only) register block address * @param inst instance number @@ -4324,6 +4547,32 @@ DT_DRV_COMPAT)(fn, __VA_ARGS__)), \ ()) +/** + * @brief Call @p fn on all node labels for a given `DT_DRV_COMPAT` instance + * + * Equivalent to DT_FOREACH_NODELABEL(DT_DRV_INST(inst), fn). + * + * @param inst instance number + * @param fn macro which will be passed each node label for the node + * with that instance number + */ +#define DT_INST_FOREACH_NODELABEL(inst, fn) \ + DT_FOREACH_NODELABEL(DT_DRV_INST(inst), fn) + +/** + * @brief Call @p fn on all node labels for a given `DT_DRV_COMPAT` instance + * with multiple arguments + * + * Equivalent to DT_FOREACH_NODELABEL_VARGS(DT_DRV_INST(inst), fn, ...). + * + * @param inst instance number + * @param fn macro which will be passed each node label for the node + * with that instance number + * @param ... additional arguments to pass to @p fn + */ +#define DT_INST_FOREACH_NODELABEL_VARGS(inst, fn, ...) \ + DT_FOREACH_NODELABEL_VARGS(DT_DRV_INST(inst), fn, __VA_ARGS__) + /** * @brief Invokes @p fn for each element of property @p prop for * a `DT_DRV_COMPAT` instance. @@ -4557,10 +4806,6 @@ #define DT_NODE_HAS_STATUS_INTERNAL(node_id, status) \ IS_ENABLED(DT_CAT3(node_id, _STATUS_, status)) -/** @brief Helper macro to OR multiple has property checks in a loop macro */ -#define DT_INST_NODE_HAS_PROP_AND_OR(inst, prop) \ - DT_INST_NODE_HAS_PROP(inst, prop) || - /** * @def DT_U64_C * @brief Macro to add ULL postfix to the devicetree address constants @@ -4571,6 +4816,13 @@ #define DT_U64_C(_v) UINT64_C(_v) #endif +/* Helpers for DT_NODELABEL_STRING_ARRAY. We define our own stringify + * in order to avoid adding a dependency on toolchain.h.. + */ +#define DT_NODELABEL_STRING_ARRAY_ENTRY_INTERNAL(nodelabel) DT_STRINGIFY_INTERNAL(nodelabel), +#define DT_STRINGIFY_INTERNAL(arg) DT_STRINGIFY_INTERNAL_HELPER(arg) +#define DT_STRINGIFY_INTERNAL_HELPER(arg) #arg + /** @endcond */ /* have these last so they have access to all previously defined macros */ diff --git a/include/zephyr/devicetree/interrupt_controller.h b/include/zephyr/devicetree/interrupt_controller.h new file mode 100644 index 0000000000000..a9c4e864ae198 --- /dev/null +++ b/include/zephyr/devicetree/interrupt_controller.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Interrupt controller devicetree macro public API header file. + */ + +#ifndef ZEPHYR_INCLUDE_DEVICETREE_INTERRUPT_CONTROLLER_H_ +#define ZEPHYR_INCLUDE_DEVICETREE_INTERRUPT_CONTROLLER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include + +/** + * @defgroup devicetree-interrupt_controller Devicetree Interrupt Controller API + * @ingroup devicetree + * @{ + */ + +/** + * @brief Get the aggregator level of an interrupt controller + * + * @note Aggregator level is equivalent to IRQ_LEVEL + 1 (a 2nd level aggregator has Zephyr level 1 + * IRQ encoding) + * + * @param node_id node identifier of an interrupt controller + * + * @return Level of the interrupt controller + */ +#define DT_INTC_GET_AGGREGATOR_LEVEL(node_id) UTIL_INC(DT_IRQ_LEVEL(node_id)) + +/** + * @brief Get the aggregator level of a `DT_DRV_COMPAT` interrupt controller + * + * @note Aggregator level is equivalent to IRQ_LEVEL + 1 (a 2nd level aggregator has Zephyr level 1 + * IRQ encoding) + * + * @param inst instance of an interrupt controller + * + * @return Level of the interrupt controller + */ +#define DT_INST_INTC_GET_AGGREGATOR_LEVEL(inst) DT_INTC_GET_AGGREGATOR_LEVEL(DT_DRV_INST(inst)) + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DEVICETREE_INTERRUPT_CONTROLLER_H_ */ diff --git a/include/zephyr/drivers/adc.h b/include/zephyr/drivers/adc.h index 18357cbd01413..46e016e697569 100644 --- a/include/zephyr/drivers/adc.h +++ b/include/zephyr/drivers/adc.h @@ -984,6 +984,6 @@ static inline bool adc_is_ready_dt(const struct adc_dt_spec *spec) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_ADC_H_ */ diff --git a/include/zephyr/drivers/auxdisplay.h b/include/zephyr/drivers/auxdisplay.h index de106f5016e03..a56c9b7699380 100644 --- a/include/zephyr/drivers/auxdisplay.h +++ b/include/zephyr/drivers/auxdisplay.h @@ -815,6 +815,6 @@ static inline int z_impl_auxdisplay_custom_command(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_AUXDISPLAY_H_ */ diff --git a/include/zephyr/drivers/bbram.h b/include/zephyr/drivers/bbram.h index 599a3588ac81a..30df6a5dd7d2b 100644 --- a/include/zephyr/drivers/bbram.h +++ b/include/zephyr/drivers/bbram.h @@ -261,6 +261,6 @@ int bbram_emul_set_power_state(const struct device *dev, bool failure); * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_BBRAM_H */ diff --git a/include/zephyr/drivers/bluetooth.h b/include/zephyr/drivers/bluetooth.h new file mode 100644 index 0000000000000..1492b647557d8 --- /dev/null +++ b/include/zephyr/drivers/bluetooth.h @@ -0,0 +1,261 @@ +/** @file + * @brief Bluetooth HCI driver API. + * + * Copyright (c) 2024 Johan Hedberg + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_H_ +#define ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_H_ + +/** + * @brief Bluetooth HCI APIs + * @defgroup bt_hci_api Bluetooth HCI APIs + * + * @since 3.7 + * @version 0.2.0 + * + * @ingroup bluetooth + * @{ + */ + +#include +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct bt_hci_setup_params { + /** The public identity address to give to the controller. This field is used when the + * driver selects @kconfig{CONFIG_BT_HCI_SET_PUBLIC_ADDR} to indicate that it supports + * setting the controller's public address. + */ + bt_addr_t public_addr; +}; + +enum { + /* The host should never send HCI_Reset */ + BT_HCI_QUIRK_NO_RESET = BIT(0), + /* The controller does not auto-initiate a DLE procedure when the + * initial connection data length parameters are not equal to the + * default data length parameters. Therefore the host should initiate + * the DLE procedure after connection establishment. + */ + BT_HCI_QUIRK_NO_AUTO_DLE = BIT(1), +}; + +/** Possible values for the 'bus' member of the bt_hci_driver struct */ +enum bt_hci_bus { + BT_HCI_BUS_VIRTUAL = 0, + BT_HCI_BUS_USB = 1, + BT_HCI_BUS_PCCARD = 2, + BT_HCI_BUS_UART = 3, + BT_HCI_BUS_RS232 = 4, + BT_HCI_BUS_PCI = 5, + BT_HCI_BUS_SDIO = 6, + BT_HCI_BUS_SPI = 7, + BT_HCI_BUS_I2C = 8, + BT_HCI_BUS_IPM = 9, +}; + +#define BT_DT_HCI_QUIRK_OR(node_id, prop, idx) DT_STRING_TOKEN_BY_IDX(node_id, prop, idx) +#define BT_DT_HCI_QUIRKS_GET(node_id) COND_CODE_1(DT_NODE_HAS_PROP(node_id, bt_hci_quirks), \ + (DT_FOREACH_PROP_ELEM_SEP(node_id, \ + bt_hci_quirks, \ + BT_DT_HCI_QUIRK_OR, \ + (|))), \ + (0)) +#define BT_DT_HCI_QUIRKS_INST_GET(inst) BT_DT_HCI_QUIRKS_GET(DT_DRV_INST(inst)) + +#define BT_DT_HCI_NAME_GET(node_id) DT_PROP_OR(node_id, bt_hci_name, "HCI") +#define BT_DT_HCI_NAME_INST_GET(inst) BT_DT_HCI_NAME_GET(DT_DRV_INST(inst)) + +#define BT_DT_HCI_BUS_GET(node_id) DT_STRING_TOKEN_OR(node_id, bt_hci_bus, BT_HCI_BUS_VIRTUAL) +#define BT_DT_HCI_BUS_INST_GET(inst) BT_DT_HCI_BUS_GET(DT_DRV_INST(inst)) + +typedef int (*bt_hci_recv_t)(const struct device *dev, struct net_buf *buf); + +__subsystem struct bt_hci_driver_api { + int (*open)(const struct device *dev, bt_hci_recv_t recv); + int (*close)(const struct device *dev); + int (*send)(const struct device *dev, struct net_buf *buf); +#if defined(CONFIG_BT_HCI_SETUP) + int (*setup)(const struct device *dev, + const struct bt_hci_setup_params *param); +#endif /* defined(CONFIG_BT_HCI_SETUP) */ +}; + +/** + * @brief Open the HCI transport. + * + * Opens the HCI transport for operation. This function must not + * return until the transport is ready for operation, meaning it + * is safe to start calling the send() handler. + * + * @param dev HCI device + * @param recv This is callback through which the HCI driver provides the + * host with data from the controller. The buffer passed to + * the callback will have its type set with bt_buf_set_type(). + * The callback is expected to be called from thread context. + * + * @return 0 on success or negative POSIX error number on failure. + */ +static inline int bt_hci_open(const struct device *dev, bt_hci_recv_t recv) +{ + const struct bt_hci_driver_api *api = (const struct bt_hci_driver_api *)dev->api; + + return api->open(dev, recv); +} + +/** + * @brief Close the HCI transport. + * + * Closes the HCI transport. This function must not return until the + * transport is closed. + * + * @param dev HCI device + * + * @return 0 on success or negative POSIX error number on failure. + */ +static inline int bt_hci_close(const struct device *dev) +{ + const struct bt_hci_driver_api *api = (const struct bt_hci_driver_api *)dev->api; + + if (api->close == NULL) { + return -ENOSYS; + } + + return api->close(dev); +} + +/** + * @brief Send HCI buffer to controller. + * + * Send an HCI packet to the controller. The packet type of the buffer + * must be set using bt_buf_set_type(). + * + * @note This function must only be called from a cooperative thread. + * + * @param dev HCI device + * @param buf Buffer containing data to be sent to the controller. + * + * @return 0 on success or negative POSIX error number on failure. + */ +static inline int bt_hci_send(const struct device *dev, struct net_buf *buf) +{ + const struct bt_hci_driver_api *api = (const struct bt_hci_driver_api *)dev->api; + + return api->send(dev, buf); +} + +#if defined(CONFIG_BT_HCI_SETUP) || defined(__DOXYGEN__) +/** + * @brief HCI vendor-specific setup + * + * Executes vendor-specific commands sequence to initialize + * BT Controller before BT Host executes Reset sequence. This is normally + * called directly after bt_hci_open(). + * + * @note @kconfig{CONFIG_BT_HCI_SETUP} must be selected for this + * field to be available. + * + * @return 0 on success or negative POSIX error number on failure. + */ +static inline int bt_hci_setup(const struct device *dev, struct bt_hci_setup_params *params) +{ + const struct bt_hci_driver_api *api = (const struct bt_hci_driver_api *)dev->api; + + if (api->setup == NULL) { + return -ENOSYS; + } + + return api->setup(dev, params); +} +#endif + +/** + * @} + */ + +/* The following functions are not strictly part of the HCI driver API, in that + * they do not take as input a struct device which implements the HCI driver API. + */ + +/** + * @brief Setup the HCI transport, which usually means to reset the + * Bluetooth IC. + * + * @note A weak version of this function is included in the H4 driver, so + * defining it is optional per board. + * + * @param dev The device structure for the bus connecting to the IC + * + * @return 0 on success, negative error value on failure + */ +int bt_hci_transport_setup(const struct device *dev); + +/** + * @brief Teardown the HCI transport. + * + * @note A weak version of this function is included in the IPC driver, so + * defining it is optional. NRF5340 includes support to put network core + * in reset state. + * + * @param dev The device structure for the bus connecting to the IC + * + * @return 0 on success, negative error value on faulure + */ +int bt_hci_transport_teardown(const struct device *dev); + +/** Allocate an HCI event buffer. + * + * This function allocates a new buffer for an HCI event. It is given the + * event code and the total length of the parameters. Upon successful return + * the buffer is ready to have the parameters encoded into it. + * + * @param evt HCI event OpCode. + * @param len Length of event parameters. + * + * @return Newly allocated buffer. + */ +struct net_buf *bt_hci_evt_create(uint8_t evt, uint8_t len); + +/** Allocate an HCI Command Complete event buffer. + * + * This function allocates a new buffer for HCI Command Complete event. + * It is given the OpCode (encoded e.g. using the BT_OP macro) and the total + * length of the parameters. Upon successful return the buffer is ready to have + * the parameters encoded into it. + * + * @param op HCI command OpCode. + * @param plen Length of command parameters. + * + * @return Newly allocated buffer. + */ +struct net_buf *bt_hci_cmd_complete_create(uint16_t op, uint8_t plen); + +/** Allocate an HCI Command Status event buffer. + * + * This function allocates a new buffer for HCI Command Status event. + * It is given the OpCode (encoded e.g. using the BT_OP macro) and the status + * code. Upon successful return the buffer is ready to have the parameters + * encoded into it. + * + * @param op HCI command OpCode. + * @param status Status code. + * + * @return Newly allocated buffer. + */ +struct net_buf *bt_hci_cmd_status_create(uint16_t op, uint8_t status); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_H_ */ diff --git a/include/zephyr/drivers/bluetooth/hci_driver.h b/include/zephyr/drivers/bluetooth/hci_driver.h index 8611765c70699..55063bf289799 100644 --- a/include/zephyr/drivers/bluetooth/hci_driver.h +++ b/include/zephyr/drivers/bluetooth/hci_driver.h @@ -12,6 +12,9 @@ /** * @brief HCI drivers + * + * @deprecated This is the old HCI driver API. Drivers should use @ref bt_hci_api instead. + * * @defgroup bt_hci_driver HCI drivers * @ingroup bluetooth * @{ @@ -37,8 +40,6 @@ enum { BT_QUIRK_NO_AUTO_DLE = BIT(1), }; -#define IS_BT_QUIRK_NO_AUTO_DLE(bt_dev) ((bt_dev)->drv->quirks & BT_QUIRK_NO_AUTO_DLE) - /** * @brief Receive data from the controller/HCI driver. * @@ -49,17 +50,10 @@ enum { * @param buf Network buffer containing data from the controller. * * @return 0 on success or negative error number on failure. - */ -int bt_recv(struct net_buf *buf); - -/** @brief Read static addresses from the controller. - * - * @param addrs Random static address and Identity Root (IR) array. - * @param size Size of array. * - * @return Number of addresses read. + * @deprecated Use the new HCI driver interface instead: @ref bt_hci_api */ -uint8_t bt_read_static_addr(struct bt_hci_vs_static_addr addrs[], uint8_t size); +__deprecated int bt_recv(struct net_buf *buf); /** Possible values for the 'bus' member of the bt_hci_driver struct */ enum bt_hci_driver_bus { @@ -165,8 +159,10 @@ struct bt_hci_driver { * @param drv A bt_hci_driver struct representing the driver. * * @return 0 on success or negative error number on failure. + * + * @deprecated Use the new HCI driver interface instead: @ref bt_hci_api */ -int bt_hci_driver_register(const struct bt_hci_driver *drv); +__deprecated int bt_hci_driver_register(const struct bt_hci_driver *drv); /** * @brief Setup the HCI transport, which usually means to reset the diff --git a/include/zephyr/drivers/bluetooth/hci_driver_bluenrg.h b/include/zephyr/drivers/bluetooth/hci_driver_bluenrg.h new file mode 100644 index 0000000000000..d65b93c586a75 --- /dev/null +++ b/include/zephyr/drivers/bluetooth/hci_driver_bluenrg.h @@ -0,0 +1,47 @@ +/** @file + * @brief BlueNRG HCI extended API. + */ + +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_HCI_DRIVER_BLUENRG_H_ +#define ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_HCI_DRIVER_BLUENRG_H_ + +/** + * @brief BlueNRG HCI Driver-Specific API + * @defgroup bluenrg_hci_driver BlueNRG HCI driver extended API + * @ingroup bluetooth + * @{ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Hardware reset the BlueNRG network coprocessor. + * + * Performs hardware reset of the BLE network coprocessor. + * It can also force to enter firmware updater mode. + * + * @param updater_mode flag to indicate whether updater mode needs to be entered. + * + * @return a non-negative value indicating success, or a + * negative error code for failure + */ + +int bluenrg_bt_reset(bool updater_mode); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_DRIVERS_BLUETOOTH_HCI_DRIVER_BLUENRG_H_ */ diff --git a/include/zephyr/drivers/can.h b/include/zephyr/drivers/can.h index 8a26b407ccbb0..9dee92ddd69fc 100644 --- a/include/zephyr/drivers/can.h +++ b/include/zephyr/drivers/can.h @@ -351,14 +351,14 @@ struct can_driver_config { /** The maximum bitrate supported by the CAN controller/transceiver combination. */ uint32_t max_bitrate; /** Initial CAN classic/CAN FD arbitration phase bitrate. */ - uint32_t bus_speed; + uint32_t bitrate; /** Initial CAN classic/CAN FD arbitration phase sample point in permille. */ uint16_t sample_point; #ifdef CONFIG_CAN_FD_MODE /** Initial CAN FD data phase sample point in permille. */ uint16_t sample_point_data; /** Initial CAN FD data phase bitrate. */ - uint32_t bus_speed_data; + uint32_t bitrate_data; #endif /* CONFIG_CAN_FD_MODE */ }; @@ -374,10 +374,12 @@ struct can_driver_config { .phy = DEVICE_DT_GET_OR_NULL(DT_PHANDLE(node_id, phys)), \ .min_bitrate = DT_CAN_TRANSCEIVER_MIN_BITRATE(node_id, _min_bitrate), \ .max_bitrate = DT_CAN_TRANSCEIVER_MAX_BITRATE(node_id, _max_bitrate), \ - .bus_speed = DT_PROP(node_id, bus_speed), \ + .bitrate = DT_PROP_OR(node_id, bitrate, \ + DT_PROP_OR(node_id, bus_speed, CONFIG_CAN_DEFAULT_BITRATE)), \ .sample_point = DT_PROP_OR(node_id, sample_point, 0), \ IF_ENABLED(CONFIG_CAN_FD_MODE, \ - (.bus_speed_data = DT_PROP_OR(node_id, bus_speed_data, 0), \ + (.bitrate_data = DT_PROP_OR(node_id, bitrate_data, \ + DT_PROP_OR(node_id, bus_speed_data, CONFIG_CAN_DEFAULT_BITRATE_DATA)), \ .sample_point_data = DT_PROP_OR(node_id, sample_point_data, 0),)) \ } @@ -1799,6 +1801,6 @@ static inline bool can_frame_matches_filter(const struct can_frame *frame, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_CAN_H_ */ diff --git a/include/zephyr/drivers/charger.h b/include/zephyr/drivers/charger.h index 457eec939beb7..6c5ebae35df3e 100644 --- a/include/zephyr/drivers/charger.h +++ b/include/zephyr/drivers/charger.h @@ -405,6 +405,6 @@ static inline int z_impl_charger_charge_enable(const struct device *dev, const b } #endif /* __cplusplus */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_CHARGER_H_ */ diff --git a/include/zephyr/drivers/clock_control/adi_max32_clock_control.h b/include/zephyr/drivers/clock_control/adi_max32_clock_control.h new file mode 100644 index 0000000000000..2922b5e2c8861 --- /dev/null +++ b/include/zephyr/drivers/clock_control/adi_max32_clock_control.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ADI_MAX32_CLOCK_CONTROL_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ADI_MAX32_CLOCK_CONTROL_H_ + +#include + +#include + +#include + +/** Driver structure definition */ + +struct max32_perclk { + uint32_t bus; + uint32_t bit; + + /* Peripheral clock source: + * Can be (see: adi_max32_clock.h file): + * + * ADI_MAX32_PRPH_CLK_SRC_PCLK + * ADI_MAX32_PRPH_CLK_SRC_EXTCLK + * ADI_MAX32_PRPH_CLK_SRC_IBRO + * ADI_MAX32_PRPH_CLK_SRC_ERFO + * ADI_MAX32_PRPH_CLK_SRC_ERTCO + * ADI_MAX32_PRPH_CLK_SRC_INRO + * ADI_MAX32_PRPH_CLK_SRC_ISO + * ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8 + */ + uint32_t clk_src; +}; + +/** Get prescaler value if it defined */ +#define ADI_MAX32_SYSCLK_PRESCALER DT_PROP_OR(DT_NODELABEL(gcr), sysclk_prescaler, 1) + +#define ADI_MAX32_CLK_IPO_FREQ DT_PROP(DT_NODELABEL(clk_ipo), clock_frequency) +#define ADI_MAX32_CLK_ERFO_FREQ DT_PROP(DT_NODELABEL(clk_erfo), clock_frequency) +#define ADI_MAX32_CLK_IBRO_FREQ DT_PROP(DT_NODELABEL(clk_ibro), clock_frequency) +#define ADI_MAX32_CLK_ISO_FREQ DT_PROP_OR(DT_NODELABEL(clk_iso), clock_frequency, 0) +#define ADI_MAX32_CLK_INRO_FREQ DT_PROP(DT_NODELABEL(clk_inro), clock_frequency) +#define ADI_MAX32_CLK_ERTCO_FREQ DT_PROP(DT_NODELABEL(clk_ertco), clock_frequency) +/* External clock may not be defined so _OR is used */ +#define ADI_MAX32_CLK_EXTCLK_FREQ DT_PROP_OR(DT_NODELABEL(clk_extclk), clock_frequency, 0) + +#define DT_GCR_CLOCKS_CTRL DT_CLOCKS_CTLR(DT_NODELABEL(gcr)) + +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_ipo)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_IPO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_IPO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_erfo)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_ERFO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_ERFO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_ibro)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_IBRO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_IBRO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_iso)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_ISO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_ISO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_inro)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_INRO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_INRO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_ertco)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_ERTCO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_ERTCO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif +#if DT_SAME_NODE(DT_GCR_CLOCKS_CTRL, DT_NODELABEL(clk_extclk)) +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_EXTCLK +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_EXTCLK_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif + +#ifndef ADI_MAX32_SYSCLK_SRC +#define ADI_MAX32_SYSCLK_SRC ADI_MAX32_CLK_IPO +#define ADI_MAX32_SYSCLK_FREQ (ADI_MAX32_CLK_IPO_FREQ / ADI_MAX32_SYSCLK_PRESCALER) +#endif + +#define ADI_MAX32_PCLK_FREQ (ADI_MAX32_SYSCLK_FREQ / 2) + +#define ADI_MAX32_GET_PRPH_CLK_FREQ(clk_src) \ + ((clk_src) == ADI_MAX32_PRPH_CLK_SRC_PCLK ? ADI_MAX32_PCLK_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_IBRO ? ADI_MAX32_CLK_IBRO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_ERFO ? ADI_MAX32_CLK_ERFO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_ERTCO ? ADI_MAX32_CLK_ERTCO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_INRO ? ADI_MAX32_CLK_INRO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_ISO ? ADI_MAX32_CLK_ISO_FREQ \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8 ? (ADI_MAX32_CLK_IBRO_FREQ / 8) \ + : (clk_src) == ADI_MAX32_PRPH_CLK_SRC_EXTCLK ? ADI_MAX32_CLK_EXTCLK_FREQ \ + : 0) + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ADI_MAX32_CLOCK_CONTROL_H_ */ diff --git a/include/zephyr/drivers/clock_control/esp32_clock_control.h b/include/zephyr/drivers/clock_control/esp32_clock_control.h new file mode 100644 index 0000000000000..aa83d78e3960c --- /dev/null +++ b/include/zephyr/drivers/clock_control/esp32_clock_control.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ESP32_CLOCK_CONTROL_H_ +#define ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ESP32_CLOCK_CONTROL_H_ + +#if defined(CONFIG_SOC_SERIES_ESP32) +#include +#elif defined(CONFIG_SOC_SERIES_ESP32S2) +#include +#elif defined(CONFIG_SOC_SERIES_ESP32S3) +#include +#elif defined(CONFIG_SOC_SERIES_ESP32C3) +#include +#elif defined(CONFIG_SOC_SERIES_ESP32C6) +#include +#endif /* CONFIG_SOC_SERIES_ESP32xx */ + +#define ESP32_CLOCK_CONTROL_SUBSYS_CPU 50 +#define ESP32_CLOCK_CONTROL_SUBSYS_RTC_FAST 51 +#define ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW 52 + +struct esp32_cpu_clock_config { + int clk_src; + uint32_t cpu_freq; + uint32_t xtal_freq; +}; + +struct esp32_rtc_clock_config { + uint32_t rtc_fast_clock_src; + uint32_t rtc_slow_clock_src; +}; + +struct esp32_clock_config { + struct esp32_cpu_clock_config cpu; + struct esp32_rtc_clock_config rtc; +}; + +#endif /* ZEPHYR_INCLUDE_DRIVERS_CLOCK_CONTROL_ESP32_CLOCK_CONTROL_H_ */ diff --git a/include/zephyr/drivers/clock_control/stm32_clock_control.h b/include/zephyr/drivers/clock_control/stm32_clock_control.h index 062fae034e311..a9ce911e5c7f0 100644 --- a/include/zephyr/drivers/clock_control/stm32_clock_control.h +++ b/include/zephyr/drivers/clock_control/stm32_clock_control.h @@ -44,6 +44,8 @@ #include #elif defined(CONFIG_SOC_SERIES_STM32H7X) #include +#elif defined(CONFIG_SOC_SERIES_STM32H7RSX) +#include #elif defined(CONFIG_SOC_SERIES_STM32U5X) #include #elif defined(CONFIG_SOC_SERIES_STM32WBAX) @@ -61,6 +63,7 @@ #define STM32_APB1_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb1_prescaler) #define STM32_APB2_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb2_prescaler) #define STM32_APB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb3_prescaler) +#define STM32_APB5_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb5_prescaler) #define STM32_APB7_PRESCALER DT_PROP(DT_NODELABEL(rcc), apb7_prescaler) #define STM32_AHB3_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb3_prescaler) #define STM32_AHB4_PRESCALER DT_PROP(DT_NODELABEL(rcc), ahb4_prescaler) @@ -86,13 +89,22 @@ #define STM32_ADC12_PRESCALER DT_PROP(DT_NODELABEL(rcc), adc12_prescaler) #define STM32_ADC34_PRESCALER DT_PROP(DT_NODELABEL(rcc), adc34_prescaler) -/** STM2H7 specifics RCC dividers */ +/** STM2H7RS specific RCC dividers */ +#if defined(CONFIG_SOC_SERIES_STM32H7RSX) +#define STM32_D1CPRE DT_PROP(DT_NODELABEL(rcc), dcpre) +#define STM32_HPRE DT_PROP(DT_NODELABEL(rcc), hpre) +#define STM32_PPRE1 DT_PROP(DT_NODELABEL(rcc), ppre1) +#define STM32_PPRE2 DT_PROP(DT_NODELABEL(rcc), ppre2) +#define STM32_PPRE4 DT_PROP(DT_NODELABEL(rcc), ppre4) +#define STM32_PPRE5 DT_PROP(DT_NODELABEL(rcc), ppre5) +#else #define STM32_D1CPRE DT_PROP(DT_NODELABEL(rcc), d1cpre) #define STM32_HPRE DT_PROP(DT_NODELABEL(rcc), hpre) #define STM32_D2PPRE1 DT_PROP(DT_NODELABEL(rcc), d2ppre1) #define STM32_D2PPRE2 DT_PROP(DT_NODELABEL(rcc), d2ppre2) #define STM32_D1PPRE DT_PROP(DT_NODELABEL(rcc), d1ppre) #define STM32_D3PPRE DT_PROP(DT_NODELABEL(rcc), d3ppre) +#endif /* CONFIG_SOC_SERIES_STM32H7RSX */ /** STM2WBA specifics RCC dividers */ #define STM32_AHB5_DIV DT_PROP(DT_NODELABEL(rcc), ahb5_div) @@ -133,7 +145,8 @@ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32u5_pll_clock, okay) || \ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32wb_pll_clock, okay) || \ DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32wba_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7_pll_clock, okay) + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll), st_stm32h7rs_pll_clock, okay) #define STM32_PLL_ENABLED 1 #define STM32_PLL_M_DIVISOR DT_PROP(DT_NODELABEL(pll), div_m) #define STM32_PLL_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll), mul_n) @@ -143,6 +156,8 @@ #define STM32_PLL_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_q, 1) #define STM32_PLL_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_r) #define STM32_PLL_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_r, 1) +#define STM32_PLL_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), div_s) +#define STM32_PLL_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll), div_s, 1) #define STM32_PLL_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll), fracn) #define STM32_PLL_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll), fracn, 1) #endif @@ -164,7 +179,8 @@ #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32u5_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7_pll_clock, okay) + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll2), st_stm32h7rs_pll_clock, okay) #define STM32_PLL2_ENABLED 1 #define STM32_PLL2_M_DIVISOR DT_PROP(DT_NODELABEL(pll2), div_m) #define STM32_PLL2_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll2), mul_n) @@ -174,12 +190,17 @@ #define STM32_PLL2_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_q, 1) #define STM32_PLL2_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_r) #define STM32_PLL2_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_r, 1) +#define STM32_PLL2_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_s) +#define STM32_PLL2_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_s, 1) +#define STM32_PLL2_T_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), div_t) +#define STM32_PLL2_T_DIVISOR DT_PROP_OR(DT_NODELABEL(pll2), div_t, 1) #define STM32_PLL2_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll2), fracn) #define STM32_PLL2_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll2), fracn, 1) #endif #if DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32h7_pll_clock, okay) || \ - DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32u5_pll_clock, okay) + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32u5_pll_clock, okay) || \ + DT_NODE_HAS_COMPAT_STATUS(DT_NODELABEL(pll3), st_stm32h7rs_pll_clock, okay) #define STM32_PLL3_ENABLED 1 #define STM32_PLL3_M_DIVISOR DT_PROP(DT_NODELABEL(pll3), div_m) #define STM32_PLL3_N_MULTIPLIER DT_PROP(DT_NODELABEL(pll3), mul_n) @@ -189,6 +210,8 @@ #define STM32_PLL3_Q_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_q, 1) #define STM32_PLL3_R_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_r) #define STM32_PLL3_R_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_r, 1) +#define STM32_PLL3_S_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), div_s) +#define STM32_PLL3_S_DIVISOR DT_PROP_OR(DT_NODELABEL(pll3), div_s, 1) #define STM32_PLL3_FRACN_ENABLED DT_NODE_HAS_PROP(DT_NODELABEL(pll3), fracn) #define STM32_PLL3_FRACN_VALUE DT_PROP_OR(DT_NODELABEL(pll3), fracn, 1) #endif diff --git a/include/zephyr/drivers/console/uart_mux.h b/include/zephyr/drivers/console/uart_mux.h deleted file mode 100644 index 56b7f80cabd7a..0000000000000 --- a/include/zephyr/drivers/console/uart_mux.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright (c) 2020 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * @file - * @brief Public APIs for UART MUX drivers - */ - -#ifndef ZEPHYR_INCLUDE_DRIVERS_UART_MUX_H_ -#define ZEPHYR_INCLUDE_DRIVERS_UART_MUX_H_ - -/** - * @brief UART Mux Interface - * @defgroup uart_mux_interface UART Mux Interface - * @ingroup io_interfaces - * @{ - */ - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct gsm_dlci; - -/** - * @typedef uart_mux_attach_cb_t - * - * @brief Define the user callback function which is called when - * the UART mux is attached properly. - * - * @param mux UART mux device - * @param dlci_address DLCI id for the virtual muxing channel - * @param connected True if DLCI is connected, false otherwise. - * @param user_data Arbitrary user data. - */ -typedef void (*uart_mux_attach_cb_t)(const struct device *mux, - int dlci_address, - bool connected, void *user_data); - -/** @brief UART mux driver API structure. */ -__subsystem struct uart_mux_driver_api { - /** - * The uart_driver_api must be placed in first position in this - * struct so that we are compatible with uart API. Note that currently - * not all of the UART API functions are implemented. - */ - struct uart_driver_api uart_api; - - /** - * Attach the mux to this UART. The API will call the callback after - * the DLCI is created or not. - */ - int (*attach)(const struct device *mux, const struct device *uart, - int dlci_address, uart_mux_attach_cb_t cb, - void *user_data); -}; - -/** - * @brief Attach physical/real UART to UART muxing device. - * - * @param mux UART mux device structure. - * @param uart Real UART device structure. - * @param dlci_address DLCI id for the virtual muxing channel - * @param cb Callback is called when the DLCI is ready and connected - * @param user_data Caller supplied optional data - * - * @retval 0 No errors, the attachment was successful - * @retval <0 Error - */ -static inline int uart_mux_attach(const struct device *mux, - const struct device *uart, - int dlci_address, uart_mux_attach_cb_t cb, - void *user_data) -{ - const struct uart_mux_driver_api *api = - (const struct uart_mux_driver_api *)mux->api; - - return api->attach(mux, uart, dlci_address, cb, user_data); -} - -/** - * @brief Get UART related to a specific DLCI channel - * - * @param dlci_address DLCI address, value >0 and <63 - * - * @return UART device if found, NULL otherwise - */ -__syscall const struct device *uart_mux_find(int dlci_address); - -/** - * @brief Allocate muxing UART device. - * - * @details This will return next available uart mux driver that will mux the - * data when read or written. This device corresponds to one DLCI channel. - * User must first call this to allocate the DLCI and then call the attach - * function to fully enable the muxing. - * - * @retval device New UART device that will automatically mux data sent to it. - * @retval NULL if error - */ -const struct device *uart_mux_alloc(void); - -/** - * @typedef uart_mux_cb_t - * @brief Callback used while iterating over UART muxes - * - * @param uart Pointer to UART device where the mux is running - * @param dev Pointer to UART mux device - * @param dlci_address DLCI channel id this UART is muxed - * @param user_data A valid pointer to user data or NULL - */ -typedef void (*uart_mux_cb_t)(const struct device *uart, - const struct device *dev, - int dlci_address, void *user_data); - -/** - * @brief Go through all the UART muxes and call callback - * for each of them - * - * @param cb User-supplied callback function to call - * @param user_data User specified data - */ -void uart_mux_foreach(uart_mux_cb_t cb, void *user_data); - -/** - * @brief Disable the mux. - * - * @details Disable does not re-instate whatever ISRs and configs were present - * before the mux was enabled. This must be done by the user. - * - * @param dev UART mux device pointer - */ -void uart_mux_disable(const struct device *dev); - -/** - * @brief Enable the mux. - * - * @details Enables the correct ISRs for the UART mux. - * - * @param dev UART mux device pointer - */ -void uart_mux_enable(const struct device *dev); - -#ifdef __cplusplus -} -#endif - -#include - -/** - * @} - */ - -#endif /* ZEPHYR_INCLUDE_DRIVERS_UART_MUX_H_ */ diff --git a/include/zephyr/drivers/counter.h b/include/zephyr/drivers/counter.h index b21af71319fd8..0e14ade3b5172 100644 --- a/include/zephyr/drivers/counter.h +++ b/include/zephyr/drivers/counter.h @@ -678,6 +678,6 @@ static inline uint32_t z_impl_counter_get_guard_period(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_COUNTER_H_ */ diff --git a/include/zephyr/drivers/dac.h b/include/zephyr/drivers/dac.h index 57f61cce00b46..8e38432051ab3 100644 --- a/include/zephyr/drivers/dac.h +++ b/include/zephyr/drivers/dac.h @@ -131,6 +131,6 @@ static inline int z_impl_dac_write_value(const struct device *dev, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_DAC_H_ */ diff --git a/include/zephyr/drivers/dai.h b/include/zephyr/drivers/dai.h index 2e6f570454006..fa78f3efb15e4 100644 --- a/include/zephyr/drivers/dai.h +++ b/include/zephyr/drivers/dai.h @@ -268,6 +268,8 @@ struct dai_config { size_t block_size; /** DAI specific link configuration. */ uint16_t link_config; + /**< tdm slot goup number*/ + uint32_t tdm_slot_group; }; /** diff --git a/include/zephyr/drivers/disk.h b/include/zephyr/drivers/disk.h index 623b65118b3be..c248ccd93db3c 100644 --- a/include/zephyr/drivers/disk.h +++ b/include/zephyr/drivers/disk.h @@ -49,6 +49,24 @@ extern "C" { #define DISK_IOCTL_GET_ERASE_BLOCK_SZ 4 /** Commit any cached read/writes to disk */ #define DISK_IOCTL_CTRL_SYNC 5 +/** Initialize the disk. This IOCTL must be issued before the disk can be + * used for I/O. It is reference counted, so only the first successful + * invocation of this macro on an uninitialized disk will initialize the IO + * device + */ +#define DISK_IOCTL_CTRL_INIT 6 +/** Deinitialize the disk. This IOCTL can be used to de-initialize the disk, + * enabling it to be removed from the system if the disk is hot-pluggable. + * Disk usage is reference counted, so for a given disk the + * `DISK_IOCTL_CTRL_DEINIT` IOCTL must be issued as many times as the + * `DISK_IOCTL_CTRL_INIT` IOCTL was issued in order to de-initialize it. + * + * This macro optionally accepts a pointer to a boolean as the `buf` parameter, + * which if true indicates the disk should be forcibly stopped, ignoring all + * reference counts. The disk driver must report success if a forced stop is + * requested, but this operation is inherently unsafe. + */ +#define DISK_IOCTL_CTRL_DEINIT 7 /** * @brief Possible return bitmasks for disk_status() @@ -77,6 +95,8 @@ struct disk_info { const struct disk_operations *ops; /** Device associated to this disk */ const struct device *dev; + /** Internally used disk reference count */ + uint16_t refcnt; }; /** diff --git a/include/zephyr/drivers/dma.h b/include/zephyr/drivers/dma.h index 36a5916b080cb..1338b9b131cd1 100644 --- a/include/zephyr/drivers/dma.h +++ b/include/zephyr/drivers/dma.h @@ -788,6 +788,6 @@ static inline uint32_t dma_burst_index(uint32_t burst) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_DMA_H_ */ diff --git a/include/zephyr/drivers/eeprom.h b/include/zephyr/drivers/eeprom.h index 2ab4d1f608234..ff5b21cbd5c7f 100644 --- a/include/zephyr/drivers/eeprom.h +++ b/include/zephyr/drivers/eeprom.h @@ -139,6 +139,6 @@ static inline size_t z_impl_eeprom_get_size(const struct device *dev) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_EEPROM_H_ */ diff --git a/include/zephyr/drivers/emul_fuel_gauge.h b/include/zephyr/drivers/emul_fuel_gauge.h index 5abd7ec4f6ffb..e86c45a2f2bf6 100644 --- a/include/zephyr/drivers/emul_fuel_gauge.h +++ b/include/zephyr/drivers/emul_fuel_gauge.h @@ -93,7 +93,7 @@ static inline int z_impl_emul_fuel_gauge_is_battery_cutoff(const struct emul *ta } #endif -#include +#include /** * @} diff --git a/include/zephyr/drivers/emul_sensor.h b/include/zephyr/drivers/emul_sensor.h index 9bbbd8d30525a..265505d5e5aca 100644 --- a/include/zephyr/drivers/emul_sensor.h +++ b/include/zephyr/drivers/emul_sensor.h @@ -27,16 +27,16 @@ */ __subsystem struct emul_sensor_driver_api { /** Sets a given fractional value for a given sensor channel. */ - int (*set_channel)(const struct emul *target, enum sensor_channel ch, const q31_t *value, - int8_t shift); + int (*set_channel)(const struct emul *target, struct sensor_chan_spec ch, + const q31_t *value, int8_t shift); /** Retrieve a range of sensor values to use with test. */ - int (*get_sample_range)(const struct emul *target, enum sensor_channel ch, q31_t *lower, + int (*get_sample_range)(const struct emul *target, struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift); /** Set the attribute value(s) of a given chanel. */ - int (*set_attribute)(const struct emul *target, enum sensor_channel ch, + int (*set_attribute)(const struct emul *target, struct sensor_chan_spec ch, enum sensor_attribute attribute, const void *value); /** Get metadata about an attribute. */ - int (*get_attribute_metadata)(const struct emul *target, enum sensor_channel ch, + int (*get_attribute_metadata)(const struct emul *target, struct sensor_chan_spec ch, enum sensor_attribute attribute, q31_t *min, q31_t *max, q31_t *increment, int8_t *shift); }; @@ -68,8 +68,9 @@ static inline bool emul_sensor_backend_is_supported(const struct emul *target) * @return -ENOTSUP if no backend API or if channel not supported by emul * @return -ERANGE if provided value is not in the sensor's supported range */ -static inline int emul_sensor_backend_set_channel(const struct emul *target, enum sensor_channel ch, - const q31_t *value, int8_t shift) +static inline int emul_sensor_backend_set_channel(const struct emul *target, + struct sensor_chan_spec ch, const q31_t *value, + int8_t shift) { if (!target || !target->backend_api) { return -ENOTSUP; @@ -101,7 +102,7 @@ static inline int emul_sensor_backend_set_channel(const struct emul *target, enu * */ static inline int emul_sensor_backend_get_sample_range(const struct emul *target, - enum sensor_channel ch, q31_t *lower, + struct sensor_chan_spec ch, q31_t *lower, q31_t *upper, q31_t *epsilon, int8_t *shift) { if (!target || !target->backend_api) { @@ -127,7 +128,7 @@ static inline int emul_sensor_backend_get_sample_range(const struct emul *target * @return < 0 on error */ static inline int emul_sensor_backend_set_attribute(const struct emul *target, - enum sensor_channel ch, + struct sensor_chan_spec ch, enum sensor_attribute attribute, const void *value) { @@ -161,7 +162,7 @@ static inline int emul_sensor_backend_set_attribute(const struct emul *target, * @return < 0 on error */ static inline int emul_sensor_backend_get_attribute_metadata(const struct emul *target, - enum sensor_channel ch, + struct sensor_chan_spec ch, enum sensor_attribute attribute, q31_t *min, q31_t *max, q31_t *increment, int8_t *shift) diff --git a/include/zephyr/drivers/entropy.h b/include/zephyr/drivers/entropy.h index dcb0c2d5ee547..de2d0f2c2d649 100644 --- a/include/zephyr/drivers/entropy.h +++ b/include/zephyr/drivers/entropy.h @@ -127,6 +127,6 @@ static inline int entropy_get_entropy_isr(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_ENTROPY_H_ */ diff --git a/include/zephyr/drivers/espi.h b/include/zephyr/drivers/espi.h index d2e64d9c5e480..62e4ce5e28bf0 100644 --- a/include/zephyr/drivers/espi.h +++ b/include/zephyr/drivers/espi.h @@ -112,14 +112,38 @@ enum espi_channel { * eSPI bus event to indicate events for which user can register callbacks */ enum espi_bus_event { + /** Indicates the eSPI bus was reset either via eSPI reset pin. + * eSPI drivers should convey the eSPI reset status to eSPI driver clients + * following eSPI specification reset pin convention: + * 0-eSPI bus in reset, 1-eSPI bus out-of-reset + * + * Note: There is no need to send this callback for in-band reset. + */ ESPI_BUS_RESET = BIT(0), + + /** Indicates the eSPI HW has received channel enable notification from eSPI host, + * once the eSPI channel is signal as ready to the eSPI host, + * eSPI drivers should convey the eSPI channel ready to eSPI driver client via this event. + */ ESPI_BUS_EVENT_CHANNEL_READY = BIT(1), + + /** Indicates the eSPI HW has received a virtual wire message from eSPI host. + * eSPI drivers should convey the eSPI virtual wire latest status. + */ ESPI_BUS_EVENT_VWIRE_RECEIVED = BIT(2), + + /** Indicates the eSPI HW has received a Out-of-band package from eSPI host. + */ ESPI_BUS_EVENT_OOB_RECEIVED = BIT(3), + + /** Indicates the eSPI HW has received a peripheral eSPI host event. + * eSPI drivers should convey the peripheral type. + */ ESPI_BUS_PERIPHERAL_NOTIFICATION = BIT(4), - ESPI_BUS_SAF_NOTIFICATION = BIT(5), + ESPI_BUS_TAF_NOTIFICATION = BIT(5), }; + /** * @brief eSPI peripheral channel events. * @@ -354,6 +378,12 @@ struct espi_request_packet { /** * @brief eSPI out-of-band transaction packet format + * + * For Tx packet, eSPI driver client shall specify the OOB payload data and its length in bytes. + * For Rx packet, eSPI driver client shall indicate the maximum number of bytes that can receive, + * while the eSPI driver should update the length field with the actual data received/available. + * + * In all cases, the length does not include OOB header size 3 bytes. */ struct espi_oob_packet { uint8_t *buf; @@ -895,12 +925,11 @@ static inline int z_impl_espi_flash_erase(const struct device *dev, * | | | eSPI reset | eSPI host * | | IRQ +<------------+ resets the * | | <-----------+ | bus - * | | | | - * | | Processed | | + * |<-----------------------------| | | + * | Report eSPI bus reset | Processed | | * | | within the | | * | | driver | | * | | | | - * | | | VW CH ready| eSPI host * | | IRQ +<------------+ enables VW * | | <-----------+ | channel @@ -1022,5 +1051,5 @@ static inline int espi_remove_callback(const struct device *dev, /** * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_ESPI_H_ */ diff --git a/include/zephyr/drivers/espi_saf.h b/include/zephyr/drivers/espi_saf.h index 31fc23c0808ee..d9a25a8d654f1 100644 --- a/include/zephyr/drivers/espi_saf.h +++ b/include/zephyr/drivers/espi_saf.h @@ -557,5 +557,5 @@ static inline int espi_saf_remove_callback(const struct device *dev, /** * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_ESPI_SAF_H_ */ diff --git a/include/zephyr/drivers/flash.h b/include/zephyr/drivers/flash.h index d26e521ce906d..7ceea4a5b254e 100644 --- a/include/zephyr/drivers/flash.h +++ b/include/zephyr/drivers/flash.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 Nordic Semiconductor ASA + * Copyright (c) 2017-2024 Nordic Semiconductor ASA * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 @@ -58,9 +58,59 @@ struct flash_pages_layout { */ struct flash_parameters { const size_t write_block_size; + /* Device capabilities. Only drivers are supposed to set the + * capabilities directly, users need to call the FLASH_CAPS_ + * macros on pointer to flash_parameters to get capabilities. + */ + struct { + /* Device has no explicit erase, so it either erases on + * write or does not require it at all. + * This also includes devices that support erase but + * do not require it. + */ + bool no_explicit_erase: 1; + } caps; uint8_t erase_value; /* Byte value of erased flash */ }; +/** Set for ordinary Flash where erase is needed before write of random data */ +#define FLASH_ERASE_C_EXPLICIT 0x01 +/** Reserved for users as initializer for variables that will later store + * capabilities. + */ +#define FLASH_ERASE_CAPS_UNSET (int)-1 +/* The values below are now reserved but not used */ +#define FLASH_ERASE_C_SUPPORTED 0x02 +#define FLASH_ERASE_C_VAL_BIT 0x04 +#define FLASH_ERASE_UNIFORM_PAGE 0x08 + + +/* @brief Parser for flash_parameters for retrieving erase capabilities + * + * The functions parses flash_parameters type object and returns combination + * of erase capabilities of 0 if device does not have any. + * Not that in some cases availability of erase may be dependent on driver + * options, so even if by hardware design a device provides some erase + * capabilities, the function may return 0 if these been disabled or not + * implemented by driver. + * + * @param p pointer to flash_parameters type object + * + * @return 0 or combination of FLASH_ERASE_C_ capabilities. + */ +static inline +int flash_params_get_erase_cap(const struct flash_parameters *p) +{ +#if defined(CONFIG_FLASH_HAS_EXPLICIT_ERASE) +#if defined(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) + return (p->caps.no_explicit_erase) ? 0 : FLASH_ERASE_C_EXPLICIT; +#else + return FLASH_ERASE_C_EXPLICIT; +#endif +#endif + return 0; +} + /** * @} */ @@ -91,6 +141,11 @@ typedef int (*flash_api_write)(const struct device *dev, off_t offset, * the driver, with the driver responsible for ensuring the "erase-protect" * after the operation completes (successfully or not) matches the erase-protect * state when the operation was started. + * + * The callback is optional for RAM non-volatile devices, which do not + * require erase by design, but may be provided if it allows device to + * work more effectively, or if device has a support for internal fill + * operation the erase in driver uses. */ typedef int (*flash_api_erase)(const struct device *dev, off_t offset, size_t size); @@ -228,12 +283,19 @@ static inline int z_impl_flash_write(const struct device *dev, off_t offset, * Any necessary erase protection management is performed by the driver * erase implementation itself. * + * The function should be used only for devices that are really + * explicit erase devices; in case when code relies on erasing + * device, i.e. setting it to erase-value, prior to some operations, + * but should work with explicit erase and RAM non-volatile devices, + * then flash_flatten should rather be used. + * * @param dev : flash device * @param offset : erase area starting offset * @param size : size of area to be erased * * @return 0 on success, negative errno code on fail. * + * @see flash_flatten() * @see flash_get_page_info_by_offs() * @see flash_get_page_info_by_idx() */ @@ -242,15 +304,59 @@ __syscall int flash_erase(const struct device *dev, off_t offset, size_t size); static inline int z_impl_flash_erase(const struct device *dev, off_t offset, size_t size) { + int rc = -ENOSYS; + const struct flash_driver_api *api = (const struct flash_driver_api *)dev->api; - int rc; - rc = api->erase(dev, offset, size); + if (api->erase != NULL) { + rc = api->erase(dev, offset, size); + } return rc; } +__syscall int flash_fill(const struct device *dev, uint8_t val, off_t offset, size_t size); + +/** + * @brief Erase part or all of a flash memory or level it + * + * If device is explicit erase type device or device driver provides erase + * callback, the callback of the device is called, in which it behaves + * the same way as flash_erase. + * If a device is does not require explicit erase, either because + * it has no erase at all or has auto-erase/erase-on-write, + * and does not provide erase callback then erase is emulated by + * leveling selected device memory area with erase_value assigned to + * device. + * + * Erase page offset and size are constrains of paged, explicit erase devices, + * but can be relaxed with devices without such requirement, which means that + * it is up to user code to make sure they are correct as the function + * will return on, if these constrains are not met, -EINVAL for + * paged device, but may succeed on non-explicit erase devices. + * For RAM non-volatile devices the erase pages are emulated, + * at this point, to allow smooth transition for code relying on + * device being paged to function properly; but this is completely + * software constrain. + * + * Generally: if your code previously required device to be erase + * prior to some actions to work, replace flash_erase calls with this + * function; but if your code can work with non-volatile RAM type devices, + * without emulating erase, you should rather have different path + * of execution for page-erase, i.e. Flash, devices and call + * flash_erase for them. + * + * @param dev : flash device + * @param offset : erase area starting offset + * @param size : size of area to be erased + * + * @return 0 on success, negative errno code on fail. + * + * @see flash_erase() + */ +__syscall int flash_flatten(const struct device *dev, off_t offset, size_t size); + struct flash_pages_info { off_t start_offset; /* offset from the base of flash address */ size_t size; @@ -513,6 +619,6 @@ static inline int z_impl_flash_ex_op(const struct device *dev, uint16_t code, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_FLASH_H_ */ diff --git a/include/zephyr/drivers/flash/flash_simulator.h b/include/zephyr/drivers/flash/flash_simulator.h index 0f7e3c5760e76..e1a201b62b3a4 100644 --- a/include/zephyr/drivers/flash/flash_simulator.h +++ b/include/zephyr/drivers/flash/flash_simulator.h @@ -34,6 +34,6 @@ __syscall void *flash_simulator_get_memory(const struct device *dev, } #endif -#include +#include #endif /* __ZEPHYR_INCLUDE_DRIVERS__FLASH_SIMULATOR_H__ */ diff --git a/include/zephyr/drivers/flash/nrf_qspi_nor.h b/include/zephyr/drivers/flash/nrf_qspi_nor.h index 2c3767ad350d1..87db5c75213f5 100644 --- a/include/zephyr/drivers/flash/nrf_qspi_nor.h +++ b/include/zephyr/drivers/flash/nrf_qspi_nor.h @@ -35,6 +35,6 @@ __syscall void nrf_qspi_nor_xip_enable(const struct device *dev, bool enable); } #endif -#include +#include #endif /* __ZEPHYR_INCLUDE_DRIVERS_FLASH_NRF_QSPI_NOR_H__ */ diff --git a/include/zephyr/drivers/fuel_gauge.h b/include/zephyr/drivers/fuel_gauge.h index f4274ea161b90..305e97b278ff4 100644 --- a/include/zephyr/drivers/fuel_gauge.h +++ b/include/zephyr/drivers/fuel_gauge.h @@ -416,6 +416,6 @@ static inline int z_impl_fuel_gauge_battery_cutoff(const struct device *dev) } #endif /* __cplusplus */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_BATTERY_H_ */ diff --git a/include/zephyr/drivers/gnss.h b/include/zephyr/drivers/gnss.h index 2c716a43a0602..2777691d7d5c4 100644 --- a/include/zephyr/drivers/gnss.h +++ b/include/zephyr/drivers/gnss.h @@ -493,6 +493,6 @@ static inline int z_impl_gnss_get_supported_systems(const struct device *dev, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_GNSS_H_ */ diff --git a/include/zephyr/drivers/gpio.h b/include/zephyr/drivers/gpio.h index 1c5cd6e3390b1..30c845414cb10 100644 --- a/include/zephyr/drivers/gpio.h +++ b/include/zephyr/drivers/gpio.h @@ -1828,6 +1828,6 @@ static inline int z_impl_gpio_get_pending_int(const struct device *dev) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_GPIO_H_ */ diff --git a/include/zephyr/drivers/hwinfo.h b/include/zephyr/drivers/hwinfo.h index 468356284be2c..ca2421f5b8ce9 100644 --- a/include/zephyr/drivers/hwinfo.h +++ b/include/zephyr/drivers/hwinfo.h @@ -75,7 +75,7 @@ extern "C" { * @brief Copy the device id to a buffer * * This routine copies "length" number of bytes of the device ID to the buffer. - * If the device ID is smaller then length, the rest of the buffer is left unchanged. + * If the device ID is smaller than length, the rest of the buffer is left unchanged. * The ID depends on the hardware and is not guaranteed unique. * * Drivers are responsible for ensuring that the ID data structure is a @@ -171,6 +171,6 @@ int z_impl_hwinfo_get_supported_reset_cause(uint32_t *supported); } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_HWINFO_H_ */ diff --git a/include/zephyr/drivers/hwspinlock.h b/include/zephyr/drivers/hwspinlock.h index 9f9fd994ea25d..c6e5b480026b3 100644 --- a/include/zephyr/drivers/hwspinlock.h +++ b/include/zephyr/drivers/hwspinlock.h @@ -154,6 +154,6 @@ static inline uint32_t z_impl_hwspinlock_get_max_id(const struct device *dev) /** @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_HWSPINLOCK_H_ */ diff --git a/include/zephyr/drivers/i2c.h b/include/zephyr/drivers/i2c.h index 04b7d02ce15d8..240d61325a345 100644 --- a/include/zephyr/drivers/i2c.h +++ b/include/zephyr/drivers/i2c.h @@ -1634,6 +1634,6 @@ static inline int i2c_reg_update_byte_dt(const struct i2c_dt_spec *spec, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_I2C_H_ */ diff --git a/include/zephyr/drivers/i2c/rtio.h b/include/zephyr/drivers/i2c/rtio.h index d4dc6c32ae22e..2f094540f7011 100644 --- a/include/zephyr/drivers/i2c/rtio.h +++ b/include/zephyr/drivers/i2c/rtio.h @@ -22,7 +22,7 @@ struct i2c_rtio { struct k_sem lock; struct k_spinlock slock; struct rtio *r; - struct rtio_mpsc io_q; + struct mpsc io_q; struct rtio_iodev iodev; struct rtio_iodev_sqe *txn_head; struct rtio_iodev_sqe *txn_curr; diff --git a/include/zephyr/drivers/i2s.h b/include/zephyr/drivers/i2s.h index 987744638ab48..0889a29148e1e 100644 --- a/include/zephyr/drivers/i2s.h +++ b/include/zephyr/drivers/i2s.h @@ -544,6 +544,6 @@ static inline int z_impl_i2s_trigger(const struct device *dev, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_I2S_H_ */ diff --git a/include/zephyr/drivers/i3c.h b/include/zephyr/drivers/i3c.h index b5411dcd9a309..14604cbe8bd94 100644 --- a/include/zephyr/drivers/i3c.h +++ b/include/zephyr/drivers/i3c.h @@ -498,6 +498,9 @@ struct i3c_msg { * Use SDR mode if none is set. */ uint8_t hdr_mode; + + /** HDR command code field (7-bit) for HDR-DDR, HDR-TSP and HDR-TSL */ + uint8_t hdr_cmd_code; }; /** @} */ @@ -1040,6 +1043,58 @@ struct i3c_device_desc { uint8_t max_ibi; } data_length; + /** Describes advanced (Target) capabilities and features */ + struct { + union { + /** + * I3C v1.0 HDR Capabilities (@c I3C_CCC_GETCAPS1_*) + * - Bit[0]: HDR-DDR + * - Bit[1]: HDR-TSP + * - Bit[2]: HDR-TSL + * - Bit[7:3]: Reserved + */ + uint8_t gethdrcap; + + /** + * I3C v1.1+ GETCAPS1 (@c I3C_CCC_GETCAPS1_*) + * - Bit[0]: HDR-DDR + * - Bit[1]: HDR-TSP + * - Bit[2]: HDR-TSL + * - Bit[3]: HDR-BT + * - Bit[7:4]: Reserved + */ + uint8_t getcap1; + }; + + /** + * GETCAPS2 (@c I3C_CCC_GETCAPS2_*) + * - Bit[3:0]: I3C 1.x Specification Version + * - Bit[5:4]: Group Address Capabilities + * - Bit[6]: HDR-DDR Write Abort + * - Bit[7]: HDR-DDR Abort CRC + */ + uint8_t getcap2; + + /** + * GETCAPS3 (@c I3C_CCC_GETCAPS3_*) + * - Bit[0]: Multi-Lane (ML) Data Transfer Support + * - Bit[1]: Device to Device Transfer (D2DXFER) Support + * - Bit[2]: Device to Device Transfer (D2DXFER) IBI Capable + * - Bit[3]: Defining Byte Support in GETCAPS + * - Bit[4]: Defining Byte Support in GETSTATUS + * - Bit[5]: HDR-BT CRC-32 Support + * - Bit[6]: IBI MDB Support for Pending Read Notification + * - Bit[7]: Reserved + */ + uint8_t getcap3; + + /** + * GETCAPS4 + * - Bit[7:0]: Reserved + */ + uint8_t getcap4; + } getcaps; + /** * Private data by the controller to aid in transactions. Do not modify. * @@ -1775,6 +1830,7 @@ static inline int i3c_write(struct i3c_device_desc *target, msg.buf = (uint8_t *)buf; msg.len = num_bytes; msg.flags = I3C_MSG_WRITE | I3C_MSG_STOP; + msg.hdr_cmd_code = 0; return i3c_transfer(target, &msg, 1); } @@ -1800,6 +1856,7 @@ static inline int i3c_read(struct i3c_device_desc *target, msg.buf = buf; msg.len = num_bytes; msg.flags = I3C_MSG_READ | I3C_MSG_STOP; + msg.hdr_cmd_code = 0; return i3c_transfer(target, &msg, 1); } @@ -1830,10 +1887,12 @@ static inline int i3c_write_read(struct i3c_device_desc *target, msg[0].buf = (uint8_t *)write_buf; msg[0].len = num_write; msg[0].flags = I3C_MSG_WRITE; + msg[0].hdr_cmd_code = 0; msg[1].buf = (uint8_t *)read_buf; msg[1].len = num_read; msg[1].flags = I3C_MSG_RESTART | I3C_MSG_READ | I3C_MSG_STOP; + msg[1].hdr_cmd_code = 0; return i3c_transfer(target, msg, 2); } @@ -1895,10 +1954,12 @@ static inline int i3c_burst_write(struct i3c_device_desc *target, msg[0].buf = &start_addr; msg[0].len = 1U; msg[0].flags = I3C_MSG_WRITE; + msg[0].hdr_cmd_code = 0; msg[1].buf = (uint8_t *)buf; msg[1].len = num_bytes; msg[1].flags = I3C_MSG_WRITE | I3C_MSG_STOP; + msg[1].hdr_cmd_code = 0; return i3c_transfer(target, msg, 2); } @@ -2071,6 +2132,6 @@ int i3c_device_basic_info_get(struct i3c_device_desc *target); * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_I3C_H_ */ diff --git a/include/zephyr/drivers/i3c/ccc.h b/include/zephyr/drivers/i3c/ccc.h index 116750bcac59b..767d922086c2d 100644 --- a/include/zephyr/drivers/i3c/ccc.h +++ b/include/zephyr/drivers/i3c/ccc.h @@ -761,7 +761,7 @@ union i3c_ccc_getmxds { /** Get Max Data Speed (GETMXDS) - Max Sustained Data Rate bitmask. */ #define I3C_CCC_GETMXDS_MAXWR_MAX_SDR_FSCL_MASK \ - (0x07U << I3C_CCC_GET_MXDS_MAXWR_MAX_SDR_FSCL_SHIFT) + (0x07U << I3C_CCC_GETMXDS_MAXWR_MAX_SDR_FSCL_SHIFT) /** * @brief Get Max Data Speed (GETMXDS) - maxWr - Max Sustained Data Rate @@ -803,7 +803,7 @@ union i3c_ccc_getmxds { /** Get Max Data Speed (GETMXDS) - maxRd - Max Sustained Data Rate bitmask. */ #define I3C_CCC_GETMXDS_MAXRD_MAX_SDR_FSCL_MASK \ - (0x07U << I3C_CCC_GET_MXDS_MAXRD_MAX_SDR_FSCL_SHIFT) + (0x07U << I3C_CCC_GETMXDS_MAXRD_MAX_SDR_FSCL_SHIFT) /** * @brief Get Max Data Speed (GETMXDS) - maxRd - Max Sustained Data Rate @@ -826,7 +826,7 @@ union i3c_ccc_getmxds { /** Get Max Data Speed (GETMXDS) - CRDHLY1 - Controller Handoff Activity State bitmask. */ #define I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_MASK \ - (0x03U << I3C_CCC_GETMXDS_CRDHLY1_SET_BUS_ACT_STATE_SHIFT) + (0x03U << I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_SHIFT) /** * @brief Get Max Data Speed (GETMXDS) - CRDHLY1 - Controller Handoff Activity State @@ -838,29 +838,147 @@ union i3c_ccc_getmxds { */ #define I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE(crhdly1) \ (((crhdly1) & \ - I3C_CCC_GETMXDS_CRDHLY1_SET_BUS_ACT_STATE_MASK) \ - >> I3C_CCC_GETMXDS_CRDHLY1_SET_BUS_ACT_STATE_SHIFT) + I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_MASK) \ + >> I3C_CCC_GETMXDS_CRDHLY1_CTRL_HANDOFF_ACT_STATE_SHIFT) + +/** + * @brief Indicate which format of GETCAPS to use. + */ +enum i3c_ccc_getcaps_fmt { + /** GETCAPS Format 1 */ + GETCAPS_FORMAT_1, + + /** GETCAPS Format 2 */ + GETCAPS_FORMAT_2, +}; + +/** + * @brief Enum for I3C Get Capabilities (GETCAPS) Format 2 Defining Byte Values. + */ +enum i3c_ccc_getcaps_defbyte { + /** Standard Target capabilities and features. */ + GETCAPS_FORMAT_2_TGTCAPS = 0x00U, + + /** Fixed 32b test pattern. */ + GETCAPS_FORMAT_2_TESTPAT = 0x5AU, + + /** Controller handoff capabilities and features. */ + GETCAPS_FORMAT_2_CRCAPS = 0x91U, + + /** Virtual Target capabilities and features. */ + GETCAPS_FORMAT_2_VTCAPS = 0x93U, + + /** Debug-capable Device capabilities and features. */ + GETCAPS_FORMAT_2_DBGCAPS = 0xD7U, + + /** Invalid defining byte. */ + GETCAPS_FORMAT_2_INVALID = 0x100, +}; /** * @brief Payload for GETCAPS CCC (Get Optional Feature Capabilities). * - * @note Only support GETCAPS Format 1. + * @note Only supports GETCAPS Format 1 and Format 2. In I3C v1.0 this was + * GETHDRCAP which only returned a single byte which is the same as the + * GETCAPS1 byte. */ -struct i3c_ccc_getcaps { - /** - * GETCAP[1-4] bytes. - */ - uint8_t getcaps[4]; +union i3c_ccc_getcaps { + union { + /** + * I3C v1.0 HDR Capabilities + * - Bit[0]: HDR-DDR + * - Bit[1]: HDR-TSP + * - Bit[2]: HDR-TSL + * - Bit[7:3]: Reserved + */ + uint8_t gethdrcap; + + /** + * I3C v1.1+ Device Capabilities + * Byte 1 GETCAPS1 + * - Bit[0]: HDR-DDR + * - Bit[1]: HDR-TSP + * - Bit[2]: HDR-TSL + * - Bit[3]: HDR-BT + * - Bit[7:4]: Reserved + * Byte 2 GETCAPS2 + * - Bit[3:0]: I3C 1.x Specification Version + * - Bit[5:4]: Group Address Capabilities + * - Bit[6]: HDR-DDR Write Abort + * - Bit[7]: HDR-DDR Abort CRC + * Byte 3 GETCAPS3 + * - Bit[0]: Multi-Lane (ML) Data Transfer Support + * - Bit[1]: Device to Device Transfer (D2DXFER) Support + * - Bit[2]: Device to Device Transfer (D2DXFER) IBI Capable + * - Bit[3]: Defining Byte Support in GETCAPS + * - Bit[4]: Defining Byte Support in GETSTATUS + * - Bit[5]: HDR-BT CRC-32 Support + * - Bit[6]: IBI MDB Support for Pending Read Notification + * - Bit[7]: Reserved + * Byte 4 GETCAPS4 + * - Bit[7:0]: Reserved + */ + uint8_t getcaps[4]; + } fmt1; + + union { + /** + * Defining Byte 0x00: TGTCAPS + * + * @see i3c_ccc_getcaps::fmt1::getcaps + */ + uint8_t tgtcaps[4]; + + /** + * Defining Byte 0x5A: TESTPAT + * + * @note should always be 0xA55AA55A in big endian + */ + uint32_t testpat; + + /** + * Defining Byte 0x91: CRCAPS + * Byte 1 CRCAPS1 + * - Bit[0]: Hot-Join Support + * - Bit[1]: Group Management Support + * - Bit[2]: Multi-Lane Support + * Byte 2 CRCAPS2 + * - Bit[0]: In-Band Interrupt Support + * - Bit[1]: Controller Pass-Back + * - Bit[2]: Deep Sleep Capable + * - Bit[3]: Delayed Controller Handoff + */ + uint8_t crcaps[2]; + + /** + * Defining Byte 0x93: VTCAPS + * Byte 1 VTCAPS1 + * - Bit[2:0]: Virtual Target Type + * - Bit[4]: Side Effects + * - Bit[5]: Shared Peripheral Detect + * Byte 2 VTCAPS2 + * - Bit[1:0]: Interrupt Requests + * - Bit[2]: Address Remapping + * - Bit[4:3]: Bus Context and Conditions + */ + uint8_t vtcaps[2]; + } fmt2; } __packed; -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR-DDR mode bit. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR-DDR mode bit. */ #define I3C_CCC_GETCAPS1_HDR_DDR BIT(0) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR-BT mode bit. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR-TSP mode bit. */ +#define I3C_CCC_GETCAPS1_HDR_TSP BIT(1) + +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR-TSL mode bit. */ +#define I3C_CCC_GETCAPS1_HDR_TSL BIT(2) + +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR-BT mode bit. */ #define I3C_CCC_GETCAPS1_HDR_BT BIT(3) /** - * @brief Get Optional Feature Capabilities (GETCAPS) - HDR Mode + * @brief Get Optional Feature Capabilities Byte 1 (GETCAPS) - HDR Mode * * Get the bit corresponding to HDR mode. * @@ -868,53 +986,53 @@ struct i3c_ccc_getcaps { */ #define I3C_CCC_GETCAPS1_HDR_MODE(x) BIT(x) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 0. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 0. */ #define I3C_CCC_GETCAPS1_HDR_MODE0 BIT(0) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 1. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 1. */ #define I3C_CCC_GETCAPS1_HDR_MODE1 BIT(1) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 2. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 2. */ #define I3C_CCC_GETCAPS1_HDR_MODE2 BIT(2) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 3. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 3. */ #define I3C_CCC_GETCAPS1_HDR_MODE3 BIT(3) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 4. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 4. */ #define I3C_CCC_GETCAPS1_HDR_MODE4 BIT(4) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 5. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 5. */ #define I3C_CCC_GETCAPS1_HDR_MODE5 BIT(5) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 6. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 6. */ #define I3C_CCC_GETCAPS1_HDR_MODE6 BIT(6) -/** Get Optional Feature Capabilities (GETCAPS) Format 1 - HDR Mode 7. */ +/** Get Optional Feature Capabilities Byte 1 (GETCAPS) Format 1 - HDR Mode 7. */ #define I3C_CCC_GETCAPS1_HDR_MODE7 BIT(7) -/** Get Optional Feature Capabilities (GETCAPS) Format 2 - HDR-DDR Write Abort bit. */ +/** Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - HDR-DDR Write Abort bit. */ #define I3C_CCC_GETCAPS2_HDRDDR_WRITE_ABORT BIT(6) -/** Get Optional Feature Capabilities (GETCAPS) Format 2 - HDR-DDR Abort CRC bit. */ +/** Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - HDR-DDR Abort CRC bit. */ #define I3C_CCC_GETCAPS2_HDRDDR_ABORT_CRC BIT(7) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * Group Address Capabilities bit shift value. */ #define I3C_CCC_GETCAPS2_GRPADDR_CAP_SHIFT 4 /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * Group Address Capabilities bitmask. */ #define I3C_CCC_GETCAPS2_GRPADDR_CAP_MASK \ (0x03U << I3C_CCC_GETCAPS2_GRPADDR_CAP_SHIFT) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - Group Address Capabilities. + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - Group Address Capabilities. * - * Obtain Group Address Capabilities value from GETCAPS Format 2 value + * Obtain Group Address Capabilities value from GETCAPS Format 1 value * obtained via GETCAPS. * * @param getcaps2 GETCAPS2 value. @@ -925,23 +1043,23 @@ struct i3c_ccc_getcaps { >> I3C_CCC_GETCAPS_GRPADDR_CAP_SHIFT) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * I3C 1.x Specification Version bit shift value. */ #define I3C_CCC_GETCAPS2_SPEC_VER_SHIFT 0 /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * I3C 1.x Specification Version bitmask. */ #define I3C_CCC_GETCAPS2_SPEC_VER_MASK \ (0x0FU << I3C_CCC_GETCAPS2_SPEC_VER_SHIFT) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 2 - + * @brief Get Optional Feature Capabilities Byte 2 (GETCAPS) Format 1 - * I3C 1.x Specification Version. * - * Obtain I3C 1.x Specification Version value from GETCAPS Format 2 value + * Obtain I3C 1.x Specification Version value from GETCAPS Format 1 value * obtained via GETCAPS. * * @param getcaps2 GETCAPS2 value. @@ -952,47 +1070,197 @@ struct i3c_ccc_getcaps { >> I3C_CCC_GETCAPS_SPEC_VER_SHIFT) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Multi-Lane Data Transfer Support bit. */ #define I3C_CCC_GETCAPS3_MLANE_SUPPORT BIT(0) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Device to Device Transfer (D2DXFER) Support bit. */ #define I3C_CCC_GETCAPS3_D2DXFER_SUPPORT BIT(1) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Device to Device Transfer (D2DXFER) IBI Capable bit. */ #define I3C_CCC_GETCAPS3_D2DXFER_IBI_CAPABLE BIT(2) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Defining Byte Support in GETCAPS bit. */ #define I3C_CCC_GETCAPS3_GETCAPS_DEFINING_BYTE_SUPPORT BIT(3) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * Defining Byte Support in GETSTATUS bit. */ #define I3C_CCC_GETCAPS3_GETSTATUS_DEFINING_BYTE_SUPPORT BIT(4) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * HDR-BT CRC-32 Support bit. */ #define I3C_CCC_GETCAPS3_HDRBT_CRC32_SUPPORT BIT(5) /** - * @brief Get Optional Feature Capabilities (GETCAPS) Format 3 - + * @brief Get Optional Feature Capabilities Byte 3 (GETCAPS) Format 1 - * IBI MDB Support for Pending Read Notification bit. */ #define I3C_CCC_GETCAPS3_IBI_MDR_PENDING_READ_NOTIFICATION BIT(6) +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Byte 1. + */ +#define I3C_CCC_GETCAPS_TESTPAT1 0xA5 + +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Byte 2. + */ +#define I3C_CCC_GETCAPS_TESTPAT2 0x5A + +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Byte 3. + */ +#define I3C_CCC_GETCAPS_TESTPAT3 0xA5 + +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Byte 4. + */ +#define I3C_CCC_GETCAPS_TESTPAT4 0x5A + +/** + * @brief Get Fixed Test Pattern (GETCAPS) Format 2 - + * Fixed Test Pattern Word in Big Endian. + */ +#define I3C_CCC_GETCAPS_TESTPAT 0xA55AA55A + +/** + * @brief Get Controller Handoff Capabilities Byte 1 (GETCAPS) Format 2 - + * Hot-Join Support. + */ +#define I3C_CCC_GETCAPS_CRCAPS1_HJ_SUPPORT BIT(0) + +/** + * @brief Get Controller Handoff Capabilities Byte 1 (GETCAPS) Format 2 - + * Group Management Support. + */ +#define I3C_CCC_GETCAPS_CRCAPS1_GRP_MANAGEMENT_SUPPORT BIT(1) + +/** + * @brief Get Controller Handoff Capabilities Byte 1 (GETCAPS) Format 2 - + * Multi-Lane Support. + */ +#define I3C_CCC_GETCAPS_CRCAPS1_ML_SUPPORT BIT(2) + +/** + * @brief Get Controller Handoff Capabilities Byte 2 (GETCAPS) Format 2 - + * In-Band Interrupt Support. + */ +#define I3C_CCC_GETCAPS_CRCAPS2_IBI_TIR_SUPPORT BIT(0) + +/** + * @brief Get Controller Handoff Capabilities Byte 2 (GETCAPS) Format 2 - + * Controller Pass-Back. + */ +#define I3C_CCC_GETCAPS_CRCAPS2_CONTROLLER_PASSBACK BIT(1) + +/** + * @brief Get Controller Handoff Capabilities Byte 2 (GETCAPS) Format 2 - + * Deep Sleep Capable. + */ +#define I3C_CCC_GETCAPS_CRCAPS2_DEEP_SLEEP_CAPABLE BIT(2) + +/** + * @brief Get Controller Handoff Capabilities Byte 2 (GETCAPS) Format 2 - + * Deep Sleep Capable. + */ +#define I3C_CCC_GETCAPS_CRCAPS2_DELAYED_CONTROLLER_HANDOFF BIT(3) + +/** Get Capabilities (GETCAPS) - VTCAP1 - Virtual Target Type bit shift value. */ +#define I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_SHIFT 0 + +/** Get Capabilities (GETCAPS) - VTCAP1 - Virtual Target Type bitmask. */ +#define I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_MASK \ + (0x07U << I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_SHIFT) + +/** + * @brief Get Capabilities (GETCAPS) - VTCAP1 - Virtual Target Type + * + * Obtain Virtual Target Type value from VTCAP1 value + * obtained via GETCAPS format 2 VTCAP def byte. + * + * @param vtcap1 VTCAP1 value. + */ +#define I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE(vtcap1) \ + (((vtcap1) & \ + I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_MASK) \ + >> I3C_CCC_GETCAPS_VTCAP1_VITRUAL_TARGET_TYPE_SHIFT) + +/** + * @brief Get Virtual Target Capabilities Byte 1 (GETCAPS) Format 2 - + * Side Effects. + */ +#define I3C_CCC_GETCAPS_VTCAP1_SIDE_EFFECTS BIT(4) + +/** + * @brief Get Virtual Target Capabilities Byte 1 (GETCAPS) Format 2 - + * Shared Peripheral Detect. + */ +#define I3C_CCC_GETCAPS_VTCAP1_SHARED_PERIPH_DETECT BIT(5) + +/** Get Capabilities (GETCAPS) - VTCAP2 - Interrupt Requests bit shift value. */ +#define I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_SHIFT 0 + +/** Get Capabilities (GETCAPS) - VTCAP2 - Interrupt Requests bitmask. */ +#define I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_MASK \ + (0x03U << I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_SHIFT) + +/** + * @brief Get Capabilities (GETCAPS) - VTCAP2 - Interrupt Requests + * + * Obtain Interrupt Requests value from VTCAP2 value + * obtained via GETCAPS format 2 VTCAP def byte. + * + * @param vtcap2 VTCAP2 value. + */ +#define I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS(vtcap2) \ + (((vtcap2) & \ + I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_MASK) \ + >> I3C_CCC_GETCAPS_VTCAP2_INTERRUPT_REQUESTS_SHIFT) + +/** + * @brief Get Virtual Target Capabilities Byte 2 (GETCAPS) Format 2 - + * Address Remapping. + */ +#define I3C_CCC_GETCAPS_VTCAP2_ADDRESS_REMAPPING BIT(2) + +/** Get Capabilities (GETCAPS) - VTCAP2 - Bus Context and Condition bit shift value. */ +#define I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_SHIFT 3 + +/** Get Capabilities (GETCAPS) - VTCAP2 - Bus Context and Condition bitmask. */ +#define I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_MASK \ + (0x03U << I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_SHIFT) + +/** + * @brief Get Capabilities (GETCAPS) - VTCAP2 - Bus Context and Condition + * + * Obtain Bus Context and Condition value from VTCAP2 value + * obtained via GETCAPS format 2 VTCAP def byte. + * + * @param vtcap2 VTCAP2 value. + */ +#define I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND(vtcap2) \ + (((vtcap2) & \ + I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_MASK) \ + >> I3C_CCC_GETCAPS_VTCAP2_BUS_CONTEXT_AND_COND_SHIFT) + /** * @brief Enum for I3C Reset Action (RSTACT) Defining Byte Values. */ @@ -1309,6 +1577,65 @@ static inline int i3c_ccc_do_getstatus_fmt2(const struct i3c_device_desc *target GETSTATUS_FORMAT_2, defbyte); } +/** + * @brief Single target GETCAPS to Get Target Status. + * + * Helper function to do GETCAPS (Get Capabilities) of + * one target. + * + * This should only be supported if Advanced Capabilities Bit of + * the BCR is set + * + * @param[in] target Pointer to the target device descriptor. + * @param[out] caps Pointer to GETCAPS payload. + * @param[in] fmt Which GETCAPS to use. + * @param[in] defbyte Defining Byte if using format 2. + * + * @return @see i3c_do_ccc + */ +int i3c_ccc_do_getcaps(const struct i3c_device_desc *target, + union i3c_ccc_getcaps *caps, + enum i3c_ccc_getcaps_fmt fmt, + enum i3c_ccc_getcaps_defbyte defbyte); + +/** + * @brief Single target GETCAPS to Get Capabilities (Format 1). + * + * Helper function to do GETCAPS (Get Capabilities, format 1) of + * one target. + * + * @param[in] target Pointer to the target device descriptor. + * @param[out] caps Pointer to GETCAPS payload. + * + * @return @see i3c_do_ccc + */ +static inline int i3c_ccc_do_getcaps_fmt1(const struct i3c_device_desc *target, + union i3c_ccc_getcaps *caps) +{ + return i3c_ccc_do_getcaps(target, caps, + GETCAPS_FORMAT_1, + GETCAPS_FORMAT_2_INVALID); +} + +/** + * @brief Single target GETCAPS to Get Capabilities (Format 2). + * + * Helper function to do GETCAPS (Get Capabilities, format 2) of + * one target. + * + * @param[in] target Pointer to the target device descriptor. + * @param[out] caps Pointer to GETCAPS payload. + * @param[in] defbyte Defining Byte for GETCAPS format 2. + * + * @return @see i3c_do_ccc + */ +static inline int i3c_ccc_do_getcaps_fmt2(const struct i3c_device_desc *target, + union i3c_ccc_getcaps *caps, + enum i3c_ccc_getcaps_defbyte defbyte) +{ + return i3c_ccc_do_getcaps(target, caps, + GETCAPS_FORMAT_2, defbyte); +} #ifdef __cplusplus } diff --git a/include/zephyr/drivers/interrupt_controller/loapic.h b/include/zephyr/drivers/interrupt_controller/loapic.h index 564355dfefa72..75a47955bc632 100644 --- a/include/zephyr/drivers/interrupt_controller/loapic.h +++ b/include/zephyr/drivers/interrupt_controller/loapic.h @@ -60,11 +60,11 @@ extern "C" { DEVICE_MMIO_TOPLEVEL_DECLARE(LOAPIC_REGS_STR); -extern uint32_t z_loapic_irq_base(void); -extern void z_loapic_enable(unsigned char cpu_number); -extern void z_loapic_int_vec_set(unsigned int irq, unsigned int vector); -extern void z_loapic_irq_enable(unsigned int irq); -extern void z_loapic_irq_disable(unsigned int irq); +uint32_t z_loapic_irq_base(void); +void z_loapic_enable(unsigned char cpu_number); +void z_loapic_int_vec_set(unsigned int irq, unsigned int vector); +void z_loapic_irq_enable(unsigned int irq); +void z_loapic_irq_disable(unsigned int irq); /** * @brief Read 64-bit value from the local APIC in x2APIC mode. diff --git a/include/zephyr/drivers/ipm.h b/include/zephyr/drivers/ipm.h index 1d8ee204c4a9b..fe300921fb3c5 100644 --- a/include/zephyr/drivers/ipm.h +++ b/include/zephyr/drivers/ipm.h @@ -270,6 +270,6 @@ static inline void z_impl_ipm_complete(const struct device *ipmdev) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_IPM_H_ */ diff --git a/include/zephyr/drivers/kscan.h b/include/zephyr/drivers/kscan.h index 0c878df4ec3b6..96c7b933a49fd 100644 --- a/include/zephyr/drivers/kscan.h +++ b/include/zephyr/drivers/kscan.h @@ -139,6 +139,6 @@ static inline int z_impl_kscan_disable_callback(const struct device *dev) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_KB_SCAN_H_ */ diff --git a/include/zephyr/drivers/led.h b/include/zephyr/drivers/led.h index f63a779fa9f40..6de5c36230c50 100644 --- a/include/zephyr/drivers/led.h +++ b/include/zephyr/drivers/led.h @@ -338,6 +338,6 @@ static inline int z_impl_led_off(const struct device *dev, uint32_t led) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_LED_H_ */ diff --git a/include/zephyr/drivers/led_strip.h b/include/zephyr/drivers/led_strip.h index b9c7a81407baa..7c297cbc6cdc1 100644 --- a/include/zephyr/drivers/led_strip.h +++ b/include/zephyr/drivers/led_strip.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Linaro Limited + * Copyright (c) 2024 Jamie McCrae * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,6 +23,7 @@ * @{ */ +#include #include #include @@ -71,6 +73,14 @@ typedef int (*led_api_update_channels)(const struct device *dev, uint8_t *channels, size_t num_channels); +/** + * @typedef led_api_length + * @brief Callback API for getting length of an LED strip. + * + * @see led_strip_length() for argument descriptions. + */ +typedef size_t (*led_api_length)(const struct device *dev); + /** * @brief LED strip driver API * @@ -79,58 +89,85 @@ typedef int (*led_api_update_channels)(const struct device *dev, __subsystem struct led_strip_driver_api { led_api_update_rgb update_rgb; led_api_update_channels update_channels; + led_api_length length; }; /** - * @brief Update an LED strip made of RGB pixels + * @brief Mandatory function to update an LED strip with the given RGB array. * - * Important: - * This routine may overwrite @a pixels. + * @param dev LED strip device. + * @param pixels Array of pixel data. + * @param num_pixels Length of pixels array. * - * This routine immediately updates the strip display according to the - * given pixels array. + * @retval 0 on success. + * @retval -errno negative errno code on failure. * - * @param dev LED strip device - * @param pixels Array of pixel data - * @param num_pixels Length of pixels array - * @return 0 on success, negative on error - * @warning May overwrite @a pixels + * @warning This routine may overwrite @a pixels. */ static inline int led_strip_update_rgb(const struct device *dev, struct led_rgb *pixels, - size_t num_pixels) { + size_t num_pixels) +{ const struct led_strip_driver_api *api = (const struct led_strip_driver_api *)dev->api; + /* Allow for out-of-tree drivers that do not have this function for 2 Zephyr releases + * until making it mandatory, function added after Zephyr 3.6 + */ + if (api->length != NULL) { + /* Ensure supplied pixel size is valid for this device */ + if (api->length(dev) < num_pixels) { + return -ERANGE; + } + } + return api->update_rgb(dev, pixels, num_pixels); } /** - * @brief Update an LED strip on a per-channel basis. + * @brief Optional function to update an LED strip with the given channel array + * (each channel byte corresponding to an individually addressable color + * channel or LED. Channels are updated linearly in strip order. * - * Important: - * This routine may overwrite @a channels. + * @param dev LED strip device. + * @param channels Array of per-channel data. + * @param num_channels Length of channels array. * - * This routine immediately updates the strip display according to the - * given channels array. Each channel byte corresponds to an - * individually addressable color channel or LED. Channels - * are updated linearly in strip order. + * @retval 0 on success. + * @retval -ENOSYS if not implemented. + * @retval -errno negative errno code on other failure. * - * @param dev LED strip device - * @param channels Array of per-channel data - * @param num_channels Length of channels array - * @return 0 on success, negative on error - * @warning May overwrite @a channels + * @warning This routine may overwrite @a channels. */ static inline int led_strip_update_channels(const struct device *dev, uint8_t *channels, - size_t num_channels) { + size_t num_channels) +{ const struct led_strip_driver_api *api = (const struct led_strip_driver_api *)dev->api; + if (api->update_channels == NULL) { + return -ENOSYS; + } + return api->update_channels(dev, channels, num_channels); } +/** + * @brief Mandatory function to get chain length (in pixels) of an LED strip device. + * + * @param dev LED strip device. + * + * @retval Length of LED strip device. + */ +static inline size_t led_strip_length(const struct device *dev) +{ + const struct led_strip_driver_api *api = + (const struct led_strip_driver_api *)dev->api; + + return api->length(dev); +} + #ifdef __cplusplus } #endif diff --git a/include/zephyr/drivers/mbox.h b/include/zephyr/drivers/mbox.h index f0ca6337bfbfa..3f8ffc6594760 100644 --- a/include/zephyr/drivers/mbox.h +++ b/include/zephyr/drivers/mbox.h @@ -486,6 +486,6 @@ static inline int mbox_max_channels_get_dt(const struct mbox_dt_spec *spec) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_MBOX_H_ */ diff --git a/include/zephyr/drivers/mdio.h b/include/zephyr/drivers/mdio.h index fe165bcb991dd..bed1b7f73ccf2 100644 --- a/include/zephyr/drivers/mdio.h +++ b/include/zephyr/drivers/mdio.h @@ -237,6 +237,6 @@ static inline int z_impl_mdio_write_c45(const struct device *dev, uint8_t prtad, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_MDIO_H_ */ diff --git a/include/zephyr/drivers/mfd/adp5585.h b/include/zephyr/drivers/mfd/adp5585.h new file mode 100644 index 0000000000000..abac20bcd51b1 --- /dev/null +++ b/include/zephyr/drivers/mfd/adp5585.h @@ -0,0 +1,126 @@ +/* + * Copyright 2024 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_MFD_ADP5585_H_ +#define ZEPHYR_INCLUDE_DRIVERS_MFD_ADP5585_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#define ADP5585_ID 0x00 +#define ADP5585_INT_STATUS 0x01 +#define ADP5585_STATUS 0x02 +#define ADP5585_FIFO_1 0x03 +#define ADP5585_FIFO_2 0x04 +#define ADP5585_FIFO_3 0x05 +#define ADP5585_FIFO_4 0x06 +#define ADP5585_FIFO_5 0x07 +#define ADP5585_FIFO_6 0x08 +#define ADP5585_FIFO_7 0x09 +#define ADP5585_FIFO_8 0x0A +#define ADP5585_FIFO_9 0x0B +#define ADP5585_FIFO_10 0x0C +#define ADP5585_FIFO_11 0x0D +#define ADP5585_FIFO_12 0x0E +#define ADP5585_FIFO_13 0x0F +#define ADP5585_FIFO_14 0x10 +#define ADP5585_FIFO_15 0x11 +#define ADP5585_FIFO_16 0x12 +#define ADP5585_GPI_INT_STAT_A 0x13 +#define ADP5585_GPI_INT_STAT_B 0x14 +#define ADP5585_GPI_STATUS_A 0x15 +#define ADP5585_GPI_STATUS_B 0x16 +#define ADP5585_RPULL_CONFIG_A 0x17 +#define ADP5585_RPULL_CONFIG_B 0x18 +#define ADP5585_RPULL_CONFIG_C 0x19 +#define ADP5585_RPULL_CONFIG_D 0x1A +#define ADP5585_GPI_INT_LEVEL_A 0x1B +#define ADP5585_GPI_INT_LEVEL_B 0x1C +#define ADP5585_GPI_EVENT_EN_A 0x1D +#define ADP5585_GPI_EVENT_EN_B 0x1E +#define ADP5585_GPI_INTERRUPT_EN_A 0x1F +#define ADP5585_GPI_INTERRUPT_EN_B 0x20 +#define ADP5585_DEBOUNCE_DIS_A 0x21 +#define ADP5585_DEBOUNCE_DIS_B 0x22 +#define ADP5585_GPO_DATA_OUT_A 0x23 +#define ADP5585_GPO_DATA_OUT_B 0x24 +#define ADP5585_GPO_OUT_MODE_A 0x25 +#define ADP5585_GPO_OUT_MODE_B 0x26 +#define ADP5585_GPIO_DIRECTION_A 0x27 +#define ADP5585_GPIO_DIRECTION_B 0x28 +#define ADP5585_RESET1_EVENT_A 0x29 +#define ADP5585_RESET1_EVENT_B 0x2A +#define ADP5585_RESET1_EVENT_C 0x2B +#define ADP5585_RESET2_EVENT_A 0x2C +#define ADP5585_RESET2_EVENT_B 0x2D +#define ADP5585_RESET_CFG 0x2E +#define ADP5585_PWM_OFFT_LOW 0x2F +#define ADP5585_PWM_OFFT_HIGH 0x30 +#define ADP5585_PWM_ONT_LOW 0x31 +#define ADP5585_PWM_ONT_HIGH 0x32 +#define ADP5585_PWM_CFG 0x33 +#define ADP5585_LOGIC_CFG 0x34 +#define ADP5585_LOGIC_FF_CFG 0x35 +#define ADP5585_LOGIC_INT_EVENT_EN 0x36 +#define ADP5585_POLL_PTIME_CFG 0x37 +#define ADP5585_PIN_CONFIG_A 0x38 +#define ADP5585_PIN_CONFIG_B 0x39 +#define ADP5585_PIN_CONFIG_C 0x3A +#define ADP5585_GENERAL_CFG 0x3B +#define ADP5585_INT_EN 0x3C + +/* ID Register */ +#define ADP5585_DEVICE_ID_MASK 0xF +#define ADP5585_MAN_ID_MASK 0xF +#define ADP5585_MAN_ID_SHIFT 4 +#define ADP5585_MAN_ID 0x02 + +#define ADP5585_PWM_CFG_EN 0x1 +#define ADP5585_PWM_CFG_MODE 0x2 +#define ADP5585_PIN_CONFIG_R3_PWM 0x8 +#define ADP5585_PIN_CONFIG_R3_MASK 0xC +#define ADP5585_GENERAL_CFG_OSC_EN 0x80 + +/* INT_EN and INT_STATUS Register */ +#define ADP5585_INT_EVENT (1U << 0) +#define ADP5585_INT_GPI (1U << 1) +#define ADP5585_INT_OVERFLOW (1U << 2) +#define ADP5585_INT_LOGIC (1U << 4) + +#define ADP5585_REG_MASK 0xFF + +struct mfd_adp5585_config { + struct gpio_dt_spec reset_gpio; + struct gpio_dt_spec nint_gpio; + struct i2c_dt_spec i2c_bus; +}; + +struct mfd_adp5585_data { + struct k_work work; + struct k_sem lock; + const struct device *dev; + struct { +#ifdef CONFIG_GPIO_ADP5585 + const struct device *gpio_dev; +#endif /* CONFIG_GPIO_ADP5585 */ + } child; + struct gpio_callback int_gpio_cb; +}; + +/** + * @brief Forward declaration of child device interrupt + * handler + */ +#ifdef CONFIG_GPIO_ADP5585 +void gpio_adp5585_irq_handler(const struct device *dev); +#endif /* CONFIG_GPIO_ADP5585 */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_MFD_AD5952_H_ */ diff --git a/include/zephyr/drivers/misc/README b/include/zephyr/drivers/misc/README index 17a18102f3678..a820cf6340875 100644 --- a/include/zephyr/drivers/misc/README +++ b/include/zephyr/drivers/misc/README @@ -15,3 +15,7 @@ This directory contains header files of the Miscellaneous Drivers. layer graphic operations like widgets, shapes, fonts, text, or bitmaps rendering. These operations are controlled by a vendor-specific API designed for this device. + +* STM32 Wake-up Pins + STM32 wake-up pins are part of the Power Control (PWR) peripheral. + They can be used to wake-up the system from Poweroff through GPIO pins. diff --git a/include/zephyr/drivers/misc/devmux/devmux.h b/include/zephyr/drivers/misc/devmux/devmux.h index 1772d719d96d6..8b01d633a94ce 100644 --- a/include/zephyr/drivers/misc/devmux/devmux.h +++ b/include/zephyr/drivers/misc/devmux/devmux.h @@ -85,6 +85,6 @@ __syscall int devmux_select_set(struct device *dev, size_t index); } #endif -#include +#include #endif /* INCLUDE_ZEPHYR_DRIVERS_MISC_DEVMUX_H_ */ diff --git a/include/zephyr/drivers/misc/stm32_wkup_pins/stm32_wkup_pins.h b/include/zephyr/drivers/misc/stm32_wkup_pins/stm32_wkup_pins.h new file mode 100644 index 0000000000000..f5b48552e2789 --- /dev/null +++ b/include/zephyr/drivers/misc/stm32_wkup_pins/stm32_wkup_pins.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public APIs for STM32 PWR wake-up pins configuration + */ + +#ifndef ZEPHYR_DRIVERS_MISC_STM32_WKUP_PINS_H_ +#define ZEPHYR_DRIVERS_MISC_STM32_WKUP_PINS_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configure a GPIO pin as a source for STM32 PWR wake-up pins + * + * @param gpio Container for GPIO pin information specified in devicetree + * + * @return 0 on success, -EINVAL on invalid values + */ +int stm32_pwr_wkup_pin_cfg_gpio(const struct gpio_dt_spec *gpio); + +/** + * @brief Enable or Disable pull-up and pull-down configuration for + * GPIO Ports that are associated with STM32 PWR wake-up pins + */ +void stm32_pwr_wkup_pin_cfg_pupd(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_DRIVERS_MISC_STM32_WKUP_PINS_H_ */ diff --git a/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h b/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h index 2c805d923ae4b..ec6fd8c1924b8 100644 --- a/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h +++ b/include/zephyr/drivers/misc/timeaware_gpio/timeaware_gpio.h @@ -190,6 +190,6 @@ static inline int z_impl_tgpio_pin_read_ts_ec(const struct device *dev, uint32_t } #endif -#include +#include #endif /* ZEPHYR_DRIVERS_MISC_TIMEAWARE_GPIO_TIMEAWARE_GPIO */ diff --git a/include/zephyr/drivers/modem/gsm_ppp.h b/include/zephyr/drivers/modem/gsm_ppp.h deleted file mode 100644 index 606752806a2d9..0000000000000 --- a/include/zephyr/drivers/modem/gsm_ppp.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2020 Endian Technologies AB - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_DRIVERS_MODEM_GSM_PPP_H_ -#define ZEPHYR_INCLUDE_DRIVERS_MODEM_GSM_PPP_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define GSM_PPP_MDM_MANUFACTURER_LENGTH 10 -#define GSM_PPP_MDM_MODEL_LENGTH 16 -#define GSM_PPP_MDM_REVISION_LENGTH 64 -#define GSM_PPP_MDM_IMEI_LENGTH 16 -#define GSM_PPP_MDM_IMSI_LENGTH 16 -#define GSM_PPP_MDM_ICCID_LENGTH 32 - -struct gsm_ppp_modem_info { - char mdm_manufacturer[GSM_PPP_MDM_MANUFACTURER_LENGTH]; - char mdm_model[GSM_PPP_MDM_MODEL_LENGTH]; - char mdm_revision[GSM_PPP_MDM_REVISION_LENGTH]; - char mdm_imei[GSM_PPP_MDM_IMEI_LENGTH]; -#if defined(CONFIG_MODEM_SIM_NUMBERS) - char mdm_imsi[GSM_PPP_MDM_IMSI_LENGTH]; - char mdm_iccid[GSM_PPP_MDM_ICCID_LENGTH]; -#endif - int mdm_rssi; -}; - -/** @cond INTERNAL_HIDDEN */ -struct device; -typedef void (*gsm_modem_power_cb)(const struct device *, void *); - -void gsm_ppp_start(const struct device *dev); -void gsm_ppp_stop(const struct device *dev); -/** @endcond */ - -/** - * @brief Register functions callbacks for power modem on/off. - * - * @param dev: gsm modem device - * @param modem_on: callback function to - * execute during gsm ppp configuring. - * @param modem_off: callback function to - * execute during gsm ppp stopping. - * @param user_data: user specified data - */ -void gsm_ppp_register_modem_power_callback(const struct device *dev, - gsm_modem_power_cb modem_on, - gsm_modem_power_cb modem_off, - void *user_data); - -/** - * @brief Get GSM modem information. - * - * @param dev: GSM modem device. - * - * @retval struct gsm_ppp_modem_info * pointer to modem information structure. - */ -const struct gsm_ppp_modem_info *gsm_ppp_modem_info(const struct device *dev); - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_INCLUDE_DRIVERS_MODEM_GSM_PPP_H_ */ diff --git a/include/zephyr/drivers/pcie/pcie.h b/include/zephyr/drivers/pcie/pcie.h index ff3cb07806402..cb55dffd5b8ca 100644 --- a/include/zephyr/drivers/pcie/pcie.h +++ b/include/zephyr/drivers/pcie/pcie.h @@ -158,20 +158,6 @@ struct pcie_bar { * These functions are arch-, board-, or SoC-specific. */ -/** - * @brief Look up the BDF based on PCI(e) vendor & device ID - * - * This function is used to look up the BDF for a device given its - * vendor and device ID. - * - * @deprecated - * @see DEVICE_PCIE_DECLARE - * - * @param id PCI(e) vendor & device ID encoded using PCIE_ID() - * @return The BDF for the device, or PCIE_BDF_NONE if it was not found - */ -__deprecated extern pcie_bdf_t pcie_bdf_lookup(pcie_id_t id); - /** * @brief Read a 32-bit word from an endpoint's configuration space. * @@ -235,18 +221,6 @@ struct pcie_scan_opt { */ int pcie_scan(const struct pcie_scan_opt *opt); -/** - * @brief Probe for the presence of a PCI(e) endpoint. - * - * @deprecated - * @see DEVICE_PCIE_DECLARE - * - * @param bdf the endpoint to probe - * @param id the endpoint ID to expect, or PCIE_ID_NONE for "any device" - * @return true if the device is present, false otherwise - */ -__deprecated extern bool pcie_probe(pcie_bdf_t bdf, pcie_id_t id); - /** * @brief Get the MBAR at a specific BAR index * @param bdf the PCI(e) endpoint diff --git a/include/zephyr/drivers/peci.h b/include/zephyr/drivers/peci.h index 03970314b538c..ebc110706c53a 100644 --- a/include/zephyr/drivers/peci.h +++ b/include/zephyr/drivers/peci.h @@ -348,6 +348,6 @@ static inline int z_impl_peci_transfer(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_PECI_H_ */ diff --git a/include/zephyr/drivers/ps2.h b/include/zephyr/drivers/ps2.h index 80351c4466184..6060ba60478f4 100644 --- a/include/zephyr/drivers/ps2.h +++ b/include/zephyr/drivers/ps2.h @@ -172,6 +172,6 @@ static inline int z_impl_ps2_disable_callback(const struct device *dev) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_PS2_H_ */ diff --git a/include/zephyr/drivers/ptp_clock.h b/include/zephyr/drivers/ptp_clock.h index fb6cc8f5a51c6..176c7be8fd16a 100644 --- a/include/zephyr/drivers/ptp_clock.h +++ b/include/zephyr/drivers/ptp_clock.h @@ -101,6 +101,6 @@ static inline int ptp_clock_rate_adjust(const struct device *dev, double rate) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_PTP_CLOCK_H_ */ diff --git a/include/zephyr/drivers/pwm.h b/include/zephyr/drivers/pwm.h index b8a4cbd12ee0a..4f21f41e87617 100644 --- a/include/zephyr/drivers/pwm.h +++ b/include/zephyr/drivers/pwm.h @@ -948,6 +948,6 @@ static inline bool pwm_is_ready_dt(const struct pwm_dt_spec *spec) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_PWM_H_ */ diff --git a/include/zephyr/drivers/reset.h b/include/zephyr/drivers/reset.h index 4e601ea8f9d47..0bf2031b9ccf9 100644 --- a/include/zephyr/drivers/reset.h +++ b/include/zephyr/drivers/reset.h @@ -16,7 +16,7 @@ * @brief Reset Controller Interface * @defgroup reset_controller_interface Reset Controller Interface * @since 3.1 - * @version 0.1.0 + * @version 0.2.0 * @ingroup io_interfaces * @{ */ @@ -74,6 +74,27 @@ struct reset_dt_spec { .id = DT_RESET_ID_BY_IDX(node_id, idx) \ } +/** + * @brief Like RESET_DT_SPEC_GET_BY_IDX(), with a fallback to a default value + * + * If the devicetree node identifier 'node_id' refers to a node with a + * 'resets' property, this expands to + * RESET_DT_SPEC_GET_BY_IDX(node_id, idx). The @p + * default_value parameter is not expanded in this case. + * + * Otherwise, this expands to @p default_value. + * + * @param node_id devicetree node identifier + * @param idx logical index into the 'resets' property + * @param default_value fallback value to expand to + * @return static initializer for a struct reset_dt_spec for the property, + * or default_value if the node or property do not exist + */ +#define RESET_DT_SPEC_GET_BY_IDX_OR(node_id, idx, default_value) \ + COND_CODE_1(DT_NODE_HAS_PROP(node_id, resets), \ + (RESET_DT_SPEC_GET_BY_IDX(node_id, idx)), \ + (default_value)) + /** * @brief Equivalent to RESET_DT_SPEC_GET_BY_IDX(node_id, 0). * @@ -84,6 +105,18 @@ struct reset_dt_spec { #define RESET_DT_SPEC_GET(node_id) \ RESET_DT_SPEC_GET_BY_IDX(node_id, 0) +/** + * @brief Equivalent to + * RESET_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value). + * + * @param node_id devicetree node identifier + * @param default_value fallback value to expand to + * @return static initializer for a struct reset_dt_spec for the property, + * or default_value if the node or property do not exist + */ +#define RESET_DT_SPEC_GET_OR(node_id, default_value) \ + RESET_DT_SPEC_GET_BY_IDX_OR(node_id, 0, default_value) + /** * @brief Static initializer for a @p reset_dt_spec from a DT_DRV_COMPAT * instance's Reset Controller property at an index. @@ -96,6 +129,21 @@ struct reset_dt_spec { #define RESET_DT_SPEC_INST_GET_BY_IDX(inst, idx) \ RESET_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx) +/** + * @brief Static initializer for a @p reset_dt_spec from a DT_DRV_COMPAT + * instance's 'resets' property at an index, with fallback + * + * @param inst DT_DRV_COMPAT instance number + * @param idx logical index into the 'resets' property + * @param default_value fallback value to expand to + * @return static initializer for a struct reset_dt_spec for the property, + * or default_value if the node or property do not exist + */ +#define RESET_DT_SPEC_INST_GET_BY_IDX_OR(inst, idx, default_value) \ + COND_CODE_1(DT_PROP_HAS_IDX(DT_DRV_INST(inst), resets, idx), \ + (RESET_DT_SPEC_GET_BY_IDX(DT_DRV_INST(inst), idx)), \ + (default_value)) + /** * @brief Equivalent to RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0). * @@ -106,6 +154,18 @@ struct reset_dt_spec { #define RESET_DT_SPEC_INST_GET(inst) \ RESET_DT_SPEC_INST_GET_BY_IDX(inst, 0) +/** + * @brief Equivalent to + * RESET_DT_SPEC_INST_GET_BY_IDX_OR(node_id, 0, default_value). + * + * @param inst DT_DRV_COMPAT instance number + * @param default_value fallback value to expand to + * @return static initializer for a struct reset_dt_spec for the property, + * or default_value if the node or property do not exist + */ +#define RESET_DT_SPEC_INST_GET_OR(inst, default_value) \ + RESET_DT_SPEC_INST_GET_BY_IDX_OR(inst, 0, default_value) + /** @cond INTERNAL_HIDDEN */ /** @@ -324,6 +384,6 @@ static inline int reset_line_toggle_dt(const struct reset_dt_spec *spec) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_RESET_H_ */ diff --git a/include/zephyr/drivers/retained_mem.h b/include/zephyr/drivers/retained_mem.h index 7f7003c300b72..a7efafbc7d413 100644 --- a/include/zephyr/drivers/retained_mem.h +++ b/include/zephyr/drivers/retained_mem.h @@ -192,6 +192,6 @@ static inline int z_impl_retained_mem_clear(const struct device *dev) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_RETAINED_MEM_ */ diff --git a/include/zephyr/drivers/rtc.h b/include/zephyr/drivers/rtc.h index ac5d5c0d35066..493bbf137d4ef 100644 --- a/include/zephyr/drivers/rtc.h +++ b/include/zephyr/drivers/rtc.h @@ -539,6 +539,6 @@ static inline struct tm *rtc_time_to_tm(struct rtc_time *timeptr) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_RTC_H_ */ diff --git a/include/zephyr/drivers/rtc/maxim_ds3231.h b/include/zephyr/drivers/rtc/maxim_ds3231.h index 2e8b9fe60ec0e..1dd6be932b01a 100644 --- a/include/zephyr/drivers/rtc/maxim_ds3231.h +++ b/include/zephyr/drivers/rtc/maxim_ds3231.h @@ -596,6 +596,6 @@ int maxim_ds3231_check_alarms(const struct device *dev); #endif /* @todo this should be syscalls/drivers/rtc/maxim_ds3231.h */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_RTC_DS3231_H_ */ diff --git a/include/zephyr/drivers/sdhc.h b/include/zephyr/drivers/sdhc.h index 7934d059896bc..98f651cfeec0e 100644 --- a/include/zephyr/drivers/sdhc.h +++ b/include/zephyr/drivers/sdhc.h @@ -519,5 +519,5 @@ static inline int z_impl_sdhc_disable_interrupt(const struct device *dev, } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SDHC_H_ */ diff --git a/include/zephyr/drivers/sensor.h b/include/zephyr/drivers/sensor.h index f110a47989648..a33a320f90304 100644 --- a/include/zephyr/drivers/sensor.h +++ b/include/zephyr/drivers/sensor.h @@ -150,6 +150,8 @@ enum sensor_channel { SENSOR_CHAN_POS_DY, /** Position change on the Z axis, in points. */ SENSOR_CHAN_POS_DZ, + /** Position change on the X, Y and Z axis, in points. */ + SENSOR_CHAN_POS_DXYZ, /** Revolutions per minute, in RPM. */ SENSOR_CHAN_RPM, @@ -418,6 +420,40 @@ typedef int (*sensor_channel_get_t)(const struct device *dev, enum sensor_channel chan, struct sensor_value *val); +/** + * @brief Sensor Channel Specification + * + * A sensor channel specification is a unique identifier per sensor device describing + * a measurement channel. + * + * @note Typically passed by value as the size of a sensor_chan_spec is a single word. + */ +struct sensor_chan_spec { + uint16_t chan_type; /**< A sensor channel type */ + uint16_t chan_idx; /**< A sensor channel index */ +}; + +/** @cond INTERNAL_HIDDEN */ +/* Ensure sensor_chan_spec is sensibly sized to pass by value */ +BUILD_ASSERT(sizeof(struct sensor_chan_spec) <= sizeof(uintptr_t), + "sensor_chan_spec size should be equal or less than the size of a machine word"); +/** @endcond */ + +/** + * @brief Check if channel specs are equivalent + * + * @param chan_spec0 First chan spec + * @param chan_spec1 Second chan spec + * @retval true If equivalent + * @retval false If not equivalent + */ +static inline bool sensor_chan_spec_eq(struct sensor_chan_spec chan_spec0, + struct sensor_chan_spec chan_spec1) +{ + return chan_spec0.chan_type == chan_spec1.chan_type && + chan_spec0.chan_idx == chan_spec1.chan_idx; +} + /** * @brief Decodes a single raw data buffer * @@ -430,13 +466,12 @@ struct sensor_decoder_api { * * @param[in] buffer The buffer provided on the @ref rtio context. * @param[in] channel The channel to get the count for - * @param[in] channel_idx The index of the channel * @param[out] frame_count The number of frames on the buffer (at least 1) * @return 0 on success * @return -ENOTSUP if the channel/channel_idx aren't found */ - int (*get_frame_count)(const uint8_t *buffer, enum sensor_channel channel, - size_t channel_idx, uint16_t *frame_count); + int (*get_frame_count)(const uint8_t *buffer, struct sensor_chan_spec channel, + uint16_t *frame_count); /** * @brief Get the size required to decode a given channel @@ -450,7 +485,8 @@ struct sensor_decoder_api { * @return 0 on success * @return -ENOTSUP if the channel is not supported */ - int (*get_size_info)(enum sensor_channel channel, size_t *base_size, size_t *frame_size); + int (*get_size_info)(struct sensor_chan_spec channel, size_t *base_size, + size_t *frame_size); /** * @brief Decode up to @p max_count samples from the buffer @@ -470,7 +506,6 @@ struct sensor_decoder_api { * * @param[in] buffer The buffer provided on the @ref rtio context * @param[in] channel The channel to decode - * @param[in] channel_idx The index of the channel * @param[in,out] fit The current frame iterator * @param[in] max_count The maximum number of channels to decode. * @param[out] data_out The decoded data @@ -478,8 +513,8 @@ struct sensor_decoder_api { * @return >0 the number of decoded frames * @return <0 on error */ - int (*decode)(const uint8_t *buffer, enum sensor_channel channel, size_t channel_idx, - uint32_t *fit, uint16_t max_count, void *data_out); + int (*decode)(const uint8_t *buffer, struct sensor_chan_spec channel, uint32_t *fit, + uint16_t max_count, void *data_out); /** * @brief Check if the given trigger type is present @@ -518,20 +553,18 @@ struct sensor_decoder_api { struct sensor_decode_context { const struct sensor_decoder_api *decoder; const uint8_t *buffer; - enum sensor_channel channel; - size_t channel_idx; + struct sensor_chan_spec channel; uint32_t fit; }; /** * @brief Initialize a sensor_decode_context */ -#define SENSOR_DECODE_CONTEXT_INIT(decoder_, buffer_, channel_, channel_index_) \ +#define SENSOR_DECODE_CONTEXT_INIT(decoder_, buffer_, channel_type_, channel_index_) \ { \ .decoder = (decoder_), \ .buffer = (buffer_), \ - .channel = (channel_), \ - .channel_idx = (channel_index_), \ + .channel = {.chan_type = (channel_type_), .chan_idx = (channel_index_)}, \ .fit = 0, \ } @@ -545,11 +578,10 @@ struct sensor_decode_context { */ static inline int sensor_decode(struct sensor_decode_context *ctx, void *out, uint16_t max_count) { - return ctx->decoder->decode(ctx->buffer, ctx->channel, ctx->channel_idx, &ctx->fit, - max_count, out); + return ctx->decoder->decode(ctx->buffer, ctx->channel, &ctx->fit, max_count, out); } -int sensor_natively_supported_channel_size_info(enum sensor_channel channel, size_t *base_size, +int sensor_natively_supported_channel_size_info(struct sensor_chan_spec channel, size_t *base_size, size_t *frame_size); /** @@ -582,6 +614,7 @@ struct sensor_stream_trigger { { \ .trigger = (_trigger), .opt = (_opt), \ } + /* * Internal data structure used to store information about the IODevice for async reading and * streaming sensor data. @@ -590,7 +623,7 @@ struct sensor_read_config { const struct device *sensor; const bool is_streaming; union { - enum sensor_channel *const channels; + struct sensor_chan_spec *const channels; struct sensor_stream_trigger *const triggers; }; size_t count; @@ -604,15 +637,16 @@ struct sensor_read_config { * * @code(.c) * SENSOR_DT_READ_IODEV(icm42688_accelgyro, DT_NODELABEL(icm42688), - * SENSOR_CHAN_ACCEL_XYZ, SENSOR_CHAN_GYRO_XYZ); + * { SENSOR_CHAN_ACCEL_XYZ, 0 }, + * { SENSOR_CHAN_GYRO_XYZ, 0 }); * * int main(void) { - * sensor_read(&icm42688_accelgyro, &rtio); + * sensor_read_async_mempool(&icm42688_accelgyro, &rtio); * } * @endcode */ #define SENSOR_DT_READ_IODEV(name, dt_node, ...) \ - static enum sensor_channel _CONCAT(__channel_array_, name)[] = {__VA_ARGS__}; \ + static struct sensor_chan_spec _CONCAT(__channel_array_, name)[] = {__VA_ARGS__}; \ static struct sensor_read_config _CONCAT(__sensor_read_config_, name) = { \ .sensor = DEVICE_DT_GET(dt_node), \ .is_streaming = false, \ @@ -653,7 +687,7 @@ struct sensor_read_config { RTIO_IODEV_DEFINE(name, &__sensor_iodev_api, &_CONCAT(__sensor_read_config_, name)) /* Used to submit an RTIO sqe to the sensor's iodev */ -typedef int (*sensor_submit_t)(const struct device *sensor, struct rtio_iodev_sqe *sqe); +typedef void (*sensor_submit_t)(const struct device *sensor, struct rtio_iodev_sqe *sqe); /* The default decoder API */ extern const struct sensor_decoder_api __sensor_default_decoder; @@ -886,10 +920,10 @@ struct __attribute__((__packed__)) sensor_data_generic_header { int8_t shift; /* This padding is needed to make sure that the 'channels' field is aligned */ - int8_t _padding[sizeof(enum sensor_channel) - 1]; + int8_t _padding[sizeof(struct sensor_chan_spec) - 1]; /* Channels present in the frame */ - enum sensor_channel channels[0]; + struct sensor_chan_spec channels[0]; }; /** @@ -897,12 +931,12 @@ struct __attribute__((__packed__)) sensor_data_generic_header { * * @param[in] chan The channel to check * @retval true if @p chan is any of @ref SENSOR_CHAN_ACCEL_XYZ, @ref SENSOR_CHAN_GYRO_XYZ, or - * @ref SENSOR_CHAN_MAGN_XYZ + * @ref SENSOR_CHAN_MAGN_XYZ, or @ref SENSOR_CHAN_POS_DXYZ * @retval false otherwise */ #define SENSOR_CHANNEL_3_AXIS(chan) \ ((chan) == SENSOR_CHAN_ACCEL_XYZ || (chan) == SENSOR_CHAN_GYRO_XYZ || \ - (chan) == SENSOR_CHAN_MAGN_XYZ) + (chan) == SENSOR_CHAN_MAGN_XYZ || (chan) == SENSOR_CHAN_POS_DXYZ) /** * @brief Get the sensor's decoder API @@ -949,12 +983,12 @@ static inline int z_impl_sensor_get_decoder(const struct device *dev, * @return < 0 on error */ __syscall int sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, const struct device *sensor, - const enum sensor_channel *channels, + const struct sensor_chan_spec *channels, size_t num_channels); static inline int z_impl_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, const struct device *sensor, - const enum sensor_channel *channels, + const struct sensor_chan_spec *channels, size_t num_channels) { struct sensor_read_config *cfg = (struct sensor_read_config *)iodev->data; @@ -964,7 +998,7 @@ static inline int z_impl_sensor_reconfigure_read_iodev(struct rtio_iodev *iodev, } cfg->sensor = sensor; - memcpy(cfg->channels, channels, num_channels * sizeof(enum sensor_channel)); + memcpy(cfg->channels, channels, num_channels * sizeof(struct sensor_chan_spec)); cfg->count = num_channels; return 0; } @@ -993,7 +1027,50 @@ static inline int sensor_stream(struct rtio_iodev *iodev, struct rtio *ctx, void } /** - * @brief Read data from a sensor. + * @brief Blocking one shot read of samples from a sensor into a buffer + * + * Using @p cfg, read data from the device by using the provided RTIO context + * @p ctx. This call will generate a @ref rtio_sqe that will be given the provided buffer. The call + * will wait for the read to complete before returning to the caller. + * + * @param[in] iodev The iodev created by @ref SENSOR_DT_READ_IODEV + * @param[in] ctx The RTIO context to service the read + * @param[in] buf Pointer to memory to read sample data into + * @param[in] buf_len Size in bytes of the given memory that are valid to read into + * @return 0 on success + * @return < 0 on error + */ +static inline int sensor_read(struct rtio_iodev *iodev, struct rtio *ctx, uint8_t *buf, + size_t buf_len) +{ + if (IS_ENABLED(CONFIG_USERSPACE)) { + struct rtio_sqe sqe; + + rtio_sqe_prep_read(&sqe, iodev, RTIO_PRIO_NORM, buf, buf_len, buf); + rtio_sqe_copy_in(ctx, &sqe, 1); + } else { + struct rtio_sqe *sqe = rtio_sqe_acquire(ctx); + + if (sqe == NULL) { + return -ENOMEM; + } + rtio_sqe_prep_read(sqe, iodev, RTIO_PRIO_NORM, buf, buf_len, buf); + } + rtio_submit(ctx, 1); + + struct rtio_cqe *cqe = rtio_cqe_consume(ctx); + int res = cqe->result; + + __ASSERT(cqe->userdata != buf, + "consumed non-matching completion for sensor read into buffer %p\n", buf); + + rtio_cqe_release(ctx, cqe); + + return res; +} + +/** + * @brief One shot non-blocking read with pool allocated buffer * * Using @p cfg, read one snapshot of data from the device by using the provided RTIO context * @p ctx. This call will generate a @ref rtio_sqe that will leverage the RTIO's internal @@ -1005,7 +1082,8 @@ static inline int sensor_stream(struct rtio_iodev *iodev, struct rtio *ctx, void * @return 0 on success * @return < 0 on error */ -static inline int sensor_read(struct rtio_iodev *iodev, struct rtio *ctx, void *userdata) +static inline int sensor_read_async_mempool(struct rtio_iodev *iodev, struct rtio *ctx, + void *userdata) { if (IS_ENABLED(CONFIG_USERSPACE)) { struct rtio_sqe sqe; @@ -1033,7 +1111,7 @@ static inline int sensor_read(struct rtio_iodev *iodev, struct rtio *ctx, void * * @param[in] result The result code of the read (0 being success) * @param[in] buf The data buffer holding the sensor data * @param[in] buf_len The length (in bytes) of the @p buf - * @param[in] userdata The optional userdata passed to sensor_read() + * @param[in] userdata The optional userdata passed to sensor_read_async_mempool() */ typedef void (*sensor_processing_callback_t)(int result, uint8_t *buf, uint32_t buf_len, void *userdata); @@ -1453,6 +1531,6 @@ DT_FOREACH_STATUS_OKAY_NODE(Z_MAYBE_SENSOR_DECODER_DECLARE_INTERNAL) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_H_ */ diff --git a/include/zephyr/drivers/sensor/grow_r502a.h b/include/zephyr/drivers/sensor/grow_r502a.h index 8b0db47188d35..81ee68ca71464 100644 --- a/include/zephyr/drivers/sensor/grow_r502a.h +++ b/include/zephyr/drivers/sensor/grow_r502a.h @@ -13,6 +13,54 @@ extern "C" { #include +/*LED color code*/ +enum r502a_led_color_idx { + R502A_LED_COLOR_RED = 0x01, + R502A_LED_COLOR_BLUE, + R502A_LED_COLOR_PURPLE, +}; + +#define R502A_BAUD_9600 1 +#define R502A_BAUD_19200 2 +#define R502A_BAUD_38400 4 +#define R502A_BAUD_57600 6 +#define R502A_BAUD_115200 12 + +enum r502a_sec_level { + R502A_SEC_LEVEL_1 = 1, + R502A_SEC_LEVEL_2, + R502A_SEC_LEVEL_3, + R502A_SEC_LEVEL_4, + R502A_SEC_LEVEL_5 +}; + +enum r502a_data_len { + R502A_PKG_LEN_32, + R502A_PKG_LEN_64, + R502A_PKG_LEN_128, + R502A_PKG_LEN_256 +}; + +enum r502a_sys_param_set { + R502A_BAUD_RATE = 4, + R502A_SECURITY_LEVEL, + R502A_DATA_PKG_LEN +}; + +struct r502a_sys_param { + uint16_t status_reg; + uint16_t system_id; + uint16_t lib_size; + uint16_t sec_level; + uint32_t addr; + uint16_t data_pkt_size; + uint32_t baud; +} __packed; + +struct r502a_template { + uint8_t *data; + size_t len; +}; enum sensor_channel_grow_r502a { /** Fingerprint template count, ID number for enrolling and searching*/ SENSOR_CHAN_FINGERPRINT = SENSOR_CHAN_PRIV_START, @@ -24,18 +72,69 @@ enum sensor_trigger_type_grow_r502a { }; enum sensor_attribute_grow_r502a { - /** Add values to the sensor which are having record storage facility */ - SENSOR_ATTR_R502A_RECORD_ADD = SENSOR_ATTR_PRIV_START, + /** To capture finger and store as feature file in + * RAM buffers char_buf_1 and char_buf_2. + */ + SENSOR_ATTR_R502A_CAPTURE = SENSOR_ATTR_PRIV_START, + /** create template from feature files at RAM buffers + * char_buf_1 & char_buf_2 and store a template data + * back in both RAM buffers char_buf_1 and char_buf_2. + */ + SENSOR_ATTR_R502A_TEMPLATE_CREATE, + /** Add template to the sensor record storage */ + /** + * @param val->val1 record index for template to be + * stored in the sensor device's flash + * library. + */ + SENSOR_ATTR_R502A_RECORD_ADD, /** To find requested data in record storage */ + /** + * @result val->val1 matched record index. + * val->val2 matching score. + */ SENSOR_ATTR_R502A_RECORD_FIND, /** To delete mentioned data from record storage */ + /** + * @param val->val1 record start index to be deleted. + * @param val->val2 number of records to be deleted. + */ SENSOR_ATTR_R502A_RECORD_DEL, /** To get available position to store data on record storage */ SENSOR_ATTR_R502A_RECORD_FREE_IDX, /** To empty the storage record*/ SENSOR_ATTR_R502A_RECORD_EMPTY, + /** To load template from storage to RAM buffer of sensor*/ + /** + * @param val->val1 record start index to be loaded in + * device internal RAM buffer. + */ + SENSOR_ATTR_R502A_RECORD_LOAD, + /** To template data stored in sensor's RAM buffer*/ + /** + * @result + * val->val1 match result. + * [R502A_FINGER_MATCH_FOUND or + * R502A_FINGER_MATCH_NOT_FOUND] + * val->val2 matching score. + */ + SENSOR_ATTR_R502A_COMPARE, + /** To read and write device's system parameters */ + /** sensor_attr_set + * @param val->val1 parameter number from enum r502a_sys_param_set. + * @param val->val2 content to be written for the respective parameter. + */ + /** sensor_attr_get + * @result val->ex.data buffer holds the system parameter values. + */ + SENSOR_ATTR_R502A_SYS_PARAM, }; +int r502a_read_sys_param(const struct device *dev, struct r502a_sys_param *val); +int fps_upload_char_buf(const struct device *dev, struct r502a_template *temp); +int fps_download_char_buf(const struct device *dev, uint8_t char_buf_id, + const struct r502a_template *temp); + #ifdef __cplusplus } #endif diff --git a/include/zephyr/drivers/sensor/lm95234.h b/include/zephyr/drivers/sensor/lm95234.h new file mode 100644 index 0000000000000..6d25ceee70489 --- /dev/null +++ b/include/zephyr/drivers/sensor/lm95234.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024, Calian Advanced Technologies + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_LM95234_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_LM95234_H_ + +#include + +enum sensor_channel_lm95234 { + /* External temperature inputs */ + SENSOR_CHAN_LM95234_REMOTE_TEMP_1 = SENSOR_CHAN_PRIV_START, + SENSOR_CHAN_LM95234_REMOTE_TEMP_2, + SENSOR_CHAN_LM95234_REMOTE_TEMP_3, + SENSOR_CHAN_LM95234_REMOTE_TEMP_4 +}; + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_LM95234_H_ */ diff --git a/include/zephyr/drivers/sensor/mcux_lpcmp.h b/include/zephyr/drivers/sensor/mcux_lpcmp.h new file mode 100644 index 0000000000000..d06f5c740eb0e --- /dev/null +++ b/include/zephyr/drivers/sensor/mcux_lpcmp.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020 Vestas Wind Systems A/S + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Data structure for the NXP MCUX low-power analog comparator (LPCMP) + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_MCUX_LPCMP_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_MCUX_LPCMP_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/** + * @brief lpcmp channels. + */ +enum sensor_channel_mcux_lpcmp { + /** LPCMP output. */ + SENSOR_CHAN_MCUX_LPCMP_OUTPUT = SENSOR_CHAN_PRIV_START, +}; + +/** + * @brief lpcmp trigger types. + */ +enum sensor_trigger_type_mcux_lpcmp { + /** LPCMP output rising event trigger. */ + SENSOR_TRIG_MCUX_LPCMP_OUTPUT_RISING = SENSOR_TRIG_PRIV_START, + /** LPCMP output falling event trigger. */ + SENSOR_TRIG_MCUX_LPCMP_OUTPUT_FALLING, +}; + +/** + * @brief lpcmp attribute types. + */ +enum sensor_attribute_mcux_lpcmp { + /** LPCMP positive input mux. */ + SENSOR_ATTR_MCUX_LPCMP_POSITIVE_MUX_INPUT = SENSOR_ATTR_COMMON_COUNT, + /** LPCMP negative input mux. */ + SENSOR_ATTR_MCUX_LPCMP_NEGATIVE_MUX_INPUT, + + /** + * LPCMP internal DAC enable. + * 0b: disable + * 1b: enable + */ + SENSOR_ATTR_MCUX_LPCMP_DAC_ENABLE, + /** + * LPCMP internal DAC high power mode disabled. + * 0b: disable + * 1b: enable + */ + SENSOR_ATTR_MCUX_LPCMP_DAC_HIGH_POWER_MODE_ENABLE, + /** LPCMP internal DAC voltage reference source. */ + SENSOR_ATTR_MCUX_LPCMP_DAC_REFERENCE_VOLTAGE_SOURCE, + /** LPCMP internal DAC output voltage value. */ + SENSOR_ATTR_MCUX_LPCMP_DAC_OUTPUT_VOLTAGE, + + /** LPCMP internal filter sample enable. */ + SENSOR_ATTR_MCUX_LPCMP_SAMPLE_ENABLE, + /** LPCMP internal filter sample count. */ + SENSOR_ATTR_MCUX_LPCMP_FILTER_COUNT, + /** LPCMP internal filter sample period. */ + SENSOR_ATTR_MCUX_LPCMP_FILTER_PERIOD, + + /** LPCMP window signal invert. */ + SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_ENABLE, + /** LPCMP window signal invert. */ + SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_SIGNAL_INVERT_ENABLE, + /** + * LPCMP COUTA signal value when a window is closed: + * 00b: latched + * 01b: set to low + * 11b: set to high + */ + SENSOR_ATTR_MCUX_LPCMP_COUTA_SIGNAL, + /** + * LPCMP COUT event to close an active window: + * xx0b: COUT event cannot close an active window + * 001b: COUT rising edge event close an active window + * 011b: COUT falling edge event close an active window + * 1x1b: COUT both edges event close an active window + */ + SENSOR_ATTR_MCUX_LPCMP_COUT_EVENT_TO_CLOSE_WINDOW +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_MCUX_LPCMP_H_ */ diff --git a/include/zephyr/drivers/sensor/veaa_x_3.h b/include/zephyr/drivers/sensor/veaa_x_3.h new file mode 100644 index 0000000000000..de08f07aedccd --- /dev/null +++ b/include/zephyr/drivers/sensor/veaa_x_3.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2024, Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DRIVERS_SENSOR_VEAA_X_3_H_ +#define ZEPHYR_INCLUDE_DRIVERS_SENSOR_VEAA_X_3_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +enum sensor_attribute_veaa_x_3 { + /* Set pressure setpoint value in kPa. */ + SENSOR_ATTR_VEAA_X_3_SETPOINT = SENSOR_ATTR_PRIV_START, + /* Supported pressure range in kPa. val1 is minimum and val2 is maximum */ + SENSOR_ATTR_VEAA_X_3_RANGE, +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_DRIVERS_SENSOR_VEAA_X_3_H_ */ diff --git a/include/zephyr/drivers/sensor_data_types.h b/include/zephyr/drivers/sensor_data_types.h index dd7f1f39c6d18..604fa614e123a 100644 --- a/include/zephyr/drivers/sensor_data_types.h +++ b/include/zephyr/drivers/sensor_data_types.h @@ -47,6 +47,7 @@ struct sensor_data_header { * - :c:enum:`SENSOR_CHAN_POS_DX` * - :c:enum:`SENSOR_CHAN_POS_DY` * - :c:enum:`SENSOR_CHAN_POS_DZ` + * - :c:enum:`SENSOR_CHAN_POS_DXYZ` */ struct sensor_three_axis_data { struct sensor_data_header header; @@ -109,6 +110,7 @@ struct sensor_q31_data { q31_t power; /**< Unit: watts */ q31_t angle; /**< Unit: degrees */ q31_t electric_charge; /**< Unit: mAh */ + q31_t humidity; /**< Unit: RH */ }; } readings[1]; }; diff --git a/include/zephyr/drivers/serial/uart_emul.h b/include/zephyr/drivers/serial/uart_emul.h index 08e6be05b1aeb..83598a235d945 100644 --- a/include/zephyr/drivers/serial/uart_emul.h +++ b/include/zephyr/drivers/serial/uart_emul.h @@ -52,7 +52,7 @@ void uart_emul_callback_tx_data_ready_set(const struct device *dev, * * @return Number of bytes appended */ -uint32_t uart_emul_put_rx_data(const struct device *dev, uint8_t *data, size_t size); +uint32_t uart_emul_put_rx_data(const struct device *dev, const uint8_t *data, size_t size); /** * @brief Read data from TX buffer @@ -91,6 +91,14 @@ uint32_t uart_emul_flush_tx_data(const struct device *dev); */ void uart_emul_set_errors(const struct device *dev, int errors); +/** + * @brief Configures if rx buffer should be released on timeout, even when only partially filled. + * + * @param dev The emulated UART device instance + * @param release_on_timeout When true, buffer will be released on timeout + */ +void uart_emul_set_release_buffer_on_timeout(const struct device *dev, bool release_on_timeout); + #ifdef __cplusplus } #endif diff --git a/include/zephyr/drivers/sip_svc/sip_svc_driver.h b/include/zephyr/drivers/sip_svc/sip_svc_driver.h index 2904986af3651..07b8f7f867541 100644 --- a/include/zephyr/drivers/sip_svc/sip_svc_driver.h +++ b/include/zephyr/drivers/sip_svc/sip_svc_driver.h @@ -349,6 +349,6 @@ static inline void z_impl_sip_svc_plat_free_async_memory(const struct device *de } -#include +#include #endif /* ZEPHYR_INCLUDE_SIP_SVC_DRIVER_H_ */ diff --git a/include/zephyr/drivers/smbus.h b/include/zephyr/drivers/smbus.h index da4a5c3a9364c..f0642d6d837e4 100644 --- a/include/zephyr/drivers/smbus.h +++ b/include/zephyr/drivers/smbus.h @@ -1092,6 +1092,6 @@ static inline int z_impl_smbus_block_pcall(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SMBUS_H_ */ diff --git a/include/zephyr/drivers/spi.h b/include/zephyr/drivers/spi.h index 067d3419de5ab..6e394ba8b2b40 100644 --- a/include/zephyr/drivers/spi.h +++ b/include/zephyr/drivers/spi.h @@ -389,9 +389,8 @@ struct spi_dt_spec { * data from the devicetree. * * Important: multiple fields are automatically constructed by this macro - * which must be checked before use. @ref spi_is_ready performs the required + * which must be checked before use. @ref spi_is_ready_dt performs the required * @ref device_is_ready checks. - * @deprecated Use @ref spi_is_ready_dt instead. * * @param node_id Devicetree node identifier for the SPI device whose * struct spi_dt_spec to create an initializer for @@ -616,7 +615,7 @@ typedef void (*spi_callback_t)(const struct device *dev, int result, void *data) /** * @typedef spi_api_io * @brief Callback API for asynchronous I/O - * See spi_transceive_async() for argument descriptions + * See spi_transceive_signal() for argument descriptions */ typedef int (*spi_api_io_async)(const struct device *dev, const struct spi_config *config, @@ -683,29 +682,6 @@ static inline bool spi_cs_is_gpio_dt(const struct spi_dt_spec *spec) return spi_cs_is_gpio(&spec->config); } -/** - * @brief Validate that SPI bus is ready. - * - * @param spec SPI specification from devicetree - * - * @retval true if the SPI bus is ready for use. - * @retval false if the SPI bus is not ready for use. - */ -__deprecated -static inline bool spi_is_ready(const struct spi_dt_spec *spec) -{ - /* Validate bus is ready */ - if (!device_is_ready(spec->bus)) { - return false; - } - /* Validate CS gpio port is ready, if it is used */ - if (spi_cs_is_gpio_dt(spec) && - !gpio_is_ready_dt(&spec->config.cs.gpio)) { - return false; - } - return true; -} - /** * @brief Validate that SPI bus (and CS gpio if defined) is ready. * @@ -956,20 +932,6 @@ static inline int spi_transceive_signal(const struct device *dev, return api->transceive_async(dev, config, tx_bufs, rx_bufs, cb, sig); } -/** - * @brief Alias for spi_transceive_signal for backwards compatibility - * - * @deprecated Use @ref spi_transceive_signal instead. - */ -__deprecated static inline int spi_transceive_async(const struct device *dev, - const struct spi_config *config, - const struct spi_buf_set *tx_bufs, - const struct spi_buf_set *rx_bufs, - struct k_poll_signal *sig) -{ - return spi_transceive_signal(dev, config, tx_bufs, rx_bufs, sig); -} - /** * @brief Read the specified amount of data from the SPI driver. * @@ -1002,25 +964,12 @@ static inline int spi_read_signal(const struct device *dev, return spi_transceive_signal(dev, config, NULL, rx_bufs, sig); } -/** - * @brief Alias for spi_read_signal for backwards compatibility - * - * @deprecated Use @ref spi_read_signal instead. - */ -__deprecated static inline int spi_read_async(const struct device *dev, - const struct spi_config *config, - const struct spi_buf_set *rx_bufs, - struct k_poll_signal *sig) -{ - return spi_read_signal(dev, config, rx_bufs, sig); -} - /** * @brief Write the specified amount of data from the SPI driver. * * @note This function is asynchronous. * - * @note This function is a helper function calling spi_transceive_async. + * @note This function is a helper function calling spi_transceive_signal. * * @note This function is available only if @kconfig{CONFIG_SPI_ASYNC} * and @kconfig{CONFIG_POLL} are selected. @@ -1046,19 +995,6 @@ static inline int spi_write_signal(const struct device *dev, return spi_transceive_signal(dev, config, tx_bufs, NULL, sig); } -/** - * @brief Alias for spi_write_signal for backwards compatibility - * - * @deprecated Use @ref spi_write_signal instead. - */ -__deprecated static inline int spi_write_async(const struct device *dev, - const struct spi_config *config, - const struct spi_buf_set *tx_bufs, - struct k_poll_signal *sig) -{ - return spi_write_signal(dev, config, tx_bufs, sig); -} - #endif /* CONFIG_POLL */ #endif /* CONFIG_SPI_ASYNC */ @@ -1331,6 +1267,6 @@ static inline int spi_release_dt(const struct spi_dt_spec *spec) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SPI_H_ */ diff --git a/include/zephyr/drivers/swdp.h b/include/zephyr/drivers/swdp.h new file mode 100644 index 0000000000000..d742280e883f9 --- /dev/null +++ b/include/zephyr/drivers/swdp.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2019 PHYTEC Messtechnik GmbH + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Serial Wire Debug Port interface driver API + */ + +#ifndef ZEPHYR_INCLUDE_SWDP_H_ +#define ZEPHYR_INCLUDE_SWDP_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* SWDP packet request bits */ +#define SWDP_REQUEST_APnDP BIT(0) +#define SWDP_REQUEST_RnW BIT(1) +#define SWDP_REQUEST_A2 BIT(2) +#define SWDP_REQUEST_A3 BIT(3) + +/* SWDP acknowledge response bits */ +#define SWDP_ACK_OK BIT(0) +#define SWDP_ACK_WAIT BIT(1) +#define SWDP_ACK_FAULT BIT(2) + +/* SWDP transfer or parity error */ +#define SWDP_TRANSFER_ERROR BIT(3) + +/* SWDP Interface pins */ +#define SWDP_SWCLK_PIN 0U +#define SWDP_SWDIO_PIN 1U +#define SWDP_nRESET_PIN 7U + +/* + * Serial Wire Interface (SWDP) driver API. + * This is the mandatory API any Serial Wire driver needs to expose. + */ +struct swdp_api { + /** + * @brief Write count bits to SWDIO from data LSB first + * + * @param dev SWDP device + * @param count Number of bits to write + * @param data Bits to write + * @return 0 on success, or error code + */ + int (*swdp_output_sequence)(const struct device *dev, + uint32_t count, + const uint8_t *data); + + /** + * @brief Read count bits from SWDIO into data LSB first + * + * @param dev SWDP device + * @param count Number of bits to read + * @param data Buffer to store bits read + * @return 0 on success, or error code + */ + int (*swdp_input_sequence)(const struct device *dev, + uint32_t count, + uint8_t *data); + + /** + * @brief Perform SWDP transfer and store response + * + * @param dev SWDP device + * @param request SWDP request bits + * @param data Data to be transferred with request + * @param idle_cycles Idle cycles between request and response + * @param response Buffer to store response (ACK/WAIT/FAULT) + * @return 0 on success, or error code + */ + int (*swdp_transfer)(const struct device *dev, + uint8_t request, + uint32_t *data, + uint8_t idle_cycles, + uint8_t *response); + + /** + * @brief Set SWCLK, SWDPIO, and nRESET pins state + * @note The bit positions are defined by the SWDP_*_PIN macros. + * + * @param dev SWDP device + * @param pins Bitmask of pins to set + * @param value Value to set pins to + * @return 0 on success, or error code + */ + int (*swdp_set_pins)(const struct device *dev, + uint8_t pins, uint8_t value); + + /** + * @brief Get SWCLK, SWDPIO, and nRESET pins state + * @note The bit positions are defined by the SWDP_*_PIN macros. + * + * @param dev SWDP device + * @param state Place to store pins state + * @return 0 on success, or error code + */ + int (*swdp_get_pins)(const struct device *dev, uint8_t *state); + + /** + * @brief Set SWDP clock frequency + * + * @param dev SWDP device + * @param clock Clock frequency in Hz + * @return 0 on success, or error code + */ + int (*swdp_set_clock)(const struct device *dev, uint32_t clock); + + /** + * @brief Configure SWDP interface + * + * @param dev SWDP device + * @param turnaround Line turnaround cycles + * @param data_phase Always generate Data Phase (also on WAIT/FAULT) + * @return 0 on success, or error code + */ + int (*swdp_configure)(const struct device *dev, + uint8_t turnaround, + bool data_phase); + + /** + * @brief Enable interface, set pins to default state + * + * @note SWDPIO is set to output mode, SWCLK and nRESET are set to high level. + * + * @param dev SWDP device + * @return 0 on success, or error code + */ + int (*swdp_port_on)(const struct device *dev); + + /** + * @brief Disable interface, set pins to High-Z mode + * + * @param dev SWDP device + * @return 0 on success, or error code + */ + int (*swdp_port_off)(const struct device *dev); +}; + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_SWDP_H_ */ diff --git a/include/zephyr/drivers/syscon.h b/include/zephyr/drivers/syscon.h index a8c5750cc4e0e..6794b48eb64a2 100644 --- a/include/zephyr/drivers/syscon.h +++ b/include/zephyr/drivers/syscon.h @@ -160,6 +160,6 @@ static inline int z_impl_syscon_get_size(const struct device *dev, size_t *size) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_SYSCON_H_ */ diff --git a/include/zephyr/drivers/timer/nrf_grtc_timer.h b/include/zephyr/drivers/timer/nrf_grtc_timer.h index 036d58517255b..f8b69d7ddf021 100644 --- a/include/zephyr/drivers/timer/nrf_grtc_timer.h +++ b/include/zephyr/drivers/timer/nrf_grtc_timer.h @@ -113,7 +113,7 @@ int z_nrf_grtc_timer_compare_read(int32_t chan, uint64_t *val); * * @param chan Channel ID. * - * @param target_time Absolute target time in ticks. + * @param target_time Absolute target time in GRTC ticks. * * @param handler User function called in the context of the GRTC interrupt. * @@ -171,6 +171,7 @@ int z_nrf_grtc_timer_capture_prepare(int32_t chan); * * @retval 0 if the timestamp was successfully caught and read. * @retval -EBUSY if capturing has not been triggered. + * @retval -EPERM if either channel is unavailable or SYSCOUNTER is not running. */ int z_nrf_grtc_timer_capture_read(int32_t chan, uint64_t *captured_time); diff --git a/include/zephyr/drivers/timer/system_timer.h b/include/zephyr/drivers/timer/system_timer.h index 654df3874599f..55f99ad3e28bc 100644 --- a/include/zephyr/drivers/timer/system_timer.h +++ b/include/zephyr/drivers/timer/system_timer.h @@ -70,7 +70,7 @@ extern "C" { * @param idle Hint to the driver that the system is about to enter * the idle state immediately after setting the timeout */ -extern void sys_clock_set_timeout(int32_t ticks, bool idle); +void sys_clock_set_timeout(int32_t ticks, bool idle); /** * @brief Timer idle exit notification @@ -84,7 +84,7 @@ extern void sys_clock_set_timeout(int32_t ticks, bool idle); * This is allowed for compatibility, but not recommended. The kernel * will figure that out on its own. */ -extern void sys_clock_idle_exit(void); +void sys_clock_idle_exit(void); /** * @brief Announce time progress to the kernel @@ -97,7 +97,7 @@ extern void sys_clock_idle_exit(void); * * @param ticks Elapsed time, in ticks */ -extern void sys_clock_announce(int32_t ticks); +void sys_clock_announce(int32_t ticks); /** * @brief Ticks elapsed since last sys_clock_announce() call @@ -107,7 +107,7 @@ extern void sys_clock_announce(int32_t ticks); * this with appropriate locking, the driver needs only provide an * instantaneous answer. */ -extern uint32_t sys_clock_elapsed(void); +uint32_t sys_clock_elapsed(void); /** * @brief Disable system timer. @@ -116,7 +116,7 @@ extern uint32_t sys_clock_elapsed(void); * The config @kconfig{CONFIG_SYSTEM_TIMER_HAS_DISABLE_SUPPORT} can be used to * check if the system timer has the capability of being disabled. */ -extern void sys_clock_disable(void); +void sys_clock_disable(void); /** * @brief Hardware cycle counter diff --git a/include/zephyr/drivers/timer/ti_dmtimer.h b/include/zephyr/drivers/timer/ti_dmtimer.h new file mode 100644 index 0000000000000..95f39390fc1f0 --- /dev/null +++ b/include/zephyr/drivers/timer/ti_dmtimer.h @@ -0,0 +1,104 @@ +/* Copyright (C) 2023 BeagleBoard.org Foundation + * Copyright (C) 2023 S Prashanth + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_DRIVERS_TIMERS_TI_DMTIMER_H_ +#define ZEPHYR_DRIVERS_TIMERS_TI_DMTIMER_H_ + +#include + +#define TI_DM_TIMER_TIDR (0x00) +#define TI_DM_TIMER_TIOCP_CFG (0x10) +#define TI_DM_TIMER_IRQ_EOI (0x20) +#define TI_DM_TIMER_IRQSTATUS_RAW (0x24) +#define TI_DM_TIMER_IRQSTATUS (0x28) /* Interrupt status register */ +#define TI_DM_TIMER_IRQENABLE_SET (0x2c) /* Interrupt enable register */ +#define TI_DM_TIMER_IRQENABLE_CLR (0x30) /* Interrupt disable register */ +#define TI_DM_TIMER_IRQWAKEEN (0x34) +#define TI_DM_TIMER_TCLR (0x38) /* Control register */ +#define TI_DM_TIMER_TCRR (0x3c) /* Counter register */ +#define TI_DM_TIMER_TLDR (0x40) /* Load register */ +#define TI_DM_TIMER_TTGR (0x44) +#define TI_DM_TIMER_TWPS (0x48) +#define TI_DM_TIMER_TMAR (0x4c) /* Match register */ +#define TI_DM_TIMER_TCAR1 (0x50) +#define TI_DM_TIMER_TSICR (0x54) +#define TI_DM_TIMER_TCAR2 (0x58) +#define TI_DM_TIMER_TPIR (0x5c) +#define TI_DM_TIMER_TNIR (0x60) +#define TI_DM_TIMER_TCVR (0x64) +#define TI_DM_TIMER_TOCR (0x68) +#define TI_DM_TIMER_TOWR (0x6c) + +#define TI_DM_TIMER_IRQSTATUS_MAT_IT_FLAG_SHIFT (0) +#define TI_DM_TIMER_IRQSTATUS_MAT_IT_FLAG_MASK (0x00000001) + +#define TI_DM_TIMER_IRQSTATUS_OVF_IT_FLAG_SHIFT (1) +#define TI_DM_TIMER_IRQSTATUS_OVF_IT_FLAG_MASK (0x00000002) + +#define TI_DM_TIMER_IRQSTATUS_TCAR_IT_FLAG_SHIFT (2) +#define TI_DM_TIMER_IRQSTATUS_TCAR_IT_FLAG_MASK (0x00000004) + +#define TI_DM_TIMER_IRQENABLE_SET_MAT_EN_FLAG_SHIFT (0) +#define TI_DM_TIMER_IRQENABLE_SET_MAT_EN_FLAG_MASK (0x00000001) + +#define TI_DM_TIMER_IRQENABLE_SET_OVF_EN_FLAG_SHIFT (1) +#define TI_DM_TIMER_IRQENABLE_SET_OVF_EN_FLAG_MASK (0x00000002) + +#define TI_DM_TIMER_IRQENABLE_SET_TCAR_EN_FLAG_SHIFT (2) +#define TI_DM_TIMER_IRQENABLE_SET_TCAR_EN_FLAG_MASK (0x00000004) + +#define TI_DM_TIMER_IRQENABLE_CLR_MAT_EN_FLAG_SHIFT (0) +#define TI_DM_TIMER_IRQENABLE_CLR_MAT_EN_FLAG_MASK (0x00000001) + +#define TI_DM_TIMER_IRQENABLE_CLR_OVF_EN_FLAG_SHIFT (1) +#define TI_DM_TIMER_IRQENABLE_CLR_OVF_EN_FLAG_MASK (0x00000002) + +#define TI_DM_TIMER_IRQENABLE_CLR_TCAR_EN_FLAG_SHIFT (2) +#define TI_DM_TIMER_IRQENABLE_CLR_TCAR_EN_FLAG_MASK (0x00000004) + +#define TI_DM_TIMER_TCLR_ST_SHIFT (0) +#define TI_DM_TIMER_TCLR_ST_MASK (0x00000001) + +#define TI_DM_TIMER_TCLR_AR_SHIFT (1) +#define TI_DM_TIMER_TCLR_AR_MASK (0x00000002) + +#define TI_DM_TIMER_TCLR_PTV_SHIFT (2) +#define TI_DM_TIMER_TCLR_PTV_MASK (0x0000001c) + +#define TI_DM_TIMER_TCLR_PRE_SHIFT (5) +#define TI_DM_TIMER_TCLR_PRE_MASK (0x00000020) + +#define TI_DM_TIMER_TCLR_CE_SHIFT (6) +#define TI_DM_TIMER_TCLR_CE_MASK (0x00000040) + +#define TI_DM_TIMER_TCLR_SCPWM_SHIFT (7) +#define TI_DM_TIMER_TCLR_SCPWM_MASK (0x00000080) + +#define TI_DM_TIMER_TCLR_TCM_SHIFT (8) +#define TI_DM_TIMER_TCLR_TCM_MASK (0x00000300) + +#define TI_DM_TIMER_TCLR_TRG_SHIFT (10) +#define TI_DM_TIMER_TCLR_TRG_MASK (0x00000c00) + +#define TI_DM_TIMER_TCLR_PT_SHIFT (12) +#define TI_DM_TIMER_TCLR_PT_MASK (0x00001000) + +#define TI_DM_TIMER_TCLR_CAPT_MODE_SHIFT (13) +#define TI_DM_TIMER_TCLR_CAPT_MODE_MASK (0x00002000) + +#define TI_DM_TIMER_TCLR_GPO_CFG_SHIFT (14) +#define TI_DM_TIMER_TCLR_GPO_CFG_MASK (0x00004000) + +#define TI_DM_TIMER_TCRR_TIMER_COUNTER_SHIFT (0) +#define TI_DM_TIMER_TCRR_TIMER_COUNTER_MASK (0xffffffff) + +#define TI_DM_TIMER_TLDR_LOAD_VALUE_SHIFT (0) +#define TI_DM_TIMER_TLDR_LOAD_VALUE_MASK (0xffffffff) + +#define TI_DM_TIMER_TMAR_COMPARE_VALUE_SHIFT (0) +#define TI_DM_TIMER_TMAR_COMPARE_VALUE_MASK (0xffffffff) + +#endif /* ZEPHYR_DRIVERS_TIMERS_TI_DMTIMER_H_ */ diff --git a/include/zephyr/drivers/uart.h b/include/zephyr/drivers/uart.h index 8db89e262f2b9..845949ea96401 100644 --- a/include/zephyr/drivers/uart.h +++ b/include/zephyr/drivers/uart.h @@ -1671,6 +1671,6 @@ static inline int z_impl_uart_drv_cmd(const struct device *dev, uint32_t cmd, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_UART_H_ */ diff --git a/include/zephyr/drivers/usb/udc.h b/include/zephyr/drivers/usb/udc.h index 7e13d565a736a..2e4d4dbcf32cc 100644 --- a/include/zephyr/drivers/usb/udc.h +++ b/include/zephyr/drivers/usb/udc.h @@ -42,6 +42,8 @@ struct udc_device_caps { uint32_t out_ack : 1; /** Controller expects device address to be set before status stage */ uint32_t addr_before_status : 1; + /** Controller can detect the state change of USB supply VBUS.*/ + uint32_t can_detect_vbus : 1; /** Maximum packet size for control endpoint */ enum udc_mps0 mps0 : 2; }; diff --git a/include/zephyr/drivers/usb/usb_bc12.h b/include/zephyr/drivers/usb/usb_bc12.h index 57f47553388c4..791539141739f 100644 --- a/include/zephyr/drivers/usb/usb_bc12.h +++ b/include/zephyr/drivers/usb/usb_bc12.h @@ -184,6 +184,6 @@ static inline int z_impl_bc12_set_result_cb(const struct device *dev, bc12_callb * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_USB_USB_BC12_H_ */ diff --git a/include/zephyr/drivers/usb_c/usbc_tcpc.h b/include/zephyr/drivers/usb_c/usbc_tcpc.h index 94b6b2049f6ff..7b94e3f93a88a 100644 --- a/include/zephyr/drivers/usb_c/usbc_tcpc.h +++ b/include/zephyr/drivers/usb_c/usbc_tcpc.h @@ -154,7 +154,9 @@ __subsystem struct tcpc_driver_api { int (*set_debug_detach)(const struct device *dev); int (*set_drp_toggle)(const struct device *dev, bool enable); int (*get_snk_ctrl)(const struct device *dev); + int (*set_snk_ctrl)(const struct device *dev, bool enable); int (*get_src_ctrl)(const struct device *dev); + int (*set_src_ctrl)(const struct device *dev, bool enable); int (*get_chip_info)(const struct device *dev, struct tcpc_chip_info *chip_info); int (*set_low_power_mode)(const struct device *dev, bool enable); int (*sop_prime_enable)(const struct device *dev, bool enable); @@ -756,6 +758,25 @@ static inline int tcpc_get_snk_ctrl(const struct device *dev) return api->get_snk_ctrl(dev); } +/** + * @brief Set the VBUS sinking state of the TCPC + * + * @param dev Runtime device structure + * @param enable True if sinking should be enabled, false if disabled + * @retval 0 on success + * @retval -ENOSYS if not implemented + */ +static inline int tcpc_set_snk_ctrl(const struct device *dev, bool enable) +{ + const struct tcpc_driver_api *api = (const struct tcpc_driver_api *)dev->api; + + if (api->set_snk_ctrl == NULL) { + return -ENOSYS; + } + + return api->set_snk_ctrl(dev, enable); +} + /** * @brief Queries the current sourcing state of the TCPC * @@ -777,6 +798,25 @@ static inline int tcpc_get_src_ctrl(const struct device *dev) return api->get_src_ctrl(dev); } +/** + * @brief Set the VBUS sourcing state of the TCPC + * + * @param dev Runtime device structure + * @param enable True if sourcing should be enabled, false if disabled + * @retval 0 on success + * @retval -ENOSYS if not implemented + */ +static inline int tcpc_set_src_ctrl(const struct device *dev, bool enable) +{ + const struct tcpc_driver_api *api = (const struct tcpc_driver_api *)dev->api; + + if (api->set_src_ctrl == NULL) { + return -ENOSYS; + } + + return api->set_src_ctrl(dev, enable); +} + /** * @brief Controls the BIST Mode of the TCPC. It disables RX alerts while the * mode is active. diff --git a/include/zephyr/drivers/video.h b/include/zephyr/drivers/video.h index 85f08920119fa..84b5558390e85 100644 --- a/include/zephyr/drivers/video.h +++ b/include/zephyr/drivers/video.h @@ -638,6 +638,9 @@ void video_buffer_release(struct video_buffer *buf); /** YUYV pixel format */ #define VIDEO_PIX_FMT_YUYV video_fourcc('Y', 'U', 'Y', 'V') /* 16 Y0-Cb0 Y1-Cr0 */ +/** XYUV32 pixel format */ +#define VIDEO_PIX_FMT_XYUV32 video_fourcc('X', 'Y', 'U', 'V') /* 32 XYUV-8-8-8-8 */ + /** * * @} diff --git a/include/zephyr/drivers/virtualization/ivshmem.h b/include/zephyr/drivers/virtualization/ivshmem.h index 20bd1e42336eb..b0662d08d5524 100644 --- a/include/zephyr/drivers/virtualization/ivshmem.h +++ b/include/zephyr/drivers/virtualization/ivshmem.h @@ -340,6 +340,6 @@ static inline int z_impl_ivshmem_enable_interrupts(const struct device *dev, * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_VIRTUALIZATION_IVSHMEM_H_ */ diff --git a/include/zephyr/drivers/w1.h b/include/zephyr/drivers/w1.h index ed691f6673370..a8301cda21b2a 100644 --- a/include/zephyr/drivers/w1.h +++ b/include/zephyr/drivers/w1.h @@ -720,6 +720,6 @@ static inline uint16_t w1_crc16(const uint16_t seed, const uint8_t *src, /** * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_W1_H_ */ diff --git a/include/zephyr/drivers/watchdog.h b/include/zephyr/drivers/watchdog.h index 5c53d10bbc70a..fdeb9ef0c3489 100644 --- a/include/zephyr/drivers/watchdog.h +++ b/include/zephyr/drivers/watchdog.h @@ -253,6 +253,6 @@ static inline int z_impl_wdt_feed(const struct device *dev, int channel_id) /** @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_DRIVERS_WATCHDOG_H_ */ diff --git a/include/zephyr/dt-bindings/adc/adc.h b/include/zephyr/dt-bindings/adc/adc.h index fafadb163b6b9..fcbb21e787594 100644 --- a/include/zephyr/dt-bindings/adc/adc.h +++ b/include/zephyr/dt-bindings/adc/adc.h @@ -6,13 +6,7 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ADC_ADC_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_ADC_ADC_H_ -/* - * Provide the BIT_MASK() macro for when this file is included from - * devicetrees. - */ -#ifndef BIT_MASK -#define BIT_MASK(n) ((1 << (n)) - 1) -#endif +#include /** Acquisition time is expressed in microseconds. */ #define ADC_ACQ_TIME_MICROSECONDS (1) diff --git a/include/zephyr/dt-bindings/adc/nxp,gau-adc.h b/include/zephyr/dt-bindings/adc/nxp,gau-adc.h new file mode 100644 index 0000000000000..712a342eedc7e --- /dev/null +++ b/include/zephyr/dt-bindings/adc/nxp,gau-adc.h @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright 2022 NXP + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NXP_GAU_ADC_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NXP_GAU_ADC_H_ + +#include + +/* Channel Sources */ +#define GAU_ADC_CH0 0 +#define GAU_ADC_CH1 1 +#define GAU_ADC_CH2 2 +#define GAU_ADC_CH3 3 +#define GAU_ADC_CH4 4 +#define GAU_ADC_CH5 5 +#define GAU_ADC_CH6 6 +#define GAU_ADC_CH7 7 +#define GAU_ADC_VBATS 8 +#define GAU_ADC_VREF 9 +#define GAU_ADC_DACA 10 +#define GAU_ADC_DACB 11 +#define GAU_ADC_VSSA 12 +#define GAU_ADC_TEMPP 15 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_ADC_NXP_GAU_ADC_H_ */ diff --git a/include/zephyr/dt-bindings/clock/adi_max32_clock.h b/include/zephyr/dt-bindings/clock/adi_max32_clock.h new file mode 100644 index 0000000000000..44fb918c22e9b --- /dev/null +++ b/include/zephyr/dt-bindings/clock/adi_max32_clock.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ADI_MAX32_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ADI_MAX32_CLOCK_H_ + +/** Peripheral clock register */ +#define ADI_MAX32_CLOCK_BUS0 0 +#define ADI_MAX32_CLOCK_BUS1 1 +#define ADI_MAX32_CLOCK_BUS2 2 + +/** Clock source for peripheral interfaces like UART, WDT... */ +#define ADI_MAX32_PRPH_CLK_SRC_PCLK 0 /* Peripheral clock */ +#define ADI_MAX32_PRPH_CLK_SRC_EXTCLK 1 /* External clock */ +#define ADI_MAX32_PRPH_CLK_SRC_IBRO 2 /* Internal Baud Rate Oscillator*/ +#define ADI_MAX32_PRPH_CLK_SRC_ERFO 3 /* External RF Oscillator */ +#define ADI_MAX32_PRPH_CLK_SRC_ERTCO 4 /* External RTC Oscillator */ +#define ADI_MAX32_PRPH_CLK_SRC_INRO 5 /* Internal Nano Ring Oscillator */ +#define ADI_MAX32_PRPH_CLK_SRC_ISO 6 /* Internal Secondary Oscillator */ +#define ADI_MAX32_PRPH_CLK_SRC_IBRO_DIV8 7 /* IBRO/8 */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ADI_MAX32_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/clock/esp32_clock.h b/include/zephyr/dt-bindings/clock/esp32_clock.h index 99ab3c7004b2a..db4abbf02f7aa 100644 --- a/include/zephyr/dt-bindings/clock/esp32_clock.h +++ b/include/zephyr/dt-bindings/clock/esp32_clock.h @@ -8,32 +8,37 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32_H_ -/* System Clock Source */ -#define ESP32_CLK_SRC_XTAL 0U -#define ESP32_CLK_SRC_PLL 1U -#define ESP32_CLK_SRC_RTC8M 2U -#define ESP32_CLK_SRC_APLL 3U +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U +#define ESP32_CLK_SRC_APLL_CLK 3U -/* Supported CPU Frequencies */ -#define ESP32_CLK_CPU_26M 26000000 -#define ESP32_CLK_CPU_40M 40000000 -#define ESP32_CLK_CPU_80M 80000000 -#define ESP32_CLK_CPU_160M 160000000 -#define ESP32_CLK_CPU_240M 240000000 +/* Supported PLL CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_PLL_240M 240000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 1062500 -/* Supported XTAL Frequencies */ -#define ESP32_CLK_XTAL_24M 24 -#define ESP32_CLK_XTAL_26M 26 -#define ESP32_CLK_XTAL_40M 40 -#define ESP32_CLK_XTAL_AUTO 0 +/* Supported XTAL frequencies */ +#define ESP32_CLK_XTAL_24M 24000000 +#define ESP32_CLK_XTAL_26M 26000000 +#define ESP32_CLK_XTAL_40M 40000000 -/* Supported RTC fast clock frequencies */ -#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D4 0 +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 1 -/* Supported RTC slow clock frequencies */ -#define ESP32_RTC_SLOW_CLK_FREQ_150K 150000U -#define ESP32_RTC_SLOW_CLK_FREQ_32K 32000U -#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_8M / 256) +/* Supported RTC slow clock sources */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 150000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ 33203 /* Modules IDs * These IDs are actually offsets in CLK and RST Control registers. diff --git a/include/zephyr/dt-bindings/clock/esp32c3_clock.h b/include/zephyr/dt-bindings/clock/esp32c3_clock.h index 6b5b3de12279c..d0a266e424f15 100644 --- a/include/zephyr/dt-bindings/clock/esp32c3_clock.h +++ b/include/zephyr/dt-bindings/clock/esp32c3_clock.h @@ -7,28 +7,34 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C3_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C3_H_ -/* System Clock Source */ -#define ESP32_CLK_SRC_XTAL 0U -#define ESP32_CLK_SRC_PLL 1U -#define ESP32_CLK_SRC_RTC8M 2U -#define ESP32_CLK_SRC_APLL 3U +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U -/* Supported CPU Frequencies */ -#define ESP32_CLK_CPU_80M 80000000 -#define ESP32_CLK_CPU_160M 160000000 +/* Supported CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 17500000 -/* Supported XTAL Frequencies */ -#define ESP32_CLK_XTAL_32M 32 -#define ESP32_CLK_XTAL_40M 40 +/* Supported XTAL frequencies */ +#define ESP32_CLK_XTAL_32M 32000000 +#define ESP32_CLK_XTAL_40M 40000000 -/* Supported RTC fast clock frequencies */ -#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U -#define ESP32_RTC_FAST_CLK_FREQ_APPROX ESP32_RTC_FAST_CLK_FREQ_8M +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D2 0 +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 1 -/* Supported RTC slow clock frequencies */ -#define ESP32_RTC_SLOW_CLK_FREQ_90K 90000U -#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_APPROX / 256) -#define ESP32_RTC_SLOW_CLK_FREQ_32K 32768U +/* Supported RTC slow clock sources */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 136000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ 68359 /* Modules IDs * These IDs are actually offsets in CLK and RST Control registers. diff --git a/include/zephyr/dt-bindings/clock/esp32c6_clock.h b/include/zephyr/dt-bindings/clock/esp32c6_clock.h new file mode 100644 index 0000000000000..9aa39b2c51edb --- /dev/null +++ b/include/zephyr/dt-bindings/clock/esp32c6_clock.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C6_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C6_H_ + +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U + +/* Supported CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 17500000 + +/* Supported XTAL Frequencies */ +#define ESP32_CLK_XTAL_32M 32000000 +#define ESP32_CLK_XTAL_40M 40000000 + +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 0 +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D2 1 + +/* Supported RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC32K 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 136000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC32K_FREQ 32768 + +/* Modules IDs + * These IDs are actually offsets in CLK and RST Control registers. + * These IDs shouldn't be changed unless there is a Hardware change + * from Espressif. + * + * Basic Modules + * Registers: DPORT_PERIP_CLK_EN_REG, DPORT_PERIP_RST_EN_REG + */ +#define ESP32_LEDC_MODULE 0 +#define ESP32_UART0_MODULE 1 +#define ESP32_UART1_MODULE 2 +#define ESP32_USB_MODULE 3 +#define ESP32_I2C0_MODULE 4 +#define ESP32_I2S1_MODULE 5 +#define ESP32_TIMG0_MODULE 6 +#define ESP32_TIMG1_MODULE 7 +#define ESP32_UHCI0_MODULE 8 +#define ESP32_RMT_MODULE 9 +#define ESP32_PCNT_MODULE 10 +#define ESP32_SPI_MODULE 11 +#define ESP32_SPI2_MODULE 12 +#define ESP32_TWAI0_MODULE 13 +#define ESP32_TWAI1_MODULE 14 +#define ESP32_RNG_MODULE 15 +#define ESP32_RSA_MODULE 16 +#define ESP32_AES_MODULE 17 +#define ESP32_SHA_MODULE 18 +#define ESP32_ECC_MODULE 19 +#define ESP32_HMAC_MODULE 20 +#define ESP32_DS_MODULE 21 +#define ESP32_SDIO_SLAVE_MODULE 22 +#define ESP32_GDMA_MODULE 23 +#define ESP32_MCPWM0_MODULE 24 +#define ESP32_ETM_MODULE 25 +#define ESP32_PARLIO_MODULE 26 +#define ESP32_SYSTIMER_MODULE 27 +#define ESP32_SARADC_MODULE 28 +#define ESP32_TEMPSENSOR_MODULE 29 +#define ESP32_REGDMA_MODULE 30 +#define ESP32_LP_I2C0_MODULE 31 +/* Peripherals clock managed by the modem_clock driver must be listed last */ +#define ESP32_WIFI_MODULE 32 +#define ESP32_BT_MODULE 33 +#define ESP32_IEEE802154_MODULE 34 +#define ESP32_COEX_MODULE 35 +#define ESP32_PHY_MODULE 36 +#define ESP32_MODULE_MAX 37 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32C6_H_ */ diff --git a/include/zephyr/dt-bindings/clock/esp32s2_clock.h b/include/zephyr/dt-bindings/clock/esp32s2_clock.h index aa9eb90de628b..5fc57c65d7049 100644 --- a/include/zephyr/dt-bindings/clock/esp32s2_clock.h +++ b/include/zephyr/dt-bindings/clock/esp32s2_clock.h @@ -7,30 +7,35 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32S2_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32S2_H_ -/* System Clock Source */ -#define ESP32_CLK_SRC_XTAL 0U -#define ESP32_CLK_SRC_PLL 1U -#define ESP32_CLK_SRC_RTC8M 2U -#define ESP32_CLK_SRC_APLL 3U +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U +#define ESP32_CLK_SRC_APLL_CLK 3U -/* Supported CPU Frequencies */ -#define ESP32_CLK_CPU_26M 26000000 -#define ESP32_CLK_CPU_40M 40000000 -#define ESP32_CLK_CPU_80M 80000000 -#define ESP32_CLK_CPU_160M 160000000 -#define ESP32_CLK_CPU_240M 240000000 +/* Supported PLL CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_PLL_240M 240000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 8500000 -/* Supported XTAL Frequencies */ -#define ESP32_CLK_XTAL_40M 40 +/* Supported XTAL frequencies */ +#define ESP32_CLK_XTAL_40M 40000000 -/* Supported RTC fast clock frequencies */ -#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U -#define ESP32_RTC_FAST_CLK_FREQ_APPROX ESP32_RTC_FAST_CLK_FREQ_8M +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D4 0 +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 1 -/* Supported RTC slow clock frequencies */ -#define ESP32_RTC_SLOW_CLK_FREQ_90K 90000U -#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_APPROX / 256) -#define ESP32_RTC_SLOW_CLK_FREQ_32K 32768U +/* Supported RTC slow clock sources */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 90000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ 33203 /* Modules IDs * These IDs are actually offsets in CLK and RST Control registers. diff --git a/include/zephyr/dt-bindings/clock/esp32s3_clock.h b/include/zephyr/dt-bindings/clock/esp32s3_clock.h index 68980d0c8bfe3..9c4bb8364ec78 100644 --- a/include/zephyr/dt-bindings/clock/esp32s3_clock.h +++ b/include/zephyr/dt-bindings/clock/esp32s3_clock.h @@ -7,30 +7,35 @@ #ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32S3_H_ #define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_ESP32S3_H_ -/* System Clock Source */ -#define ESP32_CLK_SRC_XTAL 0U -#define ESP32_CLK_SRC_PLL 1U -#define ESP32_CLK_SRC_RTC8M 2U -#define ESP32_CLK_SRC_APLL 3U +/* Supported CPU clock Sources */ +#define ESP32_CPU_CLK_SRC_XTAL 0U +#define ESP32_CPU_CLK_SRC_PLL 1U +#define ESP32_CLK_SRC_RC_FAST 2U -/* Supported CPU Frequencies */ -#define ESP32_CLK_CPU_26M 26000000 -#define ESP32_CLK_CPU_40M 40000000 -#define ESP32_CLK_CPU_80M 80000000 -#define ESP32_CLK_CPU_160M 160000000 -#define ESP32_CLK_CPU_240M 240000000 +/* Supported PLL CPU frequencies */ +#define ESP32_CLK_CPU_PLL_80M 80000000 +#define ESP32_CLK_CPU_PLL_160M 160000000 +#define ESP32_CLK_CPU_PLL_240M 240000000 +#define ESP32_CLK_CPU_RC_FAST_FREQ 17500000 -/* Supported XTAL Frequencies */ -#define ESP32_CLK_XTAL_32M 32 -#define ESP32_CLK_XTAL_40M 40 +/* Supported XTAL frequencies */ +#define ESP32_CLK_XTAL_32M 32000000 +#define ESP32_CLK_XTAL_40M 40000000 -/* Supported RTC fast clock frequencies */ -#define ESP32_RTC_FAST_CLK_FREQ_8M 8500000U +/* Supported RTC fast clock sources */ +#define ESP32_RTC_FAST_CLK_SRC_XTAL_D2 0 +#define ESP32_RTC_FAST_CLK_SRC_RC_FAST 1 -/* Supported RTC slow clock frequencies */ -#define ESP32_RTC_SLOW_CLK_FREQ_150K 150000U -#define ESP32_RTC_SLOW_CLK_FREQ_32K 32000U -#define ESP32_RTC_SLOW_CLK_FREQ_8MD256 (ESP32_RTC_FAST_CLK_FREQ_8M / 256) +/* Supported RTC slow clock sources */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW 0 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K 1 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256 2 +#define ESP32_RTC_SLOW_CLK_32K_EXT_OSC 9 + +/* RTC slow clock frequencies */ +#define ESP32_RTC_SLOW_CLK_SRC_RC_SLOW_FREQ 136000 +#define ESP32_RTC_SLOW_CLK_SRC_XTAL32K_FREQ 32768 +#define ESP32_RTC_SLOW_CLK_SRC_RC_FAST_D256_FREQ 68359 /* Modules IDs * These IDs are actually offsets in CLK and RST Control registers. diff --git a/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h b/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h index f21844a149047..18c44cab86fdd 100644 --- a/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h +++ b/include/zephyr/dt-bindings/clock/imx_ccm_rev2.h @@ -92,6 +92,8 @@ /* ENET */ #define IMX_CCM_ENET_CLK 0x1200UL #define IMX_CCM_ENET_PLL 0x1201UL +#define IMX_CCM_ENET1G_CLK 0x1202UL +#define IMX_CCM_ENET1G_PLL 0x1203UL /* FLEXSPI */ #define IMX_CCM_FLEXSPI_CLK 0x1300UL @@ -114,4 +116,11 @@ #define IMX_CCM_TPM5_CLK 0x1604UL #define IMX_CCM_TPM6_CLK 0x1605UL +/* QTMR */ +#define IMX_CCM_QTMR_CLK 0x6000UL +#define IMX_CCM_QTMR1_CLK 0x6000UL +#define IMX_CCM_QTMR2_CLK 0x6001UL +#define IMX_CCM_QTMR3_CLK 0x6002UL +#define IMX_CCM_QTMR4_CLK 0x6003UL + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_IMX_CCM_REV2_H_ */ diff --git a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h index 4d5f20f371e00..68fcb1df8b742 100644 --- a/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h +++ b/include/zephyr/dt-bindings/clock/mcux_lpc_syscon_clock.h @@ -76,9 +76,17 @@ #define MCUX_ENET_QOS_CLK MCUX_LPC_CLK_ID(0x0D, 0x00) +#define MCUX_ENET_CLK MCUX_LPC_CLK_ID(0x0D, 0x80) +#define MCUX_ENET_PLL MCUX_LPC_CLK_ID(0x0D, 0x81) + #define MCUX_LCDIC_CLK MCUX_LPC_CLK_ID(0x0E, 0x00) #define MCUX_LPADC1_CLK MCUX_LPC_CLK_ID(0x0F, 0x00) #define MCUX_LPADC2_CLK MCUX_LPC_CLK_ID(0x0F, 0x01) +#define MCUX_FLEXCAN0_CLK MCUX_LPC_CLK_ID(0x10, 0x00) +#define MCUX_FLEXCAN1_CLK MCUX_LPC_CLK_ID(0x10, 0x01) + +#define MCUX_FLEXIO0_CLK MCUX_LPC_CLK_ID(0x11, 0x00) + #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_MCUX_LPC_SYSCON_H_ */ diff --git a/include/zephyr/dt-bindings/clock/stm32h7rs_clock.h b/include/zephyr/dt-bindings/clock/stm32h7rs_clock.h new file mode 100644 index 0000000000000..579ae56b0e250 --- /dev/null +++ b/include/zephyr/dt-bindings/clock/stm32h7rs_clock.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7RS_CLOCK_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7RS_CLOCK_H_ + +#include "stm32_common_clocks.h" + +/** Domain clocks */ + +/* RM0477 */ + +/** System clock */ +/* defined in stm32_common_clocks.h */ + +/** Fixed clocks */ +/* Low speed clocks defined in stm32_common_clocks.h */ +#define STM32_SRC_HSE (STM32_SRC_LSI + 1) +#define STM32_SRC_HSI48 (STM32_SRC_HSE + 1) +#define STM32_SRC_HSI_KER (STM32_SRC_HSI48 + 1) /* HSI + HSIKERON */ +#define STM32_SRC_CSI_KER (STM32_SRC_HSI_KER + 1) /* CSI + CSIKERON */ +/** PLL outputs */ +#define STM32_SRC_PLL1_P (STM32_SRC_CSI_KER + 1) +#define STM32_SRC_PLL1_Q (STM32_SRC_PLL1_P + 1) +#define STM32_SRC_PLL1_R (STM32_SRC_PLL1_Q + 1) +#define STM32_SRC_PLL1_S (STM32_SRC_PLL1_R + 1) +#define STM32_SRC_PLL2_P (STM32_SRC_PLL1_S + 1) +#define STM32_SRC_PLL2_Q (STM32_SRC_PLL2_P + 1) +#define STM32_SRC_PLL2_R (STM32_SRC_PLL2_Q + 1) +#define STM32_SRC_PLL2_S (STM32_SRC_PLL2_R + 1) +#define STM32_SRC_PLL2_T (STM32_SRC_PLL2_S + 1) +#define STM32_SRC_PLL3_P (STM32_SRC_PLL2_T + 1) +#define STM32_SRC_PLL3_Q (STM32_SRC_PLL3_P + 1) +#define STM32_SRC_PLL3_R (STM32_SRC_PLL3_Q + 1) +#define STM32_SRC_PLL3_S (STM32_SRC_PLL3_R + 1) + +/** Clock muxes */ +#define STM32_SRC_CKPER (STM32_SRC_PLL3_S + 1) +/** Others: Not yet supported */ + +/** Bus clocks */ +#define STM32_CLOCK_BUS_AHB1 0x138 +#define STM32_CLOCK_BUS_AHB2 0x13C +#define STM32_CLOCK_BUS_AHB3 0x158 +#define STM32_CLOCK_BUS_AHB4 0x140 +#define STM32_CLOCK_BUS_AHB5 0x134 +#define STM32_CLOCK_BUS_APB1 0x148 +#define STM32_CLOCK_BUS_APB1_2 0x14C +#define STM32_CLOCK_BUS_APB2 0x150 +#define STM32_CLOCK_BUS_APB4 0x154 +#define STM32_CLOCK_BUS_APB5 0x144 +#define STM32_PERIPH_BUS_MIN STM32_CLOCK_BUS_AHB5 +#define STM32_PERIPH_BUS_MAX STM32_CLOCK_BUS_AHB3 + +#define STM32_CLOCK_REG_MASK 0xFFU +#define STM32_CLOCK_REG_SHIFT 0U +#define STM32_CLOCK_SHIFT_MASK 0x1FU +#define STM32_CLOCK_SHIFT_SHIFT 8U +#define STM32_CLOCK_MASK_MASK 0x7U +#define STM32_CLOCK_MASK_SHIFT 13U +#define STM32_CLOCK_VAL_MASK 0x7U +#define STM32_CLOCK_VAL_SHIFT 16U + +/** + * @brief STM32H7RS clock configuration bit field. + * + * - reg (0/1) [ 0 : 7 ] + * - shift (0..31) [ 8 : 12 ] + * - mask (0x1, 0x3, 0x7) [ 13 : 15 ] + * - val (0..3) [ 16 : 18 ] + * + * @param reg RCC_DxCCIP register offset + * @param shift Position within RCC_DxCCIP. + * @param mask Mask for the RCC_DxCCIP field. + * @param val Clock value (0, 1, 2 or 3). + */ +#define STM32_CLOCK(val, mask, shift, reg) \ + ((((reg) & STM32_CLOCK_REG_MASK) << STM32_CLOCK_REG_SHIFT) | \ + (((shift) & STM32_CLOCK_SHIFT_MASK) << STM32_CLOCK_SHIFT_SHIFT) | \ + (((mask) & STM32_CLOCK_MASK_MASK) << STM32_CLOCK_MASK_SHIFT) | \ + (((val) & STM32_CLOCK_VAL_MASK) << STM32_CLOCK_VAL_SHIFT)) + +/** @brief RCC_DxCCIP register offset (RM0477.pdf) */ +#define D1CCIPR_REG 0x4C +#define D2CCIPR_REG 0x50 +#define D3CCIPR_REG 0x54 +#define D4CCIPR_REG 0x58 + +/** @brief RCC_BDCR register offset */ +#define BDCR_REG 0x70 + +/** @brief Device domain clocks selection helpers (RM0477.pdf) */ + +/* TODO to be completed */ + +/** D1CCIPR devices */ +#define FMC_SEL(val) STM32_CLOCK(val, 3, 0, D1CCIPR_REG) +#define SDMMC_SEL(val) STM32_CLOCK(val, 1, 2, D1CCIPR_REG) +#define XSPI1_SEL(val) STM32_CLOCK(val, 3, 4, D1CCIPR_REG) +#define XSPI2_SEL(val) STM32_CLOCK(val, 3, 6, D1CCIPR_REG) +#define ADC_SEL(val) STM32_CLOCK(val, 3, 24, D1CCIPR_REG) +#define CKPER_SEL(val) STM32_CLOCK(val, 3, 28, D1CCIPR_REG) + +/** D2CCIPR devices */ +#define USART234578_SEL(val) STM32_CLOCK(val, 7, 0, D2CCIPR_REG) +#define SPI23_SEL(val) STM32_CLOCK(val, 7, 4, D2CCIPR_REG) +#define I2C23_SEL(val) STM32_CLOCK(val, 3, 8, D2CCIPR_REG) +#define I2C1_SEL(val) STM32_CLOCK(val, 3, 12, D2CCIPR_REG) +#define I3C1_SEL(val) STM32_CLOCK(val, 3, 12, D2CCIPR_REG) +#define LPTIM1_SEL(val) STM32_CLOCK(val, 7, 16, D2CCIPR_REG) +#define FDCAN_SEL(val) STM32_CLOCK(val, 3, 22, D2CCIPR_REG) + +/** D3CCIPR devices */ +#define USART1_SEL(val) STM32_CLOCK(val, 7, 0, D3CCIPR_REG) +#define SPI45_SEL(val) STM32_CLOCK(val, 7, 4, D3CCIPR_REG) +#define SPI1_SEL(val) STM32_CLOCK(val, 7, 8, D3CCIPR_REG) +#define SAI1_SEL(val) STM32_CLOCK(val, 7, 16, D3CCIPR_REG) +#define SAI2_SEL(val) STM32_CLOCK(val, 7, 20, D3CCIPR_REG) + +/** D4CCIPR devices */ +#define LPUART1_SEL(val) STM32_CLOCK(val, 7, 0, D4CCIPR_REG) +#define SPI6_SEL(val) STM32_CLOCK(val, 7, 4, D4CCIPR_REG) +#define LPTIM23_SEL(val) STM32_CLOCK(val, 7, 8, D4CCIPR_REG) +#define LPTIM45_SEL(val) STM32_CLOCK(val, 7, 12, D4CCIPR_REG) + +/** BDCR devices */ +#define RTC_SEL(val) STM32_CLOCK(val, 3, 8, BDCR_REG) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_CLOCK_STM32H7RS_CLOCK_H_ */ diff --git a/include/zephyr/dt-bindings/dma/dma_smartbond.h b/include/zephyr/dt-bindings/dma/dma_smartbond.h new file mode 100644 index 0000000000000..4240801c9756a --- /dev/null +++ b/include/zephyr/dt-bindings/dma/dma_smartbond.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef DMA_SMARTBOND_H_ +#define DMA_SMARTBOND_H_ + +/** + * @brief Vendror-specific DMA peripheral triggering sources. + * + * A valid triggering source should be provided when DMA + * is configured for peripheral to peripheral or memory to peripheral + * transactions. + */ +#define DMA_SMARTBOND_TRIG_MUX_SPI 0x0 +#define DMA_SMARTBOND_TRIG_MUX_SPI2 0x1 +#define DMA_SMARTBOND_TRIG_MUX_UART 0x2 +#define DMA_SMARTBOND_TRIG_MUX_UART2 0x3 +#define DMA_SMARTBOND_TRIG_MUX_I2C 0x4 +#define DMA_SMARTBOND_TRIG_MUX_I2C2 0x5 +#define DMA_SMARTBOND_TRIG_MUX_USB 0x6 +#define DMA_SMARTBOND_TRIG_MUX_UART3 0x7 +#define DMA_SMARTBOND_TRIG_MUX_PCM 0x8 +#define DMA_SMARTBOND_TRIG_MUX_SRC 0x9 +#define DMA_SMARTBOND_TRIG_MUX_GPADC 0xC +#define DMA_SMARTBOND_TRIG_MUX_SDADC 0xD +#define DMA_SMARTBOND_TRIG_MUX_NONE 0xF + +#endif /* DMA_SMARTBOND_H_ */ diff --git a/include/zephyr/dt-bindings/dma/stm32_dma.h b/include/zephyr/dt-bindings/dma/stm32_dma.h index 3021231c7bb60..d61f6dfa4786d 100644 --- a/include/zephyr/dt-bindings/dma/stm32_dma.h +++ b/include/zephyr/dt-bindings/dma/stm32_dma.h @@ -64,6 +64,8 @@ #define STM32_DMA_PERIPH_TX (STM32_DMA_MEMORY_TO_PERIPH | STM32_DMA_MEM_INC) #define STM32_DMA_PERIPH_RX (STM32_DMA_PERIPH_TO_MEMORY | STM32_DMA_MEM_INC) +#define STM32_DMA_16BITS (STM32_DMA_PERIPH_16BITS | STM32_DMA_MEM_16BITS) + /** @} */ #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_STM32_DMA_H_ */ diff --git a/include/zephyr/dt-bindings/ethernet/nxp_enet.h b/include/zephyr/dt-bindings/ethernet/nxp_enet.h index e084825da4c75..0e307c9ebfc6f 100644 --- a/include/zephyr/dt-bindings/ethernet/nxp_enet.h +++ b/include/zephyr/dt-bindings/ethernet/nxp_enet.h @@ -1,5 +1,5 @@ /* - * Copyright 2023 NXP + * Copyright 2023-2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -9,6 +9,7 @@ #define NXP_ENET_MII_MODE 0 #define NXP_ENET_RMII_MODE 1 +#define NXP_ENET_RGMII_MODE 2 #define NXP_ENET_INVALID_MII_MODE 100 #endif /* ZEPHYR_INCLUDE_DT_BINDINGS_NXP_ENET_H_ */ diff --git a/include/zephyr/dt-bindings/flash_controller/xspi.h b/include/zephyr/dt-bindings/flash_controller/xspi.h new file mode 100644 index 0000000000000..3e0610e80905d --- /dev/null +++ b/include/zephyr/dt-bindings/flash_controller/xspi.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_XSPI_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_XSPI_H_ + +/** + * @name XSPI definition for the xSPI peripherals + * Note that + * SPI mode inpossible in STR transfer rate only + */ + +/* XSPI mode operating on 1 line, 2 lines, 4 lines or 8 lines */ +/* 1 Cmd Line, 1 Address Line and 1 Data Line */ +#define XSPI_SPI_MODE 1 +/* 2 Cmd Lines, 2 Address Lines and 2 Data Lines */ +#define XSPI_DUAL_MODE 2 +/* 4 Cmd Lines, 4 Address Lines and 4 Data Lines */ +#define XSPI_QUAD_MODE 4 +/* 8 Cmd Lines, 8 Address Lines and 8 Data Lines */ +#define XSPI_OCTO_MODE 8 + +/* XSPI mode operating on Single or Double Transfer Rate */ +/* Single Transfer Rate */ +#define XSPI_STR_TRANSFER 1 +/* Double Transfer Rate */ +#define XSPI_DTR_TRANSFER 2 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_XSPI_H_ */ diff --git a/include/zephyr/dt-bindings/gpio/adi-max32-gpio.h b/include/zephyr/dt-bindings/gpio/adi-max32-gpio.h new file mode 100644 index 0000000000000..bcc50cee8d4dd --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/adi-max32-gpio.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_MAX32_GPIO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_MAX32_GPIO_H_ + +/** + * @brief MAX32-specific GPIO Flags + * @defgroup gpio_interface_max32 MAX32-specific GPIO Flags + * @ingroup gpio_interface + * @{ + */ + +/** + * @name MAX32 GPIO drive flags + * @brief MAX32 GPIO drive flags + * + * The drive flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as + * follows: + * + * - Bit 8: GPIO Supply Voltage Select + * Selects the voltage rail used for the pin. + * 0: VDDIO + * 1: VDDIOH + * + * - Bit 9: GPIO Drive Strength Select, + * MAX32_GPIO_DRV_STRENGTH_0 = 1mA + * MAX32_GPIO_DRV_STRENGTH_1 = 2mA + * MAX32_GPIO_DRV_STRENGTH_2 = 4mA + * MAX32_GPIO_DRV_STRENGTH_3 = 8mA + * + * - Bit 10: Weak pull up selection, Weak Pullup to VDDIO (1MOhm) + * 0: Disable + * 1: Enable + * + * - Bit 11: Weak pull down selection, Weak Pulldown to VDDIOH (1MOhm) + * 0: Disable + * 1: Enable + * @{ + */ + +/** GPIO Voltage Select */ +#define MAX32_GPIO_VSEL_POS (8U) +#define MAX32_GPIO_VSEL_MASK (0x01U << MAX32_GPIO_VSEL_POS) +#define MAX32_GPIO_VSEL_VDDIO (0U << MAX32_GPIO_VSEL_POS) +#define MAX32_GPIO_VSEL_VDDIOH (1U << MAX32_GPIO_VSEL_POS) + +/** GPIO Drive Strenght Select */ +#define MAX32_GPIO_DRV_STRENGTH_POS (9U) +#define MAX32_GPIO_DRV_STRENGTH_MASK (0x03U << MAX32_GPIO_DRV_STRENGTH_POS) +#define MAX32_GPIO_DRV_STRENGTH_0 (0U << MAX32_GPIO_DRV_STRENGTH_POS) +#define MAX32_GPIO_DRV_STRENGTH_1 (1U << MAX32_GPIO_DRV_STRENGTH_POS) +#define MAX32_GPIO_DRV_STRENGTH_2 (2U << MAX32_GPIO_DRV_STRENGTH_POS) +#define MAX32_GPIO_DRV_STRENGTH_3 (3U << MAX32_GPIO_DRV_STRENGTH_POS) + +/** GPIO bias weak pull up selection, to VDDIO (1MOhm) */ +#define MAX32_GPIO_WEAK_PULL_UP_POS (10U) +#define MAX32_GPIO_WEAK_PULL_UP (1U << MAX32_GPIO_WEAK_PULL_UP_POS) +/** GPIO bias weak pull down selection, to VDDIOH (1MOhm) */ +#define MAX32_GPIO_WEAK_PULL_DOWN_POS (11U) +#define MAX32_GPIO_WEAK_PULL_DOWN (1U << MAX32_GPIO_WEAK_PULL_DOWN_POS) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_MAX32_GPIO_H_ */ diff --git a/include/zephyr/dt-bindings/gpio/adi-sdp-120.h b/include/zephyr/dt-bindings/gpio/adi-sdp-120.h new file mode 100644 index 0000000000000..6188ce8c00447 --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/adi-sdp-120.h @@ -0,0 +1,87 @@ +/** + * Copyright (c) 2024 Analog Devices Inc. + * Copyright (c) 2024 Baylibre, SAS + * + * SPDX-License-Identifier: Apache-2.0 + * + * @file + * @brief SDP-120 GPIO index definitions + * + * Defines meant to be used in conjunction with the "adi,sdp-120" + * ADI SDP-120 mapping. + * + * Example usage: + * + * @code{.dts} + * &spi1 { + * cs-gpios = <&sdp_120 SDP_120_SPI_SS_N GPIO_ACTIVE_LOW>; + * + * example_device: example-dev@0 { + * compatible = "vnd,spi-device"; + * reg = <0>; + * }; + * }; + * @endcode + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_SDP_120_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_SDP_120_H_ + +/* GPIO */ + +/** + * @brief IO[n] signal on a SDP-120 GPIO nexus node following + */ + +#define SDP_120_IO(n) (n-1) + +/* SPI */ +#define SDP_120_SPI_D2 SDP_120_IO(33) /* SPI_D2 */ +#define SDP_120_SPI_D3 SDP_120_IO(34) /* SPI_D3 */ +#define SDP_120_SERIAL_INT SDP_120_IO(35) /* SERIAL_INT */ +#define SDP_120_SPI_SEL_B_N SDP_120_IO(37) /* SPI_SEL_B_N */ +#define SDP_120_SPI_SEL_C_N SDP_120_IO(38) /* SPI_SEL_C_N */ +#define SDP_120_SPI_SS_N SDP_120_IO(39) /* SPI_SS_N */ + +/* GPIO */ +#define SDP_120_GPIO0 SDP_120_IO(43) /* GPIO0 */ +#define SDP_120_GPIO2 SDP_120_IO(44) /* GPIO2 */ +#define SDP_120_GPIO4 SDP_120_IO(45) /* GPIO4 */ +#define SDP_120_GPIO6 SDP_120_IO(47) /* GPIO6 */ + +/* TMR */ +#define SDP_120_TMR_A SDP_120_IO(48) /* TMR_A */ + +/* USART */ +#define SDP_120_UART_RX SDP_120_IO(59) /* UART2_RX */ +#define SDP_120_UART_TX SDP_120_IO(62) /* UART2_TX */ + +/* TMR */ +#define SDP_120_TMR_D SDP_120_IO(72) /* TMR_D */ +#define SDP_120_TMR_B SDP_120_IO(73) /* TMR_B */ + +/* GPIO */ +#define SDP_120_GPIO7 SDP_120_IO(74) /* GPIO7 */ +#define SDP_120_GPIO5 SDP_120_IO(76) /* GPIO5 */ +#define SDP_120_GPIO3 SDP_120_IO(77) /* GPIO3 */ +#define SDP_120_GPIO1 SDP_120_IO(78) /* GPIO1 */ + +/* I2C */ +#define SDP_120_SCL_0 SDP_120_IO(79) /* SCL_0 */ +#define SDP_120_SDA_0 SDP_120_IO(80) /* SDA_0 */ + +/* SPI */ +#define SDP_120_SPI_CLK SDP_120_IO(82) /* SPI_CLK */ +#define SDP_120_SPI_MISO SDP_120_IO(83) /* SPI_MISO */ +#define SDP_120_SPI_MOSI SDP_120_IO(84) /* SPI_MOSI */ +#define SDP_120_SPI_SEL_A_N SDP_120_IO(85) /* SPI_SEL_A_N */ + +/* SPORT - no driver yet */ +#define SDP_120_SPI_SPORT_TSCLK SDP_120_IO(87) /* SPORT_TSCLK */ +#define SDP_120_SPI_SPORT_DT0 SDP_120_IO(88) /* SPORT_DT0 */ +#define SDP_120_SPI_SPORT_TFS SDP_120_IO(89) /* SPORT_TFS */ +#define SDP_120_SPI_SPORT_RFS SDP_120_IO(90) /* SPORT_RFS */ +#define SDP_120_SPI_SPORT_DR0 SDP_120_IO(91) /* SPORT_DR0 */ +#define SDP_120_SPI_SPORT_RSCLK SDP_120_IO(92) /* SPORT_RSCLK */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_ADI_SDP_120_H_ */ diff --git a/include/zephyr/dt-bindings/gpio/gpio.h b/include/zephyr/dt-bindings/gpio/gpio.h index 6e8631d7d6d3b..d485e609f12ac 100644 --- a/include/zephyr/dt-bindings/gpio/gpio.h +++ b/include/zephyr/dt-bindings/gpio/gpio.h @@ -79,11 +79,12 @@ /** @} */ -/* Note: Bits 15 downto 8 are reserved for SoC specific flags. */ - -/** Configures GPIO interrupt to wakeup the system from low power mode. +/** + * Configures GPIO interrupt to wakeup the system from low power mode. */ -#define GPIO_INT_WAKEUP (1u << 28) +#define GPIO_INT_WAKEUP (1 << 6) + +/* Note: Bits 15 downto 8 are reserved for SoC specific flags. */ /** * @} diff --git a/include/zephyr/dt-bindings/gpio/stm32-gpio.h b/include/zephyr/dt-bindings/gpio/stm32-gpio.h new file mode 100644 index 0000000000000..f9a3a4b60af6c --- /dev/null +++ b/include/zephyr/dt-bindings/gpio/stm32-gpio.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_STM32_GPIO_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_STM32_GPIO_H_ + +/** + * @brief STM32 GPIO specific flags + * + * The driver flags are encoded in the 8 upper bits of @ref gpio_dt_flags_t as + * follows: + * + * - Bit 8: Configure a GPIO pin to power on the system after Poweroff. + * + * @ingroup gpio_interface + * @{ + */ + +/** + * Configures a GPIO pin to power on the system after Poweroff. + * This flag is reserved to GPIO pins that are associated with wake-up pins + * in STM32 PWR devicetree node, through the property "wkup-gpios". + */ +#define STM32_GPIO_WKUP (1 << 8) + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_GPIO_STM32_GPIO_H_ */ diff --git a/include/zephyr/dt-bindings/interrupt-controller/esp-esp32c6-intmux.h b/include/zephyr/dt-bindings/interrupt-controller/esp-esp32c6-intmux.h new file mode 100644 index 0000000000000..644d8cfb54f20 --- /dev/null +++ b/include/zephyr/dt-bindings/interrupt-controller/esp-esp32c6-intmux.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_ESP32C6_INTMUX_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_ESP32C6_INTMUX_H_ + +#define WIFI_MAC_INTR_SOURCE 0 /* interrupt of WiFi MAC, level*/ +#define WIFI_MAC_NMI_SOURCE 1 /* interrupt of WiFi MAC, NMI*/ +#define WIFI_PWR_INTR_SOURCE 2 +#define WIFI_BB_INTR_SOURCE 3 /* interrupt of WiFi BB, level*/ +#define BT_MAC_INTR_SOURCE 4 /* will be cancelled*/ +#define BT_BB_INTR_SOURCE 5 /* interrupt of BT BB, level*/ +#define BT_BB_NMI_SOURCE 6 /* interrupt of BT BB, NMI*/ +#define LP_TIMER_INTR_SOURCE 7 +#define COEX_INTR_SOURCE 8 +#define BLE_TIMER_INTR_SOURCE 9 +#define BLE_SEC_INTR_SOURCE 10 +#define I2C_MASTER_SOURCE 11 /* interrupt of I2C Master, level*/ +#define ZB_MAC_SOURCE 12 +#define PMU_INTR_SOURCE 13 +#define EFUSE_INTR_SOURCE 14 /* interrupt of efuse, level, not likely to use*/ +#define LP_RTC_TIMER_INTR_SOURCE 15 +#define LP_UART_INTR_SOURCE 16 +#define LP_I2C_INTR_SOURCE 17 +#define LP_WDT_INTR_SOURCE 18 +#define LP_PERI_TIMEOUT_INTR_SOURCE 19 +#define LP_APM_M0_INTR_SOURCE 20 +#define LP_APM_M1_INTR_SOURCE 21 +#define FROM_CPU_INTR0_SOURCE 22 /* interrupt0 generated from a CPU, level*/ +#define FROM_CPU_INTR1_SOURCE 23 /* interrupt1 generated from a CPU, level*/ +#define FROM_CPU_INTR2_SOURCE 24 /* interrupt2 generated from a CPU, level*/ +#define FROM_CPU_INTR3_SOURCE 25 /* interrupt3 generated from a CPU, level*/ +#define ASSIST_DEBUG_INTR_SOURCE 26 /* interrupt of Assist debug module, LEVEL*/ +#define TRACE_INTR_SOURCE 27 +#define CACHE_INTR_SOURCE 28 +#define CPU_PERI_TIMEOUT_INTR_SOURCE 29 +#define GPIO_INTR_SOURCE 30 /* interrupt of GPIO, level*/ +#define GPIO_NMI_SOURCE 31 /* interrupt of GPIO, NMI*/ +#define PAU_INTR_SOURCE 32 +#define HP_PERI_TIMEOUT_INTR_SOURCE 33 +#define MODEM_PERI_TIMEOUT_INTR_SOURCE 34 +#define HP_APM_M0_INTR_SOURCE 35 +#define HP_APM_M1_INTR_SOURCE 36 +#define HP_APM_M2_INTR_SOURCE 37 +#define HP_APM_M3_INTR_SOURCE 38 +#define LP_APM0_INTR_SOURCE 39 +#define MSPI_INTR_SOURCE 40 +#define I2S1_INTR_SOURCE 41 /* interrupt of I2S1, level*/ +#define UHCI0_INTR_SOURCE 42 /* interrupt of UHCI0, level*/ +#define UART0_INTR_SOURCE 43 /* interrupt of UART0, level*/ +#define UART1_INTR_SOURCE 44 /* interrupt of UART1, level*/ +#define LEDC_INTR_SOURCE 45 /* interrupt of LED PWM, level*/ +#define TWAI0_INTR_SOURCE 46 /* interrupt of can0, level*/ +#define TWAI1_INTR_SOURCE 47 /* interrupt of can1, level*/ +#define USB_SERIAL_JTAG_INTR_SOURCE 48 /* interrupt of USB, level*/ +#define RMT_INTR_SOURCE 49 /* interrupt of remote controller, level*/ +#define I2C_EXT0_INTR_SOURCE 50 /* interrupt of I2C controller1, level*/ +#define TG0_T0_LEVEL_INTR_SOURCE 51 /* interrupt of TIMER_GROUP0, TIMER0, level*/ +#define TG0_T1_LEVEL_INTR_SOURCE 52 /* interrupt of TIMER_GROUP0, TIMER1, level*/ +#define TG0_WDT_LEVEL_INTR_SOURCE 53 /* interrupt of TIMER_GROUP0, WATCH DOG, level*/ +#define TG1_T0_LEVEL_INTR_SOURCE 54 /* interrupt of TIMER_GROUP1, TIMER0, level*/ +#define TG1_T1_LEVEL_INTR_SOURCE 55 /* interrupt of TIMER_GROUP1, TIMER1, level*/ +#define TG1_WDT_LEVEL_INTR_SOURCE 56 /* interrupt of TIMER_GROUP1, WATCHDOG, level*/ +#define SYSTIMER_TARGET0_EDGE_INTR_SOURCE 57 /* interrupt of system timer 0, EDGE*/ +#define SYSTIMER_TARGET1_EDGE_INTR_SOURCE 58 /* interrupt of system timer 1, EDGE*/ +#define SYSTIMER_TARGET2_EDGE_INTR_SOURCE 59 /* interrupt of system timer 2, EDGE*/ +#define APB_ADC_INTR_SOURCE 60 /* interrupt of APB ADC, LEVEL*/ +#define MCPWM0_INTR_SOURCE 61 /* interrupt of MCPWM0, LEVEL*/ +#define PCNT_INTR_SOURCE 62 +#define PARL_IO_INTR_SOURCE 63 +#define SLC0_INTR_SOURCE 64 +#define SLC_INTR_SOURCE 65 +#define DMA_IN_CH0_INTR_SOURCE 66 /* interrupt of general DMA IN channel 0, LEVEL*/ +#define DMA_IN_CH1_INTR_SOURCE 67 /* interrupt of general DMA IN channel 1, LEVEL*/ +#define DMA_IN_CH2_INTR_SOURCE 68 /* interrupt of general DMA IN channel 2, LEVEL*/ +#define DMA_OUT_CH0_INTR_SOURCE 69 /* interrupt of general DMA OUT channel 0, LEVEL*/ +#define DMA_OUT_CH1_INTR_SOURCE 70 /* interrupt of general DMA OUT channel 1, LEVEL*/ +#define DMA_OUT_CH2_INTR_SOURCE 71 /* interrupt of general DMA OUT channel 2, LEVEL*/ +#define GSPI2_INTR_SOURCE 72 +#define AES_INTR_SOURCE 73 /* interrupt of AES accelerator, level*/ +#define SHA_INTR_SOURCE 74 /* interrupt of SHA accelerator, level*/ +#define RSA_INTR_SOURCE 75 /* interrupt of RSA accelerator, level*/ +#define ECC_INTR_SOURCE 76 /* interrupt of ECC accelerator, level*/ +#define MAX_INTR_SOURCE 77 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_INTERRUPT_CONTROLLER_ESP32C6_INTMUX_H_ */ diff --git a/include/zephyr/dt-bindings/mipi_dbi/mipi_dbi.h b/include/zephyr/dt-bindings/mipi_dbi/mipi_dbi.h index 6956e044d11ea..25886635f5962 100644 --- a/include/zephyr/dt-bindings/mipi_dbi/mipi_dbi.h +++ b/include/zephyr/dt-bindings/mipi_dbi/mipi_dbi.h @@ -53,6 +53,62 @@ * -'-------------------------------'-------------------------------'- */ #define MIPI_DBI_MODE_SPI_4WIRE 0x2 +/** + * Parallel Bus protocol for MIPI DBI Type A based on Motorola 6800 bus. + * + * -. .--------. .------------------------ + * CS '---' '---' + * + * ------------------------------------------- + * RESX + * + * .-------------------------------- + * D/CX ----------' + * + * + * R/WX ------------------------------------------- + * + * ------------------------------------------- + * E + * + * .--------. .--------------------------. + * D[15:0]/ -| COMMAND|---| DATA | + * D[8:0]/ '--------' '--------------------------' + * D[7:0] + * + * Please refer to the MIPI DBI specification for a detailed cycle diagram. + */ +#define MIPI_DBI_MODE_6800_BUS_16_BIT 0x3 +#define MIPI_DBI_MODE_6800_BUS_9_BIT 0x4 +#define MIPI_DBI_MODE_6800_BUS_8_BIT 0x5 +/** + * Parallel Bus protocol for MIPI DBI Type B based on Intel 8080 bus. + * + * -. .- + * CS '---------------------------------------' + * + * ------------------------------------------- + * RESX + * + * --. .---------------------------- + * D/CX '-----------' + * + * ---. .--------. .---------------------- + * WRX '---' '---' + * + * ------------------------------------------- + * RDX + * + * .--------. .--------------------------. + * D[15:0]/ ---| COMMAND|---| DATA | + * D[8:0]/ '--------' '--------------------------' + * D[7:0] + * + * Please refer to the MIPI DBI specification for a detailed cycle diagram. + */ +#define MIPI_DBI_MODE_8080_BUS_16_BIT 0x6 +#define MIPI_DBI_MODE_8080_BUS_9_BIT 0x7 +#define MIPI_DBI_MODE_8080_BUS_8_BIT 0x8 /** * @} diff --git a/include/zephyr/dt-bindings/misc/nordic-domain-id-nrf54h20.h b/include/zephyr/dt-bindings/misc/nordic-domain-id-nrf54h20.h new file mode 100644 index 0000000000000..a5fd23fd34b23 --- /dev/null +++ b/include/zephyr/dt-bindings/misc/nordic-domain-id-nrf54h20.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_DOMAIN_ID_NRF54H20_H_ + +#define NRF_DOMAIN_ID_APPLICATION 2 +#define NRF_DOMAIN_ID_RADIOCORE 3 +#define NRF_DOMAIN_ID_GLOBALFAST 12 +#define NRF_DOMAIN_ID_GLOBALSLOW 13 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_DOMAIN_ID_NRF54H20_H_ */ diff --git a/include/zephyr/dt-bindings/misc/nordic-owner-id-nrf54h20.h b/include/zephyr/dt-bindings/misc/nordic-owner-id-nrf54h20.h new file mode 100644 index 0000000000000..080b4e048e22a --- /dev/null +++ b/include/zephyr/dt-bindings/misc/nordic-owner-id-nrf54h20.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_OWNER_ID_NRF54H20_H_ + +#define NRF_OWNER_ID_NONE 0 +#define NRF_OWNER_ID_APPLICATION 2 +#define NRF_OWNER_ID_RADIOCORE 3 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_MISC_NORDIC_OWNER_ID_NRF54H20_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/esp32c6-gpio-sigmap.h b/include/zephyr/dt-bindings/pinctrl/esp32c6-gpio-sigmap.h new file mode 100644 index 0000000000000..bba370d247d73 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/esp32c6-gpio-sigmap.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2023 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP32C6_GPIO_SIGMAP_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP32C6_GPIO_SIGMAP_H_ + +#define ESP_NOSIG ESP_SIG_INVAL + +#define ESP_EXT_ADC_START 0 +#define ESP_LEDC_LS_SIG_OUT0 0 +#define ESP_LEDC_LS_SIG_OUT1 1 +#define ESP_LEDC_LS_SIG_OUT2 2 +#define ESP_LEDC_LS_SIG_OUT3 3 +#define ESP_LEDC_LS_SIG_OUT4 4 +#define ESP_LEDC_LS_SIG_OUT5 5 +#define ESP_U0RXD_IN 6 +#define ESP_U0TXD_OUT 6 +#define ESP_U0CTS_IN 7 +#define ESP_U0RTS_OUT 7 +#define ESP_U0DSR_IN 8 +#define ESP_U0DTR_OUT 8 +#define ESP_U1RXD_IN 9 +#define ESP_U1TXD_OUT 9 +#define ESP_U1CTS_IN 10 +#define ESP_U1RTS_OUT 10 +#define ESP_U1DSR_IN 11 +#define ESP_U1DTR_OUT 11 +#define ESP_I2S_MCLK_IN 12 +#define ESP_I2S_MCLK_OUT 12 +#define ESP_I2SO_BCK_IN 13 +#define ESP_I2SO_BCK_OUT 13 +#define ESP_I2SO_WS_IN 14 +#define ESP_I2SO_WS_OUT 14 +#define ESP_I2SI_SD_IN 15 +#define ESP_I2SO_SD_OUT 15 +#define ESP_I2SI_BCK_IN 16 +#define ESP_I2SI_BCK_OUT 16 +#define ESP_I2SI_WS_IN 17 +#define ESP_I2SI_WS_OUT 17 +#define ESP_I2SO_SD1_OUT 18 +#define ESP_USB_JTAG_TDO_BRIDGE 19 +#define ESP_USB_JTAG_TRST 19 +#define ESP_CPU_TESTBUS0 20 +#define ESP_CPU_TESTBUS1 21 +#define ESP_CPU_TESTBUS2 22 +#define ESP_CPU_TESTBUS3 23 +#define ESP_CPU_TESTBUS4 24 +#define ESP_CPU_TESTBUS5 25 +#define ESP_CPU_TESTBUS6 26 +#define ESP_CPU_TESTBUS7 27 +#define ESP_CPU_GPIO_IN0 28 +#define ESP_CPU_GPIO_OUT0 28 +#define ESP_CPU_GPIO_IN1 29 +#define ESP_CPU_GPIO_OUT1 29 +#define ESP_CPU_GPIO_IN2 30 +#define ESP_CPU_GPIO_OUT2 30 +#define ESP_CPU_GPIO_IN3 31 +#define ESP_CPU_GPIO_OUT3 31 +#define ESP_CPU_GPIO_IN4 32 +#define ESP_CPU_GPIO_OUT4 32 +#define ESP_CPU_GPIO_IN5 33 +#define ESP_CPU_GPIO_OUT5 33 +#define ESP_CPU_GPIO_IN6 34 +#define ESP_CPU_GPIO_OUT6 34 +#define ESP_CPU_GPIO_IN7 35 +#define ESP_CPU_GPIO_OUT7 35 +#define ESP_USB_JTAG_TCK 36 +#define ESP_USB_JTAG_TMS 37 +#define ESP_USB_JTAG_TDI 38 +#define ESP_USB_JTAG_TDO 39 +#define ESP_USB_EXTPHY_VP 40 +#define ESP_USB_EXTPHY_OEN 40 +#define ESP_USB_EXTPHY_VM 41 +#define ESP_USB_EXTPHY_SPEED 41 +#define ESP_USB_EXTPHY_RCV 42 +#define ESP_USB_EXTPHY_VPO 42 +#define ESP_USB_EXTPHY_VMO 43 +#define ESP_USB_EXTPHY_SUSPND 44 +#define ESP_I2CEXT0_SCL_IN 45 +#define ESP_I2CEXT0_SCL_OUT 45 +#define ESP_I2CEXT0_SDA_IN 46 +#define ESP_I2CEXT0_SDA_OUT 46 +#define ESP_PARL_RX_DATA0 47 +#define ESP_PARL_TX_DATA0 47 +#define ESP_PARL_RX_DATA1 48 +#define ESP_PARL_TX_DATA1 48 +#define ESP_PARL_RX_DATA2 49 +#define ESP_PARL_TX_DATA2 49 +#define ESP_PARL_RX_DATA3 50 +#define ESP_PARL_TX_DATA3 50 +#define ESP_PARL_RX_DATA4 51 +#define ESP_PARL_TX_DATA4 51 +#define ESP_PARL_RX_DATA5 52 +#define ESP_PARL_TX_DATA5 52 +#define ESP_PARL_RX_DATA6 53 +#define ESP_PARL_TX_DATA6 53 +#define ESP_PARL_RX_DATA7 54 +#define ESP_PARL_TX_DATA7 54 +#define ESP_PARL_RX_DATA8 55 +#define ESP_PARL_TX_DATA8 55 +#define ESP_PARL_RX_DATA9 56 +#define ESP_PARL_TX_DATA9 56 +#define ESP_PARL_RX_DATA10 57 +#define ESP_PARL_TX_DATA10 57 +#define ESP_PARL_RX_DATA11 58 +#define ESP_PARL_TX_DATA11 58 +#define ESP_PARL_RX_DATA12 59 +#define ESP_PARL_TX_DATA12 59 +#define ESP_PARL_RX_DATA13 60 +#define ESP_PARL_TX_DATA13 60 +#define ESP_PARL_RX_DATA14 61 +#define ESP_PARL_TX_DATA14 61 +#define ESP_PARL_RX_DATA15 62 +#define ESP_PARL_TX_DATA15 62 +#define ESP_FSPICLK_IN 63 +#define ESP_FSPICLK_OUT 63 +#define ESP_FSPIQ_IN 64 +#define ESP_FSPIQ_OUT 64 +#define ESP_FSPID_IN 65 +#define ESP_FSPID_OUT 65 +#define ESP_FSPIHD_IN 66 +#define ESP_FSPIHD_OUT 66 +#define ESP_FSPIWP_IN 67 +#define ESP_FSPIWP_OUT 67 +#define ESP_FSPICS0_IN 68 +#define ESP_FSPICS0_OUT 68 +#define ESP_PARL_RX_CLK_IN 69 +#define ESP_SDIO_TOHOST_INT_OUT 69 +#define ESP_PARL_TX_CLK_IN 70 +#define ESP_PARL_TX_CLK_OUT 70 +#define ESP_RMT_SIG_IN0 71 +#define ESP_RMT_SIG_OUT0 71 +#define ESP_MODEM_DIAG0 71 +#define ESP_RMT_SIG_IN1 72 +#define ESP_RMT_SIG_OUT1 72 +#define ESP_MODEM_DIAG1 72 +#define ESP_TWAI0_RX 73 +#define ESP_TWAI0_TX 73 +#define ESP_MODEM_DIAG2 73 +#define ESP_TWAI0_BUS_OFF_ON 74 +#define ESP_MODEM_DIAG3 74 +#define ESP_TWAI0_CLKOUT 75 +#define ESP_MODEM_DIAG4 75 +#define ESP_TWAI0_STANDBY 76 +#define ESP_MODEM_DIAG5 76 +#define ESP_TWAI1_RX 77 +#define ESP_TWAI1_TX 77 +#define ESP_MODEM_DIAG6 77 +#define ESP_TWAI1_BUS_OFF_ON 78 +#define ESP_MODEM_DIAG7 78 +#define ESP_TWAI1_CLKOUT 79 +#define ESP_MODEM_DIAG8 79 +#define ESP_TWAI1_STANDBY 80 +#define ESP_MODEM_DIAG9 80 +#define ESP_EXTERN_PRIORITY_I 81 +#define ESP_EXTERN_PRIORITY_O 81 +#define ESP_EXTERN_ACTIVE_I 82 +#define ESP_EXTERN_ACTIVE_O 82 +#define ESP_GPIO_SD0_OUT 83 +#define ESP_GPIO_SD1_OUT 84 +#define ESP_GPIO_SD2_OUT 85 +#define ESP_GPIO_SD3_OUT 86 +#define ESP_PWM0_SYNC0_IN 87 +#define ESP_PWM0_OUT0A 87 +#define ESP_MODEM_DIAG10 87 +#define ESP_PWM0_SYNC1_IN 88 +#define ESP_PWM0_OUT0B 88 +#define ESP_MODEM_DIAG11 88 +#define ESP_PWM0_SYNC2_IN 89 +#define ESP_PWM0_OUT1A 89 +#define ESP_MODEM_DIAG12 89 +#define ESP_PWM0_F0_IN 90 +#define ESP_PWM0_OUT1B 90 +#define ESP_MODEM_DIAG13 90 +#define ESP_PWM0_F1_IN 91 +#define ESP_PWM0_OUT2A 91 +#define ESP_MODEM_DIAG14 91 +#define ESP_PWM0_F2_IN 92 +#define ESP_PWM0_OUT2B 92 +#define ESP_MODEM_DIAG15 92 +#define ESP_PWM0_CAP0_IN 93 +#define ESP_ANT_SEL0 93 +#define ESP_PWM0_CAP1_IN 94 +#define ESP_ANT_SEL1 94 +#define ESP_PWM0_CAP2_IN 95 +#define ESP_ANT_SEL2 95 +#define ESP_ANT_SEL3 96 +#define ESP_SIG_IN_FUNC_97 97 +#define ESP_SIG_IN_FUNC97 97 +#define ESP_SIG_IN_FUNC_98 98 +#define ESP_SIG_IN_FUNC98 98 +#define ESP_SIG_IN_FUNC_99 99 +#define ESP_SIG_IN_FUNC99 99 +#define ESP_SIG_IN_FUNC_100 100 +#define ESP_SIG_IN_FUNC100 100 +#define ESP_PCNT_SIG_CH0_IN0 101 +#define ESP_FSPICS1_OUT 101 +#define ESP_MODEM_DIAG16 101 +#define ESP_PCNT_SIG_CH1_IN0 102 +#define ESP_FSPICS2_OUT 102 +#define ESP_MODEM_DIAG17 102 +#define ESP_PCNT_CTRL_CH0_IN0 103 +#define ESP_FSPICS3_OUT 103 +#define ESP_MODEM_DIAG18 103 +#define ESP_PCNT_CTRL_CH1_IN0 104 +#define ESP_FSPICS4_OUT 104 +#define ESP_MODEM_DIAG19 104 +#define ESP_PCNT_SIG_CH0_IN1 105 +#define ESP_FSPICS5_OUT 105 +#define ESP_MODEM_DIAG20 105 +#define ESP_PCNT_SIG_CH1_IN1 106 +#define ESP_MODEM_DIAG21 106 +#define ESP_PCNT_CTRL_CH0_IN1 107 +#define ESP_MODEM_DIAG22 107 +#define ESP_PCNT_CTRL_CH1_IN1 108 +#define ESP_MODEM_DIAG23 108 +#define ESP_PCNT_SIG_CH0_IN2 109 +#define ESP_MODEM_DIAG24 109 +#define ESP_PCNT_SIG_CH1_IN2 110 +#define ESP_MODEM_DIAG25 110 +#define ESP_PCNT_CTRL_CH0_IN2 111 +#define ESP_MODEM_DIAG26 111 +#define ESP_PCNT_CTRL_CH1_IN2 112 +#define ESP_MODEM_DIAG27 112 +#define ESP_PCNT_SIG_CH0_IN3 113 +#define ESP_MODEM_DIAG28 113 +#define ESP_PCNT_SIG_CH1_IN3 114 +#define ESP_SPICLK_OUT 114 +#define ESP_MODEM_DIAG29 114 +#define ESP_PCNT_CTRL_CH0_IN3 115 +#define ESP_SPICS0_OUT 115 +#define ESP_MODEM_DIAG30 115 +#define ESP_PCNT_CTRL_CH1_IN3 116 +#define ESP_SPICS1_OUT 116 +#define ESP_MODEM_DIAG31 116 +#define ESP_GPIO_EVENT_MATRIX_IN0 117 +#define ESP_GPIO_TASK_MATRIX_OUT0 117 +#define ESP_GPIO_EVENT_MATRIX_IN1 118 +#define ESP_GPIO_TASK_MATRIX_OUT1 118 +#define ESP_GPIO_EVENT_MATRIX_IN2 119 +#define ESP_GPIO_TASK_MATRIX_OUT2 119 +#define ESP_GPIO_EVENT_MATRIX_IN3 120 +#define ESP_GPIO_TASK_MATRIX_OUT3 120 +#define ESP_SPIQ_IN 121 +#define ESP_SPIQ_OUT 121 +#define ESP_SPID_IN 122 +#define ESP_SPID_OUT 122 +#define ESP_SPIHD_IN 123 +#define ESP_SPIHD_OUT 123 +#define ESP_SPIWP_IN 124 +#define ESP_SPIWP_OUT 124 +#define ESP_CLK_OUT_OUT1 125 +#define ESP_CLK_OUT_OUT2 126 +#define ESP_CLK_OUT_OUT3 127 +#define ESP_SIG_GPIO_OUT 128 +#define ESP_GPIO_MAP_DATE 0x2201120 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_ESP32C6_GPIO_SIGMAP_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h new file mode 100644 index 0000000000000..6c80beb59d5a7 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/esp32c6-pinctrl.h @@ -0,0 +1,1984 @@ +/* + * Copyright (c) 2022 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + * + * NOTE: Autogenerated file using esp_genpinctrl.py + */ + +#ifndef INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ +#define INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ + +/* LEDC_CH0 */ +#define LEDC_CH0_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +#define LEDC_CH0_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT0) + +/* LEDC_CH1 */ +#define LEDC_CH1_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +#define LEDC_CH1_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT1) + +/* LEDC_CH2 */ +#define LEDC_CH2_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +#define LEDC_CH2_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT2) + +/* LEDC_CH3 */ +#define LEDC_CH3_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +#define LEDC_CH3_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT3) + +/* LEDC_CH4 */ +#define LEDC_CH4_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +#define LEDC_CH4_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT4) + +/* LEDC_CH5 */ +#define LEDC_CH5_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +#define LEDC_CH5_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_LEDC_LS_SIG_OUT5) + +/* SPIM2_CSEL */ +#define SPIM2_CSEL_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS0_OUT) + +#define SPIM2_CSEL_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS0_OUT) + +/* SPIM2_CSEL1 */ +#define SPIM2_CSEL1_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS1_OUT) + +#define SPIM2_CSEL1_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS1_OUT) + +/* SPIM2_CSEL2 */ +#define SPIM2_CSEL2_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS2_OUT) + +#define SPIM2_CSEL2_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS2_OUT) + +/* SPIM2_CSEL3 */ +#define SPIM2_CSEL3_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS3_OUT) + +#define SPIM2_CSEL3_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS3_OUT) + +/* SPIM2_CSEL4 */ +#define SPIM2_CSEL4_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS4_OUT) + +#define SPIM2_CSEL4_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS4_OUT) + +/* SPIM2_CSEL5 */ +#define SPIM2_CSEL5_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICS5_OUT) + +#define SPIM2_CSEL5_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICS5_OUT) + +/* SPIM2_MISO */ +#define SPIM2_MISO_GPIO0 \ + ESP32_PINMUX(0, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO1 \ + ESP32_PINMUX(1, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO2 \ + ESP32_PINMUX(2, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO3 \ + ESP32_PINMUX(3, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO4 \ + ESP32_PINMUX(4, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO5 \ + ESP32_PINMUX(5, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO6 \ + ESP32_PINMUX(6, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO7 \ + ESP32_PINMUX(7, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO8 \ + ESP32_PINMUX(8, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO9 \ + ESP32_PINMUX(9, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO10 \ + ESP32_PINMUX(10, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO11 \ + ESP32_PINMUX(11, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO12 \ + ESP32_PINMUX(12, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO13 \ + ESP32_PINMUX(13, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO14 \ + ESP32_PINMUX(14, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO15 \ + ESP32_PINMUX(15, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO16 \ + ESP32_PINMUX(16, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO17 \ + ESP32_PINMUX(17, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO18 \ + ESP32_PINMUX(18, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO19 \ + ESP32_PINMUX(19, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO20 \ + ESP32_PINMUX(20, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO21 \ + ESP32_PINMUX(21, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO22 \ + ESP32_PINMUX(22, ESP_FSPIQ_IN, ESP_NOSIG) + +#define SPIM2_MISO_GPIO23 \ + ESP32_PINMUX(23, ESP_FSPIQ_IN, ESP_NOSIG) + +/* SPIM2_MOSI */ +#define SPIM2_MOSI_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPID_OUT) + +#define SPIM2_MOSI_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPID_OUT) + +/* SPIM2_SCLK */ +#define SPIM2_SCLK_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_FSPICLK_OUT) + +#define SPIM2_SCLK_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_FSPICLK_OUT) + +/* UART0_CTS */ +#define UART0_CTS_GPIO0 \ + ESP32_PINMUX(0, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO1 \ + ESP32_PINMUX(1, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO2 \ + ESP32_PINMUX(2, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO3 \ + ESP32_PINMUX(3, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO4 \ + ESP32_PINMUX(4, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO5 \ + ESP32_PINMUX(5, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO6 \ + ESP32_PINMUX(6, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO7 \ + ESP32_PINMUX(7, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO8 \ + ESP32_PINMUX(8, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO9 \ + ESP32_PINMUX(9, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO10 \ + ESP32_PINMUX(10, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO11 \ + ESP32_PINMUX(11, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO12 \ + ESP32_PINMUX(12, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO13 \ + ESP32_PINMUX(13, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO14 \ + ESP32_PINMUX(14, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO15 \ + ESP32_PINMUX(15, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO16 \ + ESP32_PINMUX(16, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO17 \ + ESP32_PINMUX(17, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO18 \ + ESP32_PINMUX(18, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO19 \ + ESP32_PINMUX(19, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO20 \ + ESP32_PINMUX(20, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO21 \ + ESP32_PINMUX(21, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO22 \ + ESP32_PINMUX(22, ESP_U0CTS_IN, ESP_NOSIG) + +#define UART0_CTS_GPIO23 \ + ESP32_PINMUX(23, ESP_U0CTS_IN, ESP_NOSIG) + +/* UART0_DSR */ +#define UART0_DSR_GPIO0 \ + ESP32_PINMUX(0, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO1 \ + ESP32_PINMUX(1, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO2 \ + ESP32_PINMUX(2, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO3 \ + ESP32_PINMUX(3, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO4 \ + ESP32_PINMUX(4, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO5 \ + ESP32_PINMUX(5, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO6 \ + ESP32_PINMUX(6, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO7 \ + ESP32_PINMUX(7, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO8 \ + ESP32_PINMUX(8, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO9 \ + ESP32_PINMUX(9, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO10 \ + ESP32_PINMUX(10, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO11 \ + ESP32_PINMUX(11, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO12 \ + ESP32_PINMUX(12, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO13 \ + ESP32_PINMUX(13, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO14 \ + ESP32_PINMUX(14, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO15 \ + ESP32_PINMUX(15, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO16 \ + ESP32_PINMUX(16, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO17 \ + ESP32_PINMUX(17, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO18 \ + ESP32_PINMUX(18, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO19 \ + ESP32_PINMUX(19, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO20 \ + ESP32_PINMUX(20, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO21 \ + ESP32_PINMUX(21, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO22 \ + ESP32_PINMUX(22, ESP_U0DSR_IN, ESP_NOSIG) + +#define UART0_DSR_GPIO23 \ + ESP32_PINMUX(23, ESP_U0DSR_IN, ESP_NOSIG) + +/* UART0_DTR */ +#define UART0_DTR_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U0DTR_OUT) + +#define UART0_DTR_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U0DTR_OUT) + +/* UART0_RTS */ +#define UART0_RTS_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U0RTS_OUT) + +#define UART0_RTS_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U0RTS_OUT) + +/* UART0_RX */ +#define UART0_RX_GPIO0 \ + ESP32_PINMUX(0, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO1 \ + ESP32_PINMUX(1, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO2 \ + ESP32_PINMUX(2, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO3 \ + ESP32_PINMUX(3, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO4 \ + ESP32_PINMUX(4, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO5 \ + ESP32_PINMUX(5, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO6 \ + ESP32_PINMUX(6, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO7 \ + ESP32_PINMUX(7, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO8 \ + ESP32_PINMUX(8, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO9 \ + ESP32_PINMUX(9, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO10 \ + ESP32_PINMUX(10, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO11 \ + ESP32_PINMUX(11, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO12 \ + ESP32_PINMUX(12, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO13 \ + ESP32_PINMUX(13, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO14 \ + ESP32_PINMUX(14, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO15 \ + ESP32_PINMUX(15, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO16 \ + ESP32_PINMUX(16, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO17 \ + ESP32_PINMUX(17, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO18 \ + ESP32_PINMUX(18, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO19 \ + ESP32_PINMUX(19, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO20 \ + ESP32_PINMUX(20, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO21 \ + ESP32_PINMUX(21, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO22 \ + ESP32_PINMUX(22, ESP_U0RXD_IN, ESP_NOSIG) + +#define UART0_RX_GPIO23 \ + ESP32_PINMUX(23, ESP_U0RXD_IN, ESP_NOSIG) + +/* UART0_TX */ +#define UART0_TX_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U0TXD_OUT) + +#define UART0_TX_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U0TXD_OUT) + +/* UART1_CTS */ +#define UART1_CTS_GPIO0 \ + ESP32_PINMUX(0, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO1 \ + ESP32_PINMUX(1, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO2 \ + ESP32_PINMUX(2, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO3 \ + ESP32_PINMUX(3, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO4 \ + ESP32_PINMUX(4, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO5 \ + ESP32_PINMUX(5, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO6 \ + ESP32_PINMUX(6, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO7 \ + ESP32_PINMUX(7, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO8 \ + ESP32_PINMUX(8, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO9 \ + ESP32_PINMUX(9, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO10 \ + ESP32_PINMUX(10, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO11 \ + ESP32_PINMUX(11, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO12 \ + ESP32_PINMUX(12, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO13 \ + ESP32_PINMUX(13, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO14 \ + ESP32_PINMUX(14, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO15 \ + ESP32_PINMUX(15, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO16 \ + ESP32_PINMUX(16, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO17 \ + ESP32_PINMUX(17, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO18 \ + ESP32_PINMUX(18, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO19 \ + ESP32_PINMUX(19, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO20 \ + ESP32_PINMUX(20, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO21 \ + ESP32_PINMUX(21, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO22 \ + ESP32_PINMUX(22, ESP_U1CTS_IN, ESP_NOSIG) + +#define UART1_CTS_GPIO23 \ + ESP32_PINMUX(23, ESP_U1CTS_IN, ESP_NOSIG) + +/* UART1_DSR */ +#define UART1_DSR_GPIO0 \ + ESP32_PINMUX(0, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO1 \ + ESP32_PINMUX(1, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO2 \ + ESP32_PINMUX(2, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO3 \ + ESP32_PINMUX(3, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO4 \ + ESP32_PINMUX(4, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO5 \ + ESP32_PINMUX(5, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO6 \ + ESP32_PINMUX(6, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO7 \ + ESP32_PINMUX(7, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO8 \ + ESP32_PINMUX(8, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO9 \ + ESP32_PINMUX(9, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO10 \ + ESP32_PINMUX(10, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO11 \ + ESP32_PINMUX(11, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO12 \ + ESP32_PINMUX(12, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO13 \ + ESP32_PINMUX(13, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO14 \ + ESP32_PINMUX(14, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO15 \ + ESP32_PINMUX(15, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO16 \ + ESP32_PINMUX(16, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO17 \ + ESP32_PINMUX(17, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO18 \ + ESP32_PINMUX(18, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO19 \ + ESP32_PINMUX(19, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO20 \ + ESP32_PINMUX(20, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO21 \ + ESP32_PINMUX(21, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO22 \ + ESP32_PINMUX(22, ESP_U1DSR_IN, ESP_NOSIG) + +#define UART1_DSR_GPIO23 \ + ESP32_PINMUX(23, ESP_U1DSR_IN, ESP_NOSIG) + +/* UART1_DTR */ +#define UART1_DTR_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U1DTR_OUT) + +#define UART1_DTR_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U1DTR_OUT) + +/* UART1_RTS */ +#define UART1_RTS_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U1RTS_OUT) + +#define UART1_RTS_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U1RTS_OUT) + +/* UART1_RX */ +#define UART1_RX_GPIO0 \ + ESP32_PINMUX(0, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO1 \ + ESP32_PINMUX(1, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO2 \ + ESP32_PINMUX(2, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO3 \ + ESP32_PINMUX(3, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO4 \ + ESP32_PINMUX(4, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO5 \ + ESP32_PINMUX(5, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO6 \ + ESP32_PINMUX(6, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO7 \ + ESP32_PINMUX(7, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO8 \ + ESP32_PINMUX(8, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO9 \ + ESP32_PINMUX(9, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO10 \ + ESP32_PINMUX(10, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO11 \ + ESP32_PINMUX(11, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO12 \ + ESP32_PINMUX(12, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO13 \ + ESP32_PINMUX(13, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO14 \ + ESP32_PINMUX(14, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO15 \ + ESP32_PINMUX(15, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO16 \ + ESP32_PINMUX(16, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO17 \ + ESP32_PINMUX(17, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO18 \ + ESP32_PINMUX(18, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO19 \ + ESP32_PINMUX(19, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO20 \ + ESP32_PINMUX(20, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO21 \ + ESP32_PINMUX(21, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO22 \ + ESP32_PINMUX(22, ESP_U1RXD_IN, ESP_NOSIG) + +#define UART1_RX_GPIO23 \ + ESP32_PINMUX(23, ESP_U1RXD_IN, ESP_NOSIG) + +/* UART1_TX */ +#define UART1_TX_GPIO0 \ + ESP32_PINMUX(0, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO1 \ + ESP32_PINMUX(1, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO2 \ + ESP32_PINMUX(2, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO3 \ + ESP32_PINMUX(3, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO4 \ + ESP32_PINMUX(4, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO5 \ + ESP32_PINMUX(5, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO6 \ + ESP32_PINMUX(6, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO7 \ + ESP32_PINMUX(7, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO8 \ + ESP32_PINMUX(8, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO9 \ + ESP32_PINMUX(9, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO10 \ + ESP32_PINMUX(10, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO11 \ + ESP32_PINMUX(11, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO12 \ + ESP32_PINMUX(12, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO13 \ + ESP32_PINMUX(13, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO14 \ + ESP32_PINMUX(14, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO15 \ + ESP32_PINMUX(15, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO16 \ + ESP32_PINMUX(16, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO17 \ + ESP32_PINMUX(17, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO18 \ + ESP32_PINMUX(18, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO19 \ + ESP32_PINMUX(19, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO20 \ + ESP32_PINMUX(20, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO21 \ + ESP32_PINMUX(21, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO22 \ + ESP32_PINMUX(22, ESP_NOSIG, ESP_U1TXD_OUT) + +#define UART1_TX_GPIO23 \ + ESP32_PINMUX(23, ESP_NOSIG, ESP_U1TXD_OUT) + + +#endif /* INC_DT_BINDS_PINCTRL_ESP32C6_PINCTRL_HAL_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl-s1.h b/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl-s1.h index fdfde7fccac0b..38b8f6e42db80 100644 --- a/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl-s1.h +++ b/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl-s1.h @@ -26,7 +26,7 @@ /** Position of the function field. */ #define GECKO_FUN_POS 24U /** Mask for the function field. */ -#define GECKO_FUN_MSK 0xFFFU +#define GECKO_FUN_MSK 0xFFU /** Position of the pin field. */ #define GECKO_PIN_POS 0U diff --git a/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl.h index 5624f1e809ee9..a49f4fe793e54 100644 --- a/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/gecko-pinctrl.h @@ -26,7 +26,7 @@ /** Position of the function field. */ #define GECKO_FUN_POS 24U /** Mask for the function field. */ -#define GECKO_FUN_MSK 0xFFFU +#define GECKO_FUN_MSK 0xFFU /** Position of the pin field. */ #define GECKO_PIN_POS 0U diff --git a/include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h new file mode 100644 index 0000000000000..97a3ab76748d1 --- /dev/null +++ b/include/zephyr/dt-bindings/pinctrl/max32-pinctrl.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2023-2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MAX32_PINCTRL_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MAX32_PINCTRL_H_ + +/** + * @brief Pin modes + */ +#define MAX32_MODE_GPIO 0x00 +#define MAX32_MODE_AF1 0x01 +#define MAX32_MODE_AF2 0x02 +#define MAX32_MODE_AF3 0x03 +#define MAX32_MODE_AF4 0x04 +#define MAX32_MODE_AF5 0x05 + +/** + * @brief Mode, port, pin shift number + */ +#define MAX32_MODE_SHIFT 0U +#define MAX32_MODE_MASK 0x0FU +#define MAX32_PORT_SHIFT 4U +#define MAX32_PORT_MASK 0x0FU +#define MAX32_PIN_SHIFT 8U +#define MAX32_PIN_MASK 0xFFU + +/** + * @brief Pin configuration bit field. + * + * Fields: + * + * - mode [ 0 : 3 ] + * - port [ 4 : 7 ] + * - pin [ 8 : 15 ] + * + * @param port Port (0 .. 15) + * @param pin Pin (0..31) + * @param mode Mode (GPIO, AF1, AF2...). + */ +#define MAX32_PINMUX(port, pin, mode) \ + ((((port)&MAX32_PORT_MASK) << MAX32_PORT_SHIFT) | \ + (((pin)&MAX32_PIN_MASK) << MAX32_PIN_SHIFT) | \ + (((MAX32_MODE_##mode) & MAX32_MODE_MASK) << MAX32_MODE_SHIFT)) + +#define MAX32_PINMUX_PORT(pinmux) (((pinmux) >> MAX32_PORT_SHIFT) & MAX32_PORT_MASK) +#define MAX32_PINMUX_PIN(pinmux) (((pinmux) >> MAX32_PIN_SHIFT) & MAX32_PIN_MASK) +#define MAX32_PINMUX_MODE(pinmux) (((pinmux) >> MAX32_MODE_SHIFT) & MAX32_MODE_MASK) + +/* Selects the voltage rail used for the pin */ +#define MAX32_VSEL_VDDIO 0 +#define MAX32_VSEL_VDDIOH 1 + +/** + * @brief Pin configuration + */ +#define MAX32_INPUT_ENABLE_SHIFT 0x00 +#define MAX32_BIAS_PULL_UP_SHIFT 0x01 +#define MAX32_BIAS_PULL_DOWN_SHIFT 0x02 +#define MAX32_OUTPUT_ENABLE_SHIFT 0x03 +#define MAX32_POWER_SOURCE_SHIFT 0x04 +#define MAX32_OUTPUT_HIGH_SHIFT 0x05 +#define MAX32_DRV_STRENGTH_SHIFT 0x06 /* 2 bits */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_PINCTRL_MAX32_PINCTRL_H_ */ diff --git a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h index a50233ab38c7f..bdb370d2638b3 100644 --- a/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/nrf-pinctrl.h @@ -10,13 +10,12 @@ * The whole nRF pin configuration information is encoded in a 32-bit bitfield * organized as follows: * - * - 31..16: Pin function. - * - 15: Reserved. - * - 14: Pin inversion mode. - * - 13: Pin low power mode. - * - 12..9: Pin output drive configuration. - * - 8..7: Pin pull configuration. - * - 6..0: Pin number (combination of port and pin). + * - 31..17: Pin function. + * - 16: Pin inversion mode. + * - 15: Pin low power mode. + * - 14..11: Pin output drive configuration. + * - 10..9: Pin pull configuration. + * - 8..0: Pin number (combination of port and pin). */ /** @@ -25,29 +24,29 @@ */ /** Position of the function field. */ -#define NRF_FUN_POS 16U +#define NRF_FUN_POS 17U /** Mask for the function field. */ -#define NRF_FUN_MSK 0xFFFFU +#define NRF_FUN_MSK 0x7FFFU /** Position of the invert field. */ -#define NRF_INVERT_POS 14U +#define NRF_INVERT_POS 16U /** Mask for the invert field. */ #define NRF_INVERT_MSK 0x1U /** Position of the low power field. */ -#define NRF_LP_POS 13U +#define NRF_LP_POS 15U /** Mask for the low power field. */ #define NRF_LP_MSK 0x1U /** Position of the drive configuration field. */ -#define NRF_DRIVE_POS 9U +#define NRF_DRIVE_POS 11U /** Mask for the drive configuration field. */ #define NRF_DRIVE_MSK 0xFU /** Position of the pull configuration field. */ -#define NRF_PULL_POS 7U +#define NRF_PULL_POS 9U /** Mask for the pull configuration field. */ #define NRF_PULL_MSK 0x3U /** Position of the pin field. */ #define NRF_PIN_POS 0U /** Mask for the pin field. */ -#define NRF_PIN_MSK 0x7FU +#define NRF_PIN_MSK 0x1FFU /** @} */ @@ -148,6 +147,10 @@ #define NRF_FUN_EXMIF_CS0 44U /** EXMIF CS1 */ #define NRF_FUN_EXMIF_CS1 45U +/** CAN TX */ +#define NRF_FUN_CAN_TX 46U +/** CAN RX */ +#define NRF_FUN_CAN_RX 47U /** @} */ @@ -218,7 +221,7 @@ * @brief Utility macro to build nRF psels property entry. * * @param fun Pin function configuration (see NRF_FUNC_{name} macros). - * @param port Port (0 or 1). + * @param port Port (0 or 15). * @param pin Pin (0..31). */ #define NRF_PSEL(fun, port, pin) \ diff --git a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h index 0e752e54d4e0e..0c5933c580e50 100644 --- a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h +++ b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl-common.h @@ -22,9 +22,13 @@ #define STM32_PORTI 8 #define STM32_PORTJ 9 #define STM32_PORTK 10 /* IO port K */ +#define STM32_PORTM 12 /* IO port M (0xC) */ +#define STM32_PORTN 13 +#define STM32_PORTO 14 +#define STM32_PORTP 15 /* IO port P (0xF) */ #ifndef STM32_PORTS_MAX -#define STM32_PORTS_MAX (STM32_PORTK + 1) +#define STM32_PORTS_MAX (STM32_PORTP + 1) #endif /** diff --git a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h index f5d0309897a86..52612f6948d51 100644 --- a/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h +++ b/include/zephyr/dt-bindings/pinctrl/stm32-pinctrl.h @@ -44,7 +44,7 @@ #define STM32_LINE_SHIFT 5U #define STM32_LINE_MASK 0xFU #define STM32_PORT_SHIFT 9U -#define STM32_PORT_MASK 0xFU +#define STM32_PORT_MASK 0x1FU /** * @brief Pin configuration configuration bit field. @@ -53,9 +53,9 @@ * * - mode [ 0 : 4 ] * - line [ 5 : 8 ] - * - port [ 9 : 12 ] + * - port [ 9 : 13 ] * - * @param port Port ('A'..'K') + * @param port Port ('A'..'P') * @param line Pin (0..15) * @param mode Mode (ANALOG, GPIO_IN, ALTERNATE). */ diff --git a/include/zephyr/dt-bindings/power/stm32_pwr.h b/include/zephyr/dt-bindings/power/stm32_pwr.h new file mode 100644 index 0000000000000..8c7962f14ada8 --- /dev/null +++ b/include/zephyr/dt-bindings/power/stm32_pwr.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_POWER_STM32_PWR_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_POWER_STM32_PWR_H_ + +/** + * @brief STM32 power controller + * @{ + */ + +/** + * @name flags for wake-up pins sources + * @{ + */ + +#define STM32_PWR_WKUP_PIN_SRC_0 0 +#define STM32_PWR_WKUP_PIN_SRC_1 1 +#define STM32_PWR_WKUP_PIN_SRC_2 (1 << 2) + +/** @} */ + +/** @} */ + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_POWER_STM32_PWR_H_ */ diff --git a/include/zephyr/dt-bindings/reset/nxp_syscon_reset_common.h b/include/zephyr/dt-bindings/reset/nxp_syscon_reset_common.h new file mode 100644 index 0000000000000..9888572325a0f --- /dev/null +++ b/include/zephyr/dt-bindings/reset/nxp_syscon_reset_common.h @@ -0,0 +1,12 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_NXP_SYSCON_RESET_COMMON_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_NXP_SYSCON_RESET_COMMON_H_ + +#define NXP_SYSCON_RESET(offset, bit) ((offset << 16) | bit) + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RESET_NXP_SYSCON_RESET_COMMON_H_ */ diff --git a/include/zephyr/dt-bindings/reset/stm32h7rs_reset.h b/include/zephyr/dt-bindings/reset/stm32h7rs_reset.h new file mode 100644 index 0000000000000..a4a90a9cc1015 --- /dev/null +++ b/include/zephyr/dt-bindings/reset/stm32h7rs_reset.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Google Inc + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32H7RS_RESET_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32H7RS_RESET_H_ + +#include "stm32-common.h" + +/* RCC bus reset register offset */ +#define STM32_RESET_BUS_AHB1 0x80 +#define STM32_RESET_BUS_AHB2 0x84 +#define STM32_RESET_BUS_AHB3 0xA4 +#define STM32_RESET_BUS_AHB5 0x7C +#define STM32_RESET_BUS_APB5 0x8C +#define STM32_RESET_BUS_AHB4 0x88 +#define STM32_RESET_BUS_APB1L 0x90 +#define STM32_RESET_BUS_APB1H 0x94 +#define STM32_RESET_BUS_APB2 0x98 +#define STM32_RESET_BUS_APB4 0x9C + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_RESET_STM32H7RS_RESET_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/ina226.h b/include/zephyr/dt-bindings/sensor/ina226.h new file mode 100644 index 0000000000000..9efd704eb9da4 --- /dev/null +++ b/include/zephyr/dt-bindings/sensor/ina226.h @@ -0,0 +1,45 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_DT_BINDINGS_INA226_H_ +#define ZEPHYR_INCLUDE_DT_BINDINGS_INA226_H_ + +#include + +/* Reset Mode. */ +#define INA226_RST_NORMAL_OPERATION 0x00 +#define INA226_RST_SYSTEM_RESET 0x01 + +/* Averaging Mode. */ +#define INA226_AVG_MODE_1 0x00 +#define INA226_AVG_MODE_4 0x01 +#define INA226_AVG_MODE_16 0x02 +#define INA226_AVG_MODE_64 0x03 +#define INA226_AVG_MODE_128 0x04 +#define INA226_AVG_MODE_256 0x05 +#define INA226_AVG_MODE_512 0x06 +#define INA226_AVG_MODE_1024 0x07 + +/* Conversion time for bus and shunt voltage in micro-seconds. */ +#define INA226_CONV_TIME_140 0x00 +#define INA226_CONV_TIME_204 0x01 +#define INA226_CONV_TIME_332 0x02 +#define INA226_CONV_TIME_588 0x03 +#define INA226_CONV_TIME_1100 0x04 +#define INA226_CONV_TIME_2116 0x05 +#define INA226_CONV_TIME_4156 0x06 +#define INA226_CONV_TIME_8244 0x07 + +/* Operating Mode. */ +#define INA226_OPER_MODE_POWER_DOWN 0x00 +#define INA226_OPER_MODE_SHUNT_VOLTAGE_TRIG 0x01 +#define INA226_OPER_MODE_BUS_VOLTAGE_TRIG 0x02 +#define INA226_OPER_MODE_SHUNT_BUS_VOLTAGE_TRIG 0x03 +#define INA226_OPER_MODE_SHUNT_VOLTAGE_CONT 0x05 +#define INA226_OPER_MODE_BUS_VOLTAGE_CONT 0x06 +#define INA226_OPER_MODE_SHUNT_BUS_VOLTAGE_CONT 0x07 + +#endif /* ZEPHYR_INCLUDE_DT_BINDINGS_INA226_H_ */ diff --git a/include/zephyr/dt-bindings/sensor/lis2dh.h b/include/zephyr/dt-bindings/sensor/lis2dh.h index a697f34cc8024..ff13d13a321b5 100644 --- a/include/zephyr/dt-bindings/sensor/lis2dh.h +++ b/include/zephyr/dt-bindings/sensor/lis2dh.h @@ -7,7 +7,7 @@ #define ZEPHYR_INCLUDE_DT_BINDINGS_ST_LIS2DH_H_ /* GPIO interrupt configuration */ -#define LIS2DH_DT_GPIO_INT_EDGE 0 +#define LIS2DH_DT_GPIO_INT_EDGE_BOTH 0 #define LIS2DH_DT_GPIO_INT_EDGE_RISING 1 #define LIS2DH_DT_GPIO_INT_EDGE_FALLING 2 #define LIS2DH_DT_GPIO_INT_LEVEL_HIGH 3 diff --git a/include/zephyr/fatal.h b/include/zephyr/fatal.h index be3dd2078c5cd..0fa1e93363ed4 100644 --- a/include/zephyr/fatal.h +++ b/include/zephyr/fatal.h @@ -12,6 +12,7 @@ #define ZEPHYR_INCLUDE_FATAL_H #include +#include #include #include @@ -64,7 +65,7 @@ FUNC_NORETURN void k_fatal_halt(unsigned int reason); * @param esf Exception context, with details and partial or full register * state when the error occurred. May in some cases be NULL. */ -void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf); +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf); /** * Called by architecture code upon a fatal error. @@ -80,7 +81,7 @@ void k_sys_fatal_error_handler(unsigned int reason, const z_arch_esf_t *esf); * @param esf Exception context, with details and partial or full register * state when the error occurred. May in some cases be NULL. */ -void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf); +void z_fatal_error(unsigned int reason, const struct arch_esf *esf); /** @} */ diff --git a/include/zephyr/fs/fcb.h b/include/zephyr/fs/fcb.h index 959a60b328646..63d68ef0898bf 100644 --- a/include/zephyr/fs/fcb.h +++ b/include/zephyr/fs/fcb.h @@ -37,7 +37,7 @@ extern "C" { * @{ */ -#define FCB_MAX_LEN (CHAR_MAX | CHAR_MAX << 7) /**< Max length of element */ +#define FCB_MAX_LEN (0x3fffu) /**< Max length of element (16,383) */ /** * @brief FCB entry info structure. This data structure describes the element diff --git a/include/zephyr/fs/fs.h b/include/zephyr/fs/fs.h index f52cba8c1ba8e..57b7c84d6835b 100644 --- a/include/zephyr/fs/fs.h +++ b/include/zephyr/fs/fs.h @@ -160,8 +160,11 @@ struct fs_statvfs { #define FS_O_CREATE 0x10 /** Open/create file for append */ #define FS_O_APPEND 0x20 +/** Truncate the file while opening */ +#define FS_O_TRUNC 0x40 /** Bitmask for open/create flags */ -#define FS_O_FLAGS_MASK 0x30 +#define FS_O_FLAGS_MASK 0x70 + /** Bitmask for open flags */ #define FS_O_MASK (FS_O_MODE_MASK | FS_O_FLAGS_MASK) @@ -268,6 +271,7 @@ static inline void fs_dir_t_init(struct fs_dir_t *zdp) * - @c FS_O_RDWR open for read/write (FS_O_READ | FS_O_WRITE) * - @c FS_O_CREATE create file if it does not exist * - @c FS_O_APPEND move to end of file before each write + * - @c FS_O_TRUNC truncate the file * * @warning If @p flags are set to 0 the function will open file, if it exists * and is accessible, but you will have no read/write access to it. @@ -284,6 +288,7 @@ static inline void fs_dir_t_init(struct fs_dir_t *zdp) * FS_MOUNT_FLAG_READ_ONLY flag; * @retval -ENOENT when the file does not exist at the path; * @retval -ENOTSUP when not implemented by underlying file system driver; + * @retval -EACCES when trying to truncate a file without opening it for write. * @retval <0 an other negative errno code, depending on a file system back-end. */ int fs_open(struct fs_file_t *zfp, const char *file_name, fs_mode_t flags); diff --git a/include/zephyr/fs/fs_interface.h b/include/zephyr/fs/fs_interface.h index 5db637635b954..1f0d26ce5bc1e 100644 --- a/include/zephyr/fs/fs_interface.h +++ b/include/zephyr/fs/fs_interface.h @@ -13,10 +13,23 @@ extern "C" { #endif -#if defined(CONFIG_FILE_SYSTEM_MAX_FILE_NAME) && (CONFIG_FILE_SYSTEM_MAX_FILE_NAME - 0) > 0 +#if defined(CONFIG_FILE_SYSTEM_MAX_FILE_NAME) && (CONFIG_FILE_SYSTEM_MAX_FILE_NAME - 0) > 0 + +/* No in-tree file system supports name longer than 255 characters */ +#if (CONFIG_FILE_SYSTEM_LITTLEFS || CONFIG_FAT_FILESYSTEM_ELM || \ + CONFIG_FILE_SYSTEM_EXT2) && (CONFIG_FILE_SYSTEM_MAX_FILE_NAME > 255) +#error "Max allowed CONFIG_FILE_SYSTEM_MAX_FILE_NAME is 255 characters, when any in-tree FS enabled" +#endif + +/* Enabled FAT driver, without LFN, restricts name length to 12 characters */ +#if defined(CONFIG_FAT_FILESYSTEM_ELM) && !(CONFIG_FS_FATFS_LFN) && \ + (CONFIG_FILE_SYSTEM_MAX_FILE_NAME > 12) +#error "CONFIG_FILE_SYSTEM_MAX_FILE_NAME can not be > 12 if FAT is enabled without LFN" +#endif + #define MAX_FILE_NAME CONFIG_FILE_SYSTEM_MAX_FILE_NAME -#else /* CONFIG_FILE_SYSTEM_MAX_FILE_NAME */ +#else /* Select from enabled file systems */ #if defined(CONFIG_FAT_FILESYSTEM_ELM) @@ -34,7 +47,7 @@ extern "C" { #endif #if !defined(MAX_FILE_NAME) && defined(CONFIG_FILE_SYSTEM_LITTLEFS) -#define MAX_FILE_NAME 256 +#define MAX_FILE_NAME 255 #endif #if !defined(MAX_FILE_NAME) /* filesystem selection */ diff --git a/include/zephyr/internal/syscall_handler.h b/include/zephyr/internal/syscall_handler.h index d387962191778..62f1061843227 100644 --- a/include/zephyr/internal/syscall_handler.h +++ b/include/zephyr/internal/syscall_handler.h @@ -56,13 +56,13 @@ enum _obj_init_check { */ static inline bool k_is_in_user_syscall(void) { - /* This gets set on entry to the syscall's generasted z_mrsh + /* This gets set on entry to the syscall's generated z_mrsh * function and then cleared on exit. This code path is only * encountered when a syscall is made from user mode, system * calls from supervisor mode bypass everything directly to * the implementation function. */ - return !k_is_in_isr() && _current->syscall_frame != NULL; + return !k_is_in_isr() && (_current->syscall_frame != NULL); } /** @@ -647,7 +647,7 @@ static inline int k_object_validation_check(struct k_object *ko, #define K_SYSCALL_OBJ_NEVER_INIT(ptr, type) \ K_SYSCALL_IS_OBJ(ptr, type, _OBJ_INIT_FALSE) -#include +#include #endif /* _ASMLANGUAGE */ diff --git a/include/zephyr/ipc/icmsg.h b/include/zephyr/ipc/icmsg.h index 3bc03804ca824..80e3412095acb 100644 --- a/include/zephyr/ipc/icmsg.h +++ b/include/zephyr/ipc/icmsg.h @@ -111,7 +111,7 @@ int icmsg_close(const struct icmsg_config_t *conf, * @param[in] len Size of data in the @p msg buffer. * * - * @retval 0 on success. + * @retval Number of sent bytes. * @retval -EBUSY when the instance has not finished handshake with the remote * instance. * @retval -ENODATA when the requested data to send is empty. diff --git a/include/zephyr/irq.h b/include/zephyr/irq.h index 1fa559edccd34..4810a27b3e0dd 100644 --- a/include/zephyr/irq.h +++ b/include/zephyr/irq.h @@ -215,7 +215,7 @@ irq_disconnect_dynamic(unsigned int irq, unsigned int priority, * * @note * This routine must also serve as a memory barrier to ensure the uniprocessor - * implementation of `k_spinlock_t` is correct. + * implementation of spinlocks is correct. * * This routine can be called recursively, as long as the caller keeps track * of each lock-out key that is generated. Interrupts are re-enabled by @@ -263,7 +263,7 @@ unsigned int z_smp_global_lock(void); * * @note * This routine must also serve as a memory barrier to ensure the uniprocessor - * implementation of `k_spinlock_t` is correct. + * implementation of spinlocks is correct. * * This routine can only be invoked from supervisor mode. Some architectures * (for example, ARM) will fail silently if invoked from user mode instead diff --git a/include/zephyr/irq_multilevel.h b/include/zephyr/irq_multilevel.h index 25daa0302495c..b500559f1c722 100644 --- a/include/zephyr/irq_multilevel.h +++ b/include/zephyr/irq_multilevel.h @@ -12,6 +12,7 @@ #define ZEPHYR_INCLUDE_IRQ_MULTILEVEL_H_ #ifndef _ASMLANGUAGE +#include #include #include @@ -166,6 +167,93 @@ static inline unsigned int irq_parent_level_3(unsigned int irq) BIT_MASK(CONFIG_2ND_LEVEL_INTERRUPT_BITS); } +/** + * @brief Return the interrupt number for a given level + * + * @param irq IRQ number in its zephyr format + * @param level IRQ level + * + * @return IRQ number in the level + */ +static inline unsigned int irq_from_level(unsigned int irq, unsigned int level) +{ + if (level == 1) { + return irq; + } else if (level == 2) { + return irq_from_level_2(irq); + } else if (level == 3) { + return irq_from_level_3(irq); + } + + /* level is higher than 3 */ + __ASSERT_NO_MSG(false); + return irq; +} + +/** + * @brief Converts irq from level 1 to to a given level + * + * @param irq IRQ number in its zephyr format + * @param level IRQ level + * + * @return Converted IRQ number in the level + */ +static inline unsigned int irq_to_level(unsigned int irq, unsigned int level) +{ + if (level == 1) { + return irq; + } else if (level == 2) { + return irq_to_level_2(irq); + } else if (level == 3) { + return irq_to_level_3(irq); + } + + /* level is higher than 3 */ + __ASSERT_NO_MSG(false); + return irq; +} + +/** + * @brief Returns the parent IRQ of the given level raw IRQ number + * + * @param irq IRQ number in its zephyr format + * @param level IRQ level + * + * @return IRQ parent of the given level + */ +static inline unsigned int irq_parent_level(unsigned int irq, unsigned int level) +{ + if (level == 1) { + /* doesn't really make sense, but return anyway */ + return irq; + } else if (level == 2) { + return irq_parent_level_2(irq); + } else if (level == 3) { + return irq_parent_level_3(irq); + } + + /* level is higher than 3 */ + __ASSERT_NO_MSG(false); + return irq; +} + +/** + * @brief Returns the parent interrupt controller IRQ of the given IRQ number + * + * @param irq IRQ number in its zephyr format + * + * @return IRQ of the interrupt controller + */ +static inline unsigned int irq_get_intc_irq(unsigned int irq) +{ + const unsigned int level = irq_get_level(irq); + + __ASSERT_NO_MSG(level > 1 && level <= 3); + + return irq & BIT_MASK(CONFIG_1ST_LEVEL_INTERRUPT_BITS + + (level == 3 ? CONFIG_2ND_LEVEL_INTERRUPT_BITS : 0)); +} + #endif /* CONFIG_MULTI_LEVEL_INTERRUPTS */ #ifdef __cplusplus } diff --git a/include/zephyr/kernel.h b/include/zephyr/kernel.h index 56471770a7cdf..7be3ea83d4621 100644 --- a/include/zephyr/kernel.h +++ b/include/zephyr/kernel.h @@ -46,7 +46,7 @@ BUILD_ASSERT(sizeof(intptr_t) == sizeof(long)); #define K_ANY NULL -#if CONFIG_NUM_COOP_PRIORITIES + CONFIG_NUM_PREEMPT_PRIORITIES == 0 +#if (CONFIG_NUM_COOP_PRIORITIES + CONFIG_NUM_PREEMPT_PRIORITIES) == 0 #error Zero available thread priorities defined! #endif @@ -375,7 +375,7 @@ FUNC_NORETURN void k_thread_user_mode_enter(k_thread_entry_t entry, * @param ... list of kernel object pointers */ #define k_thread_access_grant(thread, ...) \ - FOR_EACH_FIXED_ARG(k_object_access_grant, (;), thread, __VA_ARGS__) + FOR_EACH_FIXED_ARG(k_object_access_grant, (;), (thread), __VA_ARGS__) /** * @brief Assign a resource memory pool to a thread @@ -1774,6 +1774,19 @@ static inline uint32_t k_uptime_get_32(void) return (uint32_t)k_uptime_get(); } +/** + * @brief Get system uptime in seconds. + * + * This routine returns the elapsed time since the system booted, + * in seconds. + * + * @return Current uptime in seconds. + */ +static inline uint32_t k_uptime_seconds(void) +{ + return k_ticks_to_sec_floor32(k_uptime_ticks()); +} + /** * @brief Get elapsed time. * @@ -2076,7 +2089,7 @@ __syscall int k_queue_is_empty(struct k_queue *queue); static inline int z_impl_k_queue_is_empty(struct k_queue *queue) { - return (int)sys_sflist_is_empty(&queue->data_q); + return sys_sflist_is_empty(&queue->data_q) ? 1 : 0; } /** @@ -2759,10 +2772,10 @@ struct k_stack { #define Z_STACK_INITIALIZER(obj, stack_buffer, stack_num_entries) \ { \ - .wait_q = Z_WAIT_Q_INIT(&obj.wait_q), \ - .base = stack_buffer, \ - .next = stack_buffer, \ - .top = stack_buffer + stack_num_entries, \ + .wait_q = Z_WAIT_Q_INIT(&(obj).wait_q), \ + .base = (stack_buffer), \ + .next = (stack_buffer), \ + .top = (stack_buffer) + (stack_num_entries), \ } /** @@ -2922,7 +2935,7 @@ struct k_mutex { */ #define Z_MUTEX_INITIALIZER(obj) \ { \ - .wait_q = Z_WAIT_Q_INIT(&obj.wait_q), \ + .wait_q = Z_WAIT_Q_INIT(&(obj).wait_q), \ .owner = NULL, \ .lock_count = 0, \ .owner_orig_prio = K_LOWEST_APPLICATION_THREAD_PRIO, \ @@ -3111,9 +3124,9 @@ struct k_sem { #define Z_SEM_INITIALIZER(obj, initial_count, count_limit) \ { \ - .wait_q = Z_WAIT_Q_INIT(&obj.wait_q), \ - .count = initial_count, \ - .limit = count_limit, \ + .wait_q = Z_WAIT_Q_INIT(&(obj).wait_q), \ + .count = (initial_count), \ + .limit = (count_limit), \ Z_POLL_EVENT_OBJ_INIT(obj) \ } @@ -3619,6 +3632,8 @@ static inline k_ticks_t k_work_delayable_remaining_get( * * @retval 0 if work was already scheduled or submitted. * @retval 1 if work has been scheduled. + * @retval 2 if @p delay is @c K_NO_WAIT and work + * was running and has been queued to the queue that was running it. * @retval -EBUSY if @p delay is @c K_NO_WAIT and * k_work_submit_to_queue() fails with this code. * @retval -EINVAL if @p delay is @c K_NO_WAIT and @@ -3883,7 +3898,7 @@ struct k_work { }; #define Z_WORK_INITIALIZER(work_handler) { \ - .handler = work_handler, \ + .handler = (work_handler), \ } /** @brief A structure used to submit work after a delay. */ @@ -3900,7 +3915,7 @@ struct k_work_delayable { #define Z_WORK_DELAYABLE_INITIALIZER(work_handler) { \ .work = { \ - .handler = work_handler, \ + .handler = (work_handler), \ .flags = K_WORK_DELAYABLE, \ }, \ } @@ -4117,7 +4132,7 @@ struct k_work_user { #define Z_WORK_USER_INITIALIZER(work_handler) \ { \ ._reserved = NULL, \ - .handler = work_handler, \ + .handler = (work_handler), \ .flags = 0 \ } #endif @@ -4852,7 +4867,7 @@ void k_mbox_data_get(struct k_mbox_msg *rx_msg, void *buffer); struct k_pipe { unsigned char *buffer; /**< Pipe buffer: may be NULL */ size_t size; /**< Buffer size */ - size_t bytes_used; /**< # bytes used in buffer */ + size_t bytes_used; /**< Number of bytes used in buffer */ size_t read_index; /**< Where in buffer to read from */ size_t write_index; /**< Where in buffer to write */ struct k_spinlock lock; /**< Synchronization lock */ @@ -5368,6 +5383,32 @@ void *k_heap_aligned_alloc(struct k_heap *h, size_t align, size_t bytes, void *k_heap_alloc(struct k_heap *h, size_t bytes, k_timeout_t timeout) __attribute_nonnull(1); +/** + * @brief Reallocate memory from a k_heap + * + * Reallocates and returns a memory buffer from the memory region owned + * by the heap. If no memory is available immediately, the call will + * block for the specified timeout (constructed via the standard + * timeout API, or K_NO_WAIT or K_FOREVER) waiting for memory to be + * freed. If the allocation cannot be performed by the expiration of + * the timeout, NULL will be returned. + * Reallocated memory is aligned on a multiple of pointer sizes. + * + * @note @a timeout must be set to K_NO_WAIT if called from ISR. + * @note When CONFIG_MULTITHREADING=n any @a timeout is treated as K_NO_WAIT. + * + * @funcprops \isr_ok + * + * @param h Heap from which to allocate + * @param ptr Original pointer returned from a previous allocation + * @param bytes Desired size of block to allocate + * @param timeout How long to wait, or K_NO_WAIT + * + * @return Pointer to memory the caller can now use, or NULL + */ +void *k_heap_realloc(struct k_heap *h, void *ptr, size_t bytes, k_timeout_t timeout) + __attribute_nonnull(1); + /** * @brief Free memory allocated by k_heap_alloc() * @@ -5383,7 +5424,7 @@ void k_heap_free(struct k_heap *h, void *mem) __attribute_nonnull(1); /* Hand-calculated minimum heap sizes needed to return a successful * 1-byte allocation. See details in lib/os/heap.[ch] */ -#define Z_HEAP_MIN_SIZE (sizeof(void *) > 4 ? 56 : 44) +#define Z_HEAP_MIN_SIZE ((sizeof(void *) > 4) ? 56 : 44) /** * @brief Define a static k_heap in the specified linker section @@ -5515,6 +5556,25 @@ void k_free(void *ptr); */ void *k_calloc(size_t nmemb, size_t size); +/** @brief Expand the size of an existing allocation + * + * Returns a pointer to a new memory region with the same contents, + * but a different allocated size. If the new allocation can be + * expanded in place, the pointer returned will be identical. + * Otherwise the data will be copies to a new block and the old one + * will be freed as per sys_heap_free(). If the specified size is + * smaller than the original, the block will be truncated in place and + * the remaining memory returned to the heap. If the allocation of a + * new block fails, then NULL will be returned and the old block will + * not be freed or modified. + * + * @param ptr Original pointer returned from a previous allocation + * @param size Amount of memory requested (in bytes). + * + * @return Pointer to memory the caller can now use, or NULL. + */ +void *k_realloc(void *ptr, size_t size); + /** @} */ /* polling API - PRIVATE */ @@ -5673,14 +5733,17 @@ struct k_poll_event { /** per-type data */ union { - void *obj; - struct k_poll_signal *signal; - struct k_sem *sem; - struct k_fifo *fifo; - struct k_queue *queue; - struct k_msgq *msgq; + /* The typed_* fields below are used by K_POLL_EVENT_*INITIALIZER() macros to ensure + * type safety of polled objects. + */ + void *obj, *typed_K_POLL_TYPE_IGNORE; + struct k_poll_signal *signal, *typed_K_POLL_TYPE_SIGNAL; + struct k_sem *sem, *typed_K_POLL_TYPE_SEM_AVAILABLE; + struct k_fifo *fifo, *typed_K_POLL_TYPE_FIFO_DATA_AVAILABLE; + struct k_queue *queue, *typed_K_POLL_TYPE_DATA_AVAILABLE; + struct k_msgq *msgq, *typed_K_POLL_TYPE_MSGQ_DATA_AVAILABLE; #ifdef CONFIG_PIPES - struct k_pipe *pipe; + struct k_pipe *pipe, *typed_K_POLL_TYPE_PIPE_DATA_AVAILABLE; #endif }; }; @@ -5693,7 +5756,7 @@ struct k_poll_event { .mode = _event_mode, \ .unused = 0, \ { \ - .obj = _event_obj, \ + .typed_##_event_type = _event_obj, \ }, \ } @@ -5706,7 +5769,7 @@ struct k_poll_event { .mode = _event_mode, \ .unused = 0, \ { \ - .obj = _event_obj, \ + .typed_##_event_type = _event_obj, \ }, \ } @@ -6095,7 +6158,7 @@ void k_sys_runtime_stats_disable(void); #endif #include -#include +#include #endif /* !_ASMLANGUAGE */ diff --git a/include/zephyr/kernel/internal/mm.h b/include/zephyr/kernel/internal/mm.h index 61a8c69c5eef4..2b5a9330e5461 100644 --- a/include/zephyr/kernel/internal/mm.h +++ b/include/zephyr/kernel/internal/mm.h @@ -16,11 +16,14 @@ * @{ */ -/* +/** + * @def K_MEM_VIRT_OFFSET + * @brief Address offset of permanent virtual mapping from physical address. + * * This is the offset to subtract from a virtual address mapped in the * kernel's permanent mapping of RAM, to obtain its physical address. * - * virt_addr = phys_addr + Z_MEM_VM_OFFSET + * virt_addr = phys_addr + K_MEM_VIRT_OFFSET * * This only works for virtual addresses within the interval * [CONFIG_KERNEL_VM_BASE, CONFIG_KERNEL_VM_BASE + (CONFIG_SRAM_SIZE * 1024)). @@ -35,17 +38,39 @@ * constraints defined. */ #ifdef CONFIG_MMU -#define Z_MEM_VM_OFFSET ((CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_OFFSET) - \ - (CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_OFFSET)) +#define K_MEM_VIRT_OFFSET ((CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_OFFSET) - \ + (CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_OFFSET)) #else -#define Z_MEM_VM_OFFSET 0 +#define K_MEM_VIRT_OFFSET 0 #endif /* CONFIG_MMU */ -#define Z_MEM_PHYS_ADDR(virt) ((virt) - Z_MEM_VM_OFFSET) -#define Z_MEM_VIRT_ADDR(phys) ((phys) + Z_MEM_VM_OFFSET) +/** + * @brief Get physical address from virtual address. + * + * This only works in the kernel's permanent mapping of RAM. + * + * @param virt Virtual address + * + * @return Physical address. + */ +#define K_MEM_PHYS_ADDR(virt) ((virt) - K_MEM_VIRT_OFFSET) + +/** + * @brief Get virtual address from physical address. + * + * This only works in the kernel's permanent mapping of RAM. + * + * @param phys Physical address + * + * @return Virtual address. + */ +#define K_MEM_VIRT_ADDR(phys) ((phys) + K_MEM_VIRT_OFFSET) -#if Z_MEM_VM_OFFSET != 0 -#define Z_VM_KERNEL 1 +#if K_MEM_VIRT_OFFSET != 0 +/** + * @brief Kernel is mapped in virtual memory if defined. + */ +#define K_MEM_IS_VM_KERNEL 1 #ifdef CONFIG_XIP #error "XIP and a virtual memory kernel are not allowed" #endif @@ -58,8 +83,18 @@ #include #include -/* Just like Z_MEM_PHYS_ADDR() but with type safety and assertions */ -static inline uintptr_t z_mem_phys_addr(void *virt) +/** + * @brief Get physical address from virtual address. + * + * This only works in the kernel's permanent mapping of RAM. + * + * Just like K_MEM_PHYS_ADDR() but with type safety and assertions. + * + * @param virt Virtual address + * + * @return Physical address. + */ +static inline uintptr_t k_mem_phys_addr(void *virt) { uintptr_t addr = (uintptr_t)virt; @@ -98,11 +133,21 @@ static inline uintptr_t z_mem_phys_addr(void *virt) * the above checks won't be sufficient with demand paging */ - return Z_MEM_PHYS_ADDR(addr); + return K_MEM_PHYS_ADDR(addr); } -/* Just like Z_MEM_VIRT_ADDR() but with type safety and assertions */ -static inline void *z_mem_virt_addr(uintptr_t phys) +/** + * @brief Get virtual address from physical address. + * + * This only works in the kernel's permanent mapping of RAM. + * + * Just like K_MEM_VIRT_ADDR() but with type safety and assertions. + * + * @param phys Physical address + * + * @return Virtual address. + */ +static inline void *k_mem_virt_addr(uintptr_t phys) { #if defined(CONFIG_KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK) __ASSERT(sys_mm_is_phys_addr_in_range(phys), @@ -125,7 +170,7 @@ static inline void *z_mem_virt_addr(uintptr_t phys) * the above check won't be sufficient with demand paging */ - return (void *)Z_MEM_VIRT_ADDR(phys); + return (void *)K_MEM_VIRT_ADDR(phys); } #ifdef __cplusplus @@ -140,6 +185,9 @@ extern "C" { * linear address representing the base of where the physical region is mapped * in the virtual address space for the Zephyr kernel. * + * The memory mapped via this function must be unmapped using + * k_mem_unmap_phys_bare(). + * * This function alters the active page tables in the area reserved * for the kernel. This function will choose the virtual address * and return it to the caller. @@ -173,8 +221,8 @@ extern "C" { * @param[in] size Size of the memory region * @param[in] flags Caching mode and access flags, see K_MAP_* macros */ -void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, - uint32_t flags); +void k_mem_map_phys_bare(uint8_t **virt_ptr, uintptr_t phys, size_t size, + uint32_t flags); /** * Unmap a virtual memory region from kernel's virtual address space. @@ -188,7 +236,7 @@ void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, * * This will align the input parameters to page boundaries so that * this can be used with the virtual address as returned by - * z_phys_map(). + * k_mem_map_phys_bare(). * * This API is only available if CONFIG_MMU is enabled. * @@ -203,17 +251,45 @@ void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, * @param virt Starting address of the virtual address region to be unmapped. * @param size Size of the virtual address region */ -void z_phys_unmap(uint8_t *virt, size_t size); +void k_mem_unmap_phys_bare(uint8_t *virt, size_t size); /** * Map memory into virtual address space with guard pages. * * This maps memory into virtual address space with a preceding and - * a succeeding guard pages. + * a succeeding guard pages. The memory mapped via this function must be + * unmapped using k_mem_unmap_phys_guard(). * - * @see k_mem_map() for additional information if called via that. + * This function maps a contiguous physical memory region into kernel's + * virtual address space with a preceding and a succeeding guard pages. + * Given a physical address and a size, return a linear address representing + * the base of where the physical region is mapped in the virtual address + * space for the Zephyr kernel. + * + * This function alters the active page tables in the area reserved + * for the kernel. This function will choose the virtual address + * and return it to the caller. + * + * If user thread access control needs to be managed in any way, do not enable + * K_MEM_PERM_USER flags here; instead manage the region's permissions + * with memory domain APIs after the mapping has been established. Setting + * K_MEM_PERM_USER here will allow all user threads to access this memory + * which is usually undesirable. + * + * Unless K_MEM_MAP_UNINIT is used, the returned memory will be zeroed. * - * @see k_mem_phys_map() for additional information if called via that. + * The returned virtual memory pointer will be page-aligned. The size + * parameter, and any base address for re-mapping purposes must be page- + * aligned. + * + * Note that the allocation includes two guard pages immediately before + * and after the requested region. The total size of the allocation will be + * the requested size plus the size of these two guard pages. + * + * Many K_MEM_MAP_* flags have been implemented to alter the behavior of this + * function, with details in the documentation for these flags. + * + * @see k_mem_map() for additional information if called via that. * * @param phys Physical address base of the memory region if not requesting * anonymous memory. Must be page-aligned. @@ -225,26 +301,27 @@ void z_phys_unmap(uint8_t *virt, size_t size); * space, insufficient physical memory to establish the mapping, * or insufficient memory for paging structures. */ -void *k_mem_map_impl(uintptr_t phys, size_t size, uint32_t flags, bool is_anon); +void *k_mem_map_phys_guard(uintptr_t phys, size_t size, uint32_t flags, bool is_anon); /** - * Un-map mapped memory + * Un-map memory mapped via k_mem_map_phys_guard(). * * This removes the memory mappings for the provided page-aligned region, * and the two guard pages surrounding the region. * - * @see k_mem_unmap() for additional information if called via that. + * This function alters the active page tables in the area reserved + * for the kernel. * - * @see k_mem_phys_unmap() for additional information if called via that. + * @see k_mem_unmap() for additional information if called via that. * - * @note Calling this function on a region which was not mapped to begin - * with is undefined behavior. + * @note Calling this function on a region which was not mapped via + * k_mem_map_phys_guard() to begin with is undefined behavior. * * @param addr Page-aligned memory region base virtual address * @param size Page-aligned memory region size * @param is_anon True if the mapped memory is from anonymous memory. */ -void k_mem_unmap_impl(void *addr, size_t size, bool is_anon); +void k_mem_unmap_phys_guard(void *addr, size_t size, bool is_anon); #ifdef __cplusplus } diff --git a/include/zephyr/kernel/mm.h b/include/zephyr/kernel/mm.h index 90dd75354835d..88ad40af42140 100644 --- a/include/zephyr/kernel/mm.h +++ b/include/zephyr/kernel/mm.h @@ -170,51 +170,7 @@ size_t k_mem_free_get(void); */ static inline void *k_mem_map(size_t size, uint32_t flags) { - return k_mem_map_impl((uintptr_t)NULL, size, flags, true); -} - -/** - * Map a physical memory region into kernel's virtual address space with guard pages. - * - * This function maps a contiguous physical memory region into kernel's - * virtual address space. Given a physical address and a size, return a - * linear address representing the base of where the physical region is mapped - * in the virtual address space for the Zephyr kernel. - * - * This function alters the active page tables in the area reserved - * for the kernel. This function will choose the virtual address - * and return it to the caller. - * - * If user thread access control needs to be managed in any way, do not enable - * K_MEM_PERM_USER flags here; instead manage the region's permissions - * with memory domain APIs after the mapping has been established. Setting - * K_MEM_PERM_USER here will allow all user threads to access this memory - * which is usually undesirable. - * - * Unless K_MEM_MAP_UNINIT is used, the returned memory will be zeroed. - * - * The returned virtual memory pointer will be page-aligned. The size - * parameter, and any base address for re-mapping purposes must be page- - * aligned. - * - * Note that the allocation includes two guard pages immediately before - * and after the requested region. The total size of the allocation will be - * the requested size plus the size of these two guard pages. - * - * Many K_MEM_MAP_* flags have been implemented to alter the behavior of this - * function, with details in the documentation for these flags. - * - * @param phys Physical address base of the memory region. - * This must be page-aligned. - * @param size Size of the memory mapping. This must be page-aligned. - * @param flags K_MEM_PERM_*, K_MEM_MAP_* control flags. - * - * @return The mapped memory location, or NULL if insufficient virtual address - * space or insufficient memory for paging structures. - */ -static inline void *k_mem_phys_map(uintptr_t phys, size_t size, uint32_t flags) -{ - return k_mem_map_impl(phys, size, flags, false); + return k_mem_map_phys_guard((uintptr_t)NULL, size, flags, true); } /** @@ -232,30 +188,7 @@ static inline void *k_mem_phys_map(uintptr_t phys, size_t size, uint32_t flags) */ static inline void k_mem_unmap(void *addr, size_t size) { - k_mem_unmap_impl(addr, size, true); -} - -/** - * Un-map memory mapped via k_mem_phys_map(). - * - * This unmaps a virtual memory region from kernel's virtual address space. - * - * This function alters the active page tables in the area reserved - * for the kernel. - * - * This removes a memory mapping for the provided page-aligned region - * and the guard pages. The kernel may re-use the associated virtual address - * region later. - * - * @note Calling this function on a region which was not mapped via - * k_mem_phys_map() to begin with is undefined behavior. - * - * @param addr Page-aligned memory region base virtual address - * @param size Page-aligned memory region size - */ -static inline void k_mem_phys_unmap(void *addr, size_t size) -{ - k_mem_unmap_impl(addr, size, false); + k_mem_unmap_phys_guard(addr, size, true); } /** diff --git a/include/zephyr/kernel/mm/demand_paging.h b/include/zephyr/kernel/mm/demand_paging.h index 35dae90a2356d..e3c85c98244d6 100644 --- a/include/zephyr/kernel/mm/demand_paging.h +++ b/include/zephyr/kernel/mm/demand_paging.h @@ -203,7 +203,7 @@ __syscall void k_mem_paging_histogram_backing_store_page_in_get( __syscall void k_mem_paging_histogram_backing_store_page_out_get( struct k_mem_paging_histogram_t *hist); -#include +#include /** @} */ @@ -229,7 +229,7 @@ __syscall void k_mem_paging_histogram_backing_store_page_out_get( * @param [out] dirty Whether the page to evict is dirty * @return The page frame to evict */ -struct z_page_frame *k_mem_paging_eviction_select(bool *dirty); +struct k_mem_page_frame *k_mem_paging_eviction_select(bool *dirty); /** * Initialization function @@ -258,19 +258,19 @@ void k_mem_paging_eviction_init(void); * contents for later retrieval. The location value must be page-aligned. * * This function may be called multiple times on the same data page. If its - * page frame has its Z_PAGE_FRAME_BACKED bit set, it is expected to return + * page frame has its K_MEM_PAGE_FRAME_BACKED bit set, it is expected to return * the previous backing store location for the data page containing a cached * clean copy. This clean copy may be updated on page-out, or used to * discard clean pages without needing to write out their contents. * * If the backing store is full, some other backing store location which caches * a loaded data page may be selected, in which case its associated page frame - * will have the Z_PAGE_FRAME_BACKED bit cleared (as it is no longer cached). + * will have the K_MEM_PAGE_FRAME_BACKED bit cleared (as it is no longer cached). * - * pf->addr will indicate the virtual address the page is currently mapped to. - * Large, sparse backing stores which can contain the entire address space - * may simply generate location tokens purely as a function of pf->addr with no - * other management necessary. + * k_mem_page_frame_to_virt(pf) will indicate the virtual address the page is + * currently mapped to. Large, sparse backing stores which can contain the + * entire address space may simply generate location tokens purely as a + * function of that virtual address with no other management necessary. * * This function distinguishes whether it was called on behalf of a page * fault. A free backing store location must always be reserved in order for @@ -285,7 +285,7 @@ void k_mem_paging_eviction_init(void); * @return 0 Success * @return -ENOMEM Backing store is full */ -int k_mem_paging_backing_store_location_get(struct z_page_frame *pf, +int k_mem_paging_backing_store_location_get(struct k_mem_page_frame *pf, uintptr_t *location, bool page_fault); @@ -302,9 +302,9 @@ int k_mem_paging_backing_store_location_get(struct z_page_frame *pf, void k_mem_paging_backing_store_location_free(uintptr_t location); /** - * Copy a data page from Z_SCRATCH_PAGE to the specified location + * Copy a data page from K_MEM_SCRATCH_PAGE to the specified location * - * Immediately before this is called, Z_SCRATCH_PAGE will be mapped read-write + * Immediately before this is called, K_MEM_SCRATCH_PAGE will be mapped read-write * to the intended source page frame for the calling context. * * Calls to this and k_mem_paging_backing_store_page_in() will always be @@ -315,9 +315,9 @@ void k_mem_paging_backing_store_location_free(uintptr_t location); void k_mem_paging_backing_store_page_out(uintptr_t location); /** - * Copy a data page from the provided location to Z_SCRATCH_PAGE. + * Copy a data page from the provided location to K_MEM_SCRATCH_PAGE. * - * Immediately before this is called, Z_SCRATCH_PAGE will be mapped read-write + * Immediately before this is called, K_MEM_SCRATCH_PAGE will be mapped read-write * to the intended destination page frame for the calling context. * * Calls to this and k_mem_paging_backing_store_page_out() will always be @@ -331,7 +331,7 @@ void k_mem_paging_backing_store_page_in(uintptr_t location); * Update internal accounting after a page-in * * This is invoked after k_mem_paging_backing_store_page_in() and interrupts - * have been* re-locked, making it safe to access the z_page_frame data. + * have been* re-locked, making it safe to access the k_mem_page_frame data. * The location value will be the same passed to * k_mem_paging_backing_store_page_in(). * @@ -340,14 +340,14 @@ void k_mem_paging_backing_store_page_in(uintptr_t location); * if it is paged out again. This may be a no-op in some implementations. * * If the backing store caches paged-in data pages, this is the appropriate - * time to set the Z_PAGE_FRAME_BACKED bit. The kernel only skips paging + * time to set the K_MEM_PAGE_FRAME_BACKED bit. The kernel only skips paging * out clean data pages if they are noted as clean in the page tables and the - * Z_PAGE_FRAME_BACKED bit is set in their associated page frame. + * K_MEM_PAGE_FRAME_BACKED bit is set in their associated page frame. * * @param pf Page frame that was loaded in * @param location Location of where the loaded data page was retrieved */ -void k_mem_paging_backing_store_page_finalize(struct z_page_frame *pf, +void k_mem_paging_backing_store_page_finalize(struct k_mem_page_frame *pf, uintptr_t location); /** @@ -360,7 +360,7 @@ void k_mem_paging_backing_store_page_finalize(struct z_page_frame *pf, * - Initialize any internal data structures and accounting for the backing * store. * - If the backing store already contains all or some loaded kernel data pages - * at boot time, Z_PAGE_FRAME_BACKED should be appropriately set for their + * at boot time, K_MEM_PAGE_FRAME_BACKED should be appropriately set for their * associated page frames, and any internal accounting set up appropriately. */ void k_mem_paging_backing_store_init(void); diff --git a/include/zephyr/kernel_structs.h b/include/zephyr/kernel_structs.h index ff8bde4e57162..cf7daff9a6cf7 100644 --- a/include/zephyr/kernel_structs.h +++ b/include/zephyr/kernel_structs.h @@ -33,13 +33,7 @@ #endif #define K_NUM_THREAD_PRIO (CONFIG_NUM_PREEMPT_PRIORITIES + CONFIG_NUM_COOP_PRIORITIES + 1) - -#if defined(CONFIG_64BIT) -#define PRIQ_BITMAP_SIZE (DIV_ROUND_UP(K_NUM_THREAD_PRIO, 8 * sizeof(uint64_t))) -#else -#define PRIQ_BITMAP_SIZE (DIV_ROUND_UP(K_NUM_THREAD_PRIO, 8 * sizeof(uint32_t))) -#endif - +#define PRIQ_BITMAP_SIZE (DIV_ROUND_UP(K_NUM_THREAD_PRIO, BITS_PER_LONG)) #ifdef __cplusplus extern "C" { @@ -127,11 +121,7 @@ struct _priq_rb { */ struct _priq_mq { sys_dlist_t queues[K_NUM_THREAD_PRIO]; -#ifdef CONFIG_64BIT - uint64_t bitmask[PRIQ_BITMAP_SIZE]; -#else - uint32_t bitmask[PRIQ_BITMAP_SIZE]; -#endif + unsigned long bitmask[PRIQ_BITMAP_SIZE]; }; struct _ready_q { @@ -250,8 +240,8 @@ struct z_kernel { #endif #if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED) - /* Need to signal an IPI at the next scheduling point */ - bool pending_ipi; + /* Identify CPUs to send IPIs to at the next scheduling point */ + atomic_t pending_ipi; #endif }; diff --git a/include/zephyr/linker/common-ram.ld b/include/zephyr/linker/common-ram.ld index 0f750f93cd8b5..ecca31165a618 100644 --- a/include/zephyr/linker/common-ram.ld +++ b/include/zephyr/linker/common-ram.ld @@ -95,10 +95,6 @@ ITERABLE_SECTION_RAM(pcie_dev, Z_LINK_ITERABLE_SUBALIGN) #endif /* PCIE */ -#if defined(CONFIG_UART_MUX) - ITERABLE_SECTION_RAM(uart_mux, Z_LINK_ITERABLE_SUBALIGN) -#endif - #if defined(CONFIG_USB_DEVICE_STACK) SECTION_DATA_PROLOGUE(usb_descriptor,,SUBALIGN(1)) { diff --git a/include/zephyr/linker/common-rom.ld b/include/zephyr/linker/common-rom.ld index 8f9c89ebdd0c6..7653c1843d1f5 100644 --- a/include/zephyr/linker/common-rom.ld +++ b/include/zephyr/linker/common-rom.ld @@ -14,4 +14,6 @@ #include +#include + #include diff --git a/include/zephyr/linker/common-rom/common-rom-debug.ld b/include/zephyr/linker/common-rom/common-rom-debug.ld index 07d89ca606966..c5b32833a09a2 100644 --- a/include/zephyr/linker/common-rom/common-rom-debug.ld +++ b/include/zephyr/linker/common-rom/common-rom-debug.ld @@ -8,3 +8,10 @@ { KEEP(*(".dbg_thread_info")); } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) + +#ifdef CONFIG_SYMTAB + SECTION_PROLOGUE(symtab,,) + { + KEEP(*(_SYMTAB_SECTION_SYMS)) + } GROUP_ROM_LINK_IN(RAMABLE_REGION, ROMABLE_REGION) +#endif /* CONFIG_SYMTAB */ diff --git a/include/zephyr/linker/common-rom/common-rom-interrupt-controllers.ld b/include/zephyr/linker/common-rom/common-rom-interrupt-controllers.ld new file mode 100644 index 0000000000000..9ee9dace34188 --- /dev/null +++ b/include/zephyr/linker/common-rom/common-rom-interrupt-controllers.ld @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2024 Meta + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + ITERABLE_SECTION_ROM(intc_table, 4) diff --git a/include/zephyr/linker/common-rom/common-rom-net.ld b/include/zephyr/linker/common-rom/common-rom-net.ld index 95aeeb99e8933..5305f9cf873c2 100644 --- a/include/zephyr/linker/common-rom/common-rom-net.ld +++ b/include/zephyr/linker/common-rom/common-rom-net.ld @@ -16,7 +16,6 @@ #if defined(CONFIG_HTTP_SERVER) ITERABLE_SECTION_ROM(http_service_desc, Z_LINK_ITERABLE_SUBALIGN) - ITERABLE_SECTION_ROM(http_resource_desc, Z_LINK_ITERABLE_SUBALIGN) #endif #if defined(CONFIG_COAP_SERVER) diff --git a/include/zephyr/linker/kobject-data.ld b/include/zephyr/linker/kobject-data.ld index 26720dbff3388..573680b235e7e 100644 --- a/include/zephyr/linker/kobject-data.ld +++ b/include/zephyr/linker/kobject-data.ld @@ -30,7 +30,7 @@ */ #if defined(LINKER_ZEPHYR_PREBUILT) -#include +#include #ifdef CONFIG_DYNAMIC_OBJECTS /* This is produced by gperf. Put a place holder here @@ -45,7 +45,7 @@ #endif /* LINKER_ZEPHYR_PREBUILT */ #if defined(LINKER_ZEPHYR_FINAL) -#include +#include #ifdef KOBJECT_DATA_ALIGN . = ALIGN(KOBJECT_DATA_ALIGN); diff --git a/include/zephyr/linker/kobject-priv-stacks.ld b/include/zephyr/linker/kobject-priv-stacks.ld index 0da28763a2bf8..53bd508927e68 100644 --- a/include/zephyr/linker/kobject-priv-stacks.ld +++ b/include/zephyr/linker/kobject-priv-stacks.ld @@ -20,7 +20,7 @@ */ #if defined(LINKER_ZEPHYR_PREBUILT) -#include +#include #ifdef KOBJECT_PRIV_STACKS_ALIGN . = ALIGN(KOBJECT_PRIV_STACKS_ALIGN); . = . + KOBJECT_PRIV_STACKS_SZ; @@ -28,7 +28,7 @@ #endif /* LINKER_ZEPHYR_PREBUILT */ #if defined(LINKER_ZEPHYR_FINAL) -#include +#include #ifdef KOBJECT_PRIV_STACKS_ALIGN . = ALIGN(KOBJECT_PRIV_STACKS_ALIGN); #endif diff --git a/include/zephyr/linker/kobject-rom.ld b/include/zephyr/linker/kobject-rom.ld index 02c31e89987c3..1bb6ee10c15d2 100644 --- a/include/zephyr/linker/kobject-rom.ld +++ b/include/zephyr/linker/kobject-rom.ld @@ -16,7 +16,7 @@ */ #if defined(LINKER_ZEPHYR_PREBUILT) -#include +#include #ifdef KOBJECT_RODATA_ALIGN . = ALIGN(KOBJECT_RODATA_ALIGN); @@ -29,7 +29,7 @@ #endif /* LINKER_ZEPHYR_PREBUILT */ #if defined(LINKER_ZEPHYR_FINAL) -#include +#include #ifdef KOBJECT_RODATA_ALIGN . = ALIGN(KOBJECT_RODATA_ALIGN); diff --git a/include/zephyr/linker/linker-defs.h b/include/zephyr/linker/linker-defs.h index f2737c7f6f2c2..d860222ffac79 100644 --- a/include/zephyr/linker/linker-defs.h +++ b/include/zephyr/linker/linker-defs.h @@ -23,7 +23,7 @@ #include #include #include -#include +#include /* We need to dummy out DT_NODE_HAS_STATUS when building the unittests. * Including devicetree.h would require generating dummy header files @@ -159,7 +159,7 @@ extern char __gcov_bss_size[]; /* end address of image, used by newlib for the heap */ extern char _end[]; -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay) +#if (DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ccm), okay)) extern char __ccm_data_rom_start[]; extern char __ccm_start[]; extern char __ccm_data_start[]; @@ -171,14 +171,14 @@ extern char __ccm_noinit_end[]; extern char __ccm_end[]; #endif -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay) +#if (DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_itcm), okay)) extern char __itcm_start[]; extern char __itcm_end[]; extern char __itcm_size[]; extern char __itcm_load_start[]; #endif -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay) +#if (DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_dtcm), okay)) extern char __dtcm_data_start[]; extern char __dtcm_data_end[]; extern char __dtcm_bss_start[]; @@ -190,7 +190,7 @@ extern char __dtcm_start[]; extern char __dtcm_end[]; #endif -#if DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ocm), okay) +#if (DT_NODE_HAS_STATUS(DT_CHOSEN(zephyr_ocm), okay)) extern char __ocm_data_start[]; extern char __ocm_data_end[]; extern char __ocm_bss_start[]; @@ -292,7 +292,7 @@ extern char lnkr_boot_noinit_size[]; /* lnkr_pinned_start[] and lnkr_pinned_end[] must encapsulate * all the pinned sections as these are used by * the MMU code to mark the physical page frames with - * Z_PAGE_FRAME_PINNED. + * K_MEM_PAGE_FRAME_PINNED. */ extern char lnkr_pinned_start[]; extern char lnkr_pinned_end[]; diff --git a/include/zephyr/linker/linker-tool-gcc.h b/include/zephyr/linker/linker-tool-gcc.h index ab8a3ad7f9aaa..c2a004b8855c9 100644 --- a/include/zephyr/linker/linker-tool-gcc.h +++ b/include/zephyr/linker/linker-tool-gcc.h @@ -89,7 +89,7 @@ */ #if defined(CONFIG_ARCH_POSIX) #define GROUP_LINK_IN(where) -#elif !defined(Z_VM_KERNEL) +#elif !defined(K_MEM_IS_VM_KERNEL) #define GROUP_LINK_IN(where) > where #endif @@ -113,7 +113,7 @@ */ #if defined(CONFIG_ARCH_POSIX) #define GROUP_ROM_LINK_IN(vregion, lregion) -#elif defined(Z_VM_KERNEL) +#elif defined(K_MEM_IS_VM_KERNEL) #define GROUP_ROM_LINK_IN(vregion, lregion) > vregion AT > lregion #else #define GROUP_ROM_LINK_IN(vregion, lregion) > lregion @@ -133,7 +133,7 @@ */ #if defined(CONFIG_ARCH_POSIX) #define GROUP_DATA_LINK_IN(vregion, lregion) -#elif defined(CONFIG_XIP) || defined(Z_VM_KERNEL) +#elif defined(CONFIG_XIP) || defined(K_MEM_IS_VM_KERNEL) #define GROUP_DATA_LINK_IN(vregion, lregion) > vregion AT > lregion #else #define GROUP_DATA_LINK_IN(vregion, lregion) > vregion @@ -151,7 +151,7 @@ */ #if defined(CONFIG_ARCH_POSIX) #define GROUP_NOLOAD_LINK_IN(vregion, lregion) -#elif defined(Z_VM_KERNEL) +#elif defined(K_MEM_IS_VM_KERNEL) #define GROUP_NOLOAD_LINK_IN(vregion, lregion) > vregion AT > lregion #elif defined(CONFIG_XIP) #define GROUP_NOLOAD_LINK_IN(vregion, lregion) > vregion AT > vregion @@ -172,7 +172,7 @@ * @param align Alignment directives, such as SUBALIGN(). ALIGN() itself is * not allowed. May be blank. */ -#ifdef Z_VM_KERNEL +#ifdef K_MEM_IS_VM_KERNEL /* If we have a virtual memory map we need ALIGN_WITH_INPUT in all sections */ #define SECTION_PROLOGUE(name, options, align) \ name options : ALIGN_WITH_INPUT align diff --git a/include/zephyr/linker/llext-sections.ld b/include/zephyr/linker/llext-sections.ld new file mode 100644 index 0000000000000..b8cc32e3d1bf1 --- /dev/null +++ b/include/zephyr/linker/llext-sections.ld @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + + /* + * Special section used by LLEXT if CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID + * is enabled. Declare this section to prevent it from being considered orphan. + * + * This section is used to temporarily save the exported symbols' names in the + * Zephyr ELF for post-processing, but it is not included in the final binary. + * + * NOTE: This section MUST start at address 0, as the post-processing scripts + * assume that the address of any data in this section (i.e., symbol names) is + * strictly equivalent to the offset inside the section. + */ +#ifdef CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID + SECTION_PROLOGUE(llext_exports_strtab, 0 (COPY), ) + { + KEEP(*(llext_exports_strtab)) + } +#endif diff --git a/include/zephyr/linker/section_tags.h b/include/zephyr/linker/section_tags.h index 5678a07325bc6..6c7c1bdd6752b 100644 --- a/include/zephyr/linker/section_tags.h +++ b/include/zephyr/linker/section_tags.h @@ -103,6 +103,12 @@ #define __isr #endif +/* Symbol table section */ +#if defined(CONFIG_SYMTAB) +#define __symtab_info Z_GENERIC_SECTION(_SYMTAB_INFO_SECTION_NAME) +#define __symtab_entry Z_GENERIC_SECTION(_SYMTAB_ENTRY_SECTION_NAME) +#endif /* CONFIG_SYMTAB */ + #endif /* !_ASMLANGUAGE */ #endif /* ZEPHYR_INCLUDE_LINKER_SECTION_TAGS_H_ */ diff --git a/include/zephyr/linker/sections.h b/include/zephyr/linker/sections.h index 2f1049d09f318..14aa4c29894cb 100644 --- a/include/zephyr/linker/sections.h +++ b/include/zephyr/linker/sections.h @@ -77,6 +77,13 @@ #define _NOCACHE_SECTION_NAME nocache #endif +/* Symbol table section */ +#if defined(CONFIG_SYMTAB) +#define _SYMTAB_INFO_SECTION_NAME .gnu.linkonce.symtab.info +#define _SYMTAB_ENTRY_SECTION_NAME .gnu.linkonce.symtab.entry +#define _SYMTAB_SECTION_SYMS .gnu.linkonce.symtab* +#endif /* CONFIG_SYMTAB */ + #if defined(CONFIG_LINKER_USE_BOOT_SECTION) #define BOOT_TEXT_SECTION_NAME boot_text #define BOOT_BSS_SECTION_NAME boot_bss diff --git a/include/zephyr/llext/elf.h b/include/zephyr/llext/elf.h index edf83cae27175..b39af854312da 100644 --- a/include/zephyr/llext/elf.h +++ b/include/zephyr/llext/elf.h @@ -196,6 +196,7 @@ struct elf64_shdr { elf64_xword sh_entsize; }; +#define SHT_NULL 0x0 #define SHT_PROGBITS 0x1 #define SHT_SYMTAB 0x2 #define SHT_STRTAB 0x3 @@ -245,8 +246,10 @@ struct elf64_sym { }; #define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 #define SHN_ABS 0xfff1 #define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff #define STT_NOTYPE 0 #define STT_OBJECT 1 diff --git a/include/zephyr/llext/llext.h b/include/zephyr/llext/llext.h index 59a136ab5d4ef..acdca225721a5 100644 --- a/include/zephyr/llext/llext.h +++ b/include/zephyr/llext/llext.h @@ -124,6 +124,11 @@ int llext_iterate(int (*fn)(struct llext *ext, void *arg), void *arg); struct llext_load_param { /** Should local relocation be performed */ bool relocate_local; + /** + * Use the virtual symbol addresses from the ELF, not addresses within + * the memory buffer, where the object is loaded + */ + bool pre_located; }; #define LLEXT_LOAD_PARAM_DEFAULT {.relocate_local = true,} diff --git a/include/zephyr/llext/loader.h b/include/zephyr/llext/loader.h index b8477eb30039f..60f0e54058238 100644 --- a/include/zephyr/llext/loader.h +++ b/include/zephyr/llext/loader.h @@ -68,12 +68,11 @@ struct llext_loader { */ void *(*peek)(struct llext_loader *ldr, size_t pos); - /** Total calculated .data size for relocatable extensions */ - size_t prog_data_size; - /** @cond ignore */ elf_ehdr_t hdr; elf_shdr_t sects[LLEXT_MEM_COUNT]; + elf_shdr_t *sect_hdrs; + bool sect_hdrs_on_heap; enum llext_mem *sect_map; uint32_t sect_cnt; /** @endcond */ diff --git a/include/zephyr/llext/symbol.h b/include/zephyr/llext/symbol.h index e42dc37c9efa4..1eb90cb3f5e65 100644 --- a/include/zephyr/llext/symbol.h +++ b/include/zephyr/llext/symbol.h @@ -10,6 +10,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -27,14 +28,27 @@ extern "C" { * Symbols may be named function or global objects that have been exported * for linking. These constant symbols are useful in the base image * as they may be placed in ROM. + * + * @note When updating this structure, make sure to also update the + * 'scripts/build/llext_prepare_exptab.py' build script. */ struct llext_const_symbol { - /** Name of symbol */ - const char *const name; + /** At build time, we always write to 'name'. + * At runtime, which field is used depends + * on CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID. + */ + union { + /** Name of symbol */ + const char *const name; + + /** Symbol Link Identifier */ + const uintptr_t slid; + }; /** Address of symbol */ const void *const addr; }; +BUILD_ASSERT(sizeof(struct llext_const_symbol) == 2 * sizeof(uintptr_t)); /** * @brief Symbols are named memory addresses @@ -75,10 +89,21 @@ struct llext_symtable { * * @param x Symbol to export to extensions */ +#if defined(CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID) +#define EXPORT_SYMBOL(x) \ + static const char Z_GENERIC_SECTION("llext_exports_strtab") __used \ + x ## _sym_name[] = STRINGIFY(x); \ + static const STRUCT_SECTION_ITERABLE(llext_const_symbol, x ## _sym) = { \ + .name = x ## _sym_name, .addr = (const void *)&x, \ + } +#elif defined(CONFIG_LLEXT) #define EXPORT_SYMBOL(x) \ static const STRUCT_SECTION_ITERABLE(llext_const_symbol, x ## _sym) = { \ .name = STRINGIFY(x), .addr = (const void *)&x, \ } +#else +#define EXPORT_SYMBOL(x) +#endif /** * @brief Exports a symbol from an extension to the base image @@ -89,12 +114,16 @@ struct llext_symtable { * * @param x Extension symbol to export to the base image */ +#if defined(CONFIG_LLEXT) && defined(LL_EXTENSION_BUILD) #define LL_EXTENSION_SYMBOL(x) \ static const struct llext_const_symbol \ Z_GENERIC_SECTION(".exported_sym") __used \ x ## _sym = { \ .name = STRINGIFY(x), .addr = (const void *)&x, \ } +#else +#define LL_EXTENSION_SYMBOL(x) +#endif /** * @} diff --git a/include/zephyr/logging/log_ctrl.h b/include/zephyr/logging/log_ctrl.h index 56b0458c2ecf1..26d09589027be 100644 --- a/include/zephyr/logging/log_ctrl.h +++ b/include/zephyr/logging/log_ctrl.h @@ -47,6 +47,12 @@ void log_core_init(void); */ void log_init(void); +/** @brief Trigger the log processing thread to process logs immediately. + * + * @note Function has no effect when CONFIG_LOG_MODE_IMMEDIATE is set. + */ +void log_thread_trigger(void); + /** * @brief Function for providing thread which is processing logs. * @@ -295,7 +301,7 @@ int log_mem_get_max_usage(uint32_t *max); #define LOG_PROCESS() false #endif -#include +#include /** * @} diff --git a/include/zephyr/logging/log_msg.h b/include/zephyr/logging/log_msg.h index 2f6b3a04616d8..ed491c9e74229 100644 --- a/include/zephyr/logging/log_msg.h +++ b/include/zephyr/logging/log_msg.h @@ -857,7 +857,7 @@ static inline uint8_t *log_msg_get_package(struct log_msg *msg, size_t *len) * @} */ -#include +#include #ifdef __cplusplus } diff --git a/include/zephyr/mgmt/updatehub.h b/include/zephyr/mgmt/updatehub.h index 57e4b82b5dbe4..c37ba42390063 100644 --- a/include/zephyr/mgmt/updatehub.h +++ b/include/zephyr/mgmt/updatehub.h @@ -98,5 +98,5 @@ __syscall int updatehub_reboot(void); * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_MGMT_UPDATEHUB_H_ */ diff --git a/include/zephyr/modem/backend/uart.h b/include/zephyr/modem/backend/uart.h index 0280494e3502e..f68f411c6e222 100644 --- a/include/zephyr/modem/backend/uart.h +++ b/include/zephyr/modem/backend/uart.h @@ -12,6 +12,7 @@ #include #include +#include #ifndef ZEPHYR_MODEM_BACKEND_UART_ #define ZEPHYR_MODEM_BACKEND_UART_ @@ -24,6 +25,7 @@ struct modem_backend_uart_isr { struct ring_buf receive_rdb[2]; struct ring_buf transmit_rb; atomic_t transmit_buf_len; + atomic_t receive_buf_len; uint8_t receive_rdb_used; uint32_t transmit_buf_put_limit; }; @@ -45,6 +47,11 @@ struct modem_backend_uart { struct k_work_delayable receive_ready_work; struct k_work transmit_idle_work; +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; + struct modem_stats_buffer transmit_buf_stats; +#endif + union { struct modem_backend_uart_isr isr; struct modem_backend_uart_async async; diff --git a/include/zephyr/modem/chat.h b/include/zephyr/modem/chat.h index afb57c912fc2f..98778fb884172 100644 --- a/include/zephyr/modem/chat.h +++ b/include/zephyr/modem/chat.h @@ -10,6 +10,7 @@ #include #include +#include #ifndef ZEPHYR_MODEM_CHAT_ #define ZEPHYR_MODEM_CHAT_ @@ -44,9 +45,9 @@ struct modem_chat_match { /** Size of separators array */ uint8_t separators_size; /** Set if modem chat instance shall use wildcards when matching */ - uint8_t wildcards : 1; + bool wildcards; /** Set if script shall not continue to next step in case of match */ - uint8_t partial : 1; + bool partial; /** Type of modem chat instance */ modem_chat_match_callback callback; }; @@ -269,6 +270,12 @@ struct modem_chat { /* Process received data */ struct k_work receive_work; + + /* Statistics */ +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; + struct modem_stats_buffer work_buf_stats; +#endif }; /** @@ -369,6 +376,150 @@ void modem_chat_script_abort(struct modem_chat *chat); */ void modem_chat_release(struct modem_chat *chat); +/** + * @brief Initialize modem chat match + * @param chat_match Modem chat match instance + */ +void modem_chat_match_init(struct modem_chat_match *chat_match); + +/** + * @brief Set match of modem chat match instance + * @param chat_match Modem chat match instance + * @param match Match to set + * @note The lifetime of match must match or exceed the lifetime of chat_match + * @warning Always call this API after match is modified + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_match_set_match(struct modem_chat_match *chat_match, const char *match); + +/** + * @brief Set separators of modem chat match instance + * @param chat_match Modem chat match instance + * @param separators Separators to set + * @note The lifetime of separators must match or exceed the lifetime of chat_match + * @warning Always call this API after separators are modified + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_match_set_separators(struct modem_chat_match *chat_match, const char *separators); + +/** + * @brief Set modem chat match callback + * @param chat_match Modem chat match instance + * @param callback Callback to set + */ +void modem_chat_match_set_callback(struct modem_chat_match *chat_match, + modem_chat_match_callback callback); + +/** + * @brief Set modem chat match partial flag + * @param chat_match Modem chat match instance + * @param partial Partial flag to set + */ +void modem_chat_match_set_partial(struct modem_chat_match *chat_match, bool partial); + +/** + * @brief Set modem chat match wildcards flag + * @param chat_match Modem chat match instance + * @param enable Enable/disable Wildcards + */ +void modem_chat_match_enable_wildcards(struct modem_chat_match *chat_match, bool enable); + +/** + * @brief Initialize modem chat script chat + * @param script_chat Modem chat script chat instance + */ +void modem_chat_script_chat_init(struct modem_chat_script_chat *script_chat); + +/** + * @brief Set request of modem chat script chat instance + * @param script_chat Modem chat script chat instance + * @param request Request to set + * @note The lifetime of request must match or exceed the lifetime of script_chat + * @warning Always call this API after request is modified + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_script_chat_set_request(struct modem_chat_script_chat *script_chat, + const char *request); + +/** + * @brief Set modem chat script chat matches + * @param script_chat Modem chat script chat instance + * @param response_matches Response match array to set + * @param response_matches_size Size of response match array + * @note The lifetime of response_matches must match or exceed the lifetime of script_chat + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_script_chat_set_response_matches(struct modem_chat_script_chat *script_chat, + const struct modem_chat_match *response_matches, + uint16_t response_matches_size); + +/** + * @brief Set modem chat script chat timeout + * @param script_chat Modem chat script chat instance + * @param timeout_ms Timeout in milliseconds + */ +void modem_chat_script_chat_set_timeout(struct modem_chat_script_chat *script_chat, + uint16_t timeout_ms); + +/** + * @brief Initialize modem chat script + * @param script Modem chat script instance + */ +void modem_chat_script_init(struct modem_chat_script *script); + +/** + * @brief Set modem chat script name + * @param script Modem chat script instance + * @param name Name to set + * @note The lifetime of name must match or exceed the lifetime of script + */ +void modem_chat_script_set_name(struct modem_chat_script *script, const char *name); + +/** + * @brief Set modem chat script chats + * @param script Modem chat script instance + * @param script_chats Chat script array to set + * @param script_chats_size Size of chat script array + * @note The lifetime of script_chats must match or exceed the lifetime of script + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_script_set_script_chats(struct modem_chat_script *script, + const struct modem_chat_script_chat *script_chats, + uint16_t script_chats_size); + +/** + * @brief Set modem chat script abort matches + * @param script Modem chat script instance + * @param abort_matches Abort match array to set + * @param abort_matches_size Size of abort match array + * @note The lifetime of abort_matches must match or exceed the lifetime of script + * + * @retval 0 if successful, negative errno code otherwise + */ +int modem_chat_script_set_abort_matches(struct modem_chat_script *script, + const struct modem_chat_match *abort_matches, + uint16_t abort_matches_size); + +/** + * @brief Set modem chat script callback + * @param script Modem chat script instance + * @param callback Callback to set + */ +void modem_chat_script_set_callback(struct modem_chat_script *script, + modem_chat_script_callback callback); + +/** + * @brief Set modem chat script timeout + * @param script Modem chat script instance + * @param timeout_s Timeout in seconds + */ +void modem_chat_script_set_timeout(struct modem_chat_script *script, uint32_t timeout_s); + #ifdef __cplusplus } #endif diff --git a/include/zephyr/modem/cmux.h b/include/zephyr/modem/cmux.h index 57ee6a8505b8a..2e6990f5aa06d 100644 --- a/include/zephyr/modem/cmux.h +++ b/include/zephyr/modem/cmux.h @@ -25,6 +25,7 @@ #include #include +#include #ifndef ZEPHYR_MODEM_CMUX_ #define ZEPHYR_MODEM_CMUX_ @@ -102,6 +103,11 @@ struct modem_cmux_dlci { /* State */ enum modem_cmux_dlci_state state; + + /* Statistics */ +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; +#endif }; struct modem_cmux_frame { @@ -160,6 +166,12 @@ struct modem_cmux { /* Synchronize actions */ struct k_event event; + + /* Statistics */ +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; + struct modem_stats_buffer transmit_buf_stats; +#endif }; /** diff --git a/include/zephyr/modem/pipe.h b/include/zephyr/modem/pipe.h index 60e877e44a34a..9b19569251439 100644 --- a/include/zephyr/modem/pipe.h +++ b/include/zephyr/modem/pipe.h @@ -61,21 +61,13 @@ struct modem_pipe_api { modem_pipe_api_close close; }; -enum modem_pipe_state { - MODEM_PIPE_STATE_CLOSED = 0, - MODEM_PIPE_STATE_OPEN, -}; - struct modem_pipe { void *data; struct modem_pipe_api *api; modem_pipe_api_callback callback; void *user_data; - enum modem_pipe_state state; - struct k_mutex lock; - struct k_condvar condvar; - uint8_t receive_ready_pending : 1; - uint8_t transmit_idle_pending : 1; + struct k_spinlock spinlock; + struct k_event event; }; /** diff --git a/include/zephyr/modem/pipelink.h b/include/zephyr/modem/pipelink.h new file mode 100644 index 0000000000000..efe178861a328 --- /dev/null +++ b/include/zephyr/modem/pipelink.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#ifndef ZEPHYR_MODEM_PIPELINK_ +#define ZEPHYR_MODEM_PIPELINK_ + +/** Pipelink event */ +enum modem_pipelink_event { + /** Modem pipe has been connected and can be opened */ + MODEM_PIPELINK_EVENT_CONNECTED = 0, + /** Modem pipe has been disconnected and can't be opened */ + MODEM_PIPELINK_EVENT_DISCONNECTED, +}; + +/** @cond INTERNAL_HIDDEN */ + +/** Forward declaration */ +struct modem_pipelink; + +/** @endcond */ + +/** + * @brief Pipelink callback definition + * @param link Modem pipelink instance + * @param event Modem pipelink event + * @param user_data User data passed to modem_pipelink_attach() + */ +typedef void (*modem_pipelink_callback)(struct modem_pipelink *link, + enum modem_pipelink_event event, + void *user_data); + +/** @cond INTERNAL_HIDDEN */ + +/** Pipelink structure */ +struct modem_pipelink { + struct modem_pipe *pipe; + modem_pipelink_callback callback; + void *user_data; + bool connected; + struct k_spinlock spinlock; +}; + +/** @endcond */ + +/** + * @brief Attach callback to pipelink + * @param link Pipelink instance + * @param callback Pipelink callback + * @param user_data User data passed to pipelink callback + */ +void modem_pipelink_attach(struct modem_pipelink *link, + modem_pipelink_callback callback, + void *user_data); + +/** + * @brief Check whether pipelink pipe is connected + * @param link Pipelink instance + * @retval true if pipe is connected + * @retval false if pipe is not connected + */ +bool modem_pipelink_is_connected(struct modem_pipelink *link); + +/** + * @brief Get pipe from pipelink + * @param link Pipelink instance + * @retval Pointer to pipe if pipelink has been initialized + * @retval NULL if pipelink has not been initialized + */ +struct modem_pipe *modem_pipelink_get_pipe(struct modem_pipelink *link); + +/** + * @brief Clear callback + * @param link Pipelink instance + */ +void modem_pipelink_release(struct modem_pipelink *link); + +/** @cond INTERNAL_HIDDEN */ + +/** Initialize modem pipelink */ +void modem_pipelink_init(struct modem_pipelink *link, struct modem_pipe *pipe); + +/** Notify user of pipelink that pipe has been connected */ +void modem_pipelink_notify_connected(struct modem_pipelink *link); + +/** Notify user of pipelink that pipe has been disconnected */ +void modem_pipelink_notify_disconnected(struct modem_pipelink *link); + +/** @endcond */ + +/** @cond INTERNAL_HIDDEN */ + +/** + * @brief Synthesize pipelink symbol from devicetree node identifier and name + * @param node_id Devicetree node identifier + * @param name Pipelink name + */ +#define MODEM_PIPELINK_DT_SYM(node_id, name) \ + _CONCAT_4(__modem_pipelink_, DT_DEP_ORD(node_id), _, name) + +/** @endcond */ + +/** + * @brief Declare pipelink from devicetree node identifier and name + * @param node_id Devicetree node identifier + * @param name Pipelink name + */ +#define MODEM_PIPELINK_DT_DECLARE(node_id, name) \ + extern struct modem_pipelink MODEM_PIPELINK_DT_SYM(node_id, name) + +/** + * @brief Define pipelink from devicetree node identifier and name + * @param node_id Devicetree node identifier + * @param name Pipelink name + */ +#define MODEM_PIPELINK_DT_DEFINE(node_id, name) \ + struct modem_pipelink MODEM_PIPELINK_DT_SYM(node_id, name) + +/** + * @brief Get pointer to pipelink from devicetree node identifier and name + * @param node_id Devicetree node identifier + * @param name Pipelink name + */ +#define MODEM_PIPELINK_DT_GET(node_id, name) \ + (&MODEM_PIPELINK_DT_SYM(node_id, name)) + +/** + * @brief Device driver instance variants of MODEM_PIPELINK_DT macros + * @{ + */ + +#define MODEM_PIPELINK_DT_INST_DECLARE(inst, name) \ + MODEM_PIPELINK_DT_DECLARE(DT_DRV_INST(inst), name) + +#define MODEM_PIPELINK_DT_INST_DEFINE(inst, name) \ + MODEM_PIPELINK_DT_DEFINE(DT_DRV_INST(inst), name) + +#define MODEM_PIPELINK_DT_INST_GET(inst, name) \ + MODEM_PIPELINK_DT_GET(DT_DRV_INST(inst), name) + +/** @} */ + +#endif /* ZEPHYR_MODEM_PIPELINK_ */ diff --git a/include/zephyr/modem/ppp.h b/include/zephyr/modem/ppp.h index c0eca885fcdc3..799aac60b0b13 100644 --- a/include/zephyr/modem/ppp.h +++ b/include/zephyr/modem/ppp.h @@ -12,6 +12,7 @@ #include #include +#include #ifndef ZEPHYR_MODEM_PPP_ #define ZEPHYR_MODEM_PPP_ @@ -113,6 +114,11 @@ struct modem_ppp { #if defined(CONFIG_NET_STATISTICS_PPP) struct net_stats_ppp stats; #endif + +#if CONFIG_MODEM_STATS + struct modem_stats_buffer receive_buf_stats; + struct modem_stats_buffer transmit_buf_stats; +#endif }; /** diff --git a/include/zephyr/modem/stats.h b/include/zephyr/modem/stats.h new file mode 100644 index 0000000000000..23fb3eac50bc8 --- /dev/null +++ b/include/zephyr/modem/stats.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024 Trackunit Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#ifndef ZEPHYR_MODEM_STATS_ +#define ZEPHYR_MODEM_STATS_ + +/** + * @cond INTERNAL_HIDDEN + */ + +/** Modem statistics buffer structure */ +struct modem_stats_buffer { + sys_snode_t node; + char name[CONFIG_MODEM_STATS_BUFFER_NAME_SIZE]; + uint32_t max_used; + uint32_t size; +}; + +/** + * @endcond + */ + +/** + * @brief Initialize modem statistics buffer + * + * @param buffer Modem statistics buffer instance + * @param name Name of buffer instance + * @param size Size of buffer + */ +void modem_stats_buffer_init(struct modem_stats_buffer *buffer, + const char *name, uint32_t size); + +/** + * @brief Advertise modem statistics buffer size + * + * @param buffer Modem statistics buffer instance + * @param length Length of buffer + * + * @note Invoke when buffer size changes + * @note Safe to invoke from ISR + */ +void modem_stats_buffer_advertise_length(struct modem_stats_buffer *buffer, uint32_t length); + +#endif /* ZEPHYR_MODEM_STATS_ */ diff --git a/include/zephyr/net/buf.h b/include/zephyr/net/buf.h index 3af2782a442e7..2855017b28243 100644 --- a/include/zephyr/net/buf.h +++ b/include/zephyr/net/buf.h @@ -963,7 +963,7 @@ struct net_buf_simple_state { static inline void net_buf_simple_save(struct net_buf_simple *buf, struct net_buf_simple_state *state) { - state->offset = net_buf_simple_headroom(buf); + state->offset = (uint16_t)net_buf_simple_headroom(buf); state->len = buf->len; } @@ -1017,10 +1017,10 @@ struct net_buf { /** Where the buffer should go when freed up. */ uint8_t pool_id; - /* Size of user data on this buffer */ + /** Size of user data on this buffer */ uint8_t user_data_size; - /* Union for convenience access to the net_buf_simple members, also + /** Union for convenience access to the net_buf_simple members, also * preserving the old API. */ union { @@ -1042,13 +1042,17 @@ struct net_buf { uint8_t *__buf; }; + /** @cond INTERNAL_HIDDEN */ struct net_buf_simple b; + /** @endcond */ }; /** System metadata for this buffer. */ uint8_t user_data[] __net_buf_align; }; +/** @cond INTERNAL_HIDDEN */ + struct net_buf_data_cb { uint8_t * __must_check (*alloc)(struct net_buf *buf, size_t *size, k_timeout_t timeout); @@ -1062,6 +1066,8 @@ struct net_buf_data_alloc { size_t max_alloc_size; }; +/** @endcond */ + /** * @brief Network buffer pool representation. * @@ -1071,7 +1077,7 @@ struct net_buf_pool { /** LIFO to place the buffer into when free */ struct k_lifo free; - /* to prevent concurrent access/modifications */ + /** To prevent concurrent access/modifications */ struct k_spinlock lock; /** Number of buffers in pool */ @@ -1080,7 +1086,7 @@ struct net_buf_pool { /** Number of uninitialized buffers */ uint16_t uninit_count; - /* Size of user data allocated to this pool */ + /** Size of user data allocated to this pool */ uint8_t user_data_size; #if defined(CONFIG_NET_BUF_POOL_USAGE) @@ -1172,12 +1178,14 @@ extern const struct net_buf_data_alloc net_buf_heap_alloc; _net_buf_##_name, _count, _ud_size, \ _destroy) +/** @cond INTERNAL_HIDDEN */ + struct net_buf_pool_fixed { uint8_t *data_pool; }; -/** @cond INTERNAL_HIDDEN */ extern const struct net_buf_data_cb net_buf_fixed_cb; + /** @endcond */ /** diff --git a/include/zephyr/net/canbus.h b/include/zephyr/net/canbus.h index da5b6a3e067bf..1d7056a72ead7 100644 --- a/include/zephyr/net/canbus.h +++ b/include/zephyr/net/canbus.h @@ -4,8 +4,12 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_NET_CAN_H_ -#define ZEPHYR_INCLUDE_NET_CAN_H_ +/** @file + * @brief CAN bus socket API definitions. + */ + +#ifndef ZEPHYR_INCLUDE_NET_CANBUS_H_ +#define ZEPHYR_INCLUDE_NET_CANBUS_H_ #include #include @@ -52,4 +56,4 @@ BUILD_ASSERT(offsetof(struct canbus_api, iface_api) == 0); } #endif -#endif /* ZEPHYR_INCLUDE_NET_CAN_H_ */ +#endif /* ZEPHYR_INCLUDE_NET_CANBUS_H_ */ diff --git a/include/zephyr/net/capture.h b/include/zephyr/net/capture.h index 0d5a61c49113c..0a90e444f728e 100644 --- a/include/zephyr/net/capture.h +++ b/include/zephyr/net/capture.h @@ -271,7 +271,7 @@ struct net_capture_cooked { /** * @brief Initialize cooked mode capture context. * - * @param cooked Cooked context struct allocated by user. + * @param ctx Cooked context struct allocated by user. * @param hatype Link-layer address type * @param halen Link-layer address length (maximum is 8 bytes) * @param addr Link-layer address @@ -307,7 +307,7 @@ static inline int net_capture_cooked_setup(struct net_capture_cooked *ctx, * layer packets so that packet boundary is not lost. * * @param ctx Cooked mode capture context. - * @param buf Data to capture. + * @param data Data to capture. * @param len Length of the data. * @param type The direction and type of the packet (did we sent it etc). * @param ptype Protocol type id. These are the ETH_P_* types set in ethernet.h diff --git a/include/zephyr/net/coap.h b/include/zephyr/net/coap.h index bd47f92106ef1..c6714ee9dcb5a 100644 --- a/include/zephyr/net/coap.h +++ b/include/zephyr/net/coap.h @@ -82,12 +82,16 @@ enum coap_method { COAP_METHOD_IPATCH = 7, /**< IPATCH */ }; +/** @cond INTERNAL_HIDDEN */ + #define COAP_REQUEST_MASK 0x07 #define COAP_VERSION_1 1U #define COAP_OBSERVE_MAX_AGE 0xFFFFFF +/** @endcond */ + /** * @brief CoAP packets may be of one of these types. */ @@ -193,10 +197,14 @@ enum coap_response_code { COAP_MAKE_RESPONSE_CODE(5, 5) }; +/** @cond INTERNAL_HIDDEN */ + #define COAP_CODE_EMPTY (0) #define COAP_TOKEN_MAX_LEN 8UL +/** @endcond */ + /** * @brief Set of Content-Format option values for CoAP. * @@ -214,11 +222,15 @@ enum coap_content_format { COAP_CONTENT_FORMAT_APP_CBOR = 60 /**< application/cbor */ }; +/** @cond INTERNAL_HIDDEN */ + /* block option helper */ #define GET_BLOCK_NUM(v) ((v) >> 4) #define GET_BLOCK_SIZE(v) (((v) & 0x7)) #define GET_MORE(v) (!!((v) & 0x08)) +/** @endcond */ + struct coap_observer; struct coap_packet; struct coap_pending; @@ -251,10 +263,15 @@ typedef void (*coap_notify_t)(struct coap_resource *resource, struct coap_resource { /** Which function to be called for each CoAP method */ coap_method_t get, post, put, del, fetch, patch, ipatch; + /** Notify function to call */ coap_notify_t notify; + /** Resource path */ const char * const *path; + /** User specific opaque data */ void *user_data; + /** List of resource observers */ sys_slist_t observers; + /** Resource age */ int age; }; @@ -262,9 +279,13 @@ struct coap_resource { * @brief Represents a remote device that is observing a local resource. */ struct coap_observer { + /** Observer list node */ sys_snode_t list; + /** Observer connection end point information */ struct sockaddr addr; + /** Observer token */ uint8_t token[8]; + /** Extended token length */ uint8_t tkl; }; @@ -344,11 +365,17 @@ struct coap_pending { * also used when observing resources. */ struct coap_reply { + /** CoAP reply callback */ coap_reply_t reply; + /** User specific opaque data */ void *user_data; + /** Reply age */ int age; + /** Reply id */ uint16_t id; + /** Reply token */ uint8_t token[8]; + /** Extended token length */ uint8_t tkl; }; @@ -721,8 +748,11 @@ static inline enum coap_block_size coap_bytes_to_block_size(uint16_t bytes) * @brief Represents the current state of a block-wise transaction. */ struct coap_block_context { + /** Total size of the block-wise transaction */ size_t total_size; + /** Current size of the block-wise transaction */ size_t current; + /** Block size */ enum coap_block_size block_size; }; diff --git a/include/zephyr/net/coap_client.h b/include/zephyr/net/coap_client.h index 819559e9d936f..a3576a244c521 100644 --- a/include/zephyr/net/coap_client.h +++ b/include/zephyr/net/coap_client.h @@ -22,7 +22,7 @@ #include #include - +/** Maximum size of a CoAP message */ #define MAX_COAP_MSG_LEN (CONFIG_COAP_CLIENT_MESSAGE_HEADER_SIZE + \ CONFIG_COAP_CLIENT_MESSAGE_SIZE) @@ -67,12 +67,17 @@ struct coap_client_request { * @brief Representation of extra options for the CoAP client request */ struct coap_client_option { + /** Option code */ uint16_t code; #if defined(CONFIG_COAP_EXTENDED_OPTIONS_LEN) + /** Option len */ uint16_t len; + /** Buffer for the length */ uint8_t value[CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE]; #else + /** Option len */ uint8_t len; + /** Buffer for the length */ uint8_t value[12]; #endif }; @@ -84,12 +89,17 @@ struct coap_client_internal_request { uint32_t last_id; uint8_t request_tkl; bool request_ongoing; + atomic_t in_callback; struct coap_block_context recv_blk_ctx; struct coap_block_context send_blk_ctx; struct coap_pending pending; struct coap_client_request coap_request; struct coap_packet request; uint8_t request_tag[COAP_TOKEN_MAX_LEN]; + + /* For GETs with observe option set */ + bool is_observe; + int last_response_id; }; struct coap_client { @@ -147,7 +157,6 @@ int coap_client_req(struct coap_client *client, int sock, const struct sockaddr */ void coap_client_cancel_requests(struct coap_client *client); - /** * @} */ diff --git a/include/zephyr/net/coap_link_format.h b/include/zephyr/net/coap_link_format.h index cabfb9ff859d9..7c7c3c5f2f378 100644 --- a/include/zephyr/net/coap_link_format.h +++ b/include/zephyr/net/coap_link_format.h @@ -70,7 +70,9 @@ int coap_well_known_core_get_len(struct coap_resource *resources, * to a valid coap_core_metadata structure. */ struct coap_core_metadata { + /** List of attributes to add */ const char * const *attributes; + /** User specific data */ void *user_data; }; diff --git a/include/zephyr/net/coap_mgmt.h b/include/zephyr/net/coap_mgmt.h index f19eec6eb4b43..a52293a926583 100644 --- a/include/zephyr/net/coap_mgmt.h +++ b/include/zephyr/net/coap_mgmt.h @@ -38,8 +38,6 @@ struct coap_service; struct coap_resource; struct coap_observer; -/** @endcond */ - enum net_event_coap_cmd { /* Service events */ NET_EVENT_COAP_CMD_SERVICE_STARTED = 1, @@ -49,6 +47,8 @@ enum net_event_coap_cmd { NET_EVENT_COAP_CMD_OBSERVER_REMOVED, }; +/** @endcond */ + /** * @brief coap_mgmt event raised when a service has started */ @@ -77,7 +77,7 @@ enum net_event_coap_cmd { * @brief CoAP Service event structure. */ struct net_event_coap_service { - /* The CoAP service for which the event is emitted */ + /** The CoAP service for which the event is emitted */ const struct coap_service *service; }; @@ -85,9 +85,9 @@ struct net_event_coap_service { * @brief CoAP Observer event structure. */ struct net_event_coap_observer { - /* The CoAP resource for which the event is emitted */ + /** The CoAP resource for which the event is emitted */ struct coap_resource *resource; - /* The observer that is added/removed */ + /** The observer that is added/removed */ struct coap_observer *observer; }; diff --git a/include/zephyr/net/conn_mgr_connectivity.h b/include/zephyr/net/conn_mgr_connectivity.h index d083509b437bc..048f40124de8a 100644 --- a/include/zephyr/net/conn_mgr_connectivity.h +++ b/include/zephyr/net/conn_mgr_connectivity.h @@ -41,13 +41,13 @@ extern "C" { NET_MGMT_EVENT_BIT) #define _NET_MGMT_CONN_IF_EVENT (NET_MGMT_IFACE_BIT | _NET_MGMT_CONN_BASE) -/** @endcond */ - enum net_event_conn_cmd { NET_EVENT_CONN_CMD_IF_TIMEOUT = 1, NET_EVENT_CONN_CMD_IF_FATAL_ERROR, }; +/** @endcond */ + /** * @brief net_mgmt event raised when a connection attempt times out */ diff --git a/include/zephyr/net/conn_mgr_monitor.h b/include/zephyr/net/conn_mgr_monitor.h index 94c50d90f1911..16a873b7b2f1d 100644 --- a/include/zephyr/net/conn_mgr_monitor.h +++ b/include/zephyr/net/conn_mgr_monitor.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief API for monitoring network connections and interfaces. + */ + #ifndef ZEPHYR_INCLUDE_CONN_MGR_H_ #define ZEPHYR_INCLUDE_CONN_MGR_H_ diff --git a/include/zephyr/net/dhcpv4.h b/include/zephyr/net/dhcpv4.h index b06a7cb0320a5..925c4e13568ac 100644 --- a/include/zephyr/net/dhcpv4.h +++ b/include/zephyr/net/dhcpv4.h @@ -40,6 +40,7 @@ enum net_dhcpv4_state { NET_DHCPV4_RENEWING, NET_DHCPV4_REBINDING, NET_DHCPV4_BOUND, + NET_DHCPV4_DECLINE, } __packed; /** @endcond */ @@ -54,14 +55,14 @@ enum net_dhcpv4_state { * within corresponding changes to net_dhcpv4_msg_type_name. */ enum net_dhcpv4_msg_type { - NET_DHCPV4_MSG_TYPE_DISCOVER = 1, - NET_DHCPV4_MSG_TYPE_OFFER = 2, - NET_DHCPV4_MSG_TYPE_REQUEST = 3, - NET_DHCPV4_MSG_TYPE_DECLINE = 4, - NET_DHCPV4_MSG_TYPE_ACK = 5, - NET_DHCPV4_MSG_TYPE_NAK = 6, - NET_DHCPV4_MSG_TYPE_RELEASE = 7, - NET_DHCPV4_MSG_TYPE_INFORM = 8, + NET_DHCPV4_MSG_TYPE_DISCOVER = 1, /**< Discover message */ + NET_DHCPV4_MSG_TYPE_OFFER = 2, /**< Offer message */ + NET_DHCPV4_MSG_TYPE_REQUEST = 3, /**< Request message */ + NET_DHCPV4_MSG_TYPE_DECLINE = 4, /**< Decline message */ + NET_DHCPV4_MSG_TYPE_ACK = 5, /**< Acknowledge message */ + NET_DHCPV4_MSG_TYPE_NAK = 6, /**< Negative acknowledge message */ + NET_DHCPV4_MSG_TYPE_RELEASE = 7, /**< Release message */ + NET_DHCPV4_MSG_TYPE_INFORM = 8, /**< Inform message */ }; struct net_dhcpv4_option_callback; diff --git a/include/zephyr/net/dns_resolve.h b/include/zephyr/net/dns_resolve.h index 46e5ad8e4df06..36983f0b09927 100644 --- a/include/zephyr/net/dns_resolve.h +++ b/include/zephyr/net/dns_resolve.h @@ -13,8 +13,10 @@ #ifndef ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_ #define ZEPHYR_INCLUDE_NET_DNS_RESOLVE_H_ +#include #include -#include +#include +#include #ifdef __cplusplus extern "C" { @@ -44,14 +46,36 @@ enum dns_query_type { /** @cond INTERNAL_HIDDEN */ +#define DNS_BUF_TIMEOUT K_MSEC(500) /* ms */ + +/* This value is recommended by RFC 1035 */ +#define DNS_RESOLVER_MAX_BUF_SIZE 512 + /* Make sure that we can compile things even if CONFIG_DNS_RESOLVER * is not enabled. */ -#if !defined(CONFIG_DNS_RESOLVER_MAX_SERVERS) -#define CONFIG_DNS_RESOLVER_MAX_SERVERS 1 +#if defined(CONFIG_DNS_RESOLVER_MAX_SERVERS) +#define DNS_RESOLVER_MAX_SERVERS CONFIG_DNS_RESOLVER_MAX_SERVERS +#else +#define DNS_RESOLVER_MAX_SERVERS 0 +#endif + +#if defined(CONFIG_DNS_NUM_CONCUR_QUERIES) +#define DNS_NUM_CONCUR_QUERIES CONFIG_DNS_NUM_CONCUR_QUERIES +#else +#define DNS_NUM_CONCUR_QUERIES 1 #endif -#if !defined(CONFIG_DNS_NUM_CONCUR_QUERIES) -#define CONFIG_DNS_NUM_CONCUR_QUERIES 1 + +#if defined(CONFIG_NET_IF_MAX_IPV6_COUNT) +#define MAX_IPV6_IFACE_COUNT CONFIG_NET_IF_MAX_IPV6_COUNT +#else +#define MAX_IPV6_IFACE_COUNT 1 +#endif + +#if defined(CONFIG_NET_IF_MAX_IPV4_COUNT) +#define MAX_IPV4_IFACE_COUNT CONFIG_NET_IF_MAX_IPV4_COUNT +#else +#define MAX_IPV4_IFACE_COUNT 1 #endif /* If mDNS is enabled, then add some extra well known multicast servers to the @@ -82,15 +106,152 @@ enum dns_query_type { #define DNS_MAX_MCAST_SERVERS (MDNS_SERVER_COUNT + LLMNR_SERVER_COUNT) +#if defined(CONFIG_MDNS_RESPONDER) +#if defined(CONFIG_NET_IPV6) +#define MDNS_MAX_IPV6_IFACE_COUNT CONFIG_NET_IF_MAX_IPV6_COUNT +#else +#define MDNS_MAX_IPV6_IFACE_COUNT 0 +#endif /* CONFIG_NET_IPV6 */ + +#if defined(CONFIG_NET_IPV4) +#define MDNS_MAX_IPV4_IFACE_COUNT CONFIG_NET_IF_MAX_IPV4_COUNT +#else +#define MDNS_MAX_IPV4_IFACE_COUNT 0 +#endif /* CONFIG_NET_IPV4 */ + +#define MDNS_MAX_POLL (MDNS_MAX_IPV4_IFACE_COUNT + MDNS_MAX_IPV6_IFACE_COUNT) +#else +#define MDNS_MAX_POLL 0 +#endif /* CONFIG_MDNS_RESPONDER */ + +#if defined(CONFIG_LLMNR_RESPONDER) +#if defined(CONFIG_NET_IPV6) && defined(CONFIG_NET_IPV4) +#define LLMNR_MAX_POLL 2 +#else +#define LLMNR_MAX_POLL 1 +#endif +#else +#define LLMNR_MAX_POLL 0 +#endif /* CONFIG_LLMNR_RESPONDER */ + +#define DNS_RESOLVER_MAX_POLL (DNS_RESOLVER_MAX_SERVERS + DNS_MAX_MCAST_SERVERS) + +/** How many sockets the dispatcher is able to poll. */ +#define DNS_DISPATCHER_MAX_POLL (DNS_RESOLVER_MAX_POLL + MDNS_MAX_POLL + LLMNR_MAX_POLL) + +#if defined(CONFIG_NET_SOCKETS_POLL_MAX) +BUILD_ASSERT(CONFIG_NET_SOCKETS_POLL_MAX >= DNS_DISPATCHER_MAX_POLL, + "CONFIG_NET_SOCKETS_POLL_MAX must be larger than " STRINGIFY(DNS_DISPATCHER_MAX_POLL)); +#endif + +/** @brief What is the type of the socket given to DNS socket dispatcher, + * resolver or responder. + */ +enum dns_socket_type { + DNS_SOCKET_RESOLVER = 1, /**< Socket is used for resolving (client type) */ + DNS_SOCKET_RESPONDER = 2 /**< Socket is used for responding (server type) */ +}; + +struct dns_resolve_context; +struct mdns_responder_context; + +/** + * @typedef dns_socket_dispatcher_cb + * @brief Callback used when the DNS socket dispatcher has found a handler for + * this type of socket. + * + * @param ctx DNS resolve or mDNS responder context. + * @param sock Socket which is seeing traffic. + * @param addr Socket address of the peer that sent the DNS packet. + * @param addrlen Length of the socket address. + * @param buf Pointer to data buffer containing the DNS message. + * @param data_len Length of the data in buffer chain. + * + * @return 0 if ok, <0 if error + */ +typedef int (*dns_socket_dispatcher_cb)(void *ctx, int sock, + struct sockaddr *addr, size_t addrlen, + struct net_buf *buf, size_t data_len); + +/** @brief DNS socket dispatcher context. */ +struct dns_socket_dispatcher { + /** slist node for the different dispatcher contexts */ + sys_snode_t node; + /** Socket service for this dispatcher instance */ + const struct net_socket_service_desc *svc; + /** DNS resolver context that contains information needed by the + * resolver/responder handler, or mDNS responder context. + */ + union { + void *ctx; + struct dns_resolve_context *resolve_ctx; + struct mdns_responder_context *mdns_ctx; + }; + + /** Type of the socket (resolver / responder) */ + enum dns_socket_type type; + /** Local endpoint address (used when binding the socket) */ + struct sockaddr local_addr; + /** DNS socket dispatcher callback is called for incoming traffic */ + dns_socket_dispatcher_cb cb; + /** Socket descriptors to poll */ + struct zsock_pollfd *fds; + /** Length of the poll array */ + int fds_len; + /** Local socket to dispatch */ + int sock; + /** There can be two contexts to dispatch. This points to the other + * context if sharing the socket between resolver / responder. + */ + struct dns_socket_dispatcher *pair; + /** Mutex lock protecting access to this dispatcher context */ + struct k_mutex lock; + /** Buffer allocation timeout */ + k_timeout_t buf_timeout; +}; + +struct mdns_responder_context { + struct sockaddr server_addr; + struct dns_socket_dispatcher dispatcher; + struct zsock_pollfd fds[1]; + int sock; +}; + +/** + * @brief Register a DNS dispatcher socket. Each code wanting to use + * the dispatcher needs to create the dispatcher context and call + * this function. + * + * @param ctx DNS socket dispatcher context. + * + * @return 0 if ok, <1 if error + */ +int dns_dispatcher_register(struct dns_socket_dispatcher *ctx); + +/** + * @brief Unregister a DNS dispatcher socket. Called when the + * resolver/responder no longer needs to receive traffic for the + * socket. + * + * @param ctx DNS socket dispatcher context. + * + * @return 0 if ok, <1 if error + */ +int dns_dispatcher_unregister(struct dns_socket_dispatcher *ctx); + /** @endcond */ /** * Address info struct is passed to callback that gets all the results. */ struct dns_addrinfo { + /** IP address information */ struct sockaddr ai_addr; + /** Length of the ai_addr field */ socklen_t ai_addrlen; - uint8_t ai_family; + /** Address family of the address information */ + uint8_t ai_family; + /** Canonical name of the address */ char ai_canonname[DNS_MAX_NAME_SIZE + 1]; }; @@ -157,29 +318,44 @@ typedef void (*dns_resolve_cb_t)(enum dns_resolve_status status, struct dns_addrinfo *info, void *user_data); +/** @cond INTERNAL_HIDDEN */ + enum dns_resolve_context_state { DNS_RESOLVE_CONTEXT_ACTIVE, DNS_RESOLVE_CONTEXT_DEACTIVATING, DNS_RESOLVE_CONTEXT_INACTIVE, }; +/** @endcond */ + /** * DNS resolve context structure. */ struct dns_resolve_context { - struct { + /** List of configured DNS servers */ + struct dns_server { /** DNS server information */ struct sockaddr dns_server; /** Connection to the DNS server */ - struct net_context *net_ctx; + int sock; /** Is this server mDNS one */ uint8_t is_mdns : 1; /** Is this server LLMNR one */ uint8_t is_llmnr : 1; - } servers[CONFIG_DNS_RESOLVER_MAX_SERVERS + DNS_MAX_MCAST_SERVERS]; + +/** @cond INTERNAL_HIDDEN */ + /** Dispatch DNS data between resolver and responder */ + struct dns_socket_dispatcher dispatcher; +/** @endcond */ + } servers[DNS_RESOLVER_MAX_POLL]; + +/** @cond INTERNAL_HIDDEN */ + /** Socket polling for each server connection */ + struct zsock_pollfd fds[DNS_RESOLVER_MAX_POLL]; +/** @endcond */ /** Prevent concurrent access */ struct k_mutex lock; @@ -240,7 +416,7 @@ struct dns_resolve_context { * cannot be used to find correct pending query. */ uint16_t query_hash; - } queries[CONFIG_DNS_NUM_CONCUR_QUERIES]; + } queries[DNS_NUM_CONCUR_QUERIES]; /** Is this context in use */ enum dns_resolve_context_state state; diff --git a/include/zephyr/net/dsa.h b/include/zephyr/net/dsa.h index 479690509a3f2..1aed17e11baad 100644 --- a/include/zephyr/net/dsa.h +++ b/include/zephyr/net/dsa.h @@ -21,6 +21,8 @@ * @{ */ +/** @cond INTERNAL_HIDDEN */ + #define NET_DSA_PORT_MAX_COUNT 8 #define DSA_STATUS_PERIOD_MS K_MSEC(1000) @@ -34,6 +36,8 @@ #define DSA_TAG_SIZE 0 #endif +/** @endcond */ + #ifdef __cplusplus extern "C" { #endif diff --git a/include/zephyr/net/dummy.h b/include/zephyr/net/dummy.h index bcf250a341cb9..4c5fe0312349b 100644 --- a/include/zephyr/net/dummy.h +++ b/include/zephyr/net/dummy.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** @file + * @brief Dummy layer 2 + * + * This is not to be included by the application. + */ #ifndef ZEPHYR_INCLUDE_NET_DUMMY_H_ #define ZEPHYR_INCLUDE_NET_DUMMY_H_ @@ -22,6 +27,7 @@ extern "C" { * @{ */ +/** Dummy L2 API operations. */ struct dummy_api { /** * The net_if_api must be placed in first position in this diff --git a/include/zephyr/net/ethernet.h b/include/zephyr/net/ethernet.h index 9ecc7340d03e7..5918f5ddf826b 100644 --- a/include/zephyr/net/ethernet.h +++ b/include/zephyr/net/ethernet.h @@ -20,11 +20,7 @@ #include #include - -#if defined(CONFIG_NET_LLDP) #include -#endif - #include #include #include @@ -49,14 +45,15 @@ extern "C" { * @{ */ -#define NET_ETH_ADDR_LEN 6U - -/** @cond INTERNAL_HIDDEN */ +#define NET_ETH_ADDR_LEN 6U /**< Ethernet MAC address length */ +/** Ethernet address */ struct net_eth_addr { - uint8_t addr[NET_ETH_ADDR_LEN]; + uint8_t addr[NET_ETH_ADDR_LEN]; /**< Buffer storing the address */ }; +/** @cond INTERNAL_HIDDEN */ + #define NET_ETH_HDR(pkt) ((struct net_eth_hdr *)net_pkt_data(pkt)) #define NET_ETH_PTYPE_CAN 0x000C /* CAN: Controller Area Network */ @@ -108,8 +105,12 @@ struct net_eth_addr { #define ETH_P_HDLC NET_ETH_PTYPE_HDLC #endif -#define NET_ETH_MINIMAL_FRAME_SIZE 60 -#define NET_ETH_MTU 1500 +/** @endcond */ + +#define NET_ETH_MINIMAL_FRAME_SIZE 60 /**< Minimum Ethernet frame size */ +#define NET_ETH_MTU 1500 /**< Ethernet MTU size */ + +/** @cond INTERNAL_HIDDEN */ #if defined(CONFIG_NET_VLAN) #define _NET_ETH_MAX_HDR_SIZE (sizeof(struct net_eth_vlan_hdr)) @@ -134,7 +135,7 @@ struct net_eth_addr { /** @endcond */ -/** Ethernet hardware capabilities */ +/** @brief Ethernet hardware capabilities */ enum ethernet_hw_caps { /** TX Checksum offloading supported for all of IPv4, UDP, TCP */ ETHERNET_HW_TX_CHKSUM_OFFLOAD = BIT(0), @@ -181,8 +182,10 @@ enum ethernet_hw_caps { /** VLAN Tag stripping */ ETHERNET_HW_VLAN_TAG_STRIP = BIT(14), - /** DSA switch */ - ETHERNET_DSA_SLAVE_PORT = BIT(15), + /** DSA switch slave port */ + ETHERNET_DSA_SLAVE_PORT = BIT(15), + + /** DSA switch master port */ ETHERNET_DSA_MASTER_PORT = BIT(16), /** IEEE 802.1Qbv (scheduled traffic) supported */ @@ -215,6 +218,8 @@ enum ethernet_config_type { ETHERNET_CONFIG_TYPE_PORTS_NUM, ETHERNET_CONFIG_TYPE_T1S_PARAM, ETHERNET_CONFIG_TYPE_TXINJECTION_MODE, + ETHERNET_CONFIG_TYPE_RX_CHECKSUM_SUPPORT, + ETHERNET_CONFIG_TYPE_TX_CHECKSUM_SUPPORT }; enum ethernet_qav_param_type { @@ -230,11 +235,14 @@ enum ethernet_t1s_param_type { }; /** @endcond */ + +/** Ethernet T1S specific parameters */ struct ethernet_t1s_param { /** Type of T1S parameter */ enum ethernet_t1s_param_type type; union { - /* PLCA is the Physical Layer (PHY) Collision + /** + * PLCA is the Physical Layer (PHY) Collision * Avoidance technique employed with multidrop * 10Base-T1S standard. * @@ -273,6 +281,7 @@ struct ethernet_t1s_param { }; }; +/** Ethernet Qav specific parameters */ struct ethernet_qav_param { /** ID of the priority queue to use */ int queue_id; @@ -314,6 +323,7 @@ enum ethernet_gate_state_operation { /** @endcond */ +/** Ethernet Qbv specific parameters */ struct ethernet_qbv_param { /** Port id */ int port_id; @@ -325,6 +335,7 @@ struct ethernet_qbv_param { /** True if Qbv is enabled or not */ bool enabled; + /** Gate control information */ struct { /** True = open, False = closed */ bool gate_status[NET_TC_TX_COUNT]; @@ -342,7 +353,8 @@ struct ethernet_qbv_param { /** Number of entries in gate control list */ uint32_t gate_control_list_len; - /* The time values are set in one go when type is set to + /** + * The time values are set in one go when type is set to * ETHERNET_QBV_PARAM_TYPE_TIME */ struct { @@ -378,6 +390,7 @@ enum ethernet_qbu_preempt_status { /** @endcond */ +/** Ethernet Qbu specific parameters */ struct ethernet_qbu_param { /** Port id */ int port_id; @@ -390,8 +403,7 @@ struct ethernet_qbu_param { /** Release advance (nanoseconds) */ uint32_t release_advance; - /** sequence of framePreemptionAdminStatus values. - */ + /** sequence of framePreemptionAdminStatus values */ enum ethernet_qbu_preempt_status frame_preempt_statuses[NET_TC_TX_COUNT]; @@ -401,14 +413,14 @@ struct ethernet_qbu_param { /** Link partner status (from Qbr) */ bool link_partner_status; - /** Additional fragment size (from Qbr). The minimum non-final + /** + * Additional fragment size (from Qbr). The minimum non-final * fragment size is (additional_fragment_size + 1) * 64 octets */ uint8_t additional_fragment_size : 2; }; }; - /** @cond INTERNAL_HIDDEN */ enum ethernet_filter_type { @@ -427,7 +439,7 @@ enum ethernet_if_types { L2_ETH_IF_TYPE_WIFI, } __packed; - +/** Ethernet filter description */ struct ethernet_filter { /** Type of filter */ enum ethernet_filter_type type; @@ -445,6 +457,7 @@ enum ethernet_txtime_param_type { /** @endcond */ +/** Ethernet TXTIME specific parameters */ struct ethernet_txtime_param { /** Type of TXTIME parameter */ enum ethernet_txtime_param_type type; @@ -454,7 +467,26 @@ struct ethernet_txtime_param { bool enable_txtime; }; +/** Protocols that are supported by checksum offloading */ +enum ethernet_checksum_support { + /** Device does not support any L3/L4 checksum offloading */ + ETHERNET_CHECKSUM_SUPPORT_NONE = NET_IF_CHECKSUM_NONE_BIT, + /** Device supports checksum offloading for the IPv4 header */ + ETHERNET_CHECKSUM_SUPPORT_IPV4_HEADER = NET_IF_CHECKSUM_IPV4_HEADER_BIT, + /** Device supports checksum offloading for ICMPv4 payload (implies IPv4 header) */ + ETHERNET_CHECKSUM_SUPPORT_IPV4_ICMP = NET_IF_CHECKSUM_IPV4_ICMP_BIT, + /** Device supports checksum offloading for the IPv6 header */ + ETHERNET_CHECKSUM_SUPPORT_IPV6_HEADER = NET_IF_CHECKSUM_IPV6_HEADER_BIT, + /** Device supports checksum offloading for ICMPv6 payload (implies IPv6 header) */ + ETHERNET_CHECKSUM_SUPPORT_IPV6_ICMP = NET_IF_CHECKSUM_IPV6_ICMP_BIT, + /** Device supports TCP checksum offloading for all supported IP protocols */ + ETHERNET_CHECKSUM_SUPPORT_TCP = NET_IF_CHECKSUM_TCP_BIT, + /** Device supports UDP checksum offloading for all supported IP protocols */ + ETHERNET_CHECKSUM_SUPPORT_UDP = NET_IF_CHECKSUM_UDP_BIT, +}; + /** @cond INTERNAL_HIDDEN */ + struct ethernet_config { union { bool auto_negotiation; @@ -479,11 +511,15 @@ struct ethernet_config { int priority_queues_num; int ports_num; + enum ethernet_checksum_support chksum_support; + struct ethernet_filter filter; }; }; + /** @endcond */ +/** Ethernet L2 API operations. */ struct ethernet_api { /** * The net_if_api must be placed in first position in this @@ -491,11 +527,11 @@ struct ethernet_api { */ struct net_if_api iface_api; -#if defined(CONFIG_NET_STATISTICS_ETHERNET) /** Collect optional ethernet specific statistics. This pointer * should be set by driver if statistics needs to be collected * for that driver. */ +#if defined(CONFIG_NET_STATISTICS_ETHERNET) struct net_stats_eth *(*get_stats)(const struct device *dev); #endif @@ -518,18 +554,18 @@ struct ethernet_api { enum ethernet_config_type type, struct ethernet_config *config); -#if defined(CONFIG_NET_VLAN) /** The IP stack will call this function when a VLAN tag is enabled * or disabled. If enable is set to true, then the VLAN tag was added, * if it is false then the tag was removed. The driver can utilize * this information if needed. */ +#if defined(CONFIG_NET_VLAN) int (*vlan_setup)(const struct device *dev, struct net_if *iface, uint16_t tag, bool enable); #endif /* CONFIG_NET_VLAN */ -#if defined(CONFIG_PTP_CLOCK) /** Return ptp_clock device that is tied to this ethernet device */ +#if defined(CONFIG_PTP_CLOCK) const struct device *(*get_ptp_clock)(const struct device *dev); #endif /* CONFIG_PTP_CLOCK */ @@ -537,12 +573,13 @@ struct ethernet_api { int (*send)(const struct device *dev, struct net_pkt *pkt); }; +/** @cond INTERNAL_HIDDEN */ + /* Make sure that the network interface API is properly setup inside * Ethernet API struct (it is the first one). */ BUILD_ASSERT(offsetof(struct ethernet_api, iface_api) == 0); -/** @cond INTERNAL_HIDDEN */ struct net_eth_hdr { struct net_eth_addr dst; struct net_eth_addr src; @@ -567,7 +604,7 @@ struct ethernet_vlan { /** @endcond */ -#if defined(CONFIG_NET_LLDP) +/** Ethernet LLDP specific parameters */ struct ethernet_lldp { /** Used for track timers */ sys_snode_t node; @@ -593,7 +630,8 @@ struct ethernet_lldp { /** LLDP RX callback function */ net_lldp_recv_cb_t cb; }; -#endif /* CONFIG_NET_LLDP */ + +/** @cond INTERNAL_HIDDEN */ enum ethernet_flags { ETH_CARRIER_UP, @@ -671,8 +709,6 @@ struct ethernet_context { */ void ethernet_init(struct net_if *iface); -/** @cond INTERNAL_HIDDEN */ - #define ETHERNET_L2_CTX_TYPE struct ethernet_context /* Separate header for VLAN as some of device interfaces might not @@ -688,7 +724,15 @@ struct net_eth_vlan_hdr { uint16_t type; } __packed; +/** @endcond */ +/** + * @brief Check if the Ethernet MAC address is a broadcast address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a broadcast address, false if not + */ static inline bool net_eth_is_addr_broadcast(struct net_eth_addr *addr) { if (addr->addr[0] == 0xff && @@ -703,6 +747,34 @@ static inline bool net_eth_is_addr_broadcast(struct net_eth_addr *addr) return false; } +/** + * @brief Check if the Ethernet MAC address is a all zeroes address. + * + * @param addr A valid pointer to an Ethernet MAC address. + * + * @return true if address is an all zeroes address, false if not + */ +static inline bool net_eth_is_addr_all_zeroes(struct net_eth_addr *addr) +{ + if (addr->addr[0] == 0x00 && + addr->addr[1] == 0x00 && + addr->addr[2] == 0x00 && + addr->addr[3] == 0x00 && + addr->addr[4] == 0x00 && + addr->addr[5] == 0x00) { + return true; + } + + return false; +} + +/** + * @brief Check if the Ethernet MAC address is unspecified. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is unspecified, false if not + */ static inline bool net_eth_is_addr_unspecified(struct net_eth_addr *addr) { if (addr->addr[0] == 0x00 && @@ -717,6 +789,13 @@ static inline bool net_eth_is_addr_unspecified(struct net_eth_addr *addr) return false; } +/** + * @brief Check if the Ethernet MAC address is a multicast address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a multicast address, false if not + */ static inline bool net_eth_is_addr_multicast(struct net_eth_addr *addr) { #if defined(CONFIG_NET_IPV6) @@ -737,16 +816,37 @@ static inline bool net_eth_is_addr_multicast(struct net_eth_addr *addr) return false; } +/** + * @brief Check if the Ethernet MAC address is a group address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a group address, false if not + */ static inline bool net_eth_is_addr_group(struct net_eth_addr *addr) { return addr->addr[0] & 0x01; } +/** + * @brief Check if the Ethernet MAC address is valid. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is valid, false if not + */ static inline bool net_eth_is_addr_valid(struct net_eth_addr *addr) { return !net_eth_is_addr_unspecified(addr) && !net_eth_is_addr_group(addr); } +/** + * @brief Check if the Ethernet MAC address is a LLDP multicast address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a LLDP multicast address, false if not + */ static inline bool net_eth_is_addr_lldp_multicast(struct net_eth_addr *addr) { #if defined(CONFIG_NET_GPTP) || defined(CONFIG_NET_LLDP) @@ -758,11 +858,20 @@ static inline bool net_eth_is_addr_lldp_multicast(struct net_eth_addr *addr) addr->addr[5] == 0x0e) { return true; } +#else + ARG_UNUSED(addr); #endif return false; } +/** + * @brief Check if the Ethernet MAC address is a PTP multicast address. + * + * @param addr A valid pointer to a Ethernet MAC address. + * + * @return true if address is a PTP multicast address, false if not + */ static inline bool net_eth_is_addr_ptp_multicast(struct net_eth_addr *addr) { #if defined(CONFIG_NET_GPTP) @@ -774,15 +883,20 @@ static inline bool net_eth_is_addr_ptp_multicast(struct net_eth_addr *addr) addr->addr[5] == 0x00) { return true; } +#else + ARG_UNUSED(addr); #endif return false; } +/** + * @brief Return Ethernet broadcast address. + * + * @return Ethernet broadcast address. + */ const struct net_eth_addr *net_eth_broadcast_addr(void); -/** @endcond */ - /** * @brief Convert IPv4 multicast address to Ethernet address. * @@ -821,6 +935,30 @@ enum ethernet_hw_caps net_eth_get_hw_capabilities(struct net_if *iface) return eth->get_capabilities(net_if_get_device(iface)); } +/** + * @brief Return ethernet device hardware configuration information. + * + * @param iface Network interface + * @param type configuration type + * @param config Ethernet configuration + * + * @return 0 if ok, <0 if error + */ +static inline +int net_eth_get_hw_config(struct net_if *iface, enum ethernet_config_type type, + struct ethernet_config *config) +{ + const struct ethernet_api *eth = + (struct ethernet_api *)net_if_get_device(iface)->api; + + if (!eth->get_config) { + return -ENOTSUP; + } + + return eth->get_config(net_if_get_device(iface), type, config); +} + + /** * @brief Add VLAN tag to the interface. * @@ -989,6 +1127,8 @@ static inline bool net_eth_is_vlan_interface(struct net_if *iface) } #endif +/** @cond INTERNAL_HIDDEN */ + #if !defined(CONFIG_ETH_DRIVER_RAW_MODE) #define Z_ETH_NET_DEVICE_INIT_INSTANCE(node_id, dev_id, name, instance, \ @@ -1017,6 +1157,8 @@ static inline bool net_eth_is_vlan_interface(struct net_if *iface) init_fn, pm, data, config, prio, \ api, mtu) +/** @endcond */ + /** * @brief Create an Ethernet network interface and bind it to network device. * @@ -1238,6 +1380,6 @@ static inline bool net_eth_type_is_wifi(struct net_if *iface) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_NET_ETHERNET_H_ */ diff --git a/include/zephyr/net/ethernet_bridge.h b/include/zephyr/net/ethernet_bridge.h index aa86f63a5616b..fa2ca54698335 100644 --- a/include/zephyr/net/ethernet_bridge.h +++ b/include/zephyr/net/ethernet_bridge.h @@ -56,6 +56,8 @@ struct eth_bridge { STRUCT_SECTION_ITERABLE(eth_bridge, name) = \ ETH_BRIDGE_INITIALIZER(name) +/** @cond INTERNAL_HIDDEN */ + struct eth_bridge_iface_context { sys_snode_t node; struct eth_bridge *instance; @@ -67,6 +69,8 @@ struct eth_bridge_listener { struct k_fifo pkt_queue; }; +/** @endcond */ + /** * @brief Add an Ethernet network interface to a bridge * diff --git a/include/zephyr/net/gptp.h b/include/zephyr/net/gptp.h index 049a94ec99e80..488583e4d533b 100644 --- a/include/zephyr/net/gptp.h +++ b/include/zephyr/net/gptp.h @@ -130,6 +130,7 @@ struct gptp_port_identity { uint16_t port_number; } __packed; +/** gPTP message flags */ struct gptp_flags { union { /** Byte access. */ @@ -140,6 +141,7 @@ struct gptp_flags { }; } __packed; +/** gPTP message header */ struct gptp_hdr { /** Type of the message. */ uint8_t message_type:4; diff --git a/include/zephyr/net/hostname.h b/include/zephyr/net/hostname.h index d9bac4393c287..4e801ffbda5c5 100644 --- a/include/zephyr/net/hostname.h +++ b/include/zephyr/net/hostname.h @@ -28,17 +28,22 @@ extern "C" { (sizeof(CONFIG_NET_HOSTNAME) - 1 + \ (IS_ENABLED(CONFIG_NET_HOSTNAME_UNIQUE) ? sizeof("0011223344556677") - 1 : 0))) #else +/** Maximum hostname length */ #define NET_HOSTNAME_MAX_LEN \ (sizeof(CONFIG_NET_HOSTNAME) - 1 + \ (IS_ENABLED(CONFIG_NET_HOSTNAME_UNIQUE) ? sizeof("0011223344556677") - 1 : 0)) #endif +/** @cond INTERNAL_HIDDEN */ + #if defined(CONFIG_NET_HOSTNAME_ENABLE) #define NET_HOSTNAME_SIZE NET_HOSTNAME_MAX_LEN + 1 #else #define NET_HOSTNAME_SIZE 1 #endif +/** @endcond */ + /** * @brief Get the device hostname * diff --git a/include/zephyr/net/http/client.h b/include/zephyr/net/http/client.h index e1ff3e63b9a86..71eb1b32f336f 100644 --- a/include/zephyr/net/http/client.h +++ b/include/zephyr/net/http/client.h @@ -16,6 +16,8 @@ /** * @brief HTTP client API * @defgroup http_client HTTP client API + * @since 2.1 + * @version 0.2.0 * @ingroup networking * @{ */ @@ -28,6 +30,8 @@ extern "C" { #endif +/** @cond INTERNAL_HIDDEN */ + #if !defined(HTTP_CRLF) #define HTTP_CRLF "\r\n" #endif @@ -36,10 +40,12 @@ extern "C" { #define HTTP_STATUS_STR_SIZE 32 #endif -/* Is there more data to come */ +/** @endcond */ + +/** Is there more data to come */ enum http_final_call { - HTTP_DATA_MORE = 0, - HTTP_DATA_FINAL = 1, + HTTP_DATA_MORE = 0, /**< More data will come */ + HTTP_DATA_FINAL = 1, /**< End of data */ }; struct http_request; @@ -172,7 +178,7 @@ struct http_response { */ size_t processed; - /* https://tools.ietf.org/html/rfc7230#section-3.1.2 + /** See https://tools.ietf.org/html/rfc7230#section-3.1.2 for more information. * The status-code element is a 3-digit integer code * * The reason-phrase element exists for the sole @@ -191,9 +197,9 @@ struct http_response { */ uint16_t http_status_code; - uint8_t cl_present : 1; - uint8_t body_found : 1; - uint8_t message_complete : 1; + uint8_t cl_present : 1; /**< Is Content-Length field present */ + uint8_t body_found : 1; /**< Is message body found */ + uint8_t message_complete : 1; /**< Is HTTP message parsing complete */ }; /** HTTP client internal data that the application should not touch diff --git a/include/zephyr/net/http/frame.h b/include/zephyr/net/http/frame.h index efdd78edf6ee5..02d063c68660b 100644 --- a/include/zephyr/net/http/frame.h +++ b/include/zephyr/net/http/frame.h @@ -4,24 +4,46 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief HTTP2 frame information. + */ + #ifndef ZEPHYR_INCLUDE_NET_HTTP_SERVER_FRAME_H_ #define ZEPHYR_INCLUDE_NET_HTTP_SERVER_FRAME_H_ #include +#ifdef __cplusplus +extern "C" { +#endif + +/** HTTP2 frame types */ enum http_frame_type { + /** Data frame */ HTTP_SERVER_DATA_FRAME = 0x00, + /** Headers frame */ HTTP_SERVER_HEADERS_FRAME = 0x01, + /** Priority frame */ HTTP_SERVER_PRIORITY_FRAME = 0x02, + /** Reset stream frame */ HTTP_SERVER_RST_STREAM_FRAME = 0x03, + /** Settings frame */ HTTP_SERVER_SETTINGS_FRAME = 0x04, + /** Push promise frame */ HTTP_SERVER_PUSH_PROMISE_FRAME = 0x05, + /** Ping frame */ HTTP_SERVER_PING_FRAME = 0x06, + /** Goaway frame */ HTTP_SERVER_GOAWAY_FRAME = 0x07, + /** Window update frame */ HTTP_SERVER_WINDOW_UPDATE_FRAME = 0x08, + /** Continuation frame */ HTTP_SERVER_CONTINUATION_FRAME = 0x09 }; +/** @cond INTERNAL_HIDDEN */ + #define HTTP_SERVER_HPACK_METHOD 0 #define HTTP_SERVER_HPACK_PATH 1 @@ -35,18 +57,32 @@ enum http_frame_type { #define HTTP_SERVER_FRAME_FLAGS_OFFSET 4 #define HTTP_SERVER_FRAME_STREAM_ID_OFFSET 5 +/** @endcond */ + +/** HTTP2 settings field */ struct http_settings_field { - uint16_t id; - uint32_t value; + uint16_t id; /**< Field id */ + uint32_t value; /**< Field value */ } __packed; +/** @brief HTTP2 settings */ enum http_settings { + /** Header table size */ HTTP_SETTINGS_HEADER_TABLE_SIZE = 1, + /** Enable push */ HTTP_SETTINGS_ENABLE_PUSH = 2, + /** Maximum number of concurrent streams */ HTTP_SETTINGS_MAX_CONCURRENT_STREAMS = 3, + /** Initial window size */ HTTP_SETTINGS_INITIAL_WINDOW_SIZE = 4, + /** Max frame size */ HTTP_SETTINGS_MAX_FRAME_SIZE = 5, + /** Max header list size */ HTTP_SETTINGS_MAX_HEADER_LIST_SIZE = 6, }; +#ifdef __cplusplus +} +#endif + #endif diff --git a/include/zephyr/net/http/hpack.h b/include/zephyr/net/http/hpack.h index 374b083ce091a..0a85cf7c8adca 100644 --- a/include/zephyr/net/http/hpack.h +++ b/include/zephyr/net/http/hpack.h @@ -26,6 +26,8 @@ extern "C" { #endif +/** @cond INTERNAL_HIDDEN */ + enum http_hpack_static_key { HTTP_SERVER_HPACK_INVALID = 0, HTTP_SERVER_HPACK_AUTHORITY = 1, @@ -94,6 +96,14 @@ enum http_hpack_static_key { /* TODO Kconfig */ #define HTTP2_HEADER_FIELD_MAX_LEN 256 +#if defined(CONFIG_HTTP_SERVER) +#define HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE CONFIG_HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE +#else +#define HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE 0 +#endif + +/** @endcond */ + /** HTTP2 header field with decoding buffer. */ struct http_hpack_header_buf { /** A pointer to the decoded header field name. */ @@ -109,12 +119,14 @@ struct http_hpack_header_buf { size_t value_len; /** Encoding/Decoding buffer. Used with Huffman encoding/decoding. */ - uint8_t buf[CONFIG_HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE]; + uint8_t buf[HTTP_SERVER_HUFFMAN_DECODE_BUFFER_SIZE]; /** Length of the data in the decoding buffer. */ size_t datalen; }; +/** @cond INTERNAL_HIDDEN */ + int http_hpack_huffman_decode(const uint8_t *encoded_buf, size_t encoded_len, uint8_t *buf, size_t buflen); int http_hpack_huffman_encode(const uint8_t *str, size_t str_len, @@ -124,6 +136,8 @@ int http_hpack_decode_header(const uint8_t *buf, size_t datalen, int http_hpack_encode_header(uint8_t *buf, size_t buflen, struct http_hpack_header_buf *header); +/** @endcond */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/http/method.h b/include/zephyr/net/http/method.h index b27e3144b236b..30f4aaeeaca7c 100644 --- a/include/zephyr/net/http/method.h +++ b/include/zephyr/net/http/method.h @@ -58,7 +58,9 @@ enum http_method { HTTP_LINK = 31, /**< LINK */ HTTP_UNLINK = 32, /**< UNLINK */ + /** @cond INTERNAL_HIDDEN */ HTTP_METHOD_END_VALUE /* keep this the last value */ + /** @endcond */ }; #ifdef __cplusplus diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index 35f1dcdc872f1..3e5223427dc7d 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -8,6 +8,16 @@ #ifndef ZEPHYR_INCLUDE_NET_HTTP_SERVER_H_ #define ZEPHYR_INCLUDE_NET_HTTP_SERVER_H_ +/** + * @file server.h + * + * @brief HTTP server API + * + * @defgroup http_server HTTP server API + * @ingroup networking + * @{ + */ + #include #include @@ -15,33 +25,96 @@ #include #include -#define HTTP_SERVER_CLIENT_BUFFER_SIZE CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE -#define HTTP_SERVER_MAX_STREAMS CONFIG_HTTP_SERVER_MAX_STREAMS +#ifdef __cplusplus +extern "C" { +#endif + +/** @cond INTERNAL_HIDDEN */ + +#if defined(CONFIG_HTTP_SERVER) +#define HTTP_SERVER_CLIENT_BUFFER_SIZE CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE +#define HTTP_SERVER_MAX_STREAMS CONFIG_HTTP_SERVER_MAX_STREAMS #define HTTP_SERVER_MAX_CONTENT_TYPE_LEN CONFIG_HTTP_SERVER_MAX_CONTENT_TYPE_LENGTH +#define HTTP_SERVER_MAX_URL_LENGTH CONFIG_HTTP_SERVER_MAX_URL_LENGTH +#else +#define HTTP_SERVER_CLIENT_BUFFER_SIZE 0 +#define HTTP_SERVER_MAX_STREAMS 0 +#define HTTP_SERVER_MAX_CONTENT_TYPE_LEN 0 +#define HTTP_SERVER_MAX_URL_LENGTH 0 +#endif + +/* Maximum header field name / value length. This is only used to detect Upgrade and + * websocket header fields and values in the http1 server so the value is quite short. + */ +#define HTTP_SERVER_MAX_HEADER_LEN 32 #define HTTP2_PREFACE "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" +/** @endcond */ + +/** + * @brief HTTP server resource type. + */ enum http_resource_type { + /** Static resource, cannot be modified on runtime. */ HTTP_RESOURCE_TYPE_STATIC, + + /** Dynamic resource, server interacts with the application via registered + * @ref http_resource_dynamic_cb_t. + */ HTTP_RESOURCE_TYPE_DYNAMIC, + + /** Websocket resource, application takes control over Websocket connection + * after and upgrade. + */ + HTTP_RESOURCE_TYPE_WEBSOCKET, }; +/** + * @brief Representation of a server resource, common for all resource types. + */ struct http_resource_detail { + /** Bitmask of supported HTTP methods (@ref http_method). */ uint32_t bitmask_of_supported_http_methods; + + /** Resource type. */ enum http_resource_type type; - int path_len; /* length of the URL path */ + + /** Length of the URL path. */ + int path_len; + + /** Content encoding of the resource. */ const char *content_encoding; + + /** Content type of the resource. */ + const char *content_type; }; + +/** @cond INTERNAL_HIDDEN */ BUILD_ASSERT(NUM_BITS( sizeof(((struct http_resource_detail *)0)->bitmask_of_supported_http_methods)) >= (HTTP_METHOD_END_VALUE - 1)); +/** @endcond */ +/** + * @brief Representation of a static server resource. + */ struct http_resource_detail_static { + /** Common resource details. */ struct http_resource_detail common; + + /** Content of the static resource. */ const void *static_data; + + /** Size of the static resource. */ size_t static_data_len; }; +/** @cond INTERNAL_HIDDEN */ +/* Make sure that the common is the first in the struct. */ +BUILD_ASSERT(offsetof(struct http_resource_detail_static, common) == 0); +/** @endcond */ + struct http_client_ctx; /** Indicates the status of the currently processed piece of data. */ @@ -76,19 +149,87 @@ typedef int (*http_resource_dynamic_cb_t)(struct http_client_ctx *client, size_t data_len, void *user_data); +/** + * @brief Representation of a dynamic server resource. + */ struct http_resource_detail_dynamic { + /** Common resource details. */ struct http_resource_detail common; + + /** Resource callback used by the server to interact with the + * application. + */ http_resource_dynamic_cb_t cb; + + /** Data buffer used to exchanged data between server and the, + * application. + */ uint8_t *data_buffer; + + /** Length of the data in the data buffer. */ size_t data_buffer_len; + + /** A pointer to the client currently processing resource, used to + * prevent concurrent access to the resource from multiple clients. + */ struct http_client_ctx *holder; + + /** A pointer to the user data registered by the application. */ void *user_data; }; -struct http_resource_detail_rest { +/** @cond INTERNAL_HIDDEN */ +BUILD_ASSERT(offsetof(struct http_resource_detail_dynamic, common) == 0); +/** @endcond */ + +/** + * @typedef http_resource_websocket_cb_t + * @brief Callback used when a Websocket connection is setup. The application + * will need to handle all functionality related to the connection like + * reading and writing websocket data, and closing the connection. + * + * @param ws_socket A socket for the Websocket data. + * @param user_data User specified data. + * + * @return 0 Accepting the connection, HTTP server library will no longer + * handle data to/from the socket and it is application responsibility + * to send and receive data to/from the supplied socket. + * <0 error, close the connection. + */ +typedef int (*http_resource_websocket_cb_t)(int ws_socket, + void *user_data); + +/** @brief Representation of a websocket server resource */ +struct http_resource_detail_websocket { + /** Common resource details. */ struct http_resource_detail common; + + /** Websocket socket value */ + int ws_sock; + + /** Resource callback used by the server to interact with the + * application. + */ + http_resource_websocket_cb_t cb; + + /** Data buffer used to exchanged data between server and the, + * application. + */ + uint8_t *data_buffer; + + /** Length of the data in the data buffer. */ + size_t data_buffer_len; + + /** A pointer to the user data registered by the application. */ + void *user_data; }; +/** @cond INTERNAL_HIDDEN */ +BUILD_ASSERT(offsetof(struct http_resource_detail_websocket, common) == 0); +/** @endcond */ + +/** @cond INTERNAL_HIDDEN */ + enum http_stream_state { HTTP_SERVER_STREAM_IDLE, HTTP_SERVER_STREAM_RESERVED_LOCAL, @@ -125,50 +266,138 @@ enum http1_parser_state { }; #define HTTP_SERVER_INITIAL_WINDOW_SIZE 65536 +#define HTTP_SERVER_WS_MAX_SEC_KEY_LEN 32 + +/** @endcond */ +/** @brief HTTP/2 stream representation. */ struct http_stream_ctx { - int stream_id; - enum http_stream_state stream_state; + int stream_id; /**< Stream identifier. */ + enum http_stream_state stream_state; /**< Stream state. */ int window_size; /**< Stream-level window size. */ }; +/** @brief HTTP/2 frame representation. */ struct http_frame { - uint32_t length; - uint32_t stream_identifier; - uint8_t type; - uint8_t flags; - uint8_t *payload; + uint32_t length; /**< Frame payload length. */ + uint32_t stream_identifier; /**< Stream ID the frame belongs to. */ + uint8_t type; /**< Frame type. */ + uint8_t flags; /**< Frame flags. */ + uint8_t *payload; /**< A pointer to the frame payload. */ }; +/** + * @brief Representation of an HTTP client connected to the server. + */ struct http_client_ctx { + /** Socket descriptor associated with the server. */ int fd; - bool preface_sent; - bool has_upgrade_header; + + /** Client data buffer. */ unsigned char buffer[HTTP_SERVER_CLIENT_BUFFER_SIZE]; - unsigned char *cursor; /**< Cursor indicating currently processed byte. */ - size_t data_len; /**< Data left to process in the buffer. */ - int window_size; /**< Connection-level window size. */ + + /** Cursor indicating currently processed byte. */ + unsigned char *cursor; + + /** Data left to process in the buffer. */ + size_t data_len; + + /** Connection-level window size. */ + int window_size; + + /** Server state for the associated client. */ enum http_server_state server_state; + + /** Currently processed HTTP/2 frame. */ struct http_frame current_frame; + + /** Currently processed resource detail. */ struct http_resource_detail *current_detail; + + /** HTTP/2 header parser context. */ struct http_hpack_header_buf header_field; + + /** HTTP/2 streams context. */ struct http_stream_ctx streams[HTTP_SERVER_MAX_STREAMS]; + + /** HTTP/1 parser configuration. */ struct http_parser_settings parser_settings; + + /** HTTP/1 parser context. */ struct http_parser parser; - unsigned char url_buffer[CONFIG_HTTP_SERVER_MAX_URL_LENGTH]; - unsigned char content_type[CONFIG_HTTP_SERVER_MAX_CONTENT_TYPE_LENGTH]; + + /** Request URL. */ + unsigned char url_buffer[HTTP_SERVER_MAX_URL_LENGTH]; + + /** Request content type. */ + unsigned char content_type[HTTP_SERVER_MAX_CONTENT_TYPE_LEN]; + + /** Temp buffer for currently processed header (HTTP/1 only). */ + unsigned char header_buffer[HTTP_SERVER_MAX_HEADER_LEN]; + + /** Request content length. */ size_t content_len; + + /** Request method. */ enum http_method method; + + /** HTTP/1 parser state. */ enum http1_parser_state parser_state; + + /** Length of the payload length in the currently processed request + * fragment (HTTP/1 only). + */ int http1_frag_data_len; - bool headers_sent; + + /** Client inactivity timer. The client connection is closed by the + * server when it expires. + */ struct k_work_delayable inactivity_timer; + +/** @cond INTERNAL_HIDDEN */ + /** Websocket security key. */ + IF_ENABLED(CONFIG_WEBSOCKET, (uint8_t ws_sec_key[HTTP_SERVER_WS_MAX_SEC_KEY_LEN])); +/** @endcond */ + + /** Flag indicating that headers were sent in the reply. */ + bool headers_sent : 1; + + /** Flag indicating that HTTP2 preface was sent. */ + bool preface_sent : 1; + + /** Flag indicating that upgrade header was present in the request. */ + bool has_upgrade_header : 1; + + /** Flag indicating HTTP/2 upgrade takes place. */ + bool http2_upgrade : 1; + + /** Flag indicating Websocket upgrade takes place. */ + bool websocket_upgrade : 1; + + /** Flag indicating Websocket key is being processed. */ + bool websocket_sec_key_next : 1; }; -/* Starts the HTTP2 server */ +/** @brief Start the HTTP2 server. + * + * The server runs in a background thread. Once started, the server will create + * a server socket for all HTTP services registered in the system and accept + * connections from clients (see @ref HTTP_SERVICE_DEFINE). + */ int http_server_start(void); -/* Stops the HTTP2 server */ +/** @brief Stop the HTTP2 server. + * + * All server sockets are closed and the server thread is suspended. + */ int http_server_stop(void); +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + #endif diff --git a/include/zephyr/net/http/service.h b/include/zephyr/net/http/service.h index 2f17b5022f7cd..e541c768f5636 100644 --- a/include/zephyr/net/http/service.h +++ b/include/zephyr/net/http/service.h @@ -7,6 +7,16 @@ #ifndef ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_ #define ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_ +/** + * @file service.h + * + * @brief HTTP service API + * + * @defgroup http_service HTTP service API + * @ingroup networking + * @{ + */ + #include #include @@ -18,8 +28,11 @@ extern "C" { #endif +/** HTTP resource description */ struct http_resource_desc { + /** Resource name */ const char *resource; + /** Detail associated with this resource */ void *detail; }; @@ -47,6 +60,8 @@ struct http_resource_desc { .detail = (void *)(_detail), \ } +/** @cond INTERNAL_HIDDEN */ + struct http_service_desc { const char *host; uint16_t *port; @@ -79,6 +94,8 @@ struct http_service_desc { (GET_ARG_N(1, GET_ARGS_LESS_N(1, __VA_ARGS__))))), ())\ } +/** @endcond */ + /** * @brief Define an HTTP service without static resources. * @@ -200,7 +217,7 @@ struct http_service_desc { /** * @brief Iterate over all HTTP services. * - * @param _it Name of iterator (of type @ref http_service_desc) + * @param _it Name of http_service_desc iterator */ #define HTTP_SERVICE_FOREACH(_it) STRUCT_SECTION_FOREACH(http_service_desc, _it) @@ -235,4 +252,8 @@ struct http_service_desc { } #endif +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_NET_HTTP_SERVICE_H_ */ diff --git a/include/zephyr/net/icmp.h b/include/zephyr/net/icmp.h index a5b9f6b2455c4..6d6a6b2c867dd 100644 --- a/include/zephyr/net/icmp.h +++ b/include/zephyr/net/icmp.h @@ -5,11 +5,12 @@ */ /** @file icmp.h + * + * @brief ICMP sending and receiving. * * @defgroup icmp Send and receive IPv4 or IPv6 ICMP Echo Request messages. * @ingroup networking * @{ - * @brief ICMP sending and receiving. */ #ifndef ZEPHYR_INCLUDE_NET_ICMP_H_ @@ -27,10 +28,10 @@ extern "C" { #endif -#define NET_ICMPV4_ECHO_REQUEST 8 -#define NET_ICMPV4_ECHO_REPLY 0 -#define NET_ICMPV6_ECHO_REQUEST 128 -#define NET_ICMPV6_ECHO_REPLY 129 +#define NET_ICMPV4_ECHO_REQUEST 8 /**< ICMPv4 Echo-Request */ +#define NET_ICMPV4_ECHO_REPLY 0 /**< ICMPv4 Echo-Reply */ +#define NET_ICMPV6_ECHO_REQUEST 128 /**< ICMPv6 Echo-Request */ +#define NET_ICMPV6_ECHO_REPLY 129 /**< ICMPv6 Echo-Reply */ struct net_icmp_ctx; struct net_icmp_ip_hdr; @@ -136,7 +137,7 @@ struct net_icmp_ping_params { /** Network packet priority. */ int priority; - /* Arbitrary payload data that will be included in the Echo Reply + /** Arbitrary payload data that will be included in the Echo Reply * verbatim. May be NULL. */ const void *data; diff --git a/include/zephyr/net/ieee802154.h b/include/zephyr/net/ieee802154.h index 927a9036db3e3..b60aa7071f390 100644 --- a/include/zephyr/net/ieee802154.h +++ b/include/zephyr/net/ieee802154.h @@ -241,10 +241,11 @@ struct ieee802154_security_ctx { /** INTERNAL_HIDDEN @endcond */ }; +/** @brief IEEE 802.15.4 device role */ enum ieee802154_device_role { - IEEE802154_DEVICE_ROLE_ENDDEVICE, - IEEE802154_DEVICE_ROLE_COORDINATOR, - IEEE802154_DEVICE_ROLE_PAN_COORDINATOR, + IEEE802154_DEVICE_ROLE_ENDDEVICE, /**< End device */ + IEEE802154_DEVICE_ROLE_COORDINATOR, /**< Coordinator */ + IEEE802154_DEVICE_ROLE_PAN_COORDINATOR, /**< PAN coordinator */ }; /** IEEE 802.15.4 L2 context. */ diff --git a/include/zephyr/net/ieee802154_ie.h b/include/zephyr/net/ieee802154_ie.h index 0be4c1576e5c0..a2378a38efa84 100644 --- a/include/zephyr/net/ieee802154_ie.h +++ b/include/zephyr/net/ieee802154_ie.h @@ -40,8 +40,8 @@ * @details See sections 7.4.2.1 and 7.4.3.1. */ enum ieee802154_ie_type { - IEEE802154_IE_TYPE_HEADER = 0x0, - IEEE802154_IE_TYPE_PAYLOAD, + IEEE802154_IE_TYPE_HEADER = 0x0, /**< Header type */ + IEEE802154_IE_TYPE_PAYLOAD, /**< Payload type */ }; /** @@ -51,13 +51,13 @@ enum ieee802154_ie_type { * are implemented. */ enum ieee802154_header_ie_element_id { - IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE = 0x00, - IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE = 0x1a, - IEEE802154_HEADER_IE_ELEMENT_ID_RIT_IE = 0x1b, - IEEE802154_HEADER_IE_ELEMENT_ID_RENDEZVOUS_TIME_IE = 0x1d, - IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE = 0x1e, - IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_1 = 0x7e, - IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_2 = 0x7f, + IEEE802154_HEADER_IE_ELEMENT_ID_VENDOR_SPECIFIC_IE = 0x00, /**< Vendor specific IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_CSL_IE = 0x1a, /**< CSL IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_RIT_IE = 0x1b, /**< RIT IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_RENDEZVOUS_TIME_IE = 0x1d, /**< Rendezvous time IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_TIME_CORRECTION_IE = 0x1e, /**< Time correction IE */ + IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_1 = 0x7e, /**< Header termination 1 */ + IEEE802154_HEADER_IE_ELEMENT_ID_HEADER_TERMINATION_2 = 0x7f, /**< Header termination 2 */ /* partial list, add additional ids as needed */ }; @@ -67,36 +67,40 @@ enum ieee802154_header_ie_element_id { /** @brief Vendor Specific Header IE, see section 7.4.2.3. */ struct ieee802154_header_ie_vendor_specific { + /** Vendor OUI */ uint8_t vendor_oui[IEEE802154_VENDOR_SPECIFIC_IE_OUI_LEN]; + /** Vendor specific information */ uint8_t *vendor_specific_info; } __packed; /** @brief Full CSL IE, see section 7.4.2.3. */ struct ieee802154_header_ie_csl_full { - uint16_t csl_phase; - uint16_t csl_period; - uint16_t csl_rendezvous_time; + uint16_t csl_phase; /**< CSL phase */ + uint16_t csl_period; /**< CSL period */ + uint16_t csl_rendezvous_time; /**< Rendezvous time */ } __packed; /** @brief Reduced CSL IE, see section 7.4.2.3. */ struct ieee802154_header_ie_csl_reduced { - uint16_t csl_phase; - uint16_t csl_period; + uint16_t csl_phase; /**< CSL phase */ + uint16_t csl_period; /**< CSL period */ } __packed; /** @brief Generic CSL IE, see section 7.4.2.3. */ struct ieee802154_header_ie_csl { union { + /** CSL full information */ struct ieee802154_header_ie_csl_full full; + /** CSL reduced information */ struct ieee802154_header_ie_csl_reduced reduced; }; } __packed; /** @brief RIT IE, see section 7.4.2.4. */ struct ieee802154_header_ie_rit { - uint8_t time_to_first_listen; - uint8_t number_of_repeat_listen; - uint16_t repeat_listen_interval; + uint8_t time_to_first_listen; /**< Time to First Listen */ + uint8_t number_of_repeat_listen; /**< Number of Repeat Listen */ + uint16_t repeat_listen_interval; /**< Repeat listen interval */ } __packed; /** @@ -104,8 +108,8 @@ struct ieee802154_header_ie_rit { * (macCslInterval is nonzero). */ struct ieee802154_header_ie_rendezvous_time_full { - uint16_t rendezvous_time; - uint16_t wakeup_interval; + uint16_t rendezvous_time; /**< Rendezvous time */ + uint16_t wakeup_interval; /**< Wakeup interval */ } __packed; /** @@ -113,22 +117,26 @@ struct ieee802154_header_ie_rendezvous_time_full { * (macCslInterval is zero). */ struct ieee802154_header_ie_rendezvous_time_reduced { - uint16_t rendezvous_time; + uint16_t rendezvous_time; /**< Rendezvous time */ } __packed; /** @brief Rendezvous Time IE, see section 7.4.2.6. */ struct ieee802154_header_ie_rendezvous_time { union { + /** Rendezvous time full information */ struct ieee802154_header_ie_rendezvous_time_full full; + /** Rendezvous time reduced information */ struct ieee802154_header_ie_rendezvous_time_reduced reduced; }; } __packed; /** @brief Time Correction IE, see section 7.4.2.7. */ struct ieee802154_header_ie_time_correction { - uint16_t time_sync_info; + uint16_t time_sync_info; /**< Time synchronization information */ } __packed; +/** @cond INTERNAL_HIDDEN */ + /* @brief Generic Header IE, see section 7.4.2.1. */ struct ieee802154_header_ie { #if CONFIG_LITTLE_ENDIAN @@ -152,6 +160,8 @@ struct ieee802154_header_ie { } content; } __packed; +/** INTERNAL_HIDDEN @endcond */ + /** @brief The header IE's header length (2 bytes). */ #define IEEE802154_HEADER_IE_HEADER_LENGTH sizeof(uint16_t) diff --git a/include/zephyr/net/ieee802154_mgmt.h b/include/zephyr/net/ieee802154_mgmt.h index 1f08c0b73c063..5937242355878 100644 --- a/include/zephyr/net/ieee802154_mgmt.h +++ b/include/zephyr/net/ieee802154_mgmt.h @@ -322,8 +322,8 @@ struct ieee802154_req_params { /** Result address */ union { - uint16_t short_addr; /* in CPU byte order */ - uint8_t addr[IEEE802154_MAX_ADDR_LENGTH]; /* in big endian */ + uint16_t short_addr; /**< in CPU byte order */ + uint8_t addr[IEEE802154_MAX_ADDR_LENGTH]; /**< in big endian */ }; /** length of address */ @@ -339,13 +339,13 @@ struct ieee802154_req_params { * see tables 9-9 and 9-10 in section 9.5. */ struct ieee802154_security_params { - uint8_t key[16]; /* secKeyDescriptor.secKey */ - uint8_t key_len; /* a key length of 16 bytes is mandatory for standards conformance */ - uint8_t key_mode : 2; /* secKeyIdMode */ - uint8_t level : 3; /* Used instead of a frame-specific SecurityLevel parameter when + uint8_t key[16]; /**< secKeyDescriptor.secKey */ + uint8_t key_len; /**< Key length of 16 bytes is mandatory for standards conformance */ + uint8_t key_mode : 2; /**< secKeyIdMode */ + uint8_t level : 3; /**< Used instead of a frame-specific SecurityLevel parameter when * constructing the auxiliary security header */ - uint8_t _unused : 3; + uint8_t _unused : 3; /**< unused value (ignore) */ }; #ifdef __cplusplus diff --git a/include/zephyr/net/ieee802154_radio.h b/include/zephyr/net/ieee802154_radio.h index 9912132918b55..028a2d1ea1b49 100644 --- a/include/zephyr/net/ieee802154_radio.h +++ b/include/zephyr/net/ieee802154_radio.h @@ -233,8 +233,8 @@ enum ieee802154_phy_channel_page { * ieee802154_phy_supported_channels. */ struct ieee802154_phy_channel_range { - uint16_t from_channel; - uint16_t to_channel; + uint16_t from_channel; /**< From channel range */ + uint16_t to_channel; /**< To channel range */ }; /** @@ -533,11 +533,11 @@ enum ieee802154_hw_caps { /** Filter type, see @ref ieee802154_radio_api::filter */ enum ieee802154_filter_type { - IEEE802154_FILTER_TYPE_IEEE_ADDR, - IEEE802154_FILTER_TYPE_SHORT_ADDR, - IEEE802154_FILTER_TYPE_PAN_ID, - IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR, - IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR, + IEEE802154_FILTER_TYPE_IEEE_ADDR, /**< Address type filter */ + IEEE802154_FILTER_TYPE_SHORT_ADDR, /**< Short address type filter */ + IEEE802154_FILTER_TYPE_PAN_ID, /**< PAN id type filter */ + IEEE802154_FILTER_TYPE_SRC_IEEE_ADDR, /**< Source address type filter */ + IEEE802154_FILTER_TYPE_SRC_SHORT_ADDR, /**< Source short address type filter */ }; /** Driver events, see @ref IEEE802154_CONFIG_EVENT_HANDLER */ @@ -1125,15 +1125,15 @@ struct ieee802154_config { union { /** see @ref IEEE802154_CONFIG_AUTO_ACK_FPB */ struct { - bool enabled; - enum ieee802154_fpb_mode mode; + bool enabled; /**< Is auto ACK FPB enabled */ + enum ieee802154_fpb_mode mode; /**< Auto ACK FPB mode */ } auto_ack_fpb; /** see @ref IEEE802154_CONFIG_ACK_FPB */ struct { - uint8_t *addr; /* in little endian for both, short and extended address */ - bool extended; - bool enabled; + uint8_t *addr; /**< little endian for both short and extended address */ + bool extended; /**< Is extended address */ + bool enabled; /**< Is enabled */ } ack_fpb; /** see @ref IEEE802154_CONFIG_PAN_COORDINATOR */ @@ -1194,6 +1194,9 @@ struct ieee802154_config { */ net_time_t duration; + /** + * Used channel + */ uint8_t channel; } rx_slot; diff --git a/include/zephyr/net/ieee802154_radio_openthread.h b/include/zephyr/net/ieee802154_radio_openthread.h index f6f9949d328fe..e45bbc6b85b4c 100644 --- a/include/zephyr/net/ieee802154_radio_openthread.h +++ b/include/zephyr/net/ieee802154_radio_openthread.h @@ -25,6 +25,7 @@ enum ieee802154_openthread_hw_caps { IEEE802154_OPENTHREAD_HW_MULTIPLE_CCA = BIT(IEEE802154_HW_CAPS_BITS_PRIV_START), }; +/** @brief TX mode */ enum ieee802154_openthread_tx_mode { /** * The @ref IEEE802154_OPENTHREAD_TX_MODE_TXTIME_MULTIPLE_CCA mode allows to send @@ -93,6 +94,7 @@ enum ieee802154_openthread_config_type { /** OpenThread specific configuration data of ieee802154 driver. */ struct ieee802154_openthread_config { union { + /** Common configuration */ struct ieee802154_config common; /** ``IEEE802154_OPENTHREAD_CONFIG_MAX_EXTRA_CCA_ATTEMPTS`` @@ -134,6 +136,7 @@ enum ieee802154_openthread_attr { */ struct ieee802154_openthread_attr_value { union { + /** Common attribute value */ struct ieee802154_attr_value common; /** @brief Attribute value for @ref IEEE802154_OPENTHREAD_ATTR_T_RECCA */ diff --git a/include/zephyr/net/igmp.h b/include/zephyr/net/igmp.h index ed39a31359f2b..7dbfd78e1d8da 100644 --- a/include/zephyr/net/igmp.h +++ b/include/zephyr/net/igmp.h @@ -27,10 +27,11 @@ extern "C" { #endif +/** IGMP parameters */ struct igmp_param { - struct in_addr *source_list; /* List of sources to include or exclude */ - size_t sources_len; /* Length of source list */ - bool include; /* Source list filter type */ + struct in_addr *source_list; /**< List of sources to include or exclude */ + size_t sources_len; /**< Length of source list */ + bool include; /**< Source list filter type */ }; /** diff --git a/include/zephyr/net/ipv4_autoconf.h b/include/zephyr/net/ipv4_autoconf.h index 5fec5eb6637db..8d1873b439f9e 100644 --- a/include/zephyr/net/ipv4_autoconf.h +++ b/include/zephyr/net/ipv4_autoconf.h @@ -13,20 +13,56 @@ /** Current state of IPv4 Autoconfiguration */ enum net_ipv4_autoconf_state { - NET_IPV4_AUTOCONF_INIT, - NET_IPV4_AUTOCONF_PROBE, - NET_IPV4_AUTOCONF_ANNOUNCE, - NET_IPV4_AUTOCONF_ASSIGNED, - NET_IPV4_AUTOCONF_RENEW, + NET_IPV4_AUTOCONF_INIT, /**< Initialization state */ + NET_IPV4_AUTOCONF_ASSIGNED, /**< Assigned state */ + NET_IPV4_AUTOCONF_RENEW, /**< Renew state */ }; +struct net_if; + +/** + * @brief Start IPv4 autoconfiguration RFC 3927: IPv4 Link Local + * + * @details Start IPv4 IP autoconfiguration + * + * @param iface A valid pointer on an interface + */ +#if defined(CONFIG_NET_IPV4_AUTO) +void net_ipv4_autoconf_start(struct net_if *iface); +#else +static inline void net_ipv4_autoconf_start(struct net_if *iface) +{ + ARG_UNUSED(iface); +} +#endif + +/** + * @brief Reset autoconf process + * + * @details Reset IPv4 IP autoconfiguration + * + * @param iface A valid pointer on an interface + */ +#if defined(CONFIG_NET_IPV4_AUTO) +void net_ipv4_autoconf_reset(struct net_if *iface); +#else +static inline void net_ipv4_autoconf_reset(struct net_if *iface) +{ + ARG_UNUSED(iface); +} +#endif + +/** @cond INTERNAL_HIDDEN */ + /** * @brief Initialize IPv4 auto configuration engine. */ #if defined(CONFIG_NET_IPV4_AUTO) void net_ipv4_autoconf_init(void); #else -#define net_ipv4_autoconf_init(...) +static inline void net_ipv4_autoconf_init(void) { } #endif +/** @endcond */ + #endif /* ZEPHYR_INCLUDE_NET_IPV4_AUTOCONF_H_ */ diff --git a/include/zephyr/net/lwm2m.h b/include/zephyr/net/lwm2m.h index e68f5fb47ad4c..0ae5314e3d0bc 100644 --- a/include/zephyr/net/lwm2m.h +++ b/include/zephyr/net/lwm2m.h @@ -7,11 +7,6 @@ /** @file lwm2m.h * - * @defgroup lwm2m_api LwM2M high-level API - * @since 1.9 - * @version 0.8.0 - * @ingroup networking - * @{ * @brief LwM2M high-level API * * @details @@ -21,6 +16,12 @@ * * @note For more information refer to Technical Specification * OMA-TS-LightweightM2M_Core-V1_1_1-20190617-A + * + * @defgroup lwm2m_api LwM2M high-level API + * @since 1.9 + * @version 0.8.0 + * @ingroup networking + * @{ */ #ifndef ZEPHYR_INCLUDE_NET_LWM2M_H_ @@ -283,7 +284,9 @@ struct lwm2m_ctx { struct lwm2m_time_series_elem { /** Cached data Unix timestamp */ time_t t; + /** Element value */ union { + /** @cond INTERNAL_HIDDEN */ uint8_t u8; uint16_t u16; uint32_t u32; @@ -295,6 +298,7 @@ struct lwm2m_time_series_elem { time_t time; double f; bool b; + /** @endcond */ }; }; @@ -329,6 +333,10 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id, * make use of this callback to pass the data back to the client or LwM2M * objects. * + * On a block-wise transfers the handler is called multiple times with the data blocks + * and increasing offset. The last block has the last_block flag set to true. + * Beginning of the block transfer has the offset set to 0. + * * A function of this type can be registered via: * lwm2m_engine_register_validate_callback() * lwm2m_engine_register_post_write_callback() @@ -344,6 +352,7 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id, * false. * @param[in] total_size Expected total size of data for a block transfer. * For non-block transfers this is 0. + * @param[in] offset Offset of the data block. For non-block transfers this is always 0. * * @return Callback returns a negative error code (errno.h) indicating * reason of failure or 0 for success. @@ -351,7 +360,7 @@ typedef void *(*lwm2m_engine_get_data_cb_t)(uint16_t obj_inst_id, typedef int (*lwm2m_engine_set_data_cb_t)(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size); + bool last_block, size_t total_size, size_t offset); /** * @brief Asynchronous event notification callback. @@ -2139,21 +2148,37 @@ void lwm2m_acknowledge(struct lwm2m_ctx *client_ctx); * lwm2m_rd_client_start() */ enum lwm2m_rd_client_event { + /** Invalid event */ LWM2M_RD_CLIENT_EVENT_NONE, + /** Bootstrap registration failure */ LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_FAILURE, + /** Bootstrap registration complete */ LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_REG_COMPLETE, + /** Bootstrap transfer complete */ LWM2M_RD_CLIENT_EVENT_BOOTSTRAP_TRANSFER_COMPLETE, + /** Registration failure */ LWM2M_RD_CLIENT_EVENT_REGISTRATION_FAILURE, + /** Registration complete */ LWM2M_RD_CLIENT_EVENT_REGISTRATION_COMPLETE, + /** Registration timeout */ LWM2M_RD_CLIENT_EVENT_REG_TIMEOUT, + /** Registration update complete */ LWM2M_RD_CLIENT_EVENT_REG_UPDATE_COMPLETE, + /** De-registration failure */ LWM2M_RD_CLIENT_EVENT_DEREGISTER_FAILURE, + /** Disconnected */ LWM2M_RD_CLIENT_EVENT_DISCONNECT, + /** Queue mode RX off */ LWM2M_RD_CLIENT_EVENT_QUEUE_MODE_RX_OFF, + /** Engine suspended */ LWM2M_RD_CLIENT_EVENT_ENGINE_SUSPENDED, + /** Network error */ LWM2M_RD_CLIENT_EVENT_NETWORK_ERROR, + /** Registration update */ LWM2M_RD_CLIENT_EVENT_REG_UPDATE, + /** De-register */ LWM2M_RD_CLIENT_EVENT_DEREGISTER, + /** Server disabled */ LWM2M_RD_CLIENT_EVENT_SERVER_DISABLED, }; @@ -2265,9 +2290,9 @@ char *lwm2m_path_log_buf(char *buf, struct lwm2m_obj_path *path); * lwm2m_send_cb() */ enum lwm2m_send_status { - LWM2M_SEND_STATUS_SUCCESS, - LWM2M_SEND_STATUS_FAILURE, - LWM2M_SEND_STATUS_TIMEOUT, + LWM2M_SEND_STATUS_SUCCESS, /**< Succeed */ + LWM2M_SEND_STATUS_FAILURE, /**< Failure */ + LWM2M_SEND_STATUS_TIMEOUT, /**< Timeout */ }; /** diff --git a/include/zephyr/net/lwm2m_path.h b/include/zephyr/net/lwm2m_path.h index cd42c4942dad4..ad012c8aba865 100644 --- a/include/zephyr/net/lwm2m_path.h +++ b/include/zephyr/net/lwm2m_path.h @@ -8,7 +8,10 @@ #define ZEPHYR_INCLUDE_NET_LWM2M_PATH_H_ /** + * @file lwm2m.h + * * @brief LwM2M path helper macros + * * @defgroup lwm2m_path_helpers LwM2M path helper macros * @ingroup lwm2m_api * @{ diff --git a/include/zephyr/net/mdio.h b/include/zephyr/net/mdio.h index 8d1998f7cec93..6ed13c1a6fd38 100644 --- a/include/zephyr/net/mdio.h +++ b/include/zephyr/net/mdio.h @@ -110,7 +110,7 @@ enum mdio_opcode { #define MDIO_AN_T1_ADV_M 0x0203U /** BASE-T1 Auto-negotiation advertisement register [47:32] */ #define MDIO_AN_T1_ADV_H 0x0204U -/* BASE-T1 PMA/PMD control register */ +/** BASE-T1 PMA/PMD control register */ #define MDIO_PMA_PMD_BT1_CTRL 0x0834U /* BASE-T1 Auto-negotiation Control register */ @@ -152,9 +152,9 @@ enum mdio_opcode { #define MDIO_AN_T1_ADV_M_MST BIT(4) /* BASE-T1 Auto-negotiation Advertisement register [47:32] */ -/* 10BASE-T1L High Level Transmit Operating Mode Request */ +/** 10BASE-T1L High Level Transmit Operating Mode Request */ #define MDIO_AN_T1_ADV_H_10L_TX_HI_REQ BIT(12) -/* 10BASE-T1L High Level Transmit Operating Mode Ability */ +/** 10BASE-T1L High Level Transmit Operating Mode Ability */ #define MDIO_AN_T1_ADV_H_10L_TX_HI BIT(13) /* BASE-T1 PMA/PMD control register */ diff --git a/include/zephyr/net/mii.h b/include/zephyr/net/mii.h index fc2a65bc306b4..371f19665c22a 100644 --- a/include/zephyr/net/mii.h +++ b/include/zephyr/net/mii.h @@ -131,8 +131,9 @@ #define MII_ADVERTISE_10_FULL (1 << 6) /** try for 10 Mb/s half duplex support */ #define MII_ADVERTISE_10_HALF (1 << 5) -/** Selector Field */ +/** Selector Field Mask */ #define MII_ADVERTISE_SEL_MASK (0x1F << 0) +/** Selector Field */ #define MII_ADVERTISE_SEL_IEEE_802_3 0x01 /* 1000BASE-T Control Register bit definitions */ @@ -141,6 +142,7 @@ /** try for 1000BASE-T half duplex support */ #define MII_ADVERTISE_1000_HALF (1 << 8) +/** Advertise all speeds */ #define MII_ADVERTISE_ALL (MII_ADVERTISE_10_HALF | MII_ADVERTISE_10_FULL |\ MII_ADVERTISE_100_HALF | MII_ADVERTISE_100_FULL |\ MII_ADVERTISE_SEL_IEEE_802_3) diff --git a/include/zephyr/net/mqtt.h b/include/zephyr/net/mqtt.h index 5bbc9f794834f..2514fc709c2c6 100644 --- a/include/zephyr/net/mqtt.h +++ b/include/zephyr/net/mqtt.h @@ -6,16 +6,17 @@ /** @file mqtt.h * - * @defgroup mqtt_socket MQTT Client library - * @since 1.14 - * @version 0.8.0 - * @ingroup networking - * @{ * @brief MQTT Client Implementation * * @note The implementation assumes TCP module is enabled. * * @note By default the implementation uses MQTT version 3.1.1. + * + * @defgroup mqtt_socket MQTT Client library + * @since 1.14 + * @version 0.8.0 + * @ingroup networking + * @{ */ #ifndef ZEPHYR_INCLUDE_NET_MQTT_H_ @@ -417,15 +418,16 @@ struct mqtt_transport { */ enum mqtt_transport_type type; + /** Use either unsecured TCP or secured TLS transport */ union { - /* TCP socket transport for MQTT */ + /** TCP socket transport for MQTT */ struct { /** Socket descriptor. */ int sock; } tcp; #if defined(CONFIG_MQTT_LIB_TLS) - /* TLS socket transport for MQTT */ + /** TLS socket transport for MQTT */ struct { /** Socket descriptor. */ int sock; @@ -559,7 +561,7 @@ struct mqtt_client { */ uint8_t clean_session : 1; - /* Userdata */ + /** User specific opaque data */ void *user_data; }; diff --git a/include/zephyr/net/mqtt_sn.h b/include/zephyr/net/mqtt_sn.h index cb1a6d3373123..102cb5e692a7a 100644 --- a/include/zephyr/net/mqtt_sn.h +++ b/include/zephyr/net/mqtt_sn.h @@ -6,15 +6,15 @@ /** @file mqtt_sn.h * - * @defgroup mqtt_sn_socket MQTT-SN Client library - * @ingroup networking - * @{ * @brief MQTT-SN Client Implementation * * @details * MQTT-SN Client's Application interface is defined in this header. * Targets protocol version 1.2. * + * @defgroup mqtt_sn_socket MQTT-SN Client library + * @ingroup networking + * @{ */ #ifndef ZEPHYR_INCLUDE_NET_MQTT_SN_H_ diff --git a/include/zephyr/net/net_context.h b/include/zephyr/net/net_context.h index 7c0de1eccd662..10327dc599597 100644 --- a/include/zephyr/net/net_context.h +++ b/include/zephyr/net/net_context.h @@ -35,6 +35,8 @@ extern "C" { /** Is this context used or not */ #define NET_CONTEXT_IN_USE BIT(0) +/** @cond INTERNAL_HIDDEN */ + /** State of the context (bits 1 & 2 in the flags) */ enum net_context_state { NET_CONTEXT_IDLE = 0, @@ -46,6 +48,8 @@ enum net_context_state { NET_CONTEXT_LISTENING = 3, }; +/** @endcond */ + /** * The address family, connection type and IP protocol are * stored into a bit field to save space. @@ -65,7 +69,7 @@ enum net_context_state { /** Is the socket closing / closed */ #define NET_CONTEXT_CLOSING_SOCK BIT(10) -/* Context is bound to a specific interface */ +/** Context is bound to a specific interface */ #define NET_CONTEXT_BOUND_TO_IFACE BIT(11) struct net_context; @@ -355,6 +359,10 @@ __net_socket struct net_context { * see RFC 5014 for details. */ uint16_t addr_preferences; +#endif +#if defined(CONFIG_NET_CONTEXT_TIMESTAMPING) + /** Enable RX, TX or both timestamps of packets send through sockets. */ + uint8_t timestamping; #endif } options; @@ -442,7 +450,7 @@ static inline void net_context_set_accepting(struct net_context *context, if (accepting) { context->flags |= NET_CONTEXT_ACCEPTING_SOCK; } else { - context->flags &= ~NET_CONTEXT_ACCEPTING_SOCK; + context->flags &= (uint16_t)~NET_CONTEXT_ACCEPTING_SOCK; } } @@ -474,13 +482,17 @@ static inline void net_context_set_closing(struct net_context *context, if (closing) { context->flags |= NET_CONTEXT_CLOSING_SOCK; } else { - context->flags &= ~NET_CONTEXT_CLOSING_SOCK; + context->flags &= (uint16_t)~NET_CONTEXT_CLOSING_SOCK; } } +/** @cond INTERNAL_HIDDEN */ + #define NET_CONTEXT_STATE_SHIFT 1 #define NET_CONTEXT_STATE_MASK 0x03 +/** @endcond */ + /** * @brief Get state for this network context. * @@ -554,7 +566,7 @@ static inline void net_context_set_family(struct net_context *context, if (family == AF_UNSPEC || family == AF_INET || family == AF_INET6 || family == AF_PACKET || family == AF_CAN) { /* Family is in BIT(4), BIT(5) and BIT(6) */ - flag = family << 3; + flag = (uint8_t)(family << 3); } context->flags |= flag; @@ -596,7 +608,7 @@ static inline void net_context_set_type(struct net_context *context, if (type == SOCK_DGRAM || type == SOCK_STREAM || type == SOCK_RAW) { /* Type is in BIT(6) and BIT(7)*/ - flag = type << 6; + flag = (uint16_t)(type << 6); } context->flags |= flag; @@ -714,7 +726,7 @@ static inline void net_context_set_iface(struct net_context *context, { NET_ASSERT(iface); - context->iface = net_if_get_by_iface(iface); + context->iface = (uint8_t)net_if_get_by_iface(iface); } /** @@ -1258,24 +1270,26 @@ int net_context_recv(struct net_context *context, int net_context_update_recv_wnd(struct net_context *context, int32_t delta); +/** @brief Network context options. These map to BSD socket option values. */ enum net_context_option { - NET_OPT_PRIORITY = 1, - NET_OPT_TXTIME = 2, - NET_OPT_SOCKS5 = 3, - NET_OPT_RCVTIMEO = 4, - NET_OPT_SNDTIMEO = 5, - NET_OPT_RCVBUF = 6, - NET_OPT_SNDBUF = 7, - NET_OPT_DSCP_ECN = 8, - NET_OPT_REUSEADDR = 9, - NET_OPT_REUSEPORT = 10, - NET_OPT_IPV6_V6ONLY = 11, - NET_OPT_RECV_PKTINFO = 12, - NET_OPT_MCAST_TTL = 13, - NET_OPT_MCAST_HOP_LIMIT = 14, - NET_OPT_UNICAST_HOP_LIMIT = 15, - NET_OPT_TTL = 16, - NET_OPT_ADDR_PREFERENCES = 17, + NET_OPT_PRIORITY = 1, /**< Context priority */ + NET_OPT_TXTIME = 2, /**< TX time */ + NET_OPT_SOCKS5 = 3, /**< SOCKS5 */ + NET_OPT_RCVTIMEO = 4, /**< Receive timeout */ + NET_OPT_SNDTIMEO = 5, /**< Send timeout */ + NET_OPT_RCVBUF = 6, /**< Receive buffer */ + NET_OPT_SNDBUF = 7, /**< Send buffer */ + NET_OPT_DSCP_ECN = 8, /**< DSCP ECN */ + NET_OPT_REUSEADDR = 9, /**< Re-use address */ + NET_OPT_REUSEPORT = 10, /**< Re-use port */ + NET_OPT_IPV6_V6ONLY = 11, /**< Share IPv4 and IPv6 port space */ + NET_OPT_RECV_PKTINFO = 12, /**< Receive packet information */ + NET_OPT_MCAST_TTL = 13, /**< IPv4 multicast TTL */ + NET_OPT_MCAST_HOP_LIMIT = 14, /**< IPv6 multicast hop limit */ + NET_OPT_UNICAST_HOP_LIMIT = 15, /**< IPv6 unicast hop limit */ + NET_OPT_TTL = 16, /**< IPv4 unicast TTL */ + NET_OPT_ADDR_PREFERENCES = 17, /**< IPv6 address preference */ + NET_OPT_TIMESTAMPING = 18, /**< Packet timestamping */ }; /** diff --git a/include/zephyr/net/net_event.h b/include/zephyr/net/net_event.h index 3d2be01fd9002..9bcba06be76eb 100644 --- a/include/zephyr/net/net_event.h +++ b/include/zephyr/net/net_event.h @@ -41,18 +41,6 @@ enum net_event_if_cmd { NET_EVENT_IF_CMD_ADMIN_UP, }; -#define NET_EVENT_IF_DOWN \ - (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_DOWN) - -#define NET_EVENT_IF_UP \ - (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_UP) - -#define NET_EVENT_IF_ADMIN_DOWN \ - (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_ADMIN_DOWN) - -#define NET_EVENT_IF_ADMIN_UP \ - (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_ADMIN_UP) - /* IPv6 Events */ #define _NET_IPV6_LAYER NET_MGMT_LAYER_L3 #define _NET_IPV6_CORE_CODE 0x060 @@ -88,175 +76,278 @@ enum net_event_ipv6_cmd { NET_EVENT_IPV6_CMD_PE_FILTER_DEL, }; +/* IPv4 Events*/ +#define _NET_IPV4_LAYER NET_MGMT_LAYER_L3 +#define _NET_IPV4_CORE_CODE 0x004 +#define _NET_EVENT_IPV4_BASE (NET_MGMT_EVENT_BIT | \ + NET_MGMT_IFACE_BIT | \ + NET_MGMT_LAYER(_NET_IPV4_LAYER) | \ + NET_MGMT_LAYER_CODE(_NET_IPV4_CORE_CODE)) + +enum net_event_ipv4_cmd { + NET_EVENT_IPV4_CMD_ADDR_ADD = 1, + NET_EVENT_IPV4_CMD_ADDR_DEL, + NET_EVENT_IPV4_CMD_MADDR_ADD, + NET_EVENT_IPV4_CMD_MADDR_DEL, + NET_EVENT_IPV4_CMD_ROUTER_ADD, + NET_EVENT_IPV4_CMD_ROUTER_DEL, + NET_EVENT_IPV4_CMD_DHCP_START, + NET_EVENT_IPV4_CMD_DHCP_BOUND, + NET_EVENT_IPV4_CMD_DHCP_STOP, + NET_EVENT_IPV4_CMD_MCAST_JOIN, + NET_EVENT_IPV4_CMD_MCAST_LEAVE, + NET_EVENT_IPV4_CMD_ACD_SUCCEED, + NET_EVENT_IPV4_CMD_ACD_FAILED, + NET_EVENT_IPV4_CMD_ACD_CONFLICT, +}; + +/* L4 network events */ +#define _NET_L4_LAYER NET_MGMT_LAYER_L4 +#define _NET_L4_CORE_CODE 0x114 +#define _NET_EVENT_L4_BASE (NET_MGMT_EVENT_BIT | \ + NET_MGMT_IFACE_BIT | \ + NET_MGMT_LAYER(_NET_L4_LAYER) | \ + NET_MGMT_LAYER_CODE(_NET_L4_CORE_CODE)) + +enum net_event_l4_cmd { + NET_EVENT_L4_CMD_CONNECTED = 1, + NET_EVENT_L4_CMD_DISCONNECTED, + NET_EVENT_L4_CMD_IPV4_CONNECTED, + NET_EVENT_L4_CMD_IPV4_DISCONNECTED, + NET_EVENT_L4_CMD_IPV6_CONNECTED, + NET_EVENT_L4_CMD_IPV6_DISCONNECTED, + NET_EVENT_L4_CMD_DNS_SERVER_ADD, + NET_EVENT_L4_CMD_DNS_SERVER_DEL, + NET_EVENT_L4_CMD_HOSTNAME_CHANGED, + NET_EVENT_L4_CMD_CAPTURE_STARTED, + NET_EVENT_L4_CMD_CAPTURE_STOPPED, +}; + +/** @endcond */ + +/** Event emitted when the network interface goes down. */ +#define NET_EVENT_IF_DOWN \ + (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_DOWN) + +/** Event emitted when the network interface goes up. */ +#define NET_EVENT_IF_UP \ + (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_UP) + +/** Event emitted when the network interface is taken down manually. */ +#define NET_EVENT_IF_ADMIN_DOWN \ + (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_ADMIN_DOWN) + +/** Event emitted when the network interface goes up manually. */ +#define NET_EVENT_IF_ADMIN_UP \ + (_NET_EVENT_IF_BASE | NET_EVENT_IF_CMD_ADMIN_UP) + +/** Event emitted when an IPv6 address is added to the system. */ #define NET_EVENT_IPV6_ADDR_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_ADD) +/** Event emitted when an IPv6 address is removed from the system. */ #define NET_EVENT_IPV6_ADDR_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_DEL) +/** Event emitted when an IPv6 multicast address is added to the system. */ #define NET_EVENT_IPV6_MADDR_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MADDR_ADD) +/** Event emitted when an IPv6 multicast address is removed from the system. */ #define NET_EVENT_IPV6_MADDR_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MADDR_DEL) +/** Event emitted when an IPv6 prefix is added to the system. */ #define NET_EVENT_IPV6_PREFIX_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PREFIX_ADD) +/** Event emitted when an IPv6 prefix is removed from the system. */ #define NET_EVENT_IPV6_PREFIX_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PREFIX_DEL) +/** Event emitted when an IPv6 multicast group is joined. */ #define NET_EVENT_IPV6_MCAST_JOIN \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MCAST_JOIN) +/** Event emitted when an IPv6 multicast group is left. */ #define NET_EVENT_IPV6_MCAST_LEAVE \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_MCAST_LEAVE) +/** Event emitted when an IPv6 router is added to the system. */ #define NET_EVENT_IPV6_ROUTER_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTER_ADD) +/** Event emitted when an IPv6 router is removed from the system. */ #define NET_EVENT_IPV6_ROUTER_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTER_DEL) +/** Event emitted when an IPv6 route is added to the system. */ #define NET_EVENT_IPV6_ROUTE_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTE_ADD) +/** Event emitted when an IPv6 route is removed from the system. */ #define NET_EVENT_IPV6_ROUTE_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ROUTE_DEL) +/** Event emitted when an IPv6 duplicate address detection succeeds. */ #define NET_EVENT_IPV6_DAD_SUCCEED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DAD_SUCCEED) +/** Event emitted when an IPv6 duplicate address detection fails. */ #define NET_EVENT_IPV6_DAD_FAILED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DAD_FAILED) +/** Event emitted when an IPv6 neighbor is added to the system. */ #define NET_EVENT_IPV6_NBR_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_NBR_ADD) +/** Event emitted when an IPv6 neighbor is removed from the system. */ #define NET_EVENT_IPV6_NBR_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_NBR_DEL) +/** Event emitted when an IPv6 DHCP client starts. */ #define NET_EVENT_IPV6_DHCP_START \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DHCP_START) +/** Event emitted when an IPv6 DHCP client address is bound. */ #define NET_EVENT_IPV6_DHCP_BOUND \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DHCP_BOUND) +/** Event emitted when an IPv6 DHCP client is stopped. */ #define NET_EVENT_IPV6_DHCP_STOP \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_DHCP_STOP) +/** IPv6 address is deprecated. */ #define NET_EVENT_IPV6_ADDR_DEPRECATED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_ADDR_DEPRECATED) +/** IPv6 Privacy extension is enabled. */ #define NET_EVENT_IPV6_PE_ENABLED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_ENABLED) +/** IPv6 Privacy extension is disabled. */ #define NET_EVENT_IPV6_PE_DISABLED \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_DISABLED) +/** IPv6 Privacy extension filter is added. */ #define NET_EVENT_IPV6_PE_FILTER_ADD \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_FILTER_ADD) +/** IPv6 Privacy extension filter is removed. */ #define NET_EVENT_IPV6_PE_FILTER_DEL \ (_NET_EVENT_IPV6_BASE | NET_EVENT_IPV6_CMD_PE_FILTER_DEL) -/* IPv4 Events*/ -#define _NET_IPV4_LAYER NET_MGMT_LAYER_L3 -#define _NET_IPV4_CORE_CODE 0x004 -#define _NET_EVENT_IPV4_BASE (NET_MGMT_EVENT_BIT | \ - NET_MGMT_IFACE_BIT | \ - NET_MGMT_LAYER(_NET_IPV4_LAYER) | \ - NET_MGMT_LAYER_CODE(_NET_IPV4_CORE_CODE)) - -enum net_event_ipv4_cmd { - NET_EVENT_IPV4_CMD_ADDR_ADD = 1, - NET_EVENT_IPV4_CMD_ADDR_DEL, - NET_EVENT_IPV4_CMD_MADDR_ADD, - NET_EVENT_IPV4_CMD_MADDR_DEL, - NET_EVENT_IPV4_CMD_ROUTER_ADD, - NET_EVENT_IPV4_CMD_ROUTER_DEL, - NET_EVENT_IPV4_CMD_DHCP_START, - NET_EVENT_IPV4_CMD_DHCP_BOUND, - NET_EVENT_IPV4_CMD_DHCP_STOP, - NET_EVENT_IPV4_CMD_MCAST_JOIN, - NET_EVENT_IPV4_CMD_MCAST_LEAVE, -}; - +/** Event emitted when an IPv4 address is added to the system. */ #define NET_EVENT_IPV4_ADDR_ADD \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ADDR_ADD) +/** Event emitted when an IPv4 address is removed from the system. */ #define NET_EVENT_IPV4_ADDR_DEL \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ADDR_DEL) +/** Event emitted when an IPv4 multicast address is added to the system. */ #define NET_EVENT_IPV4_MADDR_ADD \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_MADDR_ADD) +/** Event emitted when an IPv4 multicast address is removed from the system. */ #define NET_EVENT_IPV4_MADDR_DEL \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_MADDR_DEL) +/** Event emitted when an IPv4 router is added to the system. */ #define NET_EVENT_IPV4_ROUTER_ADD \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ROUTER_ADD) +/** Event emitted when an IPv4 router is removed from the system. */ #define NET_EVENT_IPV4_ROUTER_DEL \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ROUTER_DEL) +/** Event emitted when an IPv4 DHCP client is started. */ #define NET_EVENT_IPV4_DHCP_START \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_DHCP_START) +/** Event emitted when an IPv4 DHCP client address is bound. */ #define NET_EVENT_IPV4_DHCP_BOUND \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_DHCP_BOUND) +/** Event emitted when an IPv4 DHCP client is stopped. */ #define NET_EVENT_IPV4_DHCP_STOP \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_DHCP_STOP) +/** Event emitted when an IPv4 multicast group is joined. */ #define NET_EVENT_IPV4_MCAST_JOIN \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_MCAST_JOIN) +/** Event emitted when an IPv4 multicast group is left. */ #define NET_EVENT_IPV4_MCAST_LEAVE \ (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_MCAST_LEAVE) +/** Event emitted when an IPv4 address conflict detection succeeds. */ +#define NET_EVENT_IPV4_ACD_SUCCEED \ + (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ACD_SUCCEED) -/* L4 network events */ -#define _NET_L4_LAYER NET_MGMT_LAYER_L4 -#define _NET_L4_CORE_CODE 0x114 -#define _NET_EVENT_L4_BASE (NET_MGMT_EVENT_BIT | \ - NET_MGMT_IFACE_BIT | \ - NET_MGMT_LAYER(_NET_L4_LAYER) | \ - NET_MGMT_LAYER_CODE(_NET_L4_CORE_CODE)) +/** Event emitted when an IPv4 address conflict detection fails. */ +#define NET_EVENT_IPV4_ACD_FAILED \ + (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ACD_FAILED) -enum net_event_l4_cmd { - NET_EVENT_L4_CMD_CONNECTED = 1, - NET_EVENT_L4_CMD_DISCONNECTED, - NET_EVENT_L4_CMD_DNS_SERVER_ADD, - NET_EVENT_L4_CMD_DNS_SERVER_DEL, - NET_EVENT_L4_CMD_HOSTNAME_CHANGED, - NET_EVENT_L4_CMD_CAPTURE_STARTED, - NET_EVENT_L4_CMD_CAPTURE_STOPPED, -}; +/** Event emitted when an IPv4 address conflict was detected after the address + * was confirmed as safe to use. It's up to the application to determine on + * how to act in such case. + */ +#define NET_EVENT_IPV4_ACD_CONFLICT \ + (_NET_EVENT_IPV4_BASE | NET_EVENT_IPV4_CMD_ACD_CONFLICT) -#define NET_EVENT_L4_CONNECTED \ +/** Event emitted when the system is considered to be connected. + * The connected in this context means that the network interface is up, + * and the interface has either IPv4 or IPv6 address assigned to it. + */ +#define NET_EVENT_L4_CONNECTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_CONNECTED) +/** Event emitted when the system is no longer connected. + * Typically this means that network connectivity is lost either by + * the network interface is going down, or the interface has no longer + * an IP address etc. + */ #define NET_EVENT_L4_DISCONNECTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DISCONNECTED) + +/** Event raised when IPv4 network connectivity is available. */ +#define NET_EVENT_L4_IPV4_CONNECTED \ + (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV4_CONNECTED) + +/** Event emitted when IPv4 network connectivity is lost. */ +#define NET_EVENT_L4_IPV4_DISCONNECTED \ + (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV4_DISCONNECTED) + +/** Event emitted when IPv6 network connectivity is available. */ +#define NET_EVENT_L4_IPV6_CONNECTED \ + (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV6_CONNECTED) + +/** Event emitted when IPv6 network connectivity is lost. */ +#define NET_EVENT_L4_IPV6_DISCONNECTED \ + (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_IPV6_DISCONNECTED) + +/** Event emitted when a DNS server is added to the system. */ #define NET_EVENT_DNS_SERVER_ADD \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DNS_SERVER_ADD) +/** Event emitted when a DNS server is removed from the system. */ #define NET_EVENT_DNS_SERVER_DEL \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_DNS_SERVER_DEL) +/** Event emitted when the system hostname is changed. */ #define NET_EVENT_HOSTNAME_CHANGED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_HOSTNAME_CHANGED) +/** Network packet capture is started. */ #define NET_EVENT_CAPTURE_STARTED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_CAPTURE_STARTED) +/** Network packet capture is stopped. */ #define NET_EVENT_CAPTURE_STOPPED \ (_NET_EVENT_L4_BASE | NET_EVENT_L4_CMD_CAPTURE_STOPPED) -/** @endcond */ - /** * @brief Network Management event information structure * Used to pass information on network events like @@ -268,6 +359,7 @@ enum net_event_l4_cmd { * information. */ struct net_event_ipv6_addr { + /** IPv6 address related to this event */ struct in6_addr addr; }; @@ -281,8 +373,10 @@ struct net_event_ipv6_addr { * @note: idx will be '-1' in case of NET_EVENT_IPV6_NBR_DEL event. */ struct net_event_ipv6_nbr { + /** Neighbor IPv6 address */ struct in6_addr addr; - int idx; /* NBR index*/ + /** Neighbor index in cache */ + int idx; }; /** @@ -294,8 +388,11 @@ struct net_event_ipv6_nbr { * information. */ struct net_event_ipv6_route { + /** IPv6 address of the next hop */ struct in6_addr nexthop; - struct in6_addr addr; /* addr/prefix */ + /** IPv6 address or prefix of the route */ + struct in6_addr addr; + /** IPv6 prefix length */ uint8_t prefix_len; }; @@ -308,8 +405,11 @@ struct net_event_ipv6_route { * information. */ struct net_event_ipv6_prefix { - struct in6_addr addr; /* prefix */ + /** IPv6 prefix */ + struct in6_addr addr; + /** IPv6 prefix length */ uint8_t len; + /** IPv6 prefix lifetime in seconds */ uint32_t lifetime; }; @@ -320,6 +420,7 @@ struct net_event_ipv6_prefix { * information. */ struct net_event_l4_hostname { + /** New hostname */ char hostname[NET_HOSTNAME_SIZE]; }; @@ -334,7 +435,9 @@ struct net_event_l4_hostname { * This is only available if CONFIG_NET_IPV6_PE_FILTER_PREFIX_COUNT is >0. */ struct net_event_ipv6_pe_filter { + /** IPv6 address of privacy extension filter */ struct in6_addr prefix; + /** IPv6 filter deny or allow list */ bool is_deny_list; }; diff --git a/include/zephyr/net/net_if.h b/include/zephyr/net/net_if.h index 9c27e08d2c26a..bcadd814f394b 100644 --- a/include/zephyr/net/net_if.h +++ b/include/zephyr/net/net_if.h @@ -62,11 +62,6 @@ struct net_if_addr { struct net_timeout lifetime; #endif -#if defined(CONFIG_NET_IPV6_DAD) && defined(CONFIG_NET_NATIVE_IPV6) - /** Duplicate address detection (DAD) timer */ - sys_snode_t dad_node; - uint32_t dad_start; -#endif /** How the IP address was set */ enum net_addr_type addr_type; @@ -90,14 +85,38 @@ struct net_if_addr { */ int32_t addr_timeout; #endif +#endif /* CONFIG_NET_NATIVE_IPV6 */ + union { #if defined(CONFIG_NET_IPV6_DAD) - /** How many times we have done DAD */ - uint8_t dad_count; - /* What interface the DAD is running */ + struct { + /** Duplicate address detection (DAD) timer */ + sys_snode_t dad_node; + uint32_t dad_start; + + /** How many times we have done DAD */ + uint8_t dad_count; + }; +#endif /* CONFIG_NET_IPV6_DAD */ +#if defined(CONFIG_NET_IPV4_ACD) + struct { + /** Address conflict detection (ACD) timer. */ + sys_snode_t acd_node; + k_timepoint_t acd_timeout; + + /** ACD probe/announcement counter. */ + uint8_t acd_count; + + /** ACD status. */ + uint8_t acd_state; + }; +#endif /* CONFIG_NET_IPV4_ACD */ + }; + +#if defined(CONFIG_NET_IPV6_DAD) || defined(CONFIG_NET_IPV4_ACD) + /** What interface the conflict detection is running */ uint8_t ifindex; #endif -#endif /* CONFIG_NET_NATIVE_IPV6 */ /** Is the IP address valid forever */ uint8_t is_infinite : 1; @@ -263,15 +282,15 @@ enum net_if_flag { /** @endcond */ }; -/** Network interface operational status (RFC 2863). */ +/** @brief Network interface operational status (RFC 2863). */ enum net_if_oper_state { - NET_IF_OPER_UNKNOWN, - NET_IF_OPER_NOTPRESENT, - NET_IF_OPER_DOWN, - NET_IF_OPER_LOWERLAYERDOWN, - NET_IF_OPER_TESTING, - NET_IF_OPER_DORMANT, - NET_IF_OPER_UP, + NET_IF_OPER_UNKNOWN, /**< Initial (unknown) value */ + NET_IF_OPER_NOTPRESENT, /**< Hardware missing */ + NET_IF_OPER_DOWN, /**< Interface is down */ + NET_IF_OPER_LOWERLAYERDOWN, /**< Lower layer interface is down */ + NET_IF_OPER_TESTING, /**< Training mode */ + NET_IF_OPER_DORMANT, /**< Waiting external action */ + NET_IF_OPER_UP, /**< Interface is up */ } __packed; #if defined(CONFIG_NET_OFFLOAD) @@ -290,6 +309,7 @@ struct net_offload; #endif /* @endcond */ +/** IPv6 configuration */ struct net_if_ipv6 { /** Unicast IP addresses */ struct net_if_addr unicast[NET_IF_MAX_IPV6_ADDR]; @@ -336,6 +356,7 @@ struct net_if_ipv6 { }; #if defined(CONFIG_NET_DHCPV6) && defined(CONFIG_NET_NATIVE_IPV6) +/** DHCPv6 configuration */ struct net_if_dhcpv6 { /** Used for timer list. */ sys_snode_t node; @@ -420,6 +441,7 @@ struct net_if_addr_ipv4 { struct in_addr netmask; }; +/** IPv4 configuration */ struct net_if_ipv4 { /** Unicast IP addresses */ struct net_if_addr_ipv4 unicast[NET_IF_MAX_IPV4_ADDR]; @@ -435,6 +457,11 @@ struct net_if_ipv4 { /** IPv4 time-to-live for multicast packets */ uint8_t mcast_ttl; + +#if defined(CONFIG_NET_IPV4_ACD) + /** IPv4 conflict count. */ + uint8_t conflict_cnt; +#endif }; #if defined(CONFIG_NET_DHCPV4) && defined(CONFIG_NET_NATIVE_IPV4) @@ -492,36 +519,15 @@ struct net_if_dhcpv4 { #if defined(CONFIG_NET_IPV4_AUTO) && defined(CONFIG_NET_NATIVE_IPV4) struct net_if_ipv4_autoconf { - /** Used for timer lists */ - sys_snode_t node; - /** Backpointer to correct network interface */ struct net_if *iface; - /** Timer start */ - int64_t timer_start; - - /** Time for INIT, DISCOVER, REQUESTING, RENEWAL */ - uint32_t timer_timeout; - - /** Current IP addr */ - struct in_addr current_ip; - /** Requested IP addr */ struct in_addr requested_ip; /** IPV4 Autoconf state in the process of network address allocation. */ enum net_ipv4_autoconf_state state; - - /** Number of sent probe requests */ - uint8_t probe_cnt; - - /** Number of sent announcements */ - uint8_t announce_cnt; - - /** Incoming conflict count */ - uint8_t conflict_cnt; }; #endif /* CONFIG_NET_IPV4_AUTO */ @@ -633,7 +639,7 @@ struct net_if_dev { /** Interface's private L2 data pointer */ void *l2_data; - /* For internal use */ + /** For internal use */ ATOMIC_DEFINE(flags, NET_IF_NUM_FLAGS); /** The hardware link address */ @@ -689,7 +695,10 @@ struct net_if { int tx_pending; #endif + /** Mutex protecting this network interface instance */ struct k_mutex lock; + + /** Mutex used when sending data */ struct k_mutex tx_lock; /** Network interface specific flags */ @@ -698,14 +707,17 @@ struct net_if { */ uint8_t pe_enabled : 1; - /* If PE is enabled, then this tells whether public addresses + /** If PE is enabled, then this tells whether public addresses * are preferred over temporary ones for this interface. */ uint8_t pe_prefer_public : 1; + /** Unused bit flags (ignore) */ uint8_t _unused : 6; }; +/** @cond INTERNAL_HIDDEN */ + static inline void net_if_lock(struct net_if *iface) { NET_ASSERT(iface); @@ -745,6 +757,8 @@ static inline void net_if_tx_unlock(struct net_if *iface) k_mutex_unlock(&iface->tx_lock); } +/** @endcond */ + /** * @brief Set a value in network interface flags * @@ -1820,6 +1834,8 @@ uint8_t net_if_ipv6_get_hop_limit(struct net_if *iface); */ void net_if_ipv6_set_hop_limit(struct net_if *iface, uint8_t hop_limit); +/** @cond INTERNAL_HIDDEN */ + /* The old hop limit setter function is deprecated because the naming * of it was incorrect. The API name was missing "_if_" so this function * should not be used. @@ -1831,6 +1847,8 @@ static inline void net_ipv6_set_hop_limit(struct net_if *iface, net_if_ipv6_set_hop_limit(iface, hop_limit); } +/** @endcond */ + /** * @brief Get IPv6 multicast hop limit specified for a given interface. This is the * default value but can be overridden by the user. @@ -2628,16 +2646,61 @@ void net_if_unregister_link_cb(struct net_if_link_cb *link); void net_if_call_link_cb(struct net_if *iface, struct net_linkaddr *lladdr, int status); +/** @cond INTERNAL_HIDDEN */ + +/* used to ensure encoding of checksum support in net_if.h and + * ethernet.h is the same + */ +#define NET_IF_CHECKSUM_NONE_BIT 0 +#define NET_IF_CHECKSUM_IPV4_HEADER_BIT BIT(0) +#define NET_IF_CHECKSUM_IPV4_ICMP_BIT BIT(1) +/* Space for future protocols and restrictions for IPV4 */ +#define NET_IF_CHECKSUM_IPV6_HEADER_BIT BIT(10) +#define NET_IF_CHECKSUM_IPV6_ICMP_BIT BIT(11) +/* Space for future protocols and restrictions for IPV6 */ +#define NET_IF_CHECKSUM_TCP_BIT BIT(21) +#define NET_IF_CHECKSUM_UDP_BIT BIT(22) + +/** @endcond */ + +/** + * @brief Type of checksum for which support in the interface will be queried. + */ +enum net_if_checksum_type { + /** Interface supports IP version 4 header checksum calculation */ + NET_IF_CHECKSUM_IPV4_HEADER = NET_IF_CHECKSUM_IPV4_HEADER_BIT, + /** Interface supports checksum calculation for TCP payload in IPv4 */ + NET_IF_CHECKSUM_IPV4_TCP = NET_IF_CHECKSUM_IPV4_HEADER_BIT | + NET_IF_CHECKSUM_TCP_BIT, + /** Interface supports checksum calculation for UDP payload in IPv4 */ + NET_IF_CHECKSUM_IPV4_UDP = NET_IF_CHECKSUM_IPV4_HEADER_BIT | + NET_IF_CHECKSUM_UDP_BIT, + /** Interface supports checksum calculation for ICMP4 payload in IPv4 */ + NET_IF_CHECKSUM_IPV4_ICMP = NET_IF_CHECKSUM_IPV4_ICMP_BIT, + /** Interface supports IP version 6 header checksum calculation */ + NET_IF_CHECKSUM_IPV6_HEADER = NET_IF_CHECKSUM_IPV6_HEADER_BIT, + /** Interface supports checksum calculation for TCP payload in IPv6 */ + NET_IF_CHECKSUM_IPV6_TCP = NET_IF_CHECKSUM_IPV6_HEADER_BIT | + NET_IF_CHECKSUM_TCP_BIT, + /** Interface supports checksum calculation for UDP payload in IPv6 */ + NET_IF_CHECKSUM_IPV6_UDP = NET_IF_CHECKSUM_IPV6_HEADER_BIT | + NET_IF_CHECKSUM_UDP_BIT, + /** Interface supports checksum calculation for ICMP6 payload in IPv6 */ + NET_IF_CHECKSUM_IPV6_ICMP = NET_IF_CHECKSUM_IPV6_ICMP_BIT +}; + /** * @brief Check if received network packet checksum calculation can be avoided * or not. For example many ethernet devices support network packet offloading * in which case the IP stack does not need to calculate the checksum. * * @param iface Network interface + * @param chksum_type L3 and/or L4 protocol for which to compute checksum * * @return True if checksum needs to be calculated, false otherwise. */ -bool net_if_need_calc_rx_checksum(struct net_if *iface); +bool net_if_need_calc_rx_checksum(struct net_if *iface, + enum net_if_checksum_type chksum_type); /** * @brief Check if network packet checksum calculation can be avoided or not @@ -2646,10 +2709,12 @@ bool net_if_need_calc_rx_checksum(struct net_if *iface); * checksum. * * @param iface Network interface + * @param chksum_type L3 and/or L4 protocol for which to compute checksum * * @return True if checksum needs to be calculated, false otherwise. */ -bool net_if_need_calc_tx_checksum(struct net_if *iface); +bool net_if_need_calc_tx_checksum(struct net_if *iface, + enum net_if_checksum_type chksum_type); /** * @brief Get interface according to index @@ -3343,7 +3408,7 @@ struct net_if_api { } #endif -#include +#include /** * @} diff --git a/include/zephyr/net/net_ip.h b/include/zephyr/net/net_ip.h index cf5bc56f1da43..2e02744a72fa1 100644 --- a/include/zephyr/net/net_ip.h +++ b/include/zephyr/net/net_ip.h @@ -138,26 +138,26 @@ enum net_sock_type { /** IPv6 address struct */ struct in6_addr { union { - uint8_t s6_addr[16]; - uint16_t s6_addr16[8]; /* In big endian */ - uint32_t s6_addr32[4]; /* In big endian */ + uint8_t s6_addr[16]; /**< IPv6 address buffer */ + uint16_t s6_addr16[8]; /**< In big endian */ + uint32_t s6_addr32[4]; /**< In big endian */ }; }; -/* Binary size of the IPv6 address */ +/** Binary size of the IPv6 address */ #define NET_IPV6_ADDR_SIZE 16 /** IPv4 address struct */ struct in_addr { union { - uint8_t s4_addr[4]; - uint16_t s4_addr16[2]; /* In big endian */ - uint32_t s4_addr32[1]; /* In big endian */ - uint32_t s_addr; /* In big endian, for POSIX compatibility. */ + uint8_t s4_addr[4]; /**< IPv4 address buffer */ + uint16_t s4_addr16[2]; /**< In big endian */ + uint32_t s4_addr32[1]; /**< In big endian */ + uint32_t s_addr; /**< In big endian, for POSIX compatibility. */ }; }; -/* Binary size of the IPv4 address */ +/** Binary size of the IPv4 address */ #define NET_IPV4_ADDR_SIZE 4 /** Socket address family type */ @@ -176,51 +176,56 @@ typedef size_t socklen_t; /** Socket address struct for IPv6. */ struct sockaddr_in6 { - sa_family_t sin6_family; /* AF_INET6 */ - uint16_t sin6_port; /* Port number */ - struct in6_addr sin6_addr; /* IPv6 address */ - uint8_t sin6_scope_id; /* interfaces for a scope */ -}; - -struct sockaddr_in6_ptr { - sa_family_t sin6_family; /* AF_INET6 */ - uint16_t sin6_port; /* Port number */ - struct in6_addr *sin6_addr; /* IPv6 address */ - uint8_t sin6_scope_id; /* interfaces for a scope */ + sa_family_t sin6_family; /**< AF_INET6 */ + uint16_t sin6_port; /**< Port number */ + struct in6_addr sin6_addr; /**< IPv6 address */ + uint8_t sin6_scope_id; /**< Interfaces for a scope */ }; /** Socket address struct for IPv4. */ struct sockaddr_in { - sa_family_t sin_family; /* AF_INET */ - uint16_t sin_port; /* Port number */ - struct in_addr sin_addr; /* IPv4 address */ -}; - -struct sockaddr_in_ptr { - sa_family_t sin_family; /* AF_INET */ - uint16_t sin_port; /* Port number */ - struct in_addr *sin_addr; /* IPv4 address */ + sa_family_t sin_family; /**< AF_INET */ + uint16_t sin_port; /**< Port number */ + struct in_addr sin_addr; /**< IPv4 address */ }; /** Socket address struct for packet socket. */ struct sockaddr_ll { - sa_family_t sll_family; /* Always AF_PACKET */ - uint16_t sll_protocol; /* Physical-layer protocol */ - int sll_ifindex; /* Interface number */ - uint16_t sll_hatype; /* ARP hardware type */ - uint8_t sll_pkttype; /* Packet type */ - uint8_t sll_halen; /* Length of address */ - uint8_t sll_addr[8]; /* Physical-layer address, big endian */ + sa_family_t sll_family; /**< Always AF_PACKET */ + uint16_t sll_protocol; /**< Physical-layer protocol */ + int sll_ifindex; /**< Interface number */ + uint16_t sll_hatype; /**< ARP hardware type */ + uint8_t sll_pkttype; /**< Packet type */ + uint8_t sll_halen; /**< Length of address */ + uint8_t sll_addr[8]; /**< Physical-layer address, big endian */ +}; + +/** @cond INTERNAL_HIDDEN */ + +/** Socket address struct for IPv6 where address is a pointer */ +struct sockaddr_in6_ptr { + sa_family_t sin6_family; /**< AF_INET6 */ + uint16_t sin6_port; /**< Port number */ + struct in6_addr *sin6_addr; /**< IPv6 address */ + uint8_t sin6_scope_id; /**< interfaces for a scope */ +}; + +/** Socket address struct for IPv4 where address is a pointer */ +struct sockaddr_in_ptr { + sa_family_t sin_family; /**< AF_INET */ + uint16_t sin_port; /**< Port number */ + struct in_addr *sin_addr; /**< IPv4 address */ }; +/** Socket address struct for packet socket where address is a pointer */ struct sockaddr_ll_ptr { - sa_family_t sll_family; /* Always AF_PACKET */ - uint16_t sll_protocol; /* Physical-layer protocol */ - int sll_ifindex; /* Interface number */ - uint16_t sll_hatype; /* ARP hardware type */ - uint8_t sll_pkttype; /* Packet type */ - uint8_t sll_halen; /* Length of address */ - uint8_t *sll_addr; /* Physical-layer address, big endian */ + sa_family_t sll_family; /**< Always AF_PACKET */ + uint16_t sll_protocol; /**< Physical-layer protocol */ + int sll_ifindex; /**< Interface number */ + uint16_t sll_hatype; /**< ARP hardware type */ + uint8_t sll_pkttype; /**< Packet type */ + uint8_t sll_halen; /**< Length of address */ + uint8_t *sll_addr; /**< Physical-layer address, big endian */ }; struct sockaddr_can_ptr { @@ -228,31 +233,37 @@ struct sockaddr_can_ptr { int can_ifindex; }; +/** @endcond */ + #if !defined(HAVE_IOVEC) +/** IO vector array element */ struct iovec { - void *iov_base; - size_t iov_len; + void *iov_base; /**< Pointer to data */ + size_t iov_len; /**< Length of the data */ }; #endif +/** Message struct */ struct msghdr { - void *msg_name; /* optional socket address, big endian */ - socklen_t msg_namelen; /* size of socket address */ - struct iovec *msg_iov; /* scatter/gather array */ - size_t msg_iovlen; /* number of elements in msg_iov */ - void *msg_control; /* ancillary data */ - size_t msg_controllen; /* ancillary data buffer len */ - int msg_flags; /* flags on received message */ + void *msg_name; /**< Optional socket address, big endian */ + socklen_t msg_namelen; /**< Size of socket address */ + struct iovec *msg_iov; /**< Scatter/gather array */ + size_t msg_iovlen; /**< Number of elements in msg_iov */ + void *msg_control; /**< Ancillary data */ + size_t msg_controllen; /**< Ancillary data buffer len */ + int msg_flags; /**< Flags on received message */ }; +/** Control message ancillary data */ struct cmsghdr { - socklen_t cmsg_len; /* Number of bytes, including header */ - int cmsg_level; /* Originating protocol */ - int cmsg_type; /* Protocol-specific type */ - /* Flexible array member to force alignment of cmsghdr */ - z_max_align_t cmsg_data[]; + socklen_t cmsg_len; /**< Number of bytes, including header */ + int cmsg_level; /**< Originating protocol */ + int cmsg_type; /**< Protocol-specific type */ + z_max_align_t cmsg_data[]; /**< Flexible array member to force alignment of cmsghdr */ }; +/** @cond INTERNAL_HIDDEN */ + /* Alignment for headers and data. These are arch specific but define * them here atm if not found alredy. */ @@ -263,13 +274,24 @@ struct cmsghdr { #define ALIGN_D(x) ROUND_UP(x, __alignof__(z_max_align_t)) #endif +/** @endcond */ + #if !defined(CMSG_FIRSTHDR) +/** + * Returns a pointer to the first cmsghdr in the ancillary data buffer + * associated with the passed msghdr. It returns NULL if there isn't + * enough space for a cmsghdr in the buffer. + */ #define CMSG_FIRSTHDR(msghdr) \ ((msghdr)->msg_controllen >= sizeof(struct cmsghdr) ? \ (struct cmsghdr *)((msghdr)->msg_control) : NULL) #endif #if !defined(CMSG_NXTHDR) +/** + * Returns the next valid cmsghdr after the passed cmsghdr. It returns NULL + * when there isn't enough space left in the buffer. + */ #define CMSG_NXTHDR(msghdr, cmsg) \ (((cmsg) == NULL) ? CMSG_FIRSTHDR(msghdr) : \ (((uint8_t *)(cmsg) + ALIGN_H((cmsg)->cmsg_len) + \ @@ -281,14 +303,30 @@ struct cmsghdr { #endif #if !defined(CMSG_DATA) +/** + * Returns a pointer to the data portion of a cmsghdr. The pointer returned + * cannot be assumed to be suitably aligned for accessing arbitrary payload + * data types. Applications should not cast it to a pointer type matching + * the payload, but should instead use memcpy(3) to copy data to or from a + * suitably declared object. + */ #define CMSG_DATA(cmsg) ((uint8_t *)(cmsg) + ALIGN_D(sizeof(struct cmsghdr))) #endif #if !defined(CMSG_SPACE) +/** + * Returns the number of bytes an ancillary element with payload of the passed + * data length occupies. + */ #define CMSG_SPACE(length) (ALIGN_D(sizeof(struct cmsghdr)) + ALIGN_H(length)) #endif #if !defined(CMSG_LEN) +/** + * Returns the value to store in the cmsg_len member of the cmsghdr structure, + * taking into account any necessary alignment. + * It takes the data length as an argument. + */ #define CMSG_LEN(length) (ALIGN_D(sizeof(struct cmsghdr)) + length) #endif @@ -345,8 +383,10 @@ struct cmsghdr { /** Generic sockaddr struct. Must be cast to proper type. */ struct sockaddr { - sa_family_t sa_family; + sa_family_t sa_family; /**< Address family */ +/** @cond INTERNAL_HIDDEN */ char data[NET_SOCKADDR_MAX_SIZE - sizeof(sa_family_t)]; +/** @endcond */ }; /** @cond INTERNAL_HIDDEN */ @@ -376,15 +416,30 @@ struct net_addr { }; }; +/** A pointer to IPv6 any address (all values zero) */ +extern const struct in6_addr in6addr_any; + +/** A pointer to IPv6 loopback address (::1) */ +extern const struct in6_addr in6addr_loopback; + +/** @endcond */ + +/** IPv6 address initializer */ #define IN6ADDR_ANY_INIT { { { 0, 0, 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0 } } } + +/** IPv6 loopback address initializer */ #define IN6ADDR_LOOPBACK_INIT { { { 0, 0, 0, 0, 0, 0, 0, \ 0, 0, 0, 0, 0, 0, 0, 0, 1 } } } -extern const struct in6_addr in6addr_any; -extern const struct in6_addr in6addr_loopback; +/** IPv4 any address */ +#define INADDR_ANY 0 -/** @endcond */ +/** IPv4 address initializer */ +#define INADDR_ANY_INIT { { { INADDR_ANY } } } + +/** IPv6 loopback address initializer */ +#define INADDR_LOOPBACK_INIT { { { 127, 0, 0, 1 } } } /** Max length of the IPv4 address as a string. Defined by POSIX. */ #define INET_ADDRSTRLEN 16 @@ -399,13 +454,9 @@ extern const struct in6_addr in6addr_loopback; #define NET_IPV6_ADDR_LEN sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx") #define NET_IPV4_ADDR_LEN sizeof("xxx.xxx.xxx.xxx") -#define INADDR_ANY 0 -#define INADDR_ANY_INIT { { { INADDR_ANY } } } - -#define INADDR_LOOPBACK_INIT { { { 127, 0, 0, 1 } } } - /** @endcond */ +/** @brief IP Maximum Transfer Unit */ enum net_ip_mtu { /** IPv6 MTU length. We must be able to receive this size IPv6 packet * without fragmentation. @@ -422,7 +473,7 @@ enum net_ip_mtu { NET_IPV4_MTU = 576, }; -/** Network packet priority settings described in IEEE 802.1Q Annex I.1 */ +/** @brief Network packet priority settings described in IEEE 802.1Q Annex I.1 */ enum net_priority { NET_PRIORITY_BK = 1, /**< Background (lowest) */ NET_PRIORITY_BE = 0, /**< Best effort (default) */ @@ -434,9 +485,9 @@ enum net_priority { NET_PRIORITY_NC = 7 /**< Network control (highest) */ } __packed; -#define NET_MAX_PRIORITIES 8 /* How many priority values there are */ +#define NET_MAX_PRIORITIES 8 /**< How many priority values there are */ -/** IPv6/IPv4 network connection tuple */ +/** @brief IPv6/IPv4 network connection tuple */ struct net_tuple { struct net_addr *remote_addr; /**< IPv6/IPv4 remote address */ struct net_addr *local_addr; /**< IPv6/IPv4 local address */ @@ -445,7 +496,7 @@ struct net_tuple { enum net_ip_protocol ip_proto; /**< IP protocol */ }; -/** What is the current state of the network address */ +/** @brief What is the current state of the network address */ enum net_addr_state { NET_ADDR_ANY_STATE = -1, /**< Default (invalid) address type */ NET_ADDR_TENTATIVE = 0, /**< Tentative address */ @@ -453,7 +504,7 @@ enum net_addr_state { NET_ADDR_DEPRECATED, /**< Deprecated address */ } __packed; -/** How the network address is assigned to network interface */ +/** @brief How the network address is assigned to network interface */ enum net_addr_type { /** Default value. This is not a valid value. */ NET_ADDR_ANY = 0, @@ -687,7 +738,7 @@ static inline bool net_ipv6_is_prefix(const uint8_t *addr1, } /* Create a mask that has remaining most significant bits set */ - mask = ((0xff << (8 - remain)) ^ 0xff) << remain; + mask = (uint8_t)((0xff << (8 - remain)) ^ 0xff) << remain; return (addr1[bytes] & mask) == (addr2[bytes] & mask); } @@ -1071,7 +1122,7 @@ static inline bool net_ipv6_is_addr_solicited_node(const struct in6_addr *addr) static inline bool net_ipv6_is_addr_mcast_scope(const struct in6_addr *addr, int scope) { - return (addr->s6_addr[0] == 0xff) && (addr->s6_addr[1] == scope); + return (addr->s6_addr[0] == 0xff) && ((addr->s6_addr[1] & 0xF) == scope); } /** @@ -1754,7 +1805,7 @@ static inline int net_ipv6_pe_del_filter(struct in6_addr *addr) } #endif -#include +#include /** * @} diff --git a/include/zephyr/net/net_mgmt.h b/include/zephyr/net/net_mgmt.h index f90bc8e183646..55c65b122ec24 100644 --- a/include/zephyr/net/net_mgmt.h +++ b/include/zephyr/net/net_mgmt.h @@ -90,14 +90,33 @@ typedef int (*net_mgmt_request_handler_t)(uint32_t mgmt_request, struct net_if *iface, void *data, size_t len); +/** + * @brief Generate a network management event. + * + * @param _mgmt_request Management event identifier + * @param _iface Network interface + * @param _data Any additional data for the event + * @param _len Length of the additional data. + */ #define net_mgmt(_mgmt_request, _iface, _data, _len) \ net_mgmt_##_mgmt_request(_mgmt_request, _iface, _data, _len) +/** + * @brief Declare a request handler function for the given network event. + * + * @param _mgmt_request Management event identifier + */ #define NET_MGMT_DEFINE_REQUEST_HANDLER(_mgmt_request) \ extern int net_mgmt_##_mgmt_request(uint32_t mgmt_request, \ struct net_if *iface, \ void *data, size_t len) +/** + * @brief Create a request handler function for the given network event. + * + * @param _mgmt_request Management event identifier + * @param _func Function for handling this event + */ #define NET_MGMT_REGISTER_REQUEST_HANDLER(_mgmt_request, _func) \ FUNC_ALIAS(_func, net_mgmt_##_mgmt_request, int) @@ -258,7 +277,7 @@ void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb); * @param mgmt_event The actual network event code to notify * @param iface a valid pointer on a struct net_if if only the event is * based on an iface. NULL otherwise. - * @param info a valid pointer on the information you want to pass along + * @param info A valid pointer on the information you want to pass along * with the event. NULL otherwise. Note the data pointed there is * normalized by the related event. * @param length size of the data pointed by info pointer. @@ -266,10 +285,20 @@ void net_mgmt_del_event_callback(struct net_mgmt_event_callback *cb); * Note: info and length are disabled if CONFIG_NET_MGMT_EVENT_INFO * is not defined. */ -#ifdef CONFIG_NET_MGMT_EVENT +#if defined(CONFIG_NET_MGMT_EVENT) void net_mgmt_event_notify_with_info(uint32_t mgmt_event, struct net_if *iface, const void *info, size_t length); +#else +#define net_mgmt_event_notify_with_info(...) +#endif +/** + * @brief Used by the system to notify an event without any additional information. + * @param mgmt_event The actual network event code to notify + * @param iface A valid pointer on a struct net_if if only the event is + * based on an iface. NULL otherwise. + */ +#if defined(CONFIG_NET_MGMT_EVENT) static inline void net_mgmt_event_notify(uint32_t mgmt_event, struct net_if *iface) { @@ -277,7 +306,6 @@ static inline void net_mgmt_event_notify(uint32_t mgmt_event, } #else #define net_mgmt_event_notify(...) -#define net_mgmt_event_notify_with_info(...) #endif /** diff --git a/include/zephyr/net/net_pkt.h b/include/zephyr/net/net_pkt.h index 18eba376fe725..a2bf19eda49f0 100644 --- a/include/zephyr/net/net_pkt.h +++ b/include/zephyr/net/net_pkt.h @@ -46,6 +46,8 @@ extern "C" { struct net_context; +/** @cond INTERNAL_HIDDEN */ + /* buffer cursor used in net_pkt */ struct net_pkt_cursor { /** Current net_buf pointer by the cursor */ @@ -54,6 +56,8 @@ struct net_pkt_cursor { uint8_t *pos; }; +/** @endcond */ + /** * @brief Network packet. * @@ -72,8 +76,8 @@ struct net_pkt { /** buffer holding the packet */ union { - struct net_buf *frags; - struct net_buf *buffer; + struct net_buf *frags; /**< buffer fragment */ + struct net_buf *buffer; /**< alias to a buffer fragment */ }; /** Internal buffer iterator used for reading/writing */ @@ -163,8 +167,8 @@ struct net_pkt { /* bitfield byte alignment boundary */ -#if defined(CONFIG_NET_IPV4_AUTO) - uint8_t ipv4_auto_arp_msg : 1; /* Is this pkt IPv4 autoconf ARP +#if defined(CONFIG_NET_IPV4_ACD) + uint8_t ipv4_acd_arp_msg : 1; /* Is this pkt IPv4 conflict detection ARP * message. * Note: family needs to be * AF_INET. @@ -193,6 +197,10 @@ struct net_pkt { */ #if defined(CONFIG_NET_IP_FRAGMENT) uint8_t ip_reassembled : 1; /* Packet is a reassembled IP packet. */ +#endif +#if defined(CONFIG_NET_PKT_TIMESTAMP) + uint8_t tx_timestamping : 1; /** Timestamp transmitted packet */ + uint8_t rx_timestamping : 1; /** Timestamp received packet */ #endif /* bitfield byte alignment boundary */ @@ -385,6 +393,38 @@ static inline void net_pkt_set_ptp(struct net_pkt *pkt, bool is_ptp) pkt->ptp_pkt = is_ptp; } +static inline bool net_pkt_is_tx_timestamping(struct net_pkt *pkt) +{ +#if defined(CONFIG_NET_PKT_TIMESTAMP) + return !!(pkt->tx_timestamping); +#else + return false; +#endif +} + +static inline void net_pkt_set_tx_timestamping(struct net_pkt *pkt, bool is_timestamping) +{ +#if defined(CONFIG_NET_PKT_TIMESTAMP) + pkt->tx_timestamping = is_timestamping; +#endif +} + +static inline bool net_pkt_is_rx_timestamping(struct net_pkt *pkt) +{ +#if defined(CONFIG_NET_PKT_TIMESTAMP) + return !!(pkt->rx_timestamping); +#else + return false; +#endif +} + +static inline void net_pkt_set_rx_timestamping(struct net_pkt *pkt, bool is_timestamping) +{ +#if defined(CONFIG_NET_PKT_TIMESTAMP) + pkt->rx_timestamping = is_timestamping; +#endif +} + static inline bool net_pkt_is_captured(struct net_pkt *pkt) { return !!(pkt->captured); @@ -1202,32 +1242,32 @@ static inline void net_pkt_set_ll_proto_type(struct net_pkt *pkt, uint16_t type) pkt->ll_proto_type = type; } -#if defined(CONFIG_NET_IPV4_AUTO) -static inline bool net_pkt_ipv4_auto(struct net_pkt *pkt) +#if defined(CONFIG_NET_IPV4_ACD) +static inline bool net_pkt_ipv4_acd(struct net_pkt *pkt) { - return !!(pkt->ipv4_auto_arp_msg); + return !!(pkt->ipv4_acd_arp_msg); } -static inline void net_pkt_set_ipv4_auto(struct net_pkt *pkt, - bool is_auto_arp_msg) +static inline void net_pkt_set_ipv4_acd(struct net_pkt *pkt, + bool is_acd_arp_msg) { - pkt->ipv4_auto_arp_msg = is_auto_arp_msg; + pkt->ipv4_acd_arp_msg = is_acd_arp_msg; } -#else /* CONFIG_NET_IPV4_AUTO */ -static inline bool net_pkt_ipv4_auto(struct net_pkt *pkt) +#else /* CONFIG_NET_IPV4_ACD */ +static inline bool net_pkt_ipv4_acd(struct net_pkt *pkt) { ARG_UNUSED(pkt); return false; } -static inline void net_pkt_set_ipv4_auto(struct net_pkt *pkt, - bool is_auto_arp_msg) +static inline void net_pkt_set_ipv4_acd(struct net_pkt *pkt, + bool is_acd_arp_msg) { ARG_UNUSED(pkt); - ARG_UNUSED(is_auto_arp_msg); + ARG_UNUSED(is_acd_arp_msg); } -#endif /* CONFIG_NET_IPV4_AUTO */ +#endif /* CONFIG_NET_IPV4_ACD */ #if defined(CONFIG_NET_LLDP) static inline bool net_pkt_is_lldp(struct net_pkt *pkt) @@ -1401,9 +1441,13 @@ static inline void net_pkt_set_remote_address(struct net_pkt *pkt, #define NET_PKT_SLAB_DEFINE(name, count) \ K_MEM_SLAB_DEFINE(name, sizeof(struct net_pkt), count, 4) +/** @cond INTERNAL_HIDDEN */ + /* Backward compatibility macro */ #define NET_PKT_TX_SLAB_DEFINE(name, count) NET_PKT_SLAB_DEFINE(name, count) +/** @endcond */ + /** * @brief Create a data fragment net_buf pool * @@ -1855,9 +1899,13 @@ struct net_pkt *net_pkt_rx_alloc(k_timeout_t timeout); struct net_pkt *net_pkt_alloc_on_iface(struct net_if *iface, k_timeout_t timeout); +/** @cond INTERNAL_HIDDEN */ + /* Same as above but specifically for RX packet */ struct net_pkt *net_pkt_rx_alloc_on_iface(struct net_if *iface, k_timeout_t timeout); +/** @endcond */ + #endif /** @@ -1918,12 +1966,17 @@ struct net_pkt *net_pkt_alloc_with_buffer(struct net_if *iface, enum net_ip_protocol proto, k_timeout_t timeout); +/** @cond INTERNAL_HIDDEN */ + /* Same as above but specifically for RX packet */ struct net_pkt *net_pkt_rx_alloc_with_buffer(struct net_if *iface, size_t size, sa_family_t family, enum net_ip_protocol proto, k_timeout_t timeout); + +/** @endcond */ + #endif /** @@ -2140,7 +2193,18 @@ struct net_pkt *net_pkt_shallow_clone(struct net_pkt *pkt, */ int net_pkt_read(struct net_pkt *pkt, void *data, size_t length); -/* Read uint8_t data data a net_pkt */ +/** + * @brief Read a byte (uint8_t) from a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The destination uint8_t where to copy the data + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_read_u8(struct net_pkt *pkt, uint8_t *data) { return net_pkt_read(pkt, data, 1); @@ -2203,13 +2267,35 @@ int net_pkt_read_be32(struct net_pkt *pkt, uint32_t *data); */ int net_pkt_write(struct net_pkt *pkt, const void *data, size_t length); -/* Write uint8_t data into a net_pkt. */ +/** + * @brief Write a byte (uint8_t) data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint8_t value to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_u8(struct net_pkt *pkt, uint8_t data) { return net_pkt_write(pkt, &data, sizeof(uint8_t)); } -/* Write uint16_t big endian data into a net_pkt. */ +/** + * @brief Write a uint16_t big endian data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint16_t value in host byte order to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_be16(struct net_pkt *pkt, uint16_t data) { uint16_t data_be16 = htons(data); @@ -2217,7 +2303,18 @@ static inline int net_pkt_write_be16(struct net_pkt *pkt, uint16_t data) return net_pkt_write(pkt, &data_be16, sizeof(uint16_t)); } -/* Write uint32_t big endian data into a net_pkt. */ +/** + * @brief Write a uint32_t big endian data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint32_t value in host byte order to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_be32(struct net_pkt *pkt, uint32_t data) { uint32_t data_be32 = htonl(data); @@ -2225,7 +2322,18 @@ static inline int net_pkt_write_be32(struct net_pkt *pkt, uint32_t data) return net_pkt_write(pkt, &data_be32, sizeof(uint32_t)); } -/* Write uint32_t little endian data into a net_pkt. */ +/** + * @brief Write a uint32_t little endian data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint32_t value in host byte order to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_le32(struct net_pkt *pkt, uint32_t data) { uint32_t data_le32 = sys_cpu_to_le32(data); @@ -2233,7 +2341,18 @@ static inline int net_pkt_write_le32(struct net_pkt *pkt, uint32_t data) return net_pkt_write(pkt, &data_le32, sizeof(uint32_t)); } -/* Write uint16_t little endian data into a net_pkt. */ +/** + * @brief Write a uint16_t little endian data to a net_pkt + * + * @details net_pkt's cursor should be properly initialized and, + * if needed, positioned using net_pkt_skip. + * Cursor position will be updated after the operation. + * + * @param pkt The network packet from where to read + * @param data The uint16_t value in host byte order to write + * + * @return 0 on success, negative errno code otherwise. + */ static inline int net_pkt_write_le16(struct net_pkt *pkt, uint16_t data) { uint16_t data_le16 = sys_cpu_to_le16(data); @@ -2311,6 +2430,8 @@ bool net_pkt_is_contiguous(struct net_pkt *pkt, size_t size); */ size_t net_pkt_get_contiguous_len(struct net_pkt *pkt); +/** @cond INTERNAL_HIDDEN */ + struct net_pkt_data_access { #if !defined(CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS) void *data; @@ -2343,6 +2464,8 @@ struct net_pkt_data_access { #endif /* CONFIG_NET_HEADERS_ALWAYS_CONTIGUOUS */ +/** @endcond */ + /** * @brief Get data from a network packet in a contiguous way * diff --git a/include/zephyr/net/net_pkt_filter.h b/include/zephyr/net/net_pkt_filter.h index aa1ad89b0e619..753ca347eb45c 100644 --- a/include/zephyr/net/net_pkt_filter.h +++ b/include/zephyr/net/net_pkt_filter.h @@ -46,7 +46,7 @@ struct npf_test { /** @brief filter rule structure */ struct npf_rule { - sys_snode_t node; + sys_snode_t node; /**< Slist rule list node */ enum net_verdict result; /**< result if all tests pass */ uint32_t nb_tests; /**< number of tests for this rule */ struct npf_test *tests[]; /**< pointers to @ref npf_test instances */ @@ -59,8 +59,8 @@ extern struct npf_rule npf_default_drop; /** @brief rule set for a given test location */ struct npf_rule_list { - sys_slist_t rule_head; - struct k_spinlock lock; + sys_slist_t rule_head; /**< List head */ + struct k_spinlock lock; /**< Lock protecting the list access */ }; /** @brief rule list applied to outgoing packets */ @@ -107,6 +107,8 @@ bool npf_remove_rule(struct npf_rule_list *rules, struct npf_rule *rule); */ bool npf_remove_all_rules(struct npf_rule_list *rules); +/** @cond INTERNAL_HIDDEN */ + /* convenience shortcuts */ #define npf_insert_send_rule(rule) npf_insert_rule(&npf_send_rules, rule) #define npf_insert_recv_rule(rule) npf_insert_rule(&npf_recv_rules, rule) @@ -138,6 +140,8 @@ bool npf_remove_all_rules(struct npf_rule_list *rules); #define npf_remove_all_ipv6_recv_rules() npf_remove_all_rules(&npf_ipv6_recv_rules) #endif /* CONFIG_NET_PKT_FILTER_IPV6_HOOK */ +/** @endcond */ + /** * @brief Statically define one packet filter rule * diff --git a/include/zephyr/net/net_stats.h b/include/zephyr/net/net_stats.h index f5a567fcdbc41..5a2ac84eaa216 100644 --- a/include/zephyr/net/net_stats.h +++ b/include/zephyr/net/net_stats.h @@ -186,8 +186,13 @@ struct net_stats_udp { * @brief IPv6 neighbor discovery statistics */ struct net_stats_ipv6_nd { + /** Number of dropped IPv6 neighbor discovery packets. */ net_stats_t drop; + + /** Number of received IPv6 neighbor discovery packets. */ net_stats_t recv; + + /** Number of sent IPv6 neighbor discovery packets. */ net_stats_t sent; }; @@ -195,13 +200,13 @@ struct net_stats_ipv6_nd { * @brief IPv6 multicast listener daemon statistics */ struct net_stats_ipv6_mld { - /** Number of received IPv6 MLD queries */ + /** Number of received IPv6 MLD queries. */ net_stats_t recv; - /** Number of sent IPv6 MLD reports */ + /** Number of sent IPv6 MLD reports. */ net_stats_t sent; - /** Number of dropped IPv6 MLD packets */ + /** Number of dropped IPv6 MLD packets. */ net_stats_t drop; }; @@ -223,7 +228,10 @@ struct net_stats_ipv4_igmp { * @brief Network packet transfer times for calculating average TX time */ struct net_stats_tx_time { + /** Sum of network packet transfer times. */ uint64_t sum; + + /** Number of network packets transferred. */ net_stats_t count; }; @@ -231,10 +239,15 @@ struct net_stats_tx_time { * @brief Network packet receive times for calculating average RX time */ struct net_stats_rx_time { + /** Sum of network packet receive times. */ uint64_t sum; + + /** Number of network packets received. */ net_stats_t count; }; +/** @cond INTERNAL_HIDDEN */ + #if NET_TC_TX_COUNT == 0 #define NET_TC_TX_STATS_COUNT 1 #else @@ -247,29 +260,43 @@ struct net_stats_rx_time { #define NET_TC_RX_STATS_COUNT NET_TC_RX_COUNT #endif +/** @endcond */ + /** * @brief Traffic class statistics */ struct net_stats_tc { + /** TX statistics for each traffic class */ struct { + /** Helper for calculating average TX time statistics */ struct net_stats_tx_time tx_time; #if defined(CONFIG_NET_PKT_TXTIME_STATS_DETAIL) + /** Detailed TX time statistics inside network stack */ struct net_stats_tx_time tx_time_detail[NET_PKT_DETAIL_STATS_COUNT]; #endif + /** Number of packets sent for this traffic class */ net_stats_t pkts; + /** Number of bytes sent for this traffic class */ net_stats_t bytes; + /** Priority of this traffic class */ uint8_t priority; } sent[NET_TC_TX_STATS_COUNT]; + /** RX statistics for each traffic class */ struct { + /** Helper for calculating average RX time statistics */ struct net_stats_rx_time rx_time; #if defined(CONFIG_NET_PKT_RXTIME_STATS_DETAIL) + /** Detailed RX time statistics inside network stack */ struct net_stats_rx_time rx_time_detail[NET_PKT_DETAIL_STATS_COUNT]; #endif + /** Number of packets received for this traffic class */ net_stats_t pkts; + /** Number of bytes received for this traffic class */ net_stats_t bytes; + /** Priority of this traffic class */ uint8_t priority; } recv[NET_TC_RX_STATS_COUNT]; }; @@ -279,9 +306,13 @@ struct net_stats_tc { * @brief Power management statistics */ struct net_stats_pm { + /** Total suspend time */ uint64_t overall_suspend_time; + /** How many times we were suspended */ net_stats_t suspend_count; + /** How long the last suspend took */ uint32_t last_suspend_time; + /** Network interface last suspend start time */ uint32_t start_time; }; @@ -367,6 +398,7 @@ struct net_stats { #endif #if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) + /** Power management statistics */ struct net_stats_pm pm; #endif }; @@ -375,26 +407,61 @@ struct net_stats { * @brief Ethernet error statistics */ struct net_stats_eth_errors { + /** Number of RX length errors */ net_stats_t rx_length_errors; + + /** Number of RX overrun errors */ net_stats_t rx_over_errors; + + /** Number of RX CRC errors */ net_stats_t rx_crc_errors; + + /** Number of RX frame errors */ net_stats_t rx_frame_errors; + + /** Number of RX net_pkt allocation errors */ net_stats_t rx_no_buffer_count; + + /** Number of RX missed errors */ net_stats_t rx_missed_errors; + + /** Number of RX long length errors */ net_stats_t rx_long_length_errors; + + /** Number of RX short length errors */ net_stats_t rx_short_length_errors; + + /** Number of RX buffer align errors */ net_stats_t rx_align_errors; + + /** Number of RX DMA failed errors */ net_stats_t rx_dma_failed; + + /** Number of RX net_buf allocation errors */ net_stats_t rx_buf_alloc_failed; + /** Number of TX aborted errors */ net_stats_t tx_aborted_errors; + + /** Number of TX carrier errors */ net_stats_t tx_carrier_errors; + + /** Number of TX FIFO errors */ net_stats_t tx_fifo_errors; + + /** Number of TX heartbeat errors */ net_stats_t tx_heartbeat_errors; + + /** Number of TX window errors */ net_stats_t tx_window_errors; + + /** Number of TX DMA failed errors */ net_stats_t tx_dma_failed; + /** Number of uncorrected ECC errors */ net_stats_t uncorr_ecc_errors; + + /** Number of corrected ECC errors */ net_stats_t corr_ecc_errors; }; @@ -402,9 +469,16 @@ struct net_stats_eth_errors { * @brief Ethernet flow control statistics */ struct net_stats_eth_flow { + /** Number of RX XON flow control */ net_stats_t rx_flow_control_xon; + + /** Number of RX XOFF flow control */ net_stats_t rx_flow_control_xoff; + + /** Number of TX XON flow control */ net_stats_t tx_flow_control_xon; + + /** Number of TX XOFF flow control */ net_stats_t tx_flow_control_xoff; }; @@ -412,7 +486,10 @@ struct net_stats_eth_flow { * @brief Ethernet checksum statistics */ struct net_stats_eth_csum { + /** Number of good RX checksum offloading */ net_stats_t rx_csum_offload_good; + + /** Number of failed RX checksum offloading */ net_stats_t rx_csum_offload_errors; }; @@ -420,8 +497,13 @@ struct net_stats_eth_csum { * @brief Ethernet hardware timestamp statistics */ struct net_stats_eth_hw_timestamp { + /** Number of RX hardware timestamp cleared */ net_stats_t rx_hwtstamp_cleared; + + /** Number of RX hardware timestamp timeout */ net_stats_t tx_hwtstamp_timeouts; + + /** Number of RX hardware timestamp skipped */ net_stats_t tx_hwtstamp_skipped; }; @@ -430,8 +512,8 @@ struct net_stats_eth_hw_timestamp { * @brief Ethernet vendor specific statistics */ struct net_stats_eth_vendor { - const char * const key; - uint32_t value; + const char * const key; /**< Key name of vendor statistics */ + uint32_t value; /**< Value of the statistics key */ }; #endif @@ -439,20 +521,48 @@ struct net_stats_eth_vendor { * @brief All Ethernet specific statistics */ struct net_stats_eth { + /** Total number of bytes received and sent */ struct net_stats_bytes bytes; + + /** Total number of packets received and sent */ struct net_stats_pkts pkts; + + /** Total number of broadcast packets received and sent */ struct net_stats_pkts broadcast; + + /** Total number of multicast packets received and sent */ struct net_stats_pkts multicast; + + /** Total number of errors in RX and TX */ struct net_stats_pkts errors; + + /** Total number of errors in RX and TX */ struct net_stats_eth_errors error_details; + + /** Total number of flow control errors in RX and TX */ struct net_stats_eth_flow flow_control; + + /** Total number of checksum errors in RX and TX */ struct net_stats_eth_csum csum; + + /** Total number of hardware timestamp errors in RX and TX */ struct net_stats_eth_hw_timestamp hw_timestamp; + + /** Total number of collisions */ net_stats_t collisions; + + /** Total number of dropped TX packets */ net_stats_t tx_dropped; + + /** Total number of TX timeout errors */ net_stats_t tx_timeout_count; + + /** Total number of TX queue restarts */ net_stats_t tx_restart_queue; + + /** Total number of RX unknown protocol packets */ net_stats_t unknown_protocol; + #ifdef CONFIG_NET_STATISTICS_ETHERNET_VENDOR /** Array is terminated with an entry containing a NULL key */ struct net_stats_eth_vendor *vendor; @@ -463,7 +573,10 @@ struct net_stats_eth { * @brief All PPP specific statistics */ struct net_stats_ppp { + /** Total number of bytes received and sent */ struct net_stats_bytes bytes; + + /** Total number of packets received and sent */ struct net_stats_pkts pkts; /** Number of received and dropped PPP frames. */ @@ -488,18 +601,33 @@ struct net_stats_sta_mgmt { * @brief All Wi-Fi specific statistics */ struct net_stats_wifi { + /** Total number of beacon errors */ struct net_stats_sta_mgmt sta_mgmt; + + /** Total number of bytes received and sent */ struct net_stats_bytes bytes; + + /** Total number of packets received and sent */ struct net_stats_pkts pkts; + + /** Total number of broadcast packets received and sent */ struct net_stats_pkts broadcast; + + /** Total number of multicast packets received and sent */ struct net_stats_pkts multicast; + + /** Total number of errors in RX and TX */ struct net_stats_pkts errors; + + /** Total number of unicast packets received and sent */ struct net_stats_pkts unicast; }; #if defined(CONFIG_NET_STATISTICS_USER_API) /* Management part definitions */ +/** @cond INTERNAL_HIDDEN */ + #define _NET_STATS_LAYER NET_MGMT_LAYER_L3 #define _NET_STATS_CODE 0x101 #define _NET_STATS_BASE (NET_MGMT_LAYER(_NET_STATS_LAYER) | \ @@ -522,96 +650,133 @@ enum net_request_stats_cmd { NET_REQUEST_STATS_CMD_GET_WIFI, }; +/** @endcond */ + +/** Request all network statistics */ #define NET_REQUEST_STATS_GET_ALL \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_ALL) -NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ALL); - +/** Request all processing error statistics */ #define NET_REQUEST_STATS_GET_PROCESSING_ERROR \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PROCESSING_ERROR) -NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR); - +/** Request number of received and sent bytes */ #define NET_REQUEST_STATS_GET_BYTES \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_BYTES) -NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_BYTES); - +/** Request IP error statistics */ #define NET_REQUEST_STATS_GET_IP_ERRORS \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IP_ERRORS) +/** @cond INTERNAL_HIDDEN */ + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ALL); +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PROCESSING_ERROR); +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_BYTES); NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IP_ERRORS); +/** @endcond */ + #if defined(CONFIG_NET_STATISTICS_IPV4) +/** Request IPv4 statistics */ #define NET_REQUEST_STATS_GET_IPV4 \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IPV4) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV4); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_IPV4 */ #if defined(CONFIG_NET_STATISTICS_IPV6) +/** Request IPv6 statistics */ #define NET_REQUEST_STATS_GET_IPV6 \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IPV6) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV6); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_IPV6 */ #if defined(CONFIG_NET_STATISTICS_IPV6_ND) +/** Request IPv6 neighbor discovery statistics */ #define NET_REQUEST_STATS_GET_IPV6_ND \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_IPV6_ND) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_IPV6_ND); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_IPV6_ND */ #if defined(CONFIG_NET_STATISTICS_ICMP) +/** Request ICMPv4 and ICMPv6 statistics */ #define NET_REQUEST_STATS_GET_ICMP \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_ICMP) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ICMP); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_ICMP */ #if defined(CONFIG_NET_STATISTICS_UDP) +/** Request UDP statistics */ #define NET_REQUEST_STATS_GET_UDP \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_UDP) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_UDP); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_UDP */ #if defined(CONFIG_NET_STATISTICS_TCP) +/** Request TCP statistics */ #define NET_REQUEST_STATS_GET_TCP \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_TCP) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_TCP); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_TCP */ #if defined(CONFIG_NET_STATISTICS_ETHERNET) +/** Request Ethernet statistics */ #define NET_REQUEST_STATS_GET_ETHERNET \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_ETHERNET) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_ETHERNET); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_ETHERNET */ #if defined(CONFIG_NET_STATISTICS_PPP) +/** Request PPP statistics */ #define NET_REQUEST_STATS_GET_PPP \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PPP) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PPP); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_PPP */ #endif /* CONFIG_NET_STATISTICS_USER_API */ #if defined(CONFIG_NET_STATISTICS_POWER_MANAGEMENT) +/** Request network power management statistics */ #define NET_REQUEST_STATS_GET_PM \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_PM) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_PM); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_POWER_MANAGEMENT */ #if defined(CONFIG_NET_STATISTICS_WIFI) +/** Request Wi-Fi statistics */ #define NET_REQUEST_STATS_GET_WIFI \ (_NET_STATS_BASE | NET_REQUEST_STATS_CMD_GET_WIFI) +/** @cond INTERNAL_HIDDEN */ NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_STATS_GET_WIFI); +/** @endcond */ #endif /* CONFIG_NET_STATISTICS_WIFI */ /** diff --git a/include/zephyr/net/net_timeout.h b/include/zephyr/net/net_timeout.h index fb40ec9361601..87d312648f48e 100644 --- a/include/zephyr/net/net_timeout.h +++ b/include/zephyr/net/net_timeout.h @@ -61,12 +61,13 @@ struct net_timeout { */ sys_snode_t node; - /* Time at which the timer was last set. + /** Time at which the timer was last set. * - * This usually corresponds to the low 32 bits of k_uptime_get(). */ + * This usually corresponds to the low 32 bits of k_uptime_get(). + */ uint32_t timer_start; - /* Portion of remaining timeout that does not exceed + /** Portion of remaining timeout that does not exceed * NET_TIMEOUT_MAX_VALUE. * * This value is updated in parallel with timer_start and wrap_counter @@ -74,7 +75,7 @@ struct net_timeout { */ uint32_t timer_timeout; - /* Timer wrap count. + /** Timer wrap count. * * This tracks multiples of NET_TIMEOUT_MAX_VALUE milliseconds that * have yet to pass. It is also updated along with timer_start and diff --git a/include/zephyr/net/offloaded_netdev.h b/include/zephyr/net/offloaded_netdev.h index ce90cf77bf375..009a0666515e0 100644 --- a/include/zephyr/net/offloaded_netdev.h +++ b/include/zephyr/net/offloaded_netdev.h @@ -58,7 +58,7 @@ struct offloaded_if_api { /** Enable or disable the device (in response to admin state change) */ int (*enable)(const struct net_if *iface, bool state); - /* Types of offloaded net device */ + /** Types of offloaded net device */ enum offloaded_net_if_types (*get_type)(void); }; diff --git a/include/zephyr/net/openthread.h b/include/zephyr/net/openthread.h index 81c2629d6c025..0d933df460f77 100644 --- a/include/zephyr/net/openthread.h +++ b/include/zephyr/net/openthread.h @@ -199,8 +199,12 @@ int openthread_api_mutex_try_lock(struct openthread_context *ot_context); */ void openthread_api_mutex_unlock(struct openthread_context *ot_context); +/** @cond INTERNAL_HIDDEN */ + #define OPENTHREAD_L2_CTX_TYPE struct openthread_context +/** @endcond */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/phy.h b/include/zephyr/net/phy.h index 38c6d1f5bbe71..160b31df23797 100644 --- a/include/zephyr/net/phy.h +++ b/include/zephyr/net/phy.h @@ -42,8 +42,31 @@ enum phy_link_speed { LINK_FULL_1000BASE_T = BIT(5), }; +/** + * @brief Check if phy link is full duplex. + * + * @param x Link capabilities + * + * @return True if link is full duplex, false if not. + */ #define PHY_LINK_IS_FULL_DUPLEX(x) (x & (BIT(1) | BIT(3) | BIT(5))) + +/** + * @brief Check if phy link speed is 1 Gbit/sec. + * + * @param x Link capabilities + * + * @return True if link is 1 Gbit/sec, false if not. + */ #define PHY_LINK_IS_SPEED_1000M(x) (x & (BIT(4) | BIT(5))) + +/** + * @brief Check if phy link speed is 100 Mbit/sec. + * + * @param x Link capabilities + * + * @return True if link is 1 Mbit/sec, false if not. + */ #define PHY_LINK_IS_SPEED_100M(x) (x & (BIT(2) | BIT(3))) /** @brief Link state */ diff --git a/include/zephyr/net/ppp.h b/include/zephyr/net/ppp.h index 36c6bf64eebf3..da31eca01a18c 100644 --- a/include/zephyr/net/ppp.h +++ b/include/zephyr/net/ppp.h @@ -4,6 +4,10 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief PPP (Point-to-Point Protocol) + */ #ifndef ZEPHYR_INCLUDE_NET_PPP_H_ #define ZEPHYR_INCLUDE_NET_PPP_H_ @@ -103,6 +107,8 @@ enum ppp_phase { PPP_TERMINATE, }; +/** @cond INTERNAL_HIDDEN */ + /** * PPP states, RFC 1661 ch. 4.2 */ @@ -136,10 +142,13 @@ enum ppp_packet_type { PPP_DISCARD_REQ = 11 }; +/** @endcond */ + /** * LCP option types from RFC 1661 ch. 6 */ enum lcp_option_type { + /** Reserved option value (do not use) */ LCP_OPTION_RESERVED = 0, /** Maximum-Receive-Unit */ @@ -168,6 +177,7 @@ enum lcp_option_type { * IPCP option types from RFC 1332 */ enum ipcp_option_type { + /** Reserved IPCP option value (do not use) */ IPCP_OPTION_RESERVED = 0, /** IP Addresses */ @@ -198,6 +208,7 @@ enum ipcp_option_type { * IPV6CP option types from RFC 5072 */ enum ipv6cp_option_type { + /** Reserved IPV6CP option value (do not use) */ IPV6CP_OPTION_RESERVED = 0, /** Interface identifier */ @@ -225,6 +236,7 @@ struct ppp_fsm { /** Timeout timer */ struct k_work_delayable timer; + /** FSM callbacks */ struct { /** Acknowledge Configuration Information */ int (*config_info_ack)(struct ppp_fsm *fsm, @@ -284,6 +296,7 @@ struct ppp_fsm { struct net_pkt *pkt); } cb; + /** My options */ struct { /** Options information */ const struct ppp_my_option_info *info; @@ -329,6 +342,8 @@ struct ppp_fsm { uint8_t ack_received : 1; }; +/** @cond INTERNAL_HIDDEN */ + #define PPP_MY_OPTION_ACKED BIT(0) #define PPP_MY_OPTION_REJECTED BIT(1) @@ -336,6 +351,16 @@ struct ppp_my_option_data { uint32_t flags; }; +#define IPCP_NUM_MY_OPTIONS 3 +#define IPV6CP_NUM_MY_OPTIONS 1 + +enum ppp_flags { + PPP_CARRIER_UP, +}; + +/** @endcond */ + +/** Link control protocol options */ struct lcp_options { /** Magic number */ uint32_t magic; @@ -354,26 +379,24 @@ struct lcp_options { #define LCP_NUM_MY_OPTIONS 1 #endif +/** IPv4 control protocol options */ struct ipcp_options { /** IPv4 address */ struct in_addr address; + + /** Primary DNS server address */ struct in_addr dns1_address; + + /** Secondary DNS server address */ struct in_addr dns2_address; }; -#define IPCP_NUM_MY_OPTIONS 3 - +/** IPv6 control protocol options */ struct ipv6cp_options { /** Interface identifier */ uint8_t iid[PPP_INTERFACE_IDENTIFIER_LEN]; }; -#define IPV6CP_NUM_MY_OPTIONS 1 - -enum ppp_flags { - PPP_CARRIER_UP, -}; - /** PPP L2 context specific to certain network interface */ struct ppp_context { /** Flags representing PPP state, which are accessed from multiple @@ -384,6 +407,7 @@ struct ppp_context { /** PPP startup worker. */ struct k_work_delayable startup; + /** LCP options */ struct { /** Finite state machine for LCP */ struct ppp_fsm fsm; @@ -402,6 +426,7 @@ struct ppp_context { } lcp; #if defined(CONFIG_NET_IPV4) + /** ICMP options */ struct { /** Finite state machine for IPCP */ struct ppp_fsm fsm; @@ -418,6 +443,7 @@ struct ppp_context { #endif #if defined(CONFIG_NET_IPV6) + /** IPV6CP options */ struct { /** Finite state machine for IPV6CP */ struct ppp_fsm fsm; @@ -434,6 +460,7 @@ struct ppp_context { #endif #if defined(CONFIG_NET_L2_PPP_PAP) + /** PAP options */ struct { /** Finite state machine for PAP */ struct ppp_fsm fsm; @@ -441,7 +468,9 @@ struct ppp_context { #endif #if defined(CONFIG_NET_SHELL) + /** Network shell PPP command internal data */ struct { + /** Ping command internal data */ struct { /** Callback to be called when Echo-Reply is received. */ @@ -544,22 +573,26 @@ enum net_event_ppp_cmd { NET_EVENT_PPP_CMD_PHASE_DEAD, }; +struct net_if; + +/** @endcond */ + +/** Event emitted when PPP carrier is on */ #define NET_EVENT_PPP_CARRIER_ON \ (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_ON) +/** Event emitted when PPP carrier is off */ #define NET_EVENT_PPP_CARRIER_OFF \ (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_CARRIER_OFF) +/** Event emitted when PPP goes into running phase */ #define NET_EVENT_PPP_PHASE_RUNNING \ (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_PHASE_RUNNING) +/** Event emitted when PPP goes into dead phase */ #define NET_EVENT_PPP_PHASE_DEAD \ (_NET_PPP_EVENT | NET_EVENT_PPP_CMD_PHASE_DEAD) -struct net_if; - -/** @endcond */ - /** * @brief Raise CARRIER_ON event when PPP is connected. * diff --git a/include/zephyr/net/ptp.h b/include/zephyr/net/ptp.h new file mode 100644 index 0000000000000..d57c47e7c6c39 --- /dev/null +++ b/include/zephyr/net/ptp.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 BayLibre SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief Public functions for the Precision Time Protocol. + * + * References are to version 2019 of IEEE 1588, ("PTP") + */ + +#ifndef ZEPHYR_INCLUDE_NET_PTP_H_ +#define ZEPHYR_INCLUDE_NET_PTP_H_ + +/** + * @brief Precision Time Protocol (PTP) support + * @defgroup ptp PTP support + * @ingroup networking + * @{ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PTP_MAJOR_VERSION 2 /**< Major PTP Version */ +#define PTP_MINOR_VERSION 1 /**< Minor PTP Version */ + +#define PTP_VERSION (PTP_MINOR_VERSION << 4 | PTP_MAJOR_VERSION) /**< PTP version IEEE-1588:2019 */ + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_NET_PTP_H_ */ diff --git a/include/zephyr/net/ptp_time.h b/include/zephyr/net/ptp_time.h index 99c5037e7ba0b..269325cdde19d 100644 --- a/include/zephyr/net/ptp_time.h +++ b/include/zephyr/net/ptp_time.h @@ -109,6 +109,8 @@ extern "C" { struct net_ptp_time { /** Seconds encoded on 48 bits. */ union { + +/** @cond INTERNAL_HIDDEN */ struct { #ifdef CONFIG_LITTLE_ENDIAN uint32_t low; @@ -120,6 +122,9 @@ struct net_ptp_time { uint32_t low; #endif } _sec; +/** @endcond */ + + /** Second value. */ uint64_t second; }; @@ -147,6 +152,8 @@ struct net_ptp_time { struct net_ptp_extended_time { /** Seconds encoded on 48 bits. */ union { + +/** @cond INTERNAL_HIDDEN */ struct { #ifdef CONFIG_LITTLE_ENDIAN uint32_t low; @@ -158,11 +165,16 @@ struct net_ptp_extended_time { uint32_t low; #endif } _sec; +/** @endcond */ + + /** Second value. */ uint64_t second; }; /** Fractional nanoseconds on 48 bits. */ union { + +/** @cond INTERNAL_HIDDEN */ struct { #ifdef CONFIG_LITTLE_ENDIAN uint32_t low; @@ -174,6 +186,9 @@ struct net_ptp_extended_time { uint32_t low; #endif } _fns; +/** @endcond */ + + /** Fractional nanoseconds value. */ uint64_t fract_nsecond; }; } __packed; diff --git a/include/zephyr/net/sntp.h b/include/zephyr/net/sntp.h index a1c8a59e0e856..68a733d355d50 100644 --- a/include/zephyr/net/sntp.h +++ b/include/zephyr/net/sntp.h @@ -5,6 +5,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief SNTP (Simple Network Time Protocol) + */ + #ifndef ZEPHYR_INCLUDE_NET_SNTP_H_ #define ZEPHYR_INCLUDE_NET_SNTP_H_ @@ -23,21 +28,24 @@ extern "C" { /** Time as returned by SNTP API, fractional seconds since 1 Jan 1970 */ struct sntp_time { - uint64_t seconds; - uint32_t fraction; + uint64_t seconds; /**< Second value */ + uint32_t fraction; /**< Fractional seconds value */ #if defined(CONFIG_SNTP_UNCERTAINTY) - uint64_t uptime_us; - uint32_t uncertainty_us; + uint64_t uptime_us; /**< Uptime in microseconds */ + uint32_t uncertainty_us; /**< Uncertainty in microseconds */ #endif }; /** SNTP context */ struct sntp_ctx { + +/** @cond INTERNAL_HIDDEN */ struct { struct zsock_pollfd fds[1]; int nfds; int fd; } sock; +/** @endcond */ /** Timestamp when the request was sent from client to server. * This is used to check if the originated timestamp in the server diff --git a/include/zephyr/net/socket.h b/include/zephyr/net/socket.h index 7dfa893477473..9af729faecd85 100644 --- a/include/zephyr/net/socket.h +++ b/include/zephyr/net/socket.h @@ -22,30 +22,22 @@ * @{ */ +#include #include #include +#include #include -#include #include +#include #include #include +#include #include #ifdef __cplusplus extern "C" { #endif -/** - * @brief Definition of the monitored socket/file descriptor. - * - * An array of these descriptors is passed as an argument to poll(). - */ -struct zsock_pollfd { - int fd; /**< Socket descriptor */ - short events; /**< Requested events */ - short revents; /**< Returned events */ -}; - /** * @name Options for poll() * @{ @@ -562,6 +554,8 @@ static inline ssize_t zsock_recv(int sock, void *buf, size_t max_len, */ __syscall int zsock_fcntl_impl(int sock, int cmd, int flags); +/** @cond INTERNAL_HIDDEN */ + /* * Need this wrapper because newer GCC versions got too smart and "typecheck" * even macros. @@ -579,6 +573,8 @@ static inline int zsock_fcntl_wrapper(int sock, int cmd, ...) #define zsock_fcntl zsock_fcntl_wrapper +/** @endcond */ + /** * @brief Control underlying socket parameters * @@ -598,6 +594,8 @@ static inline int zsock_fcntl_wrapper(int sock, int cmd, ...) */ __syscall int zsock_ioctl_impl(int sock, unsigned long request, va_list ap); +/** @cond INTERNAL_HIDDEN */ + static inline int zsock_ioctl_wrapper(int sock, unsigned long request, ...) { int ret; @@ -612,6 +610,8 @@ static inline int zsock_ioctl_wrapper(int sock, unsigned long request, ...) #define zsock_ioctl zsock_ioctl_wrapper +/** @endcond */ + /** * @brief Efficiently poll multiple sockets for events * @@ -1163,8 +1163,9 @@ struct ifreq { /** Socket accepts incoming connections (ignored, for compatibility) */ #define SO_ACCEPTCONN 30 -/** Timestamp TX packets */ +/** Timestamp TX RX or both packets. Supports multiple timestamp sources. */ #define SO_TIMESTAMPING 37 + /** Protocol used with the socket */ #define SO_PROTOCOL 38 @@ -1179,6 +1180,18 @@ struct ifreq { /** Socket TX time (same as SO_TXTIME) */ #define SCM_TXTIME SO_TXTIME +/** Timestamp generation flags */ + +/** Request RX timestamps generated by network adapter. */ +#define SOF_TIMESTAMPING_RX_HARDWARE BIT(0) +/** + * Request TX timestamps generated by network adapter. + * This can be enabled via socket option or control messages. + */ +#define SOF_TIMESTAMPING_TX_HARDWARE BIT(1) + +/** */ + /** @} */ /** @@ -1378,7 +1391,7 @@ struct net_socket_register { } #endif -#include +#include /** * @} diff --git a/include/zephyr/net/socket_net_mgmt.h b/include/zephyr/net/socket_net_mgmt.h index c2c07a93b15c1..3c173f96a6f6c 100644 --- a/include/zephyr/net/socket_net_mgmt.h +++ b/include/zephyr/net/socket_net_mgmt.h @@ -29,6 +29,8 @@ extern "C" { * @{ */ +/** @cond INTERNAL_HIDDEN */ + /* Protocols of the protocol family PF_NET_MGMT */ #define NET_MGMT_EVENT_PROTO 0x01 @@ -36,6 +38,8 @@ extern "C" { #define SOL_NET_MGMT_BASE 100 #define SOL_NET_MGMT_RAW (SOL_NET_MGMT_BASE + 1) +/** @endcond */ + /** * struct sockaddr_nm - The sockaddr structure for NET_MGMT sockets * diff --git a/include/zephyr/net/socket_offload.h b/include/zephyr/net/socket_offload.h index d0f2d29cfe402..988d0fb686b34 100644 --- a/include/zephyr/net/socket_offload.h +++ b/include/zephyr/net/socket_offload.h @@ -26,9 +26,11 @@ extern "C" { * POSIX socket API standard for arguments, return values and setting of errno. */ struct socket_dns_offload { + /** DNS getaddrinfo offloaded implementation API */ int (*getaddrinfo)(const char *node, const char *service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res); + /** DNS freeaddrinfo offloaded implementation API */ void (*freeaddrinfo)(struct zsock_addrinfo *res); }; @@ -39,12 +41,16 @@ struct socket_dns_offload { */ void socket_offload_dns_register(const struct socket_dns_offload *ops); +/** @cond INTERNAL_HIDDEN */ + int socket_offload_getaddrinfo(const char *node, const char *service, const struct zsock_addrinfo *hints, struct zsock_addrinfo **res); void socket_offload_freeaddrinfo(struct zsock_addrinfo *res); +/** @endcond */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/socket_poll.h b/include/zephyr/net/socket_poll.h new file mode 100644 index 0000000000000..97e03804311ab --- /dev/null +++ b/include/zephyr/net/socket_poll.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_NET_SOCKET_POLL_H_ +#define ZEPHYR_INCLUDE_NET_SOCKET_POLL_H_ + +/* Setting for pollfd to avoid circular inclusion */ + +/** + * @brief BSD Sockets compatible API + * @defgroup bsd_sockets BSD Sockets compatible API + * @ingroup networking + * @{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Definition of the monitored socket/file descriptor. + * + * An array of these descriptors is passed as an argument to poll(). + */ +struct zsock_pollfd { + int fd; /**< Socket descriptor */ + short events; /**< Requested events */ + short revents; /**< Returned events */ +}; + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ + +#endif /* ZEPHYR_INCLUDE_NET_SOCKET_POLL_H_ */ diff --git a/include/zephyr/net/socket_select.h b/include/zephyr/net/socket_select.h index 1e7507711a118..5fca2950d6a59 100644 --- a/include/zephyr/net/socket_select.h +++ b/include/zephyr/net/socket_select.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** @file socket_select.h + * + * @brief BSD select support functions. + */ + #ifndef ZEPHYR_INCLUDE_NET_SOCKET_SELECT_H_ #define ZEPHYR_INCLUDE_NET_SOCKET_SELECT_H_ @@ -21,11 +26,11 @@ extern "C" { #endif +/** Socket file descriptor set. */ typedef struct zsock_fd_set { - uint32_t bitset[(CONFIG_POSIX_MAX_FDS + 31) / 32]; + uint32_t bitset[(CONFIG_ZVFS_OPEN_MAX + 31) / 32]; } zsock_fd_set; - /** * @brief Legacy function to poll multiple sockets for events * @@ -106,6 +111,8 @@ void ZSOCK_FD_CLR(int fd, zsock_fd_set *set); */ void ZSOCK_FD_SET(int fd, zsock_fd_set *set); +/** @cond INTERNAL_HIDDEN */ + #ifdef CONFIG_NET_SOCKETS_POSIX_NAMES #define fd_set zsock_fd_set @@ -140,11 +147,13 @@ static inline void FD_SET(int fd, zsock_fd_set *set) #endif /* CONFIG_NET_SOCKETS_POSIX_NAMES */ +/** @endcond */ + #ifdef __cplusplus } #endif -#include +#include /** * @} diff --git a/include/zephyr/net/socket_service.h b/include/zephyr/net/socket_service.h index a4e21f00a3335..c5060eb408585 100644 --- a/include/zephyr/net/socket_service.h +++ b/include/zephyr/net/socket_service.h @@ -75,6 +75,8 @@ struct net_socket_service_desc { int *idx; }; +/** @cond INTERNAL_HIDDEN */ + #define __z_net_socket_svc_get_name(_svc_id) __z_net_socket_service_##_svc_id #define __z_net_socket_svc_get_idx(_svc_id) __z_net_socket_service_idx_##_svc_id #define __z_net_socket_svc_get_owner __FILE__ ":" STRINGIFY(__LINE__) @@ -110,6 +112,8 @@ extern void net_socket_service_callback(struct k_work *work); .idx = &__z_net_socket_svc_get_idx(_name), \ } +/** @endcond */ + /** * @brief Statically define a network socket service. * The user callback is called asynchronously for this service meaning that @@ -237,7 +241,7 @@ void net_socket_service_foreach(net_socket_service_cb_t cb, void *user_data); } #endif -#include +#include /** * @} diff --git a/include/zephyr/net/socket_types.h b/include/zephyr/net/socket_types.h index 6195315e51aca..0727dd77bdf31 100644 --- a/include/zephyr/net/socket_types.h +++ b/include/zephyr/net/socket_types.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief socket types definitionis + */ + #ifndef ZEPHYR_INCLUDE_NET_SOCKET_TYPES_H_ #define ZEPHYR_INCLUDE_NET_SOCKET_TYPES_H_ @@ -16,6 +21,7 @@ #include +/** @cond INTERNAL_HIDDEN */ #ifdef CONFIG_NEWLIB_LIBC @@ -52,6 +58,8 @@ extern "C" { } #endif +/** @endcond */ + /** * @} */ diff --git a/include/zephyr/net/socketcan.h b/include/zephyr/net/socketcan.h index c4916487d9971..dd2a7049288d7 100644 --- a/include/zephyr/net/socketcan.h +++ b/include/zephyr/net/socketcan.h @@ -28,9 +28,11 @@ extern "C" { * @{ */ -/* Protocols of the protocol family PF_CAN */ +/** Protocols of the protocol family PF_CAN */ #define CAN_RAW 1 +/** @cond INTERNAL_HIDDEN */ + /* SocketCAN options */ #define SOL_CAN_BASE 100 #define SOL_CAN_RAW (SOL_CAN_BASE + CAN_RAW) @@ -39,28 +41,35 @@ enum { CAN_RAW_FILTER = 1, }; +/** @endcond */ + /* SocketCAN MTU size compatible with Linux */ #ifdef CONFIG_CAN_FD_MODE +/** SocketCAN max data length */ #define SOCKETCAN_MAX_DLEN 64U +/** CAN FD frame MTU */ #define CANFD_MTU (sizeof(struct socketcan_frame)) +/** CAN frame MTU */ #define CAN_MTU (CANFD_MTU - 56U) #else /* CONFIG_CAN_FD_MODE */ +/** SocketCAN max data length */ #define SOCKETCAN_MAX_DLEN 8U +/** CAN frame MTU */ #define CAN_MTU (sizeof(struct socketcan_frame)) #endif /* !CONFIG_CAN_FD_MODE */ /* CAN FD specific flags from Linux Kernel (include/uapi/linux/can.h) */ -#define CANFD_BRS 0x01 /* bit rate switch (second bitrate for payload data) */ -#define CANFD_ESI 0x02 /* error state indicator of the transmitting node */ -#define CANFD_FDF 0x04 /* mark CAN FD for dual use of struct canfd_frame */ +#define CANFD_BRS 0x01 /**< Bit rate switch (second bitrate for payload data) */ +#define CANFD_ESI 0x02 /**< Error state indicator of the transmitting node */ +#define CANFD_FDF 0x04 /**< Mark CAN FD for dual use of struct canfd_frame */ /** * struct sockaddr_can - The sockaddr structure for CAN sockets * */ struct sockaddr_can { - sa_family_t can_family; - int can_ifindex; + sa_family_t can_family; /**< Address family */ + int can_ifindex; /**< SocketCAN network interface index */ }; /** diff --git a/include/zephyr/net/socketutils.h b/include/zephyr/net/socketutils.h index 7a7b862a7a707..b118f7531d9ce 100644 --- a/include/zephyr/net/socketutils.h +++ b/include/zephyr/net/socketutils.h @@ -4,6 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ +/** + * @file + * @brief Socket utility functions. + */ + #ifndef ZEPHYR_INCLUDE_NET_SOCKETUTILS_H_ #define ZEPHYR_INCLUDE_NET_SOCKETUTILS_H_ diff --git a/include/zephyr/net/tftp.h b/include/zephyr/net/tftp.h index 61db441e54843..eb3df0cc0c1d2 100644 --- a/include/zephyr/net/tftp.h +++ b/include/zephyr/net/tftp.h @@ -5,11 +5,12 @@ */ /** @file tftp.h + * + * @brief TFTP Client Implementation * * @defgroup tftp_client TFTP Client library * @ingroup networking * @{ - * @brief TFTP Client Implementation */ #ifndef ZEPHYR_INCLUDE_NET_TFTP_H_ diff --git a/include/zephyr/net/trickle.h b/include/zephyr/net/trickle.h index fb6ee8f74be88..9d46ffa0b91ff 100644 --- a/include/zephyr/net/trickle.h +++ b/include/zephyr/net/trickle.h @@ -60,11 +60,11 @@ struct net_trickle { uint8_t k; /**< Redundancy constant */ uint8_t c; /**< Consistency counter */ - bool double_to; + bool double_to; /**< Flag telling if the internval is doubled */ - struct k_work_delayable timer; + struct k_work_delayable timer; /**< Internal timer struct */ net_trickle_cb_t cb; /**< Callback to be called when timer expires */ - void *user_data; + void *user_data; /**< User specific opaque data */ }; /** @cond INTERNAL_HIDDEN */ diff --git a/include/zephyr/net/virtual.h b/include/zephyr/net/virtual.h index d64bab155772b..806665296f925 100644 --- a/include/zephyr/net/virtual.h +++ b/include/zephyr/net/virtual.h @@ -81,6 +81,7 @@ struct virtual_interface_config { #endif /** @endcond */ +/** Virtual L2 API operations. */ struct virtual_interface_api { /** * The net_if_api must be placed in first position in this diff --git a/include/zephyr/net/websocket.h b/include/zephyr/net/websocket.h index 1a0853891a020..3b2d9dddd678b 100644 --- a/include/zephyr/net/websocket.h +++ b/include/zephyr/net/websocket.h @@ -38,13 +38,14 @@ extern "C" { #define WEBSOCKET_FLAG_PING 0x00000010 /**< Ping message */ #define WEBSOCKET_FLAG_PONG 0x00000020 /**< Pong message */ +/** @brief Websocket option codes */ enum websocket_opcode { - WEBSOCKET_OPCODE_CONTINUE = 0x00, - WEBSOCKET_OPCODE_DATA_TEXT = 0x01, - WEBSOCKET_OPCODE_DATA_BINARY = 0x02, - WEBSOCKET_OPCODE_CLOSE = 0x08, - WEBSOCKET_OPCODE_PING = 0x09, - WEBSOCKET_OPCODE_PONG = 0x0A, + WEBSOCKET_OPCODE_CONTINUE = 0x00, /**< Message continues */ + WEBSOCKET_OPCODE_DATA_TEXT = 0x01, /**< Textual data */ + WEBSOCKET_OPCODE_DATA_BINARY = 0x02, /**< Binary data */ + WEBSOCKET_OPCODE_CLOSE = 0x08, /**< Closing connection */ + WEBSOCKET_OPCODE_PING = 0x09, /**< Ping message */ + WEBSOCKET_OPCODE_PONG = 0x0A, /**< Pong message */ }; /** @@ -182,9 +183,38 @@ int websocket_recv_msg(int ws_sock, uint8_t *buf, size_t buf_len, * the connection. * * @param ws_sock Websocket id returned by websocket_connect(). + * + * @return <0 if error, 0 the connection was closed successfully */ int websocket_disconnect(int ws_sock); +/** + * @brief Register a socket as websocket. This is called by HTTP server + * when a connection is upgraded to a websocket connection. + * + * @param http_sock Underlying socket connection socket. + * @param recv_buf Temporary receive buffer for websocket parsing. This must + * point to a memory area that is valid for the duration of the whole + * websocket session. + * @param recv_buf_len Length of the temporary receive buffer. + * + * @return <0 if error, >=0 the actual websocket to be used by application + */ +int websocket_register(int http_sock, uint8_t *recv_buf, size_t recv_buf_len); + +/** + * @brief Unregister a websocket. This is called when we no longer need + * the underlaying "real" socket. This will close first the websocket + * and then the original socket. + * + * @param ws_sock Websocket connection socket. + * + * @return <0 if error, 0 the websocket connection is now fully closed + */ +int websocket_unregister(int ws_sock); + +/** @cond INTERNAL_HIDDEN */ + #if defined(CONFIG_WEBSOCKET_CLIENT) void websocket_init(void); #else @@ -193,6 +223,8 @@ static inline void websocket_init(void) } #endif +/** @endcond */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/wifi.h b/include/zephyr/net/wifi.h index ebfc76d2192d1..6f8bfc0cf9d7c 100644 --- a/include/zephyr/net/wifi.h +++ b/include/zephyr/net/wifi.h @@ -22,16 +22,21 @@ #include /* for ARRAY_SIZE */ +/** Length of the country code string */ #define WIFI_COUNTRY_CODE_LEN 2 +/** @cond INTERNAL_HIDDEN */ + #define WIFI_LISTEN_INTERVAL_MIN 0 #define WIFI_LISTEN_INTERVAL_MAX 65535 +/** @endcond */ + #ifdef __cplusplus extern "C" { #endif -/** IEEE 802.11 security types. */ +/** @brief IEEE 802.11 security types. */ enum wifi_security_type { /** No security. */ WIFI_SECURITY_TYPE_NONE = 0, @@ -52,15 +57,17 @@ enum wifi_security_type { /** WPA/WPA2/WPA3 PSK security. */ WIFI_SECURITY_TYPE_WPA_AUTO_PERSONAL, +/** @cond INTERNAL_HIDDEN */ __WIFI_SECURITY_TYPE_AFTER_LAST, WIFI_SECURITY_TYPE_MAX = __WIFI_SECURITY_TYPE_AFTER_LAST - 1, WIFI_SECURITY_TYPE_UNKNOWN +/** @endcond */ }; /** Helper function to get user-friendly security type name. */ const char *wifi_security_txt(enum wifi_security_type security); -/** IEEE 802.11w - Management frame protection. */ +/** @brief IEEE 802.11w - Management frame protection. */ enum wifi_mfp_options { /** MFP disabled. */ WIFI_MFP_DISABLE = 0, @@ -69,9 +76,11 @@ enum wifi_mfp_options { /** MFP required. */ WIFI_MFP_REQUIRED, +/** @cond INTERNAL_HIDDEN */ __WIFI_MFP_AFTER_LAST, WIFI_MFP_MAX = __WIFI_MFP_AFTER_LAST - 1, WIFI_MFP_UNKNOWN +/** @endcond */ }; /** Helper function to get user-friendly MFP name.*/ @@ -99,17 +108,25 @@ enum wifi_frequency_bands { /** Helper function to get user-friendly frequency band name. */ const char *wifi_band_txt(enum wifi_frequency_bands band); +/** Max SSID length */ #define WIFI_SSID_MAX_LEN 32 +/** Minimum PSK length */ #define WIFI_PSK_MIN_LEN 8 +/** Maximum PSK length */ #define WIFI_PSK_MAX_LEN 64 +/** Max SAW password length */ #define WIFI_SAE_PSWD_MAX_LEN 128 +/** MAC address length */ #define WIFI_MAC_ADDR_LEN 6 +/** Minimum channel number */ #define WIFI_CHANNEL_MIN 1 +/** Maximum channel number */ #define WIFI_CHANNEL_MAX 233 +/** Any channel number */ #define WIFI_CHANNEL_ANY 255 -/** Wi-Fi interface states. +/** @brief Wi-Fi interface states. * * Based on https://w1.fi/wpa_supplicant/devel/defs_8h.html#a4aeb27c1e4abd046df3064ea9756f0bc */ @@ -135,9 +152,11 @@ enum wifi_iface_state { /** All authentication completed, ready to pass data. */ WIFI_STATE_COMPLETED, +/** @cond INTERNAL_HIDDEN */ __WIFI_STATE_AFTER_LAST, WIFI_STATE_MAX = __WIFI_STATE_AFTER_LAST - 1, WIFI_STATE_UNKNOWN +/** @endcond */ }; /* We rely on the strict order of the enum values, so, let's check it */ @@ -155,7 +174,7 @@ BUILD_ASSERT(WIFI_STATE_DISCONNECTED < WIFI_STATE_INTERFACE_DISABLED && /** Helper function to get user-friendly interface state name. */ const char *wifi_state_txt(enum wifi_iface_state state); -/** Wi-Fi interface modes. +/** @brief Wi-Fi interface modes. * * Based on https://w1.fi/wpa_supplicant/devel/defs_8h.html#a4aeb27c1e4abd046df3064ea9756f0bc */ @@ -173,15 +192,17 @@ enum wifi_iface_mode { /** 802.11s Mesh mode. */ WIFI_MODE_MESH = 5, +/** @cond INTERNAL_HIDDEN */ __WIFI_MODE_AFTER_LAST, WIFI_MODE_MAX = __WIFI_MODE_AFTER_LAST - 1, WIFI_MODE_UNKNOWN +/** @endcond */ }; /** Helper function to get user-friendly interface mode name. */ const char *wifi_mode_txt(enum wifi_iface_mode mode); -/** Wi-Fi link operating modes +/** @brief Wi-Fi link operating modes * * As per https://en.wikipedia.org/wiki/Wi-Fi#Versions_and_generations. */ @@ -205,15 +226,17 @@ enum wifi_link_mode { /** 802.11be. */ WIFI_7, +/** @cond INTERNAL_HIDDEN */ __WIFI_LINK_MODE_AFTER_LAST, WIFI_LINK_MODE_MAX = __WIFI_LINK_MODE_AFTER_LAST - 1, WIFI_LINK_MODE_UNKNOWN +/** @endcond */ }; /** Helper function to get user-friendly link mode name. */ const char *wifi_link_mode_txt(enum wifi_link_mode link_mode); -/** Wi-Fi scanning types. */ +/** @brief Wi-Fi scanning types. */ enum wifi_scan_type { /** Active scanning (default). */ WIFI_SCAN_TYPE_ACTIVE = 0, @@ -221,7 +244,7 @@ enum wifi_scan_type { WIFI_SCAN_TYPE_PASSIVE, }; -/** Wi-Fi power save states. */ +/** @brief Wi-Fi power save states. */ enum wifi_ps { /** Power save disabled. */ WIFI_PS_DISABLED = 0, @@ -232,7 +255,7 @@ enum wifi_ps { /** Helper function to get user-friendly ps name. */ const char *wifi_ps_txt(enum wifi_ps ps_name); -/** Wi-Fi power save modes. */ +/** @brief Wi-Fi power save modes. */ enum wifi_ps_mode { /** Legacy power save mode. */ WIFI_PS_MODE_LEGACY = 0, @@ -246,11 +269,12 @@ enum wifi_ps_mode { /** Helper function to get user-friendly ps mode name. */ const char *wifi_ps_mode_txt(enum wifi_ps_mode ps_mode); -/* Interface index Min and Max values */ +/** Network interface index min value */ #define WIFI_INTERFACE_INDEX_MIN 1 +/** Network interface index max value */ #define WIFI_INTERFACE_INDEX_MAX 255 -/** Wifi operational mode */ +/** @brief Wifi operational mode */ enum wifi_operational_modes { /** STA mode setting enable */ WIFI_STA_MODE = BIT(0), @@ -266,7 +290,7 @@ enum wifi_operational_modes { WIFI_SOFTAP_MODE = BIT(5), }; -/** Mode filter settings */ +/** @brief Mode filter settings */ enum wifi_filter { /** Support management, data and control packet sniffing */ WIFI_PACKET_FILTER_ALL = BIT(0), @@ -278,7 +302,7 @@ enum wifi_filter { WIFI_PACKET_FILTER_CTRL = BIT(3), }; -/** Wi-Fi Target Wake Time (TWT) operations. */ +/** @brief Wi-Fi Target Wake Time (TWT) operations. */ enum wifi_twt_operation { /** TWT setup operation */ WIFI_TWT_SETUP = 0, @@ -289,7 +313,7 @@ enum wifi_twt_operation { /** Helper function to get user-friendly twt operation name. */ const char *wifi_twt_operation_txt(enum wifi_twt_operation twt_operation); -/** Wi-Fi Target Wake Time (TWT) negotiation types. */ +/** @brief Wi-Fi Target Wake Time (TWT) negotiation types. */ enum wifi_twt_negotiation_type { /** TWT individual negotiation */ WIFI_TWT_INDIVIDUAL = 0, @@ -302,7 +326,7 @@ enum wifi_twt_negotiation_type { /** Helper function to get user-friendly twt negotiation type name. */ const char *wifi_twt_negotiation_type_txt(enum wifi_twt_negotiation_type twt_negotiation); -/** Wi-Fi Target Wake Time (TWT) setup commands. */ +/** @brief Wi-Fi Target Wake Time (TWT) setup commands. */ enum wifi_twt_setup_cmd { /** TWT setup request */ WIFI_TWT_SETUP_CMD_REQUEST = 0, @@ -325,7 +349,7 @@ enum wifi_twt_setup_cmd { /** Helper function to get user-friendly twt setup cmd name. */ const char *wifi_twt_setup_cmd_txt(enum wifi_twt_setup_cmd twt_setup); -/** Wi-Fi Target Wake Time (TWT) negotiation status. */ +/** @brief Wi-Fi Target Wake Time (TWT) negotiation status. */ enum wifi_twt_setup_resp_status { /** TWT response received for TWT request */ WIFI_TWT_RESP_RECEIVED = 0, @@ -333,7 +357,7 @@ enum wifi_twt_setup_resp_status { WIFI_TWT_RESP_NOT_RECEIVED, }; -/** Target Wake Time (TWT) error codes. */ +/** @brief Target Wake Time (TWT) error codes. */ enum wifi_twt_fail_reason { /** Unspecified error */ WIFI_TWT_FAIL_UNSPECIFIED, @@ -359,7 +383,7 @@ enum wifi_twt_fail_reason { WIFI_TWT_FAIL_FLOW_ALREADY_EXISTS, }; -/** Wi-Fi Target Wake Time (TWT) teradown status. */ +/** @brief Wi-Fi Target Wake Time (TWT) teradown status. */ enum wifi_twt_teardown_status { /** TWT teardown success */ WIFI_TWT_TEARDOWN_SUCCESS = 0, @@ -400,7 +424,7 @@ static inline const char *wifi_twt_get_err_code_str(int16_t err_no) return ""; } -/** Wi-Fi power save parameters. */ +/** @brief Wi-Fi power save parameters. */ enum wifi_ps_param_type { /** Power save state. */ WIFI_PS_PARAM_STATE, @@ -414,7 +438,7 @@ enum wifi_ps_param_type { WIFI_PS_PARAM_TIMEOUT, }; -/** Wi-Fi power save modes. */ +/** @brief Wi-Fi power save modes. */ enum wifi_ps_wakeup_mode { /** DTIM based wakeup. */ WIFI_PS_WAKEUP_MODE_DTIM = 0, @@ -425,7 +449,7 @@ enum wifi_ps_wakeup_mode { /** Helper function to get user-friendly ps wakeup mode name. */ const char *wifi_ps_wakeup_mode_txt(enum wifi_ps_wakeup_mode ps_wakeup_mode); -/** Wi-Fi power save error codes. */ +/** @brief Wi-Fi power save error codes. */ enum wifi_config_ps_param_fail_reason { /** Unspecified error */ WIFI_PS_PARAM_FAIL_UNSPECIFIED, @@ -470,6 +494,14 @@ static inline const char *wifi_ps_get_config_err_code_str(int16_t err_no) return ""; } +/** @brief Wi-Fi AP mode configuration parameter */ +enum wifi_ap_config_param { + /** Used for AP mode configuration parameter ap_max_inactivity */ + WIFI_AP_CONFIG_PARAM_MAX_INACTIVITY = BIT(0), + /** Used for AP mode configuration parameter max_num_sta */ + WIFI_AP_CONFIG_PARAM_MAX_NUM_STA = BIT(1), +}; + #ifdef __cplusplus } #endif diff --git a/include/zephyr/net/wifi_mgmt.h b/include/zephyr/net/wifi_mgmt.h index 70fd5978fba67..616541776e06e 100644 --- a/include/zephyr/net/wifi_mgmt.h +++ b/include/zephyr/net/wifi_mgmt.h @@ -28,6 +28,8 @@ extern "C" { /* Management part definitions */ +/** @cond INTERNAL_HIDDEN */ + #define _NET_WIFI_LAYER NET_MGMT_LAYER_L2 #define _NET_WIFI_CODE 0x156 #define _NET_WIFI_BASE (NET_MGMT_IFACE_BIT | \ @@ -50,7 +52,10 @@ extern "C" { #define WIFI_MGMT_BAND_STR_SIZE_MAX 8 #define WIFI_MGMT_SCAN_MAX_BSS_CNT 65535 -/** Wi-Fi management commands */ +#define WIFI_MGMT_SKIP_INACTIVITY_POLL IS_ENABLED(CONFIG_WIFI_MGMT_AP_STA_SKIP_INACTIVITY_POLL) +/** @endcond */ + +/** @brief Wi-Fi management commands */ enum net_request_wifi_cmd { /** Scan for Wi-Fi networks */ NET_REQUEST_WIFI_CMD_SCAN = 1, @@ -84,88 +89,116 @@ enum net_request_wifi_cmd { NET_REQUEST_WIFI_CMD_VERSION, /** Set RTS threshold */ NET_REQUEST_WIFI_CMD_RTS_THRESHOLD, + /** Configure AP parameter */ + NET_REQUEST_WIFI_CMD_AP_CONFIG_PARAM, +/** @cond INTERNAL_HIDDEN */ NET_REQUEST_WIFI_CMD_MAX +/** @endcond */ }; +/** Request a Wi-Fi scan */ #define NET_REQUEST_WIFI_SCAN \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_SCAN) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_SCAN); +/** Request a Wi-Fi connect */ #define NET_REQUEST_WIFI_CONNECT \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_CONNECT) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_CONNECT); +/** Request a Wi-Fi disconnect */ #define NET_REQUEST_WIFI_DISCONNECT \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_DISCONNECT) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_DISCONNECT); +/** Request a Wi-Fi access point enable */ #define NET_REQUEST_WIFI_AP_ENABLE \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_ENABLE) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_ENABLE); +/** Request a Wi-Fi access point disable */ #define NET_REQUEST_WIFI_AP_DISABLE \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_DISABLE) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_DISABLE); +/** Request a Wi-Fi network interface status */ #define NET_REQUEST_WIFI_IFACE_STATUS \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_IFACE_STATUS) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_IFACE_STATUS); -#define NET_REQUEST_WIFI_PS \ +/** Request a Wi-Fi power save */ +#define NET_REQUEST_WIFI_PS \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_PS) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PS); -#define NET_REQUEST_WIFI_TWT \ +/** Request a Wi-Fi TWT */ +#define NET_REQUEST_WIFI_TWT \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_TWT) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_TWT); +/** Request a Wi-Fi power save configuration */ #define NET_REQUEST_WIFI_PS_CONFIG \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_PS_CONFIG) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PS_CONFIG); + +/** Request a Wi-Fi regulatory domain */ #define NET_REQUEST_WIFI_REG_DOMAIN \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_REG_DOMAIN) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_REG_DOMAIN); -#define NET_REQUEST_WIFI_MODE \ +/** Request current Wi-Fi mode */ +#define NET_REQUEST_WIFI_MODE \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_MODE) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_MODE); -#define NET_REQUEST_WIFI_PACKET_FILTER \ +/** Request Wi-Fi packet filter */ +#define NET_REQUEST_WIFI_PACKET_FILTER \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_PACKET_FILTER) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_PACKET_FILTER); -#define NET_REQUEST_WIFI_CHANNEL \ +/** Request a Wi-Fi channel */ +#define NET_REQUEST_WIFI_CHANNEL \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_CHANNEL) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_CHANNEL); +/** Request a Wi-Fi access point to disconnect a station */ #define NET_REQUEST_WIFI_AP_STA_DISCONNECT \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_STA_DISCONNECT) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_STA_DISCONNECT); -#define NET_REQUEST_WIFI_VERSION \ +/** Request a Wi-Fi version */ +#define NET_REQUEST_WIFI_VERSION \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_VERSION) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_VERSION); -#define NET_REQUEST_WIFI_RTS_THRESHOLD \ +/** Request a Wi-Fi RTS threshold */ +#define NET_REQUEST_WIFI_RTS_THRESHOLD \ (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_RTS_THRESHOLD) NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_RTS_THRESHOLD); -/** Wi-Fi management events */ + +/** Request a Wi-Fi AP parameters configuration */ +#define NET_REQUEST_WIFI_AP_CONFIG_PARAM \ + (_NET_WIFI_BASE | NET_REQUEST_WIFI_CMD_AP_CONFIG_PARAM) + +NET_MGMT_DEFINE_REQUEST_HANDLER(NET_REQUEST_WIFI_AP_CONFIG_PARAM); + +/** @brief Wi-Fi management events */ enum net_event_wifi_cmd { /** Scan results available */ NET_EVENT_WIFI_CMD_SCAN_RESULT = 1, @@ -197,46 +230,59 @@ enum net_event_wifi_cmd { NET_EVENT_WIFI_CMD_AP_STA_DISCONNECTED, }; +/** Event emitted for Wi-Fi scan result */ #define NET_EVENT_WIFI_SCAN_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_SCAN_RESULT) +/** Event emitted when Wi-Fi scan is done */ #define NET_EVENT_WIFI_SCAN_DONE \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_SCAN_DONE) +/** Event emitted for Wi-Fi connect result */ #define NET_EVENT_WIFI_CONNECT_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_CONNECT_RESULT) +/** Event emitted for Wi-Fi disconnect result */ #define NET_EVENT_WIFI_DISCONNECT_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_DISCONNECT_RESULT) -#define NET_EVENT_WIFI_IFACE_STATUS \ +/** Event emitted for Wi-Fi network interface status */ +#define NET_EVENT_WIFI_IFACE_STATUS \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_IFACE_STATUS) +/** Event emitted for Wi-Fi TWT information */ #define NET_EVENT_WIFI_TWT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_TWT) +/** Event emitted for Wi-Fi TWT sleep state */ #define NET_EVENT_WIFI_TWT_SLEEP_STATE \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_TWT_SLEEP_STATE) +/** Event emitted for Wi-Fi raw scan result */ #define NET_EVENT_WIFI_RAW_SCAN_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_RAW_SCAN_RESULT) +/** Event emitted Wi-Fi disconnect is completed */ #define NET_EVENT_WIFI_DISCONNECT_COMPLETE \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_DISCONNECT_COMPLETE) +/** Event emitted for Wi-Fi access point enable result */ #define NET_EVENT_WIFI_AP_ENABLE_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_ENABLE_RESULT) +/** Event emitted for Wi-Fi access point disable result */ #define NET_EVENT_WIFI_AP_DISABLE_RESULT \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_DISABLE_RESULT) +/** Event emitted when Wi-Fi station is connected in AP mode */ #define NET_EVENT_WIFI_AP_STA_CONNECTED \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_STA_CONNECTED) +/** Event emitted Wi-Fi station is disconnected from AP */ #define NET_EVENT_WIFI_AP_STA_DISCONNECTED \ (_NET_WIFI_EVENT | NET_EVENT_WIFI_CMD_AP_STA_DISCONNECTED) -/** Wi-Fi version */ +/** @brief Wi-Fi version */ struct wifi_version { /** Driver version */ const char *drv_version; @@ -306,7 +352,7 @@ struct wifi_scan_params { struct wifi_band_channel band_chan[WIFI_MGMT_SCAN_CHAN_MAX_MANUAL]; }; -/** Wi-Fi scan result, each result is provided to the net_mgmt_event_callback +/** @brief Wi-Fi scan result, each result is provided to the net_mgmt_event_callback * via its info attribute (see net_mgmt.h) */ struct wifi_scan_result { @@ -330,7 +376,7 @@ struct wifi_scan_result { uint8_t mac_length; }; -/** Wi-Fi connect request parameters */ +/** @brief Wi-Fi connect request parameters */ struct wifi_connect_req_params { /** SSID */ const uint8_t *ssid; @@ -358,7 +404,7 @@ struct wifi_connect_req_params { int timeout; }; -/** Wi-Fi connect result codes. To be overlaid on top of \ref wifi_status +/** @brief Wi-Fi connect result codes. To be overlaid on top of \ref wifi_status * in the connect result event for detailed status. */ enum wifi_conn_status { @@ -385,12 +431,14 @@ enum wifi_conn_status { WIFI_STATUS_DISCONN_FIRST_STATUS = WIFI_STATUS_CONN_LAST_STATUS, }; -/** Wi-Fi disconnect reason codes. To be overlaid on top of \ref wifi_status +/** @brief Wi-Fi disconnect reason codes. To be overlaid on top of \ref wifi_status * in the disconnect result event for detailed reason. */ enum wifi_disconn_reason { + /** Success, overload status as reason */ + WIFI_REASON_DISCONN_SUCCESS = 0, /** Unspecified reason */ - WIFI_REASON_DISCONN_UNSPECIFIED = WIFI_STATUS_DISCONN_FIRST_STATUS, + WIFI_REASON_DISCONN_UNSPECIFIED, /** Disconnected due to user request */ WIFI_REASON_DISCONN_USER_REQUEST, /** Disconnected due to AP leaving */ @@ -399,7 +447,7 @@ enum wifi_disconn_reason { WIFI_REASON_DISCONN_INACTIVITY, }; -/** Wi-Fi AP mode result codes. To be overlaid on top of \ref wifi_status +/** @brief Wi-Fi AP mode result codes. To be overlaid on top of \ref wifi_status * in the AP mode enable or disable result event for detailed status. */ enum wifi_ap_status { @@ -421,17 +469,21 @@ enum wifi_ap_status { WIFI_STATUS_AP_OP_NOT_PERMITTED, }; -/** Generic Wi-Fi status for commands and events */ +/** @brief Generic Wi-Fi status for commands and events */ struct wifi_status { union { + /** Status value */ int status; + /** Connection status */ enum wifi_conn_status conn_status; + /** Disconnection reason status */ enum wifi_disconn_reason disconn_reason; + /** Access point status */ enum wifi_ap_status ap_status; }; }; -/** Wi-Fi interface status */ +/** @brief Wi-Fi interface status */ struct wifi_iface_status { /** Interface state, see enum wifi_iface_state */ int state; @@ -463,11 +515,11 @@ struct wifi_iface_status { bool twt_capable; }; -/** Wi-Fi power save parameters */ +/** @brief Wi-Fi power save parameters */ struct wifi_ps_params { - /* Power save state */ + /** Power save state */ enum wifi_ps enabled; - /* Listen interval */ + /** Listen interval */ unsigned short listen_interval; /** Wi-Fi power save wakeup mode */ enum wifi_ps_wakeup_mode wakeup_mode; @@ -488,7 +540,7 @@ struct wifi_ps_params { enum wifi_config_ps_param_fail_reason fail_reason; }; -/** Wi-Fi TWT parameters */ +/** @brief Wi-Fi TWT parameters */ struct wifi_twt_params { /** TWT operation, see enum wifi_twt_operation */ enum wifi_twt_operation operation; @@ -519,7 +571,7 @@ struct wifi_twt_params { bool announce; /** Wake up time */ uint32_t twt_wake_interval; - /* Wake ahead notification is sent earlier than + /** Wake ahead notification is sent earlier than * TWT Service period (SP) start based on this duration. * This should give applications ample time to * prepare the data before TWT SP starts. @@ -536,6 +588,8 @@ struct wifi_twt_params { enum wifi_twt_fail_reason fail_reason; }; +/** @cond INTERNAL_HIDDEN */ + /* Flow ID is only 3 bits */ #define WIFI_MAX_TWT_FLOWS 8 #define WIFI_MAX_TWT_INTERVAL_US (LONG_MAX - 1) @@ -543,7 +597,9 @@ struct wifi_twt_params { #define WIFI_MAX_TWT_WAKE_INTERVAL_US 262144 #define WIFI_MAX_TWT_WAKE_AHEAD_DURATION_US (LONG_MAX - 1) -/** Wi-Fi TWT flow information */ +/** @endcond */ + +/** @brief Wi-Fi TWT flow information */ struct wifi_twt_flow_info { /** Interval = Wake up time + Sleeping time */ uint64_t twt_interval; @@ -563,11 +619,11 @@ struct wifi_twt_flow_info { bool announce; /** Wake up time */ uint32_t twt_wake_interval; - /* wake ahead duration */ + /** Wake ahead duration */ uint32_t twt_wake_ahead_duration; }; -/** Wi-Fi power save configuration */ +/** @brief Wi-Fi power save configuration */ struct wifi_ps_config { /** Number of TWT flows */ char num_twt_flows; @@ -577,7 +633,7 @@ struct wifi_ps_config { struct wifi_ps_params ps_params; }; -/** Generic get/set operation for any command*/ +/** @brief Generic get/set operation for any command*/ enum wifi_mgmt_op { /** Get operation */ WIFI_MGMT_GET = 0, @@ -585,9 +641,10 @@ enum wifi_mgmt_op { WIFI_MGMT_SET = 1, }; +/** Max regulatory channel number */ #define MAX_REG_CHAN_NUM 42 -/** Per-channel regulatory attributes */ +/** @brief Per-channel regulatory attributes */ struct wifi_reg_chan_info { /** Center frequency in MHz */ unsigned short center_frequency; @@ -601,9 +658,9 @@ struct wifi_reg_chan_info { unsigned short dfs:1; } __packed; -/** Regulatory domain information or configuration */ +/** @brief Regulatory domain information or configuration */ struct wifi_reg_domain { - /* Regulatory domain operation */ + /** Regulatory domain operation */ enum wifi_mgmt_op oper; /** Ignore all other regulatory hints over this one */ bool force; @@ -615,7 +672,7 @@ struct wifi_reg_domain { struct wifi_reg_chan_info *chan_info; }; -/** Wi-Fi TWT sleep states */ +/** @brief Wi-Fi TWT sleep states */ enum wifi_twt_sleep_state { /** TWT sleep state: sleeping */ WIFI_TWT_STATE_SLEEP = 0, @@ -624,7 +681,7 @@ enum wifi_twt_sleep_state { }; #if defined(CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS) || defined(__DOXYGEN__) -/** Wi-Fi raw scan result */ +/** @brief Wi-Fi raw scan result */ struct wifi_raw_scan_result { /** RSSI */ int8_t rssi; @@ -637,7 +694,7 @@ struct wifi_raw_scan_result { }; #endif /* CONFIG_WIFI_MGMT_RAW_SCAN_RESULTS */ -/** AP mode - connected STA details */ +/** @brief AP mode - connected STA details */ struct wifi_ap_sta_info { /** Link mode, see enum wifi_link_mode */ enum wifi_link_mode link_mode; @@ -649,6 +706,8 @@ struct wifi_ap_sta_info { bool twt_capable; }; +/** @cond INTERNAL_HIDDEN */ + /* for use in max info size calculations */ union wifi_mgmt_events { struct wifi_scan_result scan_result; @@ -661,7 +720,9 @@ union wifi_mgmt_events { struct wifi_ap_sta_info ap_sta_info; }; -/** Wi-Fi mode setup */ +/** @endcond */ + +/** @brief Wi-Fi mode setup */ struct wifi_mode_info { /** Mode setting for a specific mode of operation */ uint8_t mode; @@ -671,7 +732,7 @@ struct wifi_mode_info { enum wifi_mgmt_op oper; }; -/** Wi-Fi filter setting for monitor, prmoiscuous, TX-injection modes */ +/** @brief Wi-Fi filter setting for monitor, prmoiscuous, TX-injection modes */ struct wifi_filter_info { /** Filter setting */ uint8_t filter; @@ -683,7 +744,7 @@ struct wifi_filter_info { enum wifi_mgmt_op oper; }; -/** Wi-Fi channel setting for monitor and TX-injection modes */ +/** @brief Wi-Fi channel setting for monitor and TX-injection modes */ struct wifi_channel_info { /** Channel value to set */ uint16_t channel; @@ -693,6 +754,20 @@ struct wifi_channel_info { enum wifi_mgmt_op oper; }; +/** @cond INTERNAL_HIDDEN */ +#define WIFI_AP_STA_MAX_INACTIVITY (LONG_MAX - 1) +/** @endcond */ + +/** @brief Wi-Fi AP configuration parameter */ +struct wifi_ap_config_params { + /** Parameter used to identify the different AP parameters */ + enum wifi_ap_config_param type; + /** Parameter used for setting maximum inactivity duration for stations */ + uint32_t max_inactivity; + /** Parameter used for setting maximum number of stations */ + uint32_t max_num_sta; +}; + #include /** Scan result callback @@ -866,7 +941,14 @@ struct wifi_mgmt_ops { * @return 0 if ok, < 0 if error */ int (*set_rts_threshold)(const struct device *dev, unsigned int rts_threshold); - + /** Configure AP parameter + * + * @param dev Pointer to the device structure for the driver instance. + * @param params AP mode parameter configuration parameter info + * + * @return 0 if ok, < 0 if error + */ + int (*ap_config_params)(const struct device *dev, struct wifi_ap_config_params *params); }; /** Wi-Fi management offload API */ diff --git a/include/zephyr/net/wifi_nm.h b/include/zephyr/net/wifi_nm.h index dd97fcdd8b616..615d49157572a 100644 --- a/include/zephyr/net/wifi_nm.h +++ b/include/zephyr/net/wifi_nm.h @@ -42,6 +42,8 @@ struct wifi_nm_instance { struct net_if *mgd_ifaces[CONFIG_WIFI_NM_MAX_MANAGED_INTERFACES]; }; +/** @cond INTERNAL_HIDDEN */ + #define WIFI_NM_NAME(name) wifi_nm_##name #define DEFINE_WIFI_NM_INSTANCE(_name, _ops) \ @@ -51,6 +53,8 @@ struct wifi_nm_instance { .mgd_ifaces = { NULL }, \ } +/** @endcond */ + /** * @brief Get a Network manager instance for a given name * diff --git a/include/zephyr/net/wifi_utils.h b/include/zephyr/net/wifi_utils.h index 537db78764828..511d203353228 100644 --- a/include/zephyr/net/wifi_utils.h +++ b/include/zephyr/net/wifi_utils.h @@ -28,7 +28,10 @@ extern "C" { * @{ */ +/** Maximum length of the band specification string */ #define WIFI_UTILS_MAX_BAND_STR_LEN 3 + +/** Maximum length of the channel specification string */ #define WIFI_UTILS_MAX_CHAN_STR_LEN 4 /** diff --git a/include/zephyr/net/zperf.h b/include/zephyr/net/zperf.h index a629048330090..c97c9d014395b 100644 --- a/include/zephyr/net/zperf.h +++ b/include/zephyr/net/zperf.h @@ -24,8 +24,11 @@ extern "C" { #endif +/** @cond INTERNAL_HIDDEN */ + enum zperf_status { ZPERF_SESSION_STARTED, + ZPERF_SESSION_PERIODIC_RESULT, ZPERF_SESSION_FINISHED, ZPERF_SESSION_ERROR } __packed; @@ -40,6 +43,7 @@ struct zperf_upload_params { uint8_t tos; int tcp_nodelay; int priority; + uint32_t report_interval_ms; } options; }; @@ -49,17 +53,20 @@ struct zperf_download_params { char if_name[IFNAMSIZ]; }; +/** @endcond */ + +/** Performance results */ struct zperf_results { - uint32_t nb_packets_sent; - uint32_t nb_packets_rcvd; - uint32_t nb_packets_lost; - uint32_t nb_packets_outorder; - uint64_t total_len; - uint64_t time_in_us; - uint32_t jitter_in_us; - uint64_t client_time_in_us; - uint32_t packet_size; - uint32_t nb_packets_errors; + uint32_t nb_packets_sent; /**< Number of packets sent */ + uint32_t nb_packets_rcvd; /**< Number of packets received */ + uint32_t nb_packets_lost; /**< Number of packets lost */ + uint32_t nb_packets_outorder; /**< Number of packets out of order */ + uint64_t total_len; /**< Total length of the transferred data */ + uint64_t time_in_us; /**< Total time of the transfer in microseconds */ + uint32_t jitter_in_us; /**< Jitter in microseconds */ + uint64_t client_time_in_us; /**< Client connection time in microseconds */ + uint32_t packet_size; /**< Packet size */ + uint32_t nb_packets_errors; /**< Number of packet errors */ }; /** diff --git a/include/zephyr/pm/device_runtime.h b/include/zephyr/pm/device_runtime.h index b1404fa4ac4c8..fde8f631ca2f9 100644 --- a/include/zephyr/pm/device_runtime.h +++ b/include/zephyr/pm/device_runtime.h @@ -48,7 +48,6 @@ int pm_device_runtime_auto_enable(const struct device *dev); * @param dev Device instance. * * @retval 0 If the device runtime PM is enabled successfully. - * @retval -EPERM If device has power state locked. * @retval -EBUSY If device is busy. * @retval -ENOTSUP If the device does not support PM. * @retval -errno Other negative errno, result of suspending the device. diff --git a/include/zephyr/pm/pm.h b/include/zephyr/pm/pm.h index 09138bf1871f1..e1fb695415c16 100644 --- a/include/zephyr/pm/pm.h +++ b/include/zephyr/pm/pm.h @@ -116,6 +116,30 @@ int pm_notifier_unregister(struct pm_notifier *notifier); */ const struct pm_state_info *pm_state_next_get(uint8_t cpu); +/** + * @brief Notify exit from kernel sleep. + * + * This function would notify exit from kernel idling if a corresponding + * pm_system_suspend() notification was handled and did not return + * PM_STATE_ACTIVE. + * + * This function should be called from the ISR context of the event + * that caused the exit from kernel idling. + * + * This is required for cpu power states that would require + * interrupts to be enabled while entering low power states. e.g. C1 in x86. In + * those cases, the ISR would be invoked immediately after the event wakes up + * the CPU, before code following the CPU wait, gets a chance to execute. This + * can be ignored if no operation needs to be done at the wake event + * notification. + */ +void pm_system_resume(void); + + +/** @cond INTERNAL_HIDDEN */ +__deprecated void z_pm_save_idle_exit(void); +/** @endcond */ + /** * @} */ @@ -175,9 +199,15 @@ static inline const struct pm_state_info *pm_state_next_get(uint8_t cpu) return NULL; } -#endif /* CONFIG_PM */ +static inline void z_pm_save_idle_exit(void) +{ +} -void z_pm_save_idle_exit(void); +static inline void pm_system_resume(void) +{ +} + +#endif /* CONFIG_PM */ #ifdef __cplusplus } diff --git a/include/zephyr/pm/policy.h b/include/zephyr/pm/policy.h index e77004bbbe8fd..6fe91663bb6c7 100644 --- a/include/zephyr/pm/policy.h +++ b/include/zephyr/pm/policy.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -219,6 +220,32 @@ void pm_policy_event_update(struct pm_policy_event *evt, uint32_t time_us); */ void pm_policy_event_unregister(struct pm_policy_event *evt); +/** + * @brief Increase power state locks. + * + * Set power state locks in all power states that disable power in the given + * device. + * + * @param dev Device reference. + * + * @see pm_policy_device_power_lock_put() + * @see pm_policy_state_lock_get() + */ +void pm_policy_device_power_lock_get(const struct device *dev); + +/** + * @brief Decrease power state locks. + * + * Remove power state locks in all power states that disable power in the given + * device. + * + * @param dev Device reference. + * + * @see pm_policy_device_power_lock_get() + * @see pm_policy_state_lock_put() + */ +void pm_policy_device_power_lock_put(const struct device *dev); + #else static inline void pm_policy_state_lock_get(enum pm_state state, uint8_t substate_id) { @@ -278,6 +305,17 @@ static inline void pm_policy_event_unregister(struct pm_policy_event *evt) { ARG_UNUSED(evt); } + +static inline void pm_policy_device_power_lock_get(const struct device *dev) +{ + ARG_UNUSED(dev); +} + +static inline void pm_policy_device_power_lock_put(const struct device *dev) +{ + ARG_UNUSED(dev); +} + #endif /* CONFIG_PM */ /** diff --git a/include/zephyr/pm/state.h b/include/zephyr/pm/state.h index cc3878794113d..87363ea27d2e9 100644 --- a/include/zephyr/pm/state.h +++ b/include/zephyr/pm/state.h @@ -134,12 +134,22 @@ struct pm_state_info { * substate-id = <2>; * min-residency-us = <20000>; * exit-latency-us = <200>; + * zephyr,pm-device-disabled; * }; * }; * @endcode */ uint8_t substate_id; + /** + * Whether or not this state triggers device power management. + * + * When this property is false the power management subsystem + * will suspend devices before entering this state and will + * properly resume them when leaving it. + */ + bool pm_device_disabled; + /** * Minimum residency duration in microseconds. It is the minimum * time for a given idle state to be worthwhile energywise. @@ -156,6 +166,24 @@ struct pm_state_info { uint32_t exit_latency_us; }; +/** + * Power state information needed to lock a power state. + */ +struct pm_state_constraint { + /** + * Power management state + * + * @see pm_state + **/ + enum pm_state state; + /** + * Power management sub-state + * + * @see pm_state + **/ + uint8_t substate_id; +}; + /** @cond INTERNAL_HIDDEN */ /** @@ -209,6 +237,7 @@ struct pm_state_info { .substate_id = DT_PROP_OR(node_id, substate_id, 0), \ .min_residency_us = DT_PROP_OR(node_id, min_residency_us, 0), \ .exit_latency_us = DT_PROP_OR(node_id, exit_latency_us, 0), \ + .pm_device_disabled = DT_PROP(node_id, zephyr_pm_device_disabled), \ } /** @@ -260,6 +289,7 @@ struct pm_state_info { * power-state-name = "suspend-to-ram"; * min-residency-us = <50000>; * exit-latency-us = <500>; + * zephyr,pm-device-disabled; * }; * }; * }; diff --git a/include/zephyr/posix/dirent.h b/include/zephyr/posix/dirent.h index 43c68983ebb73..12f5d44380d9b 100644 --- a/include/zephyr/posix/dirent.h +++ b/include/zephyr/posix/dirent.h @@ -9,7 +9,7 @@ #include #include "posix_types.h" -#ifdef CONFIG_POSIX_FS +#ifdef CONFIG_POSIX_FILE_SYSTEM #include #ifdef __cplusplus @@ -32,6 +32,6 @@ struct dirent *readdir(DIR *dirp); } #endif -#endif /* CONFIG_POSIX_FS */ +#endif /* CONFIG_POSIX_FILE_SYSTEM */ #endif /* ZEPHYR_INCLUDE_POSIX_DIRENT_H_ */ diff --git a/include/zephyr/posix/mqueue.h b/include/zephyr/posix/mqueue.h index dbaa6d42a537d..aac03426da442 100644 --- a/include/zephyr/posix/mqueue.h +++ b/include/zephyr/posix/mqueue.h @@ -4,8 +4,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -#ifndef ZEPHYR_INCLUDE_POSIX_MQUEUE_H_ -#define ZEPHYR_INCLUDE_POSIX_MQUEUE_H_ +#ifndef ZEPHYR_INCLUDE_POSIX_MESSAGE_PASSING_H_ +#define ZEPHYR_INCLUDE_POSIX_MESSAGE_PASSING_H_ #include #include @@ -47,4 +47,4 @@ int mq_notify(mqd_t mqdes, const struct sigevent *notification); } #endif -#endif /* ZEPHYR_INCLUDE_POSIX_MQUEUE_H_ */ +#endif /* ZEPHYR_INCLUDE_POSIX_MESSAGE_PASSING_H_ */ diff --git a/include/zephyr/posix/posix_features.h b/include/zephyr/posix/posix_features.h new file mode 100644 index 0000000000000..4e15fbd695019 --- /dev/null +++ b/include/zephyr/posix/posix_features.h @@ -0,0 +1,347 @@ +/* + * Copyright (c) 2024 BayLibre SAS + * Copyright (c) 2024 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef INCLUDE_ZEPHYR_POSIX_POSIX_FEATURES_H_ +#define INCLUDE_ZEPHYR_POSIX_POSIX_FEATURES_H_ + +#include /* CONFIG_* */ +#include /* COND_CODE_1() */ + +/* + * POSIX Application Environment Profiles (AEP - IEEE Std 1003.13-2003) + */ + +#ifdef CONFIG_POSIX_AEP_REALTIME_MINIMAL +#define _POSIX_AEP_REALTIME_MINIMAL 200312L +#endif + +#ifdef CONFIG_POSIX_AEP_REALTIME_CONTROLLER +#define _POSIX_AEP_REALTIME_CONTROLLER 200312L +#endif + +#ifdef CONFIG_POSIX_AEP_REALTIME_DEDICATED +#define _POSIX_AEP_REALTIME_DEDICATED 200312L +#endif + +/* + * POSIX System Interfaces + */ + +#define _POSIX_VERSION 200809L + +#define _POSIX_CHOWN_RESTRICTED (0) +#define _POSIX_NO_TRUNC (0) +#define _POSIX_VDISABLE ('\0') + +/* #define _POSIX_ADVISORY_INFO (-1L) */ + +#ifdef CONFIG_POSIX_ASYNCHRONOUS_IO +#define _POSIX_ASYNCHRONOUS_IO _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_BARRIERS +#define _POSIX_BARRIERS _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_CLOCK_SELECTION +#define _POSIX_CLOCK_SELECTION _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_CPUTIME +#define _POSIX_CPUTIME _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_FSYNC +#define _POSIX_FSYNC _POSIX_VERSION +#endif + +#ifdef CONFIG_NET_IPV6 +#define _POSIX_IPV6 _POSIX_VERSION +#endif + +/* #define _POSIX_JOB_CONTROL (-1L) */ + +#ifdef CONFIG_POSIX_MAPPED_FILES +#define _POSIX_MAPPED_FILES _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_MEMLOCK +#define _POSIX_MEMLOCK _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_MEMLOCK_RANGE +#define _POSIX_MEMLOCK_RANGE _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_MEMORY_PROTECTION +#define _POSIX_MEMORY_PROTECTION _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_MESSAGE_PASSING +#define _POSIX_MESSAGE_PASSING _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_MONOTONIC_CLOCK +#define _POSIX_MONOTONIC_CLOCK _POSIX_VERSION +#endif + +/* #define _POSIX_PRIORITIZED_IO (-1L) */ + +#ifdef CONFIG_POSIX_PRIORITY_SCHEDULING +#define _POSIX_PRIORITY_SCHEDULING _POSIX_VERSION +#endif + +#ifdef CONFIG_NET_SOCKETS_PACKET +#define _POSIX_RAW_SOCKETS _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_READER_WRITER_LOCKS +#define _POSIX_READER_WRITER_LOCKS _POSIX_VERSION +#endif + +/* #define _POSIX_REALTIME_SIGNALS (-1L) */ +/* #define _POSIX_REGEXP (-1L) */ +/* #define _POSIX_SAVED_IDS (-1L) */ + +#ifdef CONFIG_POSIX_SEMAPHORES +#define _POSIX_SEMAPHORES _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_SHARED_MEMORY_OBJECTS +#define _POSIX_SHARED_MEMORY_OBJECTS _POSIX_VERSION +#endif + +/* #define _POSIX_SHELL (-1L) */ +/* #define _POSIX_SPAWN (-1L) */ + +#ifdef CONFIG_POSIX_SPIN_LOCKS +#define _POSIX_SPIN_LOCKS _POSIX_VERSION +#endif + +/* #define _POSIX_SPORADIC_SERVER (-1L) */ +/* #define _POSIX_SYNCHRONIZED_IO (-1L) */ + +#ifdef CONFIG_POSIX_THREAD_ATTR_STACKADDR +#define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_THREAD_ATTR_STACKSIZE +#define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_THREAD_CPUTIME +#define _POSIX_THREAD_CPUTIME _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_THREAD_PRIO_INHERIT +#define _POSIX_THREAD_PRIO_INHERIT _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_THREAD_PRIO_PROTECT +#define _POSIX_THREAD_PRIO_PROTECT _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_THREAD_PRIORITY_SCHEDULING +#define _POSIX_THREAD_PRIORITY_SCHEDULING _POSIX_VERSION +#endif + +/* #define _POSIX_THREAD_PROCESS_SHARED (-1L) */ +/* #define _POSIX_THREAD_ROBUST_PRIO_INHERIT (-1L) */ +/* #define _POSIX_THREAD_ROBUST_PRIO_PROTECT (-1L) */ + +#ifdef CONFIG_POSIX_THREAD_SAFE_FUNCTIONS +#define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION +#endif + +/* #define _POSIX_THREAD_SPORADIC_SERVER (-1L) */ + +#ifdef CONFIG_POSIX_THREADS +#ifndef _POSIX_THREADS +#define _POSIX_THREADS _POSIX_VERSION +#endif +#endif + +#ifdef CONFIG_POSIX_TIMEOUTS +#define _POSIX_TIMEOUTS _POSIX_VERSION +#endif + +#ifdef CONFIG_POSIX_TIMERS +#define _POSIX_TIMERS _POSIX_VERSION +#endif + +/* #define _POSIX_TRACE (-1L) */ +/* #define _POSIX_TRACE_EVENT_FILTER (-1L) */ +/* #define _POSIX_TRACE_INHERIT (-1L) */ +/* #define _POSIX_TRACE_LOG (-1L) */ +/* #define _POSIX_TYPED_MEMORY_OBJECTS (-1L) */ + +/* + * POSIX v6 Options + */ +/* #define _POSIX_V6_ILP32_OFF32 (-1L) */ +/* #define _POSIX_V6_ILP32_OFFBIG (-1L) */ +/* #define _POSIX_V6_LP64_OFF64 (-1L) */ +/* #define _POSIX_V6_LPBIG_OFFBIG (-1L) */ + +/* + * POSIX v7 Options + */ +/* #define _POSIX_V7_ILP32_OFF32 (-1L) */ +/* #define _POSIX_V7_ILP32_OFFBIG (-1L) */ +/* #define _POSIX_V7_LP64_OFF64 (-1L) */ +/* #define _POSIX_V7_LPBIG_OFFBIG (-1L) */ + +/* + * POSIX2 Options + */ +#define _POSIX2_VERSION _POSIX_VERSION +#define _POSIX2_C_BIND _POSIX2_VERSION +#define _POSIX2_C_DEV _POSIX2_VERSION +/* #define _POSIX2_CHAR_TERM (-1L) */ +/* #define _POSIX2_FORT_DEV (-1L) */ +/* #define _POSIX2_FORT_RUN (-1L) */ +/* #define _POSIX2_LOCALEDEF (-1L) */ +/* #define _POSIX2_PBS (-1L) */ +/* #define _POSIX2_PBS_ACCOUNTING (-1L) */ +/* #define _POSIX2_PBS_CHECKPOINT (-1L) */ +/* #define _POSIX2_PBS_LOCATE (-1L) */ +/* #define _POSIX2_PBS_MESSAGE (-1L) */ +/* #define _POSIX2_PBS_TRACK (-1L) */ +/* #define _POSIX2_SW_DEV (-1L) */ +/* #define _POSIX2_UPE (-1L) */ + +/* + * X/Open System Interfaces + */ +#define _XOPEN_VERSION 700 +/* #define _XOPEN_CRYPT (-1L) */ +/* #define _XOPEN_ENH_I18N (-1L) */ +/* #define _XOPEN_REALTIME (-1L) */ +/* #define _XOPEN_REALTIME_THREADS (-1L) */ +/* #define _XOPEN_SHM (-1L) */ + +#ifdef CONFIG_XOPEN_STREAMS +#define _XOPEN_STREAMS _XOPEN_VERSION +#endif + +/* #define _XOPEN_UNIX (-1L) */ +/* #define _XOPEN_UUCP (-1L) */ + +/* Maximum values */ +#define _POSIX_CLOCKRES_MIN (20000000L) + +/* Minimum values */ +#define _POSIX_AIO_LISTIO_MAX (2) +#define _POSIX_AIO_MAX (1) +#define _POSIX_ARG_MAX (4096) +#define _POSIX_CHILD_MAX (25) +#define _POSIX_DELAYTIMER_MAX \ + COND_CODE_1(CONFIG_POSIX_TIMERS, (CONFIG_POSIX_DELAYTIMER_MAX), (0)) +#define _POSIX_HOST_NAME_MAX \ + COND_CODE_1(CONFIG_POSIX_NETWORKING, (CONFIG_POSIX_HOST_NAME_MAX), (0)) +#define _POSIX_LINK_MAX (8) +#define _POSIX_LOGIN_NAME_MAX (9) +#define _POSIX_MAX_CANON (255) +#define _POSIX_MAX_INPUT (255) +#define _POSIX_MQ_OPEN_MAX \ + COND_CODE_1(CONFIG_POSIX_MESSAGE_PASSING, (CONFIG_POSIX_MQ_OPEN_MAX), (0)) +#define _POSIX_MQ_PRIO_MAX (32) +#define _POSIX_NAME_MAX (14) +#define _POSIX_NGROUPS_MAX (8) +#define _POSIX_OPEN_MAX CONFIG_POSIX_OPEN_MAX +#define _POSIX_PATH_MAX (256) +#define _POSIX_PIPE_BUF (512) +#define _POSIX_RE_DUP_MAX (255) +#define _POSIX_RTSIG_MAX \ + COND_CODE_1(CONFIG_POSIX_REALTIME_SIGNALS, (CONFIG_POSIX_RTSIG_MAX), (0)) +#define _POSIX_SEM_NSEMS_MAX \ + COND_CODE_1(CONFIG_POSIX_SEMAPHORES, (CONFIG_POSIX_SEM_NSEMS_MAX), (0)) +#define _POSIX_SEM_VALUE_MAX \ + COND_CODE_1(CONFIG_POSIX_SEMAPHORES, (CONFIG_POSIX_SEM_VALUE_MAX), (0)) +#define _POSIX_SIGQUEUE_MAX (32) +#define _POSIX_SSIZE_MAX (32767) +#define _POSIX_SS_REPL_MAX (4) +#define _POSIX_STREAM_MAX (8) +#define _POSIX_SYMLINK_MAX (255) +#define _POSIX_SYMLOOP_MAX (8) +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS (4) +#define _POSIX_THREAD_KEYS_MAX \ + COND_CODE_1(CONFIG_POSIX_THREADS, (CONFIG_POSIX_THREAD_KEYS_MAX), (0)) +#define _POSIX_THREAD_THREADS_MAX \ + COND_CODE_1(CONFIG_POSIX_THREADS, (CONFIG_POSIX_THREAD_THREADS_MAX), (0)) +#define _POSIX_TIMER_MAX \ + COND_CODE_1(CONFIG_POSIX_TIMERS, (CONFIG_POSIX_TIMER_MAX), (0)) +#define _POSIX_TRACE_EVENT_NAME_MAX (30) +#define _POSIX_TRACE_NAME_MAX (8) +#define _POSIX_TRACE_SYS_MAX (8) +#define _POSIX_TRACE_USER_EVENT_MAX (32) +#define _POSIX_TTY_NAME_MAX (9) +#define _POSIX_TZNAME_MAX (6) +#define _POSIX2_BC_BASE_MAX (99) +#define _POSIX2_BC_DIM_MAX (2048) +#define _POSIX2_BC_SCALE_MAX (99) +#define _POSIX2_BC_STRING_MAX (1000) +#define _POSIX2_CHARCLASS_NAME_MAX (14) +#define _POSIX2_COLL_WEIGHTS_MAX (2) +#define _POSIX2_EXPR_NEST_MAX (32) +#define _POSIX2_LINE_MAX (2048) +#define _XOPEN_IOV_MAX (16) +#define _XOPEN_NAME_MAX (255) +#define _XOPEN_PATH_MAX (1024) + +/* Other invariant values */ +#define NL_LANGMAX (14) +#define NL_MSGMAX (32767) +#define NL_SETMAX (255) +#define NL_TEXTMAX (_POSIX2_LINE_MAX) +#define NZERO (20) + +/* Runtime invariant values */ +#define AIO_LISTIO_MAX _POSIX_AIO_LISTIO_MAX +#define AIO_MAX _POSIX_AIO_MAX +#define AIO_PRIO_DELTA_MAX (0) +#define DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX +#define HOST_NAME_MAX _POSIX_HOST_NAME_MAX +#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX +#define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX +#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX + +#ifndef ATEXIT_MAX +#define ATEXIT_MAX 8 +#endif + +#ifndef PAGE_SIZE +#define PAGE_SIZE CONFIG_POSIX_PAGE_SIZE +#endif + +#ifndef PAGESIZE +#define PAGESIZE PAGE_SIZE +#endif + +#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS +#define PTHREAD_KEYS_MAX _POSIX_THREAD_KEYS_MAX +#define PTHREAD_THREADS_MAX _POSIX_THREAD_THREADS_MAX +#define RTSIG_MAX _POSIX_RTSIG_MAX +#define SEM_NSEMS_MAX _POSIX_SEM_NSEMS_MAX +#define SEM_VALUE_MAX _POSIX_SEM_VALUE_MAX +#define SIGQUEUE_MAX _POSIX_SIGQUEUE_MAX +#define STREAM_MAX _POSIX_STREAM_MAX +#define SYMLOOP_MAX _POSIX_SYMLOOP_MAX +#define TIMER_MAX _POSIX_TIMER_MAX +#define TTY_NAME_MAX _POSIX_TTY_NAME_MAX +#define TZNAME_MAX _POSIX_TZNAME_MAX + +/* Pathname variable values */ +#define FILESIZEBITS (32) +#define POSIX_ALLOC_SIZE_MIN (256) +#define POSIX_REC_INCR_XFER_SIZE (1024) +#define POSIX_REC_MAX_XFER_SIZE (32767) +#define POSIX_REC_MIN_XFER_SIZE (1) +#define POSIX_REC_XFER_ALIGN (4) +#define SYMLINK_MAX _POSIX_SYMLINK_MAX + +#endif /* INCLUDE_ZEPHYR_POSIX_POSIX_FEATURES_H_ */ diff --git a/include/zephyr/posix/pthread.h b/include/zephyr/posix/pthread.h index 2cc05b6df2585..f2723d68d76a6 100644 --- a/include/zephyr/posix/pthread.h +++ b/include/zephyr/posix/pthread.h @@ -276,20 +276,6 @@ int pthread_mutexattr_init(pthread_mutexattr_t *attr); */ int pthread_mutexattr_destroy(pthread_mutexattr_t *attr); -/** - * @brief Declare a pthread barrier - * - * Declaration API for a pthread barrier. This is not a - * POSIX API, it's provided to better conform with Zephyr's allocation - * strategies for kernel objects. - * - * @param name Symbol name of the barrier - * @param count Thread count, same as the "count" argument to - * pthread_barrier_init() - * @deprecated Use @ref pthread_barrier_init instead. - */ -#define PTHREAD_BARRIER_DEFINE(name, count) pthread_barrier_t name = -1 __DEPRECATED_MACRO - #define PTHREAD_BARRIER_SERIAL_THREAD 1 /* @@ -431,7 +417,7 @@ int pthread_attr_getscope(const pthread_attr_t *attr, int *contentionscope); int pthread_attr_setscope(pthread_attr_t *attr, int contentionscope); int pthread_attr_getinheritsched(const pthread_attr_t *attr, int *inheritsched); int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched); -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_THREADS int pthread_once(pthread_once_t *once, void (*initFunc)(void)); #endif FUNC_NORETURN void pthread_exit(void *retval); @@ -516,7 +502,7 @@ int pthread_setname_np(pthread_t thread, const char *name); */ int pthread_getname_np(pthread_t thread, char *name, size_t len); -#ifdef CONFIG_PTHREAD_IPC +#ifdef CONFIG_POSIX_THREADS /** * @brief Destroy a pthread_spinlock_t. diff --git a/include/zephyr/posix/signal.h b/include/zephyr/posix/signal.h index 3bbdee7317aca..165050f2ded92 100644 --- a/include/zephyr/posix/signal.h +++ b/include/zephyr/posix/signal.h @@ -7,6 +7,7 @@ #define ZEPHYR_INCLUDE_POSIX_SIGNAL_H_ #include "posix_types.h" +#include "posix_features.h" #ifdef __cplusplus extern "C" { @@ -44,7 +45,6 @@ extern "C" { /* 30 not used */ #define SIGSYS 31 /**< Bad system call */ -#define RTSIG_MAX CONFIG_POSIX_RTSIG_MAX #define SIGRTMIN 32 #define SIGRTMAX (SIGRTMIN + RTSIG_MAX) #define _NSIG (SIGRTMAX + 1) @@ -92,7 +92,6 @@ struct sigevent { int sigev_signo; }; -#ifdef CONFIG_POSIX_SIGNAL char *strsignal(int signum); int sigemptyset(sigset_t *set); int sigfillset(sigset_t *set); @@ -102,7 +101,6 @@ int sigismember(const sigset_t *set, int signo); int sigprocmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset); int pthread_sigmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset); -#endif /* CONFIG_POSIX_SIGNAL */ #ifdef __cplusplus } diff --git a/include/zephyr/posix/sys/eventfd.h b/include/zephyr/posix/sys/eventfd.h index 8f1443d7a9aac..35bef86d87e8c 100644 --- a/include/zephyr/posix/sys/eventfd.h +++ b/include/zephyr/posix/sys/eventfd.h @@ -7,21 +7,16 @@ #ifndef ZEPHYR_INCLUDE_POSIX_SYS_EVENTFD_H_ #define ZEPHYR_INCLUDE_POSIX_SYS_EVENTFD_H_ -#include - -#include -#include +#include #ifdef __cplusplus extern "C" { #endif -#define EFD_IN_USE 0x1 __DEPRECATED_MACRO -#define EFD_SEMAPHORE 0x2 -#define EFD_NONBLOCK O_NONBLOCK -#define EFD_FLAGS_SET (EFD_SEMAPHORE | EFD_NONBLOCK) __DEPRECATED_MACRO +#define EFD_SEMAPHORE ZVFS_EFD_SEMAPHORE +#define EFD_NONBLOCK ZVFS_EFD_NONBLOCK -typedef uint64_t eventfd_t; +typedef zvfs_eventfd_t eventfd_t; /** * @brief Create a file descriptor for event notification diff --git a/include/zephyr/posix/sys/mman.h b/include/zephyr/posix/sys/mman.h new file mode 100644 index 0000000000000..8cbf5fd838077 --- /dev/null +++ b/include/zephyr/posix/sys/mman.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZEPHYR_POSIX_SYS_MMAN_H_ +#define ZEPHYR_INCLUDE_ZEPHYR_POSIX_SYS_MMAN_H_ + +#include +#include + +#define PROT_NONE 0x0 +#define PROT_READ 0x1 +#define PROT_WRITE 0x2 +#define PROT_EXEC 0x4 + +#define MAP_SHARED 0x1 +#define MAP_PRIVATE 0x2 +#define MAP_FIXED 0x4 + +/* for Linux compatibility */ +#define MAP_ANONYMOUS 0x20 + +#define MS_SYNC 0x0 +#define MS_ASYNC 0x1 +#define MS_INVALIDATE 0x2 + +#define MAP_FAILED ((void *)-1) + +#define MCL_CURRENT 0 +#define MCL_FUTURE 1 + +#ifdef __cplusplus +extern "C" { +#endif + +int mlock(const void *addr, size_t len); +int mlockall(int flags); +void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off); +int msync(void *addr, size_t length, int flags); +int munlock(const void *addr, size_t len); +int munlockall(void); +int munmap(void *addr, size_t len); +int shm_open(const char *name, int oflag, mode_t mode); +int shm_unlink(const char *name); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_ZEPHYR_POSIX_SYS_MMAN_H_ */ diff --git a/include/zephyr/posix/sys/sysconf.h b/include/zephyr/posix/sys/sysconf.h index a88f16493e187..c7d8228a8cddb 100644 --- a/include/zephyr/posix/sys/sysconf.h +++ b/include/zephyr/posix/sys/sysconf.h @@ -1,17 +1,18 @@ /* * Copyright (c) 2024, Meta + * Copyright (c) 2024, Tenstorrent AI ULC * * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_POSIX_SYS_SYSCONF_H_ #define ZEPHYR_INCLUDE_POSIX_SYS_SYSCONF_H_ +#include + #ifdef __cplusplus extern "C" { #endif -#ifdef CONFIG_POSIX_SYSCONF - enum { _SC_ADVISORY_INFO, _SC_ASYNCHRONOUS_IO, @@ -21,7 +22,7 @@ enum { _SC_FSYNC, _SC_IPV6, _SC_JOB_CONTROL, - _SC_MAPPED_FILE, + _SC_MAPPED_FILES, _SC_MEMLOCK, _SC_MEMLOCK_RANGE, _SC_MEMORY_PROTECTION, @@ -140,100 +141,125 @@ enum { _SC_TZNAME_MAX, }; -#ifdef CONFIG_POSIX_SYSCONF_IMPL_MACRO -#define __z_posix_sysconf_SC_ADVISORY_INFO _POSIX_ADVISORY_INFO -#define __z_posix_sysconf_SC_ASYNCHRONOUS_IO _POSIX_ASYNCHRONOUS_IO -#define __z_posix_sysconf_SC_BARRIERS _POSIX_BARRIERS -#define __z_posix_sysconf_SC_CLOCK_SELECTION _POSIX_CLOCK_SELECTION -#define __z_posix_sysconf_SC_CPUTIME _POSIX_CPUTIME -#define __z_posix_sysconf_SC_FSYNC _POSIX_FSYNC -#define __z_posix_sysconf_SC_IPV6 _POSIX_IPV6 -#define __z_posix_sysconf_SC_JOB_CONTROL _POSIX_JOB_CONTROL -#define __z_posix_sysconf_SC_MAPPED_FILE _POSIX_MAPPED_FILES -#define __z_posix_sysconf_SC_MEMLOCK _POSIX_MEMLOCK -#define __z_posix_sysconf_SC_MEMLOCK_RANGE _POSIX_MEMLOCK_RANGE -#define __z_posix_sysconf_SC_MEMORY_PROTECTION _POSIX_MEMORY_PROTECTION -#define __z_posix_sysconf_SC_MESSAGE_PASSING _POSIX_MESSAGE_PASSING -#define __z_posix_sysconf_SC_MONOTONIC_CLOCK _POSIX_MONOTONIC_CLOCK -#define __z_posix_sysconf_SC_PRIORITIZED_IO _POSIX_PRIORITIZED_IO -#define __z_posix_sysconf_SC_PRIORITY_SCHEDULING _POSIX_PRIORITY_SCHEDULING -#define __z_posix_sysconf_SC_RAW_SOCKETS _POSIX_RAW_SOCKETS -#define __z_posix_sysconf_SC_RE_DUP_MAX _POSIX_RE_DUP_MAX -#define __z_posix_sysconf_SC_READER_WRITER_LOCKS _POSIX_READER_WRITER_LOCKS -#define __z_posix_sysconf_SC_REALTIME_SIGNALS _POSIX_REALTIME_SIGNALS -#define __z_posix_sysconf_SC_REGEXP _POSIX_REGEXP -#define __z_posix_sysconf_SC_SAVED_IDS _POSIX_SAVED_IDS -#define __z_posix_sysconf_SC_SEMAPHORES _POSIX_SEMAPHORES -#define __z_posix_sysconf_SC_SHARED_MEMORY_OBJECTS _POSIX_SHARED_MEMORY_OBJECTS -#define __z_posix_sysconf_SC_SHELL _POSIX_SHELL -#define __z_posix_sysconf_SC_SPAWN _POSIX_SPAWN -#define __z_posix_sysconf_SC_SPIN_LOCKS _POSIX_SPIN_LOCKS -#define __z_posix_sysconf_SC_SPORADIC_SERVER _POSIX_SPORADIC_SERVER -#define __z_posix_sysconf_SC_SS_REPL_MAX _POSIX_SS_REPL_MAX -#define __z_posix_sysconf_SC_SYNCHRONIZED_IO _POSIX_SYNCHRONIZED_IO -#define __z_posix_sysconf_SC_THREAD_ATTR_STACKADDR _POSIX_THREAD_ATTR_STACKADDR -#define __z_posix_sysconf_SC_THREAD_ATTR_STACKSIZE _POSIX_THREAD_ATTR_STACKSIZE -#define __z_posix_sysconf_SC_THREAD_CPUTIME _POSIX_THREAD_CPUTIME -#define __z_posix_sysconf_SC_THREAD_PRIO_INHERIT _POSIX_THREAD_PRIO_INHERIT -#define __z_posix_sysconf_SC_THREAD_PRIO_PROTECT _POSIX_THREAD_PRIO_PROTECT -#define __z_posix_sysconf_SC_THREAD_PRIORITY_SCHEDULING _POSIX_THREAD_PRIORITY_SCHEDULING -#define __z_posix_sysconf_SC_THREAD_PROCESS_SHARED _POSIX_THREAD_PROCESS_SHARED -#define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_INHERIT _POSIX_THREAD_ROBUST_PRIO_INHERIT -#define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_PROTECT _POSIX_THREAD_ROBUST_PRIO_PROTECT -#define __z_posix_sysconf_SC_THREAD_SAFE_FUNCTIONS _POSIX_THREAD_SAFE_FUNCTIONS -#define __z_posix_sysconf_SC_THREAD_SPORADIC_SERVER _POSIX_THREAD_SPORADIC_SERVER -#define __z_posix_sysconf_SC_THREADS _POSIX_THREADS -#define __z_posix_sysconf_SC_TIMEOUTS _POSIX_TIMEOUTS -#define __z_posix_sysconf_SC_TIMERS _POSIX_TIMERS -#define __z_posix_sysconf_SC_TRACE _POSIX_TRACE -#define __z_posix_sysconf_SC_TRACE_EVENT_FILTER _POSIX_TRACE_EVENT_FILTER -#define __z_posix_sysconf_SC_TRACE_EVENT_NAME_MAX _POSIX_TRACE_EVENT_NAME_MAX -#define __z_posix_sysconf_SC_TRACE_INHERIT _POSIX_TRACE_INHERIT -#define __z_posix_sysconf_SC_TRACE_LOG _POSIX_TRACE_LOG +#define __z_posix_sysconf_SC_ADVISORY_INFO (-1L) +#define __z_posix_sysconf_SC_ASYNCHRONOUS_IO \ + COND_CODE_1(CONFIG_POSIX_ASYNCHRONOUS_IO, (_POSIX_ASYNCHRONOUS_IO), (-1L)) +#define __z_posix_sysconf_SC_BARRIERS COND_CODE_1(CONFIG_POSIX_BARRIERS, (_POSIX_BARRIERS), (-1L)) +#define __z_posix_sysconf_SC_CLOCK_SELECTION \ + COND_CODE_1(CONFIG_POSIX_CLOCK_SELECTION, (_POSIX_CLOCK_SELECTION), (-1L)) +#define __z_posix_sysconf_SC_CPUTIME \ + COND_CODE_1(CONFIG_POSIX_CPUTIME, (_POSIX_CPUTIME), (-1L)) +#define __z_posix_sysconf_SC_FSYNC \ + COND_CODE_1(CONFIG_POSIX_FSYNC, (_POSIX_FSYNC), (-1L)) +#define __z_posix_sysconf_SC_IPV6 COND_CODE_1(CONFIG_NET_IPV6, (_POSIX_IPV6), (-1L)) +#define __z_posix_sysconf_SC_JOB_CONTROL (-1L) +#define __z_posix_sysconf_SC_MAPPED_FILES \ + COND_CODE_1(CONFIG_POSIX_MAPPED_FILES, (_POSIX_MAPPED_FILES), (-1L)) +#define __z_posix_sysconf_SC_MEMLOCK \ + COND_CODE_1(CONFIG_POSIX_MEMLOCK, (_POSIX_MEMLOCK), (-1L)) +#define __z_posix_sysconf_SC_MEMLOCK_RANGE \ + COND_CODE_1(CONFIG_POSIX_MEMLOCK_RANGE, (_POSIX_MEMLOCK_RANGE), (-1L)) +#define __z_posix_sysconf_SC_MEMORY_PROTECTION \ + COND_CODE_1(CONFIG_POSIX_MEMORY_PROTECTION, (_POSIX_MEMORY_PROTECTION), (-1L)) +#define __z_posix_sysconf_SC_MESSAGE_PASSING \ + COND_CODE_1(CONFIG_POSIX_MESSAGE_PASSING, (_POSIX_MESSAGE_PASSING), (-1L)) +#define __z_posix_sysconf_SC_MONOTONIC_CLOCK \ + COND_CODE_1(CONFIG_POSIX_MONOTONIC_CLOCK, (_POSIX_MONOTONIC_CLOCK), (-1L)) +#define __z_posix_sysconf_SC_PRIORITIZED_IO (-1L) +#define __z_posix_sysconf_SC_PRIORITY_SCHEDULING \ + COND_CODE_1(CONFIG_POSIX_PRIORITY_SCHEDULING, (_POSIX_PRIORITY_SCHEDULING), (-1L)) +#define __z_posix_sysconf_SC_RAW_SOCKETS \ + COND_CODE_1(CONFIG_NET_SOCKETS_PACKET, (_POSIX_RAW_SOCKETS), (-1L)) +#define __z_posix_sysconf_SC_RE_DUP_MAX _POSIX_RE_DUP_MAX +#define __z_posix_sysconf_SC_READER_WRITER_LOCKS \ + COND_CODE_1(CONFIG_POSIX_READER_WRITER_LOCKS, (_POSIX_READER_WRITER_LOCKS), (-1L)) +#define __z_posix_sysconf_SC_REALTIME_SIGNALS (-1L) +#define __z_posix_sysconf_SC_REGEXP (-1L) +#define __z_posix_sysconf_SC_SAVED_IDS (-1L) +#define __z_posix_sysconf_SC_SEMAPHORES \ + COND_CODE_1(CONFIG_POSIX_SEMAPHORES, (_POSIX_SEMAPHORES), (-1L)) +#define __z_posix_sysconf_SC_SHARED_MEMORY_OBJECTS \ + COND_CODE_1(CONFIG_POSIX_SHARED_MEMORY_OBJECTS, (_POSIX_SHARED_MEMORY_OBJECTS), (-1L)) +#define __z_posix_sysconf_SC_SHELL (-1L) +#define __z_posix_sysconf_SC_SPAWN (-1L) +#define __z_posix_sysconf_SC_SPIN_LOCKS \ + COND_CODE_1(CONFIG_POSIX_SPIN_LOCKS, (_POSIX_SPIN_LOCKS), (-1L)) +#define __z_posix_sysconf_SC_SPORADIC_SERVER (-1L) +#define __z_posix_sysconf_SC_SS_REPL_MAX _POSIX_SS_REPL_MAX +#define __z_posix_sysconf_SC_SYNCHRONIZED_IO (-1L) +#define __z_posix_sysconf_SC_THREAD_ATTR_STACKADDR \ + COND_CODE_1(CONFIG_POSIX_THREAD_ATTR_STACKADDR, (_POSIX_THREAD_ATTR_STACKADDR), (-1)) +#define __z_posix_sysconf_SC_THREAD_ATTR_STACKSIZE \ + COND_CODE_1(CONFIG_POSIX_THREAD_ATTR_STACKSIZE, (_POSIX_THREAD_ATTR_STACKSIZE), (-1L)) +#define __z_posix_sysconf_SC_THREAD_CPUTIME (-1L) +#define __z_posix_sysconf_SC_THREAD_PRIO_INHERIT \ + COND_CODE_1(CONFIG_POSIX_THREAD_PRIO_INHERIT, (_POSIX_THREAD_PRIO_INHERIT), (-1L)) +#define __z_posix_sysconf_SC_THREAD_PRIO_PROTECT (-1L) +#define __z_posix_sysconf_SC_THREAD_PRIORITY_SCHEDULING \ + COND_CODE_1(CONFIG_POSIX_THREAD_PRIORITY_SCHEDULING, (_POSIX_THREAD_PRIORITY_SCHEDULING), \ + (-1L)) +#define __z_posix_sysconf_SC_THREAD_PROCESS_SHARED (-1L) +#define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_INHERIT (-1L) +#define __z_posix_sysconf_SC_THREAD_ROBUST_PRIO_PROTECT (-1L) +#define __z_posix_sysconf_SC_THREAD_SAFE_FUNCTIONS \ + COND_CODE_1(CONFIG_POSIX_THREAD_SAFE_FUNCTIONS, (_POSIX_THREAD_SAFE_FUNCTIONS), (-1L)) +#define __z_posix_sysconf_SC_THREAD_SPORADIC_SERVER (-1L) +#define __z_posix_sysconf_SC_THREADS \ + COND_CODE_1(CONFIG_POSIX_THREADS, (_POSIX_THREADS), (-1L)) +#define __z_posix_sysconf_SC_TIMEOUTS \ + COND_CODE_1(CONFIG_POSIX_TIMEOUTS, (_POSIX_TIMEOUTS), (-1L)) +#define __z_posix_sysconf_SC_TIMERS \ + COND_CODE_1(CONFIG_POSIX_TIMEOUTS, (_POSIX_TIMERS), (-1)) +#define __z_posix_sysconf_SC_TRACE (-1L) +#define __z_posix_sysconf_SC_TRACE_EVENT_FILTER (-1L) +#define __z_posix_sysconf_SC_TRACE_EVENT_NAME_MAX _POSIX_TRACE_NAME_MAX +#define __z_posix_sysconf_SC_TRACE_INHERIT (-1L) +#define __z_posix_sysconf_SC_TRACE_LOG (-1L) #define __z_posix_sysconf_SC_TRACE_NAME_MAX _POSIX_TRACE_NAME_MAX #define __z_posix_sysconf_SC_TRACE_SYS_MAX _POSIX_TRACE_SYS_MAX #define __z_posix_sysconf_SC_TRACE_USER_EVENT_MAX _POSIX_TRACE_USER_EVENT_MAX -#define __z_posix_sysconf_SC_TYPED_MEMORY_OBJECTS _POSIX_TYPED_MEMORY_OBJECTS +#define __z_posix_sysconf_SC_TYPED_MEMORY_OBJECTS (-1L) #define __z_posix_sysconf_SC_VERSION _POSIX_VERSION -#define __z_posix_sysconf_SC_V7_ILP32_OFF32 _POSIX_V7_ILP32_OFF32 -#define __z_posix_sysconf_SC_V7_ILP32_OFFBIG _POSIX_V7_ILP32_OFFBIG -#define __z_posix_sysconf_SC_V7_LP64_OFF64 _POSIX_V7_LP64_OFF64 -#define __z_posix_sysconf_SC_V7_LPBIG_OFFBIG _POSIX_V7_LPBIG_OFFBIG -#define __z_posix_sysconf_SC_V6_ILP32_OFF32 _POSIX_V6_ILP32_OFF32 -#define __z_posix_sysconf_SC_V6_ILP32_OFFBIG _POSIX_V6_ILP32_OFFBIG -#define __z_posix_sysconf_SC_V6_LP64_OFF64 _POSIX_V6_LP64_OFF64 -#define __z_posix_sysconf_SC_V6_LPBIG_OFFBIG _POSIX_V6_LPBIG_OFFBIG +#define __z_posix_sysconf_SC_V6_ILP32_OFF32 (-1L) +#define __z_posix_sysconf_SC_V6_ILP32_OFFBIG (-1L) +#define __z_posix_sysconf_SC_V6_LP64_OFF64 (-1L) +#define __z_posix_sysconf_SC_V6_LPBIG_OFFBIG (-1L) +#define __z_posix_sysconf_SC_V7_ILP32_OFF32 (-1L) +#define __z_posix_sysconf_SC_V7_ILP32_OFFBIG (-1L) +#define __z_posix_sysconf_SC_V7_LP64_OFF64 (-1L) +#define __z_posix_sysconf_SC_V7_LPBIG_OFFBIG (-1L) #define __z_posix_sysconf_SC_BC_BASE_MAX _POSIX2_BC_BASE_MAX #define __z_posix_sysconf_SC_BC_DIM_MAX _POSIX2_BC_DIM_MAX #define __z_posix_sysconf_SC_BC_SCALE_MAX _POSIX2_BC_SCALE_MAX #define __z_posix_sysconf_SC_BC_STRING_MAX _POSIX2_BC_STRING_MAX #define __z_posix_sysconf_SC_2_C_BIND _POSIX2_C_BIND #define __z_posix_sysconf_SC_2_C_DEV _POSIX2_C_DEV -#define __z_posix_sysconf_SC_2_CHAR_TERM _POSIX2_CHAR_TERM +#define __z_posix_sysconf_SC_2_CHAR_TERM (-1L) #define __z_posix_sysconf_SC_COLL_WEIGHTS_MAX _POSIX2_COLL_WEIGHTS_MAX -#define __z_posix_sysconf_SC_DELAYTIMER_MAX _POSIX2_DELAYTIMER_MAX +#define __z_posix_sysconf_SC_DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX #define __z_posix_sysconf_SC_EXPR_NEST_MAX _POSIX2_EXPR_NEST_MAX -#define __z_posix_sysconf_SC_2_FORT_DEV _POSIX2_FORT_DEV -#define __z_posix_sysconf_SC_2_FORT_RUN _POSIX2_FORT_RUN -#define __z_posix_sysconf_SC_LINE_MAX _POSIX2_LINE_MAX -#define __z_posix_sysconf_SC_2_LOCALEDEF _POSIX2_LOCALEDEF -#define __z_posix_sysconf_SC_2_PBS _POSIX2_PBS -#define __z_posix_sysconf_SC_2_PBS_ACCOUNTING _POSIX2_PBS_ACCOUNTING -#define __z_posix_sysconf_SC_2_PBS_CHECKPOINT _POSIX2_PBS_CHECKPOINT -#define __z_posix_sysconf_SC_2_PBS_LOCATE _POSIX2_PBS_LOCATE -#define __z_posix_sysconf_SC_2_PBS_MESSAGE _POSIX2_PBS_MESSAGE -#define __z_posix_sysconf_SC_2_PBS_TRACK _POSIX2_PBS_TRACK -#define __z_posix_sysconf_SC_2_SW_DEV _POSIX2_SW_DEV -#define __z_posix_sysconf_SC_2_UPE _POSIX2_UPE +#define __z_posix_sysconf_SC_2_FORT_DEV (-1L) +#define __z_posix_sysconf_SC_2_FORT_RUN (-1L) +#define __z_posix_sysconf_SC_LINE_MAX (-1L) +#define __z_posix_sysconf_SC_2_LOCALEDEF (-1L) +#define __z_posix_sysconf_SC_2_PBS (-1L) +#define __z_posix_sysconf_SC_2_PBS_ACCOUNTING (-1L) +#define __z_posix_sysconf_SC_2_PBS_CHECKPOINT (-1L) +#define __z_posix_sysconf_SC_2_PBS_LOCATE (-1L) +#define __z_posix_sysconf_SC_2_PBS_MESSAGE (-1L) +#define __z_posix_sysconf_SC_2_PBS_TRACK (-1L) +#define __z_posix_sysconf_SC_2_SW_DEV (-1L) +#define __z_posix_sysconf_SC_2_UPE (-1L) #define __z_posix_sysconf_SC_2_VERSION _POSIX2_VERSION -#define __z_posix_sysconf_SC_XOPEN_CRYPT _XOPEN_CRYPT -#define __z_posix_sysconf_SC_XOPEN_ENH_I18N _XOPEN_ENH_I18N -#define __z_posix_sysconf_SC_XOPEN_REALTIME _XOPEN_REALTIME -#define __z_posix_sysconf_SC_XOPEN_REALTIME_THREADS _XOPEN_REALTIME_THREADS -#define __z_posix_sysconf_SC_XOPEN_SHM _XOPEN_SHM -#define __z_posix_sysconf_SC_XOPEN_STREAMS _XOPEN_STREAMS -#define __z_posix_sysconf_SC_XOPEN_UNIX _XOPEN_UNIX -#define __z_posix_sysconf_SC_XOPEN_UUCP _XOPEN_UUCP +#define __z_posix_sysconf_SC_XOPEN_CRYPT (-1L) +#define __z_posix_sysconf_SC_XOPEN_ENH_I18N (-1L) +#define __z_posix_sysconf_SC_XOPEN_REALTIME (-1L) +#define __z_posix_sysconf_SC_XOPEN_REALTIME_THREADS (-1L) +#define __z_posix_sysconf_SC_XOPEN_SHM (-1L) +#define __z_posix_sysconf_SC_XOPEN_STREAMS \ + COND_CODE_1(CONFIG_XOPEN_STREAMS, (_XOPEN_STREAMS), (-1)) +#define __z_posix_sysconf_SC_XOPEN_UNIX (-1L) +#define __z_posix_sysconf_SC_XOPEN_UUCP (-1L) #define __z_posix_sysconf_SC_XOPEN_VERSION _XOPEN_VERSION #define __z_posix_sysconf_SC_CLK_TCK (100L) #define __z_posix_sysconf_SC_GETGR_R_SIZE_MAX (0L) @@ -250,7 +276,7 @@ enum { #define __z_posix_sysconf_SC_NGROUPS_MAX _POSIX_NGROUPS_MAX #define __z_posix_sysconf_SC_MQ_OPEN_MAX MQ_OPEN_MAX #define __z_posix_sysconf_SC_MQ_PRIO_MAX MQ_PRIO_MAX -#define __z_posix_sysconf_SC_OPEN_MAX CONFIG_POSIX_MAX_FDS +#define __z_posix_sysconf_SC_OPEN_MAX CONFIG_ZVFS_OPEN_MAX #define __z_posix_sysconf_SC_PAGE_SIZE PAGE_SIZE #define __z_posix_sysconf_SC_PAGESIZE PAGESIZE #define __z_posix_sysconf_SC_THREAD_DESTRUCTOR_ITERATIONS PTHREAD_DESTRUCTOR_ITERATIONS @@ -267,11 +293,10 @@ enum { #define __z_posix_sysconf_SC_TTY_NAME_MAX TTY_NAME_MAX #define __z_posix_sysconf_SC_TZNAME_MAX TZNAME_MAX +#ifdef CONFIG_POSIX_SYSCONF_IMPL_MACRO #define sysconf(x) (long)CONCAT(__z_posix_sysconf, x) #endif -#endif - #ifdef __cplusplus } #endif diff --git a/include/zephyr/posix/sys/utsname.h b/include/zephyr/posix/sys/utsname.h index 32046f431d89d..542215076a400 100644 --- a/include/zephyr/posix/sys/utsname.h +++ b/include/zephyr/posix/sys/utsname.h @@ -6,15 +6,23 @@ #ifndef ZEPHYR_INCLUDE_POSIX_SYS_UTSNAME_H_ #define ZEPHYR_INCLUDE_POSIX_SYS_UTSNAME_H_ +#include + #ifdef __cplusplus extern "C" { #endif +/* These are for compatibility / practicality */ +#define _UTSNAME_NODENAME_LENGTH \ + COND_CODE_1(CONFIG_POSIX_SINGLE_PROCESS, (CONFIG_POSIX_UNAME_VERSION_LEN), (0)) +#define _UTSNAME_VERSION_LENGTH \ + COND_CODE_1(CONFIG_POSIX_SINGLE_PROCESS, (CONFIG_POSIX_UNAME_VERSION_LEN), (0)) + struct utsname { char sysname[sizeof("Zephyr")]; - char nodename[CONFIG_POSIX_UNAME_NODENAME_LEN + 1]; + char nodename[_UTSNAME_NODENAME_LENGTH + 1]; char release[sizeof("99.99.99-rc1")]; - char version[CONFIG_POSIX_UNAME_VERSION_LEN + 1]; + char version[_UTSNAME_VERSION_LENGTH + 1]; char machine[sizeof(CONFIG_ARCH)]; }; diff --git a/include/zephyr/posix/time.h b/include/zephyr/posix/time.h index 8038e783030f0..f0ca07284bc84 100644 --- a/include/zephyr/posix/time.h +++ b/include/zephyr/posix/time.h @@ -73,6 +73,10 @@ extern "C" { #define CLOCK_PROCESS_CPUTIME_ID 2 #endif +#ifndef CLOCK_THREAD_CPUTIME_ID +#define CLOCK_THREAD_CPUTIME_ID 3 +#endif + #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC 4 #endif @@ -83,7 +87,7 @@ extern "C" { static inline int32_t _ts_to_ms(const struct timespec *to) { - return (to->tv_sec * MSEC_PER_SEC) + (to->tv_nsec / NSEC_PER_MSEC); + return (int32_t)(to->tv_sec * MSEC_PER_SEC) + (int32_t)(to->tv_nsec / NSEC_PER_MSEC); } int clock_gettime(clockid_t clock_id, struct timespec *ts); diff --git a/include/zephyr/posix/unistd.h b/include/zephyr/posix/unistd.h index f829ebac23513..194b2bffe6f50 100644 --- a/include/zephyr/posix/unistd.h +++ b/include/zephyr/posix/unistd.h @@ -16,221 +16,16 @@ #include #include #endif -#ifdef CONFIG_POSIX_SYSCONF -#include -#endif #include #include #include +#include "posix_features.h" + #ifdef __cplusplus extern "C" { #endif -/* Version test macros */ -#define _POSIX_VERSION 200809L -#define _POSIX2_VERSION (-1L) -#define _XOPEN_VERSION (-1L) - -/* Internal helper macro to set constant if required Kconfig symbol is enabled */ -#define Z_SC_VAL_IFDEF(_def, _val) COND_CODE_1(_def, (_val), (-1L)) - -/* Constants for Options and Option Groups */ -#define _POSIX_ADVISORY_INFO (-1L) -#define _POSIX_ASYNCHRONOUS_IO Z_SC_VAL_IFDEF(CONFIG_POSIX_ASYNCHRONOUS_IO, _POSIX_VERSION) -#define _POSIX_BARRIERS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_BARRIER, _POSIX_VERSION) -#define _POSIX_CHOWN_RESTRICTED (0) -#define _POSIX_CLOCK_SELECTION Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) -#define _POSIX_CPUTIME (-1L) -#define _POSIX_FSYNC Z_SC_VAL_IFDEF(CONFIG_POSIX_FSYNC, _POSIX_VERSION) -#define _POSIX_IPV6 Z_SC_VAL_IFDEF(CONFIG_NET_IPV6, _POSIX_VERSION) -#define _POSIX_JOB_CONTROL (-1L) -#define _POSIX_MAPPED_FILES (-1L) -#define _POSIX_MEMLOCK (-1L) -#define _POSIX_MEMLOCK_RANGE (-1L) -#define _POSIX_MEMORY_PROTECTION (-1L) -#define _POSIX_MESSAGE_PASSING Z_SC_VAL_IFDEF(CONFIG_POSIX_MQUEUE, _POSIX_VERSION) -#define _POSIX_MONOTONIC_CLOCK Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) -#define _POSIX_NO_TRUNC (0) -#define _POSIX_PRIORITIZED_IO (-1L) -#define _POSIX_PRIORITY_SCHEDULING Z_SC_VAL_IFDEF(CONFIG_POSIX_PRIORITY_SCHEDULING, _POSIX_VERSION) -#define _POSIX_RAW_SOCKETS Z_SC_VAL_IFDEF(CONFIG_NET_SOCKETS_PACKET, _POSIX_VERSION) -#define _POSIX_READER_WRITER_LOCKS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_REALTIME_SIGNALS (-1L) -#define _POSIX_REGEXP (-1L) -#define _POSIX_SAVED_IDS (-1L) -#define _POSIX_SEMAPHORES Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_SHARED_MEMORY_OBJECTS (-1L) -#define _POSIX_SHELL (-1L) -#define _POSIX_SPAWN (-1L) -#define _POSIX_SPIN_LOCKS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_SPINLOCK, _POSIX_VERSION) -#define _POSIX_SPORADIC_SERVER (-1L) -#define _POSIX_SYNCHRONIZED_IO (-1L) -#define _POSIX_THREAD_ATTR_STACKADDR Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_ATTR_STACKSIZE Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_CPUTIME (-1L) -#define _POSIX_THREAD_PRIO_INHERIT _POSIX_VERSION -#define _POSIX_THREAD_PRIO_PROTECT (-1L) -#define _POSIX_THREAD_PRIORITY_SCHEDULING Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_PROCESS_SHARED (-1L) -#define _POSIX_THREAD_ROBUST_PRIO_INHERIT (-1L) -#define _POSIX_THREAD_ROBUST_PRIO_PROTECT (-1L) -#define _POSIX_THREAD_SAFE_FUNCTIONS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#define _POSIX_THREAD_SPORADIC_SERVER (-1L) - -#ifndef _POSIX_THREADS -#define _POSIX_THREADS Z_SC_VAL_IFDEF(CONFIG_PTHREAD_IPC, _POSIX_VERSION) -#endif - -#define _POSIX_TIMEOUTS Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) -#define _POSIX_TIMERS Z_SC_VAL_IFDEF(CONFIG_POSIX_CLOCK, _POSIX_VERSION) -#define _POSIX_TRACE (-1L) -#define _POSIX_TRACE_EVENT_FILTER (-1L) -#define _POSIX_TRACE_INHERIT (-1L) -#define _POSIX_TRACE_LOG (-1L) -#define _POSIX_TYPED_MEMORY_OBJECTS (-1L) -#define _POSIX_V6_ILP32_OFF32 (-1L) -#define _POSIX_V6_ILP32_OFFBIG (-1L) -#define _POSIX_V6_LP64_OFF64 (-1L) -#define _POSIX_V6_LPBIG_OFFBIG (-1L) -#define _POSIX_V7_ILP32_OFF32 (-1L) -#define _POSIX_V7_ILP32_OFFBIG (-1L) -#define _POSIX_V7_LP64_OFF64 (-1L) -#define _POSIX_V7_LPBIG_OFFBIG (-1L) -#define _POSIX2_C_BIND _POSIX_VERSION -#define _POSIX2_C_DEV (-1L) -#define _POSIX2_CHAR_TERM (-1L) -#define _POSIX2_DELAYTIMER_MAX (-1L) -#define _POSIX2_FORT_DEV (-1L) -#define _POSIX2_FORT_RUN (-1L) -#define _POSIX2_LOCALEDEF (-1L) -#define _POSIX2_PBS (-1L) -#define _POSIX2_PBS_ACCOUNTING (-1L) -#define _POSIX2_PBS_CHECKPOINT (-1L) -#define _POSIX2_PBS_LOCATE (-1L) -#define _POSIX2_PBS_MESSAGE (-1L) -#define _POSIX2_PBS_TRACK (-1L) -#define _POSIX2_SW_DEV (-1L) -#define _POSIX2_UPE (-1L) -#define _XOPEN_CRYPT (-1L) -#define _XOPEN_ENH_I18N (-1L) -#define _XOPEN_REALTIME (-1L) -#define _XOPEN_REALTIME_THREADS (-1L) -#define _XOPEN_SHM (-1L) -#define _XOPEN_STREAMS (-1L) -#define _XOPEN_UNIX (-1L) -#define _XOPEN_UUCP (-1L) - -/* Maximum values */ -#define _POSIX_CLOCKRES_MIN (20000000L) - -/* Minimum values */ -#define _POSIX_AIO_LISTIO_MAX (2) -#define _POSIX_AIO_MAX (1) -#define _POSIX_ARG_MAX (4096) -#define _POSIX_CHILD_MAX (25) -#define _POSIX_DELAYTIMER_MAX (32) -#define _POSIX_HOST_NAME_MAX (255) -#define _POSIX_LINK_MAX (8) -#define _POSIX_LOGIN_NAME_MAX (9) -#define _POSIX_MAX_CANON (255) -#define _POSIX_MAX_INPUT (255) -#define _POSIX_MQ_OPEN_MAX Z_SC_VAL_IFDEF(CONFIG_POSIX_MQUEUE, \ - CONFIG_MSG_COUNT_MAX) -#define _POSIX_MQ_PRIO_MAX (32) -#define _POSIX_NAME_MAX (14) -#define _POSIX_NGROUPS_MAX (8) -#define _POSIX_OPEN_MAX CONFIG_POSIX_MAX_FDS -#define _POSIX_PATH_MAX (256) -#define _POSIX_PIPE_BUF (512) -#define _POSIX_RE_DUP_MAX (255) -#define _POSIX_RTSIG_MAX CONFIG_POSIX_RTSIG_MAX -#define _POSIX_SEM_NSEMS_MAX CONFIG_SEM_NAMELEN_MAX -#define _POSIX_SEM_VALUE_MAX CONFIG_SEM_VALUE_MAX -#define _POSIX_SIGQUEUE_MAX (32) -#define _POSIX_SSIZE_MAX (32767) -#define _POSIX_SS_REPL_MAX (4) -#define _POSIX_STREAM_MAX (8) -#define _POSIX_SYMLINK_MAX (255) -#define _POSIX_SYMLOOP_MAX (8) -#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS (4) -#define _POSIX_THREAD_KEYS_MAX (128) -#define _POSIX_THREAD_THREADS_MAX (64) -#define _POSIX_TIMER_MAX (32) -#define _POSIX_TRACE_EVENT_NAME_MAX (30) -#define _POSIX_TRACE_NAME_MAX (8) -#define _POSIX_TRACE_SYS_MAX (8) -#define _POSIX_TRACE_USER_EVENT_MAX (32) -#define _POSIX_TTY_NAME_MAX (9) -#define _POSIX_TZNAME_MAX (6) -#define _POSIX2_BC_BASE_MAX (99) -#define _POSIX2_BC_DIM_MAX (2048) -#define _POSIX2_BC_SCALE_MAX (99) -#define _POSIX2_BC_STRING_MAX (1000) -#define _POSIX2_CHARCLASS_NAME_MAX (14) -#define _POSIX2_COLL_WEIGHTS_MAX (2) -#define _POSIX2_EXPR_NEST_MAX (32) -#define _POSIX2_LINE_MAX (2048) -#define _XOPEN_IOV_MAX (16) -#define _XOPEN_NAME_MAX (255) -#define _XOPEN_PATH_MAX (1024) - -/* Other invariant values */ -#define NL_LANGMAX (14) -#define NL_MSGMAX (32767) -#define NL_SETMAX (255) -#define NL_TEXTMAX (_POSIX2_LINE_MAX) -#define NZERO (20) - -/* Runtime invariant values */ -#define AIO_LISTIO_MAX _POSIX_AIO_LISTIO_MAX -#define AIO_MAX _POSIX_AIO_MAX -#define AIO_PRIO_DELTA_MAX (0) -#define DELAYTIMER_MAX _POSIX_DELAYTIMER_MAX -#define HOST_NAME_MAX COND_CODE_1(CONFIG_NETWORKING, \ - (NET_HOSTNAME_MAX_LEN), \ - (_POSIX_HOST_NAME_MAX)) -#define LOGIN_NAME_MAX _POSIX_LOGIN_NAME_MAX -#define MQ_OPEN_MAX _POSIX_MQ_OPEN_MAX -#define MQ_PRIO_MAX _POSIX_MQ_PRIO_MAX - -#ifndef ATEXIT_MAX -#define ATEXIT_MAX 8 -#endif - -#ifndef PAGE_SIZE -#define PAGE_SIZE BIT(CONFIG_POSIX_PAGE_SIZE_BITS) -#endif - -#ifndef PAGESIZE -#define PAGESIZE PAGE_SIZE -#endif - -#define PTHREAD_DESTRUCTOR_ITERATIONS _POSIX_THREAD_DESTRUCTOR_ITERATIONS -#define PTHREAD_KEYS_MAX COND_CODE_1(CONFIG_PTHREAD_IPC, \ - (CONFIG_MAX_PTHREAD_KEY_COUNT), \ - (_POSIX_THREAD_KEYS_MAX)) -#define PTHREAD_THREADS_MAX COND_CODE_1(CONFIG_PTHREAD_IPC, \ - (CONFIG_MAX_PTHREAD_COUNT), \ - (0)) -#define SEM_NSEMS_MAX _POSIX_SEM_NSEMS_MAX -#define SEM_VALUE_MAX CONFIG_SEM_VALUE_MAX -#define SIGQUEUE_MAX _POSIX_SIGQUEUE_MAX -#define STREAM_MAX _POSIX_STREAM_MAX -#define SYMLOOP_MAX _POSIX_SYMLOOP_MAX -#define TIMER_MAX Z_SC_VAL_IFDEF(CONFIG_TIMER, CONFIG_MAX_TIMER_COUNT) -#define TTY_NAME_MAX _POSIX_TTY_NAME_MAX -#define TZNAME_MAX _POSIX_TZNAME_MAX - -/* Pathname variable values */ -#define FILESIZEBITS (32) -#define POSIX_ALLOC_SIZE_MIN (256) -#define POSIX_REC_INCR_XFER_SIZE (1024) -#define POSIX_REC_MAX_XFER_SIZE (32767) -#define POSIX_REC_MIN_XFER_SIZE (1) -#define POSIX_REC_XFER_ALIGN (4) -#define SYMLINK_MAX _POSIX_SYMLINK_MAX - #ifdef CONFIG_POSIX_API /* File related operations */ int close(int file); @@ -257,7 +52,7 @@ static inline int gethostname(char *buf, size_t len) #endif /* CONFIG_POSIX_API */ -#ifdef CONFIG_GETOPT +#ifdef CONFIG_POSIX_C_LIB_EXT int getopt(int argc, char *const argv[], const char *optstring); extern char *optarg; extern int opterr, optind, optopt; @@ -267,13 +62,16 @@ int getentropy(void *buffer, size_t length); pid_t getpid(void); unsigned sleep(unsigned int seconds); int usleep(useconds_t useconds); -#ifdef CONFIG_POSIX_SYSCONF_IMPL_FULL -long sysconf(int opt); -#endif #if _POSIX_C_SOURCE >= 2 size_t confstr(int name, char *buf, size_t len); #endif +#ifdef CONFIG_POSIX_SYSCONF_IMPL_MACRO +#define sysconf(x) (long)CONCAT(__z_posix_sysconf, x) +#else +long sysconf(int opt); +#endif /* CONFIG_POSIX_SYSCONF_IMPL_FULL */ + #ifdef __cplusplus } #endif diff --git a/include/zephyr/random/random.h b/include/zephyr/random/random.h index bb7f502a3d1e5..293b8d00a8671 100644 --- a/include/zephyr/random/random.h +++ b/include/zephyr/random/random.h @@ -147,5 +147,5 @@ static inline uint64_t sys_rand64_get(void) * @} */ -#include +#include #endif /* ZEPHYR_INCLUDE_RANDOM_RANDOM_H_ */ diff --git a/include/zephyr/rtio/rtio.h b/include/zephyr/rtio/rtio.h index f5bb6fcd48402..a53e939b0accf 100644 --- a/include/zephyr/rtio/rtio.h +++ b/include/zephyr/rtio/rtio.h @@ -31,12 +31,12 @@ #include #include #include -#include #include #include #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -292,7 +292,7 @@ BUILD_ASSERT(sizeof(struct rtio_sqe) <= 64); * @brief A completion queue event */ struct rtio_cqe { - struct rtio_mpsc_node q; + struct mpsc_node q; int32_t result; /**< Result from operation */ void *userdata; /**< Associated userdata with operation */ @@ -300,14 +300,14 @@ struct rtio_cqe { }; struct rtio_sqe_pool { - struct rtio_mpsc free_q; + struct mpsc free_q; const uint16_t pool_size; uint16_t pool_free; struct rtio_iodev_sqe *pool; }; struct rtio_cqe_pool { - struct rtio_mpsc free_q; + struct mpsc free_q; const uint16_t pool_size; uint16_t pool_free; struct rtio_cqe *pool; @@ -362,10 +362,10 @@ struct rtio { #endif /* Submission queue */ - struct rtio_mpsc sq; + struct mpsc sq; /* Completion queue */ - struct rtio_mpsc cq; + struct mpsc cq; }; /** The memory partition associated with all RTIO context information */ @@ -422,7 +422,7 @@ static inline uint16_t __rtio_compute_mempool_block_index(const struct rtio *r, */ struct rtio_iodev_sqe { struct rtio_sqe sqe; - struct rtio_mpsc_node q; + struct mpsc_node q; struct rtio_iodev_sqe *next; struct rtio *r; }; @@ -449,9 +449,6 @@ struct rtio_iodev { /* Function pointer table */ const struct rtio_iodev_api *api; - /* Queue of RTIO contexts with requests */ - struct rtio_mpsc iodev_sq; - /* Data associated with this iodev */ void *data; }; @@ -625,7 +622,7 @@ static inline void rtio_sqe_prep_transceive(struct rtio_sqe *sqe, static inline struct rtio_iodev_sqe *rtio_sqe_pool_alloc(struct rtio_sqe_pool *pool) { - struct rtio_mpsc_node *node = rtio_mpsc_pop(&pool->free_q); + struct mpsc_node *node = mpsc_pop(&pool->free_q); if (node == NULL) { return NULL; @@ -640,14 +637,14 @@ static inline struct rtio_iodev_sqe *rtio_sqe_pool_alloc(struct rtio_sqe_pool *p static inline void rtio_sqe_pool_free(struct rtio_sqe_pool *pool, struct rtio_iodev_sqe *iodev_sqe) { - rtio_mpsc_push(&pool->free_q, &iodev_sqe->q); + mpsc_push(&pool->free_q, &iodev_sqe->q); pool->pool_free++; } static inline struct rtio_cqe *rtio_cqe_pool_alloc(struct rtio_cqe_pool *pool) { - struct rtio_mpsc_node *node = rtio_mpsc_pop(&pool->free_q); + struct mpsc_node *node = mpsc_pop(&pool->free_q); if (node == NULL) { return NULL; @@ -664,7 +661,7 @@ static inline struct rtio_cqe *rtio_cqe_pool_alloc(struct rtio_cqe_pool *pool) static inline void rtio_cqe_pool_free(struct rtio_cqe_pool *pool, struct rtio_cqe *cqe) { - rtio_mpsc_push(&pool->free_q, &cqe->q); + mpsc_push(&pool->free_q, &cqe->q); pool->pool_free++; } @@ -732,14 +729,13 @@ static inline void rtio_block_pool_free(struct rtio *r, void *buf, uint32_t buf_ #define RTIO_IODEV_DEFINE(name, iodev_api, iodev_data) \ STRUCT_SECTION_ITERABLE(rtio_iodev, name) = { \ .api = (iodev_api), \ - .iodev_sq = RTIO_MPSC_INIT((name.iodev_sq)), \ .data = (iodev_data), \ } #define Z_RTIO_SQE_POOL_DEFINE(name, sz) \ static struct rtio_iodev_sqe CONCAT(_sqe_pool_, name)[sz]; \ STRUCT_SECTION_ITERABLE(rtio_sqe_pool, name) = { \ - .free_q = RTIO_MPSC_INIT((name.free_q)), \ + .free_q = MPSC_INIT((name.free_q)), \ .pool_size = sz, \ .pool_free = sz, \ .pool = CONCAT(_sqe_pool_, name), \ @@ -749,7 +745,7 @@ static inline void rtio_block_pool_free(struct rtio *r, void *buf, uint32_t buf_ #define Z_RTIO_CQE_POOL_DEFINE(name, sz) \ static struct rtio_cqe CONCAT(_cqe_pool_, name)[sz]; \ STRUCT_SECTION_ITERABLE(rtio_cqe_pool, name) = { \ - .free_q = RTIO_MPSC_INIT((name.free_q)), \ + .free_q = MPSC_INIT((name.free_q)), \ .pool_size = sz, \ .pool_free = sz, \ .pool = CONCAT(_cqe_pool_, name), \ @@ -797,8 +793,8 @@ static inline void rtio_block_pool_free(struct rtio *r, void *buf, uint32_t buf_ .sqe_pool = _sqe_pool, \ .cqe_pool = _cqe_pool, \ IF_ENABLED(CONFIG_RTIO_SYS_MEM_BLOCKS, (.block_pool = _block_pool,)) \ - .sq = RTIO_MPSC_INIT((name.sq)), \ - .cq = RTIO_MPSC_INIT((name.cq)), \ + .sq = MPSC_INIT((name.sq)), \ + .cq = MPSC_INIT((name.cq)), \ } /** @@ -910,7 +906,7 @@ static inline struct rtio_sqe *rtio_sqe_acquire(struct rtio *r) return NULL; } - rtio_mpsc_push(&r->sq, &iodev_sqe->q); + mpsc_push(&r->sq, &iodev_sqe->q); return &iodev_sqe->sqe; } @@ -923,12 +919,12 @@ static inline struct rtio_sqe *rtio_sqe_acquire(struct rtio *r) static inline void rtio_sqe_drop_all(struct rtio *r) { struct rtio_iodev_sqe *iodev_sqe; - struct rtio_mpsc_node *node = rtio_mpsc_pop(&r->sq); + struct mpsc_node *node = mpsc_pop(&r->sq); while (node != NULL) { iodev_sqe = CONTAINER_OF(node, struct rtio_iodev_sqe, q); rtio_sqe_pool_free(r->sqe_pool, iodev_sqe); - node = rtio_mpsc_pop(&r->sq); + node = mpsc_pop(&r->sq); } } @@ -953,7 +949,7 @@ static inline struct rtio_cqe *rtio_cqe_acquire(struct rtio *r) */ static inline void rtio_cqe_produce(struct rtio *r, struct rtio_cqe *cqe) { - rtio_mpsc_push(&r->cq, &cqe->q); + mpsc_push(&r->cq, &cqe->q); } /** @@ -969,7 +965,7 @@ static inline void rtio_cqe_produce(struct rtio *r, struct rtio_cqe *cqe) */ static inline struct rtio_cqe *rtio_cqe_consume(struct rtio *r) { - struct rtio_mpsc_node *node; + struct mpsc_node *node; struct rtio_cqe *cqe = NULL; #ifdef CONFIG_RTIO_CONSUME_SEM @@ -978,7 +974,7 @@ static inline struct rtio_cqe *rtio_cqe_consume(struct rtio *r) } #endif - node = rtio_mpsc_pop(&r->cq); + node = mpsc_pop(&r->cq); if (node == NULL) { return NULL; } @@ -999,16 +995,16 @@ static inline struct rtio_cqe *rtio_cqe_consume(struct rtio *r) */ static inline struct rtio_cqe *rtio_cqe_consume_block(struct rtio *r) { - struct rtio_mpsc_node *node; + struct mpsc_node *node; struct rtio_cqe *cqe; #ifdef CONFIG_RTIO_CONSUME_SEM k_sem_take(r->consume_sem, K_FOREVER); #endif - node = rtio_mpsc_pop(&r->cq); + node = mpsc_pop(&r->cq); while (node == NULL) { Z_SPIN_DELAY(1); - node = rtio_mpsc_pop(&r->cq); + node = mpsc_pop(&r->cq); } cqe = CONTAINER_OF(node, struct rtio_cqe, q); @@ -1128,24 +1124,6 @@ static inline void rtio_iodev_sqe_err(struct rtio_iodev_sqe *iodev_sqe, int resu rtio_executor_err(iodev_sqe, result); } -/** - * @brief Cancel all requests that are pending for the iodev - * - * @param iodev IODev to cancel all requests for - */ -static inline void rtio_iodev_cancel_all(struct rtio_iodev *iodev) -{ - /* Clear pending requests as -ENODATA */ - struct rtio_mpsc_node *node = rtio_mpsc_pop(&iodev->iodev_sq); - - while (node != NULL) { - struct rtio_iodev_sqe *iodev_sqe = CONTAINER_OF(node, struct rtio_iodev_sqe, q); - - rtio_iodev_sqe_err(iodev_sqe, -ECANCELED); - node = rtio_mpsc_pop(&iodev->iodev_sq); - } -} - /** * Submit a completion queue event with a given result and userdata * @@ -1485,6 +1463,6 @@ static inline int z_impl_rtio_submit(struct rtio *r, uint32_t wait_count) } #endif -#include +#include #endif /* ZEPHYR_INCLUDE_RTIO_RTIO_H_ */ diff --git a/include/zephyr/rtio/rtio_mpsc.h b/include/zephyr/rtio/rtio_mpsc.h deleted file mode 100644 index 9551d1c5cc412..0000000000000 --- a/include/zephyr/rtio/rtio_mpsc.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 2010-2011 Dmitry Vyukov - * Copyright (c) 2022 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_RTIO_MPSC_H_ -#define ZEPHYR_RTIO_MPSC_H_ - -#include -#include -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief RTIO Multiple Producer Single Consumer (MPSC) Queue API - * @defgroup rtio_mpsc RTIO MPSC API - * @ingroup rtio - * @{ - */ - -/* - * On single core systems atomics are unnecessary - * and cause a lot of unnecessary cache invalidation - * - * Using volatile to at least ensure memory is read/written - * by the compiler generated op codes is enough. - * - * On SMP atomics *must* be used to ensure the pointers - * are updated in the correct order and the values are - * updated core caches correctly. - */ -#if defined(CONFIG_SMP) - -typedef atomic_ptr_t mpsc_ptr_t; - -#define mpsc_ptr_get(ptr) atomic_ptr_get(&(ptr)) -#define mpsc_ptr_set(ptr, val) atomic_ptr_set(&(ptr), val) -#define mpsc_ptr_set_get(ptr, val) atomic_ptr_set(&(ptr), val) - -#else - -typedef struct rtio_mpsc_node *mpsc_ptr_t; - -#define mpsc_ptr_get(ptr) ptr -#define mpsc_ptr_set(ptr, val) ptr = val -#define mpsc_ptr_set_get(ptr, val) \ - ({ \ - mpsc_ptr_t tmp = ptr; \ - ptr = val; \ - tmp; \ - }) - -#endif - -/** - * @file rtio_mpsc.h - * - * @brief A wait-free intrusive multi producer single consumer (MPSC) queue using - * a singly linked list. Ordering is First-In-First-Out. - * - * Based on the well known and widely used wait-free MPSC queue described by - * Dmitry Vyukov with some slight changes to account for needs of an - * RTOS on a variety of archs. Both consumer and producer are wait free. No CAS - * loop or lock is needed. - * - * An MPSC queue is safe to produce or consume in an ISR with O(1) push/pop. - * - * @warning MPSC is *not* safe to consume in multiple execution contexts. - */ - -/** - * @brief Queue member - */ -struct rtio_mpsc_node { - mpsc_ptr_t next; -}; - -/** - * @brief MPSC Queue - */ -struct rtio_mpsc { - mpsc_ptr_t head; - struct rtio_mpsc_node *tail; - struct rtio_mpsc_node stub; -}; - -/** - * @brief Static initializer for a mpsc queue - * - * Since the queue is - * - * @param symbol name of the queue - */ -#define RTIO_MPSC_INIT(symbol) \ - { \ - .head = (struct rtio_mpsc_node *)&symbol.stub, \ - .tail = (struct rtio_mpsc_node *)&symbol.stub, \ - .stub = { \ - .next = NULL, \ - }, \ - } - -/** - * @brief Initialize queue - * - * @param q Queue to initialize or reset - */ -static inline void rtio_mpsc_init(struct rtio_mpsc *q) -{ - mpsc_ptr_set(q->head, &q->stub); - q->tail = &q->stub; - mpsc_ptr_set(q->stub.next, NULL); -} - -/** - * @brief Push a node - * - * @param q Queue to push the node to - * @param n Node to push into the queue - */ -static ALWAYS_INLINE void rtio_mpsc_push(struct rtio_mpsc *q, struct rtio_mpsc_node *n) -{ - struct rtio_mpsc_node *prev; - int key; - - mpsc_ptr_set(n->next, NULL); - - key = arch_irq_lock(); - prev = (struct rtio_mpsc_node *)mpsc_ptr_set_get(q->head, n); - mpsc_ptr_set(prev->next, n); - arch_irq_unlock(key); -} - -/** - * @brief Pop a node off of the list - * - * @retval NULL When no node is available - * @retval node When node is available - */ -static inline struct rtio_mpsc_node *rtio_mpsc_pop(struct rtio_mpsc *q) -{ - struct rtio_mpsc_node *head; - struct rtio_mpsc_node *tail = q->tail; - struct rtio_mpsc_node *next = (struct rtio_mpsc_node *)mpsc_ptr_get(tail->next); - - /* Skip over the stub/sentinel */ - if (tail == &q->stub) { - if (next == NULL) { - return NULL; - } - - q->tail = next; - tail = next; - next = (struct rtio_mpsc_node *)mpsc_ptr_get(next->next); - } - - /* If next is non-NULL then a valid node is found, return it */ - if (next != NULL) { - q->tail = next; - return tail; - } - - head = (struct rtio_mpsc_node *)mpsc_ptr_get(q->head); - - /* If next is NULL, and the tail != HEAD then the queue has pending - * updates that can't yet be accessed. - */ - if (tail != head) { - return NULL; - } - - rtio_mpsc_push(q, &q->stub); - - next = (struct rtio_mpsc_node *)mpsc_ptr_get(tail->next); - - if (next != NULL) { - q->tail = next; - return tail; - } - - return NULL; -} - -/** - * @} - */ - -#ifdef __cplusplus -} -#endif - -#endif /* ZEPHYR_RTIO_MPSC_H_ */ diff --git a/include/zephyr/rtio/rtio_spsc.h b/include/zephyr/rtio/rtio_spsc.h deleted file mode 100644 index 07872e7d4b020..0000000000000 --- a/include/zephyr/rtio/rtio_spsc.h +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (c) 2022 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - - -#ifndef ZEPHYR_RTIO_SPSC_H_ -#define ZEPHYR_RTIO_SPSC_H_ - -#include -#include -#include -#include -#include - -/** - * @brief RTIO Single Producer Single Consumer (SPSC) Queue API - * @defgroup rtio_spsc RTIO SPSC API - * @ingroup rtio - * @{ - */ - -/** - * @file rtio_spsc.h - * - * @brief A lock-free and type safe power of 2 fixed sized single producer - * single consumer (SPSC) queue using a ringbuffer and atomics to ensure - * coherency. - * - * This SPSC queue implementation works on an array which wraps using a power of - * two size and uses a bit mask to perform a modulus. Atomics are used to allow - * single-producer single-consumer safe semantics without locks. Elements are - * expected to be of a fixed size. The API is type safe as the underlying buffer - * is typed and all usage is done through macros. - * - * An SPSC queue may be declared on a stack or statically and work as intended so - * long as its lifetime outlives any usage. Static declarations should be the - * preferred method as stack . It is meant to be a shared object between two - * execution contexts (ISR and a thread for example) - * - * An SPSC queue is safe to produce or consume in an ISR with O(1) push/pull. - * - * @warning SPSC is *not* safe to produce or consume in multiple execution - * contexts. - * - * Safe usage would be, where A and B are unique execution contexts: - * 1. ISR A producing and a Thread B consuming. - * 2. Thread A producing and ISR B consuming. - * 3. Thread A producing and Thread B consuming. - * 4. ISR A producing and ISR B consuming. - */ - -/** - * @private - * @brief Common SPSC attributes - * - * @warning Not to be manipulated without the macros! - */ -struct rtio_spsc { - /* private value only the producer thread should mutate */ - unsigned long acquire; - - /* private value only the consumer thread should mutate */ - unsigned long consume; - - /* producer mutable, consumer readable */ - atomic_t in; - - /* consumer mutable, producer readable */ - atomic_t out; - - /* mask used to automatically wrap values */ - const unsigned long mask; -}; - -/** - * @brief Statically initialize an rtio_spsc - * - * @param sz Size of the spsc, must be power of 2 (ex: 2, 4, 8) - * @param buf Buffer pointer - */ -#define RTIO_SPSC_INITIALIZER(sz, buf) \ - { \ - ._spsc = { \ - .acquire = 0, \ - .consume = 0, \ - .in = ATOMIC_INIT(0), \ - .out = ATOMIC_INIT(0), \ - .mask = sz - 1, \ - }, \ - .buffer = buf, \ - } - -/** - * @brief Declare an anonymous struct type for an rtio_spsc - * - * @param name Name of the spsc symbol to be provided - * @param type Type stored in the spsc - */ -#define RTIO_SPSC_DECLARE(name, type) \ - static struct rtio_spsc_##name { \ - struct rtio_spsc _spsc; \ - type * const buffer; \ - } - -/** - * @brief Define an rtio_spsc with a fixed size - * - * @param name Name of the spsc symbol to be provided - * @param type Type stored in the spsc - * @param sz Size of the spsc, must be power of 2 (ex: 2, 4, 8) - */ -#define RTIO_SPSC_DEFINE(name, type, sz) \ - BUILD_ASSERT(IS_POWER_OF_TWO(sz)); \ - static type __spsc_buf_##name[sz]; \ - RTIO_SPSC_DECLARE(name, type) name = RTIO_SPSC_INITIALIZER(sz, __spsc_buf_##name); - -/** - * @brief Size of the SPSC queue - * - * @param spsc SPSC reference - */ -#define rtio_spsc_size(spsc) ((spsc)->_spsc.mask + 1) - -/** - * @private - * @brief A number modulo the spsc size, assumes power of 2 - * - * @param spsc SPSC reference - * @param i Value to modulo to the size of the spsc - */ -#define z_rtio_spsc_mask(spsc, i) ((i) & (spsc)->_spsc.mask) - - -/** - * @private - * @brief Load the current "in" index from the spsc as an unsigned long - */ -#define z_rtio_spsc_in(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.in) - -/** - * @private - * @brief Load the current "out" index from the spsc as an unsigned long - */ -#define z_rtio_spsc_out(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.out) - -/** - * @brief Initialize/reset a spsc such that its empty - * - * Note that this is not safe to do while being used in a producer/consumer - * situation with multiple calling contexts (isrs/threads). - * - * @param spsc SPSC to initialize/reset - */ -#define rtio_spsc_reset(spsc) \ - ({ \ - (spsc)->_spsc.consume = 0; \ - (spsc)->_spsc.acquire = 0; \ - atomic_set(&(spsc)->_spsc.in, 0); \ - atomic_set(&(spsc)->_spsc.out, 0); \ - }) - -/** - * @brief Acquire an element to produce from the SPSC - * - * @param spsc SPSC to acquire an element from for producing - * - * @return A pointer to the acquired element or null if the spsc is full - */ -#define rtio_spsc_acquire(spsc) \ - ({ \ - unsigned long idx = z_rtio_spsc_in(spsc) + (spsc)->_spsc.acquire; \ - bool spsc_acq = (idx - z_rtio_spsc_out(spsc)) < rtio_spsc_size(spsc); \ - if (spsc_acq) { \ - (spsc)->_spsc.acquire += 1; \ - } \ - spsc_acq ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \ - }) - -/** - * @brief Produce one previously acquired element to the SPSC - * - * This makes one element available to the consumer immediately - * - * @param spsc SPSC to produce the previously acquired element or do nothing - */ -#define rtio_spsc_produce(spsc) \ - ({ \ - if ((spsc)->_spsc.acquire > 0) { \ - (spsc)->_spsc.acquire -= 1; \ - atomic_add(&(spsc)->_spsc.in, 1); \ - } \ - }) - -/** - * @brief Produce all previously acquired elements to the SPSC - * - * This makes all previous acquired elements available to the consumer - * immediately - * - * @param spsc SPSC to produce all previously acquired elements or do nothing - */ -#define rtio_spsc_produce_all(spsc) \ - ({ \ - if ((spsc)->_spsc.acquire > 0) { \ - unsigned long acquired = (spsc)->_spsc.acquire; \ - (spsc)->_spsc.acquire = 0; \ - atomic_add(&(spsc)->_spsc.in, acquired); \ - } \ - }) - -/** - * @brief Drop all previously acquired elements - * - * This makes all previous acquired elements available to be acquired again - * - * @param spsc SPSC to drop all previously acquired elements or do nothing - */ -#define rtio_spsc_drop_all(spsc) \ - do { \ - (spsc)->_spsc.acquire = 0; \ - } while (false) - -/** - * @brief Consume an element from the spsc - * - * @param spsc Spsc to consume from - * - * @return Pointer to element or null if no consumable elements left - */ -#define rtio_spsc_consume(spsc) \ - ({ \ - unsigned long idx = z_rtio_spsc_out(spsc) + (spsc)->_spsc.consume; \ - bool has_consumable = (idx != z_rtio_spsc_in(spsc)); \ - if (has_consumable) { \ - (spsc)->_spsc.consume += 1; \ - } \ - has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \ - }) - -/** - * @brief Release a consumed element - * - * @param spsc SPSC to release consumed element or do nothing - */ -#define rtio_spsc_release(spsc) \ - ({ \ - if ((spsc)->_spsc.consume > 0) { \ - (spsc)->_spsc.consume -= 1; \ - atomic_add(&(spsc)->_spsc.out, 1); \ - } \ - }) - - -/** - * @brief Release all consumed elements - * - * @param spsc SPSC to release consumed elements or do nothing - */ -#define rtio_spsc_release_all(spsc) \ - ({ \ - if ((spsc)->_spsc.consume > 0) { \ - unsigned long consumed = (spsc)->_spsc.consume; \ - (spsc)->_spsc.consume = 0; \ - atomic_add(&(spsc)->_spsc.out, consumed); \ - } \ - }) - -/** - * @brief Count of acquirable in spsc - * - * @param spsc SPSC to get item count for - */ -#define rtio_spsc_acquirable(spsc) \ - ({ \ - (((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - \ - rtio_spsc_size(spsc); \ - }) - -/** - * @brief Count of consumables in spsc - * - * @param spsc SPSC to get item count for - */ -#define rtio_spsc_consumable(spsc) \ - ({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; }) - -/** - * @brief Peek at the first available item in queue - * - * @param spsc Spsc to peek into - * - * @return Pointer to element or null if no consumable elements left - */ -#define rtio_spsc_peek(spsc) \ - ({ \ - unsigned long idx = z_rtio_spsc_out(spsc) + (spsc)->_spsc.consume; \ - bool has_consumable = (idx != z_rtio_spsc_in(spsc)); \ - has_consumable ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx)]) : NULL; \ - }) - -/** - * @brief Peek at the next item in the queue from a given one - * - * - * @param spsc SPSC to peek at - * @param item Pointer to an item in the queue - * - * @return Pointer to element or null if none left - */ -#define rtio_spsc_next(spsc, item) \ - ({ \ - unsigned long idx = ((item) - (spsc)->buffer); \ - bool has_next = z_rtio_spsc_mask(spsc, (idx + 1)) != \ - (z_rtio_spsc_mask(spsc, z_rtio_spsc_in(spsc))); \ - has_next ? &((spsc)->buffer[z_rtio_spsc_mask((spsc), idx + 1)]) : NULL; \ - }) - -/** - * @brief Get the previous item in the queue from a given one - * - * @param spsc SPSC to peek at - * @param item Pointer to an item in the queue - * - * @return Pointer to element or null if none left - */ -#define rtio_spsc_prev(spsc, item) \ - ({ \ - unsigned long idx = ((item) - &(spsc)->buffer[0]) / sizeof((spsc)->buffer[0]); \ - bool has_prev = idx != z_rtio_spsc_mask(spsc, z_rtio_spsc_out(spsc)); \ - has_prev ? &((spsc)->buffer[z_rtio_spsc_mask(spsc, idx - 1)]) : NULL; \ - }) - -/** - * @} - */ - -#endif /* ZEPHYR_RTIO_SPSC_H_ */ diff --git a/include/zephyr/sd/sd_spec.h b/include/zephyr/sd/sd_spec.h index ed61932e65516..7e08488805c55 100644 --- a/include/zephyr/sd/sd_spec.h +++ b/include/zephyr/sd/sd_spec.h @@ -12,6 +12,7 @@ #define ZEPHYR_SUBSYS_SD_SPEC_H_ #include +#include #ifdef __cplusplus extern "C" { @@ -368,7 +369,18 @@ enum sd_group_num { /* Maximum data rate possible for SD high speed cards */ enum hs_max_data_rate { - HS_MAX_DTR = 50000000, + HS_UNSUPPORTED = 0, + HS_MAX_DTR = MHZ(50), +}; + +/* Maximum data rate possible for SD uhs cards */ +enum uhs_max_data_rate { + UHS_UNSUPPORTED = 0, + UHS_SDR12_MAX_DTR = MHZ(25), + UHS_SDR25_MAX_DTR = MHZ(50), + UHS_SDR50_MAX_DTR = MHZ(100), + UHS_SDR104_MAX_DTR = MHZ(208), + UHS_DDR50_MAX_DTR = MHZ(50), }; /** @@ -379,6 +391,7 @@ enum hs_max_data_rate { */ enum sd_bus_speed { UHS_SDR12_BUS_SPEED = BIT(0), + DEFAULT_BUS_SPEED = BIT(0), HIGH_SPEED_BUS_SPEED = BIT(1), UHS_SDR25_BUS_SPEED = BIT(1), UHS_SDR50_BUS_SPEED = BIT(2), @@ -393,10 +406,14 @@ enum sd_bus_speed { * controller to identify timing of card. */ enum sd_timing_mode { + SD_TIMING_DEFAULT = 0U, + /*!< Default Mode */ SD_TIMING_SDR12 = 0U, - /*!< Default mode & SDR12 */ + /*!< SDR12 mode */ + SD_TIMING_HIGH_SPEED = 1U, + /*!< High speed mode */ SD_TIMING_SDR25 = 1U, - /*!< High speed mode & SDR25 */ + /*!< SDR25 mode */ SD_TIMING_SDR50 = 2U, /*!< SDR50 mode*/ SD_TIMING_SDR104 = 3U, @@ -411,16 +428,16 @@ enum sd_timing_mode { * Controls the SD host controller clock speed on the SD bus. */ enum sdhc_clock_speed { - SDMMC_CLOCK_400KHZ = 400000U, - SD_CLOCK_25MHZ = 25000000U, - SD_CLOCK_50MHZ = 50000000U, - SD_CLOCK_100MHZ = 100000000U, - SD_CLOCK_208MHZ = 208000000U, - MMC_CLOCK_26MHZ = 26000000U, - MMC_CLOCK_52MHZ = 52000000U, - MMC_CLOCK_DDR52 = 52000000U, - MMC_CLOCK_HS200 = 200000000U, - MMC_CLOCK_HS400 = 200000000U, /* Same clock freq as HS200, just DDR */ + SDMMC_CLOCK_400KHZ = KHZ(400), + SD_CLOCK_25MHZ = MHZ(25), + SD_CLOCK_50MHZ = MHZ(50), + SD_CLOCK_100MHZ = MHZ(100), + SD_CLOCK_208MHZ = MHZ(208), + MMC_CLOCK_26MHZ = MHZ(26), + MMC_CLOCK_52MHZ = MHZ(52), + MMC_CLOCK_DDR52 = MHZ(52), + MMC_CLOCK_HS200 = MHZ(200), + MMC_CLOCK_HS400 = MHZ(200), /* Same clock freq as HS200, just DDR */ }; /** @@ -487,7 +504,7 @@ enum sd_driver_strength { */ struct sd_switch_caps { enum hs_max_data_rate hs_max_dtr; - enum sdhc_clock_speed uhs_max_dtr; + enum uhs_max_data_rate uhs_max_dtr; enum sd_bus_speed bus_speed; enum sd_driver_type sd_drv_type; enum sd_current_limit sd_current_limit; diff --git a/include/zephyr/shell/shell_adsp_memory_window.h b/include/zephyr/shell/shell_adsp_memory_window.h new file mode 100644 index 0000000000000..f6277fd2996d5 --- /dev/null +++ b/include/zephyr/shell/shell_adsp_memory_window.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef SHELL_ADSP_MEMORY_WINDOW_H__ +#define SHELL_ADSP_MEMORY_WINDOW_H__ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +extern const struct shell_transport_api shell_adsp_memory_window_transport_api; + +struct sys_winstream; + +/** Memwindow based shell transport. */ +struct shell_adsp_memory_window { + /** Handler function registered by shell. */ + shell_transport_handler_t shell_handler; + + struct k_timer timer; + + /** Context registered by shell. */ + void *shell_context; + + /** Receive winstream object */ + struct sys_winstream *ws_rx; + + /** Transmit winstream object */ + struct sys_winstream *ws_tx; + + /** Last read sequence number */ + uint32_t read_seqno; +}; + +#define SHELL_ADSP_MEMORY_WINDOW_DEFINE(_name) \ + static struct shell_adsp_memory_window _name##_shell_adsp_memory_window;\ + struct shell_transport _name = { \ + .api = &shell_adsp_memory_window_transport_api, \ + .ctx = &_name##_shell_adsp_memory_window, \ + } + +/** + * @brief This function provides pointer to shell ADSP memory window backend instance. + * + * Function returns pointer to the shell ADSP memory window instance. This instance can be + * next used with shell_execute_cmd function in order to test commands behavior. + * + * @returns Pointer to the shell instance. + */ +const struct shell *shell_backend_adsp_memory_window_get_ptr(void); + +#ifdef __cplusplus +} +#endif + +#endif /* SHELL_ADSP_MEMORY_WINDOW_H__ */ diff --git a/include/zephyr/shell/shell_mqtt.h b/include/zephyr/shell/shell_mqtt.h index 03cd64fbdcdba..72e597e6d53b2 100644 --- a/include/zephyr/shell/shell_mqtt.h +++ b/include/zephyr/shell/shell_mqtt.h @@ -120,7 +120,7 @@ struct shell_mqtt { const struct shell *shell_backend_mqtt_get_ptr(void); /** - * @brief Function to define the device ID (devid) for which the shell mqtt backend uses as a + * @brief Function to define the device ID (devid) for which the shell mqtt backend uses as a * client ID when it connects to the broker. It will publish its output to devid_tx and subscribe * to devid_rx for input . * diff --git a/include/zephyr/smf.h b/include/zephyr/smf.h index ba0191272648b..5b5f303630da8 100644 --- a/include/zephyr/smf.h +++ b/include/zephyr/smf.h @@ -18,26 +18,27 @@ /** * @brief State Machine Framework API * @defgroup smf State Machine Framework API + * @version 0.1.0 * @ingroup os_services * @{ */ /** - * @brief Macro to create a hierarchical state. + * @brief Macro to create a hierarchical state with initial transitions. * - * @param _entry State entry function - * @param _run State run function - * @param _exit State exit function + * @param _entry State entry function or NULL + * @param _run State run function or NULL + * @param _exit State exit function or NULL * @param _parent State parent object or NULL * @param _initial State initial transition object or NULL */ -#define SMF_CREATE_STATE(_entry, _run, _exit, _parent, _initial) \ -{ \ - .entry = _entry, \ - .run = _run, \ - .exit = _exit, \ - IF_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT, (.parent = _parent,)) \ - IF_ENABLED(CONFIG_SMF_INITIAL_TRANSITION, (.initial = _initial,)) \ +#define SMF_CREATE_STATE(_entry, _run, _exit, _parent, _initial) \ +{ \ + .entry = _entry, \ + .run = _run, \ + .exit = _exit, \ + IF_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT, (.parent = _parent,)) \ + IF_ENABLED(CONFIG_SMF_INITIAL_TRANSITION, (.initial = _initial,)) \ } /** @@ -72,6 +73,7 @@ struct smf_state { const state_execution run; /** Optional method that will be run when this state exists */ const state_execution exit; +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT /** * Optional parent state that contains common entry/run/exit * implementation among various child states. @@ -79,8 +81,8 @@ struct smf_state { * run: Parent function executes AFTER child function. * exit: Parent function executes AFTER child function. * - * Note: When transitioning between two child states with a shared parent, - * that parent's exit and entry functions do not execute. + * Note: When transitioning between two child states with a shared + * parent, that parent's exit and entry functions do not execute. */ const struct smf_state *parent; @@ -89,7 +91,8 @@ struct smf_state { * Optional initial transition state. NULL for leaf states. */ const struct smf_state *initial; -#endif +#endif /* CONFIG_SMF_INITIAL_TRANSITION */ +#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ }; /** Defines the current context of the state machine. */ @@ -98,6 +101,11 @@ struct smf_ctx { const struct smf_state *current; /** Previous state the state machine executed */ const struct smf_state *previous; + +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + /** Currently executing state (which may be a parent) */ + const struct smf_state *executing; +#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ /** * This value is set by the set_terminate function and * should terminate the state machine when its set to a @@ -122,8 +130,8 @@ void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state); /** * @brief Changes a state machines state. This handles exiting the previous - * state and entering the target state. A common parent state will not - * exited nor be re-entered. + * state and entering the target state. For HSMs the entry and exit + * actions of the Least Common Ancestor will not be run. * * @param ctx State machine context * @param new_state State to transition to (NULL is valid and exits all states) diff --git a/include/zephyr/spinlock.h b/include/zephyr/spinlock.h index 51c160b0f8599..451e91cbd5475 100644 --- a/include/zephyr/spinlock.h +++ b/include/zephyr/spinlock.h @@ -316,7 +316,7 @@ static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l, #ifdef CONFIG_SMP #ifdef CONFIG_TICKET_SPINLOCKS /* Give the spinlock to the next CPU in a FIFO */ - atomic_inc(&l->owner); + (void)atomic_inc(&l->owner); #else /* Strictly we don't need atomic_clear() here (which is an * exchange operation that returns the old value). We are always @@ -325,7 +325,7 @@ static ALWAYS_INLINE void k_spin_unlock(struct k_spinlock *l, * a memory barrier when used like this, and we don't have a * Zephyr framework for that. */ - atomic_clear(&l->locked); + (void)atomic_clear(&l->locked); #endif /* CONFIG_TICKET_SPINLOCKS */ #endif /* CONFIG_SMP */ arch_irq_unlock(key.key); @@ -364,9 +364,9 @@ static ALWAYS_INLINE void k_spin_release(struct k_spinlock *l) #endif #ifdef CONFIG_SMP #ifdef CONFIG_TICKET_SPINLOCKS - atomic_inc(&l->owner); + (void)atomic_inc(&l->owner); #else - atomic_clear(&l->locked); + (void)atomic_clear(&l->locked); #endif /* CONFIG_TICKET_SPINLOCKS */ #endif /* CONFIG_SMP */ } @@ -437,7 +437,7 @@ static ALWAYS_INLINE void z_spin_onexit(__maybe_unused k_spinlock_key_t *k) */ #define K_SPINLOCK(lck) \ for (k_spinlock_key_t __i K_SPINLOCK_ONEXIT = {}, __key = k_spin_lock(lck); !__i.key; \ - k_spin_unlock(lck, __key), __i.key = 1) + k_spin_unlock((lck), __key), __i.key = 1) /** @} */ diff --git a/include/zephyr/storage/disk_access.h b/include/zephyr/storage/disk_access.h index 53774e7666edc..a5ce72dd5bfb3 100644 --- a/include/zephyr/storage/disk_access.h +++ b/include/zephyr/storage/disk_access.h @@ -39,7 +39,13 @@ extern "C" { * @brief perform any initialization * * This call is made by the consumer before doing any IO calls so that the - * disk or the backing device can do any initialization. + * disk or the backing device can do any initialization. Although still + * supported for legacy compatibility, users should instead call + * @ref disk_access_ioctl with the IOCTL @ref DISK_IOCTL_CTRL_INIT. + * + * Disk initialization is reference counted, so only the first successful call + * to initialize a uninitialized (or previously de-initialized) disk will + * actually initialize the disk * * @param[in] pdrv Disk name * diff --git a/include/zephyr/storage/flash_map.h b/include/zephyr/storage/flash_map.h index 37b7c7f322331..937e242830ae3 100644 --- a/include/zephyr/storage/flash_map.h +++ b/include/zephyr/storage/flash_map.h @@ -187,6 +187,29 @@ int flash_area_write(const struct flash_area *fa, off_t off, const void *src, */ int flash_area_erase(const struct flash_area *fa, off_t off, size_t len); +/** + * @brief Erase flash area or fill with erase-value + * + * On program-erase devices this function behaves exactly like flash_area_erase. + * On RAM non-volatile device it will call erase, if driver provides such + * callback, or will fill given range with erase-value defined by driver. + * This function should be only used by code that has not been written + * to directly support devices that do not require erase and rely on + * device being erased prior to some operations. + * Note that emulated erase, on devices that do not require, is done + * via write, which affects endurance of device. + * + * @see flash_area_erase() + * @see flash_flatten() + * + * @param[in] fa Flash area + * @param[in] off Offset relative from beginning of flash area. + * @param[in] len Number of bytes to be erase + * + * @return 0 on success, negative errno code on fail. + */ +int flash_area_flatten(const struct flash_area *fa, off_t off, size_t len); + /** * @brief Get write block size of the flash area * @@ -301,6 +324,15 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); */ #define FIXED_PARTITION_OFFSET(label) DT_REG_ADDR(DT_NODELABEL(label)) +/** + * Get fixed-partition offset from DTS node + * + * @param node DTS node of a partition + * + * @return fixed-partition offset, as defined for the partition in DTS. + */ +#define FIXED_PARTITION_NODE_OFFSET(node) DT_REG_ADDR(node) + /** * Get fixed-partition size for DTS node label * @@ -310,6 +342,15 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); */ #define FIXED_PARTITION_SIZE(label) DT_REG_SIZE(DT_NODELABEL(label)) +/** + * Get fixed-partition size for DTS node + * + * @param node DTS node of a partition + * + * @return fixed-partition size, as defined for the partition in DTS. + */ +#define FIXED_PARTITION_NODE_SIZE(node) DT_REG_SIZE(node) + /** * Get device pointer for device the area/partition resides on * @@ -330,6 +371,16 @@ uint8_t flash_area_erased_val(const struct flash_area *fa); #define FIXED_PARTITION_DEVICE(label) \ DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(label))) +/** + * Get device pointer for device the area/partition resides on + * + * @param node DTS node of a partition + * + * @return Pointer to a device. + */ +#define FIXED_PARTITION_NODE_DEVICE(node) \ + DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(node)) + #ifdef __cplusplus } #endif diff --git a/include/zephyr/storage/stream_flash.h b/include/zephyr/storage/stream_flash.h index 40787d773d52a..6d969105b6eac 100644 --- a/include/zephyr/storage/stream_flash.h +++ b/include/zephyr/storage/stream_flash.h @@ -65,6 +65,8 @@ struct stream_flash_ctx { #ifdef CONFIG_STREAM_FLASH_ERASE off_t last_erased_page_start_offset; /* Last erased offset */ #endif + uint8_t erase_value; + uint8_t write_block_size; /* Offset/size device write alignment */ }; /** diff --git a/include/zephyr/sw_isr_table.h b/include/zephyr/sw_isr_table.h index 7b1bfddb2cbda..ea708cba4f7d3 100644 --- a/include/zephyr/sw_isr_table.h +++ b/include/zephyr/sw_isr_table.h @@ -16,6 +16,7 @@ #if !defined(_ASMLANGUAGE) #include +#include #include #include #include @@ -47,10 +48,84 @@ extern struct _isr_table_entry _sw_isr_table[]; struct _irq_parent_entry { const struct device *dev; + unsigned int level; unsigned int irq; unsigned int offset; }; +/** + * @cond INTERNAL_HIDDEN + */ + +/* Mapping between aggregator level to order */ +#define Z_STR_L2 2ND +#define Z_STR_L3 3RD +/** + * @brief Get the Software ISR table offset Kconfig for the given aggregator level + * + * @param l Aggregator level, must be 2 or 3 + * + * @return `CONFIG_2ND_LVL_ISR_TBL_OFFSET` if second level aggregator, + * `CONFIG_3RD_LVL_ISR_TBL_OFFSET` if third level aggregator + */ +#define Z_SW_ISR_TBL_KCONFIG_BY_ALVL(l) CONCAT(CONFIG_, CONCAT(Z_STR_L, l), _LVL_ISR_TBL_OFFSET) + +/** + * INTERNAL_HIDDEN @endcond + */ + +/** + * @brief Get an interrupt controller node's level base ISR table offset. + * + * @param node_id node identifier of the interrupt controller + * + * @return `CONFIG_2ND_LVL_ISR_TBL_OFFSET` if node_id is a second level aggregator, + * `CONFIG_3RD_LVL_ISR_TBL_OFFSET` if it is a third level aggregator + */ +#define INTC_BASE_ISR_TBL_OFFSET(node_id) \ + Z_SW_ISR_TBL_KCONFIG_BY_ALVL(DT_INTC_GET_AGGREGATOR_LEVEL(node_id)) + +/** + * @brief Get the SW ISR table offset for an instance of interrupt controller + * + * @param inst DT_DRV_COMPAT interrupt controller driver instance number + * + * @return Software ISR table offset of the interrupt controller + */ +#define INTC_INST_ISR_TBL_OFFSET(inst) \ + (INTC_BASE_ISR_TBL_OFFSET(DT_DRV_INST(inst)) + (inst * CONFIG_MAX_IRQ_PER_AGGREGATOR)) + +/** + * @brief Get the SW ISR table offset for a child interrupt controller + * + * @details This macro is a alternative form of the `INTC_INST_ISR_TBL_OFFSET`. This is used by + * pseudo interrupt controller devices that are child of a main interrupt controller device. + * + * @param node_id node identifier of the child interrupt controller + * + * @return Software ISR table offset of the child + */ +#define INTC_CHILD_ISR_TBL_OFFSET(node_id) \ + (INTC_BASE_ISR_TBL_OFFSET(node_id) + \ + (DT_NODE_CHILD_IDX(node_id) * CONFIG_MAX_IRQ_PER_AGGREGATOR)) + +/** + * @brief Register an interrupt controller with the software ISR table + * + * @param _name Name of the interrupt controller (must be unique) + * @param _dev Pointer to the interrupt controller device instance + * @param _irq Interrupt controller IRQ number + * @param _offset Software ISR table offset of the interrupt controller + * @param _level Interrupt controller aggregator level + */ +#define IRQ_PARENT_ENTRY_DEFINE(_name, _dev, _irq, _offset, _level) \ + static const STRUCT_SECTION_ITERABLE_ALTERNATE(intc_table, _irq_parent_entry, _name) = { \ + .dev = _dev, \ + .level = _level, \ + .irq = _irq, \ + .offset = _offset, \ + } + /* * Data structure created in a special binary .intlist section for each * configured interrupt. gen_irq_tables.py pulls this out of the binary and diff --git a/include/zephyr/sys/atomic_c.h b/include/zephyr/sys/atomic_c.h index f1e23caf3625c..df36036a87738 100644 --- a/include/zephyr/sys/atomic_c.h +++ b/include/zephyr/sys/atomic_c.h @@ -85,7 +85,7 @@ __syscall atomic_val_t atomic_nand(atomic_t *target, atomic_val_t value); #define _REMOVE_DISABLE_SYSCALL_TRACING #endif -#include +#include #ifdef _REMOVE_DISABLE_SYSCALL_TRACING #undef DISABLE_SYSCALL_TRACING diff --git a/include/zephyr/sys/bitarray.h b/include/zephyr/sys/bitarray.h index 90d1f59345bb5..35ee721ddf799 100644 --- a/include/zephyr/sys/bitarray.h +++ b/include/zephyr/sys/bitarray.h @@ -168,6 +168,61 @@ int sys_bitarray_test_and_clear_bit(sys_bitarray_t *bitarray, size_t bit, int *p int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits, size_t *offset); +/** + * Calculates the bit-wise XOR of two bitarrays in a region. + * The result is stored in the first bitarray passed in (@p dst). + * Both bitarrays must be of the same size. + * + * @param dst Bitarray struct + * @param other Bitarray struct + * @param num_bits Number of bits in the region, must be larger than 0 + * @param offset Starting bit location + * + * @retval 0 Operation successful + * @retval -EINVAL Invalid argument (e.g. out-of-bounds access, mismatching bitarrays, trying to xor + * 0 bits, etc.) + */ +int sys_bitarray_xor(sys_bitarray_t *dst, sys_bitarray_t *other, size_t num_bits, size_t offset); + +/** + * Find nth bit set in region + * + * This counts the number of bits set (@p count) in a + * region (@p offset, @p num_bits) and returns the index (@p found_at) + * of the nth set bit, if it exists, as long with a zero return value. + * + * If it does not exist, @p found_at is not updated and the method returns + * + * @param[in] bitarray Bitarray struct + * @param[in] n Nth bit set to look for + * @param[in] num_bits Number of bits to check, must be larger than 0 + * @param[in] offset Starting bit position + * @param[out] found_at Index of the nth bit set, if found + * + * @retval 0 Operation successful + * @retval 1 Nth bit set was not found in region + * @retval -EINVAL Invalid argument (e.g. out-of-bounds access, trying to count 0 bits, etc.) + */ +int sys_bitarray_find_nth_set(sys_bitarray_t *bitarray, size_t n, size_t num_bits, size_t offset, + size_t *found_at); + +/** + * Count bits set in a bit array region + * + * This counts the number of bits set (@p count) in a + * region (@p offset, @p num_bits). + * + * @param[in] bitarray Bitarray struct + * @param[in] num_bits Number of bits to check, must be larger than 0 + * @param[in] offset Starting bit position + * @param[out] count Number of bits set in the region if successful + * + * @retval 0 Operation successful + * @retval -EINVAL Invalid argument (e.g. out-of-bounds access, trying to count 0 bits, etc.) + */ +int sys_bitarray_popcount_region(sys_bitarray_t *bitarray, size_t num_bits, size_t offset, + size_t *count); + /** * Free bits in a bit array * diff --git a/include/zephyr/sys/cbprintf_internal.h b/include/zephyr/sys/cbprintf_internal.h index 2ffc599aa40f4..ad6796190384d 100644 --- a/include/zephyr/sys/cbprintf_internal.h +++ b/include/zephyr/sys/cbprintf_internal.h @@ -92,6 +92,7 @@ extern "C" { #define Z_CBPRINTF_IS_PCHAR(x, flags) \ z_cbprintf_cxx_is_pchar(x, (flags) & CBPRINTF_PACKAGE_CONST_CHAR_RO) #else +/* NOLINTBEGIN(misc-redundant-expression) */ #define Z_CBPRINTF_IS_PCHAR(x, flags) \ _Generic((x) + 0, \ /* char * */ \ @@ -111,6 +112,7 @@ extern "C" { const volatile wchar_t * : 1, \ default : \ 0) +/* NOLINTEND(misc-redundant-expression) */ #endif /** @brief Check if argument fits in 32 bit word. @@ -555,8 +557,9 @@ extern "C" { #ifdef __cplusplus #define Z_CBPRINTF_ARG_SIZE(v) z_cbprintf_cxx_arg_size(v) #else +#define Z_CONSTIFY(v) (_Generic((v), char * : (const char *)(uintptr_t)(v), default : (v))) #define Z_CBPRINTF_ARG_SIZE(v) ({\ - __auto_type __v = (v) + 0; \ + __auto_type __v = (Z_CONSTIFY(v)) + 0; \ /* Static code analysis may complain about unused variable. */ \ (void)__v; \ size_t __arg_size = _Generic((v), \ @@ -580,7 +583,7 @@ extern "C" { #define Z_CBPRINTF_STORE_ARG(buf, arg) do { \ if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { \ /* If required, copy arguments by word to avoid unaligned access.*/ \ - __auto_type _v = (arg) + 0; \ + __auto_type _v = (Z_CONSTIFY(arg)) + 0; \ double _d = _Generic((arg) + 0, \ float : (arg) + 0, \ default : \ @@ -676,12 +679,12 @@ do { \ Z_CBPRINTF_IS_LONGDOUBLE(_arg) && \ !IS_ENABLED(CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE)),\ "Packaging of long double not enabled in Kconfig."); \ - while (_align_offset % Z_CBPRINTF_ALIGNMENT(_arg) != 0UL) { \ + while ((_align_offset % Z_CBPRINTF_ALIGNMENT(_arg)) != 0UL) { \ _idx += sizeof(int); \ _align_offset += sizeof(int); \ } \ uint32_t _arg_size = Z_CBPRINTF_ARG_SIZE(_arg); \ - uint32_t _loc = _idx / sizeof(int); \ + uint8_t _loc = (uint8_t)(_idx / sizeof(int)); \ if (arg_idx < 1 + _fros_cnt) { \ if (_ros_pos_en) { \ _ros_pos_buf[_ros_pos_idx++] = _loc; \ @@ -700,7 +703,7 @@ do { \ } \ } else if (_rws_pos_en) { \ _rws_buffer[_rws_pos_idx++] = arg_idx - 1; \ - _rws_buffer[_rws_pos_idx++] = _idx / sizeof(int); \ + _rws_buffer[_rws_pos_idx++] = (uint8_t)(_idx / sizeof(int)); \ } \ } \ if (_buf && _idx < (int)_max) { \ diff --git a/include/zephyr/sys/crc.h b/include/zephyr/sys/crc.h index e29fce45d9e99..c16281b10fde2 100644 --- a/include/zephyr/sys/crc.h +++ b/include/zephyr/sys/crc.h @@ -30,6 +30,14 @@ extern "C" { */ #define CRC8_CCITT_INITIAL_VALUE 0xFF +/* Initial value expected to be used at the beginning of the OpenPGP CRC-24 computation. */ +#define CRC24_PGP_INITIAL_VALUE 0x00B704CEU +/* + * The CRC-24 value is stored on a 32-bit value, only the 3 least significant bytes + * are meaningful. Use the following mask to only keep the CRC-24 value. + */ +#define CRC24_FINAL_VALUE_MASK 0x00FFFFFFU + /** * @defgroup checksum Checksum * @ingroup os_services @@ -56,6 +64,7 @@ enum crc_type { CRC16_ANSI, /**< Use @ref crc16_ansi */ CRC16_CCITT, /**< Use @ref crc16_ccitt */ CRC16_ITU_T, /**< Use @ref crc16_itu_t */ + CRC24_PGP, /**< Use @ref crc24_pgp */ CRC32_C, /**< Use @ref crc32_c */ CRC32_IEEE, /**< Use @ref crc32_ieee */ }; @@ -315,16 +324,39 @@ uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len); uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value, bool reversed); +/** + * @brief Generate an OpenPGP CRC-24 checksum as defined in RFC 4880 section 6.1. + * + * @param data A pointer to the data on which the CRC will be calculated. + * @param len Data length in bytes. + * + * @return The CRC-24 value. + */ +uint32_t crc24_pgp(const uint8_t *data, size_t len); + +/** + * @brief Update an OpenPGP CRC-24 checksum. + * + * @param crc The CRC-24 checksum that needs to be updated. The full 32-bit value of the CRC needs + * to be used between calls, do not mask the value to keep only the last 24 bits. + * @param data A pointer to the data on which the CRC will be calculated. + * @param len Data length in bytes. + * + * @return The CRC-24 value. When the last buffer of data has been processed, mask the value + * with CRC24_FINAL_VALUE_MASK to keep only the meaningful 24 bits of the CRC result. + */ +uint32_t crc24_pgp_update(uint32_t crc, const uint8_t *data, size_t len); + /** * @brief Compute a CRC checksum, in a generic way. * * This is a dispatch function that calls the individual CRC routine * determined by @p type. * - * For 7, 8, and 16-bit CRCs, the relevant @p seed and @p poly values should + * For 7, 8, 16 and 24-bit CRCs, the relevant @p seed and @p poly values should * be passed in via the least-significant byte(s). * - * Similarly, for 7, 8, and 16-bit CRCs, the relevant result is stored in the + * Similarly, for 7, 8, 16 and 24-bit CRCs, the relevant result is stored in the * least-significant byte(s) of the returned value. * * @param type CRC algorithm to use. @@ -364,6 +396,13 @@ static inline uint32_t crc_by_type(enum crc_type type, const uint8_t *src, size_ return crc16_ccitt(seed, src, len); case CRC16_ITU_T: return crc16_itu_t(seed, src, len); + case CRC24_PGP: { + uint32_t crc = crc24_pgp_update(seed, src, len); + + if (last) + crc &= CRC24_FINAL_VALUE_MASK; + return crc; + } case CRC32_C: return crc32_c(seed, src, len, first, last); case CRC32_IEEE: diff --git a/include/zephyr/sys/device_mmio.h b/include/zephyr/sys/device_mmio.h index c50a12782eef2..e500e2afb3e61 100644 --- a/include/zephyr/sys/device_mmio.h +++ b/include/zephyr/sys/device_mmio.h @@ -101,8 +101,8 @@ static inline void device_map(mm_reg_t *virt_addr, uintptr_t phys_addr, /* Pass along flags and add that we want supervisor mode * read-write access. */ - z_phys_map((uint8_t **)virt_addr, phys_addr, size, - flags | K_MEM_PERM_RW); + k_mem_map_phys_bare((uint8_t **)virt_addr, phys_addr, size, + flags | K_MEM_PERM_RW); #else ARG_UNUSED(size); ARG_UNUSED(flags); diff --git a/include/zephyr/sys/errno_private.h b/include/zephyr/sys/errno_private.h index 60df9622bb81d..5adba7bfc08b8 100644 --- a/include/zephyr/sys/errno_private.h +++ b/include/zephyr/sys/errno_private.h @@ -50,7 +50,7 @@ __syscall int *z_errno(void); #endif #if !defined(CONFIG_ERRNO_IN_TLS) && !defined(CONFIG_LIBC_ERRNO) -#include +#include #endif /* CONFIG_ERRNO_IN_TLS */ #endif /* ZEPHYR_INCLUDE_SYS_ERRNO_PRIVATE_H_ */ diff --git a/include/zephyr/sys/fdtable.h b/include/zephyr/sys/fdtable.h index bd5e70813d5e4..2c49d24210b1e 100644 --- a/include/zephyr/sys/fdtable.h +++ b/include/zephyr/sys/fdtable.h @@ -12,6 +12,20 @@ #include #include +/* File mode bits */ +#define ZVFS_MODE_IFMT 0170000 +#define ZVFS_MODE_UNSPEC 0000000 +#define ZVFS_MODE_IFIFO 0010000 +#define ZVFS_MODE_IFCHR 0020000 +#define ZVFS_MODE_IMSGQ 0030000 +#define ZVFS_MODE_IFDIR 0040000 +#define ZVFS_MODE_IFSEM 0050000 +#define ZVFS_MODE_IFBLK 0060000 +#define ZVFS_MODE_IFSHM 0070000 +#define ZVFS_MODE_IFREG 0100000 +#define ZVFS_MODE_IFLNK 0120000 +#define ZVFS_MODE_IFSOCK 0140000 + #ifdef __cplusplus extern "C" { #endif @@ -21,8 +35,14 @@ extern "C" { * Currently all operations beyond read/write/close go thru ioctl method. */ struct fd_op_vtable { - ssize_t (*read)(void *obj, void *buf, size_t sz); - ssize_t (*write)(void *obj, const void *buf, size_t sz); + union { + ssize_t (*read)(void *obj, void *buf, size_t sz); + ssize_t (*read_offs)(void *obj, void *buf, size_t sz, size_t offset); + }; + union { + ssize_t (*write)(void *obj, const void *buf, size_t sz); + ssize_t (*write_offs)(void *obj, const void *buf, size_t sz, size_t offset); + }; int (*close)(void *obj); int (*ioctl)(void *obj, unsigned int request, va_list args); }; @@ -39,6 +59,24 @@ struct fd_op_vtable { */ int z_reserve_fd(void); +/** + * @brief Finalize creation of file descriptor, with type. + * + * This function should be called exactly once after z_reserve_fd(), and + * should not be called in any other case. + * + * The difference between this function and @ref z_finalize_fd is that the + * latter does not relay type information of the created file descriptor. + * + * Values permitted for @a mode are one of `ZVFS_MODE_..`. + * + * @param fd File descriptor previously returned by z_reserve_fd() + * @param obj pointer to I/O object structure + * @param vtable pointer to I/O operation implementations for the object + * @param mode File type as specified above. + */ +void z_finalize_typed_fd(int fd, void *obj, const struct fd_op_vtable *vtable, uint32_t mode); + /** * @brief Finalize creation of file descriptor. * @@ -49,7 +87,10 @@ int z_reserve_fd(void); * @param obj pointer to I/O object structure * @param vtable pointer to I/O operation implementations for the object */ -void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable); +static inline void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable) +{ + z_finalize_typed_fd(fd, obj, vtable, ZVFS_MODE_UNSPEC); +} /** * @brief Allocate file descriptor for underlying I/O object. @@ -166,6 +207,9 @@ enum { ZFD_IOCTL_POLL_UPDATE, ZFD_IOCTL_POLL_OFFLOAD, ZFD_IOCTL_SET_LOCK, + ZFD_IOCTL_STAT, + ZFD_IOCTL_TRUNCATE, + ZFD_IOCTL_MMAP, /* Codes above 0x5400 and below 0x5500 are reserved for termios, FIO, etc */ ZFD_IOCTL_FIONREAD = 0x541B, diff --git a/include/zephyr/sys/kobject.h b/include/zephyr/sys/kobject.h index 50577ac7c02d3..9fe9b5ad212c8 100644 --- a/include/zephyr/sys/kobject.h +++ b/include/zephyr/sys/kobject.h @@ -36,7 +36,7 @@ enum k_objects { * generated during build by gen_kobject_list.py. It includes * basic kernel objects (e.g. pipes and mutexes) and driver types. */ -#include +#include /** @endcond */ @@ -283,7 +283,7 @@ static inline void k_object_free(void *obj) /** @} */ -#include +#include #ifdef __cplusplus } #endif diff --git a/include/zephyr/sys/libc-hooks.h b/include/zephyr/sys/libc-hooks.h index e00efc6de2684..b9c38bb3c4ad5 100644 --- a/include/zephyr/sys/libc-hooks.h +++ b/include/zephyr/sys/libc-hooks.h @@ -109,7 +109,7 @@ extern struct k_mem_partition z_libc_partition; #endif #endif /* CONFIG_USERSPACE */ -#include +#include /* C library memory partitions */ #define Z_LIBC_DATA K_APP_DMEM(z_libc_partition) diff --git a/include/zephyr/sys/list_gen.h b/include/zephyr/sys/list_gen.h index ba29f7d9bec26..82d1986fe9bf1 100644 --- a/include/zephyr/sys/list_gen.h +++ b/include/zephyr/sys/list_gen.h @@ -72,7 +72,7 @@ static inline sys_ ## __nname ## _t * \ sys_ ## __lname ## _peek_next(sys_ ## __nname ## _t *node) \ { \ - return node != NULL ? \ + return (node != NULL) ? \ sys_ ## __lname ## _peek_next_no_check(node) : \ NULL; \ } diff --git a/include/zephyr/sys/math_extras_impl.h b/include/zephyr/sys/math_extras_impl.h index f6f856c4ad46d..76e0fa19cb6ff 100644 --- a/include/zephyr/sys/math_extras_impl.h +++ b/include/zephyr/sys/math_extras_impl.h @@ -187,7 +187,7 @@ static inline bool size_mul_overflow(size_t a, size_t b, size_t *result) #if use_builtin(__builtin_clz) static inline int u32_count_leading_zeros(uint32_t x) { - return x == 0 ? 32 : __builtin_clz(x); + return (x == 0) ? 32 : __builtin_clz(x); } #else /* !use_builtin(__builtin_clz) */ static inline int u32_count_leading_zeros(uint32_t x) @@ -205,7 +205,7 @@ static inline int u32_count_leading_zeros(uint32_t x) #if use_builtin(__builtin_clzll) static inline int u64_count_leading_zeros(uint64_t x) { - return x == 0 ? 64 : __builtin_clzll(x); + return (x == 0) ? 64 : __builtin_clzll(x); } #else /* !use_builtin(__builtin_clzll) */ static inline int u64_count_leading_zeros(uint64_t x) @@ -221,7 +221,7 @@ static inline int u64_count_leading_zeros(uint64_t x) #if use_builtin(__builtin_ctz) static inline int u32_count_trailing_zeros(uint32_t x) { - return x == 0 ? 32 : __builtin_ctz(x); + return (x == 0) ? 32 : __builtin_ctz(x); } #else /* !use_builtin(__builtin_ctz) */ static inline int u32_count_trailing_zeros(uint32_t x) @@ -239,7 +239,7 @@ static inline int u32_count_trailing_zeros(uint32_t x) #if use_builtin(__builtin_ctzll) static inline int u64_count_trailing_zeros(uint64_t x) { - return x == 0 ? 64 : __builtin_ctzll(x); + return (x == 0) ? 64 : __builtin_ctzll(x); } #else /* !use_builtin(__builtin_ctzll) */ static inline int u64_count_trailing_zeros(uint64_t x) diff --git a/include/zephyr/sys/mpsc_lockfree.h b/include/zephyr/sys/mpsc_lockfree.h new file mode 100644 index 0000000000000..3e6c89d99a051 --- /dev/null +++ b/include/zephyr/sys/mpsc_lockfree.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2010-2011 Dmitry Vyukov + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SYS_MPSC_LOCKFREE_H_ +#define ZEPHYR_SYS_MPSC_LOCKFREE_H_ + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Multiple Producer Single Consumer (MPSC) Lockfree Queue API + * @defgroup mpsc_lockfree MPSC Lockfree Queue API + * @ingroup datastructure_apis + * @{ + */ + +/** + * @file mpsc_lockfree.h + * + * @brief A wait-free intrusive multi producer single consumer (MPSC) queue using + * a singly linked list. Ordering is First-In-First-Out. + * + * Based on the well known and widely used wait-free MPSC queue described by + * Dmitry Vyukov with some slight changes to account for needs of an + * RTOS on a variety of archs. Both consumer and producer are wait free. No CAS + * loop or lock is needed. + * + * An MPSC queue is safe to produce or consume in an ISR with O(1) push/pop. + * + * @warning MPSC is *not* safe to consume in multiple execution contexts. + */ + +/* + * On single core systems atomics are unnecessary + * and cause a lot of unnecessary cache invalidation + * + * Using volatile to at least ensure memory is read/written + * by the compiler generated op codes is enough. + * + * On SMP atomics *must* be used to ensure the pointers + * are updated in the correct order. + */ +#if IS_ENABLED(CONFIG_SMP) + +typedef atomic_ptr_t mpsc_ptr_t; + +#define mpsc_ptr_get(ptr) atomic_ptr_get(&(ptr)) +#define mpsc_ptr_set(ptr, val) atomic_ptr_set(&(ptr), val) +#define mpsc_ptr_set_get(ptr, val) atomic_ptr_set(&(ptr), val) + +#else /* IS_ENABLED(CONFIG_SMP) */ + +typedef struct mpsc_node *mpsc_ptr_t; + +#define mpsc_ptr_get(ptr) ptr +#define mpsc_ptr_set(ptr, val) ptr = val +#define mpsc_ptr_set_get(ptr, val) \ + ({ \ + mpsc_ptr_t tmp = ptr; \ + ptr = val; \ + tmp; \ + }) + +#endif /* IS_ENABLED(CONFIG_SMP) */ + +/** + * @brief Queue member + */ +struct mpsc_node { + mpsc_ptr_t next; +}; + +/** + * @brief MPSC Queue + */ +struct mpsc { + mpsc_ptr_t head; + struct mpsc_node *tail; + struct mpsc_node stub; +}; + +/** + * @brief Static initializer for a mpsc queue + * + * Since the queue is + * + * @param symbol name of the queue + */ +#define MPSC_INIT(symbol) \ + { \ + .head = (struct mpsc_node *)&symbol.stub, \ + .tail = (struct mpsc_node *)&symbol.stub, \ + .stub = { \ + .next = NULL, \ + }, \ + } + +/** + * @brief Initialize queue + * + * @param q Queue to initialize or reset + */ +static inline void mpsc_init(struct mpsc *q) +{ + mpsc_ptr_set(q->head, &q->stub); + q->tail = &q->stub; + mpsc_ptr_set(q->stub.next, NULL); +} + +/** + * @brief Push a node + * + * @param q Queue to push the node to + * @param n Node to push into the queue + */ +static ALWAYS_INLINE void mpsc_push(struct mpsc *q, struct mpsc_node *n) +{ + struct mpsc_node *prev; + int key; + + mpsc_ptr_set(n->next, NULL); + + key = arch_irq_lock(); + prev = (struct mpsc_node *)mpsc_ptr_set_get(q->head, n); + mpsc_ptr_set(prev->next, n); + arch_irq_unlock(key); +} + +/** + * @brief Pop a node off of the list + * + * @retval NULL When no node is available + * @retval node When node is available + */ +static inline struct mpsc_node *mpsc_pop(struct mpsc *q) +{ + struct mpsc_node *head; + struct mpsc_node *tail = q->tail; + struct mpsc_node *next = (struct mpsc_node *)mpsc_ptr_get(tail->next); + + /* Skip over the stub/sentinel */ + if (tail == &q->stub) { + if (next == NULL) { + return NULL; + } + + q->tail = next; + tail = next; + next = (struct mpsc_node *)mpsc_ptr_get(next->next); + } + + /* If next is non-NULL then a valid node is found, return it */ + if (next != NULL) { + q->tail = next; + return tail; + } + + head = (struct mpsc_node *)mpsc_ptr_get(q->head); + + /* If next is NULL, and the tail != HEAD then the queue has pending + * updates that can't yet be accessed. + */ + if (tail != head) { + return NULL; + } + + mpsc_push(q, &q->stub); + + next = (struct mpsc_node *)mpsc_ptr_get(tail->next); + + if (next != NULL) { + q->tail = next; + return tail; + } + + return NULL; +} + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_SYS_MPSC_LOCKFREE_H_ */ diff --git a/include/zephyr/sys/mutex.h b/include/zephyr/sys/mutex.h index 1a7968e83cbb5..e34cc90d8d908 100644 --- a/include/zephyr/sys/mutex.h +++ b/include/zephyr/sys/mutex.h @@ -128,7 +128,7 @@ static inline int sys_mutex_unlock(struct sys_mutex *mutex) return z_sys_mutex_kernel_unlock(mutex); } -#include +#include #else #include diff --git a/include/zephyr/sys/rb.h b/include/zephyr/sys/rb.h index 3054119ff660c..71d671b6222f8 100644 --- a/include/zephyr/sys/rb.h +++ b/include/zephyr/sys/rb.h @@ -232,7 +232,7 @@ struct rbnode *z_rb_foreach_next(struct rbtree *tree, struct _rb_foreach *f); for (struct _rb_foreach __f = _RB_FOREACH_INIT(tree, node); \ ({struct rbnode *n = z_rb_foreach_next(tree, &__f); \ node = n ? CONTAINER_OF(n, __typeof__(*(node)), \ - field) : NULL; }) != NULL; \ + field) : NULL; (node); }) != NULL; \ /**/) /** @} */ diff --git a/include/zephyr/sys/spsc_lockfree.h b/include/zephyr/sys/spsc_lockfree.h new file mode 100644 index 0000000000000..3f769bfbd1689 --- /dev/null +++ b/include/zephyr/sys/spsc_lockfree.h @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SYS_SPSC_LOCKFREE_H_ +#define ZEPHYR_SYS_SPSC_LOCKFREE_H_ + +#include +#include +#include +#include +#include + +/** + * @brief Single Producer Single Consumer (SPSC) Lockfree Queue API + * @defgroup spsc_lockfree SPSC API + * @ingroup datastructure_apis + * @{ + */ + +/** + * @file spsc_lockfree.h + * + * @brief A lock-free and type safe power of 2 fixed sized single producer + * single consumer (SPSC) queue using a ringbuffer and atomics to ensure + * coherency. + * + * This SPSC queue implementation works on an array which wraps using a power of + * two size and uses a bit mask to perform a modulus. Atomics are used to allow + * single-producer single-consumer safe semantics without locks. Elements are + * expected to be of a fixed size. The API is type safe as the underlying buffer + * is typed and all usage is done through macros. + * + * An SPSC queue may be declared on a stack or statically and work as intended so + * long as its lifetime outlives any usage. Static declarations should be the + * preferred method as stack . It is meant to be a shared object between two + * execution contexts (ISR and a thread for example) + * + * An SPSC queue is safe to produce or consume in an ISR with O(1) push/pull. + * + * @warning SPSC is *not* safe to produce or consume in multiple execution + * contexts. + * + * Safe usage would be, where A and B are unique execution contexts: + * 1. ISR A producing and a Thread B consuming. + * 2. Thread A producing and ISR B consuming. + * 3. Thread A producing and Thread B consuming. + * 4. ISR A producing and ISR B consuming. + */ + +/** + * @private + * @brief Common SPSC attributes + * + * @warning Not to be manipulated without the macros! + */ +struct spsc { + /* private value only the producer thread should mutate */ + unsigned long acquire; + + /* private value only the consumer thread should mutate */ + unsigned long consume; + + /* producer mutable, consumer readable */ + atomic_t in; + + /* consumer mutable, producer readable */ + atomic_t out; + + /* mask used to automatically wrap values */ + const unsigned long mask; +}; + +/** + * @brief Statically initialize an spsc + * + * @param sz Size of the spsc, must be power of 2 (ex: 2, 4, 8) + * @param buf Buffer pointer + */ +#define SPSC_INITIALIZER(sz, buf) \ + { \ + ._spsc = \ + { \ + .acquire = 0, \ + .consume = 0, \ + .in = ATOMIC_INIT(0), \ + .out = ATOMIC_INIT(0), \ + .mask = sz - 1, \ + }, \ + .buffer = buf, \ + } + +/** + * @brief Declare an anonymous struct type for an spsc + * + * @param name Name of the spsc symbol to be provided + * @param type Type stored in the spsc + */ +#define SPSC_DECLARE(name, type) \ + static struct spsc_##name { \ + struct spsc _spsc; \ + type * const buffer; \ + } + +/** + * @brief Define an spsc with a fixed size + * + * @param name Name of the spsc symbol to be provided + * @param type Type stored in the spsc + * @param sz Size of the spsc, must be power of 2 (ex: 2, 4, 8) + */ +#define SPSC_DEFINE(name, type, sz) \ + BUILD_ASSERT(IS_POWER_OF_TWO(sz)); \ + static type __spsc_buf_##name[sz]; \ + SPSC_DECLARE(name, type) name = SPSC_INITIALIZER(sz, __spsc_buf_##name); + +/** + * @brief Size of the SPSC queue + * + * @param spsc SPSC reference + */ +#define spsc_size(spsc) ((spsc)->_spsc.mask + 1) + +/** + * @private + * @brief A number modulo the spsc size, assumes power of 2 + * + * @param spsc SPSC reference + * @param i Value to modulo to the size of the spsc + */ +#define z_spsc_mask(spsc, i) ((i) & (spsc)->_spsc.mask) + +/** + * @private + * @brief Load the current "in" index from the spsc as an unsigned long + */ +#define z_spsc_in(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.in) + +/** + * @private + * @brief Load the current "out" index from the spsc as an unsigned long + */ +#define z_spsc_out(spsc) (unsigned long)atomic_get(&(spsc)->_spsc.out) + +/** + * @brief Initialize/reset a spsc such that its empty + * + * Note that this is not safe to do while being used in a producer/consumer + * situation with multiple calling contexts (isrs/threads). + * + * @param spsc SPSC to initialize/reset + */ +#define spsc_reset(spsc) \ + ({ \ + (spsc)->_spsc.consume = 0; \ + (spsc)->_spsc.acquire = 0; \ + atomic_set(&(spsc)->_spsc.in, 0); \ + atomic_set(&(spsc)->_spsc.out, 0); \ + }) + +/** + * @brief Acquire an element to produce from the SPSC + * + * @param spsc SPSC to acquire an element from for producing + * + * @return A pointer to the acquired element or null if the spsc is full + */ +#define spsc_acquire(spsc) \ + ({ \ + unsigned long idx = z_spsc_in(spsc) + (spsc)->_spsc.acquire; \ + bool spsc_acq = (idx - z_spsc_out(spsc)) < spsc_size(spsc); \ + if (spsc_acq) { \ + (spsc)->_spsc.acquire += 1; \ + } \ + spsc_acq ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \ + }) + +/** + * @brief Produce one previously acquired element to the SPSC + * + * This makes one element available to the consumer immediately + * + * @param spsc SPSC to produce the previously acquired element or do nothing + */ +#define spsc_produce(spsc) \ + ({ \ + if ((spsc)->_spsc.acquire > 0) { \ + (spsc)->_spsc.acquire -= 1; \ + atomic_add(&(spsc)->_spsc.in, 1); \ + } \ + }) + +/** + * @brief Produce all previously acquired elements to the SPSC + * + * This makes all previous acquired elements available to the consumer + * immediately + * + * @param spsc SPSC to produce all previously acquired elements or do nothing + */ +#define spsc_produce_all(spsc) \ + ({ \ + if ((spsc)->_spsc.acquire > 0) { \ + unsigned long acquired = (spsc)->_spsc.acquire; \ + (spsc)->_spsc.acquire = 0; \ + atomic_add(&(spsc)->_spsc.in, acquired); \ + } \ + }) + +/** + * @brief Drop all previously acquired elements + * + * This makes all previous acquired elements available to be acquired again + * + * @param spsc SPSC to drop all previously acquired elements or do nothing + */ +#define spsc_drop_all(spsc) \ + do { \ + (spsc)->_spsc.acquire = 0; \ + } while (false) + +/** + * @brief Consume an element from the spsc + * + * @param spsc Spsc to consume from + * + * @return Pointer to element or null if no consumable elements left + */ +#define spsc_consume(spsc) \ + ({ \ + unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \ + bool has_consumable = (idx != z_spsc_in(spsc)); \ + if (has_consumable) { \ + (spsc)->_spsc.consume += 1; \ + } \ + has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \ + }) + +/** + * @brief Release a consumed element + * + * @param spsc SPSC to release consumed element or do nothing + */ +#define spsc_release(spsc) \ + ({ \ + if ((spsc)->_spsc.consume > 0) { \ + (spsc)->_spsc.consume -= 1; \ + atomic_add(&(spsc)->_spsc.out, 1); \ + } \ + }) + +/** + * @brief Release all consumed elements + * + * @param spsc SPSC to release consumed elements or do nothing + */ +#define spsc_release_all(spsc) \ + ({ \ + if ((spsc)->_spsc.consume > 0) { \ + unsigned long consumed = (spsc)->_spsc.consume; \ + (spsc)->_spsc.consume = 0; \ + atomic_add(&(spsc)->_spsc.out, consumed); \ + } \ + }) + +/** + * @brief Count of acquirable in spsc + * + * @param spsc SPSC to get item count for + */ +#define spsc_acquirable(spsc) \ + ({ (((spsc)->_spsc.in + (spsc)->_spsc.acquire) - (spsc)->_spsc.out) - spsc_size(spsc); }) + +/** + * @brief Count of consumables in spsc + * + * @param spsc SPSC to get item count for + */ +#define spsc_consumable(spsc) ({ (spsc)->_spsc.in - (spsc)->_spsc.out - (spsc)->_spsc.consume; }) + +/** + * @brief Peek at the first available item in queue + * + * @param spsc Spsc to peek into + * + * @return Pointer to element or null if no consumable elements left + */ +#define spsc_peek(spsc) \ + ({ \ + unsigned long idx = z_spsc_out(spsc) + (spsc)->_spsc.consume; \ + bool has_consumable = (idx != z_spsc_in(spsc)); \ + has_consumable ? &((spsc)->buffer[z_spsc_mask(spsc, idx)]) : NULL; \ + }) + +/** + * @brief Peek at the next item in the queue from a given one + * + * + * @param spsc SPSC to peek at + * @param item Pointer to an item in the queue + * + * @return Pointer to element or null if none left + */ +#define spsc_next(spsc, item) \ + ({ \ + unsigned long idx = ((item) - (spsc)->buffer); \ + bool has_next = \ + z_spsc_mask(spsc, (idx + 1)) != (z_spsc_mask(spsc, z_spsc_in(spsc))); \ + has_next ? &((spsc)->buffer[z_spsc_mask((spsc), idx + 1)]) : NULL; \ + }) + +/** + * @brief Get the previous item in the queue from a given one + * + * @param spsc SPSC to peek at + * @param item Pointer to an item in the queue + * + * @return Pointer to element or null if none left + */ +#define spsc_prev(spsc, item) \ + ({ \ + unsigned long idx = ((item) - &(spsc)->buffer[0]) / sizeof((spsc)->buffer[0]); \ + bool has_prev = idx != z_spsc_mask(spsc, z_spsc_out(spsc)); \ + has_prev ? &((spsc)->buffer[z_spsc_mask(spsc, idx - 1)]) : NULL; \ + }) + +/** + * @} + */ + +#endif /* ZEPHYR_SYS_SPSC_LOCKFREE_H_ */ diff --git a/include/zephyr/sys/sys_heap.h b/include/zephyr/sys/sys_heap.h index aa72793a2421e..82f7202048e08 100644 --- a/include/zephyr/sys/sys_heap.h +++ b/include/zephyr/sys/sys_heap.h @@ -162,11 +162,6 @@ void sys_heap_free(struct sys_heap *heap, void *mem); * new block fails, then NULL will be returned and the old block will * not be freed or modified. * - * @note The return of a NULL on failure is a different behavior than - * POSIX realloc(), which specifies that the original pointer will be - * returned (i.e. it is not possible to safely detect realloc() - * failure in POSIX, but it is here). - * * @param heap Heap from which to allocate * @param ptr Original pointer returned from a previous allocation * @param align Alignment in bytes, must be a power of two diff --git a/include/zephyr/sys/time_units.h b/include/zephyr/sys/time_units.h index 62c199bc488d9..f4deb93fb399f 100644 --- a/include/zephyr/sys/time_units.h +++ b/include/zephyr/sys/time_units.h @@ -56,7 +56,7 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) } #endif /* CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME */ -#if defined(__cplusplus) && __cplusplus >= 201402L +#if defined(__cplusplus) && (__cplusplus >= 201402L) #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) #define TIME_CONSTEXPR #else @@ -272,20 +272,21 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * #!/usr/bin/perl -w * use strict; * - * my %human = ("ms" => "milliseconds", + * my %human = ("sec" => "seconds", + * "ms" => "milliseconds", * "us" => "microseconds", * "ns" => "nanoseconds", * "cyc" => "hardware cycles", * "ticks" => "ticks"); * my %human_round = ("ceil" => "Rounds up", - * "near" => "Round nearest", - * "floor" => "Truncates"); + * "near" => "Round nearest", + * "floor" => "Truncates"); * * sub big { return $_[0] eq "us" || $_[0] eq "ns"; } - * sub prefix { return $_[0] eq "ms" || $_[0] eq "us" || $_[0] eq "ns"; } + * sub prefix { return $_[0] eq "sec" || $_[0] eq "ms" || $_[0] eq "us" || $_[0] eq "ns"; } * - * for my $from_unit ("ms", "us", "ns", "cyc", "ticks") { - * for my $to_unit ("ms", "us", "ns", "cyc", "ticks") { + * for my $from_unit ("sec", "ms", "us", "ns", "cyc", "ticks") { + * for my $to_unit ("sec", "ms", "us", "ns", "cyc", "ticks") { * next if $from_unit eq $to_unit; * next if prefix($from_unit) && prefix($to_unit); * for my $round ("floor", "near", "ceil") { @@ -301,7 +302,7 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * * my $hfrom = $human{$from_unit}; * my $hto = $human{$to_unit}; - * my $hround = $human_round{$round}; + * my $hround = $human_round{$round}; * print "/", "** \@brief Convert $hfrom to $hto. $ret32 bits. $hround.\n"; * print " *\n"; * print " * Converts time values in $hfrom to $hto.\n"; @@ -314,12 +315,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * print " * Truncates to the next lowest output unit.\n"; * } * print " *\n"; - * print " * \@param t Source time in $hfrom. uint64_t\n"; - * print " *\n"; + * print " * \@warning Generated. Do not edit. See above.\n"; + * print " *\n"; + * print " * \@param t Source time in $hfrom. uint64_t\n"; + * print " *\n"; * print " * \@return The converted time value in $hto. $type\n"; * print " *", "/\n"; - * - * print "/", "* Generated. Do not edit. See above. *", "/\n"; * print "#define $sym(t) \\\n"; * print "\tz_tmcvt_$ret32(t, Z_HZ_$from_unit, Z_HZ_$to_unit,"; * print " $const_hz, $rup, $roff)\n"; @@ -333,6 +334,7 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) /* Some more concise declarations to simplify the generator script and * save bytes below */ +#define Z_HZ_sec 1 #define Z_HZ_ms 1000 #define Z_HZ_us 1000000 #define Z_HZ_ns 1000000000 @@ -340,17 +342,210 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) #define Z_HZ_ticks CONFIG_SYS_CLOCK_TICKS_PER_SEC #define Z_CCYC (!IS_ENABLED(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME)) +/** @brief Convert seconds to hardware cycles. 32 bits. Truncates. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t + */ +#define k_sec_to_cyc_floor32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, false, false) + + +/** @brief Convert seconds to hardware cycles. 64 bits. Truncates. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 64 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t + */ +#define k_sec_to_cyc_floor64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, false, false) + + +/** @brief Convert seconds to hardware cycles. 32 bits. Round nearest. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t + */ +#define k_sec_to_cyc_near32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, false, true) + + +/** @brief Convert seconds to hardware cycles. 64 bits. Round nearest. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 64 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t + */ +#define k_sec_to_cyc_near64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, false, true) + + +/** @brief Convert seconds to hardware cycles. 32 bits. Rounds up. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint32_t + */ +#define k_sec_to_cyc_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, true, false) + + +/** @brief Convert seconds to hardware cycles. 64 bits. Rounds up. + * + * Converts time values in seconds to hardware cycles. + * Computes result in 64 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in hardware cycles. uint64_t + */ +#define k_sec_to_cyc_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_cyc, Z_CCYC, true, false) + + +/** @brief Convert seconds to ticks. 32 bits. Truncates. + * + * Converts time values in seconds to ticks. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint32_t + */ +#define k_sec_to_ticks_floor32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_ticks, true, false, false) + + +/** @brief Convert seconds to ticks. 64 bits. Truncates. + * + * Converts time values in seconds to ticks. + * Computes result in 64 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint64_t + */ +#define k_sec_to_ticks_floor64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_ticks, true, false, false) + + +/** @brief Convert seconds to ticks. 32 bits. Round nearest. + * + * Converts time values in seconds to ticks. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint32_t + */ +#define k_sec_to_ticks_near32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_ticks, true, false, true) + + +/** @brief Convert seconds to ticks. 64 bits. Round nearest. + * + * Converts time values in seconds to ticks. + * Computes result in 64 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint64_t + */ +#define k_sec_to_ticks_near64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_ticks, true, false, true) + + +/** @brief Convert seconds to ticks. 32 bits. Rounds up. + * + * Converts time values in seconds to ticks. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint32_t + */ +#define k_sec_to_ticks_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_sec, Z_HZ_ticks, true, true, false) + + +/** @brief Convert seconds to ticks. 64 bits. Rounds up. + * + * Converts time values in seconds to ticks. + * Computes result in 64 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in seconds. uint64_t + * + * @return The converted time value in ticks. uint64_t + */ +#define k_sec_to_ticks_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_sec, Z_HZ_ticks, true, true, false) + + /** @brief Convert milliseconds to hardware cycles. 32 bits. Truncates. * * Converts time values in milliseconds to hardware cycles. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_floor32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, false) @@ -361,11 +556,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_floor64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, false) @@ -376,11 +572,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_near32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, true) @@ -391,11 +588,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_near64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, false, true) @@ -406,11 +604,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, true, false) @@ -421,11 +620,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_cyc_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_cyc, Z_CCYC, true, false) @@ -436,11 +636,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_floor32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_ticks, true, false, false) @@ -451,11 +652,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_floor64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_ticks, true, false, false) @@ -466,11 +668,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_near32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_ticks, true, false, true) @@ -481,11 +684,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_near64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_ticks, true, false, true) @@ -496,11 +700,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ms, Z_HZ_ticks, true, true, false) @@ -511,11 +716,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in milliseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ms_to_ticks_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ms, Z_HZ_ticks, true, true, false) @@ -526,11 +732,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_floor32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false) @@ -541,11 +748,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_floor64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, false) @@ -556,11 +764,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_near32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, true) @@ -571,11 +780,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_near64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, false, true) @@ -586,11 +796,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_ceil32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false) @@ -601,11 +812,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_cyc_ceil64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_cyc, Z_CCYC, true, false) @@ -616,11 +828,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_floor32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_ticks, true, false, false) @@ -631,11 +844,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_floor64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_ticks, true, false, false) @@ -646,11 +860,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_near32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_ticks, true, false, true) @@ -661,11 +876,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_near64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_ticks, true, false, true) @@ -676,11 +892,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_ceil32(t) \ z_tmcvt_32(t, Z_HZ_us, Z_HZ_ticks, true, true, false) @@ -691,11 +908,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in microseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_us_to_ticks_ceil64(t) \ z_tmcvt_64(t, Z_HZ_us, Z_HZ_ticks, true, true, false) @@ -706,11 +924,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_floor32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false) @@ -721,11 +940,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_floor64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, false) @@ -736,11 +956,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_near32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, true) @@ -751,11 +972,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_near64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, false, true) @@ -766,11 +988,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false) @@ -781,11 +1004,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_cyc_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_cyc, Z_CCYC, true, false) @@ -796,11 +1020,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_floor32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_ticks, true, false, false) @@ -811,11 +1036,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_floor64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, false, false) @@ -826,11 +1052,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_near32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_ticks, true, false, true) @@ -841,11 +1068,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_near64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, false, true) @@ -856,11 +1084,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ns, Z_HZ_ticks, true, true, false) @@ -871,26 +1100,124 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in nanoseconds. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ns_to_ticks_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ns, Z_HZ_ticks, true, true, false) +/** @brief Convert hardware cycles to seconds. 32 bits. Truncates. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_cyc_to_sec_floor32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, false, false) + + +/** @brief Convert hardware cycles to seconds. 64 bits. Truncates. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 64 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_cyc_to_sec_floor64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, false, false) + + +/** @brief Convert hardware cycles to seconds. 32 bits. Round nearest. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_cyc_to_sec_near32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, false, true) + + +/** @brief Convert hardware cycles to seconds. 64 bits. Round nearest. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 64 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_cyc_to_sec_near64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, false, true) + + +/** @brief Convert hardware cycles to seconds. 32 bits. Rounds up. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_cyc_to_sec_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, true, false) + + +/** @brief Convert hardware cycles to seconds. 64 bits. Rounds up. + * + * Converts time values in hardware cycles to seconds. + * Computes result in 64 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in hardware cycles. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_cyc_to_sec_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_sec, Z_CCYC, true, false) + + /** @brief Convert hardware cycles to milliseconds. 32 bits. Truncates. * * Converts time values in hardware cycles to milliseconds. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_floor32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, false) @@ -901,11 +1228,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_floor64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, false) @@ -916,11 +1244,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_near32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, true) @@ -931,11 +1260,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_near64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, false, true) @@ -946,11 +1276,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_ceil32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, true, false) @@ -961,11 +1292,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ms_ceil64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ms, Z_CCYC, true, false) @@ -976,11 +1308,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_floor32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false) @@ -991,11 +1324,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_floor64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, false) @@ -1006,11 +1340,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_near32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, true) @@ -1021,11 +1356,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_near64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, false, true) @@ -1036,11 +1372,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_ceil32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false) @@ -1051,11 +1388,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_us_ceil64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_us, Z_CCYC, true, false) @@ -1066,11 +1404,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_floor32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false) @@ -1081,11 +1420,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_floor64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, false) @@ -1096,11 +1436,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_near32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, true) @@ -1111,11 +1452,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_near64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, false, true) @@ -1126,11 +1468,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_ceil32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false) @@ -1141,11 +1484,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ns_ceil64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ns, Z_CCYC, true, false) @@ -1156,11 +1500,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_floor32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, false) @@ -1171,11 +1516,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_floor64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, false) @@ -1186,11 +1532,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_near32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, true) @@ -1201,11 +1548,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_near64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, false, true) @@ -1216,11 +1564,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_ceil32(t) \ z_tmcvt_32(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, false) @@ -1231,26 +1580,124 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in hardware cycles. uint64_t * * @return The converted time value in ticks. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_cyc_to_ticks_ceil64(t) \ z_tmcvt_64(t, Z_HZ_cyc, Z_HZ_ticks, Z_CCYC, true, false) +/** @brief Convert ticks to seconds. 32 bits. Truncates. + * + * Converts time values in ticks to seconds. + * Computes result in 32 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_ticks_to_sec_floor32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_sec, true, false, false) + + +/** @brief Convert ticks to seconds. 64 bits. Truncates. + * + * Converts time values in ticks to seconds. + * Computes result in 64 bit precision. + * Truncates to the next lowest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_ticks_to_sec_floor64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_sec, true, false, false) + + +/** @brief Convert ticks to seconds. 32 bits. Round nearest. + * + * Converts time values in ticks to seconds. + * Computes result in 32 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_ticks_to_sec_near32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_sec, true, false, true) + + +/** @brief Convert ticks to seconds. 64 bits. Round nearest. + * + * Converts time values in ticks to seconds. + * Computes result in 64 bit precision. + * Rounds to the nearest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_ticks_to_sec_near64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_sec, true, false, true) + + +/** @brief Convert ticks to seconds. 32 bits. Rounds up. + * + * Converts time values in ticks to seconds. + * Computes result in 32 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint32_t + */ +#define k_ticks_to_sec_ceil32(t) \ + z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_sec, true, true, false) + + +/** @brief Convert ticks to seconds. 64 bits. Rounds up. + * + * Converts time values in ticks to seconds. + * Computes result in 64 bit precision. + * Rounds up to the next highest output unit. + * + * @warning Generated. Do not edit. See above. + * + * @param t Source time in ticks. uint64_t + * + * @return The converted time value in seconds. uint64_t + */ +#define k_ticks_to_sec_ceil64(t) \ + z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_sec, true, true, false) + + /** @brief Convert ticks to milliseconds. 32 bits. Truncates. * * Converts time values in ticks to milliseconds. * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_floor32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ms, true, false, false) @@ -1261,11 +1708,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_floor64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ms, true, false, false) @@ -1276,11 +1724,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_near32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ms, true, false, true) @@ -1291,11 +1740,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_near64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ms, true, false, true) @@ -1306,11 +1756,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ms, true, true, false) @@ -1321,11 +1772,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in milliseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ms_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ms, true, true, false) @@ -1336,11 +1788,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_floor32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_us, true, false, false) @@ -1351,11 +1804,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_floor64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_us, true, false, false) @@ -1366,11 +1820,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_near32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_us, true, false, true) @@ -1381,11 +1836,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_near64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_us, true, false, true) @@ -1396,11 +1852,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_us, true, true, false) @@ -1411,11 +1868,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in microseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_us_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_us, true, true, false) @@ -1426,11 +1884,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_floor32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ns, true, false, false) @@ -1441,11 +1900,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_floor64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ns, true, false, false) @@ -1456,11 +1916,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_near32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ns, true, false, true) @@ -1471,11 +1932,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_near64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ns, true, false, true) @@ -1486,11 +1948,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_ns, true, true, false) @@ -1501,11 +1964,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in nanoseconds. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_ns_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_ns, true, true, false) @@ -1516,11 +1980,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_floor32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, false) @@ -1531,11 +1996,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Truncates to the next lowest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_floor64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, false) @@ -1546,11 +2012,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_near32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, true) @@ -1561,11 +2028,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds to the nearest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_near64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, false, true) @@ -1576,11 +2044,12 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 32 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint32_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_ceil32(t) \ z_tmcvt_32(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, false) @@ -1591,16 +2060,17 @@ static inline int z_impl_sys_clock_hw_cycles_per_sec_runtime_get(void) * Computes result in 64 bit precision. * Rounds up to the next highest output unit. * + * @warning Generated. Do not edit. See above. + * * @param t Source time in ticks. uint64_t * * @return The converted time value in hardware cycles. uint64_t */ -/* Generated. Do not edit. See above. */ #define k_ticks_to_cyc_ceil64(t) \ z_tmcvt_64(t, Z_HZ_ticks, Z_HZ_cyc, Z_CCYC, true, false) #if defined(CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME) -#include +#include #endif #undef TIME_CONSTEXPR diff --git a/include/zephyr/sys/util.h b/include/zephyr/sys/util.h index b457862bb9770..fe04c058b1e4a 100644 --- a/include/zephyr/sys/util.h +++ b/include/zephyr/sys/util.h @@ -271,6 +271,16 @@ extern "C" { ((type *)(((char *)(ptr)) - offsetof(type, field))); \ }) +/** + * @brief Report the size of a struct field in bytes. + * + * @param type The structure containing the field of interest. + * @param member The field to return the size of. + * + * @return The field size. + */ +#define SIZEOF_FIELD(type, member) sizeof((((type *)0)->member)) + /** * @brief Concatenate input arguments * diff --git a/include/zephyr/syscall.h b/include/zephyr/syscall.h index 73a3a648d2378..35cb36554a0a7 100644 --- a/include/zephyr/syscall.h +++ b/include/zephyr/syscall.h @@ -8,7 +8,7 @@ #ifndef ZEPHYR_INCLUDE_SYSCALL_H_ #define ZEPHYR_INCLUDE_SYSCALL_H_ -#include +#include #include #include diff --git a/include/zephyr/toolchain/gcc.h b/include/zephyr/toolchain/gcc.h index 8f1dcda0156a9..9af23fb219ea1 100644 --- a/include/zephyr/toolchain/gcc.h +++ b/include/zephyr/toolchain/gcc.h @@ -82,9 +82,9 @@ * static_assert() is not available) */ #elif !defined(__cplusplus) && \ - ((__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) || \ + (((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6))) || \ (__STDC_VERSION__) >= 201100) -#define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG) +#define BUILD_ASSERT(EXPR, MSG...) _Static_assert((EXPR), "" MSG) #else #define BUILD_ASSERT(EXPR, MSG...) #endif @@ -138,7 +138,7 @@ __extension__ ({ \ }) -#if __GNUC__ >= 7 && (defined(CONFIG_ARM) || defined(CONFIG_ARM64)) +#if (__GNUC__ >= 7) && (defined(CONFIG_ARM) || defined(CONFIG_ARM64)) /* Version of UNALIGNED_PUT() which issues a compiler_barrier() after * the store. It is required to workaround an apparent optimization @@ -590,7 +590,7 @@ do { \ /* random suffix to avoid naming conflict */ \ __typeof__(a) _value_a_ = (a); \ __typeof__(b) _value_b_ = (b); \ - _value_a_ > _value_b_ ? _value_a_ : _value_b_; \ + (_value_a_ > _value_b_) ? _value_a_ : _value_b_; \ }) /** @brief Return smaller value of two provided expressions. @@ -602,7 +602,7 @@ do { \ /* random suffix to avoid naming conflict */ \ __typeof__(a) _value_a_ = (a); \ __typeof__(b) _value_b_ = (b); \ - _value_a_ < _value_b_ ? _value_a_ : _value_b_; \ + (_value_a_ < _value_b_) ? _value_a_ : _value_b_; \ }) /** @brief Return a value clamped to a given range. diff --git a/include/zephyr/toolchain/llvm.h b/include/zephyr/toolchain/llvm.h index 8a78d4e840486..d2bc4aeac34f2 100644 --- a/include/zephyr/toolchain/llvm.h +++ b/include/zephyr/toolchain/llvm.h @@ -30,84 +30,102 @@ #include -#ifndef __INT8_C -#define __INT8_C(x) x -#endif - -#ifndef INT8_C -#define INT8_C(x) __INT8_C(x) -#endif - -#ifndef __UINT8_C -#define __UINT8_C(x) x ## U -#endif - -#ifndef UINT8_C -#define UINT8_C(x) __UINT8_C(x) -#endif - -#ifndef __INT16_C -#define __INT16_C(x) x -#endif - -#ifndef INT16_C -#define INT16_C(x) __INT16_C(x) -#endif - -#ifndef __UINT16_C -#define __UINT16_C(x) x ## U -#endif - -#ifndef UINT16_C -#define UINT16_C(x) __UINT16_C(x) -#endif - -#ifndef __INT32_C +/* + * Provide these definitions only when minimal libc is used. + * Avoid collision with defines from include/zephyr/toolchain/zephyr_stdint.h + */ +#ifdef CONFIG_MINIMAL_LIBC +#ifndef CONFIG_ENFORCE_ZEPHYR_STDINT + +#define __int_c(v, suffix) v ## suffix +#define int_c(v, suffix) __int_c(v, suffix) +#define uint_c(v, suffix) __int_c(v ## U, suffix) + +#ifdef __INT64_TYPE__ +#undef __int_least64_c_suffix__ +#undef __int_least32_c_suffix__ +#undef __int_least16_c_suffix__ +#undef __int_least8_c_suffix__ +#ifdef __INT64_C_SUFFIX__ +#define __int_least64_c_suffix__ __INT64_C_SUFFIX__ +#define __int_least32_c_suffix__ __INT64_C_SUFFIX__ +#define __int_least16_c_suffix__ __INT64_C_SUFFIX__ +#define __int_least8_c_suffix__ __INT64_C_SUFFIX__ +#endif /* __INT64_C_SUFFIX__ */ +#endif /* __INT64_TYPE__ */ + +#ifdef __INT_LEAST64_TYPE__ +#ifdef __int_least64_c_suffix__ +#define __INT64_C(x) int_c(x, __int_least64_c_suffix__) +#define __UINT64_C(x) uint_c(x, __int_least64_c_suffix__) +#else +#define __INT64_C(x) x +#define __UINT64_C(x) x ## U +#endif /* __int_least64_c_suffix__ */ +#endif /* __INT_LEAST64_TYPE__ */ + +#ifdef __INT32_TYPE__ +#undef __int_least32_c_suffix__ +#undef __int_least16_c_suffix__ +#undef __int_least8_c_suffix__ +#ifdef __INT32_C_SUFFIX__ +#define __int_least32_c_suffix__ __INT32_C_SUFFIX__ +#define __int_least16_c_suffix__ __INT32_C_SUFFIX__ +#define __int_least8_c_suffix__ __INT32_C_SUFFIX__ +#endif /* __INT32_C_SUFFIX__ */ +#endif /* __INT32_TYPE__ */ + +#ifdef __INT_LEAST32_TYPE__ +#ifdef __int_least32_c_suffix__ +#define __INT32_C(x) int_c(x, __int_least32_c_suffix__) +#define __UINT32_C(x) uint_c(x, __int_least32_c_suffix__) +#else #define __INT32_C(x) x -#endif - -#ifndef INT32_C -#define INT32_C(x) __INT32_C(x) -#endif - -#ifndef __UINT32_C #define __UINT32_C(x) x ## U -#endif - -#ifndef UINT32_C -#define UINT32_C(x) __UINT32_C(x) -#endif - -#ifndef __INT64_C -#define __INT64_C(x) x -#endif - -#ifndef INT64_C -#define INT64_C(x) __INT64_C(x) -#endif - -#ifndef __UINT64_C -#define __UINT64_C(x) x ## ULL -#endif - -#ifndef UINT64_C -#define UINT64_C(x) __UINT64_C(x) -#endif - -#ifndef __INTMAX_C -#define __INTMAX_C(x) x -#endif +#endif /* __int_least32_c_suffix__ */ +#endif /* __INT_LEAST32_TYPE__ */ + +#ifdef __INT16_TYPE__ +#undef __int_least16_c_suffix__ +#undef __int_least8_c_suffix__ +#ifdef __INT16_C_SUFFIX__ +#define __int_least16_c_suffix__ __INT16_C_SUFFIX__ +#define __int_least8_c_suffix__ __INT16_C_SUFFIX__ +#endif /* __INT16_C_SUFFIX__ */ +#endif /* __INT16_TYPE__ */ + +#ifdef __INT_LEAST16_TYPE__ +#ifdef __int_least16_c_suffix__ +#define __INT16_C(x) int_c(x, __int_least16_c_suffix__) +#define __UINT16_C(x) uint_c(x, __int_least16_c_suffix__) +#else +#define __INT16_C(x) x +#define __UINT16_C(x) x ## U +#endif /* __int_least16_c_suffix__ */ +#endif /* __INT_LEAST16_TYPE__ */ + +#ifdef __INT8_TYPE__ +#undef __int_least8_c_suffix__ +#ifdef __INT8_C_SUFFIX__ +#define __int_least8_c_suffix__ __INT8_C_SUFFIX__ +#endif /* __INT8_C_SUFFIX__ */ +#endif /* __INT8_TYPE__ */ + +#ifdef __INT_LEAST8_TYPE__ +#ifdef __int_least8_c_suffix__ +#define __INT8_C(x) int_c(x, __int_least8_c_suffix__) +#define __UINT8_C(x) uint_c(x, __int_least8_c_suffix__) +#else +#define __INT8_C(x) x +#define __UINT8_C(x) x ## U +#endif /* __int_least8_c_suffix__ */ +#endif /* __INT_LEAST8_TYPE__ */ -#ifndef INTMAX_C -#define INTMAX_C(x) __INTMAX_C(x) -#endif +#endif /* !CONFIG_ENFORCE_ZEPHYR_STDINT */ -#ifndef __UINTMAX_C -#define __UINTMAX_C(x) x ## ULL -#endif +#define __INTMAX_C(x) int_c(x, __INTMAX_C_SUFFIX__) +#define __UINTMAX_C(x) int_c(x, __UINTMAX_C_SUFFIX__) -#ifndef UINTMAX_C -#define UINTMAX_C(x) __UINTMAX_C(x) -#endif +#endif /* CONFIG_MINIMAL_LIBC */ #endif /* ZEPHYR_INCLUDE_TOOLCHAIN_LLVM_H_ */ diff --git a/include/zephyr/toolchain/mwdt.h b/include/zephyr/toolchain/mwdt.h index 0da5e7bbee57a..c4a142e4fb3b0 100644 --- a/include/zephyr/toolchain/mwdt.h +++ b/include/zephyr/toolchain/mwdt.h @@ -99,7 +99,7 @@ /* For cpp98 */ #define BUILD_ASSERT(EXPR, MSG...) #else -#define BUILD_ASSERT(EXPR, MSG...) _Static_assert(EXPR, "" MSG) +#define BUILD_ASSERT(EXPR, MSG...) _Static_assert((EXPR), "" MSG) #endif #define __builtin_arc_nop() _nop() diff --git a/include/zephyr/tracing/tracing.h b/include/zephyr/tracing/tracing.h index f1bbddeec5143..d243c27de969e 100644 --- a/include/zephyr/tracing/tracing.h +++ b/include/zephyr/tracing/tracing.h @@ -1690,6 +1690,25 @@ */ #define sys_port_trace_k_heap_free(h) +/** + * @brief Trace Heap realloc enter + * @param h Heap object + * @param ptr Pointer to reallocate + * @param bytes Bytes to reallocate + * @param timeout Timeout period + */ +#define sys_port_trace_k_heap_realloc_enter(h, ptr, bytes, timeout) + +/** + * @brief Trace Heap realloc exit + * @param h Heap object + * @param ptr Pointer to reallocate + * @param bytes Bytes to reallocate + * @param timeout Timeout period + * @param ret Return value + */ +#define sys_port_trace_k_heap_realloc_exit(h, ptr, bytes, timeout, ret) + /** * @brief Trace System Heap aligned alloc enter * @param heap Heap object @@ -1743,6 +1762,19 @@ */ #define sys_port_trace_k_heap_sys_k_calloc_exit(heap, ret) +/** + * @brief Trace System heap realloc enter + * @param heap + */ +#define sys_port_trace_k_heap_sys_k_realloc_enter(heap, ptr) + +/** + * @brief Trace System heap realloc exit + * @param heap Heap object + * @param ret Return value + */ +#define sys_port_trace_k_heap_sys_k_realloc_exit(heap, ptr, ret) + /** @} */ /* end of subsys_tracing_apis_heap */ /** @@ -1994,6 +2026,304 @@ /** @} */ /* end of subsys_tracing_apis_pm_device_runtime */ +/** + * @brief Network Socket Tracing APIs + * @defgroup subsys_tracing_apis_socket Network Socket Tracing APIs + * @{ + */ + +/** + * @brief Trace init of network sockets + * @param socket Network socket is returned + * @param family Socket address family + * @param type Socket type + * @param proto Socket protocol + */ +#define sys_port_trace_socket_init(socket, family, type, proto) + +/** + * @brief Trace close of network sockets + * @param socket Socket object + */ +#define sys_port_trace_socket_close_enter(socket) + +/** + * @brief Trace network socket close attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_close_exit(socket, ret) + +/** + * @brief Trace shutdown of network sockets + * @param socket Socket object + * @param how Socket shutdown type + */ +#define sys_port_trace_socket_shutdown_enter(socket, how) + +/** + * @brief Trace network socket shutdown attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_shutdown_exit(socket, ret) + +/** + * @brief Trace bind of network sockets + * @param socket Socket object + * @param addr Network address to bind + * @param addrlen Address length + */ +#define sys_port_trace_socket_bind_enter(socket, addr, addrlen) + +/** + * @brief Trace network socket bind attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_bind_exit(socket, ret) + +/** + * @brief Trace connect of network sockets + * @param socket Socket object + * @param addr Network address to bind + * @param addrlen Address length + */ +#define sys_port_trace_socket_connect_enter(socket, addr, addrlen) + +/** + * @brief Trace network socket connect attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_connect_exit(socket, ret) + +/** + * @brief Trace listen of network sockets + * @param socket Socket object + * @param backlog Socket backlog length + */ +#define sys_port_trace_socket_listen_enter(socket, backlog) + +/** + * @brief Trace network socket listen attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_listen_exit(socket, ret) + +/** + * @brief Trace accept of network sockets + * @param socket Socket object + */ +#define sys_port_trace_socket_accept_enter(socket) + +/** + * @brief Trace network socket accept attempt + * @param socket Socket object + * @param addr Peer network address + * @param addrlen Network address length + * @param ret Return value + */ +#define sys_port_trace_socket_accept_exit(socket, addr, addrlen, ret) + +/** + * @brief Trace sendto of network sockets + * @param socket Socket object + * @param len Length of the data to send + * @param flags Flags for this send operation + * @param dest_addr Destination network address + * @param addrlen Network address length + */ +#define sys_port_trace_socket_sendto_enter(socket, len, flags, dest_addr, addrlen) + +/** + * @brief Trace network socket sendto attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_sendto_exit(socket, ret) + +/** + * @brief Trace sendmsg of network sockets + * @param socket Socket object + * @param msg Data to send + * @param flags Flags for this send operation + */ +#define sys_port_trace_socket_sendmsg_enter(socket, msg, flags) + +/** + * @brief Trace network socket sendmsg attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_sendmsg_exit(socket, ret) + +/** + * @brief Trace recvfrom of network sockets + * @param socket Socket object + * @param max_len Maximum length of the data we can receive + * @param flags Flags for this receive operation + * @param addr Remote network address + * @param addrlen Network address length + */ +#define sys_port_trace_socket_recvfrom_enter(socket, max_len, flags, addr, addrlen) + +/** + * @brief Trace network socket recvfrom attempt + * @param socket Socket object + * @param src_addr Peer network address that send the data + * @param addrlen Length of the network address + * @param ret Return value + */ +#define sys_port_trace_socket_recvfrom_exit(socket, src_addr, addrlen, ret) + +/** + * @brief Trace recvmsg of network sockets + * @param socket Socket object + * @param msg Message buffer to receive + * @param flags Flags for this receive operation + */ +#define sys_port_trace_socket_recvmsg_enter(socket, msg, flags) + +/** + * @brief Trace network socket recvmsg attempt + * @param socket Socket object + * @param msg Message buffer received + * @param ret Return value + */ +#define sys_port_trace_socket_recvmsg_exit(socket, msg, ret) + +/** + * @brief Trace fcntl of network sockets + * @param socket Socket object + * @param cmd Command to set for this socket + * @param flags Flags for this receive operation + */ +#define sys_port_trace_socket_fcntl_enter(socket, cmd, flags) + +/** + * @brief Trace network socket fcntl attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_fcntl_exit(socket, ret) + +/** + * @brief Trace ioctl of network sockets + * @param socket Socket object + * @param req Request to set for this socket + */ +#define sys_port_trace_socket_ioctl_enter(socket, req) + +/** + * @brief Trace network socket ioctl attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_ioctl_exit(socket, ret) + +/** + * @brief Trace polling of network sockets + * @param fds Set of socket object + * @param nfds Number of socket objects in the set + * @param timeout Timeout for the poll operation + */ +#define sys_port_trace_socket_poll_enter(fds, nfds, timeout) + +/** + * @brief Trace network socket poll attempt + * @param fds Set of socket object + * @param nfds Number of socket objects in the set + * @param ret Return value + */ +#define sys_port_trace_socket_poll_exit(fds, nfds, ret) + +/** + * @brief Trace getsockopt of network sockets + * @param socket Socket object + * @param level Option level + * @param optname Option name + */ +#define sys_port_trace_socket_getsockopt_enter(socket, level, optname) + +/** + * @brief Trace network socket getsockopt attempt + * @param socket Socket object + * @param level Option level + * @param optname Option name + * @param optval Option value + * @param optlen Option value length + * @param ret Return value + */ +#define sys_port_trace_socket_getsockopt_exit(socket, level, optname, optval, optlen, ret) + +/** + * @brief Trace setsockopt of network sockets + * @param socket Socket object + * @param level Option level + * @param optname Option name + * @param optval Option value + * @param optlen Option value length + */ +#define sys_port_trace_socket_setsockopt_enter(socket, level, optname, optval, optlen) + +/** + * @brief Trace network socket setsockopt attempt + * @param socket Socket object + * @param ret Return value + */ +#define sys_port_trace_socket_setsockopt_exit(socket, ret) + +/** + * @brief Trace getpeername of network sockets + * @param socket Socket object + */ +#define sys_port_trace_socket_getpeername_enter(socket) + +/** + * @brief Trace network socket getpeername attempt + * @param socket Socket object + * @param addr Peer socket network address + * @param addrlen Length of the network address + * @param ret Return value + */ +#define sys_port_trace_socket_getpeername_exit(socket, addr, addrlen, ret) + +/** + * @brief Trace getsockname of network sockets + * @param socket Socket object + */ +#define sys_port_trace_socket_getsockname_enter(socket) + +/** + * @brief Trace network socket getsockname attempt + * @param socket Socket object + * @param addr Local socket network address + * @param addrlen Length of the network address + * @param ret Return value + */ +#define sys_port_trace_socket_getsockname_exit(socket, addr, addrlen, ret) + +/** + * @brief Trace socketpair enter call + * @param family Network address family + * @param type Socket type + * @param proto Socket protocol + * @param sv Socketpair buffer + */ +#define sys_port_trace_socket_socketpair_enter(family, type, proto, sv) + +/** + * @brief Trace network socketpair open attempt + * @param socket_A Socketpair first socket object + * @param socket_B Socketpair second socket object + * @param ret Return value + */ +#define sys_port_trace_socket_socketpair_exit(socket_A, socket_B, ret) + +/** @} */ /* end of subsys_tracing_apis_socket */ + #if defined(CONFIG_PERCEPIO_TRACERECORDER) #include "tracing_tracerecorder.h" #else diff --git a/include/zephyr/tracing/tracing_macros.h b/include/zephyr/tracing/tracing_macros.h index 7ed990617d5ed..80eed3d0f6d0f 100644 --- a/include/zephyr/tracing/tracing_macros.h +++ b/include/zephyr/tracing/tracing_macros.h @@ -185,6 +185,12 @@ #define sys_port_trace_pm_is_disabled 1 #endif +#if defined(CONFIG_TRACING_NETWORKING) + #define sys_port_trace_type_mask_socket(trace_call) trace_call +#else + #define sys_port_trace_type_mask_socket(trace_call) +#endif + /* * We cannot positively enumerate all traced APIs, as applications may trace * arbitrary custom APIs we know nothing about. Therefore we demand that tracing diff --git a/include/zephyr/tracing/tracking.h b/include/zephyr/tracing/tracking.h index 8f63fbaffa45e..bee43153191cc 100644 --- a/include/zephyr/tracing/tracking.h +++ b/include/zephyr/tracing/tracking.h @@ -95,6 +95,9 @@ extern struct k_event *_track_list_k_event; #define sys_port_track_k_event_init(event) \ sys_track_k_event_init(event); +#define sys_port_track_socket_init(sock, family, type, proto) \ + sys_track_socket_init(sock, family, type, proto); + void sys_track_k_timer_init(struct k_timer *timer); void sys_track_k_mem_slab_init(struct k_mem_slab *slab); void sys_track_k_sem_init(struct k_sem *sem); @@ -105,6 +108,7 @@ void sys_track_k_mbox_init(struct k_mbox *mbox); void sys_track_k_pipe_init(struct k_pipe *pipe); void sys_track_k_queue_init(struct k_queue *queue); void sys_track_k_event_init(struct k_event *event); +void sys_track_socket_init(int sock); /** @endcond */ @@ -142,6 +146,7 @@ void sys_track_k_event_init(struct k_event *event); #define sys_port_track_k_heap_free(h) #define sys_port_track_k_heap_init(h) #define sys_port_track_k_event_init(event) +#define sys_port_track_socket_init(sock, family, type, proto) #endif diff --git a/include/zephyr/usb/bos.h b/include/zephyr/usb/bos.h index b7a0ef08339fe..f73e7c06678ea 100644 --- a/include/zephyr/usb/bos.h +++ b/include/zephyr/usb/bos.h @@ -17,12 +17,13 @@ * @{ */ -/** - * @brief Helper macro to place the BOS compatibility descriptor - * in the right memory section. - */ -#define USB_DEVICE_BOS_DESC_DEFINE_CAP \ - static __in_section(usb, bos_desc_area, 1) __aligned(1) __used +/** Root BOS Descriptor */ +struct usb_bos_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t wTotalLength; + uint8_t bNumDeviceCaps; +} __packed; /** Device capability type codes */ enum usb_bos_capability_types { @@ -62,45 +63,6 @@ struct usb_bos_capability_msos { uint8_t bAltEnumCode; } __packed; -/** - * @brief Register BOS capability descriptor - * - * This function should be used by the application to register BOS capability - * descriptors before the USB device stack is enabled. - * - * @param[in] hdr Pointer to BOS capability descriptor - */ -void usb_bos_register_cap(struct usb_bos_platform_descriptor *hdr); - -/** - * @cond INTERNAL_HIDDEN - * Internally used functions - */ - -/* BOS Descriptor (root descriptor) */ -struct usb_bos_descriptor { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t wTotalLength; - uint8_t bNumDeviceCaps; -} __packed; - -#define USB_DEVICE_BOS_DESC_DEFINE_HDR \ - static __in_section(usb, bos_desc_area, 0) __aligned(1) __used - -size_t usb_bos_get_length(void); - -void usb_bos_fix_total_length(void); - -const void *usb_bos_get_header(void); - -#if defined(CONFIG_USB_DEVICE_BOS) -int usb_handle_bos(struct usb_setup_packet *setup, int32_t *len, uint8_t **data); -#else -#define usb_handle_bos(x, y, z) -ENOTSUP -#endif -/** @endcond */ - /** * @} */ diff --git a/include/zephyr/usb/class/usb_hid.h b/include/zephyr/usb/class/usb_hid.h index 8fc380b970e0b..f15d0526e4ac1 100644 --- a/include/zephyr/usb/class/usb_hid.h +++ b/include/zephyr/usb/class/usb_hid.h @@ -54,9 +54,7 @@ struct hid_ops { * the next transfer. */ hid_int_ready_callback int_in_ready; -#ifdef CONFIG_ENABLE_HID_INT_OUT_EP hid_int_ready_callback int_out_ready; -#endif }; /** diff --git a/include/zephyr/usb/class/usbd_hid.h b/include/zephyr/usb/class/usbd_hid.h new file mode 100644 index 0000000000000..9798b081093da --- /dev/null +++ b/include/zephyr/usb/class/usbd_hid.h @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief USBD HID device API header + */ + +#ifndef ZEPHYR_INCLUDE_USBD_HID_CLASS_DEVICE_H_ +#define ZEPHYR_INCLUDE_USBD_HID_CLASS_DEVICE_H_ + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief USBD HID Device API + * @defgroup usbd_hid_device USBD HID device API + * @ingroup usb + * @{ + */ + +/* + * HID Device overview: + * + * +---------------------+ + * | | + * | | + * | HID Device | + * | User "top half" | + * | of the device that +-------+ + * | deals with input | | + * | sampling | | + * | | | + * | | | + * | ------------------- | | + * | | | + * | HID Device user | | + * | callbacks | | + * | handlers | | + * +---------------------+ | + * ^ | HID Device Driver API: + * | | + * set_protocol() | | hid_device_register() + * get_report() | | hid_device_submit_report( + * .... | | ... + * v | + * +---------------------+ | + * | | | + * | HID Device | | + * | "bottom half" |<------+ + * | USB HID class | + * | implementation | + * | | + * | | + * +---------------------+ + * ^ + * v + * +--------------------+ + * | | + * | USB Device | + * | Support | + * | | + * +--------------------+ + */ + +/** HID report types + * Report types used in Get/Set Report requests. + */ +enum { + HID_REPORT_TYPE_INPUT = 1, + HID_REPORT_TYPE_OUTPUT, + HID_REPORT_TYPE_FEATURE, +}; + +/** + * @brief HID device user callbacks + * + * Each device depends on a user part that handles feature, input, and output + * report processing according to the device functionality described by the + * report descriptor. Which callbacks must be implemented depends on the device + * functionality. The USB device part of the HID device, cannot interpret + * device specific report descriptor and only handles USB specific parts, + * transfers and validation of requests, all reports are opaque to it. + * Callbacks are called from the USB device stack thread and must not block. + */ +struct hid_device_ops { + /** + * The interface ready callback is called with the ready argument set + * to true when the corresponding interface is part of the active + * configuration and the device can e.g. begin submitting input + * reports, and with the argument set to false when the interface is no + * longer active. This callback is optional. + */ + void (*iface_ready)(const struct device *dev, const bool ready); + + /** + * This callback is called for the HID Get Report request to get a + * feature, input, or output report, which is specified by the argument + * type. If there is no report ID in the report descriptor, the id + * argument is zero. The callback implementation must check the + * arguments, such as whether the report type is supported and the + * report length, and return a negative value to indicate an + * unsupported type or an error, or return the length of the report + * written to the buffer. + */ + int (*get_report)(const struct device *dev, + const uint8_t type, const uint8_t id, + const uint16_t len, uint8_t *const buf); + + /** + * This callback is called for the HID Set Report request to set a + * feature, input, or output report, which is specified by the argument + * type. If there is no report ID in the report descriptor, the id + * argument is zero. The callback implementation must check the + * arguments, such as whether the report type is supported, and return + * a nonzero value to indicate an unsupported type or an error. + */ + int (*set_report)(const struct device *dev, + const uint8_t type, const uint8_t id, + const uint16_t len, const uint8_t *const buf); + + /** + * Notification to limit intput report frequency. + * The device should mute an input report submission until a new + * event occurs or until the time specified by the duration value has + * elapsed. If a report ID is used in the report descriptor, the + * device must store the duration and handle the specified report + * accordingly. Duration time resolution is in miliseconds. + */ + void (*set_idle)(const struct device *dev, + const uint8_t id, const uint32_t duration); + + /** + * If a report ID is used in the report descriptor, the device + * must implement this callback and return the duration for the + * specified report ID. Duration time resolution is in miliseconds. + */ + uint32_t (*get_idle)(const struct device *dev, const uint8_t id); + + /** + * Notification that the host has changed the protocol from + * Boot Protocol(0) to Report Protocol(1) or vice versa. + */ + void (*set_protocol)(const struct device *dev, const uint8_t proto); + + /** + * Notification that input report submitted with + * hid_device_submit_report() has been sent. + * If the device does not use the callback, hid_device_submit_report() + * will be processed synchronously. + */ + void (*input_report_done)(const struct device *dev); + + /** + * New output report callback. Callback will only be called for reports + * received through the optional interrupt OUT pipe. If there is no + * interrupt OUT pipe, output reports will be received using set_report(). + * If a report ID is used in the report descriptor, the host places the ID + * in the buffer first, followed by the report data. + */ + void (*output_report)(const struct device *dev, const uint16_t len, + const uint8_t *const buf); + /** + * Optional Start of Frame (SoF) event callback. + * There will always be software and hardware dependent jitter and + * latency. This should be used very carefully, it should not block + * and the execution time should be quite short. + */ + void (*sof)(const struct device *dev); +}; + +/** + * @brief Register HID device report descriptor and user callbacks + * + * The device must register report descriptor and user callbacks before + * USB device support is initialized and enabled. + * + * @param[in] dev Pointer to HID device + * @param[in] rdesc Pointer to HID report descriptor + * @param[in] rsize Size of HID report descriptor + * @param[in] ops Pointer to HID device callbacks + */ +int hid_device_register(const struct device *dev, + const uint8_t *const rdesc, const uint16_t rsize, + const struct hid_device_ops *const ops); + +/** + * @brief Submit new input report + * + * Submit a new input report to be sent via the interrupt IN pipe. If sync is + * true, the functions will block until the report is sent. + * If the device does not provide input_report_done() callback, + * hid_device_submit_report() will be processed synchronously. + * + * @param[in] dev Pointer to HID device + * @param[in] size Size of the input report + * @param[in] report Input report buffer. Report buffer must be aligned. + * + * @return 0 on success, negative errno code on fail. + */ +int hid_device_submit_report(const struct device *dev, + const uint16_t size, const uint8_t *const report); + +/** + * @} + */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_USBD_HID_CLASS_DEVICE_H_ */ diff --git a/include/zephyr/usb/class/usbd_uac2.h b/include/zephyr/usb/class/usbd_uac2.h index 477f8465266fa..22b599a2099c4 100644 --- a/include/zephyr/usb/class/usbd_uac2.h +++ b/include/zephyr/usb/class/usbd_uac2.h @@ -19,6 +19,18 @@ #include +/** + * @brief USB Audio Class 2 device API + * @defgroup uac2_device USB Audio Class 2 device API + * @ingroup usb + * @{ + */ + +/** + * @brief Get entity ID + * + * @param node node identifier + */ #define UAC2_ENTITY_ID(node) \ ({ \ BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_PARENT(node), zephyr_uac2)); \ @@ -58,7 +70,7 @@ struct uac2_ops { * USB stack calls this function to obtain receive buffer address for * AudioStreaming interface. The buffer is owned by USB stack until * @ref data_recv_cb callback is called. The buffer must be sufficiently - * aligned for use by UDC driver. + * aligned and otherwise suitable for use by UDC driver. * * @param dev USB Audio 2 device * @param terminal Input Terminal ID linked to AudioStreaming interface @@ -126,6 +138,9 @@ void usbd_uac2_set_ops(const struct device *dev, /** * @brief Send audio data to output terminal * + * Data buffer must be sufficiently aligned and otherwise suitable for use by + * UDC driver. + * * @param dev USB Audio 2 device * @param terminal Output Terminal ID linked to AudioStreaming interface * @param data Buffer containing outgoing data @@ -136,4 +151,8 @@ void usbd_uac2_set_ops(const struct device *dev, int usbd_uac2_send(const struct device *dev, uint8_t terminal, void *data, uint16_t size); +/** + * @} + */ + #endif /* ZEPHYR_INCLUDE_USB_CLASS_USBD_UAC2_H_ */ diff --git a/include/zephyr/usb/usb_ch9.h b/include/zephyr/usb/usb_ch9.h index 8fe33f46b7171..dccc7445daa6f 100644 --- a/include/zephyr/usb/usb_ch9.h +++ b/include/zephyr/usb/usb_ch9.h @@ -12,7 +12,7 @@ * and follows, with few exceptions, the USB Specification 2.0. */ -#include +#include #include #include #include diff --git a/include/zephyr/usb/usb_device.h b/include/zephyr/usb/usb_device.h index 0de535365ee17..59c3db1cb5905 100644 --- a/include/zephyr/usb/usb_device.h +++ b/include/zephyr/usb/usb_device.h @@ -446,6 +446,23 @@ int usb_wakeup_request(void); */ bool usb_get_remote_wakeup_status(void); +/** + * @brief Helper macro to place the BOS compatibility descriptor + * in the right memory section. + */ +#define USB_DEVICE_BOS_DESC_DEFINE_CAP \ + static __in_section(usb, bos_desc_area, 1) __aligned(1) __used + +/** + * @brief Register BOS capability descriptor + * + * This function should be used by the application to register BOS capability + * descriptors before the USB device stack is enabled. + * + * @param[in] hdr Pointer to BOS capability descriptor + */ +void usb_bos_register_cap(void *hdr); + /** * @} */ diff --git a/include/zephyr/usb/usbd.h b/include/zephyr/usb/usbd.h index f278ded3e7616..7a643b15db014 100644 --- a/include/zephyr/usb/usbd.h +++ b/include/zephyr/usb/usbd.h @@ -15,6 +15,7 @@ #define ZEPHYR_INCLUDE_USBD_H_ #include +#include #include #include #include @@ -58,8 +59,10 @@ extern "C" { */ #define USB_STRING_DESCRIPTOR_LENGTH(s) (sizeof(s) * 2) -/* Used internally to keep descriptors in order */ -enum usbd_desc_usage_type { +/** Used internally to keep descriptors in order + * @cond INTERNAL_HIDDEN + */ +enum usbd_str_desc_utype { USBD_DUT_STRING_LANG, USBD_DUT_STRING_MANUFACTURER, USBD_DUT_STRING_PRODUCT, @@ -67,25 +70,52 @@ enum usbd_desc_usage_type { USBD_DUT_STRING_INTERFACE, }; +enum usbd_bos_desc_utype { + USBD_DUT_BOS_NONE, +}; +/** @endcond */ + +/** + * USBD string descriptor data + */ +struct usbd_str_desc_data { + /** Descriptor index, required for string descriptors */ + uint8_t idx; + /** Descriptor usage type (not bDescriptorType) */ + enum usbd_str_desc_utype utype : 8; + /** The string descriptor is in ASCII7 format */ + unsigned int ascii7 : 1; + /** Device stack obtains SerialNumber using the HWINFO API */ + unsigned int use_hwinfo : 1; +}; + +/** + * USBD BOS Device Capability descriptor data + */ +struct usbd_bos_desc_data { + /** Descriptor usage type (not bDescriptorType) */ + enum usbd_bos_desc_utype utype : 8; +}; + /** * Descriptor node * * Descriptor node is used to manage descriptors that are not - * directly part of a structure, such as string or bos descriptors. + * directly part of a structure, such as string or BOS capability descriptors. */ struct usbd_desc_node { /** slist node struct */ sys_dnode_t node; - /** Descriptor index, required for string descriptors */ - unsigned int idx : 8; - /** Descriptor usage type (not bDescriptorType) */ - unsigned int utype : 8; - /** If not set, string descriptor must be converted to UTF16LE */ - unsigned int utf16le : 1; - /** If not set, device stack obtains SN using the hwinfo API */ - unsigned int custom_sn : 1; - /** Pointer to a descriptor */ - void *desc; + union { + struct usbd_str_desc_data str; + struct usbd_bos_desc_data bos; + }; + /** Opaque pointer to a descriptor payload */ + const void *const ptr; + /** Descriptor size in bytes */ + uint8_t bLength; + /** Descriptor type */ + uint8_t bDescriptorType; }; /** @@ -169,13 +199,29 @@ struct usbd_status { enum usbd_speed speed : 2; }; +struct usbd_context; + +/** + * @brief Callback type definition for USB device message delivery + * + * The implementation uses the system workqueue, and a callback provided and + * registered by the application. The application callback is called in the + * context of the system workqueue. Notification messages are stored in a queue + * and delivered to the callback in sequence. + * + * @param[in] ctx Pointer to USB device support context + * @param[in] msg Pointer to USB device message + */ +typedef void (*usbd_msg_cb_t)(struct usbd_context *const ctx, + const struct usbd_msg *const msg); + /** * USB device support runtime context * * Main structure that organizes all descriptors, configuration, * and interfaces. An UDC device must be assigned to this structure. */ -struct usbd_contex { +struct usbd_context { /** Name of the USB device */ const char *name; /** Access mutex */ @@ -186,7 +232,7 @@ struct usbd_contex { usbd_msg_cb_t msg_cb; /** Middle layer runtime data */ struct usbd_ch9_data ch9_data; - /** slist to manage descriptors like string, bos */ + /** slist to manage descriptors like string, BOS */ sys_dlist_t descriptors; /** slist to manage Full-Speed device configurations */ sys_slist_t fs_configs; @@ -274,7 +320,7 @@ struct usbd_class_data { /** Name of the USB device class instance */ const char *name; /** Pointer to USB device stack context structure */ - struct usbd_contex *uds_ctx; + struct usbd_context *uds_ctx; /** Pointer to device support class API */ const struct usbd_class_api *api; /** Supported vendor request table, can be NULL */ @@ -322,7 +368,7 @@ struct usbd_class_node { * * @return Pointer to USB device runtime context */ -static inline struct usbd_contex *usbd_class_get_ctx(const struct usbd_class_data *const c_data) +static inline struct usbd_context *usbd_class_get_ctx(const struct usbd_class_data *const c_data) { return c_data->uds_ctx; } @@ -377,7 +423,7 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c .iSerialNumber = 0, \ .bNumConfigurations = 0, \ }; \ - static STRUCT_SECTION_ITERABLE(usbd_contex, device_name) = { \ + static STRUCT_SECTION_ITERABLE(usbd_context, device_name) = { \ .name = STRINGIFY(device_name), \ .dev = uhc_dev, \ .fs_desc = &fs_desc_##device_name, \ @@ -415,33 +461,38 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c * @param name Language string descriptor node identifier. */ #define USBD_DESC_LANG_DEFINE(name) \ - static struct usb_string_descriptor \ - string_desc_##name = { \ + static uint16_t langid_##name = sys_cpu_to_le16(0x0409); \ + static struct usbd_desc_node name = { \ .bLength = sizeof(struct usb_string_descriptor), \ .bDescriptorType = USB_DESC_STRING, \ - .bString = sys_cpu_to_le16(0x0409), \ - }; \ - static struct usbd_desc_node name = { \ - .idx = 0, \ - .utype = USBD_DUT_STRING_LANG, \ - .desc = &string_desc_##name, \ + .str = { \ + .idx = 0, \ + .utype = USBD_DUT_STRING_LANG, \ + }, \ + .ptr = &langid_##name, \ } -#define USBD_DESC_STRING_DEFINE(d_name, d_string, d_utype) \ - struct usb_string_descriptor_##d_name { \ - uint8_t bLength; \ - uint8_t bDescriptorType; \ - uint8_t bString[USB_BSTRING_LENGTH(d_string)]; \ - } __packed; \ - static struct usb_string_descriptor_##d_name \ - string_desc_##d_name = { \ - .bLength = USB_STRING_DESCRIPTOR_LENGTH(d_string), \ - .bDescriptorType = USB_DESC_STRING, \ - .bString = d_string, \ - }; \ - static struct usbd_desc_node d_name = { \ - .utype = d_utype, \ - .desc = &string_desc_##d_name, \ +/** + * @brief Create a string descriptor + * + * This macro defines a descriptor node and a string descriptor. + * The string literal passed to the macro should be in the ASCII7 format. It + * is converted to UTF16LE format on the host request. + * + * @param d_name Internal string descriptor node identifier name + * @param d_string ASCII7 encoded string literal + * @param d_utype String descriptor usage type + */ +#define USBD_DESC_STRING_DEFINE(d_name, d_string, d_utype) \ + static uint8_t ascii_##d_name[USB_BSTRING_LENGTH(d_string)] = d_string; \ + static struct usbd_desc_node d_name = { \ + .str = { \ + .utype = d_utype, \ + .ascii7 = true, \ + }, \ + .bLength = USB_STRING_DESCRIPTOR_LENGTH(d_string), \ + .bDescriptorType = USB_DESC_STRING, \ + .ptr = &ascii_##d_name, \ } /** @@ -475,17 +526,42 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c /** * @brief Create a string descriptor node and serial number string descriptor * - * This macro defines a descriptor node and a string descriptor that, - * when added to the device context, is automatically used as the serial number - * string descriptor. The string literal parameter is used as a placeholder, - * the unique number is obtained from hwinfo. Both descriptor node and descriptor - * are defined with static-storage-class specifier. + * This macro defines a descriptor node that, when added to the device context, + * is automatically used as the serial number string descriptor. A valid serial + * number is generated from HWID (HWINFO= whenever this string descriptor is + * requested. * * @param d_name String descriptor node identifier. - * @param d_string ASCII7 encoded serial number string literal placeholder */ -#define USBD_DESC_SERIAL_NUMBER_DEFINE(d_name, d_string) \ - USBD_DESC_STRING_DEFINE(d_name, d_string, USBD_DUT_STRING_SERIAL_NUMBER) +#define USBD_DESC_SERIAL_NUMBER_DEFINE(d_name) \ + static struct usbd_desc_node d_name = { \ + .str = { \ + .utype = USBD_DUT_STRING_SERIAL_NUMBER, \ + .ascii7 = true, \ + .use_hwinfo = true, \ + }, \ + .bDescriptorType = USB_DESC_STRING, \ + } + +/** + * @brief Define BOS Device Capability descriptor node + * + * The application defines a BOS capability descriptor node for descriptors + * such as USB 2.0 Extension Descriptor. + * + * @param name Descriptor node identifier + * @param len Device Capability descriptor length + * @param subset Pointer to a Device Capability descriptor + */ +#define USBD_DESC_BOS_DEFINE(name, len, subset) \ + static struct usbd_desc_node name = { \ + .bos = { \ + .utype = USBD_DUT_BOS_NONE, \ + }, \ + .ptr = subset, \ + .bLength = len, \ + .bDescriptorType = USB_DESC_BOS, \ + } #define USBD_DEFINE_CLASS(class_name, class_api, class_priv, class_v_reqs) \ static struct usbd_class_data class_name = { \ @@ -526,16 +602,34 @@ static inline void *usbd_class_get_private(const struct usbd_class_data *const c /** * @brief Add common USB descriptor * - * Add common descriptor like string or bos. + * Add common descriptor like string or BOS Device Capability. * * @param[in] uds_ctx Pointer to USB device support context * @param[in] dn Pointer to USB descriptor node * * @return 0 on success, other values on fail. */ -int usbd_add_descriptor(struct usbd_contex *uds_ctx, +int usbd_add_descriptor(struct usbd_context *uds_ctx, struct usbd_desc_node *dn); +/** + * @brief Get USB string descriptor index from descriptor node + * + * @param[in] desc_nd Pointer to USB descriptor node + * + * @return Descriptor index, 0 if descriptor is not part of any device + */ +uint8_t usbd_str_desc_get_idx(const struct usbd_desc_node *const desc_nd); + +/** + * @brief Remove USB string descriptor + * + * Remove linked USB string descriptor from any list. + * + * @param[in] desc_nd Pointer to USB descriptor node + */ +void usbd_remove_descriptor(struct usbd_desc_node *const desc_nd); + /** * @brief Add a USB device configuration * @@ -545,7 +639,7 @@ int usbd_add_descriptor(struct usbd_contex *uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_add_configuration(struct usbd_contex *uds_ctx, +int usbd_add_configuration(struct usbd_context *uds_ctx, const enum usbd_speed speed, struct usbd_config_node *cd); @@ -566,14 +660,33 @@ int usbd_add_configuration(struct usbd_contex *uds_ctx, * @param[in] uds_ctx Pointer to USB device support context * @param[in] name Class instance name * @param[in] speed Configuration speed - * @param[in] cfg Configuration value (similar to bConfigurationValue) + * @param[in] cfg Configuration value (bConfigurationValue) * * @return 0 on success, other values on fail. */ -int usbd_register_class(struct usbd_contex *uds_ctx, +int usbd_register_class(struct usbd_context *uds_ctx, const char *name, const enum usbd_speed speed, uint8_t cfg); +/** + * @brief Register all available USB class instances + * + * Register all available instances. Like usbd_register_class, but does not + * take the instance name and instead registers all available instances. + * + * @note This cannot be combined. If your application calls + * usbd_register_class for any device, configuration number, or instance, + * either usbd_register_class or this function will fail. + * + * @param[in] uds_ctx Pointer to USB device support context + * @param[in] speed Configuration speed + * @param[in] cfg Configuration value (bConfigurationValue) + * + * @return 0 on success, other values on fail. + */ +int usbd_register_all_classes(struct usbd_context *uds_ctx, + const enum usbd_speed speed, uint8_t cfg); + /** * @brief Unregister an USB class instance * @@ -584,14 +697,29 @@ int usbd_register_class(struct usbd_contex *uds_ctx, * @param[in] uds_ctx Pointer to USB device support context * @param[in] name Class instance name * @param[in] speed Configuration speed - * @param[in] cfg Configuration value (similar to bConfigurationValue) + * @param[in] cfg Configuration value (bConfigurationValue) * * @return 0 on success, other values on fail. */ -int usbd_unregister_class(struct usbd_contex *uds_ctx, +int usbd_unregister_class(struct usbd_context *uds_ctx, const char *name, const enum usbd_speed speed, uint8_t cfg); +/** + * @brief Unregister all available USB class instances + * + * Unregister all available instances. Like usbd_unregister_class, but does not + * take the instance name and instead unregisters all available instances. + * + * @param[in] uds_ctx Pointer to USB device support context + * @param[in] speed Configuration speed + * @param[in] cfg Configuration value (bConfigurationValue) + * + * @return 0 on success, other values on fail. + */ +int usbd_unregister_all_classes(struct usbd_context *uds_ctx, + const enum usbd_speed speed, uint8_t cfg); + /** * @brief Register USB notification message callback * @@ -600,7 +728,7 @@ int usbd_unregister_class(struct usbd_contex *uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_msg_register_cb(struct usbd_contex *const uds_ctx, +int usbd_msg_register_cb(struct usbd_context *const uds_ctx, const usbd_msg_cb_t cb); /** @@ -616,7 +744,7 @@ int usbd_msg_register_cb(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_init(struct usbd_contex *uds_ctx); +int usbd_init(struct usbd_context *uds_ctx); /** * @brief Enable the USB device support and registered class instances @@ -627,7 +755,7 @@ int usbd_init(struct usbd_contex *uds_ctx); * * @return 0 on success, other values on fail. */ -int usbd_enable(struct usbd_contex *uds_ctx); +int usbd_enable(struct usbd_context *uds_ctx); /** * @brief Disable the USB device support @@ -638,7 +766,7 @@ int usbd_enable(struct usbd_contex *uds_ctx); * * @return 0 on success, other values on fail. */ -int usbd_disable(struct usbd_contex *uds_ctx); +int usbd_disable(struct usbd_context *uds_ctx); /** * @brief Shutdown the USB device support @@ -649,7 +777,7 @@ int usbd_disable(struct usbd_contex *uds_ctx); * * @return 0 on success, other values on fail. */ -int usbd_shutdown(struct usbd_contex *const uds_ctx); +int usbd_shutdown(struct usbd_context *const uds_ctx); /** * @brief Halt endpoint @@ -659,7 +787,7 @@ int usbd_shutdown(struct usbd_contex *const uds_ctx); * * @return 0 on success, or error from udc_ep_set_halt() */ -int usbd_ep_set_halt(struct usbd_contex *uds_ctx, uint8_t ep); +int usbd_ep_set_halt(struct usbd_context *uds_ctx, uint8_t ep); /** * @brief Clear endpoint halt @@ -669,7 +797,7 @@ int usbd_ep_set_halt(struct usbd_contex *uds_ctx, uint8_t ep); * * @return 0 on success, or error from udc_ep_clear_halt() */ -int usbd_ep_clear_halt(struct usbd_contex *uds_ctx, uint8_t ep); +int usbd_ep_clear_halt(struct usbd_context *uds_ctx, uint8_t ep); /** * @brief Checks whether the endpoint is halted. @@ -679,21 +807,7 @@ int usbd_ep_clear_halt(struct usbd_contex *uds_ctx, uint8_t ep); * * @return true if endpoint is halted, false otherwise */ -bool usbd_ep_is_halted(struct usbd_contex *uds_ctx, uint8_t ep); - -/** - * @brief Allocate buffer for USB device control request - * - * Allocate a new buffer from controller's driver buffer pool. - * - * @param[in] uds_ctx Pointer to USB device support context - * @param[in] ep Endpoint address - * @param[in] size Size of the request buffer - * - * @return pointer to allocated request or NULL on error. - */ -struct net_buf *usbd_ep_ctrl_buf_alloc(struct usbd_contex *const uds_ctx, - const uint8_t ep, const size_t size); +bool usbd_ep_is_halted(struct usbd_context *uds_ctx, uint8_t ep); /** * @brief Allocate buffer for USB device request @@ -719,7 +833,7 @@ struct net_buf *usbd_ep_buf_alloc(const struct usbd_class_data *const c_data, * * @return 0 on success, all other values should be treated as error. */ -int usbd_ep_ctrl_enqueue(struct usbd_contex *const uds_ctx, +int usbd_ep_ctrl_enqueue(struct usbd_context *const uds_ctx, struct net_buf *const buf); /** @@ -743,7 +857,7 @@ int usbd_ep_enqueue(const struct usbd_class_data *const c_data, * * @return 0 on success, or error from udc_ep_dequeue() */ -int usbd_ep_dequeue(struct usbd_contex *uds_ctx, const uint8_t ep); +int usbd_ep_dequeue(struct usbd_context *uds_ctx, const uint8_t ep); /** * @brief Free USB device request buffer @@ -755,7 +869,7 @@ int usbd_ep_dequeue(struct usbd_contex *uds_ctx, const uint8_t ep); * * @return 0 on success, all other values should be treated as error. */ -int usbd_ep_buf_free(struct usbd_contex *uds_ctx, struct net_buf *buf); +int usbd_ep_buf_free(struct usbd_context *uds_ctx, struct net_buf *buf); /** * @brief Checks whether the USB device controller is suspended. @@ -764,14 +878,14 @@ int usbd_ep_buf_free(struct usbd_contex *uds_ctx, struct net_buf *buf); * * @return true if endpoint is halted, false otherwise */ -bool usbd_is_suspended(struct usbd_contex *uds_ctx); +bool usbd_is_suspended(struct usbd_context *uds_ctx); /** * @brief Initiate the USB remote wakeup (TBD) * * @return 0 on success, other values on fail. */ -int usbd_wakeup_request(struct usbd_contex *uds_ctx); +int usbd_wakeup_request(struct usbd_context *uds_ctx); /** * @brief Get actual device speed @@ -780,7 +894,7 @@ int usbd_wakeup_request(struct usbd_contex *uds_ctx); * * @return Actual device speed */ -enum usbd_speed usbd_bus_speed(const struct usbd_contex *const uds_ctx); +enum usbd_speed usbd_bus_speed(const struct usbd_context *const uds_ctx); /** * @brief Get highest speed supported by the controller @@ -789,7 +903,7 @@ enum usbd_speed usbd_bus_speed(const struct usbd_contex *const uds_ctx); * * @return Highest supported speed */ -enum usbd_speed usbd_caps_speed(const struct usbd_contex *const uds_ctx); +enum usbd_speed usbd_caps_speed(const struct usbd_context *const uds_ctx); /** * @brief Set USB device descriptor value bcdUSB @@ -800,7 +914,7 @@ enum usbd_speed usbd_caps_speed(const struct usbd_contex *const uds_ctx); * * @return 0 on success, other values on fail. */ -int usbd_device_set_bcd(struct usbd_contex *const uds_ctx, +int usbd_device_set_bcd(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint16_t bcd); /** @@ -811,7 +925,7 @@ int usbd_device_set_bcd(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_device_set_vid(struct usbd_contex *const uds_ctx, +int usbd_device_set_vid(struct usbd_context *const uds_ctx, const uint16_t vid); /** @@ -822,7 +936,7 @@ int usbd_device_set_vid(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_device_set_pid(struct usbd_contex *const uds_ctx, +int usbd_device_set_pid(struct usbd_context *const uds_ctx, const uint16_t pid); /** @@ -836,7 +950,7 @@ int usbd_device_set_pid(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx, +int usbd_device_set_code_triple(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t base_class, const uint8_t subclass, const uint8_t protocol); @@ -851,7 +965,7 @@ int usbd_device_set_code_triple(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_config_attrib_rwup(struct usbd_contex *const uds_ctx, +int usbd_config_attrib_rwup(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const bool enable); @@ -865,7 +979,7 @@ int usbd_config_attrib_rwup(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_config_attrib_self(struct usbd_contex *const uds_ctx, +int usbd_config_attrib_self(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const bool enable); @@ -879,9 +993,24 @@ int usbd_config_attrib_self(struct usbd_contex *const uds_ctx, * * @return 0 on success, other values on fail. */ -int usbd_config_maxpower(struct usbd_contex *const uds_ctx, +int usbd_config_maxpower(struct usbd_context *const uds_ctx, const enum usbd_speed speed, const uint8_t cfg, const uint8_t power); + +/** + * @brief Check that the controller can detect the VBUS state change. + * + * This can be used in a generic application to explicitly handle the VBUS + * detected event after usbd_init(). For example, to call usbd_enable() after a + * short delay to give the PMIC time to detect the bus, or to handle cases + * where usbd_enable() can only be called after a VBUS detected event. + * + * @param[in] uds_ctx Pointer to USB device support context + * + * @return true if controller can detect VBUS state change, false otherwise + */ +bool usbd_can_detect_vbus(struct usbd_context *const uds_ctx); + /** * @} */ diff --git a/include/zephyr/usb/usbd_msg.h b/include/zephyr/usb/usbd_msg.h index 00ef52a386566..a11cff7d1daff 100644 --- a/include/zephyr/usb/usbd_msg.h +++ b/include/zephyr/usb/usbd_msg.h @@ -81,18 +81,6 @@ struct usbd_msg { }; }; -/** - * @brief Callback type definition for USB device message delivery - * - * The implementation uses the system workqueue, and a callback provided and - * registered by the application. The application callback is called in the - * context of the system workqueue. Notification messages are stored in a queue - * and delivered to the callback in sequence. - * - * @param[in] msg Pointer to USB device message - */ -typedef void (*usbd_msg_cb_t)(const struct usbd_msg *const msg); - /** * @brief Returns the message type as a constant string * diff --git a/include/zephyr/zephyr.h b/include/zephyr/zephyr.h deleted file mode 100644 index 16e7dcfd6461a..0000000000000 --- a/include/zephyr/zephyr.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2015 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#ifndef ZEPHYR_INCLUDE_ZEPHYR_H_ -#define ZEPHYR_INCLUDE_ZEPHYR_H_ - -#include - -#warning " is deprecated, include instead" - -#endif /* ZEPHYR_INCLUDE_ZEPHYR_H_ */ diff --git a/include/zephyr/zvfs/eventfd.h b/include/zephyr/zvfs/eventfd.h new file mode 100644 index 0000000000000..a5e1ebfa28675 --- /dev/null +++ b/include/zephyr/zvfs/eventfd.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020 Tobias Svehagen + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_INCLUDE_ZEPHYR_ZVFS_EVENTFD_H_ +#define ZEPHYR_INCLUDE_ZEPHYR_ZVFS_EVENTFD_H_ + +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZVFS_EFD_SEMAPHORE 2 +#define ZVFS_EFD_NONBLOCK 0x4000 + +typedef uint64_t zvfs_eventfd_t; + +/** + * @brief Create a file descriptor for ZVFS event notification + * + * The returned file descriptor can be used with POSIX read/write calls or + * with the @ref zvfs_eventfd_read or @ref zvfs_eventfd_write functions. + * + * It also supports polling and by including an eventfd in a call to poll, + * it is possible to signal and wake the polling thread by simply writing to + * the eventfd. + * + * When using read() and write() on a ZVFS eventfd, the size must always be at + * least 8 bytes or the operation will fail with EINVAL. + * + * @return New ZVFS eventfd file descriptor on success, -1 on error + */ +int zvfs_eventfd(unsigned int initval, int flags); + +/** + * @brief Read from a ZVFS eventfd + * + * If call is successful, the value parameter will have the value 1 + * + * @param fd File descriptor + * @param value Pointer for storing the read value + * + * @return 0 on success, -1 on error + */ +int zvfs_eventfd_read(int fd, zvfs_eventfd_t *value); + +/** + * @brief Write to a ZVFS eventfd + * + * @param fd File descriptor + * @param value Value to write + * + * @return 0 on success, -1 on error + */ +int zvfs_eventfd_write(int fd, zvfs_eventfd_t value); + +#ifdef __cplusplus +} +#endif + +#endif /* ZEPHYR_INCLUDE_ZEPHYR_ZVFS_EVENTFD_H_ */ diff --git a/kernel/Kconfig b/kernel/Kconfig index af51267edbf1f..57c8b2997598c 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -156,7 +156,7 @@ config SCHED_CPU_MASK_PIN_ONLY config MAIN_STACK_SIZE int "Size of stack for initialization and main thread" default 2048 if COVERAGE_GCOV - default 512 if ZTEST && !(RISCV || X86 || ARM || ARC) + default 512 if ZTEST && !(RISCV || X86 || ARM || ARC || NIOS2) default 1024 help When the initialization is complete, the thread executing it then @@ -467,6 +467,12 @@ config BOOT_DELAY achieved by waiting for DCD on the serial port--however, not all serial ports have DCD. +config BOOT_CLEAR_SCREEN + bool "Clear screen" + help + Use this option to clear the screen before printing anything else. + Using a VT100 enabled terminal on the client side is required for this to work. + config THREAD_MONITOR bool "Thread monitoring" help @@ -704,6 +710,9 @@ config PIPES allows a thread to send a byte stream to another thread. Pipes can be used to synchronously transfer chunks of data in whole or in part. + Note that setting this option slightly increases the size of the + thread structure. + config KERNEL_MEM_POOL bool "Use Kernel Memory Pool" default y @@ -943,59 +952,7 @@ config BOUNDS_CHECK_BYPASS_MITIGATION macros do nothing. endmenu - -menu "Memory Domains" - -config MAX_DOMAIN_PARTITIONS - int "Maximum number of partitions per memory domain" - default 16 - range 0 255 - depends on USERSPACE - help - Configure the maximum number of partitions per memory domain. - -config ARCH_MEM_DOMAIN_DATA - bool - depends on USERSPACE - help - This hidden option is selected by the target architecture if - architecture-specific data is needed on a per memory domain basis. - If so, the architecture defines a 'struct arch_mem_domain' which is - embedded within every struct k_mem_domain. The architecture - must also define the arch_mem_domain_init() function to set this up - when a memory domain is created. - - Typical uses might be a set of page tables for that memory domain. - -config ARCH_MEM_DOMAIN_SYNCHRONOUS_API - bool - depends on USERSPACE - help - This hidden option is selected by the target architecture if - modifying a memory domain's partitions at runtime, or changing - a memory domain's thread membership requires synchronous calls - into the architecture layer. - - If enabled, the architecture layer must implement the following - APIs: - - arch_mem_domain_thread_add - arch_mem_domain_thread_remove - arch_mem_domain_partition_remove - arch_mem_domain_partition_add - - It's important to note that although supervisor threads can be - members of memory domains, they have no implications on supervisor - thread access to memory. Memory domain APIs may only be invoked from - supervisor mode. - - For these reasons, on uniprocessor systems unless memory access - policy is managed in separate software constructions like page - tables, these APIs don't need to be implemented as the underlying - memory management hardware will be reprogrammed on context switch - anyway. -endmenu - +rsource "Kconfig.mem_domain" rsource "Kconfig.smp" config TICKLESS_KERNEL @@ -1020,6 +977,12 @@ config THREAD_LOCAL_STORAGE help This option enables thread local storage (TLS) support in kernel. +config KERNEL_WHOLE_ARCHIVE + bool + help + This option forces every object file in the libkernel.a archive + to be included, rather than searching the archive for required object files. + endmenu rsource "Kconfig.device" diff --git a/kernel/Kconfig.device b/kernel/Kconfig.device index f9718c4272d0e..c0e8b490331ee 100644 --- a/kernel/Kconfig.device +++ b/kernel/Kconfig.device @@ -26,6 +26,13 @@ config DEVICE_MUTABLE Support mutable devices. Mutable devices are instantiated in SRAM instead of Flash and are runtime modifiable in kernel mode. +config DEVICE_DT_METADATA + bool "Store additional devicetree metadata for each device" + help + If enabled, additional data from the devicetree will be stored for + each device. This allows you to use device_get_by_dt_nodelabel(), + device_get_dt_metadata(), etc. + endmenu menu "Initialization Priorities" diff --git a/kernel/Kconfig.mem_domain b/kernel/Kconfig.mem_domain new file mode 100644 index 0000000000000..28f3d003639d2 --- /dev/null +++ b/kernel/Kconfig.mem_domain @@ -0,0 +1,79 @@ +# Kernel configuration options + +# Copyright (c) 2014-2015 Wind River Systems, Inc. +# SPDX-License-Identifier: Apache-2.0 + +menu "Memory Domains" + +config MAX_DOMAIN_PARTITIONS + int "Maximum number of partitions per memory domain" + default 16 + range 0 255 + depends on USERSPACE + help + Configure the maximum number of partitions per memory domain. + +config ARCH_MEM_DOMAIN_DATA + bool + depends on USERSPACE + help + This hidden option is selected by the target architecture if + architecture-specific data is needed on a per memory domain basis. + If so, the architecture defines a 'struct arch_mem_domain' which is + embedded within every struct k_mem_domain. The architecture + must also define the arch_mem_domain_init() function to set this up + when a memory domain is created. + + Typical uses might be a set of page tables for that memory domain. + +config ARCH_MEM_DOMAIN_SYNCHRONOUS_API + bool + depends on USERSPACE + help + This hidden option is selected by the target architecture if + modifying a memory domain's partitions at runtime, or changing + a memory domain's thread membership requires synchronous calls + into the architecture layer. + + If enabled, the architecture layer must implement the following + APIs: + + arch_mem_domain_thread_add + arch_mem_domain_thread_remove + arch_mem_domain_partition_remove + arch_mem_domain_partition_add + + It's important to note that although supervisor threads can be + members of memory domains, they have no implications on supervisor + thread access to memory. Memory domain APIs may only be invoked from + supervisor mode. + + For these reasons, on uniprocessor systems unless memory access + policy is managed in separate software constructions like page + tables, these APIs don't need to be implemented as the underlying + memory management hardware will be reprogrammed on context switch + anyway. + +config ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + bool + help + This hidden option is selected by the target architecture if + the architecture supports isolating thread stacks for threads + within the same memory domain. + +config MEM_DOMAIN_ISOLATED_STACKS + bool + default y + depends on (MMU || MPU) && ARCH_MEM_DOMAIN_SUPPORTS_ISOLATED_STACKS + help + If enabled, thread stacks within the same memory domains are + isolated which means threads within the same memory domains + have no access to others threads' stacks. + + If disabled, threads within the same memory domains can access + other threads' stacks. + + Regardless of this settings, threads cannot access the stacks of + threads outside of their domains. + +endmenu diff --git a/kernel/Kconfig.smp b/kernel/Kconfig.smp index 22279270b19f0..da83d1624e060 100644 --- a/kernel/Kconfig.smp +++ b/kernel/Kconfig.smp @@ -56,12 +56,11 @@ config MP_MAX_NUM_CPUS config SCHED_IPI_SUPPORTED bool help - True if the architecture supports a call to - arch_sched_ipi() to broadcast an interrupt that will call - z_sched_ipi() on other CPUs in the system. Required for - k_thread_abort() to operate with reasonable latency - (otherwise we might have to wait for the other thread to - take an interrupt, which can be arbitrarily far in the + True if the architecture supports a call to arch_sched_broadcast_ipi() + to broadcast an interrupt that will call z_sched_ipi() on other CPUs + in the system. Required for k_thread_abort() to operate with + reasonable latency (otherwise we might have to wait for the other + thread to take an interrupt, which can be arbitrarily far in the future). config TRACE_SCHED_IPI @@ -73,6 +72,24 @@ config TRACE_SCHED_IPI depends on SCHED_IPI_SUPPORTED depends on MP_MAX_NUM_CPUS>1 +config IPI_OPTIMIZE + bool "Optimize IPI delivery" + default n + depends on SCHED_IPI_SUPPORTED && MP_MAX_NUM_CPUS>1 + help + When selected, the kernel will attempt to determine the minimum + set of CPUs that need an IPI to trigger a reschedule in response to + a thread newly made ready for execution. This increases the + computation required at every scheduler operation by a value that is + O(N) in the number of CPUs, and in exchange reduces the number of + interrupts delivered. Which to choose is going to depend on + application behavior. If the architecture also supports directing + IPIs to specific CPUs then this has the potential to signficantly + reduce the number of IPIs (and consequently ISRs) processed by the + system as the number of CPUs increases. If not, the only benefit + would be to not issue any IPIs if the newly readied thread is of + lower priority than all the threads currently executing on other CPUs. + config KERNEL_COHERENCE bool "Place all shared data into coherent memory" depends on ARCH_HAS_COHERENCE diff --git a/kernel/Kconfig.vm b/kernel/Kconfig.vm index 97d6c1f424b3b..4215df89930d2 100644 --- a/kernel/Kconfig.vm +++ b/kernel/Kconfig.vm @@ -202,7 +202,7 @@ config KERNEL_VM_USE_CUSTOM_MEM_RANGE_CHECK bool help Use custom memory range check functions instead of the generic - checks in z_mem_phys_addr() and z_mem_virt_addr(). + checks in k_mem_phys_addr() and k_mem_virt_addr(). sys_mm_is_phys_addr_in_range() and sys_mm_is_virt_addr_in_range() must be implemented. diff --git a/kernel/atomic_c.c b/kernel/atomic_c.c index c873192af74cb..70fff83edb640 100644 --- a/kernel/atomic_c.c +++ b/kernel/atomic_c.c @@ -112,7 +112,7 @@ bool z_vrfy_atomic_cas(atomic_t *target, atomic_val_t old_value, return z_impl_atomic_cas((atomic_t *)target, old_value, new_value); } -#include +#include #endif /* CONFIG_USERSPACE */ bool z_impl_atomic_ptr_cas(atomic_ptr_t *target, atomic_ptr_val_t old_value, @@ -142,7 +142,7 @@ static inline bool z_vrfy_atomic_ptr_cas(atomic_ptr_t *target, return z_impl_atomic_ptr_cas(target, old_value, new_value); } -#include +#include #endif /* CONFIG_USERSPACE */ /** @@ -280,7 +280,7 @@ static inline atomic_ptr_val_t z_vrfy_atomic_ptr_set(atomic_ptr_t *target, return z_impl_atomic_ptr_set(target, value); } -#include +#include #endif /* CONFIG_USERSPACE */ /** @@ -404,11 +404,11 @@ atomic_val_t z_impl_atomic_nand(atomic_t *target, atomic_val_t value) ATOMIC_SYSCALL_HANDLER_TARGET_VALUE(atomic_nand); #ifdef CONFIG_USERSPACE -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/banner.c b/kernel/banner.c index dc2506fb9b152..5cadda0a5e985 100644 --- a/kernel/banner.c +++ b/kernel/banner.c @@ -7,7 +7,7 @@ #include #include #include -#include +#include #if defined(CONFIG_BOOT_DELAY) && (CONFIG_BOOT_DELAY > 0) #define DELAY_STR STRINGIFY(CONFIG_BOOT_DELAY) @@ -27,10 +27,21 @@ void boot_banner(void) { #if defined(CONFIG_BOOT_DELAY) && (CONFIG_BOOT_DELAY > 0) +#ifdef CONFIG_BOOT_BANNER printk("***** delaying boot " DELAY_STR "ms (per build configuration) *****\n"); +#endif /* CONFIG_BOOT_BANNER */ k_busy_wait(CONFIG_BOOT_DELAY * USEC_PER_MSEC); #endif /* defined(CONFIG_BOOT_DELAY) && (CONFIG_BOOT_DELAY > 0) */ +#if defined(CONFIG_BOOT_CLEAR_SCREEN) + /* \x1b[ = escape sequence + * 3J = erase scrollback + * 2J = erase screen + * H = move cursor to top left + */ + printk("\x1b[3J\x1b[2J\x1b[H"); +#endif /* CONFIG_BOOT_CLEAR_SCREEN */ + #ifdef CONFIG_BOOT_BANNER printk("*** " CONFIG_BOOT_BANNER_STRING " " BANNER_VERSION BANNER_POSTFIX " ***\n"); #endif /* CONFIG_BOOT_BANNER */ diff --git a/kernel/busy_wait.c b/kernel/busy_wait.c index cb7c993437d0a..da0ea149e1028 100644 --- a/kernel/busy_wait.c +++ b/kernel/busy_wait.c @@ -52,5 +52,5 @@ static inline void z_vrfy_k_busy_wait(uint32_t usec_to_wait) { z_impl_k_busy_wait(usec_to_wait); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/compiler_stack_protect.c b/kernel/compiler_stack_protect.c index 2ee2d81c7a320..928fdc6ec9ad8 100644 --- a/kernel/compiler_stack_protect.c +++ b/kernel/compiler_stack_protect.c @@ -47,11 +47,11 @@ void _StackCheckHandler(void) * The canary value gets initialized in z_cstart(). */ #ifdef CONFIG_STACK_CANARIES_TLS -__thread uintptr_t __stack_chk_guard; +__thread volatile uintptr_t __stack_chk_guard; #elif CONFIG_USERSPACE -K_APP_DMEM(z_libc_partition) uintptr_t __stack_chk_guard; +K_APP_DMEM(z_libc_partition) volatile uintptr_t __stack_chk_guard; #else -__noinit uintptr_t __stack_chk_guard; +__noinit volatile uintptr_t __stack_chk_guard; #endif /** diff --git a/kernel/condvar.c b/kernel/condvar.c index 9d8ca7a5bc87f..b8d0df95341fc 100644 --- a/kernel/condvar.c +++ b/kernel/condvar.c @@ -38,7 +38,7 @@ int z_vrfy_k_condvar_init(struct k_condvar *condvar) K_OOPS(K_SYSCALL_OBJ_INIT(condvar, K_OBJ_CONDVAR)); return z_impl_k_condvar_init(condvar); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_condvar_signal(struct k_condvar *condvar) @@ -70,7 +70,7 @@ int z_vrfy_k_condvar_signal(struct k_condvar *condvar) K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); return z_impl_k_condvar_signal(condvar); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_condvar_broadcast(struct k_condvar *condvar) @@ -84,8 +84,8 @@ int z_impl_k_condvar_broadcast(struct k_condvar *condvar) SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_condvar, broadcast, condvar); /* wake up any threads that are waiting to write */ - while ((pending_thread = z_unpend_first_thread(&condvar->wait_q)) != - NULL) { + for (pending_thread = z_unpend_first_thread(&condvar->wait_q); pending_thread != NULL; + pending_thread = z_unpend_first_thread(&condvar->wait_q)) { woken++; arch_thread_return_value_set(pending_thread, 0); z_ready_thread(pending_thread); @@ -103,7 +103,7 @@ int z_vrfy_k_condvar_broadcast(struct k_condvar *condvar) K_OOPS(K_SYSCALL_OBJ(condvar, K_OBJ_CONDVAR)); return z_impl_k_condvar_broadcast(condvar); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex, @@ -132,7 +132,7 @@ int z_vrfy_k_condvar_wait(struct k_condvar *condvar, struct k_mutex *mutex, K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); return z_impl_k_condvar_wait(condvar, mutex, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_CONDVAR diff --git a/kernel/device.c b/kernel/device.c index 6124ada5140f8..64d5a85e4503b 100644 --- a/kernel/device.c +++ b/kernel/device.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include @@ -40,13 +41,13 @@ const struct device *z_impl_device_get_binding(const char *name) * performed. Reserve string comparisons for a fallback. */ STRUCT_SECTION_FOREACH(device, dev) { - if (z_device_is_ready(dev) && (dev->name == name)) { + if (z_impl_device_is_ready(dev) && (dev->name == name)) { return dev; } } STRUCT_SECTION_FOREACH(device, dev) { - if (z_device_is_ready(dev) && (strcmp(name, dev->name) == 0)) { + if (z_impl_device_is_ready(dev) && (strcmp(name, dev->name) == 0)) { return dev; } } @@ -59,14 +60,14 @@ static inline const struct device *z_vrfy_device_get_binding(const char *name) { char name_copy[Z_DEVICE_MAX_NAME_LEN]; - if (k_usermode_string_copy(name_copy, (char *)name, sizeof(name_copy)) + if (k_usermode_string_copy(name_copy, name, sizeof(name_copy)) != 0) { return NULL; } return z_impl_device_get_binding(name_copy); } -#include +#include static inline bool z_vrfy_device_is_ready(const struct device *dev) { @@ -74,9 +75,60 @@ static inline bool z_vrfy_device_is_ready(const struct device *dev) return z_impl_device_is_ready(dev); } -#include +#include #endif /* CONFIG_USERSPACE */ +#ifdef CONFIG_DEVICE_DT_METADATA +const struct device *z_impl_device_get_by_dt_nodelabel(const char *nodelabel) +{ + /* For consistency with device_get_binding(). */ + if ((nodelabel == NULL) || (nodelabel[0] == '\0')) { + return NULL; + } + + /* Unlike device_get_binding(), which has a history of being + * used in application code, we don't expect + * device_get_by_dt_nodelabel() to be used outside of + * scenarios where a human is in the loop. The shell is the + * main expected use case. Therefore, nodelabel is probably + * not the same pointer as any of the entry->nodelabel + * elements. We therefore skip the pointer comparison that + * device_get_binding() does. + */ + STRUCT_SECTION_FOREACH(device, dev) { + const struct device_dt_nodelabels *nl = device_get_dt_nodelabels(dev); + + if (!z_impl_device_is_ready(dev)) { + continue; + } + + for (size_t i = 0; i < nl->num_nodelabels; i++) { + const char *dev_nodelabel = nl->nodelabels[i]; + + if (strcmp(nodelabel, dev_nodelabel) == 0) { + return dev; + } + } + } + + return NULL; +} + +#ifdef CONFIG_USERSPACE +static inline const struct device *z_vrfy_device_get_by_dt_nodelabel(const char *nodelabel) +{ + const char nl_copy[Z_DEVICE_MAX_NODELABEL_LEN]; + + if (k_usermode_string_copy(nl_copy, (char *)nodelabel, sizeof(nl_copy)) != 0) { + return NULL; + } + + return z_impl_device_get_by_dt_nodelabel(nl_copy); +} +#include +#endif /* CONFIG_USERSPACE */ +#endif /* CONFIG_DEVICE_DT_METADATA */ + size_t z_device_get_all_static(struct device const **devices) { size_t cnt; @@ -87,7 +139,7 @@ size_t z_device_get_all_static(struct device const **devices) return cnt; } -bool z_device_is_ready(const struct device *dev) +bool z_impl_device_is_ready(const struct device *dev) { /* * if an invalid device pointer is passed as argument, this call diff --git a/kernel/dynamic.c b/kernel/dynamic.c index d03e36693468b..a9ec33d87bdc8 100644 --- a/kernel/dynamic.c +++ b/kernel/dynamic.c @@ -105,7 +105,7 @@ static inline k_thread_stack_t *z_vrfy_k_thread_stack_alloc(size_t size, int fla { return z_impl_k_thread_stack_alloc(size, flags); } -#include +#include #endif /* CONFIG_USERSPACE */ static void dyn_cb(const struct k_thread *thread, void *user_data) @@ -166,7 +166,16 @@ int z_impl_k_thread_stack_free(k_thread_stack_t *stack) #ifdef CONFIG_USERSPACE static inline int z_vrfy_k_thread_stack_free(k_thread_stack_t *stack) { + /* The thread stack object must not be in initialized state. + * + * Thread stack objects are initialized when the thread is created + * and de-initialized whent the thread is destroyed. Since we can't + * free a stack that is in use, we have to check that the caller + * has access to the object but that it is not in use anymore. + */ + K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(stack, K_OBJ_THREAD_STACK_ELEMENT)); + return z_impl_k_thread_stack_free(stack); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/errno.c b/kernel/errno.c index 645597f02c7ef..f268bb72fdf90 100644 --- a/kernel/errno.c +++ b/kernel/errno.c @@ -43,7 +43,7 @@ static inline int *z_vrfy_z_errno(void) { return z_impl_z_errno(); } -#include +#include #else int *z_impl_z_errno(void) diff --git a/kernel/events.c b/kernel/events.c index 082f418cbe054..d2950e43c4f23 100644 --- a/kernel/events.c +++ b/kernel/events.c @@ -71,7 +71,7 @@ void z_vrfy_k_event_init(struct k_event *event) K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(event, K_OBJ_EVENT)); z_impl_k_event_init(event); } -#include +#include #endif /* CONFIG_USERSPACE */ /** @@ -190,7 +190,7 @@ uint32_t z_vrfy_k_event_post(struct k_event *event, uint32_t events) K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_post(event, events); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_event_set(struct k_event *event, uint32_t events) @@ -204,7 +204,7 @@ uint32_t z_vrfy_k_event_set(struct k_event *event, uint32_t events) K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_set(event, events); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_event_set_masked(struct k_event *event, uint32_t events, @@ -220,7 +220,7 @@ uint32_t z_vrfy_k_event_set_masked(struct k_event *event, uint32_t events, K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_set_masked(event, events, events_mask); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_event_clear(struct k_event *event, uint32_t events) @@ -234,7 +234,7 @@ uint32_t z_vrfy_k_event_clear(struct k_event *event, uint32_t events) K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_clear(event, events); } -#include +#include #endif /* CONFIG_USERSPACE */ static uint32_t k_event_wait_internal(struct k_event *event, uint32_t events, @@ -320,7 +320,7 @@ uint32_t z_vrfy_k_event_wait(struct k_event *event, uint32_t events, K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_wait(event, events, reset, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ /** @@ -342,7 +342,7 @@ uint32_t z_vrfy_k_event_wait_all(struct k_event *event, uint32_t events, K_OOPS(K_SYSCALL_OBJ(event, K_OBJ_EVENT)); return z_impl_k_event_wait_all(event, events, reset, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_EVENT diff --git a/kernel/fatal.c b/kernel/fatal.c index caee224bf5f63..06966066e3020 100644 --- a/kernel/fatal.c +++ b/kernel/fatal.c @@ -35,7 +35,7 @@ FUNC_NORETURN __weak void arch_system_halt(unsigned int reason) /* LCOV_EXCL_START */ __weak void k_sys_fatal_error_handler(unsigned int reason, - const z_arch_esf_t *esf) + const struct arch_esf *esf) { ARG_UNUSED(esf); @@ -82,7 +82,7 @@ FUNC_NORETURN void k_fatal_halt(unsigned int reason) } /* LCOV_EXCL_STOP */ -void z_fatal_error(unsigned int reason, const z_arch_esf_t *esf) +void z_fatal_error(unsigned int reason, const struct arch_esf *esf) { /* We can't allow this code to be preempted, but don't need to * synchronize between CPUs, so an arch-layer lock is diff --git a/kernel/float.c b/kernel/float.c index 69e806d3cd6eb..fa81edf8829d7 100644 --- a/kernel/float.c +++ b/kernel/float.c @@ -35,13 +35,13 @@ static inline int z_vrfy_k_float_disable(struct k_thread *thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_float_disable(thread); } -#include +#include static inline int z_vrfy_k_float_enable(struct k_thread *thread, unsigned int options) { K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_float_enable(thread, options); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/futex.c b/kernel/futex.c index 1354a6314e496..86acc0c74a02f 100644 --- a/kernel/futex.c +++ b/kernel/futex.c @@ -17,7 +17,7 @@ static struct z_futex_data *k_futex_find_data(struct k_futex *futex) struct k_object *obj; obj = k_object_find(futex); - if (obj == NULL || obj->type != K_OBJ_FUTEX) { + if ((obj == NULL) || (obj->type != K_OBJ_FUTEX)) { return NULL; } @@ -60,7 +60,7 @@ static inline int z_vrfy_k_futex_wake(struct k_futex *futex, bool wake_all) return z_impl_k_futex_wake(futex, wake_all); } -#include +#include int z_impl_k_futex_wait(struct k_futex *futex, int expected, k_timeout_t timeout) @@ -98,4 +98,4 @@ static inline int z_vrfy_k_futex_wait(struct k_futex *futex, int expected, return z_impl_k_futex_wait(futex, expected, timeout); } -#include +#include diff --git a/kernel/idle.c b/kernel/idle.c index bef193aa8e86d..62ff84e4c88dc 100644 --- a/kernel/idle.c +++ b/kernel/idle.c @@ -18,21 +18,6 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); -void z_pm_save_idle_exit(void) -{ -#ifdef CONFIG_PM - /* Some CPU low power states require notification at the ISR - * to allow any operations that needs to be done before kernel - * switches task or processes nested interrupts. - * This can be simply ignored if not required. - */ - pm_system_resume(); -#endif /* CONFIG_PM */ -#ifdef CONFIG_SYS_CLOCK_EXISTS - sys_clock_idle_exit(); -#endif /* CONFIG_SYS_CLOCK_EXISTS */ -} - void idle(void *unused1, void *unused2, void *unused3) { ARG_UNUSED(unused1); diff --git a/kernel/include/gen_offset.h b/kernel/include/gen_offset.h index bdc9f785809a6..46a651cf28da7 100644 --- a/kernel/include/gen_offset.h +++ b/kernel/include/gen_offset.h @@ -84,7 +84,13 @@ #define GEN_OFFSET_SYM(S, M) \ GEN_ABSOLUTE_SYM(__##S##_##M##_##OFFSET, offsetof(S, M)) +#define GEN_OFFSET_STRUCT(S, M) \ + GEN_ABSOLUTE_SYM(__struct_##S##_##M##_##OFFSET, offsetof(struct S, M)) + #define GEN_NAMED_OFFSET_SYM(S, M, N) \ GEN_ABSOLUTE_SYM(__##S##_##N##_##OFFSET, offsetof(S, M)) +#define GEN_NAMED_OFFSET_STRUCT(S, M, N) \ + GEN_ABSOLUTE_SYM(__struct_##S##_##N##_##OFFSET, offsetof(struct S, M)) + #endif /* ZEPHYR_KERNEL_INCLUDE_GEN_OFFSET_H_ */ diff --git a/kernel/include/ipi.h b/kernel/include/ipi.h index 77105cac16834..b353a676d4624 100644 --- a/kernel/include/ipi.h +++ b/kernel/include/ipi.h @@ -7,13 +7,25 @@ #ifndef ZEPHYR_KERNEL_INCLUDE_IPI_H_ #define ZEPHYR_KERNEL_INCLUDE_IPI_H_ +#include +#include +#include + +#define IPI_ALL_CPUS_MASK ((1 << CONFIG_MP_MAX_NUM_CPUS) - 1) + +#define IPI_CPU_MASK(cpu_id) \ + (IS_ENABLED(CONFIG_IPI_OPTIMIZE) ? BIT(cpu_id) : IPI_ALL_CPUS_MASK) + + /* defined in ipi.c when CONFIG_SMP=y */ #ifdef CONFIG_SMP -void flag_ipi(void); +void flag_ipi(uint32_t ipi_mask); void signal_pending_ipi(void); +atomic_val_t ipi_mask_create(struct k_thread *thread); #else -#define flag_ipi() do { } while (false) +#define flag_ipi(ipi_mask) do { } while (false) #define signal_pending_ipi() do { } while (false) #endif /* CONFIG_SMP */ + #endif /* ZEPHYR_KERNEL_INCLUDE_IPI_H_ */ diff --git a/kernel/include/kernel_arch_interface.h b/kernel/include/kernel_arch_interface.h index 18944dc78a06c..7ff269b69f5e8 100644 --- a/kernel/include/kernel_arch_interface.h +++ b/kernel/include/kernel_arch_interface.h @@ -341,7 +341,7 @@ int arch_page_phys_get(void *virt, uintptr_t *phys); * example of this is reserved regions in the first megabyte on PC-like systems. * * Implementations of this function should mark all relevant entries in - * z_page_frames with K_PAGE_FRAME_RESERVED. This function is called at + * k_mem_page_frames with K_PAGE_FRAME_RESERVED. This function is called at * early system initialization with mm_lock held. */ void arch_reserved_pages_update(void); @@ -390,9 +390,9 @@ void arch_mem_page_in(void *addr, uintptr_t phys); * Update current page tables for a temporary mapping * * Map a physical page frame address to a special virtual address - * Z_SCRATCH_PAGE, with read/write access to supervisor mode, such that + * K_MEM_SCRATCH_PAGE, with read/write access to supervisor mode, such that * when this function returns, the calling context can read/write the page - * frame's contents from the Z_SCRATCH_PAGE address. + * frame's contents from the K_MEM_SCRATCH_PAGE address. * * This mapping only needs to be done on the current set of page tables, * as it is only used for a short period of time exclusively by the caller. @@ -435,12 +435,12 @@ enum arch_page_location { * in that. * * @param addr Virtual data page address that took the page fault - * @param [out] location In the case of ARCH_PAGE_FAULT_PAGED_OUT, the backing + * @param [out] location In the case of ARCH_PAGE_LOCATION_PAGED_OUT, the backing * store location value used to retrieve the data page. In the case of - * ARCH_PAGE_FAULT_PAGED_IN, the physical address the page is mapped to. - * @retval ARCH_PAGE_FAULT_PAGED_OUT The page was evicted to the backing store. - * @retval ARCH_PAGE_FAULT_PAGED_IN The data page is resident in memory. - * @retval ARCH_PAGE_FAULT_BAD The page is un-mapped or otherwise has had + * ARCH_PAGE_LOCATION_PAGED_IN, the physical address the page is mapped to. + * @retval ARCH_PAGE_LOCATION_PAGED_OUT The page was evicted to the backing store. + * @retval ARCH_PAGE_LOCATION_PAGED_IN The data page is resident in memory. + * @retval ARCH_PAGE_LOCATION_BAD The page is un-mapped or otherwise has had * invalid access */ enum arch_page_location arch_page_location_get(void *addr, uintptr_t *location); @@ -583,7 +583,7 @@ static inline void arch_nop(void); * * @param esf Exception Stack Frame (arch-specific) */ -void arch_coredump_info_dump(const z_arch_esf_t *esf); +void arch_coredump_info_dump(const struct arch_esf *esf); /** * @brief Get the target code specified by the architecture. diff --git a/kernel/include/kernel_internal.h b/kernel/include/kernel_internal.h index b2e1ccf706823..bb9ee4b01f1e6 100644 --- a/kernel/include/kernel_internal.h +++ b/kernel/include/kernel_internal.h @@ -243,26 +243,6 @@ void z_handle_obj_poll_events(sys_dlist_t *events, uint32_t state); */ bool pm_system_suspend(int32_t ticks); -/** - * Notify exit from kernel idling after PM operations - * - * This function would notify exit from kernel idling if a corresponding - * pm_system_suspend() notification was handled and did not return - * PM_STATE_ACTIVE. - * - * This function would be called from the ISR context of the event - * that caused the exit from kernel idling. This will be called immediately - * after interrupts are enabled. This is called to give a chance to do - * any operations before the kernel would switch tasks or processes nested - * interrupts. This is required for cpu low power states that would require - * interrupts to be enabled while entering low power states. e.g. C1 in x86. In - * those cases, the ISR would be invoked immediately after the event wakes up - * the CPU, before code following the CPU wait, gets a chance to execute. This - * can be ignored if no operation needs to be done at the wake event - * notification. - */ -void pm_system_resume(void); - #endif /* CONFIG_PM */ #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM diff --git a/kernel/include/kernel_offsets.h b/kernel/include/kernel_offsets.h index 41b310a08188d..a7b1f4e00d37f 100644 --- a/kernel/include/kernel_offsets.h +++ b/kernel/include/kernel_offsets.h @@ -10,7 +10,7 @@ #ifndef ZEPHYR_KERNEL_INCLUDE_KERNEL_OFFSETS_H_ #define ZEPHYR_KERNEL_INCLUDE_KERNEL_OFFSETS_H_ -#include +#include /* All of this is build time magic, but LCOV gets confused. Disable coverage * for this whole file. diff --git a/kernel/include/ksched.h b/kernel/include/ksched.h index 058e44ebef3a9..a25755aac279b 100644 --- a/kernel/include/ksched.h +++ b/kernel/include/ksched.h @@ -117,7 +117,7 @@ int32_t z_sched_prio_cmp(struct k_thread *thread_1, struct k_thread *thread_2); static inline bool _is_valid_prio(int prio, void *entry_point) { - if (prio == K_IDLE_PRIO && z_is_idle_thread_entry(entry_point)) { + if ((prio == K_IDLE_PRIO) && z_is_idle_thread_entry(entry_point)) { return true; } diff --git a/kernel/include/mmu.h b/kernel/include/mmu.h index 590852e4e3706..e4a9f84d334ac 100644 --- a/kernel/include/mmu.h +++ b/kernel/include/mmu.h @@ -9,68 +9,136 @@ #ifdef CONFIG_MMU #include -#include +#include #include #include #include #include -/* - * At present, page frame management is only done for main system RAM, - * and we generate paging structures based on CONFIG_SRAM_BASE_ADDRESS - * and CONFIG_SRAM_SIZE. +/** Start address of physical memory. */ +#define K_MEM_PHYS_RAM_START ((uintptr_t)CONFIG_SRAM_BASE_ADDRESS) + +/** Size of physical memory. */ +#define K_MEM_PHYS_RAM_SIZE (KB(CONFIG_SRAM_SIZE)) + +/** End address (exclusive) of physical memory. */ +#define K_MEM_PHYS_RAM_END (K_MEM_PHYS_RAM_START + K_MEM_PHYS_RAM_SIZE) + +/** Start address of virtual memory. */ +#define K_MEM_VIRT_RAM_START ((uint8_t *)CONFIG_KERNEL_VM_BASE) + +/** Size of virtual memory. */ +#define K_MEM_VIRT_RAM_SIZE ((size_t)CONFIG_KERNEL_VM_SIZE) + +/** End address (exclusive) of virtual memory. */ +#define K_MEM_VIRT_RAM_END (K_MEM_VIRT_RAM_START + K_MEM_VIRT_RAM_SIZE) + +/** Boot-time virtual start address of the kernel image. */ +#define K_MEM_KERNEL_VIRT_START ((uint8_t *)&z_mapped_start[0]) + +/** Boot-time virtual end address of the kernel image. */ +#define K_MEM_KERNEL_VIRT_END ((uint8_t *)&z_mapped_end[0]) + +/** Boot-time virtual address space size of the kernel image. */ +#define K_MEM_KERNEL_VIRT_SIZE (K_MEM_KERNEL_VIRT_END - K_MEM_KERNEL_VIRT_START) + +/** + * @brief Offset for translating between static physical and virtual addresses. * - * If we have other RAM regions (DCCM, etc) these typically have special - * properties and shouldn't be used generically for demand paging or - * anonymous mappings. We don't currently maintain an ontology of these in the - * core kernel. + * @note Do not use directly unless you know exactly what you are going. */ -#define Z_PHYS_RAM_START ((uintptr_t)CONFIG_SRAM_BASE_ADDRESS) -#define Z_PHYS_RAM_SIZE ((size_t)KB(CONFIG_SRAM_SIZE)) -#define Z_PHYS_RAM_END (Z_PHYS_RAM_START + Z_PHYS_RAM_SIZE) -#define Z_NUM_PAGE_FRAMES (Z_PHYS_RAM_SIZE / (size_t)CONFIG_MMU_PAGE_SIZE) - -/** End virtual address of virtual address space */ -#define Z_VIRT_RAM_START ((uint8_t *)CONFIG_KERNEL_VM_BASE) -#define Z_VIRT_RAM_SIZE ((size_t)CONFIG_KERNEL_VM_SIZE) -#define Z_VIRT_RAM_END (Z_VIRT_RAM_START + Z_VIRT_RAM_SIZE) - -/* Boot-time virtual location of the kernel image. */ -#define Z_KERNEL_VIRT_START ((uint8_t *)&z_mapped_start[0]) -#define Z_KERNEL_VIRT_END ((uint8_t *)&z_mapped_end[0]) -#define Z_KERNEL_VIRT_SIZE (Z_KERNEL_VIRT_END - Z_KERNEL_VIRT_START) - -#define Z_VM_OFFSET ((CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_OFFSET) - \ - (CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_OFFSET)) - -/* Only applies to boot RAM mappings within the Zephyr image that have never - * been remapped or paged out. Never use this unless you know exactly what you - * are doing. +#define K_MEM_VM_OFFSET \ + ((CONFIG_KERNEL_VM_BASE + CONFIG_KERNEL_VM_OFFSET) - \ + (CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_OFFSET)) + +/** + * @brief Get physical address from virtual address for boot RAM mappings. + * + * @note Only applies to boot RAM mappings within the Zephyr image that have never + * been remapped or paged out. Never use this unless you know exactly what you + * are doing. + * + * @param virt Virtual address. + * + * @return Physical address. + */ +#define K_MEM_BOOT_VIRT_TO_PHYS(virt) ((uintptr_t)(((uint8_t *)(virt)) - K_MEM_VM_OFFSET)) + +/** + * @brief Get virtual address from physical address for boot RAM mappings. + * + * @note Only applies to boot RAM mappings within the Zephyr image that have never + * been remapped or paged out. Never use this unless you know exactly what you + * are doing. + * + * @param phys Physical address. + * + * @return Virtual address. */ -#define Z_BOOT_VIRT_TO_PHYS(virt) ((uintptr_t)(((uint8_t *)virt) - Z_VM_OFFSET)) -#define Z_BOOT_PHYS_TO_VIRT(phys) ((uint8_t *)(((uintptr_t)phys) + Z_VM_OFFSET)) +#define K_MEM_BOOT_PHYS_TO_VIRT(phys) ((uint8_t *)(((uintptr_t)(phys)) + K_MEM_VM_OFFSET)) +/** + * @def K_MEM_VM_FREE_START + * @brief Start address of unused, available virtual addresses. + * + * This is the start address of the virtual memory region where + * addresses can be allocated for memory mapping. This depends on whether + * CONFIG_ARCH_MAPS_ALL_RAM is enabled: + * + * - If it is enabled, which means all physical memory are mapped in virtual + * memory address space, and it is the same as + * (CONFIG_SRAM_BASE_ADDRESS + CONFIG_SRAM_SIZE). + * + * - If it is disabled, K_MEM_VM_FREE_START is the same K_MEM_KERNEL_VIRT_END which + * is the end of the kernel image. + * + */ #ifdef CONFIG_ARCH_MAPS_ALL_RAM -#define Z_FREE_VM_START Z_BOOT_PHYS_TO_VIRT(Z_PHYS_RAM_END) +#define K_MEM_VM_FREE_START K_MEM_BOOT_PHYS_TO_VIRT(K_MEM_PHYS_RAM_END) #else -#define Z_FREE_VM_START Z_KERNEL_VIRT_END +#define K_MEM_VM_FREE_START K_MEM_KERNEL_VIRT_END #endif /* CONFIG_ARCH_MAPS_ALL_RAM */ -/* +/** + * @defgroup kernel_mm_page_frame_apis Kernel Memory Page Frame Management APIs + * @ingroup kernel_mm_internal_apis + * @{ + * * Macros and data structures for physical page frame accounting, * APIs for use by eviction and backing store algorithms. This code * is otherwise not application-facing. */ +/** + * @brief Number of page frames. + * + * At present, page frame management is only done for main system RAM, + * and we generate paging structures based on CONFIG_SRAM_BASE_ADDRESS + * and CONFIG_SRAM_SIZE. + * + * If we have other RAM regions (DCCM, etc) these typically have special + * properties and shouldn't be used generically for demand paging or + * anonymous mappings. We don't currently maintain an ontology of these in the + * core kernel. + */ +#define K_MEM_NUM_PAGE_FRAMES (K_MEM_PHYS_RAM_SIZE / (size_t)CONFIG_MMU_PAGE_SIZE) + /* - * z_page_frame flags bits + * k_mem_page_frame flags bits + * + * Requirements: + * - K_MEM_PAGE_FRAME_FREE must be one of the possible sfnode flag bits + * - All bit values must be lower than CONFIG_MMU_PAGE_SIZE */ -/** This page contains critical kernel data and will never be swapped */ -#define Z_PAGE_FRAME_PINNED BIT(0) +/** This physical page is free and part of the free list */ +#define K_MEM_PAGE_FRAME_FREE BIT(0) /** This physical page is reserved by hardware; we will never use it */ -#define Z_PAGE_FRAME_RESERVED BIT(1) +#define K_MEM_PAGE_FRAME_RESERVED BIT(1) + +/** This page contains critical kernel data and will never be swapped */ +#define K_MEM_PAGE_FRAME_PINNED BIT(2) /** * This physical page is mapped to some virtual memory address @@ -78,17 +146,17 @@ * Currently, we just support one mapping per page frame. If a page frame * is mapped to multiple virtual pages then it must be pinned. */ -#define Z_PAGE_FRAME_MAPPED BIT(2) +#define K_MEM_PAGE_FRAME_MAPPED BIT(3) /** * This page frame is currently involved in a page-in/out operation */ -#define Z_PAGE_FRAME_BUSY BIT(3) +#define K_MEM_PAGE_FRAME_BUSY BIT(4) /** * This page frame has a clean copy in the backing store */ -#define Z_PAGE_FRAME_BACKED BIT(4) +#define K_MEM_PAGE_FRAME_BACKED BIT(5) /** * Data structure for physical page frames @@ -96,110 +164,133 @@ * An array of these is instantiated, one element per physical RAM page. * Hence it's necessary to constrain its size as much as possible. */ -struct z_page_frame { +struct k_mem_page_frame { union { - /* If mapped, virtual address this page is mapped to */ - void *addr; - - /* If unmapped and available, free pages list membership. */ - sys_snode_t node; + /* + * If mapped, K_MEM_PAGE_FRAME_* flags and virtual address + * this page is mapped to. + */ + uintptr_t va_and_flags; + + /* + * If unmapped and available, free pages list membership + * with the K_MEM_PAGE_FRAME_FREE flag. + */ + sys_sfnode_t node; }; - /* Z_PAGE_FRAME_* flags */ - uint8_t flags; - - /* TODO: Backing store and eviction algorithms may both need to - * introduce custom members for accounting purposes. Come up with - * a layer of abstraction for this. They may also want additional - * flags bits which shouldn't clobber each other. At all costs - * the total size of struct z_page_frame must be minimized. + /* Backing store and eviction algorithms may both need to + * require additional per-frame custom data for accounting purposes. + * They should declare their own array with indices matching + * k_mem_page_frames[] ones whenever possible. + * They may also want additional flags bits that could be stored here + * and they shouldn't clobber each other. At all costs the total + * size of struct k_mem_page_frame must be minimized. */ +}; - /* On Xtensa we can't pack this struct because of the memory alignment. - */ -#ifdef CONFIG_XTENSA -} __aligned(4); -#else -} __packed; -#endif /* CONFIG_XTENSA */ +/* Note: this must be false for the other flag bits to be valid */ +static inline bool k_mem_page_frame_is_free(struct k_mem_page_frame *pf) +{ + return (pf->va_and_flags & K_MEM_PAGE_FRAME_FREE) != 0U; +} -static inline bool z_page_frame_is_pinned(struct z_page_frame *pf) +static inline bool k_mem_page_frame_is_pinned(struct k_mem_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_PINNED) != 0U; + return (pf->va_and_flags & K_MEM_PAGE_FRAME_PINNED) != 0U; } -static inline bool z_page_frame_is_reserved(struct z_page_frame *pf) +static inline bool k_mem_page_frame_is_reserved(struct k_mem_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_RESERVED) != 0U; + return (pf->va_and_flags & K_MEM_PAGE_FRAME_RESERVED) != 0U; } -static inline bool z_page_frame_is_mapped(struct z_page_frame *pf) +static inline bool k_mem_page_frame_is_mapped(struct k_mem_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_MAPPED) != 0U; + return (pf->va_and_flags & K_MEM_PAGE_FRAME_MAPPED) != 0U; } -static inline bool z_page_frame_is_busy(struct z_page_frame *pf) +static inline bool k_mem_page_frame_is_busy(struct k_mem_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_BUSY) != 0U; + return (pf->va_and_flags & K_MEM_PAGE_FRAME_BUSY) != 0U; } -static inline bool z_page_frame_is_backed(struct z_page_frame *pf) +static inline bool k_mem_page_frame_is_backed(struct k_mem_page_frame *pf) { - return (pf->flags & Z_PAGE_FRAME_BACKED) != 0U; + return (pf->va_and_flags & K_MEM_PAGE_FRAME_BACKED) != 0U; } -static inline bool z_page_frame_is_evictable(struct z_page_frame *pf) +static inline bool k_mem_page_frame_is_evictable(struct k_mem_page_frame *pf) { - return (!z_page_frame_is_reserved(pf) && z_page_frame_is_mapped(pf) && - !z_page_frame_is_pinned(pf) && !z_page_frame_is_busy(pf)); + return (!k_mem_page_frame_is_free(pf) && + !k_mem_page_frame_is_reserved(pf) && + k_mem_page_frame_is_mapped(pf) && + !k_mem_page_frame_is_pinned(pf) && + !k_mem_page_frame_is_busy(pf)); } -/* If true, page is not being used for anything, is not reserved, is a member - * of some free pages list, isn't busy, and may be mapped in memory +/* If true, page is not being used for anything, is not reserved, is not + * a member of some free pages list, isn't busy, and is ready to be mapped + * in memory */ -static inline bool z_page_frame_is_available(struct z_page_frame *page) +static inline bool k_mem_page_frame_is_available(struct k_mem_page_frame *page) +{ + return page->va_and_flags == 0U; +} + +static inline void k_mem_page_frame_set(struct k_mem_page_frame *pf, uint8_t flags) { - return page->flags == 0U; + pf->va_and_flags |= flags; } -static inline void z_assert_phys_aligned(uintptr_t phys) +static inline void k_mem_page_frame_clear(struct k_mem_page_frame *pf, uint8_t flags) +{ + /* ensure bit inversion to follow is done on the proper type width */ + uintptr_t wide_flags = flags; + + pf->va_and_flags &= ~wide_flags; +} + +static inline void k_mem_assert_phys_aligned(uintptr_t phys) { __ASSERT(phys % CONFIG_MMU_PAGE_SIZE == 0U, "physical address 0x%lx is not page-aligned", phys); (void)phys; } -extern struct z_page_frame z_page_frames[Z_NUM_PAGE_FRAMES]; +extern struct k_mem_page_frame k_mem_page_frames[K_MEM_NUM_PAGE_FRAMES]; -static inline uintptr_t z_page_frame_to_phys(struct z_page_frame *pf) +static inline uintptr_t k_mem_page_frame_to_phys(struct k_mem_page_frame *pf) { - return (uintptr_t)((pf - z_page_frames) * CONFIG_MMU_PAGE_SIZE) + - Z_PHYS_RAM_START; + return (uintptr_t)((pf - k_mem_page_frames) * CONFIG_MMU_PAGE_SIZE) + + K_MEM_PHYS_RAM_START; } /* Presumes there is but one mapping in the virtual address space */ -static inline void *z_page_frame_to_virt(struct z_page_frame *pf) +static inline void *k_mem_page_frame_to_virt(struct k_mem_page_frame *pf) { - return pf->addr; + uintptr_t flags_mask = CONFIG_MMU_PAGE_SIZE - 1; + + return (void *)(pf->va_and_flags & ~flags_mask); } -static inline bool z_is_page_frame(uintptr_t phys) +static inline bool k_mem_is_page_frame(uintptr_t phys) { - z_assert_phys_aligned(phys); - return IN_RANGE(phys, (uintptr_t)Z_PHYS_RAM_START, - (uintptr_t)(Z_PHYS_RAM_END - 1)); + k_mem_assert_phys_aligned(phys); + return IN_RANGE(phys, (uintptr_t)K_MEM_PHYS_RAM_START, + (uintptr_t)(K_MEM_PHYS_RAM_END - 1)); } -static inline struct z_page_frame *z_phys_to_page_frame(uintptr_t phys) +static inline struct k_mem_page_frame *k_mem_phys_to_page_frame(uintptr_t phys) { - __ASSERT(z_is_page_frame(phys), + __ASSERT(k_mem_is_page_frame(phys), "0x%lx not an SRAM physical address", phys); - return &z_page_frames[(phys - Z_PHYS_RAM_START) / - CONFIG_MMU_PAGE_SIZE]; + return &k_mem_page_frames[(phys - K_MEM_PHYS_RAM_START) / + CONFIG_MMU_PAGE_SIZE]; } -static inline void z_mem_assert_virtual_region(uint8_t *addr, size_t size) +static inline void k_mem_assert_virtual_region(uint8_t *addr, size_t size) { __ASSERT((uintptr_t)addr % CONFIG_MMU_PAGE_SIZE == 0U, "unaligned addr %p", addr); @@ -208,35 +299,48 @@ static inline void z_mem_assert_virtual_region(uint8_t *addr, size_t size) __ASSERT(!Z_DETECT_POINTER_OVERFLOW(addr, size), "region %p size %zu zero or wraps around", addr, size); __ASSERT(IN_RANGE((uintptr_t)addr, - (uintptr_t)Z_VIRT_RAM_START, - ((uintptr_t)Z_VIRT_RAM_END - 1)) && + (uintptr_t)K_MEM_VIRT_RAM_START, + ((uintptr_t)K_MEM_VIRT_RAM_END - 1)) && IN_RANGE(((uintptr_t)addr + size - 1), - (uintptr_t)Z_VIRT_RAM_START, - ((uintptr_t)Z_VIRT_RAM_END - 1)), + (uintptr_t)K_MEM_VIRT_RAM_START, + ((uintptr_t)K_MEM_VIRT_RAM_END - 1)), "invalid virtual address region %p (%zu)", addr, size); } -/* Debug function, pretty-print page frame information for all frames +/** + * @brief Pretty-print page frame information for all page frames. + * + * Debug function, pretty-print page frame information for all frames * concisely to printk. */ -void z_page_frames_dump(void); +void k_mem_page_frames_dump(void); /* Convenience macro for iterating over all page frames */ -#define Z_PAGE_FRAME_FOREACH(_phys, _pageframe) \ - for (_phys = Z_PHYS_RAM_START, _pageframe = z_page_frames; \ - _phys < Z_PHYS_RAM_END; \ - _phys += CONFIG_MMU_PAGE_SIZE, _pageframe++) +#define K_MEM_PAGE_FRAME_FOREACH(_phys, _pageframe) \ + for ((_phys) = K_MEM_PHYS_RAM_START, (_pageframe) = k_mem_page_frames; \ + (_phys) < K_MEM_PHYS_RAM_END; \ + (_phys) += CONFIG_MMU_PAGE_SIZE, (_pageframe)++) + +/** @} */ +/** + * @def K_MEM_VM_RESERVED + * @brief Reserve space at the end of virtual memory. + */ #ifdef CONFIG_DEMAND_PAGING /* We reserve a virtual page as a scratch area for page-ins/outs at the end * of the address space */ -#define Z_VM_RESERVED CONFIG_MMU_PAGE_SIZE -#define Z_SCRATCH_PAGE ((void *)((uintptr_t)CONFIG_KERNEL_VM_BASE + \ - (uintptr_t)CONFIG_KERNEL_VM_SIZE - \ - CONFIG_MMU_PAGE_SIZE)) +#define K_MEM_VM_RESERVED CONFIG_MMU_PAGE_SIZE + +/** + * @brief Location of the scratch page used for demand paging. + */ +#define K_MEM_SCRATCH_PAGE ((void *)((uintptr_t)CONFIG_KERNEL_VM_BASE + \ + (uintptr_t)CONFIG_KERNEL_VM_SIZE - \ + CONFIG_MMU_PAGE_SIZE)) #else -#define Z_VM_RESERVED 0 +#define K_MEM_VM_RESERVED 0 #endif /* CONFIG_DEMAND_PAGING */ #ifdef CONFIG_DEMAND_PAGING @@ -252,7 +356,7 @@ void z_page_frames_dump(void); * * @return Number of successful page faults */ -unsigned long z_num_pagefaults_get(void); +unsigned long k_mem_num_pagefaults_get(void); /** * Free a page frame physical address by evicting its contents @@ -271,7 +375,7 @@ unsigned long z_num_pagefaults_get(void); * @retval 0 Success * @retval -ENOMEM Insufficient backing store space */ -int z_page_frame_evict(uintptr_t phys); +int k_mem_page_frame_evict(uintptr_t phys); /** * Handle a page fault for a virtual data page @@ -300,7 +404,8 @@ int z_page_frame_evict(uintptr_t phys); * @retval false This page fault was from an un-mapped page, should * be treated as an error, and not re-tried. */ -bool z_page_fault(void *addr); +bool k_mem_page_fault(void *addr); + #endif /* CONFIG_DEMAND_PAGING */ #endif /* CONFIG_MMU */ #endif /* KERNEL_INCLUDE_MMU_H */ diff --git a/kernel/include/offsets_short.h b/kernel/include/offsets_short.h index 13e1afe6dfca8..373d7e02ec981 100644 --- a/kernel/include/offsets_short.h +++ b/kernel/include/offsets_short.h @@ -7,7 +7,7 @@ #ifndef ZEPHYR_KERNEL_INCLUDE_OFFSETS_SHORT_H_ #define ZEPHYR_KERNEL_INCLUDE_OFFSETS_SHORT_H_ -#include +#include #include /* kernel */ diff --git a/kernel/include/priority_q.h b/kernel/include/priority_q.h index f744e6c5467c3..a2edc26088fa8 100644 --- a/kernel/include/priority_q.h +++ b/kernel/include/priority_q.h @@ -79,7 +79,8 @@ static ALWAYS_INLINE void z_priq_rb_add(struct _priq_rb *pq, struct k_thread *th { struct k_thread *t; - thread->base.order_key = pq->next_order_key++; + thread->base.order_key = pq->next_order_key; + ++pq->next_order_key; /* Renumber at wraparound. This is tiny code, and in practice * will almost never be hit on real systems. BUT on very @@ -89,7 +90,8 @@ static ALWAYS_INLINE void z_priq_rb_add(struct _priq_rb *pq, struct k_thread *th */ if (!pq->next_order_key) { RB_FOR_EACH_CONTAINER(&pq->tree, t, base.qnode_rb) { - t->base.order_key = pq->next_order_key++; + t->base.order_key = pq->next_order_key; + ++pq->next_order_key; } } diff --git a/kernel/init.c b/kernel/init.c index eaffb6ce763b3..cff9750567dd2 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -46,8 +46,9 @@ BUILD_ASSERT(CONFIG_MP_NUM_CPUS == CONFIG_MP_MAX_NUM_CPUS, __pinned_bss struct z_kernel _kernel; -__pinned_bss -atomic_t _cpus_active; +#ifdef CONFIG_PM +__pinned_bss atomic_t _cpus_active; +#endif /* init/main and idle threads */ K_THREAD_PINNED_STACK_DEFINE(z_main_stack, CONFIG_MAIN_STACK_SIZE); @@ -394,7 +395,7 @@ static inline int z_vrfy_device_init(const struct device *dev) return z_impl_device_init(dev); } -#include +#include #endif extern void boot_banner(void); @@ -416,8 +417,8 @@ static void bg_thread_main(void *unused1, void *unused2, void *unused3) #ifdef CONFIG_MMU /* Invoked here such that backing store or eviction algorithms may * initialize kernel objects, and that all POST_KERNEL and later tasks - * may perform memory management tasks (except for z_phys_map() which - * is allowed at any time) + * may perform memory management tasks (except for + * k_mem_map_phys_bare() which is allowed at any time) */ z_mem_manage_init(); #endif /* CONFIG_MMU */ @@ -473,6 +474,7 @@ static void init_idle_thread(int i) { struct k_thread *thread = &z_idle_threads[i]; k_thread_stack_t *stack = z_idle_stacks[i]; + size_t stack_size = K_KERNEL_STACK_SIZEOF(z_idle_stacks[i]); #ifdef CONFIG_THREAD_NAME @@ -488,7 +490,7 @@ static void init_idle_thread(int i) #endif /* CONFIG_THREAD_NAME */ z_setup_new_thread(thread, stack, - CONFIG_IDLE_STACK_SIZE, idle, &_kernel.cpus[i], + stack_size, idle, &_kernel.cpus[i], NULL, NULL, K_IDLE_PRIO, K_ESSENTIAL, tname); z_mark_thread_as_started(thread); @@ -512,11 +514,13 @@ void z_init_cpu(int id) CONFIG_SCHED_THREAD_USAGE_AUTO_ENABLE; #endif +#ifdef CONFIG_PM /* * Increment number of CPUs active. The pm subsystem * will keep track of this from here. */ atomic_inc(&_cpus_active); +#endif #ifdef CONFIG_OBJ_CORE_SYSTEM k_obj_core_init_and_link(K_OBJ_CORE(&_kernel.cpus[id]), &obj_type_cpu); @@ -561,7 +565,8 @@ static char *prepare_multithreading(void) _kernel.ready_q.cache = &z_main_thread; #endif /* CONFIG_SMP */ stack_ptr = z_setup_new_thread(&z_main_thread, z_main_stack, - CONFIG_MAIN_STACK_SIZE, bg_thread_main, + K_THREAD_STACK_SIZEOF(z_main_stack), + bg_thread_main, NULL, NULL, NULL, CONFIG_MAIN_THREAD_PRIORITY, K_ESSENTIAL, "main"); @@ -657,6 +662,9 @@ FUNC_NORETURN void z_cstart(void) /* perform basic hardware initialization */ z_sys_init_run_level(INIT_LEVEL_PRE_KERNEL_1); +#if defined(CONFIG_SMP) + arch_smp_init(); +#endif z_sys_init_run_level(INIT_LEVEL_PRE_KERNEL_2); #ifdef CONFIG_STACK_CANARIES diff --git a/kernel/ipi.c b/kernel/ipi.c index 99693c0ecbfcf..ee01c4594251c 100644 --- a/kernel/ipi.c +++ b/kernel/ipi.c @@ -13,15 +13,58 @@ extern void z_trace_sched_ipi(void); #endif -void flag_ipi(void) +void flag_ipi(uint32_t ipi_mask) { #if defined(CONFIG_SCHED_IPI_SUPPORTED) if (arch_num_cpus() > 1) { - _kernel.pending_ipi = true; + atomic_or(&_kernel.pending_ipi, (atomic_val_t)ipi_mask); } #endif /* CONFIG_SCHED_IPI_SUPPORTED */ } +/* Create a bitmask of CPUs that need an IPI. Note: sched_spinlock is held. */ +atomic_val_t ipi_mask_create(struct k_thread *thread) +{ + if (!IS_ENABLED(CONFIG_IPI_OPTIMIZE)) { + return (CONFIG_MP_MAX_NUM_CPUS > 1) ? IPI_ALL_CPUS_MASK : 0; + } + + uint32_t ipi_mask = 0; + uint32_t num_cpus = (uint32_t)arch_num_cpus(); + uint32_t id = _current_cpu->id; + struct k_thread *cpu_thread; + bool executable_on_cpu = true; + + for (uint32_t i = 0; i < num_cpus; i++) { + if (id == i) { + continue; + } + + /* + * An IPI absolutely does not need to be sent if ... + * 1. the CPU is not active, or + * 2. can not execute on the target CPU + * ... and might not need to be sent if ... + * 3. the target CPU's active thread is not preemptible, or + * 4. the target CPU's active thread has a higher priority + * (Items 3 & 4 may be overridden by a metaIRQ thread) + */ + +#if defined(CONFIG_SCHED_CPU_MASK) + executable_on_cpu = ((thread->base.cpu_mask & BIT(i)) != 0); +#endif + + cpu_thread = _kernel.cpus[i].current; + if ((cpu_thread != NULL) && + (((z_sched_prio_cmp(cpu_thread, thread) < 0) && + (thread_is_preemptible(cpu_thread))) || + thread_is_metairq(thread)) && executable_on_cpu) { + ipi_mask |= BIT(i); + } + } + + return (atomic_val_t)ipi_mask; +} void signal_pending_ipi(void) { @@ -34,9 +77,15 @@ void signal_pending_ipi(void) */ #if defined(CONFIG_SCHED_IPI_SUPPORTED) if (arch_num_cpus() > 1) { - if (_kernel.pending_ipi) { - _kernel.pending_ipi = false; - arch_sched_ipi(); + uint32_t cpu_bitmap; + + cpu_bitmap = (uint32_t)atomic_clear(&_kernel.pending_ipi); + if (cpu_bitmap != 0) { +#ifdef CONFIG_ARCH_HAS_DIRECTED_IPIS + arch_sched_directed_ipi(cpu_bitmap); +#else + arch_sched_broadcast_ipi(); +#endif } } #endif /* CONFIG_SCHED_IPI_SUPPORTED */ diff --git a/kernel/kheap.c b/kernel/kheap.c index fd29df2e92c0d..55b9feffced90 100644 --- a/kernel/kheap.c +++ b/kernel/kheap.c @@ -116,6 +116,36 @@ void *k_heap_alloc(struct k_heap *heap, size_t bytes, k_timeout_t timeout) return ret; } +void *k_heap_realloc(struct k_heap *heap, void *ptr, size_t bytes, k_timeout_t timeout) +{ + k_timepoint_t end = sys_timepoint_calc(timeout); + void *ret = NULL; + + k_spinlock_key_t key = k_spin_lock(&heap->lock); + + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap, realloc, heap, ptr, bytes, timeout); + + __ASSERT(!arch_is_in_isr() || K_TIMEOUT_EQ(timeout, K_NO_WAIT), ""); + + while (ret == NULL) { + ret = sys_heap_aligned_realloc(&heap->heap, ptr, sizeof(void *), bytes); + + if (!IS_ENABLED(CONFIG_MULTITHREADING) || + (ret != NULL) || K_TIMEOUT_EQ(timeout, K_NO_WAIT)) { + break; + } + + timeout = sys_timepoint_timeout(end); + (void) z_pend_curr(&heap->lock, key, &heap->wait_q, timeout); + key = k_spin_lock(&heap->lock); + } + + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap, realloc, heap, ptr, bytes, timeout, ret); + + k_spin_unlock(&heap->lock, key); + return ret; +} + void k_heap_free(struct k_heap *heap, void *mem) { k_spinlock_key_t key = k_spin_lock(&heap->lock); @@ -123,7 +153,7 @@ void k_heap_free(struct k_heap *heap, void *mem) sys_heap_free(&heap->heap, mem); SYS_PORT_TRACING_OBJ_FUNC(k_heap, free, heap); - if (IS_ENABLED(CONFIG_MULTITHREADING) && z_unpend_all(&heap->wait_q) != 0) { + if (IS_ENABLED(CONFIG_MULTITHREADING) && (z_unpend_all(&heap->wait_q) != 0)) { z_reschedule(&heap->lock, key); } else { k_spin_unlock(&heap->lock, key); diff --git a/kernel/mem_domain.c b/kernel/mem_domain.c index 5c41c1418fe00..16b337acf011d 100644 --- a/kernel/mem_domain.c +++ b/kernel/mem_domain.c @@ -225,8 +225,8 @@ int k_mem_domain_remove_partition(struct k_mem_domain *domain, /* find a partition that matches the given start and size */ for (p_idx = 0; p_idx < max_partitions; p_idx++) { - if (domain->partitions[p_idx].start == part->start && - domain->partitions[p_idx].size == part->size) { + if ((domain->partitions[p_idx].start == part->start) && + (domain->partitions[p_idx].size == part->size)) { break; } } diff --git a/kernel/mem_slab.c b/kernel/mem_slab.c index 7b62c96facc36..86aebe3834474 100644 --- a/kernel/mem_slab.c +++ b/kernel/mem_slab.c @@ -103,7 +103,6 @@ static struct k_obj_core_stats_desc mem_slab_stats_desc = { */ static int create_free_list(struct k_mem_slab *slab) { - uint32_t j; char *p; /* blocks must be word aligned */ @@ -113,12 +112,12 @@ static int create_free_list(struct k_mem_slab *slab) } slab->free_list = NULL; - p = slab->buffer; + p = slab->buffer + slab->info.block_size * (slab->info.num_blocks - 1); - for (j = 0U; j < slab->info.num_blocks; j++) { + while (p >= slab->buffer) { *(char **)p = slab->free_list; slab->free_list = p; - p += slab->info.block_size; + p -= slab->info.block_size; } return 0; } @@ -205,6 +204,18 @@ int k_mem_slab_init(struct k_mem_slab *slab, void *buffer, return rc; } +#if __ASSERT_ON +static bool slab_ptr_is_good(struct k_mem_slab *slab, const void *ptr) +{ + const char *p = ptr; + ptrdiff_t offset = p - slab->buffer; + + return (offset >= 0) && + (offset < (slab->info.block_size * slab->info.num_blocks)) && + ((offset % slab->info.block_size) == 0); +} +#endif + int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, k_timeout_t timeout) { k_spinlock_key_t key = k_spin_lock(&slab->lock); @@ -217,6 +228,10 @@ int k_mem_slab_alloc(struct k_mem_slab *slab, void **mem, k_timeout_t timeout) *mem = slab->free_list; slab->free_list = *(char **)(slab->free_list); slab->info.num_used++; + __ASSERT((slab->free_list == NULL && + slab->info.num_used == slab->info.num_blocks) || + slab_ptr_is_good(slab, slab->free_list), + "slab corruption detected"); #ifdef CONFIG_MEM_SLAB_TRACE_MAX_UTILIZATION slab->info.max_used = MAX(slab->info.num_used, @@ -254,14 +269,10 @@ void k_mem_slab_free(struct k_mem_slab *slab, void *mem) { k_spinlock_key_t key = k_spin_lock(&slab->lock); - __ASSERT(((char *)mem >= slab->buffer) && - ((((char *)mem - slab->buffer) % slab->info.block_size) == 0) && - ((char *)mem <= (slab->buffer + (slab->info.block_size * - (slab->info.num_blocks - 1)))), - "Invalid memory pointer provided"); + __ASSERT(slab_ptr_is_good(slab, mem), "Invalid memory pointer provided"); SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_mem_slab, free, slab); - if (slab->free_list == NULL && IS_ENABLED(CONFIG_MULTITHREADING)) { + if ((slab->free_list == NULL) && IS_ENABLED(CONFIG_MULTITHREADING)) { struct k_thread *pending_thread = z_unpend_first_thread(&slab->wait_q); if (pending_thread != NULL) { diff --git a/kernel/mempool.c b/kernel/mempool.c index 13e9c7abec24e..d8926c63ed940 100644 --- a/kernel/mempool.c +++ b/kernel/mempool.c @@ -46,7 +46,8 @@ void k_free(void *ptr) if (ptr != NULL) { heap_ref = ptr; - ptr = --heap_ref; + --heap_ref; + ptr = heap_ref; SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_free, *heap_ref, heap_ref); @@ -113,6 +114,41 @@ void *k_calloc(size_t nmemb, size_t size) return ret; } +void *k_realloc(void *ptr, size_t size) +{ + struct k_heap *heap, **heap_ref; + void *ret; + + if (size == 0) { + k_free(ptr); + return NULL; + } + if (ptr == NULL) { + return k_malloc(size); + } + heap_ref = ptr; + ptr = --heap_ref; + heap = *heap_ref; + + SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_heap_sys, k_realloc, heap, ptr); + + if (size_add_overflow(size, sizeof(heap_ref), &size)) { + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_realloc, heap, ptr, NULL); + return NULL; + } + + ret = k_heap_realloc(heap, ptr, size, K_NO_WAIT); + + if (ret != NULL) { + heap_ref = ret; + ret = ++heap_ref; + } + + SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_heap_sys, k_realloc, heap, ptr, ret); + + return ret; +} + void k_thread_system_pool_assign(struct k_thread *thread) { thread->resource_pool = _SYSTEM_HEAP; diff --git a/kernel/mmu.c b/kernel/mmu.c index 162e1c413e941..93b8464a329fd 100644 --- a/kernel/mmu.c +++ b/kernel/mmu.c @@ -31,7 +31,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); * - A page frame is a page-sized physical memory region in RAM. It is a * container where a data page may be placed. It is always referred to by * physical address. We have a convention of using uintptr_t for physical - * addresses. We instantiate a struct z_page_frame to store metadata for + * addresses. We instantiate a struct k_mem_page_frame to store metadata for * every page frame. * * - A data page is a page-sized region of data. It may exist in a page frame, @@ -51,10 +51,10 @@ struct k_spinlock z_mm_lock; */ /* Database of all RAM page frames */ -struct z_page_frame z_page_frames[Z_NUM_PAGE_FRAMES]; +struct k_mem_page_frame k_mem_page_frames[K_MEM_NUM_PAGE_FRAMES]; #if __ASSERT_ON -/* Indicator that z_page_frames has been initialized, many of these APIs do +/* Indicator that k_mem_page_frames has been initialized, many of these APIs do * not work before POST_KERNEL */ static bool page_frames_initialized; @@ -79,21 +79,24 @@ static bool page_frames_initialized; #endif /* COLOR_PAGE_FRAMES */ /* LCOV_EXCL_START */ -static void page_frame_dump(struct z_page_frame *pf) +static void page_frame_dump(struct k_mem_page_frame *pf) { - if (z_page_frame_is_reserved(pf)) { + if (k_mem_page_frame_is_free(pf)) { + COLOR(GREY); + printk("-"); + } else if (k_mem_page_frame_is_reserved(pf)) { COLOR(CYAN); printk("R"); - } else if (z_page_frame_is_busy(pf)) { + } else if (k_mem_page_frame_is_busy(pf)) { COLOR(MAGENTA); printk("B"); - } else if (z_page_frame_is_pinned(pf)) { + } else if (k_mem_page_frame_is_pinned(pf)) { COLOR(YELLOW); printk("P"); - } else if (z_page_frame_is_available(pf)) { + } else if (k_mem_page_frame_is_available(pf)) { COLOR(GREY); printk("."); - } else if (z_page_frame_is_mapped(pf)) { + } else if (k_mem_page_frame_is_mapped(pf)) { COLOR(DEFAULT); printk("M"); } else { @@ -102,16 +105,16 @@ static void page_frame_dump(struct z_page_frame *pf) } } -void z_page_frames_dump(void) +void k_mem_page_frames_dump(void) { int column = 0; __ASSERT(page_frames_initialized, "%s called too early", __func__); printk("Physical memory from 0x%lx to 0x%lx\n", - Z_PHYS_RAM_START, Z_PHYS_RAM_END); + K_MEM_PHYS_RAM_START, K_MEM_PHYS_RAM_END); - for (int i = 0; i < Z_NUM_PAGE_FRAMES; i++) { - struct z_page_frame *pf = &z_page_frames[i]; + for (int i = 0; i < K_MEM_NUM_PAGE_FRAMES; i++) { + struct k_mem_page_frame *pf = &k_mem_page_frames[i]; page_frame_dump(pf); @@ -130,12 +133,12 @@ void z_page_frames_dump(void) /* LCOV_EXCL_STOP */ #define VIRT_FOREACH(_base, _size, _pos) \ - for (_pos = _base; \ - _pos < ((uint8_t *)_base + _size); _pos += CONFIG_MMU_PAGE_SIZE) + for ((_pos) = (_base); \ + (_pos) < ((uint8_t *)(_base) + (_size)); (_pos) += CONFIG_MMU_PAGE_SIZE) #define PHYS_FOREACH(_base, _size, _pos) \ - for (_pos = _base; \ - _pos < ((uintptr_t)_base + _size); _pos += CONFIG_MMU_PAGE_SIZE) + for ((_pos) = (_base); \ + (_pos) < ((uintptr_t)(_base) + (_size)); (_pos) += CONFIG_MMU_PAGE_SIZE) /* @@ -144,8 +147,8 @@ void z_page_frames_dump(void) * Call all of these functions with z_mm_lock held. * * Overall virtual memory map: When the kernel starts, it resides in - * virtual memory in the region Z_KERNEL_VIRT_START to - * Z_KERNEL_VIRT_END. Unused virtual memory past this, up to the limit + * virtual memory in the region K_MEM_KERNEL_VIRT_START to + * K_MEM_KERNEL_VIRT_END. Unused virtual memory past this, up to the limit * noted by CONFIG_KERNEL_VM_SIZE may be used for runtime memory mappings. * * If CONFIG_ARCH_MAPS_ALL_RAM is set, we do not just map the kernel image, @@ -154,15 +157,15 @@ void z_page_frames_dump(void) * the only guarantee is that such RAM mapping outside of the Zephyr image * won't be disturbed by subsequent memory mapping calls. * - * +--------------+ <- Z_VIRT_RAM_START + * +--------------+ <- K_MEM_VIRT_RAM_START * | Undefined VM | <- May contain ancillary regions like x86_64's locore - * +--------------+ <- Z_KERNEL_VIRT_START (often == Z_VIRT_RAM_START) + * +--------------+ <- K_MEM_KERNEL_VIRT_START (often == K_MEM_VIRT_RAM_START) * | Mapping for | * | main kernel | * | image | * | | * | | - * +--------------+ <- Z_FREE_VM_START + * +--------------+ <- K_MEM_VM_FREE_START * | | * | Unused, | * | Available VM | @@ -176,8 +179,8 @@ void z_page_frames_dump(void) * +--------------+ * | Mapping | * +--------------+ <- mappings start here - * | Reserved | <- special purpose virtual page(s) of size Z_VM_RESERVED - * +--------------+ <- Z_VIRT_RAM_END + * | Reserved | <- special purpose virtual page(s) of size K_MEM_VM_RESERVED + * +--------------+ <- K_MEM_VIRT_RAM_END */ /* Bitmap of virtual addresses where one bit corresponds to one page. @@ -192,18 +195,18 @@ SYS_BITARRAY_DEFINE_STATIC(virt_region_bitmap, static bool virt_region_inited; -#define Z_VIRT_REGION_START_ADDR Z_FREE_VM_START -#define Z_VIRT_REGION_END_ADDR (Z_VIRT_RAM_END - Z_VM_RESERVED) +#define Z_VIRT_REGION_START_ADDR K_MEM_VM_FREE_START +#define Z_VIRT_REGION_END_ADDR (K_MEM_VIRT_RAM_END - K_MEM_VM_RESERVED) static inline uintptr_t virt_from_bitmap_offset(size_t offset, size_t size) { - return POINTER_TO_UINT(Z_VIRT_RAM_END) + return POINTER_TO_UINT(K_MEM_VIRT_RAM_END) - (offset * CONFIG_MMU_PAGE_SIZE) - size; } static inline size_t virt_to_bitmap_offset(void *vaddr, size_t size) { - return (POINTER_TO_UINT(Z_VIRT_RAM_END) + return (POINTER_TO_UINT(K_MEM_VIRT_RAM_END) - POINTER_TO_UINT(vaddr) - size) / CONFIG_MMU_PAGE_SIZE; } @@ -212,21 +215,21 @@ static void virt_region_init(void) size_t offset, num_bits; /* There are regions where we should never map via - * k_mem_map() and z_phys_map(). Mark them as + * k_mem_map() and k_mem_map_phys_bare(). Mark them as * already allocated so they will never be used. */ - if (Z_VM_RESERVED > 0) { + if (K_MEM_VM_RESERVED > 0) { /* Mark reserved region at end of virtual address space */ - num_bits = Z_VM_RESERVED / CONFIG_MMU_PAGE_SIZE; + num_bits = K_MEM_VM_RESERVED / CONFIG_MMU_PAGE_SIZE; (void)sys_bitarray_set_region(&virt_region_bitmap, num_bits, 0); } /* Mark all bits up to Z_FREE_VM_START as allocated */ - num_bits = POINTER_TO_UINT(Z_FREE_VM_START) - - POINTER_TO_UINT(Z_VIRT_RAM_START); - offset = virt_to_bitmap_offset(Z_VIRT_RAM_START, num_bits); + num_bits = POINTER_TO_UINT(K_MEM_VM_FREE_START) + - POINTER_TO_UINT(K_MEM_VIRT_RAM_START); + offset = virt_to_bitmap_offset(K_MEM_VIRT_RAM_START, num_bits); num_bits /= CONFIG_MMU_PAGE_SIZE; (void)sys_bitarray_set_region(&virt_region_bitmap, num_bits, offset); @@ -316,15 +319,15 @@ static void *virt_region_alloc(size_t size, size_t align) /* Here is the memory organization when trying to get an aligned * virtual address: * - * +--------------+ <- Z_VIRT_RAM_START + * +--------------+ <- K_MEM_VIRT_RAM_START * | Undefined VM | - * +--------------+ <- Z_KERNEL_VIRT_START (often == Z_VIRT_RAM_START) + * +--------------+ <- K_MEM_KERNEL_VIRT_START (often == K_MEM_VIRT_RAM_START) * | Mapping for | * | main kernel | * | image | * | | * | | - * +--------------+ <- Z_FREE_VM_START + * +--------------+ <- K_MEM_VM_FREE_START * | ... | * +==============+ <- dest_addr * | Unused | @@ -335,13 +338,13 @@ static void *virt_region_alloc(size_t size, size_t align) * | | * |..............| <- aligned_dest_addr + size * | Unused | - * +==============+ <- offset from Z_VIRT_RAM_END == dest_addr + alloc_size + * +==============+ <- offset from K_MEM_VIRT_RAM_END == dest_addr + alloc_size * | ... | * +--------------+ * | Mapping | * +--------------+ * | Reserved | - * +--------------+ <- Z_VIRT_RAM_END + * +--------------+ <- K_MEM_VIRT_RAM_END */ /* Free the two unused regions */ @@ -381,7 +384,7 @@ static void *virt_region_alloc(size_t size, size_t align) * This implies in the future there may be multiple slists managing physical * pages. Each page frame will still just have one snode link. */ -static sys_slist_t free_page_frame_list; +static sys_sflist_t free_page_frame_list; /* Number of unused and available free page frames. * This information may go stale immediately. @@ -389,46 +392,46 @@ static sys_slist_t free_page_frame_list; static size_t z_free_page_count; #define PF_ASSERT(pf, expr, fmt, ...) \ - __ASSERT(expr, "page frame 0x%lx: " fmt, z_page_frame_to_phys(pf), \ + __ASSERT(expr, "page frame 0x%lx: " fmt, k_mem_page_frame_to_phys(pf), \ ##__VA_ARGS__) /* Get an unused page frame. don't care which one, or NULL if there are none */ -static struct z_page_frame *free_page_frame_list_get(void) +static struct k_mem_page_frame *free_page_frame_list_get(void) { - sys_snode_t *node; - struct z_page_frame *pf = NULL; + sys_sfnode_t *node; + struct k_mem_page_frame *pf = NULL; - node = sys_slist_get(&free_page_frame_list); + node = sys_sflist_get(&free_page_frame_list); if (node != NULL) { z_free_page_count--; - pf = CONTAINER_OF(node, struct z_page_frame, node); - PF_ASSERT(pf, z_page_frame_is_available(pf), - "unavailable but somehow on free list"); + pf = CONTAINER_OF(node, struct k_mem_page_frame, node); + PF_ASSERT(pf, k_mem_page_frame_is_free(pf), + "on free list but not free"); + pf->va_and_flags = 0; } return pf; } /* Release a page frame back into the list of free pages */ -static void free_page_frame_list_put(struct z_page_frame *pf) +static void free_page_frame_list_put(struct k_mem_page_frame *pf) { - PF_ASSERT(pf, z_page_frame_is_available(pf), + PF_ASSERT(pf, k_mem_page_frame_is_available(pf), "unavailable page put on free list"); - /* The structure is packed, which ensures that this is true */ - void *node = pf; - sys_slist_append(&free_page_frame_list, node); + sys_sfnode_init(&pf->node, K_MEM_PAGE_FRAME_FREE); + sys_sflist_append(&free_page_frame_list, &pf->node); z_free_page_count++; } static void free_page_frame_list_init(void) { - sys_slist_init(&free_page_frame_list); + sys_sflist_init(&free_page_frame_list); } -static void page_frame_free_locked(struct z_page_frame *pf) +static void page_frame_free_locked(struct k_mem_page_frame *pf) { - pf->flags = 0; + pf->va_and_flags = 0; free_page_frame_list_put(pf); } @@ -439,9 +442,11 @@ static void page_frame_free_locked(struct z_page_frame *pf) /* Called after the frame is mapped in the arch layer, to update our * local ontology (and do some assertions while we're at it) */ -static void frame_mapped_set(struct z_page_frame *pf, void *addr) +static void frame_mapped_set(struct k_mem_page_frame *pf, void *addr) { - PF_ASSERT(pf, !z_page_frame_is_reserved(pf), + PF_ASSERT(pf, !k_mem_page_frame_is_free(pf), + "attempted to map a page frame on the free list"); + PF_ASSERT(pf, !k_mem_page_frame_is_reserved(pf), "attempted to map a reserved page frame"); /* We do allow multiple mappings for pinned page frames @@ -449,11 +454,15 @@ static void frame_mapped_set(struct z_page_frame *pf, void *addr) * This is uncommon, use-cases are for things like the * Zephyr equivalent of VSDOs */ - PF_ASSERT(pf, !z_page_frame_is_mapped(pf) || z_page_frame_is_pinned(pf), - "non-pinned and already mapped to %p", pf->addr); + PF_ASSERT(pf, !k_mem_page_frame_is_mapped(pf) || k_mem_page_frame_is_pinned(pf), + "non-pinned and already mapped to %p", + k_mem_page_frame_to_virt(pf)); + + uintptr_t flags_mask = CONFIG_MMU_PAGE_SIZE - 1; + uintptr_t va = (uintptr_t)addr & ~flags_mask; - pf->flags |= Z_PAGE_FRAME_MAPPED; - pf->addr = addr; + pf->va_and_flags &= flags_mask; + pf->va_and_flags |= va | K_MEM_PAGE_FRAME_MAPPED; } /* LCOV_EXCL_START */ @@ -470,15 +479,15 @@ static void frame_mapped_set(struct z_page_frame *pf, void *addr) static int virt_to_page_frame(void *virt, uintptr_t *phys) { uintptr_t paddr; - struct z_page_frame *pf; + struct k_mem_page_frame *pf; int ret = -EFAULT; - Z_PAGE_FRAME_FOREACH(paddr, pf) { - if (z_page_frame_is_mapped(pf)) { - if (virt == pf->addr) { + K_MEM_PAGE_FRAME_FOREACH(paddr, pf) { + if (k_mem_page_frame_is_mapped(pf)) { + if (virt == k_mem_page_frame_to_virt(pf)) { ret = 0; if (phys != NULL) { - *phys = z_page_frame_to_phys(pf); + *phys = k_mem_page_frame_to_phys(pf); } break; } @@ -492,7 +501,7 @@ static int virt_to_page_frame(void *virt, uintptr_t *phys) __weak FUNC_ALIAS(virt_to_page_frame, arch_page_phys_get, int); #ifdef CONFIG_DEMAND_PAGING -static int page_frame_prepare_locked(struct z_page_frame *pf, bool *dirty_ptr, +static int page_frame_prepare_locked(struct k_mem_page_frame *pf, bool *dirty_ptr, bool page_in, uintptr_t *location_ptr); static inline void do_backing_store_page_in(uintptr_t location); @@ -510,7 +519,7 @@ static inline void do_backing_store_page_out(uintptr_t location); */ static int map_anon_page(void *addr, uint32_t flags) { - struct z_page_frame *pf; + struct k_mem_page_frame *pf; uintptr_t phys; bool lock = (flags & K_MEM_MAP_LOCK) != 0U; @@ -523,8 +532,9 @@ static int map_anon_page(void *addr, uint32_t flags) pf = k_mem_paging_eviction_select(&dirty); __ASSERT(pf != NULL, "failed to get a page frame"); - LOG_DBG("evicting %p at 0x%lx", pf->addr, - z_page_frame_to_phys(pf)); + LOG_DBG("evicting %p at 0x%lx", + k_mem_page_frame_to_virt(pf), + k_mem_page_frame_to_phys(pf)); ret = page_frame_prepare_locked(pf, &dirty, false, &location); if (ret != 0) { return -ENOMEM; @@ -532,17 +542,17 @@ static int map_anon_page(void *addr, uint32_t flags) if (dirty) { do_backing_store_page_out(location); } - pf->flags = 0; + pf->va_and_flags = 0; #else return -ENOMEM; #endif /* CONFIG_DEMAND_PAGING */ } - phys = z_page_frame_to_phys(pf); + phys = k_mem_page_frame_to_phys(pf); arch_mem_map(addr, phys, CONFIG_MMU_PAGE_SIZE, flags | K_MEM_CACHE_WB); if (lock) { - pf->flags |= Z_PAGE_FRAME_PINNED; + k_mem_page_frame_set(pf, K_MEM_PAGE_FRAME_PINNED); } frame_mapped_set(pf, addr); @@ -551,7 +561,7 @@ static int map_anon_page(void *addr, uint32_t flags) return 0; } -void *k_mem_map_impl(uintptr_t phys, size_t size, uint32_t flags, bool is_anon) +void *k_mem_map_phys_guard(uintptr_t phys, size_t size, uint32_t flags, bool is_anon) { uint8_t *dst; size_t total_size; @@ -581,7 +591,7 @@ void *k_mem_map_impl(uintptr_t phys, size_t size, uint32_t flags, bool is_anon) /* Need extra for the guard pages (before and after) which we * won't map. */ - total_size = size + CONFIG_MMU_PAGE_SIZE * 2; + total_size = size + (CONFIG_MMU_PAGE_SIZE * 2); dst = virt_region_alloc(total_size, CONFIG_MMU_PAGE_SIZE); if (dst == NULL) { @@ -635,11 +645,11 @@ void *k_mem_map_impl(uintptr_t phys, size_t size, uint32_t flags, bool is_anon) return dst; } -void k_mem_unmap_impl(void *addr, size_t size, bool is_anon) +void k_mem_unmap_phys_guard(void *addr, size_t size, bool is_anon) { uintptr_t phys; uint8_t *pos; - struct z_page_frame *pf; + struct k_mem_page_frame *pf; k_spinlock_key_t key; size_t total_size; int ret; @@ -651,7 +661,7 @@ void k_mem_unmap_impl(void *addr, size_t size, bool is_anon) * for two guard pages. */ pos = (uint8_t *)addr - CONFIG_MMU_PAGE_SIZE; - z_mem_assert_virtual_region(pos, size + (CONFIG_MMU_PAGE_SIZE * 2)); + k_mem_assert_virtual_region(pos, size + (CONFIG_MMU_PAGE_SIZE * 2)); key = k_spin_lock(&z_mm_lock); @@ -679,8 +689,39 @@ void k_mem_unmap_impl(void *addr, size_t size, bool is_anon) if (is_anon) { /* Unmapping anonymous memory */ VIRT_FOREACH(addr, size, pos) { +#ifdef CONFIG_DEMAND_PAGING + enum arch_page_location status; + uintptr_t location; + + status = arch_page_location_get(pos, &location); + switch (status) { + case ARCH_PAGE_LOCATION_PAGED_OUT: + /* + * No pf is associated with this mapping. + * Simply get rid of the MMU entry and free + * corresponding backing store. + */ + arch_mem_unmap(pos, CONFIG_MMU_PAGE_SIZE); + k_mem_paging_backing_store_location_free(location); + continue; + case ARCH_PAGE_LOCATION_PAGED_IN: + /* + * The page is in memory but it may not be + * accessible in order to manage tracking + * of the ARCH_DATA_PAGE_ACCESSED flag + * meaning arch_page_phys_get() could fail. + * Still, we know the actual phys address. + */ + phys = location; + ret = 0; + break; + default: + ret = arch_page_phys_get(pos, &phys); + break; + } +#else ret = arch_page_phys_get(pos, &phys); - +#endif __ASSERT(ret == 0, "%s: cannot unmap an unmapped address %p", __func__, pos); @@ -689,9 +730,9 @@ void k_mem_unmap_impl(void *addr, size_t size, bool is_anon) goto out; } - __ASSERT(z_is_page_frame(phys), + __ASSERT(k_mem_is_page_frame(phys), "%s: 0x%lx is not a page frame", __func__, phys); - if (!z_is_page_frame(phys)) { + if (!k_mem_is_page_frame(phys)) { /* Physical address has no corresponding page frame * description in the page frame array. * This should not happen. Do not continue. @@ -700,11 +741,11 @@ void k_mem_unmap_impl(void *addr, size_t size, bool is_anon) } /* Grab the corresponding page frame from physical address */ - pf = z_phys_to_page_frame(phys); + pf = k_mem_phys_to_page_frame(phys); - __ASSERT(z_page_frame_is_mapped(pf), + __ASSERT(k_mem_page_frame_is_mapped(pf), "%s: 0x%lx is not a mapped page frame", __func__, phys); - if (!z_page_frame_is_mapped(pf)) { + if (!k_mem_page_frame_is_mapped(pf)) { /* Page frame is not marked mapped. * This should not happen. Do not continue. */ @@ -731,7 +772,7 @@ void k_mem_unmap_impl(void *addr, size_t size, bool is_anon) * region. So we also need to free them from the bitmap. */ pos = (uint8_t *)addr - CONFIG_MMU_PAGE_SIZE; - total_size = size + CONFIG_MMU_PAGE_SIZE * 2; + total_size = size + (CONFIG_MMU_PAGE_SIZE * 2); virt_region_free(pos, total_size); out: @@ -781,7 +822,7 @@ __weak FUNC_ALIAS(virt_region_align, arch_virt_region_align, size_t); * Data will be copied and BSS zeroed, but this must not rely on any * initialization functions being called prior to work correctly. */ -void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, uint32_t flags) +void k_mem_map_phys_bare(uint8_t **virt_ptr, uintptr_t phys, size_t size, uint32_t flags) { uintptr_t aligned_phys, addr_offset; size_t aligned_size, align_boundary; @@ -817,14 +858,14 @@ void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, uint32_t flags) */ if (IN_RANGE(aligned_phys, - (uintptr_t)Z_VIRT_RAM_START, - (uintptr_t)(Z_VIRT_RAM_END - 1)) || + (uintptr_t)K_MEM_VIRT_RAM_START, + (uintptr_t)(K_MEM_VIRT_RAM_END - 1)) || IN_RANGE(aligned_phys + aligned_size - 1, - (uintptr_t)Z_VIRT_RAM_START, - (uintptr_t)(Z_VIRT_RAM_END - 1))) { - uint8_t *adjusted_start = MAX(dest_addr, Z_VIRT_RAM_START); + (uintptr_t)K_MEM_VIRT_RAM_START, + (uintptr_t)(K_MEM_VIRT_RAM_END - 1))) { + uint8_t *adjusted_start = MAX(dest_addr, K_MEM_VIRT_RAM_START); uint8_t *adjusted_end = MIN(dest_addr + aligned_size, - Z_VIRT_RAM_END); + K_MEM_VIRT_RAM_END); size_t adjusted_sz = adjusted_end - adjusted_start; num_bits = adjusted_sz / CONFIG_MMU_PAGE_SIZE; @@ -868,7 +909,7 @@ void z_phys_map(uint8_t **virt_ptr, uintptr_t phys, size_t size, uint32_t flags) k_panic(); } -void z_phys_unmap(uint8_t *virt, size_t size) +void k_mem_unmap_phys_bare(uint8_t *virt, size_t size) { uintptr_t aligned_virt, addr_offset; size_t aligned_size; @@ -915,7 +956,7 @@ size_t k_mem_region_align(uintptr_t *aligned_addr, size_t *aligned_size, static void mark_linker_section_pinned(void *start_addr, void *end_addr, bool pin) { - struct z_page_frame *pf; + struct k_mem_page_frame *pf; uint8_t *addr; uintptr_t pinned_start = ROUND_DOWN(POINTER_TO_UINT(start_addr), @@ -926,13 +967,13 @@ static void mark_linker_section_pinned(void *start_addr, void *end_addr, VIRT_FOREACH(UINT_TO_POINTER(pinned_start), pinned_size, addr) { - pf = z_phys_to_page_frame(Z_BOOT_VIRT_TO_PHYS(addr)); + pf = k_mem_phys_to_page_frame(K_MEM_BOOT_VIRT_TO_PHYS(addr)); frame_mapped_set(pf, addr); if (pin) { - pf->flags |= Z_PAGE_FRAME_PINNED; + k_mem_page_frame_set(pf, K_MEM_PAGE_FRAME_PINNED); } else { - pf->flags &= ~Z_PAGE_FRAME_PINNED; + k_mem_page_frame_clear(pf, K_MEM_PAGE_FRAME_PINNED); } } } @@ -942,7 +983,7 @@ void z_mem_manage_init(void) { uintptr_t phys; uint8_t *addr; - struct z_page_frame *pf; + struct k_mem_page_frame *pf; k_spinlock_key_t key = k_spin_lock(&z_mm_lock); free_page_frame_list_init(); @@ -951,7 +992,7 @@ void z_mem_manage_init(void) #ifdef CONFIG_ARCH_HAS_RESERVED_PAGE_FRAMES /* If some page frames are unavailable for use as memory, arch - * code will mark Z_PAGE_FRAME_RESERVED in their flags + * code will mark K_MEM_PAGE_FRAME_RESERVED in their flags */ arch_reserved_pages_update(); #endif /* CONFIG_ARCH_HAS_RESERVED_PAGE_FRAMES */ @@ -960,9 +1001,9 @@ void z_mem_manage_init(void) /* All pages composing the Zephyr image are mapped at boot in a * predictable way. This can change at runtime. */ - VIRT_FOREACH(Z_KERNEL_VIRT_START, Z_KERNEL_VIRT_SIZE, addr) + VIRT_FOREACH(K_MEM_KERNEL_VIRT_START, K_MEM_KERNEL_VIRT_SIZE, addr) { - pf = z_phys_to_page_frame(Z_BOOT_VIRT_TO_PHYS(addr)); + pf = k_mem_phys_to_page_frame(K_MEM_BOOT_VIRT_TO_PHYS(addr)); frame_mapped_set(pf, addr); /* TODO: for now we pin the whole Zephyr image. Demand paging @@ -975,7 +1016,7 @@ void z_mem_manage_init(void) * structures, and any code used to perform page fault * handling, page-ins, etc. */ - pf->flags |= Z_PAGE_FRAME_PINNED; + k_mem_page_frame_set(pf, K_MEM_PAGE_FRAME_PINNED); } #endif /* CONFIG_LINKER_GENERIC_SECTIONS_PRESENT_AT_BOOT */ @@ -994,8 +1035,8 @@ void z_mem_manage_init(void) /* Any remaining pages that aren't mapped, reserved, or pinned get * added to the free pages list */ - Z_PAGE_FRAME_FOREACH(phys, pf) { - if (z_page_frame_is_available(pf)) { + K_MEM_PAGE_FRAME_FOREACH(phys, pf) { + if (k_mem_page_frame_is_available(pf)) { free_page_frame_list_put(pf); } } @@ -1117,7 +1158,7 @@ BUILD_ASSERT(!IS_ENABLED(CONFIG_SMP)); static void virt_region_foreach(void *addr, size_t size, void (*func)(void *)) { - z_mem_assert_virtual_region(addr, size); + k_mem_assert_virtual_region(addr, size); for (size_t offset = 0; offset < size; offset += CONFIG_MMU_PAGE_SIZE) { func((uint8_t *)addr + offset); @@ -1140,15 +1181,15 @@ static void virt_region_foreach(void *addr, size_t size, * * Returns -ENOMEM if the backing store is full */ -static int page_frame_prepare_locked(struct z_page_frame *pf, bool *dirty_ptr, +static int page_frame_prepare_locked(struct k_mem_page_frame *pf, bool *dirty_ptr, bool page_fault, uintptr_t *location_ptr) { uintptr_t phys; int ret; bool dirty = *dirty_ptr; - phys = z_page_frame_to_phys(pf); - __ASSERT(!z_page_frame_is_pinned(pf), "page frame 0x%lx is pinned", + phys = k_mem_page_frame_to_phys(pf); + __ASSERT(!k_mem_page_frame_is_pinned(pf), "page frame 0x%lx is pinned", phys); /* If the backing store doesn't have a copy of the page, even if it @@ -1162,31 +1203,31 @@ static int page_frame_prepare_locked(struct z_page_frame *pf, bool *dirty_ptr, * evicted from the backing store to make room for other evicted * pages. */ - if (z_page_frame_is_mapped(pf)) { - dirty = dirty || !z_page_frame_is_backed(pf); + if (k_mem_page_frame_is_mapped(pf)) { + dirty = dirty || !k_mem_page_frame_is_backed(pf); } if (dirty || page_fault) { arch_mem_scratch(phys); } - if (z_page_frame_is_mapped(pf)) { + if (k_mem_page_frame_is_mapped(pf)) { ret = k_mem_paging_backing_store_location_get(pf, location_ptr, page_fault); if (ret != 0) { LOG_ERR("out of backing store memory"); return -ENOMEM; } - arch_mem_page_out(pf->addr, *location_ptr); + arch_mem_page_out(k_mem_page_frame_to_virt(pf), *location_ptr); } else { /* Shouldn't happen unless this function is mis-used */ __ASSERT(!dirty, "un-mapped page determined to be dirty"); } #ifdef CONFIG_DEMAND_PAGING_ALLOW_IRQ - /* Mark as busy so that z_page_frame_is_evictable() returns false */ - __ASSERT(!z_page_frame_is_busy(pf), "page frame 0x%lx is already busy", + /* Mark as busy so that k_mem_page_frame_is_evictable() returns false */ + __ASSERT(!k_mem_page_frame_is_busy(pf), "page frame 0x%lx is already busy", phys); - pf->flags |= Z_PAGE_FRAME_BUSY; + k_mem_page_frame_set(pf, K_MEM_PAGE_FRAME_BUSY); #endif /* CONFIG_DEMAND_PAGING_ALLOW_IRQ */ /* Update dirty parameter, since we set to true if it wasn't backed * even if otherwise clean @@ -1199,7 +1240,7 @@ static int page_frame_prepare_locked(struct z_page_frame *pf, bool *dirty_ptr, static int do_mem_evict(void *addr) { bool dirty; - struct z_page_frame *pf; + struct k_mem_page_frame *pf; uintptr_t location; int key, ret; uintptr_t flags, phys; @@ -1221,8 +1262,8 @@ static int do_mem_evict(void *addr) } dirty = (flags & ARCH_DATA_PAGE_DIRTY) != 0; - pf = z_phys_to_page_frame(phys); - __ASSERT(pf->addr == addr, "page frame address mismatch"); + pf = k_mem_phys_to_page_frame(phys); + __ASSERT(k_mem_page_frame_to_virt(pf) == addr, "page frame address mismatch"); ret = page_frame_prepare_locked(pf, &dirty, false, &location); if (ret != 0) { goto out; @@ -1251,7 +1292,7 @@ int k_mem_page_out(void *addr, size_t size) { __ASSERT(page_frames_initialized, "%s called on %p too early", __func__, addr); - z_mem_assert_virtual_region(addr, size); + k_mem_assert_virtual_region(addr, size); for (size_t offset = 0; offset < size; offset += CONFIG_MMU_PAGE_SIZE) { void *pos = (uint8_t *)addr + offset; @@ -1266,10 +1307,10 @@ int k_mem_page_out(void *addr, size_t size) return 0; } -int z_page_frame_evict(uintptr_t phys) +int k_mem_page_frame_evict(uintptr_t phys) { int key, ret; - struct z_page_frame *pf; + struct k_mem_page_frame *pf; bool dirty; uintptr_t flags; uintptr_t location; @@ -1288,13 +1329,13 @@ int z_page_frame_evict(uintptr_t phys) k_sched_lock(); #endif /* CONFIG_DEMAND_PAGING_ALLOW_IRQ */ key = irq_lock(); - pf = z_phys_to_page_frame(phys); - if (!z_page_frame_is_mapped(pf)) { + pf = k_mem_phys_to_page_frame(phys); + if (!k_mem_page_frame_is_mapped(pf)) { /* Nothing to do, free page */ ret = 0; goto out; } - flags = arch_page_info_get(pf->addr, NULL, false); + flags = arch_page_info_get(k_mem_page_frame_to_virt(pf), NULL, false); /* Shouldn't ever happen */ __ASSERT((flags & ARCH_DATA_PAGE_LOADED) != 0, "data page not loaded"); dirty = (flags & ARCH_DATA_PAGE_DIRTY) != 0; @@ -1380,9 +1421,9 @@ static inline void paging_stats_eviction_inc(struct k_thread *faulting_thread, #endif /* CONFIG_DEMAND_PAGING_STATS */ } -static inline struct z_page_frame *do_eviction_select(bool *dirty) +static inline struct k_mem_page_frame *do_eviction_select(bool *dirty) { - struct z_page_frame *pf; + struct k_mem_page_frame *pf; #ifdef CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM uint32_t time_diff; @@ -1416,7 +1457,7 @@ static inline struct z_page_frame *do_eviction_select(bool *dirty) static bool do_page_fault(void *addr, bool pin) { - struct z_page_frame *pf; + struct k_mem_page_frame *pf; int key, ret; uintptr_t page_in_location, page_out_location; enum arch_page_location status; @@ -1479,8 +1520,8 @@ static bool do_page_fault(void *addr, bool pin) /* It's a physical memory address */ uintptr_t phys = page_in_location; - pf = z_phys_to_page_frame(phys); - pf->flags |= Z_PAGE_FRAME_PINNED; + pf = k_mem_phys_to_page_frame(phys); + k_mem_page_frame_set(pf, K_MEM_PAGE_FRAME_PINNED); } /* This if-block is to pin the page if it is @@ -1500,8 +1541,9 @@ static bool do_page_fault(void *addr, bool pin) /* Need to evict a page frame */ pf = do_eviction_select(&dirty); __ASSERT(pf != NULL, "failed to get a page frame"); - LOG_DBG("evicting %p at 0x%lx", pf->addr, - z_page_frame_to_phys(pf)); + LOG_DBG("evicting %p at 0x%lx", + k_mem_page_frame_to_virt(pf), + k_mem_page_frame_to_phys(pf)); paging_stats_eviction_inc(faulting_thread, dirty); } @@ -1522,16 +1564,15 @@ static bool do_page_fault(void *addr, bool pin) #ifdef CONFIG_DEMAND_PAGING_ALLOW_IRQ key = irq_lock(); - pf->flags &= ~Z_PAGE_FRAME_BUSY; + k_mem_page_frame_clear(pf, K_MEM_PAGE_FRAME_BUSY); #endif /* CONFIG_DEMAND_PAGING_ALLOW_IRQ */ + k_mem_page_frame_clear(pf, K_MEM_PAGE_FRAME_MAPPED); + frame_mapped_set(pf, addr); if (pin) { - pf->flags |= Z_PAGE_FRAME_PINNED; + k_mem_page_frame_set(pf, K_MEM_PAGE_FRAME_PINNED); } - pf->flags |= Z_PAGE_FRAME_MAPPED; - pf->addr = UINT_TO_POINTER(POINTER_TO_UINT(addr) - & ~(CONFIG_MMU_PAGE_SIZE - 1)); - arch_mem_page_in(addr, z_page_frame_to_phys(pf)); + arch_mem_page_in(addr, k_mem_page_frame_to_phys(pf)); k_mem_paging_backing_store_page_finalize(pf, page_in_location); out: irq_unlock(key); @@ -1576,14 +1617,14 @@ void k_mem_pin(void *addr, size_t size) virt_region_foreach(addr, size, do_mem_pin); } -bool z_page_fault(void *addr) +bool k_mem_page_fault(void *addr) { return do_page_fault(addr, false); } static void do_mem_unpin(void *addr) { - struct z_page_frame *pf; + struct k_mem_page_frame *pf; unsigned int key; uintptr_t flags, phys; @@ -1592,8 +1633,8 @@ static void do_mem_unpin(void *addr) __ASSERT((flags & ARCH_DATA_PAGE_NOT_MAPPED) == 0, "invalid data page at %p", addr); if ((flags & ARCH_DATA_PAGE_LOADED) != 0) { - pf = z_phys_to_page_frame(phys); - pf->flags &= ~Z_PAGE_FRAME_PINNED; + pf = k_mem_phys_to_page_frame(phys); + k_mem_page_frame_clear(pf, K_MEM_PAGE_FRAME_PINNED); } irq_unlock(key); } diff --git a/kernel/msg_q.c b/kernel/msg_q.c index b3cd959d578ac..0c461095c6b0d 100644 --- a/kernel/msg_q.c +++ b/kernel/msg_q.c @@ -97,7 +97,7 @@ int z_vrfy_k_msgq_alloc_init(struct k_msgq *msgq, size_t msg_size, return z_impl_k_msgq_alloc_init(msgq, msg_size, max_msgs); } -#include +#include #endif /* CONFIG_USERSPACE */ int k_msgq_cleanup(struct k_msgq *msgq) @@ -192,7 +192,7 @@ static inline int z_vrfy_k_msgq_put(struct k_msgq *msgq, const void *data, return z_impl_k_msgq_put(msgq, data, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_msgq_get_attrs(struct k_msgq *msgq, struct k_msgq_attrs *attrs) @@ -210,7 +210,7 @@ static inline void z_vrfy_k_msgq_get_attrs(struct k_msgq *msgq, K_OOPS(K_SYSCALL_MEMORY_WRITE(attrs, sizeof(struct k_msgq_attrs))); z_impl_k_msgq_get_attrs(msgq, attrs); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_msgq_get(struct k_msgq *msgq, void *data, k_timeout_t timeout) @@ -290,7 +290,7 @@ static inline int z_vrfy_k_msgq_get(struct k_msgq *msgq, void *data, return z_impl_k_msgq_get(msgq, data, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_msgq_peek(struct k_msgq *msgq, void *data) @@ -324,7 +324,7 @@ static inline int z_vrfy_k_msgq_peek(struct k_msgq *msgq, void *data) return z_impl_k_msgq_peek(msgq, data); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_t idx) @@ -370,7 +370,7 @@ static inline int z_vrfy_k_msgq_peek_at(struct k_msgq *msgq, void *data, uint32_ return z_impl_k_msgq_peek_at(msgq, data, idx); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_msgq_purge(struct k_msgq *msgq) @@ -383,7 +383,8 @@ void z_impl_k_msgq_purge(struct k_msgq *msgq) SYS_PORT_TRACING_OBJ_FUNC(k_msgq, purge, msgq); /* wake up any threads that are waiting to write */ - while ((pending_thread = z_unpend_first_thread(&msgq->wait_q)) != NULL) { + for (pending_thread = z_unpend_first_thread(&msgq->wait_q); pending_thread != NULL; + pending_thread = z_unpend_first_thread(&msgq->wait_q)) { arch_thread_return_value_set(pending_thread, -ENOMSG); z_ready_thread(pending_thread); } @@ -400,21 +401,21 @@ static inline void z_vrfy_k_msgq_purge(struct k_msgq *msgq) K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); z_impl_k_msgq_purge(msgq); } -#include +#include static inline uint32_t z_vrfy_k_msgq_num_free_get(struct k_msgq *msgq) { K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); return z_impl_k_msgq_num_free_get(msgq); } -#include +#include static inline uint32_t z_vrfy_k_msgq_num_used_get(struct k_msgq *msgq) { K_OOPS(K_SYSCALL_OBJ(msgq, K_OBJ_MSGQ)); return z_impl_k_msgq_num_used_get(msgq); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/mutex.c b/kernel/mutex.c index 3635e7624ca05..d60b08c4e81ba 100644 --- a/kernel/mutex.c +++ b/kernel/mutex.c @@ -76,7 +76,7 @@ static inline int z_vrfy_k_mutex_init(struct k_mutex *mutex) K_OOPS(K_SYSCALL_OBJ_INIT(mutex, K_OBJ_MUTEX)); return z_impl_k_mutex_init(mutex); } -#include +#include #endif /* CONFIG_USERSPACE */ static int32_t new_prio_for_inheritance(int32_t target, int32_t limit) @@ -205,7 +205,7 @@ static inline int z_vrfy_k_mutex_lock(struct k_mutex *mutex, K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); return z_impl_k_mutex_lock(mutex, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_mutex_unlock(struct k_mutex *mutex) @@ -289,7 +289,7 @@ static inline int z_vrfy_k_mutex_unlock(struct k_mutex *mutex) K_OOPS(K_SYSCALL_OBJ(mutex, K_OBJ_MUTEX)); return z_impl_k_mutex_unlock(mutex); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_MUTEX diff --git a/kernel/paging/statistics.c b/kernel/paging/statistics.c index 06e867cd218b1..4752ca15022d0 100644 --- a/kernel/paging/statistics.c +++ b/kernel/paging/statistics.c @@ -76,7 +76,7 @@ k_mem_paging_backing_store_histogram_bounds[ #endif /* CONFIG_DEMAND_PAGING_STATS_USING_TIMING_FUNCTIONS */ #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ -unsigned long z_num_pagefaults_get(void) +unsigned long k_mem_num_pagefaults_get(void) { unsigned long ret; unsigned int key; @@ -105,7 +105,7 @@ void z_vrfy_k_mem_paging_stats_get(struct k_mem_paging_stats_t *stats) K_OOPS(K_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats))); z_impl_k_mem_paging_stats_get(stats); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_DEMAND_PAGING_THREAD_STATS @@ -129,7 +129,7 @@ void z_vrfy_k_mem_paging_thread_stats_get(struct k_thread *thread, K_OOPS(K_SYSCALL_MEMORY_WRITE(stats, sizeof(*stats))); z_impl_k_mem_paging_thread_stats_get(thread, stats); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_DEMAND_PAGING_THREAD_STATS */ @@ -227,7 +227,7 @@ void z_vrfy_k_mem_paging_histogram_eviction_get( K_OOPS(K_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); z_impl_k_mem_paging_histogram_eviction_get(hist); } -#include +#include static inline void z_vrfy_k_mem_paging_histogram_backing_store_page_in_get( @@ -236,7 +236,7 @@ void z_vrfy_k_mem_paging_histogram_backing_store_page_in_get( K_OOPS(K_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); z_impl_k_mem_paging_histogram_backing_store_page_in_get(hist); } -#include +#include static inline void z_vrfy_k_mem_paging_histogram_backing_store_page_out_get( @@ -245,7 +245,7 @@ void z_vrfy_k_mem_paging_histogram_backing_store_page_out_get( K_OOPS(K_SYSCALL_MEMORY_WRITE(hist, sizeof(*hist))); z_impl_k_mem_paging_histogram_backing_store_page_out_get(hist); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_DEMAND_PAGING_TIMING_HISTOGRAM */ diff --git a/kernel/pipes.c b/kernel/pipes.c index de5c6656165a6..a81393c508d1c 100644 --- a/kernel/pipes.c +++ b/kernel/pipes.c @@ -93,7 +93,7 @@ static inline int z_vrfy_k_pipe_alloc_init(struct k_pipe *pipe, size_t size) return z_impl_k_pipe_alloc_init(pipe, size); } -#include +#include #endif /* CONFIG_USERSPACE */ static inline void handle_poll_events(struct k_pipe *pipe) @@ -126,7 +126,7 @@ void z_vrfy_k_pipe_flush(struct k_pipe *pipe) z_impl_k_pipe_flush(pipe); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_pipe_buffer_flush(struct k_pipe *pipe) @@ -162,8 +162,8 @@ int k_pipe_cleanup(struct k_pipe *pipe) k_spinlock_key_t key = k_spin_lock(&pipe->lock); - CHECKIF(z_waitq_head(&pipe->wait_q.readers) != NULL || - z_waitq_head(&pipe->wait_q.writers) != NULL) { + CHECKIF((z_waitq_head(&pipe->wait_q.readers) != NULL) || + (z_waitq_head(&pipe->wait_q.writers) != NULL)) { k_spin_unlock(&pipe->lock, key); SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, cleanup, pipe, -EAGAIN); @@ -308,7 +308,7 @@ static size_t pipe_buffer_list_populate(sys_dlist_t *list, static int pipe_return_code(size_t min_xfer, size_t bytes_remaining, size_t bytes_requested) { - if (bytes_requested - bytes_remaining >= min_xfer) { + if ((bytes_requested - bytes_remaining) >= min_xfer) { /* * At least the minimum number of requested * bytes have been transferred. @@ -394,7 +394,7 @@ int z_impl_k_pipe_put(struct k_pipe *pipe, const void *data, SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_pipe, put, pipe, timeout); - CHECKIF((min_xfer > bytes_to_write) || bytes_written == NULL) { + CHECKIF((min_xfer > bytes_to_write) || (bytes_written == NULL)) { SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, put, pipe, timeout, -EINVAL); @@ -519,13 +519,13 @@ int z_vrfy_k_pipe_put(struct k_pipe *pipe, const void *data, { K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); K_OOPS(K_SYSCALL_MEMORY_WRITE(bytes_written, sizeof(*bytes_written))); - K_OOPS(K_SYSCALL_MEMORY_READ((void *)data, bytes_to_write)); + K_OOPS(K_SYSCALL_MEMORY_READ(data, bytes_to_write)); - return z_impl_k_pipe_put((struct k_pipe *)pipe, data, + return z_impl_k_pipe_put(pipe, data, bytes_to_write, bytes_written, min_xfer, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ static int pipe_get_internal(k_spinlock_key_t key, struct k_pipe *pipe, @@ -704,7 +704,7 @@ int z_impl_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_pipe, get, pipe, timeout); - CHECKIF((min_xfer > bytes_to_read) || bytes_read == NULL) { + CHECKIF((min_xfer > bytes_to_read) || (bytes_read == NULL)) { SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_pipe, get, pipe, timeout, -EINVAL); @@ -727,13 +727,13 @@ int z_vrfy_k_pipe_get(struct k_pipe *pipe, void *data, size_t bytes_to_read, { K_OOPS(K_SYSCALL_OBJ(pipe, K_OBJ_PIPE)); K_OOPS(K_SYSCALL_MEMORY_WRITE(bytes_read, sizeof(*bytes_read))); - K_OOPS(K_SYSCALL_MEMORY_WRITE((void *)data, bytes_to_read)); + K_OOPS(K_SYSCALL_MEMORY_WRITE(data, bytes_to_read)); - return z_impl_k_pipe_get((struct k_pipe *)pipe, (void *)data, + return z_impl_k_pipe_get(pipe, data, bytes_to_read, bytes_read, min_xfer, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ size_t z_impl_k_pipe_read_avail(struct k_pipe *pipe) @@ -742,7 +742,7 @@ size_t z_impl_k_pipe_read_avail(struct k_pipe *pipe) k_spinlock_key_t key; /* Buffer and size are fixed. No need to spin. */ - if (pipe->buffer == NULL || pipe->size == 0U) { + if ((pipe->buffer == NULL) || (pipe->size == 0U)) { res = 0; goto out; } @@ -770,7 +770,7 @@ size_t z_vrfy_k_pipe_read_avail(struct k_pipe *pipe) return z_impl_k_pipe_read_avail(pipe); } -#include +#include #endif /* CONFIG_USERSPACE */ size_t z_impl_k_pipe_write_avail(struct k_pipe *pipe) @@ -779,7 +779,7 @@ size_t z_impl_k_pipe_write_avail(struct k_pipe *pipe) k_spinlock_key_t key; /* Buffer and size are fixed. No need to spin. */ - if (pipe->buffer == NULL || pipe->size == 0U) { + if ((pipe->buffer == NULL) || (pipe->size == 0U)) { res = 0; goto out; } @@ -807,7 +807,7 @@ size_t z_vrfy_k_pipe_write_avail(struct k_pipe *pipe) return z_impl_k_pipe_write_avail(pipe); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_PIPE diff --git a/kernel/poll.c b/kernel/poll.c index 185aba609c2e6..502e97537b9b6 100644 --- a/kernel/poll.c +++ b/kernel/poll.c @@ -434,7 +434,7 @@ static inline int z_vrfy_k_poll(struct k_poll_event *events, k_free(events_copy); K_OOPS(1); } -#include +#include #endif /* CONFIG_USERSPACE */ /* must be called with interrupts locked */ @@ -493,7 +493,7 @@ static inline void z_vrfy_k_poll_signal_init(struct k_poll_signal *sig) K_OOPS(K_SYSCALL_OBJ_INIT(sig, K_OBJ_POLL_SIGNAL)); z_impl_k_poll_signal_init(sig); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_poll_signal_reset(struct k_poll_signal *sig) @@ -521,7 +521,7 @@ void z_vrfy_k_poll_signal_check(struct k_poll_signal *sig, K_OOPS(K_SYSCALL_MEMORY_WRITE(result, sizeof(int))); z_impl_k_poll_signal_check(sig, signaled, result); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_poll_signal_raise(struct k_poll_signal *sig, int result) @@ -556,14 +556,14 @@ static inline int z_vrfy_k_poll_signal_raise(struct k_poll_signal *sig, K_OOPS(K_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); return z_impl_k_poll_signal_raise(sig, result); } -#include +#include static inline void z_vrfy_k_poll_signal_reset(struct k_poll_signal *sig) { K_OOPS(K_SYSCALL_OBJ(sig, K_OBJ_POLL_SIGNAL)); z_impl_k_poll_signal_reset(sig); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/queue.c b/kernel/queue.c index b99bfb0174ab8..a3c99d69e4062 100644 --- a/kernel/queue.c +++ b/kernel/queue.c @@ -75,7 +75,7 @@ static inline void z_vrfy_k_queue_init(struct k_queue *queue) K_OOPS(K_SYSCALL_OBJ_NEVER_INIT(queue, K_OBJ_QUEUE)); z_impl_k_queue_init(queue); } -#include +#include #endif /* CONFIG_USERSPACE */ static void prepare_thread_to_run(struct k_thread *thread, void *data) @@ -117,7 +117,7 @@ static inline void z_vrfy_k_queue_cancel_wait(struct k_queue *queue) K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); z_impl_k_queue_cancel_wait(queue); } -#include +#include #endif /* CONFIG_USERSPACE */ static int32_t queue_insert(struct k_queue *queue, void *prev, void *data, @@ -220,7 +220,7 @@ static inline int32_t z_vrfy_k_queue_alloc_append(struct k_queue *queue, K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_alloc_append(queue, data); } -#include +#include #endif /* CONFIG_USERSPACE */ int32_t z_impl_k_queue_alloc_prepend(struct k_queue *queue, void *data) @@ -241,7 +241,7 @@ static inline int32_t z_vrfy_k_queue_alloc_prepend(struct k_queue *queue, K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_alloc_prepend(queue, data); } -#include +#include #endif /* CONFIG_USERSPACE */ int k_queue_append_list(struct k_queue *queue, void *head, void *tail) @@ -249,7 +249,7 @@ int k_queue_append_list(struct k_queue *queue, void *head, void *tail) SYS_PORT_TRACING_OBJ_FUNC_ENTER(k_queue, append_list, queue); /* invalid head or tail of list */ - CHECKIF(head == NULL || tail == NULL) { + CHECKIF((head == NULL) || (tail == NULL)) { SYS_PORT_TRACING_OBJ_FUNC_EXIT(k_queue, append_list, queue, -EINVAL); return -EINVAL; @@ -408,28 +408,28 @@ static inline void *z_vrfy_k_queue_get(struct k_queue *queue, K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_get(queue, timeout); } -#include +#include static inline int z_vrfy_k_queue_is_empty(struct k_queue *queue) { K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_is_empty(queue); } -#include +#include static inline void *z_vrfy_k_queue_peek_head(struct k_queue *queue) { K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_peek_head(queue); } -#include +#include static inline void *z_vrfy_k_queue_peek_tail(struct k_queue *queue) { K_OOPS(K_SYSCALL_OBJ(queue, K_OBJ_QUEUE)); return z_impl_k_queue_peek_tail(queue); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/sched.c b/kernel/sched.c index 32cdb5eff7e7e..67e5645bc6f24 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -140,7 +140,7 @@ static ALWAYS_INLINE struct k_thread *runq_best(void) */ static inline bool should_queue_thread(struct k_thread *thread) { - return !IS_ENABLED(CONFIG_SMP) || thread != _current; + return !IS_ENABLED(CONFIG_SMP) || (thread != _current); } static ALWAYS_INLINE void queue_thread(struct k_thread *thread) @@ -272,7 +272,7 @@ static ALWAYS_INLINE struct k_thread *next_up(void) } /* Put _current back into the queue */ - if (thread != _current && active && + if ((thread != _current) && active && !z_is_idle_thread_object(_current) && !queued) { queue_thread(_current); } @@ -348,11 +348,11 @@ static void update_cache(int preempt_ok) #endif /* CONFIG_SMP */ } -static bool thread_active_elsewhere(struct k_thread *thread) +static struct _cpu *thread_active_elsewhere(struct k_thread *thread) { - /* True if the thread is currently running on another CPU. - * There are more scalable designs to answer this question in - * constant time, but this is fine for now. + /* Returns pointer to _cpu if the thread is currently running on + * another CPU. There are more scalable designs to answer this + * question in constant time, but this is fine for now. */ #ifdef CONFIG_SMP int currcpu = _current_cpu->id; @@ -362,12 +362,12 @@ static bool thread_active_elsewhere(struct k_thread *thread) for (int i = 0; i < num_cpus; i++) { if ((i != currcpu) && (_kernel.cpus[i].current == thread)) { - return true; + return &_kernel.cpus[i]; } } #endif /* CONFIG_SMP */ ARG_UNUSED(thread); - return false; + return NULL; } static void ready_thread(struct k_thread *thread) @@ -384,13 +384,14 @@ static void ready_thread(struct k_thread *thread) queue_thread(thread); update_cache(0); - flag_ipi(); + + flag_ipi(ipi_mask_create(thread)); } } void z_ready_thread_locked(struct k_thread *thread) { - if (!thread_active_elsewhere(thread)) { + if (thread_active_elsewhere(thread) == NULL) { ready_thread(thread); } } @@ -398,7 +399,7 @@ void z_ready_thread_locked(struct k_thread *thread) void z_ready_thread(struct k_thread *thread) { K_SPINLOCK(&_sched_spinlock) { - if (!thread_active_elsewhere(thread)) { + if (thread_active_elsewhere(thread) == NULL) { ready_thread(thread); } } @@ -466,11 +467,18 @@ static void z_thread_halt(struct k_thread *thread, k_spinlock_key_t key, * halt itself in the IPI. Otherwise it's unscheduled, so we * can clean it up directly. */ - if (thread_active_elsewhere(thread)) { + + struct _cpu *cpu = thread_active_elsewhere(thread); + + if (cpu != NULL) { thread->base.thread_state |= (terminate ? _THREAD_ABORTING : _THREAD_SUSPENDING); #if defined(CONFIG_SMP) && defined(CONFIG_SCHED_IPI_SUPPORTED) - arch_sched_ipi(); +#ifdef CONFIG_ARCH_HAS_DIRECTED_IPIS + arch_sched_directed_ipi(IPI_CPU_MASK(cpu->id)); +#else + arch_sched_broadcast_ipi(); +#endif #endif if (arch_is_in_isr()) { thread_halt_spin(thread, key); @@ -521,7 +529,7 @@ static inline void z_vrfy_k_thread_suspend(struct k_thread *thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); z_impl_k_thread_suspend(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_thread_resume(struct k_thread *thread) @@ -550,7 +558,7 @@ static inline void z_vrfy_k_thread_resume(struct k_thread *thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); z_impl_k_thread_resume(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ static _wait_q_t *pended_on_thread(struct k_thread *thread) @@ -731,19 +739,38 @@ void z_unpend_thread(struct k_thread *thread) bool z_thread_prio_set(struct k_thread *thread, int prio) { bool need_sched = 0; + int old_prio = thread->base.prio; K_SPINLOCK(&_sched_spinlock) { need_sched = z_is_thread_ready(thread); if (need_sched) { - /* Don't requeue on SMP if it's the running thread */ if (!IS_ENABLED(CONFIG_SMP) || z_is_thread_queued(thread)) { dequeue_thread(thread); thread->base.prio = prio; queue_thread(thread); + + if (old_prio > prio) { + flag_ipi(ipi_mask_create(thread)); + } } else { + /* + * This is a running thread on SMP. Update its + * priority, but do not requeue it. An IPI is + * needed if the priority is both being lowered + * and it is running on another CPU. + */ + thread->base.prio = prio; + + struct _cpu *cpu; + + cpu = thread_active_elsewhere(thread); + if ((cpu != NULL) && (old_prio < prio)) { + flag_ipi(IPI_CPU_MASK(cpu->id)); + } } + update_cache(1); } else { thread->base.prio = prio; @@ -958,7 +985,7 @@ int z_unpend_all(_wait_q_t *wait_q) int need_sched = 0; struct k_thread *thread; - while ((thread = z_waitq_head(wait_q)) != NULL) { + for (thread = z_waitq_head(wait_q); thread != NULL; thread = z_waitq_head(wait_q)) { z_unpend_thread(thread); z_ready_thread(thread); need_sched = 1; @@ -1006,8 +1033,8 @@ void z_impl_k_thread_priority_set(k_tid_t thread, int prio) bool need_sched = z_thread_prio_set((struct k_thread *)thread, prio); - flag_ipi(); - if (need_sched && _current->base.sched_locked == 0U) { + if ((need_sched) && (IS_ENABLED(CONFIG_SMP) || + (_current->base.sched_locked == 0U))) { z_reschedule_unlocked(); } } @@ -1025,7 +1052,7 @@ static inline void z_vrfy_k_thread_priority_set(k_tid_t thread, int prio) #endif /* CONFIG_USERSPACE_THREAD_MAY_RAISE_PRIORITY */ z_impl_k_thread_priority_set(thread, prio); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_SCHED_DEADLINE @@ -1063,7 +1090,7 @@ static inline void z_vrfy_k_thread_deadline_set(k_tid_t tid, int deadline) z_impl_k_thread_deadline_set((k_tid_t)thread, deadline); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_SCHED_DEADLINE */ @@ -1095,7 +1122,7 @@ static inline void z_vrfy_k_yield(void) { z_impl_k_yield(); } -#include +#include #endif /* CONFIG_USERSPACE */ static int32_t z_tick_sleep(k_ticks_t ticks) @@ -1173,7 +1200,7 @@ static inline int32_t z_vrfy_k_sleep(k_timeout_t timeout) { return z_impl_k_sleep(timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ int32_t z_impl_k_usleep(int us) @@ -1197,7 +1224,7 @@ static inline int32_t z_vrfy_k_usleep(int us) { return z_impl_k_usleep(us); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_wakeup(k_tid_t thread) @@ -1219,7 +1246,7 @@ void z_impl_k_wakeup(k_tid_t thread) z_mark_thread_as_not_suspended(thread); - if (!thread_active_elsewhere(thread)) { + if (thread_active_elsewhere(thread) == NULL) { ready_thread(thread); } @@ -1236,7 +1263,7 @@ static inline void z_vrfy_k_wakeup(k_tid_t thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); z_impl_k_wakeup(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ k_tid_t z_impl_k_sched_current_thread_query(void) @@ -1262,14 +1289,14 @@ static inline k_tid_t z_vrfy_k_sched_current_thread_query(void) { return z_impl_k_sched_current_thread_query(); } -#include +#include #endif /* CONFIG_USERSPACE */ static inline void unpend_all(_wait_q_t *wait_q) { struct k_thread *thread; - while ((thread = z_waitq_head(wait_q)) != NULL) { + for (thread = z_waitq_head(wait_q); thread != NULL; thread = z_waitq_head(wait_q)) { unpend_thread_no_timeout(thread); (void)z_abort_thread_timeout(thread); arch_thread_return_value_set(thread, 0); @@ -1485,7 +1512,7 @@ static inline int z_vrfy_k_thread_join(struct k_thread *thread, return z_impl_k_thread_join(thread, timeout); } -#include +#include static inline void z_vrfy_k_thread_abort(k_tid_t thread) { @@ -1498,7 +1525,7 @@ static inline void z_vrfy_k_thread_abort(k_tid_t thread) z_impl_k_thread_abort((struct k_thread *)thread); } -#include +#include #endif /* CONFIG_USERSPACE */ /* diff --git a/kernel/sem.c b/kernel/sem.c index c3c8055d0de9d..f2ae7a6cf78cb 100644 --- a/kernel/sem.c +++ b/kernel/sem.c @@ -48,7 +48,7 @@ int z_impl_k_sem_init(struct k_sem *sem, unsigned int initial_count, /* * Limit cannot be zero and count cannot be greater than limit */ - CHECKIF(limit == 0U || limit > K_SEM_MAX_LIMIT || initial_count > limit) { + CHECKIF(limit == 0U || initial_count > limit) { SYS_PORT_TRACING_OBJ_FUNC(k_sem, init, sem, -EINVAL); return -EINVAL; @@ -79,7 +79,7 @@ int z_vrfy_k_sem_init(struct k_sem *sem, unsigned int initial_count, K_OOPS(K_SYSCALL_OBJ_INIT(sem, K_OBJ_SEM)); return z_impl_k_sem_init(sem, initial_count, limit); } -#include +#include #endif /* CONFIG_USERSPACE */ static inline bool handle_poll_events(struct k_sem *sem) @@ -126,7 +126,7 @@ static inline void z_vrfy_k_sem_give(struct k_sem *sem) K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); z_impl_k_sem_give(sem); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_sem_take(struct k_sem *sem, k_timeout_t timeout) @@ -189,23 +189,23 @@ void z_impl_k_sem_reset(struct k_sem *sem) static inline int z_vrfy_k_sem_take(struct k_sem *sem, k_timeout_t timeout) { K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); - return z_impl_k_sem_take((struct k_sem *)sem, timeout); + return z_impl_k_sem_take(sem, timeout); } -#include +#include static inline void z_vrfy_k_sem_reset(struct k_sem *sem) { K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); z_impl_k_sem_reset(sem); } -#include +#include static inline unsigned int z_vrfy_k_sem_count_get(struct k_sem *sem) { K_OOPS(K_SYSCALL_OBJ(sem, K_OBJ_SEM)); return z_impl_k_sem_count_get(sem); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/smp.c b/kernel/smp.c index 704bfcd9caa9b..a56595252789a 100644 --- a/kernel/smp.c +++ b/kernel/smp.c @@ -60,6 +60,7 @@ unsigned int z_smp_global_lock(void) if (!_current->base.global_lock_count) { while (!atomic_cas(&global_lock, 0, 1)) { + arch_spin_relax(); } } diff --git a/kernel/stack.c b/kernel/stack.c index adebb2d68e80f..e637cc3ba663b 100644 --- a/kernel/stack.c +++ b/kernel/stack.c @@ -29,7 +29,8 @@ void k_stack_init(struct k_stack *stack, stack_data_t *buffer, { z_waitq_init(&stack->wait_q); stack->lock = (struct k_spinlock) {}; - stack->next = stack->base = buffer; + stack->next = buffer; + stack->base = buffer; stack->top = stack->base + num_entries; SYS_PORT_TRACING_OBJ_INIT(k_stack, stack); @@ -51,7 +52,7 @@ int32_t z_impl_k_stack_alloc_init(struct k_stack *stack, uint32_t num_entries) if (buffer != NULL) { k_stack_init(stack, buffer, num_entries); stack->flags = K_STACK_FLAG_ALLOC; - ret = (int32_t)0; + ret = 0; } else { ret = -ENOMEM; } @@ -73,7 +74,7 @@ static inline int32_t z_vrfy_k_stack_alloc_init(struct k_stack *stack, &total_size))); return z_impl_k_stack_alloc_init(stack, num_entries); } -#include +#include #endif /* CONFIG_USERSPACE */ int k_stack_cleanup(struct k_stack *stack) @@ -141,7 +142,7 @@ static inline int z_vrfy_k_stack_push(struct k_stack *stack, stack_data_t data) return z_impl_k_stack_push(stack, data); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_stack_pop(struct k_stack *stack, stack_data_t *data, @@ -196,7 +197,7 @@ static inline int z_vrfy_k_stack_pop(struct k_stack *stack, K_OOPS(K_SYSCALL_MEMORY_WRITE(data, sizeof(stack_data_t))); return z_impl_k_stack_pop(stack, data, timeout); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_OBJ_CORE_STACK diff --git a/kernel/thread.c b/kernel/thread.c index e11e53087d0dc..e39ecd3d7c81a 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -90,7 +90,7 @@ static inline void z_vrfy_k_thread_custom_data_set(void *data) { z_impl_k_thread_custom_data_set(data); } -#include +#include #endif /* CONFIG_USERSPACE */ void *z_impl_k_thread_custom_data_get(void) @@ -103,7 +103,7 @@ static inline void *z_vrfy_k_thread_custom_data_get(void) { return z_impl_k_thread_custom_data_get(); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_THREAD_CUSTOM_DATA */ @@ -118,7 +118,7 @@ static inline int z_vrfy_k_is_preempt_thread(void) { return z_impl_k_is_preempt_thread(); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_thread_priority_get(k_tid_t thread) @@ -132,7 +132,7 @@ static inline int z_vrfy_k_thread_priority_get(k_tid_t thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_priority_get(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ int z_impl_k_thread_name_set(struct k_thread *thread, const char *value) @@ -174,7 +174,7 @@ static inline int z_vrfy_k_thread_name_set(struct k_thread *thread, const char * * the current z_vrfy / z_impl split does not provide a * means of doing so. */ - if (k_usermode_string_copy(name, (char *)str, sizeof(name)) != 0) { + if (k_usermode_string_copy(name, str, sizeof(name)) != 0) { return -EFAULT; } @@ -183,7 +183,7 @@ static inline int z_vrfy_k_thread_name_set(struct k_thread *thread, const char * return -ENOSYS; #endif /* CONFIG_THREAD_NAME */ } -#include +#include #endif /* CONFIG_USERSPACE */ const char *k_thread_name_get(k_tid_t thread) @@ -284,15 +284,15 @@ static inline int z_vrfy_k_thread_name_copy(k_tid_t thread, /* Special case: we allow reading the names of initialized threads * even if we don't have permission on them */ - if (thread == NULL || ko->type != K_OBJ_THREAD || - (ko->flags & K_OBJ_FLAG_INITIALIZED) == 0) { + if ((thread == NULL) || (ko->type != K_OBJ_THREAD) || + ((ko->flags & K_OBJ_FLAG_INITIALIZED) == 0)) { return -EINVAL; } if (K_SYSCALL_MEMORY_WRITE(buf, size) != 0) { return -EFAULT; } len = strlen(thread->name); - if (len + 1 > size) { + if ((len + 1) > size) { return -ENOSPC; } @@ -304,7 +304,7 @@ static inline int z_vrfy_k_thread_name_copy(k_tid_t thread, return -ENOSYS; #endif /* CONFIG_THREAD_NAME */ } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_STACK_SENTINEL @@ -353,7 +353,7 @@ static inline void z_vrfy_k_thread_start(struct k_thread *thread) K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_start(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ #if defined(CONFIG_STACK_POINTER_RANDOM) && (CONFIG_STACK_POINTER_RANDOM != 0) @@ -429,8 +429,9 @@ static char *setup_thread_stack(struct k_thread *new_thread, * stack. If CONFIG_INIT_STACKS is enabled, the stack will be * cleared below. */ - void *stack_mapped = k_mem_phys_map((uintptr_t)stack, stack_obj_size, - K_MEM_PERM_RW | K_MEM_CACHE_WB | K_MEM_MAP_UNINIT); + void *stack_mapped = k_mem_map_phys_guard((uintptr_t)stack, stack_obj_size, + K_MEM_PERM_RW | K_MEM_CACHE_WB | K_MEM_MAP_UNINIT, + false); __ASSERT_NO_MSG((uintptr_t)stack_mapped != 0); @@ -741,7 +742,7 @@ k_tid_t z_vrfy_k_thread_create(struct k_thread *new_thread, return new_thread; } -#include +#include #endif /* CONFIG_USERSPACE */ void z_init_thread_base(struct _thread_base *thread_base, int priority, @@ -895,7 +896,7 @@ int z_vrfy_k_thread_stack_space_get(const struct k_thread *thread, return 0; } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_INIT_STACKS && CONFIG_THREAD_STACK_INFO */ @@ -906,7 +907,7 @@ static inline k_ticks_t z_vrfy_k_thread_timeout_remaining_ticks( K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_timeout_remaining_ticks(thread); } -#include +#include static inline k_ticks_t z_vrfy_k_thread_timeout_expires_ticks( const struct k_thread *thread) @@ -914,7 +915,7 @@ static inline k_ticks_t z_vrfy_k_thread_timeout_expires_ticks( K_OOPS(K_SYSCALL_OBJ(thread, K_OBJ_THREAD)); return z_impl_k_thread_timeout_expires_ticks(thread); } -#include +#include #endif /* CONFIG_USERSPACE */ #ifdef CONFIG_INSTRUMENT_THREAD_SWITCHING @@ -1051,8 +1052,8 @@ void do_thread_cleanup(struct k_thread *thread) #ifdef CONFIG_THREAD_STACK_MEM_MAPPED if (thread_cleanup_stack_addr != NULL) { - k_mem_phys_unmap(thread_cleanup_stack_addr, - thread_cleanup_stack_sz); + k_mem_unmap_phys_guard(thread_cleanup_stack_addr, + thread_cleanup_stack_sz, false); thread_cleanup_stack_addr = NULL; } diff --git a/kernel/timeout.c b/kernel/timeout.c index 8c727e204f91b..1a8a361457a14 100644 --- a/kernel/timeout.c +++ b/kernel/timeout.c @@ -32,7 +32,7 @@ static inline int z_vrfy_sys_clock_hw_cycles_per_sec_runtime_get(void) { return z_impl_sys_clock_hw_cycles_per_sec_runtime_get(); } -#include +#include #endif /* CONFIG_USERSPACE */ #endif /* CONFIG_TIMER_READS_ITS_FREQUENCY_AT_RUNTIME */ @@ -40,14 +40,14 @@ static struct _timeout *first(void) { sys_dnode_t *t = sys_dlist_peek_head(&timeout_list); - return t == NULL ? NULL : CONTAINER_OF(t, struct _timeout, node); + return (t == NULL) ? NULL : CONTAINER_OF(t, struct _timeout, node); } static struct _timeout *next(struct _timeout *t) { sys_dnode_t *n = sys_dlist_peek_next(&timeout_list, &t->node); - return n == NULL ? NULL : CONTAINER_OF(n, struct _timeout, node); + return (n == NULL) ? NULL : CONTAINER_OF(n, struct _timeout, node); } static void remove_timeout(struct _timeout *t) @@ -114,7 +114,7 @@ void z_add_timeout(struct _timeout *to, _timeout_func_t fn, struct _timeout *t; if (IS_ENABLED(CONFIG_TIMEOUT_64BIT) && - Z_TICK_ABS(timeout.ticks) >= 0) { + (Z_TICK_ABS(timeout.ticks) >= 0)) { k_ticks_t ticks = Z_TICK_ABS(timeout.ticks) - curr_tick; to->dticks = MAX(1, ticks); @@ -287,7 +287,7 @@ static inline int64_t z_vrfy_k_uptime_ticks(void) { return z_impl_k_uptime_ticks(); } -#include +#include #endif /* CONFIG_USERSPACE */ k_timepoint_t sys_timepoint_calc(k_timeout_t timeout) diff --git a/kernel/timer.c b/kernel/timer.c index 8eafbb4d7e34e..466cab6c4842f 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -188,7 +188,7 @@ static inline void z_vrfy_k_timer_start(struct k_timer *timer, K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); z_impl_k_timer_start(timer, duration, period); } -#include +#include #endif /* CONFIG_USERSPACE */ void z_impl_k_timer_stop(struct k_timer *timer) @@ -221,7 +221,7 @@ static inline void z_vrfy_k_timer_stop(struct k_timer *timer) K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); z_impl_k_timer_stop(timer); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_timer_status_get(struct k_timer *timer) @@ -241,7 +241,7 @@ static inline uint32_t z_vrfy_k_timer_status_get(struct k_timer *timer) K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_status_get(timer); } -#include +#include #endif /* CONFIG_USERSPACE */ uint32_t z_impl_k_timer_status_sync(struct k_timer *timer) @@ -309,7 +309,7 @@ static inline uint32_t z_vrfy_k_timer_status_sync(struct k_timer *timer) K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_status_sync(timer); } -#include +#include static inline k_ticks_t z_vrfy_k_timer_remaining_ticks( const struct k_timer *timer) @@ -317,7 +317,7 @@ static inline k_ticks_t z_vrfy_k_timer_remaining_ticks( K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_remaining_ticks(timer); } -#include +#include static inline k_ticks_t z_vrfy_k_timer_expires_ticks( const struct k_timer *timer) @@ -325,14 +325,14 @@ static inline k_ticks_t z_vrfy_k_timer_expires_ticks( K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_expires_ticks(timer); } -#include +#include static inline void *z_vrfy_k_timer_user_data_get(const struct k_timer *timer) { K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); return z_impl_k_timer_user_data_get(timer); } -#include +#include static inline void z_vrfy_k_timer_user_data_set(struct k_timer *timer, void *user_data) @@ -340,7 +340,7 @@ static inline void z_vrfy_k_timer_user_data_set(struct k_timer *timer, K_OOPS(K_SYSCALL_OBJ(timer, K_OBJ_TIMER)); z_impl_k_timer_user_data_set(timer, user_data); } -#include +#include #endif /* CONFIG_USERSPACE */ diff --git a/kernel/timeslicing.c b/kernel/timeslicing.c index 07ae497c7f91e..be91d9606f51e 100644 --- a/kernel/timeslicing.c +++ b/kernel/timeslicing.c @@ -58,11 +58,10 @@ static void slice_timeout(struct _timeout *timeout) slice_expired[cpu] = true; /* We need an IPI if we just handled a timeslice expiration - * for a different CPU. Ideally this would be able to target - * the specific core, but that's not part of the API yet. + * for a different CPU. */ - if (IS_ENABLED(CONFIG_SMP) && cpu != _current_cpu->id) { - flag_ipi(); + if (cpu != _current_cpu->id) { + flag_ipi(IPI_CPU_MASK(cpu)); } } diff --git a/kernel/userspace.c b/kernel/userspace.c index a60f2c76dad7d..6fcfacee8b0ca 100644 --- a/kernel/userspace.c +++ b/kernel/userspace.c @@ -94,7 +94,7 @@ const char *otype_to_str(enum k_objects otype) case K_OBJ_ANY: ret = "generic"; break; -#include +#include default: ret = "?"; break; @@ -192,7 +192,7 @@ static size_t obj_size_get(enum k_objects otype) size_t ret; switch (otype) { -#include +#include default: ret = sizeof(const struct device); break; @@ -221,7 +221,7 @@ static size_t obj_align_get(enum k_objects otype) return ret; } -static struct dyn_obj *dyn_object_find(void *obj) +static struct dyn_obj *dyn_object_find(const void *obj) { struct dyn_obj *node; k_spinlock_key_t key; @@ -277,8 +277,10 @@ static bool thread_idx_alloc(uintptr_t *tidx) if (idx != 0) { *tidx = base + (idx - 1); - sys_bitfield_clear_bit((mem_addr_t)_thread_idx_map, - *tidx); + /* Clear the bit. We already know the array index, + * and the bit to be cleared. + */ + _thread_idx_map[i] &= ~(BIT(idx - 1)); /* Clear permission from all objects */ k_object_wordlist_foreach(clear_perms_cb, @@ -308,7 +310,11 @@ static void thread_idx_free(uintptr_t tidx) /* To prevent leaked permission when index is recycled */ k_object_wordlist_foreach(clear_perms_cb, (void *)tidx); - sys_bitfield_set_bit((mem_addr_t)_thread_idx_map, tidx); + /* Figure out which bits to set in _thread_idx_map[] and set it. */ + int base = tidx / NUM_BITS(_thread_idx_map[0]); + int offset = tidx % NUM_BITS(_thread_idx_map[0]); + + _thread_idx_map[base] |= BIT(offset); } static struct k_object *dynamic_object_create(enum k_objects otype, size_t align, @@ -391,7 +397,7 @@ static void *z_object_alloc(enum k_objects otype, size_t size) struct k_object *zo; uintptr_t tidx = 0; - if (otype <= K_OBJ_ANY || otype >= K_OBJ_LAST) { + if ((otype <= K_OBJ_ANY) || (otype >= K_OBJ_LAST)) { LOG_ERR("bad object type %d requested", otype); return NULL; } @@ -490,7 +496,7 @@ struct k_object *k_object_find(const void *obj) * 11.8 but is justified since we know dynamic objects * were not declared with a const qualifier. */ - dyn = dyn_object_find((void *)obj); + dyn = dyn_object_find(obj); if (dyn != NULL) { ret = &dyn->kobj; } @@ -586,7 +592,7 @@ static void wordlist_cb(struct k_object *ko, void *ctx_ptr) struct perm_ctx *ctx = (struct perm_ctx *)ctx_ptr; if (sys_bitfield_test_bit((mem_addr_t)&ko->perms, ctx->parent_id) && - (struct k_thread *)ko->name != ctx->parent) { + ((struct k_thread *)ko->name != ctx->parent)) { sys_bitfield_set_bit((mem_addr_t)&ko->perms, ctx->child_id); } } @@ -727,7 +733,7 @@ int k_object_validate(struct k_object *ko, enum k_objects otype, enum _obj_init_check init) { if (unlikely((ko == NULL) || - (otype != K_OBJ_ANY && ko->type != otype))) { + ((otype != K_OBJ_ANY) && (ko->type != otype)))) { return -EBADF; } @@ -1008,4 +1014,4 @@ static uintptr_t handler_no_syscall(uintptr_t arg1, uintptr_t arg2, CODE_UNREACHABLE; /* LCOV_EXCL_LINE */ } -#include +#include diff --git a/kernel/userspace_handler.c b/kernel/userspace_handler.c index a26c50828d76c..ab6e4f0623c7f 100644 --- a/kernel/userspace_handler.c +++ b/kernel/userspace_handler.c @@ -64,27 +64,26 @@ static inline void z_vrfy_k_object_access_grant(const void *object, object)); k_thread_perms_set(ko, thread); } -#include +#include static inline void z_vrfy_k_object_release(const void *object) { struct k_object *ko; - ko = validate_any_object((void *)object); - K_OOPS(K_SYSCALL_VERIFY_MSG(ko != NULL, "object %p access denied", - (void *)object)); + ko = validate_any_object(object); + K_OOPS(K_SYSCALL_VERIFY_MSG(ko != NULL, "object %p access denied", object)); k_thread_perms_clear(ko, _current); } -#include +#include static inline void *z_vrfy_k_object_alloc(enum k_objects otype) { return z_impl_k_object_alloc(otype); } -#include +#include static inline void *z_vrfy_k_object_alloc_size(enum k_objects otype, size_t size) { return z_impl_k_object_alloc_size(otype, size); } -#include +#include diff --git a/kernel/version.c b/kernel/version.c index 799e555f1aaa5..029671f8259e0 100644 --- a/kernel/version.c +++ b/kernel/version.c @@ -5,7 +5,7 @@ */ #include -#include "version.h" /* generated by MAKE, at compile time */ +#include /* generated by MAKE, at compile time */ /** * @brief Return the kernel version of the present build diff --git a/lib/crc/CMakeLists.txt b/lib/crc/CMakeLists.txt index a85cc3b05cc87..7285af4f3c205 100644 --- a/lib/crc/CMakeLists.txt +++ b/lib/crc/CMakeLists.txt @@ -3,6 +3,7 @@ zephyr_sources_ifdef(CONFIG_CRC crc32c_sw.c crc32_sw.c + crc24_sw.c crc16_sw.c crc8_sw.c crc7_sw.c diff --git a/lib/crc/Kconfig b/lib/crc/Kconfig index f0745f0adedf2..0402df59d01fb 100644 --- a/lib/crc/Kconfig +++ b/lib/crc/Kconfig @@ -10,7 +10,7 @@ if CRC config CRC_SHELL bool "CRC Shell" depends on SHELL - select GETOPT + select POSIX_C_LIB_EXT help Enable CRC checking for memory regions from the shell. endif # CRC diff --git a/lib/crc/crc24_sw.c b/lib/crc/crc24_sw.c new file mode 100644 index 0000000000000..3e9b48fa014fe --- /dev/null +++ b/lib/crc/crc24_sw.c @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2024 BayLibre. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#define CRC24_PGP_POLY 0x01864cfbU + +uint32_t crc24_pgp(const uint8_t *data, size_t len) +{ + return crc24_pgp_update(CRC24_PGP_INITIAL_VALUE, data, len) & CRC24_FINAL_VALUE_MASK; +} + +/* CRC-24 implementation from the section 6.1 of the RFC 4880 */ +uint32_t crc24_pgp_update(uint32_t crc, const uint8_t *data, size_t len) +{ + int i; + + while (len--) { + crc ^= (*data++) << 16; + for (i = 0; i < 8; i++) { + crc <<= 1; + if (crc & 0x01000000) + crc ^= CRC24_PGP_POLY; + } + } + + return crc; +} diff --git a/lib/crc/crc7_sw.c b/lib/crc/crc7_sw.c index 97c370d44e7f4..970c5734c7ab3 100644 --- a/lib/crc/crc7_sw.c +++ b/lib/crc/crc7_sw.c @@ -8,7 +8,7 @@ uint8_t crc7_be(uint8_t seed, const uint8_t *src, size_t len) { - while (len--) { + while (len-- != 0UL) { uint8_t e = seed ^ *src++; uint8_t f = e ^ (e >> 4) ^ (e >> 7); diff --git a/lib/crc/crc8_sw.c b/lib/crc/crc8_sw.c index 67043d27c501d..06bbeea516bc7 100644 --- a/lib/crc/crc8_sw.c +++ b/lib/crc/crc8_sw.c @@ -37,13 +37,13 @@ uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial for (j = 0; j < 8; j++) { if (reversed) { - if (crc & 0x01) { + if ((crc & 0x01) != 0) { crc = (crc >> 1) ^ polynomial; } else { crc >>= 1; } } else { - if (crc & 0x80) { + if ((crc & 0x80) != 0) { crc = (crc << 1) ^ polynomial; } else { crc <<= 1; diff --git a/lib/crc/crc_shell.c b/lib/crc/crc_shell.c index 32393ff6f6e39..e2647ee662324 100644 --- a/lib/crc/crc_shell.c +++ b/lib/crc/crc_shell.c @@ -28,6 +28,7 @@ static const char *const crc_types[] = { [CRC16_ANSI] = "16_ansi", [CRC16_CCITT] = "16_ccitt", [CRC16_ITU_T] = "16_itu_t", + [CRC24_PGP] = "24_pgp", [CRC32_C] = "32_c", [CRC32_IEEE] = "32_ieee", }; diff --git a/lib/heap/Kconfig b/lib/heap/Kconfig index 7f01b280b3b52..89ede27800613 100644 --- a/lib/heap/Kconfig +++ b/lib/heap/Kconfig @@ -6,6 +6,7 @@ menu "Heap and Memory Allocation" config SYS_HEAP_VALIDATE bool "Internal heap validity checking" + depends on ASSERT help The sys_heap implementation is instrumented for extensive internal validation. Leave this off by default, unless diff --git a/lib/heap/heap.c b/lib/heap/heap.c index b23d160b726fe..7fb6884c90ee2 100644 --- a/lib/heap/heap.c +++ b/lib/heap/heap.c @@ -229,7 +229,7 @@ static chunkid_t alloc_chunk(struct z_heap *h, chunksz_t sz) * fragmentation waste of the order of the block allocated * only. */ - if (b->next) { + if (b->next != 0U) { chunkid_t first = b->next; int i = CONFIG_SYS_HEAP_ALLOC_LOOPS; do { @@ -265,7 +265,7 @@ void *sys_heap_alloc(struct sys_heap *heap, size_t bytes) struct z_heap *h = heap->heap; void *mem; - if (bytes == 0U || size_too_big(h, bytes)) { + if ((bytes == 0U) || size_too_big(h, bytes)) { return NULL; } @@ -323,7 +323,7 @@ void *sys_heap_aligned_alloc(struct sys_heap *heap, size_t align, size_t bytes) } __ASSERT((align & (align - 1)) == 0, "align must be a power of 2"); - if (bytes == 0 || size_too_big(h, bytes)) { + if ((bytes == 0) || size_too_big(h, bytes)) { return NULL; } diff --git a/lib/heap/heap.h b/lib/heap/heap.h index df11f18b9e0fd..1be3bd9139277 100644 --- a/lib/heap/heap.h +++ b/lib/heap/heap.h @@ -214,7 +214,7 @@ static inline void set_left_chunk_size(struct z_heap *h, chunkid_t c, static inline bool solo_free_header(struct z_heap *h, chunkid_t c) { - return big_heap(h) && chunk_size(h, c) == 1U; + return big_heap(h) && (chunk_size(h, c) == 1U); } static inline size_t chunk_header_bytes(struct z_heap *h) diff --git a/lib/heap/heap_info.c b/lib/heap/heap_info.c index 80640da2fd42a..c618af2ea0072 100644 --- a/lib/heap/heap_info.c +++ b/lib/heap/heap_info.c @@ -66,8 +66,8 @@ static void heap_print_info(struct z_heap *h, bool dump_chunks) overhead = total - free_bytes - allocated_bytes; printk("\n%zd free bytes, %zd allocated bytes, overhead = %zd bytes (%zd.%zd%%)\n", free_bytes, allocated_bytes, overhead, - (1000 * overhead + total/2) / total / 10, - (1000 * overhead + total/2) / total % 10); + (1000 * overhead + total / 2) / total / 10, + (1000 * overhead + total / 2) / total % 10); } void sys_heap_print_info(struct sys_heap *heap, bool dump_chunks) diff --git a/lib/heap/heap_validate.c b/lib/heap/heap_validate.c index af63c8cdd8c75..1a7172e56ae36 100644 --- a/lib/heap/heap_validate.c +++ b/lib/heap/heap_validate.c @@ -31,7 +31,7 @@ static bool in_bounds(struct z_heap *h, chunkid_t c) static bool valid_chunk(struct z_heap *h, chunkid_t c) { VALIDATE(chunk_size(h, c) > 0); - VALIDATE(c + chunk_size(h, c) <= h->end_chunk); + VALIDATE((c + chunk_size(h, c)) <= h->end_chunk); VALIDATE(in_bounds(h, c)); VALIDATE(right_chunk(h, left_chunk(h, c)) == c); VALIDATE(left_chunk(h, right_chunk(h, c)) == c); @@ -128,7 +128,7 @@ bool sys_heap_validate(struct sys_heap *heap) return false; } - if (empty && h->buckets[b].next != 0) { + if (empty && (h->buckets[b].next != 0)) { return false; } } diff --git a/lib/libc/Kconfig b/lib/libc/Kconfig index dc65b683118df..c04207017cf83 100644 --- a/lib/libc/Kconfig +++ b/lib/libc/Kconfig @@ -43,7 +43,6 @@ config NEWLIB_LIBC_SUPPORTED config PICOLIBC_SUPPORTED bool depends on !NATIVE_APPLICATION - depends on ("$(TOOLCHAIN_HAS_PICOLIBC)" = "y") || (NATIVE_LIBRARY) depends on !REQUIRES_FULL_LIBCPP || ("$(TOOLCHAIN_HAS_PICOLIBC)" = "y") default y select FULL_LIBC_SUPPORTED @@ -103,6 +102,13 @@ config NEWLIB_LIBC depends on !NATIVE_APPLICATION depends on NEWLIB_LIBC_SUPPORTED select NEED_LIBC_MEM_PARTITION + imply POSIX_DEVICE_IO_ALIAS_CLOSE + imply POSIX_DEVICE_IO_ALIAS_OPEN + imply POSIX_DEVICE_IO_ALIAS_READ + imply POSIX_DEVICE_IO_ALIAS_WRITE + imply POSIX_FD_MGMT_ALIAS_LSEEK + imply POSIX_FILE_SYSTEM_ALIAS_FSTAT + imply POSIX_MULTI_PROCESS_ALIAS_GETPID help Build with newlib library. The newlib library is expected to be part of the SDK in this case. diff --git a/lib/libc/arcmwdt/libc-hooks.c b/lib/libc/arcmwdt/libc-hooks.c index babf24ebda8c9..8e094d25975f0 100644 --- a/lib/libc/arcmwdt/libc-hooks.c +++ b/lib/libc/arcmwdt/libc-hooks.c @@ -59,7 +59,7 @@ static inline int z_vrfy_zephyr_write_stdout(const void *buf, int nbytes) K_OOPS(K_SYSCALL_MEMORY_READ(buf, nbytes)); return z_impl_zephyr_write_stdout(buf, nbytes); } -#include +#include #endif #ifndef CONFIG_POSIX_API diff --git a/lib/libc/minimal/Kconfig b/lib/libc/minimal/Kconfig index d7bc50c4157c2..a55bf7a87b268 100644 --- a/lib/libc/minimal/Kconfig +++ b/lib/libc/minimal/Kconfig @@ -78,13 +78,13 @@ config MINIMAL_LIBC_RAND config MINIMAL_LIBC_TIME bool "Time functions" - select COMMON_LIBC_TIME if POSIX_CLOCK + select COMMON_LIBC_TIME if POSIX_TIMERS select COMMON_LIBC_GMTIME_R default y help Enable time() and gmtime_r() for the minimal libc. - time() requires CONFIG_POSIX_CLOCK=y because it relies on the POSIX + time() requires CONFIG_POSIX_TIMERS=y because it relies on the POSIX clock_gettime() function. In order to make use of the non-reentrant gmtime(), it is necessary diff --git a/lib/libc/minimal/include/stdint.h b/lib/libc/minimal/include/stdint.h index 904f0b49b2560..80a2ff1ab2929 100644 --- a/lib/libc/minimal/include/stdint.h +++ b/lib/libc/minimal/include/stdint.h @@ -104,7 +104,7 @@ typedef __UINT_LEAST64_TYPE__ uint_least64_t; typedef __INTPTR_TYPE__ intptr_t; typedef __UINTPTR_TYPE__ uintptr_t; -#ifdef __GNUC__ +#if defined(__GNUC__) || defined(__clang__) /* These macros must produce constant integer expressions, which can't * be done in the preprocessor (casts aren't allowed). Defer to the * GCC internal functions where they're available. @@ -120,7 +120,7 @@ typedef __UINTPTR_TYPE__ uintptr_t; #define UINT32_C(_v) __UINT32_C(_v) #define UINT64_C(_v) __UINT64_C(_v) #define UINTMAX_C(_v) __UINTMAX_C(_v) -#endif /* __GNUC__ */ +#endif /* defined(__GNUC__) || defined(__clang__) */ #ifdef __CCAC__ #ifndef __INT8_C diff --git a/lib/libc/minimal/source/stdlib/atoi.c b/lib/libc/minimal/source/stdlib/atoi.c index 954f75036e143..a184f70f382b3 100644 --- a/lib/libc/minimal/source/stdlib/atoi.c +++ b/lib/libc/minimal/source/stdlib/atoi.c @@ -53,7 +53,7 @@ int atoi(const char *s) } /* Compute n as a negative number to avoid overflow on INT_MIN */ while (isdigit((unsigned char)*s) != 0) { - n = 10*n - (*s++ - '0'); + n = 10 * n - (*s++ - '0'); } return neg ? n : -n; } diff --git a/lib/libc/minimal/source/stdlib/strtol.c b/lib/libc/minimal/source/stdlib/strtol.c index 363ce7831a334..12c7a97585d5a 100644 --- a/lib/libc/minimal/source/stdlib/strtol.c +++ b/lib/libc/minimal/source/stdlib/strtol.c @@ -63,7 +63,7 @@ long strtol(const char *nptr, char **endptr, register int base) c = *s++; } - if ((base == 0 || base == 16) && + if (((base == 0) || (base == 16)) && c == '0' && (*s == 'x' || *s == 'X')) { c = s[1]; s += 2; @@ -71,7 +71,7 @@ long strtol(const char *nptr, char **endptr, register int base) } if (base == 0) { - base = c == '0' ? 8 : 10; + base = (c == '0') ? 8 : 10; } /* @@ -105,7 +105,7 @@ long strtol(const char *nptr, char **endptr, register int base) if (c >= base) { break; } - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { + if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim))) { any = -1; } else { any = 1; @@ -117,12 +117,12 @@ long strtol(const char *nptr, char **endptr, register int base) if (any < 0) { acc = neg ? LONG_MIN : LONG_MAX; errno = ERANGE; - } else if (neg) { + } else if (neg != 0) { acc = -acc; } if (endptr != NULL) { - *endptr = (char *)(any ? s - 1 : nptr); + *endptr = (char *)(any ? (s - 1) : nptr); } return acc; } diff --git a/lib/libc/minimal/source/stdlib/strtoul.c b/lib/libc/minimal/source/stdlib/strtoul.c index 31e930ef53b6c..5908d4080c8e4 100644 --- a/lib/libc/minimal/source/stdlib/strtoul.c +++ b/lib/libc/minimal/source/stdlib/strtoul.c @@ -61,15 +61,15 @@ unsigned long strtoul(const char *nptr, char **endptr, register int base) c = *s++; } - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { + if (((base == 0) || (base == 16)) && + (c == '0') && ((*s == 'x') || (*s == 'X'))) { c = s[1]; s += 2; base = 16; } if (base == 0) { - base = c == '0' ? 8 : 10; + base = (c == '0') ? 8 : 10; } cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; @@ -85,7 +85,7 @@ unsigned long strtoul(const char *nptr, char **endptr, register int base) if (c >= base) { break; } - if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) { + if ((any < 0) || (acc > cutoff) || ((acc == cutoff) && (c > cutlim))) { any = -1; } else { any = 1; @@ -96,11 +96,11 @@ unsigned long strtoul(const char *nptr, char **endptr, register int base) if (any < 0) { acc = ULONG_MAX; errno = ERANGE; - } else if (neg) { + } else if (neg != 0) { acc = -acc; } if (endptr != NULL) { - *endptr = (char *)(any ? s - 1 : nptr); + *endptr = (char *)(any ? (s - 1) : nptr); } return acc; } diff --git a/lib/libc/minimal/source/stdout/fprintf.c b/lib/libc/minimal/source/stdout/fprintf.c index 147f3e385a962..b3e57aa77e70a 100644 --- a/lib/libc/minimal/source/stdout/fprintf.c +++ b/lib/libc/minimal/source/stdout/fprintf.c @@ -10,7 +10,7 @@ #include #include -#define DESC(d) ((void *)d) +#define DESC(d) ((void *)(d)) int fprintf(FILE *ZRESTRICT stream, const char *ZRESTRICT format, ...) { diff --git a/lib/libc/minimal/source/stdout/stdout_console.c b/lib/libc/minimal/source/stdout/stdout_console.c index 33ea7ffaa66d8..e46f4a04ab41f 100644 --- a/lib/libc/minimal/source/stdout/stdout_console.c +++ b/lib/libc/minimal/source/stdout/stdout_console.c @@ -27,7 +27,7 @@ void __stdout_hook_install(int (*hook)(int c)) int z_impl_zephyr_fputc(int c, FILE *stream) { - return (stream == stdout || stream == stderr) ? _stdout_hook(c) : EOF; + return ((stream == stdout) || (stream == stderr)) ? _stdout_hook(c) : EOF; } #ifdef CONFIG_USERSPACE @@ -35,7 +35,7 @@ static inline int z_vrfy_zephyr_fputc(int c, FILE *stream) { return z_impl_zephyr_fputc(c, stream); } -#include +#include #endif int fputc(int c, FILE *stream) @@ -50,7 +50,7 @@ int fputs(const char *ZRESTRICT s, FILE *ZRESTRICT stream) ret = fwrite(s, 1, len, stream); - return len == ret ? 0 : EOF; + return (len == ret) ? 0 : EOF; } #undef putc @@ -72,7 +72,7 @@ size_t z_impl_zephyr_fwrite(const void *ZRESTRICT ptr, size_t size, size_t j; const unsigned char *p; - if ((stream != stdout && stream != stderr) || + if (((stream != stdout) && (stream != stderr)) || (nitems == 0) || (size == 0)) { return 0; } @@ -105,7 +105,7 @@ static inline size_t z_vrfy_zephyr_fwrite(const void *ZRESTRICT ptr, return z_impl_zephyr_fwrite((const void *ZRESTRICT)ptr, size, nitems, (FILE *ZRESTRICT)stream); } -#include +#include #endif size_t fwrite(const void *ZRESTRICT ptr, size_t size, size_t nitems, @@ -121,5 +121,5 @@ int puts(const char *s) return EOF; } - return fputc('\n', stdout) == EOF ? EOF : 0; + return (fputc('\n', stdout) == EOF) ? EOF : 0; } diff --git a/lib/libc/minimal/source/string/string.c b/lib/libc/minimal/source/string/string.c index a7590a598dd67..041a393440065 100644 --- a/lib/libc/minimal/source/string/string.c +++ b/lib/libc/minimal/source/string/string.c @@ -43,7 +43,7 @@ char *strncpy(char *ZRESTRICT d, const char *ZRESTRICT s, size_t n) { char *dest = d; - while ((n > 0) && *s != '\0') { + while ((n > 0) && (*s != '\0')) { *d = *s; s++; d++; @@ -92,7 +92,7 @@ char *strrchr(const char *s, int c) if (*s == (char)c) { match = (char *)s; } - } while (*s++); + } while (*s++ != '\0'); return match; } diff --git a/lib/libc/newlib/libc-hooks.c b/lib/libc/newlib/libc-hooks.c index 5e8629d441247..3db4f2c885f03 100644 --- a/lib/libc/newlib/libc-hooks.c +++ b/lib/libc/newlib/libc-hooks.c @@ -23,6 +23,15 @@ #include #include +int _fstat(int fd, struct stat *st); +int _read(int fd, void *buf, int nbytes); +int _write(int fd, const void *buf, int nbytes); +int _open(const char *name, int mode); +int _close(int file); +int _lseek(int file, int ptr, int dir); +int _kill(int pid, int sig); +int _getpid(void); + #define LIBC_BSS K_APP_BMEM(z_libc_partition) #define LIBC_DATA K_APP_DMEM(z_libc_partition) @@ -184,7 +193,7 @@ static inline int z_vrfy_zephyr_read_stdin(char *buf, int nbytes) K_OOPS(K_SYSCALL_MEMORY_WRITE(buf, nbytes)); return z_impl_zephyr_read_stdin((char *)buf, nbytes); } -#include +#include #endif int z_impl_zephyr_write_stdout(const void *buffer, int nbytes) @@ -207,11 +216,11 @@ static inline int z_vrfy_zephyr_write_stdout(const void *buf, int nbytes) K_OOPS(K_SYSCALL_MEMORY_READ(buf, nbytes)); return z_impl_zephyr_write_stdout((const void *)buf, nbytes); } -#include +#include #endif -#ifndef CONFIG_POSIX_API -int _read(int fd, char *buf, int nbytes) +#ifndef CONFIG_POSIX_DEVICE_IO +int _read(int fd, void *buf, int nbytes) { ARG_UNUSED(fd); @@ -238,16 +247,15 @@ int _close(int file) return -1; } __weak FUNC_ALIAS(_close, close, int); +#endif /* CONFIG_POSIX_DEVICE_IO */ +#ifndef CONFIG_POSIX_FD_MGMT int _lseek(int file, int ptr, int dir) { return 0; } __weak FUNC_ALIAS(_lseek, lseek, int); -#else -extern ssize_t write(int file, const char *buffer, size_t count); -#define _write write -#endif +#endif /* CONFIG_POSIX_FD_MGMT */ int _isatty(int file) { @@ -255,24 +263,31 @@ int _isatty(int file) } __weak FUNC_ALIAS(_isatty, isatty, int); +#ifndef CONFIG_POSIX_SIGNALS int _kill(int i, int j) { return 0; } __weak FUNC_ALIAS(_kill, kill, int); +#endif /* CONFIG_POSIX_SIGNALS */ -int _getpid(void) +#ifndef CONFIG_POSIX_FILE_SYSTEM +int _fstat(int file, struct stat *st) { + st->st_mode = S_IFCHR; return 0; } -__weak FUNC_ALIAS(_getpid, getpid, int); +__weak FUNC_ALIAS(_fstat, fstat, int); +#endif /* CONFIG_POSIX_FILE_SYSTEM */ -int _fstat(int file, struct stat *st) +#ifndef CONFIG_POSIX_MULTI_PROCESS +int _getpid(void) { - st->st_mode = S_IFCHR; return 0; } -__weak FUNC_ALIAS(_fstat, fstat, int); +__weak FUNC_ALIAS(_getpid, getpid, int); + +#endif /* CONFIG_POSIX_MULTI_PROCESS */ __weak void _exit(int status) { @@ -476,11 +491,6 @@ __weak FUNC_NORETURN void __chk_fail(void) } #if CONFIG_XTENSA -extern int _read(int fd, char *buf, int nbytes); -extern int _open(const char *name, int mode); -extern int _close(int file); -extern int _lseek(int file, int ptr, int dir); - /* The Newlib in xtensa toolchain has a few missing functions for the * reentrant versions of the syscalls. */ @@ -565,7 +575,7 @@ void *_sbrk_r(struct _reent *r, int count) int _gettimeofday(struct timeval *__tp, void *__tzp) { -#ifdef CONFIG_POSIX_CLOCK +#ifdef CONFIG_XSI_SINGLE_PROCESS return gettimeofday(__tp, __tzp); #else /* Non-posix systems should not call gettimeofday() here as it will diff --git a/lib/libc/picolibc/libc-hooks.c b/lib/libc/picolibc/libc-hooks.c index e7539bc5dfe11..cefb0d46ddd37 100644 --- a/lib/libc/picolibc/libc-hooks.c +++ b/lib/libc/picolibc/libc-hooks.c @@ -39,7 +39,7 @@ static inline int z_vrfy_zephyr_fputc(int c, FILE *stream) { return z_impl_zephyr_fputc(c, stream); } -#include +#include #endif static int picolibc_put(char a, FILE *f) diff --git a/lib/open-amp/resource_table.c b/lib/open-amp/resource_table.c index 2d58beb4b9289..a857c3ca05f44 100644 --- a/lib/open-amp/resource_table.c +++ b/lib/open-amp/resource_table.c @@ -34,8 +34,10 @@ extern char ram_console[]; #define __resource Z_GENERIC_SECTION(.resource_table) static struct fw_resource_table __resource resource_table = { - .ver = 1, - .num = RSC_TABLE_NUM_ENTRY, + .hdr = { + .ver = 1, + .num = RSC_TABLE_NUM_ENTRY, + }, .offset = { #if (CONFIG_OPENAMP_RSC_TABLE_NUM_RPMSG_BUFF > 0) @@ -66,14 +68,14 @@ static struct fw_resource_table __resource resource_table = { #if defined(CONFIG_RAM_CONSOLE) .cm_trace = { RSC_TRACE, - (uint32_t)ram_console, CONFIG_RAM_CONSOLE_BUFFER_SIZE + 1, 0, + (uint32_t)ram_console, CONFIG_RAM_CONSOLE_BUFFER_SIZE, 0, "Zephyr_log", }, #endif }; -void rsc_table_get(void **table_ptr, int *length) +void rsc_table_get(struct fw_resource_table **table_ptr, int *length) { - *table_ptr = (void *)&resource_table; + *table_ptr = &resource_table; *length = sizeof(resource_table); } diff --git a/lib/open-amp/resource_table.h b/lib/open-amp/resource_table.h index ba3b57e7ad824..dc577fafa7edc 100644 --- a/lib/open-amp/resource_table.h +++ b/lib/open-amp/resource_table.h @@ -41,10 +41,8 @@ enum rsc_table_entries { }; struct fw_resource_table { - unsigned int ver; - unsigned int num; - unsigned int reserved[2]; - unsigned int offset[RSC_TABLE_NUM_ENTRY]; + struct resource_table hdr; + uint32_t offset[RSC_TABLE_NUM_ENTRY]; #if (CONFIG_OPENAMP_RSC_TABLE_NUM_RPMSG_BUFF > 0) struct fw_rsc_vdev vdev; @@ -58,23 +56,23 @@ struct fw_resource_table { #endif } METAL_PACKED_END; -void rsc_table_get(void **table_ptr, int *length); +void rsc_table_get(struct fw_resource_table **table_ptr, int *length); #if (CONFIG_OPENAMP_RSC_TABLE_NUM_RPMSG_BUFF > 0) -inline struct fw_rsc_vdev *rsc_table_to_vdev(void *rsc_table) +inline struct fw_rsc_vdev *rsc_table_to_vdev(struct fw_resource_table *rsc_table) { - return &((struct fw_resource_table *)rsc_table)->vdev; + return &rsc_table->vdev; } -inline struct fw_rsc_vdev_vring *rsc_table_get_vring0(void *rsc_table) +inline struct fw_rsc_vdev_vring *rsc_table_get_vring0(struct fw_resource_table *rsc_table) { - return &((struct fw_resource_table *)rsc_table)->vring0; + return &rsc_table->vring0; } -inline struct fw_rsc_vdev_vring *rsc_table_get_vring1(void *rsc_table) +inline struct fw_rsc_vdev_vring *rsc_table_get_vring1(struct fw_resource_table *rsc_table) { - return &((struct fw_resource_table *)rsc_table)->vring1; + return &rsc_table->vring1; } #endif diff --git a/lib/os/CMakeLists.txt b/lib/os/CMakeLists.txt index 3a52bebab04b8..4ce50ad418292 100644 --- a/lib/os/CMakeLists.txt +++ b/lib/os/CMakeLists.txt @@ -40,3 +40,5 @@ zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include ${ZEPHYR_BASE}/arch/${ARCH}/include ) + +add_subdirectory_ifdef(CONFIG_ZVFS zvfs) diff --git a/lib/os/Kconfig b/lib/os/Kconfig index 14b6241b72c93..fa52338e525f1 100644 --- a/lib/os/Kconfig +++ b/lib/os/Kconfig @@ -10,6 +10,15 @@ config FDTABLE for any I/O object implementing POSIX I/O semantics (i.e. read/write + aux operations). +config ZVFS_OPEN_MAX + int "Maximum number of open file descriptors" + default 16 if WIFI_NM_WPA_SUPPLICANT + default 16 if POSIX_API + default 4 + help + Maximum number of open file descriptors, this includes + files, sockets, special devices, etc. + config PRINTK_SYNC bool "Serialize printk() calls" default y if SMP && MP_MAX_NUM_CPUS > 1 && !(EFI_CONSOLE && LOG) @@ -114,5 +123,6 @@ config POWEROFF Enable support for system power off. rsource "Kconfig.cbprintf" +rsource "zvfs/Kconfig" endmenu diff --git a/lib/os/cbprintf_complete.c b/lib/os/cbprintf_complete.c index 812ebe0d57584..08779d15b66f7 100644 --- a/lib/os/cbprintf_complete.c +++ b/lib/os/cbprintf_complete.c @@ -979,7 +979,7 @@ static char *encode_float(double value, /* Round only if the bit that would round is * set. */ - if (fract & mask) { + if ((fract & mask) != 0ULL) { fract += mask; } } @@ -1128,7 +1128,7 @@ static char *encode_float(double value, * representation and correct the precision and zero-pruning * in accordance with the ISO C rule. */ - if (decexp < (-4 + 1) || decexp > precision) { + if ((decexp < (-4 + 1)) || (decexp > precision)) { c += 'e' - 'g'; /* e or E */ if (precision > 0) { precision--; @@ -1160,7 +1160,7 @@ static char *encode_float(double value, /* Round the value to the last digit being printed. */ uint64_t round = BIT64(59); /* 0.5 */ - while (decimals--) { + while (decimals-- != 0) { _ldiv10(&round); } fract += round; @@ -1173,7 +1173,7 @@ static char *encode_float(double value, if (c == 'f') { if (decexp > 0) { /* Emit the digits above the decimal point. */ - while (decexp > 0 && digit_count > 0) { + while ((decexp > 0) && (digit_count > 0)) { *buf++ = _get_digit(&fract, &digit_count); decexp--; } @@ -1192,7 +1192,7 @@ static char *encode_float(double value, *buf++ = '.'; } - if (decexp < 0 && precision > 0) { + if ((decexp < 0) && (precision > 0)) { conv->pad0_value = -decexp; if (conv->pad0_value > precision) { conv->pad0_value = precision; @@ -1218,7 +1218,7 @@ static char *encode_float(double value, } } - while (precision > 0 && digit_count > 0) { + while ((precision > 0) && (digit_count > 0)) { *buf++ = _get_digit(&fract, &digit_count); precision--; } @@ -1364,7 +1364,7 @@ int z_cbvprintf_impl(cbprintf_cb out, void *ctx, const char *fp, */ #define OUTS(_sp, _ep) do { \ - int rc = outs(out, ctx, _sp, _ep); \ + int rc = outs(out, ctx, (_sp), (_ep)); \ \ if (rc < 0) { \ return rc; \ @@ -1601,6 +1601,26 @@ int z_cbvprintf_impl(cbprintf_cb out, void *ctx, const char *fp, break; } + case 'p': + /* Implementation-defined: null is "(nil)", non-null + * has 0x prefix followed by significant address hex + * digits, no leading zeros. + */ + if (value->ptr != NULL) { + bps = encode_uint((uintptr_t)value->ptr, conv, + buf, bpe); + + /* Use 0x prefix */ + conv->altform_0c = true; + conv->specifier = 'x'; + + goto prec_int_pad0; + } + + bps = "(nil)"; + bpe = bps + 5; + + break; case 'c': bps = buf; buf[0] = CHAR_IS_SIGNED ? value->sint : value->uint; @@ -1653,26 +1673,6 @@ int z_cbvprintf_impl(cbprintf_cb out, void *ctx, const char *fp, } } - break; - case 'p': - /* Implementation-defined: null is "(nil)", non-null - * has 0x prefix followed by significant address hex - * digits, no leading zeros. - */ - if (value->ptr != NULL) { - bps = encode_uint((uintptr_t)value->ptr, conv, - buf, bpe); - - /* Use 0x prefix */ - conv->altform_0c = true; - conv->specifier = 'x'; - - goto prec_int_pad0; - } - - bps = "(nil)"; - bpe = bps + 5; - break; case 'n': if (IS_ENABLED(CONFIG_CBPRINTF_N_SPECIFIER)) { @@ -1817,7 +1817,7 @@ int z_cbvprintf_impl(cbprintf_cb out, void *ctx, const char *fp, OUTS(cp, bpe); } else { - if (conv->altform_0c | conv->altform_0) { + if ((conv->altform_0c | conv->altform_0) != 0) { OUTC('0'); } diff --git a/lib/os/cbprintf_packaged.c b/lib/os/cbprintf_packaged.c index 1c208c42e67a1..ab0c7d2fa051a 100644 --- a/lib/os/cbprintf_packaged.c +++ b/lib/os/cbprintf_packaged.c @@ -324,7 +324,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, * Otherwise we must ensure we can store at least * the pointer to the format string itself. */ - if (buf0 != NULL && BUF_OFFSET + sizeof(char *) > len) { + if ((buf0 != NULL) && (BUF_OFFSET + sizeof(char *)) > len) { return -ENOSPC; } @@ -432,11 +432,11 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, buf = (void *) ROUND_UP(buf, align); if (buf0 != NULL) { /* make sure it fits */ - if (BUF_OFFSET + size > len) { + if ((BUF_OFFSET + size) > len) { return -ENOSPC; } if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { - memcpy(buf, &v, size); + memcpy(buf, (uint8_t *)&v, size); } else if (fmt[-1] == 'L') { *(long double *)buf = v.ld; } else { @@ -583,7 +583,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, return -ENOSPC; } if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { - memcpy(buf, &v, size); + memcpy(buf, (uint8_t *)&v, size); } else if (fmt[-1] == 'L') { *(long double *)buf = v.ld; } else { @@ -605,7 +605,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, buf = (void *) ROUND_UP(buf, align); /* make sure the data fits */ - if (buf0 != NULL && BUF_OFFSET + size > len) { + if ((buf0 != NULL) && (BUF_OFFSET + size) > len) { return -ENOSPC; } @@ -699,7 +699,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, if (buf0 != NULL) { if (Z_CBPRINTF_VA_STACK_LL_DBL_MEMCPY) { - memcpy(buf, &v, sizeof(long long)); + memcpy(buf, (uint8_t *)&v, sizeof(long long)); } else { *(long long *)buf = v; } @@ -717,7 +717,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, * worth of va_list, or about 127 arguments on a 64-bit system * (twice that on 32-bit systems). That ought to be good enough. */ - if (BUF_OFFSET / sizeof(int) > 255) { + if ((BUF_OFFSET / sizeof(int)) > 255) { __ASSERT(false, "too many format args"); return -EINVAL; } @@ -753,7 +753,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, #endif /* Store strings pointer locations of read only strings. */ - if (s_ro_cnt) { + if (s_ro_cnt != 0U) { for (i = 0; i < s_idx; i++) { if (!(str_ptr_pos[i] & STR_POS_RO_FLAG)) { continue; @@ -762,7 +762,7 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, uint8_t pos = str_ptr_pos[i] & STR_POS_MASK; /* make sure it fits */ - if (BUF_OFFSET + 1 > len) { + if ((BUF_OFFSET + 1) > len) { return -ENOSPC; } /* store the pointer position prefix */ @@ -790,13 +790,13 @@ int cbvprintf_package(void *packaged, size_t len, uint32_t flags, } /* make sure it fits */ - if (BUF_OFFSET + 1 + size > len) { + if ((BUF_OFFSET + 1 + size) > len) { return -ENOSPC; } /* store the pointer position prefix */ *buf++ = str_ptr_pos[i]; /* copy the string with its terminating '\0' */ - memcpy(buf, s, size); + memcpy(buf, (uint8_t *)s, size); buf += size; } diff --git a/lib/os/fdtable.c b/lib/os/fdtable.c index e02bc2f661f41..8e192eeb106b0 100644 --- a/lib/os/fdtable.c +++ b/lib/os/fdtable.c @@ -23,20 +23,26 @@ #include #include +struct stat; + struct fd_entry { void *obj; const struct fd_op_vtable *vtable; atomic_t refcount; struct k_mutex lock; struct k_condvar cond; + size_t offset; + uint32_t mode; }; -#ifdef CONFIG_POSIX_API +#if defined(CONFIG_POSIX_DEVICE_IO) static const struct fd_op_vtable stdinout_fd_op_vtable; -#endif -static struct fd_entry fdtable[CONFIG_POSIX_MAX_FDS] = { -#ifdef CONFIG_POSIX_API +BUILD_ASSERT(CONFIG_ZVFS_OPEN_MAX >= 3, "CONFIG_ZVFS_OPEN_MAX >= 3 for CONFIG_POSIX_DEVICE_IO"); +#endif /* defined(CONFIG_POSIX_DEVICE_IO) */ + +static struct fd_entry fdtable[CONFIG_ZVFS_OPEN_MAX] = { +#if defined(CONFIG_POSIX_DEVICE_IO) /* * Predefine entries for stdin/stdout/stderr. */ @@ -62,9 +68,7 @@ static struct fd_entry fdtable[CONFIG_POSIX_MAX_FDS] = { .cond = Z_CONDVAR_INITIALIZER(fdtable[2].cond), }, #else - { - 0 - }, + {0}, #endif }; @@ -117,7 +121,7 @@ static int _find_fd_entry(void) static int _check_fd(int fd) { - if (fd < 0 || fd >= ARRAY_SIZE(fdtable)) { + if ((fd < 0) || (fd >= ARRAY_SIZE(fdtable))) { errno = EBADF; return -1; } @@ -166,7 +170,7 @@ void *z_get_fd_obj(int fd, const struct fd_op_vtable *vtable, int err) entry = &fdtable[fd]; - if (vtable != NULL && entry->vtable != vtable) { + if ((vtable != NULL) && (entry->vtable != vtable)) { errno = err; return NULL; } @@ -224,7 +228,7 @@ void *z_get_fd_obj_and_vtable(int fd, const struct fd_op_vtable **vtable, entry = &fdtable[fd]; *vtable = entry->vtable; - if (lock) { + if (lock != NULL) { *lock = &entry->lock; } @@ -252,7 +256,7 @@ int z_reserve_fd(void) return fd; } -void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable) +void z_finalize_typed_fd(int fd, void *obj, const struct fd_op_vtable *vtable, uint32_t mode) { /* Assumes fd was already bounds-checked. */ #ifdef CONFIG_USERSPACE @@ -267,6 +271,7 @@ void z_finalize_fd(int fd, void *obj, const struct fd_op_vtable *vtable) #endif fdtable[fd].obj = obj; fdtable[fd].vtable = vtable; + fdtable[fd].mode = mode; /* Let the object know about the lock just in case it needs it * for something. For BSD sockets, the lock is used with condition @@ -296,9 +301,7 @@ int z_alloc_fd(void *obj, const struct fd_op_vtable *vtable) return fd; } -#ifdef CONFIG_POSIX_API - -ssize_t read(int fd, void *buf, size_t sz) +ssize_t zvfs_read(int fd, void *buf, size_t sz) { ssize_t res; @@ -307,16 +310,25 @@ ssize_t read(int fd, void *buf, size_t sz) } (void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER); - - res = fdtable[fd].vtable->read(fdtable[fd].obj, buf, sz); - + res = fdtable[fd].vtable->read_offs(fdtable[fd].obj, buf, sz, fdtable[fd].offset); + if (res > 0) { + switch (fdtable[fd].mode & ZVFS_MODE_IFMT) { + case ZVFS_MODE_IFDIR: + case ZVFS_MODE_IFBLK: + case ZVFS_MODE_IFSHM: + case ZVFS_MODE_IFREG: + fdtable[fd].offset += res; + break; + default: + break; + } + } k_mutex_unlock(&fdtable[fd].lock); return res; } -FUNC_ALIAS(read, _read, ssize_t); -ssize_t write(int fd, const void *buf, size_t sz) +ssize_t zvfs_write(int fd, const void *buf, size_t sz) { ssize_t res; @@ -325,16 +337,25 @@ ssize_t write(int fd, const void *buf, size_t sz) } (void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER); - - res = fdtable[fd].vtable->write(fdtable[fd].obj, buf, sz); - + res = fdtable[fd].vtable->write_offs(fdtable[fd].obj, buf, sz, fdtable[fd].offset); + if (res > 0) { + switch (fdtable[fd].mode & ZVFS_MODE_IFMT) { + case ZVFS_MODE_IFDIR: + case ZVFS_MODE_IFBLK: + case ZVFS_MODE_IFSHM: + case ZVFS_MODE_IFREG: + fdtable[fd].offset += res; + break; + default: + break; + } + } k_mutex_unlock(&fdtable[fd].lock); return res; } -FUNC_ALIAS(write, _write, ssize_t); -int close(int fd) +int zvfs_close(int fd) { int res; @@ -352,71 +373,112 @@ int close(int fd) return res; } -FUNC_ALIAS(close, _close, int); -#ifdef CONFIG_POSIX_FSYNC -int fsync(int fd) +int zvfs_fstat(int fd, struct stat *buf) { if (_check_fd(fd) < 0) { return -1; } - return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_FSYNC); + return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_STAT, buf); } -FUNC_ALIAS(fsync, _fsync, int); -#endif /* CONFIG_POSIX_FSYNC */ -off_t lseek(int fd, off_t offset, int whence) +int zvfs_fsync(int fd) { if (_check_fd(fd) < 0) { return -1; } - return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_LSEEK, - offset, whence); + return z_fdtable_call_ioctl(fdtable[fd].vtable, fdtable[fd].obj, ZFD_IOCTL_FSYNC); } -FUNC_ALIAS(lseek, _lseek, off_t); -int ioctl(int fd, unsigned long request, ...) +static inline off_t zvfs_lseek_wrap(int fd, int cmd, ...) { + off_t res; va_list args; - int res; - if (_check_fd(fd) < 0) { - return -1; - } + __ASSERT_NO_MSG(fd < ARRAY_SIZE(fdtable)); - va_start(args, request); - res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, request, args); + (void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER); + va_start(args, cmd); + res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, cmd, args); va_end(args); + if (res > 0) { + switch (fdtable[fd].mode & ZVFS_MODE_IFMT) { + case ZVFS_MODE_IFDIR: + case ZVFS_MODE_IFBLK: + case ZVFS_MODE_IFSHM: + case ZVFS_MODE_IFREG: + fdtable[fd].offset = res; + break; + default: + break; + } + } + k_mutex_unlock(&fdtable[fd].lock); return res; } -int fcntl(int fd, int cmd, ...) +off_t zvfs_lseek(int fd, off_t offset, int whence) { - va_list args; - int res; - if (_check_fd(fd) < 0) { return -1; } - /* Handle fdtable commands. */ - if (cmd == F_DUPFD) { - /* Not implemented so far. */ - errno = EINVAL; + return zvfs_lseek_wrap(fd, ZFD_IOCTL_LSEEK, offset, whence, fdtable[fd].offset); +} + +int zvfs_fcntl(int fd, int cmd, va_list args) +{ + int res; + + if (_check_fd(fd) < 0) { return -1; } /* The rest of commands are per-fd, handled by ioctl vmethod. */ + res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, cmd, args); + + return res; +} + +static inline int zvfs_ftruncate_wrap(int fd, int cmd, ...) +{ + int res; + va_list args; + + __ASSERT_NO_MSG(fd < ARRAY_SIZE(fdtable)); + + (void)k_mutex_lock(&fdtable[fd].lock, K_FOREVER); va_start(args, cmd); res = fdtable[fd].vtable->ioctl(fdtable[fd].obj, cmd, args); va_end(args); + k_mutex_unlock(&fdtable[fd].lock); return res; } +int zvfs_ftruncate(int fd, off_t length) +{ + if (_check_fd(fd) < 0) { + return -1; + } + + return zvfs_ftruncate_wrap(fd, ZFD_IOCTL_TRUNCATE, length); +} + +int zvfs_ioctl(int fd, unsigned long request, va_list args) +{ + if (_check_fd(fd) < 0) { + return -1; + } + + return fdtable[fd].vtable->ioctl(fdtable[fd].obj, request, args); +} + + +#if defined(CONFIG_POSIX_DEVICE_IO) /* * fd operations for stdio/stdout/stderr */ @@ -431,7 +493,7 @@ static ssize_t stdinout_read_vmeth(void *obj, void *buffer, size_t count) static ssize_t stdinout_write_vmeth(void *obj, const void *buffer, size_t count) { #if defined(CONFIG_BOARD_NATIVE_POSIX) - return write(1, buffer, count); + return zvfs_write(1, buffer, count); #elif defined(CONFIG_NEWLIB_LIBC) || defined(CONFIG_ARCMWDT_LIBC) return z_impl_zephyr_write_stdout(buffer, count); #else @@ -452,4 +514,4 @@ static const struct fd_op_vtable stdinout_fd_op_vtable = { .ioctl = stdinout_ioctl_vmeth, }; -#endif /* CONFIG_POSIX_API */ +#endif /* defined(CONFIG_POSIX_DEVICE_IO) */ diff --git a/lib/os/mpsc_pbuf.c b/lib/os/mpsc_pbuf.c index 52a26b5d41672..81025c1cf495b 100644 --- a/lib/os/mpsc_pbuf.c +++ b/lib/os/mpsc_pbuf.c @@ -14,7 +14,7 @@ mpsc_state_print(buffer); \ } \ } \ -} while (0) +} while (false) static inline void mpsc_state_print(struct mpsc_pbuf_buffer *buffer) { diff --git a/lib/os/mutex.c b/lib/os/mutex.c index e1c6d7fb48f12..e8198cd86b3e9 100644 --- a/lib/os/mutex.c +++ b/lib/os/mutex.c @@ -14,7 +14,7 @@ static struct k_mutex *get_k_mutex(struct sys_mutex *mutex) struct k_object *obj; obj = k_object_find(mutex); - if (obj == NULL || obj->type != K_OBJ_SYS_MUTEX) { + if ((obj == NULL) || (obj->type != K_OBJ_SYS_MUTEX)) { return NULL; } @@ -50,13 +50,13 @@ static inline int z_vrfy_z_sys_mutex_kernel_lock(struct sys_mutex *mutex, return z_impl_z_sys_mutex_kernel_lock(mutex, timeout); } -#include +#include int z_impl_z_sys_mutex_kernel_unlock(struct sys_mutex *mutex) { struct k_mutex *kernel_mutex = get_k_mutex(mutex); - if (kernel_mutex == NULL || kernel_mutex->lock_count == 0) { + if ((kernel_mutex == NULL) || (kernel_mutex->lock_count == 0)) { return -EINVAL; } @@ -71,4 +71,4 @@ static inline int z_vrfy_z_sys_mutex_kernel_unlock(struct sys_mutex *mutex) return z_impl_z_sys_mutex_kernel_unlock(mutex); } -#include +#include diff --git a/lib/os/printk.c b/lib/os/printk.c index 71a0d6aeac8b9..793c659292d3d 100644 --- a/lib/os/printk.c +++ b/lib/os/printk.c @@ -178,7 +178,7 @@ static inline void z_vrfy_k_str_out(char *c, size_t n) K_OOPS(K_SYSCALL_MEMORY_READ(c, n)); z_impl_k_str_out((char *)c, n); } -#include +#include #endif /* CONFIG_USERSPACE */ /** @@ -225,12 +225,12 @@ struct str_context { static int str_out(int c, struct str_context *ctx) { - if (ctx->str == NULL || ctx->count >= ctx->max) { + if ((ctx->str == NULL) || (ctx->count >= ctx->max)) { ctx->count++; return c; } - if (ctx->count == ctx->max - 1) { + if (ctx->count == (ctx->max - 1)) { ctx->str[ctx->count++] = '\0'; } else { ctx->str[ctx->count++] = c; diff --git a/lib/os/sem.c b/lib/os/sem.c index b7676c929c6c4..bb1b3fdc6b8ab 100644 --- a/lib/os/sem.c +++ b/lib/os/sem.c @@ -38,8 +38,7 @@ static inline atomic_t bounded_inc(atomic_t *val, atomic_t minimum, break; } - new_value = old_value < minimum ? - minimum + 1 : old_value + 1; + new_value = ((old_value < minimum) ? minimum : old_value) + 1; } while (atomic_cas(val, old_value, new_value) == 0U); return old_value; @@ -48,8 +47,8 @@ static inline atomic_t bounded_inc(atomic_t *val, atomic_t minimum, int sys_sem_init(struct sys_sem *sem, unsigned int initial_count, unsigned int limit) { - if (sem == NULL || limit == SYS_SEM_MINIMUM || - initial_count > limit || limit > INT_MAX) { + if ((sem == NULL) || (limit == SYS_SEM_MINIMUM) || + (initial_count > limit) || (limit > INT_MAX)) { return -EINVAL; } @@ -103,7 +102,7 @@ unsigned int sys_sem_count_get(struct sys_sem *sem) { int value = atomic_get(&sem->futex.val); - return value > SYS_SEM_MINIMUM ? value : SYS_SEM_MINIMUM; + return (value > SYS_SEM_MINIMUM) ? value : SYS_SEM_MINIMUM; } #else int sys_sem_init(struct sys_sem *sem, unsigned int initial_count, @@ -126,7 +125,7 @@ int sys_sem_take(struct sys_sem *sem, k_timeout_t timeout) int ret_value = 0; ret_value = k_sem_take(&sem->kernel_sem, timeout); - if (ret_value == -EAGAIN || ret_value == -EBUSY) { + if ((ret_value == -EAGAIN) || (ret_value == -EBUSY)) { ret_value = -ETIMEDOUT; } diff --git a/lib/os/zvfs/CMakeLists.txt b/lib/os/zvfs/CMakeLists.txt new file mode 100644 index 0000000000000..ca191a4d3ad7a --- /dev/null +++ b/lib/os/zvfs/CMakeLists.txt @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources_ifdef(CONFIG_ZVFS_EVENTFD zvfs_eventfd.c) diff --git a/lib/os/zvfs/Kconfig b/lib/os/zvfs/Kconfig new file mode 100644 index 0000000000000..7f50ff52befc2 --- /dev/null +++ b/lib/os/zvfs/Kconfig @@ -0,0 +1,36 @@ +# Copyright (c) 2020 Tobias Svehagen +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig ZVFS + bool "Zephyr virtual filesystem (ZVFS) support [EXPERIMENTAL]" + select FDTABLE + select EXPERIMENTAL + help + ZVFS is a central, Zephyr-native library that provides a common interoperable API for all + types of file descriptors such as those from the non-virtual FS, sockets, eventfds, FILE *'s + and more. It is designed to be used by all Zephyr subsystems that need to work with files. + +if ZVFS + +config ZVFS_EVENTFD + bool "ZVFS event file descriptor support" + select POLL + help + Enable support for ZVFS event file descriptors. An eventfd can + be used as an event wait/notify mechanism together with POSIX calls + like read, write and poll. + +if ZVFS_EVENTFD + +config ZVFS_EVENTFD_MAX + int "Maximum number of ZVFS eventfd's" + default 1 + range 1 4096 + help + The maximum number of supported event file descriptors. + +endif # ZVFS_EVENTFD + +endif # ZVFS diff --git a/lib/os/zvfs/zvfs_eventfd.c b/lib/os/zvfs/zvfs_eventfd.c new file mode 100644 index 0000000000000..069f4d680e931 --- /dev/null +++ b/lib/os/zvfs/zvfs_eventfd.c @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2020 Tobias Svehagen + * Copyright (c) 2023, Meta + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define ZVFS_EFD_IN_USE 0x1 +#define ZVFS_EFD_FLAGS_SET (ZVFS_EFD_SEMAPHORE | ZVFS_EFD_NONBLOCK) + +struct zvfs_eventfd { + struct k_poll_signal read_sig; + struct k_poll_signal write_sig; + struct k_spinlock lock; + zvfs_eventfd_t cnt; + int flags; +}; + +static ssize_t zvfs_eventfd_rw_op(void *obj, void *buf, size_t sz, + int (*op)(struct zvfs_eventfd *efd, zvfs_eventfd_t *value)); + +SYS_BITARRAY_DEFINE_STATIC(efds_bitarray, CONFIG_ZVFS_EVENTFD_MAX); +static struct zvfs_eventfd efds[CONFIG_ZVFS_EVENTFD_MAX]; +static const struct fd_op_vtable zvfs_eventfd_fd_vtable; + +static inline bool zvfs_eventfd_is_in_use(struct zvfs_eventfd *efd) +{ + return (efd->flags & ZVFS_EFD_IN_USE) != 0; +} + +static inline bool zvfs_eventfd_is_semaphore(struct zvfs_eventfd *efd) +{ + return (efd->flags & ZVFS_EFD_SEMAPHORE) != 0; +} + +static inline bool zvfs_eventfd_is_blocking(struct zvfs_eventfd *efd) +{ + return (efd->flags & ZVFS_EFD_NONBLOCK) == 0; +} + +static int zvfs_eventfd_poll_prepare(struct zvfs_eventfd *efd, + struct zsock_pollfd *pfd, + struct k_poll_event **pev, + struct k_poll_event *pev_end) +{ + if (pfd->events & ZSOCK_POLLIN) { + if (*pev == pev_end) { + errno = ENOMEM; + return -1; + } + + (*pev)->obj = &efd->read_sig; + (*pev)->type = K_POLL_TYPE_SIGNAL; + (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; + (*pev)->state = K_POLL_STATE_NOT_READY; + (*pev)++; + } + + if (pfd->events & ZSOCK_POLLOUT) { + if (*pev == pev_end) { + errno = ENOMEM; + return -1; + } + + (*pev)->obj = &efd->write_sig; + (*pev)->type = K_POLL_TYPE_SIGNAL; + (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; + (*pev)->state = K_POLL_STATE_NOT_READY; + (*pev)++; + } + + return 0; +} + +static int zvfs_eventfd_poll_update(struct zvfs_eventfd *efd, + struct zsock_pollfd *pfd, + struct k_poll_event **pev) +{ + if (pfd->events & ZSOCK_POLLIN) { + pfd->revents |= ZSOCK_POLLIN * (efd->cnt > 0); + (*pev)++; + } + + if (pfd->events & ZSOCK_POLLOUT) { + pfd->revents |= ZSOCK_POLLOUT * (efd->cnt < UINT64_MAX - 1); + (*pev)++; + } + + return 0; +} + +static int zvfs_eventfd_read_locked(struct zvfs_eventfd *efd, zvfs_eventfd_t *value) +{ + if (!zvfs_eventfd_is_in_use(efd)) { + /* file descriptor has been closed */ + return -EBADF; + } + + if (efd->cnt == 0) { + /* would block / try again */ + return -EAGAIN; + } + + /* successful read */ + if (zvfs_eventfd_is_semaphore(efd)) { + *value = 1; + --efd->cnt; + } else { + *value = efd->cnt; + efd->cnt = 0; + } + + if (efd->cnt == 0) { + k_poll_signal_reset(&efd->read_sig); + } + + k_poll_signal_raise(&efd->write_sig, 0); + + return 0; +} + +static int zvfs_eventfd_write_locked(struct zvfs_eventfd *efd, zvfs_eventfd_t *value) +{ + zvfs_eventfd_t result; + + if (!zvfs_eventfd_is_in_use(efd)) { + /* file descriptor has been closed */ + return -EBADF; + } + + if (*value == UINT64_MAX) { + /* not a permitted value */ + return -EINVAL; + } + + if (u64_add_overflow(efd->cnt, *value, &result) || result == UINT64_MAX) { + /* would block / try again */ + return -EAGAIN; + } + + /* successful write */ + efd->cnt = result; + + if (efd->cnt == (UINT64_MAX - 1)) { + k_poll_signal_reset(&efd->write_sig); + } + + k_poll_signal_raise(&efd->read_sig, 0); + + return 0; +} + +static ssize_t zvfs_eventfd_read_op(void *obj, void *buf, size_t sz) +{ + return zvfs_eventfd_rw_op(obj, buf, sz, zvfs_eventfd_read_locked); +} + +static ssize_t zvfs_eventfd_write_op(void *obj, const void *buf, size_t sz) +{ + return zvfs_eventfd_rw_op(obj, (zvfs_eventfd_t *)buf, sz, zvfs_eventfd_write_locked); +} + +static int zvfs_eventfd_close_op(void *obj) +{ + int ret; + int err; + k_spinlock_key_t key; + struct k_mutex *lock = NULL; + struct k_condvar *cond = NULL; + struct zvfs_eventfd *efd = (struct zvfs_eventfd *)obj; + + if (k_is_in_isr()) { + /* not covered by the man page, but necessary in Zephyr */ + errno = EWOULDBLOCK; + return -1; + } + + err = (int)z_get_obj_lock_and_cond(obj, &zvfs_eventfd_fd_vtable, &lock, &cond); + __ASSERT((bool)err, "z_get_obj_lock_and_cond() failed"); + __ASSERT_NO_MSG(lock != NULL); + __ASSERT_NO_MSG(cond != NULL); + + err = k_mutex_lock(lock, K_FOREVER); + __ASSERT(err == 0, "k_mutex_lock() failed: %d", err); + + key = k_spin_lock(&efd->lock); + + if (!zvfs_eventfd_is_in_use(efd)) { + errno = EBADF; + ret = -1; + goto unlock; + } + + err = sys_bitarray_free(&efds_bitarray, 1, (struct zvfs_eventfd *)obj - efds); + __ASSERT(err == 0, "sys_bitarray_free() failed: %d", err); + + efd->flags = 0; + efd->cnt = 0; + + ret = 0; + +unlock: + k_spin_unlock(&efd->lock, key); + /* when closing an zvfs_eventfd, broadcast to all waiters */ + err = k_condvar_broadcast(cond); + __ASSERT(err == 0, "k_condvar_broadcast() failed: %d", err); + err = k_mutex_unlock(lock); + __ASSERT(err == 0, "k_mutex_unlock() failed: %d", err); + + return ret; +} + +static int zvfs_eventfd_ioctl_op(void *obj, unsigned int request, va_list args) +{ + int ret; + k_spinlock_key_t key; + struct zvfs_eventfd *efd = (struct zvfs_eventfd *)obj; + + /* note: zsock_poll_internal() has already taken the mutex */ + key = k_spin_lock(&efd->lock); + + if (!zvfs_eventfd_is_in_use(efd)) { + errno = EBADF; + ret = -1; + goto unlock; + } + + switch (request) { + case F_GETFL: + ret = efd->flags & ZVFS_EFD_FLAGS_SET; + break; + + case F_SETFL: { + int flags; + + flags = va_arg(args, int); + + if (flags & ~ZVFS_EFD_FLAGS_SET) { + errno = EINVAL; + ret = -1; + } else { + int prev_flags = efd->flags & ~ZVFS_EFD_FLAGS_SET; + + efd->flags = flags | prev_flags; + ret = 0; + } + } break; + + case ZFD_IOCTL_POLL_PREPARE: { + struct zsock_pollfd *pfd; + struct k_poll_event **pev; + struct k_poll_event *pev_end; + + pfd = va_arg(args, struct zsock_pollfd *); + pev = va_arg(args, struct k_poll_event **); + pev_end = va_arg(args, struct k_poll_event *); + + ret = zvfs_eventfd_poll_prepare(obj, pfd, pev, pev_end); + } break; + + case ZFD_IOCTL_POLL_UPDATE: { + struct zsock_pollfd *pfd; + struct k_poll_event **pev; + + pfd = va_arg(args, struct zsock_pollfd *); + pev = va_arg(args, struct k_poll_event **); + + ret = zvfs_eventfd_poll_update(obj, pfd, pev); + } break; + + default: + errno = EOPNOTSUPP; + ret = -1; + break; + } + +unlock: + k_spin_unlock(&efd->lock, key); + + return ret; +} + +static const struct fd_op_vtable zvfs_eventfd_fd_vtable = { + .read = zvfs_eventfd_read_op, + .write = zvfs_eventfd_write_op, + .close = zvfs_eventfd_close_op, + .ioctl = zvfs_eventfd_ioctl_op, +}; + +/* common to both zvfs_eventfd_read_op() and zvfs_eventfd_write_op() */ +static ssize_t zvfs_eventfd_rw_op(void *obj, void *buf, size_t sz, + int (*op)(struct zvfs_eventfd *efd, zvfs_eventfd_t *value)) +{ + int err; + ssize_t ret; + k_spinlock_key_t key; + struct zvfs_eventfd *efd = obj; + struct k_mutex *lock = NULL; + struct k_condvar *cond = NULL; + + if (sz < sizeof(zvfs_eventfd_t)) { + errno = EINVAL; + return -1; + } + + if (buf == NULL) { + errno = EFAULT; + return -1; + } + + key = k_spin_lock(&efd->lock); + + if (!zvfs_eventfd_is_blocking(efd)) { + /* + * Handle the non-blocking case entirely within this scope + */ + ret = op(efd, buf); + if (ret < 0) { + errno = -ret; + ret = -1; + } else { + ret = sizeof(zvfs_eventfd_t); + } + + goto unlock_spin; + } + + /* + * Handle the blocking case below + */ + __ASSERT_NO_MSG(zvfs_eventfd_is_blocking(efd)); + + if (k_is_in_isr()) { + /* not covered by the man page, but necessary in Zephyr */ + errno = EWOULDBLOCK; + ret = -1; + goto unlock_spin; + } + + err = (int)z_get_obj_lock_and_cond(obj, &zvfs_eventfd_fd_vtable, &lock, &cond); + __ASSERT((bool)err, "z_get_obj_lock_and_cond() failed"); + __ASSERT_NO_MSG(lock != NULL); + __ASSERT_NO_MSG(cond != NULL); + + /* do not hold a spinlock when taking a mutex */ + k_spin_unlock(&efd->lock, key); + err = k_mutex_lock(lock, K_FOREVER); + __ASSERT(err == 0, "k_mutex_lock() failed: %d", err); + + while (true) { + /* retake the spinlock */ + key = k_spin_lock(&efd->lock); + + ret = op(efd, buf); + switch (ret) { + case -EAGAIN: + /* not an error in blocking mode. break and try again */ + break; + case 0: + /* success! */ + ret = sizeof(zvfs_eventfd_t); + goto unlock_mutex; + default: + /* some other error */ + __ASSERT_NO_MSG(ret < 0); + errno = -ret; + ret = -1; + goto unlock_mutex; + } + + /* do not hold a spinlock when taking a mutex */ + k_spin_unlock(&efd->lock, key); + + /* wait for a write or close */ + err = k_condvar_wait(cond, lock, K_FOREVER); + __ASSERT(err == 0, "k_condvar_wait() failed: %d", err); + } + +unlock_mutex: + k_spin_unlock(&efd->lock, key); + /* only wake a single waiter */ + err = k_condvar_signal(cond); + __ASSERT(err == 0, "k_condvar_signal() failed: %d", err); + err = k_mutex_unlock(lock); + __ASSERT(err == 0, "k_mutex_unlock() failed: %d", err); + goto out; + +unlock_spin: + k_spin_unlock(&efd->lock, key); + +out: + return ret; +} + +/* + * Public-facing API + */ + +int zvfs_eventfd(unsigned int initval, int flags) +{ + int fd = 1; + size_t offset; + struct zvfs_eventfd *efd = NULL; + + if (flags & ~ZVFS_EFD_FLAGS_SET) { + errno = EINVAL; + return -1; + } + + if (sys_bitarray_alloc(&efds_bitarray, 1, &offset) < 0) { + errno = ENOMEM; + return -1; + } + + efd = &efds[offset]; + + fd = z_reserve_fd(); + if (fd < 0) { + sys_bitarray_free(&efds_bitarray, 1, offset); + return -1; + } + + efd->flags = ZVFS_EFD_IN_USE | flags; + efd->cnt = initval; + + k_poll_signal_init(&efd->write_sig); + k_poll_signal_init(&efd->read_sig); + + if (initval != 0) { + k_poll_signal_raise(&efd->read_sig, 0); + } + + k_poll_signal_raise(&efd->write_sig, 0); + + z_finalize_fd(fd, efd, &zvfs_eventfd_fd_vtable); + + return fd; +} + +int zvfs_eventfd_read(int fd, zvfs_eventfd_t *value) +{ + int ret; + void *obj; + + obj = z_get_fd_obj(fd, &zvfs_eventfd_fd_vtable, EBADF); + if (obj == NULL) { + return -1; + } + + ret = zvfs_eventfd_rw_op(obj, value, sizeof(zvfs_eventfd_t), zvfs_eventfd_read_locked); + __ASSERT_NO_MSG(ret == -1 || ret == sizeof(zvfs_eventfd_t)); + if (ret < 0) { + return -1; + } + + return 0; +} + +int zvfs_eventfd_write(int fd, zvfs_eventfd_t value) +{ + int ret; + void *obj; + + obj = z_get_fd_obj(fd, &zvfs_eventfd_fd_vtable, EBADF); + if (obj == NULL) { + return -1; + } + + ret = zvfs_eventfd_rw_op(obj, &value, sizeof(zvfs_eventfd_t), zvfs_eventfd_write_locked); + __ASSERT_NO_MSG(ret == -1 || ret == sizeof(zvfs_eventfd_t)); + if (ret < 0) { + return -1; + } + + return 0; +} diff --git a/lib/posix/options/CMakeLists.txt b/lib/posix/options/CMakeLists.txt index 96995cbeebb81..f7da027223d4d 100644 --- a/lib/posix/options/CMakeLists.txt +++ b/lib/posix/options/CMakeLists.txt @@ -2,15 +2,13 @@ set(GEN_DIR ${ZEPHYR_BINARY_DIR}/include/generated) -zephyr_syscall_header( - posix_clock.h -) +zephyr_syscall_header_ifdef(CONFIG_POSIX_TIMERS posix_clock.h) if(CONFIG_POSIX_API) zephyr_include_directories(${ZEPHYR_BASE}/include/zephyr/posix) endif() -if(CONFIG_POSIX_SIGNAL) +if(CONFIG_POSIX_SIGNALS) set(STRSIGNAL_TABLE_H ${GEN_DIR}/posix/strsignal_table.h) add_custom_command( @@ -24,8 +22,9 @@ if(CONFIG_POSIX_SIGNAL) ) endif() -if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_CLOCK OR - CONFIG_POSIX_MQUEUE OR CONFIG_POSIX_FS OR CONFIG_EVENTFD OR CONFIG_GETOPT) +if(CONFIG_POSIX_API OR CONFIG_POSIX_THREADS OR CONFIG_POSIX_TIMERS OR + CONFIG_POSIX_MESSAGE_PASSING OR CONFIG_POSIX_FILE_SYSTEM OR CONFIG_EVENTFD OR + CONFIG_POSIX_C_LIB_EXT OR CONFIG_POSIX_SINGLE_PROCESS) # This is a temporary workaround so that Newlib declares the appropriate # types for us. POSIX features to be formalized as part of #51211 zephyr_compile_options($<$:-D_POSIX_THREADS>) @@ -33,36 +32,68 @@ if(CONFIG_POSIX_API OR CONFIG_PTHREAD_IPC OR CONFIG_POSIX_CLOCK OR endif() zephyr_library() -add_subdirectory_ifdef(CONFIG_GETOPT getopt) zephyr_library_sources_ifdef(CONFIG_EVENTFD eventfd.c) -zephyr_library_sources_ifdef(CONFIG_FNMATCH fnmatch.c) -zephyr_library_sources_ifdef(CONFIG_GETENTROPY getentropy.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_API perror.c) zephyr_library_sources_ifdef(CONFIG_POSIX_ASYNCHRONOUS_IO aio.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK clock.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK nanosleep.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_CLOCK sleep.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_CONFSTR confstr.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_ENV env.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_FS fs.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_MQUEUE mqueue.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_BARRIERS barrier.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_C_LIB_EXT + fnmatch.c + getentropy.c + getopt/getopt.c + getopt/getopt_common.c +) +zephyr_library_sources_ifdef(CONFIG_POSIX_DEVICE_IO + # perror should be moved to the common libc + perror.c + device_io.c +) +zephyr_library_sources_ifdef(CONFIG_POSIX_FD_MGMT + fd_mgmt.c +) +zephyr_library_sources_ifdef(CONFIG_POSIX_FILE_SYSTEM fs.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_FSYNC fsync.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK mlockall.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MEMLOCK_RANGE mlock.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MEMORY_PROTECTION mprotect.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MAPPED_FILES mmap.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MESSAGE_PASSING mqueue.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_MULTI_PROCESS + sleep.c + multi_process.c +) zephyr_library_sources_ifdef(CONFIG_POSIX_NETWORKING net.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_PUTMSG stropts.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNAL signal.c ${STRSIGNAL_TABLE_H}) -zephyr_library_sources_ifdef(CONFIG_POSIX_SYSCONF_IMPL_FULL sysconf.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_SHARED_MEMORY_OBJECTS shm.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_SIGNALS signal.c ${STRSIGNAL_TABLE_H}) +zephyr_library_sources_ifdef(CONFIG_POSIX_SINGLE_PROCESS + confstr.c + env.c + sysconf.c + uname.c +) +zephyr_library_sources_ifdef(CONFIG_POSIX_SPIN_LOCKS spinlock.c) zephyr_library_sources_ifdef(CONFIG_POSIX_SYSLOG syslog.c) -zephyr_library_sources_ifdef(CONFIG_POSIX_UNAME uname.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC _common.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_BARRIER barrier.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_COND cond.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_KEY key.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_MUTEX mutex.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD pthread.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_RWLOCK rwlock.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_TIMERS + clock.c + timer.c + timespec_to_timeout.c +) zephyr_library_sources_ifdef(CONFIG_POSIX_PRIORITY_SCHEDULING sched.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_IPC semaphore.c) -zephyr_library_sources_ifdef(CONFIG_PTHREAD_SPINLOCK spinlock.c) -zephyr_library_sources_ifdef(CONFIG_TIMER timer.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_READER_WRITER_LOCKS rwlock.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_SEMAPHORES semaphore.c) +zephyr_library_sources_ifdef(CONFIG_POSIX_THREADS + cond.c + key.c + mutex.c + pthread.c +) +zephyr_library_sources_ifdef(CONFIG_XOPEN_STREAMS stropts.c) +zephyr_library_sources_ifdef(CONFIG_XSI_SYSTEM_LOGGING syslog.c) + +zephyr_library_sources_ifdef(CONFIG_GETOPT_LONG + getopt/getopt_long.c +) +zephyr_include_directories_ifdef(CONFIG_POSIX_C_LIB_EXT + getopt/ +) zephyr_library_include_directories( ${ZEPHYR_BASE}/kernel/include diff --git a/lib/posix/options/Kconfig b/lib/posix/options/Kconfig index 2197148bca5bb..bdf0ed4901f05 100644 --- a/lib/posix/options/Kconfig +++ b/lib/posix/options/Kconfig @@ -1,56 +1,36 @@ # Copyright (c) 2018 Intel Corporation # Copyright (c) 2023 Meta +# Copyright (c) 2024 Tenstorrent AI ULC # # SPDX-License-Identifier: Apache-2.0 menu "POSIX Options" -config POSIX_API - depends on !NATIVE_APPLICATION - bool "POSIX APIs" - select NATIVE_LIBC_INCOMPATIBLE - help - Enable mostly-standards-compliant implementations of - various POSIX (IEEE 1003.1) APIs. - -if POSIX_CLOCK - -config PTHREAD_IPC - bool "POSIX pthread IPC API" - default y if POSIX_API - help - This enables a mostly-standards-compliant implementation of - the pthread mutex, condition variable and barrier IPC - mechanisms. - -endif # POSIX_CLOCK +rsource "Kconfig.profile" rsource "Kconfig.aio" rsource "Kconfig.barrier" -rsource "Kconfig.clock" -rsource "Kconfig.cond" -rsource "Kconfig.confstr" -rsource "Kconfig.env" -rsource "Kconfig.eventfd" -rsource "Kconfig.fdtable" -rsource "Kconfig.fnmatch" +rsource "Kconfig.c_lib_ext" +rsource "Kconfig.device_io" +rsource "Kconfig.fd_mgmt" rsource "Kconfig.fs" -rsource "Kconfig.getentropy" -rsource "Kconfig.getopt" -rsource "Kconfig.key" +rsource "Kconfig.mem" rsource "Kconfig.mqueue" -rsource "Kconfig.mutex" rsource "Kconfig.net" +rsource "Kconfig.proc1" +rsource "Kconfig.procN" rsource "Kconfig.pthread" rsource "Kconfig.rwlock" rsource "Kconfig.sched" rsource "Kconfig.semaphore" rsource "Kconfig.signal" rsource "Kconfig.spinlock" -rsource "Kconfig.stropts" -rsource "Kconfig.sysconf" -rsource "Kconfig.syslog" +rsource "Kconfig.sync_io" rsource "Kconfig.timer" -rsource "Kconfig.uname" +rsource "Kconfig.xsi" + +rsource "Kconfig.compat" + +rsource "Kconfig.deprecated" endmenu # "POSIX Options" diff --git a/lib/posix/options/Kconfig.aio b/lib/posix/options/Kconfig.aio index 6fc35349738f3..43e681f39abc8 100644 --- a/lib/posix/options/Kconfig.aio +++ b/lib/posix/options/Kconfig.aio @@ -3,8 +3,8 @@ # SPDX-License-Identifier: Apache-2.0 config POSIX_ASYNCHRONOUS_IO - bool "Asynchronous IO" - default y if POSIX_API + bool "POSIX asynchronous I/O [EXPERIMENTAL]" + select EXPERIMENTAL help Enable this option for asynchronous I/O. This option is present for conformance purposes only. All functions listed in return -1 and set errno to ENOSYS. diff --git a/lib/posix/options/Kconfig.barrier b/lib/posix/options/Kconfig.barrier index 72dd814827759..b349d0376551b 100644 --- a/lib/posix/options/Kconfig.barrier +++ b/lib/posix/options/Kconfig.barrier @@ -1,17 +1,29 @@ # Copyright (c) 2017 Intel Corporation # Copyright (c) 2023 Meta +# Copyright (c) 2024 Tenstorrent # # SPDX-License-Identifier: Apache-2.0 -TYPE = PTHREAD_BARRIER -type = pthread_barrier_t -type-function = pthread_barrier_wait -rsource "Kconfig.template.pooled_ipc_type" +menuconfig POSIX_BARRIERS + bool "POSIX barriers" + help + Select 'y' here to enable POSIX barriers. + + For more information please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_BARRIERS -if PTHREAD_BARRIER +config MAX_PTHREAD_BARRIER_COUNT + int "Maximum number of POSIX barriers" + default 5 + help + Maximum simultaneously active pthread_barrier_t in a POSIX application. + + Note: this is a non-standard option. config PTHREAD_CREATE_BARRIER - bool "Use a pthread_barrier_t to serialize pthread_create()" + bool "Use a POSIX barrier to serialize pthread_create()" help When running several SMP applications in parallel instances of Qemu, e.g. via twister, explicit serialization may be required between @@ -21,4 +33,8 @@ config PTHREAD_CREATE_BARRIER On such systems, say Y here to introduce explicit serialization via pthread_barrier_wait(). -endif +module = PTHREAD_BARRIER +module-str = POSIX thread barriers +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_BARRIERS diff --git a/lib/posix/options/Kconfig.c_lib_ext b/lib/posix/options/Kconfig.c_lib_ext new file mode 100644 index 0000000000000..e8c55d8818b19 --- /dev/null +++ b/lib/posix/options/Kconfig.c_lib_ext @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig POSIX_C_LIB_EXT + bool "POSIX general C library extension" + help + Select 'y' here and Zephyr will provide an implementation of the POSIX_C_LIB_EXT Option + Group, consisting of fnmatch(), getopt(), getsubopt(), optarg, opterr, optind, optopt, + stpcpy(), stpncpy(), strcasecmp(), strdup(), strfmon(), and strncasecmp(), strndup(), and + strnlen(). + + For more informnation, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_C_LIB_EXT + +config GETOPT_LONG + bool "Getopt long library support" + help + This option adds support of the getopt long. + Different shell backends are using their own instance of getopt to + not interfere with each other. + All not shell threads share one global instance of getopt state, hence + apart from shell this library is not thread safe. User can add support + for other threads by extending function getopt_state_get in + getopt_common.c file. + +endif # POSIX_C_LIB_EXT diff --git a/lib/posix/options/Kconfig.clock b/lib/posix/options/Kconfig.clock deleted file mode 100644 index 0d541c9f32fd8..0000000000000 --- a/lib/posix/options/Kconfig.clock +++ /dev/null @@ -1,11 +0,0 @@ -# Copyright (c) 2018 Intel Corporation -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_CLOCK - bool "clock and sleep APIs" - default y if POSIX_API - imply TIMER - depends on !NATIVE_LIBC - help - This enables POSIX clock\_\*() and \*sleep() functions. diff --git a/lib/posix/options/Kconfig.compat b/lib/posix/options/Kconfig.compat new file mode 100644 index 0000000000000..a07c2b125795e --- /dev/null +++ b/lib/posix/options/Kconfig.compat @@ -0,0 +1,18 @@ +# Copyright (c) 2020 Tobias Svehagen +# Copyright (c) 2023 Meta +# +# SPDX-License-Identifier: Apache-2.0 + +menu "Miscellaneous POSIX-related options" + +config EVENTFD + bool "Support for eventfd" + depends on !NATIVE_APPLICATION + select ZVFS + select ZVFS_EVENTFD + help + Enable support for event file descriptors, eventfd. An eventfd can + be used as an event wait/notify mechanism together with POSIX calls + like read, write and poll. + +endmenu diff --git a/lib/posix/options/Kconfig.cond b/lib/posix/options/Kconfig.cond deleted file mode 100644 index b69b35dece6f8..0000000000000 --- a/lib/posix/options/Kconfig.cond +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017 Intel Corporation -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -TYPE = PTHREAD_COND -type = pthread_cond_t -type-function = pthread_cond_wait -rsource "Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/options/Kconfig.confstr b/lib/posix/options/Kconfig.confstr deleted file mode 100644 index 154f14f2d5251..0000000000000 --- a/lib/posix/options/Kconfig.confstr +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2024, Meta -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_CONFSTR - bool "Retrieve string system configuration" - default y if POSIX_API - help - This enables the POSIX confstr() function. diff --git a/lib/posix/options/Kconfig.deprecated b/lib/posix/options/Kconfig.deprecated new file mode 100644 index 0000000000000..3f39a701dc9ce --- /dev/null +++ b/lib/posix/options/Kconfig.deprecated @@ -0,0 +1,313 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +# This file should be removed after Zephyr 4.0 is released + +menu "Deprecated POSIX options" + +config EVENTFD_MAX + int "Maximum number of eventfd's [DEPRECATED]" + default ZVFS_EVENTFD_MAX if ZVFS_EVENTFD + default 0 + help + This option is deprecated. + + Please use CONFIG_ZVFS_EVENTFD_MAX instead. + +config FNMATCH + bool "Support for fnmatch [DEPRECATED]" + select DEPRECATED + select POSIX_C_LIB_EXT + help + This option is deprecated. + + Please use CONFIG_POSIX_C_LIB_EXT instead. + +config GETENTROPY + bool "Support for getentropy [DEPRECATED]" + select DEPRECATED + select POSIX_C_LIB_EXT + help + This option is deprecated. + + Please use CONFIG_POSIX_C_LIB_EXT instead. + +config GETOPT + bool "Getopt library support [DEPRECATED]" + select DEPRECATED + select POSIX_C_LIB_EXT + help + This option is deprecated. + + Please use CONFIG_POSIX_C_LIB_EXT instead. + +config MAX_PTHREAD_COUNT + int "Maximum number of pthread_t [DEPRECATED]" + default POSIX_THREAD_THREADS_MAX if POSIX_THREADS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_THREAD_THREADS_MAX instead. + +config MAX_PTHREAD_KEY_COUNT + int "Maximum number of pthread_key_t [DEPRECATED]" + default POSIX_THREAD_KEYS_MAX if POSIX_THREADS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_THREAD_KEYS_MAX instead. + +config MAX_TIMER_COUNT + int "Maximum number of timer_t [DEPRECATED]" + default POSIX_TIMER_MAX if POSIX_TIMERS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_TIMER_MAX instead. + +config MSG_COUNT_MAX + int "Maximum number of messages in a POSIX message queue [DEPRECATED]" + default POSIX_MQ_OPEN_MAX if POSIX_MESSAGE_PASSING + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_MQ_OPEN_MAX instead. + +config POSIX_CLOCK + bool "clock and sleep APIs [DEPRECATED]" + select DEPRECATED + select POSIX_CLOCK_SELECTION + select POSIX_CPUTIME + select POSIX_MONOTONIC_CLOCK + select POSIX_TIMERS + select POSIX_TIMEOUTS + help + This option is deprecated. + + Please use CONFIG_POSIX_TIMERS instead. + +config POSIX_CONFSTR + bool "Retrieve string system configuration [DEPRECATED]" + select DEPRECATED + select POSIX_SINGLE_PROCESS + help + This option is deprecated. + + Please use CONFIG_POSIX_SINGLE_PROCESS instead. + +config POSIX_ENV + bool "Support for environ, getenv(), getenv_r(), setenv(), and unsetenv() [DEPRECATED]" + select DEPRECATED + select POSIX_SINGLE_PROCESS + help + This option is deprecated. + + Please use CONFIG_POSIX_SINGLE_PROCESS instead. + +config POSIX_FS + bool "Support for environ, getenv(), getenv_r(), setenv(), and unsetenv() [DEPRECATED]" + select DEPRECATED + select POSIX_FILE_SYSTEM + help + This option is deprecated. + + Please use CONFIG_POSIX_FILE_SYSTEM instead. + +config POSIX_LIMITS_RTSIG_MAX + int "_POSIX_RTSIG_MAX value in limits.h [DEPRECATED]" + default POSIX_RTSIG_MAX if POSIX_REALTIME_SIGNALS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_RTSIG_MAX instead. + +config POSIX_MAX_FDS + int "Maximum number of open file descriptors [DEPRECATED]" + default POSIX_OPEN_MAX + help + This option is deprecated. + + Please use CONFIG_POSIX_OPEN_MAX instead. + + See also CONFIG_ZVFS_OPEN_MAX. + +config POSIX_MAX_OPEN_FILES + int "Maximum number of open file descriptors [DEPRECATED]" + default POSIX_OPEN_MAX + help + This option is deprecated. + + Please use CONFIG_POSIX_OPEN_MAX instead. + + See also CONFIG_ZVFS_OPEN_MAX. + +config POSIX_MQUEUE + bool "Message queue support [DEPRECATED]" + select DEPRECATED + select POSIX_MESSAGE_PASSING + help + This option is deprecated. + + Please use CONFIG_POSIX_MESSAGE_PASSING instead. + +config POSIX_PUTMSG + bool "Support for putmsg function [DEPRECATED]" + select DEPRECATED + select XOPEN_STREAMS + help + This option is deprecated. + + Please use CONFIG_XOPEN_STREAMS instead. + +config POSIX_SIGNAL + bool "Support for POSIX signal APIs [DEPRECATED]" + select DEPRECATED + select POSIX_SIGNALS + help + This option is deprecated. + + Please use CONFIG_POSIX_SIGNALS instead. + +config POSIX_SYSCONF + bool "Support for sysconf() [DEPRECATED]" + select DEPRECATED + select POSIX_SINGLE_PROCESS + help + This option is deprecated. + + Please use CONFIG_POSIX_SINGLE_PROCESS instead. + +config POSIX_SYSLOG + bool "Support for syslog() [DEPRECATED]" + select DEPRECATED + select XSI_SYSTEM_LOGGING + help + This option is deprecated. + + Please use CONFIG_XSI_SYSTEM_LOGGING instead. + +config POSIX_UNAME + bool "Support for uname [DEPRECATED]" + select DEPRECATED + select POSIX_SINGLE_PROCESS + help + This option is deprecated. + + Please use CONFIG_POSIX_SINGLE_PROCESS instead. + +config PTHREAD + bool "pthread_t support [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + +config PTHREAD_BARRIER + bool "pthread_barrier_t support [DEPRECATED]" + select DEPRECATED + select POSIX_BARRIERS + help + This option is deprecated. + + Please use CONFIG_POSIX_BARRIERS instead. + +config PTHREAD_COND + bool "pthread_cond_t support [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + + +config PTHREAD_IPC + bool "POSIX pthread IPC API [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + +config PTHREAD_KEY + bool "pthread_key_t support [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + +config PTHREAD_MUTEX + bool "pthread_mutex_t support [DEPRECATED]" + select DEPRECATED + select POSIX_THREADS + help + This option is deprecated. + + Please use CONFIG_POSIX_THREADS instead. + +config PTHREAD_RWLOCK + bool "pthread_spinlock_t support [DEPRECATED]" + select DEPRECATED + select POSIX_READER_WRITER_LOCKS + help + This option is deprecated. + + Please use CONFIG_POSIX_READER_WRITER_LOCKS instead. + +config PTHREAD_SPINLOCK + bool "pthread_spinlock_t support [DEPRECATED]" + select DEPRECATED + select POSIX_SPIN_LOCKS + help + This option is deprecated. + + Please use CONFIG_POSIX_SPIN_LOCKS instead. + +config TIMER + bool "Timer support [DEPRECATED]" + select DEPRECATED + select POSIX_TIMERS + help + This option is deprecated. + + Please use CONFIG_POSIX_TIMERS instead. + +config TIMER_DELAYTIMER_MAX + int "Maximum count returned my timer_getoverrun() in POSIX application [DEPRECATED]" + default POSIX_DELAYTIMER_MAX if POSIX_TIMERS + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_DELAYTIMER_MAX instead. + +config SEM_NAMELEN_MAX + int "Maximum name length [DEPRECATED]" + default POSIX_SEM_NAMELEN_MAX if POSIX_SEMAPHORES + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_SEM_NAMELEN_MAX instead. + +config SEM_VALUE_MAX + int "Maximum semaphore limit [DEPRECATED]" + default POSIX_SEM_VALUE_MAX if POSIX_SEMAPHORES + default 0 + help + This option is deprecated. + + Please use CONFIG_POSIX_SEM_VALUE_MAX instead. + +endmenu diff --git a/lib/posix/options/Kconfig.device_io b/lib/posix/options/Kconfig.device_io new file mode 100644 index 0000000000000..9cfbd453102bc --- /dev/null +++ b/lib/posix/options/Kconfig.device_io @@ -0,0 +1,56 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menu "POSIX device I/O" + +config POSIX_DEVICE_IO + bool "POSIX device I/O [EXPERIMENTAL]" + select FDTABLE + select EXPERIMENTAL + help + Select 'y' here and Zephyr will provide an implementation of the POSIX_DEVICE_IO Option + Group such as FD_CLR(), FD_ISSET(), FD_SET(), FD_ZERO(), close(), fdopen(), fileno(), open(), + poll(), pread(), pselect(), pwrite(), read(), select(), and write(). + + For more informnation, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_DEVICE_IO + +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_DEVICE_IO_ALIAS_CLOSE + bool + help + Select 'y' here and Zephyr will provide an alias for close() as _close(). + +config POSIX_DEVICE_IO_ALIAS_OPEN + bool + help + Select 'y' here and Zephyr will provide an alias for open() as _open(). + +config POSIX_DEVICE_IO_ALIAS_READ + bool + help + Select 'y' here and Zephyr will provide an alias for read() as _read(). + +config POSIX_DEVICE_IO_ALIAS_WRITE + bool + help + Select 'y' here and Zephyr will provide an alias for write() as _write(). + +endif # POSIX_DEVICE_IO + +config POSIX_OPEN_MAX + int + default ZVFS_OPEN_MAX + help + The maximum number of files that a process can have open at one time. This option is not + directly user-configurable but can be adjusted via CONFIG_ZVFS_OPEN_MAX. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html + +endmenu diff --git a/lib/posix/options/Kconfig.env b/lib/posix/options/Kconfig.env deleted file mode 100644 index 222392d273719..0000000000000 --- a/lib/posix/options/Kconfig.env +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2023, Meta -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_ENV - bool "Support for environ, getenv(), getenv_r(), setenv(), and unsetenv()" - depends on COMMON_LIBC_MALLOC - default y if POSIX_API - help - Select this option to add support for environment variables. - -module = POSIX_ENV -module-str = POSIX env logging -source "subsys/logging/Kconfig.template.log_config" diff --git a/lib/posix/options/Kconfig.eventfd b/lib/posix/options/Kconfig.eventfd deleted file mode 100644 index eadf8f80916f6..0000000000000 --- a/lib/posix/options/Kconfig.eventfd +++ /dev/null @@ -1,23 +0,0 @@ -# Copyright (c) 2020 Tobias Svehagen -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -menuconfig EVENTFD - bool "Support for eventfd" - depends on !NATIVE_APPLICATION - select POLL - select FDTABLE - default y if POSIX_API - help - Enable support for event file descriptors, eventfd. An eventfd can - be used as an event wait/notify mechanism together with POSIX calls - like read, write and poll. - -config EVENTFD_MAX - int "Maximum number of eventfd's" - depends on EVENTFD - default 1 - range 1 4096 - help - The maximum number of supported event file descriptors. diff --git a/lib/posix/options/Kconfig.fd_mgmt b/lib/posix/options/Kconfig.fd_mgmt new file mode 100644 index 0000000000000..ca16539560148 --- /dev/null +++ b/lib/posix/options/Kconfig.fd_mgmt @@ -0,0 +1,36 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig POSIX_FD_MGMT + bool "POSIX file descriptor management [EXPERIMENTAL]" + select EXPERIMENTAL + help + Select 'y' here and Zephyr will provide implementations for the POSIX_FD_MGMT Option Group. + This includes support for dup(), dup2(), fcntl(), fseeko(), ftello(), ftruncate(), + and lseek(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_FD_MGMT + +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_FD_MGMT_ALIAS_FCNTL + bool + help + Select 'y' here and Zephyr will provide an alias for fcntl() as _fcntl(). + +config POSIX_FD_MGMT_ALIAS_FTRUNCATE + bool + help + Select 'y' here and Zephyr will provide an alias for ftruncate() as _ftruncate(). + +config POSIX_FD_MGMT_ALIAS_LSEEK + bool + help + Select 'y' here and Zephyr will provide an alias for lseek() as _lseek(). + +endif # POSIX_FD_MGMT diff --git a/lib/posix/options/Kconfig.fdtable b/lib/posix/options/Kconfig.fdtable deleted file mode 100644 index 214e4a04ae98f..0000000000000 --- a/lib/posix/options/Kconfig.fdtable +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) 2018 Linaro -# -# SPDX-License-Identifier: Apache-2.0 - -menu "File descriptor table options" - -config POSIX_MAX_FDS - int "Maximum number of open file descriptors" - default 16 if WIFI_NM_WPA_SUPPLICANT - default 16 if POSIX_API - default 4 - help - Maximum number of open file descriptors, this includes - files, sockets, special devices, etc. - -endmenu # "File descriptor table options" diff --git a/lib/posix/options/Kconfig.fnmatch b/lib/posix/options/Kconfig.fnmatch deleted file mode 100644 index 81f1a00938f3a..0000000000000 --- a/lib/posix/options/Kconfig.fnmatch +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2018 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 - -config FNMATCH - bool "Support for fnmatch" - default y if POSIX_API - help - Match filenames using the the fnmatch function. For example, the pattern - "*.c" matches the filename "hello.c". diff --git a/lib/posix/options/Kconfig.fs b/lib/posix/options/Kconfig.fs index bff95a906a9cf..663d706e3fb80 100644 --- a/lib/posix/options/Kconfig.fs +++ b/lib/posix/options/Kconfig.fs @@ -2,27 +2,19 @@ # # SPDX-License-Identifier: Apache-2.0 -menuconfig POSIX_FS +menuconfig POSIX_FILE_SYSTEM bool "POSIX file system API support" default y if POSIX_API - depends on FILE_SYSTEM + select FILE_SYSTEM select FDTABLE help This enables POSIX style file system related APIs. -if POSIX_FS +if POSIX_FILE_SYSTEM -config POSIX_MAX_OPEN_FILES - int "Maximum number of open file descriptors" - default 16 +config POSIX_FILE_SYSTEM_ALIAS_FSTAT + bool help - Maximum number of open files. Note that this setting - is additionally bounded by CONFIG_POSIX_MAX_FDS. + Select 'y' here and Zephyr will provide an alias for fstat() as _fstat(). -config POSIX_FSYNC - bool "Support for fsync()" - default y - help - This enables fsync() support. - -endif # POSIX_FS +endif # POSIX_FILE_SYSTEM diff --git a/lib/posix/options/Kconfig.getentropy b/lib/posix/options/Kconfig.getentropy deleted file mode 100644 index 7445413501929..0000000000000 --- a/lib/posix/options/Kconfig.getentropy +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2024 Google LLC -# -# SPDX-License-Identifier: Apache-2.0 - -DT_CHOSEN_ZEPHYR_ENTROPY := zephyr,entropy - -config GETENTROPY - bool "Support for getentropy" - depends on !NATIVE_APPLICATION - select NATIVE_LIBC_INCOMPATIBLE - depends on ENTROPY_HAS_DRIVER - depends on $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_ENTROPY)) - help - Enable support for getentropy() function. diff --git a/lib/posix/options/Kconfig.getopt b/lib/posix/options/Kconfig.getopt deleted file mode 100644 index 4d3559cd855c3..0000000000000 --- a/lib/posix/options/Kconfig.getopt +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2021 Nordic Semiconductor ASA -# -# SPDX-License-Identifier: Apache-2.0 - -rsource "getopt/Kconfig" diff --git a/lib/posix/options/Kconfig.key b/lib/posix/options/Kconfig.key deleted file mode 100644 index 671cce103735d..0000000000000 --- a/lib/posix/options/Kconfig.key +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2018 Intel Corporation -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -TYPE = PTHREAD_KEY -type = pthread_key_t -type-function = pthread_setspecific -rsource "Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/options/Kconfig.mem b/lib/posix/options/Kconfig.mem new file mode 100644 index 0000000000000..57b9ad9670e41 --- /dev/null +++ b/lib/posix/options/Kconfig.mem @@ -0,0 +1,76 @@ +# Copyright (c) 2024 BayLibre SAS +# +# SPDX-License-Identifier: Apache-2.0 + +menu "POSIX memory" + +config POSIX_PAGE_SIZE + hex + # TODO: something similar and arch-independent for MPUs + default MMU_PAGE_SIZE if MMU + default 0x40 + help + This option is not user-configurable. + +config POSIX_SHARED_MEMORY_OBJECTS + bool "POSIX shared memory objects [EXPERIMENTAL]" + select EXPERIMENTAL + select SYS_HASH_FUNC32 + select SYS_HASH_FUNC32_DJB2 + select FDTABLE + select POSIX_MAPPED_FILES + help + Select 'y' here and Zephyr will provide implementations of shm_open() and shm_unlink(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + +config POSIX_MAPPED_FILES + bool "POSIX memory-mapped files [EXPERIMENTAL]" + select EXPERIMENTAL + imply MMU + help + Select 'y' here and Zephyr will provide support for mmap(), msync(), and munmap(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + +if POSIX_MAPPED_FILES + +config POSIX_MEMLOCK + bool "POSIX memory locking [EXPERIMENTAL]" + select EXPERIMENTAL + help + Select 'y' here and Zephyr will provide support for mlockall() and munlockall(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + +config POSIX_MEMLOCK_RANGE + bool "POSIX range memory locking [EXPERIMENTAL]" + select EXPERIMENTAL + imply MMU + imply DEMAND_PAGING + help + Select 'y' here and Zephyr will provide support for mlock() and munlock(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + +endif + +config POSIX_MEMORY_PROTECTION + bool "POSIX memory protection [EXPERIMENTAL]" + select EXPERIMENTAL + help + Select 'y' here and Zephyr will provide support for mprotect(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.orig/functions/V2_chap02.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + +endmenu diff --git a/lib/posix/options/Kconfig.mqueue b/lib/posix/options/Kconfig.mqueue index 3688455d781fa..4a1e9925fdaf1 100644 --- a/lib/posix/options/Kconfig.mqueue +++ b/lib/posix/options/Kconfig.mqueue @@ -2,33 +2,38 @@ # # SPDX-License-Identifier: Apache-2.0 -menuconfig POSIX_MQUEUE - bool "Message queue support" - default y if POSIX_API +menuconfig POSIX_MESSAGE_PASSING + bool "POSIX message queue support" help This enabled POSIX message queue related APIs. -if POSIX_MQUEUE +if POSIX_MESSAGE_PASSING -config MSG_COUNT_MAX - int "Maximum number of messages in message queue" +config POSIX_MQ_OPEN_MAX + int "Maximum number of messages in a POSIX message queue" default 16 help Mention maximum number of messages in message queue in POSIX compliant application. +config POSIX_MQ_PRIO_MAX + int "Maximum number of POSIX message priorities" + default 32 + help + Maximum number of message priorities supported by the implementation. + config MSG_SIZE_MAX - int "Maximum size of a message" + int "Maximum size of a POSIX message" default 16 help Mention maximum size of message in bytes. config MQUEUE_NAMELEN_MAX - int "Maximum size of a name length" + int "Maximum POSIX message queue name size" default 16 range 2 255 help - Mention length of message queue name in number of characters. + Mention size of message queue name in number of characters. config HEAP_MEM_POOL_ADD_SIZE_MQUEUE def_int 1024 diff --git a/lib/posix/options/Kconfig.mutex b/lib/posix/options/Kconfig.mutex deleted file mode 100644 index 6d5729e80aa02..0000000000000 --- a/lib/posix/options/Kconfig.mutex +++ /dev/null @@ -1,9 +0,0 @@ -# Copyright (c) 2017 Intel Corporation -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -TYPE = PTHREAD_MUTEX -type = pthread_mutex_t -type-function = pthread_mutex_lock -rsource "Kconfig.template.pooled_ipc_type" diff --git a/lib/posix/options/Kconfig.net b/lib/posix/options/Kconfig.net index 5e2b363e167df..f63aaaf141152 100644 --- a/lib/posix/options/Kconfig.net +++ b/lib/posix/options/Kconfig.net @@ -2,10 +2,48 @@ # # SPDX-License-Identifier: Apache-2.0 -config POSIX_NETWORKING +menuconfig POSIX_NETWORKING bool "POSIX Networking API" - default y if POSIX_API depends on NETWORKING + select NET_HOSTNAME_ENABLE + select NET_HOSTNAME_DYNAMIC + select NET_INTERFACE_NAME + select NET_SOCKETPAIR + select NET_SOCKETS help Enable this option to support the POSIX networking API. This includes support for BSD Sockets. + + For additional details, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_NETWORKING + +config POSIX_HOST_NAME_MAX + int + default NET_HOSTNAME_MAX_LEN + help + The maximum length of a host name as defined by POSIX. + + For additional details, please see + https://pubs.opengroup.org/onlinepubs/009695399/basedefs/limits.h.html + +config POSIX_IPV6 + bool "POSIX IPv6 support" + select NET_IPV6 + help + Enable this option to support the POSIX IPv6 API. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + +config POSIX_RAW_SOCKETS + bool "POSIX RAW socket support" + select NET_SOCKETS_PACKET + help + Enable this option to support the raw sockets. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799.2008edition/xrat/V4_xsh_chap02.html#tag_22_02_10_18 + +endif # POSIX_NETWORKING diff --git a/lib/posix/options/Kconfig.proc1 b/lib/posix/options/Kconfig.proc1 new file mode 100644 index 0000000000000..9ab29048ca2bb --- /dev/null +++ b/lib/posix/options/Kconfig.proc1 @@ -0,0 +1,56 @@ +# Copyright (c) 2023 Meta +# Copyright (c) 2024 BayLibre SAS +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig POSIX_SINGLE_PROCESS + bool "POSIX single process support" + # imply COMMON_LIBC_MALLOC # for env.c + help + Select 'y' here to use confstr(), environ, errno, getenv(), setenv(), sysconf(), uname(), + or unsetenv(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_SINGLE_PROCESS + +choice POSIX_SYSCONF_IMPL_CHOICE + default POSIX_SYSCONF_IMPL_FULL if CPP + default POSIX_SYSCONF_IMPL_MACRO + prompt "Sysconf implementation method" + +config POSIX_SYSCONF_IMPL_MACRO + bool "Macro" + help + The sysconf() function is implemented compile-time constant via macros. This is the option + with the least overhead. The downside is that sysconf() is not an addressable function. + +config POSIX_SYSCONF_IMPL_FULL + bool "Full" + help + The sysconf() function is implemented as a large integer-integer array. The advantage if this + option is that all sysconf() options can be queried and that the sysconf() symbol is + addressable. + +endchoice + +config POSIX_UNAME_VERSION_LEN + int "uname version string length" + default 70 + help + Defines the maximum string length of uname version. + +config POSIX_UNAME_NODENAME_LEN + int "uname nodename string length" + default 6 if !NET_HOSTNAME_UNIQUE + default 22 if NET_HOSTNAME_UNIQUE + help + Defines the maximum string length of nodename version. + +module = POSIX_ENV +module-str = POSIX env logging +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_SINGLE_PROCESS diff --git a/lib/posix/options/Kconfig.procN b/lib/posix/options/Kconfig.procN new file mode 100644 index 0000000000000..b3a467b88b9d3 --- /dev/null +++ b/lib/posix/options/Kconfig.procN @@ -0,0 +1,28 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menuconfig POSIX_MULTI_PROCESS + bool "POSIX multi-process support [EXPERIMENTAL]" + select EXPERIMENTAL + help + Support for multi-processing. + + Note: Currently Zephyr does not support multiple processes and therefore much of this option + group is not implemented and is considered undefined behaviour. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_MULTI_PROCESS + +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_MULTI_PROCESS_ALIAS_GETPID + bool + default y + help + Select 'y' here and Zephyr will provide an alias for getpid() as _getpid(). + +endif # POSIX_MULTI_PROCESS diff --git a/lib/posix/options/Kconfig.profile b/lib/posix/options/Kconfig.profile new file mode 100644 index 0000000000000..b57e07fbc2828 --- /dev/null +++ b/lib/posix/options/Kconfig.profile @@ -0,0 +1,186 @@ +# Copyright (c) 2024 Tenstorrent +# +# SPDX-License-Identifier: Apache-2.0 + +config POSIX_API + bool "POSIX APIs" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS # clock_gettime(), pthread_create(), sem_get(), etc + select POSIX_AEP_REALTIME_MINIMAL # CLOCK_MONOTONIC, pthread_attr_setstack(), etc + select POSIX_NETWORKING if NETWORKING # inet_ntoa(), socket(), etc + imply EVENTFD # eventfd(), eventfd_read(), eventfd_write() + imply POSIX_FD_MGMT # open(), close(), read(), write() + imply POSIX_MESSAGE_PASSING # mq_open(), etc + imply POSIX_MULTI_PROCESS # sleep(), getpid(), etc + help + This option enables the required POSIX System Interfaces (base definitions), all of PSE51, + and some features found in PSE52. + + Note: in the future, this option may be deprecated in favour of subprofiling options. + +choice POSIX_AEP_CHOICE + prompt "POSIX Subprofile" + default POSIX_AEP_CHOICE_NONE + help + This choice is intended to help users select the correct POSIX profile for their + application. Choices are based on IEEE 1003.13-2003 (now inactive / reserved) and + extrapolated to the more recent Subprofiling Option Groups in IEEE 1003.3-2017. + + For more information, please refer to + https://standards.ieee.org/ieee/1003.13/3322/ + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_CHOICE_NONE + bool "No pre-defined POSIX subprofile" + help + No pre-defined POSIX profile is selected. + +config POSIX_AEP_CHOICE_BASE + bool "Base definitions (system interfaces)" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS + help + Only enable the base definitions required for all POSIX systems. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_03_01 + +config POSIX_AEP_CHOICE_PSE51 + bool "Minimal Realtime System Profile (PSE51)" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS + select POSIX_AEP_REALTIME_MINIMAL + help + PSE51 includes the POSIX Base Definitions (System Interfaces) as well as several Options and + Option Groups to facilitate device I/O, signals, mandatory configuration utilities, and + threading. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_CHOICE_PSE52 + bool "Realtime Controller System Profile (PSE52)" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS + select POSIX_AEP_REALTIME_MINIMAL + select POSIX_AEP_REALTIME_CONTROLLER + help + PSE52 includes the POSIX Base Definitions (System Interfaces) as well as all features of + PSE51. Additionally, it includes interfaces for file descriptor management, filesystem + support, support for message queues, and tracing. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_CHOICE_PSE53 + bool "Dedicated Realtime System Profile (PSE53)" + depends on !NATIVE_APPLICATION + select NATIVE_LIBC_INCOMPATIBLE + select POSIX_BASE_DEFINITIONS + select POSIX_AEP_REALTIME_MINIMAL + select POSIX_AEP_REALTIME_CONTROLLER + select POSIX_AEP_REALTIME_DEDICATED + help + PSE53 includes the POSIX Base Definitions (System Interfaces) as well as all features of + PSE52. Additionally, it includes interfaces for POSIX multi-processing, networking, pipes, + and prioritized I/O. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +# TODO: PSE54: Multi-purpose Realtime System Profile + +endchoice # POSIX_AEP_CHOICE + +# Base Definitions (System Interfaces) +config POSIX_BASE_DEFINITIONS + bool + select POSIX_ASYNCHRONOUS_IO + select POSIX_BARRIERS + select POSIX_CLOCK_SELECTION + # select POSIX_MAPPED_FILES + # select POSIX_MEMORY_PROTECTION + select POSIX_READER_WRITER_LOCKS + select POSIX_REALTIME_SIGNALS + select POSIX_SEMAPHORES + select POSIX_SPIN_LOCKS + select POSIX_THREAD_SAFE_FUNCTIONS + select POSIX_THREADS + select POSIX_TIMEOUTS + select POSIX_TIMERS + help + This option is not user configurable. It may be configured indirectly by selecting + CONFIG_POSIX_AEP_CHOICE_BASE=y. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_03_01 + +config POSIX_AEP_REALTIME_MINIMAL + bool + # Option Groups + select POSIX_DEVICE_IO + select POSIX_SIGNALS + select POSIX_SINGLE_PROCESS + select XSI_THREADS_EXT + # Options + select POSIX_FSYNC + # select POSIX_MEMLOCK + # select POSIX_MEMLOCK_RANGE + select POSIX_MONOTONIC_CLOCK + # select POSIX_SHARED_MEMORY_OBJECTS + select POSIX_SYNCHRONIZED_IO + select POSIX_THREAD_ATTR_STACKADDR + select POSIX_THREAD_ATTR_STACKSIZE + select POSIX_THREAD_CPUTIME + select POSIX_THREAD_PRIO_INHERIT + select POSIX_THREAD_PRIO_PROTECT + select POSIX_THREAD_PRIORITY_SCHEDULING + # select POSIX_THREAD_SPORADIC_SERVER + help + This option is not user configurable. It may be configured indirectly by selecting + CONFIG_POSIX_AEP_CHOICE_PSE51=y. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_REALTIME_CONTROLLER + bool + # Option Groups + select POSIX_FD_MGMT + select POSIX_FILE_SYSTEM + # Options + select POSIX_MESSAGE_PASSING + # select POSIX_TRACE + # select POSIX_TRACE_EVENT_FILTER + # select POSIX_TRACE_LOG + help + This option is not user configurable. It may be configured indirectly by selecting + CONFIG_POSIX_AEP_CHOICE_PSE52=y. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_AEP_REALTIME_DEDICATED + bool + # Option Groups + select POSIX_MULTI_PROCESS + select POSIX_NETWORKING + # select POSIX_PIPE + # select POSIX_SIGNAL_JUMP + # Options + select POSIX_CPUTIME + # select POSIX_PRIORITIZED_IO + select POSIX_PRIORITY_SCHEDULING + select POSIX_RAW_SOCKETS + # select POSIX_SPAWN + # select POSIX_SPORADIC_SERVER + help + This option is not user configurable. It may be configured indirectly by selecting + CONFIG_POSIX_AEP_CHOICE_PSE53=y. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html diff --git a/lib/posix/options/Kconfig.pthread b/lib/posix/options/Kconfig.pthread index f0c65836b6000..ec38286ff49a3 100644 --- a/lib/posix/options/Kconfig.pthread +++ b/lib/posix/options/Kconfig.pthread @@ -1,14 +1,49 @@ # Copyright (c) 2017 Intel Corporation # Copyright (c) 2023 Meta +# Copyright (c) 2024 Tenstorrent AI ULC # # SPDX-License-Identifier: Apache-2.0 -TYPE = PTHREAD -type = pthread_t -type-function = pthread_create -rsource "Kconfig.template.pooled_ipc_type" +menuconfig POSIX_THREADS + bool "POSIX thread support" + help + Select 'y' here to enable POSIX threads, mutexes, condition variables, and thread-specific + storage. + + For more information please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_THREADS + +config POSIX_THREAD_THREADS_MAX + int "Maximum number of POSIX threads" + default 5 + help + Maximum simultaneously active threads in a POSIX application. -if PTHREAD + For more information, see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html + +config MAX_PTHREAD_MUTEX_COUNT + int "Maximum number of POSIX mutexes" + default 5 + help + Maximum simultaneously active mutexes in a POSIX application. + +config MAX_PTHREAD_COND_COUNT + int "Maximum number of POSIX condition variables" + default 5 + help + Maximum simultaneously active condition variables in a POSIX application. + +config POSIX_THREAD_KEYS_MAX + int "Maximum number of POSIX thread-specific-storage keys" + default 5 + help + Maximum simultaneously active thread-specific-storage keys in a POSIX application. + + For more information, see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html config PTHREAD_RECYCLER_DELAY_MS int "Delay for reclaiming dynamic pthread stacks (ms)" @@ -27,6 +62,50 @@ config PTHREAD_RECYCLER_DELAY_MS Note: this option should be considered temporary and will likely be removed once a more synchronous solution is available. +config POSIX_THREAD_ATTR_STACKADDR + bool "Support getting and setting POSIX thread stack addresses" + help + Enable this option to use pthread_attr_getstackaddr() and + pthread_attr_setstackaddr(). + + This option was removed in IEEE 1003.1-2017 in favour of + pthread_attr_getstack() and pthread_attr_setstack(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/009696799/functions/pthread_attr_getstackaddr.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap03.html + https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_08 + +config POSIX_THREAD_ATTR_STACKSIZE + bool "Support getting and setting POSIX thread stack sizes" + help + Enable this option to use pthread_attr_getstacksize() or + pthread_attr_setstacksize(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/009696699/functions/pthread_attr_getstacksize.html + +config POSIX_THREADS_EXT + bool "Extended POSIX thread support" + help + Enable this option to use pthread_attr_getguardsize(), pthread_attr_setguardsize(), + pthread_mutexattr_gettype(), or pthread_mutexattr_settype(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config POSIX_THREAD_PRIORITY_SCHEDULING + bool "Run POSIX threads with different priorities and schedulers" + help + Enabling this option allows the application to configure different priorities and + scheduling algorithms for different threads via functions such as pthread_setschedparam() + and pthread_setschedprio(). This is required for Realtime Threads and Advanced Realtime + Threads. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_06 + https://man7.org/linux/man-pages/man7/posixoptions.7.html + config POSIX_PTHREAD_ATTR_STACKSIZE_BITS int "Significant bits for pthread_attr_t stacksize" range 8 31 @@ -59,4 +138,47 @@ config POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT facilitate a more dynamic approach to guard areas (via software or hardware) but for now it simply increases the size of thread stacks. -endif +config POSIX_THREAD_PRIO_INHERIT + bool "POSIX mutex priority inheritance" + help + Select 'y' here to enable POSIX mutex priority inheritance. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_getprotocol.html + +config POSIX_THREAD_PRIO_PROTECT + bool "POSIX mutex priority protection" + help + Select 'y' here to enable POSIX mutex priority protection. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_mutexattr_getprotocol.html + +config POSIX_THREAD_SAFE_FUNCTIONS + bool "POSIX thread-safe functions" + help + Select 'y' here to enable POSIX thread-safe functions including asctime_r(), ctime_r(), + flockfile(), ftrylockfile(), funlockfile(), getc_unlocked(), getchar_unlocked(), + getgrgid_r(), getgrnam_r(), getpwnam_r(), getpwuid_r(), gmtime_r(), localtime_r(), + putc_unlocked(), putchar_unlocked(), rand_r(), readdir_r(), strerror_r(), and strtok_r(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap02.html#tag_22_02_09_07 + +module = PTHREAD +module-str = POSIX thread +source "subsys/logging/Kconfig.template.log_config" + +module = PTHREAD_MUTEX +module-str = POSIX mutex +source "subsys/logging/Kconfig.template.log_config" + +module = PTHREAD_COND +module-str = POSIX condition variable +source "subsys/logging/Kconfig.template.log_config" + +module = PTHREAD_KEY +module-str = POSIX thread-specific data +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_THREADS diff --git a/lib/posix/options/Kconfig.rwlock b/lib/posix/options/Kconfig.rwlock index fea61551ec356..8626b3bb1a40b 100644 --- a/lib/posix/options/Kconfig.rwlock +++ b/lib/posix/options/Kconfig.rwlock @@ -2,7 +2,26 @@ # # SPDX-License-Identifier: Apache-2.0 -TYPE = PTHREAD_RWLOCK -type = pthread_rwlock_t -type-function = pthread_rwlock_timedrdlock -rsource "Kconfig.template.pooled_ipc_type" +menuconfig POSIX_READER_WRITER_LOCKS + bool "POSIX reader-writer locks" + help + Select 'y' here to enable POSIX reader-writer locks. + + For more information please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_READER_WRITER_LOCKS + +config MAX_PTHREAD_RWLOCK_COUNT + int "Maximum number of POSIX reader-writer locks" + default 5 + help + Maximum simultaneously active reader-writer locks in a POSIX application. + + Note: this is a non-standard option. + +module = PTHREAD_RWLOCK +module-str = POSIX Reader-Writer Locks +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_READER_WRITER_LOCKS diff --git a/lib/posix/options/Kconfig.sched b/lib/posix/options/Kconfig.sched index b5fb3a5dcb1e9..7e0dc70fca119 100644 --- a/lib/posix/options/Kconfig.sched +++ b/lib/posix/options/Kconfig.sched @@ -2,10 +2,19 @@ # # SPDX-License-Identifier: Apache-2.0 +menu "POSIX scheduler options" + config POSIX_PRIORITY_SCHEDULING - bool "Priority scheduling" - default y if PTHREAD - default y if POSIX_API - depends on PTHREAD + bool "POSIX priority-based process scheduling [EXPERIMENTAL]" + select EXPERIMENTAL help This enables POSIX scheduling APIs (_POSIX_PRIORITY_SCHEDULING). + + Since Zephyr does not yet support processes, most of this behaviour is undefined, except for + use of sched_get_priority_min() and sched_get_priority_max(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 + https://pubs.opengroup.org/onlinepubs/9699919799/functions/sched_get_priority_max.html + +endmenu diff --git a/lib/posix/options/Kconfig.semaphore b/lib/posix/options/Kconfig.semaphore index 53fb030736b01..65bc2a686930b 100644 --- a/lib/posix/options/Kconfig.semaphore +++ b/lib/posix/options/Kconfig.semaphore @@ -2,21 +2,35 @@ # # SPDX-License-Identifier: Apache-2.0 -menu "sem_t support" +menuconfig POSIX_SEMAPHORES + bool "POSIX semaphore support" + help + Enable this option for POSIX semaphore support. + +if POSIX_SEMAPHORES -config SEM_VALUE_MAX - int "Maximum semaphore limit" +config POSIX_SEM_VALUE_MAX + int "Maximum semaphore value" default 32767 range 1 32767 help Maximum semaphore count in POSIX compliant Application. -config SEM_NAMELEN_MAX - int "Maximum name length" +config POSIX_SEM_NSEMS_MAX + int "Maximum number of semaphores" + default 256 + help + Maximum number of semaphores in a POSIX application. + + Note: currently, in Zephyr, this only limits the number of named semaphores (i.e. those + created via sem_open()). + +config POSIX_SEM_NAMELEN_MAX + int "Maximum semaphore name length" default 16 range 2 255 help Maximum length of name for a named semaphore. The max value of 255 corresponds to {NAME_MAX}. -endmenu # "sem_t support" +endif # POSIX_SEMAPHORES diff --git a/lib/posix/options/Kconfig.signal b/lib/posix/options/Kconfig.signal index 99c225564c711..4507302e3f32d 100644 --- a/lib/posix/options/Kconfig.signal +++ b/lib/posix/options/Kconfig.signal @@ -2,24 +2,32 @@ # # SPDX-License-Identifier: Apache-2.0 -menu "Signal support" +menu "POSIX signals" + +config POSIX_REALTIME_SIGNALS + bool "POSIX realtime signals [EXPERIMENTAL]" + select EXPERIMENTAL + help + Enable support for POSIX realtime signals. + +if POSIX_REALTIME_SIGNALS -# needed outside of if clause above to define constants & types in signal.h config POSIX_RTSIG_MAX int "Maximum number of realtime signals" - default 31 if POSIX_SIGNAL - default 0 + default 8 help Define the maximum number of realtime signals (RTSIG_MAX). The range of realtime signals is [SIGRTMIN .. (SIGRTMIN+RTSIG_MAX)] -config POSIX_SIGNAL - bool "Support for POSIX signal APIs" - default y if POSIX_API +endif # POSIX_REALTIME_SIGNALS + +config POSIX_SIGNALS + bool "POSIX signals [EXPERIMENTAL]" + select EXPERIMENTAL help - Enable support for POSIX signal APIs. + Enable support for POSIX signals. -if POSIX_SIGNAL +if POSIX_SIGNALS config POSIX_SIGNAL_STRING_DESC bool "Use full description for the strsignal API" @@ -28,13 +36,6 @@ config POSIX_SIGNAL_STRING_DESC Use full description for the strsignal API. Will use 256 bytes of ROM. -config POSIX_LIMITS_RTSIG_MAX - int "_POSIX_RTSIG_MAX value in limits.h" - default 8 - help - Define the _POSIX_RTSIG_MAX value in limits.h. - IEEE 1003.1 defines this to be 8. - endif endmenu # "Signal support" diff --git a/lib/posix/options/Kconfig.spinlock b/lib/posix/options/Kconfig.spinlock index 8374aadfd6dd6..312a432ce38e9 100644 --- a/lib/posix/options/Kconfig.spinlock +++ b/lib/posix/options/Kconfig.spinlock @@ -2,7 +2,26 @@ # # SPDX-License-Identifier: Apache-2.0 -TYPE = PTHREAD_SPINLOCK -type = pthread_spinlock_t -type-function = pthread_spin_lock -rsource "Kconfig.template.pooled_ipc_type" +menuconfig POSIX_SPIN_LOCKS + bool "POSIX spin locks" + help + Select 'y' here to enable POSIX spin locks. + + For more information please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_SPIN_LOCKS + +config MAX_PTHREAD_SPINLOCK_COUNT + int "Maximum number of POSIX spin locks" + default 5 + help + Maximum simultaneously active spin locks in a POSIX application. + + Note: this is a non-standard option. + +module = PTHREAD_SPINLOCK +module-str = POSIX Spin Locks +source "subsys/logging/Kconfig.template.log_config" + +endif # POSIX_SPIN_LOCKS diff --git a/lib/posix/options/Kconfig.stropts b/lib/posix/options/Kconfig.stropts deleted file mode 100644 index 347f0f33c150a..0000000000000 --- a/lib/posix/options/Kconfig.stropts +++ /dev/null @@ -1,9 +0,0 @@ -# copyright (c) 2024 Abhinav Srivastava -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_PUTMSG - bool "Support for putmsg function" - default y if POSIX_API - help - This option provides support for the putmsg function used in message passing. diff --git a/lib/posix/options/Kconfig.sync_io b/lib/posix/options/Kconfig.sync_io new file mode 100644 index 0000000000000..4575ff06020ae --- /dev/null +++ b/lib/posix/options/Kconfig.sync_io @@ -0,0 +1,39 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menu "POSIX synchronized I/O" + +config POSIX_FSYNC + bool "Support for fsync()" + help + Select 'y' here and Zephyr will provide an implementation of fsync(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/functions/fsync.html + + +config POSIX_SYNCHRONIZED_IO + bool "POSIX synchronized I/O" + select POSIX_FSYNC + help + Select 'y' here and Zephyr will provide an implementation of fdatasync(), fsync(), + and msync(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/functions/msync.html + https://pubs.opengroup.org/onlinepubs/9699919799/functions/fdatasync.html + +if POSIX_FSYNC + +# These options are intended to be used for compatibility with external POSIX +# implementations such as those in Newlib or Picolibc. + +config POSIX_FILE_SYSTEM_ALIAS_FSYNC + bool + help + Select 'y' here and Zephyr will provide an alias for fsync() as _fsync(). + +endif # POSIX_FSYNC + +endmenu diff --git a/lib/posix/options/Kconfig.sysconf b/lib/posix/options/Kconfig.sysconf deleted file mode 100644 index 7e904d5b6722f..0000000000000 --- a/lib/posix/options/Kconfig.sysconf +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2024 BayLibre SAS -# -# SPDX-License-Identifier: Apache-2.0 - -menu "Sysconf support" - -config POSIX_SYSCONF - bool "Support for sysconf" - default y if POSIX_API - help - The sysconf() function provides a method for the application to determine - the current value of a configurable system limit or option (variable). - -config POSIX_PAGE_SIZE_BITS - int "Number of bits to use for PAGE_SIZE" - range 6 16 - default 12 if POSIX_API - default 6 - help - Define PAGE_SIZE as BIT(n), where n is the value configured here. - PAGE_SIZE is supported in the range [64, 65536] - If CONFIG_POSIX_API=y, PAGE_SIZE defaults to 4096, otherwise, it is 64 bytes. - -if POSIX_SYSCONF - -choice POSIX_SYSCONF_IMPL_CHOICE - default POSIX_SYSCONF_IMPL_FULL if CPP - default POSIX_SYSCONF_IMPL_MACRO - prompt "Sysconf implementation method" - -config POSIX_SYSCONF_IMPL_MACRO - bool "Macro" - help - The sysconf() function is implemented compile-time constant via macros. This is the option - with the least overhead. The downside is that sysconf() is not an addressable function. - -config POSIX_SYSCONF_IMPL_FULL - bool "Full" - help - The sysconf() function is implemented as a large integer-integer array. The advantage if this - option is that all sysconf() options can be queried and that the sysconf() symbol is - addressable. - -endchoice - -endif # POSIX_SYSCONF - -endmenu # "Sysconf support" diff --git a/lib/posix/options/Kconfig.syslog b/lib/posix/options/Kconfig.syslog deleted file mode 100644 index 1fedd93cddf7c..0000000000000 --- a/lib/posix/options/Kconfig.syslog +++ /dev/null @@ -1,10 +0,0 @@ -# Copyright (c) 2024, Meta -# -# SPDX-License-Identifier: Apache-2.0 - -config POSIX_SYSLOG - bool "Support for syslog()" - default y if POSIX_API - help - This option provides support for closelog(), openlog(), syslog(), - setlogmask(), and vsyslog(). diff --git a/lib/posix/options/Kconfig.template.pooled_ipc_type b/lib/posix/options/Kconfig.template.pooled_ipc_type deleted file mode 100644 index 08d804382e801..0000000000000 --- a/lib/posix/options/Kconfig.template.pooled_ipc_type +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -rsource "Kconfig.template.with_url" - -# Not user configurable (i.e. private for now) -menuconfig $(TYPE) - bool "$(type) support" - depends on PTHREAD_IPC - default y - help - Support for $(TYPE) - For more info, see - $(posix-url-base)/$(type-function).html - -if $(TYPE) - -# eventually, this size should be defaulted to 0 -config MAX_$(TYPE)_COUNT - int "Maximum number of $(type)" - default 5 - depends on $(TYPE) - help - Maximum simultaneously active $(type) in a POSIX application. - -rsource "Kconfig.template.with_logging" - -endif # $(TYPE) diff --git a/lib/posix/options/Kconfig.template.pooled_type b/lib/posix/options/Kconfig.template.pooled_type deleted file mode 100644 index 5a75c2ee890fe..0000000000000 --- a/lib/posix/options/Kconfig.template.pooled_type +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -rsource "Kconfig.template.with_url" - -# This is mainly for TIMER currently. -menuconfig $(TYPE) - bool "$(type) support" - help - For more info, see - $(posix-url-base)/$(type-function).html - -if $(TYPE) - -# eventually, this size should be defaulted to 0 as a safe value -config MAX_$(TYPE)_COUNT - int "Maximum number of $(type)" - default 5 - help - Maximum simultaneously active $(type) in a POSIX application. - -rsource "Kconfig.template.with_logging" - -endif # $(TYPE) diff --git a/lib/posix/options/Kconfig.template.with_logging b/lib/posix/options/Kconfig.template.with_logging deleted file mode 100644 index f1fc5141e7cd1..0000000000000 --- a/lib/posix/options/Kconfig.template.with_logging +++ /dev/null @@ -1,7 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -module = $(TYPE) -module-str = $(TYPE) logging -source "subsys/logging/Kconfig.template.log_config" diff --git a/lib/posix/options/Kconfig.template.with_url b/lib/posix/options/Kconfig.template.with_url deleted file mode 100644 index 33e34756ee71e..0000000000000 --- a/lib/posix/options/Kconfig.template.with_url +++ /dev/null @@ -1,5 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -posix-url-base = https://pubs.opengroup.org/onlinepubs/9699919799 diff --git a/lib/posix/options/Kconfig.timer b/lib/posix/options/Kconfig.timer index 10905e9c21d56..42eed40bce68d 100644 --- a/lib/posix/options/Kconfig.timer +++ b/lib/posix/options/Kconfig.timer @@ -1,13 +1,85 @@ # Copyright (c) 2018 Intel Corporation +# Copyright (c) 2024 Tenstorrent AI ULC # # SPDX-License-Identifier: Apache-2.0 -TYPE = TIMER -type = timer_t -type-function = timer_create -rsource "Kconfig.template.pooled_type" +menuconfig POSIX_TIMERS + bool "POSIX timers, clocks, and sleep functions" + help + Select 'y' here and Zephyr will provide implementations of clock_getres(), clock_gettime(), + clock_settime(), nanosleep(), timer_create(), timer_delete(), timer_getoverrun(), + timer_settime(), and timer_gettime(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +if POSIX_TIMERS + +config POSIX_THREAD_CPUTIME + bool "POSIX per-thread CPU-time clocks" + help + This enables CLOCK_THREAD_CPUTIME_ID. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_118 + https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_08_05_04 + +config POSIX_MONOTONIC_CLOCK + bool "POSIX Monotonic clock support" + help + This enables CLOCK_MONOTONIC. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_08_05_03 + +config POSIX_CPUTIME + bool "POSIX per-process CPU-time clocks" + help + This enables CLOCK_PROCESS_CPUTIME_ID. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_118 + https://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_08_05_04 + +config POSIX_CLOCK_SELECTION + bool "POSIX Clock selection" + help + This enables POSIX clock selection. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html#tag_24_03_04 -if TIMER +config POSIX_DELAYTIMER_MAX + int "Maximum count returned my timer_getoverrun() in POSIX application" + default 32 + help + This controls the maximum number of times a timer can overrun before + timer_getoverrun() in POSIX compliant application. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html + +config POSIX_TIMER_MAX + int "Maximum number of POSIX timers per process" + default 32 + help + Maximum simultaneously active timer_t in a POSIX application. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/limits.h.html + +config POSIX_TIMEOUTS + bool "Support timeouts for some blocking POSIX services" + help + Enable mandatory timeouts for some blocking operations. + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_port.html + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap02.html config TIMER_CREATE_WAIT int "Time to wait for timer availability (in msec) in POSIX application" @@ -17,11 +89,8 @@ config TIMER_CREATE_WAIT This controls how long to wait for resources to come available to create a new timer in POSIX compliant application -config TIMER_DELAYTIMER_MAX - int "Maximum count returned my timer_getoverrun() in POSIX application" - default 20 - help - This controls the maximum number of times a timer can overrun before - timer_getoverrun() in POSIX compliant application. +module = TIMER +module-str = POSIX Timers +source "subsys/logging/Kconfig.template.log_config" -endif # TIMER +endif # POSIX_TIMERS diff --git a/lib/posix/options/Kconfig.uname b/lib/posix/options/Kconfig.uname deleted file mode 100644 index 8b4482252492d..0000000000000 --- a/lib/posix/options/Kconfig.uname +++ /dev/null @@ -1,26 +0,0 @@ -# Copyright (c) 2023 Meta -# -# SPDX-License-Identifier: Apache-2.0 - -menuconfig POSIX_UNAME - bool "Support for uname" - default y if POSIX_API - help - The uname() function shall store information identifying the current - system in the structure pointed to by name. - -if POSIX_UNAME -config POSIX_UNAME_VERSION_LEN - int "uname version string length" - default 70 - help - Defines the maximum string length of uname version. - -config POSIX_UNAME_NODENAME_LEN - int "uname nodename string length" - default 6 if !NET_HOSTNAME_UNIQUE - default 22 if NET_HOSTNAME_UNIQUE - help - Defines the maximum string length of nodename version. - -endif # POSIX_UNAME diff --git a/lib/posix/options/Kconfig.xsi b/lib/posix/options/Kconfig.xsi new file mode 100644 index 0000000000000..f8be61e245d5d --- /dev/null +++ b/lib/posix/options/Kconfig.xsi @@ -0,0 +1,45 @@ +# Copyright (c) 2024 Tenstorrent AI ULC +# +# SPDX-License-Identifier: Apache-2.0 + +menu "X/Open system interfaces" + +config XSI_SINGLE_PROCESS + bool "X/Open single process" + depends on POSIX_SINGLE_PROCESS + depends on POSIX_TIMERS + help + Select 'y' here and Zephyr will provide implementations of + gethostid(), gettimeofday(), and putenv(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config XOPEN_STREAMS + bool "X/Open streams" + help + This option provides support for the X/Open Streams interface, including functions such as + fattach(), fdetach(), getmsg(), getpmsg(), putmsg(), and putpmsg(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap02.html#tag_02_01_05_09 + +config XSI_SYSTEM_LOGGING + bool "X/Open system logging" + help + This option provides support for closelog(), openlog(), syslog(), + setlogmask(), and vsyslog(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +config XSI_THREADS_EXT + bool "X/Open threads extensions" + help + This option provides support for pthread_attr_getstack(), pthread_attr_setstack(), + pthread_getconcurrency(), and pthread_setconcurrency(). + + For more information, please see + https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_subprofiles.html + +endmenu diff --git a/lib/posix/options/_common.c b/lib/posix/options/_common.c deleted file mode 100644 index 85a8e7cae66db..0000000000000 --- a/lib/posix/options/_common.c +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2017 Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include - -#ifdef CONFIG_POSIX_CLOCK -int64_t timespec_to_timeoutms(const struct timespec *abstime) -{ - int64_t milli_secs, secs, nsecs; - struct timespec curtime; - - /* FIXME: Zephyr does have CLOCK_REALTIME to get time. - * As per POSIX standard time should be calculated wrt CLOCK_REALTIME. - * Zephyr deviates from POSIX 1003.1 standard on this aspect. - */ - clock_gettime(CLOCK_MONOTONIC, &curtime); - secs = abstime->tv_sec - curtime.tv_sec; - nsecs = abstime->tv_nsec - curtime.tv_nsec; - - if (secs < 0 || (secs == 0 && nsecs < NSEC_PER_MSEC)) { - milli_secs = 0; - } else { - milli_secs = secs * MSEC_PER_SEC + nsecs / NSEC_PER_MSEC; - } - - return milli_secs; -} -#endif /* CONFIG_POSIX_CLOCK */ diff --git a/lib/posix/options/clock.c b/lib/posix/options/clock.c index 48789ae49c254..9ef0375803a17 100644 --- a/lib/posix/options/clock.c +++ b/lib/posix/options/clock.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2018 Intel Corporation + * Copyright (c) 2018 Friedt Professional Engineering Services, Inc * * SPDX-License-Identifier: Apache-2.0 */ @@ -57,7 +58,7 @@ int z_vrfy___posix_clock_get_base(clockid_t clock_id, struct timespec *ts) K_OOPS(K_SYSCALL_MEMORY_WRITE(ts, sizeof(*ts))); return z_impl___posix_clock_get_base(clock_id, ts); } -#include +#include #endif int clock_gettime(clockid_t clock_id, struct timespec *ts) @@ -156,14 +157,43 @@ int clock_settime(clockid_t clock_id, const struct timespec *tp) return 0; } +/* + * Note: usleep() was removed in Issue 7. + * + * It is kept here for compatibility purposes. + * + * For more information, please see + * https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap01.html + * https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xsh_chap03.html + */ +int usleep(useconds_t useconds) +{ + int32_t rem; + + if (useconds >= USEC_PER_SEC) { + errno = EINVAL; + return -1; + } + + rem = k_usleep(useconds); + __ASSERT_NO_MSG(rem >= 0); + if (rem > 0) { + /* sleep was interrupted by a call to k_wakeup() */ + errno = EINTR; + return -1; + } + + return 0; +} + /** * @brief Suspend execution for a nanosecond interval, or * until some absolute time relative to the specified clock. * * See IEEE 1003.1 */ -int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, - struct timespec *rmtp) +static int __z_clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, + struct timespec *rmtp) { uint64_t ns; uint64_t us; @@ -171,7 +201,7 @@ int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, k_spinlock_key_t key; const bool update_rmtp = rmtp != NULL; - if (!(clock_id == CLOCK_REALTIME || clock_id == CLOCK_MONOTONIC)) { + if (!((clock_id == CLOCK_REALTIME) || (clock_id == CLOCK_MONOTONIC))) { errno = EINVAL; return -1; } @@ -181,7 +211,7 @@ int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, return -1; } - if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= NSEC_PER_SEC) { + if ((rqtp->tv_sec < 0) || (rqtp->tv_nsec < 0) || (rqtp->tv_nsec >= NSEC_PER_SEC)) { errno = EINVAL; return -1; } @@ -225,6 +255,17 @@ int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, return 0; } +int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) +{ + return __z_clock_nanosleep(CLOCK_MONOTONIC, 0, rqtp, rmtp); +} + +int clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp, + struct timespec *rmtp) +{ + return __z_clock_nanosleep(clock_id, flags, rqtp, rmtp); +} + /** * @brief Get current real time. * diff --git a/lib/posix/options/device_io.c b/lib/posix/options/device_io.c new file mode 100644 index 0000000000000..585dc7000c2be --- /dev/null +++ b/lib/posix/options/device_io.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include + +/* prototypes for external, not-yet-public, functions in fdtable.c or fs.c */ +int zvfs_close(int fd); +int zvfs_open(const char *name, int flags); +ssize_t zvfs_read(int fd, void *buf, size_t sz); +ssize_t zvfs_write(int fd, const void *buf, size_t sz); + +int close(int fd) +{ + return zvfs_close(fd); +} +#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_CLOSE +FUNC_ALIAS(close, _close, int); +#endif + +int open(const char *name, int flags, ...) +{ + /* FIXME: necessarily need to check for O_CREAT and unpack ... if set */ + return zvfs_open(name, flags); +} +#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_OPEN +FUNC_ALIAS(open, _open, int); +#endif + +int poll(struct pollfd *fds, int nfds, int timeout) +{ + /* TODO: create zvfs_poll() and dispatch to subsystems based on file type */ + return zsock_poll(fds, nfds, timeout); +} + +ssize_t read(int fd, void *buf, size_t sz) +{ + return zvfs_read(fd, buf, sz); +} +#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_READ +FUNC_ALIAS(read, _read, ssize_t); +#endif + +int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) +{ + /* TODO: create zvfs_select() and dispatch to subsystems based on file type */ + return zsock_select(nfds, readfds, writefds, exceptfds, (struct zsock_timeval *)timeout); +} + +ssize_t write(int fd, const void *buf, size_t sz) +{ + return zvfs_write(fd, buf, sz); +} +#ifdef CONFIG_POSIX_DEVICE_IO_ALIAS_WRITE +FUNC_ALIAS(write, _write, ssize_t); +#endif diff --git a/lib/posix/options/env.c b/lib/posix/options/env.c index 2607ae2a4be85..56d3b4ae5430e 100644 --- a/lib/posix/options/env.c +++ b/lib/posix/options/env.c @@ -106,7 +106,7 @@ int getenv_r(const char *name, char *buf, size_t len) ret = -ERANGE; K_SPINLOCK_BREAK; } - strncpy(buf, val, vsize); + strcpy(buf, val); LOG_DBG("Found entry %s", environ[ret]); } @@ -188,7 +188,7 @@ int setenv(const char *name, const char *val, int overwrite) environ[ret] = env; } - strncpy(environ[ret], name, nsize); + strcpy(environ[ret], name); environ[ret][nsize] = '='; strncpy(environ[ret] + nsize + 1, val, vsize + 1); LOG_DBG("Added entry %s", environ[ret]); diff --git a/lib/posix/options/eventfd.c b/lib/posix/options/eventfd.c index 81b8f6d6dd810..b272bfa636fc2 100644 --- a/lib/posix/options/eventfd.c +++ b/lib/posix/options/eventfd.c @@ -1,484 +1,23 @@ /* - * Copyright (c) 2020 Tobias Svehagen - * Copyright (c) 2023, Meta + * Copyright (c) 2024, Tenstorrent AI ULC * * SPDX-License-Identifier: Apache-2.0 */ -#include -#include -#include #include -#include -#include -#include - -#define EFD_IN_USE_INTERNAL 0x1 -#define EFD_FLAGS_SET_INTERNAL (EFD_SEMAPHORE | EFD_NONBLOCK) - -struct eventfd { - struct k_poll_signal read_sig; - struct k_poll_signal write_sig; - struct k_spinlock lock; - eventfd_t cnt; - int flags; -}; - -static ssize_t eventfd_rw_op(void *obj, void *buf, size_t sz, - int (*op)(struct eventfd *efd, eventfd_t *value)); - -SYS_BITARRAY_DEFINE_STATIC(efds_bitarray, CONFIG_EVENTFD_MAX); -static struct eventfd efds[CONFIG_EVENTFD_MAX]; -static const struct fd_op_vtable eventfd_fd_vtable; - -static inline bool eventfd_is_in_use(struct eventfd *efd) -{ - return (efd->flags & EFD_IN_USE_INTERNAL) != 0; -} - -static inline bool eventfd_is_semaphore(struct eventfd *efd) -{ - return (efd->flags & EFD_SEMAPHORE) != 0; -} - -static inline bool eventfd_is_blocking(struct eventfd *efd) -{ - return (efd->flags & EFD_NONBLOCK) == 0; -} - -static int eventfd_poll_prepare(struct eventfd *efd, - struct zsock_pollfd *pfd, - struct k_poll_event **pev, - struct k_poll_event *pev_end) -{ - if (pfd->events & ZSOCK_POLLIN) { - if (*pev == pev_end) { - errno = ENOMEM; - return -1; - } - - (*pev)->obj = &efd->read_sig; - (*pev)->type = K_POLL_TYPE_SIGNAL; - (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; - (*pev)->state = K_POLL_STATE_NOT_READY; - (*pev)++; - } - - if (pfd->events & ZSOCK_POLLOUT) { - if (*pev == pev_end) { - errno = ENOMEM; - return -1; - } - - (*pev)->obj = &efd->write_sig; - (*pev)->type = K_POLL_TYPE_SIGNAL; - (*pev)->mode = K_POLL_MODE_NOTIFY_ONLY; - (*pev)->state = K_POLL_STATE_NOT_READY; - (*pev)++; - } - - return 0; -} - -static int eventfd_poll_update(struct eventfd *efd, - struct zsock_pollfd *pfd, - struct k_poll_event **pev) -{ - if (pfd->events & ZSOCK_POLLIN) { - pfd->revents |= ZSOCK_POLLIN * (efd->cnt > 0); - (*pev)++; - } - - if (pfd->events & ZSOCK_POLLOUT) { - pfd->revents |= ZSOCK_POLLOUT * (efd->cnt < UINT64_MAX - 1); - (*pev)++; - } - - return 0; -} - -static int eventfd_read_locked(struct eventfd *efd, eventfd_t *value) -{ - if (!eventfd_is_in_use(efd)) { - /* file descriptor has been closed */ - return -EBADF; - } - - if (efd->cnt == 0) { - /* would block / try again */ - return -EAGAIN; - } - - /* successful read */ - if (eventfd_is_semaphore(efd)) { - *value = 1; - --efd->cnt; - } else { - *value = efd->cnt; - efd->cnt = 0; - } - - if (efd->cnt == 0) { - k_poll_signal_reset(&efd->read_sig); - } - - k_poll_signal_raise(&efd->write_sig, 0); - - return 0; -} - -static int eventfd_write_locked(struct eventfd *efd, eventfd_t *value) -{ - eventfd_t result; - - if (!eventfd_is_in_use(efd)) { - /* file descriptor has been closed */ - return -EBADF; - } - - if (*value == UINT64_MAX) { - /* not a permitted value */ - return -EINVAL; - } - - if (u64_add_overflow(efd->cnt, *value, &result) || result == UINT64_MAX) { - /* would block / try again */ - return -EAGAIN; - } - - /* successful write */ - efd->cnt = result; - - if (efd->cnt == (UINT64_MAX - 1)) { - k_poll_signal_reset(&efd->write_sig); - } - - k_poll_signal_raise(&efd->read_sig, 0); - - return 0; -} - -static ssize_t eventfd_read_op(void *obj, void *buf, size_t sz) -{ - return eventfd_rw_op(obj, buf, sz, eventfd_read_locked); -} - -static ssize_t eventfd_write_op(void *obj, const void *buf, size_t sz) -{ - return eventfd_rw_op(obj, (eventfd_t *)buf, sz, eventfd_write_locked); -} - -static int eventfd_close_op(void *obj) -{ - int ret; - int err; - k_spinlock_key_t key; - struct k_mutex *lock = NULL; - struct k_condvar *cond = NULL; - struct eventfd *efd = (struct eventfd *)obj; - - if (k_is_in_isr()) { - /* not covered by the man page, but necessary in Zephyr */ - errno = EWOULDBLOCK; - return -1; - } - - err = (int)z_get_obj_lock_and_cond(obj, &eventfd_fd_vtable, &lock, &cond); - __ASSERT((bool)err, "z_get_obj_lock_and_cond() failed"); - __ASSERT_NO_MSG(lock != NULL); - __ASSERT_NO_MSG(cond != NULL); - - err = k_mutex_lock(lock, K_FOREVER); - __ASSERT(err == 0, "k_mutex_lock() failed: %d", err); - - key = k_spin_lock(&efd->lock); - - if (!eventfd_is_in_use(efd)) { - errno = EBADF; - ret = -1; - goto unlock; - } - - err = sys_bitarray_free(&efds_bitarray, 1, (struct eventfd *)obj - efds); - __ASSERT(err == 0, "sys_bitarray_free() failed: %d", err); - - efd->flags = 0; - efd->cnt = 0; - - ret = 0; - -unlock: - k_spin_unlock(&efd->lock, key); - /* when closing an eventfd, broadcast to all waiters */ - err = k_condvar_broadcast(cond); - __ASSERT(err == 0, "k_condvar_broadcast() failed: %d", err); - err = k_mutex_unlock(lock); - __ASSERT(err == 0, "k_mutex_unlock() failed: %d", err); - - return ret; -} - -static int eventfd_ioctl_op(void *obj, unsigned int request, va_list args) -{ - int ret; - k_spinlock_key_t key; - struct eventfd *efd = (struct eventfd *)obj; - - /* note: zsock_poll_internal() has already taken the mutex */ - key = k_spin_lock(&efd->lock); - - if (!eventfd_is_in_use(efd)) { - errno = EBADF; - ret = -1; - goto unlock; - } - - switch (request) { - case F_GETFL: - ret = efd->flags & EFD_FLAGS_SET_INTERNAL; - break; - - case F_SETFL: { - int flags; - - flags = va_arg(args, int); - - if (flags & ~EFD_FLAGS_SET_INTERNAL) { - errno = EINVAL; - ret = -1; - } else { - int prev_flags = efd->flags & ~EFD_FLAGS_SET_INTERNAL; - - efd->flags = flags | prev_flags; - ret = 0; - } - } break; - - case ZFD_IOCTL_POLL_PREPARE: { - struct zsock_pollfd *pfd; - struct k_poll_event **pev; - struct k_poll_event *pev_end; - - pfd = va_arg(args, struct zsock_pollfd *); - pev = va_arg(args, struct k_poll_event **); - pev_end = va_arg(args, struct k_poll_event *); - - ret = eventfd_poll_prepare(obj, pfd, pev, pev_end); - } break; - - case ZFD_IOCTL_POLL_UPDATE: { - struct zsock_pollfd *pfd; - struct k_poll_event **pev; - - pfd = va_arg(args, struct zsock_pollfd *); - pev = va_arg(args, struct k_poll_event **); - - ret = eventfd_poll_update(obj, pfd, pev); - } break; - - default: - errno = EOPNOTSUPP; - ret = -1; - break; - } - -unlock: - k_spin_unlock(&efd->lock, key); - - return ret; -} - -static const struct fd_op_vtable eventfd_fd_vtable = { - .read = eventfd_read_op, - .write = eventfd_write_op, - .close = eventfd_close_op, - .ioctl = eventfd_ioctl_op, -}; - -/* common to both eventfd_read_op() and eventfd_write_op() */ -static ssize_t eventfd_rw_op(void *obj, void *buf, size_t sz, - int (*op)(struct eventfd *efd, eventfd_t *value)) -{ - int err; - ssize_t ret; - k_spinlock_key_t key; - struct eventfd *efd = obj; - struct k_mutex *lock = NULL; - struct k_condvar *cond = NULL; - - if (sz < sizeof(eventfd_t)) { - errno = EINVAL; - return -1; - } - - if (buf == NULL) { - errno = EFAULT; - return -1; - } - - key = k_spin_lock(&efd->lock); - - if (!eventfd_is_blocking(efd)) { - /* - * Handle the non-blocking case entirely within this scope - */ - ret = op(efd, buf); - if (ret < 0) { - errno = -ret; - ret = -1; - } else { - ret = sizeof(eventfd_t); - } - - goto unlock_spin; - } - - /* - * Handle the blocking case below - */ - __ASSERT_NO_MSG(eventfd_is_blocking(efd)); - - if (k_is_in_isr()) { - /* not covered by the man page, but necessary in Zephyr */ - errno = EWOULDBLOCK; - ret = -1; - goto unlock_spin; - } - - err = (int)z_get_obj_lock_and_cond(obj, &eventfd_fd_vtable, &lock, &cond); - __ASSERT((bool)err, "z_get_obj_lock_and_cond() failed"); - __ASSERT_NO_MSG(lock != NULL); - __ASSERT_NO_MSG(cond != NULL); - - /* do not hold a spinlock when taking a mutex */ - k_spin_unlock(&efd->lock, key); - err = k_mutex_lock(lock, K_FOREVER); - __ASSERT(err == 0, "k_mutex_lock() failed: %d", err); - - while (true) { - /* retake the spinlock */ - key = k_spin_lock(&efd->lock); - - ret = op(efd, buf); - switch (ret) { - case -EAGAIN: - /* not an error in blocking mode. break and try again */ - break; - case 0: - /* success! */ - ret = sizeof(eventfd_t); - goto unlock_mutex; - default: - /* some other error */ - __ASSERT_NO_MSG(ret < 0); - errno = -ret; - ret = -1; - goto unlock_mutex; - } - - /* do not hold a spinlock when taking a mutex */ - k_spin_unlock(&efd->lock, key); - - /* wait for a write or close */ - err = k_condvar_wait(cond, lock, K_FOREVER); - __ASSERT(err == 0, "k_condvar_wait() failed: %d", err); - } - -unlock_mutex: - k_spin_unlock(&efd->lock, key); - /* only wake a single waiter */ - err = k_condvar_signal(cond); - __ASSERT(err == 0, "k_condvar_signal() failed: %d", err); - err = k_mutex_unlock(lock); - __ASSERT(err == 0, "k_mutex_unlock() failed: %d", err); - goto out; - -unlock_spin: - k_spin_unlock(&efd->lock, key); - -out: - return ret; -} - -/* - * Public-facing API - */ +#include int eventfd(unsigned int initval, int flags) { - int fd = 1; - size_t offset; - struct eventfd *efd = NULL; - - if (flags & ~EFD_FLAGS_SET_INTERNAL) { - errno = EINVAL; - return -1; - } - - if (sys_bitarray_alloc(&efds_bitarray, 1, &offset) < 0) { - errno = ENOMEM; - return -1; - } - - efd = &efds[offset]; - - fd = z_reserve_fd(); - if (fd < 0) { - sys_bitarray_free(&efds_bitarray, 1, offset); - return -1; - } - - efd->flags = EFD_IN_USE_INTERNAL | flags; - efd->cnt = initval; - - k_poll_signal_init(&efd->write_sig); - k_poll_signal_init(&efd->read_sig); - - if (initval != 0) { - k_poll_signal_raise(&efd->read_sig, 0); - } - - k_poll_signal_raise(&efd->write_sig, 0); - - z_finalize_fd(fd, efd, &eventfd_fd_vtable); - - return fd; + return zvfs_eventfd(initval, flags); } int eventfd_read(int fd, eventfd_t *value) { - int ret; - void *obj; - - obj = z_get_fd_obj(fd, &eventfd_fd_vtable, EBADF); - if (obj == NULL) { - return -1; - } - - ret = eventfd_rw_op(obj, value, sizeof(eventfd_t), eventfd_read_locked); - __ASSERT_NO_MSG(ret == -1 || ret == sizeof(eventfd_t)); - if (ret < 0) { - return -1; - } - - return 0; + return zvfs_eventfd_read(fd, value); } int eventfd_write(int fd, eventfd_t value) { - int ret; - void *obj; - - obj = z_get_fd_obj(fd, &eventfd_fd_vtable, EBADF); - if (obj == NULL) { - return -1; - } - - ret = eventfd_rw_op(obj, &value, sizeof(eventfd_t), eventfd_write_locked); - __ASSERT_NO_MSG(ret == -1 || ret == sizeof(eventfd_t)); - if (ret < 0) { - return -1; - } - - return 0; + return zvfs_eventfd_write(fd, value); } diff --git a/lib/posix/options/fd_mgmt.c b/lib/posix/options/fd_mgmt.c new file mode 100644 index 0000000000000..c1f60aca8e490 --- /dev/null +++ b/lib/posix/options/fd_mgmt.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include +#include +#include + +/* prototypes for external, not-yet-public, functions in fdtable.c or fs.c */ +int zvfs_fcntl(int fd, int cmd, va_list arg); +int zvfs_ftruncate(int fd, off_t length); +off_t zvfs_lseek(int fd, off_t offset, int whence); + +int fcntl(int fd, int cmd, ...) +{ + int ret; + va_list args; + + va_start(args, cmd); + ret = zvfs_fcntl(fd, cmd, args); + va_end(args); + + return ret; +} +#ifdef CONFIG_POSIX_FD_MGMT_ALIAS_FCNTL +FUNC_ALIAS(fcntl, _fcntl, int); +#endif /* CONFIG_POSIX_FD_MGMT_ALIAS_FCNTL */ + +int ftruncate(int fd, off_t length) +{ + return zvfs_ftruncate(fd, length); +} +#ifdef CONFIG_POSIX_FD_MGMT_ALIAS_FTRUNCATE +FUNC_ALIAS(ftruncate, _ftruncate, int); +#endif /* CONFIG_POSIX_FD_MGMT_ALIAS_FTRUNCATE */ + +off_t lseek(int fd, off_t offset, int whence) +{ + return zvfs_lseek(fd, offset, whence); +} +#ifdef CONFIG_POSIX_FD_MGMT_ALIAS_LSEEK +FUNC_ALIAS(lseek, _lseek, off_t); +#endif /* CONFIG_POSIX_FD_MGMT_ALIAS_LSEEK */ diff --git a/lib/posix/options/fs.c b/lib/posix/options/fs.c index 091a3ddccda0d..4d7f6d8301283 100644 --- a/lib/posix/options/fs.c +++ b/lib/posix/options/fs.c @@ -15,6 +15,8 @@ #include #include +int zvfs_fstat(int fd, struct stat *buf); + BUILD_ASSERT(PATH_MAX >= MAX_FILE_NAME, "PATH_MAX is less than MAX_FILE_NAME"); struct posix_fs_desc { @@ -26,7 +28,7 @@ struct posix_fs_desc { bool used; }; -static struct posix_fs_desc desc_array[CONFIG_POSIX_MAX_OPEN_FILES]; +static struct posix_fs_desc desc_array[CONFIG_POSIX_OPEN_MAX]; static struct fs_dirent fdirent; static struct dirent pdirent; @@ -39,7 +41,7 @@ static struct posix_fs_desc *posix_fs_alloc_obj(bool is_dir) struct posix_fs_desc *ptr = NULL; unsigned int key = irq_lock(); - for (i = 0; i < CONFIG_POSIX_MAX_OPEN_FILES; i++) { + for (i = 0; i < CONFIG_POSIX_OPEN_MAX; i++) { if (desc_array[i].used == false) { ptr = &desc_array[i]; ptr->used = true; @@ -80,12 +82,7 @@ static int posix_mode_to_zephyr(int mf) return mode; } -/** - * @brief Open a file. - * - * See IEEE 1003.1 - */ -int open(const char *name, int flags, ...) +int zvfs_open(const char *name, int flags) { int rc, fd; struct posix_fs_desc *ptr = NULL; @@ -123,10 +120,6 @@ int open(const char *name, int flags, ...) return fd; } -#if !defined(CONFIG_NEWLIB_LIBC) && !defined(CONFIG_PICOLIBC) -FUNC_ALIAS(open, _open, int); -#endif - static int fs_close_vmeth(void *obj) { struct posix_fs_desc *ptr = obj; @@ -161,7 +154,18 @@ static int fs_ioctl_vmeth(void *obj, unsigned int request, va_list args) } break; } + case ZFD_IOCTL_TRUNCATE: { + off_t length; + length = va_arg(args, off_t); + + rc = fs_truncate(&ptr->file, length); + if (rc < 0) { + errno = -rc; + return -1; + } + break; + } default: errno = EOPNOTSUPP; return -1; @@ -417,24 +421,10 @@ int mkdir(const char *path, mode_t mode) return 0; } -/** - * @brief Truncate file to specified length. - * - */ -int ftruncate(int fd, off_t length) +int fstat(int fildes, struct stat *buf) { - int rc; - struct posix_fs_desc *ptr = NULL; - - ptr = z_get_fd_obj(fd, NULL, EBADF); - if (!ptr) - return -1; - - rc = fs_truncate(&ptr->file, length); - if (rc < 0) { - errno = -rc; - return -1; - } - - return 0; + return zvfs_fstat(fildes, buf); } +#ifdef CONFIG_POSIX_FILE_SYSTEM_ALIAS_FSTAT +FUNC_ALIAS(fstat, _fstat, int); +#endif diff --git a/lib/posix/options/fsync.c b/lib/posix/options/fsync.c new file mode 100644 index 0000000000000..8ec28b4440dc9 --- /dev/null +++ b/lib/posix/options/fsync.c @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2024 Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* prototypes for external, not-yet-public, functions in fdtable.c */ +int zvfs_fsync(int fd); + +int fsync(int fd) +{ + return zvfs_fsync(fd); +} +#ifdef CONFIG_POSIX_FILE_SYSTEM_ALIAS_FSYNC +FUNC_ALIAS(fsync, _fsync, int); +#endif diff --git a/lib/posix/options/getentropy.c b/lib/posix/options/getentropy.c index dcc271617cbe2..974ea4dce507f 100644 --- a/lib/posix/options/getentropy.c +++ b/lib/posix/options/getentropy.c @@ -10,11 +10,11 @@ #include #include -#define ENTROPY_NODE DT_CHOSEN(zephyr_entropy) +#define ENTROPY_NODE DEVICE_DT_GET_OR_NULL(DT_CHOSEN(zephyr_entropy)) int getentropy(void *buffer, size_t length) { - const struct device * const entropy = DEVICE_DT_GET(ENTROPY_NODE); + const struct device *const entropy = ENTROPY_NODE; if (!buffer) { errno = EFAULT; @@ -26,7 +26,7 @@ int getentropy(void *buffer, size_t length) return -1; } - if (!device_is_ready(entropy)) { + if (entropy == NULL || !device_is_ready(entropy)) { errno = EIO; return -1; } diff --git a/lib/posix/options/getopt/CMakeLists.txt b/lib/posix/options/getopt/CMakeLists.txt deleted file mode 100644 index 642e3b9949b5a..0000000000000 --- a/lib/posix/options/getopt/CMakeLists.txt +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) 2021 Nordic Semiconductor -# -# SPDX-License-Identifier: Apache-2.0 -# - -zephyr_include_directories_ifdef( - CONFIG_GETOPT - . -) - -zephyr_sources_ifdef( - CONFIG_GETOPT - getopt.c - getopt_common.c -) - -zephyr_sources_ifdef( - CONFIG_GETOPT_LONG - getopt_long.c -) diff --git a/lib/posix/options/getopt/Kconfig b/lib/posix/options/getopt/Kconfig deleted file mode 100644 index 72c9961fb9041..0000000000000 --- a/lib/posix/options/getopt/Kconfig +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2021 Nordic Semiconductor -# SPDX-License-Identifier: Apache-2.0 - - -menuconfig GETOPT - bool "Getopt library support" - default y if POSIX_API - help - This option adds support of getopt. - Different shell backends are use their own instance of getopt to - not interfere with each other. - All not shell threads share one global instance of getopt state, hence - apart from shell this library is not thread safe. User can add support - for other threads by extending function getopt_state_get in - getopt_common.c file. - This option enables the following function: getopt. - -config GETOPT_LONG - bool "Getopt long library support" - depends on GETOPT - help - This option adds support of the getopt long. - Different shell backends are using their own instance of getopt to - not interfere with each other. - All not shell threads share one global instance of getopt state, hence - apart from shell this library is not thread safe. User can add support - for other threads by extending function getopt_state_get in - getopt_common.c file. diff --git a/lib/posix/options/getopt/getopt.h b/lib/posix/options/getopt/getopt.h index 4dfcc8b5f57b1..666c5541c635c 100644 --- a/lib/posix/options/getopt/getopt.h +++ b/lib/posix/options/getopt/getopt.h @@ -29,6 +29,10 @@ struct getopt_state { }; extern int optreset; /* reset getopt */ +extern char *optarg; +extern int opterr; +extern int optind; +extern int optopt; #define no_argument 0 #define required_argument 1 @@ -48,7 +52,7 @@ struct option { int val; }; -/* Function intializes getopt_state structure for current thread */ +/* Function initializes getopt_state structure for current thread */ void getopt_init(void); /* Function returns getopt_state structure for the current thread. */ diff --git a/lib/posix/options/key.c b/lib/posix/options/key.c index 5e68381c53b39..a7906b8d9f7ce 100644 --- a/lib/posix/options/key.c +++ b/lib/posix/options/key.c @@ -29,11 +29,11 @@ static struct k_spinlock pthread_key_lock; * perspective of the application). With a linear space, this means that * the theoretical pthread_key_t range is [0,2147483647]. */ -BUILD_ASSERT(CONFIG_MAX_PTHREAD_KEY_COUNT < PTHREAD_OBJ_MASK_INIT, +BUILD_ASSERT(CONFIG_POSIX_THREAD_KEYS_MAX < PTHREAD_OBJ_MASK_INIT, "CONFIG_MAX_PTHREAD_KEY_COUNT is too high"); -static pthread_key_obj posix_key_pool[CONFIG_MAX_PTHREAD_KEY_COUNT]; -SYS_BITARRAY_DEFINE_STATIC(posix_key_bitarray, CONFIG_MAX_PTHREAD_KEY_COUNT); +static pthread_key_obj posix_key_pool[CONFIG_POSIX_THREAD_KEYS_MAX]; +SYS_BITARRAY_DEFINE_STATIC(posix_key_bitarray, CONFIG_POSIX_THREAD_KEYS_MAX); static inline size_t posix_key_to_offset(pthread_key_obj *k) { diff --git a/lib/posix/options/mlock.c b/lib/posix/options/mlock.c new file mode 100644 index 0000000000000..b81773c3a5711 --- /dev/null +++ b/lib/posix/options/mlock.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include + +int mlock(const void *addr, size_t len) +{ + k_mem_pin(addr, len); + + return 0; +} + +int munlock(const void *addr, size_t len) +{ + k_mem_unpin(addr, len); + + return 0; +} diff --git a/lib/posix/options/mlockall.c b/lib/posix/options/mlockall.c new file mode 100644 index 0000000000000..e921b9325352b --- /dev/null +++ b/lib/posix/options/mlockall.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +int mlockall(int flags) +{ + ARG_UNUSED(flags); + + errno = ENOSYS; + return -1; +} + +int munlockall(void) +{ + errno = ENOSYS; + return -1; +} diff --git a/lib/posix/options/mmap.c b/lib/posix/options/mmap.c new file mode 100644 index 0000000000000..dae56a960e860 --- /dev/null +++ b/lib/posix/options/mmap.c @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define _page_size COND_CODE_1(CONFIG_MMU, (CONFIG_MMU_PAGE_SIZE), (PAGE_SIZE)) + +int zvfs_ioctl(int fd, int cmd, va_list args); + +static int p2z(int prot, int pflags) +{ + bool rw = (prot & PROT_WRITE) != 0; + bool ex = (prot & PROT_EXEC) != 0; + bool fixed = (pflags & MAP_FIXED) != 0; + bool shared = (pflags & MAP_SHARED) != 0; + bool private = (pflags & MAP_PRIVATE) != 0; + + if (!(shared ^ private)) { + return -1; + } + + return (rw * K_MEM_PERM_RW) | (ex * K_MEM_PERM_EXEC) | (fixed * K_MEM_DIRECT_MAP); +} + +static inline int zvfs_ioctl_wrap(int fd, int cmd, ...) +{ + int ret; + va_list args; + + va_start(args, cmd); + ret = zvfs_ioctl(fd, cmd, args); + va_end(args); + + return ret; +} + +void *mmap(void *addr, size_t len, int prot, int flags, int fd, off_t off) +{ + void *virt; + uintptr_t phys; + int zflags = p2z(prot, flags); + + if ((len == 0) || (zflags == -1)) { + errno = EINVAL; + return MAP_FAILED; + } + + if ((flags & MAP_ANONYMOUS) != 0) { + /* force behaviour to be in-line with Linux, fd is ignored */ + fd = -1; + } + + if (fd > 0) { + /* non-anonymous mapping */ + virt = NULL; + if (zvfs_ioctl_wrap(fd, ZFD_IOCTL_MMAP, addr, len, prot, flags, off, &virt) < 0) { + return MAP_FAILED; + } + + return virt; + } + + if (!IS_ENABLED(CONFIG_MMU)) { + errno = ENOTSUP; + return MAP_FAILED; + } + + if ((flags & MAP_FIXED) == 0) { + /* anonymous mapping */ + virt = k_mem_map(len, zflags); + } else { + /* a physical mapping. Care should be taken not to map the same page twice */ + virt = NULL; + phys = POINTER_TO_UINT(addr); + k_mem_map_phys_bare((uint8_t **)&virt, phys, (size_t)ROUND_UP(len, _page_size), + zflags); + } + + if (virt == NULL) { + errno = ENOMEM; + return MAP_FAILED; + } + + return virt; +} + +int msync(void *addr, size_t length, int flags) +{ + ARG_UNUSED(addr); + ARG_UNUSED(length); + ARG_UNUSED(flags); + + return 0; +} + +int munmap(void *addr, size_t len) +{ + if (len == 0) { + errno = EINVAL; + return -1; + } + + if (!IS_ENABLED(CONFIG_MMU)) { + /* cannot munmap without an MPU */ + errno = ENOTSUP; + return -1; + } + + uintptr_t phys = 0; + + if (arch_page_phys_get(addr, &phys) == 0) { + k_mem_unmap(addr, ROUND_UP(len, _page_size)); + } + + return 0; +} diff --git a/lib/posix/options/mprotect.c b/lib/posix/options/mprotect.c new file mode 100644 index 0000000000000..3bd2762763af3 --- /dev/null +++ b/lib/posix/options/mprotect.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include + +int mprotect(void *addr, size_t len, int prot) +{ + ARG_UNUSED(addr); + ARG_UNUSED(len); + ARG_UNUSED(prot); + + errno = ENOSYS; + return -1; +} diff --git a/lib/posix/options/mqueue.c b/lib/posix/options/mqueue.c index ca8e54744889c..ce77283e63782 100644 --- a/lib/posix/options/mqueue.c +++ b/lib/posix/options/mqueue.c @@ -118,7 +118,7 @@ mqd_t mq_open(const char *name, int oflags, ...) /* Check for message quantity and size in message queue */ if (attrs->mq_msgsize > CONFIG_MSG_SIZE_MAX && - attrs->mq_maxmsg > CONFIG_MSG_COUNT_MAX) { + attrs->mq_maxmsg > CONFIG_POSIX_MQ_OPEN_MAX) { goto free_mq_desc; } diff --git a/lib/posix/options/multi_process.c b/lib/posix/options/multi_process.c new file mode 100644 index 0000000000000..221dc04ae1ad9 --- /dev/null +++ b/lib/posix/options/multi_process.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +pid_t getpid(void) +{ + /* + * To maintain compatibility with some other POSIX operating systems, + * a PID of zero is used to indicate that the process exists in another namespace. + * PID zero is also used by the scheduler in some cases. + * PID one is usually reserved for the init process. + * Also note, that negative PIDs may be used by kill() + * to send signals to process groups in some implementations. + * + * At the moment, getpid just returns an arbitrary number >= 2 + */ + + return 42; +} diff --git a/lib/posix/options/nanosleep.c b/lib/posix/options/nanosleep.c deleted file mode 100644 index aafb9dbeb7993..0000000000000 --- a/lib/posix/options/nanosleep.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2018 Friedt Professional Engineering Services, Inc - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -/* required for struct timespec */ -#include -#include -#include - -/** - * @brief Suspend execution for nanosecond intervals. - * - * See IEEE 1003.1 - */ -int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) -{ - return clock_nanosleep(CLOCK_MONOTONIC, 0, rqtp, rmtp); -} diff --git a/lib/posix/options/net.c b/lib/posix/options/net.c index 5fcfdca464c8e..84e4001a9b40d 100644 --- a/lib/posix/options/net.c +++ b/lib/posix/options/net.c @@ -13,8 +13,6 @@ #include #include #include -#include -#include #include /* From arpa/inet.h */ @@ -102,11 +100,6 @@ char *if_indextoname(unsigned int ifindex, char *ifname) { int ret; - if (!IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { - errno = ENOTSUP; - return NULL; - } - ret = net_if_get_name(net_if_get_by_index(ifindex), ifname, IF_NAMESIZE); if (ret < 0) { errno = ENXIO; @@ -120,14 +113,14 @@ void if_freenameindex(struct if_nameindex *ptr) { size_t n; - if (ptr == NULL || !IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { + if (ptr == NULL) { return; } NET_IFACE_COUNT(&n); for (size_t i = 0; i < n; ++i) { - if (IS_ENABLED(CONFIG_NET_INTERFACE_NAME) && ptr[i].if_name != NULL) { + if (ptr[i].if_name != NULL) { free(ptr[i].if_name); } } @@ -141,11 +134,6 @@ struct if_nameindex *if_nameindex(void) char *name; struct if_nameindex *ni; - if (!IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { - errno = ENOTSUP; - return NULL; - } - /* FIXME: would be nice to use this without malloc */ NET_IFACE_COUNT(&n); ni = malloc((n + 1) * sizeof(*ni)); @@ -181,10 +169,6 @@ unsigned int if_nametoindex(const char *ifname) { int ret; - if (!IS_ENABLED(CONFIG_NET_INTERFACE_NAME)) { - return 0; - } - ret = net_if_get_by_name(ifname); if (ret < 0) { return 0; @@ -355,11 +339,6 @@ int listen(int sock, int backlog) return zsock_listen(sock, backlog); } -int poll(struct pollfd *fds, int nfds, int timeout) -{ - return zsock_poll(fds, nfds, timeout); -} - ssize_t recv(int sock, void *buf, size_t max_len, int flags) { return zsock_recv(sock, buf, max_len, flags); @@ -376,11 +355,6 @@ ssize_t recvmsg(int sock, struct msghdr *msg, int flags) return zsock_recvmsg(sock, msg, flags); } -int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout) -{ - return zsock_select(nfds, readfds, writefds, exceptfds, (struct zsock_timeval *)timeout); -} - ssize_t send(int sock, const void *buf, size_t len, int flags) { return zsock_send(sock, buf, len, flags); diff --git a/lib/posix/options/posix_clock.h b/lib/posix/options/posix_clock.h index a665f4ce06d90..f505dbc175271 100644 --- a/lib/posix/options/posix_clock.h +++ b/lib/posix/options/posix_clock.h @@ -14,6 +14,6 @@ __syscall int __posix_clock_get_base(clockid_t clock_id, struct timespec *ts); -#include +#include #endif diff --git a/lib/posix/options/pthread.c b/lib/posix/options/pthread.c index a46cde7614cbe..d9748c64637a7 100644 --- a/lib/posix/options/pthread.c +++ b/lib/posix/options/pthread.c @@ -86,7 +86,7 @@ static sys_dlist_t posix_thread_q[] = { SYS_DLIST_STATIC_INIT(&posix_thread_q[POSIX_THREAD_RUN_Q]), SYS_DLIST_STATIC_INIT(&posix_thread_q[POSIX_THREAD_DONE_Q]), }; -static struct posix_thread posix_thread_pool[CONFIG_MAX_PTHREAD_COUNT]; +static struct posix_thread posix_thread_pool[CONFIG_POSIX_THREAD_THREADS_MAX]; static struct k_spinlock pthread_pool_lock; static int pthread_concurrency; @@ -123,8 +123,8 @@ static inline enum posix_thread_qid posix_thread_q_get(struct posix_thread *t) * perspective of the application). With a linear space, this means that * the theoretical pthread_t range is [0,2147483647]. */ -BUILD_ASSERT(CONFIG_MAX_PTHREAD_COUNT < PTHREAD_OBJ_MASK_INIT, - "CONFIG_MAX_PTHREAD_COUNT is too high"); +BUILD_ASSERT(CONFIG_POSIX_THREAD_THREADS_MAX < PTHREAD_OBJ_MASK_INIT, + "CONFIG_POSIX_THREAD_THREADS_MAX is too high"); static inline size_t posix_thread_to_offset(struct posix_thread *t) { @@ -148,7 +148,7 @@ struct posix_thread *to_posix_thread(pthread_t pthread) return NULL; } - if (bit >= CONFIG_MAX_PTHREAD_COUNT) { + if (bit >= ARRAY_SIZE(posix_thread_pool)) { LOG_DBG("Invalid pthread (%x)", pthread); return NULL; } @@ -188,22 +188,6 @@ int pthread_equal(pthread_t pt1, pthread_t pt2) return (pt1 == pt2); } -pid_t getpid(void) -{ - /* - * To maintain compatibility with some other POSIX operating systems, - * a PID of zero is used to indicate that the process exists in another namespace. - * PID zero is also used by the scheduler in some cases. - * PID one is usually reserved for the init process. - * Also note, that negative PIDs may be used by kill() - * to send signals to process groups in some implementations. - * - * At the moment, getpid just returns an arbitrary number >= 2 - */ - - return 42; -} - static inline void __z_pthread_cleanup_init(struct __pthread_cleanup *c, void (*routine)(void *arg), void *arg) { @@ -252,8 +236,8 @@ void __z_pthread_cleanup_pop(int execute) static bool is_posix_policy_prio_valid(int priority, int policy) { - if (priority >= sched_get_priority_min(policy) && - priority <= sched_get_priority_max(policy)) { + if (priority >= posix_sched_priority_min(policy) && + priority <= posix_sched_priority_max(policy)) { return true; } @@ -879,7 +863,7 @@ int pthread_setschedprio(pthread_t thread, int prio) int ret; int new_prio = K_LOWEST_APPLICATION_THREAD_PRIO; struct posix_thread *t = NULL; - int policy; + int policy = -1; struct sched_param param; ret = pthread_getschedparam(thread, &policy, ¶m); @@ -1375,7 +1359,7 @@ int pthread_setname_np(pthread_t thread, const char *name) k_tid_t kthread; thread = get_posix_thread_idx(thread); - if (thread >= CONFIG_MAX_PTHREAD_COUNT) { + if (thread >= ARRAY_SIZE(posix_thread_pool)) { return ESRCH; } @@ -1399,7 +1383,7 @@ int pthread_getname_np(pthread_t thread, char *name, size_t len) k_tid_t kthread; thread = get_posix_thread_idx(thread); - if (thread >= CONFIG_MAX_PTHREAD_COUNT) { + if (thread >= ARRAY_SIZE(posix_thread_pool)) { return ESRCH; } @@ -1474,10 +1458,8 @@ int pthread_sigmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT static int posix_thread_pool_init(void) { - size_t i; - - for (i = 0; i < CONFIG_MAX_PTHREAD_COUNT; ++i) { - posix_thread_q_set(&posix_thread_pool[i], POSIX_THREAD_READY_Q); + ARRAY_FOR_EACH_PTR(posix_thread_pool, th) { + posix_thread_q_set(th, POSIX_THREAD_READY_Q); } return 0; diff --git a/lib/posix/options/pthread_sched.h b/lib/posix/options/pthread_sched.h index 4a70d081f8480..f51d05a985f09 100644 --- a/lib/posix/options/pthread_sched.h +++ b/lib/posix/options/pthread_sched.h @@ -7,6 +7,7 @@ #ifndef ZEPHYR_LIB_POSIX_POSIX_PTHREAD_SCHED_H_ #define ZEPHYR_LIB_POSIX_POSIX_PTHREAD_SCHED_H_ +#include #include #include @@ -16,4 +17,27 @@ static inline bool valid_posix_policy(int policy) return policy == SCHED_FIFO || policy == SCHED_RR || policy == SCHED_OTHER; } +static inline int posix_sched_priority_min(int policy) +{ + if (!valid_posix_policy(policy)) { + errno = EINVAL; + return -1; + } + + return 0; +} + +static inline int posix_sched_priority_max(int policy) +{ + if (IS_ENABLED(CONFIG_COOP_ENABLED) && policy == SCHED_FIFO) { + return CONFIG_NUM_COOP_PRIORITIES - 1; + } else if (IS_ENABLED(CONFIG_PREEMPT_ENABLED) && + (policy == SCHED_RR || policy == SCHED_OTHER)) { + return CONFIG_NUM_PREEMPT_PRIORITIES - 1; + } + + errno = EINVAL; + return -1; +} + #endif diff --git a/lib/posix/options/rwlock.c b/lib/posix/options/rwlock.c index b8a91a03232b8..f282fc26549fe 100644 --- a/lib/posix/options/rwlock.c +++ b/lib/posix/options/rwlock.c @@ -12,7 +12,7 @@ #include #include -#define CONCURRENT_READER_LIMIT (CONFIG_MAX_PTHREAD_COUNT + 1) +#define CONCURRENT_READER_LIMIT (CONFIG_POSIX_THREAD_THREADS_MAX + 1) struct posix_rwlock { struct k_sem rd_sem; diff --git a/lib/posix/options/sched.c b/lib/posix/options/sched.c index be174d92cd64e..a37b01d0106b2 100644 --- a/lib/posix/options/sched.c +++ b/lib/posix/options/sched.c @@ -16,12 +16,7 @@ */ int sched_get_priority_min(int policy) { - if (!valid_posix_policy(policy)) { - errno = EINVAL; - return -1; - } - - return 0; + return posix_sched_priority_min(policy); } /** @@ -31,15 +26,7 @@ int sched_get_priority_min(int policy) */ int sched_get_priority_max(int policy) { - if (IS_ENABLED(CONFIG_COOP_ENABLED) && policy == SCHED_FIFO) { - return CONFIG_NUM_COOP_PRIORITIES - 1; - } else if (IS_ENABLED(CONFIG_PREEMPT_ENABLED) && - (policy == SCHED_RR || policy == SCHED_OTHER)) { - return CONFIG_NUM_PREEMPT_PRIORITIES - 1; - } - - errno = EINVAL; - return -1; + return posix_sched_priority_max(policy); } /** diff --git a/lib/posix/options/semaphore.c b/lib/posix/options/semaphore.c index 45cac48372f8d..fddad0caf6b20 100644 --- a/lib/posix/options/semaphore.c +++ b/lib/posix/options/semaphore.c @@ -120,7 +120,7 @@ int sem_getvalue(sem_t *semaphore, int *value) */ int sem_init(sem_t *semaphore, int pshared, unsigned int value) { - if (value > CONFIG_SEM_VALUE_MAX) { + if (value > CONFIG_POSIX_SEM_VALUE_MAX) { errno = EINVAL; return -1; } @@ -131,7 +131,7 @@ int sem_init(sem_t *semaphore, int pshared, unsigned int value) */ __ASSERT(pshared == 0, "pshared should be 0"); - k_sem_init(semaphore, value, CONFIG_SEM_VALUE_MAX); + k_sem_init(semaphore, value, CONFIG_POSIX_SEM_VALUE_MAX); return 0; } @@ -232,7 +232,7 @@ sem_t *sem_open(const char *name, int oflags, ...) value = va_arg(va, unsigned int); va_end(va); - if (value > CONFIG_SEM_VALUE_MAX) { + if (value > CONFIG_POSIX_SEM_VALUE_MAX) { errno = EINVAL; return (sem_t *)SEM_FAILED; } @@ -243,7 +243,7 @@ sem_t *sem_open(const char *name, int oflags, ...) } namelen = strlen(name); - if ((namelen + 1) > CONFIG_SEM_NAMELEN_MAX) { + if ((namelen + 1) > CONFIG_POSIX_SEM_NAMELEN_MAX) { errno = ENAMETOOLONG; return (sem_t *)SEM_FAILED; } @@ -291,7 +291,7 @@ sem_t *sem_open(const char *name, int oflags, ...) /* 1 for this open instance, +1 for the linked name */ nsem->ref_count = 2; - (void)k_sem_init(&nsem->sem, value, CONFIG_SEM_VALUE_MAX); + (void)k_sem_init(&nsem->sem, value, CONFIG_POSIX_SEM_VALUE_MAX); sys_slist_append(&nsem_list, (sys_snode_t *)&(nsem->snode)); @@ -318,7 +318,7 @@ int sem_unlink(const char *name) return -1; } - if ((strlen(name) + 1) > CONFIG_SEM_NAMELEN_MAX) { + if ((strlen(name) + 1) > CONFIG_POSIX_SEM_NAMELEN_MAX) { errno = ENAMETOOLONG; return -1; } diff --git a/lib/posix/options/shm.c b/lib/posix/options/shm.c new file mode 100644 index 0000000000000..d1eca540fe683 --- /dev/null +++ b/lib/posix/options/shm.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 2024, Tenstorrent AI ULC + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define _page_size COND_CODE_1(CONFIG_MMU, (CONFIG_MMU_PAGE_SIZE), (PAGE_SIZE)) + +static const struct fd_op_vtable shm_vtable; + +static sys_dlist_t shm_list = SYS_DLIST_STATIC_INIT(&shm_list); + +struct shm_obj { + uint8_t *mem; + sys_dnode_t node; + size_t refs; + size_t size; + uint32_t hash; + bool unlinked: 1; + bool mapped: 1; +}; + +static inline uint32_t hash32(const char *str, size_t n) +{ + /* we need a hasher that is not sensitive to input alignment */ + return sys_hash32_djb2(str, n); +} + +static bool shm_obj_name_valid(const char *name, size_t len) +{ + if (name == NULL) { + return false; + } + + if (name[0] != '/') { + return false; + } + + if (len < 2) { + return false; + } + + return true; +} + +static struct shm_obj *shm_obj_find(uint32_t key) +{ + struct shm_obj *shm; + + SYS_DLIST_FOR_EACH_CONTAINER(&shm_list, shm, node) { + if (shm->hash == key) { + return shm; + } + } + + return NULL; +} + +static void shm_obj_add(struct shm_obj *shm) +{ + sys_dlist_init(&shm->node); + sys_dlist_append(&shm_list, &shm->node); +} + +static void shm_obj_remove(struct shm_obj *shm) +{ + sys_dlist_remove(&shm->node); + if (shm->size > 0) { + if (IS_ENABLED(CONFIG_MMU)) { + uintptr_t phys = 0; + + if (arch_page_phys_get(shm->mem, &phys) == 0) { + k_mem_unmap(shm->mem, ROUND_UP(shm->size, _page_size)); + } + } else { + k_free(shm->mem); + } + } + k_free(shm); +} + +static int shm_fstat(struct shm_obj *shm, struct stat *st) +{ + *st = (struct stat){0}; + st->st_mode = ZVFS_MODE_IFSHM; + st->st_size = shm->size; + + return 0; +} + +static int shm_ftruncate(struct shm_obj *shm, off_t length) +{ + void *virt; + + if (length < 0) { + errno = EINVAL; + return -1; + } + + if (length == 0) { + if (shm->size != 0) { + /* only allow resizing this once, for consistence */ + errno = EBUSY; + return -1; + } + + return 0; + } + + if (IS_ENABLED(CONFIG_MMU)) { + virt = k_mem_map(ROUND_UP(length, _page_size), K_MEM_PERM_RW); + } else { + virt = k_calloc(1, length); + } + + if (virt == NULL) { + errno = ENOMEM; + return -1; + } + + shm->mem = virt; + shm->size = length; + + return 0; +} + +static off_t shm_lseek(struct shm_obj *shm, off_t offset, int whence, size_t cur) +{ + size_t addend; + + switch (whence) { + case SEEK_SET: + addend = 0; + break; + case SEEK_CUR: + addend = cur; + break; + case SEEK_END: + addend = shm->size; + break; + default: + errno = EINVAL; + return -1; + } + + if ((INTPTR_MAX - addend) < offset) { + errno = EOVERFLOW; + return -1; + } + + offset += addend; + if (offset < 0) { + errno = EINVAL; + return -1; + } + + return offset; +} + +static int shm_mmap(struct shm_obj *shm, void *addr, size_t len, int prot, int flags, off_t off, + void **virt) +{ + ARG_UNUSED(addr); + ARG_UNUSED(prot); + __ASSERT_NO_MSG(virt != NULL); + + if ((len == 0) || (off < 0) || ((flags & MAP_FIXED) != 0) || + ((off & (_page_size - 1)) != 0) || ((len + off) > shm->size)) { + errno = EINVAL; + return -1; + } + + if (!IS_ENABLED(CONFIG_MMU)) { + errno = ENOTSUP; + return -1; + } + + if (shm->mem == NULL) { + errno = ENOMEM; + return -1; + } + + /* + * Note: due to Zephyr's page mapping algorithm, physical pages can only have 1 + * mapping, so different file handles will have the same virtual memory address + * underneath. + */ + *virt = shm->mem + off; + + return 0; +} + +static ssize_t shm_rw(struct shm_obj *shm, void *buf, size_t size, bool is_write, size_t offset) +{ + if (offset >= size) { + size = 0; + } else { + size = MIN(size, shm->size - offset); + } + + if (size > 0) { + if (is_write) { + memcpy(&shm->mem[offset], buf, size); + } else { + memcpy(buf, &shm->mem[offset], size); + } + } + + return size; +} + +static ssize_t shm_read(void *obj, void *buf, size_t sz, size_t offset) +{ + return shm_rw((struct shm_obj *)obj, buf, sz, false, offset); +} + +static ssize_t shm_write(void *obj, const void *buf, size_t sz, size_t offset) +{ + return shm_rw((struct shm_obj *)obj, (void *)buf, sz, true, offset); +} + +static int shm_close(void *obj) +{ + struct shm_obj *shm = obj; + + shm->refs -= (shm->refs > 0) ? 1 : 0; + if (shm->unlinked && (shm->refs == 0)) { + shm_obj_remove(shm); + } + + return 0; +} + +static int shm_ioctl(void *obj, unsigned int request, va_list args) +{ + struct shm_obj *shm = obj; + + switch (request) { + case ZFD_IOCTL_LSEEK: { + off_t offset = va_arg(args, off_t); + int whence = va_arg(args, int); + size_t cur = va_arg(args, size_t); + + return shm_lseek(shm, offset, whence, cur); + } break; + case ZFD_IOCTL_MMAP: { + void *addr = va_arg(args, void *); + size_t len = va_arg(args, size_t); + int prot = va_arg(args, int); + int flags = va_arg(args, int); + off_t off = va_arg(args, off_t); + void **maddr = va_arg(args, void **); + + return shm_mmap(shm, addr, len, prot, flags, off, maddr); + } break; + case ZFD_IOCTL_SET_LOCK: + break; + case ZFD_IOCTL_STAT: { + struct stat *st = va_arg(args, struct stat *); + + return shm_fstat(shm, st); + } break; + case ZFD_IOCTL_TRUNCATE: { + off_t length = va_arg(args, off_t); + + return shm_ftruncate(shm, length); + } break; + default: + errno = ENOTSUP; + return -1; + } + + return 0; +} + +static const struct fd_op_vtable shm_vtable = { + .read_offs = shm_read, + .write_offs = shm_write, + .close = shm_close, + .ioctl = shm_ioctl, +}; + +int shm_open(const char *name, int oflag, mode_t mode) +{ + int fd; + uint32_t key; + struct shm_obj *shm; + bool rd = (oflag & O_RDONLY) != 0; + bool rw = (oflag & O_RDWR) != 0; + bool creat = (oflag & O_CREAT) != 0; + bool excl = (oflag & O_EXCL) != 0; + bool trunc = false; /* (oflag & O_TRUNC) != 0 */ + size_t name_len = (name == NULL) ? 0 : strnlen(name, PATH_MAX); + + /* revisit when file-based permissions are available */ + if ((mode & 0777) == 0) { + errno = EINVAL; + return -1; + } + + if (!(rd ^ rw)) { + errno = EINVAL; + return -1; + } + + if (rd && trunc) { + errno = EINVAL; + return -1; + } + + if (!shm_obj_name_valid(name, name_len)) { + errno = EINVAL; + return -1; + } + + fd = z_reserve_fd(); + if (fd < 0) { + errno = EMFILE; + return -1; + } + + key = hash32(name, name_len); + shm = shm_obj_find(key); + if ((shm != NULL) && shm->unlinked) { + /* we cannot open a shm object that has already been unlinked */ + errno = EACCES; + return -1; + } + + if (creat) { + if ((shm != NULL) && excl) { + z_free_fd(fd); + errno = EEXIST; + return -1; + } + + if (shm == NULL) { + shm = k_calloc(1, sizeof(*shm)); + if (shm == NULL) { + z_free_fd(fd); + errno = ENOSPC; + return -1; + } + + shm->hash = key; + shm_obj_add(shm); + } + } else if (shm == NULL) { + errno = ENOENT; + return -1; + } + + ++shm->refs; + z_finalize_typed_fd(fd, shm, &shm_vtable, ZVFS_MODE_IFSHM); + + return fd; +} + +int shm_unlink(const char *name) +{ + uint32_t key; + struct shm_obj *shm; + size_t name_len = (name == NULL) ? 0 : strnlen(name, PATH_MAX); + + if (!shm_obj_name_valid(name, name_len)) { + errno = EINVAL; + return -1; + } + + key = hash32(name, name_len); + shm = shm_obj_find(key); + if ((shm == NULL) || shm->unlinked) { + errno = ENOENT; + return -1; + } + + shm->unlinked = true; + if (shm->refs == 0) { + shm_obj_remove(shm); + } + + return 0; +} diff --git a/lib/posix/options/signal.c b/lib/posix/options/signal.c index f14ef7fe614f9..d0674aea94b4d 100644 --- a/lib/posix/options/signal.c +++ b/lib/posix/options/signal.c @@ -8,13 +8,13 @@ #include #include +#include #include #define SIGNO_WORD_IDX(_signo) (signo / BITS_PER_LONG) #define SIGNO_WORD_BIT(_signo) (signo & BIT_MASK(LOG2(BITS_PER_LONG))) -BUILD_ASSERT(CONFIG_POSIX_LIMITS_RTSIG_MAX >= 0); -BUILD_ASSERT(CONFIG_POSIX_RTSIG_MAX >= CONFIG_POSIX_LIMITS_RTSIG_MAX); +BUILD_ASSERT(CONFIG_POSIX_RTSIG_MAX >= 0); static inline bool signo_valid(int signo) { diff --git a/lib/posix/options/sleep.c b/lib/posix/options/sleep.c index 98fff715dda5f..dd739322c75ee 100644 --- a/lib/posix/options/sleep.c +++ b/lib/posix/options/sleep.c @@ -23,27 +23,3 @@ unsigned sleep(unsigned int seconds) return rem / MSEC_PER_SEC; } -/** - * @brief Suspend execution for microsecond intervals. - * - * See IEEE 1003.1 - */ -int usleep(useconds_t useconds) -{ - int32_t rem; - - if (useconds >= USEC_PER_SEC) { - errno = EINVAL; - return -1; - } - - rem = k_usleep(useconds); - __ASSERT_NO_MSG(rem >= 0); - if (rem > 0) { - /* sleep was interrupted by a call to k_wakeup() */ - errno = EINTR; - return -1; - } - - return 0; -} diff --git a/lib/posix/options/stropts.c b/lib/posix/options/stropts.c index c1e6c9f54eda3..61d5e6abf5d68 100644 --- a/lib/posix/options/stropts.c +++ b/lib/posix/options/stropts.c @@ -4,9 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include #include +#include + #include +#include int putmsg(int fildes, const struct strbuf *ctlptr, const struct strbuf *dataptr, int flags) { @@ -19,6 +21,19 @@ int putmsg(int fildes, const struct strbuf *ctlptr, const struct strbuf *dataptr return -1; } +int putpmsg(int fildes, const struct strbuf *ctlptr, const struct strbuf *dataptr, int band, + int flags) +{ + ARG_UNUSED(fildes); + ARG_UNUSED(ctlptr); + ARG_UNUSED(dataptr); + ARG_UNUSED(band); + ARG_UNUSED(flags); + + errno = ENOSYS; + return -1; +} + int fdetach(const char *path) { ARG_UNUSED(path); @@ -66,3 +81,17 @@ int isastream(int fildes) errno = ENOSYS; return -1; } + +extern int zvfs_ioctl(int fd, unsigned long request, va_list args); + +int ioctl(int fd, unsigned long request, ...) +{ + int ret; + va_list args; + + va_start(args, request); + ret = zvfs_ioctl(fd, request, args); + va_end(args); + + return ret; +} diff --git a/lib/posix/options/sysconf.c b/lib/posix/options/sysconf.c index 78491bd6eb019..5d3492918fb40 100644 --- a/lib/posix/options/sysconf.c +++ b/lib/posix/options/sysconf.c @@ -4,263 +4,271 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include +#include #include +#ifdef CONFIG_POSIX_SYSCONF_IMPL_FULL + +#define z_sysconf(x) (long)CONCAT(__z_posix_sysconf, x) + long sysconf(int x) { switch (x) { case _SC_ADVISORY_INFO: - return _POSIX_ADVISORY_INFO; + return z_sysconf(_SC_ADVISORY_INFO); case _SC_ASYNCHRONOUS_IO: - return _POSIX_ASYNCHRONOUS_IO; + return z_sysconf(_SC_ASYNCHRONOUS_IO); case _SC_BARRIERS: - return _POSIX_BARRIERS; + return z_sysconf(_SC_BARRIERS); case _SC_CLOCK_SELECTION: - return _POSIX_CLOCK_SELECTION; + return z_sysconf(_SC_CLOCK_SELECTION); case _SC_CPUTIME: - return _POSIX_CPUTIME; + return z_sysconf(_SC_CPUTIME); case _SC_FSYNC: - return _POSIX_FSYNC; + return z_sysconf(_SC_FSYNC); case _SC_IPV6: - return _POSIX_IPV6; + return z_sysconf(_SC_IPV6); case _SC_JOB_CONTROL: - return _POSIX_JOB_CONTROL; - case _SC_MAPPED_FILE: - return _POSIX_MAPPED_FILES; + return z_sysconf(_SC_JOB_CONTROL); + case _SC_MAPPED_FILES: + return z_sysconf(_SC_MAPPED_FILES); case _SC_MEMLOCK: - return _POSIX_MEMLOCK; + return z_sysconf(_SC_MEMLOCK); case _SC_MEMLOCK_RANGE: - return _POSIX_MEMLOCK_RANGE; + return z_sysconf(_SC_MEMLOCK_RANGE); case _SC_MEMORY_PROTECTION: - return _POSIX_MEMORY_PROTECTION; + return z_sysconf(_SC_MEMORY_PROTECTION); case _SC_MESSAGE_PASSING: - return _POSIX_MESSAGE_PASSING; + return z_sysconf(_SC_MESSAGE_PASSING); case _SC_MONOTONIC_CLOCK: - return _POSIX_MONOTONIC_CLOCK; + return z_sysconf(_SC_MONOTONIC_CLOCK); case _SC_PRIORITIZED_IO: - return _POSIX_PRIORITIZED_IO; + return z_sysconf(_SC_PRIORITIZED_IO); case _SC_PRIORITY_SCHEDULING: - return _POSIX_PRIORITY_SCHEDULING; + return z_sysconf(_SC_PRIORITY_SCHEDULING); case _SC_RAW_SOCKETS: - return _POSIX_RAW_SOCKETS; + return z_sysconf(_SC_RAW_SOCKETS); case _SC_RE_DUP_MAX: - return _POSIX_RE_DUP_MAX; + return z_sysconf(_SC_RE_DUP_MAX); case _SC_READER_WRITER_LOCKS: - return _POSIX_READER_WRITER_LOCKS; + return z_sysconf(_SC_READER_WRITER_LOCKS); case _SC_REALTIME_SIGNALS: - return _POSIX_REALTIME_SIGNALS; + return z_sysconf(_SC_REALTIME_SIGNALS); case _SC_REGEXP: - return _POSIX_REGEXP; + return z_sysconf(_SC_REGEXP); case _SC_SAVED_IDS: - return _POSIX_SAVED_IDS; + return z_sysconf(_SC_SAVED_IDS); case _SC_SEMAPHORES: - return _POSIX_SEMAPHORES; + return z_sysconf(_SC_SEMAPHORES); case _SC_SHARED_MEMORY_OBJECTS: - return _POSIX_SHARED_MEMORY_OBJECTS; + return z_sysconf(_SC_SHARED_MEMORY_OBJECTS); case _SC_SHELL: - return _POSIX_SHELL; + return z_sysconf(_SC_SHELL); case _SC_SPAWN: - return _POSIX_SPAWN; + return z_sysconf(_SC_SPAWN); case _SC_SPIN_LOCKS: - return _POSIX_SPIN_LOCKS; + return z_sysconf(_SC_SPIN_LOCKS); case _SC_SPORADIC_SERVER: - return _POSIX_SPORADIC_SERVER; + return z_sysconf(_SC_SPORADIC_SERVER); case _SC_SS_REPL_MAX: - return _POSIX_SS_REPL_MAX; + return z_sysconf(_SC_SS_REPL_MAX); case _SC_SYNCHRONIZED_IO: - return _POSIX_SYNCHRONIZED_IO; + return z_sysconf(_SC_SYNCHRONIZED_IO); case _SC_THREAD_ATTR_STACKADDR: - return _POSIX_THREAD_ATTR_STACKADDR; + return z_sysconf(_SC_THREAD_ATTR_STACKADDR); case _SC_THREAD_ATTR_STACKSIZE: - return _POSIX_THREAD_ATTR_STACKSIZE; + return z_sysconf(_SC_THREAD_ATTR_STACKSIZE); case _SC_THREAD_CPUTIME: - return _POSIX_THREAD_CPUTIME; + return z_sysconf(_SC_THREAD_CPUTIME); case _SC_THREAD_PRIO_INHERIT: - return _POSIX_THREAD_PRIO_INHERIT; + return z_sysconf(_SC_THREAD_PRIO_INHERIT); case _SC_THREAD_PRIO_PROTECT: - return _POSIX_THREAD_PRIO_PROTECT; + return z_sysconf(_SC_THREAD_PRIO_PROTECT); case _SC_THREAD_PRIORITY_SCHEDULING: - return _POSIX_THREAD_PRIORITY_SCHEDULING; + return z_sysconf(_SC_THREAD_PRIORITY_SCHEDULING); case _SC_THREAD_PROCESS_SHARED: - return _POSIX_THREAD_PROCESS_SHARED; + return z_sysconf(_SC_THREAD_PROCESS_SHARED); case _SC_THREAD_ROBUST_PRIO_INHERIT: - return _POSIX_THREAD_ROBUST_PRIO_INHERIT; + return z_sysconf(_SC_THREAD_ROBUST_PRIO_INHERIT); case _SC_THREAD_ROBUST_PRIO_PROTECT: - return _POSIX_THREAD_ROBUST_PRIO_PROTECT; + return z_sysconf(_SC_THREAD_ROBUST_PRIO_PROTECT); case _SC_THREAD_SAFE_FUNCTIONS: - return _POSIX_THREAD_SAFE_FUNCTIONS; + return z_sysconf(_SC_THREAD_SAFE_FUNCTIONS); case _SC_THREAD_SPORADIC_SERVER: - return _POSIX_THREAD_SPORADIC_SERVER; + return z_sysconf(_SC_THREAD_SPORADIC_SERVER); case _SC_THREADS: - return _POSIX_THREADS; + return z_sysconf(_SC_THREADS); case _SC_TIMEOUTS: - return _POSIX_TIMEOUTS; + return z_sysconf(_SC_TIMEOUTS); case _SC_TIMERS: - return _POSIX_TIMERS; + return z_sysconf(_SC_TIMERS); case _SC_TRACE: - return _POSIX_TRACE; + return z_sysconf(_SC_TRACE); case _SC_TRACE_EVENT_FILTER: - return _POSIX_TRACE_EVENT_FILTER; + return z_sysconf(_SC_TRACE_EVENT_FILTER); case _SC_TRACE_EVENT_NAME_MAX: - return _POSIX_TRACE_EVENT_NAME_MAX; + return z_sysconf(_SC_TRACE_EVENT_NAME_MAX); case _SC_TRACE_INHERIT: - return _POSIX_TRACE_INHERIT; + return z_sysconf(_SC_TRACE_INHERIT); case _SC_TRACE_LOG: - return _POSIX_TRACE_LOG; + return z_sysconf(_SC_TRACE_LOG); case _SC_TRACE_NAME_MAX: - return _POSIX_TRACE_NAME_MAX; + return z_sysconf(_SC_TRACE_NAME_MAX); case _SC_TRACE_SYS_MAX: - return _POSIX_TRACE_SYS_MAX; + return z_sysconf(_SC_TRACE_SYS_MAX); case _SC_TRACE_USER_EVENT_MAX: - return _POSIX_TRACE_USER_EVENT_MAX; + return z_sysconf(_SC_TRACE_USER_EVENT_MAX); case _SC_TYPED_MEMORY_OBJECTS: - return _POSIX_TYPED_MEMORY_OBJECTS; + return z_sysconf(_SC_TYPED_MEMORY_OBJECTS); case _SC_VERSION: - return _POSIX_VERSION; - case _SC_V7_ILP32_OFF32: - return _POSIX_V7_ILP32_OFF32; - case _SC_V7_ILP32_OFFBIG: - return _POSIX_V7_ILP32_OFFBIG; - case _SC_V7_LP64_OFF64: - return _POSIX_V7_LP64_OFF64; - case _SC_V7_LPBIG_OFFBIG: - return _POSIX_V7_LPBIG_OFFBIG; + return z_sysconf(_SC_VERSION); case _SC_V6_ILP32_OFF32: - return _POSIX_V6_ILP32_OFF32; + return z_sysconf(_SC_V6_ILP32_OFF32); case _SC_V6_ILP32_OFFBIG: - return _POSIX_V6_ILP32_OFFBIG; + return z_sysconf(_SC_V6_ILP32_OFFBIG); case _SC_V6_LP64_OFF64: - return _POSIX_V6_LP64_OFF64; + return z_sysconf(_SC_V6_LP64_OFF64); case _SC_V6_LPBIG_OFFBIG: - return _POSIX_V6_LPBIG_OFFBIG; + return z_sysconf(_SC_V6_LPBIG_OFFBIG); + case _SC_V7_ILP32_OFF32: + return z_sysconf(_SC_V7_ILP32_OFF32); + case _SC_V7_ILP32_OFFBIG: + return z_sysconf(_SC_V7_ILP32_OFFBIG); + case _SC_V7_LP64_OFF64: + return z_sysconf(_SC_V7_LP64_OFF64); + case _SC_V7_LPBIG_OFFBIG: + return z_sysconf(_SC_V7_LPBIG_OFFBIG); case _SC_BC_BASE_MAX: - return _POSIX2_BC_BASE_MAX; + return z_sysconf(_SC_BC_BASE_MAX); case _SC_BC_DIM_MAX: - return _POSIX2_BC_DIM_MAX; + return z_sysconf(_SC_BC_DIM_MAX); case _SC_BC_SCALE_MAX: - return _POSIX2_BC_SCALE_MAX; + return z_sysconf(_SC_BC_SCALE_MAX); case _SC_BC_STRING_MAX: - return _POSIX2_BC_STRING_MAX; + return z_sysconf(_SC_BC_STRING_MAX); case _SC_2_C_BIND: - return _POSIX2_C_BIND; + return z_sysconf(_SC_2_C_BIND); case _SC_2_C_DEV: - return _POSIX2_C_DEV; + return z_sysconf(_SC_2_C_DEV); case _SC_2_CHAR_TERM: - return _POSIX2_CHAR_TERM; + return z_sysconf(_SC_2_CHAR_TERM); case _SC_COLL_WEIGHTS_MAX: - return _POSIX2_COLL_WEIGHTS_MAX; + return z_sysconf(_SC_COLL_WEIGHTS_MAX); case _SC_DELAYTIMER_MAX: - return _POSIX2_DELAYTIMER_MAX; + return z_sysconf(_SC_DELAYTIMER_MAX); case _SC_EXPR_NEST_MAX: - return _POSIX2_EXPR_NEST_MAX; + return z_sysconf(_SC_EXPR_NEST_MAX); case _SC_2_FORT_DEV: - return _POSIX2_FORT_DEV; + return z_sysconf(_SC_2_FORT_DEV); case _SC_2_FORT_RUN: - return _POSIX2_FORT_RUN; + return z_sysconf(_SC_2_FORT_RUN); case _SC_LINE_MAX: - return _POSIX2_LINE_MAX; + return z_sysconf(_SC_LINE_MAX); case _SC_2_LOCALEDEF: - return _POSIX2_LOCALEDEF; + return z_sysconf(_SC_2_LOCALEDEF); case _SC_2_PBS: - return _POSIX2_PBS; + return z_sysconf(_SC_2_PBS); case _SC_2_PBS_ACCOUNTING: - return _POSIX2_PBS_ACCOUNTING; + return z_sysconf(_SC_2_PBS_ACCOUNTING); case _SC_2_PBS_CHECKPOINT: - return _POSIX2_PBS_CHECKPOINT; + return z_sysconf(_SC_2_PBS_CHECKPOINT); case _SC_2_PBS_LOCATE: - return _POSIX2_PBS_LOCATE; + return z_sysconf(_SC_2_PBS_LOCATE); case _SC_2_PBS_MESSAGE: - return _POSIX2_PBS_MESSAGE; + return z_sysconf(_SC_2_PBS_MESSAGE); case _SC_2_PBS_TRACK: - return _POSIX2_PBS_TRACK; + return z_sysconf(_SC_2_PBS_TRACK); case _SC_2_SW_DEV: - return _POSIX2_SW_DEV; + return z_sysconf(_SC_2_SW_DEV); case _SC_2_UPE: - return _POSIX2_UPE; + return z_sysconf(_SC_2_UPE); case _SC_2_VERSION: - return _POSIX2_VERSION; + return z_sysconf(_SC_2_VERSION); case _SC_XOPEN_CRYPT: - return _XOPEN_CRYPT; + return z_sysconf(_SC_XOPEN_CRYPT); case _SC_XOPEN_ENH_I18N: - return _XOPEN_ENH_I18N; + return z_sysconf(_SC_XOPEN_ENH_I18N); case _SC_XOPEN_REALTIME: - return _XOPEN_REALTIME; + return z_sysconf(_SC_XOPEN_REALTIME); case _SC_XOPEN_REALTIME_THREADS: - return _XOPEN_REALTIME_THREADS; + return z_sysconf(_SC_XOPEN_REALTIME_THREADS); case _SC_XOPEN_SHM: - return _XOPEN_SHM; + return z_sysconf(_SC_XOPEN_SHM); case _SC_XOPEN_STREAMS: - return _XOPEN_STREAMS; + return z_sysconf(_SC_XOPEN_STREAMS); case _SC_XOPEN_UNIX: - return _XOPEN_UNIX; + return z_sysconf(_SC_XOPEN_UNIX); case _SC_XOPEN_UUCP: - return _XOPEN_UUCP; + return z_sysconf(_SC_XOPEN_UUCP); case _SC_XOPEN_VERSION: - return _XOPEN_VERSION; + return z_sysconf(_SC_XOPEN_VERSION); case _SC_CLK_TCK: - return (100L); + return z_sysconf(_SC_CLK_TCK); case _SC_GETGR_R_SIZE_MAX: - return (0L); + return z_sysconf(_SC_GETGR_R_SIZE_MAX); case _SC_GETPW_R_SIZE_MAX: - return (0L); + return z_sysconf(_SC_GETPW_R_SIZE_MAX); case _SC_AIO_LISTIO_MAX: - return AIO_LISTIO_MAX; + return z_sysconf(_SC_AIO_LISTIO_MAX); case _SC_AIO_MAX: - return AIO_MAX; + return z_sysconf(_SC_AIO_MAX); case _SC_AIO_PRIO_DELTA_MAX: - return AIO_PRIO_DELTA_MAX; + return z_sysconf(_SC_AIO_PRIO_DELTA_MAX); case _SC_ARG_MAX: - return ARG_MAX; + return z_sysconf(_SC_ARG_MAX); case _SC_ATEXIT_MAX: - return ATEXIT_MAX; + return z_sysconf(_SC_ATEXIT_MAX); case _SC_CHILD_MAX: - return CHILD_MAX; + return z_sysconf(_SC_CHILD_MAX); case _SC_HOST_NAME_MAX: - return _POSIX_HOST_NAME_MAX; + return z_sysconf(_SC_HOST_NAME_MAX); case _SC_IOV_MAX: - return IOV_MAX; + return z_sysconf(_SC_IOV_MAX); case _SC_LOGIN_NAME_MAX: - return LOGIN_NAME_MAX; + return z_sysconf(_SC_LOGIN_NAME_MAX); case _SC_NGROUPS_MAX: - return _POSIX_NGROUPS_MAX; + return z_sysconf(_SC_NGROUPS_MAX); case _SC_MQ_OPEN_MAX: - return MQ_OPEN_MAX; + return z_sysconf(_SC_MQ_OPEN_MAX); case _SC_MQ_PRIO_MAX: - return MQ_PRIO_MAX; + return z_sysconf(_SC_MQ_PRIO_MAX); case _SC_OPEN_MAX: - return CONFIG_POSIX_MAX_FDS; + return z_sysconf(_SC_OPEN_MAX); case _SC_PAGE_SIZE: - return PAGE_SIZE; + return z_sysconf(_SC_PAGE_SIZE); case _SC_PAGESIZE: - return PAGESIZE; + return z_sysconf(_SC_PAGESIZE); case _SC_THREAD_DESTRUCTOR_ITERATIONS: - return PTHREAD_DESTRUCTOR_ITERATIONS; + return z_sysconf(_SC_THREAD_DESTRUCTOR_ITERATIONS); case _SC_THREAD_KEYS_MAX: - return PTHREAD_KEYS_MAX; + return z_sysconf(_SC_THREAD_KEYS_MAX); case _SC_THREAD_STACK_MIN: - return PAGE_SIZE; + return z_sysconf(_SC_THREAD_STACK_MIN); case _SC_THREAD_THREADS_MAX: - return PTHREAD_THREADS_MAX; + return z_sysconf(_SC_THREAD_THREADS_MAX); case _SC_RTSIG_MAX: - return RTSIG_MAX; + return z_sysconf(_SC_RTSIG_MAX); case _SC_SEM_NSEMS_MAX: - return SEM_NSEMS_MAX; + return z_sysconf(_SC_SEM_NSEMS_MAX); case _SC_SEM_VALUE_MAX: - return SEM_VALUE_MAX; + return z_sysconf(_SC_SEM_VALUE_MAX); case _SC_SIGQUEUE_MAX: - return SIGQUEUE_MAX; + return z_sysconf(_SC_SIGQUEUE_MAX); case _SC_STREAM_MAX: - return STREAM_MAX; + return z_sysconf(_SC_STREAM_MAX); case _SC_SYMLOOP_MAX: - return SYMLOOP_MAX; + return z_sysconf(_SC_SYMLOOP_MAX); case _SC_TIMER_MAX: - return TIMER_MAX; + return z_sysconf(_SC_TIMER_MAX); case _SC_TTY_NAME_MAX: - return TTY_NAME_MAX; + return z_sysconf(_SC_TTY_NAME_MAX); case _SC_TZNAME_MAX: - return TZNAME_MAX; + return z_sysconf(_SC_TZNAME_MAX); default: errno = EINVAL; return -1; } } + +#endif /* CONFIG_POSIX_SYSCONF_IMPL_FULL */ diff --git a/lib/posix/options/timer.c b/lib/posix/options/timer.c index 7caecc180a127..d556c78133142 100644 --- a/lib/posix/options/timer.c +++ b/lib/posix/options/timer.c @@ -29,8 +29,8 @@ struct timer_obj { uint32_t status; }; -K_MEM_SLAB_DEFINE(posix_timer_slab, sizeof(struct timer_obj), - CONFIG_MAX_TIMER_COUNT, __alignof__(struct timer_obj)); +K_MEM_SLAB_DEFINE(posix_timer_slab, sizeof(struct timer_obj), CONFIG_POSIX_TIMER_MAX, + __alignof__(struct timer_obj)); static void zephyr_timer_wrapper(struct k_timer *ztimer) { @@ -306,8 +306,8 @@ int timer_getoverrun(timer_t timerid) int overruns = k_timer_status_get(&timer->ztimer) - 1; - if (overruns > CONFIG_TIMER_DELAYTIMER_MAX) { - overruns = CONFIG_TIMER_DELAYTIMER_MAX; + if (overruns > CONFIG_POSIX_DELAYTIMER_MAX) { + overruns = CONFIG_POSIX_DELAYTIMER_MAX; } return overruns; diff --git a/lib/posix/options/timespec_to_timeout.c b/lib/posix/options/timespec_to_timeout.c new file mode 100644 index 0000000000000..e72956e6e3e93 --- /dev/null +++ b/lib/posix/options/timespec_to_timeout.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +int64_t timespec_to_timeoutms(const struct timespec *abstime) +{ + int64_t milli_secs, secs, nsecs; + struct timespec curtime; + + /* FIXME: Zephyr does have CLOCK_REALTIME to get time. + * As per POSIX standard time should be calculated wrt CLOCK_REALTIME. + * Zephyr deviates from POSIX 1003.1 standard on this aspect. + */ + clock_gettime(CLOCK_MONOTONIC, &curtime); + secs = abstime->tv_sec - curtime.tv_sec; + nsecs = abstime->tv_nsec - curtime.tv_nsec; + + if (secs < 0 || (secs == 0 && nsecs < NSEC_PER_MSEC)) { + milli_secs = 0; + } else { + milli_secs = secs * MSEC_PER_SEC + nsecs / NSEC_PER_MSEC; + } + + return milli_secs; +} diff --git a/lib/posix/options/uname.c b/lib/posix/options/uname.c index eb1d9a3f4630a..decba8dd01435 100644 --- a/lib/posix/options/uname.c +++ b/lib/posix/options/uname.c @@ -4,11 +4,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "version.h" #include #include #include #include +#include #ifdef CONFIG_NET_HOSTNAME_ENABLE #define UTSNAME_NODENAME CONFIG_NET_HOSTNAME diff --git a/lib/posix/shell/Kconfig.env b/lib/posix/shell/Kconfig.env index d2d5fd53b3e97..bbe36bc9cbbb2 100644 --- a/lib/posix/shell/Kconfig.env +++ b/lib/posix/shell/Kconfig.env @@ -3,7 +3,7 @@ config POSIX_ENV_SHELL bool "Support for shell" - select POSIX_ENV + select POSIX_SINGLE_PROCESS select POSIX_SHELL help This shell provides access to system environment variables. diff --git a/lib/posix/shell/Kconfig.uname b/lib/posix/shell/Kconfig.uname index 11ea1166433a8..73547e3ac84b6 100644 --- a/lib/posix/shell/Kconfig.uname +++ b/lib/posix/shell/Kconfig.uname @@ -1,7 +1,7 @@ # Copyright (c) 2024 Meta # SPDX-License-Identifier: Apache-2.0 -if POSIX_UNAME +if POSIX_SINGLE_PROCESS config POSIX_UNAME_SHELL bool "Support for `uname` command" @@ -10,4 +10,4 @@ config POSIX_UNAME_SHELL help Support for `uname` command in the terminal. -endif # POSIX_UNAME +endif # POSIX_SINGLE_PROCESS diff --git a/lib/smf/smf.c b/lib/smf/smf.c index ecc107407440a..48c50e623ca8d 100644 --- a/lib/smf/smf.c +++ b/lib/smf/smf.c @@ -9,24 +9,22 @@ #include LOG_MODULE_REGISTER(smf); -/* - * Private structure (to this file) used to track state machine context. - * The structure is not used directly, but instead to cast the "internal" - * member of the smf_ctx structure. +/** + * @brief Private structure (to this file) used to track state machine context. + * The structure is not used directly, but instead to cast the "internal" + * member of the smf_ctx structure. */ struct internal_ctx { - bool new_state : 1; - bool terminate : 1; - bool exit : 1; - bool handled : 1; + bool new_state: 1; + bool terminate: 1; + bool is_exit: 1; + bool handled: 1; }; -static bool share_paren(const struct smf_state *test_state, - const struct smf_state *target_state) +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT +static bool share_paren(const struct smf_state *test_state, const struct smf_state *target_state) { - for (const struct smf_state *state = test_state; - state != NULL; - state = state->parent) { + for (const struct smf_state *state = test_state; state != NULL; state = state->parent) { if (target_state == state) { return true; } @@ -35,21 +33,10 @@ static bool share_paren(const struct smf_state *test_state, return false; } -static bool last_state_share_paren(struct smf_ctx *const ctx, - const struct smf_state *state) -{ - /* Get parent state of previous state */ - if (!ctx->previous) { - return false; - } - - return share_paren(ctx->previous->parent, state); -} - static const struct smf_state *get_child_of(const struct smf_state *states, const struct smf_state *parent) { - for (const struct smf_state *tmp = states; ; tmp = tmp->parent) { + for (const struct smf_state *tmp = states;; tmp = tmp->parent) { if (tmp->parent == parent) { return tmp; } @@ -68,22 +55,55 @@ static const struct smf_state *get_last_of(const struct smf_state *states) } /** - * @brief Execute all ancestor entry actions + * @brief Find the Least Common Ancestor (LCA) of two states + * + * @param source transition source + * @param dest transition destination + * @return LCA state, or NULL if states have no LCA. + */ +static const struct smf_state *get_lca_of(const struct smf_state *source, + const struct smf_state *dest) +{ + for (const struct smf_state *ancestor = source->parent; ancestor != NULL; + ancestor = ancestor->parent) { + if (ancestor == dest) { + return ancestor->parent; + } else if (share_paren(dest, ancestor)) { + return ancestor; + } + } + + return NULL; +} + +/** + * @brief Executes all entry actions from the direct child of topmost to the new state * * @param ctx State machine context - * @param target The entry actions of this target's ancestors are executed + * @param new_state State we are transitioning to + * @param topmost State we are entering from. Its entry action is not executed * @return true if the state machine should terminate, else false */ -__unused static bool smf_execute_ancestor_entry_actions( - struct smf_ctx *const ctx, const struct smf_state *target) +static bool smf_execute_all_entry_actions(struct smf_ctx *const ctx, + const struct smf_state *new_state, + const struct smf_state *topmost) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; - for (const struct smf_state *to_execute = get_last_of(target); - to_execute != NULL && to_execute != target; - to_execute = get_child_of(target, to_execute)) { - /* Execute parent state's entry */ - if (!last_state_share_paren(ctx, to_execute) && to_execute->entry) { + if (new_state == topmost) { + /* There are no child states, so do nothing */ + return false; + } + + for (const struct smf_state *to_execute = get_child_of(new_state, topmost); + to_execute != NULL && to_execute != new_state; + to_execute = get_child_of(new_state, to_execute)) { + /* Keep track of the executing entry action in case it calls + * smf_set_state() + */ + ctx->executing = to_execute; + /* Execute every entry action EXCEPT that of the topmost state */ + if (to_execute->entry) { to_execute->entry(ctx); /* No need to continue if terminate was set */ @@ -93,6 +113,17 @@ __unused static bool smf_execute_ancestor_entry_actions( } } + /* and execute the new state entry action */ + ctx->executing = new_state; + if (new_state->entry) { + new_state->entry(ctx); + + /* No need to continue if terminate was set */ + if (internal->terminate) { + return true; + } + } + return false; } @@ -103,9 +134,9 @@ __unused static bool smf_execute_ancestor_entry_actions( * @param target The run actions of this target's ancestors are executed * @return true if the state machine should terminate, else false */ -__unused static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) +static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; /* Execute all run actions in reverse order */ /* Return if the current state switched states */ @@ -126,9 +157,10 @@ __unused static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) } /* Try to run parent run actions */ - for (const struct smf_state *tmp_state = ctx->current->parent; - tmp_state != NULL; + for (const struct smf_state *tmp_state = ctx->current->parent; tmp_state != NULL; tmp_state = tmp_state->parent) { + /* Keep track of where we are in case an ancestor calls smf_set_state() */ + ctx->executing = tmp_state; /* Execute parent run action */ if (tmp_state->run) { tmp_state->run(ctx); @@ -156,39 +188,36 @@ __unused static bool smf_execute_ancestor_run_actions(struct smf_ctx *ctx) } /** - * @brief Execute all ancestor exit actions + * @brief Executes all exit actions from ctx->current to the direct child of topmost * * @param ctx State machine context - * @param target The exit actions of this target's ancestors are executed + * @param topmost State we are exiting to. Its exit action is not executed * @return true if the state machine should terminate, else false */ -__unused static bool smf_execute_ancestor_exit_actions( - struct smf_ctx *const ctx, const struct smf_state *target) +static bool smf_execute_all_exit_actions(struct smf_ctx *const ctx, const struct smf_state *topmost) { - struct internal_ctx * const internal = (void *) &ctx->internal; - - /* Execute all parent exit actions in reverse order */ + struct internal_ctx *const internal = (void *)&ctx->internal; - for (const struct smf_state *tmp_state = ctx->current->parent; - tmp_state != NULL; - tmp_state = tmp_state->parent) { - if ((target == NULL || !share_paren(target->parent, tmp_state)) && - tmp_state->exit) { - tmp_state->exit(ctx); + for (const struct smf_state *to_execute = ctx->current; + to_execute != NULL && to_execute != topmost; + to_execute = to_execute->parent) { + if (to_execute->exit) { + to_execute->exit(ctx); - /* No need to continue if terminate was set */ + /* No need to continue if terminate was set in the exit action */ if (internal->terminate) { return true; } } } + return false; } +#endif /* CONFIG_SMF_ANCESTOR_SUPPORT */ void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state) { - struct internal_ctx * const internal = (void *) &ctx->internal; - + struct internal_ctx *const internal = (void *)&ctx->internal; #ifdef CONFIG_SMF_INITIAL_TRANSITION /* @@ -199,98 +228,150 @@ void smf_set_initial(struct smf_ctx *ctx, const struct smf_state *init_state) init_state = init_state->initial; } #endif - internal->exit = false; + + internal->is_exit = false; internal->terminate = false; ctx->current = init_state; ctx->previous = NULL; ctx->terminate_val = 0; - if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) { - internal->new_state = false; +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + ctx->executing = init_state; + const struct smf_state *topmost = get_last_of(init_state); - if (smf_execute_ancestor_entry_actions(ctx, init_state)) { + /* Execute topmost state entry action, since smf_execute_all_entry_actions() + * doesn't + */ + if (topmost->entry) { + topmost->entry(ctx); + if (internal->terminate) { + /* No need to continue if terminate was set */ return; } } - /* Now execute the initial state's entry action */ + if (smf_execute_all_entry_actions(ctx, init_state, topmost)) { + /* No need to continue if terminate was set */ + return; + } +#else + /* execute entry action if it exists */ if (init_state->entry) { init_state->entry(ctx); } +#endif } -void smf_set_state(struct smf_ctx *const ctx, const struct smf_state *target) +void smf_set_state(struct smf_ctx *const ctx, const struct smf_state *new_state) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; + + if (new_state == NULL) { + LOG_ERR("new_state cannot be NULL"); + return; + } /* - * It does not make sense to call set_state in an exit phase of a state + * It does not make sense to call smf_set_state in an exit phase of a state * since we are already in a transition; we would always ignore the * intended state to transition into. */ - if (internal->exit) { - LOG_WRN("Calling %s from exit action", __func__); + if (internal->is_exit) { + LOG_ERR("Calling %s from exit action", __func__); return; } - internal->exit = true; +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + const struct smf_state *topmost; + + if (share_paren(ctx->executing, new_state)) { + /* new state is a parent of where we are now*/ + topmost = new_state; + } else if (share_paren(new_state, ctx->executing)) { + /* we are a parent of the new state */ + topmost = ctx->executing; + } else { + /* not directly related, find LCA */ + topmost = get_lca_of(ctx->executing, new_state); + } - /* Execute the current states exit action */ - if (ctx->current->exit) { - ctx->current->exit(ctx); + internal->is_exit = true; + internal->new_state = true; - /* - * No need to continue if terminate was set in the - * exit action - */ + /* call all exit actions up to (but not including) the topmost */ + if (smf_execute_all_exit_actions(ctx, topmost)) { + /* No need to continue if terminate was set in the exit action */ + return; + } + + /* if self-transition, call the exit action */ + if ((ctx->executing == new_state) && (new_state->exit)) { + new_state->exit(ctx); + + /* No need to continue if terminate was set in the exit action */ if (internal->terminate) { return; } } - if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) { - internal->new_state = true; + internal->is_exit = false; + + /* if self transition, call the entry action */ + if ((ctx->executing == new_state) && (new_state->entry)) { + new_state->entry(ctx); - if (smf_execute_ancestor_exit_actions(ctx, target)) { + /* No need to continue if terminate was set in the entry action */ + if (internal->terminate) { return; } } - - internal->exit = false; - #ifdef CONFIG_SMF_INITIAL_TRANSITION /* * The final target will be the deepest leaf state that * the target contains. Set that as the real target. */ - while (target->initial) { - target = target->initial; + while (new_state->initial) { + new_state = new_state->initial; } #endif /* update the state variables */ ctx->previous = ctx->current; - ctx->current = target; + ctx->current = new_state; - if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) { - if (smf_execute_ancestor_entry_actions(ctx, target)) { + /* call all entry actions (except those of topmost) */ + if (smf_execute_all_entry_actions(ctx, new_state, topmost)) { + /* No need to continue if terminate was set in the entry action */ + return; + } +#else + /* Flat state machines have a very simple transition: */ + if (ctx->current->exit) { + internal->is_exit = true; + ctx->current->exit(ctx); + /* No need to continue if terminate was set in the exit action */ + if (internal->terminate) { return; } + internal->is_exit = false; } + /* update the state variables */ + ctx->previous = ctx->current; + ctx->current = new_state; - /* Now execute the target entry action */ if (ctx->current->entry) { ctx->current->entry(ctx); - /* - * If terminate was set, it will be handled in the - * smf_run_state function - */ + /* No need to continue if terminate was set in the entry action */ + if (internal->terminate) { + return; + } } +#endif } void smf_set_terminate(struct smf_ctx *ctx, int32_t val) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; internal->terminate = true; ctx->terminate_val = val; @@ -305,22 +386,25 @@ void smf_set_handled(struct smf_ctx *ctx) int32_t smf_run_state(struct smf_ctx *const ctx) { - struct internal_ctx * const internal = (void *) &ctx->internal; + struct internal_ctx *const internal = (void *)&ctx->internal; /* No need to continue if terminate was set */ if (internal->terminate) { return ctx->terminate_val; } +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + ctx->executing = ctx->current; +#endif + if (ctx->current->run) { ctx->current->run(ctx); } - if (IS_ENABLED(CONFIG_SMF_ANCESTOR_SUPPORT)) { - if (smf_execute_ancestor_run_actions(ctx)) { - return ctx->terminate_val; - } +#ifdef CONFIG_SMF_ANCESTOR_SUPPORT + if (smf_execute_ancestor_run_actions(ctx)) { + return ctx->terminate_val; } - +#endif return 0; } diff --git a/lib/utils/bitarray.c b/lib/utils/bitarray.c index 7213ae201f54e..dfd7e6b9453fd 100644 --- a/lib/utils/bitarray.c +++ b/lib/utils/bitarray.c @@ -13,7 +13,7 @@ #include /* Number of bits represented by one bundle */ -#define bundle_bitness(ba) (sizeof(ba->bundles[0]) * 8) +#define bundle_bitness(ba) (sizeof((ba)->bundles[0]) * 8) struct bundle_data { /* Start and end index of bundles */ @@ -210,17 +210,124 @@ static void set_region(sys_bitarray_t *bitarray, size_t offset, } } -int sys_bitarray_set_bit(sys_bitarray_t *bitarray, size_t bit) +int sys_bitarray_popcount_region(sys_bitarray_t *bitarray, size_t num_bits, size_t offset, + size_t *count) { k_spinlock_key_t key; + size_t idx; + struct bundle_data bd; int ret; - size_t idx, off; + + __ASSERT_NO_MSG(bitarray != NULL); + __ASSERT_NO_MSG(bitarray->num_bits > 0); key = k_spin_lock(&bitarray->lock); + if (num_bits == 0 || offset + num_bits > bitarray->num_bits) { + ret = -EINVAL; + goto out; + } + + CHECKIF(count == NULL) { + ret = -EINVAL; + goto out; + } + + setup_bundle_data(bitarray, &bd, offset, num_bits); + + if (bd.sidx == bd.eidx) { + /* Start/end at same bundle */ + *count = POPCOUNT(bitarray->bundles[bd.sidx] & bd.smask); + } else { + /* Start/end at different bundle. + * So count the bits in start and end bundles + * separately with correct mask applied. For in-between bundles, + * count all bits. + */ + *count = 0; + *count += POPCOUNT(bitarray->bundles[bd.sidx] & bd.smask); + *count += POPCOUNT(bitarray->bundles[bd.eidx] & bd.emask); + for (idx = bd.sidx + 1; idx < bd.eidx; idx++) { + *count += POPCOUNT(bitarray->bundles[idx]); + } + } + + ret = 0; + +out: + k_spin_unlock(&bitarray->lock, key); + return ret; +} + +int sys_bitarray_xor(sys_bitarray_t *dst, sys_bitarray_t *other, size_t num_bits, size_t offset) +{ + k_spinlock_key_t key_dst, key_other; + int ret; + size_t idx; + struct bundle_data bd; + + __ASSERT_NO_MSG(dst != NULL); + __ASSERT_NO_MSG(dst->num_bits > 0); + __ASSERT_NO_MSG(other != NULL); + __ASSERT_NO_MSG(other->num_bits > 0); + + key_dst = k_spin_lock(&dst->lock); + key_other = k_spin_lock(&other->lock); + + + if (dst->num_bits != other->num_bits) { + ret = -EINVAL; + goto out; + } + + if (num_bits == 0 || offset + num_bits > dst->num_bits) { + ret = -EINVAL; + goto out; + } + + setup_bundle_data(other, &bd, offset, num_bits); + + if (bd.sidx == bd.eidx) { + /* Start/end at same bundle */ + dst->bundles[bd.sidx] = + ((other->bundles[bd.sidx] ^ dst->bundles[bd.sidx]) & bd.smask) | + (dst->bundles[bd.sidx] & ~bd.smask); + } else { + /* Start/end at different bundle. + * So xor the bits in start and end bundles according to their bitmasks + * separately. For in-between bundles, + * xor all bits. + */ + dst->bundles[bd.sidx] = + ((other->bundles[bd.sidx] ^ dst->bundles[bd.sidx]) & bd.smask) | + (dst->bundles[bd.sidx] & ~bd.smask); + dst->bundles[bd.eidx] = + ((other->bundles[bd.eidx] ^ dst->bundles[bd.eidx]) & bd.emask) | + (dst->bundles[bd.eidx] & ~bd.emask); + for (idx = bd.sidx + 1; idx < bd.eidx; idx++) { + dst->bundles[idx] ^= other->bundles[idx]; + } + } + + ret = 0; + +out: + k_spin_unlock(&other->lock, key_other); + k_spin_unlock(&dst->lock, key_dst); + return ret; +} + +int sys_bitarray_set_bit(sys_bitarray_t *bitarray, size_t bit) +{ + k_spinlock_key_t key; + int ret; + size_t idx, off; + __ASSERT_NO_MSG(bitarray != NULL); __ASSERT_NO_MSG(bitarray->num_bits > 0); + key = k_spin_lock(&bitarray->lock); + if (bit >= bitarray->num_bits) { ret = -EINVAL; goto out; @@ -453,6 +560,81 @@ int sys_bitarray_alloc(sys_bitarray_t *bitarray, size_t num_bits, return ret; } +int sys_bitarray_find_nth_set(sys_bitarray_t *bitarray, size_t n, size_t num_bits, size_t offset, + size_t *found_at) +{ + k_spinlock_key_t key; + size_t count, idx; + uint32_t mask; + struct bundle_data bd; + int ret; + + __ASSERT_NO_MSG(bitarray != NULL); + __ASSERT_NO_MSG(bitarray->num_bits > 0); + + key = k_spin_lock(&bitarray->lock); + + if (n == 0 || num_bits == 0 || offset + num_bits > bitarray->num_bits) { + ret = -EINVAL; + goto out; + } + + ret = 1; + mask = 0; + setup_bundle_data(bitarray, &bd, offset, num_bits); + + count = POPCOUNT(bitarray->bundles[bd.sidx] & bd.smask); + /* If we already found more bits set than n, we found the target bundle */ + if (count >= n) { + idx = bd.sidx; + mask = bd.smask; + goto found; + } + /* Keep looking if there are more bundles */ + if (bd.sidx != bd.eidx) { + /* We are now only looking for the remaining bits */ + n -= count; + /* First bundle was already checked, keep looking in middle (complete) + * bundles. + */ + for (idx = bd.sidx + 1; idx < bd.eidx; idx++) { + count = POPCOUNT(bitarray->bundles[idx]); + if (count >= n) { + mask = ~(mask & 0); + goto found; + } + n -= count; + } + /* Continue searching in last bundle */ + count = POPCOUNT(bitarray->bundles[bd.eidx] & bd.emask); + if (count >= n) { + idx = bd.eidx; + mask = bd.emask; + goto found; + } + } + + goto out; + +found: + /* The bit we are looking for must be in the current bundle idx. + * Find out the exact index of the bit. + */ + for (int j = 0; j <= bundle_bitness(bitarray) - 1; j++) { + if (bitarray->bundles[idx] & mask & BIT(j)) { + if (--n <= 0) { + *found_at = idx * bundle_bitness(bitarray) + j; + ret = 0; + break; + } + } + } + +out: + k_spin_unlock(&bitarray->lock, key); + return ret; +} + int sys_bitarray_free(sys_bitarray_t *bitarray, size_t num_bits, size_t offset) { diff --git a/lib/utils/hex.c b/lib/utils/hex.c index f65125e3c6a02..fe4e7351e8502 100644 --- a/lib/utils/hex.c +++ b/lib/utils/hex.c @@ -11,11 +11,11 @@ int char2hex(char c, uint8_t *x) { - if (c >= '0' && c <= '9') { + if ((c >= '0') && (c <= '9')) { *x = c - '0'; - } else if (c >= 'a' && c <= 'f') { + } else if ((c >= 'a') && (c <= 'f')) { *x = c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { + } else if ((c >= 'A') && (c <= 'F')) { *x = c - 'A' + 10; } else { return -EINVAL; @@ -39,7 +39,7 @@ int hex2char(uint8_t x, char *c) size_t bin2hex(const uint8_t *buf, size_t buflen, char *hex, size_t hexlen) { - if (hexlen < (buflen * 2U + 1U)) { + if (hexlen < ((buflen * 2U) + 1U)) { return 0; } @@ -60,7 +60,7 @@ size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen) { uint8_t dec; - if (buflen < hexlen / 2U + hexlen % 2U) { + if (buflen < (hexlen / 2U + hexlen % 2U)) { return 0; } @@ -75,7 +75,7 @@ size_t hex2bin(const char *hex, size_t hexlen, uint8_t *buf, size_t buflen) } /* regular hex conversion */ - for (size_t i = 0; i < hexlen / 2U; i++) { + for (size_t i = 0; i < (hexlen / 2U); i++) { if (char2hex(hex[2U * i], &dec) < 0) { return 0; } diff --git a/lib/utils/json.c b/lib/utils/json.c index 2041db757e97f..73ca67e2f3661 100644 --- a/lib/utils/json.c +++ b/lib/utils/json.c @@ -1002,6 +1002,13 @@ static int opaque_string_encode(struct json_obj_token *opaque, json_append_bytes return append_bytes("\"", 1, data); } +static int encoded_obj_encode(const char **str, json_append_bytes_t append_bytes, void *data) +{ + size_t len = strlen(*str); + + return append_bytes(*str, len, data); +} + static int bool_encode(const bool *value, json_append_bytes_t append_bytes, void *data) { @@ -1036,6 +1043,8 @@ static int encode(const struct json_obj_descr *descr, const void *val, return float_ascii_encode(ptr, append_bytes, data); case JSON_TOK_OPAQUE: return opaque_string_encode(ptr, append_bytes, data); + case JSON_TOK_ENCODED_OBJ: + return encoded_obj_encode(ptr, append_bytes, data); default: return -EINVAL; } diff --git a/lib/utils/onoff.c b/lib/utils/onoff.c index 899b25a83e027..49ff4ce28d188 100644 --- a/lib/utils/onoff.c +++ b/lib/utils/onoff.c @@ -173,7 +173,7 @@ static void notify_one(struct onoff_manager *mgr, onoff_client_callback cb = (onoff_client_callback)sys_notify_finalize(&cli->notify, res); - if (cb) { + if (cb != NULL) { cb(mgr, cli, state, res); } } @@ -643,7 +643,7 @@ int onoff_sync_finalize(struct onoff_sync_service *srv, k_spin_unlock(&srv->lock, key); - if (cli) { + if (cli != NULL) { /* Detect service mis-use: onoff does not callback on transition * to off, so no client should have been passed. */ diff --git a/lib/utils/timeutil.c b/lib/utils/timeutil.c index 18c173acc8dc4..10800198445ad 100644 --- a/lib/utils/timeutil.c +++ b/lib/utils/timeutil.c @@ -34,9 +34,9 @@ static int64_t time_days_from_civil(int64_t y, { y -= m <= 2; - int64_t era = (y >= 0 ? y : y - 399) / 400; + int64_t era = ((y >= 0) ? y : (y - 399)) / 400; unsigned int yoe = y - era * 400; - unsigned int doy = (153U * (m + (m > 2 ? -3 : 9)) + 2U) / 5U + d; + unsigned int doy = (153U * (m + ((m > 2) ? -3 : 9)) + 2U) / 5U + d; unsigned int doe = yoe * 365U + yoe / 4U - yoe / 100U + doy; return era * 146097 + (time_t)doe - 719468; @@ -148,7 +148,7 @@ int timeutil_sync_ref_from_local(const struct timeutil_sync_state *tsp, rv = -ERANGE; } else { *refp = ref_abs; - rv = (int)(tsp->skew != 1.0f); + rv = (tsp->skew != 1.0f) ? 1 : 0; } } @@ -175,7 +175,7 @@ int timeutil_sync_local_from_ref(const struct timeutil_sync_state *tsp, + (int64_t)local_delta; *localp = local_abs; - rv = (int)(tsp->skew != 1.0f); + rv = (tsp->skew != 1.0f) ? 1 : 0; } return rv; diff --git a/modules/Kconfig.mcuboot b/modules/Kconfig.mcuboot index a2e1803b13899..b46c709d8ef44 100644 --- a/modules/Kconfig.mcuboot +++ b/modules/Kconfig.mcuboot @@ -199,7 +199,6 @@ config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP bool "MCUboot has been configured for DirectXIP operation" select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE select MCUBOOT_BOOTLOADER_NO_DOWNGRADE - select MCUBOOT_IMGTOOL_OVERWRITE_ONLY help MCUboot expects slot0_partition and slot1_partition to exist in DT. In this mode MCUboot can boot from either partition and will @@ -215,7 +214,6 @@ config MCUBOOT_BOOTLOADER_MODE_DIRECT_XIP_WITH_REVERT select MCUBOOT_BOOTUTIL_LIB_FOR_DIRECT_XIP select MCUBOOT_BOOTLOADER_MODE_HAS_NO_DOWNGRADE select MCUBOOT_BOOTLOADER_NO_DOWNGRADE - select MCUBOOT_IMGTOOL_OVERWRITE_ONLY help MCUboot expects slot0_partition and slot1_partition to exist in DT. In this mode MCUboot will boot the application with the higher version diff --git a/modules/Kconfig.mcux b/modules/Kconfig.mcux index 3f20250f58b0a..4931c33568c52 100644 --- a/modules/Kconfig.mcux +++ b/modules/Kconfig.mcux @@ -282,11 +282,6 @@ config HAS_MCUX_SMC help Set if the SMC module is present in the SoC. -config HAS_MCUX_CSI - bool - help - Set if the CMOS Sensor Interface module is present in the SoC. - config HAS_MCUX_LPTMR bool help @@ -374,4 +369,22 @@ config HAS_MCUX_XBARA help Set if the XBARA module is present on the SoC. +config NXP_FW_LOADER + bool "Include firmware loader component" + help + The firmware loader is used to load firmwares to embedded tranceivers. + It is needed to enable connectivity features. + +config NXP_MONOLITHIC_BT + bool "BT firmware monolithic build" + help + If enabled, the BT firmware used by the device will be linked with the + application directly. + +config NXP_RF_IMU + bool "Include RF_IMU adapter for intercore messaging" + select EVENTS + help + RF_IMU adapter is needed for intercore messaging. + endif # HAS_MCUX diff --git a/modules/Kconfig.microchip b/modules/Kconfig.microchip index 8c30ae6087d42..7497d99ead0a5 100644 --- a/modules/Kconfig.microchip +++ b/modules/Kconfig.microchip @@ -7,3 +7,6 @@ config HAS_MEC_HAL config HAS_MPFS_HAL bool "Microchip MPFS HAL drivers support" + +config HAS_MEC5_HAL + bool "Microchip MEC5 HAL drivers support" diff --git a/modules/Kconfig.silabs b/modules/Kconfig.silabs index 0078bfc0b9879..c5fb0d6ca149d 100644 --- a/modules/Kconfig.silabs +++ b/modules/Kconfig.silabs @@ -6,4 +6,4 @@ config HAS_SILABS_GECKO bool select HAS_CMSIS_CORE - depends on SOC_VENDOR_SILABS + depends on SOC_FAMILY_SILABS_S0 || SOC_FAMILY_SILABS_S1 || SOC_FAMILY_SILABS_S2 diff --git a/modules/Kconfig.simplelink b/modules/Kconfig.simplelink index cbcf1766d6b27..13b26b1ca1a48 100644 --- a/modules/Kconfig.simplelink +++ b/modules/Kconfig.simplelink @@ -7,15 +7,15 @@ config HAS_CC3220SDK # SimpleLink drivers require types (stdint.h) from c library which is not # provided by minimal lbc # Selecting ERRNO lets host driver use Zephyr's __errno -# Selecting PTHREAD_IPC and POSIX_API are needed to build the host driver +# Selecting POSIX_THREADS and POSIX_API are needed to build the host driver config SIMPLELINK_HOST_DRIVER bool "Build the SimpleLink WiFi Host Driver" depends on HAS_CC3220SDK depends on MULTITHREADING select REQUIRES_FULL_LIBC select ERRNO - select PTHREAD_IPC - select POSIX_CLOCK + select POSIX_THREADS + select POSIX_TIMERS help Build the SimpleLink host driver diff --git a/modules/fatfs/zfs_diskio.c b/modules/fatfs/zfs_diskio.c index 7a5061f15b6e4..2b0fa742e711e 100644 --- a/modules/fatfs/zfs_diskio.c +++ b/modules/fatfs/zfs_diskio.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2018-2021 Zephyr contributors * Copyright (c) 2022 Nordic Semiconductor ASA + * Copyright 2024 NXP * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,6 +13,7 @@ */ #include #include /* FatFs lower layer API */ +#include /* Zephyr specific FatFS API */ #include static const char * const pdrv_str[] = {FF_VOLUME_STRS}; @@ -31,13 +33,9 @@ DSTATUS disk_status(BYTE pdrv) /* Initialize a Drive */ DSTATUS disk_initialize(BYTE pdrv) { - __ASSERT(pdrv < ARRAY_SIZE(pdrv_str), "pdrv out-of-range\n"); + uint8_t param = DISK_IOCTL_POWER_ON; - if (disk_access_init(pdrv_str[pdrv]) != 0) { - return STA_NOINIT; - } else { - return RES_OK; - } + return disk_ioctl(pdrv, CTRL_POWER, ¶m); } /* Read Sector(s) */ @@ -109,6 +107,27 @@ DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) } break; + /* Optional IOCTL command used by Zephyr fs_unmount implementation, + * not called by FATFS + */ + case CTRL_POWER: + if (((*(uint8_t *)buff)) == DISK_IOCTL_POWER_OFF) { + /* Power disk off */ + if (disk_access_ioctl(pdrv_str[pdrv], + DISK_IOCTL_CTRL_DEINIT, + NULL) != 0) { + ret = RES_ERROR; + } + } else { + /* Power disk on */ + if (disk_access_ioctl(pdrv_str[pdrv], + DISK_IOCTL_CTRL_INIT, + NULL) != 0) { + ret = STA_NOINIT; + } + } + break; + default: ret = RES_PARERR; break; diff --git a/modules/fatfs/zfs_diskio.h b/modules/fatfs/zfs_diskio.h new file mode 100644 index 0000000000000..b22c75586be71 --- /dev/null +++ b/modules/fatfs/zfs_diskio.h @@ -0,0 +1,22 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_MODULES_FATFS_ZFS_DISKIO_H_ +#define ZEPHYR_MODULES_FATFS_ZFS_DISKIO_H_ +/* + * Header file for Zephyr specific portions of the FatFS disk interface. + * These APIs are internal to Zephyr's FatFS VFS implementation + */ + +/* + * Values that can be passed to buffer pointer used by disk_ioctl() when + * sending CTRL_POWER IOCTL + */ +#define DISK_IOCTL_POWER_OFF 0x0 +#define DISK_IOCTL_POWER_ON 0x1 + + +#endif /* ZEPHYR_MODULES_FATFS_ZFS_DISKIO_H_ */ diff --git a/modules/hal_ambiq/Kconfig b/modules/hal_ambiq/Kconfig index 24aaf1189cd75..10d3f785ce647 100644 --- a/modules/hal_ambiq/Kconfig +++ b/modules/hal_ambiq/Kconfig @@ -45,4 +45,14 @@ config AMBIQ_HAL_USE_MSPI help Use the MSPI driver from Ambiq HAL +config AMBIQ_HAL_USE_HWINFO + bool + help + Use the HWINFO driver from Ambiq HAL + +config AMBIQ_HAL_USE_BLEIF + bool + help + Use the BLEIF driver from Ambiq HAL + endif # AMBIQ_HAL diff --git a/modules/hal_infineon/CMakeLists.txt b/modules/hal_infineon/CMakeLists.txt index 99d925b1396a0..c6d9d95aa246e 100644 --- a/modules/hal_infineon/CMakeLists.txt +++ b/modules/hal_infineon/CMakeLists.txt @@ -2,7 +2,7 @@ # Copyright (c) 2022 Cypress Semiconductor Corporation. # SPDX-License-Identifier: Apache-2.0 -if(CONFIG_HAS_XMCLIB OR CONFIG_SOC_FAMILY_PSOC6 OR CONFIG_SOC_FAMILY_INFINEON_CAT1) +if(CONFIG_HAS_XMCLIB OR CONFIG_SOC_FAMILY_PSOC6_LEGACY OR CONFIG_SOC_FAMILY_INFINEON_CAT1) zephyr_library_named(modules_hal_infineon) zephyr_library_compile_options(-Wno-array-bounds) endif() @@ -12,7 +12,7 @@ if (CONFIG_HAS_XMCLIB) add_subdirectory(${ZEPHYR_HAL_INFINEON_MODULE_DIR}/XMCLib XMCLib) endif() -if (CONFIG_SOC_FAMILY_INFINEON_CAT1A OR CONFIG_SOC_FAMILY_PSOC6) +if (CONFIG_SOC_FAMILY_INFINEON_CAT1 OR CONFIG_SOC_FAMILY_PSOC6_LEGACY) ## Add core-lib sources for CAT1 devices add_subdirectory(core-lib) @@ -23,7 +23,7 @@ if (CONFIG_SOC_FAMILY_INFINEON_CAT1A OR CONFIG_SOC_FAMILY_PSOC6) add_subdirectory(mtb-template-cat1) endif() -if (CONFIG_SOC_FAMILY_INFINEON_CAT1A) +if (CONFIG_SOC_FAMILY_INFINEON_CAT1 AND NOT CONFIG_SOC_FAMILY_PSOC6_LEGACY) ## Add mtb-hal-cat1 sources for CAT1 devices add_subdirectory(mtb-hal-cat1) diff --git a/modules/hal_infineon/Kconfig b/modules/hal_infineon/Kconfig index 723579c5d5b92..fb1431faed20b 100644 --- a/modules/hal_infineon/Kconfig +++ b/modules/hal_infineon/Kconfig @@ -4,7 +4,7 @@ config ZEPHYR_HAL_INFINEON_MODULE bool -if SOC_FAMILY_PSOC6 || SOC_FAMILY_INFINEON_CAT1 +if SOC_FAMILY_INFINEON_CAT1 || SOC_FAMILY_PSOC6_LEGACY config USE_INFINEON_ADC bool @@ -77,8 +77,7 @@ config USE_INFINEON_FLASH help Enable Flash HAL module driver for Infineon devices -endif # SOC_FAMILY_PSOC6 - +endif # SOC_FAMILY_INFINEON_CAT1 || SOC_FAMILY_PSOC6_LEGACY config USE_INFINEON_ABSTRACTION_RTOS bool "Abstraction RTOS component (Zephyr support)" help diff --git a/modules/hal_infineon/btstack-integration/CMakeLists.txt b/modules/hal_infineon/btstack-integration/CMakeLists.txt index d82fe10662dda..8033fe3044384 100644 --- a/modules/hal_infineon/btstack-integration/CMakeLists.txt +++ b/modules/hal_infineon/btstack-integration/CMakeLists.txt @@ -2,14 +2,39 @@ # # SPDX-License-Identifier: Apache-2.0 -set(hal_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}) -set(hal_ble_dir ${hal_dir}/bluetooth-freertos) -set(hal_blobs_dir ${hal_dir}/zephyr/blobs/img/bluetooth/firmware) -set(blob_gen_inc_file ${ZEPHYR_BINARY_DIR}/include/generated/bt_firmware.hcd.inc) +set(hal_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}) +set(btstack_integration ${hal_dir}/btstack-integration) +set(hal_blobs_dir ${hal_dir}/zephyr/blobs/img/bluetooth/firmware) +set(blob_gen_inc_file ${ZEPHYR_BINARY_DIR}/include/generated/bt_firmware.hcd.inc) + +######################################################################################### +# btstack integration assets sources for cyw208xx +######################################################################################### + +if(CONFIG_BT_CYW208XX) + + zephyr_include_directories(${btstack_integration}/../btstack/wiced_include) + zephyr_include_directories(${btstack_integration}/COMPONENT_BTSS-IPC/platform/include) + zephyr_include_directories(${btstack_integration}/COMPONENT_BTSS-IPC/platform/ipc/include) + + zephyr_library_sources(${btstack_integration}/COMPONENT_BTSS-IPC/platform/ipc/cybt_platform_freertos.c) + zephyr_library_sources(${btstack_integration}/COMPONENT_BTSS-IPC/platform/ipc/cybt_platform_hci.c) + zephyr_library_sources(${btstack_integration}/COMPONENT_BTSS-IPC/platform/ipc/cybt_bt_task.c) + zephyr_library_sources(${btstack_integration}/COMPONENT_BTSS-IPC/platform/ipc/cybt_host_stack_platform_interface.c) + zephyr_library_sources(${btstack_integration}/COMPONENT_BTSS-IPC/platform/ipc/cybt_platform_task.c) + + zephyr_library_sources(${btstack_integration}/COMPONENT_BTSS-IPC/platform/common/cybt_platform_main.c) + zephyr_library_sources(${btstack_integration}/COMPONENT_BTSS-IPC/platform/common/cybt_platform_trace.c) + zephyr_library_sources(${btstack_integration}/COMPONENT_BTSS-IPC/platform/common/cybt_prm.c) + + #zephyr_library_sources(${btstack_integration}/COMPONENT_BTSS-IPC/platform/common/cybt_patchram_download.c) +endif() ######################################################################################### # BT firmware ######################################################################################### + +# HCD files for CYW43xx devices # CYW43012 modules if(CONFIG_CYW43012_MURATA_1LV) set(blob_hcd_file ${hal_blobs_dir}/COMPONENT_43012/COMPONENT_MURATA-1LV/bt_firmware.hcd) @@ -30,6 +55,38 @@ if(CONFIG_CYW4373_STERLING_LWB5PLUS) set(blob_hcd_file ${hal_blobs_dir}/COMPONENT_4373/COMPONENT_STERLING-LWB5plus/bt_firmware.hcd) endif() +# HCD files for CYW208xx + +# CYW20829 device (FW patch for 0dBm TX Power) +if(CONFIG_CYW20829_BT_FW_TX0) + set(blob_hcd_file ${hal_blobs_dir}/COMPONENT_CYW20829B0/COMPONENT_BTFW-TX0/bt_firmware.hcd) +endif() + +# CYW20829 device (FW patch for 10dBm TX Power) +if(CONFIG_CYW20829_BT_FW_TX10) + set(blob_hcd_file ${hal_blobs_dir}/COMPONENT_CYW20829B0/COMPONENT_BTFW-TX10/bt_firmware.hcd) +endif() + +# CYW20829 device (FW patch with PAwR support for 0dBm TX Power) +if(CONFIG_CYW20829_BT_FW_PAWR_TX0) + set(blob_hcd_file ${hal_blobs_dir}/COMPONENT_CYW20829B0/COMPONENT_BTFW-PAWR-TX0/bt_firmware.hcd) +endif() + +# CYW20829 device (FW patch with PAwR support for 10dBm TX Power) +if(CONFIG_CYW20829_BT_FW_PAWR_TX10) + set(blob_hcd_file ${hal_blobs_dir}/COMPONENT_CYW20829B0/COMPONENT_BTFW-PAWR-TX10/bt_firmware.hcd) +endif() + +# CYW20829 device (FW patch with ISOC support for 0dBm TX Power) +if(CONFIG_CYW20829_BT_FW_ISOC_TX0) + set(blob_hcd_file ${hal_blobs_dir}/COMPONENT_CYW20829B0/COMPONENT_BTFW-ISOC-TX0/bt_firmware.hcd) +endif() + +# CYW20829 device (FW patch with ISOC support for 10dBm TX Power) +if(CONFIG_CYW20829_BT_FW_ISOC_TX10) + set(blob_hcd_file ${hal_blobs_dir}/COMPONENT_CYW20829B0/COMPONENT_BTFW-ISOC-TX10/bt_firmware.hcd) +endif() + # use user provided FIRMWARE HCD file (path must be defined in CONFIG_AIROC_CUSTOM_FIRMWARE_HCD_BLOB) if(CONFIG_AIROC_CUSTOM_FIRMWARE_HCD_BLOB) # Allowed to pass absolute path to HCD blob file, or relative path from Application folder. diff --git a/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt b/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt index c94bd1db60c34..2d7641f59b641 100644 --- a/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt +++ b/modules/hal_infineon/mtb-hal-cat1/CMakeLists.txt @@ -5,9 +5,11 @@ set(hal_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-hal-cat1) set(hal_cat1a_dir ${hal_dir}/COMPONENT_CAT1A) +set(hal_cat1b_dir ${hal_dir}/COMPONENT_CAT1B) # PSoC 6 family defines zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A COMPONENT_CAT1A) +zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B COMPONENT_CAT1B) zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 COMPONENT_CAT1) zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 CY_USING_HAL) @@ -15,6 +17,7 @@ zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 CY_USING_HAL) zephyr_include_directories(${hal_dir}/include) zephyr_include_directories(${hal_dir}/include_pvt) zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A ${hal_cat1a_dir}/include) +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B ${hal_cat1b_dir}/include) # Packages sources zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_104_M_CSP_BLE @@ -29,8 +32,6 @@ zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_124_BGA ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_01_124_bga.c) zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_124_BGA_SIP ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_01_124_bga_sip.c) -zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_43_SMT - ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_01_43_smt.c) zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_68_QFN_BLE ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_01_68_qfn_ble.c) zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_01_80_WLCSP @@ -56,6 +57,12 @@ zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_04_68_QFN zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_PSOC6_04_80_TQFP ${hal_cat1a_dir}/source/pin_packages/cyhal_psoc6_04_80_tqfp.c) +zephyr_library_sources_ifdef(CONFIG_SOC_PACKAGE_CYW20829_56_QFN + ${hal_cat1b_dir}/source/pin_packages/cyhal_cyw20829_56_qfn.c) + +zephyr_library_sources_ifdef(CONFIG_SOC_DIE_CYW20829 + ${hal_cat1b_dir}/source/triggers/cyhal_triggers_cyw20829.c) + zephyr_library_sources_ifdef(CONFIG_SOC_DIE_PSOC6_01 ${hal_cat1a_dir}/source/triggers/cyhal_triggers_psoc6_01.c) zephyr_library_sources_ifdef(CONFIG_SOC_DIE_PSOC6_02 diff --git a/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt b/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt index f71e0b2b3a952..fd14d6da28055 100644 --- a/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt +++ b/modules/hal_infineon/mtb-pdl-cat1/CMakeLists.txt @@ -6,24 +6,38 @@ set(pdl_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1) set(pdl_drv_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1/drivers) set(pdl_dev_cat1a_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1/devices/COMPONENT_CAT1A) +set(pdl_dev_cat1b_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-pdl-cat1/devices/COMPONENT_CAT1B) + +# Generate PDL specific SOC defines zephyr_compile_definitions(${CONFIG_SOC_PART_NUMBER}) -zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 ${CONFIG_SOC}) +zephyr_compile_definitions_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1 $) + +# Generate PDL specific define (w. *_device) for SOC module (e.g: CYBLE_416045_02) +zephyr_compile_definitions_ifdef(CONFIG_SOC_CYBLE_416045_02 CYBLE_416045_02_device) # Add mtb-pdl-cat1 zephyr_include_directories(${pdl_drv_dir}/include) -zephyr_include_directories(${pdl_dev_cat1a_dir}/include) -zephyr_include_directories(${pdl_dev_cat1a_dir}/include/ip) -zephyr_library_sources(${pdl_dev_cat1a_dir}/source/cy_device.c) +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A ${pdl_dev_cat1a_dir}/include) +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A ${pdl_dev_cat1a_dir}/include/ip) +zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1A ${pdl_dev_cat1a_dir}/source/cy_device.c) + + +zephyr_include_directories(${pdl_drv_dir}/include) +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B ${pdl_dev_cat1b_dir}/include) +zephyr_include_directories_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B ${pdl_dev_cat1b_dir}/include/ip) +zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_INFINEON_CAT1B ${pdl_dev_cat1b_dir}/source/cy_device.c) + zephyr_library_sources(${pdl_drv_dir}/source/TOOLCHAIN_GCC_ARM/cy_syslib_ext.S) # Peripheral drivers -zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_PSOC6 ${pdl_drv_dir}/source/cy_sysint.c) +zephyr_library_sources_ifdef(CONFIG_SOC_FAMILY_PSOC6_LEGACY ${pdl_drv_dir}/source/cy_sysint.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_ADC ${pdl_drv_dir}/source/cy_sar.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_I2C ${pdl_drv_dir}/source/cy_scb_i2c.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_LPTIMER ${pdl_drv_dir}/source/cy_mcwdt.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_PWM ${pdl_drv_dir}/source/cy_tcpwm_pwm.c) +zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_RTC ${pdl_drv_dir}/source/cy_rtc.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_SDIO ${pdl_drv_dir}/source/cy_sd_host.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_SPI ${pdl_drv_dir}/source/cy_scb_spi.c) zephyr_library_sources_ifdef(CONFIG_USE_INFINEON_TIMER ${pdl_drv_dir}/source/cy_tcpwm_counter.c) @@ -55,8 +69,18 @@ zephyr_library_sources(${pdl_drv_dir}/source/cy_ipc_pipe.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_ipc_sema.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_prot.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_sysclk.c) +if(CONFIG_SOC_FAMILY_INFINEON_CAT1B) + zephyr_library_sources(${pdl_drv_dir}/source/cy_sysclk_v2.c) + zephyr_library_sources(${pdl_drv_dir}/source/cy_systick_v2.c) + zephyr_library_sources(${pdl_drv_dir}/source/cy_syspm_v2.c) + zephyr_library_sources(${pdl_drv_dir}/source/cy_syspm_btss.c) +endif() zephyr_library_sources(${pdl_drv_dir}/source/cy_syslib.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_syspm.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_systick.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_trigmux.c) zephyr_library_sources(${pdl_drv_dir}/source/cy_wdt.c) + +# add IPC_BT driver for CYW208XX devices +zephyr_library_sources_ifdef(CONFIG_BT_CYW208XX ${pdl_drv_dir}/source/cy_ipc_bt.c) +zephyr_library_sources_ifdef(CONFIG_BT_CYW208XX ${pdl_drv_dir}/source/cy_syspm_pdcm.c) diff --git a/modules/hal_infineon/mtb-template-cat1/CMakeLists.txt b/modules/hal_infineon/mtb-template-cat1/CMakeLists.txt index 896156527fa8b..8e7df38166db8 100644 --- a/modules/hal_infineon/mtb-template-cat1/CMakeLists.txt +++ b/modules/hal_infineon/mtb-template-cat1/CMakeLists.txt @@ -5,10 +5,22 @@ set(template_dir ${ZEPHYR_HAL_INFINEON_MODULE_DIR}/mtb-template-cat1) set(cat1a_dir ${template_dir}/files/templates/cat1a) +set(cat1b_dir ${template_dir}/files/templates/cat1b) -zephyr_include_directories(${cat1a_dir}/COMPONENT_MTB) +if(CONFIG_SOC_FAMILY_INFINEON_CAT1A) + zephyr_include_directories(${cat1a_dir}/COMPONENT_MTB) + zephyr_include_directories(${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM33/HEADER_FILES) -zephyr_library_sources_ifdef(CONFIG_CPU_CORTEX_M4 - ${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM4/system_psoc6_cm4.c) -zephyr_library_sources_ifdef(CONFIG_CPU_CORTEX_M0PLUS - ${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM0P/system_psoc6_cm0plus.c) + zephyr_library_sources_ifdef(CONFIG_CPU_CORTEX_M4 + ${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM4/system_psoc6_cm4.c) + zephyr_library_sources_ifdef(CONFIG_CPU_CORTEX_M0PLUS + ${cat1a_dir}/COMPONENT_MTB/COMPONENT_CM0P/system_psoc6_cm0plus.c) +endif() + + +# Add support cyw20829 (cat1b) +if(CONFIG_SOC_FAMILY_INFINEON_CAT1B) + zephyr_include_directories(${cat1b_dir}/COMPONENT_MTB) + zephyr_include_directories(${cat1b_dir}/COMPONENT_MTB/COMPONENT_CM33/HEADER_FILES) + zephyr_library_sources(${cat1b_dir}/COMPONENT_MTB/COMPONENT_CM33/system_cyw20829.c) +endif() diff --git a/modules/hal_nordic/CMakeLists.txt b/modules/hal_nordic/CMakeLists.txt index c4a7134935cdd..ac9b3f8ce4c6c 100644 --- a/modules/hal_nordic/CMakeLists.txt +++ b/modules/hal_nordic/CMakeLists.txt @@ -6,12 +6,13 @@ if (CONFIG_NRF_802154_RADIO_DRIVER OR CONFIG_NRF_802154_SERIALIZATION) endif (CONFIG_NRF_802154_RADIO_DRIVER OR CONFIG_NRF_802154_SERIALIZATION) add_subdirectory_ifdef(CONFIG_HAS_NRFX nrfx) +add_subdirectory_ifdef(CONFIG_HAS_NRFS nrfs) if(CONFIG_NRF_REGTOOL_GENERATE_UICR) list(APPEND nrf_regtool_components GENERATE:UICR) endif() if(DEFINED nrf_regtool_components) - find_package(nrf-regtool 5.1.0 + find_package(nrf-regtool 5.3.0 COMPONENTS ${nrf_regtool_components} PATHS ${CMAKE_CURRENT_LIST_DIR}/nrf-regtool NO_CMAKE_PATH diff --git a/modules/hal_nordic/Kconfig b/modules/hal_nordic/Kconfig index c9cc93e93293c..13ab8d9cd2f9c 100644 --- a/modules/hal_nordic/Kconfig +++ b/modules/hal_nordic/Kconfig @@ -55,7 +55,7 @@ endchoice config NRF_802154_TEMPERATURE_UPDATE bool "nRF 802.15.4 temperature update" - default y + default y if !SOC_NRF54H20 help Enable temperature update for nRF 802.15.4 driver @@ -235,5 +235,6 @@ endif # NRF_802154_RADIO_DRIVER || NRF_802154_SERIALIZATION endmenu # HAS_NORDIC_DRIVERS +rsource "nrfs/Kconfig" rsource "nrfx/Kconfig" rsource "Kconfig.nrf_regtool" diff --git a/modules/hal_nordic/nrf_802154/serialization/platform/nrf_802154_spinel_backend_ipc.c b/modules/hal_nordic/nrf_802154/serialization/platform/nrf_802154_spinel_backend_ipc.c index b2629eef67b76..6df811f6badb6 100644 --- a/modules/hal_nordic/nrf_802154/serialization/platform/nrf_802154_spinel_backend_ipc.c +++ b/modules/hal_nordic/nrf_802154/serialization/platform/nrf_802154_spinel_backend_ipc.c @@ -15,6 +15,10 @@ #include "../../spinel_base/spinel.h" #include "../../src/include/nrf_802154_spinel.h" +#if defined(CONFIG_SOC_NRF5340_CPUAPP) +#include +#endif + #define LOG_LEVEL LOG_LEVEL_INFO #define LOG_MODULE_NAME spinel_ipc_backend LOG_MODULE_REGISTER(LOG_MODULE_NAME); @@ -50,6 +54,10 @@ nrf_802154_ser_err_t nrf_802154_backend_init(void) DEVICE_DT_GET(DT_CHOSEN(nordic_802154_spinel_ipc)); int err; +#if defined(CONFIG_SOC_NRF5340_CPUAPP) + nrf53_cpunet_enable(true); +#endif + err = ipc_service_open_instance(ipc_instance); if (err < 0 && err != -EALREADY) { LOG_ERR("Failed to open IPC instance: %d", err); diff --git a/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c b/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c index 3a3d9501d0c79..1db86f5ad142d 100644 --- a/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c +++ b/modules/hal_nordic/nrf_802154/sl_opensource/platform/nrf_802154_clock_zephyr.c @@ -4,18 +4,21 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include #include #include #include +#include +#if defined(CONFIG_CLOCK_CONTROL_NRF) #include #include +#elif !defined(NRF54H_SERIES) +#error No implementation to start or stop HFCLK due to missing clock_control. +#endif static bool hfclk_is_running; -static bool lfclk_is_running; -static struct onoff_client hfclk_cli; -static struct onoff_client lfclk_cli; void nrf_802154_clock_init(void) { @@ -27,6 +30,15 @@ void nrf_802154_clock_deinit(void) /* Intentionally empty. */ } +bool nrf_802154_clock_hfclk_is_running(void) +{ + return hfclk_is_running; +} + +#if defined(CONFIG_CLOCK_CONTROL_NRF) + +static struct onoff_client hfclk_cli; + static void hfclk_on_callback(struct onoff_manager *mgr, struct onoff_client *cli, uint32_t state, @@ -63,53 +75,39 @@ void nrf_802154_clock_hfclk_stop(void) hfclk_is_running = false; } -bool nrf_802154_clock_hfclk_is_running(void) -{ - return hfclk_is_running; -} +#elif defined(NRF54H_SERIES) -static void lfclk_on_callback(struct onoff_manager *mgr, - struct onoff_client *cli, - uint32_t state, - int res) -{ - lfclk_is_running = true; - nrf_802154_clock_lfclk_ready(); -} +#define NRF_LRCCONF_RADIO_PD NRF_LRCCONF010 +#define MAX_HFXO_RAMP_UP_TIME_US 1000 -void nrf_802154_clock_lfclk_start(void) +static void hfclk_started_timer_handler(struct k_timer *dummy) { - int ret; - struct onoff_manager *mgr = - z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF); - - __ASSERT_NO_MSG(mgr != NULL); - - sys_notify_init_callback(&lfclk_cli.notify, lfclk_on_callback); - - ret = onoff_request(mgr, &lfclk_cli); - __ASSERT_NO_MSG(ret >= 0); + hfclk_is_running = true; + nrf_802154_clock_hfclk_ready(); } -void nrf_802154_clock_lfclk_stop(void) -{ - int ret; - struct onoff_manager *mgr = - z_nrf_clock_control_get_onoff(CLOCK_CONTROL_NRF_SUBSYS_LF); +K_TIMER_DEFINE(hfclk_started_timer, hfclk_started_timer_handler, NULL); - __ASSERT_NO_MSG(mgr != NULL); +void nrf_802154_clock_hfclk_start(void) +{ + /* Use register directly, there is no support for that task in nrf_lrcconf_task_trigger. + * This code might cause troubles if there are other HFXO users in this CPU. + */ + NRF_LRCCONF_RADIO_PD->EVENTS_HFXOSTARTED = 0x0; + NRF_LRCCONF_RADIO_PD->TASKS_REQHFXO = 0x1; - ret = onoff_cancel_or_release(mgr, &lfclk_cli); - __ASSERT_NO_MSG(ret >= 0); - lfclk_is_running = false; + k_timer_start(&hfclk_started_timer, K_USEC(MAX_HFXO_RAMP_UP_TIME_US), K_NO_WAIT); } -bool nrf_802154_clock_lfclk_is_running(void) +void nrf_802154_clock_hfclk_stop(void) { - return lfclk_is_running; -} + /* Use register directly, there is no support for that task in nrf_lrcconf_task_trigger. + * This code might cause troubles if there are other HFXO users in this CPU. + */ + NRF_LRCCONF_RADIO_PD->TASKS_STOPREQHFXO = 0x1; + NRF_LRCCONF_RADIO_PD->EVENTS_HFXOSTARTED = 0x0; -__WEAK void nrf_802154_clock_lfclk_ready(void) -{ - /* Intentionally empty. */ + hfclk_is_running = false; } + +#endif diff --git a/modules/hal_nordic/nrfs/CMakeLists.txt b/modules/hal_nordic/nrfs/CMakeLists.txt new file mode 100644 index 0000000000000..c601b8a4233c9 --- /dev/null +++ b/modules/hal_nordic/nrfs/CMakeLists.txt @@ -0,0 +1,41 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + + +if(CONFIG_NRFS) + zephyr_library() + if(NOT DEFINED NRFS_DIR) + set(NRFS_DIR ${ZEPHYR_CURRENT_MODULE_DIR}/nrfs CACHE PATH "nrfs directory") + endif() + + set(INC_DIR ${NRFS_DIR}/include) + set(SRC_DIR ${NRFS_DIR}/src) + set(HELPERS_DIR ${NRFS_DIR}/helpers) + + zephyr_include_directories(${INC_DIR}) + zephyr_include_directories(${INC_DIR}/services) + zephyr_include_directories(${HELPERS_DIR}) + zephyr_include_directories(.) + zephyr_include_directories(${CMAKE_CURRENT_SOURCE_DIR}/backends) + zephyr_include_directories_ifdef(CONFIG_NRFS_DVFS_LOCAL_DOMAIN ${CMAKE_CURRENT_SOURCE_DIR}/dvfs) + + zephyr_library_sources(${HELPERS_DIR}/dvfs_oppoint.c) + + if(CONFIG_NRFS_LOCAL_DOMAIN) + zephyr_library_sources_ifdef(CONFIG_NRFS_CLOCK_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_clock.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_DIAG_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_diag.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_DVFS_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_dvfs.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_MRAM_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_mram.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_PMIC_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_pmic.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_RESET_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_reset.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_TEMP_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_temp.c) + zephyr_library_sources_ifdef(CONFIG_NRFS_VBUS_DETECTOR_SERVICE_ENABLED ${SRC_DIR}/services/nrfs_usb.c) + zephyr_library_sources(${SRC_DIR}/internal/nrfs_dispatcher.c) + add_subdirectory_ifdef(CONFIG_NRFS_DVFS_LOCAL_DOMAIN dvfs) + + if(CONFIG_NRFS_DIAG_SERVICE_ENABLED) + message(WARNING "This service is for Nordic Semiconductor INTERNAL purposes ONLY. Use it with caution due to risk of hardware damage!") + endif() + endif() + zephyr_library_sources_ifdef(CONFIG_NRFS_LOCAL_DOMAIN backends/nrfs_backend_ipc_service.c) +endif() diff --git a/modules/hal_nordic/nrfs/Kconfig b/modules/hal_nordic/nrfs/Kconfig new file mode 100644 index 0000000000000..b4f6715fdd2d8 --- /dev/null +++ b/modules/hal_nordic/nrfs/Kconfig @@ -0,0 +1,116 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config HAS_NRFS + bool + +menu "nRF Services" + depends on HAS_NRFS + +config NRFS_HAS_CLOCK_SERVICE + bool + +config NRFS_HAS_CONST_LATENCY_SERVICE + bool + +config NRFS_HAS_DIAG_SERVICE + bool + +config NRFS_HAS_DVFS_SERVICE + bool + +config NRFS_HAS_MRAM_SERVICE + bool + +config NRFS_HAS_PMIC_SERVICE + bool + +config NRFS_HAS_RESET_SERVICE + bool + +config NRFS_HAS_TEMP_SERVICE + bool + +config NRFS_HAS_VBUS_DETECTOR_SERVICE + bool + +config NRFS + bool "nRF Services Support" + select NRFS_LOCAL_DOMAIN if (SOC_NRF54H20_CPUAPP || SOC_NRF54H20_CPURAD) + depends on HAS_NRFS + help + This option enables the nRF Services library. + +if NRFS + +config NRFS_LOCAL_DOMAIN + bool "nRF Services Local Domain Support" + depends on $(dt_alias_enabled,ipc-to-cpusys) + select IPC_SERVICE + select MBOX + select EVENTS + select REBOOT + help + This option enables the nRF Services Local Domain libraries. + +config NRFS_DVFS_LOCAL_DOMAIN + bool "Local domain that supports DVFS" + depends on NRFS_LOCAL_DOMAIN + depends on NRFS_DVFS_SERVICE_ENABLED + default y if NRFS_DVFS_SERVICE_ENABLED + +menu "Enabled Services" + +module = NRFS +module-str = nRF-Services +source "subsys/logging/Kconfig.template.log_config" + +config NRFS_RESET_SERVICE_ENABLED + bool "Reset service" + depends on NRFS_HAS_RESET_SERVICE + +config NRFS_MRAM_SERVICE_ENABLED + bool "MRAM latency service" + depends on NRFS_HAS_MRAM_SERVICE + +config NRFS_TEMP_SERVICE_ENABLED + bool "Temperature service" + depends on NRFS_HAS_TEMP_SERVICE + default y + +config NRFS_VBUS_DETECTOR_SERVICE_ENABLED + bool "VBUS detector for the USB peripheral" + depends on NRFS_HAS_VBUS_DETECTOR_SERVICE + default y + +config NRFS_CONST_LATENCY_SERVICE_ENABLED + bool "DPPI constant latency service" + depends on NRFS_HAS_CONST_LATENCY_SERVICE + default y + +config NRFS_PMIC_SERVICE_ENABLED + bool "PMIC service" + depends on NRFS_HAS_PMIC_SERVICE + +config NRFS_DVFS_SERVICE_ENABLED + bool "DVFS service" + depends on NRFS_HAS_DVFS_SERVICE + default y if SOC_NRF54H20_CPUAPP + +config NRFS_DIAG_SERVICE_ENABLED + bool "System Diagnostics service (only for development purposes)" + depends on NRFS_HAS_DIAG_SERVICE + +config NRFS_CLOCK_SERVICE_ENABLED + bool "Clock service" + depends on NRFS_HAS_CLOCK_SERVICE + default y +endmenu + +rsource "backends/Kconfig" +if NRFS_DVFS_LOCAL_DOMAIN +rsource "dvfs/Kconfig" +endif # NRFS_DVFS_LOCAL_DOMAIN + +endif # NRFS +endmenu diff --git a/modules/hal_nordic/nrfs/backends/Kconfig b/modules/hal_nordic/nrfs/backends/Kconfig new file mode 100644 index 0000000000000..2dc97ea63ceb9 --- /dev/null +++ b/modules/hal_nordic/nrfs/backends/Kconfig @@ -0,0 +1,28 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + + +menu "NRFS backend settings" + +module = NRFS_BACKEND +module-str = NRFS backend +source "subsys/logging/Kconfig.template.log_config" + +config NRFS_BACKEND_IPC_SERVICE_INIT_PRIO + int "Initialization priority for NRFS IPC backend" + default 51 + help + This should be higher than priority of other drivers/subsystems + used by NRFS backend. For example MBOX_INIT_PRIORITY which is 50. + +config NRFS_MAX_BACKEND_PACKET_SIZE + int "Maximum IPC data packet size in bytes" + range 8 128 + default 32 + +config NRFS_BACKEND_TX_MSG_QUEUE_SIZE + int "Size of TX buffer message queue size" + range 1 16 + default 8 + +endmenu diff --git a/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c new file mode 100644 index 0000000000000..172b5957b2392 --- /dev/null +++ b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "nrfs_backend_ipc_service.h" + +#include +#include + +#include +#include +#include +#include +#include + +LOG_MODULE_REGISTER(NRFS_BACKEND, CONFIG_NRFS_BACKEND_LOG_LEVEL); + +#define MAX_PACKET_DATA_SIZE (CONFIG_NRFS_MAX_BACKEND_PACKET_SIZE) + +K_MSGQ_DEFINE(ipc_transmit_msgq, sizeof(struct ipc_data_packet), + CONFIG_NRFS_BACKEND_TX_MSG_QUEUE_SIZE, 4); + +static struct k_work backend_send_work; + +static struct ipc_data_packet rx_data; +static struct ipc_data_packet tx_data; + +static void ipc_sysctrl_ept_bound(void *priv); +static void ipc_sysctrl_ept_recv(const void *data, size_t size, void *priv); + +static K_EVENT_DEFINE(ipc_connected_event); + +#define IPC_INIT_DONE_EVENT (0x01) + +struct ipc_channel_config { + const struct device *ipc_instance; + struct ipc_ept_cfg *endpoint_config; + struct ipc_ept ipc_ept; + atomic_t status; + bool enabled; +}; + +static struct ipc_ept_cfg ipc_sysctrl_ept_cfg = { + .name = "ipc_to_sysctrl", + .cb = { + .bound = ipc_sysctrl_ept_bound, + .received = ipc_sysctrl_ept_recv, + }, +}; + +static struct ipc_channel_config ipc_cpusys_channel_config = { + .ipc_instance = DEVICE_DT_GET(DT_ALIAS(ipc_to_cpusys)), + .endpoint_config = &ipc_sysctrl_ept_cfg, + .status = ATOMIC_INIT(NOT_CONNECTED), + .enabled = true +}; + +/** + * @brief nrfs backend error handler + * + * @param error_id The id of an error to handle. + * @param error additional error code if needed, if not needed use 0. + * @param fatal true if fatal error and needs special handling + */ +__weak void nrfs_backend_error_handler(enum nrfs_backend_error error_id, int error, bool fatal) +{ + switch (error_id) { + case NRFS_ERROR_EPT_RECEIVE_DATA_TOO_LONG: + LOG_ERR("Received data is too long. Config error."); + break; + + case NRFS_ERROR_NO_DATA_RECEIVED: + LOG_ERR("No data in received message!"); + break; + + case NRFS_ERROR_IPC_OPEN_INSTANCE: + LOG_ERR("IPC open instance failure with error: %d", error); + break; + + case NRFS_ERROR_IPC_REGISTER_ENDPOINT: + LOG_ERR("IPC register endpoint failure with error: %d", error); + break; + + default: + LOG_ERR("Undefined error id: %d, error cause: %d", error_id, error); + break; + } + + if (fatal) { + nrfs_backend_fatal_error_handler(error_id); + } +} + +static void ipc_sysctrl_ept_bound(void *priv) +{ + LOG_INF("Bound to sysctrl."); + k_event_post(&ipc_connected_event, IPC_INIT_DONE_EVENT); + atomic_set(&ipc_cpusys_channel_config.status, CONNECTED); +} + +static void ipc_sysctrl_ept_recv(const void *data, size_t size, void *priv) +{ + __ASSERT(size <= MAX_PACKET_DATA_SIZE, "Received data is too long. Config error."); + if (size <= MAX_PACKET_DATA_SIZE) { + rx_data.channel_id = IPC_CPUSYS_CHANNEL_ID; + rx_data.size = size; + if (data) { + memcpy(rx_data.data, (uint8_t *)data, size); + nrfs_dispatcher_notify(&rx_data.data, rx_data.size); + } else { + nrfs_backend_error_handler(NRFS_ERROR_NO_DATA_RECEIVED, 0, false); + } + } else { + nrfs_backend_error_handler(NRFS_ERROR_EPT_RECEIVE_DATA_TOO_LONG, 0, true); + } +} + +static void nrfs_backend_send_work(struct k_work *item) +{ + static struct ipc_data_packet data_to_send; + + LOG_DBG("Sending data from workqueue"); + while (k_msgq_get(&ipc_transmit_msgq, &data_to_send, K_NO_WAIT) == 0) { + ipc_service_send(&ipc_cpusys_channel_config.ipc_ept, &tx_data.data, tx_data.size); + } +} + +/** + * @brief Initialize ipc channel + * + * @return -EINVAL when instance configuration is invalid. + * @return -EIO when no backend is registered. + * @return -EALREADY when the instance is already opened (or being opened). + * @return -EBUSY when the instance is busy. + * @return 0 on success + */ +static int ipc_channel_init(void) +{ + struct ipc_channel_config *ch_cfg; + int ret = 0; + + k_work_init(&backend_send_work, nrfs_backend_send_work); + ch_cfg = &ipc_cpusys_channel_config; + + ret = ipc_service_open_instance(ch_cfg->ipc_instance); + if ((ret < 0) && (ret != -EALREADY)) { + nrfs_backend_error_handler(NRFS_ERROR_IPC_OPEN_INSTANCE, ret, false); + return ret; + } + + LOG_INF("ipc_service_open_instance() done."); + + ret = ipc_service_register_endpoint(ch_cfg->ipc_instance, + &ch_cfg->ipc_ept, + ch_cfg->endpoint_config); + if (ret < 0) { + nrfs_backend_error_handler(NRFS_ERROR_IPC_REGISTER_ENDPOINT, ret, false); + return ret; + } + + LOG_INF("ipc_service_register_endpoint() done."); + + return ret; +} + +nrfs_err_t nrfs_backend_send(void *message, size_t size) +{ + return nrfs_backend_send_ex(message, size, K_NO_WAIT, false); +} + +nrfs_err_t nrfs_backend_send_ex(void *message, size_t size, k_timeout_t timeout, bool high_prio) +{ + if (atomic_get(&ipc_cpusys_channel_config.status) != CONNECTED) { + LOG_WRN("Backend not yet connected to sysctrl"); + return NRFS_ERR_INVALID_STATE; + } + + if (size <= MAX_PACKET_DATA_SIZE) { + int err; + + tx_data.channel_id = IPC_CPUSYS_CHANNEL_ID; + tx_data.size = size; + memcpy(tx_data.data, (uint8_t *)message, size); + + err = k_msgq_put(&ipc_transmit_msgq, &tx_data, timeout); + if (err) { + return NRFS_ERR_IPC; + } + + err = k_work_submit(&backend_send_work); + + return err >= 0 ? 0 : NRFS_ERR_IPC; + } + + LOG_ERR("Trying to send %d bytes where max is %d.", size, MAX_PACKET_DATA_SIZE); + + return NRFS_ERR_IPC; +} + +bool nrfs_backend_connected(void) +{ + return atomic_get(&ipc_cpusys_channel_config.status) == CONNECTED; +} + +int nrfs_backend_wait_for_connection(k_timeout_t timeout) +{ + uint32_t events; + + if (nrfs_backend_connected()) { + return 0; + } + + events = k_event_wait(&ipc_connected_event, IPC_INIT_DONE_EVENT, false, timeout); + + return (events == IPC_INIT_DONE_EVENT ? 0 : (-EAGAIN)); +} + +__weak void nrfs_backend_fatal_error_handler(enum nrfs_backend_error error_id) +{ + LOG_ERR("Fatal error: %d rebooting...", error_id); + sys_reboot(SYS_REBOOT_WARM); +} + +SYS_INIT(ipc_channel_init, POST_KERNEL, CONFIG_NRFS_BACKEND_IPC_SERVICE_INIT_PRIO); diff --git a/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h new file mode 100644 index 0000000000000..572c05e864c78 --- /dev/null +++ b/modules/hal_nordic/nrfs/backends/nrfs_backend_ipc_service.h @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NRFS_BACKEND_IPC_SERVICE_H +#define NRFS_BACKEND_IPC_SERVICE_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct __packed ipc_data_packet { + uint16_t channel_id; + uint16_t size; + uint8_t data[CONFIG_NRFS_MAX_BACKEND_PACKET_SIZE]; +}; + +enum ipc_channel_status { + NOT_CONNECTED = 0, + CONNECTED = 1 +}; + +enum nrfs_backend_error { + NRFS_ERROR_EPT_RECEIVE_QUEUE_ERROR = 0, + NRFS_ERROR_EPT_RECEIVE_DATA_TOO_LONG, + NRFS_ERROR_IPC_CHANNEL_INIT, + NRFS_ERROR_SEND_DATA, + NRFS_ERROR_NO_DATA_RECEIVED, + NRFS_ERROR_IPC_OPEN_INSTANCE, + NRFS_ERROR_IPC_REGISTER_ENDPOINT, + NRFS_ERROR_BACKEND_NOT_CONNECTED, + NRFS_ERROR_COUNT +}; + +#define IPC_CPUSYS_CHANNEL_ID 0x5C + +/** + * @brief function to check if backend is connected to sysctrl + * + * @return true Backend connected. + * @return false Backend not connected. + */ +bool nrfs_backend_connected(void); + +/** + * @brief this function will block until connection or timeout expires + * + * @param timeout + * + * @return 0 Connection done. + * @return -EAGAIN Waiting period timed out. + */ +int nrfs_backend_wait_for_connection(k_timeout_t timeout); + +/** + * @brief Extended function for sending a message over the chosen transport backend. + * + * This function is used by services to send requests to the System Controller. + * + * @param[in] message Pointer to the message payload. + * @param[in] size Message payload size. + * @param[in] timeout Non-negative waiting period to add the message, + * or one of the special values K_NO_WAIT and K_FOREVER. + * @param[in] high_prio True if message should be sent with higher priority. + * + * @retval NRFS_SUCCESS Message sent successfully. + * @retval NRFS_ERR_IPC Backend returned error during message sending. + */ +nrfs_err_t nrfs_backend_send_ex(void *message, size_t size, k_timeout_t timeout, bool high_prio); + +/** + * @brief Fatal error handler for unrecoverable errors + * + * This is weak function so it can be overridden if needed. + * Error is considered fatal when there is no option to send message to sysctrl + * even after retry. Communication with sysctrl is crucial for system to work properly. + * + * @param error_id parameter to identify error. + */ +void nrfs_backend_fatal_error_handler(enum nrfs_backend_error error_id); + +#ifdef __cplusplus +} +#endif + +#endif /* NRFS_BACKEND_IPC_SERVICE_H */ diff --git a/modules/hal_nordic/nrfs/dvfs/CMakeLists.txt b/modules/hal_nordic/nrfs/dvfs/CMakeLists.txt new file mode 100644 index 0000000000000..4512a91b36aff --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library_sources_ifdef(CONFIG_NRFS_DVFS_LOCAL_DOMAIN ld_dvfs.c + ld_dvfs_handler.c) diff --git a/modules/hal_nordic/nrfs/dvfs/Kconfig b/modules/hal_nordic/nrfs/dvfs/Kconfig new file mode 100644 index 0000000000000..0a6078a0db04e --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/Kconfig @@ -0,0 +1,40 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +menu "Local domain DVFS library" + +module = LOCAL_DOMAIN_DVFS_LIB +module-str = Local domain DVFS library +source "subsys/logging/Kconfig.template.log_config" + +config NRFS_LOCAL_DOMAIN_DVFS_TEST + bool "Local domain DVFS test" + help + Disable hw registers interaction for testing. + +config NRFS_LOCAL_DOMAIN_DVFS_SCALE_DOWN_AFTER_INIT + bool "Local domain scale down after init" + help + Request lowest oppoint after DVFS initialization. + +config NRFS_LOCAL_DOMAIN_DOWNSCALE_SAFETY_TIMEOUT_US + int "Voltage downscale procedure safety timeout in us" + range 1 10000000 + default 1000000 if (NRFS_LOCAL_DOMAIN_DVFS_TEST || LOG) + default 1500 + +config NRFS_LOCAL_DOMAIN_DVFS_HANDLER_TASK_STACK_SIZE + int "Stack size used for DVFS handling task" + range 256 2048 + default 1024 if LOG + default 512 + +config NRFS_LOCAL_DOMAIN_DVFS_HANDLER_TASK_PRIORITY + int "Priority of DVFS handling task" + range -16 NUM_PREEMPT_PRIORITIES + default 0 + +endmenu diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs.c b/modules/hal_nordic/nrfs/dvfs/ld_dvfs.c new file mode 100644 index 0000000000000..883161e9f9236 --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs.c @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "ld_dvfs.h" + +#include +#include + +#include +#include +LOG_MODULE_REGISTER(LD_DVFS_LIB, CONFIG_LOCAL_DOMAIN_DVFS_LIB_LOG_LEVEL); + +#define TRANSIENT_ZBB_ABB_SLOT 0 +#define CURR_TARG_ABB_SLOT 1 +#define LD_ABB_CLR_ZBB 0 +/* TODO: this values needs to be provided by HW team */ +/* for now reset value will be used */ +#define LD_ABB_CTRL4_NORMAL_OPERATION 0x10800UL +#define LD_ABB_CTRL4_TRANSITION_OPERATION 0x10800UL + +/* + * wait max 500ms with 10us intervals for hsfll freq change event + */ +#define HSFLL_FREQ_CHANGE_MAX_DELAY_MS 500UL +#define HSFLL_FREQ_CHANGE_CHECK_INTERVAL_US 10 +#define HSFLL_FREQ_CHANGE_CHECK_MAX_ATTEMPTS \ + ((HSFLL_FREQ_CHANGE_MAX_DELAY_MS) * (USEC_PER_MSEC) / (HSFLL_FREQ_CHANGE_CHECK_INTERVAL_US)) + +#define ABB_STATUS_CHANGE_MAX_DELAY_MS 5000UL +#define ABB_STATUS_CHANGE_CHECK_INTERVAL_US 10 +#define ABB_STATUS_CHANGE_CHECK_MAX_ATTEMPTS \ + ((ABB_STATUS_CHANGE_MAX_DELAY_MS) * (USEC_PER_MSEC) / (ABB_STATUS_CHANGE_CHECK_INTERVAL_US)) + +void ld_dvfs_init(void) +{ +#if defined(NRF_SECURE) + + const struct dvfs_oppoint_data *opp_data = get_dvfs_oppoint_data(DVFS_FREQ_HIGH); + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s", __func__); + LOG_DBG("REGW: NRF_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT], + opp_data->abb_pvtmoncycles); + + /*For app core.*/ + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT], + opp_data->abb_pvtmoncycles); +#else + /* TODO: Change to NRFX Hal function when available. */ + NRF_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT] = opp_data->abb_ringo; + NRF_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT] = opp_data->abb_lockrange; + NRF_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT] = opp_data->abb_pvtmoncycles; + + NRF_APPLICATION_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT] = opp_data->abb_ringo; + NRF_APPLICATION_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT] = opp_data->abb_lockrange; + NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT] = opp_data->abb_pvtmoncycles; +#endif +#endif +} + +void ld_dvfs_clear_zbb(void) +{ +#if defined(NRF_SECURE) +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s", __func__); + LOG_DBG("REGW: NRF_ABB->CONFIG.CTRL1.MODE 0x%x, V: 0x%x", + (uint32_t)&NRF_ABB->CONFIG.CTRL1, + LD_ABB_CLR_ZBB); +#else + /* TODO: Change to NRFX Hal function when available. */ + NRF_ABB->CONFIG.CTRL1 &= ~(ABB_CONFIG_CTRL1_MODE_Msk); + NRF_APPLICATION_ABB->CONFIG.CTRL1 &= ~(ABB_CONFIG_CTRL1_MODE_Msk); +#endif +#endif +} + +#if defined(NRF_SECURE) + +#define DOWNSCALE_SAFETY_TIMEOUT (K_USEC(CONFIG_NRFS_LOCAL_DOMAIN_DOWNSCALE_SAFETY_TIMEOUT_US)) + +atomic_t increased_power_consumption; + +/** + * @brief Secure domain needs to check if downscale is done in defined time + * window. This is needed to avoid battery drain if dvfs procedure + * takes to much time (some failure?). + */ +__weak void ld_dvfs_secure_downscale_timeout(struct k_timer *timer) +{ + ARG_UNUSED(timer); + + LOG_ERR("Downscale timeout expired, reset board."); + atomic_set(&increased_power_consumption, 0); +} + +K_TIMER_DEFINE(dvfs_downscale_secure_timer, ld_dvfs_secure_downscale_timeout, NULL); + +/** + * @brief Secure domain starts increased power consumption, needed by dvfs sequence. + * This function can be reimplemented in other module if needed. + */ +__weak void ld_dvfs_secure_start_increased_power_consumption(void) +{ + LOG_INF("Start increased power consumption for DVFS sequence and start safety timer."); + k_timer_start(&dvfs_downscale_secure_timer, DOWNSCALE_SAFETY_TIMEOUT, K_NO_WAIT); + atomic_set(&increased_power_consumption, 1); + + volatile uint8_t idle_counter = 0; + + while (atomic_get(&increased_power_consumption)) { + if (idle_counter < 100) { + k_yield(); + idle_counter++; + } else { + idle_counter = 0; + k_usleep(1); + } + } +} + +/** + * @brief Secure domain stops increased power consumption at the end of downscale. + * This function can be reimplemented in other module if needed. + */ +__weak void ld_dvfs_secure_stop_increased_power_consumption(void) +{ + LOG_INF("Stop increased power consumption for DVFS sequence."); + k_timer_stop(&dvfs_downscale_secure_timer); + atomic_set(&increased_power_consumption, 0); +} + +#endif + +void ld_dvfs_configure_abb_for_transition(enum dvfs_frequency_setting transient_opp, + enum dvfs_frequency_setting curr_targ_opp) +{ +#if defined(NRF_SECURE) + const struct dvfs_oppoint_data *opp_data = get_dvfs_oppoint_data(transient_opp); + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s", __func__); + LOG_DBG("transient_opp: %d, curr_targ_opp: %d", transient_opp, curr_targ_opp); + LOG_DBG("REGW: NRF_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.RINGO[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.LOCKRANGE[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.PVTMONCYCLES[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_pvtmoncycles); + + /* For app core.*/ + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.RINGO[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.LOCKRANGE[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + TRANSIENT_ZBB_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[TRANSIENT_ZBB_ABB_SLOT], + opp_data->abb_pvtmoncycles); +#else + + NRF_ABB->TRIM.RINGO[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_ringo; + NRF_ABB->TRIM.LOCKRANGE[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_lockrange; + NRF_ABB->TRIM.PVTMONCYCLES[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_pvtmoncycles; + + NRF_APPLICATION_ABB->TRIM.RINGO[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_ringo; + NRF_APPLICATION_ABB->TRIM.LOCKRANGE[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_lockrange; + NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[TRANSIENT_ZBB_ABB_SLOT] = opp_data->abb_pvtmoncycles; +#endif + opp_data = get_dvfs_oppoint_data(curr_targ_opp); + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("REGW: NRF_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT], + opp_data->abb_pvtmoncycles); + + LOG_DBG("REGW: TODO: NRF_ABB->CONFIG.CTRL4 0x%x, V: 0x%lx", + (uint32_t)&NRF_ABB->CONFIG.CTRL4, + LD_ABB_CTRL4_TRANSITION_OPERATION); + + /* For app core */ + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.RINGO[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT], + opp_data->abb_ringo); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.LOCKRANGE[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT], + opp_data->abb_lockrange); + LOG_DBG("REGW: NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[%d] 0x%x, V: 0x%x", + CURR_TARG_ABB_SLOT, + (uint32_t)&NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT], + opp_data->abb_pvtmoncycles); + + LOG_DBG("REGW: TODO: NRF_APPLICATION_ABB->CONFIG.CTRL4 0x%x, V: 0x%lx", + (uint32_t)&NRF_APPLICATION_ABB->CONFIG.CTRL4, + LD_ABB_CTRL4_TRANSITION_OPERATION); +#else + NRF_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT] = opp_data->abb_ringo; + NRF_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT] = opp_data->abb_lockrange; + NRF_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT] = opp_data->abb_pvtmoncycles; + + NRF_ABB->CONFIG.CTRL4 = LD_ABB_CTRL4_TRANSITION_OPERATION; + + NRF_APPLICATION_ABB->TRIM.RINGO[CURR_TARG_ABB_SLOT] = opp_data->abb_ringo; + NRF_APPLICATION_ABB->TRIM.LOCKRANGE[CURR_TARG_ABB_SLOT] = opp_data->abb_lockrange; + NRF_APPLICATION_ABB->TRIM.PVTMONCYCLES[CURR_TARG_ABB_SLOT] = opp_data->abb_pvtmoncycles; + + NRF_APPLICATION_ABB->CONFIG.CTRL4 = LD_ABB_CTRL4_TRANSITION_OPERATION; + +#endif +#endif +} + +int32_t ld_dvfs_configure_hsfll(enum dvfs_frequency_setting oppoint) +{ + nrf_hsfll_trim_t hsfll_trim = {}; + + if (oppoint >= DVFS_FREQ_COUNT) { + LOG_ERR("Not valid oppoint %d", oppoint); + return -EINVAL; + } + + uint8_t freq_trim = get_dvfs_oppoint_data(oppoint)->new_f_trim_entry; + +#ifdef CONFIG_SOC_NRF54H20_CPUAPP + hsfll_trim.vsup = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.VSUP; + hsfll_trim.coarse = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.COARSE[freq_trim]; + hsfll_trim.fine = NRF_FICR->TRIM.APPLICATION.HSFLL.TRIM.FINE[freq_trim]; +#else + hsfll_trim.vsup = NRF_FICR->TRIM.SECURE.HSFLL.TRIM.VSUP; + hsfll_trim.coarse = NRF_FICR->TRIM.SECURE.HSFLL.TRIM.COARSE[freq_trim]; + hsfll_trim.fine = NRF_FICR->TRIM.SECURE.HSFLL.TRIM.FINE[freq_trim]; +#endif + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s oppoint: %d", __func__, oppoint); + LOG_DBG("REGW: NRF_HSFLL->MIRROR 0x%x, V: 0x%x", (uint32_t)&NRF_HSFLL->MIRROR, 1); + LOG_DBG("REGW: NRF_HSFLL->TRIM.COARSE 0x%x, V: 0x%x", + (uint32_t)&NRF_HSFLL->TRIM.COARSE, + hsfll_trim.coarse); + LOG_DBG("REGW: NRF_HSFLL->TRIM.FINE 0x%x, V: 0x%x", + (uint32_t)&NRF_HSFLL->TRIM.FINE, + hsfll_trim.fine); + LOG_DBG("REGW: NRF_HSFLL->MIRROR 0x%x, V: 0x%x", (uint32_t)&NRF_HSFLL->MIRROR, 0); + + LOG_DBG("REGW: NRF_HSFLL->CLOCKCTRL.MULT 0x%x, V: 0x%x", + (uint32_t)&NRF_HSFLL->CLOCKCTRL.MULT, + get_dvfs_oppoint_data(oppoint)->new_f_mult); + + LOG_DBG("REGW: NRF_HSFLL->NRF_HSFLL_TASK_FREQ_CHANGE 0x%x, V: 0x%x", + (uint32_t)NRF_HSFLL + NRF_HSFLL_TASK_FREQ_CHANGE, + 0x1); + return 0; +#else + + nrf_hsfll_trim_set(NRF_HSFLL, &hsfll_trim); + nrf_barrier_w(); + + nrf_hsfll_clkctrl_mult_set(NRF_HSFLL, get_dvfs_oppoint_data(oppoint)->new_f_mult); + nrf_hsfll_task_trigger(NRF_HSFLL, NRF_HSFLL_TASK_FREQ_CHANGE); + /* Trigger hsfll task one more time, SEE PAC-4078 */ + nrf_hsfll_task_trigger(NRF_HSFLL, NRF_HSFLL_TASK_FREQ_CHANGE); + + bool hsfll_freq_changed = false; + + NRFX_WAIT_FOR(nrf_hsfll_event_check(NRF_HSFLL, NRF_HSFLL_EVENT_FREQ_CHANGED), + HSFLL_FREQ_CHANGE_CHECK_MAX_ATTEMPTS, + HSFLL_FREQ_CHANGE_CHECK_INTERVAL_US, + hsfll_freq_changed); + + if (hsfll_freq_changed) { + return 0; + } + + return -ETIMEDOUT; +#endif +} + +void ld_dvfs_scaling_background_process(bool downscaling) +{ +#if defined(NRF_SECURE) + if (NRF_DOMAIN == NRF_DOMAIN_SECURE) { + if (downscaling) { + ld_dvfs_secure_start_increased_power_consumption(); + } + } +#endif +} + +void ld_dvfs_scaling_finish(bool downscaling) +{ +#if defined(NRF_SECURE) +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_TEST) + LOG_DBG("%s", __func__); + LOG_DBG("REGW: NRF_ABB->CONFIG.CTRL4 0x%x, V: 0x%lx", + (uint32_t)&NRF_ABB->CONFIG.CTRL4, + LD_ABB_CTRL4_NORMAL_OPERATION); + LOG_DBG("REGW: NRF_APPLICATION_ABB->CONFIG.CTRL4 0x%x, V: 0x%lx", + (uint32_t)&NRF_APPLICATION_ABB->CONFIG.CTRL4, + LD_ABB_CTRL4_NORMAL_OPERATION); +#else + NRF_ABB->CONFIG.CTRL4 = LD_ABB_CTRL4_NORMAL_OPERATION; + NRF_APPLICATION_ABB->CONFIG.CTRL4 = LD_ABB_CTRL4_NORMAL_OPERATION; +#endif + + if (NRF_DOMAIN == NRF_DOMAIN_SECURE) { + if (downscaling) { + ld_dvfs_secure_stop_increased_power_consumption(); + } + } +#endif +} diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs.h b/modules/hal_nordic/nrfs/dvfs/ld_dvfs.h new file mode 100644 index 0000000000000..947a9b5a1afd2 --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef LD_DVFS_H +#define LD_DVFS_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function for initializing the Dynamic Voltage and Frequency Scaling service + * from LD perspective.. + * + */ +void ld_dvfs_init(void); + +/** + * @brief Function for clearing the zero bias + * + */ +void ld_dvfs_clear_zbb(void); + +/** + * @brief Configure ABB registers to transition process. + * + * @param transient_opp current operation point + * @param curr_targ_opp target operation point + */ +void ld_dvfs_configure_abb_for_transition(enum dvfs_frequency_setting transient_opp, + enum dvfs_frequency_setting curr_targ_opp); + +/** + * @brief Configure hsfll depending on selected oppoint + * + * @param enum oppoint target operation point + * @return 0 value indicates no error. + * @return -EINVAL invalid oppoint or domain. + * @return -ETIMEDOUT frequency change took more than HSFLL_FREQ_CHANGE_MAX_DELAY_MS + */ +int32_t ld_dvfs_configure_hsfll(enum dvfs_frequency_setting oppoint); + +/** + * @brief Background process during scaling. + * + * @param downscaling indicates if down-scaling is running + */ +void ld_dvfs_scaling_background_process(bool downscaling); + +/** + * @brief Last step for local domain in downscale procedure + * + * @param downscaling indicates if down-scaling is running + */ +void ld_dvfs_scaling_finish(bool downscaling); + +#ifdef __cplusplus +} +#endif + +#endif /* LD_DVFS_H */ diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c new file mode 100644 index 0000000000000..20e879c4f737e --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.c @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "ld_dvfs_handler.h" +#include "ld_dvfs.h" + +#include +#include +#include + +#include +#include +LOG_MODULE_DECLARE(LD_DVFS_LIB, CONFIG_LOCAL_DOMAIN_DVFS_LIB_LOG_LEVEL); + +static K_SEM_DEFINE(dvfs_service_sync_sem, 0, 1); +static K_SEM_DEFINE(dvfs_service_idle_sem, 0, 1); + +#define DVFS_SERV_HDL_INIT_DONE_BIT_POS (0) +#define DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS (1) + +static atomic_t dvfs_service_handler_state_bits; +static enum dvfs_frequency_setting current_freq_setting; + +static void dvfs_service_handler_set_state_bit(uint32_t bit_pos) +{ + atomic_set_bit(&dvfs_service_handler_state_bits, bit_pos); +} + +static void dvfs_service_handler_clear_state_bit(uint32_t bit_pos) +{ + atomic_clear_bit(&dvfs_service_handler_state_bits, bit_pos); +} + +static bool dvfs_service_handler_get_state_bit(uint32_t bit_pos) +{ + return atomic_test_bit(&dvfs_service_handler_state_bits, bit_pos); +} + +static bool dvfs_service_handler_init_done(void) +{ + return dvfs_service_handler_get_state_bit(DVFS_SERV_HDL_INIT_DONE_BIT_POS); +} + +static bool dvfs_service_handler_freq_change_in_progress(void) +{ + return dvfs_service_handler_get_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS); +} + +static void dvfs_service_handler_nrfs_error_check(nrfs_err_t err) +{ + if (err != NRFS_SUCCESS) { + LOG_ERR("Failed with nrfs error: %d", err); + } +} + +static void dvfs_service_handler_error(int err) +{ + if (err != 0) { + LOG_ERR("Failed with error: %d", err); + } +} + +static uint32_t *get_next_context(void) +{ + static uint32_t ctx; + + ctx++; + return &ctx; +} + +static bool dvfs_service_handler_freq_setting_allowed(enum dvfs_frequency_setting freq_setting) +{ + if (freq_setting == DVFS_FREQ_HIGH || freq_setting == DVFS_FREQ_MEDLOW || + freq_setting == DVFS_FREQ_LOW) { + return true; + } + + return false; +} + +static enum dvfs_frequency_setting dvfs_service_handler_get_current_oppoint(void) +{ + LOG_INF("Current LD freq setting: %d", current_freq_setting); + return current_freq_setting; +} + +/* Function to check if current operation is down-scaling */ +static bool dvfs_service_handler_is_downscaling(enum dvfs_frequency_setting target_freq_setting) +{ + if (dvfs_service_handler_freq_setting_allowed(target_freq_setting)) { + LOG_DBG("Checking if downscaling %s", + (dvfs_service_handler_get_current_oppoint() < target_freq_setting) ? "YES" : + "NO"); + return dvfs_service_handler_get_current_oppoint() < target_freq_setting; + } + + return false; +} + +/* Function handling steps for scaling preparation. */ +static void dvfs_service_handler_prepare_to_scale(enum dvfs_frequency_setting oppoint_freq) +{ + LOG_INF("Prepare to scale, oppoint freq %d", oppoint_freq); + enum dvfs_frequency_setting new_oppoint = oppoint_freq; + enum dvfs_frequency_setting current_oppoint = dvfs_service_handler_get_current_oppoint(); + + if (new_oppoint == current_oppoint) { + LOG_INF("New oppoint is same as previous, no change"); + } else { + ld_dvfs_configure_abb_for_transition(current_oppoint, new_oppoint); + + if (dvfs_service_handler_is_downscaling(new_oppoint)) { + int32_t err = ld_dvfs_configure_hsfll(new_oppoint); + + if (err != 0) { + dvfs_service_handler_error(err); + } + } + } +} + +/* Do background job during scaling process (e.g. increased power consumption during down-scale). */ +static void dvfs_service_handler_scaling_background_job(enum dvfs_frequency_setting oppoint_freq) +{ + LOG_INF("Perform scaling background job if needed."); + if (dvfs_service_handler_is_downscaling(oppoint_freq)) { + k_sem_give(&dvfs_service_idle_sem); + } +} + +/* Perform scaling finnish procedure. */ +static void dvfs_service_handler_scaling_finish(enum dvfs_frequency_setting oppoint_freq) +{ + LOG_INF("Scaling finnish oppoint freq %d", oppoint_freq); + ld_dvfs_scaling_finish(dvfs_service_handler_is_downscaling(oppoint_freq)); + if (!dvfs_service_handler_is_downscaling(oppoint_freq)) { + int32_t err = ld_dvfs_configure_hsfll(oppoint_freq); + + if (err != 0) { + dvfs_service_handler_error(err); + } + } + current_freq_setting = oppoint_freq; +} + +/* Function to set hsfll to highest frequency when switched to ABB. */ +static void dvfs_service_handler_set_initial_hsfll_config(void) +{ + int32_t err = ld_dvfs_configure_hsfll(DVFS_FREQ_HIGH); + + current_freq_setting = DVFS_FREQ_HIGH; + if (err != 0) { + dvfs_service_handler_error(err); + } +} + +/* DVFS event handler callback function.*/ +static void nrfs_dvfs_evt_handler(nrfs_dvfs_evt_t const *p_evt, void *context) +{ + LOG_INF("%s", __func__); + switch (p_evt->type) { + case NRFS_DVFS_EVT_INIT_PREPARATION: + LOG_INF("DVFS handler EVT_INIT_PREPARATION"); +#if defined(NRF_SECURE) + ld_dvfs_clear_zbb(); + dvfs_service_handler_nrfs_error_check( + nrfs_dvfs_init_complete_request(get_next_context())); + LOG_INF("DVFS handler EVT_INIT_PREPARATION handled"); +#else + LOG_ERR("DVFS handler - unexpected EVT_INIT_PREPARATION"); +#endif + break; + case NRFS_DVFS_EVT_INIT_DONE: + LOG_INF("DVFS handler EVT_INIT_DONE"); + dvfs_service_handler_set_initial_hsfll_config(); + dvfs_service_handler_set_state_bit(DVFS_SERV_HDL_INIT_DONE_BIT_POS); + k_sem_give(&dvfs_service_sync_sem); + LOG_INF("DVFS handler EVT_INIT_DONE handled"); + break; + case NRFS_DVFS_EVT_OPPOINT_REQ_CONFIRMED: + /* Optional confirmation from sysctrl, wait for oppoint.*/ + LOG_INF("DVFS handler EVT_OPPOINT_REQ_CONFIRMED"); + break; + case NRFS_DVFS_EVT_OPPOINT_SCALING_PREPARE: + /*Target oppoint will be received here.*/ + LOG_INF("DVFS handler EVT_OPPOINT_SCALING_PREPARE"); +#if !defined(NRF_SECURE) + if (dvfs_service_handler_is_downscaling(p_evt->freq)) { +#endif + dvfs_service_handler_prepare_to_scale(p_evt->freq); + dvfs_service_handler_nrfs_error_check( + nrfs_dvfs_ready_to_scale(get_next_context())); + dvfs_service_handler_scaling_background_job(p_evt->freq); + LOG_INF("DVFS handler EVT_OPPOINT_SCALING_PREPARE handled"); +#if !defined(NRF_SECURE) + current_freq_setting = p_evt->freq; + } else { + LOG_ERR("DVFS handler - unexpected EVT_OPPOINT_SCALING_PREPARE"); + } +#endif + break; + case NRFS_DVFS_EVT_OPPOINT_SCALING_DONE: + LOG_INF("DVFS handler EVT_OPPOINT_SCALING_DONE"); + dvfs_service_handler_clear_state_bit(DVFS_SERV_HDL_FREQ_CHANGE_IN_PROGRESS_BIT_POS); + dvfs_service_handler_scaling_finish(p_evt->freq); + LOG_INF("DVFS handler EVT_OPPOINT_SCALING_DONE handled"); + break; + case NRFS_DVFS_EVT_REJECT: + LOG_ERR("DVFS handler - request rejected"); + break; + default: + LOG_ERR("DVFS handler - unexpected event: 0x%x", p_evt->type); + break; + } +} + +/* Task to handle dvfs init procedure. */ +static void dvfs_service_handler_task(void *dummy0, void *dummy1, void *dummy2) +{ + ARG_UNUSED(dummy0); + ARG_UNUSED(dummy1); + ARG_UNUSED(dummy2); + + LOG_INF("Trim ABB for default voltage."); + ld_dvfs_init(); + + LOG_INF("Waiting for backend init"); + /* Wait for ipc initialization */ + nrfs_backend_wait_for_connection(K_FOREVER); + + nrfs_err_t status; + + LOG_INF("nrfs_dvfs_init"); + status = nrfs_dvfs_init(nrfs_dvfs_evt_handler); + dvfs_service_handler_nrfs_error_check(status); + + LOG_INF("nrfs_dvfs_init_prepare_request"); + status = nrfs_dvfs_init_prepare_request(get_next_context()); + dvfs_service_handler_nrfs_error_check(status); + + /* Wait for init*/ + k_sem_take(&dvfs_service_sync_sem, K_FOREVER); + + LOG_INF("DVFS init done."); + +#if defined(CONFIG_NRFS_LOCAL_DOMAIN_DVFS_SCALE_DOWN_AFTER_INIT) + LOG_INF("Requesting lowest frequency oppoint."); + dvfs_service_handler_change_freq_setting(DVFS_FREQ_LOW); +#endif + + while (1) { + k_sem_take(&dvfs_service_idle_sem, K_FOREVER); + /* perform background processing */ + ld_dvfs_scaling_background_process(true); + } +} + +K_THREAD_DEFINE(dvfs_service_handler_task_id, + CONFIG_NRFS_LOCAL_DOMAIN_DVFS_HANDLER_TASK_STACK_SIZE, + dvfs_service_handler_task, + NULL, + NULL, + NULL, + CONFIG_NRFS_LOCAL_DOMAIN_DVFS_HANDLER_TASK_PRIORITY, + 0, + 0); + +int32_t dvfs_service_handler_change_freq_setting(enum dvfs_frequency_setting freq_setting) +{ + if (!dvfs_service_handler_init_done()) { + LOG_INF("Init not done!"); + return -EAGAIN; + } + + if (dvfs_service_handler_freq_change_in_progress()) { + LOG_INF("Frequency change in progress."); + return -EBUSY; + } + + if (!dvfs_service_handler_freq_setting_allowed(freq_setting)) { + return -ENXIO; + } + + nrfs_err_t status = nrfs_dvfs_oppoint_request(freq_setting, get_next_context()); + + dvfs_service_handler_nrfs_error_check(status); + + return status; +} diff --git a/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h new file mode 100644 index 0000000000000..b15e630eb2c89 --- /dev/null +++ b/modules/hal_nordic/nrfs/dvfs/ld_dvfs_handler.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#ifndef LD_DVFS_HANDLER_H +#define LD_DVFS_HANDLER_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Function to request LD frequency change. + * + * @param frequency requested frequency setting from enum dvfs_frequency_setting. + * @return EBUSY Frequency change in progress. + * @return EAGAIN DVFS init in progress. + * @return ENXIO Not supported frequency settings. + * @return NRFS_SUCCESS Request sent successfully. + * @return NRFS_ERR_INVALID_STATE Service is uninitialized. + * @return NRFS_ERR_IPC Backend returned error during request sending. + */ +int32_t dvfs_service_handler_change_freq_setting(enum dvfs_frequency_setting freq_setting); + +#ifdef __cplusplus +} +#endif + +#endif /* LD_DVFS_HANDLER_H */ diff --git a/modules/hal_nordic/nrfs/nrfs_config.h b/modules/hal_nordic/nrfs/nrfs_config.h new file mode 100644 index 0000000000000..20cf6cece0e3e --- /dev/null +++ b/modules/hal_nordic/nrfs/nrfs_config.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef NRFS_CONFIG_H +#define NRFS_CONFIG_H + + +#ifdef CONFIG_NRFS_TEMP_SERVICE_ENABLED +#define NRFS_TEMP_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_MRAM_SERVICE_ENABLED +#define NRFS_MRAM_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_RESET_SERVICE_ENABLED +#define NRFS_RESET_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_VBUS_DETECTOR_SERVICE_ENABLED +#define NRFS_VBUS_DETECTOR_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_PMIC_SERVICE_ENABLED +#define NRFS_PMIC_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_DVFS_SERVICE_ENABLED +#define NRFS_DVFS_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_DIAG_SERVICE_ENABLED +#define NRFS_DIAG_SERVICE_ENABLED +#endif + +#ifdef CONFIG_NRFS_CLOCK_SERVICE_ENABLED +#define NRFS_CLOCK_SERVICE_ENABLED +#endif + +#ifdef CONFIG_SOC_POSIX +#define NRFS_UNIT_TESTS_ENABLED +#endif + +#endif /* NRFS_CONFIG_H */ diff --git a/modules/hal_nordic/nrfx/CMakeLists.txt b/modules/hal_nordic/nrfx/CMakeLists.txt index 55911170d968f..5ad29dddc4632 100644 --- a/modules/hal_nordic/nrfx/CMakeLists.txt +++ b/modules/hal_nordic/nrfx/CMakeLists.txt @@ -45,6 +45,8 @@ zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54H20_CPUPPR NRF54H20_XXAA zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54L15_ENGA NRF54L15_ENGA_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54L15_ENGA_CPUAPP NRF_APPLICATION) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF54L15_ENGA_CPUFLPR NRF_FLPR) +zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF54L15 NRF54L15_XXAA) +zephyr_compile_definitions_ifdef(CONFIG_SOC_COMPATIBLE_NRF54L15_CPUAPP NRF_APPLICATION) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF9120 NRF9120_XXAA) zephyr_compile_definitions_ifdef(CONFIG_SOC_NRF9160 NRF9160_XXAA) @@ -108,6 +110,7 @@ zephyr_library_sources_ifdef(CONFIG_NRFX_PWM ${SRC_DIR}/nrfx_pwm.c) zephyr_library_sources_ifdef(CONFIG_NRFX_QDEC ${SRC_DIR}/nrfx_qdec.c) zephyr_library_sources_ifdef(CONFIG_NRFX_QSPI ${SRC_DIR}/nrfx_qspi.c) zephyr_library_sources_ifdef(CONFIG_NRFX_RNG ${SRC_DIR}/nrfx_rng.c) +zephyr_library_sources_ifdef(CONFIG_NRFX_RRAMC ${SRC_DIR}/nrfx_rramc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_RTC ${SRC_DIR}/nrfx_rtc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_SAADC ${SRC_DIR}/nrfx_saadc.c) zephyr_library_sources_ifdef(CONFIG_NRFX_SPI ${SRC_DIR}/nrfx_spi.c) @@ -128,10 +131,6 @@ if(CONFIG_NRFX_TWI OR CONFIG_NRFX_TWIM) zephyr_library_sources(${SRC_DIR}/nrfx_twi_twim.c) endif() -if (CONFIG_NRF_GRTC_TIMER AND CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT) - zephyr_compile_definitions(NRF_GRTC_HAS_EXTENDED=1) -endif() - # Inject HAL "CONFIG_NFCT_PINS_AS_GPIOS" definition if user requests to # configure the NFCT pins as GPIOS. Do the same with "CONFIG_GPIO_AS_PINRESET" # to configure the reset GPIO as nRESET. This way, the HAL will take care of diff --git a/modules/hal_nordic/nrfx/Kconfig b/modules/hal_nordic/nrfx/Kconfig index 32386d54274dc..10ecd585ef3f4 100644 --- a/modules/hal_nordic/nrfx/Kconfig +++ b/modules/hal_nordic/nrfx/Kconfig @@ -265,6 +265,10 @@ config NRFX_RNG bool "RNG driver" depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_NRF_RNG)) +config NRFX_RRAMC + bool "RRAMC driver" + depends on $(dt_has_compat,$(DT_COMPAT_NORDIC_RRAM_CONTROLLER)) + config NRFX_RTC bool @@ -946,7 +950,6 @@ config NRFX_UARTE_CONFIG_TX_LINK config NRFX_UARTE_CONFIG_RX_CACHE_ENABLED bool "UARTE RX caching support" - default y if $(dt_nodelabel_has_compat,shared_ram3x_region,$(DT_COMPAT_NORDIC_OWNED_MEMORY)) depends on NRFX_UARTE help Feature might be enabled on platforms which has limitations regarding addresses @@ -980,6 +983,16 @@ config NRFX_WDT31 depends on $(dt_nodelabel_has_compat,wdt31,$(DT_COMPAT_NORDIC_NRF_WDT)) select NRFX_WDT +config NRFX_WDT010 + bool "WDT010 driver instance" + depends on $(dt_nodelabel_has_compat,wdt010,$(DT_COMPAT_NORDIC_NRF_WDT)) + select NRFX_WDT + +config NRFX_WDT011 + bool "WDT011 driver instance" + depends on $(dt_nodelabel_has_compat,wdt011,$(DT_COMPAT_NORDIC_NRF_WDT)) + select NRFX_WDT + config NRFX_WDT130 bool "WDT130 driver instance" depends on $(dt_nodelabel_has_compat,wdt130,$(DT_COMPAT_NORDIC_NRF_WDT)) diff --git a/modules/hal_nordic/nrfx/nrfx_config.h b/modules/hal_nordic/nrfx/nrfx_config.h index 284147ba0006c..d1f9314954ae5 100644 --- a/modules/hal_nordic/nrfx/nrfx_config.h +++ b/modules/hal_nordic/nrfx/nrfx_config.h @@ -32,7 +32,7 @@ #endif #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC -#if defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_COMPATIBLE_NRF53X) #define NRFX_CLOCK_CONFIG_LF_SRC 1 #else #define NRFX_CLOCK_CONFIG_LF_SRC 0 @@ -40,7 +40,7 @@ #endif // CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL -#if defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_SERIES_NRF53X) +#if defined(CONFIG_SOC_SERIES_NRF91X) || defined(CONFIG_SOC_COMPATIBLE_NRF53X) #define NRFX_CLOCK_CONFIG_LF_SRC 2 #else #define NRFX_CLOCK_CONFIG_LF_SRC 1 @@ -48,7 +48,7 @@ #endif // CONFIG_CLOCK_CONTROL_NRF_K32SRC_XTAL #ifdef CONFIG_CLOCK_CONTROL_NRF_K32SRC_SYNTH -#ifdef CONFIG_SOC_SERIES_NRF53X +#ifdef CONFIG_SOC_COMPATIBLE_NRF53X #define NRFX_CLOCK_CONFIG_LF_SRC 3 #else #define NRFX_CLOCK_CONFIG_LF_SRC 2 @@ -120,6 +120,19 @@ #define NRFX_GRTC_CONFIG_LOG_ENABLED 1 #endif +#ifdef CONFIG_NRF_GRTC_TIMER_CLOCK_MANAGEMENT +#define NRF_GRTC_HAS_EXTENDED 1 +#endif +#ifdef CONFIG_NRF_GRTC_SLEEP_ALLOWED +#define NRFX_GRTC_CONFIG_SLEEP_ALLOWED 1 +#endif +#ifdef CONFIG_NRF_GRTC_TIMER_AUTO_KEEP_ALIVE +#define NRFX_GRTC_CONFIG_AUTOEN 1 +#endif +#ifdef CONFIG_NRF_GRTC_START_SYSCOUNTER +#define NRFX_GRTC_CONFIG_AUTOSTART 1 +#endif + #ifdef CONFIG_NRFX_GPIOTE #define NRFX_GPIOTE_ENABLED 1 #endif @@ -312,6 +325,10 @@ #define NRFX_RNG_CONFIG_LOG_ENABLED 1 #endif +#ifdef CONFIG_NRFX_RRAMC +#define NRFX_RRAMC_ENABLED 1 +#endif + #ifdef CONFIG_NRFX_RTC #define NRFX_RTC_ENABLED 1 #endif @@ -491,7 +508,7 @@ #define NRFX_SPIS136_ENABLED 1 #endif #ifdef CONFIG_NRFX_SPIS137 -#define NRFX_SPIS130_ENABLED 1 +#define NRFX_SPIS137_ENABLED 1 #endif #ifdef CONFIG_NRFX_SYSTICK @@ -824,6 +841,12 @@ #ifdef CONFIG_NRFX_WDT31 #define NRFX_WDT31_ENABLED 1 #endif +#ifdef CONFIG_NRFX_WDT010 +#define NRFX_WDT010_ENABLED 1 +#endif +#ifdef CONFIG_NRFX_WDT011 +#define NRFX_WDT011_ENABLED 1 +#endif #ifdef CONFIG_NRFX_WDT130 #define NRFX_WDT130_ENABLED 1 #endif diff --git a/modules/hal_nordic/nrfx/nrfx_glue.h b/modules/hal_nordic/nrfx/nrfx_glue.h index 593aff6fcc7a3..0f480a70f494a 100644 --- a/modules/hal_nordic/nrfx/nrfx_glue.h +++ b/modules/hal_nordic/nrfx/nrfx_glue.h @@ -334,8 +334,11 @@ void nrfx_busy_wait(uint32_t usec_to_wait); NRFX_PPI_GROUPS_USED_BY_802154_DRV | \ NRFX_PPI_GROUPS_USED_BY_MPSL) -/** @brief Bitmask that defines GPIOTE channels that are reserved for use outside of the nrfx library. */ -#define NRFX_GPIOTE_CHANNELS_USED NRFX_GPIOTE_CHANNELS_USED_BY_BT_CTLR +/** @brief Bitmask that defines GPIOTE130 channels reserved for use outside of the nrfx library. */ +#define NRFX_GPIOTE130_CHANNELS_USED \ + (~NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), owned_channels) | \ + NRFX_CONFIG_MASK_DT(DT_NODELABEL(gpiote130), child_owned_channels)) + #if defined(CONFIG_BT_CTLR) /* @@ -348,11 +351,9 @@ void nrfx_busy_wait(uint32_t usec_to_wait); #include #define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_CHANNELS #define NRFX_PPI_GROUPS_USED_BY_BT_CTLR BT_CTLR_USED_PPI_GROUPS -#define NRFX_GPIOTE_CHANNELS_USED_BY_BT_CTLR BT_CTLR_USED_GPIOTE_CHANNELS #else #define NRFX_PPI_CHANNELS_USED_BY_BT_CTLR 0 #define NRFX_PPI_GROUPS_USED_BY_BT_CTLR 0 -#define NRFX_GPIOTE_CHANNELS_USED_BY_BT_CTLR 0 #endif #if defined(CONFIG_NRF_802154_RADIO_DRIVER) @@ -368,6 +369,10 @@ void nrfx_busy_wait(uint32_t usec_to_wait); #include <../src/nrf_802154_peripherals_nrf54l.h> #define NRFX_PPI_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK #define NRFX_PPI_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK +#elif defined(NRF54H_SERIES) +#include <../src/nrf_802154_peripherals_nrf54h.h> +#define NRFX_PPI_CHANNELS_USED_BY_802154_DRV NRF_802154_DPPI_CHANNELS_USED_MASK +#define NRFX_PPI_GROUPS_USED_BY_802154_DRV NRF_802154_DPPI_GROUPS_USED_MASK #else #error Unsupported chip family #endif diff --git a/modules/hal_nxp/CMakeLists.txt b/modules/hal_nxp/CMakeLists.txt index 2f2e53d22ea85..98075e4b1e6b8 100644 --- a/modules/hal_nxp/CMakeLists.txt +++ b/modules/hal_nxp/CMakeLists.txt @@ -1,5 +1,6 @@ # # Copyright (c) 2021 Linaro, Limited +# Copyright 2024 NXP # # SPDX-License-Identifier: Apache-2.0 # @@ -7,6 +8,7 @@ if(CONFIG_HAS_MCUX OR CONFIG_HAS_IMX_HAL OR CONFIG_HAS_NXP_S32_HAL) add_subdirectory(${ZEPHYR_CURRENT_MODULE_DIR} hal_nxp) add_subdirectory_ifdef(CONFIG_USB_DEVICE_DRIVER usb) + add_subdirectory_ifdef(CONFIG_UDC_DRIVER usb) zephyr_sources_ifdef(CONFIG_PWM_MCUX_CTIMER ${ZEPHYR_CURRENT_MODULE_DIR}/mcux/mcux-sdk/drivers/ctimer/fsl_ctimer.c) zephyr_include_directories_ifdef(CONFIG_PWM_MCUX_CTIMER @@ -22,5 +24,8 @@ if(CONFIG_HAS_MCUX OR CONFIG_HAS_IMX_HAL OR CONFIG_HAS_NXP_S32_HAL) if(CONFIG_NOCACHE_MEMORY) zephyr_compile_definitions_ifdef(CONFIG_USB_DEVICE_DRIVER DATA_SECTION_IS_CACHEABLE=1) + zephyr_compile_definitions_ifdef(CONFIG_UDC_DRIVER DATA_SECTION_IS_CACHEABLE=1) endif() + + add_subdirectory_ifdef(CONFIG_BT_H4_NXP_CTLR bt_controller) endif() diff --git a/modules/hal_nxp/bt_controller/CMakeLists.txt b/modules/hal_nxp/bt_controller/CMakeLists.txt new file mode 100644 index 0000000000000..af3678364d30a --- /dev/null +++ b/modules/hal_nxp/bt_controller/CMakeLists.txt @@ -0,0 +1,21 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +set(hal_nxp_dir ${ZEPHYR_HAL_NXP_MODULE_DIR}) +set(hal_nxp_blobs_dir ${hal_nxp_dir}/zephyr/blobs) +set(blob_gen_file ${ZEPHYR_BINARY_DIR}/include/generated/bt_nxp_ctlr_fw.h) + +if(CONFIG_BT_NXP_NW612) + set(blob_file ${hal_nxp_blobs_dir}/iw612/uart_nw61x_se.h) +endif() + +if (NOT DEFINED blob_file) + message(FATAL_ERROR "Unsupported controller. Please select a BT conntroller, refer to ./driver/bluetooth/hci/Kconfig.nxp") +endif() + +zephyr_blobs_verify(FILES ${blob_file} REQUIRED) + +configure_file(${blob_file} ${blob_gen_file} COPYONLY) diff --git a/modules/hal_nxp/usb/CMakeLists.txt b/modules/hal_nxp/usb/CMakeLists.txt index 380aa3aef87af..da427e3601b8c 100644 --- a/modules/hal_nxp/usb/CMakeLists.txt +++ b/modules/hal_nxp/usb/CMakeLists.txt @@ -1,6 +1,9 @@ # -# Copyright (c) 2021, NXP +# Copyright (c) 2021,2024 NXP # # SPDX-License-Identifier: Apache-2.0 # zephyr_include_directories(.) +if(CONFIG_DT_HAS_NXP_USBPHY_ENABLED) +zephyr_include_directories(${ZEPHYR_HAL_NXP_MODULE_DIR}/mcux/middleware/mcux-sdk-middleware-usb/phy) +endif() diff --git a/modules/hal_nxp/usb/usb_device_config.h b/modules/hal_nxp/usb/usb_device_config.h index 31a62ffbfebc5..a97d9181c1b11 100644 --- a/modules/hal_nxp/usb/usb_device_config.h +++ b/modules/hal_nxp/usb/usb_device_config.h @@ -13,6 +13,7 @@ /****************************************************************************** * Definitions *****************************************************************************/ +#ifdef CONFIG_USB_DEVICE_DRIVER /* EHCI instance count */ #ifdef CONFIG_USB_DC_NXP_EHCI #define USB_DEVICE_CONFIG_EHCI (1U) @@ -51,5 +52,57 @@ BUILD_ASSERT(NUM_INSTS <= 1, "Only one USB device supported"); /* Number of endpoints supported */ #define USB_DEVICE_CONFIG_ENDPOINTS (DT_INST_PROP(0, num_bidir_endpoints)) +#else + +#ifdef CONFIG_UDC_NXP_EHCI +#define USB_DEVICE_CONFIG_EHCI (DT_NUM_INST_STATUS_OKAY(nxp_ehci)) +#endif + +#ifdef CONFIG_UDC_NXP_IP3511 + +#if defined(USBHSD_BASE_ADDRS) && defined(USB_BASE_ADDRS) +#define USB_DEVICE_CONFIG_LPCIP3511HS (1U) +#define USB_DEVICE_CONFIG_LPCIP3511FS (1U) + +#else + +#ifdef USBHSD_BASE_ADDRS +#define USB_DEVICE_CONFIG_LPCIP3511HS (DT_NUM_INST_STATUS_OKAY(nxp_lpcip3511)) +#else +#define USB_DEVICE_CONFIG_LPCIP3511HS (0U) +#endif + +#ifdef USB_BASE_ADDRS +#define USB_DEVICE_CONFIG_LPCIP3511FS (DT_NUM_INST_STATUS_OKAY(nxp_lpcip3511)) +#else +#define USB_DEVICE_CONFIG_LPCIP3511FS (0U) +#endif + +#endif +#endif + +/* calculte the num of endponts. + * mcux ip3511 driver doesn't use USB_DEVICE_CONFIG_ENDPOINTS, + * so use ehci endpoint number if ehci is enabled. + */ +#if DT_HAS_COMPAT_STATUS_OKAY(nxp_ehci) +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_ehci +#elif DT_HAS_COMPAT_STATUS_OKAY(nxp_lpcip3511) +#undef DT_DRV_COMPAT +#define DT_DRV_COMPAT nxp_lpcip3511 +#endif + +/* Number of endpoints supported */ +#define USB_DEVICE_CONFIG_ENDPOINTS (DT_INST_PROP(0, num_bidir_endpoints)) + +#define USB_DEVICE_CONFIG_SELF_POWER (1U) + +#if ((defined(USB_DEVICE_CONFIG_EHCI)) && (USB_DEVICE_CONFIG_EHCI > 0U)) +/*! @brief How many the DTD are supported. */ +#define USB_DEVICE_CONFIG_EHCI_MAX_DTD (16U) +#endif + +#endif #endif /* __USB_DEVICE_CONFIG_H__ */ diff --git a/modules/hostap/CMakeLists.txt b/modules/hostap/CMakeLists.txt index b340c3882c8b7..a7e3aa334bdfa 100644 --- a/modules/hostap/CMakeLists.txt +++ b/modules/hostap/CMakeLists.txt @@ -25,7 +25,6 @@ zephyr_library_compile_definitions( TLS_DEFAULT_CIPHERS=\""DEFAULT:!EXP:!LOW"\" CONFIG_SME CONFIG_NO_CONFIG_WRITE - CONFIG_NO_CONFIG_BLOBS CONFIG_CTRL_IFACE CONFIG_NO_RANDOM_POOL CONFIG_SHA256 @@ -76,10 +75,6 @@ zephyr_library_include_directories( ${ZEPHYR_BASE}/include/net ) -zephyr_library_compile_definitions_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO - CONFIG_NO_PBKDF2 -) - zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_NO_DEBUG CONFIG_NO_STDOUT_DEBUG ) @@ -225,17 +220,6 @@ zephyr_library_sources_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE ${HOSTAP_SRC_BASE}/rsn_supp/wpa.c ${HOSTAP_SRC_BASE}/rsn_supp/preauth.c ${HOSTAP_SRC_BASE}/rsn_supp/wpa_ie.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-bignum.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-ec.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls.c - ${HOSTAP_SRC_BASE}/crypto/tls_mbedtls.c - ${HOSTAP_SRC_BASE}/crypto/aes-wrap.c - ${HOSTAP_SRC_BASE}/crypto/aes-unwrap.c - ${HOSTAP_SRC_BASE}/crypto/rc4.c - ${HOSTAP_SRC_BASE}/crypto/sha1-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha384-prf.c ) zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3 @@ -243,7 +227,6 @@ zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3 ${HOSTAP_SRC_BASE}/common/dragonfly.c ${HOSTAP_SRC_BASE}/crypto/dh_groups.c - ${HOSTAP_SRC_BASE}/crypto/sha256-kdf.c ) zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3 @@ -255,9 +238,6 @@ zephyr_library_include_directories_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_N ${CMAKE_SOURCE_DIR} ) -zephyr_library_link_libraries_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE - mbedTLS) - zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_P2P ${WIFI_NM_WPA_SUPPLICANT_BASE}/p2p_supplicant.c ${WIFI_NM_WPA_SUPPLICANT_BASE}/p2p_supplicant_sd.c @@ -305,28 +285,10 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPS EAP_WSC ) -zephyr_library_sources_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE - ${HOSTAP_SRC_BASE}/common/wpa_common.c - ${HOSTAP_SRC_BASE}/rsn_supp/wpa.c - ${HOSTAP_SRC_BASE}/rsn_supp/preauth.c - ${HOSTAP_SRC_BASE}/rsn_supp/wpa_ie.c - - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-bignum.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-ec.c - ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls.c - ${HOSTAP_SRC_BASE}/crypto/aes-wrap.c - ${HOSTAP_SRC_BASE}/crypto/aes-unwrap.c - ${HOSTAP_SRC_BASE}/crypto/rc4.c - ${HOSTAP_SRC_BASE}/crypto/sha1-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c - ${HOSTAP_SRC_BASE}/crypto/sha384-prf.c -) - zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE - ${HOSTAP_SRC_BASE}/crypto/tls_mbedtls.c ${HOSTAP_SRC_BASE}/eap_peer/eap_tls.c ${HOSTAP_SRC_BASE}/eap_peer/eap_tls_common.c + ${HOSTAP_SRC_BASE}/eap_common/eap_common.c ${HOSTAP_SRC_BASE}/eap_peer/eap_peap.c ${HOSTAP_SRC_BASE}/eap_common/eap_peap_common.c @@ -364,17 +326,10 @@ zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE ${HOSTAP_SRC_BASE}/eap_common/eap_ikev2_common.c ${HOSTAP_SRC_BASE}/eap_common/ikev2_common.c - # common - ${HOSTAP_SRC_BASE}/crypto/sha384-tlsprf.c - ${HOSTAP_SRC_BASE}/crypto/sha256-tlsprf.c - ${HOSTAP_SRC_BASE}/crypto/sha1-tlsprf.c - ${HOSTAP_SRC_BASE}/crypto/sha1-tprf.c - ${HOSTAP_SRC_BASE}/crypto/ms_funcs.c - ${HOSTAP_SRC_BASE}/crypto/aes-eax.c - # MD4 removed from MbedTLS - ${HOSTAP_SRC_BASE}/crypto/md4-internal - ${HOSTAP_SRC_BASE}/crypto/aes-encblock.c + ${HOSTAP_SRC_BASE}/eap_peer/eap_sim.c + ${HOSTAP_SRC_BASE}/eap_common/eap_sim_common.c + ${HOSTAP_SRC_BASE}/eap_peer/eap_aka.c ) zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE @@ -410,4 +365,101 @@ zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_EAPOL zephyr_library_compile_definitions_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_NW_SEL_RELIABILITY CONFIG_NW_SEL_RELIABILITY ) + +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_DPP + ${WIFI_NM_WPA_SUPPLICANT_BASE}/dpp_supplicant.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/offchannel.c + ${WIFI_NM_WPA_SUPPLICANT_BASE}/gas_query.c + + ${HOSTAP_SRC_BASE}/ap/dpp_hostapd.c + ${HOSTAP_SRC_BASE}/ap/gas_query_ap.c + ${HOSTAP_SRC_BASE}/ap/gas_serv.c + + ${HOSTAP_SRC_BASE}/common/dpp_tcp.c + ${HOSTAP_SRC_BASE}/common/dpp.c + ${HOSTAP_SRC_BASE}/common/dpp_pkex.c + ${HOSTAP_SRC_BASE}/common/dpp_crypto.c + ${HOSTAP_SRC_BASE}/common/dpp_auth.c + ${HOSTAP_SRC_BASE}/common/dpp_reconfig.c + ${HOSTAP_SRC_BASE}/common/gas_server.c + ${HOSTAP_SRC_BASE}/common/gas.c + ${HOSTAP_SRC_BASE}/common/dpp_backup.c + + ${HOSTAP_SRC_BASE}/crypto/aes-siv.c + + ${HOSTAP_SRC_BASE}/utils/json.c + ${HOSTAP_SRC_BASE}/utils/ip_addr.c + + ${HOSTAP_SRC_BASE}/tls/asn1.c +) + +# crypto mbedtls related +if(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO) +zephyr_library_sources( + ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-bignum.c + ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls-ec.c + ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls.c + ${HOSTAP_SRC_BASE}/crypto/tls_mbedtls.c + ${HOSTAP_SRC_BASE}/crypto/aes-internal.c + ${HOSTAP_SRC_BASE}/crypto/aes-wrap.c + ${HOSTAP_SRC_BASE}/crypto/aes-unwrap.c + ${HOSTAP_SRC_BASE}/crypto/rc4.c + ${HOSTAP_SRC_BASE}/crypto/sha1-internal.c + ${HOSTAP_SRC_BASE}/crypto/sha1-prf.c + ${HOSTAP_SRC_BASE}/crypto/sha1-tlsprf.c + ${HOSTAP_SRC_BASE}/crypto/sha256-prf.c + ${HOSTAP_SRC_BASE}/crypto/sha256-kdf.c + ${HOSTAP_SRC_BASE}/crypto/sha384-prf.c + ${HOSTAP_SRC_BASE}/crypto/sha384-kdf.c + ${HOSTAP_SRC_BASE}/crypto/sha512-internal.c + ${HOSTAP_SRC_BASE}/crypto/sha512.c + ${HOSTAP_SRC_BASE}/crypto/sha512-prf.c + ${HOSTAP_SRC_BASE}/crypto/sha512-kdf.c +) + +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_WPA3 + ${HOSTAP_SRC_BASE}/crypto/sha256-kdf.c +) + +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + # common + ${HOSTAP_SRC_BASE}/crypto/sha384-tlsprf.c + ${HOSTAP_SRC_BASE}/crypto/sha256-tlsprf.c + ${HOSTAP_SRC_BASE}/crypto/sha1-tlsprf.c + ${HOSTAP_SRC_BASE}/crypto/sha1-tprf.c + ${HOSTAP_SRC_BASE}/crypto/ms_funcs.c + ${HOSTAP_SRC_BASE}/crypto/aes-eax.c + # MD4 removed from MbedTLS + ${HOSTAP_SRC_BASE}/crypto/md4-internal.c + ${HOSTAP_SRC_BASE}/crypto/aes-encblock.c +) +endif() + +if(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT) +zephyr_include_directories( + ${HOSTAP_BASE}/port/mbedtls +) + +zephyr_library_sources( + ${HOSTAP_SRC_BASE}/crypto/crypto_mbedtls_alt.c + ${HOSTAP_SRC_BASE}/crypto/tls_mbedtls_alt.c + ${HOSTAP_SRC_BASE}/crypto/rc4.c +) + +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA + ${HOSTAP_BASE}/port/mbedtls/supp_psa_api.c +) + +zephyr_library_sources_ifdef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE + ${HOSTAP_SRC_BASE}/crypto/ms_funcs.c + ${HOSTAP_SRC_BASE}/crypto/aes-eax.c + ${HOSTAP_SRC_BASE}/crypto/md4-internal.c + ${HOSTAP_SRC_BASE}/crypto/fips_prf_internal.c + ${HOSTAP_SRC_BASE}/crypto/milenage.c +) +endif() + +zephyr_library_link_libraries_ifndef(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE + mbedTLS) + endif() diff --git a/modules/hostap/Kconfig b/modules/hostap/Kconfig index 473b6278055cf..f90ab2c0b8833 100644 --- a/modules/hostap/Kconfig +++ b/modules/hostap/Kconfig @@ -7,8 +7,8 @@ config WIFI_NM_WPA_SUPPLICANT bool "WPA Suplicant from hostap project [EXPERIMENTAL]" - select POSIX_CLOCK - select POSIX_SIGNAL + select POSIX_TIMERS + select POSIX_SIGNALS select POSIX_API select NET_SOCKETS select NET_SOCKETS_PACKET @@ -41,7 +41,7 @@ config WIFI_NM_WPA_SUPPLICANT_WQ_PRIO int "Thread priority of wpa_supplicant iface workqueue" default 7 -# Currently we default POSIX_MAX_FDS to 16 in lib/posix/Kconfig +# Currently we default ZVFS_OPEN_MAX to 16 in lib/posix/Kconfig # l2_packet - 1 # ctrl_iface - 2 * socketpairs = 4(local and global) # z_wpa_event_sock - 1 socketpair = 2 @@ -106,6 +106,8 @@ choice WIFI_NM_WPA_SUPPLICANT_CRYPTO_BACKEND default WIFI_NM_WPA_SUPPLICANT_CRYPTO help Select the crypto implementation to use for WPA supplicant. + WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT support enterprise + and DPP. And use Mbedtls PSA apis for HW acceleration. config WIFI_NM_WPA_SUPPLICANT_CRYPTO bool "Crypto support for WiFi" @@ -114,7 +116,7 @@ config WIFI_NM_WPA_SUPPLICANT_CRYPTO select MBEDTLS_CIPHER_MODE_CBC_ENABLED select MBEDTLS_ECP_C select MBEDTLS_ECP_ALL_ENABLED - select MBEDTLS_MAC_CMAC_ENABLED + select MBEDTLS_CMAC select MBEDTLS_PKCS5_C select MBEDTLS_PK_WRITE_C select MBEDTLS_ECDH_C @@ -125,11 +127,37 @@ config WIFI_NM_WPA_SUPPLICANT_CRYPTO select MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED select MBEDTLS_KEY_EXCHANGE_ALL_ENABLED +config WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT + bool "Crypto Mbedtls alt support for WiFi" + select MBEDTLS + select MBEDTLS_CIPHER_MODE_CTR_ENABLED + select MBEDTLS_CIPHER_MODE_CBC_ENABLED + select MBEDTLS_ECP_C + select MBEDTLS_ECP_ALL_ENABLED + select MBEDTLS_CMAC + select MBEDTLS_PKCS5_C + select MBEDTLS_PK_WRITE_C + select MBEDTLS_ECDH_C + select MBEDTLS_ECDSA_C + select MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + select MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + select MBEDTLS_NIST_KW_C + select MBEDTLS_DHM_C + select MBEDTLS_HKDF_C + select MBEDTLS_SERVER_NAME_INDICATION + select MBEDTLS_X509_CRL_PARSE_C + config WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE bool "No Crypto support for WiFi" endchoice +config WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA + bool "Crypto Platform Secure Architecture support for WiFi" + default y if WIFI_NM_WPA_SUPPLICANT_CRYPTO_ALT + help + Support Mbedtls 3.x to use PSA apis instead of legacy apis. + config WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE bool "Enterprise Crypto support for WiFi" depends on !WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE @@ -174,6 +202,18 @@ config WIFI_NM_WPA_SUPPLICANT_BSS_MAX_IDLE_TIME config WIFI_NM_WPA_SUPPLICANT_NO_DEBUG bool "Disable printing of debug messages, saves code size significantly" + +config WIFI_NM_WPA_SUPPLICANT_DPP + bool "WFA Easy Connect DPP" + select DPP + select DPP2 + select DPP3 + select GAS + select GAS_SERVER + select OFFCHANNEL + select MBEDTLS_X509_CSR_WRITE_C + select MBEDTLS_X509_CSR_PARSE_C + # Create hidden config options that are used in hostap. This way we do not need # to mark them as allowed for CI checks, and also someone else cannot use the # same name options. @@ -188,7 +228,7 @@ config NO_CONFIG_WRITE config NO_CONFIG_BLOBS bool - default y + default y if !WIFI_NM_WPA_SUPPLICANT_DPP && !WIFI_NM_WPA_SUPPLICANT_CRYPTO_ENTERPRISE config CTRL_IFACE bool @@ -211,7 +251,7 @@ config NO_WPA config NO_PBKDF2 bool - default y + default y if WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE config SAE_PK bool @@ -254,6 +294,9 @@ config P2P config GAS bool +config GAS_SERVER + bool + config OFFCHANNEL bool @@ -358,6 +401,15 @@ config RRM config WMM_AC bool +config DPP + bool + +config DPP2 + bool + +config DPP3 + bool + config NW_SEL_RELIABILITY bool default y diff --git a/modules/hostap/src/supp_main.c b/modules/hostap/src/supp_main.c index 69a4dd8438b11..80d90c70fb6d8 100644 --- a/modules/hostap/src/supp_main.c +++ b/modules/hostap/src/supp_main.c @@ -14,6 +14,9 @@ LOG_MODULE_REGISTER(wifi_supplicant, CONFIG_WIFI_NM_WPA_SUPPLICANT_LOG_LEVEL); #if !defined(CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE) && !defined(CONFIG_MBEDTLS_ENABLE_HEAP) #include #endif /* !CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE && !CONFIG_MBEDTLS_ENABLE_HEAP */ +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA +#include "supp_psa_api.h" +#endif #include #include @@ -523,6 +526,10 @@ static void handler(void) mbedtls_platform_set_calloc_free(calloc, free); #endif /* !CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_NONE && !CONFIG_MBEDTLS_ENABLE_HEAP */ +#ifdef CONFIG_WIFI_NM_WPA_SUPPLICANT_CRYPTO_MBEDTLS_PSA + supp_psa_crypto_init(); +#endif + ctx = get_default_context(); k_work_queue_init(&ctx->iface_wq); diff --git a/modules/loramac-node/CMakeLists.txt b/modules/loramac-node/CMakeLists.txt index 9e0bdbc98771c..a711ab3e5fe94 100644 --- a/modules/loramac-node/CMakeLists.txt +++ b/modules/loramac-node/CMakeLists.txt @@ -55,7 +55,7 @@ zephyr_library_sources_ifdef(CONFIG_HAS_SEMTECH_LORAMAC ${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/mac/LoRaMacSerializer.c ) -zephyr_library_sources_ifdef(CONFIG_LORAWAN_FRAG_TRANSPORT +zephyr_library_sources_ifdef(CONFIG_LORAWAN_FRAG_TRANSPORT_DECODER_SEMTECH ${ZEPHYR_LORAMAC_NODE_MODULE_DIR}/src/apps/LoRaMac/common/LmHandler/packages/FragDecoder.c ) diff --git a/modules/lvgl/input/lvgl_encoder_input.c b/modules/lvgl/input/lvgl_encoder_input.c index b68ca67b87149..e87352799f29c 100644 --- a/modules/lvgl/input/lvgl_encoder_input.c +++ b/modules/lvgl/input/lvgl_encoder_input.c @@ -28,6 +28,8 @@ static void lvgl_encoder_process_event(const struct device *dev, struct input_ev data->pending_event.enc_diff = evt->value; } else if (evt->code == cfg->button_input_code) { data->pending_event.state = evt->value ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; + data->pending_event.enc_diff = 0; + data->pending_event.key = LV_KEY_ENTER; } else { LOG_DBG("Ignored input event: %u", evt->code); return; diff --git a/modules/lvgl/input/lvgl_pointer_input.c b/modules/lvgl/input/lvgl_pointer_input.c index e1b1224375057..679be46abb5e7 100644 --- a/modules/lvgl/input/lvgl_pointer_input.c +++ b/modules/lvgl/input/lvgl_pointer_input.c @@ -61,37 +61,50 @@ static void lvgl_pointer_process_event(const struct device *dev, struct input_ev return; } - point->x = data->point_x; - point->y = data->point_y; + lv_point_t tmp_point = { + .x = data->point_x, + .y = data->point_y, + }; if (cfg->invert_x) { if (cap->current_orientation == DISPLAY_ORIENTATION_NORMAL || cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_180) { - point->x = cap->x_resolution - data->point_x; + tmp_point.x = cap->x_resolution - tmp_point.x; } else { - point->x = cap->y_resolution - data->point_x; + tmp_point.x = cap->y_resolution - tmp_point.x; } } if (cfg->invert_y) { if (cap->current_orientation == DISPLAY_ORIENTATION_NORMAL || cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_180) { - point->y = cap->y_resolution - data->point_y; + tmp_point.y = cap->y_resolution - tmp_point.y; } else { - point->y = cap->x_resolution - data->point_y; + tmp_point.y = cap->x_resolution - tmp_point.y; } } /* rotate touch point to match display rotation */ - if (cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_90) { - point->x = data->point_y; - point->y = cap->y_resolution - data->point_x; - } else if (cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_180) { - point->x = cap->x_resolution - data->point_x; - point->y = cap->y_resolution - data->point_y; - } else if (cap->current_orientation == DISPLAY_ORIENTATION_ROTATED_270) { - point->x = cap->x_resolution - data->point_y; - point->y = data->point_x; + switch (cap->current_orientation) { + case DISPLAY_ORIENTATION_NORMAL: + point->x = tmp_point.x; + point->y = tmp_point.y; + break; + case DISPLAY_ORIENTATION_ROTATED_90: + point->x = tmp_point.y; + point->y = cap->y_resolution - tmp_point.x; + break; + case DISPLAY_ORIENTATION_ROTATED_180: + point->x = cap->x_resolution - tmp_point.x; + point->y = cap->y_resolution - tmp_point.y; + break; + case DISPLAY_ORIENTATION_ROTATED_270: + point->x = cap->x_resolution - tmp_point.y; + point->y = tmp_point.x; + break; + default: + LOG_ERR("Invalid display orientation"); + break; } /* filter readings within display */ diff --git a/modules/lvgl/lvgl_fs.c b/modules/lvgl/lvgl_fs.c index a05e21748d41a..63a902ea9572d 100644 --- a/modules/lvgl/lvgl_fs.c +++ b/modules/lvgl/lvgl_fs.c @@ -88,6 +88,7 @@ static lv_fs_res_t lvgl_fs_close(struct _lv_fs_drv_t *drv, void *file) int err; err = fs_close((struct fs_file_t *)file); + LV_MEM_CUSTOM_FREE(file); return errno_to_lv_fs_res(err); } diff --git a/modules/lvgl/lvgl_shell.c b/modules/lvgl/lvgl_shell.c index e8ac27e22f906..42d5a5e7a2ac3 100644 --- a/modules/lvgl/lvgl_shell.c +++ b/modules/lvgl/lvgl_shell.c @@ -6,7 +6,7 @@ #include #include -#include +#include #ifdef CONFIG_LV_Z_MEM_POOL_SYS_HEAP #include "lvgl_mem.h" diff --git a/modules/mbedtls/CMakeLists.txt b/modules/mbedtls/CMakeLists.txt index 01a7ed09c28ea..ae4d0e1f3b2b5 100644 --- a/modules/mbedtls/CMakeLists.txt +++ b/modules/mbedtls/CMakeLists.txt @@ -29,6 +29,12 @@ zephyr_interface_library_named(mbedTLS) include ) + if (CONFIG_MBEDTLS_PSA_P256M_DRIVER_RAW) + target_include_directories(mbedTLS INTERFACE + ${ZEPHYR_CURRENT_MODULE_DIR}/3rdparty/p256-m/p256-m + ) + endif() + # Add base library with files required by all drivers/backends. zephyr_library_named(mbedTLSBase) @@ -44,6 +50,7 @@ zephyr_interface_library_named(mbedTLS) ${ZEPHYR_CURRENT_MODULE_DIR}/library/bignum_mod_raw.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/bignum_mod.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/bignum.c + ${ZEPHYR_CURRENT_MODULE_DIR}/library/block_cipher.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/camellia.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/ccm.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/chacha20.c @@ -88,6 +95,7 @@ zephyr_interface_library_named(mbedTLS) ${ZEPHYR_CURRENT_MODULE_DIR}/library/sha1.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/sha256.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/sha512.c + ${ZEPHYR_CURRENT_MODULE_DIR}/library/sha3.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/threading.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/timing.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/version_features.c @@ -132,6 +140,14 @@ zephyr_interface_library_named(mbedTLS) ) endif() + if(CONFIG_MBEDTLS_PSA_P256M_DRIVER_ENABLED) + list(APPEND crypto_source + ${ZEPHYR_CURRENT_MODULE_DIR}/3rdparty/p256-m/p256-m_driver_entrypoints.c + ${ZEPHYR_CURRENT_MODULE_DIR}/3rdparty/p256-m/p256-m/p256-m.c + ) + zephyr_library_include_directories(${ZEPHYR_CURRENT_MODULE_DIR}/library) + endif() + list(APPEND crypto_source ${ZEPHYR_CURRENT_MODULE_DIR}/library/pem.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/pkcs12.c @@ -139,6 +155,7 @@ zephyr_interface_library_named(mbedTLS) ${ZEPHYR_CURRENT_MODULE_DIR}/library/pkparse.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/pkwrite.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/pk.c + ${ZEPHYR_CURRENT_MODULE_DIR}/library/pk_ecc.c ${ZEPHYR_CURRENT_MODULE_DIR}/library/pk_wrap.c ) diff --git a/modules/mbedtls/Kconfig b/modules/mbedtls/Kconfig index daaee438a38c7..dab5ef4215d99 100644 --- a/modules/mbedtls/Kconfig +++ b/modules/mbedtls/Kconfig @@ -13,6 +13,7 @@ config MBEDTLS_PROMPTLESS mbed TLS menu prompt and instead handle the selection of MBEDTLS from dependent sub-configurations and thus prevent stuck symbol behavior. +rsource "Kconfig.psa" menuconfig MBEDTLS bool "mbed TLS Support" if !MBEDTLS_PROMPTLESS diff --git a/modules/mbedtls/Kconfig.psa b/modules/mbedtls/Kconfig.psa new file mode 100644 index 0000000000000..7562032bf3d4e --- /dev/null +++ b/modules/mbedtls/Kconfig.psa @@ -0,0 +1,355 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# This file was automatically generated by create_psa_files.py +# from: ../../../modules/crypto/mbedtls/include/psa/crypto_config.h. +# Do not edit it manually. + +config PSA_CRYPTO_CLIENT + bool + help + Promptless symbol to state that there is a PSA crypto API provider + enabled in the system. This allows to select desired PSA_WANT features. + +if PSA_CRYPTO_CLIENT + +config PSA_CRYPTO_ENABLE_ALL + bool "All PSA crypto features" + +config PSA_WANT_ALG_CBC_NO_PADDING + bool "PSA_WANT_ALG_CBC_NO_PADDING" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CBC_PKCS7 + bool "PSA_WANT_ALG_CBC_PKCS7" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CCM + bool "PSA_WANT_ALG_CCM" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CCM_STAR_NO_TAG + bool "PSA_WANT_ALG_CCM_STAR_NO_TAG" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CMAC + bool "PSA_WANT_ALG_CMAC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CFB + bool "PSA_WANT_ALG_CFB" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CHACHA20_POLY1305 + bool "PSA_WANT_ALG_CHACHA20_POLY1305" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_CTR + bool "PSA_WANT_ALG_CTR" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_DETERMINISTIC_ECDSA + bool "PSA_WANT_ALG_DETERMINISTIC_ECDSA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_ECB_NO_PADDING + bool "PSA_WANT_ALG_ECB_NO_PADDING" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_ECDH + bool "PSA_WANT_ALG_ECDH" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_FFDH + bool "PSA_WANT_ALG_FFDH" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_ECDSA + bool "PSA_WANT_ALG_ECDSA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_JPAKE + bool "PSA_WANT_ALG_JPAKE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_GCM + bool "PSA_WANT_ALG_GCM" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_HKDF + bool "PSA_WANT_ALG_HKDF" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_HKDF_EXTRACT + bool "PSA_WANT_ALG_HKDF_EXTRACT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_HKDF_EXPAND + bool "PSA_WANT_ALG_HKDF_EXPAND" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_HMAC + bool "PSA_WANT_ALG_HMAC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_MD5 + bool "PSA_WANT_ALG_MD5" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_OFB + bool "PSA_WANT_ALG_OFB" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_PBKDF2_HMAC + bool "PSA_WANT_ALG_PBKDF2_HMAC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 + bool "PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RIPEMD160 + bool "PSA_WANT_ALG_RIPEMD160" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RSA_OAEP + bool "PSA_WANT_ALG_RSA_OAEP" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RSA_PKCS1V15_CRYPT + bool "PSA_WANT_ALG_RSA_PKCS1V15_CRYPT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RSA_PKCS1V15_SIGN + bool "PSA_WANT_ALG_RSA_PKCS1V15_SIGN" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_RSA_PSS + bool "PSA_WANT_ALG_RSA_PSS" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA_1 + bool "PSA_WANT_ALG_SHA_1" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA_224 + bool "PSA_WANT_ALG_SHA_224" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA_256 + bool "PSA_WANT_ALG_SHA_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA_384 + bool "PSA_WANT_ALG_SHA_384" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA_512 + bool "PSA_WANT_ALG_SHA_512" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA3_224 + bool "PSA_WANT_ALG_SHA3_224" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA3_256 + bool "PSA_WANT_ALG_SHA3_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA3_384 + bool "PSA_WANT_ALG_SHA3_384" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_SHA3_512 + bool "PSA_WANT_ALG_SHA3_512" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_STREAM_CIPHER + bool "PSA_WANT_ALG_STREAM_CIPHER" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_TLS12_PRF + bool "PSA_WANT_ALG_TLS12_PRF" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_TLS12_PSK_TO_MS + bool "PSA_WANT_ALG_TLS12_PSK_TO_MS" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS + bool "PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_BRAINPOOL_P_R1_256 + bool "PSA_WANT_ECC_BRAINPOOL_P_R1_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_BRAINPOOL_P_R1_384 + bool "PSA_WANT_ECC_BRAINPOOL_P_R1_384" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_BRAINPOOL_P_R1_512 + bool "PSA_WANT_ECC_BRAINPOOL_P_R1_512" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_MONTGOMERY_255 + bool "PSA_WANT_ECC_MONTGOMERY_255" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_MONTGOMERY_448 + bool "PSA_WANT_ECC_MONTGOMERY_448" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_K1_192 + bool "PSA_WANT_ECC_SECP_K1_192" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_K1_256 + bool "PSA_WANT_ECC_SECP_K1_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_192 + bool "PSA_WANT_ECC_SECP_R1_192" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_224 + bool "PSA_WANT_ECC_SECP_R1_224" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_256 + bool "PSA_WANT_ECC_SECP_R1_256" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_384 + bool "PSA_WANT_ECC_SECP_R1_384" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_ECC_SECP_R1_521 + bool "PSA_WANT_ECC_SECP_R1_521" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_2048 + bool "PSA_WANT_DH_RFC7919_2048" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_3072 + bool "PSA_WANT_DH_RFC7919_3072" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_4096 + bool "PSA_WANT_DH_RFC7919_4096" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_6144 + bool "PSA_WANT_DH_RFC7919_6144" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_DH_RFC7919_8192 + bool "PSA_WANT_DH_RFC7919_8192" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DERIVE + bool "PSA_WANT_KEY_TYPE_DERIVE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_PASSWORD + bool "PSA_WANT_KEY_TYPE_PASSWORD" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_PASSWORD_HASH + bool "PSA_WANT_KEY_TYPE_PASSWORD_HASH" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_HMAC + bool "PSA_WANT_KEY_TYPE_HMAC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_AES + bool "PSA_WANT_KEY_TYPE_AES" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ARIA + bool "PSA_WANT_KEY_TYPE_ARIA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_CAMELLIA + bool "PSA_WANT_KEY_TYPE_CAMELLIA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_CHACHA20 + bool "PSA_WANT_KEY_TYPE_CHACHA20" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DES + bool "PSA_WANT_KEY_TYPE_DES" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY + bool "PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY + bool "PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RAW_DATA + bool "PSA_WANT_KEY_TYPE_RAW_DATA" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY + bool "PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE + bool "PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE + bool "PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC + bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT + bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT + bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +config PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE + bool "PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE" if !MBEDTLS_PROMPTLESS + default y if PSA_CRYPTO_ENABLE_ALL + +endif # PSA_CRYPTO_CLIENT diff --git a/modules/mbedtls/Kconfig.tls-generic b/modules/mbedtls/Kconfig.tls-generic index d75abd64be2f0..f4fe0db1c4114 100644 --- a/modules/mbedtls/Kconfig.tls-generic +++ b/modules/mbedtls/Kconfig.tls-generic @@ -12,20 +12,19 @@ menu "Supported TLS version" config MBEDTLS_TLS_VERSION_1_0 bool "Support for TLS 1.0" select MBEDTLS_CIPHER - select MBEDTLS_MAC_MD5_ENABLED - select MBEDTLS_MAC_SHA1_ENABLED + select MBEDTLS_MD5 + select MBEDTLS_SHA1 select MBEDTLS_MD config MBEDTLS_TLS_VERSION_1_1 bool "Support for TLS 1.1 (DTLS 1.0)" select MBEDTLS_CIPHER - select MBEDTLS_MAC_MD5_ENABLED - select MBEDTLS_MAC_SHA1_ENABLED + select MBEDTLS_MD5 + select MBEDTLS_SHA1 select MBEDTLS_MD config MBEDTLS_TLS_VERSION_1_2 bool "Support for TLS 1.2 (DTLS 1.2)" - default y if !NET_L2_OPENTHREAD select MBEDTLS_CIPHER select MBEDTLS_MD @@ -76,7 +75,9 @@ config MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED config MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED bool - default y if MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || \ + default y + depends on \ + MBEDTLS_KEY_EXCHANGE_PSK_ENABLED || \ MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED || \ MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED || \ MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED @@ -90,7 +91,11 @@ config MBEDTLS_PSK_MAX_LEN config MBEDTLS_KEY_EXCHANGE_RSA_ENABLED bool "RSA-only based ciphersuite modes" - default y if !NET_L2_OPENTHREAD + default y if UOSCORE || UEDHOC + select MBEDTLS_MD + select PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY if PSA_CRYPTO_CLIENT + select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC if PSA_CRYPTO_CLIENT + select PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT if PSA_CRYPTO_CLIENT config MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED bool "DHE-RSA based ciphersuite modes" @@ -105,7 +110,7 @@ config MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED config MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED bool "ECDH-ECDSA based ciphersuite modes" - depends on MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C + depends on (MBEDTLS_ECDH_C && MBEDTLS_ECDSA_C) || (PSA_WANT_ALG_ECDH && PSA_WANT_ALG_ECDSA) config MBEDTLS_ECDSA_DETERMINISTIC bool "Deterministic ECDSA (RFC 6979)" @@ -206,34 +211,14 @@ config MBEDTLS_ECP_NIST_OPTIM endif -comment "Supported hash" - -config MBEDTLS_HASH_ALL_ENABLED - bool "All available hashes" - select MBEDTLS_HASH_SHA256_ENABLED - select MBEDTLS_HASH_SHA384_ENABLED - select MBEDTLS_HASH_SHA512_ENABLED - -config MBEDTLS_HASH_SHA256_ENABLED - bool "SHA224 and SHA256 hashes" - -config MBEDTLS_HASH_SHA384_ENABLED - bool "SHA384 hash" - select MBEDTLS_HASH_SHA512_ENABLED - -config MBEDTLS_HASH_SHA512_ENABLED - bool "SHA512 hash" - -comment "Supported cipher modes" +comment "Supported ciphers and cipher modes" config MBEDTLS_CIPHER_ALL_ENABLED - bool "All available ciphers" + bool "All available ciphers and modes" select MBEDTLS_CIPHER_AES_ENABLED select MBEDTLS_CIPHER_CAMELLIA_ENABLED select MBEDTLS_CIPHER_DES_ENABLED - select MBEDTLS_CIPHER_ARC4_ENABLED select MBEDTLS_CIPHER_CHACHA20_ENABLED - select MBEDTLS_CIPHER_BLOWFISH_ENABLED select MBEDTLS_CIPHER_CCM_ENABLED select MBEDTLS_CIPHER_GCM_ENABLED select MBEDTLS_CIPHER_MODE_XTS_ENABLED @@ -241,111 +226,124 @@ config MBEDTLS_CIPHER_ALL_ENABLED select MBEDTLS_CIPHER_MODE_CTR_ENABLED select MBEDTLS_CHACHAPOLY_AEAD_ENABLED +config MBEDTLS_SOME_AEAD_CIPHER_ENABLED + bool + default y + depends on \ + MBEDTLS_CIPHER_AES_ENABLED || \ + MBEDTLS_CIPHER_CAMELLIA_ENABLED + +config MBEDTLS_SOME_CIPHER_ENABLED + bool + default y + depends on \ + MBEDTLS_SOME_AEAD_CIPHER_ENABLED || \ + MBEDTLS_CIPHER_DES_ENABLED || \ + MBEDTLS_CIPHER_CHACHA20_ENABLED + config MBEDTLS_CIPHER_AES_ENABLED bool "AES block cipher" - default y + +if MBEDTLS_CIPHER_AES_ENABLED config MBEDTLS_AES_ROM_TABLES - depends on MBEDTLS_CIPHER_AES_ENABLED bool "Use precomputed AES tables stored in ROM." - default y config MBEDTLS_AES_FEWER_TABLES - depends on MBEDTLS_CIPHER_AES_ENABLED bool "Reduce the size of precomputed AES tables by ~6kB" + default y + depends on MBEDTLS_AES_ROM_TABLES help Reduce the size of the AES tables at a tradeoff of more arithmetic operations at runtime. Specifically 4 table lookups are converted to 1 table lookup, 3 additions and 6 bit shifts. +config MBEDTLS_CIPHER_MODE_XTS_ENABLED + bool "Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES" + +endif # MBEDTLS_CIPHER_AES_ENABLED + config MBEDTLS_CIPHER_CAMELLIA_ENABLED bool "Camellia block cipher" config MBEDTLS_CIPHER_DES_ENABLED bool "DES block cipher" - default y if !NET_L2_OPENTHREAD - -config MBEDTLS_CIPHER_ARC4_ENABLED - bool "ARC4 stream cipher" config MBEDTLS_CIPHER_CHACHA20_ENABLED bool "ChaCha20 stream cipher" -config MBEDTLS_CIPHER_BLOWFISH_ENABLED - bool "Blowfish block cipher" +if MBEDTLS_SOME_AEAD_CIPHER_ENABLED config MBEDTLS_CIPHER_CCM_ENABLED bool "Counter with CBC-MAC (CCM) mode for 128-bit block cipher" - depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_CAMELLIA_ENABLED default y if UOSCORE || UEDHOC config MBEDTLS_CIPHER_GCM_ENABLED - bool "Galois/Counter Mode (GCM) for AES" - depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_CAMELLIA_ENABLED + bool "Galois/Counter Mode (GCM) for symmetric ciphers" -config MBEDTLS_CIPHER_MODE_XTS_ENABLED - bool "Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES" - depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_CAMELLIA_ENABLED +endif # MBEDTLS_SOME_AEAD_CIPHER_ENABLED + +if MBEDTLS_SOME_CIPHER_ENABLED config MBEDTLS_CIPHER_MODE_CBC_ENABLED bool "Cipher Block Chaining mode (CBC) for symmetric ciphers" default y if !NET_L2_OPENTHREAD config MBEDTLS_CIPHER_MODE_CTR_ENABLED - bool "Counter Block Cipher mode (CTR) for symmetric ciphers." + bool "Counter Block Cipher mode (CTR) for symmetric ciphers" + +endif # MBEDTLS_SOME_CIPHER_ENABLED config MBEDTLS_CHACHAPOLY_AEAD_ENABLED bool "ChaCha20-Poly1305 AEAD algorithm" - depends on MBEDTLS_CIPHER_CHACHA20_ENABLED || MBEDTLS_MAC_POLY1305_ENABLED + depends on MBEDTLS_CIPHER_CHACHA20_ENABLED && MBEDTLS_POLY1305 -comment "Supported message authentication methods" +config MBEDTLS_CMAC + bool "CMAC (Cipher-based Message Authentication Code) mode for block ciphers." + depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_DES_ENABLED -config MBEDTLS_MAC_ALL_ENABLED +comment "Supported hash algorithms" + +config MBEDTLS_HASH_ALL_ENABLED bool "All available MAC methods" - select MBEDTLS_MAC_MD4_ENABLED - select MBEDTLS_MAC_MD5_ENABLED - select MBEDTLS_MAC_SHA1_ENABLED - select MBEDTLS_MAC_SHA256_ENABLED - select MBEDTLS_MAC_SHA384_ENABLED - select MBEDTLS_MAC_SHA512_ENABLED - select MBEDTLS_MAC_POLY1305_ENABLED - select MBEDTLS_MAC_CMAC_ENABLED - -config MBEDTLS_MAC_MD4_ENABLED - bool "MD4 hash algorithm" - -config MBEDTLS_MAC_MD5_ENABLED + select MBEDTLS_MD5 + select MBEDTLS_SHA1 + select MBEDTLS_SHA224 + select MBEDTLS_SHA256 + select MBEDTLS_SHA384 + select MBEDTLS_SHA512 + select MBEDTLS_POLY1305 + +config MBEDTLS_MD5 bool "MD5 hash algorithm" -config MBEDTLS_MAC_SHA1_ENABLED - bool "SHA1 hash algorithm" +config MBEDTLS_SHA1 + bool "SHA-1 hash algorithm" + +config MBEDTLS_SHA224 + bool "SHA-224 hash algorithm" -config MBEDTLS_MAC_SHA256_ENABLED - bool "SHA-224 and SHA-256 hash algorithms" +config MBEDTLS_SHA256 + bool "SHA-256 hash algorithm" default y config MBEDTLS_SHA256_SMALLER bool "Smaller SHA-256 implementation" - depends on MBEDTLS_MAC_SHA256_ENABLED + depends on MBEDTLS_SHA256 default y help - Enable an implementation of SHA-256 that has lower ROM footprint but also - lower performance + Enable an implementation of SHA-256 that has a + smaller ROM footprint but also lower performance. -config MBEDTLS_MAC_SHA384_ENABLED +config MBEDTLS_SHA384 bool "SHA-384 hash algorithm" - select MBEDTLS_MAC_SHA512_ENABLED -config MBEDTLS_MAC_SHA512_ENABLED +config MBEDTLS_SHA512 bool "SHA-512 hash algorithm" -config MBEDTLS_MAC_POLY1305_ENABLED - bool "Poly1305 MAC algorithm" - -config MBEDTLS_MAC_CMAC_ENABLED - bool "CMAC (Cipher-based Message Authentication Code) mode for block ciphers." - depends on MBEDTLS_CIPHER_AES_ENABLED || MBEDTLS_CIPHER_DES_ENABLED +config MBEDTLS_POLY1305 + bool "Poly1305 hash family" endmenu @@ -364,6 +362,7 @@ comment "Other configurations" config MBEDTLS_CIPHER bool "generic cipher layer." + default y if PSA_WANT_ALG_CMAC config MBEDTLS_MD bool "generic message digest layer." @@ -387,7 +386,7 @@ config MBEDTLS_HAVE_ASM config MBEDTLS_ENTROPY_ENABLED bool "MbedTLS generic entropy pool" - depends on MBEDTLS_MAC_SHA256_ENABLED || MBEDTLS_MAC_SHA384_ENABLED || MBEDTLS_MAC_SHA512_ENABLED + depends on MBEDTLS_SHA256 || MBEDTLS_SHA384 || MBEDTLS_SHA512 default y if MBEDTLS_ZEPHYR_ENTROPY config MBEDTLS_OPENTHREAD_OPTIMIZATIONS_ENABLED @@ -420,7 +419,6 @@ config MBEDTLS_SERVER_NAME_INDICATION config MBEDTLS_PK_WRITE_C bool "The generic public (asymmetric) key writer" - default y if MBEDTLS_PSA_CRYPTO_C help Enable generic public key write functions. @@ -442,16 +440,18 @@ config MBEDTLS_SSL_CACHE_C help "This option enables simple SSL cache implementation (server side)." +if MBEDTLS_SSL_CACHE_C + config MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT int "Default timeout for SSL cache entires" - depends on MBEDTLS_SSL_CACHE_C default 86400 config MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES int "Maximum number of SSL cache entires" - depends on MBEDTLS_SSL_CACHE_C default 5 +endif # MBEDTLS_SSL_CACHE_C + config MBEDTLS_SSL_EXTENDED_MASTER_SECRET bool "(D)TLS Extended Master Secret extension" depends on MBEDTLS_TLS_VERSION_1_2 @@ -460,16 +460,68 @@ config MBEDTLS_SSL_EXTENDED_MASTER_SECRET which ensures that master secrets are different for every connection and every session. +choice MBEDTLS_PSA_CRYPTO_RND_SOURCE + prompt "Select random source for built-in PSA crypto" + depends on MBEDTLS_PSA_CRYPTO_C + default MBEDTLS_PSA_CRYPTO_LEGACY_RNG + +config MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG + bool "Use a cryptographically secure driver as random source" + depends on CSPRNG_ENABLED + help + Use cryptographically secure random generator to provide random data + instead of legacy MbedTLS modules (ENTROPY + CTR_DRBG/HMAC_DRBG). + +config MBEDTLS_PSA_CRYPTO_LEGACY_RNG + bool "Use legacy modules to generate random data" + select MBEDTLS_ENTROPY_ENABLED + select MBEDTLS_HMAC_DRBG_ENABLED if !MBEDTLS_CTR_DRBG_ENABLED + help + Use legacy MbedTLS modules (ENTROPY + CTR_DRBG/HMAC_DRBG) as random + source generators. + +endchoice + config MBEDTLS_PSA_CRYPTO_C bool "Platform Security Architecture cryptography API" - depends on MBEDTLS_ENTROPY_ENABLED - depends on MBEDTLS_CTR_DRBG_ENABLED || MBEDTLS_HMAC_DRBG_ENABLED default y if UOSCORE || UEDHOC +config MBEDTLS_USE_PSA_CRYPTO + bool "Use PSA APIs instead of legacy MbedTLS when possible" + default y if MBEDTLS_PSA_CRYPTO_CLIENT + help + Use PSA APIs instead of legacy MbedTLS functions in TLS/DTLS and other + "intermediate" modules such as PK, MD and Cipher. + +config MBEDTLS_PSA_CRYPTO_CLIENT + bool + default y + depends on BUILD_WITH_TFM || MBEDTLS_PSA_CRYPTO_C + select PSA_CRYPTO_CLIENT + config MBEDTLS_LMS bool "Support LMS signature schemes" + depends on MBEDTLS_PSA_CRYPTO_CLIENT + depends on MBEDTLS_SHA256 + select PSA_WANT_ALG_SHA_256 + +config MBEDTLS_PSA_P256M_DRIVER_ENABLED + bool "P256-M driver" depends on MBEDTLS_PSA_CRYPTO_C - depends on MBEDTLS_HASH_SHA256_ENABLED + imply PSA_WANT_ALG_SHA_256 + help + Enable support for the optimized sofware implementation of the secp256r1 + curve through the standard PSA API interface. + +config MBEDTLS_PSA_P256M_DRIVER_RAW + bool "Access p256-m driver directly (without PSA interface)" + select MBEDTLS_PSA_P256M_DRIVER_ENABLED + help + Allow access to p256-m driver directly without using the PSA interface. + Warning: usage of this kconfig is prohibited in Zephyr's code base. Users + can make optionally enable it in case very memory constrained + devices, but please be aware that the p256-m interface is + absolutely not guaranted to remain stable over time. config MBEDTLS_SSL_DTLS_CONNECTION_ID bool "DTLS Connection ID extension" @@ -479,4 +531,32 @@ config MBEDTLS_SSL_DTLS_CONNECTION_ID which allows to identify DTLS connections across changes in the underlying transport. + +config MBEDTLS_NIST_KW_C + bool "NIST key wrap" + depends on MBEDTLS_CIPHER_AES_ENABLED + help + Key Wrapping mode for 128-bit block ciphers, + as defined in NIST SP 800-38F. + +config MBEDTLS_DHM_C + bool "Diffie-Hellman-Merkle mode" + help + Used by the following key exchanges, + DHE-RSA, DHE-PSK + +config MBEDTLS_X509_CRL_PARSE_C + bool "X509 CRL parsing" + help + Used by X509 CRL parsing + +config MBEDTLS_X509_CSR_WRITE_C + bool "X509 Certificate Signing Requests writing" + help + For X.509 certificate request writing. + +config MBEDTLS_X509_CSR_PARSE_C + bool "X509 Certificate Signing Request parsing" + help + For reading X.509 certificate request. endmenu diff --git a/modules/mbedtls/configs/config-psa.h b/modules/mbedtls/configs/config-psa.h new file mode 100644 index 0000000000000..e0278f761b889 --- /dev/null +++ b/modules/mbedtls/configs/config-psa.h @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file was automatically generated by create_psa_files.py + * from: ../../../modules/crypto/mbedtls/include/psa/crypto_config.h + * Do not edit it manually. + */ + +#ifndef CONFIG_PSA_H +#define CONFIG_PSA_H + +#if defined(CONFIG_PSA_WANT_ALG_CBC_NO_PADDING) +#define PSA_WANT_ALG_CBC_NO_PADDING 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CBC_PKCS7) +#define PSA_WANT_ALG_CBC_PKCS7 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CCM) +#define PSA_WANT_ALG_CCM 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CCM_STAR_NO_TAG) +#define PSA_WANT_ALG_CCM_STAR_NO_TAG 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CMAC) +#define PSA_WANT_ALG_CMAC 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CFB) +#define PSA_WANT_ALG_CFB 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CHACHA20_POLY1305) +#define PSA_WANT_ALG_CHACHA20_POLY1305 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_CTR) +#define PSA_WANT_ALG_CTR 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_DETERMINISTIC_ECDSA) +#define PSA_WANT_ALG_DETERMINISTIC_ECDSA 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_ECB_NO_PADDING) +#define PSA_WANT_ALG_ECB_NO_PADDING 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_ECDH) +#define PSA_WANT_ALG_ECDH 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_FFDH) +#define PSA_WANT_ALG_FFDH 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_ECDSA) +#define PSA_WANT_ALG_ECDSA 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_JPAKE) +#define PSA_WANT_ALG_JPAKE 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_GCM) +#define PSA_WANT_ALG_GCM 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_HKDF) +#define PSA_WANT_ALG_HKDF 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_HKDF_EXTRACT) +#define PSA_WANT_ALG_HKDF_EXTRACT 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_HKDF_EXPAND) +#define PSA_WANT_ALG_HKDF_EXPAND 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_HMAC) +#define PSA_WANT_ALG_HMAC 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_MD5) +#define PSA_WANT_ALG_MD5 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_OFB) +#define PSA_WANT_ALG_OFB 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_PBKDF2_HMAC) +#define PSA_WANT_ALG_PBKDF2_HMAC 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128) +#define PSA_WANT_ALG_PBKDF2_AES_CMAC_PRF_128 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RIPEMD160) +#define PSA_WANT_ALG_RIPEMD160 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RSA_OAEP) +#define PSA_WANT_ALG_RSA_OAEP 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RSA_PKCS1V15_CRYPT) +#define PSA_WANT_ALG_RSA_PKCS1V15_CRYPT 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RSA_PKCS1V15_SIGN) +#define PSA_WANT_ALG_RSA_PKCS1V15_SIGN 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_RSA_PSS) +#define PSA_WANT_ALG_RSA_PSS 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_1) +#define PSA_WANT_ALG_SHA_1 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_224) +#define PSA_WANT_ALG_SHA_224 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_256) +#define PSA_WANT_ALG_SHA_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_384) +#define PSA_WANT_ALG_SHA_384 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA_512) +#define PSA_WANT_ALG_SHA_512 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA3_224) +#define PSA_WANT_ALG_SHA3_224 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA3_256) +#define PSA_WANT_ALG_SHA3_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA3_384) +#define PSA_WANT_ALG_SHA3_384 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_SHA3_512) +#define PSA_WANT_ALG_SHA3_512 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_STREAM_CIPHER) +#define PSA_WANT_ALG_STREAM_CIPHER 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_TLS12_PRF) +#define PSA_WANT_ALG_TLS12_PRF 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_TLS12_PSK_TO_MS) +#define PSA_WANT_ALG_TLS12_PSK_TO_MS 1 +#endif + +#if defined(CONFIG_PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS) +#define PSA_WANT_ALG_TLS12_ECJPAKE_TO_PMS 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_BRAINPOOL_P_R1_256) +#define PSA_WANT_ECC_BRAINPOOL_P_R1_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_BRAINPOOL_P_R1_384) +#define PSA_WANT_ECC_BRAINPOOL_P_R1_384 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_BRAINPOOL_P_R1_512) +#define PSA_WANT_ECC_BRAINPOOL_P_R1_512 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_MONTGOMERY_255) +#define PSA_WANT_ECC_MONTGOMERY_255 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_MONTGOMERY_448) +#define PSA_WANT_ECC_MONTGOMERY_448 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_K1_192) +#define PSA_WANT_ECC_SECP_K1_192 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_K1_256) +#define PSA_WANT_ECC_SECP_K1_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_192) +#define PSA_WANT_ECC_SECP_R1_192 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_224) +#define PSA_WANT_ECC_SECP_R1_224 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_256) +#define PSA_WANT_ECC_SECP_R1_256 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_384) +#define PSA_WANT_ECC_SECP_R1_384 1 +#endif + +#if defined(CONFIG_PSA_WANT_ECC_SECP_R1_521) +#define PSA_WANT_ECC_SECP_R1_521 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_2048) +#define PSA_WANT_DH_RFC7919_2048 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_3072) +#define PSA_WANT_DH_RFC7919_3072 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_4096) +#define PSA_WANT_DH_RFC7919_4096 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_6144) +#define PSA_WANT_DH_RFC7919_6144 1 +#endif + +#if defined(CONFIG_PSA_WANT_DH_RFC7919_8192) +#define PSA_WANT_DH_RFC7919_8192 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DERIVE) +#define PSA_WANT_KEY_TYPE_DERIVE 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_PASSWORD) +#define PSA_WANT_KEY_TYPE_PASSWORD 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_PASSWORD_HASH) +#define PSA_WANT_KEY_TYPE_PASSWORD_HASH 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_HMAC) +#define PSA_WANT_KEY_TYPE_HMAC 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_AES) +#define PSA_WANT_KEY_TYPE_AES 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ARIA) +#define PSA_WANT_KEY_TYPE_ARIA 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_CAMELLIA) +#define PSA_WANT_KEY_TYPE_CAMELLIA 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_CHACHA20) +#define PSA_WANT_KEY_TYPE_CHACHA20 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DES) +#define PSA_WANT_KEY_TYPE_DES 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY) +#define PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY) +#define PSA_WANT_KEY_TYPE_DH_PUBLIC_KEY 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RAW_DATA) +#define PSA_WANT_KEY_TYPE_RAW_DATA 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY) +#define PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_IMPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_EXPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_GENERATE 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE) +#define PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_DERIVE 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_BASIC 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_IMPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_EXPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE) +#define PSA_WANT_KEY_TYPE_RSA_KEY_PAIR_GENERATE 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_BASIC 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_IMPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_EXPORT 1 +#endif + +#if defined(CONFIG_PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE) +#define PSA_WANT_KEY_TYPE_DH_KEY_PAIR_GENERATE 1 +#endif + +#endif /* CONFIG_PSA_H */ diff --git a/modules/mbedtls/configs/config-tls-generic.h b/modules/mbedtls/configs/config-tls-generic.h index 18be5b4119ebb..d76b425a569ae 100644 --- a/modules/mbedtls/configs/config-tls-generic.h +++ b/modules/mbedtls/configs/config-tls-generic.h @@ -35,7 +35,6 @@ #if defined(CONFIG_MBEDTLS_LMS) #define MBEDTLS_LMS_C -#define PSA_WANT_ALG_SHA_256 1 #endif #if defined(CONFIG_MBEDTLS_HAVE_TIME_DATE) @@ -164,18 +163,10 @@ #define MBEDTLS_DES_C #endif -#if defined(CONFIG_MBEDTLS_CIPHER_ARC4_ENABLED) -#define MBEDTLS_ARC4_C -#endif - #if defined(CONFIG_MBEDTLS_CIPHER_CHACHA20_ENABLED) #define MBEDTLS_CHACHA20_C #endif -#if defined(CONFIG_MBEDTLS_CIPHER_BLOWFISH_ENABLED) -#define MBEDTLS_BLOWFISH_C -#endif - #if defined(CONFIG_MBEDTLS_CIPHER_CCM_ENABLED) #define MBEDTLS_CCM_C #endif @@ -272,23 +263,21 @@ #define MBEDTLS_ECP_NIST_OPTIM #endif -/* Supported message authentication methods */ - -#if defined(CONFIG_MBEDTLS_MAC_MD4_ENABLED) -#define MBEDTLS_MD4_C -#endif +/* Supported hash algorithms */ -#if defined(CONFIG_MBEDTLS_MAC_MD5_ENABLED) +#if defined(CONFIG_MBEDTLS_MD5) #define MBEDTLS_MD5_C #endif -#if defined(CONFIG_MBEDTLS_MAC_SHA1_ENABLED) +#if defined(CONFIG_MBEDTLS_SHA1) #define MBEDTLS_SHA1_C #endif -#if defined(CONFIG_MBEDTLS_MAC_SHA256_ENABLED) || \ - defined(CONFIG_MBEDTLS_HASH_SHA256_ENABLED) +#if defined(CONFIG_MBEDTLS_SHA224) #define MBEDTLS_SHA224_C +#endif + +#if defined(CONFIG_MBEDTLS_SHA256) #define MBEDTLS_SHA256_C #endif @@ -296,21 +285,19 @@ #define MBEDTLS_SHA256_SMALLER #endif -#if defined(CONFIG_MBEDTLS_MAC_SHA384_ENABLED) || \ - defined(CONFIG_MBEDTLS_HASH_SHA384_ENABLED) +#if defined(CONFIG_MBEDTLS_SHA384) #define MBEDTLS_SHA384_C #endif -#if defined(CONFIG_MBEDTLS_MAC_SHA512_ENABLED) || \ - defined(CONFIG_MBEDTLS_HASH_SHA512_ENABLED) +#if defined(CONFIG_MBEDTLS_SHA512) #define MBEDTLS_SHA512_C #endif -#if defined(CONFIG_MBEDTLS_MAC_POLY1305_ENABLED) +#if defined(CONFIG_MBEDTLS_POLY1305) #define MBEDTLS_POLY1305_C #endif -#if defined(CONFIG_MBEDTLS_MAC_CMAC_ENABLED) +#if defined(CONFIG_MBEDTLS_CMAC) #define MBEDTLS_CMAC_C #endif @@ -374,12 +361,6 @@ defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) #define MBEDTLS_RSA_C -#endif - -#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) || \ - defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) #define MBEDTLS_PKCS1_V15 #define MBEDTLS_PKCS1_V21 #endif @@ -429,7 +410,7 @@ #define MBEDTLS_PK_C #endif -#if defined(MBEDTLS_ECDSA_C) || defined(MBEDTLS_RSA_C) || defined(MBEDTLS_X509_USE_C) +#if defined(MBEDTLS_ECDSA_C) || defined(MBEDTLS_X509_USE_C) #define MBEDTLS_ASN1_PARSE_C #endif @@ -468,17 +449,36 @@ #define MBEDTLS_SSL_EXTENDED_MASTER_SECRET #endif +#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +#define MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG +#endif + #if defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) #define MBEDTLS_PSA_CRYPTO_C -#define MBEDTLS_USE_PSA_CRYPTO +#define MBEDTLS_PSA_ASSUME_EXCLUSIVE_BUFFERS + +#if defined(CONFIG_MBEDTLS_PSA_P256M_DRIVER_ENABLED) +#define MBEDTLS_PSA_P256M_DRIVER_ENABLED +#endif -#if defined(CONFIG_ARCH_POSIX) +#if defined(CONFIG_ARCH_POSIX) && !defined(CONFIG_PICOLIBC) #define MBEDTLS_PSA_KEY_SLOT_COUNT 64 #define MBEDTLS_PSA_CRYPTO_STORAGE_C #define MBEDTLS_PSA_ITS_FILE_C #define MBEDTLS_FS_IO #endif +#endif /* CONFIG_MBEDTLS_PSA_CRYPTO_C */ + +#if defined(CONFIG_MBEDTLS_USE_PSA_CRYPTO) +#define MBEDTLS_USE_PSA_CRYPTO +#endif + +#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) +#define MBEDTLS_PSA_CRYPTO_CLIENT +#define MBEDTLS_PSA_CRYPTO_CONFIG +#define MBEDTLS_PSA_CRYPTO_CONFIG_FILE "config-psa.h" + #endif #if defined(CONFIG_MBEDTLS_TLS_VERSION_1_2) && defined(CONFIG_MBEDTLS_PSA_CRYPTO_C) @@ -489,15 +489,33 @@ #define MBEDTLS_SSL_DTLS_CONNECTION_ID #endif -/* User config file */ +#if defined(CONFIG_MBEDTLS_NIST_KW_C) +#define MBEDTLS_NIST_KW_C +#endif + +#if defined(CONFIG_MBEDTLS_DHM_C) +#define MBEDTLS_DHM_C +#endif + +#if defined(CONFIG_MBEDTLS_X509_CRL_PARSE_C) +#define MBEDTLS_X509_CRL_PARSE_C +#endif + +#if defined(CONFIG_MBEDTLS_X509_CSR_WRITE_C) +#define MBEDTLS_X509_CSR_WRITE_C +#define MBEDTLS_X509_CREATE_C +#endif + +#if defined(CONFIG_MBEDTLS_X509_CSR_PARSE_C) +#define MBEDTLS_X509_CSR_PARSE_C +#endif #if defined(CONFIG_MBEDTLS_USER_CONFIG_FILE) #include CONFIG_MBEDTLS_USER_CONFIG_FILE #endif #if defined(CONFIG_BUILD_WITH_TFM) -#define MBEDTLS_PSA_CRYPTO_CLIENT #undef MBEDTLS_PSA_CRYPTO_C -#endif /* CONFIG_BUILD_WITH_TFM */ +#endif #endif /* MBEDTLS_CONFIG_H */ diff --git a/modules/mbedtls/create_psa_files.py b/modules/mbedtls/create_psa_files.py new file mode 100755 index 0000000000000..fe6d0b79b4655 --- /dev/null +++ b/modules/mbedtls/create_psa_files.py @@ -0,0 +1,129 @@ +#!/bin/python3 + +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +import re +import os +import sys +import argparse +from typing import List + +SCRIPT_PATH = os.path.dirname(__file__) +INPUT_REL_PATH = os.path.join("..", "..", "..", "modules", "crypto", "mbedtls", + "include", "psa", "crypto_config.h") +INPUT_FILE = os.path.normpath(os.path.join(SCRIPT_PATH, INPUT_REL_PATH)) + +KCONFIG_PATH=os.path.join(SCRIPT_PATH, "Kconfig.psa") +HEADER_PATH=os.path.join(SCRIPT_PATH, "configs", "config-psa.h") + +KCONFIG_HEADER="""\ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# This file was automatically generated by {} +# from: {}. +# Do not edit it manually. + +config PSA_CRYPTO_CLIENT + bool + help + Promptless symbol to state that there is a PSA crypto API provider + enabled in the system. This allows to select desired PSA_WANT features. + +if PSA_CRYPTO_CLIENT + +config PSA_CRYPTO_ENABLE_ALL + bool "All PSA crypto features" +""".format(os.path.basename(__file__), INPUT_REL_PATH) + +KCONFIG_FOOTER="\nendif # PSA_CRYPTO_CLIENT\n" + +H_HEADER="""\ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* This file was automatically generated by {} + * from: {} + * Do not edit it manually. + */ + +#ifndef CONFIG_PSA_H +#define CONFIG_PSA_H +""".format(os.path.basename(__file__), INPUT_REL_PATH) + +H_FOOTER="\n#endif /* CONFIG_PSA_H */\n" + +def parse_psa_symbols(input_file: str): + symbols = [] + with open(input_file) as file: + content = file.readlines() + for line in content: + res = re.findall(r"^#define *(PSA_WANT_\w+)", line) + if len(res) > 0: + symbols.append(res[0]) + return symbols + +def generate_kconfig_content(symbols: List[str]) -> str: + output = [] + for sym in symbols: + output.append(""" +config {0} +\tbool "{0}" if !MBEDTLS_PROMPTLESS +\tdefault y if PSA_CRYPTO_ENABLE_ALL +""".format(sym)) + + return KCONFIG_HEADER + "".join(output) + KCONFIG_FOOTER + +def generate_header_content(symbols: List[str]) -> str: + output = [] + for sym in symbols: + output.append(""" +#if defined(CONFIG_{0}) +#define {0} 1 +#endif +""".format(sym)) + + return H_HEADER + "".join(output) + H_FOOTER + +def generate_output_file(content: str, file_name: str): + with open(file_name, "wt") as output_file: + output_file.write(content) + +def check_file(content: str, file_name: str): + file_content = "" + with open(file_name) as input_file: + file_content = input_file.read() + if file_content != content: + print() + return False + return True + +def main(): + arg_parser = argparse.ArgumentParser(allow_abbrev = False) + arg_parser.add_argument("--check", action = "store_true", default = False) + args = arg_parser.parse_args() + + check_files = args.check + + psa_symbols = parse_psa_symbols(INPUT_FILE) + kconfig_content = generate_kconfig_content(psa_symbols) + header_content = generate_header_content(psa_symbols) + + if check_files: + if ((not check_file(kconfig_content, KCONFIG_PATH)) or + (not check_file(header_content, HEADER_PATH))): + print("Error: PSA Kconfig and header files do not match with the current" + "version of MbedTLS. Please update them.") + sys.exit(1) + else: + generate_output_file(kconfig_content, KCONFIG_PATH) + generate_output_file(header_content, HEADER_PATH) + + sys.exit(0) + +if __name__ == "__main__": + main() diff --git a/modules/mbedtls/zephyr_init.c b/modules/mbedtls/zephyr_init.c index 28a6a40fdc545..bfdc83863463c 100644 --- a/modules/mbedtls/zephyr_init.c +++ b/modules/mbedtls/zephyr_init.c @@ -94,6 +94,12 @@ static int _mbedtls_init(void) mbedtls_debug_set_threshold(CONFIG_MBEDTLS_DEBUG_LEVEL); #endif +#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_CLIENT) + if (psa_crypto_init() != PSA_SUCCESS) { + return -EIO; + } +#endif + return 0; } @@ -115,3 +121,26 @@ mbedtls_ms_time_t mbedtls_ms_time(void) { return (mbedtls_ms_time_t)k_uptime_get(); } + +#if defined(CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) +/* MBEDTLS_PSA_CRYPTO_C requires a random generator to work and this can + * be achieved through either legacy MbedTLS modules + * (ENTROPY + CTR_DRBG/HMAC_DRBG) or provided externally by enabling the + * CONFIG_MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG. In the latter case the following + * callback functions needs to be defined. + */ +psa_status_t mbedtls_psa_external_get_random( + mbedtls_psa_external_random_context_t *context, + uint8_t *output, size_t output_size, size_t *output_length) +{ + (void) context; + + if (sys_csrand_get(output, output_size) != 0) { + return PSA_ERROR_GENERIC_ERROR; + } + + *output_length = output_size; + + return PSA_SUCCESS; +} +#endif diff --git a/modules/openthread/CMakeLists.txt b/modules/openthread/CMakeLists.txt index c638d3394f4cb..c155fab65f986 100644 --- a/modules/openthread/CMakeLists.txt +++ b/modules/openthread/CMakeLists.txt @@ -44,11 +44,13 @@ kconfig_to_ot_option(CONFIG_OPENTHREAD_BACKBONE_ROUTER_DUA_NDPROXYING OT_BACKBON kconfig_to_ot_option(CONFIG_OPENTHREAD_BACKBONE_ROUTER_MULTICAST_ROUTING OT_BACKBONE_ROUTER_MULTICAST_ROUTING "Enable BBR MR support") kconfig_to_ot_option(CONFIG_OPENTHREAD_BLE_TCAT OT_BLE_TCAT "Enable BLE TCAT support") kconfig_to_ot_option(CONFIG_OPENTHREAD_BORDER_AGENT OT_BORDER_AGENT "Enable Border Agent") +kconfig_to_ot_option(CONFIG_OPENTHREAD_BORDER_AGENT_EPHEMERAL_KEY_ENABLE OT_BORDER_AGENT_EPSKC "Border agent ephemeral PSKc") kconfig_to_ot_option(CONFIG_OPENTHREAD_BORDER_ROUTER OT_BORDER_ROUTER "Enable Border Router") kconfig_to_ot_option(CONFIG_OPENTHREAD_BORDER_ROUTING OT_BORDER_ROUTING "Enable Border routing") kconfig_to_ot_option(CONFIG_OPENTHREAD_BORDER_ROUTING_COUNTERS OT_BORDER_ROUTING_COUNTERS "Enable Border routing counters") kconfig_to_ot_option(CONFIG_OPENTHREAD_BORDER_ROUTING_DHCP6_PD OT_BORDER_ROUTING_DHCP6_PD "DHCPv6-PD support in border routing") kconfig_to_ot_option(CONFIG_OPENTHREAD_CHANNEL_MANAGER OT_CHANNEL_MANAGER "Enable channel manager support") +kconfig_to_ot_option(CONFIG_OPENTHREAD_CHANNEL_MANAGER_CSL OT_CHANNEL_MANAGER_CSL "Channel manager for CSL channel") kconfig_to_ot_option(CONFIG_OPENTHREAD_CHANNEL_MONITOR OT_CHANNEL_MONITOR "Enable channel monitor support") kconfig_to_ot_option(CONFIG_OPENTHREAD_COAP OT_COAP "Enable CoAP API") kconfig_to_ot_option(CONFIG_OPENTHREAD_COAP_BLOCK OT_COAP_BLOCK "Enable CoAP Block-wise option support") @@ -83,8 +85,10 @@ kconfig_to_ot_option(CONFIG_OPENTHREAD_LEGACY OT_LEGACY "Enable legacy network s kconfig_to_ot_option(CONFIG_OPENTHREAD_LINK_METRICS_INITIATOR OT_LINK_METRICS_INITIATOR "Enable Link Metrics initiator for Thread 1.2") kconfig_to_ot_option(CONFIG_OPENTHREAD_LINK_METRICS_MANAGER OT_LINK_METRICS_MANAGER "Enable Link Metrics manager for Thread 1.2") kconfig_to_ot_option(CONFIG_OPENTHREAD_LINK_METRICS_SUBJECT OT_LINK_METRICS_SUBJECT "Enable Link Metrics subject for Thread 1.2") +kconfig_to_ot_option(CONFIG_OPENTHREAD_PLATFORM_LOG_CRASH_DUMP OT_PLATFORM_LOG_CRASH_DUMP "Platform log crash dump") kconfig_to_ot_option(CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC OT_LOG_LEVEL_DYNAMIC "Enable dynamic log level control") kconfig_to_ot_option(CONFIG_OPENTHREAD_MAC_FILTER OT_MAC_FILTER "Enable MAC filter support") +kconfig_to_ot_option(CONFIG_OPENTHREAD_MULTICAST_DNS OT_MDNS "multicast DNS (mDNS)") kconfig_to_ot_option(CONFIG_OPENTHREAD_MESH_DIAG OT_MESH_DIAG "Enable Mesh Diagnostics") kconfig_to_ot_option(CONFIG_OPENTHREAD_MESSAGE_USE_HEAP OT_MESSAGE_USE_HEAP "Enable heap allocator for message buffers") kconfig_to_ot_option(CONFIG_OPENTHREAD_MLE_LONG_ROUTES OT_MLE_LONG_ROUTES "Enable MLE long routes support (Experimental)") @@ -119,6 +123,7 @@ kconfig_to_ot_option(CONFIG_OPENTHREAD_TX_BEACON_PAYLOAD OT_TX_BEACON_PAYLOAD "E kconfig_to_ot_option(CONFIG_OPENTHREAD_TX_QUEUE_STATISTICS OT_TX_QUEUE_STATS "Enable tx queue statistics") kconfig_to_ot_option(CONFIG_OPENTHREAD_UDP_FORWARD OT_UDP_FORWARD "Enable UDP forward feature") kconfig_to_ot_option(CONFIG_OPENTHREAD_UPTIME OT_UPTIME "Enable support for tracking OpenThread instance's uptime") +kconfig_to_ot_option(CONFIG_OPENTHREAD_VERHOEFF_CHECKSUM OT_VERHOEFF_CHECKSUM "Verhoeff checksum") if(CONFIG_OPENTHREAD_COPROCESSOR_VENDOR_HOOK_SOURCE) set(OT_NCP_VENDOR_HOOK_SOURCE ${CONFIG_OPENTHREAD_COPROCESSOR_VENDOR_HOOK_SOURCE} CACHE STRING "NCP vendor hook source file name" FORCE) diff --git a/modules/openthread/Kconfig.features b/modules/openthread/Kconfig.features index 7fd9ed5080207..32f451ca38ead 100644 --- a/modules/openthread/Kconfig.features +++ b/modules/openthread/Kconfig.features @@ -46,6 +46,9 @@ config OPENTHREAD_BLE_TCAT config OPENTHREAD_BORDER_AGENT bool "Border Agent support" +config OPENTHREAD_BORDER_AGENT_EPHEMERAL_KEY_ENABLE + bool "Border agent ephemeral PSKc" + config OPENTHREAD_BORDER_ROUTER bool "Border Router support" @@ -65,6 +68,9 @@ config OPENTHREAD_CHANNEL_MANAGER bool "Channel manager support" depends on OPENTHREAD_CHANNEL_MONITOR +config OPENTHREAD_CHANNEL_MANAGER_CSL + bool "Channel manager for CSL channel" + config OPENTHREAD_COAP bool "OpenThread CoAP support" help @@ -192,12 +198,18 @@ config OPENTHREAD_LINK_METRICS_MANAGER config OPENTHREAD_LINK_METRICS_SUBJECT bool "Link Metrics subject" +config OPENTHREAD_PLATFORM_LOG_CRASH_DUMP + bool "Platform log crash dump" + config OPENTHREAD_LOG_LEVEL_DYNAMIC bool "Dynamic log level control" config OPENTHREAD_MAC_FILTER bool "MAC filter support" +config OPENTHREAD_MULTICAST_DNS + bool "Multicast DNS (mDNS)" + config OPENTHREAD_MESH_DIAG bool "Mesh Diagnostics" depends on OPENTHREAD_FTD @@ -359,3 +371,6 @@ config OPENTHREAD_UDP_FORWARD config OPENTHREAD_UPTIME bool "Openthread uptime counter" default y if OPENTHREAD_FTD + +config OPENTHREAD_VERHOEFF_CHECKSUM + bool "Verhoeff checksum" diff --git a/modules/openthread/platform/ble.c b/modules/openthread/platform/ble.c index 7b41556b6173a..55330e1ffe769 100644 --- a/modules/openthread/platform/ble.c +++ b/modules/openthread/platform/ble.c @@ -23,7 +23,9 @@ #include /* OpenThread BLE driver API */ +#include #include +#include /* Zephyr Logging */ @@ -100,13 +102,17 @@ static struct bt_conn_cb conn_callbacks = {.connected = connected, .le_param_req = le_param_req, .le_param_updated = le_param_updated}; -static const struct bt_data ad[] = { +static uint8_t service_data[OT_TCAT_ADVERTISEMENT_MAX_LEN] = {0}; +static const uint8_t service_data_size = ARRAY_SIZE(service_data); + +static struct bt_data ad[] = { BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN), + BT_DATA(BT_DATA_SVC_DATA16, service_data, service_data_size), }; -static const struct bt_data sd[] = { +static struct bt_data sd[] = { BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(TOBLE_SERVICE_UUID)), + BT_DATA(BT_DATA_SVC_DATA16, service_data, service_data_size), }; /* Zephyr BLE Message Queue and Thread */ @@ -388,12 +394,52 @@ static void bt_ready(int err) k_sem_give(&ot_plat_ble_init_semaphore); /* BLE stack up an running */ } +void otPlatBleGetLinkCapabilities(otInstance *aInstance, + otBleLinkCapabilities *aBleLinkCapabilities) +{ + ARG_UNUSED(aInstance); + + aBleLinkCapabilities->mGattNotifications = 1; + aBleLinkCapabilities->mL2CapDirect = 0; + aBleLinkCapabilities->mRsv = 0; +} + +bool otPlatBleSupportsMultiRadio(otInstance *aInstance) +{ + OT_UNUSED_VARIABLE(aInstance); + + return false; +} + +otError otPlatBleGetAdvertisementBuffer(otInstance *aInstance, uint8_t **aAdvertisementBuffer) +{ + ARG_UNUSED(aInstance); + + *aAdvertisementBuffer = service_data; + + return OT_ERROR_NONE; +} + +otError otPlatBleGapAdvSetData(otInstance *aInstance, uint8_t *aAdvertisementData, + uint16_t aAdvertisementLen) +{ + ARG_UNUSED(aInstance); + + if (aAdvertisementLen > OT_TCAT_ADVERTISEMENT_MAX_LEN || aAdvertisementData == NULL) { + LOG_ERR("Invalid TCAT Advertisement parameters advlen: %d", aAdvertisementLen); + return OT_ERROR_INVALID_ARGS; + } + + ad[1].data_len = (uint8_t)aAdvertisementLen; + sd[1].data_len = (uint8_t)aAdvertisementLen; + return OT_ERROR_NONE; +} + otError otPlatBleGapAdvStart(otInstance *aInstance, uint16_t aInterval) { ARG_UNUSED(aInstance); ARG_UNUSED(aInterval); - /* TO DO advertisement format change */ int err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err != 0 && err != -EALREADY) { diff --git a/modules/percepio/CMakeLists.txt b/modules/percepio/CMakeLists.txt index 62fe2b058f9cb..c02b669f0b359 100644 --- a/modules/percepio/CMakeLists.txt +++ b/modules/percepio/CMakeLists.txt @@ -73,6 +73,17 @@ if(CONFIG_PERCEPIO_TRACERECORDER) ) endif() + if(CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_FILE) + zephyr_library_sources( + ${TRACERECORDER_DIR}/streamports/File/trcStreamPort.c + ) + + zephyr_include_directories( + ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/File/config/ + ${TRACERECORDER_DIR}/streamports/File/include/ + ) + endif() + if (CONFIG_PERCEPIO_TRC_CFG_STREAM_PORT_ZEPHYR_SEMIHOST) zephyr_library_sources( ${TRACERECORDER_DIR}/kernelports/Zephyr/streamports/Semihost/trcStreamPort.c diff --git a/modules/thrift/CMakeLists.txt b/modules/thrift/CMakeLists.txt index 468286c03e6c1..d26b6ef9c3ee4 100644 --- a/modules/thrift/CMakeLists.txt +++ b/modules/thrift/CMakeLists.txt @@ -12,7 +12,6 @@ zephyr_include_directories(include) zephyr_include_directories(${THRIFT_UPSTREAM}/lib/cpp/src) zephyr_library_sources( - src/_stat.c src/thrift/server/TFDServer.cpp ${THRIFT_UPSTREAM}/lib/cpp/src/thrift/protocol/TProtocol.cpp ${THRIFT_UPSTREAM}/lib/cpp/src/thrift/server/TConnectedClient.cpp diff --git a/modules/thrift/src/_stat.c b/modules/thrift/src/_stat.c deleted file mode 100644 index 688e1a53ceffb..0000000000000 --- a/modules/thrift/src/_stat.c +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2022 Meta - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include - -int stat(const char *restrict path, struct stat *restrict buf) -{ - ARG_UNUSED(path); - ARG_UNUSED(buf); - - errno = ENOTSUP; - - return -1; -} diff --git a/modules/trusted-firmware-m/CMakeLists.txt b/modules/trusted-firmware-m/CMakeLists.txt index 5e551777080ff..b3d836490d618 100644 --- a/modules/trusted-firmware-m/CMakeLists.txt +++ b/modules/trusted-firmware-m/CMakeLists.txt @@ -35,6 +35,25 @@ if (CONFIG_BUILD_WITH_TFM) list(APPEND TFM_CMAKE_ARGS -DBL2=TRUE) list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_IMAGE_VERSION_S=${CONFIG_TFM_IMAGE_VERSION_S}) list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_IMAGE_VERSION_NS=${CONFIG_TFM_IMAGE_VERSION_NS}) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_SIGNATURE_TYPE=${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE}) + + # TF-M's config/check_config.cmake requires MCUBOOT_BUILTIN_KEY=OFF for RSA + # and MCUBOOT_USE_PSA_CRYPTO for EC-P. The others are dependencies needed + # for either the build or the boot to succeed. + if (${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE} MATCHES "^RSA") + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_BUILTIN_KEY=OFF) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_HW_KEY=ON) + elseif (${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE} MATCHES "^EC-P") + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_USE_PSA_CRYPTO=ON) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_BUILTIN_KEY=ON) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_HW_KEY=OFF) + endif() + + foreach(SUFFIX IN ITEMS "S" "NS") + string(CONFIGURE ${CONFIG_TFM_KEY_FILE_${SUFFIX}} CONFIG_TFM_KEY_FILE_${SUFFIX}) + list(APPEND TFM_CMAKE_ARGS -DMCUBOOT_KEY_${SUFFIX}=${CONFIG_TFM_KEY_FILE_${SUFFIX}}) + endforeach() + else() list(APPEND TFM_CMAKE_ARGS -DBL2=FALSE) endif() @@ -135,8 +154,6 @@ if (CONFIG_BUILD_WITH_TFM) set(TFM_BINARY_DIR ${CMAKE_BINARY_DIR}/tfm) - set(PSA_ARCH_TESTS_PATH ${ZEPHYR_CURRENT_MODULE_DIR}/../psa-arch-tests) - set(TFM_INTERFACE_SOURCE_DIR ${TFM_BINARY_DIR}/api_ns/interface/src) set(TFM_INTERFACE_INCLUDE_DIR ${TFM_BINARY_DIR}/api_ns/interface/include) set(TFM_INTERFACE_LIB_DIR ${TFM_BINARY_DIR}/api_ns/interface/lib) @@ -201,6 +218,16 @@ if (CONFIG_BUILD_WITH_TFM) message(FATAL_ERROR "Unsupported ZEPHYR_TOOLCHAIN_VARIANT: ${ZEPHYR_TOOLCHAIN_VARIANT}") endif() + if (CONFIG_TFM_PARTITION_INITIAL_ATTESTATION AND CONFIG_TFM_QCBOR_PATH STREQUAL "") + # TODO: Remove this when QCBOR licensing issues w/t_cose have been resolved, + # or only allow it when 'QCBOR_PATH' is set to a local path where QCBOR has + # been manually downloaded by the user before starting the build. + message(FATAL_ERROR "CONFIG_TFM_PARTITION_INITIAL_ATTESTATION is not available " + "with TF-M due to licensing issues with a dependent library. This " + "restriction will be removed once licensing issues have been resolved." + ) + endif() + string(REPLACE "toolchain" "toolchain_ns" TFM_TOOLCHAIN_NS_FILE ${TFM_TOOLCHAIN_FILE}) if(CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0_NS) @@ -228,6 +255,8 @@ if (CONFIG_BUILD_WITH_TFM) list(APPEND TFM_CMAKE_ARGS -DCONFIG_TFM_ENABLE_FP=OFF) endif() + list(APPEND TFM_CMAKE_ARGS -DTFM_TESTS_REVISION_CHECKS=OFF) + file(MAKE_DIRECTORY ${TFM_BINARY_DIR}) add_custom_target(tfm_cmake DEPENDS ${TFM_BINARY_DIR}/CMakeCache.txt @@ -241,13 +270,11 @@ if (CONFIG_BUILD_WITH_TFM) -DCMAKE_BUILD_TYPE=${TFM_CMAKE_BUILD_TYPE} -DTFM_PLATFORM=${CONFIG_TFM_BOARD} -DCONFIG_TFM_BUILD_LOG_QUIET=ON - -DSILENCE_TFM_VERSION_WARNING=ON -DCONFIG_TFM_MEMORY_USAGE_QUIET=OFF -DPython3_EXECUTABLE=${Python3_EXECUTABLE} ${TFM_CMAKE_ARGS} $> -DMBEDCRYPTO_PATH=$>,$,${ZEPHYR_MBEDTLS_MODULE_DIR}> - -DPSA_ARCH_TESTS_PATH=${PSA_ARCH_TESTS_PATH} ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR} WORKING_DIRECTORY ${TFM_BINARY_DIR} COMMAND_EXPAND_LISTS diff --git a/modules/trusted-firmware-m/Kconfig.tfm b/modules/trusted-firmware-m/Kconfig.tfm index 1c11a997cf7ff..8834256ccbb56 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm +++ b/modules/trusted-firmware-m/Kconfig.tfm @@ -30,6 +30,7 @@ menuconfig BUILD_WITH_TFM depends on TFM_BOARD != "" depends on ARM_TRUSTZONE_M select BUILD_OUTPUT_HEX + select PSA_CRYPTO_CLIENT imply INIT_ARCH_HW_AT_BOOT imply ARM_NONSECURE_PREEMPTIBLE_SECURE_CALLS imply MBEDTLS @@ -52,27 +53,8 @@ menuconfig BUILD_WITH_TFM if BUILD_WITH_TFM -config TFM_KEY_FILE_S - string "Path to private key used to sign secure firmware images." - depends on BUILD_WITH_TFM - default "${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/bl2/ext/mcuboot/root-RSA-3072.pem" - help - The path and filename for the .pem file containing the private key - that should be used by the BL2 bootloader when signing secure - firmware images. - -config TFM_KEY_FILE_NS - string "Path to private key used to sign non-secure firmware images." - depends on BUILD_WITH_TFM - default "${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/bl2/ext/mcuboot/root-RSA-3072_1.pem" - help - The path and filename for the .pem file containing the private key - that should be used by the BL2 bootloader when signing non-secure - firmware images. - config TFM_PROFILE string - depends on BUILD_WITH_TFM default "profile_small" if TFM_PROFILE_TYPE_SMALL default "profile_medium" if TFM_PROFILE_TYPE_MEDIUM default "profile_medium_arotless" if TFM_PROFILE_TYPE_AROTLESS @@ -84,7 +66,6 @@ config TFM_PROFILE choice TFM_PROFILE_TYPE prompt "TF-M build profile" - depends on BUILD_WITH_TFM default TFM_PROFILE_TYPE_NOT_SET help The TF-M build profile selection. Can be empty (not set), @@ -133,7 +114,6 @@ endchoice config TFM_ISOLATION_LEVEL int "Isolation level setting." if (TFM_PROFILE_TYPE_NOT_SET && TFM_IPC) range 1 3 - depends on BUILD_WITH_TFM default 1 if TFM_PROFILE_TYPE_SMALL || !TFM_IPC default 2 if TFM_PROFILE_TYPE_MEDIUM default 3 if TFM_PROFILE_TYPE_LARGE @@ -258,6 +238,28 @@ config TFM_CONNECTION_BASED_SERVICE_API if TFM_BL2 +config TFM_MCUBOOT_SIGNATURE_TYPE + string "The signature type used to sign the secure and non-secure firmware images." + default "EC-P256" + help + Available types: RSA-2048, RSA-3072, EC-P256, EC-P384. + +config TFM_KEY_FILE_S + string "Path to private key used to sign secure firmware images." + default "${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/bl2/ext/mcuboot/root-${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE}.pem" + help + The path and filename for the .pem file containing the private key + that should be used by the BL2 bootloader when signing secure + firmware images. + +config TFM_KEY_FILE_NS + string "Path to private key used to sign non-secure firmware images." + default "${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/bl2/ext/mcuboot/root-${CONFIG_TFM_MCUBOOT_SIGNATURE_TYPE}_1.pem" + help + The path and filename for the .pem file containing the private key + that should be used by the BL2 bootloader when signing non-secure + firmware images. + config TFM_MCUBOOT_IMAGE_NUMBER int "Granularity of FW updates of TFM and app" range 1 2 @@ -392,6 +394,7 @@ config TFM_PSA_TEST_STORAGE config TFM_PSA_TEST_INITIAL_ATTESTATION bool "Initial attestation tests" depends on MAIN_STACK_SIZE >= 4096 + select TFM_PARTITION_INITIAL_ATTESTATION help Enable the PSA Initial Attestation test suite. diff --git a/modules/trusted-firmware-m/Kconfig.tfm.partitions b/modules/trusted-firmware-m/Kconfig.tfm.partitions index 67b46f5328ba9..1e45ad144ca6d 100644 --- a/modules/trusted-firmware-m/Kconfig.tfm.partitions +++ b/modules/trusted-firmware-m/Kconfig.tfm.partitions @@ -45,7 +45,6 @@ config TFM_PARTITION_INITIAL_ATTESTATION bool "Secure partition 'Initial Attestation'" depends on TFM_PARTITION_CRYPTO depends on TFM_INITIAL_ATTESTATION_KEY - default n help Setting this option will cause '-DTFM_PARTITION_INITIAL_ATTESTATION' to be passed to the TF-M build system. Look at 'config_default.cmake' diff --git a/modules/trusted-firmware-m/nordic/CMakeLists.txt b/modules/trusted-firmware-m/nordic/CMakeLists.txt index d75b34a810988..c351f97f906a5 100644 --- a/modules/trusted-firmware-m/nordic/CMakeLists.txt +++ b/modules/trusted-firmware-m/nordic/CMakeLists.txt @@ -14,7 +14,6 @@ set(partition_includes set(board_includes ${CMAKE_BINARY_DIR}/../zephyr/misc/generated/syscalls_links/include - ${ZEPHYR_BASE}/include ) target_include_directories(platform_region_defs diff --git a/modules/trusted-firmware-m/nordic/include/RTE_Device.h b/modules/trusted-firmware-m/nordic/include/RTE_Device.h index ca886583fa925..0c5c498e43a27 100644 --- a/modules/trusted-firmware-m/nordic/include/RTE_Device.h +++ b/modules/trusted-firmware-m/nordic/include/RTE_Device.h @@ -7,7 +7,7 @@ #ifndef __RTE_DEVICE_H #define __RTE_DEVICE_H -#include +#include /* ARRAY_SIZE causes a conflict as it is defined both by TF-M and indirectly by devicetree.h */ #undef ARRAY_SIZE diff --git a/modules/trusted-firmware-m/nordic/include/device_cfg.h b/modules/trusted-firmware-m/nordic/include/device_cfg.h index 9b766a35eb956..84fdea0e1a9bf 100644 --- a/modules/trusted-firmware-m/nordic/include/device_cfg.h +++ b/modules/trusted-firmware-m/nordic/include/device_cfg.h @@ -7,7 +7,7 @@ #ifndef DEVICE_CFG_H__ #define DEVICE_CFG_H__ -#include +#include /* ARRAY_SIZE causes a conflict as it is defined both by TF-M and indirectly by devicetree.h */ #undef ARRAY_SIZE diff --git a/modules/trusted-firmware-m/nordic/ns/CMakeLists.txt b/modules/trusted-firmware-m/nordic/ns/CMakeLists.txt index 5bb8cb5bd94ae..67ee755c25eca 100644 --- a/modules/trusted-firmware-m/nordic/ns/CMakeLists.txt +++ b/modules/trusted-firmware-m/nordic/ns/CMakeLists.txt @@ -17,7 +17,6 @@ set(partition_includes set(board_includes ${CMAKE_BINARY_DIR}/../zephyr/misc/generated/syscalls_links/include - ${ZEPHYR_BASE}/include ) target_include_directories(platform_region_defs diff --git a/samples/application_development/code_relocation_nocopy/README.rst b/samples/application_development/code_relocation_nocopy/README.rst index f8ac178a7e94d..9b7ca572a0fff 100644 --- a/samples/application_development/code_relocation_nocopy/README.rst +++ b/samples/application_development/code_relocation_nocopy/README.rst @@ -10,18 +10,14 @@ using a custom linker script. Differently from the code relocation sample, this sample is relocating the content of the ext_code.c file to a different FLASH section and the code is XIP -directly from there without the need to copy / relocate the code. +directly from there without the need to copy / relocate the code. All other code +(e.g. main(), Zephyr kernel) stays in the internal flash. nRF5340 DK platform instructions ******************************** The nRF5340 DK has a 64 Mb external flash memory supporting Quad SPI. It is -possible to do XIP from the external flash memory. - -The external flash memory is mapped to 0x10000000. - -In this sample we relocate some of the code to the external flash memory with -the remaining Zephyr kernel in the internal flash. +mapped to 0x10000000. To build and flash the application (including the external memory part): @@ -31,7 +27,32 @@ To build and flash the application (including the external memory part): :goals: build flash :compact: -Execution output: +STM32F769I-Discovery platform instructions +****************************************** + +The stm32f769i_disco has 64MB of external flash attached via QSPI. It is mapped +to 0x90000000. + +.. zephyr-app-commands:: + :zephyr-app: samples/application_development/code_relocation_nocopy + :board: stm32f769i_disco + :goals: build flash + :compact: + +STM32 b_u585i_iot02a Discovery kit instructions +*********************************************** + +The b_u585i_iot02a has 64MB of external flash attached via OSPI. It is mapped +to 0x70000000. + +.. zephyr-app-commands:: + :zephyr-app: samples/application_development/code_relocation_nocopy + :board: b_u585i_iot02a + :goals: build flash + :compact: + +Execution output +**************** .. code-block:: console diff --git a/samples/application_development/code_relocation_nocopy/boards/b_u585i_iot02a.conf b/samples/application_development/code_relocation_nocopy/boards/b_u585i_iot02a.conf new file mode 100644 index 0000000000000..eac2504a7850e --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/b_u585i_iot02a.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/boards/stm32f769i_disco.conf b/samples/application_development/code_relocation_nocopy/boards/stm32f769i_disco.conf new file mode 100644 index 0000000000000..eac2504a7850e --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/stm32f769i_disco.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/boards/stm32h745i_disco_m7.conf b/samples/application_development/code_relocation_nocopy/boards/stm32h745i_disco_m7.conf new file mode 100644 index 0000000000000..eac2504a7850e --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/stm32h745i_disco_m7.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/boards/stm32h747i_disco_m7.conf b/samples/application_development/code_relocation_nocopy/boards/stm32h747i_disco_m7.conf new file mode 100644 index 0000000000000..eac2504a7850e --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/stm32h747i_disco_m7.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/boards/stm32h750b_dk.conf b/samples/application_development/code_relocation_nocopy/boards/stm32h750b_dk.conf new file mode 100644 index 0000000000000..eac2504a7850e --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/stm32h750b_dk.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/boards/stm32h7b3i_dk.conf b/samples/application_development/code_relocation_nocopy/boards/stm32h7b3i_dk.conf new file mode 100644 index 0000000000000..eac2504a7850e --- /dev/null +++ b/samples/application_development/code_relocation_nocopy/boards/stm32h7b3i_dk.conf @@ -0,0 +1,2 @@ +CONFIG_FLASH=y +CONFIG_STM32_MEMMAP=y diff --git a/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld b/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld index 7ead7f6bae483..7d4e3a964fc35 100644 --- a/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld +++ b/samples/application_development/code_relocation_nocopy/linker_arm_nocopy.ld @@ -26,6 +26,20 @@ #define EXTFLASH_SIZE DT_PROP_OR(EXTFLASH_NODE, size_in_bytes, \ DT_PROP(EXTFLASH_NODE, size) / 8) +#elif defined(CONFIG_STM32_MEMMAP) && DT_NODE_EXISTS(DT_INST(0, st_stm32_ospi_nor)) +/* On stm32 OSPI, external flash is mapped in XIP region at address given by the reg property. */ + +#define EXTFLASH_NODE DT_INST(0, st_stm32_ospi_nor) +#define EXTFLASH_ADDR DT_REG_ADDR(DT_INST(0, st_stm32_ospi_nor)) +#define EXTFLASH_SIZE DT_REG_ADDR_BY_IDX(DT_INST(0, st_stm32_ospi_nor), 1) + +#elif defined(CONFIG_STM32_MEMMAP) && DT_NODE_EXISTS(DT_INST(0, st_stm32_qspi_nor)) +/* On stm32 QSPI, external flash is mapped in XIP region at address given by the reg property. */ + +#define EXTFLASH_NODE DT_INST(0, st_stm32_qspi_nor) +#define EXTFLASH_ADDR DT_REG_ADDR(DT_INST(0, st_stm32_qspi_nor)) +#define EXTFLASH_SIZE DT_REG_ADDR_BY_IDX(DT_INST(0, st_stm32_qspi_nor), 1) + #else /* diff --git a/samples/application_development/code_relocation_nocopy/sample.yaml b/samples/application_development/code_relocation_nocopy/sample.yaml index b9415221e2468..79c6bb65c5f65 100644 --- a/samples/application_development/code_relocation_nocopy/sample.yaml +++ b/samples/application_development/code_relocation_nocopy/sample.yaml @@ -6,6 +6,12 @@ tests: platform_allow: - qemu_cortex_m3 - nrf5340dk/nrf5340/cpuapp + - stm32f769i_disco + - stm32h7b3i_dk + - b_u585i_iot02a + - stm32h745i_disco/stm32h745xx/m7 + - stm32h750b_dk + - stm32f746g_disco integration_platforms: - qemu_cortex_m3 tags: linker diff --git a/samples/application_development/sysbuild/with_mcuboot/sample.yaml b/samples/application_development/sysbuild/with_mcuboot/sample.yaml deleted file mode 100644 index 785bc0d24004d..0000000000000 --- a/samples/application_development/sysbuild/with_mcuboot/sample.yaml +++ /dev/null @@ -1,20 +0,0 @@ -sample: - description: Sample with MCUboot built through sysbuild - name: with mcuboot -tests: - sample.application_development.sysbuild.with_mcuboot: - sysbuild: true - # Platform allowed is used as twister using sysbuild still lacks proper - # filtering support, see discussion in #49552. - platform_allow: - - reel_board - - nrf52840dk/nrf52840 - integration_platforms: - - nrf52840dk/nrf52840 - tags: mcuboot - harness: console - harness_config: - type: multi_line - regex: - - "Address of sample(.*)" - - "Hello sysbuild with mcuboot!(.*)" diff --git a/samples/arch/smp/pktqueue/src/main.c b/samples/arch/smp/pktqueue/src/main.c index 009cd2de966ec..cfffd813a8bc2 100644 --- a/samples/arch/smp/pktqueue/src/main.c +++ b/samples/arch/smp/pktqueue/src/main.c @@ -5,7 +5,27 @@ */ #include "pktqueue.h" -#include "main.h" + +/* Amount of parallel processed sender/receiver queues of packet headers */ +#define QUEUE_NUM 2 + +/* Amount of execution threads per pair of queues*/ +#define THREADS_NUM (CONFIG_MP_MAX_NUM_CPUS+1) + +/* Amount of packet headers in a queue */ +#define SIZE_OF_QUEUE 5000 + +/* Size of packet header (in bytes) */ +#define SIZE_OF_HEADER 24 + +/* CRC16 polynomial */ +#define POLYNOMIAL 0x8005 + +/* CRC bytes in the packet */ +#define CRC_BYTE_1 10 +#define CRC_BYTE_2 11 + +#define STACK_SIZE 2048 static struct k_thread tthread[THREADS_NUM*QUEUE_NUM]; static struct k_thread qthread[QUEUE_NUM]; diff --git a/samples/arch/smp/pktqueue/src/main.h b/samples/arch/smp/pktqueue/src/main.h deleted file mode 100644 index 20020563ca164..0000000000000 --- a/samples/arch/smp/pktqueue/src/main.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2020 Synopsys, Inc. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - - -/* Amount of parallel processed sender/receiver queues of packet headers */ -#define QUEUE_NUM 2 - -/* Amount of execution threads per pair of queues*/ -#define THREADS_NUM (CONFIG_MP_MAX_NUM_CPUS+1) - -/* Amount of packet headers in a queue */ -#define SIZE_OF_QUEUE 5000 - -/* Size of packet header (in bytes) */ -#define SIZE_OF_HEADER 24 - -/* CRC16 polynomial */ -#define POLYNOMIAL 0x8005 - -/* CRC bytes in the packet */ -#define CRC_BYTE_1 10 -#define CRC_BYTE_2 11 - -#define STACK_SIZE 2048 diff --git a/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay b/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay new file mode 100644 index 0000000000000..a2aeeeefee29f --- /dev/null +++ b/samples/basic/blinky_pwm/boards/beagleconnect_freedom.overlay @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2024 Ayush Singh + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + pwm-led0 = &pwm_led0; + }; + + pwmleds { + compatible = "pwm-leds"; + pwm_led0: pwm_led_0 { + pwms = <&pwm0 0 255 PWM_POLARITY_NORMAL>; + label = "PWM MB1"; + }; + }; +}; + +&pinctrl { + pwm0_default: pwm0_default { + pinmux = <17 IOC_PORT_MCU_PORT_EVENT1>; + bias-disable; + drive-strength = <8>; + }; +}; + +&gpt0 { + status = "okay"; +}; + +&pwm0 { + status = "okay"; + pinctrl-0 = <&pwm0_default>; + pinctrl-names = "default"; +}; diff --git a/samples/basic/blinky_pwm/boards/xiao_rp2040.overlay b/samples/basic/blinky_pwm/boards/xiao_rp2040.overlay new file mode 100644 index 0000000000000..43e054ede94f1 --- /dev/null +++ b/samples/basic/blinky_pwm/boards/xiao_rp2040.overlay @@ -0,0 +1,13 @@ +&{/pwm_leds} { + status = "okay"; +}; + +&pwm_led0 { + status = "okay"; +}; + +&pwm { + status = "okay"; + divider-frac-4 = <15>; + divider-int-4 = <255>; +}; diff --git a/samples/basic/blinky_pwm/sample.yaml b/samples/basic/blinky_pwm/sample.yaml index de2cb234933c2..d2087f73347f3 100644 --- a/samples/basic/blinky_pwm/sample.yaml +++ b/samples/basic/blinky_pwm/sample.yaml @@ -7,4 +7,13 @@ tests: - drivers - pwm depends_on: pwm - harness: led + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "PWM-based blinky" + - "Calibrating for channel [0-9]+" + - "Done calibrating; maximum/minimum periods [0-9]+/[0-9]+ nsec" + - "Using period [0-9]+" + - "Using period [0-9]+" diff --git a/samples/basic/blinky_pwm/src/main.c b/samples/basic/blinky_pwm/src/main.c index de1f6409c6d29..6539c05d5ccae 100644 --- a/samples/basic/blinky_pwm/src/main.c +++ b/samples/basic/blinky_pwm/src/main.c @@ -63,6 +63,7 @@ int main(void) printk("Error %d: failed to set pulse width\n", ret); return 0; } + printk("Using period %d\n", period); period = dir ? (period * 2U) : (period / 2U); if (period > max_period) { diff --git a/samples/basic/fade_led/boards/xiao_rp2040.overlay b/samples/basic/fade_led/boards/xiao_rp2040.overlay new file mode 100644 index 0000000000000..62c3a142cd4a6 --- /dev/null +++ b/samples/basic/fade_led/boards/xiao_rp2040.overlay @@ -0,0 +1,4 @@ +&pwm { + status = "okay"; + divider-int-4 = <255>; +}; diff --git a/samples/basic/fade_led/sample.yaml b/samples/basic/fade_led/sample.yaml index eae1afefe5b48..603c572147191 100644 --- a/samples/basic/fade_led/sample.yaml +++ b/samples/basic/fade_led/sample.yaml @@ -6,7 +6,14 @@ tests: - drivers - pwm depends_on: pwm - harness: led filter: dt_alias_exists("pwm-led0") and dt_compat_enabled("pwm-leds") integration_platforms: - nrf51dk/nrf51822 + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - "PWM-based LED fade" + - "Using pulse width [0-9]+%" + - "Using pulse width [0-9]+%" diff --git a/samples/basic/fade_led/src/main.c b/samples/basic/fade_led/src/main.c index ab7b2aca0328f..c6a49a13a1222 100644 --- a/samples/basic/fade_led/src/main.c +++ b/samples/basic/fade_led/src/main.c @@ -40,6 +40,7 @@ int main(void) printk("Error %d: failed to set pulse width\n", ret); return 0; } + printk("Using pulse width %d%%\n", 100 * pulse_width / pwm_led0.period); if (dir) { pulse_width += step; diff --git a/samples/basic/hash_map/src/main.c b/samples/basic/hash_map/src/main.c index 3c91928396397..b0861bcbb2e69 100644 --- a/samples/basic/hash_map/src/main.c +++ b/samples/basic/hash_map/src/main.c @@ -47,7 +47,7 @@ int main(void) LOG_DBG("Inserted %zu", i); - if (k_uptime_get() / MSEC_PER_SEC > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { + if (k_uptime_seconds() > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { goto out; } } @@ -60,7 +60,7 @@ int main(void) LOG_DBG("Replaced %zu", i); - if (k_uptime_get() / MSEC_PER_SEC > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { + if (k_uptime_seconds() > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { goto out; } } @@ -72,7 +72,7 @@ int main(void) LOG_DBG("Removed %zu", i - 1); - if (k_uptime_get() / MSEC_PER_SEC > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { + if (k_uptime_seconds() > CONFIG_TEST_LIB_HASH_MAP_DURATION_S) { goto out; } } diff --git a/samples/bluetooth/bap_broadcast_assistant/CMakeLists.txt b/samples/bluetooth/bap_broadcast_assistant/CMakeLists.txt new file mode 100644 index 0000000000000..2bc2770469109 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_assistant/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bap_broadcast_assistant) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/broadcast_audio_assistant/Kconfig b/samples/bluetooth/bap_broadcast_assistant/Kconfig similarity index 100% rename from samples/bluetooth/broadcast_audio_assistant/Kconfig rename to samples/bluetooth/bap_broadcast_assistant/Kconfig diff --git a/samples/bluetooth/bap_broadcast_assistant/README.rst b/samples/bluetooth/bap_broadcast_assistant/README.rst new file mode 100644 index 0000000000000..bf472b8a03179 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_assistant/README.rst @@ -0,0 +1,56 @@ +.. zephyr:code-sample:: bluetooth_bap_broadcast_assistant + :name: Bluetooth: Broadcast Audio Assistant + :relevant-api: bt_bap + + Use LE Audio Broadcast Assistant functionality + +Overview +******** + +Application demonstrating the LE Audio broadcast assistant functionality. + +The sample will automatically try to connect to a device in the BAP Scan Delegator +role (advertising support for the Broadcast Audio Scan Service (BASS)). +It will then search for a broadcast source and (if found) add the broadcast ID to +the BAP Scan Delegator. + +Practical use of this sample requires a sink (e.g. the Broadcast Audio Sink sample or +a set of LE Audio Broadcast capable earbuds) and a source (e.g. the Broadcast Audio +Source sample). + +This sample can be found under +:zephyr_file:`samples/bluetooth/bap_broadcast_assistant` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support +* Broadcast Audio Source and Sink devices + +Building and Running +******************** + +The application will act as a broadcast assistant with optionally preconfigured +filtering of broadcast sink and broadcast source names. By default, the application will +search for and connect to the first broadcast audio sink found (advertising PACS and +BASS UUIDs) and then search for and select the first broadcast audio source found +(advertising a broadcast ID). + +Filter these by modifying the following configs: + +``CONFIG_SELECT_SINK_NAME``: Substring of BT name of the sink. + +and + +``CONFIG_SELECT_SOURCE_NAME``: Substring of BT name or broadcast name of the source. + +Building for an nrf52840dk +-------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_broadcast_assistant/ + :board: nrf52840dk/nrf52840 + :goals: build diff --git a/samples/bluetooth/broadcast_audio_assistant/prj.conf b/samples/bluetooth/bap_broadcast_assistant/prj.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_assistant/prj.conf rename to samples/bluetooth/bap_broadcast_assistant/prj.conf diff --git a/samples/bluetooth/bap_broadcast_assistant/sample.yaml b/samples/bluetooth/bap_broadcast_assistant/sample.yaml new file mode 100644 index 0000000000000..771cf6c5cb5ce --- /dev/null +++ b/samples/bluetooth/bap_broadcast_assistant/sample.yaml @@ -0,0 +1,11 @@ +sample: + description: Bluetooth Low Energy Broadcast Assistant sample + name: Bluetooth Low Energy Broadcast Assistant sample +tests: + sample.bluetooth.bap_broadcast_assistant: + harness: bluetooth + platform_allow: + - nrf52840dk/nrf52840 + integration_platforms: + - nrf52840dk/nrf52840 + tags: bluetooth diff --git a/samples/bluetooth/bap_broadcast_assistant/src/main.c b/samples/bluetooth/bap_broadcast_assistant/src/main.c new file mode 100644 index 0000000000000..500a8d2c290b1 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_assistant/src/main.c @@ -0,0 +1,691 @@ +/* + * Copyright (c) 2024 Demant A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define NAME_LEN 30 +#define PA_SYNC_SKIP 5 +#define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 20 /* Set the timeout relative to interval */ +/* Broadcast IDs are 24bit, so this is out of valid range */ +#define INVALID_BROADCAST_ID 0xFFFFFFFFU + +static void scan_for_broadcast_sink(void); + +/* Struct to collect information from scanning + * for Broadcast Source or Sink + */ +struct scan_recv_info { + char bt_name[NAME_LEN]; + char broadcast_name[NAME_LEN]; + uint32_t broadcast_id; + bool has_bass; + bool has_pacs; +}; + +static struct bt_conn *broadcast_sink_conn; +static uint32_t selected_broadcast_id; +static uint8_t selected_sid; +static uint16_t selected_pa_interval; +static bt_addr_le_t selected_addr; +static struct bt_le_per_adv_sync *pa_sync; +static uint8_t received_base[UINT8_MAX]; +static size_t received_base_size; +static struct bt_bap_bass_subgroup + bass_subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]; + +static bool scanning_for_broadcast_source; + +static struct k_mutex base_store_mutex; +static K_SEM_DEFINE(sem_source_discovered, 0, 1); +static K_SEM_DEFINE(sem_sink_discovered, 0, 1); +static K_SEM_DEFINE(sem_sink_connected, 0, 1); +static K_SEM_DEFINE(sem_sink_disconnected, 0, 1); +static K_SEM_DEFINE(sem_security_updated, 0, 1); +static K_SEM_DEFINE(sem_bass_discovered, 0, 1); +static K_SEM_DEFINE(sem_pa_synced, 0, 1); +static K_SEM_DEFINE(sem_received_base_subgroups, 0, 1); + +static bool device_found(struct bt_data *data, void *user_data) +{ + struct scan_recv_info *sr_info = (struct scan_recv_info *)user_data; + struct bt_uuid_16 adv_uuid; + + switch (data->type) { + case BT_DATA_NAME_SHORTENED: + case BT_DATA_NAME_COMPLETE: + memcpy(sr_info->bt_name, data->data, MIN(data->data_len, NAME_LEN - 1)); + return true; + case BT_DATA_BROADCAST_NAME: + memcpy(sr_info->broadcast_name, data->data, MIN(data->data_len, NAME_LEN - 1)); + return true; + case BT_DATA_SVC_DATA16: + /* Check for Broadcast ID */ + if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) { + return true; + } + + if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + return true; + } + + if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO) != 0) { + return true; + } + + sr_info->broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); + return true; + case BT_DATA_UUID16_SOME: + case BT_DATA_UUID16_ALL: + /* NOTE: According to the BAP 1.0.1 Spec, + * Section 3.9.2. Additional Broadcast Audio Scan Service requirements, + * If the Scan Delegator implements a Broadcast Sink, it should also + * advertise a Service Data field containing the Broadcast Audio + * Scan Service (BASS) UUID. + * + * However, it seems that this is not the case with the sinks available + * while developing this sample application. Therefore, we instead, + * search for the existence of BASS and PACS in the list of service UUIDs, + * which does seem to exist in the sinks available. + */ + + /* Check for BASS and PACS */ + if (data->data_len % sizeof(uint16_t) != 0U) { + printk("UUID16 AD malformed\n"); + return true; + } + + for (size_t i = 0; i < data->data_len; i += sizeof(uint16_t)) { + const struct bt_uuid *uuid; + uint16_t u16; + + memcpy(&u16, &data->data[i], sizeof(u16)); + uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(u16)); + + if (bt_uuid_cmp(uuid, BT_UUID_BASS) == 0) { + sr_info->has_bass = true; + continue; + } + + if (bt_uuid_cmp(uuid, BT_UUID_PACS) == 0) { + sr_info->has_pacs = true; + continue; + } + } + return true; + default: + return true; + } +} + +static bool base_store(struct bt_data *data, void *user_data) +{ + const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); + int base_size; + int base_subgroup_count; + + /* Base is NULL if the data does not contain a valid BASE */ + if (base == NULL) { + return true; + } + + /* Can not fit all the received subgroups with the size CONFIG_BT_BAP_BASS_MAX_SUBGROUPS */ + base_subgroup_count = bt_bap_base_get_subgroup_count(base); + if (base_subgroup_count < 0 || base_subgroup_count > CONFIG_BT_BAP_BASS_MAX_SUBGROUPS) { + printk("Got invalid subgroup count: %d\n", base_subgroup_count); + return true; + } + + base_size = bt_bap_base_get_size(base); + if (base_size < 0) { + printk("BASE get size failed (%d)\n", base_size); + + return true; + } + + /* Compare BASE and copy if different */ + k_mutex_lock(&base_store_mutex, K_FOREVER); + if ((size_t)base_size != received_base_size || + memcmp(base, received_base, (size_t)base_size) != 0) { + (void)memcpy(received_base, base, base_size); + received_base_size = (size_t)base_size; + } + k_mutex_unlock(&base_store_mutex); + + /* Stop parsing */ + k_sem_give(&sem_received_base_subgroups); + return false; +} + +static void pa_recv(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_recv_info *info, + struct net_buf_simple *buf) +{ + bt_data_parse(buf, base_store, NULL); +} + +static bool add_pa_sync_base_subgroup_bis_cb(const struct bt_bap_base_subgroup_bis *bis, + void *user_data) +{ + struct bt_bap_bass_subgroup *subgroup_param = user_data; + + subgroup_param->bis_sync |= BIT(bis->index); + + return true; +} + +static bool add_pa_sync_base_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, + void *user_data) +{ + struct bt_bap_broadcast_assistant_add_src_param *param = user_data; + struct bt_bap_bass_subgroup *subgroup_param; + uint8_t *data; + int ret; + + ret = bt_bap_base_get_subgroup_codec_meta(subgroup, &data); + if (ret < 0) { + return false; + } + + subgroup_param = param->subgroups; + + if (ret > ARRAY_SIZE(subgroup_param->metadata)) { + printk("Cannot fit %d octets into subgroup param with size %zu", ret, + ARRAY_SIZE(subgroup_param->metadata)); + return false; + } + + ret = bt_bap_base_subgroup_foreach_bis(subgroup, add_pa_sync_base_subgroup_bis_cb, + subgroup_param); + if (ret < 0) { + return false; + } + + param->num_subgroups++; + + return true; +} + +static bool is_substring(const char *substr, const char *str) +{ + const size_t str_len = strlen(str); + const size_t sub_str_len = strlen(substr); + + if (sub_str_len > str_len) { + return false; + } + + for (size_t pos = 0; pos < str_len; pos++) { + if (pos + sub_str_len > str_len) { + return false; + } + + if (strncasecmp(substr, &str[pos], sub_str_len) == 0) { + return true; + } + } + + return false; +} + +static uint16_t interval_to_sync_timeout(uint16_t pa_interval) +{ + uint16_t pa_timeout; + + if (pa_interval == BT_BAP_PA_INTERVAL_UNKNOWN) { + /* Use maximum value to maximize chance of success */ + pa_timeout = BT_GAP_PER_ADV_MAX_TIMEOUT; + } else { + uint32_t interval_ms; + uint32_t timeout; + + /* Add retries and convert to unit in 10's of ms */ + interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(pa_interval); + timeout = (interval_ms * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO) / 10; + + /* Enforce restraints */ + pa_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT); + } + + return pa_timeout; +} + +static int pa_sync_create(void) +{ + struct bt_le_per_adv_sync_param create_params = {0}; + + bt_addr_le_copy(&create_params.addr, &selected_addr); + create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE; + create_params.sid = selected_sid; + create_params.skip = PA_SYNC_SKIP; + create_params.timeout = interval_to_sync_timeout(selected_pa_interval); + + return bt_le_per_adv_sync_create(&create_params, &pa_sync); +} + +static void scan_recv_cb(const struct bt_le_scan_recv_info *info, + struct net_buf_simple *ad) +{ + int err; + struct scan_recv_info sr_info = {0}; + + if (scanning_for_broadcast_source) { + /* Scan for and select Broadcast Source */ + + sr_info.broadcast_id = INVALID_BROADCAST_ID; + + /* We are only interested in non-connectable periodic advertisers */ + if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0 || + info->interval == 0) { + return; + } + + bt_data_parse(ad, device_found, (void *)&sr_info); + + if (sr_info.broadcast_id != INVALID_BROADCAST_ID) { + printk("Broadcast Source Found:\n"); + printk(" BT Name: %s\n", sr_info.bt_name); + printk(" Broadcast Name: %s\n", sr_info.broadcast_name); + printk(" Broadcast ID: 0x%06x\n\n", sr_info.broadcast_id); + +#if defined(CONFIG_SELECT_SOURCE_NAME) + if (strlen(CONFIG_SELECT_SOURCE_NAME) > 0U) { + /* Compare names with CONFIG_SELECT_SOURCE_NAME */ + if (is_substring(CONFIG_SELECT_SOURCE_NAME, sr_info.bt_name) || + is_substring(CONFIG_SELECT_SOURCE_NAME, + sr_info.broadcast_name)) { + printk("Match found for '%s'\n", CONFIG_SELECT_SOURCE_NAME); + } else { + printk("'%s' not found in names\n\n", + CONFIG_SELECT_SOURCE_NAME); + return; + } + } +#endif /* CONFIG_SELECT_SOURCE_NAME */ + + err = bt_le_scan_stop(); + if (err != 0) { + printk("bt_le_scan_stop failed with %d\n", err); + } + + /* TODO: Add support for syncing to the PA and parsing the BASE + * in order to obtain the right subgroup information to send to + * the sink when adding a broadcast source (see in main function below). + */ + + printk("Selecting Broadcast ID: 0x%06x\n", sr_info.broadcast_id); + + selected_broadcast_id = sr_info.broadcast_id; + selected_sid = info->sid; + selected_pa_interval = info->interval; + bt_addr_le_copy(&selected_addr, info->addr); + + k_sem_give(&sem_source_discovered); + + printk("Attempting to PA sync to the broadcaster with id 0x%06X\n", + selected_broadcast_id); + } + } else { + /* Scan for and connect to Broadcast Sink */ + + /* We are only interested in connectable advertisers */ + if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) == 0) { + return; + } + + bt_data_parse(ad, device_found, (void *)&sr_info); + + if (sr_info.has_bass && sr_info.has_pacs) { + printk("Broadcast Sink Found:\n"); + printk(" BT Name: %s\n", sr_info.bt_name); + + if (strlen(CONFIG_SELECT_SINK_NAME) > 0U) { + /* Compare names with CONFIG_SELECT_SINK_NAME */ + if (is_substring(CONFIG_SELECT_SINK_NAME, sr_info.bt_name)) { + printk("Match found for '%s'\n", CONFIG_SELECT_SINK_NAME); + } else { + printk("'%s' not found in names\n\n", + CONFIG_SELECT_SINK_NAME); + return; + } + } + + err = bt_le_scan_stop(); + if (err != 0) { + printk("bt_le_scan_stop failed with %d\n", err); + } + + printk("Connecting to Broadcast Sink: %s\n", sr_info.bt_name); + + err = bt_conn_le_create(info->addr, BT_CONN_LE_CREATE_CONN, + BT_LE_CONN_PARAM_DEFAULT, + &broadcast_sink_conn); + if (err != 0) { + printk("Failed creating connection (err=%u)\n", err); + scan_for_broadcast_sink(); + } + + k_sem_give(&sem_sink_discovered); + } + } +} + +static void scan_timeout_cb(void) +{ + printk("Scan timeout\n"); +} + +static struct bt_le_scan_cb scan_callbacks = { + .recv = scan_recv_cb, + .timeout = scan_timeout_cb, +}; + +static void scan_for_broadcast_source(void) +{ + int err; + + scanning_for_broadcast_source = true; + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err) { + printk("Scanning failed to start (err %d)\n", err); + return; + } + + printk("Scanning for Broadcast Source successfully started\n"); + + err = k_sem_take(&sem_source_discovered, K_FOREVER); + if (err != 0) { + printk("Failed to take sem_source_discovered (err %d)\n", err); + } +} + +static void scan_for_broadcast_sink(void) +{ + int err; + + scanning_for_broadcast_source = false; + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err) { + printk("Scanning failed to start (err %d)\n", err); + return; + } + + printk("Scanning for Broadcast Sink successfully started\n"); + + err = k_sem_take(&sem_sink_discovered, K_FOREVER); + if (err != 0) { + printk("Failed to take sem_sink_discovered (err %d)\n", err); + } +} + +static void connected(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (err != 0) { + printk("Failed to connect to %s (%u)\n", addr, err); + + bt_conn_unref(broadcast_sink_conn); + broadcast_sink_conn = NULL; + + scan_for_broadcast_sink(); + return; + } + + if (conn != broadcast_sink_conn) { + return; + } + + printk("Connected: %s\n", addr); + k_sem_give(&sem_sink_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != broadcast_sink_conn) { + return; + } + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); + + bt_conn_unref(broadcast_sink_conn); + broadcast_sink_conn = NULL; + + k_sem_give(&sem_sink_disconnected); +} + +static void security_changed_cb(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err) +{ + if (err == 0) { + printk("Security level changed: %u\n", level); + k_sem_give(&sem_security_updated); + } else { + printk("Failed to set security level: %u\n", err); + } +} + +static void bap_broadcast_assistant_discover_cb(struct bt_conn *conn, int err, + uint8_t recv_state_count) +{ + if (err == 0) { + printk("BASS discover done with %u recv states\n", + recv_state_count); + k_sem_give(&sem_bass_discovered); + } else { + printk("BASS discover failed (%d)\n", err); + } +} + +static void bap_broadcast_assistant_add_src_cb(struct bt_conn *conn, int err) +{ + if (err == 0) { + printk("BASS add source successful\n"); + } else { + printk("BASS add source failed (%d)\n", err); + } +} + +static void pa_sync_synced_cb(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info) +{ + if (sync == pa_sync) { + printk("PA sync %p synced for broadcast sink with broadcast ID 0x%06X\n", sync, + selected_broadcast_id); + + k_sem_give(&sem_pa_synced); + } +} + +static struct bt_bap_broadcast_assistant_cb ba_cbs = { + .discover = bap_broadcast_assistant_discover_cb, + .add_src = bap_broadcast_assistant_add_src_cb, +}; + +static struct bt_le_per_adv_sync_cb pa_synced_cb = { + .synced = pa_sync_synced_cb, + .recv = pa_recv, +}; + +static void reset(void) +{ + printk("\n\nReset...\n\n"); + + broadcast_sink_conn = NULL; + selected_broadcast_id = INVALID_BROADCAST_ID; + selected_sid = 0; + selected_pa_interval = 0; + (void)memset(&selected_addr, 0, sizeof(selected_addr)); + + k_sem_reset(&sem_source_discovered); + k_sem_reset(&sem_sink_discovered); + k_sem_reset(&sem_sink_connected); + k_sem_reset(&sem_sink_disconnected); + k_sem_reset(&sem_security_updated); + k_sem_reset(&sem_bass_discovered); + k_sem_reset(&sem_pa_synced); + k_sem_reset(&sem_received_base_subgroups); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .security_changed = security_changed_cb +}; + +int main(void) +{ + int err; + struct bt_bap_broadcast_assistant_add_src_param param = { 0 }; + + err = bt_enable(NULL); + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + return 0; + } + + printk("Bluetooth initialized\n"); + + bt_bap_broadcast_assistant_register_cb(&ba_cbs); + bt_le_per_adv_sync_cb_register(&pa_synced_cb); + bt_le_scan_cb_register(&scan_callbacks); + + k_mutex_init(&base_store_mutex); + + while (true) { + scan_for_broadcast_sink(); + + err = k_sem_take(&sem_sink_connected, K_FOREVER); + if (err != 0) { + printk("Failed to take sem_sink_connected (err %d)\n", err); + } + + err = bt_bap_broadcast_assistant_discover(broadcast_sink_conn); + if (err != 0) { + printk("Failed to discover BASS on the sink (err %d)\n", err); + } + + err = k_sem_take(&sem_security_updated, K_SECONDS(10)); + if (err != 0) { + printk("Failed to take sem_security_updated (err %d), resetting\n", err); + bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_AUTH_FAIL); + + if (k_sem_take(&sem_sink_disconnected, K_SECONDS(10)) != 0) { + /* This should not happen */ + return -ETIMEDOUT; + } + + reset(); + continue; + } + + err = k_sem_take(&sem_bass_discovered, K_SECONDS(10)); + if (err != 0) { + if (err == -EAGAIN) { + printk("Failed to take sem_bass_discovered (err %d)\n", err); + } + bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE); + + if (k_sem_take(&sem_sink_disconnected, K_SECONDS(10)) != 0) { + /* This should not happen */ + return -ETIMEDOUT; + } + + reset(); + continue; + } + + /* TODO: Discover and parse the PACS on the sink and use the information + * when discovering and adding a source to the sink. + * Also, before populating the parameters to sync to the broadcast source + * first, parse the source BASE and determine if the sink supports the source. + * If not, then look for another source. + */ + + scan_for_broadcast_source(); + + printk("Scan stopped, attempting to PA sync to the broadcaster with id 0x%06X\n", + selected_broadcast_id); + err = pa_sync_create(); + if (err != 0) { + printk("Could not create Broadcast PA sync: %d, resetting\n", err); + return -ETIMEDOUT; + } + + printk("Waiting for PA synced\n"); + err = k_sem_take(&sem_pa_synced, K_FOREVER); + if (err != 0) { + printk("sem_pa_synced timed out, resetting\n"); + return err; + } + + memset(bass_subgroups, 0, sizeof(bass_subgroups)); + bt_addr_le_copy(¶m.addr, &selected_addr); + param.adv_sid = selected_sid; + param.pa_interval = selected_pa_interval; + param.broadcast_id = selected_broadcast_id; + param.pa_sync = true; + param.subgroups = bass_subgroups; + + /* Wait to receive subgroups */ + err = k_sem_take(&sem_received_base_subgroups, K_FOREVER); + if (err != 0) { + printk("Failed to take sem_received_base_subgroups (err %d)\n", err); + return err; + } + + k_mutex_lock(&base_store_mutex, K_FOREVER); + err = bt_bap_base_foreach_subgroup((const struct bt_bap_base *)received_base, + add_pa_sync_base_subgroup_cb, ¶m); + k_mutex_unlock(&base_store_mutex); + + if (err < 0) { + printk("Could not add BASE to params %d\n", err); + continue; + } + + err = bt_bap_broadcast_assistant_add_src(broadcast_sink_conn, ¶m); + if (err) { + printk("Failed to add source: %d\n", err); + bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE); + + if (k_sem_take(&sem_sink_disconnected, K_SECONDS(10)) != 0) { + /* This should not happen */ + return -ETIMEDOUT; + } + + reset(); + continue; + } + + /* Reset if the sink disconnects */ + err = k_sem_take(&sem_sink_disconnected, K_FOREVER); + if (err != 0) { + printk("Failed to take sem_sink_disconnected (err %d)\n", err); + } + + reset(); + } + + return 0; +} diff --git a/samples/bluetooth/bap_broadcast_sink/CMakeLists.txt b/samples/bluetooth/bap_broadcast_sink/CMakeLists.txt new file mode 100644 index 0000000000000..66649d87a33c8 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_sink/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bap_unicast_server) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/broadcast_audio_sink/Kconfig b/samples/bluetooth/bap_broadcast_sink/Kconfig similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/Kconfig rename to samples/bluetooth/bap_broadcast_sink/Kconfig diff --git a/samples/bluetooth/broadcast_audio_sink/Kconfig.sysbuild b/samples/bluetooth/bap_broadcast_sink/Kconfig.sysbuild similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/Kconfig.sysbuild rename to samples/bluetooth/bap_broadcast_sink/Kconfig.sysbuild diff --git a/samples/bluetooth/bap_broadcast_sink/README.rst b/samples/bluetooth/bap_broadcast_sink/README.rst new file mode 100644 index 0000000000000..39ca9a483e7b3 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_sink/README.rst @@ -0,0 +1,80 @@ +.. zephyr:code-sample:: bluetooth_bap_broadcast_sink + :name: Bluetooth: Broadcast Audio Sink + :relevant-api: bluetooth + + Bluetooth: Broadcast Audio Sink + +Overview +******** + +Application demonstrating the LE Audio broadcast sink functionality. +Starts by scanning for LE Audio broadcast sources and then synchronizes to +the first found and listens to it until the source is (potentially) stopped. + +This sample can be found under +:zephyr_file:`samples/bluetooth/bap_broadcast_sink` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Use `CONFIG_TARGET_BROADCAST_NAME` Kconfig to specify the name (CONFIG_BT_DEVICE_NAME) +of a broadcast source to listen to. With default value (empty string), sink +device will listen to all available broadcast sources. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_broadcast_sink/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_broadcast_sink/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_broadcast_sink/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_broadcast_sink/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/broadcast_audio_sink/boards/nrf52833dk_nrf52833.conf b/samples/bluetooth/bap_broadcast_sink/boards/nrf52833dk_nrf52833.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/boards/nrf52833dk_nrf52833.conf rename to samples/bluetooth/bap_broadcast_sink/boards/nrf52833dk_nrf52833.conf diff --git a/samples/bluetooth/broadcast_audio_sink/boards/nrf52833dk_nrf52833.overlay b/samples/bluetooth/bap_broadcast_sink/boards/nrf52833dk_nrf52833.overlay similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/boards/nrf52833dk_nrf52833.overlay rename to samples/bluetooth/bap_broadcast_sink/boards/nrf52833dk_nrf52833.overlay diff --git a/samples/bluetooth/broadcast_audio_sink/boards/nrf52840dongle_nrf52840.conf b/samples/bluetooth/bap_broadcast_sink/boards/nrf52840dongle_nrf52840.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/boards/nrf52840dongle_nrf52840.conf rename to samples/bluetooth/bap_broadcast_sink/boards/nrf52840dongle_nrf52840.conf diff --git a/samples/bluetooth/broadcast_audio_sink/boards/nrf52840dongle_nrf52840.overlay b/samples/bluetooth/bap_broadcast_sink/boards/nrf52840dongle_nrf52840.overlay similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/boards/nrf52840dongle_nrf52840.overlay rename to samples/bluetooth/bap_broadcast_sink/boards/nrf52840dongle_nrf52840.overlay diff --git a/samples/bluetooth/broadcast_audio_sink/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/bap_broadcast_sink/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf rename to samples/bluetooth/bap_broadcast_sink/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf diff --git a/samples/bluetooth/bap_broadcast_sink/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/bap_broadcast_sink/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..69b3cc51473c7 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_sink/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,3 @@ +# Use USB Audio as audio sink +CONFIG_USE_USB_AUDIO_OUTPUT=y +CONFIG_USB_DEVICE_PRODUCT="USB Broadcast Sink" diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf52833dk_nrf52833.overlay b/samples/bluetooth/bap_broadcast_sink/boards/nrf5340dk_nrf5340_cpuapp.overlay similarity index 100% rename from samples/bluetooth/broadcast_audio_source/boards/nrf52833dk_nrf52833.overlay rename to samples/bluetooth/bap_broadcast_sink/boards/nrf5340dk_nrf5340_cpuapp.overlay diff --git a/samples/bluetooth/broadcast_audio_sink/overlay-bt_ll_sw_split.conf b/samples/bluetooth/bap_broadcast_sink/overlay-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/overlay-bt_ll_sw_split.conf rename to samples/bluetooth/bap_broadcast_sink/overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/broadcast_audio_sink/prj.conf b/samples/bluetooth/bap_broadcast_sink/prj.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/prj.conf rename to samples/bluetooth/bap_broadcast_sink/prj.conf diff --git a/samples/bluetooth/bap_broadcast_sink/sample.yaml b/samples/bluetooth/bap_broadcast_sink/sample.yaml new file mode 100644 index 0000000000000..b6360768f0ab5 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_sink/sample.yaml @@ -0,0 +1,28 @@ +sample: + description: Bluetooth Low Energy Audio Broadcast Sink sample + name: Bluetooth Low Energy Audio Broadcast Sink sample +tests: + sample.bluetooth.bap_broadcast_sink: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + - nrf5340bsim/nrf5340/cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.bap_broadcast_sink.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dongle/nrf52840 + integration_platforms: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dongle/nrf52840 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/bap_broadcast_sink/src/main.c b/samples/bluetooth/bap_broadcast_sink/src/main.c new file mode 100644 index 0000000000000..4a2b6ca95696b --- /dev/null +++ b/samples/bluetooth/bap_broadcast_sink/src/main.c @@ -0,0 +1,1661 @@ +/* + * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * Copyright (c) 2024 Demant A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include +#if defined(CONFIG_LIBLC3) +#include "lc3.h" +#endif /* defined(CONFIG_LIBLC3) */ +#if defined(CONFIG_USB_DEVICE_AUDIO) +#include +#include +#include +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ + + +BUILD_ASSERT(IS_ENABLED(CONFIG_SCAN_SELF) || IS_ENABLED(CONFIG_SCAN_OFFLOAD), + "Either SCAN_SELF or SCAN_OFFLOAD must be enabled"); + +#define SEM_TIMEOUT K_SECONDS(60) +#define BROADCAST_ASSISTANT_TIMEOUT K_SECONDS(120) /* 2 minutes */ + +#define LOG_INTERVAL 1000U + +#if defined(CONFIG_SCAN_SELF) +#define ADV_TIMEOUT K_SECONDS(CONFIG_SCAN_DELAY) +#else /* !CONFIG_SCAN_SELF */ +#define ADV_TIMEOUT K_FOREVER +#endif /* CONFIG_SCAN_SELF */ + +#define INVALID_BROADCAST_ID (BT_AUDIO_BROADCAST_ID_MAX + 1) +#define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 5 /* Set the timeout relative to interval */ +#define PA_SYNC_SKIP 5 +#define NAME_LEN sizeof(CONFIG_TARGET_BROADCAST_NAME) + 1 +#define BROADCAST_DATA_ELEMENT_SIZE sizeof(int16_t) + +#if defined(CONFIG_LIBLC3) +#define LC3_MAX_SAMPLE_RATE 48000U +#define LC3_MAX_FRAME_DURATION_US 10000U +#define LC3_MAX_NUM_SAMPLES_MONO ((LC3_MAX_FRAME_DURATION_US * LC3_MAX_SAMPLE_RATE) \ + / USEC_PER_SEC) +#define LC3_MAX_NUM_SAMPLES_STEREO (LC3_MAX_NUM_SAMPLES_MONO * 2) + +#define LC3_ENCODER_STACK_SIZE 4096 +#define LC3_ENCODER_PRIORITY 5 +#endif /* defined(CONFIG_LIBLC3) */ + +#if defined(CONFIG_USB_DEVICE_AUDIO) +#define USB_ENQUEUE_COUNT 10U +#define USB_SAMPLE_RATE 48000U +#define USB_FRAME_DURATION_US 1000U +#define USB_MONO_SAMPLE_SIZE \ + ((USB_FRAME_DURATION_US * USB_SAMPLE_RATE * BROADCAST_DATA_ELEMENT_SIZE) / USEC_PER_SEC) +#define USB_STEREO_SAMPLE_SIZE (USB_MONO_SAMPLE_SIZE * 2) +#define USB_RING_BUF_SIZE (5 * LC3_MAX_NUM_SAMPLES_STEREO) /* 5 SDUs*/ +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ + +static K_SEM_DEFINE(sem_broadcast_sink_stopped, 0U, 1U); +static K_SEM_DEFINE(sem_connected, 0U, 1U); +static K_SEM_DEFINE(sem_disconnected, 0U, 1U); +static K_SEM_DEFINE(sem_broadcaster_found, 0U, 1U); +static K_SEM_DEFINE(sem_pa_synced, 0U, 1U); +static K_SEM_DEFINE(sem_base_received, 0U, 1U); +static K_SEM_DEFINE(sem_syncable, 0U, 1U); +static K_SEM_DEFINE(sem_pa_sync_lost, 0U, 1U); +static K_SEM_DEFINE(sem_broadcast_code_received, 0U, 1U); +static K_SEM_DEFINE(sem_pa_request, 0U, 1U); +static K_SEM_DEFINE(sem_past_request, 0U, 1U); +static K_SEM_DEFINE(sem_bis_sync_requested, 0U, 1U); +static K_SEM_DEFINE(sem_stream_connected, 0U, CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT); +static K_SEM_DEFINE(sem_stream_started, 0U, CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT); +static K_SEM_DEFINE(sem_big_synced, 0U, 1U); + +/* Sample assumes that we only have a single Scan Delegator receive state */ +static const struct bt_bap_scan_delegator_recv_state *req_recv_state; +static struct bt_bap_broadcast_sink *broadcast_sink; +static struct bt_le_scan_recv_info broadcaster_info; +static bt_addr_le_t broadcaster_addr; +static struct bt_le_per_adv_sync *pa_sync; +static uint32_t broadcaster_broadcast_id; +static struct broadcast_sink_stream { + struct bt_bap_stream stream; + size_t recv_cnt; + size_t loss_cnt; + size_t error_cnt; + size_t valid_cnt; +#if defined(CONFIG_LIBLC3) + struct net_buf *in_buf; + struct k_work_delayable lc3_decode_work; + + /* LC3 config values */ + enum bt_audio_location chan_allocation; + uint16_t lc3_octets_per_frame; + uint8_t lc3_frames_blocks_per_sdu; + + /* Internal lock for protecting net_buf from multiple access */ + struct k_mutex lc3_decoder_mutex; + lc3_decoder_t lc3_decoder; + lc3_decoder_mem_48k_t lc3_decoder_mem; +#endif /* defined(CONFIG_LIBLC3) */ +} streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; + +static struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)]; +static volatile bool big_synced; +static volatile bool base_received; +static struct bt_conn *broadcast_assistant_conn; +static struct bt_le_ext_adv *ext_adv; +static volatile uint8_t stream_count; + +static const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_CAP_FREQ_16KHZ | BT_AUDIO_CODEC_CAP_FREQ_24KHZ, + BT_AUDIO_CODEC_CAP_DURATION_10, BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1), 40u, 60u, + CONFIG_MAX_CODEC_FRAMES_PER_SDU, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + +/* Create a mask for the maximum BIS we can sync to using the number of streams + * we have. We add an additional 1 since the bis indexes start from 1 and not + * 0. + */ +static const uint32_t bis_index_mask = BIT_MASK(ARRAY_SIZE(streams) + 1U); +static uint32_t requested_bis_sync; +static uint32_t bis_index_bitfield; +static uint8_t sink_broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]; + +uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */ + +static int stop_adv(void); + +#if defined(CONFIG_USB_DEVICE_AUDIO) +RING_BUF_DECLARE(usb_ring_buf, USB_RING_BUF_SIZE); +NET_BUF_POOL_DEFINE(usb_tx_buf_pool, USB_ENQUEUE_COUNT, USB_STEREO_SAMPLE_SIZE, 0, net_buf_destroy); + +static void add_to_usb_ring_buf(const int16_t audio_buf[LC3_MAX_NUM_SAMPLES_STEREO]); +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ + +#if defined(CONFIG_LIBLC3) +static K_SEM_DEFINE(lc3_decoder_sem, 0, 1); + +static void do_lc3_decode(lc3_decoder_t decoder, const void *in_data, uint8_t octets_per_frame, + int16_t out_data[LC3_MAX_NUM_SAMPLES_MONO]); +static void lc3_decoder_thread(void *arg1, void *arg2, void *arg3); +K_THREAD_DEFINE(decoder_tid, LC3_ENCODER_STACK_SIZE, lc3_decoder_thread, + NULL, NULL, NULL, LC3_ENCODER_PRIORITY, 0, -1); + +/* Consumer thread of the decoded stream data */ +static void lc3_decoder_thread(void *arg1, void *arg2, void *arg3) +{ + while (true) { +#if defined(CONFIG_USB_DEVICE_AUDIO) + static int16_t right_frames[CONFIG_MAX_CODEC_FRAMES_PER_SDU] + [LC3_MAX_NUM_SAMPLES_MONO]; + static int16_t left_frames[CONFIG_MAX_CODEC_FRAMES_PER_SDU] + [LC3_MAX_NUM_SAMPLES_MONO]; + size_t right_frames_cnt = 0; + size_t left_frames_cnt = 0; + + memset(right_frames, 0, sizeof(right_frames)); + memset(left_frames, 0, sizeof(left_frames)); +#else + static int16_t lc3_audio_buf[LC3_MAX_NUM_SAMPLES_MONO]; +#endif /* CONFIG_USB_DEVICE_AUDIO */ + + k_sem_take(&lc3_decoder_sem, K_FOREVER); + + for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { + struct broadcast_sink_stream *stream = &streams[i]; + const uint8_t frames_blocks_per_sdu = stream->lc3_frames_blocks_per_sdu; + const uint16_t octets_per_frame = stream->lc3_octets_per_frame; + uint16_t frames_per_block; + struct net_buf *buf; + + k_mutex_lock(&stream->lc3_decoder_mutex, K_FOREVER); + + if (stream->in_buf == NULL) { + k_mutex_unlock(&stream->lc3_decoder_mutex); + + continue; + } + + buf = net_buf_ref(stream->in_buf); + net_buf_unref(stream->in_buf); + stream->in_buf = NULL; + k_mutex_unlock(&stream->lc3_decoder_mutex); + + frames_per_block = bt_audio_get_chan_count(stream->chan_allocation); + if (buf->len != + (frames_per_block * octets_per_frame * frames_blocks_per_sdu)) { + printk("Expected %u frame blocks with %u frames of size %u, but " + "length is %u\n", + frames_blocks_per_sdu, frames_per_block, octets_per_frame, + buf->len); + + net_buf_unref(buf); + + continue; + } + +#if defined(CONFIG_USB_DEVICE_AUDIO) + const bool has_left = + (stream->chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0; + const bool has_right = + (stream->chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0; + const bool is_mono = + stream->chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO; + + /* Split the SDU into frames*/ + for (uint8_t i = 0U; i < frames_blocks_per_sdu; i++) { + for (uint16_t j = 0U; j < frames_per_block; j++) { + const bool is_left = j == 0 && has_left; + const bool is_right = + has_right && (j == 0 || (j == 1 && has_left)); + const void *data = net_buf_pull_mem(buf, octets_per_frame); + int16_t *out_frame; + + if (is_left) { + out_frame = left_frames[left_frames_cnt++]; + } else if (is_right) { + out_frame = right_frames[right_frames_cnt++]; + } else if (is_mono) { + /* Use left as mono*/ + out_frame = left_frames[left_frames_cnt++]; + } else { + /* unused channel */ + break; + } + + do_lc3_decode(stream->lc3_decoder, data, octets_per_frame, + out_frame); + } + } +#else + /* Dummy behavior: Decode and discard data */ + for (uint8_t i = 0U; i < frames_blocks_per_sdu; i++) { + for (uint16_t j = 0U; j < frames_per_block; j++) { + const void *data = net_buf_pull_mem(buf, octets_per_frame); + + do_lc3_decode(stream->lc3_decoder, data, octets_per_frame, + lc3_audio_buf); + } + } +#endif /* CONFIG_USB_DEVICE_AUDIO */ + + net_buf_unref(buf); + } + +#if defined(CONFIG_USB_DEVICE_AUDIO) + const bool is_left_only = right_frames_cnt == 0U; + const bool is_right_only = left_frames_cnt == 0U; + + if (!is_left_only && !is_right_only && left_frames_cnt != right_frames_cnt) { + printk("Mismatch between number of left (%zu) and right (%zu) frames, " + "discard SDU", + left_frames_cnt, right_frames_cnt); + continue; + } + + /* Send frames to USB - If we only have a single channel we mix it to stereo */ + for (size_t i = 0U; i < MAX(left_frames_cnt, right_frames_cnt); i++) { + const bool is_single_channel = is_left_only || is_right_only; + static int16_t stereo_frame[LC3_MAX_NUM_SAMPLES_STEREO]; + int16_t *right_frame = right_frames[i]; + int16_t *left_frame = left_frames[i]; + + /* Not enough space to store data */ + if (ring_buf_space_get(&usb_ring_buf) < sizeof(stereo_frame)) { + break; + } + + memset(stereo_frame, 0, sizeof(stereo_frame)); + + /* Generate the stereo frame + * + * If we only have single channel then that is always stored in the + * left_frame, and we mix that to stereo + */ + for (int j = 0; j < LC3_MAX_NUM_SAMPLES_MONO; j++) { + if (is_single_channel) { + /* Mix to stereo */ + if (is_left_only) { + stereo_frame[j * 2] = left_frame[j]; + stereo_frame[j * 2 + 1] = left_frame[j]; + } else if (is_right_only) { + stereo_frame[j * 2] = right_frame[j]; + stereo_frame[j * 2 + 1] = right_frame[j]; + } + } else { + stereo_frame[j * 2] = left_frame[j]; + stereo_frame[j * 2 + 1] = right_frame[j]; + } + } + + add_to_usb_ring_buf(stereo_frame); + } +#endif /* CONFIG_USB_DEVICE_AUDIO */ + } +} + +/** Decode LC3 data on a stream and returns true if successful */ +static void do_lc3_decode(lc3_decoder_t decoder, const void *in_data, uint8_t octets_per_frame, + int16_t out_data[LC3_MAX_NUM_SAMPLES_MONO]) +{ + int err; + + err = lc3_decode(decoder, in_data, octets_per_frame, LC3_PCM_FORMAT_S16, out_data, 1); + if (err == 1) { + printk(" decoder performed PLC\n"); + } else if (err < 0) { + printk(" decoder failed - wrong parameters? (err = %d)\n", err); + } +} + +static int lc3_enable(struct broadcast_sink_stream *sink_stream) +{ + size_t chan_alloc_bit_cnt; + size_t sdu_size_required; + int frame_duration_us; + int freq_hz; + int ret; + + printk("Enable: stream with codec %p\n", sink_stream->stream.codec_cfg); + + ret = bt_audio_codec_cfg_get_freq(sink_stream->stream.codec_cfg); + if (ret > 0) { + freq_hz = bt_audio_codec_cfg_freq_to_freq_hz(ret); + } else { + printk("Error: Codec frequency not set, cannot start codec."); + return -1; + } + + ret = bt_audio_codec_cfg_get_frame_dur(sink_stream->stream.codec_cfg); + if (ret > 0) { + frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + } else { + printk("Error: Frame duration not set, cannot start codec."); + return ret; + } + + ret = bt_audio_codec_cfg_get_chan_allocation(sink_stream->stream.codec_cfg, + &sink_stream->chan_allocation, true); + if (ret != 0) { + printk("Error: Channel allocation not set, invalid configuration for LC3"); + return ret; + } + + ret = bt_audio_codec_cfg_get_octets_per_frame(sink_stream->stream.codec_cfg); + if (ret > 0) { + sink_stream->lc3_octets_per_frame = (uint16_t)ret; + } else { + printk("Error: Octets per frame not set, invalid configuration for LC3"); + return ret; + } + + ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(sink_stream->stream.codec_cfg, true); + if (ret > 0) { + sink_stream->lc3_frames_blocks_per_sdu = (uint8_t)ret; + } else { + printk("Error: Frame blocks per SDU not set, invalid configuration for LC3"); + return ret; + } + + /* An SDU can consist of X frame blocks, each with Y frames (one per channel) of size Z in + * them. The minimum SDU size required for this is X * Y * Z. + */ + chan_alloc_bit_cnt = bt_audio_get_chan_count(sink_stream->chan_allocation); + sdu_size_required = chan_alloc_bit_cnt * sink_stream->lc3_octets_per_frame * + sink_stream->lc3_frames_blocks_per_sdu; + if (sdu_size_required < sink_stream->stream.qos->sdu) { + printk("With %zu channels and %u octets per frame and %u frames per block, SDUs " + "shall be at minimum %zu, but the stream has been configured for %u", + chan_alloc_bit_cnt, sink_stream->lc3_octets_per_frame, + sink_stream->lc3_frames_blocks_per_sdu, sdu_size_required, + sink_stream->stream.qos->sdu); + + return -EINVAL; + } + + printk("Enabling LC3 decoder with frame duration %uus, frequency %uHz and with channel " + "allocation 0x%08X, %u octets per frame and %u frame blocks per SDU\n", + frame_duration_us, freq_hz, sink_stream->chan_allocation, + sink_stream->lc3_octets_per_frame, sink_stream->lc3_frames_blocks_per_sdu); + +#if defined(CONFIG_USB_DEVICE_AUDIO) + sink_stream->lc3_decoder = lc3_setup_decoder(frame_duration_us, freq_hz, USB_SAMPLE_RATE, + &sink_stream->lc3_decoder_mem); +#else + sink_stream->lc3_decoder = lc3_setup_decoder(frame_duration_us, freq_hz, 0, + &sink_stream->lc3_decoder_mem); +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ + + if (sink_stream->lc3_decoder == NULL) { + printk("ERROR: Failed to setup LC3 decoder - wrong parameters?\n"); + return -1; + } + + k_thread_start(decoder_tid); + + return 0; +} +#endif /* defined(CONFIG_LIBLC3) */ + +#if defined(CONFIG_USB_DEVICE_AUDIO) +/* Move the LC3 data to the USB ring buffer */ +static void add_to_usb_ring_buf(const int16_t audio_buf[LC3_MAX_NUM_SAMPLES_STEREO]) +{ + uint32_t size; + + size = ring_buf_put(&usb_ring_buf, (uint8_t *)audio_buf, + LC3_MAX_NUM_SAMPLES_STEREO * sizeof(int16_t)); + if (size != LC3_MAX_NUM_SAMPLES_STEREO) { + static int rb_put_failures; + + rb_put_failures++; + if (rb_put_failures == LOG_INTERVAL) { + printk("%s: Failure to add to usb_ring_buf %d, %u\n", __func__, + rb_put_failures, size); + } + } +} + +/* USB consumer callback, called every 1ms, consumes data from ring-buffer */ +static void usb_data_request_cb(const struct device *dev) +{ + uint8_t usb_audio_data[USB_STEREO_SAMPLE_SIZE] = {0}; + static struct net_buf *pcm_buf; + static size_t cnt; + uint32_t size; + int err; + + size = ring_buf_get(&usb_ring_buf, (uint8_t *)usb_audio_data, sizeof(usb_audio_data)); + if (size == 0) { + /* size is 0, noop */ + return; + } + /* Size lower than USB_STEREO_SAMPLE_SIZE is OK as usb_audio_data is 0-initialized */ + + pcm_buf = net_buf_alloc(&usb_tx_buf_pool, K_NO_WAIT); + if (pcm_buf == NULL) { + printk("Could not allocate pcm_buf\n"); + return; + } + + net_buf_add_mem(pcm_buf, usb_audio_data, sizeof(usb_audio_data)); + + if (cnt % LOG_INTERVAL == 0) { + printk("Sending USB audio (count = %zu)\n", cnt); + } + + err = usb_audio_send(dev, pcm_buf, USB_STEREO_SAMPLE_SIZE); + if (err) { + printk("Failed to send USB audio: %d\n", err); + net_buf_unref(pcm_buf); + } + + cnt++; +} + +static void usb_data_written_cb(const struct device *dev, struct net_buf *buf, size_t size) +{ + /* Unreference the buffer now that the USB is done with it */ + net_buf_unref(buf); +} +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ + +static void stream_connected_cb(struct bt_bap_stream *stream) +{ + printk("Stream %p connected\n", stream); + + k_sem_give(&sem_stream_connected); +} + +static void stream_disconnected_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + int err; + + printk("Stream %p disconnected with reason 0x%02X\n", stream, reason); + + err = k_sem_take(&sem_stream_connected, K_NO_WAIT); + if (err != 0) { + printk("Failed to take sem_stream_connected: %d\n", err); + } +} + +static void stream_started_cb(struct bt_bap_stream *stream) +{ + struct broadcast_sink_stream *sink_stream = + CONTAINER_OF(stream, struct broadcast_sink_stream, stream); + + printk("Stream %p started\n", stream); + + total_rx_iso_packet_count = 0U; + sink_stream->recv_cnt = 0U; + sink_stream->loss_cnt = 0U; + sink_stream->valid_cnt = 0U; + sink_stream->error_cnt = 0U; + +#if defined(CONFIG_LIBLC3) + int err; + + if (stream->codec_cfg != 0 && stream->codec_cfg->id != BT_HCI_CODING_FORMAT_LC3) { + /* No subgroups with LC3 was found */ + printk("Did not parse an LC3 codec\n"); + return; + } + + err = lc3_enable(sink_stream); + if (err < 0) { + printk("Error: cannot enable LC3 codec: %d", err); + return; + } +#endif /* CONFIG_LIBLC3 */ + + k_sem_give(&sem_stream_started); + if (k_sem_count_get(&sem_stream_started) == stream_count) { + big_synced = true; + k_sem_give(&sem_big_synced); + } +} + +static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + int err; + + printk("Stream %p stopped with reason 0x%02X\n", stream, reason); + + err = k_sem_take(&sem_stream_started, K_NO_WAIT); + if (err != 0) { + printk("Failed to take sem_stream_started: %d\n", err); + } + + if (k_sem_count_get(&sem_stream_started) != stream_count) { + big_synced = false; + } +} + +static void stream_recv_cb(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + struct broadcast_sink_stream *sink_stream = + CONTAINER_OF(stream, struct broadcast_sink_stream, stream); + + if (info->flags & BT_ISO_FLAGS_ERROR) { + sink_stream->error_cnt++; + } + + if (info->flags & BT_ISO_FLAGS_LOST) { + sink_stream->loss_cnt++; + } + + if (info->flags & BT_ISO_FLAGS_VALID) { + sink_stream->valid_cnt++; +#if defined(CONFIG_LIBLC3) + k_mutex_lock(&sink_stream->lc3_decoder_mutex, K_FOREVER); + if (sink_stream->in_buf != NULL) { + net_buf_unref(sink_stream->in_buf); + sink_stream->in_buf = NULL; + } + + sink_stream->in_buf = net_buf_ref(buf); + k_mutex_unlock(&sink_stream->lc3_decoder_mutex); + k_sem_give(&lc3_decoder_sem); +#endif /* defined(CONFIG_LIBLC3) */ + } + + total_rx_iso_packet_count++; + sink_stream->recv_cnt++; + if ((sink_stream->recv_cnt % LOG_INTERVAL) == 0U) { + printk("Stream %p: received %u total ISO packets: Valid %u | Error %u | Loss %u\n", + &sink_stream->stream, sink_stream->recv_cnt, sink_stream->valid_cnt, + sink_stream->error_cnt, sink_stream->loss_cnt); + } +} + +static struct bt_bap_stream_ops stream_ops = { + .connected = stream_connected_cb, + .disconnected = stream_disconnected_cb, + .started = stream_started_cb, + .stopped = stream_stopped_cb, + .recv = stream_recv_cb, +}; + +#if defined(CONFIG_TARGET_BROADCAST_CHANNEL) +struct find_valid_bis_data { + struct { + uint8_t index; + enum bt_audio_location chan_allocation; + } bis[BT_ISO_BIS_INDEX_MAX]; + + uint8_t cnt; +}; + +/** + * This is called for each BIS in a subgroup + * + * It returns `false` if the current BIS contains all of the channels we are looking for, + * or if it does not contain any and we are looking for BT_AUDIO_LOCATION_MONO_AUDIO. This stops + * the iteration of the remaining BIS in the subgroup. + * + * It returns `true` if the BIS either contains none or some of the channels we are looking for. + * If it contains some, then that is being stored in the user_data, so that the calling function + * can check if a combination of the BIS satisfy the channel allocations we want. + */ +static bool find_valid_bis_cb(const struct bt_bap_base_subgroup_bis *bis, + void *user_data) +{ + struct find_valid_bis_data *data = user_data; + struct bt_audio_codec_cfg codec_cfg = {0}; + enum bt_audio_location chan_allocation; + int err; + + err = bt_bap_base_subgroup_bis_codec_to_codec_cfg(bis, &codec_cfg); + if (err != 0) { + printk("Could not get codec configuration for BIS: %d\n", err); + return true; + } + + err = bt_audio_codec_cfg_get_chan_allocation(&codec_cfg, &chan_allocation, true); + if (err != 0) { + printk("Could not find channel allocation for BIS: %d\n", err); + + if (err == -ENODATA && strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { + /* Accept no channel allocation data available + * if TARGET_BROADCAST_NAME defined. Use current index. + */ + data->bis[0].index = bis->index; + data->bis[0].chan_allocation = chan_allocation; + data->cnt = 1; + + return false; + } + } else { + if ((chan_allocation & CONFIG_TARGET_BROADCAST_CHANNEL) == + CONFIG_TARGET_BROADCAST_CHANNEL) { + /* Found single BIS with all channels we want - keep as only and stop + * parsing + */ + data->bis[0].index = bis->index; + data->bis[0].chan_allocation = chan_allocation; + data->cnt = 1; + + return false; + } else if ((chan_allocation & CONFIG_TARGET_BROADCAST_CHANNEL) != 0) { + /* BIS contains part of what we are looking for - Store and see if there are + * other BIS that may fill the gaps + */ + data->bis[data->cnt].index = bis->index; + data->bis[data->cnt].chan_allocation = chan_allocation; + data->cnt++; + } + } + + return true; +} + +/** + * This function searches all the BIS in a subgroup for a set of BIS indexes that satisfy + * CONFIG_TARGET_BROADCAST_CHANNEL + * + * Returns `true` if the right channels were found, otherwise `false`. + */ +static bool find_valid_bis_in_subgroup_bis(const struct bt_bap_base_subgroup *subgroup, + uint32_t *bis_indexes) +{ + struct find_valid_bis_data data = {0}; + int err; + + err = bt_bap_base_subgroup_foreach_bis(subgroup, find_valid_bis_cb, &data); + if (err == -ECANCELED) { + /* We found what we are looking for in a single BIS */ + + *bis_indexes = BIT(data.bis[0].index); + + return true; + } else if (err == 0) { + /* We are finished parsing all BIS - Try to find a combination that satisfy our + * channel allocation. For simplicity this is using a greedy approach, rather than + * an optimal one. + */ + enum bt_audio_location chan_allocation = BT_AUDIO_LOCATION_MONO_AUDIO; + *bis_indexes = 0; + + for (uint8_t i = 0U; i < data.cnt; i++) { + chan_allocation |= data.bis[i].chan_allocation; + *bis_indexes |= BIT(data.bis[i].index); + + if ((chan_allocation & CONFIG_TARGET_BROADCAST_CHANNEL) == + CONFIG_TARGET_BROADCAST_CHANNEL) { + return true; + } + } + } + + /* Some error occurred or we did not find expected channel allocation */ + return false; +} + +/** + * Called for each subgroup in the BASE. Will populate the 32-bit bitfield of BIS indexes if the + * subgroup contains it. + * + * The channel allocation may + * - Not exist at all, implicitly meaning BT_AUDIO_LOCATION_MONO_AUDIO + * - Exist only in the subgroup codec configuration + * - Exist only in the BIS codec configuration + * - Exist in both the subgroup and BIS codec configuration, in which case, the BIS codec + * configuration overwrites the subgroup values + * + * This function returns `true` if the subgroup does not support the channels in + * CONFIG_TARGET_BROADCAST_CHANNEL which makes it iterate over the next subgroup, and returns + * `false` if this subgroup satisfies our CONFIG_TARGET_BROADCAST_CHANNEL. + */ +static bool find_valid_bis_in_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, + void *user_data) +{ + enum bt_audio_location chan_allocation; + struct bt_audio_codec_cfg codec_cfg; + uint32_t *bis_indexes = user_data; + int err; + + /* We only want indexes from a single subgroup, so reset between each of them*/ + *bis_indexes = 0U; + + err = bt_bap_base_subgroup_codec_to_codec_cfg(subgroup, &codec_cfg); + if (err != 0) { + printk("Could not get codec configuration: %d\n", err); + + return true; + } + + err = bt_audio_codec_cfg_get_chan_allocation(&codec_cfg, &chan_allocation, false); + if (err != 0) { + printk("Could not find subgroup channel allocation: %d - Looking in the BISes\n", + err); + + /* Find chan alloc in BIS */ + if (find_valid_bis_in_subgroup_bis(subgroup, bis_indexes)) { + /* Found BISes with correct channel allocation */ + return false; + } + } else { + /* If the subgroup contains a single channel, then we just grab the first BIS index + */ + if (bt_audio_get_chan_count(chan_allocation) == 1 && + chan_allocation == CONFIG_TARGET_BROADCAST_CHANNEL) { + uint32_t subgroup_bis_indexes; + + /* Set bis_indexes to the first bit set */ + err = bt_bap_base_subgroup_get_bis_indexes(subgroup, &subgroup_bis_indexes); + if (err != 0) { + /* Should never happen as that would indicate an invalid + * subgroup If it does, we just parse the next subgroup + */ + return true; + } + + /* We found the BIS index we want, stop parsing*/ + *bis_indexes = BIT(find_lsb_set(subgroup_bis_indexes) - 1); + + return false; + } else if ((chan_allocation & CONFIG_TARGET_BROADCAST_CHANNEL) == + CONFIG_TARGET_BROADCAST_CHANNEL) { + /* The subgroup contains all channels we are looking for/ + * We continue searching each BIS to get the minimal amount of BIS that + * satisfy CONFIG_TARGET_BROADCAST_CHANNEL. + */ + + if (find_valid_bis_in_subgroup_bis(subgroup, bis_indexes)) { + /* Found BISes with correct channel allocation */ + return false; + } + } + } + + return true; +} + +/** + * This function gets a 32-bit bitfield of BIS indexes that cover the channel allocation values in + * CONFIG_TARGET_BROADCAST_CHANNEL. + */ +static int base_get_valid_bis_indexes(const struct bt_bap_base *base, uint32_t *bis_indexes) +{ + int err; + + err = bt_bap_base_foreach_subgroup(base, find_valid_bis_in_subgroup_cb, bis_indexes); + if (err != -ECANCELED) { + printk("Failed to parse subgroups: %d\n", err); + return err != 0 ? err : -ENOENT; + } + + return 0; +} +#endif /* CONFIG_TARGET_BROADCAST_CHANNEL */ + +static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base, + size_t base_size) +{ + uint32_t base_bis_index_bitfield = 0U; + int err; + + if (base_received) { + return; + } + + printk("Received BASE with %d subgroups from broadcast sink %p\n", + bt_bap_base_get_subgroup_count(base), sink); + +#if defined(CONFIG_TARGET_BROADCAST_CHANNEL) + err = base_get_valid_bis_indexes(base, &base_bis_index_bitfield); + if (err != 0) { + printk("Failed to find a valid BIS\n"); + return; + } +#else + err = bt_bap_base_get_bis_indexes(base, &base_bis_index_bitfield); + if (err != 0) { + printk("Failed to BIS indexes: %d\n", err); + return; + } +#endif /* CONFIG_TARGET_BROADCAST_CHANNEL */ + + bis_index_bitfield = base_bis_index_bitfield & bis_index_mask; + + printk("bis_index_bitfield = 0x%08x\n", bis_index_bitfield); + + if (broadcast_assistant_conn == NULL) { + /* No broadcast assistant requesting anything */ + requested_bis_sync = BT_BAP_BIS_SYNC_NO_PREF; + k_sem_give(&sem_bis_sync_requested); + } + + base_received = true; + k_sem_give(&sem_base_received); +} + +static void syncable_cb(struct bt_bap_broadcast_sink *sink, const struct bt_iso_biginfo *biginfo) +{ + printk("Broadcast sink (%p) is syncable, BIG %s\n", (void *)sink, + biginfo->encryption ? "encrypted" : "not encrypted"); + + k_sem_give(&sem_syncable); + + if (!biginfo->encryption) { + /* Use the semaphore as a boolean */ + k_sem_reset(&sem_broadcast_code_received); + k_sem_give(&sem_broadcast_code_received); + } +} + +static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = { + .base_recv = base_recv_cb, + .syncable = syncable_cb, +}; + +static void pa_timer_handler(struct k_work *work) +{ + if (req_recv_state != NULL) { + enum bt_bap_pa_state pa_state; + + if (req_recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { + pa_state = BT_BAP_PA_STATE_NO_PAST; + } else { + pa_state = BT_BAP_PA_STATE_FAILED; + } + + bt_bap_scan_delegator_set_pa_state(req_recv_state->src_id, + pa_state); + } + + printk("PA timeout\n"); +} + +static K_WORK_DELAYABLE_DEFINE(pa_timer, pa_timer_handler); + +static uint16_t interval_to_sync_timeout(uint16_t pa_interval) +{ + uint16_t pa_timeout; + + if (pa_interval == BT_BAP_PA_INTERVAL_UNKNOWN) { + /* Use maximum value to maximize chance of success */ + pa_timeout = BT_GAP_PER_ADV_MAX_TIMEOUT; + } else { + uint32_t interval_ms; + uint32_t timeout; + + /* Add retries and convert to unit in 10's of ms */ + interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(pa_interval); + timeout = (interval_ms * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO) / 10; + + /* Enforce restraints */ + pa_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT); + } + + return pa_timeout; +} + +static int pa_sync_past(struct bt_conn *conn, uint16_t pa_interval) +{ + struct bt_le_per_adv_sync_transfer_param param = { 0 }; + int err; + + param.skip = PA_SYNC_SKIP; + param.timeout = interval_to_sync_timeout(pa_interval); + + err = bt_le_per_adv_sync_transfer_subscribe(conn, ¶m); + if (err != 0) { + printk("Could not do PAST subscribe: %d\n", err); + } else { + printk("Syncing with PAST\n"); + (void)k_work_reschedule(&pa_timer, K_MSEC(param.timeout * 10)); + } + + return err; +} + +static void recv_state_updated_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state) +{ + printk("Receive state updated, pa sync state: %u\n", recv_state->pa_sync_state); + + for (uint8_t i = 0; i < recv_state->num_subgroups; i++) { + printk("subgroup %d bis_sync: 0x%08x\n", i, recv_state->subgroups[i].bis_sync); + } + + req_recv_state = recv_state; +} + +static int pa_sync_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state, + bool past_avail, uint16_t pa_interval) +{ + + printk("Received request to sync to PA (PAST %savailble): %u\n", past_avail ? "" : "not ", + recv_state->pa_sync_state); + + req_recv_state = recv_state; + + if (recv_state->pa_sync_state == BT_BAP_PA_STATE_SYNCED || + recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { + /* Already syncing */ + /* TODO: Terminate existing sync and then sync to new?*/ + return -1; + } + + if (IS_ENABLED(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER) && past_avail) { + int err; + + err = pa_sync_past(conn, pa_interval); + if (err != 0) { + printk("Failed to subscribe to PAST: %d\n", err); + + return err; + } + + k_sem_give(&sem_past_request); + + err = bt_bap_scan_delegator_set_pa_state(recv_state->src_id, + BT_BAP_PA_STATE_INFO_REQ); + if (err != 0) { + printk("Failed to set PA state to BT_BAP_PA_STATE_INFO_REQ: %d\n", err); + + return err; + } + } + + k_sem_give(&sem_pa_request); + + return 0; +} + +static int pa_sync_term_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state) +{ + int err; + + printk("PA sync termination req, pa sync state: %u\n", recv_state->pa_sync_state); + + for (uint8_t i = 0; i < recv_state->num_subgroups; i++) { + printk("subgroup %d bis_sync: 0x%08x\n", i, recv_state->subgroups[i].bis_sync); + } + + req_recv_state = recv_state; + + printk("Delete periodic advertising sync\n"); + err = bt_le_per_adv_sync_delete(pa_sync); + if (err != 0) { + printk("Could not delete per adv sync: %d\n", err); + + return err; + } + + return 0; +} + +static void broadcast_code_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state, + const uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]) +{ + printk("Broadcast code received for %p\n", recv_state); + + req_recv_state = recv_state; + + (void)memcpy(sink_broadcast_code, broadcast_code, BT_AUDIO_BROADCAST_CODE_SIZE); + + /* Use the semaphore as a boolean */ + k_sem_reset(&sem_broadcast_code_received); + k_sem_give(&sem_broadcast_code_received); +} + +static int bis_sync_req_cb(struct bt_conn *conn, + const struct bt_bap_scan_delegator_recv_state *recv_state, + const uint32_t bis_sync_req[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]) +{ + printk("BIS sync request received for %p: 0x%08x->0x%08x, broadcast id: 0x%06x, (%s)\n", + recv_state, requested_bis_sync, bis_sync_req[0], recv_state->broadcast_id, + big_synced ? "BIG synced" : "BIG not synced"); + + /* We only care about a single subgroup in this sample */ + if (big_synced && requested_bis_sync != bis_sync_req[0]) { + /* If the BIS sync request is received while we are already + * synced, it means that the requested BIS sync has changed. + */ + int err; + + /* The stream stopped callback will be called as part of this, + * and we do not need to wait for any events from the + * controller. Thus, when this returns, the `big_synced` + * is back to false. + */ + err = bt_bap_broadcast_sink_stop(broadcast_sink); + if (err != 0) { + printk("Failed to stop Broadcast Sink: %d\n", err); + + return err; + } + + k_sem_give(&sem_broadcast_sink_stopped); + } + + requested_bis_sync = bis_sync_req[0]; + broadcaster_broadcast_id = recv_state->broadcast_id; + if (bis_sync_req[0] != 0) { + k_sem_give(&sem_bis_sync_requested); + } + + return 0; +} + +static struct bt_bap_scan_delegator_cb scan_delegator_cbs = { + .recv_state_updated = recv_state_updated_cb, + .pa_sync_req = pa_sync_req_cb, + .pa_sync_term_req = pa_sync_term_req_cb, + .broadcast_code = broadcast_code_cb, + .bis_sync_req = bis_sync_req_cb, +}; + +static void connected(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (err != 0U) { + printk("Failed to connect to %s (%u)\n", addr, err); + + broadcast_assistant_conn = NULL; + return; + } + + printk("Connected: %s\n", addr); + broadcast_assistant_conn = bt_conn_ref(conn); + + k_sem_give(&sem_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != broadcast_assistant_conn) { + return; + } + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); + + bt_conn_unref(broadcast_assistant_conn); + broadcast_assistant_conn = NULL; + + k_sem_give(&sem_disconnected); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, +}; + +static struct bt_pacs_cap cap = { + .codec_cap = &codec_cap, +}; + +static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) +{ + const struct bt_le_scan_recv_info *info = user_data; + char le_addr[BT_ADDR_LE_STR_LEN]; + struct bt_uuid_16 adv_uuid; + uint32_t broadcast_id; + + if (data->type != BT_DATA_SVC_DATA16) { + return true; + } + + if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) { + return true; + } + + if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { + return true; + } + + if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) { + return true; + } + + broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); + + bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr)); + + printk("Found broadcaster with ID 0x%06X and addr %s and sid 0x%02X\n", broadcast_id, + le_addr, info->sid); + + if (broadcast_assistant_conn == NULL /* Not requested by Broadcast Assistant */ || + (req_recv_state != NULL && bt_addr_le_eq(info->addr, &req_recv_state->addr) && + info->sid == req_recv_state->adv_sid && + broadcast_id == req_recv_state->broadcast_id)) { + + /* Store info for PA sync parameters */ + memcpy(&broadcaster_info, info, sizeof(broadcaster_info)); + bt_addr_le_copy(&broadcaster_addr, info->addr); + broadcaster_broadcast_id = broadcast_id; + printk("broadcaster_broadcast_id = 0x%06X\n", broadcaster_broadcast_id); + k_sem_give(&sem_broadcaster_found); + } + + /* Stop parsing */ + return false; +} + +static bool is_substring(const char *substr, const char *str) +{ + const size_t str_len = strlen(str); + const size_t sub_str_len = strlen(substr); + + if (sub_str_len > str_len) { + return false; + } + + for (size_t pos = 0; pos < str_len; pos++) { + if (pos + sub_str_len > str_len) { + return false; + } + + if (strncasecmp(substr, &str[pos], sub_str_len) == 0) { + return true; + } + } + + return false; +} + +static bool data_cb(struct bt_data *data, void *user_data) +{ + char *name = user_data; + + switch (data->type) { + case BT_DATA_NAME_SHORTENED: + case BT_DATA_NAME_COMPLETE: + case BT_DATA_BROADCAST_NAME: + memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1)); + return false; + default: + return true; + } +} + +static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) +{ + if (info->interval != 0U) { + /* call to bt_data_parse consumes netbufs so shallow clone for verbose output */ + + /* If req_recv_state is not NULL then we have been requested by a broadcast + * assistant to sync to a specific broadcast source. In that case we do not apply + * our own broadcast name filter. + */ + if (req_recv_state == NULL && strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { + struct net_buf_simple buf_copy; + char name[NAME_LEN] = {0}; + + net_buf_simple_clone(ad, &buf_copy); + bt_data_parse(&buf_copy, data_cb, name); + if (!(is_substring(CONFIG_TARGET_BROADCAST_NAME, name))) { + return; + } + } + bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)info); + } +} + +static struct bt_le_scan_cb bap_scan_cb = { + .recv = broadcast_scan_recv, +}; + +static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync, + struct bt_le_per_adv_sync_synced_info *info) +{ + if (sync == pa_sync || + (req_recv_state != NULL && bt_addr_le_eq(info->addr, &req_recv_state->addr) && + info->sid == req_recv_state->adv_sid)) { + printk("PA sync %p synced for broadcast sink with broadcast ID 0x%06X\n", sync, + broadcaster_broadcast_id); + + if (pa_sync == NULL) { + pa_sync = sync; + } + + k_work_cancel_delayable(&pa_timer); + k_sem_give(&sem_pa_synced); + } +} + +static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync, + const struct bt_le_per_adv_sync_term_info *info) +{ + if (sync == pa_sync) { + printk("PA sync %p lost with reason 0x%02X\n", sync, info->reason); + pa_sync = NULL; + + k_sem_give(&sem_pa_sync_lost); + + if (info->reason != BT_HCI_ERR_LOCALHOST_TERM_CONN && req_recv_state != NULL) { + int err; + + if (k_sem_count_get(&sem_stream_connected) > 0) { + err = bt_bap_broadcast_sink_stop(broadcast_sink); + if (err != 0) { + printk("Failed to stop Broadcast Sink: %d\n", err); + + return; + } + } + + err = bt_bap_scan_delegator_rem_src(req_recv_state->src_id); + if (err != 0) { + printk("Failed to remove source: %d\n", err); + + return; + } + + k_sem_give(&sem_broadcast_sink_stopped); + } + } +} + +static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = { + .synced = bap_pa_sync_synced_cb, + .term = bap_pa_sync_terminated_cb, +}; + +static int init(void) +{ + int err; + + err = bt_enable(NULL); + if (err) { + printk("Bluetooth enable failed (err %d)\n", err); + return err; + } + + printk("Bluetooth initialized\n"); + + err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); + if (err) { + printk("Capability register failed (err %d)\n", err); + return err; + } + + bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs); + bt_bap_scan_delegator_register_cb(&scan_delegator_cbs); + bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb); + bt_le_scan_cb_register(&bap_scan_cb); + + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + streams[i].stream.ops = &stream_ops; + } + + /* Initialize ring buffers and USB */ +#if defined(CONFIG_USB_DEVICE_AUDIO) + const struct device *hs_dev = DEVICE_DT_GET(DT_NODELABEL(hs_0)); + static const struct usb_audio_ops usb_ops = { + .data_request_cb = usb_data_request_cb, + .data_written_cb = usb_data_written_cb, + }; + + if (!device_is_ready(hs_dev)) { + printk("Cannot get USB Headset Device\n"); + return -EIO; + } + + usb_audio_register(hs_dev, &usb_ops); + err = usb_enable(NULL); + if (err && err != -EALREADY) { + printk("Failed to enable USB\n"); + return err; + } +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ + + return 0; +} + +static int reset(void) +{ + int err; + + printk("Reset\n"); + + bis_index_bitfield = 0U; + requested_bis_sync = 0U; + req_recv_state = NULL; + big_synced = false; + base_received = false; + stream_count = 0U; + (void)memset(sink_broadcast_code, 0, sizeof(sink_broadcast_code)); + (void)memset(&broadcaster_info, 0, sizeof(broadcaster_info)); + (void)memset(&broadcaster_addr, 0, sizeof(broadcaster_addr)); + broadcaster_broadcast_id = INVALID_BROADCAST_ID; + + if (broadcast_sink != NULL) { + err = bt_bap_broadcast_sink_delete(broadcast_sink); + if (err) { + printk("Deleting broadcast sink failed (err %d)\n", err); + + return err; + } + + broadcast_sink = NULL; + } + + if (pa_sync != NULL) { + bt_le_per_adv_sync_delete(pa_sync); + if (err) { + printk("Deleting PA sync failed (err %d)\n", err); + + return err; + } + + pa_sync = NULL; + } + + k_sem_reset(&sem_broadcaster_found); + k_sem_reset(&sem_pa_synced); + k_sem_reset(&sem_base_received); + k_sem_reset(&sem_syncable); + k_sem_reset(&sem_pa_sync_lost); + k_sem_reset(&sem_broadcast_code_received); + k_sem_reset(&sem_bis_sync_requested); + k_sem_reset(&sem_stream_connected); + k_sem_reset(&sem_stream_started); + k_sem_reset(&sem_broadcast_sink_stopped); + + return 0; +} + +static int start_adv(void) +{ + const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, + BT_UUID_16_ENCODE(BT_UUID_BASS_VAL), + BT_UUID_16_ENCODE(BT_UUID_PACS_VAL)), + BT_DATA_BYTES(BT_DATA_SVC_DATA16, BT_UUID_16_ENCODE(BT_UUID_BASS_VAL)), + BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, + sizeof(CONFIG_BT_DEVICE_NAME) - 1), + }; + int err; + + /* Create a connectable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &ext_adv); + if (err != 0) { + printk("Failed to create advertising set (err %d)\n", err); + + return err; + } + + err = bt_le_ext_adv_set_data(ext_adv, ad, ARRAY_SIZE(ad), NULL, 0); + if (err != 0) { + printk("Failed to set advertising data (err %d)\n", err); + + return err; + } + + err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err != 0) { + printk("Failed to start advertising set (err %d)\n", err); + + return err; + } + + return 0; +} + +static int stop_adv(void) +{ + int err; + + err = bt_le_ext_adv_stop(ext_adv); + if (err != 0) { + printk("Failed to stop advertising set (err %d)\n", err); + + return err; + } + + err = bt_le_ext_adv_delete(ext_adv); + if (err != 0) { + printk("Failed to delete advertising set (err %d)\n", err); + + return err; + } + + ext_adv = NULL; + + return 0; +} + +static int pa_sync_create(void) +{ + struct bt_le_per_adv_sync_param create_params = {0}; + + bt_addr_le_copy(&create_params.addr, &broadcaster_addr); + create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE; + create_params.sid = broadcaster_info.sid; + create_params.skip = PA_SYNC_SKIP; + create_params.timeout = interval_to_sync_timeout(broadcaster_info.interval); + + return bt_le_per_adv_sync_create(&create_params, &pa_sync); +} + +int main(void) +{ + int err; + + err = init(); + if (err) { + printk("Init failed (err %d)\n", err); + return 0; + } + + for (size_t i = 0U; i < ARRAY_SIZE(streams_p); i++) { + streams_p[i] = &streams[i].stream; +#if defined(CONFIG_LIBLC3) + k_mutex_init(&streams[i].lc3_decoder_mutex); +#endif /* defined(CONFIG_LIBLC3) */ + } + + while (true) { + uint32_t sync_bitfield; + + err = reset(); + if (err != 0) { + printk("Resetting failed: %d - Aborting\n", err); + + return 0; + } + + if (IS_ENABLED(CONFIG_SCAN_OFFLOAD)) { + if (broadcast_assistant_conn == NULL) { + k_sem_reset(&sem_connected); + + printk("Starting advertising\n"); + /* Stop advertising before starting if needed */ + if (ext_adv != NULL) { + err = stop_adv(); + if (err != 0) { + printk("Unable to stop advertising: %d\n", err); + + return 0; + } + } + err = start_adv(); + if (err != 0) { + printk("Unable to start advertising connectable: %d\n", + err); + + return 0; + } + + printk("Waiting for Broadcast Assistant\n"); + err = k_sem_take(&sem_connected, ADV_TIMEOUT); + if (err != 0) { + printk("No Broadcast Assistant connected\n"); + + err = stop_adv(); + if (err != 0) { + printk("Unable to stop advertising: %d\n", err); + + return 0; + } + } + } + + if (broadcast_assistant_conn != NULL) { + k_sem_reset(&sem_pa_request); + k_sem_reset(&sem_past_request); + k_sem_reset(&sem_disconnected); + + /* Wait for the PA request to determine if we + * should start scanning, or wait for PAST + */ + printk("Waiting for PA sync request\n"); + err = k_sem_take(&sem_pa_request, + BROADCAST_ASSISTANT_TIMEOUT); + if (err != 0) { + printk("sem_pa_request timed out, resetting\n"); + continue; + } + + if (k_sem_take(&sem_past_request, K_NO_WAIT) == 0) { + goto wait_for_pa_sync; + } /* else continue with scanning below */ + } + } + + if (strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { + printk("Scanning for broadcast sources containing " + "`" CONFIG_TARGET_BROADCAST_NAME "`\n"); + } else { + printk("Scanning for broadcast sources\n"); + } + + err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL); + if (err != 0 && err != -EALREADY) { + printk("Unable to start scan for broadcast sources: %d\n", + err); + return 0; + } + + printk("Waiting for Broadcaster\n"); + err = k_sem_take(&sem_broadcaster_found, SEM_TIMEOUT); + if (err != 0) { + printk("sem_broadcaster_found timed out, resetting\n"); + continue; + } + + err = bt_le_scan_stop(); + if (err != 0) { + printk("bt_le_scan_stop failed with %d, resetting\n", err); + continue; + } + + printk("Attempting to PA sync to the broadcaster with id 0x%06X\n", + broadcaster_broadcast_id); + err = pa_sync_create(); + if (err != 0) { + printk("Could not create Broadcast PA sync: %d, resetting\n", err); + continue; + } + +wait_for_pa_sync: + printk("Waiting for PA synced\n"); + err = k_sem_take(&sem_pa_synced, SEM_TIMEOUT); + if (err != 0) { + printk("sem_pa_synced timed out, resetting\n"); + continue; + } + + printk("Broadcast source PA synced, creating Broadcast Sink\n"); + err = bt_bap_broadcast_sink_create(pa_sync, broadcaster_broadcast_id, + &broadcast_sink); + if (err != 0) { + printk("Failed to create broadcast sink: %d\n", err); + continue; + } + + printk("Broadcast Sink created, waiting for BASE\n"); + err = k_sem_take(&sem_base_received, SEM_TIMEOUT); + if (err != 0) { + printk("sem_base_received timed out, resetting\n"); + continue; + } + + printk("BASE received, waiting for syncable\n"); + err = k_sem_take(&sem_syncable, SEM_TIMEOUT); + if (err != 0) { + printk("sem_syncable timed out, resetting\n"); + continue; + } + + /* sem_broadcast_code_received is also given if the + * broadcast is not encrypted + */ + printk("Waiting for broadcast code\n"); + err = k_sem_take(&sem_broadcast_code_received, SEM_TIMEOUT); + if (err != 0) { + printk("sem_broadcast_code_received timed out, resetting\n"); + continue; + } + + printk("Waiting for BIS sync request\n"); + err = k_sem_take(&sem_bis_sync_requested, SEM_TIMEOUT); + if (err != 0) { + printk("sem_bis_sync_requested timed out, resetting\n"); + continue; + } + + sync_bitfield = bis_index_bitfield & requested_bis_sync; + stream_count = 0; + for (int i = 1; i < BT_ISO_MAX_GROUP_ISO_COUNT; i++) { + if ((sync_bitfield & BIT(i)) != 0) { + stream_count++; + } + } + + printk("Syncing to broadcast with bitfield: 0x%08x = 0x%08x (bis_index) & 0x%08x " + "(req_bis_sync), stream_count = %u\n", + sync_bitfield, bis_index_bitfield, requested_bis_sync, stream_count); + + err = bt_bap_broadcast_sink_sync(broadcast_sink, sync_bitfield, streams_p, + sink_broadcast_code); + if (err != 0) { + printk("Unable to sync to broadcast source: %d\n", err); + return 0; + } + + printk("Waiting for stream(s) started\n"); + err = k_sem_take(&sem_big_synced, SEM_TIMEOUT); + if (err != 0) { + printk("sem_big_synced timed out, resetting\n"); + continue; + } + + printk("Waiting for PA disconnected\n"); + k_sem_take(&sem_pa_sync_lost, K_FOREVER); + + printk("Waiting for sink to stop\n"); + err = k_sem_take(&sem_broadcast_sink_stopped, SEM_TIMEOUT); + if (err != 0) { + printk("sem_broadcast_sink_stopped timed out, resetting\n"); + continue; + } + } + + return 0; +} diff --git a/samples/bluetooth/broadcast_audio_sink/sysbuild.cmake b/samples/bluetooth/bap_broadcast_sink/sysbuild.cmake similarity index 100% rename from samples/bluetooth/broadcast_audio_sink/sysbuild.cmake rename to samples/bluetooth/bap_broadcast_sink/sysbuild.cmake diff --git a/samples/bluetooth/bap_broadcast_source/CMakeLists.txt b/samples/bluetooth/bap_broadcast_source/CMakeLists.txt new file mode 100644 index 0000000000000..66649d87a33c8 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_source/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bap_unicast_server) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/broadcast_audio_source/Kconfig b/samples/bluetooth/bap_broadcast_source/Kconfig similarity index 100% rename from samples/bluetooth/broadcast_audio_source/Kconfig rename to samples/bluetooth/bap_broadcast_source/Kconfig diff --git a/samples/bluetooth/broadcast_audio_source/Kconfig.sysbuild b/samples/bluetooth/bap_broadcast_source/Kconfig.sysbuild similarity index 100% rename from samples/bluetooth/broadcast_audio_source/Kconfig.sysbuild rename to samples/bluetooth/bap_broadcast_source/Kconfig.sysbuild diff --git a/samples/bluetooth/bap_broadcast_source/README.rst b/samples/bluetooth/bap_broadcast_source/README.rst new file mode 100644 index 0000000000000..b4a3ac7226565 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_source/README.rst @@ -0,0 +1,79 @@ +.. zephyr:code-sample:: bluetooth_bap_broadcast_source + :name: Bluetooth: Broadcast Audio Source + :relevant-api: bluetooth + + Bluetooth: Broadcast Audio Source + +Overview +******** + +Application demonstrating the LE Audio broadcast audio source functionality. +Will start advertising extended advertising with audio flags, periodic advertising with the +broadcast audio source endpoint (BASE) and finally the BIGinfo together with +(mock) Audio (ISO) data. + +The broadcast source will reset every 30 seconds to show the full API. + +This sample can be found under +:zephyr_file:`samples/bluetooth/bap_broadcast_source` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_broadcast_source/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_broadcast_source/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_broadcast_source/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_broadcast_source/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf52833dk_nrf52833.conf b/samples/bluetooth/bap_broadcast_source/boards/nrf52833dk_nrf52833.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_source/boards/nrf52833dk_nrf52833.conf rename to samples/bluetooth/bap_broadcast_source/boards/nrf52833dk_nrf52833.conf diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf52840dongle_nrf52840.overlay b/samples/bluetooth/bap_broadcast_source/boards/nrf52833dk_nrf52833.overlay similarity index 100% rename from samples/bluetooth/broadcast_audio_source/boards/nrf52840dongle_nrf52840.overlay rename to samples/bluetooth/bap_broadcast_source/boards/nrf52833dk_nrf52833.overlay diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf52840dongle_nrf52840.conf b/samples/bluetooth/bap_broadcast_source/boards/nrf52840dongle_nrf52840.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_source/boards/nrf52840dongle_nrf52840.conf rename to samples/bluetooth/bap_broadcast_source/boards/nrf52840dongle_nrf52840.conf diff --git a/samples/bluetooth/bap_broadcast_source/boards/nrf52840dongle_nrf52840.overlay b/samples/bluetooth/bap_broadcast_source/boards/nrf52840dongle_nrf52840.overlay new file mode 100644 index 0000000000000..b8e72f1b61c5b --- /dev/null +++ b/samples/bluetooth/bap_broadcast_source/boards/nrf52840dongle_nrf52840.overlay @@ -0,0 +1,15 @@ +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; + + hs_0: hs_0 { + compatible = "usb-audio-hs"; + mic-feature-mute; + mic-channel-l; + mic-channel-r; + + hp-feature-mute; + hp-channel-l; + hp-channel-r; + }; +}; diff --git a/samples/bluetooth/broadcast_audio_source/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/bap_broadcast_source/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_source/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf rename to samples/bluetooth/bap_broadcast_source/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf diff --git a/samples/bluetooth/bap_broadcast_source/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/bap_broadcast_source/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..8b65fa9a9d857 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_source/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,3 @@ +# Use USB Audio as audio source +CONFIG_USE_USB_AUDIO_INPUT=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr Broadcast Source" diff --git a/samples/bluetooth/bap_broadcast_source/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/bluetooth/bap_broadcast_source/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..b8e72f1b61c5b --- /dev/null +++ b/samples/bluetooth/bap_broadcast_source/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,15 @@ +zephyr_udc0: &usbd { + compatible = "nordic,nrf-usbd"; + status = "okay"; + + hs_0: hs_0 { + compatible = "usb-audio-hs"; + mic-feature-mute; + mic-channel-l; + mic-channel-r; + + hp-feature-mute; + hp-channel-l; + hp-channel-r; + }; +}; diff --git a/samples/bluetooth/bap_broadcast_source/overlay-bt_ll_sw_split.conf b/samples/bluetooth/bap_broadcast_source/overlay-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..3711a34921368 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_source/overlay-bt_ll_sw_split.conf @@ -0,0 +1,20 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Zephyr Controller tested maximum advertising data that can be set in a single HCI command +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 + +# Enable support for Broadcast ISO in Zephyr Bluetooth Controller +CONFIG_BT_CTLR_ADV_ISO=y + +# Sufficient ISO PDU length for any BAP LC3 presets (155) +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=155 + +# Number of supported streams +CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 +CONFIG_BT_CTLR_ISOAL_SOURCES=2 + +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 diff --git a/samples/bluetooth/broadcast_audio_source/prj.conf b/samples/bluetooth/bap_broadcast_source/prj.conf similarity index 100% rename from samples/bluetooth/broadcast_audio_source/prj.conf rename to samples/bluetooth/bap_broadcast_source/prj.conf diff --git a/samples/bluetooth/bap_broadcast_source/sample.yaml b/samples/bluetooth/bap_broadcast_source/sample.yaml new file mode 100644 index 0000000000000..27262103b29db --- /dev/null +++ b/samples/bluetooth/bap_broadcast_source/sample.yaml @@ -0,0 +1,29 @@ +sample: + description: Bluetooth Low Energy Broadcast Audio Source sample + name: Bluetooth Low Energy Broadcast Audio Source sample +tests: + sample.bluetooth.bap_broadcast_source: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + - nrf5340bsim/nrf5340/cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.bap_broadcast_source.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk/nrf52820 + - nrf52833dk/nrf52833 + - nrf52840dongle/nrf52840 + integration_platforms: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dongle/nrf52840 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/bap_broadcast_source/src/main.c b/samples/bluetooth/bap_broadcast_source/src/main.c new file mode 100644 index 0000000000000..fc3befa01d314 --- /dev/null +++ b/samples/bluetooth/bap_broadcast_source/src/main.c @@ -0,0 +1,623 @@ +/* + * Copyright (c) 2022-2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +BUILD_ASSERT(strlen(CONFIG_BROADCAST_CODE) <= BT_AUDIO_BROADCAST_CODE_SIZE, + "Invalid broadcast code"); + +/* Zephyr Controller works best while Extended Advertising interval to be a multiple + * of the ISO Interval minus 10 ms (max. advertising random delay). This is + * required to place the AUX_ADV_IND PDUs in a non-overlapping interval with the + * Broadcast ISO radio events. + * + * I.e. for a 7.5 ms ISO interval use 90 ms minus 10 ms ==> 80 ms advertising + * interval. + * And, for 10 ms ISO interval, can use 90 ms minus 10 ms ==> 80 ms advertising + * interval. + */ +#define BT_LE_EXT_ADV_CUSTOM BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV, 0x0080, 0x0080, NULL) + +/* When BROADCAST_ENQUEUE_COUNT > 1 we can enqueue enough buffers to ensure that + * the controller is never idle + */ +#define BROADCAST_ENQUEUE_COUNT 3U +#define TOTAL_BUF_NEEDED (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT) + +BUILD_ASSERT(CONFIG_BT_ISO_TX_BUF_COUNT >= TOTAL_BUF_NEEDED, + "CONFIG_BT_ISO_TX_BUF_COUNT should be at least " + "BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT"); + +#if defined(CONFIG_BAP_BROADCAST_16_2_1) + +static struct bt_bap_lc3_preset preset_active = BT_BAP_LC3_BROADCAST_PRESET_16_2_1( + BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT, + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + +#define BROADCAST_SAMPLE_RATE 16000 + +#elif defined(CONFIG_BAP_BROADCAST_24_2_1) + +static struct bt_bap_lc3_preset preset_active = BT_BAP_LC3_BROADCAST_PRESET_24_2_1( + BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT, + BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + +#define BROADCAST_SAMPLE_RATE 24000 + +#endif + +#if defined(CONFIG_BAP_BROADCAST_16_2_1) +#define MAX_SAMPLE_RATE 16000 +#elif defined(CONFIG_BAP_BROADCAST_24_2_1) +#define MAX_SAMPLE_RATE 24000 +#endif +#define MAX_FRAME_DURATION_US 10000 +#define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC) + +#if defined(CONFIG_LIBLC3) +#include "lc3.h" + +#if defined(CONFIG_USB_DEVICE_AUDIO) +#include +#include +#include + +/* USB Audio Data is downsampled from 48kHz to match broadcast preset when receiving data */ +#define USB_SAMPLE_RATE 48000 +#define USB_DOWNSAMPLE_RATE BROADCAST_SAMPLE_RATE +#define USB_FRAME_DURATION_US 1000 +#define USB_NUM_SAMPLES ((USB_FRAME_DURATION_US * USB_DOWNSAMPLE_RATE) / USEC_PER_SEC) +#define USB_BYTES_PER_SAMPLE 2 +#define USB_CHANNELS 2 + +#define RING_BUF_USB_FRAMES 20 +#define AUDIO_RING_BUF_BYTES (USB_NUM_SAMPLES * USB_BYTES_PER_SAMPLE * RING_BUF_USB_FRAMES) +#else /* !defined(CONFIG_USB_DEVICE_AUDIO) */ + +#include + +#define AUDIO_VOLUME (INT16_MAX - 3000) /* codec does clipping above INT16_MAX - 3000 */ +#define AUDIO_TONE_FREQUENCY_HZ 400 + +/** + * Use the math lib to generate a sine-wave using 16 bit samples into a buffer. + * + * @param buf Destination buffer + * @param length_us Length of the buffer in microseconds + * @param frequency_hz frequency in Hz + * @param sample_rate_hz sample-rate in Hz. + */ +static void fill_audio_buf_sin(int16_t *buf, int length_us, int frequency_hz, int sample_rate_hz) +{ + const int sine_period_samples = sample_rate_hz / frequency_hz; + const unsigned int num_samples = (length_us * sample_rate_hz) / USEC_PER_SEC; + const float step = 2 * 3.1415f / sine_period_samples; + + for (unsigned int i = 0; i < num_samples; i++) { + const float sample = sinf(i * step); + + buf[i] = (int16_t)(AUDIO_VOLUME * sample); + } +} +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ +#endif /* defined(CONFIG_LIBLC3) */ + +static struct broadcast_source_stream { + struct bt_bap_stream stream; + uint16_t seq_num; + size_t sent_cnt; +#if defined(CONFIG_LIBLC3) + lc3_encoder_t lc3_encoder; +#if defined(CONFIG_BAP_BROADCAST_16_2_1) + lc3_encoder_mem_16k_t lc3_encoder_mem; +#elif defined(CONFIG_BAP_BROADCAST_24_2_1) + lc3_encoder_mem_48k_t lc3_encoder_mem; +#endif +#if defined(CONFIG_USB_DEVICE_AUDIO) + struct ring_buf audio_ring_buf; + uint8_t _ring_buffer_memory[AUDIO_RING_BUF_BYTES]; +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ +#endif /* defined(CONFIG_LIBLC3) */ +} streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; +static struct bt_bap_broadcast_source *broadcast_source; + +NET_BUF_POOL_FIXED_DEFINE(tx_pool, TOTAL_BUF_NEEDED, BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +static int16_t send_pcm_data[MAX_NUM_SAMPLES]; +static uint16_t seq_num; +static bool stopping; + +static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(streams)); +static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams)); + +#define BROADCAST_SOURCE_LIFETIME 120U /* seconds */ + +#if defined(CONFIG_LIBLC3) +static int freq_hz; +static int frame_duration_us; +static int frames_per_sdu; +static int octets_per_frame; + +static K_SEM_DEFINE(lc3_encoder_sem, 0U, TOTAL_BUF_NEEDED); +#endif + +static void send_data(struct broadcast_source_stream *source_stream) +{ + struct bt_bap_stream *stream = &source_stream->stream; + struct net_buf *buf; + int ret; + + if (stopping) { + return; + } + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + if (buf == NULL) { + printk("Could not allocate buffer when sending on %p\n", stream); + return; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); +#if defined(CONFIG_LIBLC3) + uint8_t lc3_encoded_buffer[preset_active.qos.sdu]; + + if (source_stream->lc3_encoder == NULL) { + printk("LC3 encoder not setup, cannot encode data.\n"); + net_buf_unref(buf); + return; + } + +#if defined(CONFIG_USB_DEVICE_AUDIO) + uint32_t size = ring_buf_get(&source_stream->audio_ring_buf, (uint8_t *)send_pcm_data, + sizeof(send_pcm_data)); + + if (size < sizeof(send_pcm_data)) { + const size_t padding_size = sizeof(send_pcm_data) - size; + + printk("Not enough bytes ready, padding %d!\n", padding_size); + memset(&((uint8_t *)send_pcm_data)[size], 0, padding_size); + } +#endif + + ret = lc3_encode(source_stream->lc3_encoder, LC3_PCM_FORMAT_S16, send_pcm_data, 1, + octets_per_frame, lc3_encoded_buffer); + if (ret == -1) { + printk("LC3 encoder failed - wrong parameters?: %d", ret); + net_buf_unref(buf); + return; + } + + net_buf_add_mem(buf, lc3_encoded_buffer, preset_active.qos.sdu); +#else + net_buf_add_mem(buf, send_pcm_data, preset_active.qos.sdu); +#endif /* defined(CONFIG_LIBLC3) */ + + ret = bt_bap_stream_send(stream, buf, source_stream->seq_num++); + if (ret < 0) { + /* This will end broadcasting on this stream. */ + printk("Unable to broadcast data on %p: %d\n", stream, ret); + net_buf_unref(buf); + return; + } + + source_stream->sent_cnt++; + if ((source_stream->sent_cnt % 1000U) == 0U) { + printk("Stream %p: Sent %u total ISO packets\n", stream, source_stream->sent_cnt); + } +} + +#if defined(CONFIG_LIBLC3) +static void init_lc3_thread(void *arg1, void *arg2, void *arg3) +{ + const struct bt_audio_codec_cfg *codec_cfg = &preset_active.codec_cfg; + int ret; + + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + freq_hz = bt_audio_codec_cfg_freq_to_freq_hz(ret); + } else { + return; + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + } else { + printk("Error: Frame duration not set, cannot start codec."); + return; + } + + octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); + frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true); + + if (freq_hz < 0) { + printk("Error: Codec frequency not set, cannot start codec."); + return; + } + + if (frame_duration_us < 0) { + printk("Error: Frame duration not set, cannot start codec."); + return; + } + + if (octets_per_frame < 0) { + printk("Error: Octets per frame not set, cannot start codec."); + return; + } + +#if !defined(CONFIG_USB_DEVICE_AUDIO) + /* If USB is not used as a sound source, generate a sine wave */ + fill_audio_buf_sin(send_pcm_data, frame_duration_us, AUDIO_TONE_FREQUENCY_HZ, freq_hz); +#endif + + /* Create the encoder instance. This shall complete before stream_started() is called. */ + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + printk("Initializing lc3 encoder for stream %zu\n", i); + streams[i].lc3_encoder = lc3_setup_encoder(frame_duration_us, freq_hz, 0, + &streams[i].lc3_encoder_mem); + + if (streams[i].lc3_encoder == NULL) { + printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n"); + } + } + + while (true) { + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + k_sem_take(&lc3_encoder_sem, K_FOREVER); + } + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + send_data(&streams[i]); + } + } +} + +#define LC3_ENCODER_STACK_SIZE 4 * 4096 +#define LC3_ENCODER_PRIORITY 5 + +K_THREAD_DEFINE(encoder, LC3_ENCODER_STACK_SIZE, init_lc3_thread, NULL, NULL, NULL, + LC3_ENCODER_PRIORITY, 0, -1); + +#if defined(CONFIG_USB_DEVICE_AUDIO) +static void data_received(const struct device *dev, struct net_buf *buffer, size_t size) +{ + static int count; + int16_t *pcm; + int nsamples, ratio; + int16_t usb_pcm_data[USB_CHANNELS][USB_NUM_SAMPLES]; + + if (!buffer) { + return; + } + + if (!size) { + net_buf_unref(buffer); + return; + } + + pcm = (int16_t *)net_buf_pull_mem(buffer, size); + + /* 'size' is in bytes, containing 1ms, 48kHz, stereo, 2 bytes per sample. + * Take left channel and do a simple downsample to 16kHz/24Khz + * matching the broadcast preset. + */ + + ratio = USB_SAMPLE_RATE / USB_DOWNSAMPLE_RATE; + nsamples = size / (sizeof(int16_t) * USB_CHANNELS * ratio); + for (size_t i = 0, j = 0; i < nsamples; i++, j += USB_CHANNELS * ratio) { + usb_pcm_data[0][i] = pcm[j]; + usb_pcm_data[1][i] = pcm[j + 1]; + } + + for (size_t i = 0U; i < MIN(ARRAY_SIZE(streams), 2); i++) { + const uint32_t size_put = + ring_buf_put(&(streams[i].audio_ring_buf), (uint8_t *)(usb_pcm_data[i]), + nsamples * USB_BYTES_PER_SAMPLE); + if (size_put < nsamples * USB_BYTES_PER_SAMPLE) { + printk("Not enough room for samples in %s buffer: %u < %u, total capacity: " + "%u\n", + i == 0 ? "left" : "right", size_put, nsamples * USB_BYTES_PER_SAMPLE, + ring_buf_capacity_get(&(streams[i].audio_ring_buf))); + } + } + + count++; + if ((count % 1000) == 0) { + printk("USB Data received (count = %d)\n", count); + } + + net_buf_unref(buffer); +} + +static const struct usb_audio_ops ops = {.data_received_cb = data_received}; +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ +#endif /* defined(CONFIG_LIBLC3) */ + +static void stream_started_cb(struct bt_bap_stream *stream) +{ + struct broadcast_source_stream *source_stream = + CONTAINER_OF(stream, struct broadcast_source_stream, stream); + + source_stream->seq_num = 0U; + source_stream->sent_cnt = 0U; + k_sem_give(&sem_started); +} + +static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + k_sem_give(&sem_stopped); +} + +static void stream_sent_cb(struct bt_bap_stream *stream) +{ +#if defined(CONFIG_LIBLC3) + k_sem_give(&lc3_encoder_sem); +#else + /* If no LC3 encoder is used, just send mock data directly */ + struct broadcast_source_stream *source_stream = + CONTAINER_OF(stream, struct broadcast_source_stream, stream); + + send_data(source_stream); +#endif +} + +static struct bt_bap_stream_ops stream_ops = { + .started = stream_started_cb, .stopped = stream_stopped_cb, .sent = stream_sent_cb}; + +static int setup_broadcast_source(struct bt_bap_broadcast_source **source) +{ + struct bt_bap_broadcast_source_stream_param + stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; + struct bt_bap_broadcast_source_subgroup_param + subgroup_param[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT]; + struct bt_bap_broadcast_source_param create_param = {0}; + const size_t streams_per_subgroup = ARRAY_SIZE(stream_params) / ARRAY_SIZE(subgroup_param); + uint8_t left[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_CHAN_ALLOC, + BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_LEFT))}; + uint8_t right[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_CHAN_ALLOC, + BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_RIGHT))}; + int err; + + for (size_t i = 0U; i < ARRAY_SIZE(subgroup_param); i++) { + subgroup_param[i].params_count = streams_per_subgroup; + subgroup_param[i].params = stream_params + i * streams_per_subgroup; + subgroup_param[i].codec_cfg = &preset_active.codec_cfg; + } + + for (size_t j = 0U; j < ARRAY_SIZE(stream_params); j++) { + stream_params[j].stream = &streams[j].stream; + stream_params[j].data = j == 0 ? left : right; + stream_params[j].data_len = j == 0 ? sizeof(left) : sizeof(right); + bt_bap_stream_cb_register(stream_params[j].stream, &stream_ops); + } + + create_param.params_count = ARRAY_SIZE(subgroup_param); + create_param.params = subgroup_param; + create_param.qos = &preset_active.qos; + create_param.encryption = strlen(CONFIG_BROADCAST_CODE) > 0; + create_param.packing = BT_ISO_PACKING_SEQUENTIAL; + + if (create_param.encryption) { + memcpy(create_param.broadcast_code, CONFIG_BROADCAST_CODE, + strlen(CONFIG_BROADCAST_CODE)); + } + + printk("Creating broadcast source with %zu subgroups with %zu streams\n", + ARRAY_SIZE(subgroup_param), ARRAY_SIZE(subgroup_param) * streams_per_subgroup); + + err = bt_bap_broadcast_source_create(&create_param, source); + if (err != 0) { + printk("Unable to create broadcast source: %d\n", err); + return err; + } + + return 0; +} + +int main(void) +{ + struct bt_le_ext_adv *adv; + int err; + + err = bt_enable(NULL); + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + return 0; + } + printk("Bluetooth initialized\n"); + + for (size_t i = 0U; i < ARRAY_SIZE(send_pcm_data); i++) { + /* Initialize mock data */ + send_pcm_data[i] = i; + } + +#if defined(CONFIG_LIBLC3) +#if defined(CONFIG_USB_DEVICE_AUDIO) + const struct device *hs_dev; + + hs_dev = DEVICE_DT_GET(DT_NODELABEL(hs_0)); + + if (!device_is_ready(hs_dev)) { + printk("Device USB Headset is not ready\n"); + return 0; + } + + printk("Found USB Headset Device\n"); + + (void)memset(streams, 0, sizeof(streams)); + + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + ring_buf_init(&(streams[i].audio_ring_buf), sizeof(streams[i]._ring_buffer_memory), + streams[i]._ring_buffer_memory); + printk("Initialized ring buf %zu: capacity: %u\n", i, + ring_buf_capacity_get(&(streams[i].audio_ring_buf))); + } + + usb_audio_register(hs_dev, &ops); + + err = usb_enable(NULL); + if (err && err != -EALREADY) { + printk("Failed to enable USB (%d)", err); + return 0; + } + +#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ + k_thread_start(encoder); +#endif /* defined(CONFIG_LIBLC3) */ + + while (true) { + /* Broadcast Audio Streaming Endpoint advertising data */ + NET_BUF_SIMPLE_DEFINE(ad_buf, BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); + NET_BUF_SIMPLE_DEFINE(base_buf, 128); + struct bt_data ext_ad[2]; + struct bt_data per_ad; + uint32_t broadcast_id; + + /* Create a connectable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CUSTOM, NULL, &adv); + if (err != 0) { + printk("Unable to create extended advertising set: %d\n", err); + return 0; + } + + /* Set periodic advertising parameters */ + err = bt_le_per_adv_set_param(adv, BT_LE_PER_ADV_DEFAULT); + if (err) { + printk("Failed to set periodic advertising parameters (err %d)\n", err); + return 0; + } + + printk("Creating broadcast source\n"); + err = setup_broadcast_source(&broadcast_source); + if (err != 0) { + printk("Unable to setup broadcast source: %d\n", err); + return 0; + } + + err = bt_bap_broadcast_source_get_id(broadcast_source, &broadcast_id); + if (err != 0) { + printk("Unable to get broadcast ID: %d\n", err); + return 0; + } + + /* Setup extended advertising data */ + net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); + net_buf_simple_add_le24(&ad_buf, broadcast_id); + ext_ad[0].type = BT_DATA_SVC_DATA16; + ext_ad[0].data_len = ad_buf.len; + ext_ad[0].data = ad_buf.data; + ext_ad[1] = (struct bt_data)BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, + sizeof(CONFIG_BT_DEVICE_NAME) - 1); + err = bt_le_ext_adv_set_data(adv, ext_ad, 2, NULL, 0); + if (err != 0) { + printk("Failed to set extended advertising data: %d\n", err); + return 0; + } + + /* Setup periodic advertising data */ + err = bt_bap_broadcast_source_get_base(broadcast_source, &base_buf); + if (err != 0) { + printk("Failed to get encoded BASE: %d\n", err); + return 0; + } + + per_ad.type = BT_DATA_SVC_DATA16; + per_ad.data_len = base_buf.len; + per_ad.data = base_buf.data; + err = bt_le_per_adv_set_data(adv, &per_ad, 1); + if (err != 0) { + printk("Failed to set periodic advertising data: %d\n", err); + return 0; + } + + /* Start extended advertising */ + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err) { + printk("Failed to start extended advertising: %d\n", err); + return 0; + } + + /* Enable Periodic Advertising */ + err = bt_le_per_adv_start(adv); + if (err) { + printk("Failed to enable periodic advertising: %d\n", err); + return 0; + } + + printk("Starting broadcast source\n"); + stopping = false; + err = bt_bap_broadcast_source_start(broadcast_source, adv); + if (err != 0) { + printk("Unable to start broadcast source: %d\n", err); + return 0; + } + + /* Wait for all to be started */ + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + k_sem_take(&sem_started, K_FOREVER); + } + printk("Broadcast source started\n"); + + /* Initialize sending */ + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) { + stream_sent_cb(&streams[i].stream); + } + } + +#if defined(CONFIG_LIBLC3) && defined(CONFIG_USB_DEVICE_AUDIO) + /* Never stop streaming when using USB Audio as input */ + k_sleep(K_FOREVER); +#endif /* defined(CONFIG_LIBLC3) && defined(CONFIG_USB_DEVICE_AUDIO) */ + printk("Waiting %u seconds before stopped\n", BROADCAST_SOURCE_LIFETIME); + k_sleep(K_SECONDS(BROADCAST_SOURCE_LIFETIME)); + printk("Stopping broadcast source\n"); + stopping = true; + err = bt_bap_broadcast_source_stop(broadcast_source); + if (err != 0) { + printk("Unable to stop broadcast source: %d\n", err); + return 0; + } + + /* Wait for all to be stopped */ + for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { + k_sem_take(&sem_stopped, K_FOREVER); + } + printk("Broadcast source stopped\n"); + + printk("Deleting broadcast source\n"); + err = bt_bap_broadcast_source_delete(broadcast_source); + if (err != 0) { + printk("Unable to delete broadcast source: %d\n", err); + return 0; + } + printk("Broadcast source deleted\n"); + broadcast_source = NULL; + seq_num = 0; + + err = bt_le_per_adv_stop(adv); + if (err) { + printk("Failed to stop periodic advertising (err %d)\n", err); + return 0; + } + + err = bt_le_ext_adv_stop(adv); + if (err) { + printk("Failed to stop extended advertising (err %d)\n", err); + return 0; + } + + err = bt_le_ext_adv_delete(adv); + if (err) { + printk("Failed to delete extended advertising (err %d)\n", err); + return 0; + } + } + return 0; +} diff --git a/samples/bluetooth/broadcast_audio_source/sysbuild.cmake b/samples/bluetooth/bap_broadcast_source/sysbuild.cmake similarity index 100% rename from samples/bluetooth/broadcast_audio_source/sysbuild.cmake rename to samples/bluetooth/bap_broadcast_source/sysbuild.cmake diff --git a/samples/bluetooth/bap_unicast_client/CMakeLists.txt b/samples/bluetooth/bap_unicast_client/CMakeLists.txt new file mode 100644 index 0000000000000..125a189a61b14 --- /dev/null +++ b/samples/bluetooth/bap_unicast_client/CMakeLists.txt @@ -0,0 +1,14 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bap_unicast_client) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_sources_ifdef(CONFIG_LIBLC3 src/stream_lc3.c) +zephyr_sources_ifdef(CONFIG_BT_AUDIO_TX src/stream_tx.c) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/public_broadcast_source/Kconfig.sysbuild b/samples/bluetooth/bap_unicast_client/Kconfig.sysbuild similarity index 100% rename from samples/bluetooth/public_broadcast_source/Kconfig.sysbuild rename to samples/bluetooth/bap_unicast_client/Kconfig.sysbuild diff --git a/samples/bluetooth/bap_unicast_client/README.rst b/samples/bluetooth/bap_unicast_client/README.rst new file mode 100644 index 0000000000000..f38cecd8dc2d0 --- /dev/null +++ b/samples/bluetooth/bap_unicast_client/README.rst @@ -0,0 +1,83 @@ +.. _bluetooth_bap_unicast_client: + +Bluetooth: Unicast Audio Client +############################### + +Overview +******** + +Application demonstrating the LE Audio unicast client functionality. Scans for and +connects to a LE Audio unicast server and establishes an audio stream. + +This sample can be found under +:zephyr_file:`samples/bluetooth/bap_unicast_client` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf52840dk +-------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_client/ + :board: nrf52840dk/nrf52840 + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_client/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_server/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf52_bsim +----------------------------------- + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_client/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf5340bsim +------------------------------------ + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_client/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild diff --git a/samples/bluetooth/unicast_audio_client/boards/native_sim.conf b/samples/bluetooth/bap_unicast_client/boards/native_sim.conf similarity index 100% rename from samples/bluetooth/unicast_audio_client/boards/native_sim.conf rename to samples/bluetooth/bap_unicast_client/boards/native_sim.conf diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf52_bsim.conf b/samples/bluetooth/bap_unicast_client/boards/nrf52_bsim.conf similarity index 100% rename from samples/bluetooth/unicast_audio_client/boards/nrf52_bsim.conf rename to samples/bluetooth/bap_unicast_client/boards/nrf52_bsim.conf diff --git a/samples/bluetooth/bap_unicast_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/bap_unicast_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..f28300b84c50e --- /dev/null +++ b/samples/bluetooth/bap_unicast_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -0,0 +1,13 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y +# The LC3 codec uses a large amount of stack. This app runs the decoding codec in the RX thread, +# hence increase the stack size for that thread. +CONFIG_BT_RX_STACK_SIZE=4096 + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf b/samples/bluetooth/bap_unicast_client/boards/nrf5340bsim_nrf5340_cpuapp.conf similarity index 100% rename from samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpuapp.conf rename to samples/bluetooth/bap_unicast_client/boards/nrf5340bsim_nrf5340_cpuapp.conf diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf b/samples/bluetooth/bap_unicast_client/boards/nrf5340bsim_nrf5340_cpunet.conf similarity index 100% rename from samples/bluetooth/unicast_audio_client/boards/nrf5340bsim_nrf5340_cpunet.conf rename to samples/bluetooth/bap_unicast_client/boards/nrf5340bsim_nrf5340_cpunet.conf diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/bap_unicast_client/boards/nrf5340dk_nrf5340_cpuapp.conf similarity index 100% rename from samples/bluetooth/unicast_audio_client/boards/nrf5340dk_nrf5340_cpuapp.conf rename to samples/bluetooth/bap_unicast_client/boards/nrf5340dk_nrf5340_cpuapp.conf diff --git a/samples/bluetooth/bap_unicast_client/overlay-bt_ll_sw_split.conf b/samples/bluetooth/bap_unicast_client/overlay-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..755e7fafa786f --- /dev/null +++ b/samples/bluetooth/bap_unicast_client/overlay-bt_ll_sw_split.conf @@ -0,0 +1,16 @@ +CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 +CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 +CONFIG_BT_CTLR_ISOAL_SOURCES=2 +CONFIG_BT_CTLR_ISOAL_SINKS=1 + +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 + +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y + +# Use the below if the sample is sending stale packet sequence number +# CONFIG_BT_CTLR_ISOAL_SN_STRICT=n diff --git a/samples/bluetooth/unicast_audio_client/prj.conf b/samples/bluetooth/bap_unicast_client/prj.conf similarity index 100% rename from samples/bluetooth/unicast_audio_client/prj.conf rename to samples/bluetooth/bap_unicast_client/prj.conf diff --git a/samples/bluetooth/unicast_audio_client/sample.yaml b/samples/bluetooth/bap_unicast_client/sample.yaml similarity index 100% rename from samples/bluetooth/unicast_audio_client/sample.yaml rename to samples/bluetooth/bap_unicast_client/sample.yaml diff --git a/samples/bluetooth/bap_unicast_client/src/main.c b/samples/bluetooth/bap_unicast_client/src/main.c new file mode 100644 index 0000000000000..cc8e5d7d6d8f3 --- /dev/null +++ b/samples/bluetooth/bap_unicast_client/src/main.c @@ -0,0 +1,941 @@ +/* + * Copyright (c) 2021-2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stream_tx.h" + +static void start_scan(void); + +uint64_t unicast_audio_recv_ctr; /* This value is exposed to test code */ + +static struct bt_bap_unicast_client_cb unicast_client_cbs; +static struct bt_conn *default_conn; +static struct bt_bap_unicast_group *unicast_group; +static struct audio_sink { + struct bt_bap_ep *ep; + uint16_t seq_num; +} sinks[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT]; +static struct bt_bap_ep *sources[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT]; + +static struct bt_bap_stream streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT + + CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT]; +static size_t configured_sink_stream_count; +static size_t configured_source_stream_count; + +#define configured_stream_count (configured_sink_stream_count + \ + configured_source_stream_count) + +/* Select a codec configuration to apply that is mandatory to support by both client and server. + * Allows this sample application to work without logic to parse the codec capabilities of the + * server and selection of an appropriate codec configuration. + */ +static struct bt_bap_lc3_preset codec_configuration = BT_BAP_LC3_UNICAST_PRESET_16_2_1( + BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); + +static K_SEM_DEFINE(sem_connected, 0, 1); +static K_SEM_DEFINE(sem_disconnected, 0, 1); +static K_SEM_DEFINE(sem_mtu_exchanged, 0, 1); +static K_SEM_DEFINE(sem_security_updated, 0, 1); +static K_SEM_DEFINE(sem_sinks_discovered, 0, 1); +static K_SEM_DEFINE(sem_sources_discovered, 0, 1); +static K_SEM_DEFINE(sem_stream_configured, 0, 1); +static K_SEM_DEFINE(sem_stream_qos, 0, ARRAY_SIZE(sinks) + ARRAY_SIZE(sources)); +static K_SEM_DEFINE(sem_stream_enabled, 0, 1); +static K_SEM_DEFINE(sem_stream_started, 0, 1); +static K_SEM_DEFINE(sem_stream_connected, 0, 1); + +static void print_hex(const uint8_t *ptr, size_t len) +{ + while (len-- != 0) { + printk("%02x", *ptr++); + } +} + +static bool print_cb(struct bt_data *data, void *user_data) +{ + const char *str = (const char *)user_data; + + printk("%s: type 0x%02x value_len %u\n", str, data->type, data->data_len); + print_hex(data->data, data->data_len); + printk("\n"); + + return true; +} + +static void print_codec_cap(const struct bt_audio_codec_cap *codec_cap) +{ + printk("codec id 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid, + codec_cap->vid, codec_cap->data_len); + + if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) { + bt_audio_data_parse(codec_cap->data, codec_cap->data_len, print_cb, "data"); + } else { /* If not LC3, we cannot assume it's LTV */ + printk("data: "); + print_hex(codec_cap->data, codec_cap->data_len); + printk("\n"); + } + + bt_audio_data_parse(codec_cap->meta, codec_cap->meta_len, print_cb, "meta"); +} + +static bool check_audio_support_and_connect(struct bt_data *data, + void *user_data) +{ + struct net_buf_simple ascs_svc_data; + bt_addr_le_t *addr = user_data; + uint8_t announcement_type; + uint32_t audio_contexts; + const struct bt_uuid *uuid; + uint16_t uuid_val; + uint8_t meta_len; + size_t min_size; + int err; + + printk("[AD]: %u data_len %u\n", data->type, data->data_len); + + if (data->type != BT_DATA_SVC_DATA16) { + return true; /* Continue parsing to next AD data type */ + } + + if (data->data_len < sizeof(uuid_val)) { + printk("AD invalid size %u\n", data->data_len); + return true; /* Continue parsing to next AD data type */ + } + + net_buf_simple_init_with_data(&ascs_svc_data, (void *)data->data, + data->data_len); + + uuid_val = net_buf_simple_pull_le16(&ascs_svc_data); + uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(uuid_val)); + if (bt_uuid_cmp(uuid, BT_UUID_ASCS) != 0) { + /* We are looking for the ASCS service data */ + return true; /* Continue parsing to next AD data type */ + } + + min_size = sizeof(announcement_type) + sizeof(audio_contexts) + sizeof(meta_len); + if (ascs_svc_data.len < min_size) { + printk("AD invalid size %u\n", data->data_len); + return false; /* Stop parsing */ + } + + announcement_type = net_buf_simple_pull_u8(&ascs_svc_data); + audio_contexts = net_buf_simple_pull_le32(&ascs_svc_data); + meta_len = net_buf_simple_pull_u8(&ascs_svc_data); + + err = bt_le_scan_stop(); + if (err != 0) { + printk("Failed to stop scan: %d\n", err); + return false; /* Stop parsing */ + } + + printk("Audio server found with type %u, contexts 0x%08x and meta_len %u; connecting\n", + announcement_type, audio_contexts, meta_len); + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, + BT_LE_CONN_PARAM_DEFAULT, + &default_conn); + if (err != 0) { + printk("Create conn to failed (%u)\n", err); + start_scan(); + } + + return false; /* Stop parsing */ +} + +static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, + struct net_buf_simple *ad) +{ + char addr_str[BT_ADDR_LE_STR_LEN]; + + if (default_conn != NULL) { + /* Already connected */ + return; + } + + /* We're only interested in connectable events */ + if (type != BT_GAP_ADV_TYPE_ADV_IND && + type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND && + type != BT_GAP_ADV_TYPE_EXT_ADV) { + return; + } + + (void)bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + printk("Device found: %s (RSSI %d)\n", addr_str, rssi); + + /* connect only to devices in close proximity */ + if (rssi < -50) { + return; + } + + bt_data_parse(ad, check_audio_support_and_connect, (void *)addr); +} + +static void start_scan(void) +{ + int err; + + /* This demo doesn't require active scan */ + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); + if (err != 0) { + printk("Scanning failed to start (err %d)\n", err); + return; + } + + printk("Scanning successfully started\n"); +} + +static void stream_configured(struct bt_bap_stream *stream, + const struct bt_audio_codec_qos_pref *pref) +{ + printk("Audio Stream %p configured\n", stream); + + k_sem_give(&sem_stream_configured); +} + +static void stream_qos_set(struct bt_bap_stream *stream) +{ + printk("Audio Stream %p QoS set\n", stream); + + k_sem_give(&sem_stream_qos); +} + +static void stream_enabled(struct bt_bap_stream *stream) +{ + printk("Audio Stream %p enabled\n", stream); + + k_sem_give(&sem_stream_enabled); +} + +static bool stream_is_tx(const struct bt_bap_stream *stream) +{ + struct bt_bap_ep_info info; + int err; + + if (stream == NULL || stream->ep == NULL) { + return false; + } + + err = bt_bap_ep_get_info(stream->ep, &info); + if (err != 0) { + return false; + } + + return info.can_send; +} + +static void stream_connected_cb(struct bt_bap_stream *stream) +{ + printk("Audio Stream %p connected\n", stream); + + /* Reset sequence number for sinks */ + for (size_t i = 0U; i < configured_sink_stream_count; i++) { + if (stream->ep == sinks[i].ep) { + sinks[i].seq_num = 0U; + break; + } + } + + k_sem_give(&sem_stream_connected); +} + +static void stream_started(struct bt_bap_stream *stream) +{ + printk("Audio Stream %p started\n", stream); + /* Register the stream for TX if it can send */ + if (IS_ENABLED(CONFIG_BT_AUDIO_TX) && stream_is_tx(stream)) { + const int err = stream_tx_register(stream); + + if (err != 0) { + printk("Failed to register stream %p for TX: %d\n", stream, err); + } + } + + k_sem_give(&sem_stream_started); +} + +static void stream_metadata_updated(struct bt_bap_stream *stream) +{ + printk("Audio Stream %p metadata updated\n", stream); +} + +static void stream_disabled(struct bt_bap_stream *stream) +{ + printk("Audio Stream %p disabled\n", stream); +} + +static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason) +{ + printk("Audio Stream %p stopped with reason 0x%02X\n", stream, reason); + + /* Unregister the stream for TX if it can send */ + if (IS_ENABLED(CONFIG_BT_AUDIO_TX) && stream_is_tx(stream)) { + const int err = stream_tx_unregister(stream); + + if (err != 0) { + printk("Failed to unregister stream %p for TX: %d", stream, err); + } + } +} + +static void stream_released(struct bt_bap_stream *stream) +{ + printk("Audio Stream %p released\n", stream); +} + +static void stream_recv(struct bt_bap_stream *stream, + const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + if (info->flags & BT_ISO_FLAGS_VALID) { + unicast_audio_recv_ctr++; + printk("Incoming audio on stream %p len %u (%"PRIu64")\n", stream, buf->len, + unicast_audio_recv_ctr); + } +} + +static struct bt_bap_stream_ops stream_ops = { + .configured = stream_configured, + .qos_set = stream_qos_set, + .enabled = stream_enabled, + .started = stream_started, + .metadata_updated = stream_metadata_updated, + .disabled = stream_disabled, + .stopped = stream_stopped, + .released = stream_released, + .recv = stream_recv, + .connected = stream_connected_cb, +}; + +static void add_remote_source(struct bt_bap_ep *ep) +{ + for (size_t i = 0U; i < ARRAY_SIZE(sources); i++) { + if (sources[i] == NULL) { + printk("Source #%zu: ep %p\n", i, ep); + sources[i] = ep; + return; + } + } + + printk("Could not add source ep\n"); +} + +static void add_remote_sink(struct bt_bap_ep *ep) +{ + for (size_t i = 0U; i < ARRAY_SIZE(sinks); i++) { + if (sinks[i].ep == NULL) { + printk("Sink #%zu: ep %p\n", i, ep); + sinks[i].ep = ep; + return; + } + } + + printk("Could not add sink ep\n"); +} + +static void print_remote_codec_cap(const struct bt_audio_codec_cap *codec_cap, + enum bt_audio_dir dir) +{ + printk("codec_cap %p dir 0x%02x\n", codec_cap, dir); + + print_codec_cap(codec_cap); +} + +static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) +{ + if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) { + printk("Discovery failed: %d\n", err); + return; + } + + if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) { + printk("Discover sinks completed without finding any sink ASEs\n"); + } else { + printk("Discover sinks complete: err %d\n", err); + } + + k_sem_give(&sem_sinks_discovered); +} + +static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) +{ + if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) { + printk("Discovery failed: %d\n", err); + return; + } + + if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) { + printk("Discover sinks completed without finding any source ASEs\n"); + } else { + printk("Discover sources complete: err %d\n", err); + } + + k_sem_give(&sem_sources_discovered); +} + +static void connected(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (err != 0) { + printk("Failed to connect to %s (%u)\n", addr, err); + + bt_conn_unref(default_conn); + default_conn = NULL; + + start_scan(); + return; + } + + if (conn != default_conn) { + return; + } + + printk("Connected: %s\n", addr); + k_sem_give(&sem_connected); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != default_conn) { + return; + } + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); + + bt_conn_unref(default_conn); + default_conn = NULL; + + k_sem_give(&sem_disconnected); +} + +static void security_changed_cb(struct bt_conn *conn, bt_security_t level, + enum bt_security_err err) +{ + if (err == 0) { + k_sem_give(&sem_security_updated); + } else { + printk("Failed to set security level: %u", err); + } +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, + .security_changed = security_changed_cb +}; + +static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx) +{ + printk("MTU exchanged: %u/%u\n", tx, rx); + k_sem_give(&sem_mtu_exchanged); +} + +static struct bt_gatt_cb gatt_callbacks = { + .att_mtu_updated = att_mtu_updated, +}; + +static void unicast_client_location_cb(struct bt_conn *conn, + enum bt_audio_dir dir, + enum bt_audio_location loc) +{ + printk("dir %u loc %X\n", dir, loc); +} + +static void available_contexts_cb(struct bt_conn *conn, + enum bt_audio_context snk_ctx, + enum bt_audio_context src_ctx) +{ + printk("snk ctx %u src ctx %u\n", snk_ctx, src_ctx); +} + +static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, + const struct bt_audio_codec_cap *codec_cap) +{ + print_remote_codec_cap(codec_cap, dir); +} + +static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep) +{ + if (dir == BT_AUDIO_DIR_SOURCE) { + add_remote_source(ep); + } else if (dir == BT_AUDIO_DIR_SINK) { + add_remote_sink(ep); + } +} + +static struct bt_bap_unicast_client_cb unicast_client_cbs = { + .location = unicast_client_location_cb, + .available_contexts = available_contexts_cb, + .pac_record = pac_record_cb, + .endpoint = endpoint_cb, +}; + +static int init(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + printk("Bluetooth enable failed (err %d)\n", err); + return err; + } + + for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { + streams[i].ops = &stream_ops; + } + + bt_gatt_cb_register(&gatt_callbacks); + + if (IS_ENABLED(CONFIG_BT_AUDIO_TX)) { + stream_tx_init(); + } + + return 0; +} + +static int scan_and_connect(void) +{ + int err; + + start_scan(); + + err = k_sem_take(&sem_connected, K_FOREVER); + if (err != 0) { + printk("failed to take sem_connected (err %d)\n", err); + return err; + } + + err = k_sem_take(&sem_mtu_exchanged, K_FOREVER); + if (err != 0) { + printk("failed to take sem_mtu_exchanged (err %d)\n", err); + return err; + } + + err = bt_conn_set_security(default_conn, BT_SECURITY_L2); + if (err != 0) { + printk("failed to set security (err %d)\n", err); + return err; + } + + err = k_sem_take(&sem_security_updated, K_FOREVER); + if (err != 0) { + printk("failed to take sem_security_updated (err %d)\n", err); + return err; + } + + return 0; +} + +static int discover_sinks(void) +{ + int err; + + unicast_client_cbs.discover = discover_sinks_cb; + + err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SINK); + if (err != 0) { + printk("Failed to discover sinks: %d\n", err); + return err; + } + + err = k_sem_take(&sem_sinks_discovered, K_FOREVER); + if (err != 0) { + printk("failed to take sem_sinks_discovered (err %d)\n", err); + return err; + } + + return 0; +} + +static int discover_sources(void) +{ + int err; + + unicast_client_cbs.discover = discover_sources_cb; + + err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SOURCE); + if (err != 0) { + printk("Failed to discover sources: %d\n", err); + return err; + } + + err = k_sem_take(&sem_sources_discovered, K_FOREVER); + if (err != 0) { + printk("failed to take sem_sources_discovered (err %d)\n", err); + return err; + } + + return 0; +} + +static int configure_stream(struct bt_bap_stream *stream, struct bt_bap_ep *ep) +{ + int err; + + err = bt_bap_stream_config(default_conn, stream, ep, &codec_configuration.codec_cfg); + if (err != 0) { + return err; + } + + err = k_sem_take(&sem_stream_configured, K_FOREVER); + if (err != 0) { + printk("failed to take sem_stream_configured (err %d)\n", err); + return err; + } + + return 0; +} + +static int configure_streams(void) +{ + int err; + + for (size_t i = 0; i < ARRAY_SIZE(sinks); i++) { + struct bt_bap_ep *ep = sinks[i].ep; + struct bt_bap_stream *stream = &streams[i]; + + if (ep == NULL) { + continue; + } + + err = configure_stream(stream, ep); + if (err != 0) { + printk("Could not configure sink stream[%zu]: %d\n", + i, err); + return err; + } + + printk("Configured sink stream[%zu]\n", i); + configured_sink_stream_count++; + } + + for (size_t i = 0; i < ARRAY_SIZE(sources); i++) { + struct bt_bap_ep *ep = sources[i]; + struct bt_bap_stream *stream = &streams[i + configured_sink_stream_count]; + + if (ep == NULL) { + continue; + } + + err = configure_stream(stream, ep); + if (err != 0) { + printk("Could not configure source stream[%zu]: %d\n", + i, err); + return err; + } + + printk("Configured source stream[%zu]\n", i); + configured_source_stream_count++; + } + + return 0; +} + +static int create_group(void) +{ + const size_t params_count = MAX(configured_sink_stream_count, + configured_source_stream_count); + struct bt_bap_unicast_group_stream_pair_param pair_params[params_count]; + struct bt_bap_unicast_group_stream_param stream_params[configured_stream_count]; + struct bt_bap_unicast_group_param param; + int err; + + for (size_t i = 0U; i < configured_stream_count; i++) { + stream_params[i].stream = &streams[i]; + stream_params[i].qos = &codec_configuration.qos; + } + + for (size_t i = 0U; i < params_count; i++) { + if (i < configured_sink_stream_count) { + pair_params[i].tx_param = &stream_params[i]; + } else { + pair_params[i].tx_param = NULL; + } + + if (i < configured_source_stream_count) { + pair_params[i].rx_param = &stream_params[i + configured_sink_stream_count]; + } else { + pair_params[i].rx_param = NULL; + } + } + + param.params = pair_params; + param.params_count = params_count; + param.packing = BT_ISO_PACKING_SEQUENTIAL; + + err = bt_bap_unicast_group_create(¶m, &unicast_group); + if (err != 0) { + printk("Could not create unicast group (err %d)\n", err); + return err; + } + + return 0; +} + +static int delete_group(void) +{ + int err; + + err = bt_bap_unicast_group_delete(unicast_group); + if (err != 0) { + printk("Could not create unicast group (err %d)\n", err); + return err; + } + + return 0; +} + +static int set_stream_qos(void) +{ + int err; + + err = bt_bap_stream_qos(default_conn, unicast_group); + if (err != 0) { + printk("Unable to setup QoS: %d\n", err); + return err; + } + + for (size_t i = 0U; i < configured_stream_count; i++) { + printk("QoS: waiting for %zu streams\n", configured_stream_count); + err = k_sem_take(&sem_stream_qos, K_FOREVER); + if (err != 0) { + printk("failed to take sem_stream_qos (err %d)\n", err); + return err; + } + } + + return 0; +} + +static int enable_streams(void) +{ + for (size_t i = 0U; i < configured_stream_count; i++) { + int err; + + err = bt_bap_stream_enable(&streams[i], codec_configuration.codec_cfg.meta, + codec_configuration.codec_cfg.meta_len); + if (err != 0) { + printk("Unable to enable stream: %d\n", err); + return err; + } + + err = k_sem_take(&sem_stream_enabled, K_FOREVER); + if (err != 0) { + printk("failed to take sem_stream_enabled (err %d)\n", err); + return err; + } + } + + return 0; +} + +static int connect_streams(void) +{ + for (size_t i = 0U; i < configured_stream_count; i++) { + int err; + + k_sem_reset(&sem_stream_connected); + + err = bt_bap_stream_connect(&streams[i]); + if (err == -EALREADY) { + /* We have already connected a paired stream */ + continue; + } else if (err != 0) { + printk("Unable to start stream: %d\n", err); + return err; + } + + err = k_sem_take(&sem_stream_connected, K_FOREVER); + if (err != 0) { + printk("failed to take sem_stream_connected (err %d)\n", err); + return err; + } + } + + return 0; +} + +static enum bt_audio_dir stream_dir(const struct bt_bap_stream *stream) +{ + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(stream->ep, &ep_info); + if (err != 0) { + printk("Failed to get ep info for %p: %d\n", stream, err); + __ASSERT_NO_MSG(false); + + return 0; + } + + return ep_info.dir; +} + +static int start_streams(void) +{ + for (size_t i = 0U; i < configured_stream_count; i++) { + struct bt_bap_stream *stream = &streams[i]; + int err; + + if (stream_dir(stream) == BT_AUDIO_DIR_SOURCE) { + err = bt_bap_stream_start(&streams[i]); + if (err != 0) { + printk("Unable to start stream: %d\n", err); + return err; + } + } /* Sink streams are started by the unicast server */ + + err = k_sem_take(&sem_stream_started, K_FOREVER); + if (err != 0) { + printk("failed to take sem_stream_started (err %d)\n", err); + return err; + } + } + + return 0; +} + +static void reset_data(void) +{ + k_sem_reset(&sem_connected); + k_sem_reset(&sem_disconnected); + k_sem_reset(&sem_mtu_exchanged); + k_sem_reset(&sem_security_updated); + k_sem_reset(&sem_sinks_discovered); + k_sem_reset(&sem_sources_discovered); + k_sem_reset(&sem_stream_configured); + k_sem_reset(&sem_stream_qos); + k_sem_reset(&sem_stream_enabled); + k_sem_reset(&sem_stream_started); + k_sem_reset(&sem_stream_connected); + + configured_sink_stream_count = 0; + configured_source_stream_count = 0; + memset(sinks, 0, sizeof(sinks)); + memset(sources, 0, sizeof(sources)); +} + +int main(void) +{ + int err; + + printk("Initializing\n"); + err = init(); + if (err != 0) { + return 0; + } + printk("Initialized\n"); + + err = bt_bap_unicast_client_register_cb(&unicast_client_cbs); + if (err != 0) { + printk("Failed to register client callbacks: %d", err); + return 0; + } + + while (true) { + reset_data(); + + printk("Waiting for connection\n"); + err = scan_and_connect(); + if (err != 0) { + return 0; + } + printk("Connected\n"); + + printk("Discovering sinks\n"); + err = discover_sinks(); + if (err != 0) { + return 0; + } + printk("Sinks discovered\n"); + + printk("Discovering sources\n"); + err = discover_sources(); + if (err != 0) { + return 0; + } + printk("Sources discovered\n"); + + printk("Configuring streams\n"); + err = configure_streams(); + if (err != 0) { + return 0; + } + + if (configured_stream_count == 0U) { + printk("No streams were configured\n"); + return 0; + } + + printk("Creating unicast group\n"); + err = create_group(); + if (err != 0) { + return 0; + } + printk("Unicast group created\n"); + + printk("Setting stream QoS\n"); + err = set_stream_qos(); + if (err != 0) { + return 0; + } + printk("Stream QoS Set\n"); + + printk("Enabling streams\n"); + err = enable_streams(); + if (err != 0) { + return 0; + } + printk("Streams enabled\n"); + + printk("Connecting streams\n"); + err = connect_streams(); + if (err != 0) { + return 0; + } + printk("Streams connected\n"); + + printk("Starting streams\n"); + err = start_streams(); + if (err != 0) { + return 0; + } + printk("Streams started\n"); + + /* Wait for disconnect */ + err = k_sem_take(&sem_disconnected, K_FOREVER); + if (err != 0) { + printk("failed to take sem_disconnected (err %d)\n", err); + return 0; + } + + printk("Deleting group\n"); + err = delete_group(); + if (err != 0) { + return 0; + } + printk("Group deleted\n"); + } +} diff --git a/samples/bluetooth/bap_unicast_client/src/stream_lc3.c b/samples/bluetooth/bap_unicast_client/src/stream_lc3.c new file mode 100644 index 0000000000000..fd8c0a1fcd178 --- /dev/null +++ b/samples/bluetooth/bap_unicast_client/src/stream_lc3.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "stream_lc3.h" +#include "stream_tx.h" + +LOG_MODULE_REGISTER(lc3, LOG_LEVEL_INF); + +#define LC3_MAX_SAMPLE_RATE 48000U +#define LC3_MAX_FRAME_DURATION_US 10000U +#define LC3_MAX_NUM_SAMPLES ((LC3_MAX_FRAME_DURATION_US * LC3_MAX_SAMPLE_RATE) / USEC_PER_SEC) +/* codec does clipping above INT16_MAX - 3000 */ +#define AUDIO_VOLUME (INT16_MAX - 3000) +#define AUDIO_TONE_FREQUENCY_HZ 400 + +static int16_t audio_buf[LC3_MAX_NUM_SAMPLES]; +/** + * Use the math lib to generate a sine-wave using 16 bit samples into a buffer. + * + * @param stream The TX stream to generate and fill the sine wave for + */ +static void fill_audio_buf_sin(struct tx_stream *stream) +{ + const unsigned int num_samples = + (stream->lc3_tx.frame_duration_us * stream->lc3_tx.freq_hz) / USEC_PER_SEC; + const int sine_period_samples = stream->lc3_tx.freq_hz / AUDIO_TONE_FREQUENCY_HZ; + const float step = 2 * 3.1415f / sine_period_samples; + + for (unsigned int i = 0; i < num_samples; i++) { + const float sample = sinf(i * step); + + audio_buf[i] = (int16_t)(AUDIO_VOLUME * sample); + } +} + +static int extract_lc3_config(struct tx_stream *stream) +{ + const struct bt_audio_codec_cfg *codec_cfg = stream->bap_stream->codec_cfg; + struct stream_lc3_tx *lc3_tx = &stream->lc3_tx; + int ret; + + LOG_INF("Extracting LC3 configuration values"); + + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret >= 0) { + ret = bt_audio_codec_cfg_freq_to_freq_hz(ret); + if (ret > 0) { + if (LC3_CHECK_SR_HZ(ret)) { + lc3_tx->freq_hz = (uint32_t)ret; + } else { + LOG_ERR("Unsupported sampling frequency for LC3: %d", ret); + + return ret; + } + } else { + LOG_ERR("Invalid frequency: %d", ret); + + return ret; + } + } else { + LOG_ERR("Could not get frequency: %d", ret); + + return ret; + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret >= 0) { + ret = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + if (ret > 0) { + if (LC3_CHECK_DT_US(ret)) { + lc3_tx->frame_duration_us = (uint32_t)ret; + } else { + LOG_ERR("Unsupported frame duration for LC3: %d", ret); + + return ret; + } + } else { + LOG_ERR("Invalid frame duration: %d", ret); + + return ret; + } + } else { + LOG_ERR("Could not get frame duration: %d", ret); + + return ret; + } + + ret = bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &lc3_tx->chan_allocation, false); + if (ret != 0) { + LOG_DBG("Could not get channel allocation: %d", ret); + lc3_tx->chan_allocation = BT_AUDIO_LOCATION_MONO_AUDIO; + } + + lc3_tx->chan_cnt = bt_audio_get_chan_count(lc3_tx->chan_allocation); + + ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true); + if (ret >= 0) { + lc3_tx->frame_blocks_per_sdu = (uint8_t)ret; + } + + ret = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); + if (ret >= 0) { + lc3_tx->octets_per_frame = (uint16_t)ret; + } else { + LOG_ERR("Could not get octets per frame: %d", ret); + + return ret; + } + + return 0; +} + +static bool encode_frame(struct tx_stream *stream, uint8_t index, struct net_buf *out_buf) +{ + const uint16_t octets_per_frame = stream->lc3_tx.octets_per_frame; + int lc3_ret; + + /* Generate sine wave */ + fill_audio_buf_sin(stream); + + lc3_ret = lc3_encode(stream->lc3_tx.encoder, LC3_PCM_FORMAT_S16, audio_buf, 1, + octets_per_frame, net_buf_tail(out_buf)); + if (lc3_ret < 0) { + LOG_ERR("LC3 encoder failed - wrong parameters?: %d", lc3_ret); + + return false; + } + + out_buf->len += octets_per_frame; + + return true; +} + +static bool encode_frame_block(struct tx_stream *stream, struct net_buf *out_buf) +{ + for (uint8_t i = 0U; i < stream->lc3_tx.chan_cnt; i++) { + /* We provide the total number of decoded frames to `decode_frame` for logging + * purposes + */ + if (!encode_frame(stream, i, out_buf)) { + return false; + } + } + + return true; +} + +void stream_lc3_add_data(struct tx_stream *stream, struct net_buf *buf) +{ + for (uint8_t i = 0U; i < stream->lc3_tx.frame_blocks_per_sdu; i++) { + if (!encode_frame_block(stream, buf)) { + break; + } + } +} + +int stream_lc3_init(struct tx_stream *stream) +{ + int err; + + err = extract_lc3_config(stream); + if (err != 0) { + memset(&stream->lc3_tx, 0, sizeof(stream->lc3_tx)); + + return err; + } + + /* Fill audio buffer with Sine wave only once and repeat encoding the same tone frame */ + LOG_INF("Initializing sine wave data"); + fill_audio_buf_sin(stream); + + LOG_INF("Setting up LC3 encoder"); + stream->lc3_tx.encoder = + lc3_setup_encoder(stream->lc3_tx.frame_duration_us, stream->lc3_tx.freq_hz, 0, + &stream->lc3_tx.encoder_mem); + + if (stream->lc3_tx.encoder == NULL) { + LOG_ERR("Failed to setup LC3 encoder"); + + memset(&stream->lc3_tx, 0, sizeof(stream->lc3_tx)); + + return -ENOEXEC; + } + + return 0; +} diff --git a/samples/bluetooth/bap_unicast_client/src/stream_lc3.h b/samples/bluetooth/bap_unicast_client/src/stream_lc3.h new file mode 100644 index 0000000000000..28e921e7e05aa --- /dev/null +++ b/samples/bluetooth/bap_unicast_client/src/stream_lc3.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef STREAM_LC3_H +#define STREAM_LC3_H + +#include + +#include +#include +#include + +/* Since the lc3.h header file is not available when CONFIG_LIBLC3=n, we need to guard the include + * and use of it + */ +#if defined(CONFIG_LIBLC3) +/* Header file for the liblc3 */ +#include + +struct stream_lc3_tx { + uint32_t freq_hz; + uint32_t frame_duration_us; + uint16_t octets_per_frame; + uint8_t frame_blocks_per_sdu; + uint8_t chan_cnt; + enum bt_audio_location chan_allocation; + lc3_encoder_t encoder; + lc3_encoder_mem_48k_t encoder_mem; +}; +#endif /* CONFIG_LIBLC3 */ + +/* Opaque definition to avoid including stream_tx.h */ +struct tx_stream; + +/* + * @brief Initialize LC3 encoder for a stream + * + * This will initialize the encoder for the provided TX stream + */ +int stream_lc3_init(struct tx_stream *stream); + +/** + * Add LC3 encoded data to the provided buffer from the provided stream + * + * @param stream The TX stream to add data from + * @param buf The buffer to store the encoded audio data in + */ +void stream_lc3_add_data(struct tx_stream *stream, struct net_buf *buf); + +#endif /* STREAM_LC3_H */ diff --git a/samples/bluetooth/bap_unicast_client/src/stream_tx.c b/samples/bluetooth/bap_unicast_client/src/stream_tx.c new file mode 100644 index 0000000000000..91f668db17a1b --- /dev/null +++ b/samples/bluetooth/bap_unicast_client/src/stream_tx.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stream_lc3.h" +#include "stream_tx.h" + +LOG_MODULE_REGISTER(stream_tx, LOG_LEVEL_INF); + +static struct tx_stream tx_streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT]; + +static bool stream_is_streaming(const struct bt_bap_stream *bap_stream) +{ + struct bt_bap_ep_info ep_info; + int err; + + if (bap_stream == NULL) { + return false; + } + + /* No-op if stream is not configured */ + if (bap_stream->ep == NULL) { + return false; + } + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err != 0) { + false; + } + + return ep_info.state == BT_BAP_EP_STATE_STREAMING; +} + +static void tx_thread_func(void *arg1, void *arg2, void *arg3) +{ + NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + static uint8_t mock_data[CONFIG_BT_ISO_TX_MTU]; + + for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) { + mock_data[i] = (uint8_t)i; + } + + /* This loop will attempt to send on all streams in the streaming state in a round robin + * fashion. + * The TX is controlled by the number of buffers configured, and increasing + * CONFIG_BT_ISO_TX_BUF_COUNT will allow for more streams in parallel, or to submit more + * buffers per stream. + * Once a buffer has been freed by the stack, it triggers the next TX. + */ + while (true) { + int err = -ENOEXEC; + + for (size_t i = 0U; i < ARRAY_SIZE(tx_streams); i++) { + struct bt_bap_stream *bap_stream = tx_streams[i].bap_stream; + + if (stream_is_streaming(bap_stream)) { + struct net_buf *buf; + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + + if (IS_ENABLED(CONFIG_LIBLC3) && + bap_stream->codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { + stream_lc3_add_data(&tx_streams[i], buf); + } else { + net_buf_add_mem(buf, mock_data, bap_stream->qos->sdu); + } + + err = bt_bap_stream_send(bap_stream, buf, tx_streams[i].seq_num); + if (err == 0) { + tx_streams[i].seq_num++; + } else { + LOG_ERR("Unable to send: %d", err); + net_buf_unref(buf); + } + } /* No-op if stream is not streaming */ + } + + if (err != 0) { + /* In case of any errors, retry with a delay */ + k_sleep(K_MSEC(10)); + } + } +} + +int stream_tx_register(struct bt_bap_stream *bap_stream) +{ + if (bap_stream == NULL) { + return -EINVAL; + } + + for (size_t i = 0U; i < ARRAY_SIZE(tx_streams); i++) { + if (tx_streams[i].bap_stream == NULL) { + tx_streams[i].bap_stream = bap_stream; + tx_streams[i].seq_num = 0U; + + if (IS_ENABLED(CONFIG_LIBLC3) && + bap_stream->codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { + const int err = stream_lc3_init(&tx_streams[i]); + + if (err != 0) { + tx_streams[i].bap_stream = NULL; + + return err; + } + } + + LOG_INF("Registered %p for TX", bap_stream); + + return 0; + } + } + + return -ENOMEM; +} + +int stream_tx_unregister(struct bt_bap_stream *bap_stream) +{ + if (bap_stream == NULL) { + return -EINVAL; + } + + for (size_t i = 0U; i < ARRAY_SIZE(tx_streams); i++) { + if (tx_streams[i].bap_stream == bap_stream) { + tx_streams[i].bap_stream = NULL; + + LOG_INF("Unregistered %p for TX", bap_stream); + + return 0; + } + } + + return -ENODATA; +} + +void stream_tx_init(void) +{ + static bool thread_started; + + if (!thread_started) { + static K_KERNEL_STACK_DEFINE(tx_thread_stack, + IS_ENABLED(CONFIG_LIBLC3) ? 4096U : 1024U); + const int tx_thread_prio = K_PRIO_PREEMPT(5); + static struct k_thread tx_thread; + + k_thread_create(&tx_thread, tx_thread_stack, K_KERNEL_STACK_SIZEOF(tx_thread_stack), + tx_thread_func, NULL, NULL, NULL, tx_thread_prio, 0, K_NO_WAIT); + k_thread_name_set(&tx_thread, "TX thread"); + thread_started = true; + } +} diff --git a/samples/bluetooth/bap_unicast_client/src/stream_tx.h b/samples/bluetooth/bap_unicast_client/src/stream_tx.h new file mode 100644 index 0000000000000..d5b17ccc796b3 --- /dev/null +++ b/samples/bluetooth/bap_unicast_client/src/stream_tx.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef STREAM_TX_H +#define STREAM_TX_H + +#include +#include +#include +#include + +#include "stream_lc3.h" + +struct tx_stream { + struct bt_bap_stream *bap_stream; + uint16_t seq_num; + +#if defined(CONFIG_LIBLC3) + struct stream_lc3_tx lc3_tx; +#endif /* CONFIG_LIBLC3 */ +}; + +/** + * @brief Initialize TX + * + * This will initialize TX if not already initialized. This creates and starts a thread that + * will attempt to send data on all streams registered with stream_tx_register(). + */ +void stream_tx_init(void); + +/** + * @brief Register a stream for TX + * + * This will add it to the list of streams the TX thread will attempt to send on. + * + * @retval 0 on success + * @retval -EINVAL if @p bap_stream is NULL + * @retval -EINVAL if @p bap_stream.codec_cfg contains invalid values + * @retval -ENOEXEC if the LC3 encoder failed to initialize + * @retval -ENOMEM if not more streams can be registered + */ +int stream_tx_register(struct bt_bap_stream *bap_stream); + +/** + * @brief Unregister a stream for TX + * + * This will remove it to the list of streams the TX thread will attempt to send on. + * + * @retval 0 on success + * @retval -EINVAL if @p bap_stream is NULL + * @retval -EALREADY if the stream is currently not registered + */ +int stream_tx_unregister(struct bt_bap_stream *bap_stream); + +#endif /* STREAM_TX_H */ diff --git a/samples/bluetooth/public_broadcast_sink/sysbuild.cmake b/samples/bluetooth/bap_unicast_client/sysbuild.cmake similarity index 100% rename from samples/bluetooth/public_broadcast_sink/sysbuild.cmake rename to samples/bluetooth/bap_unicast_client/sysbuild.cmake diff --git a/samples/bluetooth/bap_unicast_server/CMakeLists.txt b/samples/bluetooth/bap_unicast_server/CMakeLists.txt new file mode 100644 index 0000000000000..66649d87a33c8 --- /dev/null +++ b/samples/bluetooth/bap_unicast_server/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(bap_unicast_server) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/unicast_audio_client/Kconfig.sysbuild b/samples/bluetooth/bap_unicast_server/Kconfig.sysbuild similarity index 100% rename from samples/bluetooth/unicast_audio_client/Kconfig.sysbuild rename to samples/bluetooth/bap_unicast_server/Kconfig.sysbuild diff --git a/samples/bluetooth/bap_unicast_server/README.rst b/samples/bluetooth/bap_unicast_server/README.rst new file mode 100644 index 0000000000000..d7f3b8b277657 --- /dev/null +++ b/samples/bluetooth/bap_unicast_server/README.rst @@ -0,0 +1,83 @@ +.. _bluetooth_bap_unicast_server: + +Bluetooth: Unicast Audio Server +############################### + +Overview +******** + +Application demonstrating the LE Audio unicast server functionality. +Starts advertising and awaits connection from a LE Audio unicast client. + +This sample can be found under +:zephyr_file:`samples/bluetooth/bap_unicast_server` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf52840dk +-------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_server/ + :board: nrf52840dk/nrf52840 + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_server/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_server/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf52_bsim +----------------------------------- + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_server/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf5340bsim +------------------------------------ + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/bap_unicast_server/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild diff --git a/samples/bluetooth/unicast_audio_server/boards/native_sim.conf b/samples/bluetooth/bap_unicast_server/boards/native_sim.conf similarity index 100% rename from samples/bluetooth/unicast_audio_server/boards/native_sim.conf rename to samples/bluetooth/bap_unicast_server/boards/native_sim.conf diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf52_bsim.conf b/samples/bluetooth/bap_unicast_server/boards/nrf52_bsim.conf similarity index 100% rename from samples/bluetooth/unicast_audio_server/boards/nrf52_bsim.conf rename to samples/bluetooth/bap_unicast_server/boards/nrf52_bsim.conf diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpuapp.conf b/samples/bluetooth/bap_unicast_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf similarity index 100% rename from samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpuapp.conf rename to samples/bluetooth/bap_unicast_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf diff --git a/samples/bluetooth/bap_unicast_server/boards/nrf5340bsim_nrf5340_cpuapp.conf b/samples/bluetooth/bap_unicast_server/boards/nrf5340bsim_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..7c6a3aecc2687 --- /dev/null +++ b/samples/bluetooth/bap_unicast_server/boards/nrf5340bsim_nrf5340_cpuapp.conf @@ -0,0 +1,10 @@ +# For LC3 the following configs are needed +CONFIG_FPU=y +CONFIG_LIBLC3=y + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpunet.conf b/samples/bluetooth/bap_unicast_server/boards/nrf5340bsim_nrf5340_cpunet.conf similarity index 100% rename from samples/bluetooth/unicast_audio_server/boards/nrf5340bsim_nrf5340_cpunet.conf rename to samples/bluetooth/bap_unicast_server/boards/nrf5340bsim_nrf5340_cpunet.conf diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/bap_unicast_server/boards/nrf5340dk_nrf5340_cpuapp.conf similarity index 100% rename from samples/bluetooth/unicast_audio_server/boards/nrf5340dk_nrf5340_cpuapp.conf rename to samples/bluetooth/bap_unicast_server/boards/nrf5340dk_nrf5340_cpuapp.conf diff --git a/samples/bluetooth/bap_unicast_server/overlay-bt_ll_sw_split.conf b/samples/bluetooth/bap_unicast_server/overlay-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..8c6d99253a6b8 --- /dev/null +++ b/samples/bluetooth/bap_unicast_server/overlay-bt_ll_sw_split.conf @@ -0,0 +1,14 @@ +CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 +CONFIG_BT_CTLR_ISO_TX_BUFFERS=2 +CONFIG_BT_CTLR_ISOAL_SOURCES=1 +CONFIG_BT_CTLR_ISOAL_SINKS=2 + +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 + +# Use the below if the sample is sending stale packet sequence number +# CONFIG_BT_CTLR_ADVANCED_FEATURES=y +# CONFIG_BT_CTLR_ISOAL_SN_STRICT=n diff --git a/samples/bluetooth/unicast_audio_server/prj.conf b/samples/bluetooth/bap_unicast_server/prj.conf similarity index 100% rename from samples/bluetooth/unicast_audio_server/prj.conf rename to samples/bluetooth/bap_unicast_server/prj.conf diff --git a/samples/bluetooth/unicast_audio_server/sample.yaml b/samples/bluetooth/bap_unicast_server/sample.yaml similarity index 100% rename from samples/bluetooth/unicast_audio_server/sample.yaml rename to samples/bluetooth/bap_unicast_server/sample.yaml diff --git a/samples/bluetooth/bap_unicast_server/src/main.c b/samples/bluetooth/bap_unicast_server/src/main.c new file mode 100644 index 0000000000000..7763484d1a5a7 --- /dev/null +++ b/samples/bluetooth/bap_unicast_server/src/main.c @@ -0,0 +1,795 @@ +/* + * Copyright (c) 2021-2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define AVAILABLE_SINK_CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \ + BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ + BT_AUDIO_CONTEXT_TYPE_MEDIA | \ + BT_AUDIO_CONTEXT_TYPE_GAME | \ + BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL) + +#define AVAILABLE_SOURCE_CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \ + BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ + BT_AUDIO_CONTEXT_TYPE_MEDIA | \ + BT_AUDIO_CONTEXT_TYPE_GAME) + +NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ASCS_ASE_SRC_COUNT, + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +static const struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3( + BT_AUDIO_CODEC_CAP_FREQ_ANY, BT_AUDIO_CODEC_CAP_DURATION_10, + BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1), 40u, 120u, 1u, + (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); + +static struct bt_conn *default_conn; +static struct k_work_delayable audio_send_work; +static struct bt_bap_stream sink_streams[CONFIG_BT_ASCS_ASE_SNK_COUNT]; +static struct audio_source { + struct bt_bap_stream stream; + uint16_t seq_num; + uint16_t max_sdu; + size_t len_to_send; +} source_streams[CONFIG_BT_ASCS_ASE_SRC_COUNT]; +static size_t configured_source_stream_count; + +static const struct bt_audio_codec_qos_pref qos_pref = + BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000); + +static K_SEM_DEFINE(sem_disconnected, 0, 1); + +static uint8_t unicast_server_addata[] = { + BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), /* ASCS UUID */ + BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, /* Target Announcement */ + BT_BYTES_LIST_LE16(AVAILABLE_SINK_CONTEXT), + BT_BYTES_LIST_LE16(AVAILABLE_SOURCE_CONTEXT), + 0x00, /* Metadata length */ +}; + +/* TODO: Expand with BAP data */ +static const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL)), + BT_DATA(BT_DATA_SVC_DATA16, unicast_server_addata, ARRAY_SIZE(unicast_server_addata)), + BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), +}; + +#define AUDIO_DATA_TIMEOUT_US 1000000UL /* Send data every 1 second */ +#define SDU_INTERVAL_US 10000UL /* 10 ms SDU interval */ + +static uint16_t get_and_incr_seq_num(const struct bt_bap_stream *stream) +{ + for (size_t i = 0U; i < configured_source_stream_count; i++) { + if (stream == &source_streams[i].stream) { + uint16_t seq_num; + + seq_num = source_streams[i].seq_num; + + if (IS_ENABLED(CONFIG_LIBLC3)) { + source_streams[i].seq_num++; + } else { + source_streams[i].seq_num += (AUDIO_DATA_TIMEOUT_US / + SDU_INTERVAL_US); + } + + return seq_num; + } + } + + printk("Could not find endpoint from stream %p\n", stream); + + return 0; +} + +#if defined(CONFIG_LIBLC3) + +#include "lc3.h" + +#define MAX_SAMPLE_RATE 48000 +#define MAX_FRAME_DURATION_US 10000 +#define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC) + +static int16_t audio_buf[MAX_NUM_SAMPLES]; +static lc3_decoder_t lc3_decoder; +static lc3_decoder_mem_48k_t lc3_decoder_mem; +static int frames_per_sdu; + +#endif + +void print_hex(const uint8_t *ptr, size_t len) +{ + while (len-- != 0) { + printk("%02x", *ptr++); + } +} + +static bool print_cb(struct bt_data *data, void *user_data) +{ + const char *str = (const char *)user_data; + + printk("%s: type 0x%02x value_len %u\n", str, data->type, data->data_len); + print_hex(data->data, data->data_len); + printk("\n"); + + return true; +} + +static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) +{ + printk("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid, + codec_cfg->vid, codec_cfg->data_len); + + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { + enum bt_audio_location chan_allocation; + int ret; + + /* LC3 uses the generic LTV format - other codecs might do as well */ + + bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, print_cb, "data"); + + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_freq_to_freq_hz(ret)); + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + printk(" Frame Duration: %d us\n", + bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); + } + + ret = bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, false); + if (ret == 0) { + printk(" Channel allocation: 0x%x\n", chan_allocation); + } + + printk(" Octets per frame: %d (negative means value not pressent)\n", + bt_audio_codec_cfg_get_octets_per_frame(codec_cfg)); + printk(" Frames per SDU: %d\n", + bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true)); + } else { + print_hex(codec_cfg->data, codec_cfg->data_len); + } + + bt_audio_data_parse(codec_cfg->meta, codec_cfg->meta_len, print_cb, "meta"); +} + +static void print_qos(const struct bt_audio_codec_qos *qos) +{ + printk("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u " + "rtn %u latency %u pd %u\n", + qos->interval, qos->framing, qos->phy, qos->sdu, + qos->rtn, qos->latency, qos->pd); +} + +/** + * @brief Send audio data on timeout + * + * This will send an increasing amount of audio data, starting from 1 octet. + * The data is just mock data, and does not actually represent any audio. + * + * First iteration : 0x00 + * Second iteration: 0x00 0x01 + * Third iteration : 0x00 0x01 0x02 + * + * And so on, until it wraps around the configured MTU (CONFIG_BT_ISO_TX_MTU) + * + * @param work Pointer to the work structure + */ +static void audio_timer_timeout(struct k_work *work) +{ + int ret; + static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU]; + static bool data_initialized; + struct net_buf *buf; + + if (!data_initialized) { + /* TODO: Actually encode some audio data */ + for (size_t i = 0U; i < ARRAY_SIZE(buf_data); i++) { + buf_data[i] = (uint8_t)i; + } + + data_initialized = true; + } + + /* We configured the sink streams to be first in `streams`, so that + * we can use `stream[i]` to select sink streams (i.e. streams with + * data going to the server) + */ + for (size_t i = 0; i < configured_source_stream_count; i++) { + struct bt_bap_stream *stream = &source_streams[i].stream; + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + + net_buf_add_mem(buf, buf_data, ++source_streams[i].len_to_send); + + ret = bt_bap_stream_send(stream, buf, get_and_incr_seq_num(stream)); + if (ret < 0) { + printk("Failed to send audio data on streams[%zu] (%p): (%d)\n", + i, stream, ret); + net_buf_unref(buf); + } else { + printk("Sending mock data with len %zu on streams[%zu] (%p)\n", + source_streams[i].len_to_send, i, stream); + } + + if (source_streams[i].len_to_send >= source_streams[i].max_sdu) { + source_streams[i].len_to_send = 0; + } + } + +#if defined(CONFIG_LIBLC3) + k_work_schedule(&audio_send_work, K_USEC(MAX_FRAME_DURATION_US)); +#else + k_work_schedule(&audio_send_work, K_USEC(AUDIO_DATA_TIMEOUT_US)); +#endif +} + +static enum bt_audio_dir stream_dir(const struct bt_bap_stream *stream) +{ + for (size_t i = 0U; i < ARRAY_SIZE(source_streams); i++) { + if (stream == &source_streams[i].stream) { + return BT_AUDIO_DIR_SOURCE; + } + } + + for (size_t i = 0U; i < ARRAY_SIZE(sink_streams); i++) { + if (stream == &sink_streams[i]) { + return BT_AUDIO_DIR_SINK; + } + } + + __ASSERT(false, "Invalid stream %p", stream); + return 0; +} + +static struct bt_bap_stream *stream_alloc(enum bt_audio_dir dir) +{ + if (dir == BT_AUDIO_DIR_SOURCE) { + for (size_t i = 0; i < ARRAY_SIZE(source_streams); i++) { + struct bt_bap_stream *stream = &source_streams[i].stream; + + if (!stream->conn) { + return stream; + } + } + } else { + for (size_t i = 0; i < ARRAY_SIZE(sink_streams); i++) { + struct bt_bap_stream *stream = &sink_streams[i]; + + if (!stream->conn) { + return stream; + } + } + } + + return NULL; +} + +static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir, + const struct bt_audio_codec_cfg *codec_cfg, struct bt_bap_stream **stream, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) +{ + printk("ASE Codec Config: conn %p ep %p dir %u\n", conn, ep, dir); + + print_codec_cfg(codec_cfg); + + *stream = stream_alloc(dir); + if (*stream == NULL) { + printk("No streams available\n"); + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM, BT_BAP_ASCS_REASON_NONE); + + return -ENOMEM; + } + + printk("ASE Codec Config stream %p\n", *stream); + + if (dir == BT_AUDIO_DIR_SOURCE) { + configured_source_stream_count++; + } + + *pref = qos_pref; + +#if defined(CONFIG_LIBLC3) + /* Nothing to free as static memory is used */ + lc3_decoder = NULL; +#endif + + return 0; +} + +static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir, + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) +{ + printk("ASE Codec Reconfig: stream %p\n", stream); + + print_codec_cfg(codec_cfg); + +#if defined(CONFIG_LIBLC3) + /* Nothing to free as static memory is used */ + lc3_decoder = NULL; +#endif + + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_UNSUPPORTED, BT_BAP_ASCS_REASON_NONE); + + /* We only support one QoS at the moment, reject changes */ + return -ENOEXEC; +} + +static int lc3_qos(struct bt_bap_stream *stream, const struct bt_audio_codec_qos *qos, + struct bt_bap_ascs_rsp *rsp) +{ + printk("QoS: stream %p qos %p\n", stream, qos); + + print_qos(qos); + + for (size_t i = 0U; i < configured_source_stream_count; i++) { + if (stream == &source_streams[i].stream) { + source_streams[i].max_sdu = qos->sdu; + break; + } + } + + return 0; +} + +static int lc3_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len, + struct bt_bap_ascs_rsp *rsp) +{ + printk("Enable: stream %p meta_len %zu\n", stream, meta_len); + +#if defined(CONFIG_LIBLC3) + { + int frame_duration_us; + int freq; + int ret; + + ret = bt_audio_codec_cfg_get_freq(stream->codec_cfg); + if (ret > 0) { + freq = bt_audio_codec_cfg_freq_to_freq_hz(ret); + } else { + printk("Error: Codec frequency not set, cannot start codec."); + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID, + BT_BAP_ASCS_REASON_CODEC_DATA); + return ret; + } + + ret = bt_audio_codec_cfg_get_frame_dur(stream->codec_cfg); + if (ret > 0) { + frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); + } else { + printk("Error: Frame duration not set, cannot start codec."); + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID, + BT_BAP_ASCS_REASON_CODEC_DATA); + return ret; + } + + frames_per_sdu = + bt_audio_codec_cfg_get_frame_blocks_per_sdu(stream->codec_cfg, true); + + lc3_decoder = lc3_setup_decoder(frame_duration_us, + freq, + 0, /* No resampling */ + &lc3_decoder_mem); + + if (lc3_decoder == NULL) { + printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n"); + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID, + BT_BAP_ASCS_REASON_CODEC_DATA); + return -1; + } + } +#endif + + return 0; +} + +static int lc3_start(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) +{ + printk("Start: stream %p\n", stream); + + for (size_t i = 0U; i < configured_source_stream_count; i++) { + if (stream == &source_streams[i].stream) { + source_streams[i].seq_num = 0U; + source_streams[i].len_to_send = 0U; + break; + } + } + + if (configured_source_stream_count > 0 && + !k_work_delayable_is_pending(&audio_send_work)) { + + /* Start send timer */ + k_work_schedule(&audio_send_work, K_MSEC(0)); + } + + return 0; +} + +static bool data_func_cb(struct bt_data *data, void *user_data) +{ + struct bt_bap_ascs_rsp *rsp = (struct bt_bap_ascs_rsp *)user_data; + + if (!BT_AUDIO_METADATA_TYPE_IS_KNOWN(data->type)) { + printk("Invalid metadata type %u or length %u\n", data->type, data->data_len); + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED, data->type); + + return -EINVAL; + } + + return true; +} + +static int lc3_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len, + struct bt_bap_ascs_rsp *rsp) +{ + printk("Metadata: stream %p meta_len %zu\n", stream, meta_len); + + return bt_audio_data_parse(meta, meta_len, data_func_cb, rsp); +} + +static int lc3_disable(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) +{ + printk("Disable: stream %p\n", stream); + + return 0; +} + +static int lc3_stop(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) +{ + printk("Stop: stream %p\n", stream); + + return 0; +} + +static int lc3_release(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) +{ + printk("Release: stream %p\n", stream); + return 0; +} + +static const struct bt_bap_unicast_server_cb unicast_server_cb = { + .config = lc3_config, + .reconfig = lc3_reconfig, + .qos = lc3_qos, + .enable = lc3_enable, + .start = lc3_start, + .metadata = lc3_metadata, + .disable = lc3_disable, + .stop = lc3_stop, + .release = lc3_release, +}; + + +#if defined(CONFIG_LIBLC3) + +static void stream_recv_lc3_codec(struct bt_bap_stream *stream, + const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + const uint8_t *in_buf; + uint8_t err = -1; + const int octets_per_frame = buf->len / frames_per_sdu; + + if (lc3_decoder == NULL) { + printk("LC3 decoder not setup, cannot decode data.\n"); + return; + } + + if ((info->flags & BT_ISO_FLAGS_VALID) == 0) { + printk("Bad packet: 0x%02X\n", info->flags); + + in_buf = NULL; + } else { + in_buf = buf->data; + } + + /* This code is to demonstrate the use of the LC3 codec. On an actual implementation + * it might be required to offload the processing to another task to avoid blocking the + * BT stack. + */ + for (int i = 0; i < frames_per_sdu; i++) { + + int offset = 0; + + err = lc3_decode(lc3_decoder, in_buf + offset, octets_per_frame, + LC3_PCM_FORMAT_S16, audio_buf, 1); + + if (in_buf != NULL) { + offset += octets_per_frame; + } + } + + printk("RX stream %p len %u\n", stream, buf->len); + + if (err == 1) { + printk(" decoder performed PLC\n"); + return; + + } else if (err < 0) { + printk(" decoder failed - wrong parameters?\n"); + return; + } +} + +#else + +static void stream_recv(struct bt_bap_stream *stream, + const struct bt_iso_recv_info *info, + struct net_buf *buf) +{ + if (info->flags & BT_ISO_FLAGS_VALID) { + printk("Incoming audio on stream %p len %u\n", stream, buf->len); + } +} + +#endif + +static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason) +{ + printk("Audio Stream %p stopped with reason 0x%02X\n", stream, reason); + + /* Stop send timer */ + k_work_cancel_delayable(&audio_send_work); +} + + +static void stream_enabled_cb(struct bt_bap_stream *stream) +{ + /* The unicast server is responsible for starting sink ASEs after the + * client has enabled them. + */ + if (stream_dir(stream) == BT_AUDIO_DIR_SINK) { + const int err = bt_bap_stream_start(stream); + + if (err != 0) { + printk("Failed to start stream %p: %d", stream, err); + } + } +} + +static struct bt_bap_stream_ops stream_ops = { +#if defined(CONFIG_LIBLC3) + .recv = stream_recv_lc3_codec, +#else + .recv = stream_recv, +#endif + .stopped = stream_stopped, + .enabled = stream_enabled_cb, +}; + +static void connected(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (err != 0) { + printk("Failed to connect to %s (%u)\n", addr, err); + + default_conn = NULL; + return; + } + + printk("Connected: %s\n", addr); + default_conn = bt_conn_ref(conn); +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != default_conn) { + return; + } + + bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); + + bt_conn_unref(default_conn); + default_conn = NULL; + + k_sem_give(&sem_disconnected); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected, + .disconnected = disconnected, +}; + +static struct bt_pacs_cap cap_sink = { + .codec_cap = &lc3_codec_cap, +}; + +static struct bt_pacs_cap cap_source = { + .codec_cap = &lc3_codec_cap, +}; + +static int set_location(void) +{ + int err; + + if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) { + err = bt_pacs_set_location(BT_AUDIO_DIR_SINK, + BT_AUDIO_LOCATION_FRONT_CENTER); + if (err != 0) { + printk("Failed to set sink location (err %d)\n", err); + return err; + } + } + + if (IS_ENABLED(CONFIG_BT_PAC_SRC_LOC)) { + err = bt_pacs_set_location(BT_AUDIO_DIR_SOURCE, + (BT_AUDIO_LOCATION_FRONT_LEFT | + BT_AUDIO_LOCATION_FRONT_RIGHT)); + if (err != 0) { + printk("Failed to set source location (err %d)\n", err); + return err; + } + } + + printk("Location successfully set\n"); + + return 0; +} + +static int set_supported_contexts(void) +{ + int err; + + if (IS_ENABLED(CONFIG_BT_PAC_SNK)) { + err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK, + AVAILABLE_SINK_CONTEXT); + if (err != 0) { + printk("Failed to set sink supported contexts (err %d)\n", + err); + + return err; + } + } + + if (IS_ENABLED(CONFIG_BT_PAC_SRC)) { + err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE, + AVAILABLE_SOURCE_CONTEXT); + if (err != 0) { + printk("Failed to set source supported contexts (err %d)\n", + err); + + return err; + } + } + + printk("Supported contexts successfully set\n"); + + return 0; +} + +static int set_available_contexts(void) +{ + int err; + + if (IS_ENABLED(CONFIG_BT_PAC_SNK)) { + err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK, + AVAILABLE_SINK_CONTEXT); + if (err != 0) { + printk("Failed to set sink available contexts (err %d)\n", err); + return err; + } + } + + if (IS_ENABLED(CONFIG_BT_PAC_SRC)) { + err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE, + AVAILABLE_SOURCE_CONTEXT); + if (err != 0) { + printk("Failed to set source available contexts (err %d)\n", err); + return err; + } + } + + printk("Available contexts successfully set\n"); + return 0; +} + +int main(void) +{ + struct bt_le_ext_adv *adv; + int err; + + err = bt_enable(NULL); + if (err != 0) { + printk("Bluetooth init failed (err %d)\n", err); + return 0; + } + + printk("Bluetooth initialized\n"); + + bt_bap_unicast_server_register_cb(&unicast_server_cb); + + bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink); + bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap_source); + + for (size_t i = 0; i < ARRAY_SIZE(sink_streams); i++) { + bt_bap_stream_cb_register(&sink_streams[i], &stream_ops); + } + + for (size_t i = 0; i < ARRAY_SIZE(source_streams); i++) { + bt_bap_stream_cb_register(&source_streams[i].stream, + &stream_ops); + } + + err = set_location(); + if (err != 0) { + return 0; + } + + err = set_supported_contexts(); + if (err != 0) { + return 0; + } + + err = set_available_contexts(); + if (err != 0) { + return 0; + } + + /* Create a connectable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &adv); + if (err) { + printk("Failed to create advertising set (err %d)\n", err); + return 0; + } + + err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0); + if (err) { + printk("Failed to set advertising data (err %d)\n", err); + return 0; + } + + while (true) { + struct k_work_sync sync; + + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err) { + printk("Failed to start advertising set (err %d)\n", err); + return 0; + } + + printk("Advertising successfully started\n"); + + if (CONFIG_BT_ASCS_ASE_SRC_COUNT > 0) { + /* Start send timer */ + k_work_init_delayable(&audio_send_work, audio_timer_timeout); + } + + err = k_sem_take(&sem_disconnected, K_FOREVER); + if (err != 0) { + printk("failed to take sem_disconnected (err %d)\n", err); + return 0; + } + + /* reset data */ + configured_source_stream_count = 0U; + k_work_cancel_delayable_sync(&audio_send_work, &sync); + + } + return 0; +} diff --git a/samples/bluetooth/unicast_audio_client/sysbuild.cmake b/samples/bluetooth/bap_unicast_server/sysbuild.cmake similarity index 100% rename from samples/bluetooth/unicast_audio_client/sysbuild.cmake rename to samples/bluetooth/bap_unicast_server/sysbuild.cmake diff --git a/samples/bluetooth/beacon/sample.yaml b/samples/bluetooth/beacon/sample.yaml index 9073de8c1fc0f..d76a16eb566f0 100644 --- a/samples/bluetooth/beacon/sample.yaml +++ b/samples/bluetooth/beacon/sample.yaml @@ -6,13 +6,20 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 + - nrf51dk/nrf51822 - nrf52dk/nrf52832 + - nrf54l15pdk/nrf54l15/cpuapp tags: bluetooth integration_platforms: - qemu_cortex_m3 - + - nrf51dk/nrf51822 + - nrf52dk/nrf52832 + - nrf54l15pdk/nrf54l15/cpuapp sample.bluetooth.beacon-coex: extra_args: CONF_FILE="prj-coex.conf" harness: bluetooth - platform_allow: nrf52840dk/nrf52840 + platform_allow: + - nrf52840dk/nrf52840 + integration_platforms: + - nrf52840dk/nrf52840 tags: bluetooth diff --git a/samples/bluetooth/broadcast_audio_assistant/CMakeLists.txt b/samples/bluetooth/broadcast_audio_assistant/CMakeLists.txt deleted file mode 100644 index 770ad7912f365..0000000000000 --- a/samples/bluetooth/broadcast_audio_assistant/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(broadcast_audio_assistant) - -target_sources(app PRIVATE - src/main.c -) - -zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/broadcast_audio_assistant/README.rst b/samples/bluetooth/broadcast_audio_assistant/README.rst deleted file mode 100644 index e0a7ec5a0126d..0000000000000 --- a/samples/bluetooth/broadcast_audio_assistant/README.rst +++ /dev/null @@ -1,56 +0,0 @@ -.. zephyr:code-sample:: bluetooth_broadcast_audio_assistant - :name: Bluetooth: Broadcast Audio Assistant - :relevant-api: bt_bap - - Use LE Audio Broadcast Assistant functionality - -Overview -******** - -Application demonstrating the LE Audio broadcast assistant functionality. - -The sample will automatically try to connect to a device in the BAP Scan Delegator -role (advertising support for the Broadcast Audio Scan Service (BASS)). -It will then search for a broadcast source and (if found) add the broadcast ID to -the BAP Scan Delegator. - -Practical use of this sample requires a sink (e.g. the Broadcast Audio Sink sample or -a set of LE Audio Broadcast capable earbuds) and a source (e.g. the Broadcast Audio -Source sample). - -This sample can be found under -:zephyr_file:`samples/bluetooth/broadcast_audio_assistant` in the Zephyr tree. - -Check the :ref:`bluetooth samples section ` for general information. - -Requirements -************ - -* BlueZ running on the host, or -* A board with Bluetooth Low Energy 5.2 support -* Broadcast Audio Source and Sink devices - -Building and Running -******************** - -The application will act as a broadcast assistant with optionally preconfigured -filtering of broadcast sink and broadcast source names. By default, the application will -search for and connect to the first broadcast audio sink found (advertising PACS and -BASS UUIDs) and then search for and select the first broadcast audio source found -(advertising a broadcast ID). - -Filter these by modifying the following configs: - -``CONFIG_SELECT_SINK_NAME``: Substring of BT name of the sink. - -and - -``CONFIG_SELECT_SOURCE_NAME``: Substring of BT name or broadcast name of the source. - -Building for an nrf52840dk --------------------------- - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/broadcast_audio_assistant/ - :board: nrf52840dk/nrf52840 - :goals: build diff --git a/samples/bluetooth/broadcast_audio_assistant/sample.yaml b/samples/bluetooth/broadcast_audio_assistant/sample.yaml deleted file mode 100644 index cc36702ac4d58..0000000000000 --- a/samples/bluetooth/broadcast_audio_assistant/sample.yaml +++ /dev/null @@ -1,11 +0,0 @@ -sample: - description: Bluetooth Low Energy Broadcast Assistant sample - name: Bluetooth Low Energy Broadcast Assistant sample -tests: - sample.bluetooth.broadcast_audio_assistant: - harness: bluetooth - platform_allow: - - nrf52840dk/nrf52840 - integration_platforms: - - nrf52840dk/nrf52840 - tags: bluetooth diff --git a/samples/bluetooth/broadcast_audio_assistant/src/main.c b/samples/bluetooth/broadcast_audio_assistant/src/main.c deleted file mode 100644 index 3c8bdf1de6985..0000000000000 --- a/samples/bluetooth/broadcast_audio_assistant/src/main.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Copyright (c) 2024 Demant A/S - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#define NAME_LEN 30 -#define PA_SYNC_SKIP 5 -#define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 20 /* Set the timeout relative to interval */ -/* Broadcast IDs are 24bit, so this is out of valid range */ -#define INVALID_BROADCAST_ID 0xFFFFFFFFU - -static void scan_for_broadcast_sink(void); - -/* Struct to collect information from scanning - * for Broadcast Source or Sink - */ -struct scan_recv_info { - char bt_name[NAME_LEN]; - char broadcast_name[NAME_LEN]; - uint32_t broadcast_id; - bool has_bass; - bool has_pacs; -}; - -static struct bt_conn *broadcast_sink_conn; -static uint32_t selected_broadcast_id; -static uint8_t selected_sid; -static uint16_t selected_pa_interval; -static bt_addr_le_t selected_addr; -static struct bt_le_per_adv_sync *pa_sync; -static uint8_t received_base[UINT8_MAX]; -static uint8_t received_base_size; -static struct bt_bap_bass_subgroup - bass_subgroups[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]; - -static bool scanning_for_broadcast_source; - -static struct k_mutex base_store_mutex; -static K_SEM_DEFINE(sem_source_discovered, 0, 1); -static K_SEM_DEFINE(sem_sink_discovered, 0, 1); -static K_SEM_DEFINE(sem_sink_connected, 0, 1); -static K_SEM_DEFINE(sem_sink_disconnected, 0, 1); -static K_SEM_DEFINE(sem_security_updated, 0, 1); -static K_SEM_DEFINE(sem_bass_discovered, 0, 1); -static K_SEM_DEFINE(sem_pa_synced, 0, 1); -static K_SEM_DEFINE(sem_received_base_subgroups, 0, 1); - -static bool device_found(struct bt_data *data, void *user_data) -{ - struct scan_recv_info *sr_info = (struct scan_recv_info *)user_data; - struct bt_uuid_16 adv_uuid; - - switch (data->type) { - case BT_DATA_NAME_SHORTENED: - case BT_DATA_NAME_COMPLETE: - memcpy(sr_info->bt_name, data->data, MIN(data->data_len, NAME_LEN - 1)); - return true; - case BT_DATA_BROADCAST_NAME: - memcpy(sr_info->broadcast_name, data->data, MIN(data->data_len, NAME_LEN - 1)); - return true; - case BT_DATA_SVC_DATA16: - /* Check for Broadcast ID */ - if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) { - return true; - } - - if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { - return true; - } - - if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO) != 0) { - return true; - } - - sr_info->broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); - return true; - case BT_DATA_UUID16_SOME: - case BT_DATA_UUID16_ALL: - /* NOTE: According to the BAP 1.0.1 Spec, - * Section 3.9.2. Additional Broadcast Audio Scan Service requirements, - * If the Scan Delegator implements a Broadcast Sink, it should also - * advertise a Service Data field containing the Broadcast Audio - * Scan Service (BASS) UUID. - * - * However, it seems that this is not the case with the sinks available - * while developing this sample application. Therefore, we instead, - * search for the existence of BASS and PACS in the list of service UUIDs, - * which does seem to exist in the sinks available. - */ - - /* Check for BASS and PACS */ - if (data->data_len % sizeof(uint16_t) != 0U) { - printk("UUID16 AD malformed\n"); - return true; - } - - for (size_t i = 0; i < data->data_len; i += sizeof(uint16_t)) { - const struct bt_uuid *uuid; - uint16_t u16; - - memcpy(&u16, &data->data[i], sizeof(u16)); - uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(u16)); - - if (bt_uuid_cmp(uuid, BT_UUID_BASS) == 0) { - sr_info->has_bass = true; - continue; - } - - if (bt_uuid_cmp(uuid, BT_UUID_PACS) == 0) { - sr_info->has_pacs = true; - continue; - } - } - return true; - default: - return true; - } -} - -static bool base_store(struct bt_data *data, void *user_data) -{ - const struct bt_bap_base *base = bt_bap_base_get_base_from_ad(data); - uint8_t base_size; - int base_subgroup_count; - - /* Base is NULL if the data does not contain a valid BASE */ - if (base == NULL) { - return true; - } - - /* Can not fit all the received subgroups with the size CONFIG_BT_BAP_BASS_MAX_SUBGROUPS */ - base_subgroup_count = bt_bap_base_get_subgroup_count(base); - if (base_subgroup_count < 0 || base_subgroup_count > CONFIG_BT_BAP_BASS_MAX_SUBGROUPS) { - printk("Got invalid subgroup count: %d\n", base_subgroup_count); - return true; - } - - base_size = data->data_len - BT_UUID_SIZE_16; /* the BASE comes after the UUID */ - - /* Compare BASE and copy if different */ - k_mutex_lock(&base_store_mutex, K_FOREVER); - if (base_size != received_base_size || memcmp(base, received_base, base_size) != 0) { - (void)memcpy(received_base, base, base_size); - received_base_size = base_size; - } - k_mutex_unlock(&base_store_mutex); - - /* Stop parsing */ - k_sem_give(&sem_received_base_subgroups); - return false; -} - -static void pa_recv(struct bt_le_per_adv_sync *sync, - const struct bt_le_per_adv_sync_recv_info *info, - struct net_buf_simple *buf) -{ - bt_data_parse(buf, base_store, NULL); -} - -static bool add_pa_sync_base_subgroup_bis_cb(const struct bt_bap_base_subgroup_bis *bis, - void *user_data) -{ - struct bt_bap_bass_subgroup *subgroup_param = user_data; - - subgroup_param->bis_sync |= BIT(bis->index); - - return true; -} - -static bool add_pa_sync_base_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, - void *user_data) -{ - struct bt_bap_broadcast_assistant_add_src_param *param = user_data; - struct bt_bap_bass_subgroup *subgroup_param; - uint8_t *data; - int ret; - - ret = bt_bap_base_get_subgroup_codec_meta(subgroup, &data); - if (ret < 0) { - return false; - } - - subgroup_param = param->subgroups; - - if (ret > ARRAY_SIZE(subgroup_param->metadata)) { - printk("Cannot fit %d octets into subgroup param with size %zu", ret, - ARRAY_SIZE(subgroup_param->metadata)); - return false; - } - - ret = bt_bap_base_subgroup_foreach_bis(subgroup, add_pa_sync_base_subgroup_bis_cb, - subgroup_param); - if (ret < 0) { - return false; - } - - param->num_subgroups++; - - return true; -} - -static bool is_substring(const char *substr, const char *str) -{ - const size_t str_len = strlen(str); - const size_t sub_str_len = strlen(substr); - - if (sub_str_len > str_len) { - return false; - } - - for (size_t pos = 0; pos < str_len; pos++) { - if (pos + sub_str_len > str_len) { - return false; - } - - if (strncasecmp(substr, &str[pos], sub_str_len) == 0) { - return true; - } - } - - return false; -} - -static uint16_t interval_to_sync_timeout(uint16_t pa_interval) -{ - uint16_t pa_timeout; - - if (pa_interval == BT_BAP_PA_INTERVAL_UNKNOWN) { - /* Use maximum value to maximize chance of success */ - pa_timeout = BT_GAP_PER_ADV_MAX_TIMEOUT; - } else { - uint32_t interval_ms; - uint32_t timeout; - - /* Add retries and convert to unit in 10's of ms */ - interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(pa_interval); - timeout = (interval_ms * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO) / 10; - - /* Enforce restraints */ - pa_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT); - } - - return pa_timeout; -} - -static int pa_sync_create(void) -{ - struct bt_le_per_adv_sync_param create_params = {0}; - - bt_addr_le_copy(&create_params.addr, &selected_addr); - create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE; - create_params.sid = selected_sid; - create_params.skip = PA_SYNC_SKIP; - create_params.timeout = interval_to_sync_timeout(selected_pa_interval); - - return bt_le_per_adv_sync_create(&create_params, &pa_sync); -} - -static void scan_recv_cb(const struct bt_le_scan_recv_info *info, - struct net_buf_simple *ad) -{ - int err; - struct scan_recv_info sr_info = {0}; - - if (scanning_for_broadcast_source) { - /* Scan for and select Broadcast Source */ - - sr_info.broadcast_id = INVALID_BROADCAST_ID; - - /* We are only interested in non-connectable periodic advertisers */ - if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) != 0 || - info->interval == 0) { - return; - } - - bt_data_parse(ad, device_found, (void *)&sr_info); - - if (sr_info.broadcast_id != INVALID_BROADCAST_ID) { - printk("Broadcast Source Found:\n"); - printk(" BT Name: %s\n", sr_info.bt_name); - printk(" Broadcast Name: %s\n", sr_info.broadcast_name); - printk(" Broadcast ID: 0x%06x\n\n", sr_info.broadcast_id); - -#if defined(CONFIG_SELECT_SOURCE_NAME) - if (strlen(CONFIG_SELECT_SOURCE_NAME) > 0U) { - /* Compare names with CONFIG_SELECT_SOURCE_NAME */ - if (is_substring(CONFIG_SELECT_SOURCE_NAME, sr_info.bt_name) || - is_substring(CONFIG_SELECT_SOURCE_NAME, - sr_info.broadcast_name)) { - printk("Match found for '%s'\n", CONFIG_SELECT_SOURCE_NAME); - } else { - printk("'%s' not found in names\n\n", - CONFIG_SELECT_SOURCE_NAME); - return; - } - } -#endif /* CONFIG_SELECT_SOURCE_NAME */ - - err = bt_le_scan_stop(); - if (err != 0) { - printk("bt_le_scan_stop failed with %d\n", err); - } - - /* TODO: Add support for syncing to the PA and parsing the BASE - * in order to obtain the right subgroup information to send to - * the sink when adding a broadcast source (see in main function below). - */ - - printk("Selecting Broadcast ID: 0x%06x\n", sr_info.broadcast_id); - - selected_broadcast_id = sr_info.broadcast_id; - selected_sid = info->sid; - selected_pa_interval = info->interval; - bt_addr_le_copy(&selected_addr, info->addr); - - k_sem_give(&sem_source_discovered); - - printk("Attempting to PA sync to the broadcaster with id 0x%06X\n", - selected_broadcast_id); - } - } else { - /* Scan for and connect to Broadcast Sink */ - - /* We are only interested in connectable advertisers */ - if ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE) == 0) { - return; - } - - bt_data_parse(ad, device_found, (void *)&sr_info); - - if (sr_info.has_bass && sr_info.has_pacs) { - printk("Broadcast Sink Found:\n"); - printk(" BT Name: %s\n", sr_info.bt_name); - - if (strlen(CONFIG_SELECT_SINK_NAME) > 0U) { - /* Compare names with CONFIG_SELECT_SINK_NAME */ - if (is_substring(CONFIG_SELECT_SINK_NAME, sr_info.bt_name)) { - printk("Match found for '%s'\n", CONFIG_SELECT_SINK_NAME); - } else { - printk("'%s' not found in names\n\n", - CONFIG_SELECT_SINK_NAME); - return; - } - } - - err = bt_le_scan_stop(); - if (err != 0) { - printk("bt_le_scan_stop failed with %d\n", err); - } - - printk("Connecting to Broadcast Sink: %s\n", sr_info.bt_name); - - err = bt_conn_le_create(info->addr, BT_CONN_LE_CREATE_CONN, - BT_LE_CONN_PARAM_DEFAULT, - &broadcast_sink_conn); - if (err != 0) { - printk("Failed creating connection (err=%u)\n", err); - scan_for_broadcast_sink(); - } - - k_sem_give(&sem_sink_discovered); - } - } -} - -static void scan_timeout_cb(void) -{ - printk("Scan timeout\n"); -} - -static struct bt_le_scan_cb scan_callbacks = { - .recv = scan_recv_cb, - .timeout = scan_timeout_cb, -}; - -static void scan_for_broadcast_source(void) -{ - int err; - - scanning_for_broadcast_source = true; - - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); - if (err) { - printk("Scanning failed to start (err %d)\n", err); - return; - } - - printk("Scanning for Broadcast Source successfully started\n"); - - err = k_sem_take(&sem_source_discovered, K_FOREVER); - if (err != 0) { - printk("Failed to take sem_source_discovered (err %d)\n", err); - } -} - -static void scan_for_broadcast_sink(void) -{ - int err; - - scanning_for_broadcast_source = false; - - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); - if (err) { - printk("Scanning failed to start (err %d)\n", err); - return; - } - - printk("Scanning for Broadcast Sink successfully started\n"); - - err = k_sem_take(&sem_sink_discovered, K_FOREVER); - if (err != 0) { - printk("Failed to take sem_sink_discovered (err %d)\n", err); - } -} - -static void connected(struct bt_conn *conn, uint8_t err) -{ - char addr[BT_ADDR_LE_STR_LEN]; - - (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - - if (err != 0) { - printk("Failed to connect to %s (%u)\n", addr, err); - - bt_conn_unref(broadcast_sink_conn); - broadcast_sink_conn = NULL; - - scan_for_broadcast_sink(); - return; - } - - if (conn != broadcast_sink_conn) { - return; - } - - printk("Connected: %s\n", addr); - k_sem_give(&sem_sink_connected); -} - -static void disconnected(struct bt_conn *conn, uint8_t reason) -{ - char addr[BT_ADDR_LE_STR_LEN]; - - if (conn != broadcast_sink_conn) { - return; - } - - (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - - printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); - - bt_conn_unref(broadcast_sink_conn); - broadcast_sink_conn = NULL; - - k_sem_give(&sem_sink_disconnected); -} - -static void security_changed_cb(struct bt_conn *conn, bt_security_t level, - enum bt_security_err err) -{ - if (err == 0) { - printk("Security level changed: %u\n", level); - k_sem_give(&sem_security_updated); - } else { - printk("Failed to set security level: %u\n", err); - } -} - -static void bap_broadcast_assistant_discover_cb(struct bt_conn *conn, int err, - uint8_t recv_state_count) -{ - if (err == 0) { - printk("BASS discover done with %u recv states\n", - recv_state_count); - k_sem_give(&sem_bass_discovered); - } else { - printk("BASS discover failed (%d)\n", err); - } -} - -static void bap_broadcast_assistant_add_src_cb(struct bt_conn *conn, int err) -{ - if (err == 0) { - printk("BASS add source successful\n"); - } else { - printk("BASS add source failed (%d)\n", err); - } -} - -static void pa_sync_synced_cb(struct bt_le_per_adv_sync *sync, - struct bt_le_per_adv_sync_synced_info *info) -{ - if (sync == pa_sync) { - printk("PA sync %p synced for broadcast sink with broadcast ID 0x%06X\n", sync, - selected_broadcast_id); - - k_sem_give(&sem_pa_synced); - } -} - -static struct bt_bap_broadcast_assistant_cb ba_cbs = { - .discover = bap_broadcast_assistant_discover_cb, - .add_src = bap_broadcast_assistant_add_src_cb, -}; - -static struct bt_le_per_adv_sync_cb pa_synced_cb = { - .synced = pa_sync_synced_cb, - .recv = pa_recv, -}; - -static void reset(void) -{ - printk("\n\nReset...\n\n"); - - broadcast_sink_conn = NULL; - selected_broadcast_id = INVALID_BROADCAST_ID; - selected_sid = 0; - selected_pa_interval = 0; - (void)memset(&selected_addr, 0, sizeof(selected_addr)); - - k_sem_reset(&sem_source_discovered); - k_sem_reset(&sem_sink_discovered); - k_sem_reset(&sem_sink_connected); - k_sem_reset(&sem_sink_disconnected); - k_sem_reset(&sem_security_updated); - k_sem_reset(&sem_bass_discovered); - k_sem_reset(&sem_pa_synced); - k_sem_reset(&sem_received_base_subgroups); -} - -BT_CONN_CB_DEFINE(conn_callbacks) = { - .connected = connected, - .disconnected = disconnected, - .security_changed = security_changed_cb -}; - -int main(void) -{ - int err; - struct bt_bap_broadcast_assistant_add_src_param param = { 0 }; - - err = bt_enable(NULL); - if (err) { - printk("Bluetooth init failed (err %d)\n", err); - return 0; - } - - printk("Bluetooth initialized\n"); - - bt_bap_broadcast_assistant_register_cb(&ba_cbs); - bt_le_per_adv_sync_cb_register(&pa_synced_cb); - bt_le_scan_cb_register(&scan_callbacks); - - k_mutex_init(&base_store_mutex); - - while (true) { - scan_for_broadcast_sink(); - - err = k_sem_take(&sem_sink_connected, K_FOREVER); - if (err != 0) { - printk("Failed to take sem_sink_connected (err %d)\n", err); - } - - err = bt_bap_broadcast_assistant_discover(broadcast_sink_conn); - if (err != 0) { - printk("Failed to discover BASS on the sink (err %d)\n", err); - } - - err = k_sem_take(&sem_security_updated, K_SECONDS(10)); - if (err != 0) { - printk("Failed to take sem_security_updated (err %d), resetting\n", err); - bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_AUTH_FAIL); - - if (k_sem_take(&sem_sink_disconnected, K_SECONDS(10)) != 0) { - /* This should not happen */ - return -ETIMEDOUT; - } - - reset(); - continue; - } - - err = k_sem_take(&sem_bass_discovered, K_SECONDS(10)); - if (err != 0) { - if (err == -EAGAIN) { - printk("Failed to take sem_bass_discovered (err %d)\n", err); - } - bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE); - - if (k_sem_take(&sem_sink_disconnected, K_SECONDS(10)) != 0) { - /* This should not happen */ - return -ETIMEDOUT; - } - - reset(); - continue; - } - - /* TODO: Discover and parse the PACS on the sink and use the information - * when discovering and adding a source to the sink. - * Also, before populating the parameters to sync to the broadcast source - * first, parse the source BASE and determine if the sink supports the source. - * If not, then look for another source. - */ - - scan_for_broadcast_source(); - - printk("Scan stopped, attempting to PA sync to the broadcaster with id 0x%06X\n", - selected_broadcast_id); - err = pa_sync_create(); - if (err != 0) { - printk("Could not create Broadcast PA sync: %d, resetting\n", err); - return -ETIMEDOUT; - } - - printk("Waiting for PA synced\n"); - err = k_sem_take(&sem_pa_synced, K_FOREVER); - if (err != 0) { - printk("sem_pa_synced timed out, resetting\n"); - return err; - } - - memset(bass_subgroups, 0, sizeof(bass_subgroups)); - bt_addr_le_copy(¶m.addr, &selected_addr); - param.adv_sid = selected_sid; - param.pa_interval = selected_pa_interval; - param.broadcast_id = selected_broadcast_id; - param.pa_sync = true; - param.subgroups = bass_subgroups; - - /* Wait to receive subgroups */ - err = k_sem_take(&sem_received_base_subgroups, K_FOREVER); - if (err != 0) { - printk("Failed to take sem_received_base_subgroups (err %d)\n", err); - return err; - } - - k_mutex_lock(&base_store_mutex, K_FOREVER); - err = bt_bap_base_foreach_subgroup((const struct bt_bap_base *)received_base, - add_pa_sync_base_subgroup_cb, ¶m); - k_mutex_unlock(&base_store_mutex); - - if (err < 0) { - printk("Could not add BASE to params %d\n", err); - continue; - } - - err = bt_bap_broadcast_assistant_add_src(broadcast_sink_conn, ¶m); - if (err) { - printk("Failed to add source: %d\n", err); - bt_conn_disconnect(broadcast_sink_conn, BT_HCI_ERR_UNSUPP_REMOTE_FEATURE); - - if (k_sem_take(&sem_sink_disconnected, K_SECONDS(10)) != 0) { - /* This should not happen */ - return -ETIMEDOUT; - } - - reset(); - continue; - } - - /* Reset if the sink disconnects */ - err = k_sem_take(&sem_sink_disconnected, K_FOREVER); - if (err != 0) { - printk("Failed to take sem_sink_disconnected (err %d)\n", err); - } - - reset(); - } - - return 0; -} diff --git a/samples/bluetooth/broadcast_audio_sink/CMakeLists.txt b/samples/bluetooth/broadcast_audio_sink/CMakeLists.txt deleted file mode 100644 index 2b20af75d5689..0000000000000 --- a/samples/bluetooth/broadcast_audio_sink/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(unicast_audio_server) - -target_sources(app PRIVATE - src/main.c -) - -zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/broadcast_audio_sink/README.rst b/samples/bluetooth/broadcast_audio_sink/README.rst deleted file mode 100644 index 5c837c1652c94..0000000000000 --- a/samples/bluetooth/broadcast_audio_sink/README.rst +++ /dev/null @@ -1,80 +0,0 @@ -.. zephyr:code-sample:: bluetooth_broadcast_audio_sink - :name: Bluetooth: Broadcast Audio Sink - :relevant-api: bluetooth - - Bluetooth: Broadcast Audio Sink - -Overview -******** - -Application demonstrating the LE Audio broadcast sink functionality. -Starts by scanning for LE Audio broadcast sources and then synchronizes to -the first found and listens to it until the source is (potentially) stopped. - -This sample can be found under -:zephyr_file:`samples/bluetooth/broadcast_audio_sink` in the Zephyr tree. - -Check the :ref:`bluetooth samples section ` for general information. - -Use `CONFIG_TARGET_BROADCAST_NAME` Kconfig to specify the name (CONFIG_BT_DEVICE_NAME) -of a broadcast source to listen to. With default value (empty string), sink -device will listen to all available broadcast sources. - -Requirements -************ - -* BlueZ running on the host, or -* A board with Bluetooth Low Energy 5.2 support - -Building and Running -******************** - -When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, -use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO -feature support. - -Building for an nrf5340dk -------------------------- - -You can build both the application core image and an appropriate controller image for the network -core with: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/broadcast_audio_sink/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -If you prefer to only build the application core image, you can do so by doing instead: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/broadcast_audio_sink/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - -In that case you can pair this application core image with the -:ref:`hci_ipc sample ` -:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. - -Building for a simulated nrf5340bsim ------------------------------------- - -Similarly to how you would for real HW, you can do: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/broadcast_audio_sink/ - :board: nrf5340bsim/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. -For more information, check :ref:`this board documentation `. - -Building for a simulated nrf52_bsim ------------------------------------ - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/broadcast_audio_sink/ - :board: nrf52_bsim - :goals: build - :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/broadcast_audio_sink/sample.yaml b/samples/bluetooth/broadcast_audio_sink/sample.yaml deleted file mode 100644 index ef88ecc4bb23a..0000000000000 --- a/samples/bluetooth/broadcast_audio_sink/sample.yaml +++ /dev/null @@ -1,28 +0,0 @@ -sample: - description: Bluetooth Low Energy Audio Broadcast Sink sample - name: Bluetooth Low Energy Audio Broadcast Sink sample -tests: - sample.bluetooth.broadcast_audio_sink: - harness: bluetooth - platform_allow: - - qemu_cortex_m3 - - qemu_x86 - - nrf5340dk/nrf5340/cpuapp - - nrf5340bsim/nrf5340/cpuapp - integration_platforms: - - qemu_x86 - - nrf5340dk/nrf5340/cpuapp - tags: bluetooth - sysbuild: true - sample.bluetooth.broadcast_audio_sink.bt_ll_sw_split: - harness: bluetooth - platform_allow: - - nrf52_bsim - - nrf52833dk/nrf52833 - - nrf52840dongle/nrf52840 - integration_platforms: - - nrf52_bsim - - nrf52833dk/nrf52833 - - nrf52840dongle/nrf52840 - extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf - tags: bluetooth diff --git a/samples/bluetooth/broadcast_audio_sink/src/main.c b/samples/bluetooth/broadcast_audio_sink/src/main.c deleted file mode 100644 index ae55ca13b128e..0000000000000 --- a/samples/bluetooth/broadcast_audio_sink/src/main.c +++ /dev/null @@ -1,1587 +0,0 @@ -/* - * Copyright (c) 2022-2023 Nordic Semiconductor ASA - * Copyright (c) 2024 Demant A/S - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include - -#include -#include -#include -#include -#include -#if defined(CONFIG_LIBLC3) -#include "lc3.h" -#endif /* defined(CONFIG_LIBLC3) */ -#if defined(CONFIG_USB_DEVICE_AUDIO) -#include -#include -#include -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ - - -BUILD_ASSERT(IS_ENABLED(CONFIG_SCAN_SELF) || IS_ENABLED(CONFIG_SCAN_OFFLOAD), - "Either SCAN_SELF or SCAN_OFFLOAD must be enabled"); - -#define SEM_TIMEOUT K_SECONDS(60) -#define BROADCAST_ASSISTANT_TIMEOUT K_SECONDS(120) /* 2 minutes */ - -#define LOG_INTERVAL 1000U - -#if defined(CONFIG_SCAN_SELF) -#define ADV_TIMEOUT K_SECONDS(CONFIG_SCAN_DELAY) -#else /* !CONFIG_SCAN_SELF */ -#define ADV_TIMEOUT K_FOREVER -#endif /* CONFIG_SCAN_SELF */ - -#define INVALID_BROADCAST_ID (BT_AUDIO_BROADCAST_ID_MAX + 1) -#define PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO 20 /* Set the timeout relative to interval */ -#define PA_SYNC_SKIP 5 -#define NAME_LEN sizeof(CONFIG_TARGET_BROADCAST_NAME) + 1 -#define BROADCAST_DATA_ELEMENT_SIZE sizeof(int16_t) - -#if defined(CONFIG_LIBLC3) -#define LC3_MAX_SAMPLE_RATE 48000U -#define LC3_MAX_FRAME_DURATION_US 10000U -#define LC3_MAX_NUM_SAMPLES_MONO ((LC3_MAX_FRAME_DURATION_US * LC3_MAX_SAMPLE_RATE) \ - / USEC_PER_SEC) -#define LC3_MAX_NUM_SAMPLES_STEREO (LC3_MAX_NUM_SAMPLES_MONO * 2) - -#define LC3_ENCODER_STACK_SIZE 4096 -#define LC3_ENCODER_PRIORITY 5 -#endif /* defined(CONFIG_LIBLC3) */ - -#if defined(CONFIG_USB_DEVICE_AUDIO) -#define USB_ENQUEUE_COUNT 10U -#define USB_SAMPLE_RATE 48000U -#define USB_FRAME_DURATION_US 1000U -#define USB_MONO_SAMPLE_SIZE \ - ((USB_FRAME_DURATION_US * USB_SAMPLE_RATE * BROADCAST_DATA_ELEMENT_SIZE) / USEC_PER_SEC) -#define USB_STEREO_SAMPLE_SIZE (USB_MONO_SAMPLE_SIZE * 2) -#define USB_RING_BUF_SIZE (5 * LC3_MAX_NUM_SAMPLES_STEREO) /* 5 SDUs*/ -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ - -static K_SEM_DEFINE(sem_connected, 0U, 1U); -static K_SEM_DEFINE(sem_disconnected, 0U, 1U); -static K_SEM_DEFINE(sem_broadcaster_found, 0U, 1U); -static K_SEM_DEFINE(sem_pa_synced, 0U, 1U); -static K_SEM_DEFINE(sem_base_received, 0U, 1U); -static K_SEM_DEFINE(sem_syncable, 0U, 1U); -static K_SEM_DEFINE(sem_pa_sync_lost, 0U, 1U); -static K_SEM_DEFINE(sem_broadcast_code_received, 0U, 1U); -static K_SEM_DEFINE(sem_pa_request, 0U, 1U); -static K_SEM_DEFINE(sem_past_request, 0U, 1U); -static K_SEM_DEFINE(sem_bis_sync_requested, 0U, 1U); -static K_SEM_DEFINE(sem_bis_synced, 0U, CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT); - -/* Sample assumes that we only have a single Scan Delegator receive state */ -static const struct bt_bap_scan_delegator_recv_state *req_recv_state; -static struct bt_bap_broadcast_sink *broadcast_sink; -static struct bt_le_scan_recv_info broadcaster_info; -static bt_addr_le_t broadcaster_addr; -static struct bt_le_per_adv_sync *pa_sync; -static uint32_t broadcaster_broadcast_id; -static struct broadcast_sink_stream { - struct bt_bap_stream stream; - size_t recv_cnt; - size_t loss_cnt; - size_t error_cnt; - size_t valid_cnt; -#if defined(CONFIG_LIBLC3) - struct net_buf *in_buf; - struct k_work_delayable lc3_decode_work; - - /* LC3 config values */ - enum bt_audio_location chan_allocation; - uint16_t lc3_octets_per_frame; - uint8_t lc3_frames_blocks_per_sdu; - - /* Internal lock for protecting net_buf from multiple access */ - struct k_mutex lc3_decoder_mutex; - lc3_decoder_t lc3_decoder; - lc3_decoder_mem_48k_t lc3_decoder_mem; -#endif /* defined(CONFIG_LIBLC3) */ -} streams[CONFIG_BT_BAP_BROADCAST_SNK_STREAM_COUNT]; - -static struct bt_bap_stream *streams_p[ARRAY_SIZE(streams)]; -static struct bt_conn *broadcast_assistant_conn; -static struct bt_le_ext_adv *ext_adv; - -static const struct bt_audio_codec_cap codec_cap = BT_AUDIO_CODEC_CAP_LC3( - BT_AUDIO_CODEC_CAP_FREQ_16KHZ | BT_AUDIO_CODEC_CAP_FREQ_24KHZ, - BT_AUDIO_CODEC_CAP_DURATION_10, BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1), 40u, 60u, - CONFIG_MAX_CODEC_FRAMES_PER_SDU, - (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); - -/* Create a mask for the maximum BIS we can sync to using the number of streams - * we have. We add an additional 1 since the bis indexes start from 1 and not - * 0. - */ -static const uint32_t bis_index_mask = BIT_MASK(ARRAY_SIZE(streams) + 1U); -static uint32_t requested_bis_sync; -static uint32_t bis_index_bitfield; -static uint8_t sink_broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]; - -uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */ - -static int stop_adv(void); - -#if defined(CONFIG_USB_DEVICE_AUDIO) -RING_BUF_DECLARE(usb_ring_buf, USB_RING_BUF_SIZE); -NET_BUF_POOL_DEFINE(usb_tx_buf_pool, USB_ENQUEUE_COUNT, USB_STEREO_SAMPLE_SIZE, 0, net_buf_destroy); - -static void add_to_usb_ring_buf(const int16_t audio_buf[LC3_MAX_NUM_SAMPLES_STEREO]); -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ - -#if defined(CONFIG_LIBLC3) -static K_SEM_DEFINE(lc3_decoder_sem, 0, 1); - -static void do_lc3_decode(lc3_decoder_t decoder, const void *in_data, uint8_t octets_per_frame, - int16_t out_data[LC3_MAX_NUM_SAMPLES_MONO]); -static void lc3_decoder_thread(void *arg1, void *arg2, void *arg3); -K_THREAD_DEFINE(decoder_tid, LC3_ENCODER_STACK_SIZE, lc3_decoder_thread, - NULL, NULL, NULL, LC3_ENCODER_PRIORITY, 0, -1); - -static size_t get_chan_cnt(enum bt_audio_location chan_allocation) -{ - size_t cnt = 0U; - - if (chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO) { - return 1; - } - - while (chan_allocation != 0) { - cnt += chan_allocation & 1U; - chan_allocation >>= 1; - } - - return cnt; -} - -/* Consumer thread of the decoded stream data */ -static void lc3_decoder_thread(void *arg1, void *arg2, void *arg3) -{ - while (true) { -#if defined(CONFIG_USB_DEVICE_AUDIO) - static int16_t right_frames[CONFIG_MAX_CODEC_FRAMES_PER_SDU] - [LC3_MAX_NUM_SAMPLES_MONO]; - static int16_t left_frames[CONFIG_MAX_CODEC_FRAMES_PER_SDU] - [LC3_MAX_NUM_SAMPLES_MONO]; - size_t right_frames_cnt = 0; - size_t left_frames_cnt = 0; - - memset(right_frames, 0, sizeof(right_frames)); - memset(left_frames, 0, sizeof(left_frames)); -#else - static int16_t lc3_audio_buf[LC3_MAX_NUM_SAMPLES_MONO]; -#endif /* CONFIG_USB_DEVICE_AUDIO */ - - k_sem_take(&lc3_decoder_sem, K_FOREVER); - - for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { - struct broadcast_sink_stream *stream = &streams[i]; - const uint8_t frames_blocks_per_sdu = stream->lc3_frames_blocks_per_sdu; - const uint16_t octets_per_frame = stream->lc3_octets_per_frame; - uint16_t frames_per_block; - struct net_buf *buf; - - k_mutex_lock(&stream->lc3_decoder_mutex, K_FOREVER); - - if (stream->in_buf == NULL) { - k_mutex_unlock(&stream->lc3_decoder_mutex); - - continue; - } - - buf = net_buf_ref(stream->in_buf); - net_buf_unref(stream->in_buf); - stream->in_buf = NULL; - k_mutex_unlock(&stream->lc3_decoder_mutex); - - frames_per_block = get_chan_cnt(stream->chan_allocation); - if (buf->len != - (frames_per_block * octets_per_frame * frames_blocks_per_sdu)) { - printk("Expected %u frame blocks with %u frames of size %u, but " - "length is %u\n", - frames_blocks_per_sdu, frames_per_block, octets_per_frame, - buf->len); - - net_buf_unref(buf); - - continue; - } - -#if defined(CONFIG_USB_DEVICE_AUDIO) - const bool has_left = - (stream->chan_allocation & BT_AUDIO_LOCATION_FRONT_LEFT) != 0; - const bool has_right = - (stream->chan_allocation & BT_AUDIO_LOCATION_FRONT_RIGHT) != 0; - const bool is_mono = - stream->chan_allocation == BT_AUDIO_LOCATION_MONO_AUDIO; - - /* Split the SDU into frames*/ - for (uint8_t i = 0U; i < frames_blocks_per_sdu; i++) { - for (uint16_t j = 0U; j < frames_per_block; j++) { - const bool is_left = j == 0 && has_left; - const bool is_right = - has_right && (j == 0 || (j == 1 && has_left)); - const void *data = net_buf_pull_mem(buf, octets_per_frame); - int16_t *out_frame; - - if (is_left) { - out_frame = left_frames[left_frames_cnt++]; - } else if (is_right) { - out_frame = right_frames[right_frames_cnt++]; - } else if (is_mono) { - /* Use left as mono*/ - out_frame = left_frames[left_frames_cnt++]; - } else { - /* unused channel */ - break; - } - - do_lc3_decode(stream->lc3_decoder, data, octets_per_frame, - out_frame); - } - } -#else - /* Dummy behavior: Decode and discard data */ - for (uint8_t i = 0U; i < frames_blocks_per_sdu; i++) { - for (uint16_t j = 0U; j < frames_per_block; j++) { - const void *data = net_buf_pull_mem(buf, octets_per_frame); - - do_lc3_decode(stream->lc3_decoder, data, octets_per_frame, - lc3_audio_buf); - } - } -#endif /* CONFIG_USB_DEVICE_AUDIO */ - - net_buf_unref(buf); - } - -#if defined(CONFIG_USB_DEVICE_AUDIO) - const bool is_left_only = right_frames_cnt == 0U; - const bool is_right_only = left_frames_cnt == 0U; - - if (!is_left_only && !is_right_only && left_frames_cnt != right_frames_cnt) { - printk("Mismatch between number of left (%zu) and right (%zu) frames, " - "discard SDU", - left_frames_cnt, right_frames_cnt); - continue; - } - - /* Send frames to USB - If we only have a single channel we mix it to stereo */ - for (size_t i = 0U; i < MAX(left_frames_cnt, right_frames_cnt); i++) { - const bool is_single_channel = is_left_only || is_right_only; - static int16_t stereo_frame[LC3_MAX_NUM_SAMPLES_STEREO]; - int16_t *right_frame = right_frames[i]; - int16_t *left_frame = left_frames[i]; - - /* Not enough space to store data */ - if (ring_buf_space_get(&usb_ring_buf) < sizeof(stereo_frame)) { - break; - } - - memset(stereo_frame, 0, sizeof(stereo_frame)); - - /* Generate the stereo frame - * - * If we only have single channel then that is always stored in the - * left_frame, and we mix that to stereo - */ - for (int j = 0; j < LC3_MAX_NUM_SAMPLES_MONO; j++) { - if (is_single_channel) { - /* Mix to stereo */ - if (is_left_only) { - stereo_frame[j * 2] = left_frame[j]; - stereo_frame[j * 2 + 1] = left_frame[j]; - } else if (is_right_only) { - stereo_frame[j * 2] = right_frame[j]; - stereo_frame[j * 2 + 1] = right_frame[j]; - } - } else { - stereo_frame[j * 2] = left_frame[j]; - stereo_frame[j * 2 + 1] = right_frame[j]; - } - } - - add_to_usb_ring_buf(stereo_frame); - } -#endif /* CONFIG_USB_DEVICE_AUDIO */ - } -} - -/** Decode LC3 data on a stream and returns true if successful */ -static void do_lc3_decode(lc3_decoder_t decoder, const void *in_data, uint8_t octets_per_frame, - int16_t out_data[LC3_MAX_NUM_SAMPLES_MONO]) -{ - int err; - - err = lc3_decode(decoder, in_data, octets_per_frame, LC3_PCM_FORMAT_S16, out_data, 1); - if (err == 1) { - printk(" decoder performed PLC\n"); - } else if (err < 0) { - printk(" decoder failed - wrong parameters? (err = %d)\n", err); - } -} - -static int lc3_enable(struct broadcast_sink_stream *sink_stream) -{ - size_t chan_alloc_bit_cnt; - size_t sdu_size_required; - int frame_duration_us; - int freq_hz; - int ret; - - printk("Enable: stream with codec %p\n", sink_stream->stream.codec_cfg); - - ret = bt_audio_codec_cfg_get_freq(sink_stream->stream.codec_cfg); - if (ret > 0) { - freq_hz = bt_audio_codec_cfg_freq_to_freq_hz(ret); - } else { - printk("Error: Codec frequency not set, cannot start codec."); - return -1; - } - - ret = bt_audio_codec_cfg_get_frame_dur(sink_stream->stream.codec_cfg); - if (ret > 0) { - frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); - } else { - printk("Error: Frame duration not set, cannot start codec."); - return ret; - } - - ret = bt_audio_codec_cfg_get_chan_allocation(sink_stream->stream.codec_cfg, - &sink_stream->chan_allocation); - if (ret != 0) { - printk("Error: Channel allocation not set, invalid configuration for LC3"); - return ret; - } - - ret = bt_audio_codec_cfg_get_octets_per_frame(sink_stream->stream.codec_cfg); - if (ret > 0) { - sink_stream->lc3_octets_per_frame = (uint16_t)ret; - } else { - printk("Error: Octets per frame not set, invalid configuration for LC3"); - return ret; - } - - ret = bt_audio_codec_cfg_get_frame_blocks_per_sdu(sink_stream->stream.codec_cfg, true); - if (ret > 0) { - sink_stream->lc3_frames_blocks_per_sdu = (uint8_t)ret; - } else { - printk("Error: Frame blocks per SDU not set, invalid configuration for LC3"); - return ret; - } - - /* An SDU can consist of X frame blocks, each with Y frames (one per channel) of size Z in - * them. The minimum SDU size required for this is X * Y * Z. - */ - chan_alloc_bit_cnt = get_chan_cnt(sink_stream->chan_allocation); - sdu_size_required = chan_alloc_bit_cnt * sink_stream->lc3_octets_per_frame * - sink_stream->lc3_frames_blocks_per_sdu; - if (sdu_size_required < sink_stream->stream.qos->sdu) { - printk("With %zu channels and %u octets per frame and %u frames per block, SDUs " - "shall be at minimum %zu, but the stream has been configured for %u", - chan_alloc_bit_cnt, sink_stream->lc3_octets_per_frame, - sink_stream->lc3_frames_blocks_per_sdu, sdu_size_required, - sink_stream->stream.qos->sdu); - - return -EINVAL; - } - - printk("Enabling LC3 decoder with frame duration %uus, frequency %uHz and with channel " - "allocation 0x%08X, %u octets per frame and %u frame blocks per SDU\n", - frame_duration_us, freq_hz, sink_stream->chan_allocation, - sink_stream->lc3_octets_per_frame, sink_stream->lc3_frames_blocks_per_sdu); - -#if defined(CONFIG_USB_DEVICE_AUDIO) - sink_stream->lc3_decoder = lc3_setup_decoder(frame_duration_us, freq_hz, USB_SAMPLE_RATE, - &sink_stream->lc3_decoder_mem); -#else - sink_stream->lc3_decoder = lc3_setup_decoder(frame_duration_us, freq_hz, 0, - &sink_stream->lc3_decoder_mem); -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ - - if (sink_stream->lc3_decoder == NULL) { - printk("ERROR: Failed to setup LC3 decoder - wrong parameters?\n"); - return -1; - } - - k_thread_start(decoder_tid); - - return 0; -} -#endif /* defined(CONFIG_LIBLC3) */ - -#if defined(CONFIG_USB_DEVICE_AUDIO) -/* Move the LC3 data to the USB ring buffer */ -static void add_to_usb_ring_buf(const int16_t audio_buf[LC3_MAX_NUM_SAMPLES_STEREO]) -{ - uint32_t size; - - size = ring_buf_put(&usb_ring_buf, (uint8_t *)audio_buf, - LC3_MAX_NUM_SAMPLES_STEREO * sizeof(int16_t)); - if (size != LC3_MAX_NUM_SAMPLES_STEREO) { - static int rb_put_failures; - - rb_put_failures++; - if (rb_put_failures == LOG_INTERVAL) { - printk("%s: Failure to add to usb_ring_buf %d, %u\n", __func__, - rb_put_failures, size); - } - } -} - -/* USB consumer callback, called every 1ms, consumes data from ring-buffer */ -static void usb_data_request_cb(const struct device *dev) -{ - uint8_t usb_audio_data[USB_STEREO_SAMPLE_SIZE] = {0}; - static struct net_buf *pcm_buf; - static size_t cnt; - uint32_t size; - int err; - - size = ring_buf_get(&usb_ring_buf, (uint8_t *)usb_audio_data, sizeof(usb_audio_data)); - if (size == 0) { - /* size is 0, noop */ - return; - } - /* Size lower than USB_STEREO_SAMPLE_SIZE is OK as usb_audio_data is 0-initialized */ - - pcm_buf = net_buf_alloc(&usb_tx_buf_pool, K_NO_WAIT); - if (pcm_buf == NULL) { - printk("Could not allocate pcm_buf\n"); - return; - } - - net_buf_add_mem(pcm_buf, usb_audio_data, sizeof(usb_audio_data)); - - if (cnt % LOG_INTERVAL == 0) { - printk("Sending USB audio (count = %zu)\n", cnt); - } - - err = usb_audio_send(dev, pcm_buf, USB_STEREO_SAMPLE_SIZE); - if (err) { - printk("Failed to send USB audio: %d\n", err); - net_buf_unref(pcm_buf); - } - - cnt++; -} - -static void usb_data_written_cb(const struct device *dev, struct net_buf *buf, size_t size) -{ - /* Unreference the buffer now that the USB is done with it */ - net_buf_unref(buf); -} -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ - -static void stream_started_cb(struct bt_bap_stream *stream) -{ - struct broadcast_sink_stream *sink_stream = - CONTAINER_OF(stream, struct broadcast_sink_stream, stream); - - printk("Stream %p started\n", stream); - - total_rx_iso_packet_count = 0U; - sink_stream->recv_cnt = 0U; - sink_stream->loss_cnt = 0U; - sink_stream->valid_cnt = 0U; - sink_stream->error_cnt = 0U; - -#if defined(CONFIG_LIBLC3) - int err; - - if (stream->codec_cfg != 0 && stream->codec_cfg->id != BT_HCI_CODING_FORMAT_LC3) { - /* No subgroups with LC3 was found */ - printk("Did not parse an LC3 codec\n"); - return; - } - - err = lc3_enable(sink_stream); - if (err < 0) { - printk("Error: cannot enable LC3 codec: %d", err); - return; - } -#endif /* CONFIG_LIBLC3 */ - - k_sem_give(&sem_bis_synced); -} - -static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) -{ - int err; - - printk("Stream %p stopped with reason 0x%02X\n", stream, reason); - - err = k_sem_take(&sem_bis_synced, K_NO_WAIT); - if (err != 0) { - printk("Failed to take sem_bis_synced: %d\n", err); - } -} - -static void stream_recv_cb(struct bt_bap_stream *stream, const struct bt_iso_recv_info *info, - struct net_buf *buf) -{ - struct broadcast_sink_stream *sink_stream = - CONTAINER_OF(stream, struct broadcast_sink_stream, stream); - - if (info->flags & BT_ISO_FLAGS_ERROR) { - sink_stream->error_cnt++; - } - - if (info->flags & BT_ISO_FLAGS_LOST) { - sink_stream->loss_cnt++; - } - - if (info->flags & BT_ISO_FLAGS_VALID) { - sink_stream->valid_cnt++; -#if defined(CONFIG_LIBLC3) - k_mutex_lock(&sink_stream->lc3_decoder_mutex, K_FOREVER); - if (sink_stream->in_buf != NULL) { - net_buf_unref(sink_stream->in_buf); - sink_stream->in_buf = NULL; - } - - sink_stream->in_buf = net_buf_ref(buf); - k_mutex_unlock(&sink_stream->lc3_decoder_mutex); - k_sem_give(&lc3_decoder_sem); -#endif /* defined(CONFIG_LIBLC3) */ - } - - total_rx_iso_packet_count++; - sink_stream->recv_cnt++; - if ((sink_stream->recv_cnt % LOG_INTERVAL) == 0U) { - printk("Stream %p: received %u total ISO packets: Valid %u | Error %u | Loss %u\n", - &sink_stream->stream, sink_stream->recv_cnt, sink_stream->valid_cnt, - sink_stream->error_cnt, sink_stream->loss_cnt); - } -} - -static struct bt_bap_stream_ops stream_ops = { - .started = stream_started_cb, - .stopped = stream_stopped_cb, - .recv = stream_recv_cb, -}; - -#if defined(CONFIG_TARGET_BROADCAST_CHANNEL) -struct find_valid_bis_data { - struct { - uint8_t index; - enum bt_audio_location chan_allocation; - } bis[BT_ISO_BIS_INDEX_MAX]; - - uint8_t cnt; -}; - -/** - * This is called for each BIS in a subgroup - * - * It returns `false` if the current BIS contains all of the channels we are looking for, - * or if it does not contain any and we are looking for BT_AUDIO_LOCATION_MONO_AUDIO. This stops - * the iteration of the remaining BIS in the subgroup. - * - * It returns `true` if the BIS either contains none or some of the channels we are looking for. - * If it contains some, then that is being stored in the user_data, so that the calling function - * can check if a combination of the BIS satisfy the channel allocations we want. - */ -static bool find_valid_bis_cb(const struct bt_bap_base_subgroup_bis *bis, - void *user_data) -{ - struct find_valid_bis_data *data = user_data; - struct bt_audio_codec_cfg codec_cfg = {0}; - enum bt_audio_location chan_allocation; - int err; - - err = bt_bap_base_subgroup_bis_codec_to_codec_cfg(bis, &codec_cfg); - if (err != 0) { - printk("Could not get codec configuration for BIS: %d\n", err); - return true; - } - - err = bt_audio_codec_cfg_get_chan_allocation(&codec_cfg, &chan_allocation); - if (err != 0) { - printk("Could not find channel allocation for BIS: %d\n", err); - - /* Absence of channel allocation is implicitly mono as per the BAP spec */ - if (CONFIG_TARGET_BROADCAST_CHANNEL == BT_AUDIO_LOCATION_MONO_AUDIO) { - data->bis[0].index = bis->index; - data->bis[0].chan_allocation = chan_allocation; - data->cnt = 1; - - return false; - } else if (err == -ENODATA && strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { - /* Accept no channel allocation data available - * if TARGET_BROADCAST_NAME defined. Use current index. - */ - data->bis[0].index = bis->index; - data->bis[0].chan_allocation = chan_allocation; - data->cnt = 1; - - return false; - } - } else { - if ((chan_allocation & CONFIG_TARGET_BROADCAST_CHANNEL) == - CONFIG_TARGET_BROADCAST_CHANNEL) { - /* Found single BIS with all channels we want - keep as only and stop - * parsing - */ - data->bis[0].index = bis->index; - data->bis[0].chan_allocation = chan_allocation; - data->cnt = 1; - - return false; - } else if ((chan_allocation & CONFIG_TARGET_BROADCAST_CHANNEL) != 0) { - /* BIS contains part of what we are looking for - Store and see if there are - * other BIS that may fill the gaps - */ - data->bis[data->cnt].index = bis->index; - data->bis[data->cnt].chan_allocation = chan_allocation; - data->cnt++; - } - } - - return true; -} - -/** - * This function searches all the BIS in a subgroup for a set of BIS indexes that satisfy - * CONFIG_TARGET_BROADCAST_CHANNEL - * - * Returns `true` if the right channels were found, otherwise `false`. - */ -static bool find_valid_bis_in_subgroup_bis(const struct bt_bap_base_subgroup *subgroup, - uint32_t *bis_indexes) -{ - struct find_valid_bis_data data = {0}; - int err; - - err = bt_bap_base_subgroup_foreach_bis(subgroup, find_valid_bis_cb, &data); - if (err == -ECANCELED) { - /* We found what we are looking for in a single BIS */ - - *bis_indexes = BIT(data.bis[0].index); - - return true; - } else if (err == 0) { - /* We are finished parsing all BIS - Try to find a combination that satisfy our - * channel allocation. For simplicity this is using a greedy approach, rather than - * an optimal one. - */ - enum bt_audio_location chan_allocation = BT_AUDIO_LOCATION_MONO_AUDIO; - *bis_indexes = 0; - - for (uint8_t i = 0U; i < data.cnt; i++) { - chan_allocation |= data.bis[i].chan_allocation; - *bis_indexes |= BIT(data.bis[i].index); - - if ((chan_allocation & CONFIG_TARGET_BROADCAST_CHANNEL) == - CONFIG_TARGET_BROADCAST_CHANNEL) { - return true; - } - } - } - - /* Some error occurred or we did not find expected channel allocation */ - return false; -} - -/** - * Called for each subgroup in the BASE. Will populate the 32-bit bitfield of BIS indexes if the - * subgroup contains it. - * - * The channel allocation may - * - Not exist at all, implicitly meaning BT_AUDIO_LOCATION_MONO_AUDIO - * - Exist only in the subgroup codec configuration - * - Exist only in the BIS codec configuration - * - Exist in both the subgroup and BIS codec configuration, in which case, the BIS codec - * configuration overwrites the subgroup values - * - * This function returns `true` if the subgroup does not support the channels in - * CONFIG_TARGET_BROADCAST_CHANNEL which makes it iterate over the next subgroup, and returns - * `false` if this subgroup satisfies our CONFIG_TARGET_BROADCAST_CHANNEL. - */ -static bool find_valid_bis_in_subgroup_cb(const struct bt_bap_base_subgroup *subgroup, - void *user_data) -{ - enum bt_audio_location chan_allocation; - struct bt_audio_codec_cfg codec_cfg; - uint32_t *bis_indexes = user_data; - int err; - - /* We only want indexes from a single subgroup, so reset between each of them*/ - *bis_indexes = 0U; - - err = bt_bap_base_subgroup_codec_to_codec_cfg(subgroup, &codec_cfg); - if (err != 0) { - printk("Could not get codec configuration: %d\n", err); - - return true; - } - - err = bt_audio_codec_cfg_get_chan_allocation(&codec_cfg, &chan_allocation); - if (err != 0) { - printk("Could not find subgroup channel allocation: %d - Looking in the BISes\n", - err); - - /* Find chan alloc in BIS */ - if (find_valid_bis_in_subgroup_bis(subgroup, bis_indexes)) { - /* Found BISes with correct channel allocation */ - return false; - } - } else { - /* If the subgroup contains a single channel, then we just grab the first BIS index - */ - if (get_chan_cnt(chan_allocation) == 1 && - chan_allocation == CONFIG_TARGET_BROADCAST_CHANNEL) { - uint32_t subgroup_bis_indexes; - - /* Set bis_indexes to the first bit set */ - err = bt_bap_base_subgroup_get_bis_indexes(subgroup, &subgroup_bis_indexes); - if (err != 0) { - /* Should never happen as that would indicate an invalid - * subgroup If it does, we just parse the next subgroup - */ - return true; - } - - /* We found the BIS index we want, stop parsing*/ - *bis_indexes = BIT(find_lsb_set(subgroup_bis_indexes) - 1); - - return false; - } else if ((chan_allocation & CONFIG_TARGET_BROADCAST_CHANNEL) == - CONFIG_TARGET_BROADCAST_CHANNEL) { - /* The subgroup contains all channels we are looking for/ - * We continue searching each BIS to get the minimal amount of BIS that - * satisfy CONFIG_TARGET_BROADCAST_CHANNEL. - */ - - if (find_valid_bis_in_subgroup_bis(subgroup, bis_indexes)) { - /* Found BISes with correct channel allocation */ - return false; - } - } - } - - return true; -} - -/** - * This function gets a 32-bit bitfield of BIS indexes that cover the channel allocation values in - * CONFIG_TARGET_BROADCAST_CHANNEL. - */ -static int base_get_valid_bis_indexes(const struct bt_bap_base *base, uint32_t *bis_indexes) -{ - int err; - - err = bt_bap_base_foreach_subgroup(base, find_valid_bis_in_subgroup_cb, bis_indexes); - if (err != -ECANCELED) { - printk("Failed to parse subgroups: %d\n", err); - return err != 0 ? err : -ENOENT; - } - - return 0; -} -#endif /* CONFIG_TARGET_BROADCAST_CHANNEL */ - -static void base_recv_cb(struct bt_bap_broadcast_sink *sink, const struct bt_bap_base *base, - size_t base_size) -{ - uint32_t base_bis_index_bitfield = 0U; - int err; - - if (k_sem_count_get(&sem_base_received) != 0U) { - return; - } - - printk("Received BASE with %d subgroups from broadcast sink %p\n", - bt_bap_base_get_subgroup_count(base), sink); - -#if defined(CONFIG_TARGET_BROADCAST_CHANNEL) - err = base_get_valid_bis_indexes(base, &base_bis_index_bitfield); - if (err != 0) { - printk("Failed to find a valid BIS\n"); - return; - } -#else - err = bt_bap_base_get_bis_indexes(base, &base_bis_index_bitfield); - if (err != 0) { - printk("Failed to BIS indexes: %d\n", err); - return; - } -#endif /* CONFIG_TARGET_BROADCAST_CHANNEL */ - - bis_index_bitfield = base_bis_index_bitfield & bis_index_mask; - - if (broadcast_assistant_conn == NULL) { - /* No broadcast assistant requesting anything */ - requested_bis_sync = BT_BAP_BIS_SYNC_NO_PREF; - k_sem_give(&sem_bis_sync_requested); - } - - k_sem_give(&sem_base_received); -} - -static void syncable_cb(struct bt_bap_broadcast_sink *sink, const struct bt_iso_biginfo *biginfo) -{ - k_sem_give(&sem_syncable); - - if (!biginfo->encryption) { - /* Use the semaphore as a boolean */ - k_sem_reset(&sem_broadcast_code_received); - k_sem_give(&sem_broadcast_code_received); - } -} - -static struct bt_bap_broadcast_sink_cb broadcast_sink_cbs = { - .base_recv = base_recv_cb, - .syncable = syncable_cb, -}; - -static void pa_timer_handler(struct k_work *work) -{ - if (req_recv_state != NULL) { - enum bt_bap_pa_state pa_state; - - if (req_recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { - pa_state = BT_BAP_PA_STATE_NO_PAST; - } else { - pa_state = BT_BAP_PA_STATE_FAILED; - } - - bt_bap_scan_delegator_set_pa_state(req_recv_state->src_id, - pa_state); - } - - printk("PA timeout\n"); -} - -static K_WORK_DELAYABLE_DEFINE(pa_timer, pa_timer_handler); - -static uint16_t interval_to_sync_timeout(uint16_t pa_interval) -{ - uint16_t pa_timeout; - - if (pa_interval == BT_BAP_PA_INTERVAL_UNKNOWN) { - /* Use maximum value to maximize chance of success */ - pa_timeout = BT_GAP_PER_ADV_MAX_TIMEOUT; - } else { - uint32_t interval_ms; - uint32_t timeout; - - /* Add retries and convert to unit in 10's of ms */ - interval_ms = BT_GAP_PER_ADV_INTERVAL_TO_MS(pa_interval); - timeout = (interval_ms * PA_SYNC_INTERVAL_TO_TIMEOUT_RATIO) / 10; - - /* Enforce restraints */ - pa_timeout = CLAMP(timeout, BT_GAP_PER_ADV_MIN_TIMEOUT, BT_GAP_PER_ADV_MAX_TIMEOUT); - } - - return pa_timeout; -} - -static int pa_sync_past(struct bt_conn *conn, uint16_t pa_interval) -{ - struct bt_le_per_adv_sync_transfer_param param = { 0 }; - int err; - - param.skip = PA_SYNC_SKIP; - param.timeout = interval_to_sync_timeout(pa_interval); - - err = bt_le_per_adv_sync_transfer_subscribe(conn, ¶m); - if (err != 0) { - printk("Could not do PAST subscribe: %d\n", err); - } else { - printk("Syncing with PAST\n"); - (void)k_work_reschedule(&pa_timer, K_MSEC(param.timeout * 10)); - } - - return err; -} - -static int pa_sync_req_cb(struct bt_conn *conn, - const struct bt_bap_scan_delegator_recv_state *recv_state, - bool past_avail, uint16_t pa_interval) -{ - - printk("Received request to sync to PA (PAST %savailble): %u\n", past_avail ? "" : "not ", - recv_state->pa_sync_state); - - req_recv_state = recv_state; - - if (recv_state->pa_sync_state == BT_BAP_PA_STATE_SYNCED || - recv_state->pa_sync_state == BT_BAP_PA_STATE_INFO_REQ) { - /* Already syncing */ - /* TODO: Terminate existing sync and then sync to new?*/ - return -1; - } - - if (IS_ENABLED(CONFIG_BT_PER_ADV_SYNC_TRANSFER_RECEIVER) && past_avail) { - int err; - - err = pa_sync_past(conn, pa_interval); - if (err != 0) { - printk("Failed to subscribe to PAST: %d\n", err); - - return err; - } - - k_sem_give(&sem_past_request); - - err = bt_bap_scan_delegator_set_pa_state(recv_state->src_id, - BT_BAP_PA_STATE_INFO_REQ); - if (err != 0) { - printk("Failed to set PA state to BT_BAP_PA_STATE_INFO_REQ: %d\n", err); - - return err; - } - } - - k_sem_give(&sem_pa_request); - - return 0; -} - -static int pa_sync_term_req_cb(struct bt_conn *conn, - const struct bt_bap_scan_delegator_recv_state *recv_state) -{ - int err; - - req_recv_state = recv_state; - - err = bt_bap_broadcast_sink_delete(broadcast_sink); - if (err != 0) { - return err; - } - - broadcast_sink = NULL; - - return 0; -} - -static void broadcast_code_cb(struct bt_conn *conn, - const struct bt_bap_scan_delegator_recv_state *recv_state, - const uint8_t broadcast_code[BT_AUDIO_BROADCAST_CODE_SIZE]) -{ - printk("Broadcast code received for %p\n", recv_state); - - req_recv_state = recv_state; - - (void)memcpy(sink_broadcast_code, broadcast_code, BT_AUDIO_BROADCAST_CODE_SIZE); - - /* Use the semaphore as a boolean */ - k_sem_reset(&sem_broadcast_code_received); - k_sem_give(&sem_broadcast_code_received); -} - -static int bis_sync_req_cb(struct bt_conn *conn, - const struct bt_bap_scan_delegator_recv_state *recv_state, - const uint32_t bis_sync_req[CONFIG_BT_BAP_BASS_MAX_SUBGROUPS]) -{ - const bool bis_synced = k_sem_count_get(&sem_bis_synced) > 0U; - - printk("BIS sync request received for %p: 0x%08x\n", - recv_state, bis_sync_req[0]); - - /* We only care about a single subgroup in this sample */ - if (bis_synced && requested_bis_sync != bis_sync_req[0]) { - /* If the BIS sync request is received while we are already - * synced, it means that the requested BIS sync has changed. - */ - int err; - - /* The stream stopped callback will be called as part of this, - * and we do not need to wait for any events from the - * controller. Thus, when this returns, the `sem_bis_synced` - * is back to 0. - */ - err = bt_bap_broadcast_sink_stop(broadcast_sink); - if (err != 0) { - printk("Failed to stop Broadcast Sink: %d\n", err); - - return err; - } - } - - requested_bis_sync = bis_sync_req[0]; - broadcaster_broadcast_id = recv_state->broadcast_id; - if (bis_sync_req[0] != 0) { - k_sem_give(&sem_bis_sync_requested); - } - - return 0; -} - -static struct bt_bap_scan_delegator_cb scan_delegator_cbs = { - .pa_sync_req = pa_sync_req_cb, - .pa_sync_term_req = pa_sync_term_req_cb, - .broadcast_code = broadcast_code_cb, - .bis_sync_req = bis_sync_req_cb, -}; - -static void connected(struct bt_conn *conn, uint8_t err) -{ - char addr[BT_ADDR_LE_STR_LEN]; - - bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - - if (err != 0U) { - printk("Failed to connect to %s (%u)\n", addr, err); - - broadcast_assistant_conn = NULL; - return; - } - - printk("Connected: %s\n", addr); - broadcast_assistant_conn = bt_conn_ref(conn); - - k_sem_give(&sem_connected); -} - -static void disconnected(struct bt_conn *conn, uint8_t reason) -{ - char addr[BT_ADDR_LE_STR_LEN]; - - if (conn != broadcast_assistant_conn) { - return; - } - - bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - - printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); - - bt_conn_unref(broadcast_assistant_conn); - broadcast_assistant_conn = NULL; - - k_sem_give(&sem_disconnected); -} - -BT_CONN_CB_DEFINE(conn_callbacks) = { - .connected = connected, - .disconnected = disconnected, -}; - -static struct bt_pacs_cap cap = { - .codec_cap = &codec_cap, -}; - -static bool scan_check_and_sync_broadcast(struct bt_data *data, void *user_data) -{ - const struct bt_le_scan_recv_info *info = user_data; - char le_addr[BT_ADDR_LE_STR_LEN]; - struct bt_uuid_16 adv_uuid; - uint32_t broadcast_id; - - if (data->type != BT_DATA_SVC_DATA16) { - return true; - } - - if (data->data_len < BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE) { - return true; - } - - if (!bt_uuid_create(&adv_uuid.uuid, data->data, BT_UUID_SIZE_16)) { - return true; - } - - if (bt_uuid_cmp(&adv_uuid.uuid, BT_UUID_BROADCAST_AUDIO)) { - return true; - } - - broadcast_id = sys_get_le24(data->data + BT_UUID_SIZE_16); - - bt_addr_le_to_str(info->addr, le_addr, sizeof(le_addr)); - - printk("Found broadcaster with ID 0x%06X and addr %s and sid 0x%02X\n", broadcast_id, - le_addr, info->sid); - - if (broadcast_assistant_conn == NULL) { - /* Not requested by Broadcast Assistant */ - k_sem_give(&sem_broadcaster_found); - } else if (req_recv_state != NULL && - bt_addr_le_eq(info->addr, &req_recv_state->addr) && - info->sid == req_recv_state->adv_sid && - broadcast_id == req_recv_state->broadcast_id) { - k_sem_give(&sem_broadcaster_found); - } - - /* Store info for PA sync parameters */ - memcpy(&broadcaster_info, info, sizeof(broadcaster_info)); - bt_addr_le_copy(&broadcaster_addr, info->addr); - broadcaster_broadcast_id = broadcast_id; - - /* Stop parsing */ - return false; -} - -static bool is_substring(const char *substr, const char *str) -{ - const size_t str_len = strlen(str); - const size_t sub_str_len = strlen(substr); - - if (sub_str_len > str_len) { - return false; - } - - for (size_t pos = 0; pos < str_len; pos++) { - if (pos + sub_str_len > str_len) { - return false; - } - - if (strncasecmp(substr, &str[pos], sub_str_len) == 0) { - return true; - } - } - - return false; -} - -static bool data_cb(struct bt_data *data, void *user_data) -{ - char *name = user_data; - - switch (data->type) { - case BT_DATA_NAME_SHORTENED: - case BT_DATA_NAME_COMPLETE: - case BT_DATA_BROADCAST_NAME: - memcpy(name, data->data, MIN(data->data_len, NAME_LEN - 1)); - return false; - default: - return true; - } -} - -static void broadcast_scan_recv(const struct bt_le_scan_recv_info *info, struct net_buf_simple *ad) -{ - if (info->interval != 0U) { - /* call to bt_data_parse consumes netbufs so shallow clone for verbose output */ - - /* If req_recv_state is NULL then we have been requested by a broadcast assistant to - * sync to a specific broadcast source. In that case we do not apply our own - * broadcast name filter. - */ - if (req_recv_state != NULL && strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { - struct net_buf_simple buf_copy; - char name[NAME_LEN] = {0}; - - net_buf_simple_clone(ad, &buf_copy); - bt_data_parse(&buf_copy, data_cb, name); - if (!(is_substring(CONFIG_TARGET_BROADCAST_NAME, name))) { - return; - } - } - bt_data_parse(ad, scan_check_and_sync_broadcast, (void *)info); - } -} - -static struct bt_le_scan_cb bap_scan_cb = { - .recv = broadcast_scan_recv, -}; - -static void bap_pa_sync_synced_cb(struct bt_le_per_adv_sync *sync, - struct bt_le_per_adv_sync_synced_info *info) -{ - if (sync == pa_sync || - (req_recv_state != NULL && bt_addr_le_eq(info->addr, &req_recv_state->addr) && - info->sid == req_recv_state->adv_sid)) { - printk("PA sync %p synced for broadcast sink with broadcast ID 0x%06X\n", sync, - broadcaster_broadcast_id); - - if (pa_sync == NULL) { - pa_sync = sync; - } - - k_work_cancel_delayable(&pa_timer); - k_sem_give(&sem_pa_synced); - } -} - -static void bap_pa_sync_terminated_cb(struct bt_le_per_adv_sync *sync, - const struct bt_le_per_adv_sync_term_info *info) -{ - if (sync == pa_sync) { - printk("PA sync %p lost with reason %u\n", sync, info->reason); - pa_sync = NULL; - - k_sem_give(&sem_pa_sync_lost); - } -} - -static struct bt_le_per_adv_sync_cb bap_pa_sync_cb = { - .synced = bap_pa_sync_synced_cb, - .term = bap_pa_sync_terminated_cb, -}; - -static int init(void) -{ - int err; - - err = bt_enable(NULL); - if (err) { - printk("Bluetooth enable failed (err %d)\n", err); - return err; - } - - printk("Bluetooth initialized\n"); - - err = bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap); - if (err) { - printk("Capability register failed (err %d)\n", err); - return err; - } - - bt_bap_broadcast_sink_register_cb(&broadcast_sink_cbs); - bt_bap_scan_delegator_register_cb(&scan_delegator_cbs); - bt_le_per_adv_sync_cb_register(&bap_pa_sync_cb); - bt_le_scan_cb_register(&bap_scan_cb); - - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - streams[i].stream.ops = &stream_ops; - } - - /* Initialize ring buffers and USB */ -#if defined(CONFIG_USB_DEVICE_AUDIO) - const struct device *hs_dev = DEVICE_DT_GET(DT_NODELABEL(hs_0)); - static const struct usb_audio_ops usb_ops = { - .data_request_cb = usb_data_request_cb, - .data_written_cb = usb_data_written_cb, - }; - - if (!device_is_ready(hs_dev)) { - printk("Cannot get USB Headset Device\n"); - return -EIO; - } - - usb_audio_register(hs_dev, &usb_ops); - err = usb_enable(NULL); - if (err && err != -EALREADY) { - printk("Failed to enable USB\n"); - return err; - } -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ - - return 0; -} - -static int reset(void) -{ - int err; - - bis_index_bitfield = 0U; - requested_bis_sync = 0U; - req_recv_state = NULL; - (void)memset(sink_broadcast_code, 0, sizeof(sink_broadcast_code)); - (void)memset(&broadcaster_info, 0, sizeof(broadcaster_info)); - (void)memset(&broadcaster_addr, 0, sizeof(broadcaster_addr)); - broadcaster_broadcast_id = INVALID_BROADCAST_ID; - - if (broadcast_sink != NULL) { - err = bt_bap_broadcast_sink_delete(broadcast_sink); - if (err) { - printk("Deleting broadcast sink failed (err %d)\n", err); - - return err; - } - - broadcast_sink = NULL; - } - - if (pa_sync != NULL) { - bt_le_per_adv_sync_delete(pa_sync); - if (err) { - printk("Deleting PA sync failed (err %d)\n", err); - - return err; - } - - pa_sync = NULL; - } - - if (IS_ENABLED(CONFIG_SCAN_OFFLOAD)) { - if (broadcast_assistant_conn != NULL) { - err = bt_conn_disconnect(broadcast_assistant_conn, - BT_HCI_ERR_REMOTE_USER_TERM_CONN); - if (err) { - printk("Disconnecting Broadcast Assistant failed (err %d)\n", - err); - - return err; - } - - err = k_sem_take(&sem_disconnected, SEM_TIMEOUT); - if (err != 0) { - printk("Failed to take sem_disconnected: %d\n", err); - - return err; - } - } - - if (ext_adv != NULL) { - stop_adv(); - } - - k_sem_reset(&sem_connected); - k_sem_reset(&sem_disconnected); - k_sem_reset(&sem_pa_request); - k_sem_reset(&sem_past_request); - } - - k_sem_reset(&sem_broadcaster_found); - k_sem_reset(&sem_pa_synced); - k_sem_reset(&sem_base_received); - k_sem_reset(&sem_syncable); - k_sem_reset(&sem_pa_sync_lost); - k_sem_reset(&sem_broadcast_code_received); - k_sem_reset(&sem_bis_sync_requested); - k_sem_reset(&sem_bis_synced); - return 0; -} - -static int start_adv(void) -{ - const struct bt_data ad[] = { - BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, - BT_UUID_16_ENCODE(BT_UUID_BASS_VAL), - BT_UUID_16_ENCODE(BT_UUID_PACS_VAL)), - BT_DATA_BYTES(BT_DATA_SVC_DATA16, BT_UUID_16_ENCODE(BT_UUID_BASS_VAL)), - BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, - sizeof(CONFIG_BT_DEVICE_NAME) - 1), - }; - int err; - - /* Create a non-connectable non-scannable advertising set */ - err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &ext_adv); - if (err != 0) { - printk("Failed to create advertising set (err %d)\n", err); - - return err; - } - - err = bt_le_ext_adv_set_data(ext_adv, ad, ARRAY_SIZE(ad), NULL, 0); - if (err != 0) { - printk("Failed to set advertising data (err %d)\n", err); - - return err; - } - - err = bt_le_ext_adv_start(ext_adv, BT_LE_EXT_ADV_START_DEFAULT); - if (err != 0) { - printk("Failed to start advertising set (err %d)\n", err); - - return err; - } - - return 0; -} - -static int stop_adv(void) -{ - int err; - - err = bt_le_ext_adv_stop(ext_adv); - if (err != 0) { - printk("Failed to stop advertising set (err %d)\n", err); - - return err; - } - - err = bt_le_ext_adv_delete(ext_adv); - if (err != 0) { - printk("Failed to delete advertising set (err %d)\n", err); - - return err; - } - - ext_adv = NULL; - - return 0; -} - -static int pa_sync_create(void) -{ - struct bt_le_per_adv_sync_param create_params = {0}; - - bt_addr_le_copy(&create_params.addr, &broadcaster_addr); - create_params.options = BT_LE_PER_ADV_SYNC_OPT_FILTER_DUPLICATE; - create_params.sid = broadcaster_info.sid; - create_params.skip = PA_SYNC_SKIP; - create_params.timeout = interval_to_sync_timeout(broadcaster_info.interval); - - return bt_le_per_adv_sync_create(&create_params, &pa_sync); -} - -int main(void) -{ - int err; - - err = init(); - if (err) { - printk("Init failed (err %d)\n", err); - return 0; - } - - for (size_t i = 0U; i < ARRAY_SIZE(streams_p); i++) { - streams_p[i] = &streams[i].stream; -#if defined(CONFIG_LIBLC3) - k_mutex_init(&streams[i].lc3_decoder_mutex); -#endif /* defined(CONFIG_LIBLC3) */ - } - - while (true) { - uint32_t sync_bitfield; - - err = reset(); - if (err != 0) { - printk("Resetting failed: %d - Aborting\n", err); - - return 0; - } - - if (IS_ENABLED(CONFIG_SCAN_OFFLOAD)) { - printk("Starting advertising\n"); - err = start_adv(); - if (err != 0) { - printk("Unable to start advertising connectable: %d\n", - err); - - return 0; - } - - printk("Waiting for Broadcast Assistant\n"); - err = k_sem_take(&sem_connected, ADV_TIMEOUT); - if (err != 0) { - printk("No Broadcast Assistant connected\n"); - - err = stop_adv(); - if (err != 0) { - printk("Unable to stop advertising: %d\n", - err); - - return 0; - } - } else { - /* Wait for the PA request to determine if we - * should start scanning, or wait for PAST - */ - printk("Waiting for PA sync request\n"); - err = k_sem_take(&sem_pa_request, - BROADCAST_ASSISTANT_TIMEOUT); - if (err != 0) { - printk("sem_pa_request timed out, resetting\n"); - continue; - } - - if (k_sem_take(&sem_past_request, K_NO_WAIT) == 0) { - goto wait_for_pa_sync; - } /* else continue with scanning below */ - } - } - - if (strlen(CONFIG_TARGET_BROADCAST_NAME) > 0U) { - printk("Scanning for broadcast sources containing`" - CONFIG_TARGET_BROADCAST_NAME "`\n"); - } else { - printk("Scanning for broadcast sources\n"); - } - - err = bt_le_scan_start(BT_LE_SCAN_ACTIVE, NULL); - if (err != 0 && err != -EALREADY) { - printk("Unable to start scan for broadcast sources: %d\n", - err); - return 0; - } - - err = k_sem_take(&sem_broadcaster_found, SEM_TIMEOUT); - if (err != 0) { - printk("sem_broadcaster_found timed out, resetting\n"); - continue; - } - printk("Broadcast source found, waiting for PA sync\n"); - - err = bt_le_scan_stop(); - if (err != 0) { - printk("bt_le_scan_stop failed with %d, resetting\n", err); - continue; - } - - printk("Attempting to PA sync to the broadcaster with id 0x%06X\n", - broadcaster_broadcast_id); - err = pa_sync_create(); - if (err != 0) { - printk("Could not create Broadcast PA sync: %d, resetting\n", err); - continue; - } - -wait_for_pa_sync: - printk("Waiting for PA synced\n"); - err = k_sem_take(&sem_pa_synced, SEM_TIMEOUT); - if (err != 0) { - printk("sem_pa_synced timed out, resetting\n"); - continue; - } - - printk("Broadcast source PA synced, creating Broadcast Sink\n"); - err = bt_bap_broadcast_sink_create(pa_sync, broadcaster_broadcast_id, - &broadcast_sink); - if (err != 0) { - printk("Failed to create broadcast sink: %d\n", err); - continue; - } - - printk("Broadcast Sink created, waiting for BASE\n"); - err = k_sem_take(&sem_base_received, SEM_TIMEOUT); - if (err != 0) { - printk("sem_base_received timed out, resetting\n"); - continue; - } - printk("BASE received, waiting for syncable\n"); - - err = k_sem_take(&sem_syncable, SEM_TIMEOUT); - if (err != 0) { - printk("sem_syncable timed out, resetting\n"); - continue; - } - - /* sem_broadcast_code_received is also given if the - * broadcast is not encrypted - */ - printk("Waiting for broadcast code\n"); - err = k_sem_take(&sem_broadcast_code_received, SEM_TIMEOUT); - if (err != 0) { - printk("sem_broadcast_code_received timed out, resetting\n"); - continue; - } - - printk("Waiting for BIS sync request\n"); - err = k_sem_take(&sem_bis_sync_requested, SEM_TIMEOUT); - if (err != 0) { - printk("sem_bis_sync_requested timed out, resetting\n"); - continue; - } - - sync_bitfield = bis_index_bitfield & requested_bis_sync; - printk("Syncing to broadcast with bitfield: 0x%08x\n", sync_bitfield); - err = bt_bap_broadcast_sink_sync(broadcast_sink, sync_bitfield, streams_p, - sink_broadcast_code); - if (err != 0) { - printk("Unable to sync to broadcast source: %d\n", err); - return 0; - } - - printk("Waiting for BIG sync\n"); - err = k_sem_take(&sem_bis_synced, SEM_TIMEOUT); - if (err != 0) { - printk("sem_bis_synced timed out, resetting\n"); - continue; - } - - printk("Waiting for PA disconnected\n"); - k_sem_take(&sem_pa_sync_lost, K_FOREVER); - } - return 0; -} diff --git a/samples/bluetooth/broadcast_audio_source/CMakeLists.txt b/samples/bluetooth/broadcast_audio_source/CMakeLists.txt deleted file mode 100644 index 2b20af75d5689..0000000000000 --- a/samples/bluetooth/broadcast_audio_source/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(unicast_audio_server) - -target_sources(app PRIVATE - src/main.c -) - -zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/broadcast_audio_source/README.rst b/samples/bluetooth/broadcast_audio_source/README.rst deleted file mode 100644 index 67b576d40460f..0000000000000 --- a/samples/bluetooth/broadcast_audio_source/README.rst +++ /dev/null @@ -1,79 +0,0 @@ -.. zephyr:code-sample:: bluetooth_broadcast_audio_source - :name: Bluetooth: Broadcast Audio Source - :relevant-api: bluetooth - - Bluetooth: Broadcast Audio Source - -Overview -******** - -Application demonstrating the LE Audio broadcast audio source functionality. -Will start advertising extended advertising with audio flags, periodic advertising with the -broadcast audio source endpoint (BASE) and finally the BIGinfo together with -(mock) Audio (ISO) data. - -The broadcast source will reset every 30 seconds to show the full API. - -This sample can be found under -:zephyr_file:`samples/bluetooth/broadcast_audio_source` in the Zephyr tree. - -Check the :ref:`bluetooth samples section ` for general information. - -Requirements -************ - -* BlueZ running on the host, or -* A board with Bluetooth Low Energy 5.2 support - -Building and Running -******************** - -When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, -use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO -feature support. - -Building for an nrf5340dk -------------------------- - -You can build both the application core image and an appropriate controller image for the network -core with: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/broadcast_audio_source/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -If you prefer to only build the application core image, you can do so by doing instead: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/broadcast_audio_source/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - -In that case you can pair this application core image with the -:ref:`hci_ipc sample ` -:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. - -Building for a simulated nrf5340bsim ------------------------------------- - -Similarly to how you would for real HW, you can do: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/broadcast_audio_source/ - :board: nrf5340bsim/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. -For more information, check :ref:`this board documentation `. - -Building for a simulated nrf52_bsim ------------------------------------ - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/broadcast_audio_source/ - :board: nrf52_bsim - :goals: build - :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/broadcast_audio_source/overlay-bt_ll_sw_split.conf b/samples/bluetooth/broadcast_audio_source/overlay-bt_ll_sw_split.conf deleted file mode 100644 index c73ff9c3ea9b8..0000000000000 --- a/samples/bluetooth/broadcast_audio_source/overlay-bt_ll_sw_split.conf +++ /dev/null @@ -1,24 +0,0 @@ -# Zephyr Bluetooth Controller -CONFIG_BT_LL_SW_SPLIT=y - -# Zephyr Controller tested maximum advertising data that can be set in a single HCI command -CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 - -# Enable support for Broadcast ISO in Zephyr Bluetooth Controller -CONFIG_BT_CTLR_ADV_ISO=y - -# Sufficient ISO PDU length for any BAP LC3 presets (155) -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=155 - -# Number of supported streams -CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 -CONFIG_BT_CTLR_ISOAL_SOURCES=2 - -# FIXME: Host needs CONFIG_BT_ISO_TX_MTU + 4 bytes for sequence number, and optionally -# additional + 4 bytes for timestamp when not using BT_ISO_TIMESTAMP_NONE in bt_iso_chan_send(), -# otherwise Host tries to fragment ISO data. -# When Host is fixed, CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE can inherit the -# CONFIG_BT_ISO_TX_MTU value. -# -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 diff --git a/samples/bluetooth/broadcast_audio_source/sample.yaml b/samples/bluetooth/broadcast_audio_source/sample.yaml deleted file mode 100644 index 047323dd3c72e..0000000000000 --- a/samples/bluetooth/broadcast_audio_source/sample.yaml +++ /dev/null @@ -1,29 +0,0 @@ -sample: - description: Bluetooth Low Energy Broadcast Audio Source sample - name: Bluetooth Low Energy Broadcast Audio Source sample -tests: - sample.bluetooth.broadcast_audio_source: - harness: bluetooth - platform_allow: - - qemu_cortex_m3 - - qemu_x86 - - nrf5340dk/nrf5340/cpuapp - - nrf5340bsim/nrf5340/cpuapp - integration_platforms: - - qemu_x86 - - nrf5340dk/nrf5340/cpuapp - tags: bluetooth - sysbuild: true - sample.bluetooth.broadcast_audio_source.bt_ll_sw_split: - harness: bluetooth - platform_allow: - - nrf52_bsim - - nrf52833dk/nrf52820 - - nrf52833dk/nrf52833 - - nrf52840dongle/nrf52840 - integration_platforms: - - nrf52_bsim - - nrf52833dk/nrf52833 - - nrf52840dongle/nrf52840 - extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf - tags: bluetooth diff --git a/samples/bluetooth/broadcast_audio_source/src/main.c b/samples/bluetooth/broadcast_audio_source/src/main.c deleted file mode 100644 index dee7de02a8a32..0000000000000 --- a/samples/bluetooth/broadcast_audio_source/src/main.c +++ /dev/null @@ -1,655 +0,0 @@ -/* - * Copyright (c) 2022-2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include - -BUILD_ASSERT(strlen(CONFIG_BROADCAST_CODE) <= BT_AUDIO_BROADCAST_CODE_SIZE, - "Invalid broadcast code"); - -/* Zephyr Controller works best while Extended Advertising interval to be a multiple - * of the ISO Interval minus 10 ms (max. advertising random delay). This is - * required to place the AUX_ADV_IND PDUs in a non-overlapping interval with the - * Broadcast ISO radio events. - * - * I.e. for a 7.5 ms ISO interval use 90 ms minus 10 ms ==> 80 ms advertising - * interval. - * And, for 10 ms ISO interval, can use 90 ms minus 10 ms ==> 80 ms advertising - * interval. - */ -#define BT_LE_EXT_ADV_CUSTOM \ - BT_LE_ADV_PARAM(BT_LE_ADV_OPT_EXT_ADV, 0x0080, 0x0080, NULL) - -/* When BROADCAST_ENQUEUE_COUNT > 1 we can enqueue enough buffers to ensure that - * the controller is never idle - */ -#define BROADCAST_ENQUEUE_COUNT 3U -#define TOTAL_BUF_NEEDED (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT) - -BUILD_ASSERT(CONFIG_BT_ISO_TX_BUF_COUNT >= TOTAL_BUF_NEEDED, - "CONFIG_BT_ISO_TX_BUF_COUNT should be at least " - "BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT"); - -#if defined(CONFIG_BAP_BROADCAST_16_2_1) - -static struct bt_bap_lc3_preset preset_active = BT_BAP_LC3_BROADCAST_PRESET_16_2_1( - BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT, - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); - -#define BROADCAST_SAMPLE_RATE 16000 - -#elif defined(CONFIG_BAP_BROADCAST_24_2_1) - -static struct bt_bap_lc3_preset preset_active = BT_BAP_LC3_BROADCAST_PRESET_24_2_1( - BT_AUDIO_LOCATION_FRONT_LEFT | BT_AUDIO_LOCATION_FRONT_RIGHT, - BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); - -#define BROADCAST_SAMPLE_RATE 24000 - -#endif - -#if defined(CONFIG_BAP_BROADCAST_16_2_1) -#define MAX_SAMPLE_RATE 16000 -#elif defined(CONFIG_BAP_BROADCAST_24_2_1) -#define MAX_SAMPLE_RATE 24000 -#endif -#define MAX_FRAME_DURATION_US 10000 -#define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC) - -#if defined(CONFIG_LIBLC3) -#include "lc3.h" - -#if defined(CONFIG_USB_DEVICE_AUDIO) -#include -#include -#include - -/* USB Audio Data is downsampled from 48kHz to match broadcast preset when receiving data */ -#define USB_SAMPLE_RATE 48000 -#define USB_DOWNSAMPLE_RATE BROADCAST_SAMPLE_RATE -#define USB_FRAME_DURATION_US 1000 -#define USB_NUM_SAMPLES ((USB_FRAME_DURATION_US * USB_DOWNSAMPLE_RATE) / USEC_PER_SEC) -#define USB_BYTES_PER_SAMPLE 2 -#define USB_CHANNELS 2 - -#define RING_BUF_USB_FRAMES 20 -#define AUDIO_RING_BUF_BYTES USB_NUM_SAMPLES * USB_BYTES_PER_SAMPLE * RING_BUF_USB_FRAMES -#else /* !defined(CONFIG_USB_DEVICE_AUDIO) */ - -#include - -#define AUDIO_VOLUME (INT16_MAX - 3000) /* codec does clipping above INT16_MAX - 3000 */ -#define AUDIO_TONE_FREQUENCY_HZ 400 - -/** - * Use the math lib to generate a sine-wave using 16 bit samples into a buffer. - * - * @param buf Destination buffer - * @param length_us Length of the buffer in microseconds - * @param frequency_hz frequency in Hz - * @param sample_rate_hz sample-rate in Hz. - */ -static void fill_audio_buf_sin(int16_t *buf, int length_us, int frequency_hz, int sample_rate_hz) -{ - const int sine_period_samples = sample_rate_hz / frequency_hz; - const unsigned int num_samples = (length_us * sample_rate_hz) / USEC_PER_SEC; - const float step = 2 * 3.1415f / sine_period_samples; - - for (unsigned int i = 0; i < num_samples; i++) { - const float sample = sinf(i * step); - - buf[i] = (int16_t)(AUDIO_VOLUME * sample); - } -} -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ -#endif /* defined(CONFIG_LIBLC3) */ - -static struct broadcast_source_stream { - struct bt_bap_stream stream; - uint16_t seq_num; - size_t sent_cnt; -#if defined(CONFIG_LIBLC3) - lc3_encoder_t lc3_encoder; -#if defined(CONFIG_BAP_BROADCAST_16_2_1) - lc3_encoder_mem_16k_t lc3_encoder_mem; -#elif defined(CONFIG_BAP_BROADCAST_24_2_1) - lc3_encoder_mem_48k_t lc3_encoder_mem; -#endif -#if defined(CONFIG_USB_DEVICE_AUDIO) - struct ring_buf audio_ring_buf; - uint8_t _ring_buffer_memory[AUDIO_RING_BUF_BYTES]; -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ -#endif /* defined(CONFIG_LIBLC3) */ -} streams[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; -static struct bt_bap_broadcast_source *broadcast_source; - -NET_BUF_POOL_FIXED_DEFINE(tx_pool, - TOTAL_BUF_NEEDED, - BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), - CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); - -static int16_t send_pcm_data[MAX_NUM_SAMPLES]; -static uint16_t seq_num; -static bool stopping; - -static K_SEM_DEFINE(sem_started, 0U, ARRAY_SIZE(streams)); -static K_SEM_DEFINE(sem_stopped, 0U, ARRAY_SIZE(streams)); - -#define BROADCAST_SOURCE_LIFETIME 120U /* seconds */ - -#if defined(CONFIG_LIBLC3) -static int freq_hz; -static int frame_duration_us; -static int frames_per_sdu; -static int octets_per_frame; - -static K_SEM_DEFINE(lc3_encoder_sem, 0U, TOTAL_BUF_NEEDED); -#endif - -static void send_data(struct broadcast_source_stream *source_stream) -{ - struct bt_bap_stream *stream = &source_stream->stream; - struct net_buf *buf; - int ret; - - if (stopping) { - return; - } - - buf = net_buf_alloc(&tx_pool, K_FOREVER); - if (buf == NULL) { - printk("Could not allocate buffer when sending on %p\n", - stream); - return; - } - - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); -#if defined(CONFIG_LIBLC3) - uint8_t lc3_encoded_buffer[preset_active.qos.sdu]; - - if (source_stream->lc3_encoder == NULL) { - printk("LC3 encoder not setup, cannot encode data.\n"); - net_buf_unref(buf); - return; - } - -#if defined(CONFIG_USB_DEVICE_AUDIO) - uint32_t size = ring_buf_get(&source_stream->audio_ring_buf, - (uint8_t *)send_pcm_data, sizeof(send_pcm_data)); - - if (size < sizeof(send_pcm_data)) { - const size_t padding_size = sizeof(send_pcm_data) - size; - - printk("Not enough bytes ready, padding %d!\n", padding_size); - memset(&((uint8_t *)send_pcm_data)[size], 0, padding_size); - } -#endif - - ret = lc3_encode(source_stream->lc3_encoder, LC3_PCM_FORMAT_S16, - send_pcm_data, 1, octets_per_frame, lc3_encoded_buffer); - if (ret == -1) { - printk("LC3 encoder failed - wrong parameters?: %d", ret); - net_buf_unref(buf); - return; - } - - net_buf_add_mem(buf, lc3_encoded_buffer, preset_active.qos.sdu); -#else - net_buf_add_mem(buf, send_pcm_data, preset_active.qos.sdu); -#endif /* defined(CONFIG_LIBLC3) */ - - ret = bt_bap_stream_send(stream, buf, source_stream->seq_num++); - if (ret < 0) { - /* This will end broadcasting on this stream. */ - printk("Unable to broadcast data on %p: %d\n", stream, ret); - net_buf_unref(buf); - return; - } - - source_stream->sent_cnt++; - if ((source_stream->sent_cnt % 1000U) == 0U) { - printk("Stream %p: Sent %u total ISO packets\n", stream, source_stream->sent_cnt); - } -} - -#if defined(CONFIG_LIBLC3) -static void init_lc3_thread(void *arg1, void *arg2, void *arg3) -{ - const struct bt_audio_codec_cfg *codec_cfg = &preset_active.codec_cfg; - int ret; - - ret = bt_audio_codec_cfg_get_freq(codec_cfg); - if (ret > 0) { - freq_hz = bt_audio_codec_cfg_freq_to_freq_hz(ret); - } else { - return; - } - - ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); - if (ret > 0) { - frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); - } else { - printk("Error: Frame duration not set, cannot start codec."); - return; - } - - octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); - frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true); - - if (freq_hz < 0) { - printk("Error: Codec frequency not set, cannot start codec."); - return; - } - - if (frame_duration_us < 0) { - printk("Error: Frame duration not set, cannot start codec."); - return; - } - - if (octets_per_frame < 0) { - printk("Error: Octets per frame not set, cannot start codec."); - return; - } - -#if !defined(CONFIG_USB_DEVICE_AUDIO) - /* If USB is not used as a sound source, generate a sine wave */ - fill_audio_buf_sin(send_pcm_data, frame_duration_us, AUDIO_TONE_FREQUENCY_HZ, freq_hz); -#endif - - /* Create the encoder instance. This shall complete before stream_started() is called. */ - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - printk("Initializing lc3 encoder for stream %zu\n", i); - streams[i].lc3_encoder = lc3_setup_encoder(frame_duration_us, freq_hz, - 0, &streams[i].lc3_encoder_mem); - - if (streams[i].lc3_encoder == NULL) { - printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n"); - } - } - - while (true) { - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - k_sem_take(&lc3_encoder_sem, K_FOREVER); - } - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - send_data(&streams[i]); - } - } -} - -#define LC3_ENCODER_STACK_SIZE 4 * 4096 -#define LC3_ENCODER_PRIORITY 5 - -K_THREAD_DEFINE(encoder, LC3_ENCODER_STACK_SIZE, init_lc3_thread, - NULL, NULL, NULL, LC3_ENCODER_PRIORITY, 0, -1); - -#if defined(CONFIG_USB_DEVICE_AUDIO) -static void data_received(const struct device *dev, - struct net_buf *buffer, - size_t size) -{ - static int count; - int16_t *pcm; - int nsamples, ratio; - int16_t usb_pcm_data[USB_CHANNELS][USB_NUM_SAMPLES]; - - if (!buffer) { - return; - } - - if (!size) { - net_buf_unref(buffer); - return; - } - - pcm = (int16_t *)net_buf_pull_mem(buffer, size); - - /* 'size' is in bytes, containing 1ms, 48kHz, stereo, 2 bytes per sample. - * Take left channel and do a simple downsample to 16kHz/24Khz - * matching the broadcast preset. - */ - - ratio = USB_SAMPLE_RATE / USB_DOWNSAMPLE_RATE; - nsamples = size / (sizeof(int16_t) * USB_CHANNELS * ratio); - for (size_t i = 0, j = 0; i < nsamples; i++, j += USB_CHANNELS * ratio) { - usb_pcm_data[0][i] = pcm[j]; - usb_pcm_data[1][i] = pcm[j + 1]; - } - - for (size_t i = 0U; i < MIN(ARRAY_SIZE(streams), 2); i++) { - const uint32_t size_put = ring_buf_put(&(streams[i].audio_ring_buf), - (uint8_t *)(usb_pcm_data[i]), nsamples * USB_BYTES_PER_SAMPLE); - if (size_put < nsamples * USB_BYTES_PER_SAMPLE) { - printk("Not enough room for samples in %s buffer: %u < %u, total capacity: %u\n", - i == 0 ? "left" : "right", - size_put, - nsamples * USB_BYTES_PER_SAMPLE, - ring_buf_capacity_get(&(streams[i].audio_ring_buf))); - } - } - - count++; - if ((count % 1000) == 0) { - printk("USB Data received (count = %d)\n", count); - } - - net_buf_unref(buffer); -} - -static const struct usb_audio_ops ops = { - .data_received_cb = data_received -}; -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ -#endif /* defined(CONFIG_LIBLC3) */ - -static void stream_started_cb(struct bt_bap_stream *stream) -{ - struct broadcast_source_stream *source_stream = - CONTAINER_OF(stream, struct broadcast_source_stream, stream); - - source_stream->seq_num = 0U; - source_stream->sent_cnt = 0U; - k_sem_give(&sem_started); -} - -static void stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) -{ - k_sem_give(&sem_stopped); -} - -static void stream_sent_cb(struct bt_bap_stream *stream) -{ -#if defined(CONFIG_LIBLC3) - k_sem_give(&lc3_encoder_sem); -#else - /* If no LC3 encoder is used, just send mock data directly */ - struct broadcast_source_stream *source_stream = - CONTAINER_OF(stream, struct broadcast_source_stream, stream); - - send_data(source_stream); -#endif -} - -static struct bt_bap_stream_ops stream_ops = { - .started = stream_started_cb, - .stopped = stream_stopped_cb, - .sent = stream_sent_cb -}; - -static int setup_broadcast_source(struct bt_bap_broadcast_source **source) -{ - struct bt_bap_broadcast_source_stream_param - stream_params[CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT]; - struct bt_bap_broadcast_source_subgroup_param - subgroup_param[CONFIG_BT_BAP_BROADCAST_SRC_SUBGROUP_COUNT]; - struct bt_bap_broadcast_source_param create_param = {0}; - const size_t streams_per_subgroup = ARRAY_SIZE(stream_params) / ARRAY_SIZE(subgroup_param); - uint8_t left[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_CHAN_ALLOC, - BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_LEFT))}; - uint8_t right[] = {BT_AUDIO_CODEC_DATA(BT_AUDIO_CODEC_CFG_CHAN_ALLOC, - BT_BYTES_LIST_LE32(BT_AUDIO_LOCATION_FRONT_RIGHT))}; - int err; - - for (size_t i = 0U; i < ARRAY_SIZE(subgroup_param); i++) { - subgroup_param[i].params_count = streams_per_subgroup; - subgroup_param[i].params = stream_params + i * streams_per_subgroup; - subgroup_param[i].codec_cfg = &preset_active.codec_cfg; - } - - for (size_t j = 0U; j < ARRAY_SIZE(stream_params); j++) { - stream_params[j].stream = &streams[j].stream; - stream_params[j].data = j == 0 ? left : right; - stream_params[j].data_len = j == 0 ? sizeof(left) : sizeof(right); - bt_bap_stream_cb_register(stream_params[j].stream, &stream_ops); - } - - create_param.params_count = ARRAY_SIZE(subgroup_param); - create_param.params = subgroup_param; - create_param.qos = &preset_active.qos; - create_param.encryption = strlen(CONFIG_BROADCAST_CODE) > 0; - create_param.packing = BT_ISO_PACKING_SEQUENTIAL; - - if (create_param.encryption) { - memcpy(create_param.broadcast_code, CONFIG_BROADCAST_CODE, - strlen(CONFIG_BROADCAST_CODE)); - } - - printk("Creating broadcast source with %zu subgroups with %zu streams\n", - ARRAY_SIZE(subgroup_param), - ARRAY_SIZE(subgroup_param) * streams_per_subgroup); - - err = bt_bap_broadcast_source_create(&create_param, source); - if (err != 0) { - printk("Unable to create broadcast source: %d\n", err); - return err; - } - - return 0; -} - -static const struct bt_data ad[] = { - BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), -}; - -int main(void) -{ - struct bt_le_ext_adv *adv; - int err; - - err = bt_enable(NULL); - if (err) { - printk("Bluetooth init failed (err %d)\n", err); - return 0; - } - printk("Bluetooth initialized\n"); - - for (size_t i = 0U; i < ARRAY_SIZE(send_pcm_data); i++) { - /* Initialize mock data */ - send_pcm_data[i] = i; - } - -#if defined(CONFIG_LIBLC3) -#if defined(CONFIG_USB_DEVICE_AUDIO) - const struct device *hs_dev; - - hs_dev = DEVICE_DT_GET(DT_NODELABEL(hs_0)); - - if (!device_is_ready(hs_dev)) { - printk("Device USB Headset is not ready\n"); - return 0; - } - - printk("Found USB Headset Device\n"); - - (void)memset(streams, 0, sizeof(streams)); - - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - ring_buf_init(&(streams[i].audio_ring_buf), - sizeof(streams[i]._ring_buffer_memory), - streams[i]._ring_buffer_memory); - printk("Initialized ring buf %zu: capacity: %u\n", i, - ring_buf_capacity_get(&(streams[i].audio_ring_buf))); - } - - usb_audio_register(hs_dev, &ops); - - err = usb_enable(NULL); - if (err && err != -EALREADY) { - printk("Failed to enable USB (%d)", err); - return 0; - } - -#endif /* defined(CONFIG_USB_DEVICE_AUDIO) */ - k_thread_start(encoder); -#endif /* defined(CONFIG_LIBLC3) */ - - while (true) { - /* Broadcast Audio Streaming Endpoint advertising data */ - NET_BUF_SIMPLE_DEFINE(ad_buf, - BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); - NET_BUF_SIMPLE_DEFINE(base_buf, 128); - struct bt_data ext_ad; - struct bt_data per_ad; - uint32_t broadcast_id; - - /* Create a non-connectable non-scannable advertising set */ - err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CUSTOM, NULL, &adv); - if (err != 0) { - printk("Unable to create extended advertising set: %d\n", - err); - return 0; - } - - err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0); - if (err) { - printk("Failed to set advertising data (err %d)\n", err); - return 0; - } - - /* Set periodic advertising parameters */ - err = bt_le_per_adv_set_param(adv, BT_LE_PER_ADV_DEFAULT); - if (err) { - printk("Failed to set periodic advertising parameters" - " (err %d)\n", err); - return 0; - } - - printk("Creating broadcast source\n"); - err = setup_broadcast_source(&broadcast_source); - if (err != 0) { - printk("Unable to setup broadcast source: %d\n", err); - return 0; - } - - err = bt_bap_broadcast_source_get_id(broadcast_source, &broadcast_id); - if (err != 0) { - printk("Unable to get broadcast ID: %d\n", err); - return 0; - } - - /* Setup extended advertising data */ - net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); - net_buf_simple_add_le24(&ad_buf, broadcast_id); - ext_ad.type = BT_DATA_SVC_DATA16; - ext_ad.data_len = ad_buf.len; - ext_ad.data = ad_buf.data; - err = bt_le_ext_adv_set_data(adv, &ext_ad, 1, NULL, 0); - if (err != 0) { - printk("Failed to set extended advertising data: %d\n", - err); - return 0; - } - - /* Setup periodic advertising data */ - err = bt_bap_broadcast_source_get_base(broadcast_source, &base_buf); - if (err != 0) { - printk("Failed to get encoded BASE: %d\n", err); - return 0; - } - - per_ad.type = BT_DATA_SVC_DATA16; - per_ad.data_len = base_buf.len; - per_ad.data = base_buf.data; - err = bt_le_per_adv_set_data(adv, &per_ad, 1); - if (err != 0) { - printk("Failed to set periodic advertising data: %d\n", - err); - return 0; - } - - /* Start extended advertising */ - err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); - if (err) { - printk("Failed to start extended advertising: %d\n", - err); - return 0; - } - - /* Enable Periodic Advertising */ - err = bt_le_per_adv_start(adv); - if (err) { - printk("Failed to enable periodic advertising: %d\n", - err); - return 0; - } - - printk("Starting broadcast source\n"); - stopping = false; - err = bt_bap_broadcast_source_start(broadcast_source, adv); - if (err != 0) { - printk("Unable to start broadcast source: %d\n", err); - return 0; - } - - /* Wait for all to be started */ - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - k_sem_take(&sem_started, K_FOREVER); - } - printk("Broadcast source started\n"); - - /* Initialize sending */ - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) { - stream_sent_cb(&streams[i].stream); - } - } - -#if defined(CONFIG_LIBLC3) && defined(CONFIG_USB_DEVICE_AUDIO) - /* Never stop streaming when using USB Audio as input */ - k_sleep(K_FOREVER); -#endif /* defined(CONFIG_LIBLC3) && defined(CONFIG_USB_DEVICE_AUDIO) */ - printk("Waiting %u seconds before stopped\n", - BROADCAST_SOURCE_LIFETIME); - k_sleep(K_SECONDS(BROADCAST_SOURCE_LIFETIME)); - printk("Stopping broadcast source\n"); - stopping = true; - err = bt_bap_broadcast_source_stop(broadcast_source); - if (err != 0) { - printk("Unable to stop broadcast source: %d\n", err); - return 0; - } - - /* Wait for all to be stopped */ - for (size_t i = 0U; i < ARRAY_SIZE(streams); i++) { - k_sem_take(&sem_stopped, K_FOREVER); - } - printk("Broadcast source stopped\n"); - - printk("Deleting broadcast source\n"); - err = bt_bap_broadcast_source_delete(broadcast_source); - if (err != 0) { - printk("Unable to delete broadcast source: %d\n", err); - return 0; - } - printk("Broadcast source deleted\n"); - broadcast_source = NULL; - seq_num = 0; - - err = bt_le_per_adv_stop(adv); - if (err) { - printk("Failed to stop periodic advertising (err %d)\n", - err); - return 0; - } - - err = bt_le_ext_adv_stop(adv); - if (err) { - printk("Failed to stop extended advertising (err %d)\n", - err); - return 0; - } - - err = bt_le_ext_adv_delete(adv); - if (err) { - printk("Failed to delete extended advertising (err %d)\n", - err); - return 0; - } - } - return 0; -} diff --git a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c index 8da6984ee55d6..f2e7127b406bd 100644 --- a/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c +++ b/samples/bluetooth/broadcaster_multiple/src/broadcaster_multiple.c @@ -88,7 +88,7 @@ int broadcaster_multiple(void) /* Use advertising set instance index as SID */ adv_param.sid = index; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(&adv_param, NULL, &adv[index]); if (err) { printk("Failed to create advertising set %d (err %d)\n", diff --git a/samples/bluetooth/cap_acceptor/CMakeLists.txt b/samples/bluetooth/cap_acceptor/CMakeLists.txt new file mode 100644 index 0000000000000..f8d344cc9810f --- /dev/null +++ b/samples/bluetooth/cap_acceptor/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(cap_acceptor) + +target_sources(app PRIVATE + src/main.c + src/cap_acceptor_unicast.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/unicast_audio_server/Kconfig.sysbuild b/samples/bluetooth/cap_acceptor/Kconfig.sysbuild similarity index 100% rename from samples/bluetooth/unicast_audio_server/Kconfig.sysbuild rename to samples/bluetooth/cap_acceptor/Kconfig.sysbuild diff --git a/samples/bluetooth/cap_acceptor/README.rst b/samples/bluetooth/cap_acceptor/README.rst new file mode 100644 index 0000000000000..dce148cfd0116 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/README.rst @@ -0,0 +1,74 @@ +.. zephyr:code-sample:: bluetooth_cap_acceptor + :name: Bluetooth: Common Audio Profile Acceptor + :relevant-api: bt_cap bt_bap bluetooth + + CAP Acceptor sample that advertises audio availability to CAP Initiators. + +Overview +******** + +Application demonstrating the CAP Acceptor functionality. +Starts by advertising for a CAP Initiator to connect and set up available streams. + +This sample can be found under :zephyr_file:`samples/bluetooth/cap_acceptor` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use ``-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf`` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_acceptor/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_acceptor/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_acceptor/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_acceptor/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..96dc0eb4e3b2c --- /dev/null +++ b/samples/bluetooth/cap_acceptor/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -0,0 +1,6 @@ +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..96dc0eb4e3b2c --- /dev/null +++ b/samples/bluetooth/cap_acceptor/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,6 @@ +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/cap_acceptor/overlay-bt_ll_sw_split.conf b/samples/bluetooth/cap_acceptor/overlay-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..e4bcdbad7c533 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/overlay-bt_ll_sw_split.conf @@ -0,0 +1,13 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Zephyr Controller tested maximum advertising data that can be set in a single HCI command +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 + +# Enable support for central ISO in Zephyr Bluetooth Controller +CONFIG_BT_CTLR_PERIPHERAL_ISO=y + +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 diff --git a/samples/bluetooth/cap_acceptor/prj.conf b/samples/bluetooth/cap_acceptor/prj.conf new file mode 100644 index 0000000000000..4a67de1e58226 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/prj.conf @@ -0,0 +1,36 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_PERIPHERAL=y +CONFIG_BT_ISO_PERIPHERAL=y +CONFIG_BT_GATT_DYNAMIC_DB=y +CONFIG_BT_GATT_CLIENT=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_DEVICE_NAME="CAP Acceptor" + +CONFIG_BT_AUDIO=y + +CONFIG_BT_SMP=y +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y + +# CAP +CONFIG_BT_CAP_ACCEPTOR=y + +# BAP support +CONFIG_BT_BAP_UNICAST_SERVER=y + +# Mandatory to support at least 1 for ASCS +CONFIG_BT_ATT_PREPARE_COUNT=1 + +# Support an ISO channel per ASE +CONFIG_BT_ASCS=y +CONFIG_BT_ASCS_ASE_SNK_COUNT=1 +CONFIG_BT_ASCS_ASE_SRC_COUNT=1 + +# Support an ISO channel per ASE +CONFIG_BT_ISO_MAX_CHAN=2 + +# PACS +CONFIG_BT_PAC_SNK=y +CONFIG_BT_PAC_SNK_LOC=y +CONFIG_BT_PAC_SRC=y +CONFIG_BT_PAC_SRC_LOC=y diff --git a/samples/bluetooth/cap_acceptor/sample.yaml b/samples/bluetooth/cap_acceptor/sample.yaml new file mode 100644 index 0000000000000..6be99aab18382 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/sample.yaml @@ -0,0 +1,30 @@ +sample: + description: Bluetooth Low Energy Common Audio Profile Acceptor sample + name: Bluetooth Low Energy Common Audio Profile Acceptor sample +tests: + sample.bluetooth.cap_acceptor: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + - nrf5340bsim/nrf5340/cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.cap_acceptor.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52840 + - nrf52840dongle/nrf52840 + integration_platforms: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52840 + - nrf52840dongle/nrf52840 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/cap_acceptor/src/cap_acceptor.h b/samples/bluetooth/cap_acceptor/src/cap_acceptor.h new file mode 100644 index 0000000000000..7db7dec601924 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/src/cap_acceptor.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#define SINK_CONTEXT BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED +#define SOURCE_CONTEXT BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED + +/** Struct to contain information for a specific peer (CAP) device */ +struct peer_config { + /** Stream for the source endpoint */ + struct bt_cap_stream source_stream; + /** Stream for the sink endpoint */ + struct bt_cap_stream sink_stream; + /** Semaphore to help wait for a release operation if the source stream is not idle */ + struct k_sem source_stream_sem; + /** Semaphore to help wait for a release operation if the sink stream is not idle */ + struct k_sem sink_stream_sem; + /** ACL connection object for the peer device */ + struct bt_conn *conn; + /** Current sequence number for TX */ + uint16_t tx_seq_num; +}; + +/** + * @brief Initialize the unicast part of the CAP Acceptor + * + * @param peer Pointer to the specific peer to initialize the CAP Acceptor for + * + * @retval 0 if success + * @retval -ENOEXEC if callbacks failed to be registered + */ +int init_cap_acceptor_unicast(struct peer_config *peer); + +/** + * @brief Request to allocate a CAP stream + * + * @param dir Audio direction of the stream to allocate + * + * @retval Pointer to the allocated CAP stream + * @retval NULL if no more CAP streams for the @p dir could be allocated + */ +struct bt_cap_stream *stream_alloc(enum bt_audio_dir dir); + +/** + * Notify about a released stream + + * This is used to handle some state checks in the main.c file. + * + * @param cap_stream Pointer to the stream that was released + */ +void stream_released(const struct bt_cap_stream *cap_stream); diff --git a/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c new file mode 100644 index 0000000000000..9015eb409955a --- /dev/null +++ b/samples/bluetooth/cap_acceptor/src/cap_acceptor_unicast.c @@ -0,0 +1,436 @@ +/** @file + * @brief Bluetooth Common Audio Profile (CAP) Acceptor unicast. + * + * Copyright (c) 2021-2024 Nordic Semiconductor ASA + * Copyright (c) 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cap_acceptor.h" + +LOG_MODULE_REGISTER(cap_acceptor_unicast, LOG_LEVEL_INF); + +#define PREF_PHY BT_GAP_LE_PHY_2M +#define MIN_PD 20000U +#define MAX_PD 40000U +#define UNFRAMED_SUPPORTED true +#define LATENCY 20U +#define RTN 2U + +static const struct bt_audio_codec_qos_pref qos_pref = BT_AUDIO_CODEC_QOS_PREF( + UNFRAMED_SUPPORTED, PREF_PHY, RTN, LATENCY, MIN_PD, MAX_PD, MIN_PD, MAX_PD); +uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */ + +static bool log_codec_cfg_cb(struct bt_data *data, void *user_data) +{ + const char *str = (const char *)user_data; + + LOG_DBG("\t%s: type 0x%02x value_len %u", str, data->type, data->data_len); + LOG_HEXDUMP_DBG(data->data, data->data_len, "\t\tdata"); + + return true; +} + +static void log_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) +{ + LOG_INF("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u", codec_cfg->id, codec_cfg->cid, + codec_cfg->vid, codec_cfg->data_len); + + if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { + enum bt_audio_location chan_allocation; + int ret; + + /* LC3 uses the generic LTV format - other codecs might do as well */ + + bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, log_codec_cfg_cb, "data"); + + ret = bt_audio_codec_cfg_get_freq(codec_cfg); + if (ret > 0) { + LOG_INF("\tFrequency: %d Hz", bt_audio_codec_cfg_freq_to_freq_hz(ret)); + } + + ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); + if (ret > 0) { + LOG_INF("\tFrame Duration: %d us", + bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); + } + + if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, true) == + 0) { + LOG_INF("\tChannel allocation: 0x%08X", chan_allocation); + } + + ret = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); + if (ret > 0) { + LOG_INF("\tOctets per frame: %d", ret); + } + + LOG_INF("\tFrames per SDU: %d", + bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true)); + } else { + LOG_HEXDUMP_DBG(codec_cfg->data, codec_cfg->data_len, "data"); + } + + bt_audio_data_parse(codec_cfg->meta, codec_cfg->meta_len, log_codec_cfg_cb, "meta"); +} + +static void log_qos(const struct bt_audio_codec_qos *qos) +{ + LOG_INF("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u rtn %u latency %u pd %u", + qos->interval, qos->framing, qos->phy, qos->sdu, qos->rtn, qos->latency, qos->pd); +} + +static int unicast_server_config_cb(struct bt_conn *conn, const struct bt_bap_ep *ep, + enum bt_audio_dir dir, + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_bap_stream **bap_stream, + struct bt_audio_codec_qos_pref *const pref, + struct bt_bap_ascs_rsp *rsp) +{ + struct bt_cap_stream *cap_stream; + + LOG_INF("ASE Codec Config: conn %p ep %p dir %u", (void *)conn, (void *)ep, dir); + + log_codec_cfg(codec_cfg); + + cap_stream = stream_alloc(dir); + if (cap_stream == NULL) { + LOG_WRN("No streams available"); + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM, BT_BAP_ASCS_REASON_NONE); + + return -ENOMEM; + } + + *bap_stream = &cap_stream->bap_stream; + + LOG_INF("ASE Codec Config bap_stream %p", *bap_stream); + + *pref = qos_pref; + + return 0; +} + +static int unicast_server_reconfig_cb(struct bt_bap_stream *bap_stream, enum bt_audio_dir dir, + const struct bt_audio_codec_cfg *codec_cfg, + struct bt_audio_codec_qos_pref *const pref, + struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("ASE Codec Reconfig: bap_stream %p", bap_stream); + log_codec_cfg(codec_cfg); + *pref = qos_pref; + + return 0; +} + +static int unicast_server_qos_cb(struct bt_bap_stream *bap_stream, + const struct bt_audio_codec_qos *qos, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("QoS: bap_stream %p qos %p", bap_stream, qos); + + log_qos(qos); + + return 0; +} + +static int unicast_server_enable_cb(struct bt_bap_stream *bap_stream, const uint8_t meta[], + size_t meta_len, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Enable: bap_stream %p meta_len %zu", bap_stream, meta_len); + + return 0; +} + +static int unicast_server_start_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Start: bap_stream %p", bap_stream); + + return 0; +} + +struct data_func_param { + struct bt_bap_ascs_rsp *rsp; + bool stream_context_present; +}; + +static bool data_func_cb(struct bt_data *data, void *user_data) +{ + struct data_func_param *func_param = (struct data_func_param *)user_data; + + if (data->type == BT_AUDIO_METADATA_TYPE_STREAM_CONTEXT) { + func_param->stream_context_present = true; + } + + return true; +} + +static int unicast_server_metadata_cb(struct bt_bap_stream *bap_stream, const uint8_t meta[], + size_t meta_len, struct bt_bap_ascs_rsp *rsp) +{ + struct data_func_param func_param = { + .rsp = rsp, + .stream_context_present = false, + }; + int err; + + LOG_INF("Metadata: bap_stream %p meta_len %zu", bap_stream, meta_len); + + err = bt_audio_data_parse(meta, meta_len, data_func_cb, &func_param); + if (err != 0) { + return err; + } + + if (!func_param.stream_context_present) { + LOG_ERR("Stream audio context not present"); + *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED, + BT_BAP_ASCS_REASON_NONE); + + return -EINVAL; + } + + return 0; +} + +static int unicast_server_disable_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Disable: bap_stream %p", bap_stream); + + return 0; +} + +static int unicast_server_stop_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Stop: bap_stream %p", bap_stream); + + return 0; +} + +static int unicast_server_release_cb(struct bt_bap_stream *bap_stream, struct bt_bap_ascs_rsp *rsp) +{ + LOG_INF("Release: bap_stream %p", bap_stream); + + return 0; +} + +static const struct bt_bap_unicast_server_cb unicast_server_cb = { + .config = unicast_server_config_cb, + .reconfig = unicast_server_reconfig_cb, + .qos = unicast_server_qos_cb, + .enable = unicast_server_enable_cb, + .start = unicast_server_start_cb, + .metadata = unicast_server_metadata_cb, + .disable = unicast_server_disable_cb, + .stop = unicast_server_stop_cb, + .release = unicast_server_release_cb, +}; + +static void unicast_stream_configured_cb(struct bt_bap_stream *bap_stream, + const struct bt_audio_codec_qos_pref *pref) +{ + LOG_INF("Configured bap_stream %p", bap_stream); + + /* TODO: The preference should be used/taken into account when + * setting the QoS + */ + + LOG_INF("Local preferences: unframed %s, phy %u, rtn %u, latency %u, pd_min %u, pd_max " + "%u, pref_pd_min %u, pref_pd_max %u", + pref->unframed_supported ? "supported" : "not supported", pref->phy, pref->rtn, + pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max); +} + +static void unicast_stream_qos_set_cb(struct bt_bap_stream *bap_stream) +{ + LOG_INF("QoS set bap_stream %p", bap_stream); +} + +static void unicast_stream_enabled_cb(struct bt_bap_stream *bap_stream) +{ + struct bt_bap_ep_info ep_info; + int err; + + LOG_INF("Enabled bap_stream %p", bap_stream); + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err != 0) { + LOG_ERR("Failed to get ep info: %d", err); + + return; + } + + if (ep_info.dir == BT_AUDIO_DIR_SINK) { + /* Automatically do the receiver start ready operation */ + err = bt_bap_stream_start(bap_stream); + if (err != 0) { + LOG_ERR("Failed to start: %d", err); + + return; + } + } +} + +static void unicast_stream_started_cb(struct bt_bap_stream *bap_stream) +{ + LOG_INF("Started bap_stream %p", bap_stream); + total_rx_iso_packet_count = 0U; +} + +static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *bap_stream) +{ + LOG_INF("Metadata updated bap_stream %p", bap_stream); +} + +static void unicast_stream_disabled_cb(struct bt_bap_stream *bap_stream) +{ + LOG_INF("Disabled bap_stream %p", bap_stream); +} + +static void unicast_stream_stopped_cb(struct bt_bap_stream *bap_stream, uint8_t reason) +{ + LOG_INF("Stopped bap_stream %p with reason 0x%02X", bap_stream, reason); +} + +static void unicast_stream_released_cb(struct bt_bap_stream *bap_stream) +{ + struct bt_cap_stream *cap_stream = + CONTAINER_OF(bap_stream, struct bt_cap_stream, bap_stream); + + LOG_INF("Released bap_stream %p", bap_stream); + + stream_released(cap_stream); +} + +static void unicast_stream_recv_cb(struct bt_bap_stream *bap_stream, + const struct bt_iso_recv_info *info, struct net_buf *buf) +{ + /* Triggered every time we receive an HCI data packet from the controller. + * A call to this does not indicate valid data + * (see the `info->flags` for which flags to check), + */ + + if ((total_rx_iso_packet_count % 100U) == 0U) { + LOG_INF("Received %llu HCI ISO data packets", total_rx_iso_packet_count); + } + + total_rx_iso_packet_count++; +} + +static void tx_thread_func(void *arg1, void *arg2, void *arg3) +{ + NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + static uint8_t data[CONFIG_BT_ISO_TX_MTU]; + struct peer_config *peer = arg1; + struct bt_cap_stream *cap_stream = &peer->source_stream; + struct bt_bap_stream *bap_stream = &cap_stream->bap_stream; + + for (size_t i = 0U; i < ARRAY_SIZE(data); i++) { + data[i] = (uint8_t)i; + } + + while (true) { + /* No-op if stream is not configured */ + if (bap_stream->ep != NULL) { + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err == 0) { + if (ep_info.state == BT_BAP_EP_STATE_STREAMING) { + struct net_buf *buf; + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + + net_buf_add_mem(buf, data, bap_stream->qos->sdu); + + err = bt_cap_stream_send(cap_stream, buf, peer->tx_seq_num); + if (err == 0) { + peer->tx_seq_num++; + continue; /* Attempt to send again ASAP */ + } else { + LOG_ERR("Unable to send: %d", err); + net_buf_unref(buf); + } + } + } + } + + /* In case of any errors, retry with a delay */ + k_sleep(K_MSEC(100)); + } +} + +int init_cap_acceptor_unicast(struct peer_config *peer) +{ + static struct bt_bap_stream_ops unicast_stream_ops = { + .configured = unicast_stream_configured_cb, + .qos_set = unicast_stream_qos_set_cb, + .enabled = unicast_stream_enabled_cb, + .started = unicast_stream_started_cb, + .metadata_updated = unicast_stream_metadata_updated_cb, + .disabled = unicast_stream_disabled_cb, + .stopped = unicast_stream_stopped_cb, + .released = unicast_stream_released_cb, + .recv = unicast_stream_recv_cb, + }; + static bool cbs_registered; + + if (!cbs_registered) { + int err; + + err = bt_bap_unicast_server_register_cb(&unicast_server_cb); + if (err != 0) { + LOG_ERR("Failed to register BAP unicast server callbacks: %d", err); + + return -ENOEXEC; + } + + cbs_registered = true; + } + + bt_cap_stream_ops_register(&peer->source_stream, &unicast_stream_ops); + bt_cap_stream_ops_register(&peer->sink_stream, &unicast_stream_ops); + + if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SRC)) { + static bool thread_started; + + if (!thread_started) { + static K_KERNEL_STACK_DEFINE(tx_thread_stack, 1024); + const int tx_thread_prio = K_PRIO_PREEMPT(5); + static struct k_thread tx_thread; + + k_thread_create(&tx_thread, tx_thread_stack, + K_KERNEL_STACK_SIZEOF(tx_thread_stack), tx_thread_func, + peer, NULL, NULL, tx_thread_prio, 0, K_NO_WAIT); + k_thread_name_set(&tx_thread, "TX thread"); + thread_started = true; + } + } + + return 0; +} diff --git a/samples/bluetooth/cap_acceptor/src/main.c b/samples/bluetooth/cap_acceptor/src/main.c new file mode 100644 index 0000000000000..fe53bcb7eaae2 --- /dev/null +++ b/samples/bluetooth/cap_acceptor/src/main.c @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cap_acceptor.h" + +LOG_MODULE_REGISTER(cap_acceptor, LOG_LEVEL_INF); + +#define SUPPORTED_DURATION (BT_AUDIO_CODEC_CAP_DURATION_7_5 | BT_AUDIO_CODEC_CAP_DURATION_10) +#define MAX_CHAN_PER_STREAM BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(2) +#define SUPPORTED_FREQ BT_AUDIO_CODEC_CAP_FREQ_ANY +#define SEM_TIMEOUT K_SECONDS(5) +#define MAX_SDU 155U +#define MIN_SDU 30U +#define FRAMES_PER_SDU 2 + +static const struct bt_data ad[] = { + BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), + BT_DATA_BYTES(BT_DATA_UUID16_SOME, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), + BT_UUID_16_ENCODE(BT_UUID_CAS_VAL)), + BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), + BT_DATA_BYTES(BT_DATA_SVC_DATA16, + BT_UUID_16_ENCODE(BT_UUID_CAS_VAL), + BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED), + IF_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER, + (BT_DATA_BYTES(BT_DATA_SVC_DATA16, + BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), + BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, + BT_BYTES_LIST_LE16(SINK_CONTEXT), + BT_BYTES_LIST_LE16(SOURCE_CONTEXT), + 0x00, /* Metadata length */), + )) +}; + +static struct bt_le_ext_adv *adv; +static struct peer_config peer; + +static K_SEM_DEFINE(sem_state_change, 0, 1); + +static void connected_cb(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + LOG_INF("Connected: %s", addr); + + peer.conn = bt_conn_ref(conn); + k_sem_give(&sem_state_change); +} + +static void disconnected_cb(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != peer.conn) { + return; + } + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + LOG_INF("Disconnected: %s (reason 0x%02x)", addr, reason); + + bt_conn_unref(peer.conn); + peer.conn = NULL; + k_sem_give(&sem_state_change); +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected_cb, + .disconnected = disconnected_cb, +}; + +static int advertise(void) +{ + int err; + + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &adv); + if (err) { + LOG_ERR("Failed to create advertising set: %d", err); + + return err; + } + + err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0); + if (err) { + LOG_ERR("Failed to set advertising data: %d", err); + + return err; + } + + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err) { + LOG_ERR("Failed to start advertising set: %d", err); + + return err; + } + + LOG_INF("Advertising successfully started"); + + /* Wait for connection*/ + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Failed to take sem_state_change: err %d", err); + + return err; + } + + return 0; +} + +struct bt_cap_stream *stream_alloc(enum bt_audio_dir dir) +{ + if (dir == BT_AUDIO_DIR_SINK && peer.sink_stream.bap_stream.ep == NULL) { + return &peer.sink_stream; + } else if (dir == BT_AUDIO_DIR_SOURCE && peer.source_stream.bap_stream.ep == NULL) { + return &peer.source_stream; + } + + return NULL; +} + +void stream_released(const struct bt_cap_stream *cap_stream) +{ + if (cap_stream == &peer.source_stream) { + k_sem_give(&peer.source_stream_sem); + } else if (cap_stream == &peer.sink_stream) { + k_sem_give(&peer.sink_stream_sem); + } +} + +static int reset_cap_acceptor(void) +{ + int err; + + LOG_INF("Resetting"); + + if (peer.conn != NULL) { + err = bt_conn_disconnect(peer.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err != 0) { + return err; + } + + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Timeout on disconnect: %d", err); + return err; + } + } + + if (adv != NULL) { + err = bt_le_ext_adv_stop(adv); + if (err != 0) { + LOG_ERR("Failed to stop advertiser: %d", err); + return err; + } + + err = bt_le_ext_adv_delete(adv); + if (err != 0) { + LOG_ERR("Failed to delete advertiser: %d", err); + return err; + } + + adv = NULL; + } + + if (peer.source_stream.bap_stream.ep != NULL) { + err = k_sem_take(&peer.source_stream_sem, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on source_stream_sem: %d", err); + return err; + } + } + + if (peer.sink_stream.bap_stream.ep != NULL) { + err = k_sem_take(&peer.sink_stream_sem, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on sink_stream_sem: %d", err); + return err; + } + } + + k_sem_reset(&sem_state_change); + + return 0; +} + +/** Register the PAC records for PACS */ +static int register_pac(enum bt_audio_dir dir, enum bt_audio_context context, + struct bt_pacs_cap *cap) +{ + int err; + + err = bt_pacs_cap_register(dir, cap); + if (err != 0) { + LOG_ERR("Failed to register capabilities: %d", err); + + return err; + } + + err = bt_pacs_set_location(dir, BT_AUDIO_LOCATION_MONO_AUDIO); + if (err != 0) { + LOG_ERR("Failed to set location: %d", err); + + return err; + } + + err = bt_pacs_set_supported_contexts(dir, context); + if (err != 0 && err != -EALREADY) { + LOG_ERR("Failed to set supported contexts: %d", err); + + return err; + } + + err = bt_pacs_set_available_contexts(dir, context); + if (err != 0 && err != -EALREADY) { + LOG_ERR("Failed to set available contexts: %d", err); + + return err; + } + + return 0; +} + +static int init_cap_acceptor(void) +{ + static const struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3( + SUPPORTED_FREQ, SUPPORTED_DURATION, MAX_CHAN_PER_STREAM, MIN_SDU, MAX_SDU, + FRAMES_PER_SDU, (SINK_CONTEXT | SOURCE_CONTEXT)); + int err; + + err = bt_enable(NULL); + if (err != 0) { + LOG_ERR("Bluetooth enable failed: %d", err); + + return 0; + } + + LOG_INF("Bluetooth initialized"); + + if (IS_ENABLED(CONFIG_BT_PAC_SNK)) { + static struct bt_pacs_cap sink_cap = { + .codec_cap = &lc3_codec_cap, + }; + int err; + + err = register_pac(BT_AUDIO_DIR_SINK, SINK_CONTEXT, &sink_cap); + if (err != 0) { + LOG_ERR("Failed to register sink capabilities: %d", err); + + return -ENOEXEC; + } + } + + if (IS_ENABLED(CONFIG_BT_PAC_SRC)) { + static struct bt_pacs_cap source_cap = { + .codec_cap = &lc3_codec_cap, + }; + int err; + + err = register_pac(BT_AUDIO_DIR_SOURCE, SOURCE_CONTEXT, &source_cap); + if (err != 0) { + LOG_ERR("Failed to register sink capabilities: %d", err); + + return -ENOEXEC; + } + } + + return 0; +} + +int main(void) +{ + int err; + + err = init_cap_acceptor(); + if (err != 0) { + return 0; + } + + if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_SERVER)) { + err = init_cap_acceptor_unicast(&peer); + if (err != 0) { + return 0; + } + } + + LOG_INF("CAP Acceptor initialized"); + + while (true) { + err = reset_cap_acceptor(); + if (err != 0) { + LOG_ERR("Failed to reset"); + + break; + } + + /* Start advertising as a CAP Acceptor, which includes setting the required + * advertising data based on the roles we support. The Common Audio Service data is + * always advertised, as CAP Initiators and CAP Commanders will use this to identify + * our device as a CAP Acceptor. + */ + err = advertise(); + if (err != 0) { + continue; + } + + /* After advertising we expect CAP Initiators to connect to us and setup streams, + * and eventually disconnect again. As a CAP Acceptor we just need to react to their + * requests and not do anything else. + */ + + /* Reset if disconnected */ + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Failed to take sem_state_change: err %d", err); + + break; + } + } + + /* TODO: Add CAP acceptor broadcast support */ + + return 0; +} diff --git a/samples/bluetooth/unicast_audio_server/sysbuild.cmake b/samples/bluetooth/cap_acceptor/sysbuild.cmake similarity index 100% rename from samples/bluetooth/unicast_audio_server/sysbuild.cmake rename to samples/bluetooth/cap_acceptor/sysbuild.cmake diff --git a/samples/bluetooth/cap_initiator/CMakeLists.txt b/samples/bluetooth/cap_initiator/CMakeLists.txt new file mode 100644 index 0000000000000..21d0a06e5e498 --- /dev/null +++ b/samples/bluetooth/cap_initiator/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(cap_initiator) + +target_sources(app PRIVATE + src/main.c + src/cap_initiator_unicast.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/cap_initiator/Kconfig.sysbuild b/samples/bluetooth/cap_initiator/Kconfig.sysbuild new file mode 100644 index 0000000000000..f37b265ecbc27 --- /dev/null +++ b/samples/bluetooth/cap_initiator/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340dk" + default "nrf5340_audio_dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340_audio_dk" + default "nrf5340bsim/nrf5340/cpunet" if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/cap_initiator/README.rst b/samples/bluetooth/cap_initiator/README.rst new file mode 100644 index 0000000000000..d88bb7cc1366b --- /dev/null +++ b/samples/bluetooth/cap_initiator/README.rst @@ -0,0 +1,74 @@ +.. zephyr:code-sample:: bluetooth_cap_initiator + :name: Bluetooth: Common Audio Profile Initiator + :relevant-api: bt_cap bt_bap bluetooth + + CAP Initiator sample that connects to CAP Acceptors and setup audio streaming. + +Overview +******** + +Application demonstrating the CAP Initiator functionality. +Starts by scanning for a CAP Acceptor and then connects to and sets up available streams. + +This sample can be found under :zephyr_file:`samples/bluetooth/cap_initiator` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use ``-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf`` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_initiator/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_initiator/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_initiator/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/cap_initiator/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..96dc0eb4e3b2c --- /dev/null +++ b/samples/bluetooth/cap_initiator/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf @@ -0,0 +1,6 @@ +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..96dc0eb4e3b2c --- /dev/null +++ b/samples/bluetooth/cap_initiator/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,6 @@ +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +CONFIG_BT_TINYCRYPT_ECC=y diff --git a/samples/bluetooth/cap_initiator/overlay-bt_ll_sw_split.conf b/samples/bluetooth/cap_initiator/overlay-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..35d452e15dc38 --- /dev/null +++ b/samples/bluetooth/cap_initiator/overlay-bt_ll_sw_split.conf @@ -0,0 +1,13 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Zephyr Controller tested maximum advertising data that can be set in a single HCI command +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 + +# Enable support for central ISO in Zephyr Bluetooth Controller +CONFIG_BT_CTLR_CENTRAL_ISO=y + +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 diff --git a/samples/bluetooth/cap_initiator/prj.conf b/samples/bluetooth/cap_initiator/prj.conf new file mode 100644 index 0000000000000..254fe45d9d503 --- /dev/null +++ b/samples/bluetooth/cap_initiator/prj.conf @@ -0,0 +1,29 @@ +CONFIG_BT=y +CONFIG_LOG=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_AUDIO=y +CONFIG_BT_EXT_ADV=y +CONFIG_BT_DEVICE_NAME="CAP Initiator" + +CONFIG_BT_SMP=y +CONFIG_BT_TINYCRYPT_ECC=y +CONFIG_BT_KEYS_OVERWRITE_OLDEST=y + +# CAP support +CONFIG_BT_CAP_INITIATOR=y + +# CSIP support +CONFIG_BT_CSIP_SET_COORDINATOR=y + +# BAP support +CONFIG_BT_ISO_MAX_CHAN=2 +CONFIG_BT_BAP_UNICAST_CLIENT=y +CONFIG_BT_BAP_UNICAST_CLIENT_GROUP_STREAM_COUNT=2 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT=2 +CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT=2 + +# Controller configuration +CONFIG_BT_CTLR_CENTRAL_ISO=y + +# Supports the highest SDU size required by any BAP LC3 presets (155) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/cap_initiator/sample.yaml b/samples/bluetooth/cap_initiator/sample.yaml new file mode 100644 index 0000000000000..12a6022bcd7d0 --- /dev/null +++ b/samples/bluetooth/cap_initiator/sample.yaml @@ -0,0 +1,30 @@ +sample: + description: Bluetooth Low Energy Common Audio Profile Initiator sample + name: Bluetooth Low Energy Common Audio Profile Initiator sample +tests: + sample.bluetooth.cap_initiator: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + - nrf5340bsim/nrf5340/cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.cap_initiator.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52840 + - nrf52840dongle/nrf52840 + integration_platforms: + - nrf52_bsim + - nrf52833dk/nrf52833 + - nrf52840dk/nrf52840 + - nrf52840dongle/nrf52840 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/cap_initiator/src/cap_initiator.h b/samples/bluetooth/cap_initiator/src/cap_initiator.h new file mode 100644 index 0000000000000..8aecaa87e1d4b --- /dev/null +++ b/samples/bluetooth/cap_initiator/src/cap_initiator.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @brief Run the application as a CAP Initiator for unicast + * + * This will start scanning for and connecting to a CAP acceptor, and then attempt to setup + * unicast streams. + * + * @return 0 if success, errno on failure. + */ +int cap_initiator_unicast(void); diff --git a/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c b/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c new file mode 100644 index 0000000000000..030fe3835c365 --- /dev/null +++ b/samples/bluetooth/cap_initiator/src/cap_initiator_unicast.c @@ -0,0 +1,908 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "cap_initiator.h" + +LOG_MODULE_REGISTER(cap_initiator_unicast, LOG_LEVEL_INF); + +#define SEM_TIMEOUT K_SECONDS(5) + +/* We use the same config for both sink and source streams + * For simplicity we use the mandatory configuration 16_2_1 + */ +static struct bt_bap_lc3_preset unicast_preset_16_2_1 = BT_BAP_LC3_UNICAST_PRESET_16_2_1( + BT_AUDIO_LOCATION_MONO_AUDIO, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); +static struct bt_bap_unicast_group *unicast_group; +uint64_t total_rx_iso_packet_count; /* This value is exposed to test code */ + +/** Struct to contain information for a specific peer (CAP) device */ +struct peer_config { + /** Stream for the source endpoint */ + struct bt_cap_stream source_stream; + /** Stream for the sink endpoint */ + struct bt_cap_stream sink_stream; + /** Semaphore to help wait for a release operation if the source stream is not idle */ + struct k_sem source_stream_sem; + /** Semaphore to help wait for a release operation if the sink stream is not idle */ + struct k_sem sink_stream_sem; + /** Reference to the endpoint for the source stream */ + struct bt_bap_ep *source_ep; + /** Reference to the endpoint for the sink stream */ + struct bt_bap_ep *sink_ep; + /** ACL connection object for the peer device */ + struct bt_conn *conn; + /** Current sequence number for TX */ + uint16_t tx_seq_num; +}; + +/* TODO: Expand to multiple ACL connections */ +static struct peer_config peer; + +static K_SEM_DEFINE(sem_proc, 0, 1); +static K_SEM_DEFINE(sem_state_change, 0, 1); +static K_SEM_DEFINE(sem_mtu_exchanged, 0, 1); +static K_SEM_DEFINE(sem_security_changed, 0, 1); + +static void unicast_stream_configured_cb(struct bt_bap_stream *stream, + const struct bt_audio_codec_qos_pref *pref) +{ + LOG_INF("Configured stream %p", stream); + + /* TODO: The preference should be used/taken into account when + * setting the QoS + */ + + LOG_INF("Remote preferences: unframed %s, phy %u, rtn %u, latency %u, pd_min %u, pd_max " + "%u, pref_pd_min %u, pref_pd_max %u", + pref->unframed_supported ? "supported" : "not supported", pref->phy, pref->rtn, + pref->latency, pref->pd_min, pref->pd_max, pref->pref_pd_min, pref->pref_pd_max); +} + +static void unicast_stream_qos_set_cb(struct bt_bap_stream *stream) +{ + LOG_INF("QoS set stream %p", stream); +} + +static void unicast_stream_enabled_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Enabled stream %p", stream); +} + +static void unicast_stream_started_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Started stream %p", stream); + total_rx_iso_packet_count = 0U; +} + +static void unicast_stream_metadata_updated_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Metadata updated stream %p", stream); +} + +static void unicast_stream_disabled_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Disabled stream %p", stream); +} + +static void unicast_stream_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + LOG_INF("Stopped stream %p with reason 0x%02X", stream, reason); +} + +static void unicast_stream_released_cb(struct bt_bap_stream *stream) +{ + LOG_INF("Released stream %p", stream); + + if (stream == &peer.source_stream.bap_stream) { + k_sem_give(&peer.source_stream_sem); + } else if (stream == &peer.sink_stream.bap_stream) { + k_sem_give(&peer.sink_stream_sem); + } +} + +static void unicast_stream_recv_cb(struct bt_bap_stream *stream, + const struct bt_iso_recv_info *info, struct net_buf *buf) +{ + /* Triggered every time we receive an HCI data packet from the controller. + * A call to this does not indicate valid data + * (see the `info->flags` for which flags to check), + */ + + if ((total_rx_iso_packet_count % 100U) == 0U) { + LOG_INF("Received %llu HCI ISO data packets", total_rx_iso_packet_count); + } + + total_rx_iso_packet_count++; +} + +static struct bt_bap_stream_ops unicast_stream_ops = { + .configured = unicast_stream_configured_cb, + .qos_set = unicast_stream_qos_set_cb, + .enabled = unicast_stream_enabled_cb, + .started = unicast_stream_started_cb, + .metadata_updated = unicast_stream_metadata_updated_cb, + .disabled = unicast_stream_disabled_cb, + .stopped = unicast_stream_stopped_cb, + .released = unicast_stream_released_cb, + .recv = unicast_stream_recv_cb, +}; + +static void tx_thread_func(void *arg1, void *arg2, void *arg3) +{ + NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ISO_TX_BUF_COUNT, + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + static uint8_t data[CONFIG_BT_ISO_TX_MTU]; + struct bt_cap_stream *cap_stream = &peer.sink_stream; + struct bt_bap_stream *bap_stream = &cap_stream->bap_stream; + + for (size_t i = 0U; i < ARRAY_SIZE(data); i++) { + data[i] = (uint8_t)i; + } + + while (true) { + /* No-op if stream is not configured */ + if (bap_stream->ep != NULL) { + struct bt_bap_ep_info ep_info; + int err; + + err = bt_bap_ep_get_info(bap_stream->ep, &ep_info); + if (err == 0) { + if (ep_info.state == BT_BAP_EP_STATE_STREAMING) { + struct net_buf *buf; + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + + net_buf_add_mem(buf, data, bap_stream->qos->sdu); + + err = bt_cap_stream_send(cap_stream, buf, peer.tx_seq_num); + if (err == 0) { + peer.tx_seq_num++; + continue; /* Attempt to send again ASAP */ + } else { + LOG_ERR("Unable to send: %d", err); + net_buf_unref(buf); + } + } + } + } + + /* In case of any errors, retry with a delay */ + k_sleep(K_MSEC(100)); + } +} + +static bool log_codec_cb(struct bt_data *data, void *user_data) +{ + const char *str = (const char *)user_data; + + LOG_DBG("\t%s: type 0x%02x value_len %u", str, data->type, data->data_len); + LOG_HEXDUMP_DBG(data->data, data->data_len, "\t\tdata"); + + return true; +} + +static void log_codec(const struct bt_audio_codec_cap *codec_cap, enum bt_audio_dir dir) +{ + LOG_INF("codec id 0x%02x cid 0x%04x vid 0x%04x count %u", codec_cap->id, codec_cap->cid, + codec_cap->vid, codec_cap->data_len); + + if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) { + bt_audio_data_parse(codec_cap->data, codec_cap->data_len, log_codec_cb, "data"); + } else { /* If not LC3, we cannot assume it's LTV */ + LOG_HEXDUMP_DBG(codec_cap->data, codec_cap->data_len, "data"); + } + + bt_audio_data_parse(codec_cap->meta, codec_cap->meta_len, log_codec_cb, "meta"); +} + +static void add_remote_sink(struct bt_bap_ep *ep) +{ + if (peer.sink_ep == NULL) { + LOG_INF("Sink ep: %p", (void *)ep); + peer.sink_ep = ep; + return; + } +} + +static void add_remote_source(struct bt_bap_ep *ep) +{ + if (peer.source_ep == NULL) { + LOG_INF("Source ep: %p", (void *)ep); + peer.source_ep = ep; + return; + } +} + +static void discover_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) +{ + if (dir == BT_AUDIO_DIR_SINK) { + if (err != 0) { + LOG_ERR("Discovery sinks failed: %d", err); + } else { + LOG_INF("Discover sinks complete"); + } + } else if (dir == BT_AUDIO_DIR_SOURCE) { + if (err != 0) { + LOG_ERR("Discovery sources failed: %d", err); + } else { + LOG_INF("Discover sources complete"); + } + } + + k_sem_give(&sem_proc); +} + +static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, + const struct bt_audio_codec_cap *codec_cap) +{ + log_codec(codec_cap, dir); +} + +static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep) +{ + if (dir == BT_AUDIO_DIR_SOURCE) { + add_remote_source(ep); + } else if (dir == BT_AUDIO_DIR_SINK) { + add_remote_sink(ep); + } +} + +static int discover_sinks(void) +{ + int err; + + LOG_INF("Discovering sink ASEs"); + k_sem_reset(&sem_proc); + + bt_cap_stream_ops_register(&peer.sink_stream, &unicast_stream_ops); + + err = bt_bap_unicast_client_discover(peer.conn, BT_AUDIO_DIR_SINK); + if (err != 0) { + LOG_ERR("Failed to discover sink: %d", err); + return err; + } + + err = k_sem_take(&sem_proc, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on sinks discover: %d", err); + return err; + } + + return err; +} + +static int discover_sources(void) +{ + int err; + + LOG_INF("Discovering source ASEs"); + k_sem_reset(&sem_proc); + + bt_cap_stream_ops_register(&peer.source_stream, &unicast_stream_ops); + + err = bt_bap_unicast_client_discover(peer.conn, BT_AUDIO_DIR_SOURCE); + if (err != 0) { + LOG_ERR("Failed to discover sources: %d", err); + return err; + } + + err = k_sem_take(&sem_proc, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on sources discover: %d", err); + return err; + } + + return 0; +} + +static int unicast_group_create(void) +{ + struct bt_bap_unicast_group_stream_param source_stream_param = { + .qos = &unicast_preset_16_2_1.qos, + .stream = &peer.source_stream.bap_stream, + }; + struct bt_bap_unicast_group_stream_param sink_stream_param = { + .qos = &unicast_preset_16_2_1.qos, + .stream = &peer.sink_stream.bap_stream, + }; + struct bt_bap_unicast_group_stream_pair_param pair_params = {0}; + struct bt_bap_unicast_group_param group_param = {0}; + int err; + + if (peer.source_ep != NULL) { + pair_params.rx_param = &source_stream_param; + } + + if (peer.sink_ep != NULL) { + pair_params.tx_param = &sink_stream_param; + } + + group_param.params_count = 1U; + group_param.params = &pair_params; + + err = bt_bap_unicast_group_create(&group_param, &unicast_group); + if (err != 0) { + LOG_ERR("Failed to create group: %d", err); + return err; + } + + LOG_INF("Created group"); + + return err; +} + +static int unicast_group_delete(void) +{ + int err; + + err = bt_bap_unicast_group_delete(unicast_group); + if (err != 0) { + LOG_ERR("Failed to delete group: %d", err); + return err; + } + unicast_group = NULL; + + LOG_INF("Deleted group"); + + return err; +} + +static void cap_discovery_complete_cb(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, + const struct bt_csip_set_coordinator_csis_inst *csis_inst) +{ + if (err != 0) { + LOG_ERR("CAS discovery completed with error: %d", err); + + return; + } + + if (IS_ENABLED(CONFIG_BT_CAP_ACCEPTOR_SET_MEMBER) && csis_inst != NULL) { + LOG_INF("Found CAS with CSIS %p", csis_inst); + /* TODO: Do set member discovery */ + } else { + LOG_INF("Found CAS"); + } + + k_sem_give(&sem_proc); +} + +static void unicast_start_complete_cb(int err, struct bt_conn *conn) +{ + if (err != 0) { + LOG_ERR("Failed to start (failing conn %p): %d", (void *)conn, err); + return; + } + + k_sem_give(&sem_proc); +} + +static int discover_cas(void) +{ + int err; + + LOG_INF("Discovering CAS"); + k_sem_reset(&sem_proc); + + err = bt_cap_initiator_unicast_discover(peer.conn); + if (err != 0) { + LOG_ERR("Failed to discover CAS: %d", err); + return err; + } + + err = k_sem_take(&sem_proc, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on CAS discover: %d", err); + return err; + } + + return err; +} + +static int unicast_audio_start(void) +{ + /* TODO: Expand to start multiple streams on multiple CAP acceptors */ + struct bt_cap_unicast_audio_start_stream_param stream_param[2] = {0}; + struct bt_cap_unicast_audio_start_param param = {0}; + int err; + + LOG_INF("Starting streams"); + + if (peer.sink_ep != NULL) { + stream_param[param.count].member.member = peer.conn; + stream_param[param.count].stream = &peer.sink_stream; + stream_param[param.count].ep = peer.sink_ep; + stream_param[param.count].codec_cfg = &unicast_preset_16_2_1.codec_cfg; + param.count++; + } + + if (peer.source_ep != NULL) { + stream_param[param.count].member.member = peer.conn; + stream_param[param.count].stream = &peer.source_stream; + stream_param[param.count].ep = peer.source_ep; + stream_param[param.count].codec_cfg = &unicast_preset_16_2_1.codec_cfg; + param.count++; + } + + param.type = BT_CAP_SET_TYPE_AD_HOC; + param.stream_params = stream_param; + + err = bt_cap_initiator_unicast_audio_start(¶m); + if (err != 0) { + LOG_ERR("Failed to start unicast audio: %d", err); + return err; + } + + return err; +} + +static void att_mtu_updated_cb(struct bt_conn *conn, uint16_t tx, uint16_t rx) +{ + LOG_INF("MTU exchanged: %u/%u", tx, rx); + k_sem_give(&sem_mtu_exchanged); +} + +static void start_scan(void) +{ + int err; + + err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, NULL); + if (err != 0) { + LOG_ERR("Scanning failed to start: %d", err); + return; + } + + LOG_INF("Scanning successfully started"); +} + +static void connected_cb(struct bt_conn *conn, uint8_t err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + if (err != 0) { + LOG_ERR("Failed to connect to %s: %u", addr, err); + + bt_conn_unref(peer.conn); + peer.conn = NULL; + + start_scan(); + return; + } + + if (conn != peer.conn) { + return; + } + + LOG_INF("Connected: %s", addr); + k_sem_give(&sem_state_change); +} + +static void disconnected_cb(struct bt_conn *conn, uint8_t reason) +{ + char addr[BT_ADDR_LE_STR_LEN]; + + if (conn != peer.conn) { + return; + } + + (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); + + LOG_INF("Disconnected: %s (reason 0x%02x)", addr, reason); + + bt_conn_unref(peer.conn); + peer.conn = NULL; + + k_sem_give(&sem_state_change); +} + +static void security_changed_cb(struct bt_conn *conn, bt_security_t level, + enum bt_security_err sec_err) +{ + if (sec_err == 0) { + LOG_INF("Security changed: %u", level); + k_sem_give(&sem_security_changed); + } else { + LOG_ERR("Failed to set security level: %d", sec_err); + + if (sec_err == BT_SECURITY_ERR_PIN_OR_KEY_MISSING) { + int err; + + LOG_INF("Removing old key"); + err = bt_unpair(BT_ID_DEFAULT, bt_conn_get_dst(conn)); + if (err != 0) { + LOG_ERR("Failed to remove old key: %d", err); + } + } + } +} + +BT_CONN_CB_DEFINE(conn_callbacks) = { + .connected = connected_cb, + .disconnected = disconnected_cb, + .security_changed = security_changed_cb, +}; + +static bool check_audio_support_and_connect_cb(struct bt_data *data, void *user_data) +{ + char addr_str[BT_ADDR_LE_STR_LEN]; + bt_addr_le_t *addr = user_data; + const struct bt_uuid *uuid; + uint16_t uuid_val; + int err; + + LOG_DBG("[AD]: %u data_len %u", data->type, data->data_len); + + if (data->type != BT_DATA_SVC_DATA16) { + return true; /* Continue parsing to next AD data type */ + } + + if (data->data_len < sizeof(uuid_val)) { + LOG_DBG("AD invalid size %u", data->data_len); + return true; /* Continue parsing to next AD data type */ + } + + /* We are looking for the CAS service data */ + uuid_val = sys_get_le16(data->data); + uuid = BT_UUID_DECLARE_16(uuid_val); + if (bt_uuid_cmp(uuid, BT_UUID_CAS) != 0) { + return true; /* Continue parsing to next AD data type */ + } + + bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); + LOG_INF("Attempt to connect to %s", addr_str); + + err = bt_le_scan_stop(); + if (err != 0) { + LOG_ERR("Failed to stop scan: %d", err); + return false; + } + + err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, BT_LE_CONN_PARAM_DEFAULT, &peer.conn); + if (err != 0) { + LOG_WRN("Create conn to failed: %d, restarting scan", err); + start_scan(); + } + + return false; /* Stop parsing */ +} + +static void scan_recv_cb(const struct bt_le_scan_recv_info *info, struct net_buf_simple *buf) +{ + if (peer.conn != NULL) { + /* Already connected */ + return; + } + + /* Check for connectable, extended advertising */ + if (((info->adv_props & BT_GAP_ADV_PROP_EXT_ADV) != 0) && + ((info->adv_props & BT_GAP_ADV_PROP_CONNECTABLE)) != 0) { + /* Check for TMAS support in advertising data */ + bt_data_parse(buf, check_audio_support_and_connect_cb, (void *)info->addr); + } +} + +static int scan_and_connect(void) +{ + int err; + + start_scan(); + + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Failed to take sem_state_change: %d", err); + return err; + } + + return 0; +} + +static void exchange_cb(struct bt_conn *conn, uint8_t err, struct bt_gatt_exchange_params *params) +{ + if (err == BT_ATT_ERR_SUCCESS) { + LOG_INF("MTU exchange done"); + k_sem_give(&sem_proc); + } else { + LOG_ERR("MTU exchange failed: err %u", err); + } +} + +static int exchange_mtu(void) +{ + int err; + + if (!IS_ENABLED(CONFIG_BT_GATT_AUTO_UPDATE_MTU)) { + static struct bt_gatt_exchange_params exchange_params = { + .func = exchange_cb, + }; + + LOG_INF("Exchanging MTU"); + + k_sem_reset(&sem_proc); + + err = bt_gatt_exchange_mtu(peer.conn, &exchange_params); + if (err != 0) { + LOG_ERR("Failed to exchange MTU: %d", err); + } + + err = k_sem_take(&sem_proc, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on MTU exchange request: %d", err); + return err; + } + } + + LOG_INF("Waiting for MTU exchange"); + err = k_sem_take(&sem_mtu_exchanged, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on MTU exchange: %d", err); + return err; + } + + return 0; +} + +static int update_security(void) +{ + int err; + + err = bt_conn_set_security(peer.conn, BT_SECURITY_L2); + if (err != 0) { + LOG_ERR("Failed to set security: %d", err); + return err; + } + + LOG_INF("Waiting for security change"); + err = k_sem_take(&sem_security_changed, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on security: %d", err); + return err; + } + + return 0; +} + +static int init_cap_initiator(void) +{ + static struct bt_bap_unicast_client_cb unicast_client_cbs = { + .discover = discover_cb, + .pac_record = pac_record_cb, + .endpoint = endpoint_cb, + }; + static struct bt_cap_initiator_cb cap_cb = { + .unicast_discovery_complete = cap_discovery_complete_cb, + .unicast_start_complete = unicast_start_complete_cb, + }; + static struct bt_gatt_cb gatt_callbacks = { + .att_mtu_updated = att_mtu_updated_cb, + }; + static struct bt_le_scan_cb scan_callbacks = { + .recv = scan_recv_cb, + }; + int err; + + err = bt_cap_initiator_register_cb(&cap_cb); + if (err != 0) { + LOG_ERR("Failed to register CAP callbacks: %d", err); + + return err; + } + + err = bt_bap_unicast_client_register_cb(&unicast_client_cbs); + if (err != 0) { + LOG_ERR("Failed to register BAP unicast client callbacks: %d", err); + + return err; + } + + bt_gatt_cb_register(&gatt_callbacks); + bt_le_scan_cb_register(&scan_callbacks); + + k_sem_init(&peer.source_stream_sem, 0, 1); + k_sem_init(&peer.sink_stream_sem, 0, 1); + + if (IS_ENABLED(CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK)) { + static bool thread_started; + + if (!thread_started) { + static K_KERNEL_STACK_DEFINE(tx_thread_stack, 1024); + const int tx_thread_prio = K_PRIO_PREEMPT(5); + static struct k_thread tx_thread; + + k_thread_create(&tx_thread, tx_thread_stack, + K_KERNEL_STACK_SIZEOF(tx_thread_stack), tx_thread_func, + net_buf_pull_be16, NULL, NULL, tx_thread_prio, 0, + K_NO_WAIT); + k_thread_name_set(&tx_thread, "TX thread"); + thread_started = true; + } + } + + return 0; +} + +static int reset_cap_initiator(void) +{ + int err; + + LOG_INF("Resetting"); + + if (peer.conn != NULL) { + err = bt_conn_disconnect(peer.conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + if (err != 0) { + return err; + } + + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Timeout on disconnect: %d", err); + return err; + } + } + + if (peer.source_stream.bap_stream.ep != NULL) { + err = k_sem_take(&peer.source_stream_sem, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on source_stream_sem: %d", err); + return err; + } + } + + if (peer.sink_stream.bap_stream.ep != NULL) { + err = k_sem_take(&peer.sink_stream_sem, SEM_TIMEOUT); + if (err != 0) { + LOG_ERR("Timeout on sink_stream_sem: %d", err); + return err; + } + } + + if (unicast_group != NULL) { + int err; + + err = unicast_group_delete(); + if (err != 0) { + return err; + } + + return err; + } + + peer.source_ep = NULL; + peer.sink_ep = NULL; + k_sem_reset(&sem_proc); + k_sem_reset(&sem_state_change); + k_sem_reset(&sem_mtu_exchanged); + + return 0; +} + +int cap_initiator_unicast(void) +{ + int err; + + err = init_cap_initiator(); + if (err != 0) { + return err; + } + + LOG_INF("CAP initiator unicast initialized"); + + while (true) { + err = reset_cap_initiator(); + if (err != 0) { + LOG_ERR("Failed to reset"); + + return err; + } + + /* Start scanning for and connecting to CAP Acceptors. CAP Acceptors are identified + * by their advertising data + */ + err = scan_and_connect(); + if (err != 0) { + continue; + } + + /* BAP mandates support for an MTU of at least 65 octets. Because of that, we + * should always exchange the MTU before accessing BAP related services to ensure + * correctness + */ + err = exchange_mtu(); + if (err != 0) { + continue; + } + + /* LE Audio services require encryption with LE Secure Connections, so we increase + * security before attempting to do any LE Audio operations + */ + err = update_security(); + if (err != 0) { + continue; + } + + /* All remote CAP Acceptors shall have the Common Audio Service (CAS) so we start by + * discovering that on the remote device to determine if they are really CAP + * Acceptors. If they are only a BAP Unicast Server we ignore them. + */ + err = discover_cas(); + if (err != 0) { + continue; + } + + /* Discover sink ASEs and capabilities. This may not result in any endpoints if they + * remote device is only a source (e.g. a microphone) + */ + err = discover_sinks(); + if (err != 0) { + continue; + } + + /* Discover source ASEs and capabilities. This may not result in any endpoints if + * they remote device is only a sink (e.g. a speaker) + */ + err = discover_sources(); + if (err != 0) { + continue; + } + + /* Create a unicast group (Connected Isochronous Group (CIG)) based on what we have + * found on the remote device + */ + err = unicast_group_create(); + if (err != 0) { + continue; + } + + /* Execute the start operation which will take one or more streams into the + * streaming state + */ + err = unicast_audio_start(); + if (err != 0) { + continue; + } + + /* Reset if disconnected */ + err = k_sem_take(&sem_state_change, K_FOREVER); + if (err != 0) { + LOG_ERR("Failed to take sem_state_change: err %d", err); + + return err; + } + } + + return 0; +} diff --git a/samples/bluetooth/cap_initiator/src/main.c b/samples/bluetooth/cap_initiator/src/main.c new file mode 100644 index 0000000000000..f40a2a517f5d1 --- /dev/null +++ b/samples/bluetooth/cap_initiator/src/main.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "cap_initiator.h" + +LOG_MODULE_REGISTER(cap_initiator, LOG_LEVEL_INF); + +int main(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + LOG_ERR("Bluetooth enable failed: %d", err); + + return 0; + } + + LOG_INF("Bluetooth initialized"); + + /* TODO: Add CAP initiator broadcast support*/ + + /* If the CONFIG_BT_CAP_INITIATOR_UNICAST is enabled we call the cap_initiator_unicast + * function that runs the application as a CAP Initiator for unicast. This will attempt to + * scan for and connect to a CAP acceptor to set up a stream + * + * Since cap_initiator_unicast runs as a while (true) loop, this shall be done as the last + * thing in this function + */ + if (IS_ENABLED(CONFIG_BT_CAP_INITIATOR_UNICAST)) { + err = cap_initiator_unicast(); + } + + if (err != 0) { + LOG_ERR("Failed to run CAP Initiator: %d", err); + } + + return 0; +} diff --git a/samples/bluetooth/cap_initiator/sysbuild.cmake b/samples/bluetooth/cap_initiator/sysbuild.cmake new file mode 100644 index 0000000000000..2523aac8ea76f --- /dev/null +++ b/samples/bluetooth/cap_initiator/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) + # For builds in the nrf5340, we build the netcore image with the controller + + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/bluetooth/central_hr/prj_minimal.conf b/samples/bluetooth/central_hr/prj_minimal.conf new file mode 100644 index 0000000000000..1dcf300b1ef75 --- /dev/null +++ b/samples/bluetooth/central_hr/prj_minimal.conf @@ -0,0 +1,103 @@ +CONFIG_BT=y +CONFIG_BT_SMP=y +CONFIG_BT_CENTRAL=y + +# Drivers and peripherals +CONFIG_I2C=n +CONFIG_WATCHDOG=n +CONFIG_PINCTRL=n +CONFIG_SPI=n +CONFIG_GPIO=n +CONFIG_SERIAL=n + +# Power management +CONFIG_PM=n + +# Interrupts +CONFIG_DYNAMIC_INTERRUPTS=n +CONFIG_IRQ_OFFLOAD=n + +# Memory protection +CONFIG_THREAD_STACK_INFO=n +CONFIG_THREAD_CUSTOM_DATA=n +CONFIG_FPU=n + +# Boot +CONFIG_BOOT_BANNER=n +CONFIG_BOOT_DELAY=0 + +# Console +CONFIG_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_STDOUT_CONSOLE=n +CONFIG_PRINTK=n +CONFIG_EARLY_CONSOLE=n + +# Build +CONFIG_SIZE_OPTIMIZATIONS=y + +# ARM +CONFIG_ARM_MPU=n + +# In order to correctly tune the stack sizes for the threads the following +# Configurations can enabled to print the current use: +# CONFIG_THREAD_NAME=y +# CONFIG_THREAD_ANALYZER=y +# CONFIG_THREAD_ANALYZER_AUTO=y +# CONFIG_THREAD_ANALYZER_RUN_UNLOCKED=y +# CONFIG_THREAD_ANALYZER_USE_PRINTK=y +# CONFIG_THREAD_ANALYZER_AUTO_INTERVAL=20 +# CONFIG_CONSOLE=y +# CONFIG_UART_CONSOLE=y +# CONFIG_SERIAL=y +# CONFIG_PRINTK=y + +# Example output of thread analyzer +# BT RX : STACK: unused 576 usage 448 / 1024 (43 %); CPU: 0 % +# BT RX pri : STACK: unused 260 usage 188 / 448 (41 %); CPU: 0 % +# BT ECC : STACK: unused 256 usage 888 / 1144 (77 %); CPU: 1 % +# BT TX : STACK: unused 296 usage 344 / 640 (53 %); CPU: 0 % +# thread_analyzer : STACK: unused 128 usage 384 / 512 (75 %); CPU: 1 % +# sysworkq : STACK: unused 856 usage 168 / 1024 (16 %); CPU: 0 % +# logging : STACK: unused 232 usage 536 / 768 (69 %); CPU: 0 % +# idle 00 : STACK: unused 208 usage 48 / 256 (18 %); CPU: 97 % +# main : STACK: unused 576 usage 448 / 1024 (43 %); CPU: 0 % +CONFIG_BT_RX_STACK_SIZE=1024 +CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y +CONFIG_BT_HCI_TX_STACK_SIZE=640 +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_IDLE_STACK_SIZE=128 +CONFIG_MAIN_STACK_SIZE=640 +CONFIG_ISR_STACK_SIZE=1024 + +# Disable features not needed +CONFIG_TIMESLICING=n +CONFIG_COMMON_LIBC_MALLOC=n +CONFIG_LOG=n +CONFIG_ASSERT=n + +# Disable Bluetooth features not needed +# CONFIG_BT_DEBUG_NONE=y +CONFIG_BT_ASSERT=n +CONFIG_BT_DATA_LEN_UPDATE=n +CONFIG_BT_PHY_UPDATE=n +CONFIG_BT_GATT_CACHING=n +CONFIG_BT_GATT_SERVICE_CHANGED=n +CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=n +CONFIG_BT_SETTINGS_CCC_LAZY_LOADING=y +CONFIG_BT_HCI_VS=n + +# Disable Bluetooth controller features not needed +CONFIG_BT_CTLR_PRIVACY=n +CONFIG_BT_CTLR_PHY_2M=n + +# Reduce Bluetooth buffers +CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT=1 +CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=45 +CONFIG_BT_BUF_ACL_RX_COUNT=2 +CONFIG_BT_BUF_EVT_RX_COUNT=2 + +CONFIG_BT_L2CAP_TX_BUF_COUNT=2 +CONFIG_BT_CTLR_RX_BUFFERS=1 +CONFIG_BT_BUF_ACL_TX_COUNT=3 +CONFIG_BT_BUF_ACL_TX_SIZE=27 diff --git a/samples/bluetooth/central_hr/sample.yaml b/samples/bluetooth/central_hr/sample.yaml index 8a53401860b6c..1c563422d3999 100644 --- a/samples/bluetooth/central_hr/sample.yaml +++ b/samples/bluetooth/central_hr/sample.yaml @@ -5,6 +5,14 @@ tests: arch_allow: x86 harness: bluetooth tags: bluetooth + sample.bluetooth.central_hr.minimal: + harness: bluetooth + platform_allow: + - bbc_microbit + integration_platforms: + - bbc_microbit + extra_args: EXTRA_CONF_FILE=prj_minimal.conf + tags: bluetooth sample.bluetooth.central_hr.bt_ll_sw_split.extended: harness: bluetooth platform_allow: diff --git a/samples/bluetooth/ibeacon/boards/efr32bg22_brd4184a.conf b/samples/bluetooth/central_ht/boards/frdm_rw612.conf similarity index 100% rename from samples/bluetooth/ibeacon/boards/efr32bg22_brd4184a.conf rename to samples/bluetooth/central_ht/boards/frdm_rw612.conf diff --git a/samples/bluetooth/central_ht/boards/rd_rw612_bga.conf b/samples/bluetooth/central_ht/boards/rd_rw612_bga.conf new file mode 100644 index 0000000000000..2df782efc7115 --- /dev/null +++ b/samples/bluetooth/central_ht/boards/rd_rw612_bga.conf @@ -0,0 +1 @@ +CONFIG_PM=y diff --git a/samples/bluetooth/central_ht/sample.yaml b/samples/bluetooth/central_ht/sample.yaml index f41b228970576..48d2803dde561 100644 --- a/samples/bluetooth/central_ht/sample.yaml +++ b/samples/bluetooth/central_ht/sample.yaml @@ -11,3 +11,11 @@ tests: tags: bluetooth integration_platforms: - qemu_cortex_m3 + sample.bluetooth.central_ht.nxp: + # Disabling monolithic since CI environment doesn't use blobs + harness: bluetooth + platform_allow: + - rd_rw612_bga + - frdm_rw612 + extra_configs: + - CONFIG_NXP_MONOLITHIC_BT=n diff --git a/samples/bluetooth/central_iso/overlay-bt_ll_sw_split.conf b/samples/bluetooth/central_iso/overlay-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..320c5c352b116 --- /dev/null +++ b/samples/bluetooth/central_iso/overlay-bt_ll_sw_split.conf @@ -0,0 +1,33 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Zephyr Bluetooth LE Controller needs 16 event buffers to generate Extended +# Advertising Report for receiving the complete 1650 bytes of data +CONFIG_BT_BUF_EVT_RX_COUNT=16 + +# Set maximum scan data length for Extended Scanning in Bluetooth LE Controller +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 + +# Increase Zephyr Bluetooth LE Controller Rx buffer to receive complete chain +# of PDUs +CONFIG_BT_CTLR_RX_BUFFERS=9 + +# Sufficient ISO SDU and PDU length for this sample with ISO_TX_MTU of 247 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 +CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 + +# Number of supported streami sources and sinks +CONFIG_BT_CTLR_ISOAL_SOURCES=2 +CONFIG_BT_CTLR_ISOAL_SINKS=1 + +# Support the highest SDU size required by this sample 247 + 8 bytes of HCI ISO Data +# packet overhead (timestamp and HCI ISO Data packet header) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 +CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 + +# Use Low Latency Connected ISO policy +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y + +# Use the below if the sample is sending stale packet sequence number +# CONFIG_BT_CTLR_ISOAL_SN_STRICT=n diff --git a/samples/bluetooth/central_iso/sample.yaml b/samples/bluetooth/central_iso/sample.yaml index 0cdbb7a501cd1..455ff8fcb0001 100644 --- a/samples/bluetooth/central_iso/sample.yaml +++ b/samples/bluetooth/central_iso/sample.yaml @@ -8,3 +8,14 @@ tests: integration_platforms: - qemu_x86 tags: bluetooth + sample.bluetooth.central_iso.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf52_bsim + - nrf52833dk/nrf52833 + integration_platforms: + - nrf52833dk/nrf52833 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/direct_adv/src/main.c b/samples/bluetooth/direct_adv/src/main.c index b277cd4205a11..97734ae83f0c3 100644 --- a/samples/bluetooth/direct_adv/src/main.c +++ b/samples/bluetooth/direct_adv/src/main.c @@ -128,7 +128,7 @@ static void bt_ready(void) adv_param.options |= BT_LE_ADV_OPT_DIR_ADDR_RPA; err = bt_le_adv_start(&adv_param, NULL, 0, NULL, 0); } else { - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); } if (err) { diff --git a/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52820.overlay b/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52820.overlay index cdda1ac13f729..fa37e5f76de31 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52820.overlay +++ b/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52820.overlay @@ -11,13 +11,13 @@ */ dfe-antenna-num = <10>; /* This is an example switch pattern that will be used to set an - * antenna for Tx PDU (period before start of Tx CTE). + * antenna for Rx PDU (period before start of Rx CTE). */ dfe-pdu-antenna = <0x1>; /* These are example GPIO pin numbers that are provided to * Radio peripheral. The pins will be acquired by Radio to - * drive antenna switching when AoD is enabled. + * drive antenna switching when AoA is enabled. */ dfegpio0-gpios = <&gpio0 3 0>; dfegpio1-gpios = <&gpio0 4 0>; diff --git a/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.overlay b/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.overlay index cdda1ac13f729..fa37e5f76de31 100644 --- a/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.overlay +++ b/samples/bluetooth/direction_finding_connectionless_rx/boards/nrf52833dk_nrf52833.overlay @@ -11,13 +11,13 @@ */ dfe-antenna-num = <10>; /* This is an example switch pattern that will be used to set an - * antenna for Tx PDU (period before start of Tx CTE). + * antenna for Rx PDU (period before start of Rx CTE). */ dfe-pdu-antenna = <0x1>; /* These are example GPIO pin numbers that are provided to * Radio peripheral. The pins will be acquired by Radio to - * drive antenna switching when AoD is enabled. + * drive antenna switching when AoA is enabled. */ dfegpio0-gpios = <&gpio0 3 0>; dfegpio1-gpios = <&gpio0 4 0>; diff --git a/samples/bluetooth/direction_finding_connectionless_tx/src/main.c b/samples/bluetooth/direction_finding_connectionless_tx/src/main.c index ef6a89b885239..f827e39a6573c 100644 --- a/samples/bluetooth/direction_finding_connectionless_tx/src/main.c +++ b/samples/bluetooth/direction_finding_connectionless_tx/src/main.c @@ -42,8 +42,8 @@ static struct bt_le_ext_adv_start_param ext_adv_start_param = { }; static struct bt_le_per_adv_param per_adv_param = { - .interval_min = BT_GAP_ADV_SLOW_INT_MIN, - .interval_max = BT_GAP_ADV_SLOW_INT_MAX, + .interval_min = BT_GAP_PER_ADV_SLOW_INT_MIN, + .interval_max = BT_GAP_PER_ADV_SLOW_INT_MAX, .options = BT_LE_ADV_OPT_USE_TX_POWER, }; diff --git a/samples/bluetooth/direction_finding_peripheral/src/main.c b/samples/bluetooth/direction_finding_peripheral/src/main.c index c122ae21a1448..214449c3580ee 100644 --- a/samples/bluetooth/direction_finding_peripheral/src/main.c +++ b/samples/bluetooth/direction_finding_peripheral/src/main.c @@ -100,7 +100,7 @@ static void bt_ready(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err) { printk("Advertising failed to start (err %d)\n", err); return; diff --git a/samples/bluetooth/eddystone/src/main.c b/samples/bluetooth/eddystone/src/main.c index b649e636ab6a7..33a01396c9198 100644 --- a/samples/bluetooth/eddystone/src/main.c +++ b/samples/bluetooth/eddystone/src/main.c @@ -431,8 +431,7 @@ static int eds_slot_restart(struct eds_slot *slot, uint8_t type) addr = oob.addr; } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), - NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); } else { size_t count = 1; @@ -635,7 +634,7 @@ static void bt_ready(int err) printk("Bluetooth initialized\n"); /* Start advertising */ - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; diff --git a/samples/bluetooth/encrypted_advertising/central/src/central_ead.c b/samples/bluetooth/encrypted_advertising/central/src/central_ead.c index a321592007172..ddfb98cad8aa7 100644 --- a/samples/bluetooth/encrypted_advertising/central/src/central_ead.c +++ b/samples/bluetooth/encrypted_advertising/central/src/central_ead.c @@ -38,7 +38,6 @@ static struct bt_conn_cb central_cb; static struct bt_conn_auth_cb central_auth_cb; static struct k_poll_signal conn_signal; -static struct k_poll_signal sec_update_signal; static struct k_poll_signal passkey_enter_signal; static struct k_poll_signal device_found_cb_completed; @@ -348,7 +347,6 @@ static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_ if (!err) { LOG_DBG("Security changed: %s level %u", addr, level); - k_poll_signal_raise(&sec_update_signal, 0); } else { LOG_DBG("Security failed: %s level %u err %d", addr, level, err); } @@ -411,7 +409,6 @@ static int init_bt(void) k_poll_signal_init(&conn_signal); k_poll_signal_init(&passkey_enter_signal); - k_poll_signal_init(&sec_update_signal); k_poll_signal_init(&gatt_disc_signal); k_poll_signal_init(&gatt_read_signal); k_poll_signal_init(&device_found_cb_completed); diff --git a/samples/bluetooth/extended_adv/advertiser/src/main.c b/samples/bluetooth/extended_adv/advertiser/src/main.c index be51694fd1ad2..efb8dbc3e1fde 100644 --- a/samples/bluetooth/extended_adv/advertiser/src/main.c +++ b/samples/bluetooth/extended_adv/advertiser/src/main.c @@ -102,7 +102,7 @@ int main(void) return err; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/handsfree/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf b/samples/bluetooth/handsfree/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf new file mode 100644 index 0000000000000..9e8851c73af1b --- /dev/null +++ b/samples/bluetooth/handsfree/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf @@ -0,0 +1,2 @@ +#select NXP NW612 Chipset +CONFIG_BT_NXP_NW612=y diff --git a/samples/bluetooth/handsfree/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay b/samples/bluetooth/handsfree/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay new file mode 100644 index 0000000000000..96ef63ad60b2e --- /dev/null +++ b/samples/bluetooth/handsfree/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay @@ -0,0 +1,11 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,sram = &dtcm; + }; +}; diff --git a/samples/bluetooth/handsfree_ag/CMakeLists.txt b/samples/bluetooth/handsfree_ag/CMakeLists.txt new file mode 100644 index 0000000000000..af90adf8b82e2 --- /dev/null +++ b/samples/bluetooth/handsfree_ag/CMakeLists.txt @@ -0,0 +1,10 @@ +#SPDX - License - Identifier : Apache - 2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(handsfree_ag) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/handsfree_ag/Kconfig b/samples/bluetooth/handsfree_ag/Kconfig new file mode 100644 index 0000000000000..f3a1edbcdc9b1 --- /dev/null +++ b/samples/bluetooth/handsfree_ag/Kconfig @@ -0,0 +1,24 @@ +# +# Copyright 2024 NXP +# +# SPDX-License-Identifier: Apache-2.0 +# + +mainmenu "Bluetooth: handsfree AG" + +config BT_HFP_AG_DISCOVER_RESULT_COUNT + int "Maximum result count per device discovery" + default 10 + +config BT_HFP_AG_CALL_OUTGOING + bool "The simulate call: outgoing (y), incoming (n)" + +config BT_HFP_AG_START_CALL_DELAY_TIME + int "The delay time used to start simulating a call after AG connection" + default 5000 + help + The Delay time is used to wait for the peer to start dialing. If the + peer does not dial within the timeout period, AG satrt simulating a + call. The unit is ms. + +source "Kconfig.zephyr" diff --git a/samples/bluetooth/handsfree_ag/README.rst b/samples/bluetooth/handsfree_ag/README.rst new file mode 100644 index 0000000000000..9d2e2d9343aca --- /dev/null +++ b/samples/bluetooth/handsfree_ag/README.rst @@ -0,0 +1,23 @@ +.. _bt_handsfree_ag: + +Bluetooth: Handsfree Audio Gateway +################################## + +Overview +******** + +Application demonstrating usage of the Hands-free Audio Gateway (AG) APIs. + +Requirements +************ + +* Running on the host with Bluetooth BR/EDR (Classic) support, or +* A board with Bluetooth BR/EDR (Classic) support + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/bluetooth/handsfree_ag` in +the Zephyr tree. + +See :ref:`bluetooth samples section ` for details. diff --git a/samples/bluetooth/handsfree_ag/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf b/samples/bluetooth/handsfree_ag/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf new file mode 100644 index 0000000000000..9e8851c73af1b --- /dev/null +++ b/samples/bluetooth/handsfree_ag/boards/mimxrt1170_evk_mimxrt1176_cm7_B.conf @@ -0,0 +1,2 @@ +#select NXP NW612 Chipset +CONFIG_BT_NXP_NW612=y diff --git a/samples/bluetooth/handsfree_ag/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay b/samples/bluetooth/handsfree_ag/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay new file mode 100644 index 0000000000000..96ef63ad60b2e --- /dev/null +++ b/samples/bluetooth/handsfree_ag/boards/mimxrt1170_evk_mimxrt1176_cm7_B.overlay @@ -0,0 +1,11 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,sram = &dtcm; + }; +}; diff --git a/samples/bluetooth/handsfree_ag/prj.conf b/samples/bluetooth/handsfree_ag/prj.conf new file mode 100644 index 0000000000000..cd315ed26b8b7 --- /dev/null +++ b/samples/bluetooth/handsfree_ag/prj.conf @@ -0,0 +1,6 @@ +CONFIG_BT=y +CONFIG_BT_CLASSIC=y +CONFIG_BT_RFCOMM=y +CONFIG_BT_HFP_AG=y +CONFIG_BT_CENTRAL=y +CONFIG_BT_DEVICE_NAME="Handsfree-ag" diff --git a/samples/bluetooth/handsfree_ag/sample.yaml b/samples/bluetooth/handsfree_ag/sample.yaml new file mode 100644 index 0000000000000..416834fc191e8 --- /dev/null +++ b/samples/bluetooth/handsfree_ag/sample.yaml @@ -0,0 +1,13 @@ +sample: + name: Bluetooth Handsfree Audio Gateway +tests: + sample.bluetooth.handsfree.ag: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + tags: bluetooth + integration_platforms: + - qemu_cortex_m3 + extra_configs: + - CONFIG_BT_HFP_AG_CALL_OUTGOING=y diff --git a/samples/bluetooth/handsfree_ag/src/main.c b/samples/bluetooth/handsfree_ag/src/main.c new file mode 100644 index 0000000000000..03c76eb0805b5 --- /dev/null +++ b/samples/bluetooth/handsfree_ag/src/main.c @@ -0,0 +1,384 @@ +/* main.c - Application main entry point */ + +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static struct bt_conn *default_conn; +struct bt_hfp_ag *hfp_ag; + +static struct bt_br_discovery_param br_discover; + +static struct bt_br_discovery_param br_discover; +static struct bt_br_discovery_result scan_result[CONFIG_BT_HFP_AG_DISCOVER_RESULT_COUNT]; + +struct k_work discover_work; +struct k_work_delayable call_connect_work; +struct k_work_delayable call_disconnect_work; + +struct k_work_delayable call_remote_ringing_work; +struct k_work_delayable call_remote_accept_work; + +NET_BUF_POOL_DEFINE(sdp_discover_pool, 10, BT_L2CAP_BUF_SIZE(CONFIG_BT_L2CAP_TX_MTU), + CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); + +static void ag_connected(struct bt_hfp_ag *ag) +{ + printk("HFP AG connected!\n"); + k_work_schedule(&call_connect_work, K_MSEC(CONFIG_BT_HFP_AG_START_CALL_DELAY_TIME)); +} + +static void ag_disconnected(struct bt_hfp_ag *ag) +{ + printk("HFP AG disconnected!\n"); +} + +static void ag_sco_connected(struct bt_hfp_ag *ag, struct bt_conn *sco_conn) +{ + printk("HFP AG SCO connected!\n"); +} + +static void ag_sco_disconnected(struct bt_hfp_ag *ag) +{ + printk("HFP AG SCO disconnected!\n"); +} + +static void ag_ringing(struct bt_hfp_ag *ag, bool in_band) +{ + printk("Ringing (in bond? %s)\n", in_band ? "Yes" : "No"); +} + +static void ag_accept(struct bt_hfp_ag *ag) +{ + printk("Call Accepted\n"); + k_work_schedule(&call_disconnect_work, K_SECONDS(10)); +} + +static void ag_reject(struct bt_hfp_ag *ag) +{ + printk("Call Rejected\n"); + k_work_schedule(&call_disconnect_work, K_SECONDS(1)); +} + +static void ag_terminate(struct bt_hfp_ag *ag) +{ + printk("Call terminated\n"); + k_work_schedule(&call_disconnect_work, K_SECONDS(1)); +} + +static void ag_outgoing(struct bt_hfp_ag *ag, const char *number) +{ + printk("Call outgoing, remote number %s\n", number); + k_work_cancel_delayable(&call_connect_work); + k_work_schedule(&call_remote_ringing_work, K_SECONDS(1)); +} + +static void ag_incoming(struct bt_hfp_ag *ag, const char *number) +{ + printk("Incoming call, remote number %s\n", number); + k_work_cancel_delayable(&call_connect_work); +} + +static struct bt_hfp_ag_cb ag_cb = { + .connected = ag_connected, + .disconnected = ag_disconnected, + .sco_connected = ag_sco_connected, + .sco_disconnected = ag_sco_disconnected, + .outgoing = ag_outgoing, + .incoming = ag_incoming, + .ringing = ag_ringing, + .accept = ag_accept, + .reject = ag_reject, + .terminate = ag_terminate, +}; + +static uint8_t sdp_discover_cb(struct bt_conn *conn, struct bt_sdp_client_result *result) +{ + int err; + uint16_t value; + + printk("Discover done\n"); + + if (result->resp_buf != NULL) { + err = bt_sdp_get_proto_param(result->resp_buf, BT_SDP_PROTO_RFCOMM, &value); + + if (err != 0) { + printk("Fail to parser RFCOMM the SDP response!\n"); + } else { + printk("The server channel is %d\n", value); + err = bt_hfp_ag_connect(conn, &hfp_ag, value); + if (err != 0) { + printk("Fail to create hfp AG connection (err %d)\n", err); + } + } + } + + return BT_SDP_DISCOVER_UUID_STOP; +} + +static struct bt_sdp_discover_params sdp_discover = { + .func = sdp_discover_cb, + .pool = &sdp_discover_pool, + .uuid = BT_UUID_DECLARE_16(BT_SDP_HANDSFREE_SVCLASS), +}; + +static void connected(struct bt_conn *conn, uint8_t err) +{ + int res; + + if (err) { + if (default_conn != NULL) { + default_conn = NULL; + } + printk("Connection failed (err 0x%02x)\n", err); + } else { + if (default_conn == conn) { + struct bt_conn_info info; + + bt_conn_get_info(conn, &info); + if (info.type != BT_CONN_TYPE_BR) { + return; + } + + /* + * Do an SDP Query on Successful ACL connection complete with the + * required device + */ + res = bt_sdp_discover(default_conn, &sdp_discover); + if (res) { + printk("SDP discovery failed (err %d)\r\n", res); + } else { + printk("SDP discovery started\r\n"); + } + printk("Connected\n"); + } + } +} + +static void disconnected(struct bt_conn *conn, uint8_t reason) +{ + printk("Disconnected (reason 0x%02x)\n", reason); + + if (default_conn != conn) { + return; + } + + if (default_conn) { + default_conn = NULL; + } else { + return; + } +} + +static void security_changed(struct bt_conn *conn, bt_security_t level, enum bt_security_err err) +{ + char addr[BT_ADDR_LE_STR_LEN]; + struct bt_conn_info info; + + bt_conn_get_info(conn, &info); + + bt_addr_to_str(info.br.dst, addr, sizeof(addr)); + + printk("Security changed: %s level %u (err %d)\n", addr, level, err); +} + +static struct bt_conn_cb conn_callbacks = { + .connected = connected, + .disconnected = disconnected, + .security_changed = security_changed, +}; + +static void scan_discovery_cb(struct bt_br_discovery_result *results, size_t count) +{ + char addr[BT_ADDR_LE_STR_LEN]; + uint8_t *eir; + bool cod_hf = false; + static uint8_t temp[240]; + size_t len = sizeof(results->eir); + uint8_t major_device; + uint8_t minor_device; + size_t i; + + for (i = 0; i < count; i++) { + bt_addr_to_str(&results[i].addr, addr, sizeof(addr)); + printk("Device[%d]: %s, rssi %d, cod 0x%X%X%X", i, addr, results[i].rssi, + results[i].cod[0], results[i].cod[1], results[i].cod[2]); + + major_device = (uint8_t)BT_COD_MAJOR_DEVICE_CLASS(results[i].cod); + minor_device = (uint8_t)BT_COD_MINOR_DEVICE_CLASS(results[i].cod); + + if ((major_device & BT_COD_MAJOR_AUDIO_VIDEO) && + (minor_device & BT_COD_MAJOR_AUDIO_VIDEO_MINOR_HANDS_FREE)) { + cod_hf = true; + } + + eir = results[i].eir; + + while ((eir[0] > 2) && (len > eir[0])) { + switch (eir[1]) { + case BT_DATA_NAME_SHORTENED: + case BT_DATA_NAME_COMPLETE: + memcpy(temp, &eir[2], eir[0] - 1); + temp[eir[0] - 1] = '\0'; /* Set end flag */ + printk(", name %s", temp); + break; + } + len = len - eir[0] - 1; + eir = eir + eir[0] + 1; + } + printk("\n"); + + if (cod_hf) { + break; + } + } + + if (!cod_hf) { + (void)k_work_submit(&discover_work); + } else { + (void)k_work_cancel(&discover_work); + default_conn = bt_conn_create_br(&results[i].addr, BT_BR_CONN_PARAM_DEFAULT); + + if (default_conn == NULL) { + printk("Fail to create the connecton\n"); + } else { + bt_conn_unref(default_conn); + } + } +} + +static void discover_work_handler(struct k_work *work) +{ + int err; + + br_discover.length = 10; + br_discover.limited = false; + + err = bt_br_discovery_start(&br_discover, scan_result, + CONFIG_BT_HFP_AG_DISCOVER_RESULT_COUNT, scan_discovery_cb); + if (err) { + printk("Fail to start discovery (err %d)\n", err); + return; + } +} + +static void call_connect_work_handler(struct k_work *work) +{ +#if CONFIG_BT_HFP_AG_CALL_OUTGOING + int err; + + printk("Dialing\n"); + + err = bt_hfp_ag_outgoing(hfp_ag, "test_hf"); + + if (err != 0) { + printk("Fail to dial a call (err %d)\n", err); + } +#else + int err = bt_hfp_ag_remote_incoming(hfp_ag, "test_hf"); + + if (err != 0) { + printk("Fail to set remote incoming call (err %d)\n", err); + } +#endif /* CONFIG_BT_HFP_AG_CALL_OUTGOING */ +} + +static void call_disconnect_work_handler(struct k_work *work) +{ + int err; + + if (default_conn != NULL) { + err = bt_conn_disconnect(default_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN); + + if (err != 0) { + printk("Fail to disconnect acl connection (err %d)\n", err); + } + } +} + +static void call_remote_ringing_work_handler(struct k_work *work) +{ + int err; + + printk("Remote starts ringing\n"); + + err = bt_hfp_ag_remote_ringing(hfp_ag); + + if (err != 0) { + printk("Fail to notify hfp unit that the remote starts ringing (err %d)\n", err); + } else { + k_work_schedule(&call_remote_accept_work, K_SECONDS(1)); + } +} + +static void call_remote_accept_work_handler(struct k_work *work) +{ + int err; + + printk("Remote accepts the call\n"); + + err = bt_hfp_ag_remote_accept(hfp_ag); + + if (err != 0) { + printk("Fail to notify hfp unit that the remote accepts call (err %d)\n", err); + } +} + +static void bt_ready(int err) +{ + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + return; + } + + if (IS_ENABLED(CONFIG_SETTINGS)) { + settings_load(); + } + + printk("Bluetooth initialized\n"); + + bt_conn_cb_register(&conn_callbacks); + + bt_hfp_ag_register(&ag_cb); + + k_work_init(&discover_work, discover_work_handler); + + (void)k_work_submit(&discover_work); + + k_work_init_delayable(&call_connect_work, call_connect_work_handler); + k_work_init_delayable(&call_disconnect_work, call_disconnect_work_handler); + + k_work_init_delayable(&call_remote_ringing_work, call_remote_ringing_work_handler); + k_work_init_delayable(&call_remote_accept_work, call_remote_accept_work_handler); +} + +int main(void) +{ + int err; + + printk("Bluetooth Handsfree AG demo start...\n"); + + err = bt_enable(bt_ready); + if (err) { + printk("Bluetooth init failed (err %d)\n", err); + } + return 0; +} diff --git a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c index 3fe6948e63dd7..e2b4b3022de79 100644 --- a/samples/bluetooth/hap_ha/src/bap_unicast_sr.c +++ b/samples/bluetooth/hap_ha/src/bap_unicast_sr.c @@ -93,7 +93,8 @@ static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); } - if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation) == 0) { + ret = bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, false); + if (ret == 0) { printk(" Channel allocation: 0x%x\n", chan_allocation); } diff --git a/samples/bluetooth/hap_ha/src/csip_set_member.c b/samples/bluetooth/hap_ha/src/csip_set_member.c index 9d76a335571f5..962ac3579dad7 100644 --- a/samples/bluetooth/hap_ha/src/csip_set_member.c +++ b/samples/bluetooth/hap_ha/src/csip_set_member.c @@ -41,7 +41,7 @@ int csip_set_member_init(void) .set_size = 2, .rank = CONFIG_HAP_HA_SET_RANK, .lockable = false, - .set_sirk = CSIP_SIRK_DEBUG, + .sirk = CSIP_SIRK_DEBUG, .cb = &csip_cb, }; diff --git a/samples/bluetooth/hap_ha/src/main.c b/samples/bluetooth/hap_ha/src/main.c index 205feceb0b849..586ed60046919 100644 --- a/samples/bluetooth/hap_ha/src/main.c +++ b/samples/bluetooth/hap_ha/src/main.c @@ -100,7 +100,7 @@ static void adv_work_handler(struct k_work *work) int err; if (ext_adv == NULL) { - /* Create a non-connectable non-scannable advertising set */ + /* Create a connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, &adv_cb, &ext_adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf index 7fd4d377b1d76..27f7b9b80ea20 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_bis-bt_ll_sw_split.conf @@ -77,7 +77,7 @@ CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=6 CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_ISO=y -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 # ISO Receive Controller @@ -89,7 +89,7 @@ CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf index 18606ee3a67f2..040e1db6b4f17 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_cis-bt_ll_sw_split.conf @@ -77,12 +77,12 @@ CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=6 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf index 823343bc3f65d..8fbd3d3af2dcc 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf @@ -9,6 +9,9 @@ CONFIG_IPC_SERVICE_BACKEND_RPMSG_WQ_STACK_SIZE=512 CONFIG_HEAP_MEM_POOL_SIZE=8192 CONFIG_CBPRINTF_REDUCED_INTEGRAL=y +CONFIG_ISR_TABLES_LOCAL_DECLARATION=y +CONFIG_LTO=y + CONFIG_BT=y CONFIG_BT_HCI_RAW=y CONFIG_BT_MAX_CONN=2 @@ -82,7 +85,7 @@ CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=6 CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_ISO=y -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 # ISO Receive Controller @@ -95,12 +98,12 @@ CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf index 22d7f2e726dbb..05645663bc442 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_broadcast-bt_ll_sw_split.conf @@ -31,8 +31,8 @@ CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 CONFIG_BT_CTLR_ADV_ISO=y CONFIG_BT_CTLR_ISO_TX_BUFFERS=16 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 CONFIG_BT_CTLR_ISOAL_SOURCES=2 diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf index c6e0172b69460..56e80860f326b 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_central-bt_ll_sw_split.conf @@ -44,12 +44,12 @@ CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=191 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=n -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=16 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf index 3272d896ca62c..b72aaa624f1a7 100644 --- a/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_ipc/nrf5340_cpunet_iso_peripheral-bt_ll_sw_split.conf @@ -44,12 +44,12 @@ CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=n CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=16 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_ipc/src/main.c b/samples/bluetooth/hci_ipc/src/main.c index 5f0614139be7a..6e1f275ffd03c 100644 --- a/samples/bluetooth/hci_ipc/src/main.c +++ b/samples/bluetooth/hci_ipc/src/main.c @@ -294,7 +294,7 @@ void bt_ctlr_assert_handle(char *file, uint32_t line) struct net_buf *buf; buf = hci_vs_err_assert(file, line); - if (buf == NULL) { + if (buf != NULL) { /* Send the event over ipc */ hci_ipc_send(buf, HCI_FATAL_ERR_MSG); } else { @@ -320,7 +320,7 @@ void bt_ctlr_assert_handle(char *file, uint32_t line) #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) +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf) { /* Disable interrupts, this is unrecoverable */ (void)irq_lock(); diff --git a/samples/bluetooth/hci_pwr_ctrl/src/main.c b/samples/bluetooth/hci_pwr_ctrl/src/main.c index 74318525753da..f4c66ed2e094d 100644 --- a/samples/bluetooth/hci_pwr_ctrl/src/main.c +++ b/samples/bluetooth/hci_pwr_ctrl/src/main.c @@ -43,8 +43,7 @@ static K_THREAD_STACK_DEFINE(pwr_thread_stack, 512); static const int8_t txpower[DEVICE_BEACON_TXPOWER_NUM] = {4, 0, -3, -8, -15, -18, -23, -30}; static const struct bt_le_adv_param *param = - BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, - 0x0020, 0x0020, NULL); + BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME, 0x0020, 0x0020, NULL); static void read_conn_rssi(uint16_t handle, int8_t *rssi) { diff --git a/samples/bluetooth/hci_uart/README.rst b/samples/bluetooth/hci_uart/README.rst index a7a82fc8d01d0..84fc12080992b 100644 --- a/samples/bluetooth/hci_uart/README.rst +++ b/samples/bluetooth/hci_uart/README.rst @@ -177,9 +177,9 @@ driver instead of the built-in controller: CONFIG_BT_HCI=y CONFIG_BT_CTLR=n - CONFIG_BT_H4=y -Similarly, the `zephyr,bt-uart` DTS property selects which uart to use: +Similarly, the `zephyr,bt-hci` DTS property selects which HCI instance to use. +The UART needs to have as its child node a HCI UART node: .. code-block:: dts @@ -187,6 +187,14 @@ Similarly, the `zephyr,bt-uart` DTS property selects which uart to use: chosen { zephyr,console = &uart0; zephyr,shell-uart = &uart0; - zephyr,bt-uart = &uart1; + zephyr,bt-hci = &bt_hci_uart; + }; + }; + + &uart1 { + status = "okay"; + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; }; }; diff --git a/samples/bluetooth/hci_uart/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/bluetooth/hci_uart/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 0000000000000..7ba5755c68133 --- /dev/null +++ b/samples/bluetooth/hci_uart/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + &uart20 { + compatible = "nordic,nrf-uarte"; + current-speed = <1000000>; + status = "okay"; + hw-flow-control; +}; diff --git a/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840.overlay b/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840.overlay index 4209320fcff3f..8ec74170f94eb 100644 --- a/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840.overlay +++ b/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840.overlay @@ -4,9 +4,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include +#include -#include +#include &uart1 { current-speed = <1000000>; diff --git a/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840_0_14_0.overlay b/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840_0_14_0.overlay index 409d3bada63f0..692d2a5749b07 100644 --- a/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840_0_14_0.overlay +++ b/samples/bluetooth/hci_uart/boards/nrf9160dk_nrf52840_0_14_0.overlay @@ -5,4 +5,4 @@ */ /* Use the reset line that is available starting from v0.14.0 of the DK. */ -#include +#include diff --git a/samples/bluetooth/hci_uart/dts/arm/nordic/override.dtsi b/samples/bluetooth/hci_uart/dts/arm/nordic/override.dtsi new file mode 100644 index 0000000000000..882f70755d59d --- /dev/null +++ b/samples/bluetooth/hci_uart/dts/arm/nordic/override.dtsi @@ -0,0 +1,7 @@ +/* Keep default IRQ priority low for peripherals to reduce Radio ISR latency. + * ARM Cortex-M4 lowest priority value of 5, i.e. considering Zephyr reserved 2 + * levels for Exceptions and ZLI (if enabled). + * ARM Cortex-M0 lowest priority value of 3, i.e. we use it as Zephyr has no + * support for ZLI on Cortex-M0. + */ +#define NRF_DEFAULT_IRQ_PRIORITY 3 diff --git a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf index 3774532c42415..8d6dbdd87b016 100644 --- a/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf +++ b/samples/bluetooth/hci_uart/overlay-all-bt_ll_sw_split.conf @@ -80,7 +80,7 @@ CONFIG_BT_CTLR_DF_CONN_CTE_REQ=y CONFIG_BT_CTLR_ADV_EXT=y CONFIG_BT_CTLR_ADV_PERIODIC=y CONFIG_BT_CTLR_ADV_ISO=y -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247 CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 # ISO Receive Controller @@ -93,12 +93,12 @@ CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 # ISO Connection Oriented CONFIG_BT_CTLR_CENTRAL_ISO=y CONFIG_BT_CTLR_PERIPHERAL_ISO=y -CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247 CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 # ISO Transmissions CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255 CONFIG_BT_CTLR_ISOAL_SOURCES=2 # ISO Receptions diff --git a/samples/bluetooth/hci_uart/sample.yaml b/samples/bluetooth/hci_uart/sample.yaml index 033a16c0cb143..7aa49e1eba592 100644 --- a/samples/bluetooth/hci_uart/sample.yaml +++ b/samples/bluetooth/hci_uart/sample.yaml @@ -58,3 +58,13 @@ tests: tags: - uart - bluetooth + sample.bluetooth.hci_uart.nrf54l15.all: + harness: bluetooth + platform_allow: nrf54l15pdk/nrf54l15/cpuapp + integration_platforms: + - nrf54l15pdk/nrf54l15/cpuapp + extra_args: + - OVERLAY_CONFIG=overlay-all-bt_ll_sw_split.conf + tags: + - uart + - bluetooth diff --git a/samples/bluetooth/hci_uart_3wire/CMakeLists.txt b/samples/bluetooth/hci_uart_3wire/CMakeLists.txt new file mode 100644 index 0000000000000..c4f3f3fbbe81b --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(hci_uart_3wire) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/bluetooth/hci_uart_3wire/README.rst b/samples/bluetooth/hci_uart_3wire/README.rst new file mode 100644 index 0000000000000..43e9ea0c6d9a8 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/README.rst @@ -0,0 +1,200 @@ +.. _bluetooth-hci-uart-3wire-sample: + +Bluetooth: HCI UART 3WIRE +######################### + +Overview +********* + +Expose the Zephyr Bluetooth controller support over UART to another device/CPU +using the H:5 HCI transport protocol. + +Requirements +************ + +* A board with BLE support + +Default UART settings +********************* + +By default the controller builds use the following settings: + +* Baudrate: 1Mbit/s +* 8 bits, no parity, 1 stop bit +* Hardware Flow Control (RTS/CTS) disabled + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/bluetooth/hci_uart_3wire` in the +Zephyr tree, and it is built as a standard Zephyr application. + +Using the controller with emulators and BlueZ +********************************************* + +The instructions below show how to use a Nordic nRF5x device as a Zephyr BLE +controller and expose it to Linux's BlueZ. This can be very useful for testing +the Zephyr Link Layer with the BlueZ Host. The Zephyr BLE controller can also +provide a modern BLE 5.0 controller to a Linux-based machine for native +BLE support or QEMU-based development. + +First, make sure you have a recent BlueZ version installed by following the +instructions in the :ref:`bluetooth_bluez` section. + +Now build and flash the sample for the Nordic nRF5x board of your choice. +All of the Nordic Development Kits come with a Segger IC that provides a +debugger interface and a CDC ACM serial port bridge. More information can be +found in :ref:`nordic_segger`. + +For example, to build for the nRF52840 Development Kit: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/hci_uart_3wire + :board: nrf52840dk/nrf52840 + :goals: build flash + +.. _bluetooth-hci-uart-3wire-qemu-posix: + +Using the controller with QEMU or native_sim +============================================ + +In order to use the HCI UART H:5 controller with QEMU or :ref:`native_sim ` you will +need to attach it to the Linux Host first. To do so simply build the sample and +connect the UART to the Linux machine, and then attach it with this command: + +.. code-block:: console + + sudo hciattach -n /dev/ttyACM0 3wire 1000000 + +.. note:: + Depending on the serial port you are using you will need to modify the + ``/dev/ttyACM0`` string to point to the serial device your controller is + connected to. + +.. note:: + If using the BBC micro:bit you will need to modify the baudrate argument + from ``1000000`` to ``115200``. + +.. note:: + The ``-R`` flag passed to ``btattach`` instructs the kernel to avoid + interacting with the controller and instead just be aware of it in order + to proxy it to QEMU later. + +If you are running :file:`btmon` you should see a brief log showing how the +Linux kernel identifies the attached controller. + +Once the controller is attached follow the instructions in the +:ref:`bluetooth_qemu_native` section to use QEMU with it. + +.. _bluetooth-hci-uart-3wire-bluez: + +Using the controller with BlueZ +=============================== + +In order to use the HCI UART H:5 controller with BlueZ you will need to attach it +to the Linux Host first. To do so simply build the sample and connect the +UART to the Linux machine, and then attach it with this command: + +.. code-block:: console + + sudo hciattach -n /dev/ttyACM0 3wire 1000000 + +.. note:: + Depending on the serial port you are using you will need to modify the + ``/dev/ttyACM0`` string to point to the serial device your controller is + connected to. + +.. note:: + If using the BBC micro:bit you will need to modify the baudrate argument + from ``1000000`` to ``115200``. + +If you are running :file:`btmon` you should see a comprehensive log showing how +BlueZ loads and initializes the attached controller. + +Once the controller is attached follow the instructions in the +:ref:`bluetooth_ctlr_bluez` section to use BlueZ with it. + +Debugging the controller +======================== + +The sample can be debugged using RTT since the UART is otherwise used by this +application. To enable debug over RTT the debug configuration file can be used. + +.. code-block:: console + + west build samples/bluetooth/hci_uart_3wire -- -DEXTRA_CONF_FILE='debug.conf' + +Then attach RTT as described here: :ref:`Using Segger J-Link ` + +Support for the Direction Finding +================================= + +The sample can be built with the support for the BLE Direction Finding. +To enable this feature build this sample for specific board variants that provide +required hardware configuration for the Radio. + +.. code-block:: console + + west build samples/bluetooth/hci_uart_3wire -b nrf52833dk/nrf52833@df -- -DCONFIG_BT_CTLR_DF=y + +You can use following targets: + +* ``nrf5340dk/nrf5340/cpunet@df`` +* ``nrf52833dk/nrf52833@df`` + +Check the :ref:`bluetooth_direction_finding_connectionless_rx` and the :ref:`bluetooth_direction_finding_connectionless_tx` for more details. + +Using a USB CDC ACM UART +======================== + +The sample can be configured to use a USB UART instead. See :zephyr_file:`samples/bluetooth/hci_uart_3wire/boards/nrf52840dongle_nrf52840.conf` and :zephyr_file:`samples/bluetooth/hci_uart_3wire/boards/nrf52840dongle_nrf52840.overlay`. + +Using the controller with the Zephyr host +========================================= + +This describes how to hook up a board running this sample to a board running +an application that uses the Zephyr host. + +On the controller side, the `zephyr,bt-c2h-uart` DTS property (in the `chosen` +block) is used to select which uart device to use. For example if we want to +keep the console logs, we can keep console on uart0 and the HCI on uart1 like +so: + +.. code-block:: dts + + / { + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,bt-c2h-uart = &uart1; + }; + }; + +On the host application, some config options need to be used to select the H5 +driver instead of the built-in controller: + +.. code-block:: kconfig + + CONFIG_BT_HCI=y + CONFIG_BT_CTLR=n + +Similarly, the `zephyr,bt-hci` DTS property selects which HCI instance to use. +The UART needs to have as its child node a HCI UART node: + +.. code-block:: dts + + / { + chosen { + zephyr,console = &uart0; + zephyr,shell-uart = &uart0; + zephyr,bt-hci = &bt_hci_uart; + }; + }; + + &uart1 { + status = "okay"; + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-3wire-uart"; + status = "okay"; + }; + }; diff --git a/samples/bluetooth/hci_uart_3wire/boards/96b_nitrogen.overlay b/samples/bluetooth/hci_uart_3wire/boards/96b_nitrogen.overlay new file mode 100644 index 0000000000000..f3050da174716 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/96b_nitrogen.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "okay"; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/bbc_microbit.conf b/samples/bluetooth/hci_uart_3wire/boards/bbc_microbit.conf new file mode 100644 index 0000000000000..4ec62e167ccc2 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/bbc_microbit.conf @@ -0,0 +1,8 @@ +CONFIG_MAIN_STACK_SIZE=512 +CONFIG_IDLE_STACK_SIZE=256 +CONFIG_ISR_STACK_SIZE=512 +CONFIG_BT_MAX_CONN=10 +# Revert values set in prj.conf, set them to their Kconfig default value +CONFIG_BT_BUF_CMD_TX_SIZE=65 +CONFIG_BT_BUF_ACL_RX_SIZE=69 +CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=43 diff --git a/samples/bluetooth/hci_uart_3wire/boards/bbc_microbit_v2.overlay b/samples/bluetooth/hci_uart_3wire/boards/bbc_microbit_v2.overlay new file mode 100644 index 0000000000000..f3050da174716 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/bbc_microbit_v2.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "okay"; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf52833dk_nrf52833.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf52833dk_nrf52833.overlay new file mode 100644 index 0000000000000..4763dc348cc99 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf52833dk_nrf52833.overlay @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + &uart0 { + compatible = "nordic,nrf-uarte"; + current-speed = <1000000>; + status = "okay"; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf52833dk_nrf52833_df.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf52833dk_nrf52833_df.overlay new file mode 100644 index 0000000000000..5bfb3a2a4b1ab --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf52833dk_nrf52833_df.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + &uart0 { + compatible = "nordic,nrf-uarte"; + current-speed = <1000000>; + status = "okay"; +}; + +&radio { + status = "okay"; + /* This is an example number of antennas that may be available + * on antenna matrix board. + */ + dfe-antenna-num = <10>; + /* This is an example switch pattern that will be used to set an + * antenna for Tx PDU (period before start of Tx CTE). + */ + dfe-pdu-antenna = <0x0>; + + /* These are example GPIO pin numbers that are provided to + * Radio peripheral. The pins will be acquired by Radio to + * drive antenna switching when AoD is enabled. + */ + dfegpio0-gpios = <&gpio0 3 0>; + dfegpio1-gpios = <&gpio0 4 0>; + dfegpio2-gpios = <&gpio0 28 0>; + dfegpio3-gpios = <&gpio0 29 0>; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf52840dk_nrf52840.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 0000000000000..f3050da174716 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "okay"; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf52840dongle_nrf52840.conf b/samples/bluetooth/hci_uart_3wire/boards/nrf52840dongle_nrf52840.conf new file mode 100644 index 0000000000000..f87530dd3c2c7 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf52840dongle_nrf52840.conf @@ -0,0 +1,4 @@ +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr HCI UART 3Wire sample" +CONFIG_USB_CDC_ACM=y +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf52_blenano2.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf52_blenano2.overlay new file mode 100644 index 0000000000000..f3050da174716 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf52_blenano2.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <1000000>; + status = "okay"; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf52dk_nrf52832.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf52dk_nrf52832.overlay new file mode 100644 index 0000000000000..70a51fae78b5b --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf52dk_nrf52832.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&uart0 { + compatible = "nordic,nrf-uart"; + current-speed = <115200>; + status = "okay"; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf5340dk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..69855b64d7b54 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&uart0 { + compatible = "nordic,nrf-uarte"; + current-speed = <1000000>; + status = "okay"; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf5340dk_nrf5340_cpunet.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf5340dk_nrf5340_cpunet.overlay new file mode 100644 index 0000000000000..69855b64d7b54 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf5340dk_nrf5340_cpunet.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&uart0 { + compatible = "nordic,nrf-uarte"; + current-speed = <1000000>; + status = "okay"; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf5340dk_nrf5340_cpunet_df.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf5340dk_nrf5340_cpunet_df.overlay new file mode 100644 index 0000000000000..b065708f0b6bc --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf5340dk_nrf5340_cpunet_df.overlay @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + + &uart0 { + compatible = "nordic,nrf-uarte"; + current-speed = <1000000>; + status = "okay"; +}; + +&radio { + status = "okay"; + /* This is an example number of antennas that may be available + * on antenna matrix board. + */ + dfe-antenna-num = <10>; + /* This is an example switch pattern that will be used to set an + * antenna for Tx PDU (period before start of Tx CTE). + */ + dfe-pdu-antenna = <0x0>; + + /* These are example GPIO pin numbers that are provided to + * Radio peripheral. The pins will be acquired by Radio to + * drive antenna switching when AoD is enabled. + */ + dfegpio0-gpios = <&gpio0 4 0>; + dfegpio1-gpios = <&gpio0 5 0>; + dfegpio2-gpios = <&gpio0 6 0>; + dfegpio3-gpios = <&gpio0 7 0>; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf5340pdk_nrf5340_cpuapp.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf5340pdk_nrf5340_cpuapp.overlay new file mode 100644 index 0000000000000..69855b64d7b54 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf5340pdk_nrf5340_cpuapp.overlay @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +&uart0 { + compatible = "nordic,nrf-uarte"; + current-speed = <1000000>; + status = "okay"; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf9160dk_nrf52840.conf b/samples/bluetooth/hci_uart_3wire/boards/nrf9160dk_nrf52840.conf new file mode 100644 index 0000000000000..764798d6ef16f --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf9160dk_nrf52840.conf @@ -0,0 +1,4 @@ +# Override prj.conf defaults +CONFIG_CONSOLE=y +CONFIG_STDOUT_CONSOLE=y +CONFIG_UART_CONSOLE=y diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf9160dk_nrf52840.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf9160dk_nrf52840.overlay new file mode 100644 index 0000000000000..b8ad454a58a76 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf9160dk_nrf52840.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include + +&uart1 { + current-speed = <1000000>; +}; + +/ { + chosen { + zephyr,bt-c2h-uart=&uart1; + }; +}; diff --git a/samples/bluetooth/hci_uart_3wire/boards/nrf9160dk_nrf52840_0_14_0.overlay b/samples/bluetooth/hci_uart_3wire/boards/nrf9160dk_nrf52840_0_14_0.overlay new file mode 100644 index 0000000000000..409d3bada63f0 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/boards/nrf9160dk_nrf52840_0_14_0.overlay @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Use the reset line that is available starting from v0.14.0 of the DK. */ +#include diff --git a/samples/bluetooth/hci_uart_3wire/debug.conf b/samples/bluetooth/hci_uart_3wire/debug.conf new file mode 100644 index 0000000000000..7d0c43dab62f7 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/debug.conf @@ -0,0 +1,21 @@ +CONFIG_ASSERT=y + +CONFIG_THREAD_NAME=y +CONFIG_THREAD_ANALYZER=y +CONFIG_THREAD_ANALYZER_AUTO=y +CONFIG_THREAD_ANALYZER_RUN_UNLOCKED=y + +CONFIG_HW_STACK_PROTECTION=y + +CONFIG_CONSOLE=y +CONFIG_LOG=y +CONFIG_LOG_BUFFER_SIZE=4096 +CONFIG_RTT_CONSOLE=y +CONFIG_LOG_BACKEND_RTT=y +CONFIG_LOG_BACKEND_RTT_MODE_DROP=n +CONFIG_USE_SEGGER_RTT=y +CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096 +CONFIG_LOG_BACKEND_SHOW_COLOR=n +CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=1024 + +CONFIG_LOG_DEFAULT_LEVEL=3 diff --git a/samples/bluetooth/hci_uart_3wire/overlay-all-bt_ll_sw_split.conf b/samples/bluetooth/hci_uart_3wire/overlay-all-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..75542eff6705e --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/overlay-all-bt_ll_sw_split.conf @@ -0,0 +1,108 @@ +CONFIG_BT_BUF_EVT_RX_COUNT=16 + +CONFIG_BT_BUF_EVT_RX_SIZE=255 +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_ACL_TX_SIZE=251 +CONFIG_BT_BUF_CMD_TX_SIZE=255 + +# Host and Controller common dependencies +CONFIG_BT_EXT_ADV=y +CONFIG_BT_PER_ADV=y +CONFIG_BT_PER_ADV_SYNC=y +CONFIG_BT_PER_ADV_SYNC_MAX=2 + +# Broadcast and Connected ISO +CONFIG_BT_ISO_BROADCASTER=y +CONFIG_BT_ISO_SYNC_RECEIVER=y +CONFIG_BT_ISO_CENTRAL=y +CONFIG_BT_ISO_PERIPHERAL=y + +# ISO Streams +CONFIG_BT_ISO_MAX_CHAN=2 + +# Controller +CONFIG_BT_LL_SW_SPLIT=y +CONFIG_BT_CTLR_DTM_HCI=y + +# Rx ACL and Adv Reports +CONFIG_BT_CTLR_RX_BUFFERS=9 +CONFIG_BT_CTLR_DATA_LENGTH_MAX=251 + +# Coded PHY support +CONFIG_BT_CTLR_PHY_CODED=y + +# Advertising Sets and Extended Scanning +CONFIG_BT_CTLR_ADV_EXT=y +CONFIG_BT_CTLR_ADV_SET=3 +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 +CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 + +CONFIG_BT_CTLR_ADVANCED_FEATURES=y +CONFIG_BT_CTLR_ADV_AUX_SET=3 +CONFIG_BT_CTLR_ADV_AUX_PDU_BACK2BACK=y +CONFIG_BT_CTLR_ADV_SYNC_SET=3 +CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK=y +CONFIG_BT_CTLR_ADV_DATA_BUF_MAX=6 + +# Increase the below to receive interleaved advertising chains +CONFIG_BT_CTLR_SCAN_AUX_SET=1 + +CONFIG_BT_CTLR_ADV_RESERVE_MAX=n +CONFIG_BT_CTLR_CENTRAL_RESERVE_MAX=n +CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE=n +CONFIG_BT_CTLR_SCAN_UNRESERVED=y +CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH=y +CONFIG_BT_TICKER_EXT=y +CONFIG_BT_TICKER_EXT_SLOT_WINDOW_YIELD=y + +# Control Procedure +CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=6 + +# Direction Finding +CONFIG_BT_CTLR_DF=y +CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX=3 +CONFIG_BT_CTLR_DF_PER_SCAN_CTE_NUM_MAX=3 + +# Direction Finding Tx +CONFIG_BT_CTLR_DF_CTE_TX=y +CONFIG_BT_CTLR_DF_CONN_CTE_TX=y +CONFIG_BT_CTLR_DF_ANT_SWITCH_TX=y +CONFIG_BT_CTLR_DF_CONN_CTE_RSP=y + +# Direction Finding Rx +CONFIG_BT_CTLR_DF_CTE_RX=y +CONFIG_BT_CTLR_DF_CONN_CTE_RX=y +CONFIG_BT_CTLR_DF_ANT_SWITCH_RX=y +CONFIG_BT_CTLR_DF_CONN_CTE_REQ=y + +# ISO Broadcaster Controller +CONFIG_BT_CTLR_ADV_EXT=y +CONFIG_BT_CTLR_ADV_PERIODIC=y +CONFIG_BT_CTLR_ADV_ISO=y +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 + +# ISO Receive Controller +CONFIG_BT_CTLR_ADV_EXT=y +CONFIG_BT_CTLR_SYNC_PERIODIC=y +CONFIG_BT_CTLR_SYNC_ISO=y +CONFIG_BT_CTLR_SYNC_ISO_PDU_LEN_MAX=251 +CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2 + +# ISO Connection Oriented +CONFIG_BT_CTLR_CENTRAL_ISO=y +CONFIG_BT_CTLR_PERIPHERAL_ISO=y +CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=251 +CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251 + +# ISO Transmissions +CONFIG_BT_CTLR_ISO_TX_BUFFERS=8 +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=251 +CONFIG_BT_CTLR_ISOAL_SOURCES=2 + +# ISO Receptions +CONFIG_BT_CTLR_ISO_RX_BUFFERS=8 +CONFIG_BT_CTLR_ISOAL_SINKS=2 + +# Tx Power Dynamic Control +CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y diff --git a/samples/bluetooth/hci_uart_3wire/prj.conf b/samples/bluetooth/hci_uart_3wire/prj.conf new file mode 100644 index 0000000000000..02f16a24138b3 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/prj.conf @@ -0,0 +1,22 @@ +CONFIG_CONSOLE=n +CONFIG_STDOUT_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_GPIO=y +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_HCI_RAW_H4=y +CONFIG_BT_HCI_RAW_H4_ENABLE=y +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 +CONFIG_BT_MAX_CONN=16 +CONFIG_BT_TINYCRYPT_ECC=n +CONFIG_BT_CTLR_DTM_HCI=y + +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 + +# Workaround: Unable to allocate command buffer when using K_NO_WAIT since +# Host number of completed commands does not follow normal flow control. +CONFIG_BT_BUF_CMD_TX_COUNT=10 diff --git a/samples/bluetooth/hci_uart_3wire/sample.yaml b/samples/bluetooth/hci_uart_3wire/sample.yaml new file mode 100644 index 0000000000000..19e799cf853c4 --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/sample.yaml @@ -0,0 +1,60 @@ +sample: + name: Bluetooth HCI UART 3Wire + description: Allows Zephyr to provide Bluetooth connectivity via UART 3Wire +tests: + sample.bluetooth.hci_uart_3wire.nrf5: + harness: bluetooth + platform_allow: + - nrf52dk/nrf52832 + tags: + - uart + - bluetooth + sample.bluetooth.hci_uart_3wire.nrf52833.df: + harness: bluetooth + platform_allow: nrf52833dk/nrf52833 + extra_args: DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + extra_configs: + - CONFIG_BT_CTLR_DF=y + tags: + - uart + - bluetooth + sample.bluetooth.hci_uart_3wire.nrf5340_netcore.df: + harness: bluetooth + platform_allow: nrf5340dk/nrf5340/cpunet + extra_args: DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + extra_configs: + - CONFIG_BT_CTLR_DF=y + tags: + - uart + - bluetooth + sample.bluetooth.hci_uart_3wire.nrf52833.df.iq_report: + harness: bluetooth + platform_allow: nrf52833dk/nrf52833 + extra_args: DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + extra_configs: + - CONFIG_BT_CTLR_DF=y + - CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT=y + tags: + - uart + - bluetooth + sample.bluetooth.hci_uart_3wire.nrf5340_netcore.df.iq_report: + harness: bluetooth + platform_allow: nrf5340dk/nrf5340/cpunet + extra_args: DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay + extra_configs: + - CONFIG_BT_CTLR_DF=y + - CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT=y + tags: + - uart + - bluetooth + sample.bluetooth.hci_uart_3wire.nrf52833.all: + harness: bluetooth + platform_allow: nrf52833dk/nrf52833 + integration_platforms: + - nrf52833dk/nrf52833 + extra_args: + - OVERLAY_CONFIG=overlay-all-bt_ll_sw_split.conf + - DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay + tags: + - uart + - bluetooth diff --git a/samples/bluetooth/hci_uart_3wire/src/main.c b/samples/bluetooth/hci_uart_3wire/src/main.c new file mode 100644 index 0000000000000..9c8a66e6a3c0f --- /dev/null +++ b/samples/bluetooth/hci_uart_3wire/src/main.c @@ -0,0 +1,821 @@ +/* + * Copyright (c) 2024 Xiaomi Coopration + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#define LOG_MODULE_NAME hci_uart_3wire +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +static K_KERNEL_STACK_DEFINE(tx_stack, CONFIG_BT_HCI_TX_STACK_SIZE); +static K_KERNEL_STACK_DEFINE(rx_stack, CONFIG_BT_RX_STACK_SIZE); + +static struct k_thread tx_thread_data; +static struct k_thread rx_thread_data; + +static struct k_work_delayable ack_work; +static struct k_work_delayable retx_work; + +#define HCI_3WIRE_ACK_PKT 0x00 +#define HCI_COMMAND_PKT 0x01 +#define HCI_ACLDATA_PKT 0x02 +#define HCI_SCODATA_PKT 0x03 +#define HCI_EVENT_PKT 0x04 +#define HCI_ISODATA_PKT 0x05 +#define HCI_3WIRE_LINK_PKT 0x0f +#define HCI_VENDOR_PKT 0xff + +static bool reliable_packet(uint8_t type) +{ + switch (type) { + case HCI_COMMAND_PKT: + case HCI_ACLDATA_PKT: + case HCI_EVENT_PKT: + case HCI_ISODATA_PKT: + return true; + default: + return false; + } +} + +/* FIXME: Correct timeout */ +#define H5_RX_ACK_TIMEOUT K_MSEC(250) +#define H5_TX_ACK_TIMEOUT K_MSEC(250) + +#define SLIP_DELIMITER 0xc0 +#define SLIP_ESC 0xdb +#define SLIP_ESC_DELIM 0xdc +#define SLIP_ESC_ESC 0xdd + +#define H5_RX_ESC 1 +#define H5_TX_ACK_PEND 2 + +#define H5_HDR_SEQ(hdr) ((hdr)[0] & 0x07) +#define H5_HDR_ACK(hdr) (((hdr)[0] >> 3) & 0x07) +#define H5_HDR_CRC(hdr) (((hdr)[0] >> 6) & 0x01) +#define H5_HDR_RELIABLE(hdr) (((hdr)[0] >> 7) & 0x01) +#define H5_HDR_PKT_TYPE(hdr) ((hdr)[1] & 0x0f) +#define H5_HDR_LEN(hdr) ((((hdr)[1] >> 4) & 0x0f) + ((hdr)[2] << 4)) + +#define H5_SET_SEQ(hdr, seq) ((hdr)[0] |= (seq)) +#define H5_SET_ACK(hdr, ack) ((hdr)[0] |= (ack) << 3) +#define H5_SET_RELIABLE(hdr) ((hdr)[0] |= 1 << 7) +#define H5_SET_TYPE(hdr, type) ((hdr)[1] |= type) +#define H5_SET_LEN(hdr, len) (((hdr)[1] |= ((len) & 0x0f) << 4), \ + ((hdr)[2] |= (len) >> 4)) + +#define H5_TX_WIN 4 + +static struct h5 { + struct net_buf *rx_buf; + + struct k_fifo tx_queue; + struct k_fifo rx_queue; + struct k_fifo unack_queue; + + uint8_t tx_win; + uint8_t tx_ack; + uint8_t tx_seq; + + uint8_t rx_ack; + + enum { + UNINIT, + INIT, + ACTIVE, + } link_state; + + enum { + START, + HEADER, + PAYLOAD, + END, + } rx_state; +} h5; + +static uint8_t unack_queue_len; + +static const uint8_t sync_req[] = { 0x01, 0x7e }; +static const uint8_t sync_rsp[] = { 0x02, 0x7d }; +/* Third byte may change */ +static const uint8_t conf_req[] = { 0x03, 0xfc }; +static uint8_t conf_rsp[3] = { 0x04, 0x7b,}; + +/* H5 signal buffers pool */ +#define MAX_SIG_LEN 3 +#define SIGNAL_COUNT 2 +#define SIG_BUF_SIZE (BT_BUF_RESERVE + MAX_SIG_LEN) +NET_BUF_POOL_DEFINE(h5_pool, SIGNAL_COUNT, SIG_BUF_SIZE, 0, NULL); + +static const struct device *const h5_dev = + DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_c2h_uart)); + +static K_FIFO_DEFINE(tx_queue); + +static struct k_poll_signal tx_queue_change = + K_POLL_SIGNAL_INITIALIZER(tx_queue_change); + +static void h5_reset_rx(void) +{ + if (h5.rx_buf) { + net_buf_unref(h5.rx_buf); + h5.rx_buf = NULL; + } + + h5.rx_state = START; +} + +static int h5_unslip_byte(uint8_t *byte) +{ + int count; + + if (*byte != SLIP_ESC) { + return 0; + } + + do { + count = uart_fifo_read(h5_dev, byte, sizeof(*byte)); + } while (!count); + + switch (*byte) { + case SLIP_ESC_DELIM: + *byte = SLIP_DELIMITER; + break; + case SLIP_ESC_ESC: + *byte = SLIP_ESC; + break; + default: + LOG_ERR("Invalid escape byte %x\n", *byte); + return -EIO; + } + + return 0; +} + +static void process_unack(void) +{ + uint8_t next_seq = h5.tx_seq; + uint8_t number_removed = unack_queue_len; + + if (!unack_queue_len) { + return; + } + + LOG_DBG("rx_ack %u tx_ack %u tx_seq %u unack_queue_len %u", h5.rx_ack, h5.tx_ack, h5.tx_seq, + unack_queue_len); + + while (unack_queue_len > 0) { + if (next_seq == h5.rx_ack) { + /* Next sequence number is the same as last received + * ack number + */ + break; + } + + number_removed--; + /* Similar to (n - 1) % 8 with unsigned conversion */ + next_seq = (next_seq - 1) & 0x07; + } + + if (next_seq != h5.rx_ack) { + LOG_ERR("Wrong sequence: rx_ack %u tx_seq %u next_seq %u", h5.rx_ack, h5.tx_seq, + next_seq); + } + + LOG_DBG("Need to remove %u packet from the queue", number_removed); + + while (number_removed) { + struct net_buf *buf = net_buf_get(&h5.unack_queue, K_NO_WAIT); + + if (!buf) { + LOG_ERR("Unack queue is empty"); + break; + } + + /* TODO: print or do something with packet */ + LOG_DBG("Remove buf from the unack_queue"); + + net_buf_unref(buf); + unack_queue_len--; + number_removed--; + } +} + +static void h5_print_header(const uint8_t *hdr, const char *str) +{ + if (H5_HDR_RELIABLE(hdr)) { + LOG_DBG("%s REL: seq %u ack %u crc %u type %u len %u", str, H5_HDR_SEQ(hdr), + H5_HDR_ACK(hdr), H5_HDR_CRC(hdr), H5_HDR_PKT_TYPE(hdr), H5_HDR_LEN(hdr)); + } else { + LOG_DBG("%s UNREL: ack %u crc %u type %u len %u", str, H5_HDR_ACK(hdr), + H5_HDR_CRC(hdr), H5_HDR_PKT_TYPE(hdr), H5_HDR_LEN(hdr)); + } +} + +static void hexdump(const char *str, const uint8_t *packet, size_t length) +{ + int n = 0; + + if (!length) { + printk("%s zero-length signal packet\n", str); + return; + } + + while (length--) { + if (n % 16 == 0) { + printk("%s %08X ", str, n); + } + + printk("%02X ", *packet++); + + n++; + if (n % 8 == 0) { + if (n % 16 == 0) { + printk("\n"); + } else { + printk(" "); + } + } + } + + if (n % 16) { + printk("\n"); + } +} + +static uint8_t h5_slip_byte(uint8_t byte) +{ + switch (byte) { + case SLIP_DELIMITER: + uart_poll_out(h5_dev, SLIP_ESC); + uart_poll_out(h5_dev, SLIP_ESC_DELIM); + return 2; + case SLIP_ESC: + uart_poll_out(h5_dev, SLIP_ESC); + uart_poll_out(h5_dev, SLIP_ESC_ESC); + return 2; + default: + uart_poll_out(h5_dev, byte); + return 1; + } +} + +static void h5_send(const uint8_t *payload, uint8_t type, int len) +{ + uint8_t hdr[4]; + int i; + + hexdump("<= ", payload, len); + + (void)memset(hdr, 0, sizeof(hdr)); + + /* Set ACK for outgoing packet and stop delayed work */ + H5_SET_ACK(hdr, h5.tx_ack); + /* If cancel fails we may ack the same seq number twice, this is OK. */ + (void)k_work_cancel_delayable(&ack_work); + + if (reliable_packet(type)) { + H5_SET_RELIABLE(hdr); + H5_SET_SEQ(hdr, h5.tx_seq); + h5.tx_seq = (h5.tx_seq + 1) % 8; + } + + H5_SET_TYPE(hdr, type); + H5_SET_LEN(hdr, len); + + /* Calculate CRC */ + hdr[3] = ~((hdr[0] + hdr[1] + hdr[2]) & 0xff); + + h5_print_header(hdr, "TX: <"); + + uart_poll_out(h5_dev, SLIP_DELIMITER); + + for (i = 0; i < 4; i++) { + h5_slip_byte(hdr[i]); + } + + for (i = 0; i < len; i++) { + h5_slip_byte(payload[i]); + } + + uart_poll_out(h5_dev, SLIP_DELIMITER); +} + +/* Delayed work taking care about retransmitting packets */ +static void retx_timeout(struct k_work *work) +{ + ARG_UNUSED(work); + + LOG_DBG("unack_queue_len %u", unack_queue_len); + + if (unack_queue_len) { + struct k_fifo tmp_queue; + struct net_buf *buf; + + k_fifo_init(&tmp_queue); + + /* Queue to temporary queue */ + while ((buf = net_buf_get(&h5.tx_queue, K_NO_WAIT))) { + net_buf_put(&tmp_queue, buf); + } + + /* Queue unack packets to the beginning of the queue */ + while ((buf = net_buf_get(&h5.unack_queue, K_NO_WAIT))) { + /* include also packet type */ + net_buf_push(buf, sizeof(uint8_t)); + net_buf_put(&h5.tx_queue, buf); + h5.tx_seq = (h5.tx_seq - 1) & 0x07; + unack_queue_len--; + } + + /* Queue saved packets from temp queue */ + while ((buf = net_buf_get(&tmp_queue, K_NO_WAIT))) { + net_buf_put(&h5.tx_queue, buf); + } + } + + k_poll_signal_raise(&tx_queue_change, 0); +} + +static void ack_timeout(struct k_work *work) +{ + ARG_UNUSED(work); + + LOG_DBG(""); + + h5_send(NULL, HCI_3WIRE_ACK_PKT, 0); +} + +static void h5_process_complete_packet(uint8_t *hdr) +{ + struct net_buf *buf; + + LOG_DBG(""); + + /* rx_ack should be in every packet */ + h5.rx_ack = H5_HDR_ACK(hdr); + + if (reliable_packet(H5_HDR_PKT_TYPE(hdr))) { + /* For reliable packet increment next transmit ack number */ + h5.tx_ack = (h5.tx_ack + 1) % 8; + /* Submit delayed work to ack the packet */ + k_work_reschedule(&ack_work, H5_RX_ACK_TIMEOUT); + } + + h5_print_header(hdr, "RX: >"); + + process_unack(); + + buf = h5.rx_buf; + h5.rx_buf = NULL; + + switch (H5_HDR_PKT_TYPE(hdr)) { + case HCI_3WIRE_ACK_PKT: + net_buf_unref(buf); + break; + case HCI_3WIRE_LINK_PKT: + net_buf_put(&h5.rx_queue, buf); + break; + case HCI_COMMAND_PKT: + case HCI_ACLDATA_PKT: + case HCI_ISODATA_PKT: + hexdump("=> ", buf->data, buf->len); + net_buf_put(&tx_queue, buf); + break; + } +} + +static void bt_uart_isr(const struct device *unused, void *user_data) +{ + static int remaining; + uint8_t byte, type; + int ret; + static uint8_t hdr[4]; + size_t buf_tailroom; + + ARG_UNUSED(unused); + ARG_UNUSED(user_data); + + while (uart_irq_update(h5_dev) && + uart_irq_is_pending(h5_dev)) { + + if (!uart_irq_rx_ready(h5_dev)) { + if (uart_irq_tx_ready(h5_dev)) { + LOG_DBG("transmit ready"); + } else { + LOG_DBG("spurious interrupt"); + } + /* Only the UART RX path is interrupt-enabled */ + break; + } + + ret = uart_fifo_read(h5_dev, &byte, sizeof(byte)); + if (!ret) { + continue; + } + + switch (h5.rx_state) { + case START: + if (byte == SLIP_DELIMITER) { + h5.rx_state = HEADER; + remaining = sizeof(hdr); + } + break; + case HEADER: + /* In a case we confuse ending slip delimiter + * with starting one. + */ + if (byte == SLIP_DELIMITER) { + remaining = sizeof(hdr); + continue; + } + + if (h5_unslip_byte(&byte) < 0) { + h5_reset_rx(); + continue; + } + + memcpy(&hdr[sizeof(hdr) - remaining], &byte, 1); + remaining--; + + if (remaining) { + break; + } + + remaining = H5_HDR_LEN(hdr); + type = H5_HDR_PKT_TYPE(hdr); + + switch (type) { + case HCI_COMMAND_PKT: + case HCI_ACLDATA_PKT: + case HCI_ISODATA_PKT: + h5.rx_buf = bt_buf_get_tx(BT_BUF_H4, K_NO_WAIT, + &type, sizeof(type)); + if (!h5.rx_buf) { + LOG_WRN("No available data buffers"); + h5_reset_rx(); + continue; + } + + h5.rx_state = PAYLOAD; + break; + case HCI_3WIRE_LINK_PKT: + case HCI_3WIRE_ACK_PKT: + h5.rx_buf = net_buf_alloc(&h5_pool, K_NO_WAIT); + if (!h5.rx_buf) { + LOG_WRN("No available signal buffers"); + h5_reset_rx(); + continue; + } + + h5.rx_state = PAYLOAD; + break; + default: + LOG_ERR("Wrong packet type %u", type); + h5.rx_state = END; + break; + } + if (!remaining) { + h5.rx_state = END; + } + break; + case PAYLOAD: + if (byte == SLIP_DELIMITER) { + LOG_WRN("Unexpected ending delimiter"); + h5_reset_rx(); + continue; + } + + if (h5_unslip_byte(&byte) < 0) { + h5_reset_rx(); + continue; + } + + buf_tailroom = net_buf_tailroom(h5.rx_buf); + if (buf_tailroom < sizeof(byte)) { + LOG_ERR("Not enough space in buffer %zu/%zu", sizeof(byte), + buf_tailroom); + h5_reset_rx(); + break; + } + + net_buf_add_mem(h5.rx_buf, &byte, sizeof(byte)); + remaining--; + if (!remaining) { + h5.rx_state = END; + } + break; + case END: + if (byte != SLIP_DELIMITER) { + LOG_ERR("Missing ending SLIP_DELIMITER"); + h5_reset_rx(); + break; + } + + LOG_DBG("Received full packet: type %u", H5_HDR_PKT_TYPE(hdr)); + + /* Check when full packet is received, it can be done + * when parsing packet header but we need to receive + * full packet anyway to clear UART. + */ + if (H5_HDR_RELIABLE(hdr) && + H5_HDR_SEQ(hdr) != h5.tx_ack) { + LOG_ERR("Seq expected %u got %u. Drop packet", h5.tx_ack, + H5_HDR_SEQ(hdr)); + h5_reset_rx(); + break; + } + + h5_process_complete_packet(hdr); + h5.rx_state = START; + break; + } + } +} + +static int h5_queue(struct net_buf *buf) +{ + LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + + net_buf_put(&h5.tx_queue, buf); + + return 0; +} + +static uint8_t h5_get_type(struct net_buf *buf) +{ + return net_buf_pull_u8(buf); +} + +static void process_events(struct k_poll_event *ev, int count) +{ + struct net_buf *buf; + uint8_t type; + int err; + + LOG_DBG("count %d", count); + + for (; count; ev++, count--) { + LOG_DBG("ev->state %u", ev->state); + + switch (ev->state) { + case K_POLL_STATE_SIGNALED: + break; + case K_POLL_STATE_SEM_AVAILABLE: + /* After this fn is exec'd, `bt_conn_prepare_events()` + * will be called once again, and this time buffers will + * be available, so the FIFO will be added to the poll + * list instead of the ctlr buffers semaphore. + */ + break; + case K_POLL_STATE_FIFO_DATA_AVAILABLE: + if (ev->tag == 0) { + /* Wait until a buffer is available */ + buf = net_buf_get(&tx_queue, K_NO_WAIT); + __ASSERT_NO_MSG(buf); + + /* Pass buffer to the stack */ + err = bt_send(buf); + if (err) { + LOG_ERR("Unable to send (err %d)", err); + net_buf_unref(buf); + } + } else if (ev->tag == 2) { + buf = net_buf_get(&h5.tx_queue, K_FOREVER); + __ASSERT_NO_MSG(buf); + + type = h5_get_type(buf); + h5_send(buf->data, type, buf->len); + + /* buf is dequeued from tx_queue and queued to unack + * queue. + */ + net_buf_put(&h5.unack_queue, buf); + unack_queue_len++; + + k_work_reschedule(&retx_work, H5_TX_ACK_TIMEOUT); + } + break; + case K_POLL_STATE_NOT_READY: + break; + default: + LOG_WRN("Unexpected k_poll event state %u", ev->state); + break; + } + } +} + +static void tx_thread(void *p1, void *p2, void *p3) +{ + static struct k_poll_event events[] = { + K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, + K_POLL_MODE_NOTIFY_ONLY, + &tx_queue, 0), + K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_SIGNAL, + K_POLL_MODE_NOTIFY_ONLY, + &tx_queue_change, 1), + K_POLL_EVENT_STATIC_INITIALIZER(K_POLL_TYPE_FIFO_DATA_AVAILABLE, + K_POLL_MODE_NOTIFY_ONLY, + &h5.tx_queue, 2), + }; + + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + LOG_DBG(""); + + while (true) { + int err, ev_count = 2; + + events[0].state = K_POLL_STATE_NOT_READY; + events[1].state = K_POLL_STATE_NOT_READY; + tx_queue_change.signaled = 0U; + + if (h5.link_state == ACTIVE && unack_queue_len < h5.tx_win) { + events[2].state = K_POLL_STATE_NOT_READY; + ev_count++; + } + + err = k_poll(events, ev_count, K_FOREVER); + process_events(events, ev_count); + + /* Make sure we don't hog the CPU if there's all the time + * some ready events. + */ + k_yield(); + } +} + +static void rx_thread(void *p1, void *p2, void *p3) +{ + ARG_UNUSED(p1); + ARG_UNUSED(p2); + ARG_UNUSED(p3); + + LOG_DBG(""); + + while (true) { + struct net_buf *buf, *cache; + + buf = net_buf_get(&h5.rx_queue, K_FOREVER); + + hexdump("=> ", buf->data, buf->len); + + if (!memcmp(buf->data, sync_req, sizeof(sync_req))) { + if (h5.link_state == ACTIVE) { + while ((cache = net_buf_get(&h5.unack_queue, K_NO_WAIT))) { + net_buf_unref(cache); + } + + unack_queue_len = 0; + + while ((cache = net_buf_get(&h5.tx_queue, K_NO_WAIT))) { + net_buf_unref(cache); + } + + h5_reset_rx(); + + h5.rx_ack = 0; + h5.link_state = INIT; + h5.tx_ack = 0; + h5.tx_seq = 0; + } + + h5_send(sync_rsp, HCI_3WIRE_LINK_PKT, sizeof(sync_rsp)); + } else if (!memcmp(buf->data, conf_req, 2)) { + if (buf->len > 2) { + uint8_t tx_win = buf->data[2] & 0x07; + + /* Configuration field present */ + h5.tx_win = MIN(h5.tx_win, tx_win); + } + + conf_rsp[2] = h5.tx_win; + + /* + * The Host sends Config Response messages with a + * Configuration Field. + */ + h5_send(conf_rsp, HCI_3WIRE_LINK_PKT, sizeof(conf_rsp)); + + LOG_DBG("Finished H5 configuration, tx_win %u", h5.tx_win); + + h5.link_state = ACTIVE; + } else { + LOG_ERR("Not handled yet %x %x", buf->data[0], buf->data[1]); + } + + net_buf_unref(buf); + + /* Make sure we don't hog the CPU if the rx_queue never + * gets empty. + */ + k_yield(); + } +} + +static int hci_uart_init(void) +{ + LOG_DBG(""); + + if (IS_ENABLED(CONFIG_USB_CDC_ACM)) { + if (usb_enable(NULL)) { + LOG_ERR("Failed to enable USB"); + return -EINVAL; + } + } + + if (!device_is_ready(h5_dev)) { + LOG_ERR("HCI UART %s is not ready", h5_dev->name); + return -EINVAL; + } + + uart_irq_rx_disable(h5_dev); + uart_irq_tx_disable(h5_dev); + + uart_irq_callback_set(h5_dev, bt_uart_isr); + + uart_irq_rx_enable(h5_dev); + + return 0; +} + +SYS_INIT(hci_uart_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); + +int main(void) +{ + /* incoming events and data from the controller */ + static K_FIFO_DEFINE(rx_queue); + int err; + + LOG_DBG("Start"); + __ASSERT(h5_dev, "UART device is NULL"); + + /* Enable the raw interface, this will in turn open the HCI driver */ + bt_enable_raw(&rx_queue); + + /* TX thread */ + k_fifo_init(&h5.tx_queue); + k_thread_create(&tx_thread_data, tx_stack, + K_KERNEL_STACK_SIZEOF(tx_stack), + tx_thread, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_HCI_TX_PRIO), + 0, K_NO_WAIT); + k_thread_name_set(&tx_thread_data, "tx_thread"); + + k_fifo_init(&h5.rx_queue); + k_thread_create(&rx_thread_data, rx_stack, + K_KERNEL_STACK_SIZEOF(rx_stack), + rx_thread, NULL, NULL, NULL, + K_PRIO_COOP(CONFIG_BT_RX_PRIO), + 0, K_NO_WAIT); + k_thread_name_set(&rx_thread_data, "rx_thread"); + + /* Unack queue */ + k_fifo_init(&h5.unack_queue); + + /* Init delayed work */ + k_work_init_delayable(&ack_work, ack_timeout); + k_work_init_delayable(&retx_work, retx_timeout); + + h5.tx_win = H5_TX_WIN; + + while (1) { + struct net_buf *buf; + + buf = net_buf_get(&rx_queue, K_FOREVER); + err = h5_queue(buf); + if (err) { + LOG_ERR("Failed to send"); + } + } + + return 0; +} diff --git a/samples/bluetooth/hci_uart_async/README.rst b/samples/bluetooth/hci_uart_async/README.rst index 7dbb4bbbdb63c..065231e926c3c 100644 --- a/samples/bluetooth/hci_uart_async/README.rst +++ b/samples/bluetooth/hci_uart_async/README.rst @@ -143,9 +143,9 @@ driver instead of the built-in controller: CONFIG_BT_HCI=y CONFIG_BT_CTLR=n - CONFIG_BT_H4=y -Similarly, the `zephyr,bt-uart` DTS property selects which uart to use: +Similarly, the `zephyr,bt-hci` DTS property selects which HCI instance to use. +The UART needs to have as its child node a HCI UART node: .. code-block:: dts @@ -153,6 +153,14 @@ Similarly, the `zephyr,bt-uart` DTS property selects which uart to use: chosen { zephyr,console = &uart0; zephyr,shell-uart = &uart0; - zephyr,bt-uart = &uart1; + zephyr,bt-hci = &bt_hci_uart; + }; + }; + + &uart1 { + status = "okay"; + bt_hci_uart: bt_hci_uart { + compatible = "zephyr,bt-hci-uart"; + status = "okay"; }; }; diff --git a/samples/bluetooth/hci_uart_async/boards/nrf52_bsim.overlay b/samples/bluetooth/hci_uart_async/boards/nrf52_bsim.overlay index adef7109b3c9f..e3745738a19c8 100644 --- a/samples/bluetooth/hci_uart_async/boards/nrf52_bsim.overlay +++ b/samples/bluetooth/hci_uart_async/boards/nrf52_bsim.overlay @@ -1 +1,3 @@ -/* Purposely empty. To avoid using the one provided by the application */ +&bt_hci_uart { + status = "disabled"; +}; diff --git a/samples/bluetooth/hci_uart_async/src/hci_uart_async.c b/samples/bluetooth/hci_uart_async/src/hci_uart_async.c index cf9cc600d5cf5..856ebc4752486 100644 --- a/samples/bluetooth/hci_uart_async/src/hci_uart_async.c +++ b/samples/bluetooth/hci_uart_async/src/hci_uart_async.c @@ -37,14 +37,6 @@ static const struct device *const hci_uart_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_ static K_THREAD_STACK_DEFINE(h2c_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); static struct k_thread h2c_thread; -enum h4_type { - H4_CMD = 0x01, - H4_ACL = 0x02, - H4_SCO = 0x03, - H4_EVT = 0x04, - H4_ISO = 0x05, -}; - struct k_poll_signal uart_h2c_rx_sig; struct k_poll_signal uart_c2h_tx_sig; @@ -82,33 +74,33 @@ static int uart_c2h_tx(const uint8_t *data, size_t size) } /* Function expects that type is validated and only CMD, ISO or ACL will be used. */ -static uint32_t hci_payload_size(const uint8_t *hdr_buf, enum h4_type type) +static uint32_t hci_payload_size(const uint8_t *hdr_buf, uint8_t h4_type) { - switch (type) { - case H4_CMD: + switch (h4_type) { + case BT_HCI_H4_CMD: return ((const struct bt_hci_cmd_hdr *)hdr_buf)->param_len; - case H4_ACL: + case BT_HCI_H4_ACL: return sys_le16_to_cpu(((const struct bt_hci_acl_hdr *)hdr_buf)->len); - case H4_ISO: + case BT_HCI_H4_ISO: return bt_iso_hdr_len( sys_le16_to_cpu(((const struct bt_hci_iso_hdr *)hdr_buf)->len)); default: - LOG_ERR("Invalid type: %u", type); + LOG_ERR("Invalid type: %u", h4_type); return 0; } } -static uint8_t hci_hdr_size(enum h4_type type) +static uint8_t hci_hdr_size(uint8_t h4_type) { - switch (type) { - case H4_CMD: + switch (h4_type) { + case BT_HCI_H4_CMD: return sizeof(struct bt_hci_cmd_hdr); - case H4_ACL: + case BT_HCI_H4_ACL: return sizeof(struct bt_hci_acl_hdr); - case H4_ISO: + case BT_HCI_H4_ISO: return sizeof(struct bt_hci_iso_hdr); default: - LOG_ERR("Unexpected h4 type: %u", type); + LOG_ERR("Unexpected h4 type: %u", h4_type); return 0; } } @@ -159,10 +151,11 @@ static void send_hw_error(void) struct net_buf *buf = bt_buf_get_rx(BT_BUF_EVT, K_FOREVER); + net_buf_add_u8(buf, BT_HCI_H4_EVT); net_buf_add_mem(buf, hci_evt_hw_err, sizeof(hci_evt_hw_err)); /* Inject the message into the c2h queue. */ - bt_recv(buf); + net_buf_put(&c2h_queue, buf); /* The c2h thread will send the message at some point. The host * will receive it and reset the controller. @@ -171,7 +164,7 @@ static void send_hw_error(void) static void recover_sync_by_reset_pattern(void) { - /* { H4_CMD, le_16(HCI_CMD_OP_RESET), len=0 } */ + /* { BT_HCI_H4_CMD, le_16(HCI_CMD_OP_RESET), len=0 } */ const uint8_t h4_cmd_reset[] = {0x01, 0x03, 0x0C, 0x00}; const uint32_t reset_pattern = sys_get_be32(h4_cmd_reset); int err; @@ -367,7 +360,7 @@ const struct { struct bt_hci_evt_hdr hdr; struct bt_hci_evt_cmd_complete cc; } __packed cc_evt = { - .h4 = H4_EVT, + .h4 = BT_HCI_H4_EVT, .hdr = {.evt = BT_HCI_EVT_CMD_COMPLETE, .len = sizeof(struct bt_hci_evt_cmd_complete)}, .cc = {.ncmd = 1, .opcode = sys_cpu_to_le16(BT_OP_NOP)}, }; diff --git a/samples/bluetooth/hci_usb/src/main.c b/samples/bluetooth/hci_usb/src/main.c index c27af0e56db3e..18c7f0d5edc51 100644 --- a/samples/bluetooth/hci_usb/src/main.c +++ b/samples/bluetooth/hci_usb/src/main.c @@ -14,7 +14,7 @@ static int enable_usb_device_next(void) { - struct usbd_contex *sample_usbd = sample_usbd_init_device(NULL); + struct usbd_context *sample_usbd = sample_usbd_init_device(NULL); if (sample_usbd == NULL) { printk("Failed to initialize USB device"); diff --git a/samples/bluetooth/hci_vs_scan_req/sample.yaml b/samples/bluetooth/hci_vs_scan_req/sample.yaml index 9f2aad6f3637a..245a83aa0d96a 100644 --- a/samples/bluetooth/hci_vs_scan_req/sample.yaml +++ b/samples/bluetooth/hci_vs_scan_req/sample.yaml @@ -5,8 +5,8 @@ tests: harness: bluetooth platform_allow: - nrf52dk/nrf52832 - - qemu_cortex_m3 - - qemu_x86 - tags: bluetooth integration_platforms: - - qemu_cortex_m3 + - nrf52dk/nrf52832 + extra_configs: + - CONFIG_BT_LL_SW_SPLIT=y + tags: bluetooth diff --git a/samples/bluetooth/ibeacon/boards/sltb010a.conf b/samples/bluetooth/ibeacon/boards/sltb010a.conf new file mode 100644 index 0000000000000..2df782efc7115 --- /dev/null +++ b/samples/bluetooth/ibeacon/boards/sltb010a.conf @@ -0,0 +1 @@ +CONFIG_PM=y diff --git a/samples/bluetooth/iso_broadcast/overlay-bt_ll_sw_split.conf b/samples/bluetooth/iso_broadcast/overlay-bt_ll_sw_split.conf index a5f8b3cc1c5bf..19264a9d041af 100644 --- a/samples/bluetooth/iso_broadcast/overlay-bt_ll_sw_split.conf +++ b/samples/bluetooth/iso_broadcast/overlay-bt_ll_sw_split.conf @@ -1,13 +1,20 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Zephyr Controller tested maximum advertising data that can be set in a single HCI command +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 + +# Enable support for Broadcast ISO in Zephyr Bluetooth Controller CONFIG_BT_CTLR_ADV_ISO=y + +# Sufficient ISO PDU length for this sample CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=4 -CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 +# Number of supported streams +CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 CONFIG_BT_CTLR_ISOAL_SOURCES=2 -# FIXME: Host needs CONFIG_BT_ISO_TX_MTU + 4 bytes for sequence number, and -# optionally additional + 4 bytes for timestamp when not using -# BT_ISO_TIMESTAMP_NONE in bt_iso_chan_send(), otherwise Host tries to fragment -# ISO data. -# When Host is fixed, CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE can inherit the -# CONFIG_BT_ISO_TX_MTU value. +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=12 diff --git a/samples/bluetooth/iso_broadcast/sample.yaml b/samples/bluetooth/iso_broadcast/sample.yaml index 10fb481688c62..92bde54d7a0c7 100644 --- a/samples/bluetooth/iso_broadcast/sample.yaml +++ b/samples/bluetooth/iso_broadcast/sample.yaml @@ -17,8 +17,8 @@ tests: - qemu_cortex_m3 - qemu_x86 - nrf52_bsim - - nrf52dk/nrf52832 + - nrf52833dk/nrf52833 integration_platforms: - - nrf52dk/nrf52832 + - nrf52833dk/nrf52833 extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf tags: bluetooth diff --git a/samples/bluetooth/iso_broadcast/src/main.c b/samples/bluetooth/iso_broadcast/src/main.c index e0ff7dd306e08..85460d10fdd5c 100644 --- a/samples/bluetooth/iso_broadcast/src/main.c +++ b/samples/bluetooth/iso_broadcast/src/main.c @@ -105,7 +105,7 @@ int main(void) return 0; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, &adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c b/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c index 1040f0cd21483..94f334ff54d84 100644 --- a/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c +++ b/samples/bluetooth/iso_broadcast_benchmark/src/broadcaster.c @@ -617,7 +617,7 @@ static int create_big(struct bt_le_ext_adv **adv, struct bt_iso_big **big) { int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ LOG_INF("Creating Extended Advertising set"); err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); if (err != 0) { diff --git a/samples/bluetooth/mtu_update/peripheral/src/peripheral_mtu_update.c b/samples/bluetooth/mtu_update/peripheral/src/peripheral_mtu_update.c index 7e87dd5dfdfdd..46ea497433441 100644 --- a/samples/bluetooth/mtu_update/peripheral/src/peripheral_mtu_update.c +++ b/samples/bluetooth/mtu_update/peripheral/src/peripheral_mtu_update.c @@ -63,7 +63,7 @@ void run_peripheral_sample(uint8_t *notify_data, size_t notify_data_size, uint16 struct bt_gatt_attr *notify_crch = bt_gatt_find_by_uuid(mtu_test.attrs, 0xffff, ¬ify_characteristic_uuid.uuid); - bt_le_adv_start(BT_LE_ADV_CONN, adv_ad_data, ARRAY_SIZE(adv_ad_data), NULL, 0); + bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, adv_ad_data, ARRAY_SIZE(adv_ad_data), NULL, 0); bool infinite = seconds == 0; diff --git a/samples/bluetooth/public_broadcast_sink/CMakeLists.txt b/samples/bluetooth/pbp_public_broadcast_sink/CMakeLists.txt similarity index 100% rename from samples/bluetooth/public_broadcast_sink/CMakeLists.txt rename to samples/bluetooth/pbp_public_broadcast_sink/CMakeLists.txt diff --git a/samples/bluetooth/public_broadcast_sink/Kconfig.sysbuild b/samples/bluetooth/pbp_public_broadcast_sink/Kconfig.sysbuild similarity index 100% rename from samples/bluetooth/public_broadcast_sink/Kconfig.sysbuild rename to samples/bluetooth/pbp_public_broadcast_sink/Kconfig.sysbuild diff --git a/samples/bluetooth/pbp_public_broadcast_sink/README.rst b/samples/bluetooth/pbp_public_broadcast_sink/README.rst new file mode 100644 index 0000000000000..4e4ecaaa38df0 --- /dev/null +++ b/samples/bluetooth/pbp_public_broadcast_sink/README.rst @@ -0,0 +1,77 @@ +.. zephyr:code-sample:: bluetooth_public_broadcast_sink + :name: Bluetooth: Public Broadcast Sink + :relevant-api: bluetooth + + Bluetooth: Public Broadcast Sink + +Overview +******** + +Application demonstrating the LE Public Broadcast Profile sink functionality. +Starts by scanning for LE Audio broadcast sources and then synchronizes to +the first found source which defines a Public Broadcast Announcement including +a High Quality Public Broadcast Audio Stream configuration. + +This sample can be found under +:zephyr_file:`samples/bluetooth/pbp_public_broadcast_sink` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/pbp_public_broadcast_sink/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/pbp_public_broadcast_sink/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/pbp_public_broadcast_sink/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/pbp_public_broadcast_sink/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/public_broadcast_sink/overlay-bt_ll_sw_split.conf b/samples/bluetooth/pbp_public_broadcast_sink/overlay-bt_ll_sw_split.conf similarity index 100% rename from samples/bluetooth/public_broadcast_sink/overlay-bt_ll_sw_split.conf rename to samples/bluetooth/pbp_public_broadcast_sink/overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/public_broadcast_sink/prj.conf b/samples/bluetooth/pbp_public_broadcast_sink/prj.conf similarity index 100% rename from samples/bluetooth/public_broadcast_sink/prj.conf rename to samples/bluetooth/pbp_public_broadcast_sink/prj.conf diff --git a/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml b/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml new file mode 100644 index 0000000000000..2c4d31fd4b98e --- /dev/null +++ b/samples/bluetooth/pbp_public_broadcast_sink/sample.yaml @@ -0,0 +1,27 @@ +sample: + description: Bluetooth Low Energy Audio PBP Broadcast Sink sample + name: Bluetooth Low Energy Audio PBP Broadcast Sink sample +tests: + sample.bluetooth.pbp_public_broadcast_sink: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + - nrf5340bsim/nrf5340/cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.pbp_public_broadcast_sink.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk/nrf52820 + - nrf52833dk/nrf52833 + integration_platforms: + - nrf52_bsim + - nrf52833dk/nrf52833 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/public_broadcast_sink/src/main.c b/samples/bluetooth/pbp_public_broadcast_sink/src/main.c similarity index 100% rename from samples/bluetooth/public_broadcast_sink/src/main.c rename to samples/bluetooth/pbp_public_broadcast_sink/src/main.c diff --git a/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake b/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake new file mode 100644 index 0000000000000..2523aac8ea76f --- /dev/null +++ b/samples/bluetooth/pbp_public_broadcast_sink/sysbuild.cmake @@ -0,0 +1,24 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if(SB_CONFIG_NET_CORE_IMAGE_HCI_IPC) + # For builds in the nrf5340, we build the netcore image with the controller + + set(NET_APP hci_ipc) + set(NET_APP_SRC_DIR ${ZEPHYR_BASE}/samples/bluetooth/${NET_APP}) + + ExternalZephyrProject_Add( + APPLICATION ${NET_APP} + SOURCE_DIR ${NET_APP_SRC_DIR} + BOARD ${SB_CONFIG_NET_CORE_BOARD} + ) + + set(${NET_APP}_CONF_FILE + ${NET_APP_SRC_DIR}/nrf5340_cpunet_iso-bt_ll_sw_split.conf + CACHE INTERNAL "" + ) + + native_simulator_set_child_images(${DEFAULT_IMAGE} ${NET_APP}) +endif() + +native_simulator_set_final_executable(${DEFAULT_IMAGE}) diff --git a/samples/bluetooth/pbp_public_broadcast_source/CMakeLists.txt b/samples/bluetooth/pbp_public_broadcast_source/CMakeLists.txt new file mode 100644 index 0000000000000..7bd57f8e86da9 --- /dev/null +++ b/samples/bluetooth/pbp_public_broadcast_source/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(pbp_public_broadcast_source) + +target_sources(app PRIVATE + src/main.c +) + +zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/pbp_public_broadcast_source/Kconfig.sysbuild b/samples/bluetooth/pbp_public_broadcast_source/Kconfig.sysbuild new file mode 100644 index 0000000000000..f37b265ecbc27 --- /dev/null +++ b/samples/bluetooth/pbp_public_broadcast_source/Kconfig.sysbuild @@ -0,0 +1,15 @@ +# Copyright 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "share/sysbuild/Kconfig" + +config NET_CORE_BOARD + string + default "nrf5340dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340dk" + default "nrf5340_audio_dk/nrf5340/cpunet" if "$(BOARD)" = "nrf5340_audio_dk" + default "nrf5340bsim/nrf5340/cpunet" if $(BOARD_TARGET_STRING) = "NRF5340BSIM_NRF5340_CPUAPP" + +config NET_CORE_IMAGE_HCI_IPC + bool "HCI IPC image on network core" + default y + depends on NET_CORE_BOARD != "" diff --git a/samples/bluetooth/pbp_public_broadcast_source/README.rst b/samples/bluetooth/pbp_public_broadcast_source/README.rst new file mode 100644 index 0000000000000..80856f43a2462 --- /dev/null +++ b/samples/bluetooth/pbp_public_broadcast_source/README.rst @@ -0,0 +1,77 @@ +.. zephyr:code-sample:: bluetooth_public_broadcast_source + :name: Bluetooth: Public Broadcast Source + :relevant-api: bluetooth + + Bluetooth: Public Broadcast Source + +Overview +******** + +Application demonstrating the LE Public Broadcast Profile source functionality. +Will start advertising extended advertising and includes a Broadcast Audio Announcement. +The advertised broadcast audio stream quality will cycle between high and standard quality +every 15 seconds. + +This sample can be found under +:zephyr_file:`samples/bluetooth/pbp_public_broadcast_source` in the Zephyr tree. + +Check the :ref:`bluetooth samples section ` for general information. + +Requirements +************ + +* BlueZ running on the host, or +* A board with Bluetooth Low Energy 5.2 support + +Building and Running +******************** + +When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, +use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO +feature support. + +Building for an nrf5340dk +------------------------- + +You can build both the application core image and an appropriate controller image for the network +core with: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/pbp_public_broadcast_source/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +If you prefer to only build the application core image, you can do so by doing instead: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/pbp_public_broadcast_source/ + :board: nrf5340dk/nrf5340/cpuapp + :goals: build + +In that case you can pair this application core image with the +:ref:`hci_ipc sample ` +:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. + +Building for a simulated nrf5340bsim +------------------------------------ + +Similarly to how you would for real HW, you can do: + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/pbp_public_broadcast_source/ + :board: nrf5340bsim/nrf5340/cpuapp + :goals: build + :west-args: --sysbuild + +Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. +For more information, check :ref:`this board documentation `. + +Building for a simulated nrf52_bsim +----------------------------------- + +.. zephyr-app-commands:: + :zephyr-app: samples/bluetooth/pbp_public_broadcast_source/ + :board: nrf52_bsim + :goals: build + :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/pbp_public_broadcast_source/overlay-bt_ll_sw_split.conf b/samples/bluetooth/pbp_public_broadcast_source/overlay-bt_ll_sw_split.conf new file mode 100644 index 0000000000000..3711a34921368 --- /dev/null +++ b/samples/bluetooth/pbp_public_broadcast_source/overlay-bt_ll_sw_split.conf @@ -0,0 +1,20 @@ +# Zephyr Bluetooth Controller +CONFIG_BT_LL_SW_SPLIT=y + +# Zephyr Controller tested maximum advertising data that can be set in a single HCI command +CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 + +# Enable support for Broadcast ISO in Zephyr Bluetooth Controller +CONFIG_BT_CTLR_ADV_ISO=y + +# Sufficient ISO PDU length for any BAP LC3 presets (155) +CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=155 + +# Number of supported streams +CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 +CONFIG_BT_CTLR_ISOAL_SOURCES=2 + +# Support the highest SDU size required by any BAP LC3 presets (155) + 8 bytes of HCI ISO Data +# packet overhead (the Packet_Sequence_Number, ISO_SDU_Length, Packet_Status_Flag fields; and +# the optional Time_Stamp field, if supplied) +CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 diff --git a/samples/bluetooth/public_broadcast_source/prj.conf b/samples/bluetooth/pbp_public_broadcast_source/prj.conf similarity index 100% rename from samples/bluetooth/public_broadcast_source/prj.conf rename to samples/bluetooth/pbp_public_broadcast_source/prj.conf diff --git a/samples/bluetooth/pbp_public_broadcast_source/sample.yaml b/samples/bluetooth/pbp_public_broadcast_source/sample.yaml new file mode 100644 index 0000000000000..31809027f2921 --- /dev/null +++ b/samples/bluetooth/pbp_public_broadcast_source/sample.yaml @@ -0,0 +1,27 @@ +sample: + description: Bluetooth Low Energy Public Broadcast Source sample + name: Bluetooth Low Energy Public Broadcast Source sample +tests: + sample.bluetooth.pbp_public_broadcast_source: + harness: bluetooth + platform_allow: + - qemu_cortex_m3 + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + - nrf5340bsim/nrf5340/cpuapp + integration_platforms: + - qemu_x86 + - nrf5340dk/nrf5340/cpuapp + tags: bluetooth + sysbuild: true + sample.bluetooth.pbp_public_broadcast_source.bt_ll_sw_split: + harness: bluetooth + platform_allow: + - nrf52_bsim + - nrf52833dk/nrf52820 + - nrf52833dk/nrf52833 + integration_platforms: + - nrf52_bsim + - nrf52833dk/nrf52833 + extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf + tags: bluetooth diff --git a/samples/bluetooth/pbp_public_broadcast_source/src/main.c b/samples/bluetooth/pbp_public_broadcast_source/src/main.c new file mode 100644 index 0000000000000..f4dab65bbb291 --- /dev/null +++ b/samples/bluetooth/pbp_public_broadcast_source/src/main.c @@ -0,0 +1,435 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BROADCAST_ENQUEUE_COUNT 2U + +/* PBS ASCII text */ +#define PBS_DEMO 'P', 'B', 'P' + +NET_BUF_POOL_FIXED_DEFINE(tx_pool, + (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT), + BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); + +static K_SEM_DEFINE(sem_broadcast_started, 0, 1); +static K_SEM_DEFINE(sem_broadcast_stopped, 0, 1); + +static struct bt_cap_stream broadcast_source_stream; +static struct bt_cap_stream *broadcast_stream; + +static uint8_t bis_codec_data[] = {BT_AUDIO_CODEC_DATA( + BT_AUDIO_CODEC_CFG_FREQ, BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CFG_FREQ_48KHZ))}; + +const uint8_t pba_metadata[] = { + BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, PBS_DEMO) +}; + +static uint8_t appearance_addata[] = { + BT_BYTES_LIST_LE16(BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE) +}; + +static const char broadcast_name[] = "PBP Source Demo"; + +static struct bt_bap_lc3_preset broadcast_preset_48_2_1 = + BT_BAP_LC3_UNICAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT, + BT_AUDIO_CONTEXT_TYPE_MEDIA); + +static const struct bt_data ad[] = { + BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), +}; + +struct bt_cap_initiator_broadcast_stream_param stream_params; +struct bt_cap_initiator_broadcast_subgroup_param subgroup_param; +struct bt_cap_initiator_broadcast_create_param create_param; +struct bt_cap_broadcast_source *broadcast_source; +struct bt_le_ext_adv *ext_adv; + +static void broadcast_started_cb(struct bt_bap_stream *stream) +{ + printk("Stream %p started\n", stream); + k_sem_give(&sem_broadcast_started); +} + +static void broadcast_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) +{ + if (reason == BT_HCI_ERR_LOCALHOST_TERM_CONN) { + printk("Stream %p ended\n", stream); + } else { + printk("Stream %p stopped with reason 0x%02X\n", stream, reason); + } + + k_sem_give(&sem_broadcast_stopped); +} + +static void broadcast_sent_cb(struct bt_bap_stream *stream) +{ + static uint8_t mock_data[CONFIG_BT_ISO_TX_MTU]; + static bool mock_data_initialized; + static uint32_t seq_num; + struct net_buf *buf; + int ret; + + if (broadcast_preset_48_2_1.qos.sdu > CONFIG_BT_ISO_TX_MTU) { + printk("Invalid SDU %u for the MTU: %d", broadcast_preset_48_2_1.qos.sdu, + CONFIG_BT_ISO_TX_MTU); + + return; + } + + if (!mock_data_initialized) { + for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) { + /* Initialize mock data */ + mock_data[i] = (uint8_t)i; + } + mock_data_initialized = true; + } + + buf = net_buf_alloc(&tx_pool, K_FOREVER); + if (buf == NULL) { + printk("Could not allocate buffer when sending on %p\n", stream); + + return; + } + + net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); + net_buf_add_mem(buf, mock_data, broadcast_preset_48_2_1.qos.sdu); + ret = bt_bap_stream_send(stream, buf, seq_num++); + if (ret < 0) { + /* This will end broadcasting on this stream. */ + net_buf_unref(buf); + + return; + } +} + +static struct bt_bap_stream_ops broadcast_stream_ops = { + .started = broadcast_started_cb, + .stopped = broadcast_stopped_cb, + .sent = broadcast_sent_cb +}; + +static int setup_extended_adv(struct bt_le_ext_adv **adv) +{ + int err; + + /* Create a non-connectable advertising set */ + err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); + if (err != 0) { + printk("Unable to create extended advertising set: %d\n", err); + + return err; + } + + /* Set advertising data to have complete local name set */ + err = bt_le_ext_adv_set_data(*adv, ad, ARRAY_SIZE(ad), NULL, 0); + if (err) { + printk("Failed to set advertising data (err %d)\n", err); + + return 0; + } + + /* Set periodic advertising parameters */ + err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT); + if (err) { + printk("Failed to set periodic advertising parameters: %d\n", err); + + return err; + } + + return 0; +} + +static int setup_extended_adv_data(struct bt_cap_broadcast_source *source, + struct bt_le_ext_adv *adv) +{ + /* Broadcast Audio Streaming Endpoint advertising data */ + NET_BUF_SIMPLE_DEFINE(ad_buf, + BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); + NET_BUF_SIMPLE_DEFINE(base_buf, 128); + NET_BUF_SIMPLE_DEFINE(pbp_ad_buf, BT_UUID_SIZE_16 + 1 + ARRAY_SIZE(pba_metadata)); + static enum bt_pbp_announcement_feature pba_params; + struct bt_data ext_ad[4]; + struct bt_data per_ad; + uint32_t broadcast_id; + int err; + + err = bt_cap_initiator_broadcast_get_id(source, &broadcast_id); + if (err != 0) { + printk("Unable to get broadcast ID: %d\n", err); + + return err; + } + + /* Setup extended advertising data */ + ext_ad[0].type = BT_DATA_GAP_APPEARANCE; + ext_ad[0].data_len = 2; + ext_ad[0].data = appearance_addata; + /* Broadcast name AD Type */ + ext_ad[1].type = BT_DATA_BROADCAST_NAME; + ext_ad[1].data_len = ARRAY_SIZE(broadcast_name); + ext_ad[1].data = broadcast_name; + /* Broadcast Audio Announcement */ + net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); + net_buf_simple_add_le24(&ad_buf, broadcast_id); + ext_ad[2].type = BT_DATA_SVC_DATA16; + ext_ad[2].data_len = ad_buf.len + sizeof(ext_ad[2].type); + ext_ad[2].data = ad_buf.data; + + /** + * Create a Public Broadcast Announcement + * Cycle between high and standard quality public broadcast audio. + */ + if (pba_params & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY) { + pba_params = 0; + pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_STANDARD_QUALITY; + printk("Starting stream with standard quality!\n"); + } else { + pba_params = 0; + pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY; + printk("Starting stream with high quality!\n"); + } + err = bt_pbp_get_announcement(&pba_metadata[1], ARRAY_SIZE(pba_metadata) - 1, + pba_params, &pbp_ad_buf); + if (err != 0) { + printk("Failed to create public broadcast announcement!: %d\n", err); + + return err; + } + ext_ad[3].type = BT_DATA_SVC_DATA16; + ext_ad[3].data_len = pbp_ad_buf.len; + ext_ad[3].data = pbp_ad_buf.data; + err = bt_le_ext_adv_set_data(adv, ext_ad, ARRAY_SIZE(ext_ad), NULL, 0); + if (err != 0) { + printk("Failed to set extended advertising data: %d\n", err); + + return err; + } + + /* Setup periodic advertising data */ + err = bt_cap_initiator_broadcast_get_base(source, &base_buf); + if (err != 0) { + printk("Failed to get encoded BASE: %d\n", err); + + return err; + } + + per_ad.type = BT_DATA_SVC_DATA16; + per_ad.data_len = base_buf.len; + per_ad.data = base_buf.data; + err = bt_le_per_adv_set_data(adv, &per_ad, 1); + if (err != 0) { + printk("Failed to set periodic advertising data: %d\n", err); + + return err; + } + + return 0; +} + +static int start_extended_adv(struct bt_le_ext_adv *adv) +{ + int err; + + /* Start extended advertising */ + err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); + if (err) { + printk("Failed to start extended advertising: %d\n", err); + + return err; + } + + /* Enable Periodic Advertising */ + err = bt_le_per_adv_start(adv); + if (err) { + printk("Failed to enable periodic advertising: %d\n", err); + + return err; + } + + return 0; +} + +static int stop_and_delete_extended_adv(struct bt_le_ext_adv *adv) +{ + int err; + + /* Stop extended advertising */ + err = bt_le_per_adv_stop(adv); + if (err) { + printk("Failed to stop periodic advertising: %d\n", err); + + return err; + } + + err = bt_le_ext_adv_stop(adv); + if (err) { + printk("Failed to stop extended advertising: %d\n", err); + + return err; + } + + err = bt_le_ext_adv_delete(adv); + if (err) { + printk("Failed to delete extended advertising: %d\n", err); + + return err; + } + + return 0; +} + +static int reset(void) +{ + k_sem_reset(&sem_broadcast_started); + k_sem_reset(&sem_broadcast_stopped); + + return 0; +} + +int cap_initiator_init(void) +{ + if (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE)) { + broadcast_stream = &broadcast_source_stream; + bt_bap_stream_cb_register(&broadcast_stream->bap_stream, &broadcast_stream_ops); + } + + return 0; +} + +void cap_initiator_setup(void) +{ + int err; + + stream_params.stream = &broadcast_source_stream; + stream_params.data_len = ARRAY_SIZE(bis_codec_data); + stream_params.data = bis_codec_data; + + subgroup_param.stream_count = 1U; + subgroup_param.stream_params = &stream_params; + subgroup_param.codec_cfg = &broadcast_preset_48_2_1.codec_cfg; + + create_param.subgroup_count = 1U; + create_param.subgroup_params = &subgroup_param; + create_param.qos = &broadcast_preset_48_2_1.qos; + create_param.packing = BT_ISO_PACKING_SEQUENTIAL; + create_param.encryption = false; + + while (true) { + err = reset(); + if (err != 0) { + printk("Resetting failed: %d - Aborting\n", err); + + return; + } + + err = setup_extended_adv(&ext_adv); + if (err != 0) { + printk("Unable to setup extended advertiser: %d\n", err); + + return; + } + + err = bt_cap_initiator_broadcast_audio_create(&create_param, &broadcast_source); + if (err != 0) { + printk("Unable to create broadcast source: %d\n", err); + + return; + } + + err = bt_cap_initiator_broadcast_audio_start(broadcast_source, ext_adv); + if (err != 0) { + printk("Unable to start broadcast source: %d\n", err); + + return; + } + + err = setup_extended_adv_data(broadcast_source, ext_adv); + if (err != 0) { + printk("Unable to setup extended advertising data: %d\n", err); + + return; + } + + err = start_extended_adv(ext_adv); + if (err != 0) { + printk("Unable to start extended advertiser: %d\n", err); + + return; + } + k_sem_take(&sem_broadcast_started, K_FOREVER); + + /* Initialize sending */ + for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) { + broadcast_sent_cb(&broadcast_stream->bap_stream); + } + + /* Keeping running for a little while */ + k_sleep(K_SECONDS(15)); + + err = bt_cap_initiator_broadcast_audio_stop(broadcast_source); + if (err != 0) { + printk("Failed to stop broadcast source: %d\n", err); + + return; + } + + k_sem_take(&sem_broadcast_stopped, K_FOREVER); + err = bt_cap_initiator_broadcast_audio_delete(broadcast_source); + if (err != 0) { + printk("Failed to stop broadcast source: %d\n", err); + + return; + } + broadcast_source = NULL; + + err = stop_and_delete_extended_adv(ext_adv); + if (err != 0) { + printk("Failed to stop and delete extended advertising: %d\n", err); + + return; + } + } +} + + +int main(void) +{ + int err; + + err = bt_enable(NULL); + if (err != 0) { + printk("Bluetooth enable failed (err %d)\n", err); + + return err; + } + + printk("Bluetooth initialized\n"); + + /* Initialize CAP Initiator */ + err = cap_initiator_init(); + if (err != 0) { + return err; + } + + printk("CAP initialized\n"); + + /* Configure and start broadcast stream */ + cap_initiator_setup(); + + return 0; +} diff --git a/samples/bluetooth/public_broadcast_source/sysbuild.cmake b/samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake similarity index 100% rename from samples/bluetooth/public_broadcast_source/sysbuild.cmake rename to samples/bluetooth/pbp_public_broadcast_source/sysbuild.cmake diff --git a/samples/bluetooth/periodic_adv/src/main.c b/samples/bluetooth/periodic_adv/src/main.c index 9b584966ce77f..a927c82e16c2b 100644 --- a/samples/bluetooth/periodic_adv/src/main.c +++ b/samples/bluetooth/periodic_adv/src/main.c @@ -30,7 +30,7 @@ int main(void) return 0; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, &adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/periodic_adv_conn/sample.yaml b/samples/bluetooth/periodic_adv_conn/sample.yaml index cfc9d0522f492..cc3ea8e24e902 100644 --- a/samples/bluetooth/periodic_adv_conn/sample.yaml +++ b/samples/bluetooth/periodic_adv_conn/sample.yaml @@ -6,10 +6,6 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 - - nrf52840dk/nrf52840 tags: bluetooth integration_platforms: - - nrf52840dk/nrf52840 - extra_configs: - - CONFIG_BT_CTLR=n - - CONFIG_BT_NO_DRIVER=y + - qemu_cortex_m3 diff --git a/samples/bluetooth/periodic_adv_conn/src/main.c b/samples/bluetooth/periodic_adv_conn/src/main.c index 63818ddbeea5b..1bfcc55977af0 100644 --- a/samples/bluetooth/periodic_adv_conn/src/main.c +++ b/samples/bluetooth/periodic_adv_conn/src/main.c @@ -181,7 +181,7 @@ int main(void) return 0; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, &adv_cb, &pawr_adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/periodic_adv_rsp/sample.yaml b/samples/bluetooth/periodic_adv_rsp/sample.yaml index dcb37b9fe4a83..fd22311303b16 100644 --- a/samples/bluetooth/periodic_adv_rsp/sample.yaml +++ b/samples/bluetooth/periodic_adv_rsp/sample.yaml @@ -6,10 +6,6 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 - - nrf52840dk/nrf52840 tags: bluetooth integration_platforms: - - nrf52840dk/nrf52840 - extra_configs: - - CONFIG_BT_CTLR=n - - CONFIG_BT_NO_DRIVER=y + - qemu_cortex_m3 diff --git a/samples/bluetooth/periodic_adv_rsp/src/main.c b/samples/bluetooth/periodic_adv_rsp/src/main.c index 6764b023a5ad2..b88c724a2225a 100644 --- a/samples/bluetooth/periodic_adv_rsp/src/main.c +++ b/samples/bluetooth/periodic_adv_rsp/src/main.c @@ -266,7 +266,7 @@ int main(void) return 0; } - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, &adv_cb, &pawr_adv); if (err) { printk("Failed to create advertising set (err %d)\n", err); diff --git a/samples/bluetooth/periodic_sync_conn/sample.yaml b/samples/bluetooth/periodic_sync_conn/sample.yaml index e7aca788eea6b..a13d15c8ff0c3 100644 --- a/samples/bluetooth/periodic_sync_conn/sample.yaml +++ b/samples/bluetooth/periodic_sync_conn/sample.yaml @@ -6,10 +6,6 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 - - nrf52840dk/nrf52840 tags: bluetooth integration_platforms: - - nrf52840dk/nrf52840 - extra_configs: - - CONFIG_BT_CTLR=n - - CONFIG_BT_NO_DRIVER=y + - qemu_cortex_m3 diff --git a/samples/bluetooth/periodic_sync_rsp/sample.yaml b/samples/bluetooth/periodic_sync_rsp/sample.yaml index c0f073b19e01b..e31e7f61badd2 100644 --- a/samples/bluetooth/periodic_sync_rsp/sample.yaml +++ b/samples/bluetooth/periodic_sync_rsp/sample.yaml @@ -6,10 +6,6 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 - - nrf52840dk/nrf52840 tags: bluetooth integration_platforms: - - nrf52840dk/nrf52840 - extra_configs: - - CONFIG_BT_CTLR=n - - CONFIG_BT_NO_DRIVER=y + - qemu_cortex_m3 diff --git a/samples/bluetooth/peripheral/src/main.c b/samples/bluetooth/peripheral/src/main.c index d0c62ec48e398..1abc19166d2c0 100644 --- a/samples/bluetooth/peripheral/src/main.c +++ b/samples/bluetooth/peripheral/src/main.c @@ -291,7 +291,7 @@ static void bt_ready(void) settings_load(); } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; diff --git a/samples/bluetooth/peripheral_accept_list/src/main.c b/samples/bluetooth/peripheral_accept_list/src/main.c index ddf390cb06394..6add0de5d66c9 100644 --- a/samples/bluetooth/peripheral_accept_list/src/main.c +++ b/samples/bluetooth/peripheral_accept_list/src/main.c @@ -120,7 +120,7 @@ static void bt_ready(void) bond_count = 0; bt_foreach_bond(BT_ID_DEFAULT, add_bonded_addr_to_filter_list, NULL); - adv_param = *BT_LE_ADV_CONN; + adv_param = *BT_LE_ADV_CONN_ONE_TIME; /* If we have got at least one bond, activate the filter */ if (bond_count) { diff --git a/samples/bluetooth/peripheral_csc/src/main.c b/samples/bluetooth/peripheral_csc/src/main.c index 1a9970adb2663..cdedeca2fc4ff 100644 --- a/samples/bluetooth/peripheral_csc/src/main.c +++ b/samples/bluetooth/peripheral_csc/src/main.c @@ -378,7 +378,7 @@ static void bt_ready(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; diff --git a/samples/bluetooth/peripheral_dis/src/main.c b/samples/bluetooth/peripheral_dis/src/main.c index f17bbc7c51ec2..b20f7f3748b48 100644 --- a/samples/bluetooth/peripheral_dis/src/main.c +++ b/samples/bluetooth/peripheral_dis/src/main.c @@ -100,7 +100,7 @@ int main(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return 0; diff --git a/samples/bluetooth/peripheral_esp/src/main.c b/samples/bluetooth/peripheral_esp/src/main.c index 88ae192ce9091..6a2d40f9b1297 100644 --- a/samples/bluetooth/peripheral_esp/src/main.c +++ b/samples/bluetooth/peripheral_esp/src/main.c @@ -421,7 +421,7 @@ static void bt_ready(void) printk("Bluetooth initialized\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; diff --git a/samples/bluetooth/peripheral_gatt_write/src/peripheral_gatt_write.c b/samples/bluetooth/peripheral_gatt_write/src/peripheral_gatt_write.c index 019f8262cd603..41bb65988cbf3 100644 --- a/samples/bluetooth/peripheral_gatt_write/src/peripheral_gatt_write.c +++ b/samples/bluetooth/peripheral_gatt_write/src/peripheral_gatt_write.c @@ -66,7 +66,7 @@ uint32_t peripheral_gatt_write(uint32_t count) (void)bt_conn_auth_cb_register(&auth_callbacks); #endif /* CONFIG_BT_SMP */ - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return 0U; diff --git a/samples/bluetooth/peripheral_hids/src/main.c b/samples/bluetooth/peripheral_hids/src/main.c index ef743b7c57ddc..92e60744fe90a 100644 --- a/samples/bluetooth/peripheral_hids/src/main.c +++ b/samples/bluetooth/peripheral_hids/src/main.c @@ -98,7 +98,7 @@ static void bt_ready(int err) settings_load(); } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; diff --git a/samples/bluetooth/peripheral_hr/prj_minimal.conf b/samples/bluetooth/peripheral_hr/prj_minimal.conf index a9feeb48cb00b..6446273584ae9 100644 --- a/samples/bluetooth/peripheral_hr/prj_minimal.conf +++ b/samples/bluetooth/peripheral_hr/prj_minimal.conf @@ -91,7 +91,7 @@ CONFIG_BT_GATT_CACHING=n CONFIG_BT_GATT_SERVICE_CHANGED=n CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=n CONFIG_BT_SETTINGS_CCC_LAZY_LOADING=y -CONFIG_BT_HCI_VS_EXT=n +CONFIG_BT_HCI_VS=n # Disable Bluetooth controller features not needed CONFIG_BT_CTLR_PRIVACY=n @@ -103,7 +103,6 @@ CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=45 CONFIG_BT_BUF_ACL_RX_COUNT=2 CONFIG_BT_BUF_EVT_RX_COUNT=2 -CONFIG_BT_CONN_TX_MAX=2 CONFIG_BT_L2CAP_TX_BUF_COUNT=2 CONFIG_BT_CTLR_RX_BUFFERS=1 CONFIG_BT_BUF_ACL_TX_COUNT=3 diff --git a/samples/bluetooth/peripheral_hr/sample.yaml b/samples/bluetooth/peripheral_hr/sample.yaml index afc3077ac15c7..6a4f2edead029 100644 --- a/samples/bluetooth/peripheral_hr/sample.yaml +++ b/samples/bluetooth/peripheral_hr/sample.yaml @@ -7,8 +7,30 @@ tests: platform_allow: - qemu_cortex_m3 - qemu_x86 + - nrf52_bsim + - nrf5340bsim/nrf5340/cpuapp + - nrf51dk/nrf51822 + - nrf52dk/nrf52832 + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15pdk/nrf54l15/cpuapp integration_platforms: - qemu_cortex_m3 + - nrf52_bsim + - nrf5340bsim/nrf5340/cpuapp + - nrf51dk/nrf51822 + - nrf52dk/nrf52832 + - nrf52840dk/nrf52840 + - nrf5340dk/nrf5340/cpuapp + - nrf54l15pdk/nrf54l15/cpuapp + tags: bluetooth + sample.bluetooth.peripheral_hr.minimal: + harness: bluetooth + platform_allow: + - bbc_microbit + integration_platforms: + - bbc_microbit + extra_args: EXTRA_CONF_FILE=prj_minimal.conf tags: bluetooth sample.bluetooth.peripheral_hr.bt_ll_sw_split.extended: harness: bluetooth diff --git a/samples/bluetooth/peripheral_hr/src/main.c b/samples/bluetooth/peripheral_hr/src/main.c index 03279c0840f4e..5081d93a64b32 100644 --- a/samples/bluetooth/peripheral_hr/src/main.c +++ b/samples/bluetooth/peripheral_hr/src/main.c @@ -204,7 +204,7 @@ int main(void) #if !defined(CONFIG_BT_EXT_ADV) printk("Starting Legacy Advertising (connectable and scannable)\n"); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return 0; @@ -281,7 +281,16 @@ int main(void) blink_stop(); #endif /* HAS_LED */ } else if (atomic_test_and_clear_bit(state, STATE_DISCONNECTED)) { -#if defined(CONFIG_BT_EXT_ADV) +#if !defined(CONFIG_BT_EXT_ADV) + printk("Starting Legacy Advertising (connectable and scannable)\n"); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, + ARRAY_SIZE(sd)); + if (err) { + printk("Advertising failed to start (err %d)\n", err); + return 0; + } + +#else /* CONFIG_BT_EXT_ADV */ printk("Starting Extended Advertising (connectable and non-scannable)\n"); err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); if (err) { diff --git a/samples/bluetooth/peripheral_ht/boards/frdm_rw612.conf b/samples/bluetooth/peripheral_ht/boards/frdm_rw612.conf new file mode 100644 index 0000000000000..2df782efc7115 --- /dev/null +++ b/samples/bluetooth/peripheral_ht/boards/frdm_rw612.conf @@ -0,0 +1 @@ +CONFIG_PM=y diff --git a/samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf b/samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf new file mode 100644 index 0000000000000..2df782efc7115 --- /dev/null +++ b/samples/bluetooth/peripheral_ht/boards/rd_rw612_bga.conf @@ -0,0 +1 @@ +CONFIG_PM=y diff --git a/samples/bluetooth/peripheral_ht/sample.yaml b/samples/bluetooth/peripheral_ht/sample.yaml index 4ff509843e064..be53ecd851908 100644 --- a/samples/bluetooth/peripheral_ht/sample.yaml +++ b/samples/bluetooth/peripheral_ht/sample.yaml @@ -23,3 +23,11 @@ tests: extra_args: SHIELD=frdm_kw41z integration_platforms: - mimxrt1020_evk + sample.bluetooth.peripheral_ht.nxp: + # Disabling monolithic since CI environment doesn't use blobs + harness: bluetooth + platform_allow: + - rd_rw612_bga + - frdm_rw612 + extra_configs: + - CONFIG_NXP_MONOLITHIC_BT=n diff --git a/samples/bluetooth/peripheral_ht/src/main.c b/samples/bluetooth/peripheral_ht/src/main.c index 197ee1cdaec43..704bad983b240 100644 --- a/samples/bluetooth/peripheral_ht/src/main.c +++ b/samples/bluetooth/peripheral_ht/src/main.c @@ -62,7 +62,7 @@ static void bt_ready(void) hts_init(); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; diff --git a/samples/bluetooth/peripheral_iso/src/main.c b/samples/bluetooth/peripheral_iso/src/main.c index e93b11bcf7f5e..7af0208216b86 100644 --- a/samples/bluetooth/peripheral_iso/src/main.c +++ b/samples/bluetooth/peripheral_iso/src/main.c @@ -176,7 +176,7 @@ int main(void) return 0; } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return 0; diff --git a/samples/bluetooth/peripheral_nus/src/main.c b/samples/bluetooth/peripheral_nus/src/main.c index e94a45a0e083b..767b2286fb237 100644 --- a/samples/bluetooth/peripheral_nus/src/main.c +++ b/samples/bluetooth/peripheral_nus/src/main.c @@ -61,7 +61,7 @@ int main(void) return err; } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Failed to start advertising: %d\n", err); return err; diff --git a/samples/bluetooth/peripheral_ots/boards/rd_rw612_bga.conf b/samples/bluetooth/peripheral_ots/boards/rd_rw612_bga.conf new file mode 100644 index 0000000000000..b25149c8ec46a --- /dev/null +++ b/samples/bluetooth/peripheral_ots/boards/rd_rw612_bga.conf @@ -0,0 +1 @@ +CONFIG_BT_RX_STACK_SIZE=1800 diff --git a/samples/bluetooth/peripheral_ots/src/main.c b/samples/bluetooth/peripheral_ots/src/main.c index 50f9fc4de71c5..f6d92f0b5cab5 100644 --- a/samples/bluetooth/peripheral_ots/src/main.c +++ b/samples/bluetooth/peripheral_ots/src/main.c @@ -334,8 +334,7 @@ int main(void) return 0; } - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), - sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return 0; diff --git a/samples/bluetooth/peripheral_past/src/main.c b/samples/bluetooth/peripheral_past/src/main.c index 398e691cf61c7..5ed4e864e80c9 100644 --- a/samples/bluetooth/peripheral_past/src/main.c +++ b/samples/bluetooth/peripheral_past/src/main.c @@ -146,7 +146,7 @@ int main(void) return 0; } - err = bt_le_adv_start(BT_LE_ADV_CONN, NULL, 0, sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, NULL, 0, sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return 0; diff --git a/samples/bluetooth/peripheral_sc_only/src/main.c b/samples/bluetooth/peripheral_sc_only/src/main.c index 0b75d55242749..dae77354098eb 100644 --- a/samples/bluetooth/peripheral_sc_only/src/main.c +++ b/samples/bluetooth/peripheral_sc_only/src/main.c @@ -141,11 +141,10 @@ int main(void) printk("Bluetooth initialized\n"); - bt_conn_auth_cb_register(&auth_cb_display); bt_conn_auth_info_cb_register(&auth_cb_info); - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return 0; diff --git a/samples/bluetooth/public_broadcast_sink/README.rst b/samples/bluetooth/public_broadcast_sink/README.rst deleted file mode 100644 index 6be21803d94a9..0000000000000 --- a/samples/bluetooth/public_broadcast_sink/README.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. zephyr:code-sample:: bluetooth_public_broadcast_sink - :name: Bluetooth: Public Broadcast Sink - :relevant-api: bluetooth - - Bluetooth: Public Broadcast Sink - -Overview -******** - -Application demonstrating the LE Public Broadcast Profile sink functionality. -Starts by scanning for LE Audio broadcast sources and then synchronizes to -the first found source which defines a Public Broadcast Announcement including -a High Quality Public Broadcast Audio Stream configuration. - -This sample can be found under -:zephyr_file:`samples/bluetooth/public_broadcast_sink` in the Zephyr tree. - -Check the :ref:`bluetooth samples section ` for general information. - -Requirements -************ - -* BlueZ running on the host, or -* A board with Bluetooth Low Energy 5.2 support - -Building and Running -******************** - -When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, -use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO -feature support. - -Building for an nrf5340dk -------------------------- - -You can build both the application core image and an appropriate controller image for the network -core with: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/public_broadcast_sink/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -If you prefer to only build the application core image, you can do so by doing instead: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/public_broadcast_sink/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - -In that case you can pair this application core image with the -:ref:`hci_ipc sample ` -:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. - -Building for a simulated nrf5340bsim ------------------------------------- - -Similarly to how you would for real HW, you can do: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/public_broadcast_sink/ - :board: nrf5340bsim/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. -For more information, check :ref:`this board documentation `. - -Building for a simulated nrf52_bsim ------------------------------------ - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/public_broadcast_sink/ - :board: nrf52_bsim - :goals: build - :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/public_broadcast_sink/sample.yaml b/samples/bluetooth/public_broadcast_sink/sample.yaml deleted file mode 100644 index cf437a737033b..0000000000000 --- a/samples/bluetooth/public_broadcast_sink/sample.yaml +++ /dev/null @@ -1,27 +0,0 @@ -sample: - description: Bluetooth Low Energy Audio PBP Broadcast Sink sample - name: Bluetooth Low Energy Audio PBP Broadcast Sink sample -tests: - sample.bluetooth.public_broadcast_sink: - harness: bluetooth - platform_allow: - - qemu_cortex_m3 - - qemu_x86 - - nrf5340dk/nrf5340/cpuapp - - nrf5340bsim/nrf5340/cpuapp - integration_platforms: - - qemu_x86 - - nrf5340dk/nrf5340/cpuapp - tags: bluetooth - sysbuild: true - sample.bluetooth.public_broadcast_sink.bt_ll_sw_split: - harness: bluetooth - platform_allow: - - nrf52_bsim - - nrf52833dk/nrf52820 - - nrf52833dk/nrf52833 - integration_platforms: - - nrf52_bsim - - nrf52833dk/nrf52833 - extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf - tags: bluetooth diff --git a/samples/bluetooth/public_broadcast_source/CMakeLists.txt b/samples/bluetooth/public_broadcast_source/CMakeLists.txt deleted file mode 100644 index 6331703e2d89a..0000000000000 --- a/samples/bluetooth/public_broadcast_source/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(public_broadcast_source) - -target_sources(app PRIVATE - src/main.c -) - -zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/public_broadcast_source/README.rst b/samples/bluetooth/public_broadcast_source/README.rst deleted file mode 100644 index 7d7a585219848..0000000000000 --- a/samples/bluetooth/public_broadcast_source/README.rst +++ /dev/null @@ -1,77 +0,0 @@ -.. zephyr:code-sample:: bluetooth_public_broadcast_source - :name: Bluetooth: Public Broadcast Source - :relevant-api: bluetooth - - Bluetooth: Public Broadcast Source - -Overview -******** - -Application demonstrating the LE Public Broadcast Profile source functionality. -Will start advertising extended advertising and includes a Broadcast Audio Announcement. -The advertised broadcast audio stream quality will cycle between high and standard quality -every 15 seconds. - -This sample can be found under -:zephyr_file:`samples/bluetooth/public_broadcast_source` in the Zephyr tree. - -Check the :ref:`bluetooth samples section ` for general information. - -Requirements -************ - -* BlueZ running on the host, or -* A board with Bluetooth Low Energy 5.2 support - -Building and Running -******************** - -When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, -use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO -feature support. - -Building for an nrf5340dk -------------------------- - -You can build both the application core image and an appropriate controller image for the network -core with: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/public_broadcast_source/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -If you prefer to only build the application core image, you can do so by doing instead: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/public_broadcast_source/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - -In that case you can pair this application core image with the -:ref:`hci_ipc sample ` -:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. - -Building for a simulated nrf5340bsim ------------------------------------- - -Similarly to how you would for real HW, you can do: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/public_broadcast_source/ - :board: nrf5340bsim/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. -For more information, check :ref:`this board documentation `. - -Building for a simulated nrf52_bsim ------------------------------------ - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/public_broadcast_source/ - :board: nrf52_bsim - :goals: build - :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf diff --git a/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf b/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf deleted file mode 100644 index c73ff9c3ea9b8..0000000000000 --- a/samples/bluetooth/public_broadcast_source/overlay-bt_ll_sw_split.conf +++ /dev/null @@ -1,24 +0,0 @@ -# Zephyr Bluetooth Controller -CONFIG_BT_LL_SW_SPLIT=y - -# Zephyr Controller tested maximum advertising data that can be set in a single HCI command -CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 - -# Enable support for Broadcast ISO in Zephyr Bluetooth Controller -CONFIG_BT_CTLR_ADV_ISO=y - -# Sufficient ISO PDU length for any BAP LC3 presets (155) -CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=155 - -# Number of supported streams -CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2 -CONFIG_BT_CTLR_ISOAL_SOURCES=2 - -# FIXME: Host needs CONFIG_BT_ISO_TX_MTU + 4 bytes for sequence number, and optionally -# additional + 4 bytes for timestamp when not using BT_ISO_TIMESTAMP_NONE in bt_iso_chan_send(), -# otherwise Host tries to fragment ISO data. -# When Host is fixed, CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE can inherit the -# CONFIG_BT_ISO_TX_MTU value. -# -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=163 diff --git a/samples/bluetooth/public_broadcast_source/sample.yaml b/samples/bluetooth/public_broadcast_source/sample.yaml deleted file mode 100644 index d40c04855579e..0000000000000 --- a/samples/bluetooth/public_broadcast_source/sample.yaml +++ /dev/null @@ -1,27 +0,0 @@ -sample: - description: Bluetooth Low Energy Public Broadcast Source sample - name: Bluetooth Low Energy Public Broadcast Source sample -tests: - sample.bluetooth.public_broadcast_source: - harness: bluetooth - platform_allow: - - qemu_cortex_m3 - - qemu_x86 - - nrf5340dk/nrf5340/cpuapp - - nrf5340bsim/nrf5340/cpuapp - integration_platforms: - - qemu_x86 - - nrf5340dk/nrf5340/cpuapp - tags: bluetooth - sysbuild: true - sample.bluetooth.public_broadcast_source.bt_ll_sw_split: - harness: bluetooth - platform_allow: - - nrf52_bsim - - nrf52833dk/nrf52820 - - nrf52833dk/nrf52833 - integration_platforms: - - nrf52_bsim - - nrf52833dk/nrf52833 - extra_args: OVERLAY_CONFIG=overlay-bt_ll_sw_split.conf - tags: bluetooth diff --git a/samples/bluetooth/public_broadcast_source/src/main.c b/samples/bluetooth/public_broadcast_source/src/main.c deleted file mode 100644 index 5ffb94d785f0d..0000000000000 --- a/samples/bluetooth/public_broadcast_source/src/main.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright 2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BROADCAST_ENQUEUE_COUNT 2U - -/* PBS ASCII text */ -#define PBS_DEMO 'P', 'B', 'P' - -NET_BUF_POOL_FIXED_DEFINE(tx_pool, - (BROADCAST_ENQUEUE_COUNT * CONFIG_BT_BAP_BROADCAST_SRC_STREAM_COUNT), - BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), 8, NULL); - -static K_SEM_DEFINE(sem_broadcast_started, 0, 1); -static K_SEM_DEFINE(sem_broadcast_stopped, 0, 1); - -static struct bt_cap_stream broadcast_source_stream; -static struct bt_cap_stream *broadcast_stream; - -static uint8_t bis_codec_data[] = {BT_AUDIO_CODEC_DATA( - BT_AUDIO_CODEC_CFG_FREQ, BT_BYTES_LIST_LE16(BT_AUDIO_CODEC_CFG_FREQ_48KHZ))}; - -const uint8_t pba_metadata[] = { - BT_AUDIO_CODEC_DATA(BT_AUDIO_METADATA_TYPE_PROGRAM_INFO, PBS_DEMO) -}; - -static uint8_t appearance_addata[] = { - BT_BYTES_LIST_LE16(BT_APPEARANCE_AUDIO_SOURCE_BROADCASTING_DEVICE) -}; - -static const char broadcast_name[] = "PBP Source Demo"; - -static struct bt_bap_lc3_preset broadcast_preset_48_2_1 = - BT_BAP_LC3_UNICAST_PRESET_48_2_1(BT_AUDIO_LOCATION_FRONT_LEFT, - BT_AUDIO_CONTEXT_TYPE_MEDIA); - -static const struct bt_data ad[] = { - BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), -}; - -struct bt_cap_initiator_broadcast_stream_param stream_params; -struct bt_cap_initiator_broadcast_subgroup_param subgroup_param; -struct bt_cap_initiator_broadcast_create_param create_param; -struct bt_cap_broadcast_source *broadcast_source; -struct bt_le_ext_adv *ext_adv; - -static void broadcast_started_cb(struct bt_bap_stream *stream) -{ - printk("Stream %p started\n", stream); - k_sem_give(&sem_broadcast_started); -} - -static void broadcast_stopped_cb(struct bt_bap_stream *stream, uint8_t reason) -{ - if (reason == BT_HCI_ERR_LOCALHOST_TERM_CONN) { - printk("Stream %p ended\n", stream); - } else { - printk("Stream %p stopped with reason 0x%02X\n", stream, reason); - } - - k_sem_give(&sem_broadcast_stopped); -} - -static void broadcast_sent_cb(struct bt_bap_stream *stream) -{ - static uint8_t mock_data[CONFIG_BT_ISO_TX_MTU]; - static bool mock_data_initialized; - static uint32_t seq_num; - struct net_buf *buf; - int ret; - - if (broadcast_preset_48_2_1.qos.sdu > CONFIG_BT_ISO_TX_MTU) { - printk("Invalid SDU %u for the MTU: %d", broadcast_preset_48_2_1.qos.sdu, - CONFIG_BT_ISO_TX_MTU); - - return; - } - - if (!mock_data_initialized) { - for (size_t i = 0U; i < ARRAY_SIZE(mock_data); i++) { - /* Initialize mock data */ - mock_data[i] = (uint8_t)i; - } - mock_data_initialized = true; - } - - buf = net_buf_alloc(&tx_pool, K_FOREVER); - if (buf == NULL) { - printk("Could not allocate buffer when sending on %p\n", stream); - - return; - } - - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - net_buf_add_mem(buf, mock_data, broadcast_preset_48_2_1.qos.sdu); - ret = bt_bap_stream_send(stream, buf, seq_num++); - if (ret < 0) { - /* This will end broadcasting on this stream. */ - net_buf_unref(buf); - - return; - } -} - -static struct bt_bap_stream_ops broadcast_stream_ops = { - .started = broadcast_started_cb, - .stopped = broadcast_stopped_cb, - .sent = broadcast_sent_cb -}; - -static int setup_extended_adv(struct bt_le_ext_adv **adv) -{ - int err; - - /* Create a non-connectable non-scannable advertising set */ - err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); - if (err != 0) { - printk("Unable to create extended advertising set: %d\n", err); - - return err; - } - - /* Set advertising data to have complete local name set */ - err = bt_le_ext_adv_set_data(*adv, ad, ARRAY_SIZE(ad), NULL, 0); - if (err) { - printk("Failed to set advertising data (err %d)\n", err); - - return 0; - } - - /* Set periodic advertising parameters */ - err = bt_le_per_adv_set_param(*adv, BT_LE_PER_ADV_DEFAULT); - if (err) { - printk("Failed to set periodic advertising parameters: %d\n", err); - - return err; - } - - return 0; -} - -static int setup_extended_adv_data(struct bt_cap_broadcast_source *source, - struct bt_le_ext_adv *adv) -{ - /* Broadcast Audio Streaming Endpoint advertising data */ - NET_BUF_SIMPLE_DEFINE(ad_buf, - BT_UUID_SIZE_16 + BT_AUDIO_BROADCAST_ID_SIZE); - NET_BUF_SIMPLE_DEFINE(base_buf, 128); - NET_BUF_SIMPLE_DEFINE(pbp_ad_buf, BT_UUID_SIZE_16 + 1 + ARRAY_SIZE(pba_metadata)); - static enum bt_pbp_announcement_feature pba_params; - struct bt_data ext_ad[4]; - struct bt_data per_ad; - uint32_t broadcast_id; - int err; - - err = bt_cap_initiator_broadcast_get_id(source, &broadcast_id); - if (err != 0) { - printk("Unable to get broadcast ID: %d\n", err); - - return err; - } - - /* Setup extended advertising data */ - ext_ad[0].type = BT_DATA_GAP_APPEARANCE; - ext_ad[0].data_len = 2; - ext_ad[0].data = appearance_addata; - /* Broadcast name AD Type */ - ext_ad[1].type = BT_DATA_BROADCAST_NAME; - ext_ad[1].data_len = ARRAY_SIZE(broadcast_name); - ext_ad[1].data = broadcast_name; - /* Broadcast Audio Announcement */ - net_buf_simple_add_le16(&ad_buf, BT_UUID_BROADCAST_AUDIO_VAL); - net_buf_simple_add_le24(&ad_buf, broadcast_id); - ext_ad[2].type = BT_DATA_SVC_DATA16; - ext_ad[2].data_len = ad_buf.len + sizeof(ext_ad[2].type); - ext_ad[2].data = ad_buf.data; - - /** - * Create a Public Broadcast Announcement - * Cycle between high and standard quality public broadcast audio. - */ - if (pba_params & BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY) { - pba_params = 0; - pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_STANDARD_QUALITY; - printk("Starting stream with standard quality!\n"); - } else { - pba_params = 0; - pba_params |= BT_PBP_ANNOUNCEMENT_FEATURE_HIGH_QUALITY; - printk("Starting stream with high quality!\n"); - } - err = bt_pbp_get_announcement(&pba_metadata[1], ARRAY_SIZE(pba_metadata) - 1, - pba_params, &pbp_ad_buf); - if (err != 0) { - printk("Failed to create public broadcast announcement!: %d\n", err); - - return err; - } - ext_ad[3].type = BT_DATA_SVC_DATA16; - ext_ad[3].data_len = pbp_ad_buf.len; - ext_ad[3].data = pbp_ad_buf.data; - err = bt_le_ext_adv_set_data(adv, ext_ad, ARRAY_SIZE(ext_ad), NULL, 0); - if (err != 0) { - printk("Failed to set extended advertising data: %d\n", err); - - return err; - } - - /* Setup periodic advertising data */ - err = bt_cap_initiator_broadcast_get_base(source, &base_buf); - if (err != 0) { - printk("Failed to get encoded BASE: %d\n", err); - - return err; - } - - per_ad.type = BT_DATA_SVC_DATA16; - per_ad.data_len = base_buf.len; - per_ad.data = base_buf.data; - err = bt_le_per_adv_set_data(adv, &per_ad, 1); - if (err != 0) { - printk("Failed to set periodic advertising data: %d\n", err); - - return err; - } - - return 0; -} - -static int start_extended_adv(struct bt_le_ext_adv *adv) -{ - int err; - - /* Start extended advertising */ - err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); - if (err) { - printk("Failed to start extended advertising: %d\n", err); - - return err; - } - - /* Enable Periodic Advertising */ - err = bt_le_per_adv_start(adv); - if (err) { - printk("Failed to enable periodic advertising: %d\n", err); - - return err; - } - - return 0; -} - -static int stop_and_delete_extended_adv(struct bt_le_ext_adv *adv) -{ - int err; - - /* Stop extended advertising */ - err = bt_le_per_adv_stop(adv); - if (err) { - printk("Failed to stop periodic advertising: %d\n", err); - - return err; - } - - err = bt_le_ext_adv_stop(adv); - if (err) { - printk("Failed to stop extended advertising: %d\n", err); - - return err; - } - - err = bt_le_ext_adv_delete(adv); - if (err) { - printk("Failed to delete extended advertising: %d\n", err); - - return err; - } - - return 0; -} - -static int reset(void) -{ - k_sem_reset(&sem_broadcast_started); - k_sem_reset(&sem_broadcast_stopped); - - return 0; -} - -int cap_initiator_init(void) -{ - if (IS_ENABLED(CONFIG_BT_BAP_BROADCAST_SOURCE)) { - broadcast_stream = &broadcast_source_stream; - bt_bap_stream_cb_register(&broadcast_stream->bap_stream, &broadcast_stream_ops); - } - - return 0; -} - -void cap_initiator_setup(void) -{ - int err; - - stream_params.stream = &broadcast_source_stream; - stream_params.data_len = ARRAY_SIZE(bis_codec_data); - stream_params.data = bis_codec_data; - - subgroup_param.stream_count = 1U; - subgroup_param.stream_params = &stream_params; - subgroup_param.codec_cfg = &broadcast_preset_48_2_1.codec_cfg; - - create_param.subgroup_count = 1U; - create_param.subgroup_params = &subgroup_param; - create_param.qos = &broadcast_preset_48_2_1.qos; - create_param.packing = BT_ISO_PACKING_SEQUENTIAL; - create_param.encryption = false; - - while (true) { - err = reset(); - if (err != 0) { - printk("Resetting failed: %d - Aborting\n", err); - - return; - } - - err = setup_extended_adv(&ext_adv); - if (err != 0) { - printk("Unable to setup extended advertiser: %d\n", err); - - return; - } - - err = bt_cap_initiator_broadcast_audio_create(&create_param, &broadcast_source); - if (err != 0) { - printk("Unable to create broadcast source: %d\n", err); - - return; - } - - err = bt_cap_initiator_broadcast_audio_start(broadcast_source, ext_adv); - if (err != 0) { - printk("Unable to start broadcast source: %d\n", err); - - return; - } - - err = setup_extended_adv_data(broadcast_source, ext_adv); - if (err != 0) { - printk("Unable to setup extended advertising data: %d\n", err); - - return; - } - - err = start_extended_adv(ext_adv); - if (err != 0) { - printk("Unable to start extended advertiser: %d\n", err); - - return; - } - k_sem_take(&sem_broadcast_started, K_FOREVER); - - /* Initialize sending */ - for (unsigned int j = 0U; j < BROADCAST_ENQUEUE_COUNT; j++) { - broadcast_sent_cb(&broadcast_stream->bap_stream); - } - - /* Keeping running for a little while */ - k_sleep(K_SECONDS(15)); - - err = bt_cap_initiator_broadcast_audio_stop(broadcast_source); - if (err != 0) { - printk("Failed to stop broadcast source: %d\n", err); - - return; - } - - k_sem_take(&sem_broadcast_stopped, K_FOREVER); - err = bt_cap_initiator_broadcast_audio_delete(broadcast_source); - if (err != 0) { - printk("Failed to stop broadcast source: %d\n", err); - - return; - } - broadcast_source = NULL; - - err = stop_and_delete_extended_adv(ext_adv); - if (err != 0) { - printk("Failed to stop and delete extended advertising: %d\n", err); - - return; - } - } -} - - -int main(void) -{ - int err; - - err = bt_enable(NULL); - if (err != 0) { - printk("Bluetooth enable failed (err %d)\n", err); - - return err; - } - - printk("Bluetooth initialized\n"); - - /* Initialize CAP Initiator */ - err = cap_initiator_init(); - if (err != 0) { - return err; - } - - printk("CAP initialized\n"); - - /* Configure and start broadcast stream */ - cap_initiator_setup(); - - return 0; -} diff --git a/samples/bluetooth/st_ble_sensor/src/main.c b/samples/bluetooth/st_ble_sensor/src/main.c index 95060f9167a62..515b1ab616680 100644 --- a/samples/bluetooth/st_ble_sensor/src/main.c +++ b/samples/bluetooth/st_ble_sensor/src/main.c @@ -142,7 +142,7 @@ static void bt_ready(int err) } LOG_INF("Bluetooth initialized"); /* Start advertising */ - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), NULL, 0); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), NULL, 0); if (err) { LOG_ERR("Advertising failed to start (err %d)", err); return; diff --git a/samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 3c7c698c48b8c..0000000000000 --- a/samples/bluetooth/tmap_bmr/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_PERIPHERAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 57d674179ff93..0000000000000 --- a/samples/bluetooth/tmap_bms/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_CENTRAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/tmap_bms/src/cap_initiator.c b/samples/bluetooth/tmap_bms/src/cap_initiator.c index 2c0019e234c21..3cce613dd9863 100644 --- a/samples/bluetooth/tmap_bms/src/cap_initiator.c +++ b/samples/bluetooth/tmap_bms/src/cap_initiator.c @@ -115,7 +115,7 @@ static int setup_extended_adv(struct bt_le_ext_adv **adv) { int err; - /* Create a non-connectable non-scannable advertising set */ + /* Create a non-connectable advertising set */ err = bt_le_ext_adv_create(BT_LE_EXT_ADV_NCONN, NULL, adv); if (err != 0) { printk("Unable to create extended advertising set: %d\n", err); diff --git a/samples/bluetooth/tmap_central/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_central/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 57d674179ff93..0000000000000 --- a/samples/bluetooth/tmap_central/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_CENTRAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/tmap_central/src/cap_initiator.c b/samples/bluetooth/tmap_central/src/cap_initiator.c index dc7e54c439da4..fd20fadaa7105 100644 --- a/samples/bluetooth/tmap_central/src/cap_initiator.c +++ b/samples/bluetooth/tmap_central/src/cap_initiator.c @@ -98,6 +98,7 @@ static struct bt_bap_lc3_preset unicast_preset_48_2_1 = BT_AUDIO_CONTEXT_TYPE_MEDIA); static void cap_discovery_complete_cb(struct bt_conn *conn, int err, + const struct bt_csip_set_coordinator_set_member *member, const struct bt_csip_set_coordinator_csis_inst *csis_inst) { if (err != 0) { diff --git a/samples/bluetooth/tmap_peripheral/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/tmap_peripheral/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 3c7c698c48b8c..0000000000000 --- a/samples/bluetooth/tmap_peripheral/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_PERIPHERAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c index 523b3e1d82aee..8e325855e655a 100644 --- a/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c +++ b/samples/bluetooth/tmap_peripheral/src/bap_unicast_sr.c @@ -1,7 +1,7 @@ /** @file * @brief Bluetooth Basic Audio Profile (BAP) Unicast Server role. * - * Copyright (c) 2021-2023 Nordic Semiconductor ASA + * Copyright (c) 2021-2024 Nordic Semiconductor ASA * Copyright (c) 2022 Codecoup * Copyright (c) 2023 NXP * @@ -82,7 +82,8 @@ static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); } - if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation) == 0) { + ret = bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation, false); + if (ret == 0) { printk(" Channel allocation: 0x%x\n", chan_allocation); } @@ -293,10 +294,23 @@ static void stream_recv(struct bt_bap_stream *stream, const struct bt_iso_recv_i static void stream_enabled(struct bt_bap_stream *stream) { - const int err = bt_bap_stream_start(stream); + struct bt_bap_ep_info ep_info; + int err; + err = bt_bap_ep_get_info(stream->ep, &ep_info); if (err != 0) { - printk("Failed to start stream %p: %d", stream, err); + printk("Failed to get ep info: %d\n", err); + return; + } + + /* The unicast server is responsible for starting the sink streams */ + if (ep_info.dir == BT_AUDIO_DIR_SINK) { + /* Automatically do the receiver start ready operation */ + err = bt_bap_stream_start(stream); + + if (err != 0) { + printk("Failed to start stream %p: %d", stream, err); + } } } diff --git a/samples/bluetooth/unicast_audio_client/CMakeLists.txt b/samples/bluetooth/unicast_audio_client/CMakeLists.txt deleted file mode 100644 index 633ce9502e20c..0000000000000 --- a/samples/bluetooth/unicast_audio_client/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(unicast_audio_client) - -target_sources(app PRIVATE - src/main.c -) - -zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/unicast_audio_client/README.rst b/samples/bluetooth/unicast_audio_client/README.rst deleted file mode 100644 index 67087dfdfcc3c..0000000000000 --- a/samples/bluetooth/unicast_audio_client/README.rst +++ /dev/null @@ -1,83 +0,0 @@ -.. _bluetooth_unicast_audio_client: - -Bluetooth: Unicast Audio Client -############################### - -Overview -******** - -Application demonstrating the LE Audio unicast client functionality. Scans for and -connects to a LE Audio unicast server and establishes an audio stream. - -This sample can be found under -:zephyr_file:`samples/bluetooth/unicast_audio_client` in the Zephyr tree. - -Check the :ref:`bluetooth samples section ` for general information. - -Requirements -************ - -* BlueZ running on the host, or -* A board with Bluetooth Low Energy 5.2 support - -Building and Running -******************** - -When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, -use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO -feature support. - -Building for an nrf52840dk --------------------------- - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_client/ - :board: nrf52840dk/nrf52840 - :goals: build - :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf - -Building for an nrf5340dk -------------------------- - -You can build both the application core image and an appropriate controller image for the network -core with: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_client/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -If you prefer to only build the application core image, you can do so by doing instead: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_server/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - -In that case you can pair this application core image with the -:ref:`hci_ipc sample ` -:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. - -Building for a simulated nrf52_bsim ------------------------------------ - -Similarly to how you would for real HW, you can do: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_client/ - :board: nrf52_bsim - :goals: build - :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf - -Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. -For more information, check :ref:`this board documentation `. - -Building for a simulated nrf5340bsim ------------------------------------- - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_client/ - :board: nrf5340bsim/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/unicast_audio_client/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 57d674179ff93..0000000000000 --- a/samples/bluetooth/unicast_audio_client/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_CENTRAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf deleted file mode 100644 index 8d48d5e1c2072..0000000000000 --- a/samples/bluetooth/unicast_audio_client/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ /dev/null @@ -1,6 +0,0 @@ -# For LC3 the following configs are needed -CONFIG_FPU=y -CONFIG_LIBLC3=y -# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence -# inctease stack size for that thread. -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf b/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf deleted file mode 100644 index 1c29b28e2ddaf..0000000000000 --- a/samples/bluetooth/unicast_audio_client/overlay-bt_ll_sw_split.conf +++ /dev/null @@ -1,11 +0,0 @@ -CONFIG_BT_LL_SW_SPLIT=y -CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650 -CONFIG_BT_CTLR_ISO_TX_BUFFERS=4 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 -CONFIG_BT_CTLR_ISOAL_SOURCES=2 -CONFIG_BT_CTLR_ISOAL_SINKS=1 -CONFIG_BT_CTLR_ADVANCED_FEATURES=y -CONFIG_BT_CTLR_CONN_ISO_LOW_LATENCY_POLICY=y - -# Use the below if the sample is sending stale packet sequence number -# CONFIG_BT_CTLR_ISOAL_SN_STRICT=n diff --git a/samples/bluetooth/unicast_audio_client/src/main.c b/samples/bluetooth/unicast_audio_client/src/main.c deleted file mode 100644 index 170808db24a9b..0000000000000 --- a/samples/bluetooth/unicast_audio_client/src/main.c +++ /dev/null @@ -1,1160 +0,0 @@ -/* - * Copyright (c) 2021-2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -static void start_scan(void); - -uint64_t unicast_audio_recv_ctr; /* This value is exposed to test code */ - -static struct bt_bap_unicast_client_cb unicast_client_cbs; -static struct bt_conn *default_conn; -static struct k_work_delayable audio_send_work; -static struct bt_bap_unicast_group *unicast_group; -static struct audio_sink { - struct bt_bap_ep *ep; - uint16_t seq_num; -} sinks[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT]; -static struct bt_bap_ep *sources[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT]; -NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT, - BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), - CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); - -static struct bt_bap_stream streams[CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SNK_COUNT + - CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT]; -static size_t configured_sink_stream_count; -static size_t configured_source_stream_count; - -#define configured_stream_count (configured_sink_stream_count + \ - configured_source_stream_count) - -/* Select a codec configuration to apply that is mandatory to support by both client and server. - * Allows this sample application to work without logic to parse the codec capabilities of the - * server and selection of an appropriate codec configuration. - */ -static struct bt_bap_lc3_preset codec_configuration = BT_BAP_LC3_UNICAST_PRESET_16_2_1( - BT_AUDIO_LOCATION_FRONT_LEFT, BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED); - -static K_SEM_DEFINE(sem_connected, 0, 1); -static K_SEM_DEFINE(sem_disconnected, 0, 1); -static K_SEM_DEFINE(sem_mtu_exchanged, 0, 1); -static K_SEM_DEFINE(sem_security_updated, 0, 1); -static K_SEM_DEFINE(sem_sinks_discovered, 0, 1); -static K_SEM_DEFINE(sem_sources_discovered, 0, 1); -static K_SEM_DEFINE(sem_stream_configured, 0, 1); -static K_SEM_DEFINE(sem_stream_qos, 0, ARRAY_SIZE(sinks) + ARRAY_SIZE(sources)); -static K_SEM_DEFINE(sem_stream_enabled, 0, 1); -static K_SEM_DEFINE(sem_stream_started, 0, 1); - -#define AUDIO_DATA_TIMEOUT_US 1000000UL /* Send data every 1 second */ - -static uint16_t get_and_incr_seq_num(const struct bt_bap_stream *stream) -{ - for (size_t i = 0U; i < configured_sink_stream_count; i++) { - if (stream->ep == sinks[i].ep) { - uint16_t seq_num; - - seq_num = sinks[i].seq_num; - - if (IS_ENABLED(CONFIG_LIBLC3)) { - sinks[i].seq_num++; - } else { - sinks[i].seq_num += (AUDIO_DATA_TIMEOUT_US / - codec_configuration.qos.interval); - } - - return seq_num; - } - } - - printk("Could not find endpoint from stream %p\n", stream); - - return 0; -} - -#if defined(CONFIG_LIBLC3) - -#include "lc3.h" -#include "math.h" - -#define MAX_SAMPLE_RATE 48000 -#define MAX_FRAME_DURATION_US 10000 -#define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC) -#define AUDIO_VOLUME (INT16_MAX - 3000) /* codec does clipping above INT16_MAX - 3000 */ -#define AUDIO_TONE_FREQUENCY_HZ 400 - -static int16_t audio_buf[MAX_NUM_SAMPLES]; -static lc3_encoder_t lc3_encoder; -static lc3_encoder_mem_48k_t lc3_encoder_mem; -static int freq_hz; -static int frame_duration_us; -static int frame_duration_100us; -static int frames_per_sdu; -static int octets_per_frame; - -/** - * Use the math lib to generate a sine-wave using 16 bit samples into a buffer. - * - * @param buf Destination buffer - * @param length_us Length of the buffer in microseconds - * @param frequency_hz frequency in Hz - * @param sample_rate_hz sample-rate in Hz. - */ -static void fill_audio_buf_sin(int16_t *buf, int length_us, int frequency_hz, int sample_rate_hz) -{ - const int sine_period_samples = sample_rate_hz / frequency_hz; - const unsigned int num_samples = (length_us * sample_rate_hz) / USEC_PER_SEC; - const float step = 2 * 3.1415f / sine_period_samples; - - for (unsigned int i = 0; i < num_samples; i++) { - const float sample = sinf(i * step); - - buf[i] = (int16_t)(AUDIO_VOLUME * sample); - } -} - -static void lc3_audio_timer_timeout(struct k_work *work) -{ - /* For the first call-back we push multiple audio frames to the buffer to use the - * controller ISO buffer to handle jitter. - */ - const uint8_t prime_count = 2; - static int64_t start_time; - static int32_t sdu_cnt; - int32_t sdu_goal_cnt; - int64_t uptime, run_time_ms, run_time_100us; - - k_work_schedule(&audio_send_work, K_USEC(codec_configuration.qos.interval)); - - if (lc3_encoder == NULL) { - printk("LC3 encoder not setup, cannot encode data.\n"); - return; - } - - if (start_time == 0) { - /* Read start time and produce the number of frames needed to catch up with any - * inaccuracies in the timer. by calculating the number of frames we should - * have sent and compare to how many were actually sent. - */ - start_time = k_uptime_get(); - } - - uptime = k_uptime_get(); - run_time_ms = uptime - start_time; - - /* PDU count calculations done in 100us units to allow 7.5ms framelength in fixed-point */ - run_time_100us = run_time_ms * 10; - sdu_goal_cnt = run_time_100us / (frame_duration_100us * frames_per_sdu); - - /* Add primer value to ensure the controller do not run low on data due to jitter */ - sdu_goal_cnt += prime_count; - - printk("LC3 encode %d frames in %d SDUs\n", (sdu_goal_cnt - sdu_cnt) * frames_per_sdu, - (sdu_goal_cnt - sdu_cnt)); - - while (sdu_cnt < sdu_goal_cnt) { - const uint16_t tx_sdu_len = frames_per_sdu * octets_per_frame; - struct net_buf *buf; - uint8_t *net_buffer; - off_t offset = 0; - - buf = net_buf_alloc(&tx_pool, K_FOREVER); - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - - net_buffer = net_buf_tail(buf); - buf->len += tx_sdu_len; - - for (int i = 0; i < frames_per_sdu; i++) { - int lc3_ret; - - lc3_ret = lc3_encode(lc3_encoder, LC3_PCM_FORMAT_S16, - audio_buf, 1, octets_per_frame, - net_buffer + offset); - offset += octets_per_frame; - - if (lc3_ret == -1) { - printk("LC3 encoder failed - wrong parameters?: %d", - lc3_ret); - net_buf_unref(buf); - return; - } - } - - for (size_t i = 0U; i < configured_sink_stream_count; i++) { - struct bt_bap_stream *stream = &streams[i]; - struct net_buf *buf_to_send; - int ret; - - /* Clone the buffer if sending on more than 1 stream */ - if (i == configured_sink_stream_count - 1) { - buf_to_send = buf; - } else { - buf_to_send = net_buf_clone(buf, K_FOREVER); - } - - ret = bt_bap_stream_send(stream, buf_to_send, get_and_incr_seq_num(stream)); - if (ret < 0) { - printk(" Failed to send LC3 audio data on streams[%zu] (%d)\n", - i, ret); - net_buf_unref(buf_to_send); - } else { - printk(" TX LC3 l on streams[%zu]: %zu\n", - tx_sdu_len, i); - sdu_cnt++; - } - } - } -} - -static int init_lc3(void) -{ - const struct bt_audio_codec_cfg *codec_cfg = &codec_configuration.codec_cfg; - unsigned int num_samples; - int ret; - - ret = bt_audio_codec_cfg_get_freq(codec_cfg); - if (ret > 0) { - freq_hz = bt_audio_codec_cfg_freq_to_freq_hz(ret); - } else { - return ret; - } - - ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); - if (ret > 0) { - frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); - } - - octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); - frames_per_sdu = bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true); - octets_per_frame = bt_audio_codec_cfg_get_octets_per_frame(codec_cfg); - - if (freq_hz < 0) { - printk("Error: Codec frequency not set, cannot start codec."); - return -1; - } - - if (frame_duration_us < 0) { - printk("Error: Frame duration not set, cannot start codec."); - return -1; - } - - if (octets_per_frame < 0) { - printk("Error: Octets per frame not set, cannot start codec."); - return -1; - } - - frame_duration_100us = frame_duration_us / 100; - - - /* Fill audio buffer with Sine wave only once and repeat encoding the same tone frame */ - fill_audio_buf_sin(audio_buf, frame_duration_us, AUDIO_TONE_FREQUENCY_HZ, freq_hz); - - num_samples = ((frame_duration_us * freq_hz) / USEC_PER_SEC); - for (unsigned int i = 0; i < num_samples; i++) { - printk("%3i: %6i\n", i, audio_buf[i]); - } - - /* Create the encoder instance. This shall complete before stream_started() is called. */ - lc3_encoder = lc3_setup_encoder(frame_duration_us, - freq_hz, - 0, /* No resampling */ - &lc3_encoder_mem); - - if (lc3_encoder == NULL) { - printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n"); - return -1; - } - return 0; -} - -#else - -#define init_lc3(...) 0 - -/** - * @brief Send audio data on timeout - * - * This will send an increasing amount of audio data, starting from 1 octet. - * The data is just mock data, and does not actually represent any audio. - * - * First iteration : 0x00 - * Second iteration: 0x00 0x01 - * Third iteration : 0x00 0x01 0x02 - * - * And so on, until it wraps around the configured MTU (CONFIG_BT_ISO_TX_MTU) - * - * @param work Pointer to the work structure - */ -static void audio_timer_timeout(struct k_work *work) -{ - static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU]; - static bool data_initialized; - struct net_buf *buf; - static size_t len_to_send = 1; - - if (!data_initialized) { - /* TODO: Actually encode some audio data */ - for (int i = 0; i < ARRAY_SIZE(buf_data); i++) { - buf_data[i] = (uint8_t)i; - } - - data_initialized = true; - } - - buf = net_buf_alloc(&tx_pool, K_FOREVER); - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - net_buf_add_mem(buf, buf_data, len_to_send); - - /* We configured the sink streams to be first in `streams`, so that - * we can use `stream[i]` to select sink streams (i.e. streams with - * data going to the server) - */ - for (size_t i = 0U; i < configured_sink_stream_count; i++) { - struct bt_bap_stream *stream = &streams[i]; - struct net_buf *buf_to_send; - int ret; - - /* Clone the buffer if sending on more than 1 stream */ - if (i == configured_sink_stream_count - 1) { - buf_to_send = buf; - } else { - buf_to_send = net_buf_clone(buf, K_FOREVER); - } - - ret = bt_bap_stream_send(stream, buf_to_send, get_and_incr_seq_num(stream)); - if (ret < 0) { - printk("Failed to send audio data on streams[%zu]: (%d)\n", - i, ret); - net_buf_unref(buf_to_send); - } else { - printk("Sending mock data with len %zu on streams[%zu]\n", - len_to_send, i); - } - } - - k_work_schedule(&audio_send_work, K_USEC(AUDIO_DATA_TIMEOUT_US)); - - len_to_send++; - if (len_to_send > codec_configuration.qos.sdu) { - len_to_send = 1; - } -} - -#endif - -static void print_hex(const uint8_t *ptr, size_t len) -{ - while (len-- != 0) { - printk("%02x", *ptr++); - } -} - -static bool print_cb(struct bt_data *data, void *user_data) -{ - const char *str = (const char *)user_data; - - printk("%s: type 0x%02x value_len %u\n", str, data->type, data->data_len); - print_hex(data->data, data->data_len); - printk("\n"); - - return true; -} - -static void print_codec_cap(const struct bt_audio_codec_cap *codec_cap) -{ - printk("codec id 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cap->id, codec_cap->cid, - codec_cap->vid, codec_cap->data_len); - - if (codec_cap->id == BT_HCI_CODING_FORMAT_LC3) { - bt_audio_data_parse(codec_cap->data, codec_cap->data_len, print_cb, "data"); - } else { /* If not LC3, we cannot assume it's LTV */ - printk("data: "); - print_hex(codec_cap->data, codec_cap->data_len); - printk("\n"); - } - - bt_audio_data_parse(codec_cap->meta, codec_cap->meta_len, print_cb, "meta"); -} - -static bool check_audio_support_and_connect(struct bt_data *data, - void *user_data) -{ - struct net_buf_simple ascs_svc_data; - bt_addr_le_t *addr = user_data; - uint8_t announcement_type; - uint32_t audio_contexts; - const struct bt_uuid *uuid; - uint16_t uuid_val; - uint8_t meta_len; - size_t min_size; - int err; - - printk("[AD]: %u data_len %u\n", data->type, data->data_len); - - if (data->type != BT_DATA_SVC_DATA16) { - return true; /* Continue parsing to next AD data type */ - } - - if (data->data_len < sizeof(uuid_val)) { - printk("AD invalid size %u\n", data->data_len); - return true; /* Continue parsing to next AD data type */ - } - - net_buf_simple_init_with_data(&ascs_svc_data, (void *)data->data, - data->data_len); - - uuid_val = net_buf_simple_pull_le16(&ascs_svc_data); - uuid = BT_UUID_DECLARE_16(sys_le16_to_cpu(uuid_val)); - if (bt_uuid_cmp(uuid, BT_UUID_ASCS) != 0) { - /* We are looking for the ASCS service data */ - return true; /* Continue parsing to next AD data type */ - } - - min_size = sizeof(announcement_type) + sizeof(audio_contexts) + sizeof(meta_len); - if (ascs_svc_data.len < min_size) { - printk("AD invalid size %u\n", data->data_len); - return false; /* Stop parsing */ - } - - announcement_type = net_buf_simple_pull_u8(&ascs_svc_data); - audio_contexts = net_buf_simple_pull_le32(&ascs_svc_data); - meta_len = net_buf_simple_pull_u8(&ascs_svc_data); - - err = bt_le_scan_stop(); - if (err != 0) { - printk("Failed to stop scan: %d\n", err); - return false; /* Stop parsing */ - } - - printk("Audio server found with type %u, contexts 0x%08x and meta_len %u; connecting\n", - announcement_type, audio_contexts, meta_len); - - err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN, - BT_LE_CONN_PARAM_DEFAULT, - &default_conn); - if (err != 0) { - printk("Create conn to failed (%u)\n", err); - start_scan(); - } - - return false; /* Stop parsing */ -} - -static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type, - struct net_buf_simple *ad) -{ - char addr_str[BT_ADDR_LE_STR_LEN]; - - if (default_conn != NULL) { - /* Already connected */ - return; - } - - /* We're only interested in connectable events */ - if (type != BT_GAP_ADV_TYPE_ADV_IND && - type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND && - type != BT_GAP_ADV_TYPE_EXT_ADV) { - return; - } - - (void)bt_addr_le_to_str(addr, addr_str, sizeof(addr_str)); - printk("Device found: %s (RSSI %d)\n", addr_str, rssi); - - /* connect only to devices in close proximity */ - if (rssi < -50) { - return; - } - - bt_data_parse(ad, check_audio_support_and_connect, (void *)addr); -} - -static void start_scan(void) -{ - int err; - - /* This demo doesn't require active scan */ - err = bt_le_scan_start(BT_LE_SCAN_PASSIVE, device_found); - if (err != 0) { - printk("Scanning failed to start (err %d)\n", err); - return; - } - - printk("Scanning successfully started\n"); -} - -static void stream_configured(struct bt_bap_stream *stream, - const struct bt_audio_codec_qos_pref *pref) -{ - printk("Audio Stream %p configured\n", stream); - - k_sem_give(&sem_stream_configured); -} - -static void stream_qos_set(struct bt_bap_stream *stream) -{ - printk("Audio Stream %p QoS set\n", stream); - - k_sem_give(&sem_stream_qos); -} - -static void stream_enabled(struct bt_bap_stream *stream) -{ - printk("Audio Stream %p enabled\n", stream); - - k_sem_give(&sem_stream_enabled); -} - -static void stream_started(struct bt_bap_stream *stream) -{ - printk("Audio Stream %p started\n", stream); - - /* Reset sequence number for sinks */ - for (size_t i = 0U; i < configured_sink_stream_count; i++) { - if (stream->ep == sinks[i].ep) { - sinks[i].seq_num = 0U; - break; - } - } - - k_sem_give(&sem_stream_started); -} - -static void stream_metadata_updated(struct bt_bap_stream *stream) -{ - printk("Audio Stream %p metadata updated\n", stream); -} - -static void stream_disabled(struct bt_bap_stream *stream) -{ - printk("Audio Stream %p disabled\n", stream); -} - -static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason) -{ - printk("Audio Stream %p stopped with reason 0x%02X\n", stream, reason); - - /* Stop send timer */ - k_work_cancel_delayable(&audio_send_work); -} - -static void stream_released(struct bt_bap_stream *stream) -{ - printk("Audio Stream %p released\n", stream); -} - -static void stream_recv(struct bt_bap_stream *stream, - const struct bt_iso_recv_info *info, - struct net_buf *buf) -{ - if (info->flags & BT_ISO_FLAGS_VALID) { - unicast_audio_recv_ctr++; - printk("Incoming audio on stream %p len %u (%"PRIu64")\n", stream, buf->len, - unicast_audio_recv_ctr); - } -} - -static struct bt_bap_stream_ops stream_ops = { - .configured = stream_configured, - .qos_set = stream_qos_set, - .enabled = stream_enabled, - .started = stream_started, - .metadata_updated = stream_metadata_updated, - .disabled = stream_disabled, - .stopped = stream_stopped, - .released = stream_released, - .recv = stream_recv -}; - -static void add_remote_source(struct bt_bap_ep *ep) -{ - for (size_t i = 0U; i < ARRAY_SIZE(sources); i++) { - if (sources[i] == NULL) { - printk("Source #%zu: ep %p\n", i, ep); - sources[i] = ep; - return; - } - } - - printk("Could not add source ep\n"); -} - -static void add_remote_sink(struct bt_bap_ep *ep) -{ - for (size_t i = 0U; i < ARRAY_SIZE(sinks); i++) { - if (sinks[i].ep == NULL) { - printk("Sink #%zu: ep %p\n", i, ep); - sinks[i].ep = ep; - return; - } - } - - printk("Could not add sink ep\n"); -} - -static void print_remote_codec_cap(const struct bt_audio_codec_cap *codec_cap, - enum bt_audio_dir dir) -{ - printk("codec_cap %p dir 0x%02x\n", codec_cap, dir); - - print_codec_cap(codec_cap); -} - -static void discover_sinks_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) -{ - if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) { - printk("Discovery failed: %d\n", err); - return; - } - - if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) { - printk("Discover sinks completed without finding any sink ASEs\n"); - } else { - printk("Discover sinks complete: err %d\n", err); - } - - k_sem_give(&sem_sinks_discovered); -} - -static void discover_sources_cb(struct bt_conn *conn, int err, enum bt_audio_dir dir) -{ - if (err != 0 && err != BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) { - printk("Discovery failed: %d\n", err); - return; - } - - if (err == BT_ATT_ERR_ATTRIBUTE_NOT_FOUND) { - printk("Discover sinks completed without finding any source ASEs\n"); - } else { - printk("Discover sources complete: err %d\n", err); - } - - k_sem_give(&sem_sources_discovered); -} - -static void connected(struct bt_conn *conn, uint8_t err) -{ - char addr[BT_ADDR_LE_STR_LEN]; - - (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - - if (err != 0) { - printk("Failed to connect to %s (%u)\n", addr, err); - - bt_conn_unref(default_conn); - default_conn = NULL; - - start_scan(); - return; - } - - if (conn != default_conn) { - return; - } - - printk("Connected: %s\n", addr); - k_sem_give(&sem_connected); -} - -static void disconnected(struct bt_conn *conn, uint8_t reason) -{ - char addr[BT_ADDR_LE_STR_LEN]; - - if (conn != default_conn) { - return; - } - - (void)bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - - printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); - - bt_conn_unref(default_conn); - default_conn = NULL; - - k_sem_give(&sem_disconnected); -} - -static void security_changed_cb(struct bt_conn *conn, bt_security_t level, - enum bt_security_err err) -{ - if (err == 0) { - k_sem_give(&sem_security_updated); - } else { - printk("Failed to set security level: %u", err); - } -} - -BT_CONN_CB_DEFINE(conn_callbacks) = { - .connected = connected, - .disconnected = disconnected, - .security_changed = security_changed_cb -}; - -static void att_mtu_updated(struct bt_conn *conn, uint16_t tx, uint16_t rx) -{ - printk("MTU exchanged: %u/%u\n", tx, rx); - k_sem_give(&sem_mtu_exchanged); -} - -static struct bt_gatt_cb gatt_callbacks = { - .att_mtu_updated = att_mtu_updated, -}; - -static void unicast_client_location_cb(struct bt_conn *conn, - enum bt_audio_dir dir, - enum bt_audio_location loc) -{ - printk("dir %u loc %X\n", dir, loc); -} - -static void available_contexts_cb(struct bt_conn *conn, - enum bt_audio_context snk_ctx, - enum bt_audio_context src_ctx) -{ - printk("snk ctx %u src ctx %u\n", snk_ctx, src_ctx); -} - -static void pac_record_cb(struct bt_conn *conn, enum bt_audio_dir dir, - const struct bt_audio_codec_cap *codec_cap) -{ - print_remote_codec_cap(codec_cap, dir); -} - -static void endpoint_cb(struct bt_conn *conn, enum bt_audio_dir dir, struct bt_bap_ep *ep) -{ - if (dir == BT_AUDIO_DIR_SOURCE) { - add_remote_source(ep); - } else if (dir == BT_AUDIO_DIR_SINK) { - add_remote_sink(ep); - } -} - -static struct bt_bap_unicast_client_cb unicast_client_cbs = { - .location = unicast_client_location_cb, - .available_contexts = available_contexts_cb, - .pac_record = pac_record_cb, - .endpoint = endpoint_cb, -}; - -static int init(void) -{ - int err; - - err = bt_enable(NULL); - if (err != 0) { - printk("Bluetooth enable failed (err %d)\n", err); - return err; - } - - for (size_t i = 0; i < ARRAY_SIZE(streams); i++) { - streams[i].ops = &stream_ops; - } - - bt_gatt_cb_register(&gatt_callbacks); - -#if defined(CONFIG_LIBLC3) - k_work_init_delayable(&audio_send_work, lc3_audio_timer_timeout); -#else - k_work_init_delayable(&audio_send_work, audio_timer_timeout); -#endif - - return 0; -} - -static int scan_and_connect(void) -{ - int err; - - start_scan(); - - err = k_sem_take(&sem_connected, K_FOREVER); - if (err != 0) { - printk("failed to take sem_connected (err %d)\n", err); - return err; - } - - err = k_sem_take(&sem_mtu_exchanged, K_FOREVER); - if (err != 0) { - printk("failed to take sem_mtu_exchanged (err %d)\n", err); - return err; - } - - err = bt_conn_set_security(default_conn, BT_SECURITY_L2); - if (err != 0) { - printk("failed to set security (err %d)\n", err); - return err; - } - - err = k_sem_take(&sem_security_updated, K_FOREVER); - if (err != 0) { - printk("failed to take sem_security_updated (err %d)\n", err); - return err; - } - - return 0; -} - -static int discover_sinks(void) -{ - int err; - - unicast_client_cbs.discover = discover_sinks_cb; - - err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SINK); - if (err != 0) { - printk("Failed to discover sinks: %d\n", err); - return err; - } - - err = k_sem_take(&sem_sinks_discovered, K_FOREVER); - if (err != 0) { - printk("failed to take sem_sinks_discovered (err %d)\n", err); - return err; - } - - return 0; -} - -static int discover_sources(void) -{ - int err; - - unicast_client_cbs.discover = discover_sources_cb; - - err = bt_bap_unicast_client_discover(default_conn, BT_AUDIO_DIR_SOURCE); - if (err != 0) { - printk("Failed to discover sources: %d\n", err); - return err; - } - - err = k_sem_take(&sem_sources_discovered, K_FOREVER); - if (err != 0) { - printk("failed to take sem_sources_discovered (err %d)\n", err); - return err; - } - - return 0; -} - -static int configure_stream(struct bt_bap_stream *stream, struct bt_bap_ep *ep) -{ - int err; - - err = bt_bap_stream_config(default_conn, stream, ep, &codec_configuration.codec_cfg); - if (err != 0) { - return err; - } - - err = k_sem_take(&sem_stream_configured, K_FOREVER); - if (err != 0) { - printk("failed to take sem_stream_configured (err %d)\n", err); - return err; - } - - return 0; -} - -static int configure_streams(void) -{ - int err; - - for (size_t i = 0; i < ARRAY_SIZE(sinks); i++) { - struct bt_bap_ep *ep = sinks[i].ep; - struct bt_bap_stream *stream = &streams[i]; - - if (ep == NULL) { - continue; - } - - err = configure_stream(stream, ep); - if (err != 0) { - printk("Could not configure sink stream[%zu]: %d\n", - i, err); - return err; - } - - printk("Configured sink stream[%zu]\n", i); - configured_sink_stream_count++; - } - - for (size_t i = 0; i < ARRAY_SIZE(sources); i++) { - struct bt_bap_ep *ep = sources[i]; - struct bt_bap_stream *stream = &streams[i + configured_sink_stream_count]; - - if (ep == NULL) { - continue; - } - - err = configure_stream(stream, ep); - if (err != 0) { - printk("Could not configure source stream[%zu]: %d\n", - i, err); - return err; - } - - printk("Configured source stream[%zu]\n", i); - configured_source_stream_count++; - } - - return 0; -} - -static int create_group(void) -{ - const size_t params_count = MAX(configured_sink_stream_count, - configured_source_stream_count); - struct bt_bap_unicast_group_stream_pair_param pair_params[params_count]; - struct bt_bap_unicast_group_stream_param stream_params[configured_stream_count]; - struct bt_bap_unicast_group_param param; - int err; - - for (size_t i = 0U; i < configured_stream_count; i++) { - stream_params[i].stream = &streams[i]; - stream_params[i].qos = &codec_configuration.qos; - } - - for (size_t i = 0U; i < params_count; i++) { - if (i < configured_sink_stream_count) { - pair_params[i].tx_param = &stream_params[i]; - } else { - pair_params[i].tx_param = NULL; - } - - if (i < configured_source_stream_count) { - pair_params[i].rx_param = &stream_params[i + configured_sink_stream_count]; - } else { - pair_params[i].rx_param = NULL; - } - } - - param.params = pair_params; - param.params_count = params_count; - param.packing = BT_ISO_PACKING_SEQUENTIAL; - - err = bt_bap_unicast_group_create(¶m, &unicast_group); - if (err != 0) { - printk("Could not create unicast group (err %d)\n", err); - return err; - } - - return 0; -} - -static int delete_group(void) -{ - int err; - - err = bt_bap_unicast_group_delete(unicast_group); - if (err != 0) { - printk("Could not create unicast group (err %d)\n", err); - return err; - } - - return 0; -} - -static int set_stream_qos(void) -{ - int err; - - err = bt_bap_stream_qos(default_conn, unicast_group); - if (err != 0) { - printk("Unable to setup QoS: %d\n", err); - return err; - } - - for (size_t i = 0U; i < configured_stream_count; i++) { - printk("QoS: waiting for %zu streams\n", configured_stream_count); - err = k_sem_take(&sem_stream_qos, K_FOREVER); - if (err != 0) { - printk("failed to take sem_stream_qos (err %d)\n", err); - return err; - } - } - - return 0; -} - -static int enable_streams(void) -{ - if (IS_ENABLED(CONFIG_LIBLC3)) { - int err = init_lc3(); - - if (err != 0) { - return err; - } - } - - for (size_t i = 0U; i < configured_stream_count; i++) { - int err; - - err = bt_bap_stream_enable(&streams[i], codec_configuration.codec_cfg.meta, - codec_configuration.codec_cfg.meta_len); - if (err != 0) { - printk("Unable to enable stream: %d\n", err); - return err; - } - - err = k_sem_take(&sem_stream_enabled, K_FOREVER); - if (err != 0) { - printk("failed to take sem_stream_enabled (err %d)\n", err); - return err; - } - } - - return 0; -} - -static int start_streams(void) -{ - for (size_t i = 0U; i < configured_stream_count; i++) { - int err; - - err = bt_bap_stream_start(&streams[i]); - if (err != 0) { - printk("Unable to start stream: %d\n", err); - return err; - } - - err = k_sem_take(&sem_stream_started, K_FOREVER); - if (err != 0) { - printk("failed to take sem_stream_started (err %d)\n", err); - return err; - } - } - - return 0; -} - -static void reset_data(void) -{ - k_sem_reset(&sem_connected); - k_sem_reset(&sem_disconnected); - k_sem_reset(&sem_mtu_exchanged); - k_sem_reset(&sem_security_updated); - k_sem_reset(&sem_sinks_discovered); - k_sem_reset(&sem_sources_discovered); - k_sem_reset(&sem_stream_configured); - k_sem_reset(&sem_stream_qos); - k_sem_reset(&sem_stream_enabled); - k_sem_reset(&sem_stream_started); - - configured_sink_stream_count = 0; - configured_source_stream_count = 0; - memset(sinks, 0, sizeof(sinks)); - memset(sources, 0, sizeof(sources)); -} - -int main(void) -{ - int err; - - printk("Initializing\n"); - err = init(); - if (err != 0) { - return 0; - } - printk("Initialized\n"); - - err = bt_bap_unicast_client_register_cb(&unicast_client_cbs); - if (err != 0) { - printk("Failed to register client callbacks: %d", err); - return 0; - } - - while (true) { - reset_data(); - - printk("Waiting for connection\n"); - err = scan_and_connect(); - if (err != 0) { - return 0; - } - printk("Connected\n"); - - printk("Discovering sinks\n"); - err = discover_sinks(); - if (err != 0) { - return 0; - } - printk("Sinks discovered\n"); - - printk("Discovering sources\n"); - err = discover_sources(); - if (err != 0) { - return 0; - } - printk("Sources discovered\n"); - - printk("Configuring streams\n"); - err = configure_streams(); - if (err != 0) { - return 0; - } - - if (configured_stream_count == 0U) { - printk("No streams were configured\n"); - return 0; - } - - printk("Creating unicast group\n"); - err = create_group(); - if (err != 0) { - return 0; - } - printk("Unicast group created\n"); - - printk("Setting stream QoS\n"); - err = set_stream_qos(); - if (err != 0) { - return 0; - } - printk("Stream QoS Set\n"); - - printk("Enabling streams\n"); - err = enable_streams(); - if (err != 0) { - return 0; - } - printk("Streams enabled\n"); - - printk("Starting streams\n"); - err = start_streams(); - if (err != 0) { - return 0; - } - printk("Streams started\n"); - - if (CONFIG_BT_BAP_UNICAST_CLIENT_ASE_SRC_COUNT > 0) { - /* Start send timer */ - k_work_schedule(&audio_send_work, K_MSEC(0)); - } - - /* Wait for disconnect */ - err = k_sem_take(&sem_disconnected, K_FOREVER); - if (err != 0) { - printk("failed to take sem_disconnected (err %d)\n", err); - return 0; - } - - printk("Deleting group\n"); - err = delete_group(); - if (err != 0) { - return 0; - } - printk("Group deleted\n"); - } -} diff --git a/samples/bluetooth/unicast_audio_server/CMakeLists.txt b/samples/bluetooth/unicast_audio_server/CMakeLists.txt deleted file mode 100644 index 2b20af75d5689..0000000000000 --- a/samples/bluetooth/unicast_audio_server/CMakeLists.txt +++ /dev/null @@ -1,11 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(unicast_audio_server) - -target_sources(app PRIVATE - src/main.c -) - -zephyr_library_include_directories(${ZEPHYR_BASE}/samples/bluetooth) diff --git a/samples/bluetooth/unicast_audio_server/README.rst b/samples/bluetooth/unicast_audio_server/README.rst deleted file mode 100644 index b3f40dfa82088..0000000000000 --- a/samples/bluetooth/unicast_audio_server/README.rst +++ /dev/null @@ -1,83 +0,0 @@ -.. _bluetooth_unicast_audio_server: - -Bluetooth: Unicast Audio Server -############################### - -Overview -******** - -Application demonstrating the LE Audio unicast server functionality. -Starts advertising and awaits connection from a LE Audio unicast client. - -This sample can be found under -:zephyr_file:`samples/bluetooth/unicast_audio_server` in the Zephyr tree. - -Check the :ref:`bluetooth samples section ` for general information. - -Requirements -************ - -* BlueZ running on the host, or -* A board with Bluetooth Low Energy 5.2 support - -Building and Running -******************** - -When building targeting an nrf52 series board with the Zephyr Bluetooth Controller, -use `-DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf` to enable the required ISO -feature support. - -Building for an nrf52840dk --------------------------- - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_server/ - :board: nrf52840dk/nrf52840 - :goals: build - :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf - -Building for an nrf5340dk -------------------------- - -You can build both the application core image and an appropriate controller image for the network -core with: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_server/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild - -If you prefer to only build the application core image, you can do so by doing instead: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_server/ - :board: nrf5340dk/nrf5340/cpuapp - :goals: build - -In that case you can pair this application core image with the -:ref:`hci_ipc sample ` -:zephyr_file:`samples/bluetooth/hci_ipc/nrf5340_cpunet_iso-bt_ll_sw_split.conf` configuration. - -Building for a simulated nrf52_bsim ------------------------------------ - -Similarly to how you would for real HW, you can do: - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_server/ - :board: nrf52_bsim - :goals: build - :gen-args: -DOVERLAY_CONFIG=overlay-bt_ll_sw_split.conf - -Note this will produce a Linux executable in `./build/zephyr/zephyr.exe`. -For more information, check :ref:`this board documentation `. - -Building for a simulated nrf5340bsim ------------------------------------- - -.. zephyr-app-commands:: - :zephyr-app: samples/bluetooth/unicast_audio_server/ - :board: nrf5340bsim/nrf5340/cpuapp - :goals: build - :west-args: --sysbuild diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf52840dk_nrf52840.conf b/samples/bluetooth/unicast_audio_server/boards/nrf52840dk_nrf52840.conf deleted file mode 100644 index 3c7c698c48b8c..0000000000000 --- a/samples/bluetooth/unicast_audio_server/boards/nrf52840dk_nrf52840.conf +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG_BT_CTLR_PERIPHERAL_ISO=y - -# Supports the highest SDU size required by any BAP LC3 presets (155) -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 diff --git a/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf b/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf deleted file mode 100644 index 8d48d5e1c2072..0000000000000 --- a/samples/bluetooth/unicast_audio_server/boards/nrf5340_audio_dk_nrf5340_cpuapp.conf +++ /dev/null @@ -1,6 +0,0 @@ -# For LC3 the following configs are needed -CONFIG_FPU=y -CONFIG_LIBLC3=y -# The LC3 codec uses a large amount of stack. This app runs the codec in the work-queue, hence -# inctease stack size for that thread. -CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=4096 diff --git a/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf b/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf deleted file mode 100644 index 1499e379d4e22..0000000000000 --- a/samples/bluetooth/unicast_audio_server/overlay-bt_ll_sw_split.conf +++ /dev/null @@ -1,10 +0,0 @@ -CONFIG_BT_LL_SW_SPLIT=y -CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191 -CONFIG_BT_CTLR_ISO_TX_BUFFERS=2 -CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=155 -CONFIG_BT_CTLR_ISOAL_SOURCES=1 -CONFIG_BT_CTLR_ISOAL_SINKS=2 - -# Use the below if the sample is sending stale packet sequence number -# CONFIG_BT_CTLR_ADVANCED_FEATURES=y -# CONFIG_BT_CTLR_ISOAL_SN_STRICT=n diff --git a/samples/bluetooth/unicast_audio_server/src/main.c b/samples/bluetooth/unicast_audio_server/src/main.c deleted file mode 100644 index db2a76fbab60f..0000000000000 --- a/samples/bluetooth/unicast_audio_server/src/main.c +++ /dev/null @@ -1,794 +0,0 @@ -/* - * Copyright (c) 2021-2023 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#define AVAILABLE_SINK_CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \ - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ - BT_AUDIO_CONTEXT_TYPE_MEDIA | \ - BT_AUDIO_CONTEXT_TYPE_GAME | \ - BT_AUDIO_CONTEXT_TYPE_INSTRUCTIONAL) - -#define AVAILABLE_SOURCE_CONTEXT (BT_AUDIO_CONTEXT_TYPE_UNSPECIFIED | \ - BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | \ - BT_AUDIO_CONTEXT_TYPE_MEDIA | \ - BT_AUDIO_CONTEXT_TYPE_GAME) - -NET_BUF_POOL_FIXED_DEFINE(tx_pool, CONFIG_BT_ASCS_ASE_SRC_COUNT, - BT_ISO_SDU_BUF_SIZE(CONFIG_BT_ISO_TX_MTU), - CONFIG_BT_CONN_TX_USER_DATA_SIZE, NULL); - -static const struct bt_audio_codec_cap lc3_codec_cap = BT_AUDIO_CODEC_CAP_LC3( - BT_AUDIO_CODEC_CAP_FREQ_ANY, BT_AUDIO_CODEC_CAP_DURATION_10, - BT_AUDIO_CODEC_CAP_CHAN_COUNT_SUPPORT(1), 40u, 120u, 1u, - (BT_AUDIO_CONTEXT_TYPE_CONVERSATIONAL | BT_AUDIO_CONTEXT_TYPE_MEDIA)); - -static struct bt_conn *default_conn; -static struct k_work_delayable audio_send_work; -static struct bt_bap_stream sink_streams[CONFIG_BT_ASCS_ASE_SNK_COUNT]; -static struct audio_source { - struct bt_bap_stream stream; - uint16_t seq_num; - uint16_t max_sdu; - size_t len_to_send; -} source_streams[CONFIG_BT_ASCS_ASE_SRC_COUNT]; -static size_t configured_source_stream_count; - -static const struct bt_audio_codec_qos_pref qos_pref = - BT_AUDIO_CODEC_QOS_PREF(true, BT_GAP_LE_PHY_2M, 0x02, 10, 40000, 40000, 40000, 40000); - -static K_SEM_DEFINE(sem_disconnected, 0, 1); - -static uint8_t unicast_server_addata[] = { - BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL), /* ASCS UUID */ - BT_AUDIO_UNICAST_ANNOUNCEMENT_TARGETED, /* Target Announcement */ - BT_BYTES_LIST_LE16(AVAILABLE_SINK_CONTEXT), - BT_BYTES_LIST_LE16(AVAILABLE_SOURCE_CONTEXT), - 0x00, /* Metadata length */ -}; - -/* TODO: Expand with BAP data */ -static const struct bt_data ad[] = { - BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)), - BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_ASCS_VAL)), - BT_DATA(BT_DATA_SVC_DATA16, unicast_server_addata, ARRAY_SIZE(unicast_server_addata)), - BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1), -}; - -#define AUDIO_DATA_TIMEOUT_US 1000000UL /* Send data every 1 second */ -#define SDU_INTERVAL_US 10000UL /* 10 ms SDU interval */ - -static uint16_t get_and_incr_seq_num(const struct bt_bap_stream *stream) -{ - for (size_t i = 0U; i < configured_source_stream_count; i++) { - if (stream == &source_streams[i].stream) { - uint16_t seq_num; - - seq_num = source_streams[i].seq_num; - - if (IS_ENABLED(CONFIG_LIBLC3)) { - source_streams[i].seq_num++; - } else { - source_streams[i].seq_num += (AUDIO_DATA_TIMEOUT_US / - SDU_INTERVAL_US); - } - - return seq_num; - } - } - - printk("Could not find endpoint from stream %p\n", stream); - - return 0; -} - -#if defined(CONFIG_LIBLC3) - -#include "lc3.h" - -#define MAX_SAMPLE_RATE 48000 -#define MAX_FRAME_DURATION_US 10000 -#define MAX_NUM_SAMPLES ((MAX_FRAME_DURATION_US * MAX_SAMPLE_RATE) / USEC_PER_SEC) - -static int16_t audio_buf[MAX_NUM_SAMPLES]; -static lc3_decoder_t lc3_decoder; -static lc3_decoder_mem_48k_t lc3_decoder_mem; -static int frames_per_sdu; - -#endif - -void print_hex(const uint8_t *ptr, size_t len) -{ - while (len-- != 0) { - printk("%02x", *ptr++); - } -} - -static bool print_cb(struct bt_data *data, void *user_data) -{ - const char *str = (const char *)user_data; - - printk("%s: type 0x%02x value_len %u\n", str, data->type, data->data_len); - print_hex(data->data, data->data_len); - printk("\n"); - - return true; -} - -static void print_codec_cfg(const struct bt_audio_codec_cfg *codec_cfg) -{ - printk("codec_cfg 0x%02x cid 0x%04x vid 0x%04x count %u\n", codec_cfg->id, codec_cfg->cid, - codec_cfg->vid, codec_cfg->data_len); - - if (codec_cfg->id == BT_HCI_CODING_FORMAT_LC3) { - enum bt_audio_location chan_allocation; - int ret; - - /* LC3 uses the generic LTV format - other codecs might do as well */ - - bt_audio_data_parse(codec_cfg->data, codec_cfg->data_len, print_cb, "data"); - - ret = bt_audio_codec_cfg_get_freq(codec_cfg); - if (ret > 0) { - printk(" Frequency: %d Hz\n", bt_audio_codec_cfg_freq_to_freq_hz(ret)); - } - - ret = bt_audio_codec_cfg_get_frame_dur(codec_cfg); - if (ret > 0) { - printk(" Frame Duration: %d us\n", - bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret)); - } - - if (bt_audio_codec_cfg_get_chan_allocation(codec_cfg, &chan_allocation) == 0) { - printk(" Channel allocation: 0x%x\n", chan_allocation); - } - - printk(" Octets per frame: %d (negative means value not pressent)\n", - bt_audio_codec_cfg_get_octets_per_frame(codec_cfg)); - printk(" Frames per SDU: %d\n", - bt_audio_codec_cfg_get_frame_blocks_per_sdu(codec_cfg, true)); - } else { - print_hex(codec_cfg->data, codec_cfg->data_len); - } - - bt_audio_data_parse(codec_cfg->meta, codec_cfg->meta_len, print_cb, "meta"); -} - -static void print_qos(const struct bt_audio_codec_qos *qos) -{ - printk("QoS: interval %u framing 0x%02x phy 0x%02x sdu %u " - "rtn %u latency %u pd %u\n", - qos->interval, qos->framing, qos->phy, qos->sdu, - qos->rtn, qos->latency, qos->pd); -} - -/** - * @brief Send audio data on timeout - * - * This will send an increasing amount of audio data, starting from 1 octet. - * The data is just mock data, and does not actually represent any audio. - * - * First iteration : 0x00 - * Second iteration: 0x00 0x01 - * Third iteration : 0x00 0x01 0x02 - * - * And so on, until it wraps around the configured MTU (CONFIG_BT_ISO_TX_MTU) - * - * @param work Pointer to the work structure - */ -static void audio_timer_timeout(struct k_work *work) -{ - int ret; - static uint8_t buf_data[CONFIG_BT_ISO_TX_MTU]; - static bool data_initialized; - struct net_buf *buf; - - if (!data_initialized) { - /* TODO: Actually encode some audio data */ - for (size_t i = 0U; i < ARRAY_SIZE(buf_data); i++) { - buf_data[i] = (uint8_t)i; - } - - data_initialized = true; - } - - /* We configured the sink streams to be first in `streams`, so that - * we can use `stream[i]` to select sink streams (i.e. streams with - * data going to the server) - */ - for (size_t i = 0; i < configured_source_stream_count; i++) { - struct bt_bap_stream *stream = &source_streams[i].stream; - - buf = net_buf_alloc(&tx_pool, K_FOREVER); - net_buf_reserve(buf, BT_ISO_CHAN_SEND_RESERVE); - - net_buf_add_mem(buf, buf_data, ++source_streams[i].len_to_send); - - ret = bt_bap_stream_send(stream, buf, get_and_incr_seq_num(stream)); - if (ret < 0) { - printk("Failed to send audio data on streams[%zu] (%p): (%d)\n", - i, stream, ret); - net_buf_unref(buf); - } else { - printk("Sending mock data with len %zu on streams[%zu] (%p)\n", - source_streams[i].len_to_send, i, stream); - } - - if (source_streams[i].len_to_send >= source_streams[i].max_sdu) { - source_streams[i].len_to_send = 0; - } - } - -#if defined(CONFIG_LIBLC3) - k_work_schedule(&audio_send_work, K_USEC(MAX_FRAME_DURATION_US)); -#else - k_work_schedule(&audio_send_work, K_USEC(AUDIO_DATA_TIMEOUT_US)); -#endif -} - -static enum bt_audio_dir stream_dir(const struct bt_bap_stream *stream) -{ - for (size_t i = 0U; i < ARRAY_SIZE(source_streams); i++) { - if (stream == &source_streams[i].stream) { - return BT_AUDIO_DIR_SOURCE; - } - } - - for (size_t i = 0U; i < ARRAY_SIZE(sink_streams); i++) { - if (stream == &sink_streams[i]) { - return BT_AUDIO_DIR_SINK; - } - } - - __ASSERT(false, "Invalid stream %p", stream); - return 0; -} - -static struct bt_bap_stream *stream_alloc(enum bt_audio_dir dir) -{ - if (dir == BT_AUDIO_DIR_SOURCE) { - for (size_t i = 0; i < ARRAY_SIZE(source_streams); i++) { - struct bt_bap_stream *stream = &source_streams[i].stream; - - if (!stream->conn) { - return stream; - } - } - } else { - for (size_t i = 0; i < ARRAY_SIZE(sink_streams); i++) { - struct bt_bap_stream *stream = &sink_streams[i]; - - if (!stream->conn) { - return stream; - } - } - } - - return NULL; -} - -static int lc3_config(struct bt_conn *conn, const struct bt_bap_ep *ep, enum bt_audio_dir dir, - const struct bt_audio_codec_cfg *codec_cfg, struct bt_bap_stream **stream, - struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) -{ - printk("ASE Codec Config: conn %p ep %p dir %u\n", conn, ep, dir); - - print_codec_cfg(codec_cfg); - - *stream = stream_alloc(dir); - if (*stream == NULL) { - printk("No streams available\n"); - *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_NO_MEM, BT_BAP_ASCS_REASON_NONE); - - return -ENOMEM; - } - - printk("ASE Codec Config stream %p\n", *stream); - - if (dir == BT_AUDIO_DIR_SOURCE) { - configured_source_stream_count++; - } - - *pref = qos_pref; - -#if defined(CONFIG_LIBLC3) - /* Nothing to free as static memory is used */ - lc3_decoder = NULL; -#endif - - return 0; -} - -static int lc3_reconfig(struct bt_bap_stream *stream, enum bt_audio_dir dir, - const struct bt_audio_codec_cfg *codec_cfg, - struct bt_audio_codec_qos_pref *const pref, struct bt_bap_ascs_rsp *rsp) -{ - printk("ASE Codec Reconfig: stream %p\n", stream); - - print_codec_cfg(codec_cfg); - -#if defined(CONFIG_LIBLC3) - /* Nothing to free as static memory is used */ - lc3_decoder = NULL; -#endif - - *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_UNSUPPORTED, BT_BAP_ASCS_REASON_NONE); - - /* We only support one QoS at the moment, reject changes */ - return -ENOEXEC; -} - -static int lc3_qos(struct bt_bap_stream *stream, const struct bt_audio_codec_qos *qos, - struct bt_bap_ascs_rsp *rsp) -{ - printk("QoS: stream %p qos %p\n", stream, qos); - - print_qos(qos); - - for (size_t i = 0U; i < configured_source_stream_count; i++) { - if (stream == &source_streams[i].stream) { - source_streams[i].max_sdu = qos->sdu; - break; - } - } - - return 0; -} - -static int lc3_enable(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len, - struct bt_bap_ascs_rsp *rsp) -{ - printk("Enable: stream %p meta_len %zu\n", stream, meta_len); - -#if defined(CONFIG_LIBLC3) - { - int frame_duration_us; - int freq; - int ret; - - ret = bt_audio_codec_cfg_get_freq(stream->codec_cfg); - if (ret > 0) { - freq = bt_audio_codec_cfg_freq_to_freq_hz(ret); - } else { - printk("Error: Codec frequency not set, cannot start codec."); - *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID, - BT_BAP_ASCS_REASON_CODEC_DATA); - return ret; - } - - ret = bt_audio_codec_cfg_get_frame_dur(stream->codec_cfg); - if (ret > 0) { - frame_duration_us = bt_audio_codec_cfg_frame_dur_to_frame_dur_us(ret); - } else { - printk("Error: Frame duration not set, cannot start codec."); - *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID, - BT_BAP_ASCS_REASON_CODEC_DATA); - return ret; - } - - frames_per_sdu = - bt_audio_codec_cfg_get_frame_blocks_per_sdu(stream->codec_cfg, true); - - lc3_decoder = lc3_setup_decoder(frame_duration_us, - freq, - 0, /* No resampling */ - &lc3_decoder_mem); - - if (lc3_decoder == NULL) { - printk("ERROR: Failed to setup LC3 encoder - wrong parameters?\n"); - *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_CONF_INVALID, - BT_BAP_ASCS_REASON_CODEC_DATA); - return -1; - } - } -#endif - - return 0; -} - -static int lc3_start(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) -{ - printk("Start: stream %p\n", stream); - - for (size_t i = 0U; i < configured_source_stream_count; i++) { - if (stream == &source_streams[i].stream) { - source_streams[i].seq_num = 0U; - source_streams[i].len_to_send = 0U; - break; - } - } - - if (configured_source_stream_count > 0 && - !k_work_delayable_is_pending(&audio_send_work)) { - - /* Start send timer */ - k_work_schedule(&audio_send_work, K_MSEC(0)); - } - - return 0; -} - -static bool data_func_cb(struct bt_data *data, void *user_data) -{ - struct bt_bap_ascs_rsp *rsp = (struct bt_bap_ascs_rsp *)user_data; - - if (!BT_AUDIO_METADATA_TYPE_IS_KNOWN(data->type)) { - printk("Invalid metadata type %u or length %u\n", data->type, data->data_len); - *rsp = BT_BAP_ASCS_RSP(BT_BAP_ASCS_RSP_CODE_METADATA_REJECTED, data->type); - - return -EINVAL; - } - - return true; -} - -static int lc3_metadata(struct bt_bap_stream *stream, const uint8_t meta[], size_t meta_len, - struct bt_bap_ascs_rsp *rsp) -{ - printk("Metadata: stream %p meta_len %zu\n", stream, meta_len); - - return bt_audio_data_parse(meta, meta_len, data_func_cb, rsp); -} - -static int lc3_disable(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) -{ - printk("Disable: stream %p\n", stream); - - return 0; -} - -static int lc3_stop(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) -{ - printk("Stop: stream %p\n", stream); - - return 0; -} - -static int lc3_release(struct bt_bap_stream *stream, struct bt_bap_ascs_rsp *rsp) -{ - printk("Release: stream %p\n", stream); - return 0; -} - -static const struct bt_bap_unicast_server_cb unicast_server_cb = { - .config = lc3_config, - .reconfig = lc3_reconfig, - .qos = lc3_qos, - .enable = lc3_enable, - .start = lc3_start, - .metadata = lc3_metadata, - .disable = lc3_disable, - .stop = lc3_stop, - .release = lc3_release, -}; - - -#if defined(CONFIG_LIBLC3) - -static void stream_recv_lc3_codec(struct bt_bap_stream *stream, - const struct bt_iso_recv_info *info, - struct net_buf *buf) -{ - const uint8_t *in_buf; - uint8_t err = -1; - const int octets_per_frame = buf->len / frames_per_sdu; - - if (lc3_decoder == NULL) { - printk("LC3 decoder not setup, cannot decode data.\n"); - return; - } - - if ((info->flags & BT_ISO_FLAGS_VALID) == 0) { - printk("Bad packet: 0x%02X\n", info->flags); - - in_buf = NULL; - } else { - in_buf = buf->data; - } - - /* This code is to demonstrate the use of the LC3 codec. On an actual implementation - * it might be required to offload the processing to another task to avoid blocking the - * BT stack. - */ - for (int i = 0; i < frames_per_sdu; i++) { - - int offset = 0; - - err = lc3_decode(lc3_decoder, in_buf + offset, octets_per_frame, - LC3_PCM_FORMAT_S16, audio_buf, 1); - - if (in_buf != NULL) { - offset += octets_per_frame; - } - } - - printk("RX stream %p len %u\n", stream, buf->len); - - if (err == 1) { - printk(" decoder performed PLC\n"); - return; - - } else if (err < 0) { - printk(" decoder failed - wrong parameters?\n"); - return; - } -} - -#else - -static void stream_recv(struct bt_bap_stream *stream, - const struct bt_iso_recv_info *info, - struct net_buf *buf) -{ - if (info->flags & BT_ISO_FLAGS_VALID) { - printk("Incoming audio on stream %p len %u\n", stream, buf->len); - } -} - -#endif - -static void stream_stopped(struct bt_bap_stream *stream, uint8_t reason) -{ - printk("Audio Stream %p stopped with reason 0x%02X\n", stream, reason); - - /* Stop send timer */ - k_work_cancel_delayable(&audio_send_work); -} - - -static void stream_enabled_cb(struct bt_bap_stream *stream) -{ - /* The unicast server is responsible for starting sink ASEs after the - * client has enabled them. - */ - if (stream_dir(stream) == BT_AUDIO_DIR_SINK) { - const int err = bt_bap_stream_start(stream); - - if (err != 0) { - printk("Failed to start stream %p: %d", stream, err); - } - } -} - -static struct bt_bap_stream_ops stream_ops = { -#if defined(CONFIG_LIBLC3) - .recv = stream_recv_lc3_codec, -#else - .recv = stream_recv, -#endif - .stopped = stream_stopped, - .enabled = stream_enabled_cb, -}; - -static void connected(struct bt_conn *conn, uint8_t err) -{ - char addr[BT_ADDR_LE_STR_LEN]; - - bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - - if (err != 0) { - printk("Failed to connect to %s (%u)\n", addr, err); - - default_conn = NULL; - return; - } - - printk("Connected: %s\n", addr); - default_conn = bt_conn_ref(conn); -} - -static void disconnected(struct bt_conn *conn, uint8_t reason) -{ - char addr[BT_ADDR_LE_STR_LEN]; - - if (conn != default_conn) { - return; - } - - bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr)); - - printk("Disconnected: %s (reason 0x%02x)\n", addr, reason); - - bt_conn_unref(default_conn); - default_conn = NULL; - - k_sem_give(&sem_disconnected); -} - -BT_CONN_CB_DEFINE(conn_callbacks) = { - .connected = connected, - .disconnected = disconnected, -}; - -static struct bt_pacs_cap cap_sink = { - .codec_cap = &lc3_codec_cap, -}; - -static struct bt_pacs_cap cap_source = { - .codec_cap = &lc3_codec_cap, -}; - -static int set_location(void) -{ - int err; - - if (IS_ENABLED(CONFIG_BT_PAC_SNK_LOC)) { - err = bt_pacs_set_location(BT_AUDIO_DIR_SINK, - BT_AUDIO_LOCATION_FRONT_CENTER); - if (err != 0) { - printk("Failed to set sink location (err %d)\n", err); - return err; - } - } - - if (IS_ENABLED(CONFIG_BT_PAC_SRC_LOC)) { - err = bt_pacs_set_location(BT_AUDIO_DIR_SOURCE, - (BT_AUDIO_LOCATION_FRONT_LEFT | - BT_AUDIO_LOCATION_FRONT_RIGHT)); - if (err != 0) { - printk("Failed to set source location (err %d)\n", err); - return err; - } - } - - printk("Location successfully set\n"); - - return 0; -} - -static int set_supported_contexts(void) -{ - int err; - - if (IS_ENABLED(CONFIG_BT_PAC_SNK)) { - err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SINK, - AVAILABLE_SINK_CONTEXT); - if (err != 0) { - printk("Failed to set sink supported contexts (err %d)\n", - err); - - return err; - } - } - - if (IS_ENABLED(CONFIG_BT_PAC_SRC)) { - err = bt_pacs_set_supported_contexts(BT_AUDIO_DIR_SOURCE, - AVAILABLE_SOURCE_CONTEXT); - if (err != 0) { - printk("Failed to set source supported contexts (err %d)\n", - err); - - return err; - } - } - - printk("Supported contexts successfully set\n"); - - return 0; -} - -static int set_available_contexts(void) -{ - int err; - - if (IS_ENABLED(CONFIG_BT_PAC_SNK)) { - err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SINK, - AVAILABLE_SINK_CONTEXT); - if (err != 0) { - printk("Failed to set sink available contexts (err %d)\n", err); - return err; - } - } - - if (IS_ENABLED(CONFIG_BT_PAC_SRC)) { - err = bt_pacs_set_available_contexts(BT_AUDIO_DIR_SOURCE, - AVAILABLE_SOURCE_CONTEXT); - if (err != 0) { - printk("Failed to set source available contexts (err %d)\n", err); - return err; - } - } - - printk("Available contexts successfully set\n"); - return 0; -} - -int main(void) -{ - struct bt_le_ext_adv *adv; - int err; - - err = bt_enable(NULL); - if (err != 0) { - printk("Bluetooth init failed (err %d)\n", err); - return 0; - } - - printk("Bluetooth initialized\n"); - - bt_bap_unicast_server_register_cb(&unicast_server_cb); - - bt_pacs_cap_register(BT_AUDIO_DIR_SINK, &cap_sink); - bt_pacs_cap_register(BT_AUDIO_DIR_SOURCE, &cap_source); - - for (size_t i = 0; i < ARRAY_SIZE(sink_streams); i++) { - bt_bap_stream_cb_register(&sink_streams[i], &stream_ops); - } - - for (size_t i = 0; i < ARRAY_SIZE(source_streams); i++) { - bt_bap_stream_cb_register(&source_streams[i].stream, - &stream_ops); - } - - err = set_location(); - if (err != 0) { - return 0; - } - - err = set_supported_contexts(); - if (err != 0) { - return 0; - } - - err = set_available_contexts(); - if (err != 0) { - return 0; - } - - /* Create a non-connectable non-scannable advertising set */ - err = bt_le_ext_adv_create(BT_LE_EXT_ADV_CONN, NULL, &adv); - if (err) { - printk("Failed to create advertising set (err %d)\n", err); - return 0; - } - - err = bt_le_ext_adv_set_data(adv, ad, ARRAY_SIZE(ad), NULL, 0); - if (err) { - printk("Failed to set advertising data (err %d)\n", err); - return 0; - } - - while (true) { - struct k_work_sync sync; - - err = bt_le_ext_adv_start(adv, BT_LE_EXT_ADV_START_DEFAULT); - if (err) { - printk("Failed to start advertising set (err %d)\n", err); - return 0; - } - - printk("Advertising successfully started\n"); - - if (CONFIG_BT_ASCS_ASE_SRC_COUNT > 0) { - /* Start send timer */ - k_work_init_delayable(&audio_send_work, audio_timer_timeout); - } - - err = k_sem_take(&sem_disconnected, K_FOREVER); - if (err != 0) { - printk("failed to take sem_disconnected (err %d)\n", err); - return 0; - } - - /* reset data */ - configured_source_stream_count = 0U; - k_work_cancel_delayable_sync(&audio_send_work, &sync); - - } - return 0; -} diff --git a/samples/boards/arc_secure_services/nsim_sem_normal_defconfig b/samples/boards/arc_secure_services/nsim_sem_normal_defconfig index 91b9775a7dd6b..80e70c38a35ed 100644 --- a/samples/boards/arc_secure_services/nsim_sem_normal_defconfig +++ b/samples/boards/arc_secure_services/nsim_sem_normal_defconfig @@ -1,4 +1,4 @@ -CONFIG_SOC_NSIM=y +CONFIG_SOC_FAMILY_NSIM_ARC_CLASSIC=y CONFIG_SOC_NSIM_SEM=y CONFIG_BOARD_NSIM=y CONFIG_SYS_CLOCK_TICKS_PER_SEC=100 diff --git a/samples/boards/bbc_microbit/pong/src/ble.c b/samples/boards/bbc_microbit/pong/src/ble.c index 9f86a8e8712bf..c1da7af5b3f29 100644 --- a/samples/boards/bbc_microbit/pong/src/ble.c +++ b/samples/boards/bbc_microbit/pong/src/ble.c @@ -471,8 +471,8 @@ static void ble_timeout(struct k_work *work) k_work_reschedule(&ble_work, K_NO_WAIT); break; case BLE_ADV_START: - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), - sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, + ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; diff --git a/samples/boards/esp32/xt_wdt/CMakeLists.txt b/samples/boards/esp32/xt_wdt/CMakeLists.txt new file mode 100644 index 0000000000000..899973e1b6905 --- /dev/null +++ b/samples/boards/esp32/xt_wdt/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(xt_wdt_sample) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/esp32/xt_wdt/README.rst b/samples/boards/esp32/xt_wdt/README.rst new file mode 100644 index 0000000000000..05f9052e0a87b --- /dev/null +++ b/samples/boards/esp32/xt_wdt/README.rst @@ -0,0 +1,60 @@ +.. _xt_wdt_sample: + +Espressif XT WDT Sample +####################### + +Overview +******** + +This sample shows how to work with XTAL32K Watchdog Timer (XT WDT) peripheral. +To properly run this sample, you need to have a board with an external 32.728 Hz +crystal oscillator connected to the XTAL_32K_P and XTAL_32K_N pins. + +The app will ask for the crystal removal to simulate a crystal failure and trigger +the XT WDT interrupt. Internally the hardware switch the RTC SLOW clock source from +ESP32_RTC_SLOW_CLK_SRC_XTAL32K to ESP32_RTC_SLOW_CLK_SRC_RC_SLOW (136 KHz for C3 and S3 / +9 KHz for S2). + +Supported SoCs +************** + +The following SoCs supports the XT WDT peripheral: + +* ESP32-C3 +* ESP32-S2 +* ESP32-S3 + +Building and Running +******************** + +Make sure you have your board connected over USB port and the external crystal is connected +to pins XTAL_32K_P and XTAL_32K_N. + +.. code-block:: console + + west build -p -b esp32s3_devkitm/esp32s3/procpu samples/boards/esp32/xt_wdt + west flash + +If using another supported Espressif board, replace the argument in the above +command with a proper board name (e.g., `esp32s2_saola`). + +Sample Output +============= + +To check output of this sample, run ``west espressif monitor`` or any other serial +console program (e.g., minicom, putty, screen, etc). +This example uses ``west espressif monitor``, which automatically detects the serial +port at ``/dev/ttyUSB0``: + +.. code-block:: console + + $ west espressif monitor + +.. code-block:: console + + *** Booting Zephyr OS build v3.6.0-3896-gb4a7f061524f *** + [00:00:01.287,000] xt_wdt_sample: XT WDT Sample on esp32s3_devkitm/esp32s3/procpu + [00:00:01.287,000] xt_wdt_sample: Current RTC SLOW clock rate: 32768 Hz + [00:00:01.287,000] xt_wdt_sample: Remove the external 32K crystal to trigger the watchdog + XT WDT callback + [00:00:03.554,000] xt_wdt_sample: Current RTC SLOW clock rate: 136000 Hz diff --git a/samples/boards/esp32/xt_wdt/app.overlay b/samples/boards/esp32/xt_wdt/app.overlay new file mode 100644 index 0000000000000..8a95767c5e2a1 --- /dev/null +++ b/samples/boards/esp32/xt_wdt/app.overlay @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&rtc { + slow-clk-src = ; +}; + +&xt_wdt { + status = "okay"; +}; diff --git a/samples/boards/esp32/xt_wdt/prj.conf b/samples/boards/esp32/xt_wdt/prj.conf new file mode 100644 index 0000000000000..b465d96394864 --- /dev/null +++ b/samples/boards/esp32/xt_wdt/prj.conf @@ -0,0 +1,3 @@ +CONFIG_LOG=y +CONFIG_WATCHDOG=y +CONFIG_WDT_LOG_LEVEL_INF=y diff --git a/samples/boards/esp32/xt_wdt/sample.yaml b/samples/boards/esp32/xt_wdt/sample.yaml new file mode 100644 index 0000000000000..01a159a61bbd2 --- /dev/null +++ b/samples/boards/esp32/xt_wdt/sample.yaml @@ -0,0 +1,10 @@ +sample: + description: Application to test XT WDT + name: xt_wdt_sample +tests: + sample.board.esp32.xt_wdt: + platform_allow: + - esp32c3_devkitm + - esp32s2_saola + - esp32s3_devkitm/esp32s3/procpu + tags: esp32 diff --git a/samples/boards/esp32/xt_wdt/src/main.c b/samples/boards/esp32/xt_wdt/src/main.c new file mode 100644 index 0000000000000..c2a3387d05c9f --- /dev/null +++ b/samples/boards/esp32/xt_wdt/src/main.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024 Espressif Systems (Shanghai) Co., Ltd. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +LOG_MODULE_REGISTER(xt_wdt_sample, CONFIG_WDT_LOG_LEVEL); + +K_SEM_DEFINE(wdt_sem, 0, 1); + +static const struct device *const clk_dev = DEVICE_DT_GET_ONE(espressif_esp32_rtc); +const struct device *const wdt = DEVICE_DT_GET_ONE(espressif_esp32_xt_wdt); + +static void wdt_callback(const struct device *wdt_dev, int channel_id) +{ + printk("XT WDT callback\n"); + k_sem_give(&wdt_sem); +} + +int main(void) +{ + uint32_t clk_rate = 0; + + if (!device_is_ready(clk_dev)) { + LOG_ERR("Clock device is not ready"); + return -EIO; + } + + if (!device_is_ready(wdt)) { + LOG_ERR("XT WDT device is not ready"); + return -EIO; + } + + LOG_INF("XT WDT Sample on %s", CONFIG_BOARD_TARGET); + + clock_control_get_rate(clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW, + &clk_rate); + + LOG_INF("Current RTC SLOW clock rate: %d Hz", clk_rate); + + /* Set up the watchdog */ + struct wdt_timeout_cfg wdt_config = { + .window.max = 200, + .callback = wdt_callback, + }; + + wdt_install_timeout(wdt, &wdt_config); + + wdt_setup(wdt, 0); + + LOG_INF("Remove the external 32K crystal to trigger the watchdog"); + + k_sem_take(&wdt_sem, K_FOREVER); + + clock_control_get_rate(clk_dev, (clock_control_subsys_t)ESP32_CLOCK_CONTROL_SUBSYS_RTC_SLOW, + &clk_rate); + + LOG_INF("Current RTC SLOW clock rate: %d Hz", clk_rate); + + return 0; +} diff --git a/samples/boards/nrf/mesh/onoff-app/prj.conf b/samples/boards/nrf/mesh/onoff-app/prj.conf index 0fdf19b8cfce0..e6f744fb95ab2 100644 --- a/samples/boards/nrf/mesh/onoff-app/prj.conf +++ b/samples/boards/nrf/mesh/onoff-app/prj.conf @@ -22,7 +22,6 @@ CONFIG_BT_DATA_LEN_UPDATE=n CONFIG_BT_PHY_UPDATE=n CONFIG_BT_CTLR_CHAN_SEL_2=n CONFIG_BT_CTLR_MIN_USED_CHAN=n -CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT_PERIPHERAL=y @@ -79,8 +78,6 @@ CONFIG_BT_MESH_LOG_LEVEL_DBG=y #CONFIG_BT_MESH_ADV_LOG_LEVEL_DBG=y #CONFIG_BT_MESH_SELF_TEST=y -#CONFIG_BT_HCI_VS_EXT=n - #CONFIG_STACK_USAGE=y CONFIG_BT_RX_STACK_SIZE=4096 diff --git a/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/prj.conf b/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/prj.conf index b5a01e39e566f..f23b4dc2a304b 100644 --- a/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/prj.conf +++ b/samples/boards/nrf/mesh/onoff_level_lighting_vnd_app/prj.conf @@ -17,7 +17,6 @@ CONFIG_BT_DATA_LEN_UPDATE=n CONFIG_BT_PHY_UPDATE=n CONFIG_BT_CTLR_CHAN_SEL_2=n CONFIG_BT_CTLR_MIN_USED_CHAN=n -CONFIG_BT_CTLR_ADV_EXT=n CONFIG_BT_CTLR_PRIVACY=n CONFIG_BT_CTLR_TX_PWR_PLUS_8=y diff --git a/samples/boards/nrf/nrfx_prs/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/boards/nrf/nrfx_prs/boards/nrf5340dk_nrf5340_cpuapp.overlay index d187d4a5f99d2..4bbf47524a804 100644 --- a/samples/boards/nrf/nrfx_prs/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/samples/boards/nrf/nrfx_prs/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -1,20 +1,20 @@ &pinctrl { spi1_default_alt: spi1_default_alt { group1 { - psels = , - ; + psels = , + ; }; group2 { - psels = ; + psels = ; bias-pull-down; }; }; spi1_sleep_alt: spi1_sleep_alt { group1 { - psels = , - , - ; + psels = , + , + ; low-power-enable; }; }; diff --git a/samples/boards/nrf/nrfx_prs/sample.yaml b/samples/boards/nrf/nrfx_prs/sample.yaml index 149dd1724838e..95c772d7d890d 100644 --- a/samples/boards/nrf/nrfx_prs/sample.yaml +++ b/samples/boards/nrf/nrfx_prs/sample.yaml @@ -17,3 +17,8 @@ tests: - "nrfx PRS example on .*" - "-> press \".*\" to trigger a transfer" - "-> press \".*\" to switch the type of peripheral" + - "Switched to SPIM" + - "-- Background transfer on \".*\" --" + - "Tx: 4E 6F 72 64 69 63 20 53 65 6D 69 63 6F 6E 64 75 63 74 6F 72 00" + - "Rx:" + - "-- Background transfer on \".*\" --" diff --git a/samples/boards/reel_board/mesh_badge/src/main.c b/samples/boards/reel_board/mesh_badge/src/main.c index 932e25f2d89be..3442a7851aa78 100644 --- a/samples/boards/reel_board/mesh_badge/src/main.c +++ b/samples/boards/reel_board/mesh_badge/src/main.c @@ -180,7 +180,8 @@ static void bt_ready(int err) if (!mesh_is_initialized()) { /* Start advertising */ - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, + ARRAY_SIZE(sd)); if (err) { printk("Advertising failed to start (err %d)\n", err); return; diff --git a/samples/boards/stm32/backup_sram/boards/nucleo_h563zi.overlay b/samples/boards/stm32/backup_sram/boards/nucleo_h563zi.overlay new file mode 100644 index 0000000000000..377726bbd4ccf --- /dev/null +++ b/samples/boards/stm32/backup_sram/boards/nucleo_h563zi.overlay @@ -0,0 +1,9 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Thorsten Spätling + */ + +&backup_sram{ + status = "okay"; +}; diff --git a/samples/boards/stm32/bluetooth/interactive_gui/CMakeLists.txt b/samples/boards/stm32/bluetooth/interactive_gui/CMakeLists.txt new file mode 100644 index 0000000000000..37dc403fcca8a --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(st_interactive_gui) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/stm32/bluetooth/interactive_gui/README.rst b/samples/boards/stm32/bluetooth/interactive_gui/README.rst new file mode 100644 index 0000000000000..e086eec0c8e4e --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/README.rst @@ -0,0 +1,37 @@ +.. _samples_boards_stm32_bluetooth_interactive-gui: +.. zephyr:code-sample:: st_bluetooth_interactive_gui + :name: Bluetooth: ST Interactive GUI + :relevant-api: bluenrg_hci_driver bluetooth + +Expose ST BlueNRG Bluetooth network coprocessor over UART + +Overview +********* + +Expose the Bluetooth network coprocessor via UART to a PC to be used +with the ST BlueNRG GUI app. In this case, the main MCU becomes an intermediate level, +and it passes the data between the host (PC) and controller. + +Requirements +************ + +* A board based on BlueNRG BLE module such as :ref:`disco_l475_iot1_board` +* `BlueNRG GUI`_ application installed on your PC + +Default UART settings +********************* + +It depends on the board default settings for ``zephyr,bt-c2h-uart`` DTS property. +The UART default settings are: + +* Baudrate: 115200 bps +* 8 bits, no parity, 1 stop bit + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/boards/stm32/bluetooth/interactive_gui` in the +Zephyr tree. + +.. _BlueNRG GUI: + https://www.st.com/en/embedded-software/stsw-bnrgui.html diff --git a/samples/boards/stm32/bluetooth/interactive_gui/prj.conf b/samples/boards/stm32/bluetooth/interactive_gui/prj.conf new file mode 100644 index 0000000000000..74ce94a7cc53d --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/prj.conf @@ -0,0 +1,15 @@ +CONFIG_CONSOLE=n +CONFIG_STDOUT_CONSOLE=n +CONFIG_UART_CONSOLE=n +CONFIG_SERIAL=y +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_BT=y +CONFIG_BT_HCI_RAW=y +CONFIG_BT_HCI_RAW_H4=y +CONFIG_BT_HCI_RAW_H4_ENABLE=y +CONFIG_BT_BUF_ACL_RX_SIZE=255 +CONFIG_BT_BUF_CMD_TX_SIZE=255 +CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255 +CONFIG_BT_BLUENRG_ACI=n +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512 +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=y diff --git a/samples/boards/stm32/bluetooth/interactive_gui/sample.yaml b/samples/boards/stm32/bluetooth/interactive_gui/sample.yaml new file mode 100644 index 0000000000000..695c6e93a6f8b --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/sample.yaml @@ -0,0 +1,12 @@ +sample: + name: Bluetooth ST Interactive GUI + description: Allows BlueNRG-based boards to connect to BlueNRG GUI application via UART +tests: + sample.boards.stm32.bluetooth.interactive_gui: + harness: bluetooth + platform_allow: + - sensortile_box_pro + - disco_l475_iot1 + tags: + - uart + - bluetooth diff --git a/samples/boards/stm32/bluetooth/interactive_gui/src/main.c b/samples/boards/stm32/bluetooth/interactive_gui/src/main.c new file mode 100644 index 0000000000000..82d008e4d6c9a --- /dev/null +++ b/samples/boards/stm32/bluetooth/interactive_gui/src/main.c @@ -0,0 +1,462 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * Copyright (c) 2016 Nordic Semiconductor ASA + * Copyright (c) 2015-2016 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LOG_MODULE_NAME gui_hci_uart +LOG_MODULE_REGISTER(LOG_MODULE_NAME); + +static const struct device *const hci_uart_dev = + DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_c2h_uart)); +static K_THREAD_STACK_DEFINE(tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE); +static struct k_thread tx_thread_data; +static K_FIFO_DEFINE(tx_queue); + +/* RX in terms of bluetooth communication */ +static K_FIFO_DEFINE(uart_tx_queue); + +#define H4_ST_EXT_CMD 0x81 +#define H4_ST_VND_CMD 0xFF + +#define ST_IDLE 0 /* Waiting for packet type. */ +#define ST_HDR 1 /* Receiving packet header. */ +#define ST_PAYLOAD 2 /* Receiving packet payload. */ +#define ST_DISCARD 3 /* Dropping packet. */ + +/* Length of a discard/flush buffer. + * This is sized to align with a BLE HCI packet: + * 1 byte H:4 header + 32 bytes ACL/event data + * Bigger values might overflow the stack since this is declared as a local + * variable, smaller ones will force the caller to call into discard more + * often. + */ +#define H4_DISCARD_LEN 33 + +#define RESP_VENDOR_CODE_OFFSET 1 +#define RESP_LEN_OFFSET_LSB 2 +#define RESP_LEN_OFFSET_MSB 3 +#define RESP_CMDCODE_OFFSET 4 +#define RESP_STATUS_OFFSET 5 +#define RESP_PARAM_OFFSET 6 + +/* Types of vendor codes */ +#define VENDOR_CODE_ERROR 0 +#define VENDOR_CODE_RESPONSE 1 + +/* Commands */ +#define VENDOR_CMD_READ_VERSION 0x01 +#define VENDOR_CMD_BLUENRG_RESET 0x04 +#define VENDOR_CMD_HW_BOOTLOADER 0x05 + +struct bt_hci_ext_cmd_hdr { + uint16_t opcode; + uint16_t param_len; +} __packed; + +struct bt_vendor_cmd_hdr { + uint8_t opcode; + uint16_t param_len; +} __packed; + +struct bt_vendor_rsp_hdr { + uint8_t vendor_code; + uint16_t param_len; + uint8_t opcode; + uint8_t status; + uint8_t params[2]; +} __packed; + +static int h4_send(struct net_buf *buf); + +static uint16_t parse_cmd(uint8_t *hci_buffer, uint16_t hci_pckt_len, uint8_t *buffer_out) +{ + uint16_t len = 0; + struct bt_vendor_cmd_hdr *hdr = (struct bt_vendor_cmd_hdr *) hci_buffer; + struct bt_vendor_rsp_hdr *rsp = (struct bt_vendor_rsp_hdr *) (buffer_out + 1); + + buffer_out[0] = H4_ST_VND_CMD; + rsp->vendor_code = VENDOR_CODE_RESPONSE; + rsp->opcode = hdr->opcode; + rsp->status = 0; + + switch (hdr->opcode) { + case VENDOR_CMD_READ_VERSION: + rsp->params[0] = KERNEL_VERSION_MAJOR; + if (KERNEL_PATCHLEVEL >= 9) { + rsp->params[1] = (KERNEL_VERSION_MINOR * 10) + 9; + } else { + rsp->params[1] = (KERNEL_VERSION_MINOR * 10) + KERNEL_PATCHLEVEL; + } + len = 2; + break; +#if DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) || DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) + case VENDOR_CMD_BLUENRG_RESET: + bluenrg_bt_reset(0); + break; + case VENDOR_CMD_HW_BOOTLOADER: + bluenrg_bt_reset(1); + break; +#endif /* DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v1) || DT_HAS_COMPAT_STATUS_OKAY(st_hci_spi_v2) */ + default: + rsp->vendor_code = VENDOR_CODE_ERROR; + rsp->status = BT_HCI_ERR_UNKNOWN_CMD; + } + + len += 2; /* Status and Command code */ + rsp->param_len = sys_cpu_to_le16(len); + len += RESP_CMDCODE_OFFSET; + + return len; +} + +static int send_evt(uint8_t *response, uint8_t len) +{ + struct net_buf *buf; + + buf = bt_buf_get_rx(BT_BUF_EVT, K_NO_WAIT); + + if (!buf) { + LOG_ERR("EVT no buffer"); + return -ENOMEM; + } + if (len > net_buf_tailroom(buf)) { + LOG_ERR("EVT too long: %d", len); + net_buf_unref(buf); + return -ENOMEM; + } + net_buf_add_mem(buf, response, len); + + return h4_send(buf); +} + +static int h4_read(const struct device *uart, uint8_t *buf, size_t len) +{ + int rx = uart_fifo_read(uart, buf, len); + + LOG_DBG("read %d req %d", rx, len); + return rx; +} + +static bool valid_type(uint8_t type) +{ + return (type == BT_HCI_H4_CMD) | (type == H4_ST_EXT_CMD) | + (type == BT_HCI_H4_ACL) | (type == BT_HCI_H4_ISO) | (type == H4_ST_VND_CMD); +} + +/* Function expects that type is validated and only CMD, ISO or ACL are used. */ +static uint32_t get_len(const uint8_t *hdr_buf, uint8_t type) +{ + switch (type) { + case BT_HCI_H4_CMD: + return ((const struct bt_hci_cmd_hdr *)hdr_buf)->param_len; + case H4_ST_EXT_CMD: + return ((const struct bt_hci_ext_cmd_hdr *)hdr_buf)->param_len; + case H4_ST_VND_CMD: + return ((const struct bt_vendor_cmd_hdr *)hdr_buf)->param_len; + case BT_HCI_H4_ISO: + return bt_iso_hdr_len( + sys_le16_to_cpu(((const struct bt_hci_iso_hdr *)hdr_buf)->len)); + case BT_HCI_H4_ACL: + return sys_le16_to_cpu(((const struct bt_hci_acl_hdr *)hdr_buf)->len); + default: + LOG_ERR("Invalid type: %u", type); + return 0; + } +} + +/* Function expects that type is validated and only CMD, ISO or ACL are used. */ +static int hdr_len(uint8_t type) +{ + switch (type) { + case BT_HCI_H4_CMD: + return sizeof(struct bt_hci_cmd_hdr); + case H4_ST_EXT_CMD: + return sizeof(struct bt_hci_ext_cmd_hdr); + case H4_ST_VND_CMD: + return sizeof(struct bt_vendor_cmd_hdr); + case BT_HCI_H4_ISO: + return sizeof(struct bt_hci_iso_hdr); + case BT_HCI_H4_ACL: + return sizeof(struct bt_hci_acl_hdr); + default: + LOG_ERR("Invalid type: %u", type); + return 0; + } +} + +static struct net_buf *alloc_tx_buf(uint8_t type) +{ + uint8_t alloc_type = type; + struct net_buf *buf; + + switch (type) { + case H4_ST_EXT_CMD: + case BT_HCI_H4_CMD: + case H4_ST_VND_CMD: + alloc_type = BT_HCI_H4_CMD; + break; + case BT_HCI_H4_ISO: + case BT_HCI_H4_ACL: + break; + default: + LOG_ERR("Invalid type: %u", type); + return NULL; + } + buf = bt_buf_get_tx(BT_BUF_H4, K_NO_WAIT, &alloc_type, sizeof(alloc_type)); + if (buf && (type == H4_ST_VND_CMD)) { + bt_buf_set_type(buf, type); + } + return buf; +} + +static void rx_isr(void) +{ + static struct net_buf *buf; + static int remaining; + static uint8_t state; + static uint8_t type; + static uint8_t hdr_buf[MAX(sizeof(struct bt_hci_cmd_hdr), sizeof(struct bt_hci_acl_hdr))]; + int read; + + do { + switch (state) { + case ST_IDLE: + /* Get packet type */ + read = h4_read(hci_uart_dev, &type, sizeof(type)); + /* since we read in loop until no data is in the fifo, + * it is possible that read = 0. + */ + if (read) { + if (valid_type(type)) { + /* Get expected header size and switch + * to receiving header. + */ + remaining = hdr_len(type); + state = ST_HDR; + } else { + LOG_WRN("Unknown header %d", type); + } + } + break; + case ST_HDR: + read = h4_read(hci_uart_dev, &hdr_buf[hdr_len(type) - remaining], + remaining); + remaining -= read; + if (remaining == 0) { + /* Header received. Allocate buffer and get + * payload length. If allocation fails leave + * interrupt. On failed allocation state machine + * is reset. + */ + uint8_t header_length; + + buf = alloc_tx_buf(type); + if (!buf) { + LOG_ERR("No available command buffers!"); + state = ST_IDLE; + return; + } + + remaining = get_len(hdr_buf, type); + header_length = hdr_len(type); + if (type == H4_ST_EXT_CMD) { + /* Convert to regular HCI_CMD */ + if (remaining > 255) { + LOG_ERR("len > 255"); + net_buf_unref(buf); + state = ST_DISCARD; + } else { + header_length--; + } + } + net_buf_add_mem(buf, hdr_buf, header_length); + if (remaining > net_buf_tailroom(buf)) { + LOG_ERR("Not enough space in buffer"); + net_buf_unref(buf); + state = ST_DISCARD; + } else { + state = ST_PAYLOAD; + } + + } + break; + case ST_PAYLOAD: + read = h4_read(hci_uart_dev, net_buf_tail(buf), remaining); + buf->len += read; + remaining -= read; + if (remaining == 0) { + /* Packet received */ + LOG_DBG("putting RX packet in queue."); + net_buf_put(&tx_queue, buf); + state = ST_IDLE; + } + break; + case ST_DISCARD: + uint8_t discard[H4_DISCARD_LEN]; + size_t to_read = MIN(remaining, sizeof(discard)); + + read = h4_read(hci_uart_dev, discard, to_read); + remaining -= read; + if (remaining == 0) { + state = ST_IDLE; + } + break; + default: + read = 0; + __ASSERT_NO_MSG(0); + break; + + } + } while (read); +} + +static void tx_isr(void) +{ + static struct net_buf *buf; + int len; + + if (!buf) { + buf = net_buf_get(&uart_tx_queue, K_NO_WAIT); + if (!buf) { + uart_irq_tx_disable(hci_uart_dev); + return; + } + } + len = uart_fifo_fill(hci_uart_dev, buf->data, buf->len); + net_buf_pull(buf, len); + if (!buf->len) { + net_buf_unref(buf); + buf = NULL; + } +} + +static void bt_uart_isr(const struct device *unused, void *user_data) +{ + ARG_UNUSED(unused); + ARG_UNUSED(user_data); + + if (!(uart_irq_rx_ready(hci_uart_dev) || uart_irq_tx_ready(hci_uart_dev))) { + LOG_DBG("spurious interrupt"); + } + if (uart_irq_tx_ready(hci_uart_dev)) { + tx_isr(); + } + if (uart_irq_rx_ready(hci_uart_dev)) { + rx_isr(); + } +} + +static void tx_thread(void *p1, void *p2, void *p3) +{ + enum bt_buf_type buf_type; + + while (1) { + struct net_buf *buf; + int err = 0; + uint8_t len; + uint8_t response[16]; + + /* Wait until a buffer is available */ + buf = net_buf_get(&tx_queue, K_FOREVER); + buf_type = bt_buf_get_type(buf); + if (buf_type == H4_ST_VND_CMD) { + len = parse_cmd(buf->data, buf->len, response); + err = send_evt(response, len); + if (!err) { + net_buf_unref(buf); + } + } else { + /* Pass buffer to the stack */ + err = bt_send(buf); + } + if (err) { + LOG_ERR("Unable to send (err %d)", err); + net_buf_unref(buf); + } + + /* Give other threads a chance to run if tx_queue keeps getting + * new data all the time. + */ + k_yield(); + } +} + +static int h4_send(struct net_buf *buf) +{ + LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf), buf->len); + net_buf_put(&uart_tx_queue, buf); + uart_irq_tx_enable(hci_uart_dev); + return 0; +} + +static int hci_uart_init(void) +{ + LOG_DBG(""); + if (!device_is_ready(hci_uart_dev)) { + LOG_ERR("HCI UART %s is not ready", hci_uart_dev->name); + return -EINVAL; + } + uart_irq_rx_disable(hci_uart_dev); + uart_irq_tx_disable(hci_uart_dev); + uart_irq_callback_set(hci_uart_dev, bt_uart_isr); + uart_irq_rx_enable(hci_uart_dev); + return 0; +} + +int main(void) +{ + /* incoming events and data from the controller */ + static K_FIFO_DEFINE(rx_queue); + int err; + + LOG_DBG("Start"); + __ASSERT(hci_uart_dev, "UART device is NULL"); + + /* Enable the raw interface, this will in turn open the HCI driver */ + bt_enable_raw(&rx_queue); + /* Spawn the TX thread and start feeding commands and data to the controller */ + k_thread_create(&tx_thread_data, tx_thread_stack, + K_THREAD_STACK_SIZEOF(tx_thread_stack), tx_thread, + NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT); + k_thread_name_set(&tx_thread_data, "HCI uart TX"); + + while (1) { + struct net_buf *buf; + + buf = net_buf_get(&rx_queue, K_FOREVER); + err = h4_send(buf); + if (err) { + LOG_ERR("Failed to send"); + } + } + return 0; +} + +SYS_INIT(hci_uart_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE); diff --git a/samples/boards/stm32/i2c_timing/CMakeLists.txt b/samples/boards/stm32/i2c_timing/CMakeLists.txt new file mode 100644 index 0000000000000..e9f2b44191722 --- /dev/null +++ b/samples/boards/stm32/i2c_timing/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(i2c_timing) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/boards/stm32/i2c_timing/README.rst b/samples/boards/stm32/i2c_timing/README.rst new file mode 100644 index 0000000000000..a951a0872e22a --- /dev/null +++ b/samples/boards/stm32/i2c_timing/README.rst @@ -0,0 +1,81 @@ +.. _i2c_config: + +STM32 I2C V2 timings +#################### + +Overview +******** +This sample simply demonstrate the **get_config** API of the stm32 I2C driver. +The I2C peripheral configuration is checked regarding the I2C bitrate which can be: + + - + - + - + + +In case of the I2C V2, the I2C peripheral of the STM32 microcontrollers have +a TIMING register to write in order to generate the correct I2C clock signal. +This value depends on the peripheral clock input and the I2C speed. +The calculation of that TIMING value can be given by the `STM32CubeMX`_ application +**or** by the present sample. + +Because the code sequence to calculate the I2C V2 TIMING value is heavy, +it is not advised to enable it in production binary. +By enabling CONFIG_I2C_STM32_V2_TIMING flag, this sample allows to +retrieve timing register configuration for the defined ``clock-frequency``. +User can then configure timing in his application by adapting the following dts +snippet with the output of this sample: + + + .. code-block:: c + + &i2c { + timings = <160000000 I2C_BITRATE_STANDARD 0xB0C03E40>, + <160000000 I2C_BITRATE_FAST 0xC041090F>, + <160000000 I2C_BITRATE_FAST_PLUS 0x6021050A>; + } + + +Building and Running +******************** + +In order to run this sample, make sure to + +- enable ``i2c`` node in your board DT file. +- enable the CONFIG_I2C_STM32_V2_TIMING=y in the board **conf** file +- alias the **i2c-0** to your ``i2c`` node of the board **overlay** file + + .. zephyr-app-commands:: + :zephyr-app: samples/boards/stm32/i2c_config + :board: b_u585i_iot02a + :goals: build + :compact: + +Sample Output +============= +When setting the b_u585i_iot02a.overlay to + + .. code-block:: c + + / { + aliases { + i2c-0 = &i2c2; + }; + }; + &i2c2 { + /delete-property/ clock-frequency; + clock-frequency = ; + }; + +The sample gives the corresponding TIMING value to report to the Device Tree: + +.. code-block:: console + + I2C timing value, report to the DTS : + timings = <160000000 I2C_BITRATE_FAST 0xC041090F>; + + I2C config : I2C_BITRATE_FAST + + +.. _STM32CubeMX: + https://www.st.com/en/development-tools/stm32cubemx.html diff --git a/samples/boards/stm32/i2c_timing/boards/nucleo_l476rg.overlay b/samples/boards/stm32/i2c_timing/boards/nucleo_l476rg.overlay new file mode 100644 index 0000000000000..a5e6a1ff1cf15 --- /dev/null +++ b/samples/boards/stm32/i2c_timing/boards/nucleo_l476rg.overlay @@ -0,0 +1,10 @@ +/ { + aliases { + i2c-0 = &i2c1; + }; +}; + +&i2c1 { + /delete-property/ clock-frequency; + clock-frequency = ; +}; diff --git a/samples/boards/stm32/i2c_timing/boards/nucleo_wb55rg.overlay b/samples/boards/stm32/i2c_timing/boards/nucleo_wb55rg.overlay new file mode 100644 index 0000000000000..a5e6a1ff1cf15 --- /dev/null +++ b/samples/boards/stm32/i2c_timing/boards/nucleo_wb55rg.overlay @@ -0,0 +1,10 @@ +/ { + aliases { + i2c-0 = &i2c1; + }; +}; + +&i2c1 { + /delete-property/ clock-frequency; + clock-frequency = ; +}; diff --git a/samples/boards/stm32/i2c_timing/prj.conf b/samples/boards/stm32/i2c_timing/prj.conf new file mode 100644 index 0000000000000..f5c70dc8a2047 --- /dev/null +++ b/samples/boards/stm32/i2c_timing/prj.conf @@ -0,0 +1,4 @@ +CONFIG_I2C=y +CONFIG_I2C_STM32_V2_TIMING=y +CONFIG_LOG=y +CONFIG_I2C_LOG_LEVEL_INF=y diff --git a/samples/boards/stm32/i2c_timing/sample.yaml b/samples/boards/stm32/i2c_timing/sample.yaml new file mode 100644 index 0000000000000..aacd13ef98d44 --- /dev/null +++ b/samples/boards/stm32/i2c_timing/sample.yaml @@ -0,0 +1,15 @@ +sample: + name: STM32 I2C V2 timing +tests: + sample.boards.stm32.i2c_timing: + depends_on: i2c + tags: + - drivers + - i2c + filter: dt_compat_enabled("st,stm32-i2c-v2") + platform_allow: nucleo_l476rg nucleo_wb55rg + harness: console + harness_config: + type: one_line + regex: + - "I2C freq. I2C_BITRATE_*" diff --git a/samples/boards/stm32/i2c_timing/src/main.c b/samples/boards/stm32/i2c_timing/src/main.c new file mode 100644 index 0000000000000..41b8dfa2dee25 --- /dev/null +++ b/samples/boards/stm32/i2c_timing/src/main.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + + + +#include +#include + + +#if DT_NODE_HAS_STATUS(DT_ALIAS(i2c_0), okay) +#define I2C_DEV_NODE DT_ALIAS(i2c_0) +#else +#error "Please set the correct I2C device" +#endif + +int main(void) +{ + const struct device *const i2c_dev = DEVICE_DT_GET(I2C_DEV_NODE); + uint32_t i2c_cfg; + + if (!device_is_ready(i2c_dev)) { + printk("I2C device is not ready\n"); + return -1; + } + + /* Verify i2c_get_config() */ + if (i2c_get_config(i2c_dev, (uint32_t *)&i2c_cfg)) { + printk("I2C get_config failed\n"); + return -1; + } + + /* I2C BIT RATE */ + printk("\nI2C freq."); + + if ((I2C_SPEED_GET(i2c_cfg) == 1) && + (DT_PROP(I2C_DEV_NODE, clock_frequency) == 100000)) { + printk(" I2C_BITRATE_STANDARD\n"); + } else if ((I2C_SPEED_GET(i2c_cfg) == 2) && + (DT_PROP(I2C_DEV_NODE, clock_frequency) == 400000)) { + printk(" I2C_BITRATE_FAST\n"); + } else if ((I2C_SPEED_GET(i2c_cfg) == 3) && + (DT_PROP(I2C_DEV_NODE, clock_frequency) == 1000000)) { + printk(" I2C_SPEED_FAST_PLUS\n"); + } else { + printk(" I2C speed mismatch (%d)\n", I2C_SPEED_GET(i2c_cfg)); + } + + return 0; +} diff --git a/samples/boards/stm32/power_mgmt/adc/prj.conf b/samples/boards/stm32/power_mgmt/adc/prj.conf index c5359fe02387d..6c9650f1dfb2b 100644 --- a/samples/boards/stm32/power_mgmt/adc/prj.conf +++ b/samples/boards/stm32/power_mgmt/adc/prj.conf @@ -1,6 +1,6 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n +CONFIG_PM_DEVICE_SYSTEM_MANAGED=y CONFIG_ADC=y #CONFIG_DEBUG=y diff --git a/samples/boards/stm32/power_mgmt/blinky/prj.conf b/samples/boards/stm32/power_mgmt/blinky/prj.conf index fa60e82b4f0a4..6888f24a03f9a 100644 --- a/samples/boards/stm32/power_mgmt/blinky/prj.conf +++ b/samples/boards/stm32/power_mgmt/blinky/prj.conf @@ -1,5 +1,5 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n +CONFIG_PM_DEVICE_SYSTEM_MANAGED=y CONFIG_ASSERT=y diff --git a/samples/boards/stm32/power_mgmt/serial_wakeup/prj.conf b/samples/boards/stm32/power_mgmt/serial_wakeup/prj.conf index ca1e6cf73a9df..526010f5d162d 100644 --- a/samples/boards/stm32/power_mgmt/serial_wakeup/prj.conf +++ b/samples/boards/stm32/power_mgmt/serial_wakeup/prj.conf @@ -1,7 +1,7 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=y +CONFIG_PM_DEVICE_SYSTEM_MANAGED=n CONFIG_SHELL=y diff --git a/samples/boards/stm32/power_mgmt/suspend_to_ram/boards/nucleo_wba55cg.overlay b/samples/boards/stm32/power_mgmt/suspend_to_ram/boards/nucleo_wba55cg.overlay index bf8f1747cffc6..5976dfdbc7600 100644 --- a/samples/boards/stm32/power_mgmt/suspend_to_ram/boards/nucleo_wba55cg.overlay +++ b/samples/boards/stm32/power_mgmt/suspend_to_ram/boards/nucleo_wba55cg.overlay @@ -31,18 +31,6 @@ /* adjust channel number according to pinmux in board.dts */ io-channels = <&adc4 8>; }; - - leds: leds { - compatible = "gpio-leds"; - red_led_3: led_3 { - gpios = <&gpiob 8 GPIO_ACTIVE_LOW>; - label = "User LD2"; - }; - }; - - aliases { - led2 = &red_led_3; - }; }; &lptim1 { diff --git a/samples/boards/stm32/power_mgmt/suspend_to_ram/prj.conf b/samples/boards/stm32/power_mgmt/suspend_to_ram/prj.conf index 78963168c5a81..ce43f3f936fb5 100644 --- a/samples/boards/stm32/power_mgmt/suspend_to_ram/prj.conf +++ b/samples/boards/stm32/power_mgmt/suspend_to_ram/prj.conf @@ -1,7 +1,7 @@ CONFIG_PM=y CONFIG_PM_DEVICE=y CONFIG_PM_DEVICE_RUNTIME=y -CONFIG_PM_DEVICE_RUNTIME_EXCLUSIVE=n +CONFIG_PM_DEVICE_SYSTEM_MANAGED=y CONFIG_PM_S2RAM=y CONFIG_ADC=y CONFIG_ENTROPY_GENERATOR=y diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/CMakeLists.txt b/samples/boards/stm32/power_mgmt/wkup_pins/CMakeLists.txt new file mode 100644 index 0000000000000..f0d58364d27aa --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(stm32_wkup_pins) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/README.rst b/samples/boards/stm32/power_mgmt/wkup_pins/README.rst new file mode 100644 index 0000000000000..3592ca0da55ee --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/README.rst @@ -0,0 +1,38 @@ +.. _gpio-as-a-wkup-pin-src-sample: + +GPIO As A Wake-up Pin Source +############################ + +Overview +******** + +This sample is a minimum application to demonstrate using a wake-up pin with a GPIO as +a source to power on an STM32 SoC after Poweroff. + +The system will power off automatically ``WAIT_TIME_US`` us after boot. +Press the user button designated in boards's devicetree overlay as "wkup-src" to power it on again. + +.. _gpio-as-a-wkup-pin-src-sample-requirements: + +Requirements +************ + +The SoC should support POWEROFF functionality & have a wake-up pin that corresponds +to the GPIO pin of a user button. +To support another board, add an overlay in boards folder. +Make sure that wake-up pins are configured in SoC dtsi file. + +Building and Running +******************** + +Build and flash wkup_pins as follows, changing ``nucleo_u5a5zj_q`` for your board: + +.. zephyr-app-commands:: + :zephyr-app: samples/boards/stm32/power_mgmt/wkup_pins + :board: nucleo_u5a5zj_q + :goals: build flash + :compact: + +After flashing, the LED in ON. +The LED will be turned off when the system is powered off. +Press the user button to power on the system again. diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_l4r5zi.overlay b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_l4r5zi.overlay new file mode 100644 index 0000000000000..8e0cac01094aa --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_l4r5zi.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + wkup-src = &user_button; + }; +}; + +&pwr { + status = "okay"; +}; diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u575zi_q.overlay b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u575zi_q.overlay new file mode 100644 index 0000000000000..8e0cac01094aa --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u575zi_q.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + wkup-src = &user_button; + }; +}; + +&pwr { + status = "okay"; +}; diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u5a5zj_q.overlay b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u5a5zj_q.overlay new file mode 100644 index 0000000000000..8e0cac01094aa --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_u5a5zj_q.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + wkup-src = &user_button; + }; +}; + +&pwr { + status = "okay"; +}; diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_wl55jc.overlay b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_wl55jc.overlay new file mode 100644 index 0000000000000..7c792105d6d55 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/boards/nucleo_wl55jc.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + wkup-src = &user_button_1; + }; +}; + +&pwr { + status = "okay"; +}; diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/prj.conf b/samples/boards/stm32/power_mgmt/wkup_pins/prj.conf new file mode 100644 index 0000000000000..2331687b7894e --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/prj.conf @@ -0,0 +1,2 @@ +CONFIG_POWEROFF=y +CONFIG_STM32_WKUP_PINS=y diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/sample.yaml b/samples/boards/stm32/power_mgmt/wkup_pins/sample.yaml new file mode 100644 index 0000000000000..1fb3ead82e729 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/sample.yaml @@ -0,0 +1,12 @@ +sample: + name: GPIO As A Wake-up Pin Source +tests: + sample.boards.stm32.power_mgmt.wkup_pins: + build_only: true + filter: dt_enabled_alias_with_parent_compat("wkup-src", + "gpio-keys") and dt_compat_enabled("st,stm32-pwr") + platform_allow: + - nucleo_l4r5zi + - nucleo_u575zi_q + - nucleo_u5a5zj_q + - nucleo_wl55jc diff --git a/samples/boards/stm32/power_mgmt/wkup_pins/src/main.c b/samples/boards/stm32/power_mgmt/wkup_pins/src/main.c new file mode 100644 index 0000000000000..2284a76b03561 --- /dev/null +++ b/samples/boards/stm32/power_mgmt/wkup_pins/src/main.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#define WAIT_TIME_US 4000000 + +#define WKUP_SRC_NODE DT_ALIAS(wkup_src) +#if !DT_NODE_HAS_STATUS(WKUP_SRC_NODE, okay) +#error "Unsupported board: wkup_src devicetree alias is not defined" +#endif + +static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(WKUP_SRC_NODE, gpios); + +static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); + +int main(void) +{ + printk("\nWake-up button is connected to %s pin %d\n", button.port->name, button.pin); + + __ASSERT_NO_MSG(gpio_is_ready_dt(&led)); + gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); + gpio_pin_set(led.port, led.pin, 1); + + /* Setup button GPIO pin as a source for exiting Poweroff */ + gpio_pin_configure_dt(&button, STM32_GPIO_WKUP); + + printk("Will wait %ds before powering the system off\n", (WAIT_TIME_US / 1000000)); + k_busy_wait(WAIT_TIME_US); + + printk("Powering off\n"); + printk("Press the user button to power the system on\n\n"); + + sys_poweroff(); + /* Will remain powered off until wake-up or reset button is pressed */ + + return 0; +} diff --git a/samples/drivers/adc/adc_dt/boards/frdm_mcxn947_mcxn947_cpu0.overlay b/samples/drivers/adc/adc_dt/boards/frdm_mcxn947_mcxn947_cpu0.overlay new file mode 100644 index 0000000000000..051e3c1a3a47f --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/frdm_mcxn947_mcxn947_cpu0.overlay @@ -0,0 +1,50 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&lpadc0 0>, <&lpadc0 1>; + }; +}; + +&lpadc0 { + #address-cells = <1>; + #size-cells = <0>; + + /* + * To use this sample: + * LPADC0 CH1A and CH1B are set up in differential mode (B-A) + * - Connect LPADC0 CH1A signal to voltage between 0~1.8V (J8 pin 20) + * - Connect LPADC0 CH1B signal to voltage between 0~1.8V (J8 pin 24) + * LPADC0 CH2A is set up in single ended mode + * - Connect LPADC0 CH2A signal to voltage between 0~1.8V (J8 pin 28) + */ + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <13>; + zephyr,input-positive = ; + zephyr,input-negative = ; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_EXTERNAL1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + zephyr,input-positive = ; + }; +}; diff --git a/samples/drivers/adc/adc_dt/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/adc/adc_dt/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 0000000000000..7c78d5891d4ba --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 7>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.01 */ + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.02 */ + zephyr,resolution = <12>; + zephyr,oversampling = <8>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.03 */ + zephyr,input-negative = ; /* P1.07 */ + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/adc_dt/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/drivers/adc/adc_dt/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 0000000000000..f185624f9b933 --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 7>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.11 */ + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.06 */ + zephyr,resolution = <12>; + zephyr,oversampling = <8>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.13 */ + zephyr,input-negative = ; /* P1.14 */ + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/adc_dt/boards/nucleo_h563zi.overlay b/samples/drivers/adc/adc_dt/boards/nucleo_h563zi.overlay new file mode 100644 index 0000000000000..ad80e9ac5871a --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/nucleo_h563zi.overlay @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024, Vitrolife A/S + */ + + / { + zephyr,user { + /* CN9 pin 1 */ + io-channels = <&adc1 3>; + }; +}; + +&adc1 { + #address-cells = <1>; + #size-cells = <0>; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/adc_dt/boards/rd_rw612_bga.overlay b/samples/drivers/adc/adc_dt/boards/rd_rw612_bga.overlay new file mode 100644 index 0000000000000..32098b10883ce --- /dev/null +++ b/samples/drivers/adc/adc_dt/boards/rd_rw612_bga.overlay @@ -0,0 +1,38 @@ +/* + * Copyright 2022 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc0 0 &adc0 1>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <16>; + zephyr,input-positive = ; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <16>; + zephyr,input-positive = ; + }; +}; diff --git a/samples/drivers/adc/adc_dt/boards/efm32pg_stk3402a.overlay b/samples/drivers/adc/adc_dt/boards/slstk3402a.overlay similarity index 100% rename from samples/drivers/adc/adc_dt/boards/efm32pg_stk3402a.overlay rename to samples/drivers/adc/adc_dt/boards/slstk3402a.overlay diff --git a/samples/drivers/adc/adc_dt/frdm_rw612.overlay b/samples/drivers/adc/adc_dt/frdm_rw612.overlay new file mode 100644 index 0000000000000..32098b10883ce --- /dev/null +++ b/samples/drivers/adc/adc_dt/frdm_rw612.overlay @@ -0,0 +1,38 @@ +/* + * Copyright 2022 NXP + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/ { + zephyr,user { + /* adjust channel number according to pinmux in board.dts */ + io-channels = <&adc0 0 &adc0 1>; + }; +}; + +&adc0 { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <16>; + zephyr,input-positive = ; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_VDD_1"; + zephyr,vref-mv = <1800>; + zephyr,acquisition-time = ; + zephyr,resolution = <16>; + zephyr,input-positive = ; + }; +}; diff --git a/samples/drivers/adc/adc_dt/sample.yaml b/samples/drivers/adc/adc_dt/sample.yaml index a4d6c8f5fea03..48c4e3181eb36 100644 --- a/samples/drivers/adc/adc_dt/sample.yaml +++ b/samples/drivers/adc/adc_dt/sample.yaml @@ -15,6 +15,8 @@ tests: - stm32h735g_disco - nrf51dk/nrf51822 - nrf52840dk/nrf52840 + - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp - mec172xevb_assy6906 - gd32f350r_eval - gd32f450i_eval @@ -29,6 +31,7 @@ tests: - mr_canhubk3 - longan_nano - longan_nano/gd32vf103/lite + - rd_rw612_bga integration_platforms: - nucleo_l073rz - nrf52840dk/nrf52840 diff --git a/samples/drivers/adc/adc_dt/src/main.c b/samples/drivers/adc/adc_dt/src/main.c index 0f781eac7000e..cb607a0ff0d17 100644 --- a/samples/drivers/adc/adc_dt/src/main.c +++ b/samples/drivers/adc/adc_dt/src/main.c @@ -54,7 +54,11 @@ int main(void) } } +#ifndef CONFIG_COVERAGE while (1) { +#else + for (int k = 0; k < 10; k++) { +#endif printk("ADC reading[%u]:\n", count++); for (size_t i = 0U; i < ARRAY_SIZE(adc_channels); i++) { int32_t val_mv; diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 0000000000000..5f7e20136b49c --- /dev/null +++ b/samples/drivers/adc/adc_sequence/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + */ + +/ { + aliases { + adc0 = &adc; + }; +}; + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 7>; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.01 */ + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.02 */ + zephyr,resolution = <12>; + zephyr,oversampling = <8>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1_2"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.03 */ + zephyr,input-negative = ; /* P1.07 */ + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/adc_sequence/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/drivers/adc/adc_sequence/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 0000000000000..a0639a405c405 --- /dev/null +++ b/samples/drivers/adc/adc_sequence/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,51 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024 Nordic Semiconductor ASA + */ + +/ { + zephyr,user { + io-channels = <&adc 0>, <&adc 1>, <&adc 7>; + }; +}; + +/ { + aliases { + adc0 = &adc; + }; +}; + +&adc { + #address-cells = <1>; + #size-cells = <0>; + + channel@0 { + reg = <0>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.11 */ + zephyr,resolution = <10>; + }; + + channel@1 { + reg = <1>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.06 */ + zephyr,resolution = <12>; + zephyr,oversampling = <8>; + }; + + channel@7 { + reg = <7>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,input-positive = ; /* P1.13 */ + zephyr,input-negative = ; /* P1.14 */ + zephyr,resolution = <12>; + }; +}; diff --git a/samples/drivers/adc/adc_sequence/sample.yaml b/samples/drivers/adc/adc_sequence/sample.yaml index f9f657b4fbb00..cec7ee09bc825 100644 --- a/samples/drivers/adc/adc_sequence/sample.yaml +++ b/samples/drivers/adc/adc_sequence/sample.yaml @@ -9,6 +9,8 @@ tests: - cy8cproto_063_ble - cy8cproto_062_4343w - nrf52840dk/nrf52840 + - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf52840dk/nrf52840 harness: console @@ -16,6 +18,6 @@ tests: harness_config: type: multi_line regex: - - "ADC sequence reading\\[\\d+\\]:" + - "ADC sequence reading \\[\\d+\\]:" - "- .+, channel \\d+, \\d+ sequence samples:" - "- - \\d+ (= \\d+mV)|(\\(value in mV not available\\))" diff --git a/samples/drivers/adc/adc_sequence/src/main.c b/samples/drivers/adc/adc_sequence/src/main.c index 9dda1acfb4672..0e401f9cc340e 100644 --- a/samples/drivers/adc/adc_sequence/src/main.c +++ b/samples/drivers/adc/adc_sequence/src/main.c @@ -56,7 +56,11 @@ int main(void) } } +#ifndef CONFIG_COVERAGE while (1) { +#else + for (int k = 0; k < 10; k++) { +#endif printf("ADC sequence reading [%u]:\n", count++); k_msleep(1000); diff --git a/samples/drivers/charger/README.rst b/samples/drivers/charger/README.rst index 2399b0061c09a..2dc69e26dde56 100644 --- a/samples/drivers/charger/README.rst +++ b/samples/drivers/charger/README.rst @@ -7,4 +7,18 @@ Overview ******** -This sample demonstrates how to use the :ref:`charger_api`. +This sample demonstrates how to use the :ref:`charger_api` API. + +The sample application performs a simple charging task loop. + +- The application will first poll for external power provided to the charger device. +- If power is provided to the charger, then the sample application will attempt to enable the charge + cycle. +- After the charge cycle is initiated, the sample application will check the status property of the + charger device and report any relevant information to the log. +- Once the charger device reports that the charge cycle has completed, the application returns. + +Note that this sample terminates once the charge cycle completes and does not attempt to "top-off" +the battery pack. Additionally, the sample intentionally does not respond to the reported charger +health state and the implications the environment may have on the charge cycle execution. The +responsibility of responding to these events falls on the user or the charger device implementation. diff --git a/samples/drivers/clock_control_litex/README.rst b/samples/drivers/clock_control_litex/README.rst index c2fa951bd3803..0a7d7878cb2b5 100644 --- a/samples/drivers/clock_control_litex/README.rst +++ b/samples/drivers/clock_control_litex/README.rst @@ -21,16 +21,22 @@ Configuration Basic configuration of the driver, including default settings for clock outputs, is held in Device Tree clock control nodes. .. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi + :language: dts :start-at: clk0: clock-controller@0 { :end-at: }; + :dedent: .. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi + :language: dts :start-at: clk1: clock-controller@1 { :end-at: }; + :dedent: .. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi + :language: dts :start-at: clock0: clock@e0004800 { :end-at: }; + :dedent: This configuration defines 2 clock outputs: ``clk0`` and ``clk1`` with default frequency set to 100MHz, 0 degrees phase offset and 50% duty cycle. Special care should be taken when defining values for FPGA-specific configuration (parameters from ``litex,divclk-divide-min`` to ``litex,vco-margin``). diff --git a/samples/drivers/counter/maxim_ds3231/README.rst b/samples/drivers/counter/maxim_ds3231/README.rst index ee870006b4b3c..b0534c806c55f 100644 --- a/samples/drivers/counter/maxim_ds3231/README.rst +++ b/samples/drivers/counter/maxim_ds3231/README.rst @@ -145,7 +145,7 @@ corresponding devicetree overlay. .. zephyr-app-commands:: :zephyr-app: samples/drivers/counter/maxim_ds3231 - :board: efr32mg_sltb004a + :board: sltb004a :goals: build :compact: diff --git a/samples/drivers/counter/maxim_ds3231/boards/efr32mg_sltb004a.overlay b/samples/drivers/counter/maxim_ds3231/boards/sltb004a.overlay similarity index 100% rename from samples/drivers/counter/maxim_ds3231/boards/efr32mg_sltb004a.overlay rename to samples/drivers/counter/maxim_ds3231/boards/sltb004a.overlay diff --git a/samples/drivers/counter/maxim_ds3231/sample.yaml b/samples/drivers/counter/maxim_ds3231/sample.yaml index bf32d825e7a4c..238b7a2c816e3 100644 --- a/samples/drivers/counter/maxim_ds3231/sample.yaml +++ b/samples/drivers/counter/maxim_ds3231/sample.yaml @@ -6,10 +6,10 @@ tests: sample.basic.maxim_ds3231: build_only: true platform_allow: - - efr32mg_sltb004a + - sltb004a - frdm_k64f - nrf51dk/nrf51822 - nucleo_l476rg - particle_xenon integration_platforms: - - efr32mg_sltb004a + - sltb004a diff --git a/samples/drivers/crypto/boards/da1469x_dk_pro.overlay b/samples/drivers/crypto/boards/da1469x_dk_pro.overlay new file mode 100644 index 0000000000000..873bafe029d2f --- /dev/null +++ b/samples/drivers/crypto/boards/da1469x_dk_pro.overlay @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2023 Renesas Electronics Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&crypto { + status = "okay"; +}; diff --git a/samples/drivers/crypto/prj_mtls_shim.conf b/samples/drivers/crypto/prj_mtls_shim.conf index c72b663fcf5fb..71d350424a3be 100644 --- a/samples/drivers/crypto/prj_mtls_shim.conf +++ b/samples/drivers/crypto/prj_mtls_shim.conf @@ -1,6 +1,7 @@ CONFIG_MBEDTLS=y CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_HEAP_SIZE=512 +CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y CONFIG_MBEDTLS_CIPHER_GCM_ENABLED=y diff --git a/samples/drivers/crypto/src/main.c b/samples/drivers/crypto/src/main.c index 38205ef5df619..1d65cbd3c7706 100644 --- a/samples/drivers/crypto/src/main.c +++ b/samples/drivers/crypto/src/main.c @@ -29,6 +29,8 @@ LOG_MODULE_REGISTER(main); #define CRYPTO_DEV_COMPAT nxp_mcux_dcp #elif CONFIG_CRYPTO_NRF_ECB #define CRYPTO_DEV_COMPAT nordic_nrf_ecb +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_smartbond_crypto) +#define CRYPTO_DEV_COMPAT renesas_smartbond_crypto #else #error "You need to enable one crypto device" #endif @@ -65,7 +67,7 @@ static void print_buffer_comparison(const uint8_t *wanted_result, } } - printk("\n But got:\n"); + printk("\nBut got:\n"); for (i = 0, j = 1; i < length; i++, j++) { printk("0x%02x ", result[i]); diff --git a/samples/drivers/dac/boards/frdm_rw612.overlay b/samples/drivers/dac/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..008f7e3b4ea21 --- /dev/null +++ b/samples/drivers/dac/boards/frdm_rw612.overlay @@ -0,0 +1,12 @@ +/ { + zephyr,user { + dac = <&dac0>; + dac-channel-id = <1>; + dac-resolution = <10>; + }; +}; + +&dac0 { + nxp,conversion-rate = "500K"; + nxp,output-voltage-range = "large"; +}; diff --git a/samples/drivers/dac/boards/rd_rw612_bga.overlay b/samples/drivers/dac/boards/rd_rw612_bga.overlay new file mode 100644 index 0000000000000..55409f2be1867 --- /dev/null +++ b/samples/drivers/dac/boards/rd_rw612_bga.overlay @@ -0,0 +1,12 @@ +/ { + zephyr,user { + dac = <&dac0>; + dac-channel-id = <0>; + dac-resolution = <10>; + }; +}; + +&dac0 { + nxp,conversion-rate = "500K"; + nxp,output-voltage-range = "large"; +}; diff --git a/samples/drivers/dac/sample.yaml b/samples/drivers/dac/sample.yaml index e83c20d5fc0ff..9c7a53beef1f3 100644 --- a/samples/drivers/dac/sample.yaml +++ b/samples/drivers/dac/sample.yaml @@ -43,6 +43,7 @@ tests: - stm32l562e_dk - twr_ke18f - lpcxpresso55s36 + - rd_rw612_bga depends_on: dac integration_platforms: - nucleo_l152re diff --git a/samples/drivers/display/sample.yaml b/samples/drivers/display/sample.yaml index 50038edf93936..33d72e11c740b 100644 --- a/samples/drivers/display/sample.yaml +++ b/samples/drivers/display/sample.yaml @@ -88,12 +88,6 @@ tests: harness: console harness_config: fixture: fixture_display - sample.display.mcux_elcdif: - platform_allow: mimxrt1050_evk - tags: display - harness: console - harness_config: - fixture: fixture_display sample.display.mcux_dcnano_lcdif: platform_allow: mimxrt595_evk/mimxrt595s/cm33 tags: display @@ -175,3 +169,25 @@ tests: harness: console harness_config: fixture: fixture_display + sample.display.rk043fn66hs_ctg: + platform_allow: + - mimxrt1064_evk + - mimxrt1060_evk + - mimxrt1050_evk + - mimxrt1040_evk + tags: display + harness: console + extra_args: SHIELD=rk043fn66hs_ctg + harness_config: + fixture: fixture_display + sample.display.rk043fn02h_ct: + platform_allow: + - mimxrt1064_evk + - mimxrt1060_evk + - mimxrt1050_evk + - mimxrt1040_evk + tags: display + harness: console + extra_args: SHIELD=rk043fn02h_ct + harness_config: + fixture: fixture_display diff --git a/samples/drivers/espi/boards/mec15xxevb_assy6853.conf b/samples/drivers/espi/boards/mec15xxevb_assy6853.conf index 62985ba39b6f0..fe4958b7645c3 100644 --- a/samples/drivers/espi/boards/mec15xxevb_assy6853.conf +++ b/samples/drivers/espi/boards/mec15xxevb_assy6853.conf @@ -5,7 +5,7 @@ CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100 CONFIG_ESPI_AUTOMATIC_WARNING_ACKNOWLEDGE=n # Sample code doesn't handle ACPI host communication CONFIG_ESPI_PERIPHERAL_HOST_IO=n -# Test SAF flash portal read/erase/write on EVB -CONFIG_ESPI_SAF=y +# Test TAF flash portal read/erase/write on EVB +CONFIG_ESPI_TAF=y CONFIG_SPI=y CONFIG_SPI_XEC_QMSPI=y diff --git a/samples/drivers/espi/boards/mec172xevb_assy6906.conf b/samples/drivers/espi/boards/mec172xevb_assy6906.conf index ecdb27d5f61e9..de64ab5da4635 100644 --- a/samples/drivers/espi/boards/mec172xevb_assy6906.conf +++ b/samples/drivers/espi/boards/mec172xevb_assy6906.conf @@ -7,7 +7,7 @@ CONFIG_LOG_PROCESS_THREAD_SLEEP_MS=100 CONFIG_ESPI_AUTOMATIC_WARNING_ACKNOWLEDGE=n # Sample code doesn't handle ACPI host communication CONFIG_ESPI_PERIPHERAL_HOST_IO=n -# Test SAF flash portal read/erase/write on EVB -CONFIG_ESPI_SAF=y +# Test TAF flash portal read/erase/write on EVB +CONFIG_ESPI_TAF=y CONFIG_SPI=y CONFIG_SPI_XEC_QMSPI_LDMA=y diff --git a/samples/drivers/espi/src/main.c b/samples/drivers/espi/src/main.c index a51b79776af66..fff0998459dbb 100644 --- a/samples/drivers/espi/src/main.c +++ b/samples/drivers/espi/src/main.c @@ -16,7 +16,7 @@ /* OOB operations will be attempted regardless of channel enabled or not */ #include "espi_oob_handler.h" -#ifdef CONFIG_ESPI_SAF +#ifdef CONFIG_ESPI_TAF #include #endif @@ -65,7 +65,7 @@ static uint8_t flash_write_buf[MAX_TEST_BUF_SIZE]; static uint8_t flash_read_buf[MAX_TEST_BUF_SIZE]; #endif -#ifdef CONFIG_ESPI_SAF +#ifdef CONFIG_ESPI_TAF #define SAF_BASE_ADDR DT_REG_ADDR(DT_NODELABEL(espi_saf0)) #define SAF_TEST_FREQ_HZ 24000000U @@ -128,7 +128,7 @@ static const struct espi_saf_flash_cfg flash_w25q128 = { * by QMSPI driver. * Use SAF hardware default TAG map. */ -#ifdef CONFIG_ESPI_SAF_XEC_V2 +#ifdef CONFIG_ESPI_TAF_XEC_V2 static const struct espi_saf_cfg saf_cfg1 = { .nflash_devices = 1U, .hwcfg = {.version = 2U, /* TODO */ @@ -757,7 +757,7 @@ int espi_saf_test1(uint32_t spi_addr) return rc; } -#endif /* CONFIG_ESPI_SAF */ +#endif /* CONFIG_ESPI_TAF */ static void host_warn_handler(uint32_t signal, uint32_t status) { @@ -1187,7 +1187,7 @@ int espi_test(void) return -ENODEV; } -#ifdef CONFIG_ESPI_SAF +#ifdef CONFIG_ESPI_TAF if (!device_is_ready(qspi_dev)) { LOG_ERR("%s: device not ready.", qspi_dev->name); return -ENODEV; @@ -1223,7 +1223,7 @@ int espi_test(void) espi_init(); -#ifdef CONFIG_ESPI_SAF +#ifdef CONFIG_ESPI_TAF /* * eSPI SAF configuration must be after eSPI configuration. * eSPI SAF EC portal flash tests before EC releases RSMRST# and diff --git a/samples/drivers/flash_shell/sample.yaml b/samples/drivers/flash_shell/sample.yaml index cd19cdad656fc..2481013c2f5a1 100644 --- a/samples/drivers/flash_shell/sample.yaml +++ b/samples/drivers/flash_shell/sample.yaml @@ -9,6 +9,8 @@ tests: filter: CONFIG_FLASH_HAS_DRIVER_ENABLED platform_exclude: - nucleo_h745zi_q/stm32h745xx/m4 + - stm32h7s78_dk + - stm32h745i_disco/stm32h745xx/m4 - stm32h747i_disco/stm32h747xx/m4 - gd32f350r_eval - arduino_portenta_h7/stm32h747xx/m4 diff --git a/samples/drivers/jesd216/README.rst b/samples/drivers/jesd216/README.rst index 71887480a58ee..1b9492f619b91 100644 --- a/samples/drivers/jesd216/README.rst +++ b/samples/drivers/jesd216/README.rst @@ -20,7 +20,7 @@ supports :kconfig:option:`CONFIG_FLASH_JESD216_API`. .. zephyr-app-commands:: :zephyr-app: samples/drivers/jesd216 - :board: efr32mg_sltb004a + :board: sltb004a :goals: build flash :compact: diff --git a/samples/drivers/jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay deleted file mode 100644 index b8f138ad2b2e2..0000000000000 --- a/samples/drivers/jesd216/boards/nrf54h20dk_nrf54h20_cpuapp.overlay +++ /dev/null @@ -1,9 +0,0 @@ -/* - * Copyright (c) 2024 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&mx25uw63 { - status = "okay"; -}; diff --git a/samples/drivers/jesd216/sample.yaml b/samples/drivers/jesd216/sample.yaml index 4ab18259153c7..c2742a68d4644 100644 --- a/samples/drivers/jesd216/sample.yaml +++ b/samples/drivers/jesd216/sample.yaml @@ -29,5 +29,7 @@ tests: integration_platforms: - nrf52840dk/nrf52840 sample.drivers.stm32.jesd216: - filter: dt_compat_enabled("st,stm32-ospi-nor") or dt_compat_enabled("st,stm32-qspi-nor") + filter: dt_compat_enabled("st,stm32-xspi-nor") + or dt_compat_enabled("st,stm32-ospi-nor") + or dt_compat_enabled("st,stm32-qspi-nor") depends_on: spi diff --git a/samples/drivers/jesd216/src/main.c b/samples/drivers/jesd216/src/main.c index 92dd10208dd24..7450df86ed277 100644 --- a/samples/drivers/jesd216/src/main.c +++ b/samples/drivers/jesd216/src/main.c @@ -20,6 +20,8 @@ #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_qspi_nor) #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_ospi_nor) #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_ospi_nor) +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_xspi_nor) +#define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(st_stm32_xspi_nor) #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_s32_qspi_nor) #define FLASH_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(nxp_s32_qspi_nor) #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_imx_flexspi_nor) diff --git a/samples/drivers/led_is31fl3194/CMakeLists.txt b/samples/drivers/led_is31fl3194/CMakeLists.txt new file mode 100644 index 0000000000000..ed52c77a3fd0e --- /dev/null +++ b/samples/drivers/led_is31fl3194/CMakeLists.txt @@ -0,0 +1,7 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(led_is31fl3194) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/drivers/led_is31fl3194/README.rst b/samples/drivers/led_is31fl3194/README.rst new file mode 100644 index 0000000000000..0773587a4f80e --- /dev/null +++ b/samples/drivers/led_is31fl3194/README.rst @@ -0,0 +1,28 @@ +.. zephyr:code-sample:: is31fl3194 + :name: IS31FL3194 RGB LED + :relevant-api: led_interface + + Cycle colors on an RGB LED connected to the IS31FL3194 using the LED API. + +Overview +******** + +This sample cycles several colors on an RGB LED forever using the LED API. + +Building and Running +******************** + +This sample can be built and executed on an Arduino Nicla Sense ME, or on +any board where the devicetree has an I2C device node with compatible +:dtcompatible:`issi,is31fl3194` enabled, along with the relevant bus +controller node also being enabled. + +.. zephyr-app-commands:: + :zephyr-app: samples/drivers/led/issi_is31fl3194 + :board: arduino_nicla_sense_me + :goals: build flash + :compact: + +After flashing, the LED starts to switch colors and messages with the current +LED color are printed on the console. If a runtime error occurs, the sample +exits without printing to the console. diff --git a/samples/drivers/led_is31fl3194/prj.conf b/samples/drivers/led_is31fl3194/prj.conf new file mode 100644 index 0000000000000..555740ded902d --- /dev/null +++ b/samples/drivers/led_is31fl3194/prj.conf @@ -0,0 +1,2 @@ +CONFIG_LED=y +CONFIG_LOG=y diff --git a/samples/drivers/led_is31fl3194/sample.yaml b/samples/drivers/led_is31fl3194/sample.yaml new file mode 100644 index 0000000000000..0cb932b05d2ee --- /dev/null +++ b/samples/drivers/led_is31fl3194/sample.yaml @@ -0,0 +1,10 @@ +sample: + description: Demonstration of the IS31FL3194 LED driver + name: is31fl3194 sample +tests: + sample.drivers.led.is31fl3194: + filter: dt_compat_enabled("issi,is31fl3194") + tags: LED + depends_on: i2c + integration_platforms: + - arduino_nicla_sense_me diff --git a/samples/drivers/led_is31fl3194/src/main.c b/samples/drivers/led_is31fl3194/src/main.c new file mode 100644 index 0000000000000..335d152101b0f --- /dev/null +++ b/samples/drivers/led_is31fl3194/src/main.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +/* 1000 msec = 1 sec */ +#define SLEEP_TIME_MS 1000 + +/* Structure describing a color by its component values and name */ +struct color_data { + uint8_t r, g, b; + const char *name; +}; + +/* The sequence of colors the RGB LED will display */ +static const struct color_data color_sequence[] = { + { 0xFF, 0x00, 0x00, "Red" }, + { 0x00, 0xFF, 0x00, "Green" }, + { 0x00, 0x00, 0xFF, "Blue" }, + { 0xFF, 0xFF, 0xFF, "White" }, + { 0xFF, 0xFF, 0x00, "Yellow" }, + { 0xFF, 0x00, 0xFF, "Purple" }, + { 0x00, 0xFF, 0xFF, "Cyan" }, + { 0xF4, 0x79, 0x20, "Orange" }, +}; + +/* + * A build error on this line means your board is unsupported. + */ +const struct device *led = DEVICE_DT_GET_ANY(issi_is31fl3194); + +int main(void) +{ + int ret; + int i = 0; + + if (!device_is_ready(led)) { + return 0; + } + + while (1) { + ret = led_set_color(led, 0, 3, &(color_sequence[i].r)); + if (ret < 0) { + return 0; + } + + printk("LED color: %s\n", color_sequence[i].name); + k_msleep(SLEEP_TIME_MS); + i = (i + 1) % ARRAY_SIZE(color_sequence); + } + + return 0; +} diff --git a/samples/drivers/led_strip/Kconfig b/samples/drivers/led_strip/Kconfig index 2931d4cc929b8..fdf12abde2446 100644 --- a/samples/drivers/led_strip/Kconfig +++ b/samples/drivers/led_strip/Kconfig @@ -9,14 +9,6 @@ config SAMPLE_LED_UPDATE_DELAY help Delay between LED updates in ms. -config SAMPLE_LED_STRIP_LENGTH - int "LED strip length" - default 0 - help - Number of LEDs in the strip. - If the value is zero, use the 'chain-length' property in - devicetree instead to determine LED numbers. - endmenu source "Kconfig.zephyr" diff --git a/samples/drivers/led_strip/README.rst b/samples/drivers/led_strip/README.rst index a6b0032792634..27c211e24e403 100644 --- a/samples/drivers/led_strip/README.rst +++ b/samples/drivers/led_strip/README.rst @@ -65,9 +65,6 @@ Building and Running The sample updates the LED strip periodically. The update frequency can be modified by changing the :kconfig:option:`CONFIG_SAMPLE_LED_UPDATE_DELAY`. -If there is no chain-length property in the devicetree node, you need to set -the number of LEDs in the :kconfig:option:`CONFIG_SAMPLE_LED_STRIP_LENGTH` option. - Then build and flash the application: .. zephyr-app-commands:: diff --git a/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.conf b/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.conf index 49fc84a0a95fc..0232f7d97c347 100644 --- a/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.conf +++ b/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.conf @@ -1,3 +1 @@ CONFIG_SPI_STM32_INTERRUPT=y - -CONFIG_SAMPLE_LED_STRIP_LENGTH=1 diff --git a/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.overlay b/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.overlay index b4be11a83a9e8..49bee930cca93 100644 --- a/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.overlay +++ b/samples/drivers/led_strip/boards/96b_carbon_stm32f401xe.overlay @@ -4,12 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &spi2 { lpd8806: lpd8806@0 { compatible = "greeled,lpd8806"; reg = <0>; spi-max-frequency = <2000000>; + chain-length = <1>; + color-mapping = ; }; }; diff --git a/samples/drivers/led_strip/boards/adafruit_itsybitsy.conf b/samples/drivers/led_strip/boards/adafruit_itsybitsy.conf deleted file mode 100644 index 9c347a3558884..0000000000000 --- a/samples/drivers/led_strip/boards/adafruit_itsybitsy.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SAMPLE_LED_STRIP_LENGTH=4 diff --git a/samples/drivers/led_strip/boards/adafruit_trinket_m0.conf b/samples/drivers/led_strip/boards/adafruit_trinket_m0.conf deleted file mode 100644 index af9d53eddc073..0000000000000 --- a/samples/drivers/led_strip/boards/adafruit_trinket_m0.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SAMPLE_LED_STRIP_LENGTH=1 diff --git a/samples/drivers/led_strip/boards/blueclover_plt_demo_v2_nrf52832.conf b/samples/drivers/led_strip/boards/blueclover_plt_demo_v2_nrf52832.conf index e4aff43aee811..a97acd9ffab89 100644 --- a/samples/drivers/led_strip/boards/blueclover_plt_demo_v2_nrf52832.conf +++ b/samples/drivers/led_strip/boards/blueclover_plt_demo_v2_nrf52832.conf @@ -1,3 +1,2 @@ # Enable LED 5V Regulator CONFIG_REGULATOR=y -CONFIG_SAMPLE_LED_STRIP_LENGTH=4 diff --git a/samples/drivers/led_strip/boards/nucleo_l432kc.conf b/samples/drivers/led_strip/boards/nucleo_l432kc.conf deleted file mode 100644 index af9d53eddc073..0000000000000 --- a/samples/drivers/led_strip/boards/nucleo_l432kc.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_SAMPLE_LED_STRIP_LENGTH=1 diff --git a/samples/drivers/led_strip/boards/nucleo_l432kc.overlay b/samples/drivers/led_strip/boards/nucleo_l432kc.overlay index 0a7fce2fe75ed..383637d77173d 100644 --- a/samples/drivers/led_strip/boards/nucleo_l432kc.overlay +++ b/samples/drivers/led_strip/boards/nucleo_l432kc.overlay @@ -4,12 +4,18 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + &spi1 { apa102: apa102@0 { compatible = "apa,apa102"; reg = <0>; spi-max-frequency = <5250000>; + chain-length = <1>; + color-mapping = ; }; }; diff --git a/samples/drivers/led_strip/boards/xiao_rp2040.conf b/samples/drivers/led_strip/boards/xiao_rp2040.conf new file mode 100644 index 0000000000000..8230eb9896b4f --- /dev/null +++ b/samples/drivers/led_strip/boards/xiao_rp2040.conf @@ -0,0 +1,2 @@ +CONFIG_GPIO=y +CONFIG_GPIO_HOGS=y diff --git a/samples/drivers/led_strip/src/main.c b/samples/drivers/led_strip/src/main.c index d6dafcd68ea92..45e8fad35cd9d 100644 --- a/samples/drivers/led_strip/src/main.c +++ b/samples/drivers/led_strip/src/main.c @@ -21,9 +21,7 @@ LOG_MODULE_REGISTER(main); #define STRIP_NODE DT_ALIAS(led_strip) -#if CONFIG_SAMPLE_LED_STRIP_LENGTH != 0 -#define STRIP_NUM_PIXELS CONFIG_SAMPLE_LED_STRIP_LENGTH -#elif DT_NODE_HAS_PROP(DT_ALIAS(led_strip), chain_length) +#if DT_NODE_HAS_PROP(DT_ALIAS(led_strip), chain_length) #define STRIP_NUM_PIXELS DT_PROP(DT_ALIAS(led_strip), chain_length) #else #error Unable to determine length of LED strip diff --git a/samples/drivers/mbox/CMakeLists.txt b/samples/drivers/mbox/CMakeLists.txt index d279843dacd24..3ca0508ab8c64 100644 --- a/samples/drivers/mbox/CMakeLists.txt +++ b/samples/drivers/mbox/CMakeLists.txt @@ -17,7 +17,8 @@ if(CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP OR CONFIG_BOARD_MIMXRT1170_EVK_MIMXRT1176_CM7 OR CONFIG_BOARD_MIMXRT1160_EVK_MIMXRT1166_CM7 OR CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU0 OR - CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP) + CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUAPP OR + CONFIG_BOARD_STM32H747I_DISCO_STM32H747XX_M7) message(STATUS "${BOARD}${BOARD_QUALIFIERS} compile as Main in this sample") else() message(FATAL_ERROR "${BOARD}${BOARD_QUALIFIERS} is not supported for this sample") diff --git a/samples/drivers/mbox/Kconfig.sysbuild b/samples/drivers/mbox/Kconfig.sysbuild index b8d7e17c29a36..c89a6f7b3f78b 100644 --- a/samples/drivers/mbox/Kconfig.sysbuild +++ b/samples/drivers/mbox/Kconfig.sysbuild @@ -15,3 +15,4 @@ string default "mimxrt1160_evk/mimxrt1166/cm4" if $(BOARD) = "mimxrt1160_evk" default "lpcxpresso55s69/lpc55s69/cpu1" if $(BOARD) = "lpcxpresso55s69" default "nrf54h20dk/nrf54h20/cpuppr" if $(BOARD) = "nrf54h20dk" + default "stm32h747i_disco/stm32h747xx/m4" if $(BOARD) = "stm32h747i_disco" diff --git a/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.conf b/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.conf new file mode 100644 index 0000000000000..acba758575a87 --- /dev/null +++ b/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.conf @@ -0,0 +1 @@ +CONFIG_MBOX_STM32_HSEM=y diff --git a/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.overlay b/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.overlay new file mode 100644 index 0000000000000..d86cbbc2d42ea --- /dev/null +++ b/samples/drivers/mbox/boards/stm32h747i_disco_stm32h747xx_m7.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + mbox-consumer { + compatible = "vnd,mbox-consumer"; + mboxes = <&mailbox 11>, <&mailbox 10>; + mbox-names = "tx", "rx"; + }; +}; + +&mailbox { + status = "okay"; +}; diff --git a/samples/drivers/mbox/remote/CMakeLists.txt b/samples/drivers/mbox/remote/CMakeLists.txt index 9c19a0e8b4695..9bc1c67a61c08 100644 --- a/samples/drivers/mbox/remote/CMakeLists.txt +++ b/samples/drivers/mbox/remote/CMakeLists.txt @@ -15,7 +15,8 @@ if(CONFIG_BOARD_NRF5340DK_NRF5340_CPUNET OR CONFIG_BOARD_MIMXRT1170_EVK_MIMXRT1176_CM4 OR CONFIG_BOARD_MIMXRT1160_EVK_MIMXRT1166_CM4 OR CONFIG_BOARD_LPCXPRESSO55S69_LPC55S69_CPU1 OR - CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUPPR) + CONFIG_BOARD_NRF54H20DK_NRF54H20_CPUPPR OR + CONFIG_BOARD_STM32H747I_DISCO_STM32H747XX_M4) message(STATUS "${BOARD}${BOARD_QUALIFIERS} compile as remote in this sample") else() message(FATAL_ERROR "${BOARD}${BOARD_QUALIFIERS} is not supported for this sample") diff --git a/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf b/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf new file mode 100644 index 0000000000000..110236f8fbde8 --- /dev/null +++ b/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf @@ -0,0 +1,5 @@ +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_LOG_BACKEND_UART=y + +CONFIG_MBOX_STM32_HSEM=y diff --git a/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay b/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay new file mode 100644 index 0000000000000..c39e05aeb9c8d --- /dev/null +++ b/samples/drivers/mbox/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + zephyr,console = &uart8; + zephyr,shell-uart = &uart8; + }; + + mbox-consumer { + compatible = "vnd,mbox-consumer"; + mboxes = <&mailbox 10>, <&mailbox 11>; + mbox-names = "tx", "rx"; + }; +}; + +&uart8 { + status = "okay"; +}; + +&mailbox { + status = "okay"; +}; diff --git a/samples/drivers/memc/boards/rd_rw612_bga.conf b/samples/drivers/memc/boards/rd_rw612_bga.conf index 60bfc1c626249..f76b8554671c6 100644 --- a/samples/drivers/memc/boards/rd_rw612_bga.conf +++ b/samples/drivers/memc/boards/rd_rw612_bga.conf @@ -1,5 +1,22 @@ # Copyright 2023 NXP # SPDX-License-Identifier: Apache-2.0 -# RW is configured to execute from code ram, so use rom loader to load image -CONFIG_NXP_RW_ROM_RAMLOADER=y +# In order to safely access the PSRAM on port B of the RW FlexSPI peripheral, +# the QSPI flash on port A must be configured by the application. Otherwise, +# the PSRAM configuration will overwrite the LUT entries for the QSPI flash, +# and the application will no longer be able to XIP from the flash. +# To make sure the QSPI flash is configured, enable flash drivers. +CONFIG_FLASH=y + +# Initialization priorities are critical here. The FlexSPI MEMC driver must +# initialize first. Then, the QSPI flash driver must initialize to program +# the LUT table for port A. Finally, the PSRAM driver can initialize and +# program the LUT table for port B +CONFIG_MEMC_MCUX_FLEXSPI_INIT_PRIORITY=0 +CONFIG_FLASH_INIT_PRIORITY=50 +CONFIG_MEMC_INIT_PRIORITY=60 + +# This board has the PSRAM attached to the same FLEXSPI device as the flash +# chip used for XIP, so we must explicitly enable the FLEXSPI MEMC driver +# to reconfigure the flash device it is executing from +CONFIG_MEMC_MCUX_FLEXSPI_INIT_XIP=y diff --git a/samples/drivers/memc/boards/rd_rw612_bga.overlay b/samples/drivers/memc/boards/rd_rw612_bga.overlay index d02a07662da1a..e32be713e3b88 100644 --- a/samples/drivers/memc/boards/rd_rw612_bga.overlay +++ b/samples/drivers/memc/boards/rd_rw612_bga.overlay @@ -5,10 +5,6 @@ */ / { - chosen { - zephyr,flash = &sram_code; - }; - aliases { sram-ext = &is66wvq8m4; }; @@ -17,3 +13,30 @@ &is66wvq8m4 { status = "okay"; }; + +&pinctrl { + pinmux_flexspi_safe: pinmux-flexspi-safe { + group0 { + pinmux = ; + slew-rate = "normal"; + }; + + group1 { + pinmux = ; + slew-rate = "normal"; + bias-pull-down; + }; + }; +}; + +/* Override pin control state to use one that only changes the PSRAM pin + * configuration + */ +&flexspi { + pinctrl-0 = <&pinmux_flexspi_safe>; +}; diff --git a/samples/drivers/memc/src/main.c b/samples/drivers/memc/src/main.c index 1347cce2b12b2..901eb064fb128 100644 --- a/samples/drivers/memc/src/main.c +++ b/samples/drivers/memc/src/main.c @@ -12,8 +12,14 @@ #include "memc_mcux_flexspi.h" #define FLEXSPI_DEV DEVICE_DT_GET(DT_PARENT(DT_ALIAS(sram_ext))) #define MEMC_PORT DT_REG_ADDR(DT_ALIAS(sram_ext)) -#define MEMC_BASE memc_flexspi_get_ahb_address(FLEXSPI_DEV, MEMC_PORT, 0) +#define MEMC_BASE ((void *)memc_flexspi_get_ahb_address(FLEXSPI_DEV, MEMC_PORT, 0)) #define MEMC_SIZE (DT_PROP(DT_ALIAS(sram_ext), size) / 8) +#elif DT_HAS_COMPAT_STATUS_OKAY(renesas_smartbond_nor_psram) +#include +#define MEMC_BASE ((void *)MCU_QSPIR_M_BASE) +#define MEMC_SIZE (DT_PROP(DT_ALIAS(sram_ext), dev_size) / 8) +#else +#error At least one driver should be selected! #endif void dump_memory(uint8_t *p, uint32_t size) diff --git a/samples/drivers/soc_flash_nrf/README.rst b/samples/drivers/soc_flash_nrf/README.rst index 2b69d8d6cb639..9f34ee631b6e9 100644 --- a/samples/drivers/soc_flash_nrf/README.rst +++ b/samples/drivers/soc_flash_nrf/README.rst @@ -1,5 +1,5 @@ .. zephyr:code-sample:: soc-flash-nrf - :name: nRF SoC flash + :name: nRF SoC Internal Storage :relevant-api: flash_interface flash_area_api Use the flash API to interact with the SoC flash. @@ -7,10 +7,11 @@ Overview ******** -This sample demonstrates using the :ref:`Flash API ` on an SoC internal flash. -The sample uses :ref:`Flash map API ` to obtain device for flash, using -DTS node label, and then directly uses :ref:`Flash API ` to perform -flash operations. +This sample demonstrates using the :ref:`Flash API ` on an SoC internal storage. +The sample uses :ref:`Flash map API ` to obtain a device that has +partition defined with label `storage_partition`, then uses :ref:`Flash API ` +to directly access and modify contents of a device, within area defined for said +partition. Within the sample, user may observe how read/write/erase operations are performed on a device, and how to first check whether device is @@ -19,11 +20,9 @@ ready for operation. Building and Running ******************** -The application will build for any SoC with internal flash memory -access enabled, as it is default for SoC devices, and fixed-partition -defined over that internal flash labeled `slot1_partition`, when -:kconfig:option:`CONFIG_TRUSTED_EXECUTION_NONSECURE` is not selected, -or `slot1_ns_partition`, when the Kconfig option is selected. +The application will build for any SoC with internal storage +access enabled, as it is default for SoC devices with defined +fixed-partition, over that internal storage, labeled `storage_partition`. .. zephyr-app-commands:: :zephyr-app: samples/drivers/soc_flash_nrf @@ -38,8 +37,8 @@ Sample Output *** Booting Zephyr OS build v2.7.99-17621-g54832687bcbb *** - Nordic nRF5 Flash Testing - ========================= + Nordic nRF5 Internal Storage Sample + =================================== Test 1: Flash erase page at 0x82000 Flash erase succeeded! diff --git a/samples/drivers/soc_flash_nrf/src/main.c b/samples/drivers/soc_flash_nrf/src/main.c index 29606a9ca5dfe..d55214afcc515 100644 --- a/samples/drivers/soc_flash_nrf/src/main.c +++ b/samples/drivers/soc_flash_nrf/src/main.c @@ -1,6 +1,7 @@ /* * Copyright (c) 2016 Linaro Limited * 2016 Intel Corporation. + * Copyright (c) 2024 Nordic Semiconductor ASA * * SPDX-License-Identifier: Apache-2.0 */ @@ -27,9 +28,45 @@ #define FLASH_TEST_OFFSET2 0x41234 #define FLASH_TEST_PAGE_IDX 37 +#if IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) && \ + IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) +#define FLASH_PE_RUNTIME_CHECK(cond) (cond) +#elif IS_ENABLED(CONFIG_FLASH_HAS_EXPLICIT_ERASE) +#define FLASH_PE_RUNTIME_CHECK(cond) (true) +#else +/* Assumed IS_ENABLED(CONFIG_FLASH_HAS_NO_EXPLICIT_ERASE) */ +#define FLASH_PE_RUNTIME_CHECK(cond) (false) +#endif + +/** + * Depending on value of condition erase a device or not. The condition + * is supposed to be value of erase_requirement picked up from + * flash_parameters.flags for device. + */ +static void erase_when_needed(const struct device *dev, bool condition, + uint32_t off, uint32_t size) +{ + /* + * Alwayes invoke erase when there are only erase requiring devices, + * never invoke erase when there are no devices requiring erase, + * always check condition if there are both kind of devices. + */ + if (FLASH_PE_RUNTIME_CHECK(condition)) { + if (flash_erase(dev, off, size) != 0) { + printf(" Erase failed!\n"); + } else { + printf(" Erase succeeded!\n"); + } + } else { + (void)condition; + printf(" Erase not required by device\n"); + } +} + int main(void) { const struct device *flash_dev = TEST_PARTITION_DEVICE; + struct flash_parameters flash_params; uint32_t buf_array_1[4] = { TEST_DATA_WORD_0, TEST_DATA_WORD_1, TEST_DATA_WORD_2, TEST_DATA_WORD_3 }; uint32_t buf_array_2[4] = { TEST_DATA_WORD_3, TEST_DATA_WORD_1, @@ -41,35 +78,35 @@ int main(void) uint32_t buf_word = 0U; uint32_t i, offset; - printf("\nNordic nRF5 Flash Testing\n"); - printf("=========================\n"); + memcpy(&flash_params, flash_get_parameters(flash_dev), sizeof(flash_params)); + + printf("\nNordic nRF5 Internal Storage Sample\n"); + printf("=====================================\n"); if (!device_is_ready(flash_dev)) { - printf("Flash device not ready\n"); + printf("Internal storage device not ready\n"); return 0; } - printf("\nTest 1: Flash erase page at 0x%x\n", TEST_PARTITION_OFFSET); - if (flash_erase(flash_dev, TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE) != 0) { - printf(" Flash erase failed!\n"); - } else { - printf(" Flash erase succeeded!\n"); - } + printf("\nTest 1: Internal storage erase page at 0x%x\n", TEST_PARTITION_OFFSET); + erase_when_needed(flash_dev, + flash_params_get_erase_cap(&flash_params) & FLASH_ERASE_C_EXPLICIT, + TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE); - printf("\nTest 2: Flash write (word array 1)\n"); + printf("\nTest 2: Internal storage write (word array 1)\n"); for (i = 0U; i < ARRAY_SIZE(buf_array_1); i++) { offset = TEST_PARTITION_OFFSET + (i << 2); printf(" Attempted to write %x at 0x%x\n", buf_array_1[i], offset); if (flash_write(flash_dev, offset, &buf_array_1[i], sizeof(uint32_t)) != 0) { - printf(" Flash write failed!\n"); + printf(" Write failed!\n"); return 0; } printf(" Attempted to read 0x%x\n", offset); if (flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0) { - printf(" Flash read failed!\n"); + printf(" Read failed!\n"); return 0; } printf(" Data read: %x\n", buf_word); @@ -81,27 +118,24 @@ int main(void) } offset = TEST_PARTITION_OFFSET; - printf("\nTest 3: Flash erase (2 pages at 0x%x)\n", offset); - if (flash_erase(flash_dev, offset, FLASH_PAGE_SIZE * 2) != 0) { - printf(" Flash erase failed!\n"); - } else { - printf(" Flash erase succeeded!\n"); - } - - printf("\nTest 4: Flash write (word array 2)\n"); + printf("\nTest 3: Internal storage erase (2 pages at 0x%x)\n", offset); + erase_when_needed(flash_dev, + flash_params_get_erase_cap(&flash_params) & FLASH_ERASE_C_EXPLICIT, + offset, FLASH_PAGE_SIZE * 2); + printf("\nTest 4: Internal storage write (word array 2)\n"); for (i = 0U; i < ARRAY_SIZE(buf_array_2); i++) { offset = TEST_PARTITION_OFFSET + (i << 2); printf(" Attempted to write %x at 0x%x\n", buf_array_2[i], offset); if (flash_write(flash_dev, offset, &buf_array_2[i], sizeof(uint32_t)) != 0) { - printf(" Flash write failed!\n"); + printf(" Write failed!\n"); return 0; } printf(" Attempted to read 0x%x\n", offset); if (flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0) { - printf(" Flash read failed!\n"); + printf(" Read failed!\n"); return 0; } printf(" Data read: %x\n", buf_word); @@ -112,12 +146,10 @@ int main(void) } } - printf("\nTest 5: Flash erase page at 0x%x\n", TEST_PARTITION_OFFSET); - if (flash_erase(flash_dev, TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE) != 0) { - printf(" Flash erase failed!\n"); - } else { - printf(" Flash erase succeeded!\n"); - } + printf("\nTest 5: Internal storage erase page at 0x%x\n", TEST_PARTITION_OFFSET); + erase_when_needed(flash_dev, + flash_params_get_erase_cap(&flash_params) & FLASH_ERASE_C_EXPLICIT, + TEST_PARTITION_OFFSET, FLASH_PAGE_SIZE); printf("\nTest 6: Non-word aligned write (word array 3)\n"); for (i = 0U; i < ARRAY_SIZE(buf_array_3); i++) { @@ -126,13 +158,13 @@ int main(void) offset); if (flash_write(flash_dev, offset, &buf_array_3[i], sizeof(uint32_t)) != 0) { - printf(" Flash write failed!\n"); + printf(" Write failed!\n"); return 0; } printf(" Attempted to read 0x%x\n", offset); if (flash_read(flash_dev, offset, &buf_word, sizeof(uint32_t)) != 0) { - printf(" Flash read failed!\n"); + printf(" Read failed!\n"); return 0; } printf(" Data read: %x\n", buf_word); @@ -185,8 +217,7 @@ int main(void) #endif printf("\nTest 8: Write block size API\n"); - printf(" write-block-size = %u\n", - flash_get_write_block_size(flash_dev)); + printf(" write-block-size = %u\n", flash_params.write_block_size); printf("\nFinished!\n"); return 0; diff --git a/samples/drivers/spi_flash/README.rst b/samples/drivers/spi_flash/README.rst index 3767444b3a2c8..1d48c19af1154 100644 --- a/samples/drivers/spi_flash/README.rst +++ b/samples/drivers/spi_flash/README.rst @@ -15,8 +15,8 @@ savings is correctly implemented. Building and Running ******************** -The application will build only for a target that has a :ref:`devicetree ` -``spi-flash0`` alias that refers to an entry with one of the following bindings as a compatible: +The application will build only for a target that has a devicetree node with one of the +following bindings as a compatible: * :dtcompatible:`jedec,spi-nor`, * :dtcompatible:`st,stm32-qspi-nor`, diff --git a/samples/drivers/spi_flash/boards/adp_xc7k_ae350.overlay b/samples/drivers/spi_flash/boards/adp_xc7k_ae350.overlay deleted file mode 100644 index 653722098eacb..0000000000000 --- a/samples/drivers/spi_flash/boards/adp_xc7k_ae350.overlay +++ /dev/null @@ -1,11 +0,0 @@ -/* - * Copyright (c) 2023 Andes Technology Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/ { - aliases { - spi-flash0 = &mx25u16; - }; -}; diff --git a/samples/drivers/spi_flash/boards/mec172xevb_assy6906.overlay b/samples/drivers/spi_flash/boards/mec172xevb_assy6906.overlay index f9fdc2e53680a..54f2957791cc3 100644 --- a/samples/drivers/spi_flash/boards/mec172xevb_assy6906.overlay +++ b/samples/drivers/spi_flash/boards/mec172xevb_assy6906.overlay @@ -4,12 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -/ { - aliases { - spi-flash0 = &spi1_cs0_flash; - }; -}; - &spi0 { status = "okay"; compatible = "microchip,xec-qmspi-ldma"; diff --git a/samples/drivers/spi_flash/boards/stm32h573i_dk.overlay b/samples/drivers/spi_flash/boards/stm32h573i_dk.overlay new file mode 100644 index 0000000000000..7d53447687632 --- /dev/null +++ b/samples/drivers/spi_flash/boards/stm32h573i_dk.overlay @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&xspi1 { + /* request 57 for XSPI1 */ + dmas = <&gpdma1 4 57 STM32_DMA_PERIPH_TX + &gpdma1 5 57 STM32_DMA_PERIPH_RX>; + dma-names = "tx", "rx"; +}; + +&gpdma1 { + status = "okay"; +}; diff --git a/samples/drivers/spi_flash/sample.yaml b/samples/drivers/spi_flash/sample.yaml index b3bec006e9cb0..b7c7a06924386 100644 --- a/samples/drivers/spi_flash/sample.yaml +++ b/samples/drivers/spi_flash/sample.yaml @@ -6,7 +6,7 @@ tests: - spi - flash filter: dt_compat_enabled("jedec,spi-nor") or dt_compat_enabled("st,stm32-qspi-nor") - or dt_compat_enabled("st,stm32-ospi-nor") + or dt_compat_enabled("st,stm32-ospi-nor") or dt_compat_enabled("st,stm32-xspi-nor") or (dt_compat_enabled("nordic,qspi-nor") and CONFIG_NORDIC_QSPI_NOR) platform_exclude: hifive_unmatched harness: console diff --git a/samples/drivers/spi_flash/src/main.c b/samples/drivers/spi_flash/src/main.c index 2faadd309c6e8..b84359ae05bb1 100644 --- a/samples/drivers/spi_flash/src/main.c +++ b/samples/drivers/spi_flash/src/main.c @@ -26,10 +26,26 @@ #endif #define SPI_FLASH_SECTOR_SIZE 4096 -#if defined(CONFIG_FLASH_STM32_OSPI) || defined(CONFIG_FLASH_STM32_QSPI) +#if defined(CONFIG_FLASH_STM32_OSPI) || \ + defined(CONFIG_FLASH_STM32_QSPI) || \ + defined(CONFIG_FLASH_STM32_XSPI) #define SPI_FLASH_MULTI_SECTOR_TEST #endif +#if DT_HAS_COMPAT_STATUS_OKAY(jedec_spi_nor) +#define SPI_FLASH_COMPAT jedec_spi_nor +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_qspi_nor) +#define SPI_FLASH_COMPAT st_stm32_qspi_nor +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_ospi_nor) +#define SPI_FLASH_COMPAT st_stm32_ospi_nor +#elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_xspi_nor) +#define SPI_FLASH_COMPAT st_stm32_xspi_nor +#elif DT_HAS_COMPAT_STATUS_OKAY(nordic_qspi_nor) +#define SPI_FLASH_COMPAT nordic_qspi_nor +#else +#define SPI_FLASH_COMPAT invalid +#endif + const uint8_t erased[] = { 0xff, 0xff, 0xff, 0xff }; void single_sector_test(const struct device *flash_dev) @@ -190,7 +206,7 @@ void multi_sector_test(const struct device *flash_dev) int main(void) { - const struct device *flash_dev = DEVICE_DT_GET(DT_ALIAS(spi_flash0)); + const struct device *flash_dev = DEVICE_DT_GET_ONE(SPI_FLASH_COMPAT); if (!device_is_ready(flash_dev)) { printk("%s: device not ready.\n", flash_dev->name); diff --git a/samples/drivers/watchdog/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/drivers/watchdog/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 0000000000000..94e0d719af4ef --- /dev/null +++ b/samples/drivers/watchdog/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,8 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt010 { + status = "okay"; +}; diff --git a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay index 66157d79fb36f..5c765a8a89633 100644 --- a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay +++ b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -3,6 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -&wdt30 { +&wdt31 { status = "okay"; }; diff --git a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay new file mode 100644 index 0000000000000..5c765a8a89633 --- /dev/null +++ b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr.overlay @@ -0,0 +1,8 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt31 { + status = "okay"; +}; diff --git a/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay new file mode 100644 index 0000000000000..5c765a8a89633 --- /dev/null +++ b/samples/drivers/watchdog/boards/nrf54l15pdk_nrf54l15_cpuflpr_xip.overlay @@ -0,0 +1,8 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +&wdt31 { + status = "okay"; +}; diff --git a/samples/index.rst b/samples/index.rst index 8581a330d40a8..0120c87769d7e 100644 --- a/samples/index.rst +++ b/samples/index.rst @@ -13,6 +13,7 @@ Samples and Demos classic basic/* userspace/* + sysbuild/* subsys/subsys.rst net/net.rst bluetooth/bluetooth.rst diff --git a/samples/modules/canopennode/README.rst b/samples/modules/canopennode/README.rst index 50b53aab99f1f..4b735f9b5d7b7 100644 --- a/samples/modules/canopennode/README.rst +++ b/samples/modules/canopennode/README.rst @@ -452,10 +452,10 @@ Sheet (EDS) file https://github.com/CANopenNode/CANopenNode .. _EN 50325-4: - https://can-cia.org/groups/international-standardization/ + https://can-cia.org/cia-groups/international-standardization/ .. _CiA 301: - https://can-cia.org/groups/specifications/ + https://can-cia.org/cia-groups/technical-documents/ .. _CANopen for Python: https://github.com/christiansandberg/canopen diff --git a/samples/modules/canopennode/sample.yaml b/samples/modules/canopennode/sample.yaml index 7cc95c0ed179c..2a9d0bbd147f2 100644 --- a/samples/modules/canopennode/sample.yaml +++ b/samples/modules/canopennode/sample.yaml @@ -15,20 +15,18 @@ common: - "(.*)CANopen stack initialized" tests: sample.modules.canopennode: - filter: dt_label_with_parent_compat_enabled("storage_partition", "fixed-partitions") - and dt_chosen_enabled("zephyr,flash-controller") and CONFIG_FLASH_HAS_DRIVER_ENABLED - platform_exclude: - - nucleo_h723zg - - nucleo_h743zi - - nucleo_h745zi_q/stm32h745xx/m7 - - nucleo_h753zi + depends_on: nvs sample.modules.canopennode.program_download: sysbuild: true + depends_on: nvs platform_allow: - frdm_k64f - twr_ke18f integration_platforms: - frdm_k64f - extra_args: canopennode_CONF_FILE=prj_img_mgmt.conf + extra_args: + canopennode_CONF_FILE=prj_img_mgmt.conf + SB_CONFIG_BOOTLOADER_MCUBOOT=y + sample.modules.canopennode.no_storage: extra_args: CONF_FILE=prj_no_storage.conf diff --git a/samples/modules/canopennode/src/main.c b/samples/modules/canopennode/src/main.c index c470e1f173216..e741f569466ae 100644 --- a/samples/modules/canopennode/src/main.c +++ b/samples/modules/canopennode/src/main.c @@ -15,7 +15,9 @@ LOG_MODULE_REGISTER(app); #define CAN_INTERFACE DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus)) -#define CAN_BITRATE (DT_PROP(DT_CHOSEN(zephyr_canbus), bus_speed) / 1000) +#define CAN_BITRATE (DT_PROP_OR(DT_CHOSEN(zephyr_canbus), bitrate, \ + DT_PROP_OR(DT_CHOSEN(zephyr_canbus), bus_speed, \ + CONFIG_CAN_DEFAULT_BITRATE)) / 1000) static struct gpio_dt_spec led_green_gpio = GPIO_DT_SPEC_GET_OR( DT_ALIAS(green_led), gpios, {0}); diff --git a/samples/modules/canopennode/sysbuild.conf b/samples/modules/canopennode/sysbuild.conf deleted file mode 100644 index 47f00ff3cff85..0000000000000 --- a/samples/modules/canopennode/sysbuild.conf +++ /dev/null @@ -1 +0,0 @@ -SB_CONFIG_BOOTLOADER_MCUBOOT=y diff --git a/samples/modules/cmsis_dsp/moving_average/CMakeLists.txt b/samples/modules/cmsis_dsp/moving_average/CMakeLists.txt new file mode 100644 index 0000000000000..64052f8e1c4ca --- /dev/null +++ b/samples/modules/cmsis_dsp/moving_average/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(moving_average) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/modules/cmsis_dsp/moving_average/README.rst b/samples/modules/cmsis_dsp/moving_average/README.rst new file mode 100644 index 0000000000000..dd99f5885e3a5 --- /dev/null +++ b/samples/modules/cmsis_dsp/moving_average/README.rst @@ -0,0 +1,63 @@ +.. zephyr:code-sample:: cmsis-dsp-moving-average + :name: CMSIS-DSP moving average + + Use the CMSIS-DSP library to calculate the moving average of a signal. + +Overview +******** + +This sample demonstrates how to use the CMSIS-DSP library to calculate the moving average of a +signal. + +It can be run on any board supported in Zephyr, but note that CMSIS-DSP is specifically optimized +for ARM Cortex-A and Cortex-M processors. + +A **moving average** filter is a common method used for smoothing noisy data. It can be implemented +as a finite impulse response (FIR) filter where the filter coefficients are all equal to 1/N, where +N is the number of "taps" (i.e. the size of the moving average window). + +The sample uses a very simple input signal of 32 samples, and computes the moving average using a +"window" of 10 samples. The resulting output is computed in one single call to the ``arm_fir_q31()`` +CMSIS-DSP function, and displayed on the console. + +.. note:: + In order to allow an easy comparison of the efficiency of the CMSIS-DSP library when used on ARM + processors vs. other architectures, the sample outputs the time and number of cycles it took to + compute the moving average. + +Requirements +************ + +CMSIS-DSP is an optional module and needs to be added explicitly to your Zephyr workspace: + +.. code-block:: shell + + west config manifest.project-filter -- +cmsis-dsp + west update cmsis-dsp + +Building and Running +********************* + +The demo can be built as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/modules/cmsis-dsp/moving_average + :host-os: unix + :board: qemu_cortex_m0 + :goals: run + :compact: + +The sample will output the number of cycles it took to compute the moving averages, as well as the +computed average for each 10-sample long window of the input signal. + +.. code-block:: console + + *** Booting Zephyr OS build v3.6.0-224-gb55824751d6c *** + Time: 244 us (244 cycles) + Input[00]: 0 0 0 0 0 0 0 0 0 0 | Output[00]: 0.00 + Input[01]: 0 0 0 0 0 0 0 0 0 1 | Output[01]: 0.10 + Input[02]: 0 0 0 0 0 0 0 0 1 2 | Output[02]: 0.30 + Input[03]: 0 0 0 0 0 0 0 1 2 3 | Output[03]: 0.60 + ... + Input[30]: 21 22 23 24 25 26 27 28 29 30 | Output[30]: 25.50 + Input[31]: 22 23 24 25 26 27 28 29 30 31 | Output[31]: 26.50 diff --git a/samples/modules/cmsis_dsp/moving_average/prj.conf b/samples/modules/cmsis_dsp/moving_average/prj.conf new file mode 100644 index 0000000000000..73412a76fb0ad --- /dev/null +++ b/samples/modules/cmsis_dsp/moving_average/prj.conf @@ -0,0 +1,5 @@ +CONFIG_REQUIRES_FULL_LIBC=y +CONFIG_REQUIRES_FLOAT_PRINTF=y + +CONFIG_CMSIS_DSP=y +CONFIG_CMSIS_DSP_FILTERING=y diff --git a/samples/modules/cmsis_dsp/moving_average/sample.yaml b/samples/modules/cmsis_dsp/moving_average/sample.yaml new file mode 100644 index 0000000000000..2bcc8359158f8 --- /dev/null +++ b/samples/modules/cmsis_dsp/moving_average/sample.yaml @@ -0,0 +1,48 @@ +sample: + description: Use CMSIS DSP to calculate moving average + name: CMSIS DSP Moving Average +tests: + sample.modules.cmsis_dsp.moving_average: + tags: + - samples + integration_platforms: + - qemu_cortex_m0 + - native_sim + modules: + - cmsis-dsp + harness: console + harness_config: + type: multi_line + regex: + - "Input\\[00\\]: 0 0 0 0 0 0 0 0 0 0 | Output\\[00\\]: 0.00" + - "Input\\[01\\]: 0 0 0 0 0 0 0 0 0 1 | Output\\[01\\]: 0.10" + - "Input\\[02\\]: 0 0 0 0 0 0 0 0 1 2 | Output\\[02\\]: 0.30" + - "Input\\[03\\]: 0 0 0 0 0 0 0 1 2 3 | Output\\[03\\]: 0.60" + - "Input\\[04\\]: 0 0 0 0 0 0 1 2 3 4 | Output\\[04\\]: 1.00" + - "Input\\[05\\]: 0 0 0 0 0 1 2 3 4 5 | Output\\[05\\]: 1.50" + - "Input\\[06\\]: 0 0 0 0 1 2 3 4 5 6 | Output\\[06\\]: 2.10" + - "Input\\[07\\]: 0 0 0 1 2 3 4 5 6 7 | Output\\[07\\]: 2.80" + - "Input\\[08\\]: 0 0 1 2 3 4 5 6 7 8 | Output\\[08\\]: 3.60" + - "Input\\[09\\]: 0 1 2 3 4 5 6 7 8 9 | Output\\[09\\]: 4.50" + - "Input\\[10\\]: 1 2 3 4 5 6 7 8 9 10 | Output\\[10\\]: 5.50" + - "Input\\[11\\]: 2 3 4 5 6 7 8 9 10 11 | Output\\[11\\]: 6.50" + - "Input\\[12\\]: 3 4 5 6 7 8 9 10 11 12 | Output\\[12\\]: 7.50" + - "Input\\[13\\]: 4 5 6 7 8 9 10 11 12 13 | Output\\[13\\]: 8.50" + - "Input\\[14\\]: 5 6 7 8 9 10 11 12 13 14 | Output\\[14\\]: 9.50" + - "Input\\[15\\]: 6 7 8 9 10 11 12 13 14 15 | Output\\[15\\]: 10.50" + - "Input\\[16\\]: 7 8 9 10 11 12 13 14 15 16 | Output\\[16\\]: 11.50" + - "Input\\[17\\]: 8 9 10 11 12 13 14 15 16 17 | Output\\[17\\]: 12.50" + - "Input\\[18\\]: 9 10 11 12 13 14 15 16 17 18 | Output\\[18\\]: 13.50" + - "Input\\[19\\]: 10 11 12 13 14 15 16 17 18 19 | Output\\[19\\]: 14.50" + - "Input\\[20\\]: 11 12 13 14 15 16 17 18 19 20 | Output\\[20\\]: 15.50" + - "Input\\[21\\]: 12 13 14 15 16 17 18 19 20 21 | Output\\[21\\]: 16.50" + - "Input\\[22\\]: 13 14 15 16 17 18 19 20 21 22 | Output\\[22\\]: 17.50" + - "Input\\[23\\]: 14 15 16 17 18 19 20 21 22 23 | Output\\[23\\]: 18.50" + - "Input\\[24\\]: 15 16 17 18 19 20 21 22 23 24 | Output\\[24\\]: 19.50" + - "Input\\[25\\]: 16 17 18 19 20 21 22 23 24 25 | Output\\[25\\]: 20.50" + - "Input\\[26\\]: 17 18 19 20 21 22 23 24 25 26 | Output\\[26\\]: 21.50" + - "Input\\[27\\]: 18 19 20 21 22 23 24 25 26 27 | Output\\[27\\]: 22.50" + - "Input\\[28\\]: 19 20 21 22 23 24 25 26 27 28 | Output\\[28\\]: 23.50" + - "Input\\[29\\]: 20 21 22 23 24 25 26 27 28 29 | Output\\[29\\]: 24.50" + - "Input\\[30\\]: 21 22 23 24 25 26 27 28 29 30 | Output\\[30\\]: 25.50" + - "Input\\[31\\]: 22 23 24 25 26 27 28 29 30 31 | Output\\[31\\]: 26.50" diff --git a/samples/modules/cmsis_dsp/moving_average/src/main.c b/samples/modules/cmsis_dsp/moving_average/src/main.c new file mode 100644 index 0000000000000..bab71912c185b --- /dev/null +++ b/samples/modules/cmsis_dsp/moving_average/src/main.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2024 Benjamin Cabé + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "arm_math.h" + +#define NUM_TAPS 10 /* Number of taps in the FIR filter (length of the moving average window) */ +#define BLOCK_SIZE 32 /* Number of samples processed per block */ + +/* + * Filter coefficients are all equal for a moving average filter. Here, 1/NUM_TAPS = 0.1f. + */ +q31_t firCoeffs[NUM_TAPS] = {0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, + 0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD, 0x0CCCCCCD}; + +arm_fir_instance_q31 sFIR; +q31_t firState[NUM_TAPS + BLOCK_SIZE - 1]; + +int main(void) +{ + q31_t input[BLOCK_SIZE]; + q31_t output[BLOCK_SIZE]; + uint32_t start, end; + + /* Initialize input data with a ramp from 0 to 31 */ + for (int i = 0; i < BLOCK_SIZE; i++) { + input[i] = i << 24; /* Convert to Q31 format */ + } + + /* Initialize the FIR filter */ + arm_fir_init_q31(&sFIR, NUM_TAPS, firCoeffs, firState, BLOCK_SIZE); + + /* Apply the FIR filter to the input data and measure how many cycles this takes */ + start = k_cycle_get_32(); + arm_fir_q31(&sFIR, input, output, BLOCK_SIZE); + end = k_cycle_get_32(); + + printf("Time: %u us (%u cycles)\n", k_cyc_to_us_floor32(end - start), end - start); + + for (int i = 0; i < BLOCK_SIZE; i++) { + printf("Input[%02d]: ", i); + for (int j = NUM_TAPS - 1; j >= 0; j--) { + if (j <= i) { + printf("%2d ", (int)(input[i - j] >> 24)); + } else { + printf("%2d ", 0); + } + } + printf("| Output[%02d]: %6.2f\n", i, (double)output[i] / (1 << 24)); + } + + return 0; +} diff --git a/samples/modules/lvgl/accelerometer_chart/prj.conf b/samples/modules/lvgl/accelerometer_chart/prj.conf index a5d6e2e831e7f..4930ab3bc2f6f 100644 --- a/samples/modules/lvgl/accelerometer_chart/prj.conf +++ b/samples/modules/lvgl/accelerometer_chart/prj.conf @@ -7,3 +7,4 @@ CONFIG_LV_Z_MEM_POOL_SIZE=16384 CONFIG_DISPLAY=y CONFIG_INPUT=y CONFIG_SENSOR=y +CONFIG_EMUL=y diff --git a/samples/modules/thrift/hello/client/prj.conf b/samples/modules/thrift/hello/client/prj.conf index a83715ddfc792..c8ac179680b18 100644 --- a/samples/modules/thrift/hello/client/prj.conf +++ b/samples/modules/thrift/hello/client/prj.conf @@ -6,6 +6,7 @@ CONFIG_CPP=y CONFIG_STD_CPP17=y CONFIG_CPP_EXCEPTIONS=y CONFIG_POSIX_API=y +CONFIG_XOPEN_STREAMS=y CONFIG_COMMON_LIBC_THRD=y CONFIG_DYNAMIC_THREAD=y CONFIG_THREAD_STACK_INFO=y @@ -28,7 +29,7 @@ CONFIG_NET_TCP=y CONFIG_NET_IPV6=n CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_CONNECTION_MANAGER=y # Kernel options @@ -61,7 +62,7 @@ CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" # Number of socket descriptors might need adjusting # if there are more than 1 handlers defined. -CONFIG_POSIX_MAX_FDS=16 +CONFIG_ZVFS_OPEN_MAX=16 # Some platforms require relatively large stack sizes. # This can be tuned per-board. diff --git a/samples/modules/thrift/hello/server/prj.conf b/samples/modules/thrift/hello/server/prj.conf index 1aacd9d14d758..78b009fb3e285 100644 --- a/samples/modules/thrift/hello/server/prj.conf +++ b/samples/modules/thrift/hello/server/prj.conf @@ -6,6 +6,7 @@ CONFIG_CPP=y CONFIG_STD_CPP17=y CONFIG_CPP_EXCEPTIONS=y CONFIG_POSIX_API=y +CONFIG_XOPEN_STREAMS=y CONFIG_NET_SOCKETPAIR=y CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_EVENTFD=y @@ -51,7 +52,7 @@ CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" # Number of socket descriptors might need adjusting # if there are more than 1 handlers defined. -CONFIG_POSIX_MAX_FDS=16 +CONFIG_ZVFS_OPEN_MAX=16 # Some platforms require relatively large stack sizes. # This can be tuned per-board. diff --git a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf index 161f2d7176b2e..ae48071eeb57d 100644 --- a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf +++ b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.conf @@ -1,4 +1,6 @@ CONFIG_UART_ASYNC_API=y +CONFIG_UART_1_ASYNC=y +CONFIG_UART_1_INTERRUPT_DRIVEN=n # Enable HW RX byte counting. This especially matters at higher baud rates. CONFIG_UART_1_NRF_HW_ASYNC=y CONFIG_UART_1_NRF_HW_ASYNC_TIMER=1 diff --git a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.overlay b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.overlay index c639ec8b30537..6fd249e01c4ee 100644 --- a/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.overlay +++ b/samples/net/cellular_modem/boards/nrf9160dk_nrf52840.overlay @@ -1,4 +1,4 @@ -#include +#include / { aliases { diff --git a/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf b/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf index b0866d8c86cf5..045f9eb43388b 100644 --- a/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf +++ b/samples/net/cellular_modem/boards/nrf9160dk_nrf9160_ns.conf @@ -1,4 +1,6 @@ CONFIG_UART_ASYNC_API=y +CONFIG_UART_1_ASYNC=y +CONFIG_UART_1_INTERRUPT_DRIVEN=n # Enable HW RX byte counting. This especially matters at higher baud rates. CONFIG_UART_1_NRF_HW_ASYNC=y CONFIG_UART_1_NRF_HW_ASYNC_TIMER=1 diff --git a/samples/net/cellular_modem/prj.conf b/samples/net/cellular_modem/prj.conf index 345d49bf463fd..d51e0cc7a270e 100644 --- a/samples/net/cellular_modem/prj.conf +++ b/samples/net/cellular_modem/prj.conf @@ -26,6 +26,15 @@ CONFIG_MODEM=y CONFIG_PM_DEVICE=y CONFIG_MODEM_CELLULAR=y +# Statistics +CONFIG_MODEM_STATS=y +CONFIG_SHELL=y + +# Testing +CONFIG_MODEM_AT_SHELL=y +CONFIG_PM_DEVICE_SHELL=y +CONFIG_SHELL_WILDCARD=n + # Logging CONFIG_LOG=y CONFIG_MODEM_MODULES_LOG_LEVEL_DBG=y diff --git a/samples/net/cloud/aws_iot_mqtt/prj.conf b/samples/net/cloud/aws_iot_mqtt/prj.conf index 30277ffb18c18..fbede2f3bf946 100644 --- a/samples/net/cloud/aws_iot_mqtt/prj.conf +++ b/samples/net/cloud/aws_iot_mqtt/prj.conf @@ -13,7 +13,6 @@ CONFIG_HW_STACK_PROTECTION=y CONFIG_REQUIRES_FULL_LIBC=y CONFIG_SNTP=y CONFIG_JSON_LIBRARY=y -CONFIG_POSIX_CLOCK=y CONFIG_POSIX_API=y # DNS diff --git a/samples/net/cloud/mqtt_azure/prj.conf b/samples/net/cloud/mqtt_azure/prj.conf index 2a88f746f5ff2..b857f7e43176c 100644 --- a/samples/net/cloud/mqtt_azure/prj.conf +++ b/samples/net/cloud/mqtt_azure/prj.conf @@ -33,6 +33,12 @@ CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=100000 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=10240 CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y +CONFIG_MBEDTLS_SHA1=y +CONFIG_MBEDTLS_SHA384=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECP_C=y # Network configuration CONFIG_NET_CONFIG_SETTINGS=y diff --git a/samples/net/cloud/mqtt_azure/src/digicert.cer b/samples/net/cloud/mqtt_azure/src/digicert.cer index cb0db66eb25a1..f019ce6804034 100644 --- a/samples/net/cloud/mqtt_azure/src/digicert.cer +++ b/samples/net/cloud/mqtt_azure/src/digicert.cer @@ -1,3 +1,4 @@ +/* Baltimore CyberTrust Root */ "-----BEGIN CERTIFICATE-----\r\n" "MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ\r\n" "RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD\r\n" @@ -19,3 +20,62 @@ "ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS\r\n" "R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp\r\n" "-----END CERTIFICATE-----\r\n" + +/* DigiCert Global Root G2 */ +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh\r\n" +"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\r\n" +"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\r\n" +"MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT\r\n" +"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\r\n" +"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG\r\n" +"9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI\r\n" +"2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx\r\n" +"1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ\r\n" +"q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz\r\n" +"tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ\r\n" +"vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP\r\n" +"BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV\r\n" +"5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY\r\n" +"1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4\r\n" +"NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG\r\n" +"Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91\r\n" +"8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe\r\n" +"pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl\r\n" +"MrY=\r\n" +"-----END CERTIFICATE-----\r\n" + +/* Microsoft RSA Root Certificate Authority 2017 */ +"-----BEGIN CERTIFICATE-----\r\n" +"MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl\r\n" +"MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw\r\n" +"NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5\r\n" +"IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG\r\n" +"EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N\r\n" +"aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi\r\n" +"MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ\r\n" +"Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0\r\n" +"ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1\r\n" +"HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm\r\n" +"gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ\r\n" +"jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc\r\n" +"aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG\r\n" +"YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6\r\n" +"W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K\r\n" +"UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH\r\n" +"+FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q\r\n" +"W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/\r\n" +"BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC\r\n" +"NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC\r\n" +"LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC\r\n" +"gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6\r\n" +"tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh\r\n" +"SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2\r\n" +"TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3\r\n" +"pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR\r\n" +"xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp\r\n" +"GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9\r\n" +"dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN\r\n" +"AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB\r\n" +"RA+GsCyRxj3qrg+E\r\n" +"-----END CERTIFICATE-----\r\n" diff --git a/samples/net/cloud/mqtt_azure/src/main.c b/samples/net/cloud/mqtt_azure/src/main.c index 46ee6c66820b2..841c1fb7ebe0f 100644 --- a/samples/net/cloud/mqtt_azure/src/main.c +++ b/samples/net/cloud/mqtt_azure/src/main.c @@ -8,6 +8,7 @@ LOG_MODULE_REGISTER(mqtt_azure, LOG_LEVEL_DBG); #include +#include #include #include diff --git a/samples/net/cloud/tagoio_http_post/README.rst b/samples/net/cloud/tagoio_http_post/README.rst index 30778353c503c..f227f9016317f 100644 --- a/samples/net/cloud/tagoio_http_post/README.rst +++ b/samples/net/cloud/tagoio_http_post/README.rst @@ -24,8 +24,6 @@ Requirements * Ethernet: Using default configuration * WiFi: Using default configuration plus wifi overlay - * Modem: Using default configuration plus modem overlay - TagoIO Device Configuration *************************** @@ -81,58 +79,6 @@ need fill ``CONFIG_TAGOIO_HTTP_WIFI_SSID`` with your wifi network SSID and :goals: build flash :compact: - -Modem -===== - -The Modem support is quite similar to WIFI, you need a board with an embedded -Modem support or you can add a shield. Currently, the overlay was created to -allow modems with PPP support. This was tested using ``SIMcom SIM808 EVB``. -Additionally you need fill ``CONFIG_MODEM_GSM_APN`` with the correspondent Access -Point Name (APN) at -:zephyr_file:`samples/net/cloud/tagoio_http_post/overlay-modem.conf` file. A -DTC overlay file should be used to configure the glue between the modem and the -uart port. It can reside at boards directory, with the board name, or it can be -a special designator like defined at ``arduino.overlay``. - -.. zephyr-app-commands:: - :zephyr-app: samples/net/cloud/tagoio_http_post - :board: sam4e_xpro - :gen-args: -DEXTRA_CONF_FILE=overlay-modem.conf - :goals: build flash - :compact: - -.. zephyr-app-commands:: - :zephyr-app: samples/net/cloud/tagoio_http_post - :board: frdm_k64f - :gen-args: -DEXTRA_CONF_FILE=overlay-modem.conf -DDTC_OVERLAY_FILE=arduino.overlay - :goals: build flash - :compact: - -In a terminal window you can check if communication is happen: - -.. code-block:: console - - $ minicom -D /dev/ttyACM0 - - *** Booting Zephyr OS build zephyr-v2.4.0-1135-g137732e23c1e *** - - - [00:00:02.172,000] modem_gsm: Manufacturer: SIMCOM_Lt - [00:00:02.227,000] modem_gsm: Model: SIMCOM_SIM808 - [00:00:02.283,000] modem_gsm: Revision: 1418B04SIM808M32 - [00:00:02.338,000] modem_gsm: IMSI: XXXXXX - [00:00:02.393,000] modem_gsm: ICCID: XXXXXX - [00:00:02.453,000] modem_gsm: IMEI: XXXXXX - [00:00:02.574,000] modem_gsm: Attached to packet service! - [00:00:02.575,000] net_ppp: Initializing PPP to use UART_3 - [00:00:13.370,000] tagoio: TagoIO IoT - HTTP Client - Temperature demo - [00:00:13.370,000] tagoio: Temp: 20 - [00:00:25.237,000] tagoio: Temp: 76 - [00:00:37.581,000] tagoio: Temp: 36 - [00:00:50.437,000] tagoio: Temp: 98 - - Visualizing TagoIO dashboard **************************** diff --git a/samples/net/cloud/tagoio_http_post/arduino.overlay b/samples/net/cloud/tagoio_http_post/arduino.overlay deleted file mode 100644 index d0e658836e810..0000000000000 --- a/samples/net/cloud/tagoio_http_post/arduino.overlay +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2021 G-Technologies Sdn. Bhd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - - &arduino_serial { - status = "okay"; - current-speed = <115200>; - - gsm: gsm-modem { - compatible = "zephyr,gsm-ppp"; - }; -}; diff --git a/samples/net/cloud/tagoio_http_post/boards/sam4e_xpro.conf b/samples/net/cloud/tagoio_http_post/boards/sam4e_xpro.conf deleted file mode 100644 index 7eed5ce32ed89..0000000000000 --- a/samples/net/cloud/tagoio_http_post/boards/sam4e_xpro.conf +++ /dev/null @@ -1 +0,0 @@ -CONFIG_USART_SAM=y diff --git a/samples/net/cloud/tagoio_http_post/boards/sam4e_xpro.overlay b/samples/net/cloud/tagoio_http_post/boards/sam4e_xpro.overlay deleted file mode 100644 index 60a4d02243119..0000000000000 --- a/samples/net/cloud/tagoio_http_post/boards/sam4e_xpro.overlay +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2021 G-Technologies Sdn. Bhd. - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&usart1 { - status = "okay"; - current-speed = <115200>; - - gsm: gsm-modem { - compatible = "zephyr,gsm-ppp"; - }; -}; diff --git a/samples/net/cloud/tagoio_http_post/overlay-modem.conf b/samples/net/cloud/tagoio_http_post/overlay-modem.conf deleted file mode 100644 index 4256d82f6da8a..0000000000000 --- a/samples/net/cloud/tagoio_http_post/overlay-modem.conf +++ /dev/null @@ -1,24 +0,0 @@ -# UART support -CONFIG_SERIAL=y - -# GSM modem support -CONFIG_MODEM=y -CONFIG_MODEM_SHELL=y -CONFIG_MODEM_CMD_HANDLER_MAX_PARAM_COUNT=20 -CONFIG_MODEM_GSM_PPP=y -CONFIG_MODEM_GSM_RX_STACK_SIZE=1024 -CONFIG_MODEM_GSM_APN="" - -# Network management events -CONFIG_NET_CONNECTION_MANAGER=y - -# PPP networking support -CONFIG_NET_NATIVE=y -CONFIG_NET_DRIVERS=y -CONFIG_NET_PPP=y -CONFIG_NET_L2_PPP=y -CONFIG_NET_L2_PPP_TIMEOUT=10000 - -CONFIG_DNS_RESOLVER_MAX_SERVERS=1 -CONFIG_DNS_SERVER_IP_ADDRESSES=y -CONFIG_DNS_SERVER1="8.8.8.8" diff --git a/samples/net/cloud/tagoio_http_post/sample.yaml b/samples/net/cloud/tagoio_http_post/sample.yaml index 8e4ac0b37eaf8..08a67c0343a0e 100644 --- a/samples/net/cloud/tagoio_http_post/sample.yaml +++ b/samples/net/cloud/tagoio_http_post/sample.yaml @@ -4,9 +4,6 @@ common: - cloud - dns - http - - ppp - - modem - - gsm - wifi min_ram: 64 harness: net @@ -32,11 +29,3 @@ tests: - nucleo_f767zi integration_platforms: - frdm_k64f - sample.net.cloud.tagoio_http_post.modem: - extra_args: OVERLAY_CONFIG="overlay-modem.conf" - platform_allow: sam4e_xpro - sample.net.cloud.tagoio_http_post.modem.arduino: - extra_args: - - OVERLAY_CONFIG="overlay-modem.conf" - - DTC_OVERLAY_FILE="arduino.overlay" - platform_allow: frdm_k64f diff --git a/samples/net/dns_resolve/prj.conf b/samples/net/dns_resolve/prj.conf index 95d6d0ed0bc19..b2de8a0dd4f7c 100644 --- a/samples/net/dns_resolve/prj.conf +++ b/samples/net/dns_resolve/prj.conf @@ -14,6 +14,8 @@ CONFIG_NET_IPV6=y CONFIG_NET_IPV4=y CONFIG_NET_DHCPV4=n +CONFIG_NET_SOCKETS_POLL_MAX=4 + # Enable the DNS resolver CONFIG_DNS_RESOLVER=y # Enable additional buffers diff --git a/samples/net/dns_resolve/sample.yaml b/samples/net/dns_resolve/sample.yaml index f5808607b57f4..cafc9beac83f5 100644 --- a/samples/net/dns_resolve/sample.yaml +++ b/samples/net/dns_resolve/sample.yaml @@ -4,6 +4,9 @@ common: tags: - net - dns + platform_exclude: + - native_posix + - native_posix/native/64 sample: description: DNS resolver, mDNS and LLMNR responder name: DNS resolver and responder sample application diff --git a/samples/net/dsa/src/main.c b/samples/net/dsa/src/main.c index 4bd2b36d229b7..a7c0e14dd2c07 100644 --- a/samples/net/dsa/src/main.c +++ b/samples/net/dsa/src/main.c @@ -71,7 +71,7 @@ int start_slave_port_packet_socket(struct net_if *iface, struct sockaddr_ll dst; int ret; - pd->sock = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL); + pd->sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (pd->sock < 0) { LOG_ERR("Failed to create RAW socket : %d", errno); return -errno; diff --git a/samples/net/gptp/sample.yaml b/samples/net/gptp/sample.yaml index b0a49d2413910..44bf695d628da 100644 --- a/samples/net/gptp/sample.yaml +++ b/samples/net/gptp/sample.yaml @@ -17,6 +17,7 @@ tests: - native_sim/native/64 - nucleo_f767zi - nucleo_h743zi + - nucleo_h753zi - nucleo_h745zi_q/stm32h745xx/m7 depends_on: eth integration_platforms: diff --git a/samples/net/gsm_modem/CMakeLists.txt b/samples/net/gsm_modem/CMakeLists.txt deleted file mode 100644 index b32fe0e5b20f6..0000000000000 --- a/samples/net/gsm_modem/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) - -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(gsm_modem) - -target_sources(app PRIVATE src/main.c) diff --git a/samples/net/gsm_modem/README.rst b/samples/net/gsm_modem/README.rst deleted file mode 100644 index 2021b0e055495..0000000000000 --- a/samples/net/gsm_modem/README.rst +++ /dev/null @@ -1,40 +0,0 @@ -.. zephyr:code-sample:: gsm-modem - :name: Generic GSM modem - - Use a GSM modem to connect to a GPRS network. - -Overview -******** - -The Zephyr GSM modem sample application allows user to have a connection -to GPRS network. The connection to GSM modem is done using -:ref:`PPP (Point-to-Point Protocol) `. - -The source code of this sample application can be found at: -:zephyr_file:`samples/net/gsm_modem`. - -Requirements -************ - -- GSM modem card. The sample has been tested with SIMCOM SIM808 card. All - GSM modem cards should work as long as they support **AT+CGDCONT** command. -- Almost any Zephyr enabled board with sufficient resources can be used. - The sample has been tested with :ref:`reel_board`. - -Build and Running -***************** - -If you are using an external modem like the SIMCOM card, then connect -the necessary pins like RX and TX from your Zephyr target board to the -modem card. Internal modems, like what is found in :ref:`particle_boron` -board, are not yet supported. - -.. zephyr-app-commands:: - :zephyr-app: samples/net/gsm_modem - :board: reel_board - :goals: build flash - :gen-args: -DCONFIG_MODEM_GSM_APN=\"internet\" - :compact: - -Note that you might need to change the APN name according to your GSM network -configuration. diff --git a/samples/net/gsm_modem/boards/b_u585i_iot02a.conf b/samples/net/gsm_modem/boards/b_u585i_iot02a.conf deleted file mode 100644 index c344244d2063d..0000000000000 --- a/samples/net/gsm_modem/boards/b_u585i_iot02a.conf +++ /dev/null @@ -1,12 +0,0 @@ -CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_GSM_MUX=y -CONFIG_UART_MUX=y -CONFIG_MODEM_GSM_APN="internet" -CONFIG_MAIN_STACK_SIZE=8192 -CONFIG_MODEM_GSM_QUECTEL=y -CONFIG_MODEM_SHELL=n -CONFIG_NET_MGMT_EVENT_INFO=y -CONFIG_NET_MGMT_EVENT_MONITOR=y -CONFIG_NET_MGMT_EVENT_MONITOR_AUTO_START=y -CONFIG_NET_LOG=y -CONFIG_NET_MGMT_EVENT_LOG_LEVEL_DBG=y diff --git a/samples/net/gsm_modem/boards/b_u585i_iot02a.overlay b/samples/net/gsm_modem/boards/b_u585i_iot02a.overlay deleted file mode 100644 index f8d862f473772..0000000000000 --- a/samples/net/gsm_modem/boards/b_u585i_iot02a.overlay +++ /dev/null @@ -1,37 +0,0 @@ -/ { - aliases { - modem-uart = &usart2; - modem = &modem; - }; -}; - -&gpioh { - misc_fixed_usart2 { - gpio-hog; - gpios = <13 GPIO_ACTIVE_HIGH>; - output-high; - }; -}; - -&gpdma1 { - status = "okay"; -}; - -/* BG95 */ -&usart2 { - pinctrl-0 = <&usart2_tx_pa2 &usart2_rx_pa3 &usart2_rts_pa1 &usart2_cts_pa0>; - pinctrl-names = "default"; - current-speed = <115200>; - hw-flow-control; - - dmas = <&gpdma1 0 27 STM32_DMA_PERIPH_TX - &gpdma1 1 26 STM32_DMA_PERIPH_RX>; - dma-names = "tx", "rx"; - - status = "okay"; - - modem: modem { - compatible = "zephyr,gsm-ppp"; - status = "okay"; - }; -}; diff --git a/samples/net/gsm_modem/boards/frdm_uart2_dts.overlay b/samples/net/gsm_modem/boards/frdm_uart2_dts.overlay deleted file mode 100644 index 55c6e86f74d23..0000000000000 --- a/samples/net/gsm_modem/boards/frdm_uart2_dts.overlay +++ /dev/null @@ -1,12 +0,0 @@ -/* - * UART 2 is configured on FRDM pins PTD0, rts; PTD1, cts; PTD2, rx; PTD3, tx - * see https://www.nxp.com/docs/en/data-sheet/K64P144M120SF5.pdf chapter 5.1, - * page 74 - */ -&uart2 { - status = "okay"; - current-speed = <115200>; - gsm: gsm-modem { - compatible = "zephyr,gsm-ppp"; - }; -}; diff --git a/samples/net/gsm_modem/prj.conf b/samples/net/gsm_modem/prj.conf deleted file mode 100644 index c9494495d6a47..0000000000000 --- a/samples/net/gsm_modem/prj.conf +++ /dev/null @@ -1,35 +0,0 @@ -# UART support -CONFIG_SERIAL=y - -# GSM modem support -CONFIG_MODEM=y -CONFIG_MODEM_GSM_PPP=y - -# PPP networking support -CONFIG_NET_DRIVERS=y -CONFIG_NET_PPP=y -CONFIG_NET_L2_PPP=y -CONFIG_NET_NATIVE=y -CONFIG_NETWORKING=y - -CONFIG_NET_L2_PPP_TIMEOUT=10000 - -# IPv4 enables PPP IPCP support -CONFIG_NET_IPV4=y -CONFIG_NET_IPV6=n - -# Network management events -CONFIG_NET_CONNECTION_MANAGER=y - -# Log buffers, modem and PPP -CONFIG_LOG=y -CONFIG_NET_LOG=y -#CONFIG_LOG_BUFFER_SIZE=16384 -#CONFIG_MODEM_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_NET_CONNECTION_MANAGER_LOG_LEVEL_DBG=y - -CONFIG_NET_SHELL=y -CONFIG_MODEM_SHELL=y diff --git a/samples/net/gsm_modem/sample.yaml b/samples/net/gsm_modem/sample.yaml deleted file mode 100644 index bb5c3d4735464..0000000000000 --- a/samples/net/gsm_modem/sample.yaml +++ /dev/null @@ -1,22 +0,0 @@ -common: - harness: net - depends_on: serial-net - tags: - - net - - ppp - - modem - - gsm - platform_allow: frdm_k64f - extra_args: DTC_OVERLAY_FILE="boards/frdm_uart2_dts.overlay" -sample: - description: Sample for generic GSM modem - name: Generic GSM modem using PPP -tests: - sample.net.ppp.gsm.modem: - extra_configs: - - CONFIG_TEST_RANDOM_GENERATOR=y - sample.net.ppp.gsm.modem.mux: - extra_configs: - - CONFIG_TEST_RANDOM_GENERATOR=y - - CONFIG_GSM_MUX=y - - CONFIG_UART_MUX=y diff --git a/samples/net/gsm_modem/src/main.c b/samples/net/gsm_modem/src/main.c deleted file mode 100644 index 522a8c6660690..0000000000000 --- a/samples/net/gsm_modem/src/main.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2020, Intel Corporation - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -LOG_MODULE_REGISTER(sample_gsm_ppp, LOG_LEVEL_DBG); - -#define GSM_MODEM_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_gsm_ppp) -#define UART_NODE DT_BUS(GSM_MODEM_NODE) - -static const struct device *const gsm_dev = DEVICE_DT_GET(GSM_MODEM_NODE); -static struct net_mgmt_event_callback mgmt_cb; -static bool starting = IS_ENABLED(CONFIG_GSM_PPP_AUTOSTART); - -static int cmd_sample_modem_suspend(const struct shell *sh, - size_t argc, char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - if (!starting) { - shell_fprintf(sh, SHELL_NORMAL, "Modem is already stopped.\n"); - return -ENOEXEC; - } - - gsm_ppp_stop(gsm_dev); - starting = false; - - return 0; -} - -static int cmd_sample_modem_resume(const struct shell *sh, - size_t argc, char *argv[]) -{ - ARG_UNUSED(argc); - ARG_UNUSED(argv); - - if (starting) { - shell_fprintf(sh, SHELL_NORMAL, "Modem is already started.\n"); - return -ENOEXEC; - } - - gsm_ppp_start(gsm_dev); - starting = true; - - return 0; -} - -SHELL_STATIC_SUBCMD_SET_CREATE(sample_commands, - SHELL_CMD(resume, NULL, - "Resume the modem\n", - cmd_sample_modem_resume), - SHELL_CMD(suspend, NULL, - "Suspend the modem\n", - cmd_sample_modem_suspend), - SHELL_SUBCMD_SET_END -); - -SHELL_CMD_REGISTER(sample, &sample_commands, - "Sample application commands", NULL); - - -static void event_handler(struct net_mgmt_event_callback *cb, - uint32_t mgmt_event, struct net_if *iface) -{ - ARG_UNUSED(cb); - ARG_UNUSED(iface); - - if ((mgmt_event & (NET_EVENT_L4_CONNECTED - | NET_EVENT_L4_DISCONNECTED)) != mgmt_event) { - return; - } - - if (mgmt_event == NET_EVENT_L4_CONNECTED) { - LOG_INF("Network connected"); - return; - } - - if (mgmt_event == NET_EVENT_L4_DISCONNECTED) { - LOG_INF("Network disconnected"); - return; - } -} - -static void modem_on_cb(const struct device *dev, void *user_data) -{ - ARG_UNUSED(dev); - ARG_UNUSED(user_data); - - LOG_INF("GSM modem on callback fired"); -} - -static void modem_off_cb(const struct device *dev, void *user_data) -{ - ARG_UNUSED(dev); - ARG_UNUSED(user_data); - - LOG_INF("GSM modem off callback fired"); -} - -int main(void) -{ - const struct device *const uart_dev = DEVICE_DT_GET(UART_NODE); - - /* Optional register modem power callbacks */ - gsm_ppp_register_modem_power_callback(gsm_dev, modem_on_cb, modem_off_cb, NULL); - - LOG_INF("Board '%s' APN '%s' UART '%s' device %p (%s)", - CONFIG_BOARD, CONFIG_MODEM_GSM_APN, - uart_dev->name, uart_dev, gsm_dev->name); - - net_mgmt_init_event_callback(&mgmt_cb, event_handler, - NET_EVENT_L4_CONNECTED | - NET_EVENT_L4_DISCONNECTED); - net_mgmt_add_event_callback(&mgmt_cb); - - return 0; -} diff --git a/samples/net/lwm2m_client/overlay-dtls-cert.conf b/samples/net/lwm2m_client/overlay-dtls-cert.conf index 1362115f74669..e2f4ede69d1b6 100644 --- a/samples/net/lwm2m_client/overlay-dtls-cert.conf +++ b/samples/net/lwm2m_client/overlay-dtls-cert.conf @@ -12,7 +12,9 @@ CONFIG_MBEDTLS_TLS_VERSION_1_2=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=32768 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=1500 +CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y +CONFIG_MBEDTLS_CIPHER_GCM_ENABLED=y # Disable RSA, use only ECC certificates CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=n @@ -24,8 +26,6 @@ CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y CONFIG_MBEDTLS_ECDH_C=y CONFIG_MBEDTLS_ECDSA_C=y CONFIG_MBEDTLS_ECP_C=y -CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y -CONFIG_MBEDTLS_CIPHER_GCM_ENABLED=y # Optional: we could use just binary DER certificates CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y diff --git a/samples/net/lwm2m_client/overlay-dtls.conf b/samples/net/lwm2m_client/overlay-dtls.conf index 930230d8ba4b2..b19c2f8c95217 100644 --- a/samples/net/lwm2m_client/overlay-dtls.conf +++ b/samples/net/lwm2m_client/overlay-dtls.conf @@ -12,6 +12,7 @@ CONFIG_MBEDTLS_SSL_DTLS_CONNECTION_ID=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=8192 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=1500 +CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y # Disable RSA, we don't parse certs: saves flash/memory diff --git a/samples/net/lwm2m_client/src/firmware_update.c b/samples/net/lwm2m_client/src/firmware_update.c index dd6dcd8d59983..5ef2e1cf127c0 100644 --- a/samples/net/lwm2m_client/src/firmware_update.c +++ b/samples/net/lwm2m_client/src/firmware_update.c @@ -38,13 +38,13 @@ static void *firmware_get_buf(uint16_t obj_inst_id, uint16_t res_id, return firmware_buf; } -static int firmware_block_received_cb(uint16_t obj_inst_id, - uint16_t res_id, uint16_t res_inst_id, - uint8_t *data, uint16_t data_len, - bool last_block, size_t total_size) +static int firmware_block_received_cb(uint16_t obj_inst_id, uint16_t res_id, + uint16_t res_inst_id, uint8_t *data, + uint16_t data_len, bool last_block, + size_t total_size, size_t offset) { - LOG_INF("FIRMWARE: BLOCK RECEIVED: len:%u last_block:%d", - data_len, last_block); + LOG_INF("FIRMWARE: BLOCK RECEIVED: offset:%zd len:%u last_block:%d", + offset, data_len, last_block); return 0; } diff --git a/samples/net/lwm2m_client/src/led.c b/samples/net/lwm2m_client/src/led.c index 98055baa580cf..d4aa638889070 100644 --- a/samples/net/lwm2m_client/src/led.c +++ b/samples/net/lwm2m_client/src/led.c @@ -22,7 +22,7 @@ static uint32_t led_state; /* TODO: Move to a pre write hook that can handle ret codes once available */ static int led_on_off_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, - uint16_t data_len, bool last_block, size_t total_size) + uint16_t data_len, bool last_block, size_t total_size, size_t offset) { int ret = 0; uint32_t led_val; diff --git a/samples/net/lwm2m_client/src/timer.c b/samples/net/lwm2m_client/src/timer.c index 17814ae134cec..861074513440d 100644 --- a/samples/net/lwm2m_client/src/timer.c +++ b/samples/net/lwm2m_client/src/timer.c @@ -17,7 +17,7 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME); /* An example data validation callback. */ static int timer_on_off_validate_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { LOG_INF("Validating On/Off data"); @@ -34,7 +34,7 @@ static int timer_on_off_validate_cb(uint16_t obj_inst_id, uint16_t res_id, uint1 static int timer_digital_state_cb(uint16_t obj_inst_id, uint16_t res_id, uint16_t res_inst_id, uint8_t *data, uint16_t data_len, bool last_block, - size_t total_size) + size_t total_size, size_t offset) { bool *digital_state = (bool *)data; diff --git a/samples/net/mdns_responder/prj.conf b/samples/net/mdns_responder/prj.conf index db58992f3f8e0..60f6fa3326d72 100644 --- a/samples/net/mdns_responder/prj.conf +++ b/samples/net/mdns_responder/prj.conf @@ -8,6 +8,8 @@ CONFIG_NET_IPV4=y CONFIG_NET_IF_MAX_IPV6_COUNT=3 CONFIG_NET_IF_MAX_IPV4_COUNT=3 +CONFIG_NET_SOCKETS_POLL_MAX=6 + CONFIG_NET_HOSTNAME_ENABLE=y CONFIG_NET_HOSTNAME_UNIQUE=n CONFIG_NET_HOSTNAME="zephyr" @@ -27,6 +29,7 @@ CONFIG_PRINTK=y CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=5 +CONFIG_NET_IF_MCAST_IPV4_ADDR_COUNT=3 CONFIG_NET_PKT_RX_COUNT=10 CONFIG_NET_PKT_TX_COUNT=10 diff --git a/samples/net/mqtt_publisher/boards/frdm_k64f.conf b/samples/net/mqtt_publisher/boards/frdm_k64f.conf new file mode 100644 index 0000000000000..922c1e4b05f34 --- /dev/null +++ b/samples/net/mqtt_publisher/boards/frdm_k64f.conf @@ -0,0 +1 @@ +CONFIG_MAX_THREAD_BYTES=3 diff --git a/samples/net/mqtt_sn_publisher/prj.conf b/samples/net/mqtt_sn_publisher/prj.conf index 367ba8082f489..efe1a8f3e207e 100644 --- a/samples/net/mqtt_sn_publisher/prj.conf +++ b/samples/net/mqtt_sn_publisher/prj.conf @@ -5,7 +5,7 @@ CONFIG_NET_IPV4=y CONFIG_NET_IPV6=n CONFIG_NET_SOCKETS=y CONFIG_POSIX_API=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_CONNECTION_MANAGER=y # Kernel options diff --git a/samples/net/ptp/CMakeLists.txt b/samples/net/ptp/CMakeLists.txt new file mode 100644 index 0000000000000..edbda19d0c925 --- /dev/null +++ b/samples/net/ptp/CMakeLists.txt @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/lib) + +project(ptp) +target_sources(app PRIVATE src/main.c) diff --git a/samples/net/ptp/Kconfig b/samples/net/ptp/Kconfig new file mode 100644 index 0000000000000..620b26fac4f60 --- /dev/null +++ b/samples/net/ptp/Kconfig @@ -0,0 +1,18 @@ +# Private config options for PTP sample app + +# Copyright (c) 2024 BayLibre SAS +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "PTP sample application" + +if PTP + +config NET_SAMPLE_RUN_DURATION + int "Run the application this many seconds" + default 0 + help + A value of zero means that the sample application is run forever. + +endif + +source "Kconfig.zephyr" diff --git a/samples/net/ptp/README.rst b/samples/net/ptp/README.rst new file mode 100644 index 0000000000000..71343931c550c --- /dev/null +++ b/samples/net/ptp/README.rst @@ -0,0 +1,70 @@ +.. zephyr:code-sample:: ptp + :name: PTP + :relevant-api: ptp ptp_time ptp_clock + + Enable PTP support and monitor messages and events via logging. + +Overview +******** + +The PTP sample application for Zephyr will enable PTP support. + +The source code for this sample application can be found at: +:zephyr_file:`samples/net/ptp`. + +Requirements +************ + +For generic host connectivity, that can be used for debugging purposes, see +:ref:`networking_with_native_sim` for details. + +Building and Running +******************** + +A good way to run this sample is to run this PTP application inside +native_sim board as described in :ref:`networking_with_native_sim` or with +embedded device like Nucleo-H743-ZI, Nucleo-H745ZI-Q, Nucleo-F767ZI or +Nucleo-H563ZI. Note that PTP is only supported for +boards that have an Ethernet port and which has support for collecting +timestamps for sent and received Ethernet frames. + +Follow these steps to build the PTP sample application: + +.. zephyr-app-commands:: + :zephyr-app: samples/net/ptp + :board: + :goals: build + :compact: + +Setting up Linux Host +===================== + +By default PTP in Zephyr will not print any PTP debug messages to console. +One can enable debug prints by setting +:kconfig:option:`CONFIG_PTP_LOG_LEVEL_DBG` in the config file. + +Get linuxptp project sources + +.. code-block:: console + + git clone git://git.code.sf.net/p/linuxptp/code + +Compile the ``ptp4l`` daemon and start it like this: + +.. code-block:: console + + sudo ./ptp4l -4 -f -i zeth -m -q -l 6 -S + +Compile Zephyr application. + +.. zephyr-app-commands:: + :zephyr-app: samples/net/ptp + :board: native_sim + :goals: build + :compact: + +When the Zephyr image is build, you can start it like this: + +.. code-block:: console + + build/zephyr/zephyr.exe -attach_uart diff --git a/samples/net/ptp/boards/native_posix.conf b/samples/net/ptp/boards/native_posix.conf new file mode 100644 index 0000000000000..e2f26372eede3 --- /dev/null +++ b/samples/net/ptp/boards/native_posix.conf @@ -0,0 +1,8 @@ +# Settings for native_posix ethernet driver +CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK=y + +#CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=y +CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:2a" + +# Assume 1 ms accuracy for native_posix simulated clock +CONFIG_PTP_CLOCK_ACCURACY_1MS=y diff --git a/samples/net/ptp/boards/native_posix_native_64.conf b/samples/net/ptp/boards/native_posix_native_64.conf new file mode 100644 index 0000000000000..e2f26372eede3 --- /dev/null +++ b/samples/net/ptp/boards/native_posix_native_64.conf @@ -0,0 +1,8 @@ +# Settings for native_posix ethernet driver +CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK=y + +#CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=y +CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:2a" + +# Assume 1 ms accuracy for native_posix simulated clock +CONFIG_PTP_CLOCK_ACCURACY_1MS=y diff --git a/samples/net/ptp/boards/native_sim.conf b/samples/net/ptp/boards/native_sim.conf new file mode 100644 index 0000000000000..e2f26372eede3 --- /dev/null +++ b/samples/net/ptp/boards/native_sim.conf @@ -0,0 +1,8 @@ +# Settings for native_posix ethernet driver +CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK=y + +#CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=y +CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:2a" + +# Assume 1 ms accuracy for native_posix simulated clock +CONFIG_PTP_CLOCK_ACCURACY_1MS=y diff --git a/samples/net/ptp/boards/native_sim_native_64.conf b/samples/net/ptp/boards/native_sim_native_64.conf new file mode 100644 index 0000000000000..e2f26372eede3 --- /dev/null +++ b/samples/net/ptp/boards/native_sim_native_64.conf @@ -0,0 +1,8 @@ +# Settings for native_posix ethernet driver +CONFIG_ETH_NATIVE_POSIX_PTP_CLOCK=y + +#CONFIG_ETH_NATIVE_POSIX_RANDOM_MAC=y +CONFIG_ETH_NATIVE_POSIX_MAC_ADDR="00:00:5e:00:53:2a" + +# Assume 1 ms accuracy for native_posix simulated clock +CONFIG_PTP_CLOCK_ACCURACY_1MS=y diff --git a/samples/net/ptp/boards/qemu_x86.conf b/samples/net/ptp/boards/qemu_x86.conf new file mode 100644 index 0000000000000..e32acfe7b5aa2 --- /dev/null +++ b/samples/net/ptp/boards/qemu_x86.conf @@ -0,0 +1 @@ +CONFIG_USERSPACE=n diff --git a/samples/net/ptp/docker-test.sh b/samples/net/ptp/docker-test.sh new file mode 100644 index 0000000000000..1eb5d2b8beeb8 --- /dev/null +++ b/samples/net/ptp/docker-test.sh @@ -0,0 +1,29 @@ +# Copyright (c) 2024 BayLibre SAS +# SPDX-License-Identifier: Apache-2.0 + +if [ -z "$RUNNING_FROM_MAIN_SCRIPT" ]; then + echo "Do not run this script directly!" + echo "Run $ZEPHYR_BASE/scripts/net/run-sample-tests.sh instead." + exit 1 +fi + +# Running PTP sample using Docker testing + +start_configuration || return $? +start_docker \ + "/usr/local/sbin/ptp4l -4 -f /etc/gptp.cfg -m -q -l 6 -S -i eth0" \ + || return $? + +# For native_sim PTP run, the delay threshold needs to be huge +start_zephyr "$overlay" "-DCONFIG_NET_SAMPLE_RUN_DURATION=15" \ + +wait_zephyr +ptp_result=$? + +if [ $ptp_result -eq 1 -o $ptp_result -eq 2 ]; then + result=0 +else + result=1 +fi + +stop_docker diff --git a/samples/net/ptp/prj.conf b/samples/net/ptp/prj.conf new file mode 100644 index 0000000000000..2c4e13f838981 --- /dev/null +++ b/samples/net/ptp/prj.conf @@ -0,0 +1,35 @@ +CONFIG_NETWORKING=y +CONFIG_NET_LOG=y +CONFIG_LOG=y +CONFIG_NET_IPV4=y +CONFIG_NET_DHCPV4=n +CONFIG_NET_UDP=y + +CONFIG_TEST_RANDOM_GENERATOR=y + +CONFIG_NET_PKT_RX_COUNT=32 +CONFIG_NET_PKT_TX_COUNT=32 +CONFIG_NET_BUF_RX_COUNT=32 +CONFIG_NET_BUF_TX_COUNT=32 +CONFIG_NET_MAX_CONTEXTS=10 + +CONFIG_INIT_STACKS=y +CONFIG_PRINTK=y +CONFIG_NET_SHELL=y + +# Ethernet is needed for PTP +CONFIG_NET_L2_ETHERNET=y + +CONFIG_NET_CONFIG_NEED_IPV4=y +CONFIG_NET_CONFIG_SETTINGS=y + +# First ethernet interface will use these settings +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" + +# PTP settings +CONFIG_PTP_CLOCK=y +CONFIG_PTP=y +CONFIG_PTP_LOG_LEVEL_DBG=y + +CONFIG_LOG_MODE_DEFERRED=y diff --git a/samples/net/ptp/sample.yaml b/samples/net/ptp/sample.yaml new file mode 100644 index 0000000000000..706a88f03c93c --- /dev/null +++ b/samples/net/ptp/sample.yaml @@ -0,0 +1,20 @@ +common: + harness: net + tags: + - net + - ptp +sample: + description: Test PTP functionality + name: PTP sample app +tests: + sample.net.ptp: + platform_allow: + - native_sim + - native_sim/native/64 + - nucleo_h563zi + - nucleo_h743zi + - nucleo_h745zi_q/stm32h745xx/m7 + - qemu_x86 + depends_on: eth + integration_platforms: + - nucleo_h563zi diff --git a/samples/net/ptp/src/main.c b/samples/net/ptp/src/main.c new file mode 100644 index 0000000000000..97672dc14f274 --- /dev/null +++ b/samples/net/ptp/src/main.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2024 BayLibre SAS + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(net_ptp_sample, LOG_LEVEL_DBG); + +#include + +#include +#include + +#include "ptp/clock.h" +#include "ptp/port.h" + +static int run_duration = CONFIG_NET_SAMPLE_RUN_DURATION; +static struct k_work_delayable stop_sample; +static struct k_sem quit_lock; + +static void stop_handler(struct k_work *work) +{ + ARG_UNUSED(work); + + k_sem_give(&quit_lock); +} + +static int get_current_status(void) +{ + struct ptp_port *port; + sys_slist_t *ports_list = ptp_clock_ports_list(); + + if (!ports_list || sys_slist_len(ports_list) == 0) { + return -EINVAL; + } + + port = CONTAINER_OF(sys_slist_peek_head(ports_list), struct ptp_port, node); + + if (!port) { + return -EINVAL; + } + + switch (ptp_port_state(port)) { + case PTP_PS_INITIALIZING: + case PTP_PS_FAULTY: + case PTP_PS_DISABLED: + case PTP_PS_LISTENING: + case PTP_PS_PRE_TIME_TRANSMITTER: + case PTP_PS_PASSIVE: + case PTP_PS_UNCALIBRATED: + printk("FAIL\n"); + return 0; + case PTP_PS_TIME_RECEIVER: + printk("TIME RECEIVER\n"); + return 2; + case PTP_PS_TIME_TRANSMITTER: + case PTP_PS_GRAND_MASTER: + printk("TIME TRANSMITTER\n"); + return 1; + } + + return -1; +} + +void init_testing(void) +{ + uint32_t uptime = k_uptime_get_32(); + int ret; + + if (run_duration == 0) { + return; + } + + k_sem_init(&quit_lock, 0, K_SEM_MAX_LIMIT); + + k_work_init_delayable(&stop_sample, stop_handler); + k_work_reschedule(&stop_sample, K_SECONDS(run_duration)); + + k_sem_take(&quit_lock, K_FOREVER); + + LOG_INF("Stopping after %u seconds", + (k_uptime_get_32() - uptime) / 1000); + + /* Try to figure out what is the sync state. + * Return: + * <0 - configuration error + * 0 - not time sync + * 1 - we are TimeTransmitter + * 2 - we are TimeReceiver + */ + ret = get_current_status(); + + exit(ret); +} + +int main(void) +{ + init_testing(); + return 0; +} diff --git a/samples/net/secure_mqtt_sensor_actuator/CMakeLists.txt b/samples/net/secure_mqtt_sensor_actuator/CMakeLists.txt new file mode 100644 index 0000000000000..af4feece2dc50 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/CMakeLists.txt @@ -0,0 +1,11 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(secure_mqtt_sensor_actuator) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) + +zephyr_include_directories(${APPLICATION_SOURCE_DIR}/src/tls_config) diff --git a/samples/net/secure_mqtt_sensor_actuator/Kconfig b/samples/net/secure_mqtt_sensor_actuator/Kconfig new file mode 100644 index 0000000000000..19d15187acf26 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/Kconfig @@ -0,0 +1,58 @@ +# Copyright (c) 2024 Analog Devices, Inc. +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "Secure MQTT Sensor Actuator Sample Application" + +config NET_SAMPLE_MQTT_BROKER_HOSTNAME + string "Hostname of MQTT broker" + default "test.mosquitto.org" + help + MQTT broker's hostname or IP address. + +config NET_SAMPLE_MQTT_BROKER_PORT + string "MQTT Broker Connection Port" + default "8883" + help + Port through which the application should connect to the MQTT broker. + Secure MQTT uses port 8883. + +config NET_SAMPLE_MQTT_PUB_TOPIC + string "The MQTT topic the application should publish data to" + default "zephyr_sample/sensor" + +config NET_SAMPLE_MQTT_SUB_TOPIC_CMD + string "The MQTT topic the application will receive commands on" + default "zephyr_sample/command" + +config NET_SAMPLE_MQTT_PUBLISH_INTERVAL + int "Interval between MQTT publishes (in seconds)" + default 3 + help + This config determines the frequency at which MQTT publishes occur. + +choice NET_SAMPLE_MQTT_QOS + prompt "Quality of Service level used for MQTT publish and subscribe" + default NET_SAMPLE_MQTT_QOS_1_AT_LEAST_ONCE + +config NET_SAMPLE_MQTT_QOS_0_AT_MOST_ONCE + bool "QoS 0 / At most once delivery" + help + No acknowledgment needed for published message. + +config NET_SAMPLE_MQTT_QOS_1_AT_LEAST_ONCE + bool "QoS 1 / At least once delivery" + help + If acknowledgment expected for published message, duplicate messages permitted. + +config NET_SAMPLE_MQTT_QOS_2_EXACTLY_ONCE + bool "QoS 2 / Exactly once delivery" + help + Acknowledgment expected and message shall be published only once. + +endchoice + +config NET_SAMPLE_MQTT_PAYLOAD_SIZE + int "Size of MQTT payload in bytes" + default 128 + +source "Kconfig.zephyr" diff --git a/samples/net/secure_mqtt_sensor_actuator/README.rst b/samples/net/secure_mqtt_sensor_actuator/README.rst new file mode 100644 index 0000000000000..b2ff6a1573c14 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/README.rst @@ -0,0 +1,219 @@ +.. zephyr:code-sample:: secure-mqtt-sensor-actuator + :name: Secure MQTT Sensor/Actuator + :relevant-api: mqtt_socket sensor_interface + + Implement an MQTT-based IoT sensor/actuator device + +Overview +******** + +This sample demonstrates the implementation of an IoT sensor/actuator device. +The application uses the MQTT protocol to securely send sensor data +to a remote MQTT broker, while responding to commands received over MQTT. + +Features: + +- Establishing network connectivity using a DHCPv4 lease +- Establishing a secure MQTT connection (using TLS 1.2) to MQTT broker +- Publishing temperature sensor data in JSON format to the MQTT broker at a user-defined interval +- Subscribing to user-defined topic(s) on MQTT broker +- Responding to commands received over the network (LED control) +- Handling of MQTT connection, re-connecting and keep-alive +- Network status LED + +Requirements +************ +- Board with network capability (tested with adi_eval_adin1110ebz) +- `Eclipse Mosquitto`_ MQTT broker +- DHCP server +- Network connection between the board and Mosquitto broker + +Build and Running +***************** +This application relies on an network connection between the board and an MQTT broker. +This broker can exist locally (e.g. on a host PC) or a publicly available MQTT broker + can be used. +For quick sampling/testing, a configuration is provided to connect to a local MQTT broker +without security, using a static IP address. + +Hardware Setup +============== +If using Ethernet, connect the board to the MQTT broker. This may be your host PC +(for locally hosted Mosquitto broker) or your internet router +(to connect to the public Mosquitto broker). +If required, connect a temperature sensor to the board. + +Software Setup +============== +The temperature sensor should be aliased in devicetree as ``ambient-temp0``. +If a board does not include an on-board temperature sensor, one can be connected externally +and a board overlay file used to add the sensor and alias: + +.. code-block:: devicetree + + / { + aliases { + ambient-temp0 = &adt7420; + }; + }; + }; + +It is possible to use other types of sensors, by adding them in devicetree and by changing +``SENSOR_CHAN`` :file:`in device.c` to match the desired sensor type. + +There are a few ways to configure the application: + +.. list-table:: + + * - :file:`prj.conf` + - Default config: Secure MQTT, dynamic IP address (DHCP) + + * - :file:`overlay-static.conf` + - Secure MQTT, static IP address + + * - :file:`overlay-static-insecure.conf` + - Unsecure MQTT, static IP address + +**Default Config:** + +Using the default config, the application will use DHCP to acquire an IP address and attempt +to securely connect to an MQTT broker using TLS 1.2. + +- The MQTT broker to which the board will connect is specified by + ``CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME``. + By default, this is set to test.mosquitto.org. +- Connecting securely using TLS, requires the inclusion of the broker's CA certificate + in the application. +- Download the CA certificate in DER or PEM format from https://test.mosquitto.org +- In :file:`tls_config/cert.h`, set ``ca_certificate[]`` to the contents of the cert. +- By connecting the board to your internet router, it should automatically be assigned + an IPv4 address using DHCP. +- The application will then attempt to connect to the public Mosquitto broker + and begin publishing data. +- It is also possible to connect securely to a locally hosted MQTT broker. + This will require provisioning of certificates. + The CA cert should be included in the build as described above. + ``CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME`` should be configured to match the + local broker hostname/IP address. + Depending on the CA cert being used, additional MbedTLS config options may need to be enabled. + This can be done using Kconfig or using a custom MbedTLS config file + (see modules/mbedtls/Kconfig). + See https://mosquitto.org/man/mosquitto-tls-7.html for more info on setting up + TLS support for Mosquitto locally. +- A DHCP server can be installed on the host PC to handle assigning an IP to the board + e.g. dnsmasq (Linux) or DHCP Server for Windows (Windows). +- Build the sample with default config: + +.. zephyr-app-commands:: + :zephyr-app: samples/net/secure_mqtt_sensor_actuator + :board: adi_eval_adin1110ebz + :goals: build + :compact: + +**Static IP Config:** + +Use the :file:`overlay-static.conf` Kconfig overlay to disable DHCP and use +a static IP address config. +The device, gateway, and DNS server IP addresses should be set according to +your local network configuration. + +.. zephyr-app-commands:: + :zephyr-app: samples/net/secure_mqtt_sensor_actuator + :board: adi_eval_adin1110ebz + :conf: "prj.conf overlay-static.conf" + :goals: build + :compact: + +**Static IP/Unsecure MQTT Config:** + +Use the :file:`overlay-static-insecure.conf` Kconfig overlay to disable TLS and DHCP. +This config requires connecting to a locally hosted Mosquitto MQTT broker. + +- In :file:`overlay-static-insecure.conf`, set the IP address of the board and the Mosquitto + broker (i.e. IP address of Ethernet port on host PC). These addresses should be in the + same subnet e.g. 192.0.2.1 and 192.0.2.2. +- On your host PC, install Mosquitto. +- Create a file called ``unsecure.conf`` with the following content: + +.. code-block:: console + + listener 1883 0.0.0.0 + allow_anonymous true + + +- Start a Mosquitto broker using the configuration file: + +.. code-block:: console + + $ sudo mosquitto -v -c unsecure.conf + +- Build the sample with quick test config: + +.. zephyr-app-commands:: + :zephyr-app: samples/net/secure_mqtt_sensor_actuator + :board: adi_eval_adin1110ebz + :conf: "prj.conf overlay-static-insecure.conf" + :goals: build + :compact: + +Using the Sample +================ +- Once the board establishes an MQTT connection with the Mosquitto broker, the network + LED will turn on and the board will begin publishing sensor readings in JSON format + at a regular interval determined by ``CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL``. + +- Use Mosquitto to subscribe to the sensor data being sent from the board: + +.. code-block:: console + + $ mosquitto_sub -d -h -t zephyr_sample/sensor + +- The application will subscribe to a topic determined by ``CONFIG_NET_SAMPLE_MQTT_SUB_TOPIC_CMD``. + If a supported command string is received by the board on this topic, the board will execute + an associated command handler function. + Supported commands (defined in :file:`device.c`): + + - ``led_on``, turn on board LED + - ``led_off``, turn off board LED + +- Use Mosquitto to publish these commands to the MQTT broker: + +.. code-block:: console + + $ mosquitto_pub -d -h --cafile -t zephyr_sample/command -m "led_on" + +- The Quality of Service (QoS) level that is used for MQTT publishing and + subscriptions can be configured using Kconfig. + +Sample output +============= + +.. code-block:: console + + *** Booting Zephyr OS build v3.6.0-2212-g2c9c4f3733e9 *** + [00:00:00.181,000] app_device: Device adt7420@48 is ready + [00:00:00.181,000] app_device: Device leds is ready + [00:00:00.181,000] app_main: MAC Address: 00:E0:FE:FE:DA:C8 + [00:00:00.181,000] app_main: Bringing up network.. + [00:00:00.801,000] net_dhcpv4: Received: 192.168.1.17 + [00:00:00.801,000] app_main: Network connectivity up! + [00:00:00.818,000] app_mqtt: Connecting to MQTT broker @ 91.121.93.94 + [00:00:01.154,000] net_mqtt: Connect completed + [00:00:01.197,000] app_mqtt: Connected to MQTT broker! + [00:00:01.197,000] app_mqtt: Hostname: test.mosquitto.org + [00:00:01.198,000] app_mqtt: Client ID: adi_eval_adin1110ebz_9a + [00:00:01.198,000] app_mqtt: Port: 8883 + [00:00:01.198,000] app_mqtt: TLS: Enabled + [00:00:01.198,000] app_mqtt: Subscribing to 1 topic(s) + [00:00:01.238,000] app_mqtt: SUBACK packet ID: 5841 + [00:00:04.200,000] app_mqtt: Published to topic 'zephyr_sample/sensor', QoS 1 + [00:00:04.319,000] app_mqtt: PUBACK packet ID: 1 + [00:00:07.202,000] app_mqtt: Published to topic 'zephyr_sample/sensor', QoS 1 + [00:00:07.323,000] app_mqtt: PUBACK packet ID: 2 + [00:00:10.204,000] app_mqtt: Published to topic 'zephyr_sample/sensor', QoS 1 + [00:00:10.322,000] app_mqtt: PUBACK packet ID: 3 + [00:00:12.769,000] app_mqtt: MQTT payload received! + [00:00:12.769,000] app_mqtt: topic: 'zephyr_sample/command', payload: led_on + [00:00:12.770,000] app_device: Executing device command: led_on + +.. _Eclipse Mosquitto: https://mosquitto.org/download/ diff --git a/samples/net/secure_mqtt_sensor_actuator/boards/adi_eval_adin1110ebz.overlay b/samples/net/secure_mqtt_sensor_actuator/boards/adi_eval_adin1110ebz.overlay new file mode 100644 index 0000000000000..8182bb8b230a0 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/boards/adi_eval_adin1110ebz.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&adin1110 { + mdio { + /* Enable link status LED */ + ethernet-phy@1 { + led0-en; + led1-en; + }; + }; +}; diff --git a/samples/net/secure_mqtt_sensor_actuator/overlay-static-insecure.conf b/samples/net/secure_mqtt_sensor_actuator/overlay-static-insecure.conf new file mode 100644 index 0000000000000..33655bfe4e10b --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/overlay-static-insecure.conf @@ -0,0 +1,18 @@ +# Config to disable TLS and DHCPv4, allowing insecure MQTT and a static IP address. +# This allows quick testing of the application without need for a DHCP server or secure MQTT broker set up. +# Only recommended for quick sampling/testing. +# Usage: west build -b -- -DOVERLAY_CONFIG=overlay-static-insecure.conf + +# Disable MQTT with TLS +CONFIG_MQTT_LIB_TLS=n + +# Disable DHCP +CONFIG_NET_DHCPV4=n + +# Insecure MQTT uses port 1883 +CONFIG_NET_SAMPLE_MQTT_BROKER_PORT="1883" + +# Static IP address config +CONFIG_NET_CONFIG_SETTINGS=y +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME="192.0.2.2" diff --git a/samples/net/secure_mqtt_sensor_actuator/overlay-static.conf b/samples/net/secure_mqtt_sensor_actuator/overlay-static.conf new file mode 100644 index 0000000000000..69737f64078f8 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/overlay-static.conf @@ -0,0 +1,8 @@ +CONFIG_NET_DHCPV4=n +CONFIG_NET_CONFIG_SETTINGS=y +CONFIG_NET_CONFIG_NEED_IPV4=y +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" +CONFIG_DNS_RESOLVER=y +CONFIG_DNS_SERVER_IP_ADDRESSES=y +CONFIG_DNS_SERVER1="192.0.2.2" diff --git a/samples/net/secure_mqtt_sensor_actuator/prj.conf b/samples/net/secure_mqtt_sensor_actuator/prj.conf new file mode 100644 index 0000000000000..b87eaa2c348f5 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/prj.conf @@ -0,0 +1,59 @@ +# Enable network stack +CONFIG_NETWORKING=y +CONFIG_NET_LOG=y + +# Enable IPv4 +CONFIG_NET_IPV4=y + +# Enable IPv6 +CONFIG_NET_IPV6=y + +# Enable TCP +CONFIG_NET_TCP=y + +# Enable DHCP +CONFIG_NET_DHCPV4=y + +# Enable Sockets (used by MQTT lib) +CONFIG_NET_SOCKETS=y +CONFIG_NET_SOCKETS_SOCKOPT_TLS=y + +# Enable MQTT +CONFIG_MQTT_LIB=y +CONFIG_MQTT_LIB_TLS=y + +# Enable Mbed TLS +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_ENABLE_HEAP=y +CONFIG_MBEDTLS_HEAP_SIZE=60000 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y +CONFIG_MBEDTLS_SERVER_NAME_INDICATION=y + +# Enable JSON +CONFIG_JSON_LIBRARY=y + +# Enable net conn manager +CONFIG_NET_CONNECTION_MANAGER=y + +# Enable device hostname +CONFIG_NET_HOSTNAME_ENABLE=y + +# Enable Posix API functionality +CONFIG_POSIX_API=y + +# Enable sensor API +CONFIG_SENSOR=y + +# Enable LED API +CONFIG_LED=y + +# Main stack size +CONFIG_MAIN_STACK_SIZE=2048 + +# System work queue stack size +CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048 + +# Increase Rx net buffers +CONFIG_NET_BUF_RX_COUNT=100 diff --git a/samples/net/secure_mqtt_sensor_actuator/sample.yaml b/samples/net/secure_mqtt_sensor_actuator/sample.yaml new file mode 100644 index 0000000000000..44b9a4d7d2a3a --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/sample.yaml @@ -0,0 +1,33 @@ +sample: + name: Secure MQTT Sensor/Actuator Sample +tests: + sample.net.secure_mqtt_sensor_actuator: + harness: net + tags: + - net + - mqtt + - sensors + filter: dt_alias_exists("ambient-temp0") + integration_platforms: + - adi_eval_adin1110ebz + sample.net.secure_mqtt_sensor_actuator.staticip: + harness: net + extra_args: OVERLAY_CONFIG="overlay-static.conf" + tags: + - net + - mqtt + - sensors + filter: dt_alias_exists("ambient-temp0") + integration_platforms: + - native_sim + sample.net.secure_mqtt_sensor_actuator.staticip_insecure: + harness: net + extra_args: OVERLAY_CONFIG="overlay-static-insecure.conf" + tags: + - net + - mqtt + - sensors + filter: dt_alias_exists("ambient-temp0") + integration_platforms: + - adi_eval_adin1110ebz + - native_sim diff --git a/samples/net/secure_mqtt_sensor_actuator/src/device.c b/samples/net/secure_mqtt_sensor_actuator/src/device.c new file mode 100644 index 0000000000000..7ac800e43e20c --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/device.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(app_device, LOG_LEVEL_DBG); + +#include +#include +#include +#include + +#include "device.h" + +#define SENSOR_CHAN SENSOR_CHAN_AMBIENT_TEMP +#define SENSOR_UNIT "Celsius" + +/* Devices */ +static const struct device *sensor = DEVICE_DT_GET_OR_NULL(DT_ALIAS(ambient_temp0)); +static const struct device *leds = DEVICE_DT_GET_OR_NULL(DT_INST(0, gpio_leds)); + +/* Command handlers */ +static void led_on_handler(void) +{ + device_write_led(LED_USER, LED_ON); +} + +static void led_off_handler(void) +{ + device_write_led(LED_USER, LED_OFF); +} + +/* Supported device commands */ +struct device_cmd device_commands[] = { + {"led_on", led_on_handler}, + {"led_off", led_off_handler} +}; + +const size_t num_device_commands = ARRAY_SIZE(device_commands); + +/* Command dispatcher */ +void device_command_handler(uint8_t *command) +{ + for (int i = 0; i < num_device_commands; i++) { + if (strcmp(command, device_commands[i].command) == 0) { + LOG_INF("Executing device command: %s", device_commands[i].command); + return device_commands[i].handler(); + } + } + LOG_ERR("Unknown command: %s", command); +} + +int device_read_sensor(struct sensor_sample *sample) +{ + int rc; + struct sensor_value sensor_val; + + /* Read sample only if a real sensor device is present + * otherwise return a dummy value + */ + if (sensor == NULL) { + sample->unit = SENSOR_UNIT; + sample->value = 20.0 + (double)sys_rand32_get() / UINT32_MAX * 5.0; + return 0; + } + + rc = sensor_sample_fetch(sensor); + if (rc) { + LOG_ERR("Failed to fetch sensor sample [%d]", rc); + return rc; + } + + rc = sensor_channel_get(sensor, SENSOR_CHAN, &sensor_val); + if (rc) { + LOG_ERR("Failed to get sensor channel [%d]", rc); + return rc; + } + + sample->unit = SENSOR_UNIT; + sample->value = sensor_value_to_double(&sensor_val); + return rc; +} + +int device_write_led(enum led_id led_idx, enum led_state state) +{ + int rc; + + switch (state) { + case LED_OFF: + if (leds == NULL) { + LOG_INF("LED %d OFF", led_idx); + break; + } + led_off(leds, led_idx); + break; + case LED_ON: + if (leds == NULL) { + LOG_INF("LED %d ON", led_idx); + break; + } + led_on(leds, led_idx); + break; + default: + LOG_ERR("Invalid LED state setting"); + rc = -EINVAL; + break; + } + + return rc; +} + +bool devices_ready(void) +{ + bool rc = true; + + /* Check readiness only if a real sensor device is present */ + if (sensor != NULL) { + if (!device_is_ready(sensor)) { + LOG_ERR("Device %s is not ready", sensor->name); + rc = false; + } else { + LOG_INF("Device %s is ready", sensor->name); + } + } + + if (leds != NULL) { + if (!device_is_ready(leds)) { + LOG_ERR("Device %s is not ready", leds->name); + rc = false; + } else { + LOG_INF("Device %s is ready", leds->name); + } + } + + return rc; +} diff --git a/samples/net/secure_mqtt_sensor_actuator/src/device.h b/samples/net/secure_mqtt_sensor_actuator/src/device.h new file mode 100644 index 0000000000000..ad09b9d3efa90 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/device.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DEVICE_H__ +#define __DEVICE_H__ + +/** @brief Sensor sample structure */ +struct sensor_sample { + const char *unit; + int value; +}; + +/** @brief Available board LEDs */ +enum led_id { + LED_NET, /* Network status LED*/ + LED_USER /* User LED */ +}; + +/** @brief LED states */ +enum led_state { + LED_OFF, + LED_ON +}; + +/** @brief Device command consisting of a command string + * and associated handler function pointer + */ +struct device_cmd { + const char *command; + void (*handler)(); +}; + +/** + * @brief Check if all devices are ready + */ +bool devices_ready(void); + +/** + * @brief Read sample from the sensor + */ +int device_read_sensor(struct sensor_sample *sample); + +/** + * @brief Write to a board LED + */ +int device_write_led(enum led_id led_idx, enum led_state state); + +/** + * @brief Handler function for commands received over MQTT + */ +void device_command_handler(uint8_t *command); + +#endif /* __DEVICE_H__ */ diff --git a/samples/net/secure_mqtt_sensor_actuator/src/main.c b/samples/net/secure_mqtt_sensor_actuator/src/main.c new file mode 100644 index 0000000000000..64993139e9007 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/main.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(app_main, LOG_LEVEL_DBG); + +#include +#include +#include +#include +#include + +#include "mqtt_client.h" +#include "device.h" + +#define NET_L4_EVENT_MASK (NET_EVENT_L4_CONNECTED | NET_EVENT_L4_DISCONNECTED) + +/* MQTT client struct */ +static struct mqtt_client client_ctx; + +/* MQTT publish work item */ +struct k_work_delayable mqtt_publish_work; + +static struct net_mgmt_event_callback net_l4_mgmt_cb; + +/* Network connection semaphore */ +K_SEM_DEFINE(net_conn_sem, 0, 1); + +static void net_l4_evt_handler(struct net_mgmt_event_callback *cb, + uint32_t mgmt_event, struct net_if *iface) +{ + switch (mgmt_event) { + case NET_EVENT_L4_CONNECTED: + k_sem_give(&net_conn_sem); + LOG_INF("Network connectivity up!"); + break; + case NET_EVENT_L4_DISCONNECTED: + LOG_INF("Network connectivity down!"); + break; + default: + break; + } +} + +/** Print the device's MAC address to console */ +void log_mac_addr(struct net_if *iface) +{ + struct net_linkaddr *mac; + + mac = net_if_get_link_addr(iface); + + LOG_INF("MAC Address: %02X:%02X:%02X:%02X:%02X:%02X", + mac->addr[0], mac->addr[1], mac->addr[3], + mac->addr[3], mac->addr[4], mac->addr[5]); +} + +/** The system work queue is used to handle periodic MQTT publishing. + * Work queuing begins when the MQTT connection is established. + * Use CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL to set the publish frequency. + */ + +static void publish_work_handler(struct k_work *work) +{ + int rc; + + if (mqtt_connected) { + rc = app_mqtt_publish(&client_ctx); + if (rc != 0) { + LOG_INF("MQTT Publish failed [%d]", rc); + } + k_work_reschedule(&mqtt_publish_work, + K_SECONDS(CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL)); + } else { + k_work_cancel_delayable(&mqtt_publish_work); + } +} + +int main(void) +{ + int rc; + struct net_if *iface; + + devices_ready(); + + iface = net_if_get_default(); + if (iface == NULL) { + LOG_ERR("No network interface configured"); + return -ENETDOWN; + } + + log_mac_addr(iface); + + /* Register callbacks for L4 events */ + net_mgmt_init_event_callback(&net_l4_mgmt_cb, &net_l4_evt_handler, NET_L4_EVENT_MASK); + net_mgmt_add_event_callback(&net_l4_mgmt_cb); + + LOG_INF("Bringing up network.."); + +#if defined(CONFIG_NET_DHCPV4) + net_dhcpv4_start(iface); +#else + /* If using static IP, L4 Connect callback will happen, + * before conn mgr is initialised, so resend events here + * to check for connectivity + */ + conn_mgr_mon_resend_status(); +#endif + + /* Wait for network to come up */ + while (k_sem_take(&net_conn_sem, K_MSEC(MSECS_NET_POLL_TIMEOUT)) != 0) { + LOG_INF("Waiting for network connection.."); + } + + rc = app_mqtt_init(&client_ctx); + if (rc != 0) { + LOG_ERR("MQTT Init failed [%d]", rc); + return rc; + } + + /* Initialise MQTT publish work item */ + k_work_init_delayable(&mqtt_publish_work, publish_work_handler); + + /* Thread main loop */ + while (1) { + /* Block until MQTT connection is up */ + app_mqtt_connect(&client_ctx); + + /* We are now connected, begin queueing periodic MQTT publishes */ + k_work_reschedule(&mqtt_publish_work, + K_SECONDS(CONFIG_NET_SAMPLE_MQTT_PUBLISH_INTERVAL)); + + /* Handle MQTT inputs and connection */ + app_mqtt_run(&client_ctx); + } + + return rc; +} diff --git a/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.c b/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.c new file mode 100644 index 0000000000000..3fdb6f3abf479 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.c @@ -0,0 +1,510 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +LOG_MODULE_REGISTER(app_mqtt, LOG_LEVEL_DBG); + +#include +#include +#include +#include +#include + +#include "mqtt_client.h" +#include "device.h" + +/* Buffers for MQTT client */ +static uint8_t rx_buffer[CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE]; +static uint8_t tx_buffer[CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE]; + +/* MQTT payload buffer */ +static uint8_t payload_buf[CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE]; + +/* MQTT broker details */ +static struct sockaddr_storage broker; + +/* Socket descriptor */ +static struct zsock_pollfd fds[1]; +static int nfds; + +/* JSON payload format */ +static const struct json_obj_descr sensor_sample_descr[] = { + JSON_OBJ_DESCR_PRIM(struct sensor_sample, unit, JSON_TOK_STRING), + JSON_OBJ_DESCR_PRIM(struct sensor_sample, value, JSON_TOK_NUMBER), +}; + +/* MQTT connectivity status flag */ +bool mqtt_connected; + +/* MQTT client ID buffer */ +static uint8_t client_id[50]; + +#if defined(CONFIG_MQTT_LIB_TLS) +#include "tls_config/cert.h" + +/* This should match the CN field in the server's CA cert */ +#define TLS_SNI_HOSTNAME CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME +#define APP_CA_CERT_TAG 1 + +static const sec_tag_t m_sec_tags[] = { + APP_CA_CERT_TAG, +}; + +/** Register CA certificate for TLS */ +static int tls_init(void) +{ + int rc; + + rc = tls_credential_add(APP_CA_CERT_TAG, TLS_CREDENTIAL_CA_CERTIFICATE, + ca_certificate, sizeof(ca_certificate)); + if (rc < 0) { + LOG_ERR("Failed to register public certificate: %d", rc); + return rc; + } + + return rc; +} +#endif + +static void prepare_fds(struct mqtt_client *client) +{ + if (client->transport.type == MQTT_TRANSPORT_NON_SECURE) { + fds[0].fd = client->transport.tcp.sock; + } +#if defined(CONFIG_MQTT_LIB_TLS) + else if (client->transport.type == MQTT_TRANSPORT_SECURE) { + fds[0].fd = client->transport.tls.sock; + } +#endif + + fds[0].events = ZSOCK_POLLIN; + nfds = 1; +} + +static void clear_fds(void) +{ + nfds = 0; +} + +/** Initialise the MQTT client ID as the board name with random hex postfix */ +static void init_mqtt_client_id(void) +{ + snprintk(client_id, sizeof(client_id), CONFIG_BOARD"_%x", (uint8_t)sys_rand32_get()); +} + +static inline void on_mqtt_connect(void) +{ + mqtt_connected = true; + device_write_led(LED_NET, LED_ON); + LOG_INF("Connected to MQTT broker!"); + LOG_INF("Hostname: %s", CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME); + LOG_INF("Client ID: %s", client_id); + LOG_INF("Port: %s", CONFIG_NET_SAMPLE_MQTT_BROKER_PORT); + LOG_INF("TLS: %s", + IS_ENABLED(CONFIG_MQTT_LIB_TLS) ? "Enabled" : "Disabled"); +} + +static inline void on_mqtt_disconnect(void) +{ + mqtt_connected = false; + clear_fds(); + device_write_led(LED_NET, LED_OFF); + LOG_INF("Disconnected from MQTT broker"); +} + +/** Called when an MQTT payload is received. + * Reads the payload and calls the commands + * handler if a payloads is received on the + * command topic + */ +static void on_mqtt_publish(struct mqtt_client *const client, const struct mqtt_evt *evt) +{ + int rc; + uint8_t payload[CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE]; + + rc = mqtt_read_publish_payload(client, payload, + CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE); + if (rc < 0) { + LOG_ERR("Failed to read received MQTT payload [%d]", rc); + return; + } + /* Place null terminator at end of payload buffer */ + payload[rc] = '\0'; + + LOG_INF("MQTT payload received!"); + LOG_INF("topic: '%s', payload: %s", + evt->param.publish.message.topic.topic.utf8, payload); + + /* If the topic is a command, call the command handler */ + if (strcmp(evt->param.publish.message.topic.topic.utf8, + CONFIG_NET_SAMPLE_MQTT_SUB_TOPIC_CMD) == 0) { + device_command_handler(payload); + } +} + +/** Handler for asynchronous MQTT events */ +static void mqtt_event_handler(struct mqtt_client *const client, const struct mqtt_evt *evt) +{ + switch (evt->type) { + case MQTT_EVT_CONNACK: + if (evt->result != 0) { + LOG_ERR("MQTT Event Connect failed [%d]", evt->result); + break; + } + on_mqtt_connect(); + break; + + case MQTT_EVT_DISCONNECT: + on_mqtt_disconnect(); + break; + + case MQTT_EVT_PINGRESP: + LOG_INF("PINGRESP packet"); + break; + + case MQTT_EVT_PUBACK: + if (evt->result != 0) { + LOG_ERR("MQTT PUBACK error [%d]", evt->result); + break; + } + + LOG_INF("PUBACK packet ID: %u", evt->param.puback.message_id); + break; + + case MQTT_EVT_PUBREC: + if (evt->result != 0) { + LOG_ERR("MQTT PUBREC error [%d]", evt->result); + break; + } + + LOG_INF("PUBREC packet ID: %u", evt->param.pubrec.message_id); + + const struct mqtt_pubrel_param rel_param = { + .message_id = evt->param.pubrec.message_id + }; + + mqtt_publish_qos2_release(client, &rel_param); + break; + + case MQTT_EVT_PUBREL: + if (evt->result != 0) { + LOG_ERR("MQTT PUBREL error [%d]", evt->result); + break; + } + + LOG_INF("PUBREL packet ID: %u", evt->param.pubrel.message_id); + + const struct mqtt_pubcomp_param rec_param = { + .message_id = evt->param.pubrel.message_id + }; + + mqtt_publish_qos2_complete(client, &rec_param); + break; + + case MQTT_EVT_PUBCOMP: + if (evt->result != 0) { + LOG_ERR("MQTT PUBCOMP error %d", evt->result); + break; + } + + LOG_INF("PUBCOMP packet ID: %u", evt->param.pubcomp.message_id); + break; + + case MQTT_EVT_SUBACK: + if (evt->result == 0x80) { + LOG_ERR("MQTT SUBACK error [%d]", evt->result); + break; + } + + LOG_INF("SUBACK packet ID: %d", evt->param.suback.message_id); + break; + + case MQTT_EVT_PUBLISH: + const struct mqtt_publish_param *p = &evt->param.publish; + + if (p->message.topic.qos == MQTT_QOS_1_AT_LEAST_ONCE) { + const struct mqtt_puback_param ack_param = { + .message_id = p->message_id + }; + mqtt_publish_qos1_ack(client, &ack_param); + } else if (p->message.topic.qos == MQTT_QOS_2_EXACTLY_ONCE) { + const struct mqtt_pubrec_param rec_param = { + .message_id = p->message_id + }; + mqtt_publish_qos2_receive(client, &rec_param); + } + + on_mqtt_publish(client, evt); + + default: + break; + } +} + +/** Poll the MQTT socket for received data */ +static int poll_mqtt_socket(struct mqtt_client *client, int timeout) +{ + int rc; + + prepare_fds(client); + + if (nfds <= 0) { + return -EINVAL; + } + + rc = zsock_poll(fds, nfds, timeout); + if (rc < 0) { + LOG_ERR("Socket poll error [%d]", rc); + } + + return rc; +} + +/** Retrieves a sensor sample and encodes it in JSON format */ +static int get_mqtt_payload(struct mqtt_binstr *payload) +{ + int rc; + struct sensor_sample sample; + + rc = device_read_sensor(&sample); + if (rc != 0) { + LOG_ERR("Failed to get sensor sample [%d]", rc); + return rc; + } + + rc = json_obj_encode_buf(sensor_sample_descr, ARRAY_SIZE(sensor_sample_descr), + &sample, payload_buf, CONFIG_NET_SAMPLE_MQTT_PAYLOAD_SIZE); + if (rc != 0) { + LOG_ERR("Failed to encode JSON object [%d]", rc); + return rc; + } + + payload->data = payload_buf; + payload->len = strlen(payload->data); + + return rc; +} + +int app_mqtt_publish(struct mqtt_client *client) +{ + int rc; + struct mqtt_publish_param param; + struct mqtt_binstr payload; + static uint16_t msg_id = 1; + struct mqtt_topic topic = { + .topic = { + .utf8 = CONFIG_NET_SAMPLE_MQTT_PUB_TOPIC, + .size = strlen(topic.topic.utf8) + }, + .qos = IS_ENABLED(CONFIG_NET_SAMPLE_MQTT_QOS_0_AT_MOST_ONCE) ? 0 : + (IS_ENABLED(CONFIG_NET_SAMPLE_MQTT_QOS_1_AT_LEAST_ONCE) ? 1 : 2) + }; + + rc = get_mqtt_payload(&payload); + if (rc != 0) { + LOG_ERR("Failed to get MQTT payload [%d]", rc); + } + + param.message.topic = topic; + param.message.payload = payload; + param.message_id = msg_id++; + param.dup_flag = 0; + param.retain_flag = 0; + + rc = mqtt_publish(client, ¶m); + if (rc != 0) { + LOG_ERR("MQTT Publish failed [%d]", rc); + } + + LOG_INF("Published to topic '%s', QoS %d", + param.message.topic.topic.utf8, + param.message.topic.qos); + + return rc; +} + +int app_mqtt_subscribe(struct mqtt_client *client) +{ + int rc; + struct mqtt_topic sub_topics[] = { + { + .topic = { + .utf8 = CONFIG_NET_SAMPLE_MQTT_SUB_TOPIC_CMD, + .size = strlen(sub_topics->topic.utf8) + }, + .qos = IS_ENABLED(CONFIG_NET_SAMPLE_MQTT_QOS_0_AT_MOST_ONCE) ? 0 : + (IS_ENABLED(CONFIG_NET_SAMPLE_MQTT_QOS_1_AT_LEAST_ONCE) ? 1 : 2) + } + }; + const struct mqtt_subscription_list sub_list = { + .list = sub_topics, + .list_count = ARRAY_SIZE(sub_topics), + .message_id = 5841u + }; + + LOG_INF("Subscribing to %d topic(s)", sub_list.list_count); + + rc = mqtt_subscribe(client, &sub_list); + if (rc != 0) { + LOG_ERR("MQTT Subscribe failed [%d]", rc); + } + + return rc; +} + +/** Process incoming MQTT data and keep the connection alive*/ +int app_mqtt_process(struct mqtt_client *client) +{ + int rc; + + rc = poll_mqtt_socket(client, mqtt_keepalive_time_left(client)); + if (rc != 0) { + if (fds[0].revents & ZSOCK_POLLIN) { + /* MQTT data received */ + rc = mqtt_input(client); + if (rc != 0) { + LOG_ERR("MQTT Input failed [%d]", rc); + return rc; + } + /* Socket error */ + if (fds[0].revents & (ZSOCK_POLLHUP | ZSOCK_POLLERR)) { + LOG_ERR("MQTT socket closed / error"); + return -ENOTCONN; + } + } + } else { + /* Socket poll timed out, time to call mqtt_live() */ + rc = mqtt_live(client); + if (rc != 0) { + LOG_ERR("MQTT Live failed [%d]", rc); + return rc; + } + } + + return 0; +} + +void app_mqtt_run(struct mqtt_client *client) +{ + int rc; + + /* Subscribe to MQTT topics */ + app_mqtt_subscribe(client); + + /* Thread will primarily remain in this loop */ + while (mqtt_connected) { + rc = app_mqtt_process(client); + if (rc != 0) { + break; + } + } + /* Gracefully close connection */ + mqtt_disconnect(client); +} + +void app_mqtt_connect(struct mqtt_client *client) +{ + int rc = 0; + + mqtt_connected = false; + + /* Block until MQTT CONNACK event callback occurs */ + while (!mqtt_connected) { + rc = mqtt_connect(client); + if (rc != 0) { + LOG_ERR("MQTT Connect failed [%d]", rc); + k_msleep(MSECS_WAIT_RECONNECT); + continue; + } + + /* Poll MQTT socket for response */ + rc = poll_mqtt_socket(client, MSECS_NET_POLL_TIMEOUT); + if (rc > 0) { + mqtt_input(client); + } + + if (!mqtt_connected) { + mqtt_abort(client); + } + } +} + +int app_mqtt_init(struct mqtt_client *client) +{ + int rc; + uint8_t broker_ip[NET_IPV4_ADDR_LEN]; + struct sockaddr_in *broker4; + struct addrinfo *result; + const struct addrinfo hints = { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM + }; + + /* Resolve IP address of MQTT broker */ + rc = getaddrinfo(CONFIG_NET_SAMPLE_MQTT_BROKER_HOSTNAME, + CONFIG_NET_SAMPLE_MQTT_BROKER_PORT, &hints, &result); + if (rc != 0) { + LOG_ERR("Failed to resolve broker hostname [%s]", gai_strerror(rc)); + return -EIO; + } + if (result == NULL) { + LOG_ERR("Broker address not found"); + return -ENOENT; + } + + broker4 = (struct sockaddr_in *)&broker; + broker4->sin_addr.s_addr = ((struct sockaddr_in *)result->ai_addr)->sin_addr.s_addr; + broker4->sin_family = AF_INET; + broker4->sin_port = ((struct sockaddr_in *)result->ai_addr)->sin_port; + freeaddrinfo(result); + + /* Log resolved IP address */ + inet_ntop(AF_INET, &broker4->sin_addr.s_addr, broker_ip, sizeof(broker_ip)); + LOG_INF("Connecting to MQTT broker @ %s", broker_ip); + + /* MQTT client configuration */ + init_mqtt_client_id(); + mqtt_client_init(client); + client->broker = &broker; + client->evt_cb = mqtt_event_handler; + client->client_id.utf8 = client_id; + client->client_id.size = strlen(client->client_id.utf8); + client->password = NULL; + client->user_name = NULL; + client->protocol_version = MQTT_VERSION_3_1_1; + + /* MQTT buffers configuration */ + client->rx_buf = rx_buffer; + client->rx_buf_size = sizeof(rx_buffer); + client->tx_buf = tx_buffer; + client->tx_buf_size = sizeof(tx_buffer); + + /* MQTT transport configuration */ +#if defined(CONFIG_MQTT_LIB_TLS) + struct mqtt_sec_config *tls_config; + + client->transport.type = MQTT_TRANSPORT_SECURE; + + rc = tls_init(); + if (rc != 0) { + LOG_ERR("TLS init error"); + return rc; + } + + tls_config = &client->transport.tls.config; + tls_config->peer_verify = TLS_PEER_VERIFY_REQUIRED; + tls_config->cipher_list = NULL; + tls_config->sec_tag_list = m_sec_tags; + tls_config->sec_tag_count = ARRAY_SIZE(m_sec_tags); +#if defined(CONFIG_MBEDTLS_SERVER_NAME_INDICATION) + tls_config->hostname = TLS_SNI_HOSTNAME; +#else + tls_config->hostname = NULL; +#endif /* CONFIG_MBEDTLS_SERVER_NAME_INDICATION */ +#endif /* CONFIG_MQTT_LIB_TLS */ + + return rc; +} diff --git a/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.h b/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.h new file mode 100644 index 0000000000000..d78c2b05d342a --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/mqtt_client.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __MQTT_CLIENT_H__ +#define __MQTT_CLIENT_H__ + +/** MQTT connection timeouts */ +#define MSECS_NET_POLL_TIMEOUT 5000 +#define MSECS_WAIT_RECONNECT 1000 + +/** MQTT connection status flag */ +extern bool mqtt_connected; + +/** + * @brief Initialise the MQTT client & broker configuration + */ +int app_mqtt_init(struct mqtt_client *client); + +/** + * @brief Blocking function that establishes connectivity to the MQTT broker + */ +void app_mqtt_connect(struct mqtt_client *client); + +/** + * @brief Subscribes to user-defined MQTT topics and continuously + * processes incoming data while the MQTT connection is active + */ +void app_mqtt_run(struct mqtt_client *client); + +/** + * @brief Subscribe to user-defined MQTT topics + */ +int app_mqtt_subscribe(struct mqtt_client *client); + +/** + * @brief Publish MQTT payload + */ +int app_mqtt_publish(struct mqtt_client *client); + +#endif /* __MQTT_CLIENT_H__ */ diff --git a/samples/net/secure_mqtt_sensor_actuator/src/tls_config/cert.h b/samples/net/secure_mqtt_sensor_actuator/src/tls_config/cert.h new file mode 100644 index 0000000000000..e044f465b9e05 --- /dev/null +++ b/samples/net/secure_mqtt_sensor_actuator/src/tls_config/cert.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Analog Devices, Inc. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __CERT_H__ +#define __CERT_H__ + +/* The CA certficate of the MQTT broker should be included here + * The certificate can either be in DER or PEM format. + * A DER certificate can be converted to a byte array using + * "cat ca.crt | sed -e '1d;$d' | base64 -d |xxd -i" + * If using a PEM certifificate, each line should be wrapped in "\r\n" + */ + +/* CA certificate for Mosquitto public broker + * (available from test.mosquitto.org, valid at time of development) + */ +static const unsigned char ca_certificate[] = "-----BEGIN CERTIFICATE-----\r\n" +"MIIEAzCCAuugAwIBAgIUBY1hlCGvdj4NhBXkZ/uLUZNILAwwDQYJKoZIhvcNAQEL\r\n" +"BQAwgZAxCzAJBgNVBAYTAkdCMRcwFQYDVQQIDA5Vbml0ZWQgS2luZ2RvbTEOMAwG\r\n" +"A1UEBwwFRGVyYnkxEjAQBgNVBAoMCU1vc3F1aXR0bzELMAkGA1UECwwCQ0ExFjAU\r\n" +"BgNVBAMMDW1vc3F1aXR0by5vcmcxHzAdBgkqhkiG9w0BCQEWEHJvZ2VyQGF0Y2hv\r\n" +"by5vcmcwHhcNMjAwNjA5MTEwNjM5WhcNMzAwNjA3MTEwNjM5WjCBkDELMAkGA1UE\r\n" +"BhMCR0IxFzAVBgNVBAgMDlVuaXRlZCBLaW5nZG9tMQ4wDAYDVQQHDAVEZXJieTES\r\n" +"MBAGA1UECgwJTW9zcXVpdHRvMQswCQYDVQQLDAJDQTEWMBQGA1UEAwwNbW9zcXVp\r\n" +"dHRvLm9yZzEfMB0GCSqGSIb3DQEJARYQcm9nZXJAYXRjaG9vLm9yZzCCASIwDQYJ\r\n" +"KoZIhvcNAQEBBQADggEPADCCAQoCggEBAME0HKmIzfTOwkKLT3THHe+ObdizamPg\r\n" +"UZmD64Tf3zJdNeYGYn4CEXbyP6fy3tWc8S2boW6dzrH8SdFf9uo320GJA9B7U1FW\r\n" +"Te3xda/Lm3JFfaHjkWw7jBwcauQZjpGINHapHRlpiCZsquAthOgxW9SgDgYlGzEA\r\n" +"s06pkEFiMw+qDfLo/sxFKB6vQlFekMeCymjLCbNwPJyqyhFmPWwio/PDMruBTzPH\r\n" +"3cioBnrJWKXc3OjXdLGFJOfj7pP0j/dr2LH72eSvv3PQQFl90CZPFhrCUcRHSSxo\r\n" +"E6yjGOdnz7f6PveLIB574kQORwt8ePn0yidrTC1ictikED3nHYhMUOUCAwEAAaNT\r\n" +"MFEwHQYDVR0OBBYEFPVV6xBUFPiGKDyo5V3+Hbh4N9YSMB8GA1UdIwQYMBaAFPVV\r\n" +"6xBUFPiGKDyo5V3+Hbh4N9YSMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\r\n" +"BQADggEBAGa9kS21N70ThM6/Hj9D7mbVxKLBjVWe2TPsGfbl3rEDfZ+OKRZ2j6AC\r\n" +"6r7jb4TZO3dzF2p6dgbrlU71Y/4K0TdzIjRj3cQ3KSm41JvUQ0hZ/c04iGDg/xWf\r\n" +"+pp58nfPAYwuerruPNWmlStWAXf0UTqRtg4hQDWBuUFDJTuWuuBvEXudz74eh/wK\r\n" +"sMwfu1HFvjy5Z0iMDU8PUDepjVolOCue9ashlS4EB5IECdSR2TItnAIiIwimx839\r\n" +"LdUdRudafMu5T5Xma182OC0/u/xRlEm+tvKGGmfFcN0piqVl8OrSPBgIlb+1IKJE\r\n" +"m/XriWr/Cq4h/JfB7NTsezVslgkBaoU=\r\n" +"-----END CERTIFICATE-----\r\n"; + +#endif /* __CERT_H__ */ diff --git a/samples/net/sockets/big_http_download/prj.conf b/samples/net/sockets/big_http_download/prj.conf index 988a81908bd95..a406f314dfb29 100644 --- a/samples/net/sockets/big_http_download/prj.conf +++ b/samples/net/sockets/big_http_download/prj.conf @@ -2,6 +2,7 @@ CONFIG_REQUIRES_FULL_LIBC=y CONFIG_MBEDTLS=y CONFIG_MBEDTLS_ENABLE_HEAP=y +CONFIG_MBEDTLS_MD=y CONFIG_MAIN_STACK_SIZE=2536 # Networking config diff --git a/samples/net/sockets/big_http_download/sample.yaml b/samples/net/sockets/big_http_download/sample.yaml index b8777a4e8711d..d27f131836da1 100644 --- a/samples/net/sockets/big_http_download/sample.yaml +++ b/samples/net/sockets/big_http_download/sample.yaml @@ -4,11 +4,15 @@ sample: common: filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC harness: net + depends_on: netif min_ram: 32 min_flash: 128 tags: - net - socket + platform_exclude: + - native_posix + - native_posix/native/64 tests: sample.net.sockets.big_http_download: extra_configs: diff --git a/samples/net/sockets/coap_server/CMakeLists.txt b/samples/net/sockets/coap_server/CMakeLists.txt index 17d207098254b..932e3cfdeebea 100644 --- a/samples/net/sockets/coap_server/CMakeLists.txt +++ b/samples/net/sockets/coap_server/CMakeLists.txt @@ -8,4 +8,11 @@ FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) target_include_directories(app PRIVATE ${ZEPHYR_BASE}/subsys/net/ip) +# Support LD linker template zephyr_linker_sources(DATA_SECTIONS sections-ram.ld) + +# Support CMake linker generator +zephyr_iterable_section( + NAME coap_resource_coap_server + GROUP DATA_REGION ${XIP_ALIGN_WITH_INPUT} + SUBALIGN CONFIG_LINKER_ITERABLE_SUBALIGN) diff --git a/samples/net/sockets/dumb_http_server_mt/prj.conf b/samples/net/sockets/dumb_http_server_mt/prj.conf index af851a0406e3e..7b802e6e8b482 100644 --- a/samples/net/sockets/dumb_http_server_mt/prj.conf +++ b/samples/net/sockets/dumb_http_server_mt/prj.conf @@ -2,7 +2,7 @@ CONFIG_TEST_RANDOM_GENERATOR=y # POSIX options -CONFIG_POSIX_MAX_FDS=20 +CONFIG_ZVFS_OPEN_MAX=20 CONFIG_POSIX_API=y # Networking config diff --git a/samples/net/sockets/dumb_http_server_mt/sample.yaml b/samples/net/sockets/dumb_http_server_mt/sample.yaml index dc0c81822468e..4d278431c2241 100644 --- a/samples/net/sockets/dumb_http_server_mt/sample.yaml +++ b/samples/net/sockets/dumb_http_server_mt/sample.yaml @@ -3,6 +3,7 @@ sample: name: socket_dumb_http_server_mt common: harness: net + depends_on: netif min_ram: 128 min_flash: 128 tags: diff --git a/samples/net/sockets/echo_client/overlay-tls.conf b/samples/net/sockets/echo_client/overlay-tls.conf index 8235291cefc19..b6183e9f14daa 100644 --- a/samples/net/sockets/echo_client/overlay-tls.conf +++ b/samples/net/sockets/echo_client/overlay-tls.conf @@ -12,4 +12,4 @@ CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048 CONFIG_NET_SOCKETS_SOCKOPT_TLS=y CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4 CONFIG_NET_SOCKETS_ENABLE_DTLS=y -CONFIG_POSIX_MAX_FDS=8 +CONFIG_ZVFS_OPEN_MAX=8 diff --git a/samples/net/sockets/echo_client/src/echo-client.c b/samples/net/sockets/echo_client/src/echo-client.c index 9343b3b408e13..59bc9be99f91e 100644 --- a/samples/net/sockets/echo_client/src/echo-client.c +++ b/samples/net/sockets/echo_client/src/echo-client.c @@ -28,7 +28,7 @@ LOG_MODULE_REGISTER(net_echo_client_sample, LOG_LEVEL_DBG); #include #include - +#include #include #include #include diff --git a/samples/net/sockets/echo_server/overlay-tls.conf b/samples/net/sockets/echo_server/overlay-tls.conf index f9d650ecd0293..fa91a0f6258b5 100644 --- a/samples/net/sockets/echo_server/overlay-tls.conf +++ b/samples/net/sockets/echo_server/overlay-tls.conf @@ -13,4 +13,4 @@ CONFIG_NET_SOCKETS_SOCKOPT_TLS=y CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=6 CONFIG_NET_SOCKETS_ENABLE_DTLS=y CONFIG_NET_SOCKETS_DTLS_TIMEOUT=30000 -CONFIG_POSIX_MAX_FDS=16 +CONFIG_ZVFS_OPEN_MAX=16 diff --git a/samples/net/sockets/echo_server/prj.conf b/samples/net/sockets/echo_server/prj.conf index e88c98eda3956..c95e09b71b85f 100644 --- a/samples/net/sockets/echo_server/prj.conf +++ b/samples/net/sockets/echo_server/prj.conf @@ -6,7 +6,7 @@ CONFIG_NET_IPV6=y CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y CONFIG_POSIX_API=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_CONNECTION_MANAGER=y # Kernel options @@ -48,7 +48,7 @@ CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" # Number of socket descriptors might need adjusting # if there are more than 1 handlers defined. -CONFIG_POSIX_MAX_FDS=12 +CONFIG_ZVFS_OPEN_MAX=12 # How many client can connect to echo-server simultaneously CONFIG_NET_SAMPLE_NUM_HANDLERS=1 diff --git a/samples/net/sockets/echo_server/src/tcp.c b/samples/net/sockets/echo_server/src/tcp.c index 3df5ceaec9a76..c9d5cc68ebd29 100644 --- a/samples/net/sockets/echo_server/src/tcp.c +++ b/samples/net/sockets/echo_server/src/tcp.c @@ -101,12 +101,20 @@ static int start_tcp_proto(struct data *data, } #endif - /* Prefer IPv6 temporary addresses */ if (bind_addr->sa_family == AF_INET6) { + /* Prefer IPv6 temporary addresses */ optval = IPV6_PREFER_SRC_PUBLIC; (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, &optval, sizeof(optval)); + + /* + * Bind only to IPv6 without mapping to IPv4, since we bind to + * IPv4 using another socket + */ + optval = 1; + (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, IPV6_V6ONLY, + &optval, sizeof(optval)); } ret = bind(data->tcp.sock, bind_addr, bind_addrlen); diff --git a/samples/net/sockets/echo_server/src/udp.c b/samples/net/sockets/echo_server/src/udp.c index 6707410381fa5..3afe29301514d 100644 --- a/samples/net/sockets/echo_server/src/udp.c +++ b/samples/net/sockets/echo_server/src/udp.c @@ -78,12 +78,20 @@ static int start_udp_proto(struct data *data, struct sockaddr *bind_addr, } #endif - /* Prefer IPv6 temporary addresses */ if (bind_addr->sa_family == AF_INET6) { + /* Prefer IPv6 temporary addresses */ optval = IPV6_PREFER_SRC_PUBLIC; (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, IPV6_ADDR_PREFERENCES, &optval, sizeof(optval)); + + /* + * Bind only to IPv6 without mapping to IPv4, since we bind to + * IPv4 using another socket + */ + optval = 1; + (void)setsockopt(data->tcp.sock, IPPROTO_IPV6, IPV6_V6ONLY, + &optval, sizeof(optval)); } ret = bind(data->udp.sock, bind_addr, bind_addrlen); diff --git a/samples/net/sockets/echo_service/prj.conf b/samples/net/sockets/echo_service/prj.conf index d7ffe73835280..b9c053c27a2b6 100644 --- a/samples/net/sockets/echo_service/prj.conf +++ b/samples/net/sockets/echo_service/prj.conf @@ -10,7 +10,7 @@ CONFIG_NET_IPV6=y CONFIG_NET_TCP=y CONFIG_NET_SOCKETS=y CONFIG_NET_IPV4_MAPPING_TO_IPV6=y -CONFIG_POSIX_MAX_FDS=10 +CONFIG_ZVFS_OPEN_MAX=10 CONFIG_NET_MAX_CONN=5 CONFIG_NET_SOCKETS_SERVICE=y CONFIG_NET_SOCKETS_POLL_MAX=20 diff --git a/samples/net/sockets/http_client/README.rst b/samples/net/sockets/http_client/README.rst index 855c36d068a29..d360ae45edfae 100644 --- a/samples/net/sockets/http_client/README.rst +++ b/samples/net/sockets/http_client/README.rst @@ -1,5 +1,5 @@ .. zephyr:code-sample:: sockets-http-client - :name: HTTP client + :name: HTTP Client :relevant-api: bsd_sockets http_client tls_credentials secure_sockets_options Implement an HTTP(S) client that issues a variety of HTTP requests. diff --git a/samples/net/sockets/http_get/overlay-tls.conf b/samples/net/sockets/http_get/overlay-tls.conf index 29bfc2372f853..0cf82f18cf857 100644 --- a/samples/net/sockets/http_get/overlay-tls.conf +++ b/samples/net/sockets/http_get/overlay-tls.conf @@ -6,6 +6,7 @@ CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=60000 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=7168 -CONFIG_MBEDTLS_MAC_ALL_ENABLED=y +CONFIG_MBEDTLS_HASH_ALL_ENABLED=y +CONFIG_MBEDTLS_CMAC=y CONFIG_NET_SOCKETS_SOCKOPT_TLS=y diff --git a/samples/net/sockets/http_get/sample.yaml b/samples/net/sockets/http_get/sample.yaml index 4e454da50a7d7..2aba5c7d60d8c 100644 --- a/samples/net/sockets/http_get/sample.yaml +++ b/samples/net/sockets/http_get/sample.yaml @@ -3,11 +3,15 @@ sample: name: socket_http_get common: filter: CONFIG_FULL_LIBC_SUPPORTED + depends_on: netif min_ram: 32 min_flash: 80 tags: - net - socket + platform_exclude: + - native_posix + - native_posix/native/64 tests: sample.net.sockets.http_get: filter: not CONFIG_NET_SOCKETS_OFFLOAD and not CONFIG_NATIVE_LIBC @@ -15,6 +19,8 @@ tests: platform_exclude: - cc3220sf_launchxl - cc3235sf_launchxl + - native_posix + - native_posix/native/64 extra_configs: - CONFIG_POSIX_API=y sample.net.sockets.http_get.offload.simplelink: @@ -25,7 +31,7 @@ tests: - socket - offload - simplelink - sample.get.sockets.http_get.nsos.http: + sample.net.sockets.http_get.nsos.http: harness: console harness_config: type: multi_line @@ -38,7 +44,7 @@ tests: - native_sim - native_sim/native/64 extra_args: OVERLAY_CONFIG="overlay-nsos.conf" - sample.get.sockets.http_get.nsos.https: + sample.net.sockets.http_get.nsos.https: harness: console harness_config: type: multi_line diff --git a/samples/net/sockets/http_server/CMakeLists.txt b/samples/net/sockets/http_server/CMakeLists.txt index 5b27e5ee7ca96..2a8d03ac9b28e 100644 --- a/samples/net/sockets/http_server/CMakeLists.txt +++ b/samples/net/sockets/http_server/CMakeLists.txt @@ -32,6 +32,8 @@ generate_inc_file_for_target(app ${source_file_index} ${gen_dir}/index.html.gz.i set(source_file_not_found src/not_found_page.html) generate_inc_file_for_target(app ${source_file_not_found} ${gen_dir}/not_found_page.html.gz.inc --gzip) +target_sources_ifdef(CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE app PRIVATE src/ws.c) + target_link_libraries(app PRIVATE zephyr_interface zephyr) zephyr_linker_sources(SECTIONS sections-rom.ld) diff --git a/samples/net/sockets/http_server/Kconfig b/samples/net/sockets/http_server/Kconfig index 90104be01fa19..ca55f9692e34b 100644 --- a/samples/net/sockets/http_server/Kconfig +++ b/samples/net/sockets/http_server/Kconfig @@ -38,4 +38,16 @@ config NET_SAMPLE_CERTS_WITH_SC Enable this flag, if you are interested to run this application with signed certificates and keys. +config NET_SAMPLE_WEBSOCKET_SERVICE + bool "Enable websocket service" + default y if HTTP_SERVER_WEBSOCKET + +config NET_SAMPLE_NUM_WEBSOCKET_HANDLERS + int "How many websocket connections to serve at the same time" + depends on NET_SAMPLE_WEBSOCKET_SERVICE + default 1 + help + Each websocket connection is served by a thread which needs + memory. Only increase the value here if really needed. + source "Kconfig.zephyr" diff --git a/samples/net/sockets/http_server/README.rst b/samples/net/sockets/http_server/README.rst index cc4cd1c548219..4d802ae1a35c4 100644 --- a/samples/net/sockets/http_server/README.rst +++ b/samples/net/sockets/http_server/README.rst @@ -1,10 +1,13 @@ -Zephyr HTTP Server -================== +.. zephyr:code-sample:: sockets-http-server + :name: HTTP Server + :relevant-api: http_service http_server tls_credentials + + Implement an HTTP(s) Server demonstrating various resource types. Overview -------- -This sample application demonstrates the use of the ``http_server`` library. +This sample application demonstrates the use of the :ref:`http_server_interface` library. This library provides high-level functions to simplify and abstract server implementation. The server supports the HTTP/1.1 protocol which can also be upgraded to HTTP/2, it also support native HTTP/2 protocol without upgrading. @@ -59,10 +62,38 @@ the requirements. These are the configurable parameters: - ``CONFIG_HTTP_SERVER_MAX_URL_LENGTH``: Specifies the maximum length of an HTTP URL that the server can process. +- ``CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE``: Enables Websocket service endpoint. + This allows a Websocket client to connect to ``/`` endpoint, all the data that + the client sends is echoed back. + To customize these options, we can run ``west build -t menuconfig``, which provides us with an interactive configuration interface. Then we could navigate from the top-level menu to: ``-> Subsystems and OS Services -> Networking -> Network Protocols``. +Websocket Connectivity +---------------------- + +You can use a simple Websocket client application like this to test the Websocket +connectivity. + +.. code-block:: python + + import websocket + + websocket.enableTrace(True) + ws = websocket.WebSocket() + ws.connect("ws://192.0.2.1/") + ws.send("Hello, Server") + print(ws.recv()) + while True: + line = input("> ") + if line == "quit": + break + ws.send(line) + print(ws.recv()) + ws.close() + + Performance Analysis -------------------- diff --git a/samples/net/sockets/http_server/prj.conf b/samples/net/sockets/http_server/prj.conf index 9e56f3332e7f2..c9c80be2429dd 100644 --- a/samples/net/sockets/http_server/prj.conf +++ b/samples/net/sockets/http_server/prj.conf @@ -5,7 +5,7 @@ CONFIG_LOG=y CONFIG_ENTROPY_GENERATOR=y CONFIG_TEST_RANDOM_GENERATOR=y CONFIG_INIT_STACKS=y -CONFIG_POSIX_MAX_FDS=32 +CONFIG_ZVFS_OPEN_MAX=32 CONFIG_POSIX_API=y CONFIG_FDTABLE=y CONFIG_NET_SOCKETS_POLL_MAX=32 @@ -30,6 +30,7 @@ CONFIG_JSON_LIBRARY=y CONFIG_HTTP_PARSER_URL=y CONFIG_HTTP_PARSER=y CONFIG_HTTP_SERVER=y +CONFIG_HTTP_SERVER_WEBSOCKET=y # Network buffers CONFIG_NET_PKT_RX_COUNT=16 @@ -60,6 +61,7 @@ CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=60000 CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048 +CONFIG_MBEDTLS_USE_PSA_CRYPTO=n CONFIG_NET_SOCKETS_SOCKOPT_TLS=y CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=6 CONFIG_TLS_CREDENTIALS=y diff --git a/samples/net/sockets/http_server/sample.yaml b/samples/net/sockets/http_server/sample.yaml index eeaca47d386ed..8af05127cd4b4 100644 --- a/samples/net/sockets/http_server/sample.yaml +++ b/samples/net/sockets/http_server/sample.yaml @@ -3,6 +3,7 @@ sample: name: http_server_sample common: harness: net + depends_on: netif min_ram: 192 tags: - http diff --git a/samples/net/sockets/http_server/src/main.c b/samples/net/sockets/http_server/src/main.c index dac4499029d4d..ff72f2ed5bbde 100644 --- a/samples/net/sockets/http_server/src/main.c +++ b/samples/net/sockets/http_server/src/main.c @@ -1,5 +1,6 @@ /* * Copyright (c) 2023, Emna Rekik + * Copyright (c) 2024, Nordic Semiconductor * * SPDX-License-Identifier: Apache-2.0 */ @@ -30,6 +31,7 @@ struct http_resource_detail_static index_html_gz_resource_detail = { .type = HTTP_RESOURCE_TYPE_STATIC, .bitmask_of_supported_http_methods = BIT(HTTP_GET), .content_encoding = "gzip", + .content_type = "text/html", }, .static_data = index_html_gz, .static_data_len = sizeof(index_html_gz), @@ -88,6 +90,27 @@ struct http_resource_detail_dynamic dyn_resource_detail = { HTTP_RESOURCE_DEFINE(dyn_resource, test_http_service, "/dynamic", &dyn_resource_detail); +#if defined(CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE) +extern int ws_setup(int ws_socket, void *user_data); + +static uint8_t ws_recv_buffer[1024]; + +struct http_resource_detail_websocket ws_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_WEBSOCKET, + + /* We need HTTP/1.1 Get method for upgrading */ + .bitmask_of_supported_http_methods = BIT(HTTP_GET), + }, + .cb = ws_setup, + .data_buffer = ws_recv_buffer, + .data_buffer_len = sizeof(ws_recv_buffer), + .user_data = NULL, /* Fill this for any user specific data */ +}; + +HTTP_RESOURCE_DEFINE(ws_resource, test_http_service, "/", &ws_resource_detail); + +#endif /* CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE */ #endif /* CONFIG_NET_SAMPLE_HTTP_SERVICE */ #if defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE) diff --git a/samples/net/sockets/http_server/src/ws.c b/samples/net/sockets/http_server/src/ws.c new file mode 100644 index 0000000000000..d62283b5bbc56 --- /dev/null +++ b/samples/net/sockets/http_server/src/ws.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2024, Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_DECLARE(net_http_server_sample, LOG_LEVEL_DBG); + +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) || defined(CONFIG_COVERAGE_GCOV) +#define STACK_SIZE 4096 +#else +#define STACK_SIZE 2048 +#endif + +#if defined(CONFIG_NET_TC_THREAD_COOPERATIVE) +#define THREAD_PRIORITY K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1) +#else +#define THREAD_PRIORITY K_PRIO_PREEMPT(8) +#endif + +#if defined(CONFIG_USERSPACE) +#include +extern struct k_mem_partition app_partition; +extern struct k_mem_domain app_domain; +#define APP_BMEM K_APP_BMEM(app_partition) +#define APP_DMEM K_APP_DMEM(app_partition) +#else +#define APP_BMEM +#define APP_DMEM +#endif + +#define MAX_CLIENT_QUEUE CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS +#define RECV_BUFFER_SIZE 1280 + +K_THREAD_STACK_ARRAY_DEFINE(ws_handler_stack, + CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS, + STACK_SIZE); +static struct k_thread ws_handler_thread[CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS]; +static APP_BMEM bool ws_handler_in_use[CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS]; + +static struct data { + int sock; + uint32_t counter; + uint32_t bytes_received; + struct pollfd fds[1]; + char recv_buffer[RECV_BUFFER_SIZE]; +} config[CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS] = { + [0 ... (CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS - 1)] = { + .sock = -1, + .fds[0].fd = -1, + } +}; + +static int get_free_slot(struct data *cfg) +{ + for (int i = 0; i < CONFIG_NET_SAMPLE_NUM_WEBSOCKET_HANDLERS; i++) { + if (cfg[i].sock < 0) { + return i; + } + } + + return -1; +} + +static ssize_t sendall(int sock, const void *buf, size_t len) +{ + while (len) { + ssize_t out_len = send(sock, buf, len, 0); + + if (out_len < 0) { + return out_len; + } + buf = (const char *)buf + out_len; + len -= out_len; + } + + return 0; +} + +static void ws_handler(void *ptr1, void *ptr2, void *ptr3) +{ + int slot = POINTER_TO_INT(ptr1); + struct data *cfg = ptr2; + bool *in_use = ptr3; + int offset = 0; + int received; + int client; + int ret; + + client = cfg->sock; + + cfg->fds[0].fd = client; + cfg->fds[0].events = POLLIN; + + /* In this example, we start to receive data from the websocket + * and send it back to the client. Note that we could either use + * the BSD socket interface if we do not care about Websocket + * specific packets, or we could use the websocket_{send/recv}_msg() + * function to send websocket specific data. + */ + while (true) { + if (poll(cfg->fds, 1, -1) < 0) { + LOG_ERR("Error in poll:%d", errno); + continue; + } + + if (cfg->fds[0].fd < 0) { + continue; + } + + if (cfg->fds[0].revents & ZSOCK_POLLHUP) { + LOG_DBG("Client #%d has disconnected", client); + break; + } + + received = recv(client, + cfg->recv_buffer + offset, + sizeof(cfg->recv_buffer) - offset, + 0); + + if (received == 0) { + /* Connection closed */ + LOG_INF("[%d] Connection closed", slot); + break; + } else if (received < 0) { + /* Socket error */ + LOG_ERR("[%d] Connection error %d", slot, errno); + break; + } + + cfg->bytes_received += received; + offset += received; + +#if !defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + /* To prevent fragmentation of the response, reply only if + * buffer is full or there is no more data to read + */ + if (offset == sizeof(cfg->recv_buffer) || + (recv(client, cfg->recv_buffer + offset, + sizeof(cfg->recv_buffer) - offset, + MSG_PEEK | MSG_DONTWAIT) < 0 && + (errno == EAGAIN || errno == EWOULDBLOCK))) { +#endif + ret = sendall(client, cfg->recv_buffer, offset); + if (ret < 0) { + LOG_ERR("[%d] Failed to send data, closing socket", + slot); + break; + } + + LOG_DBG("[%d] Received and replied with %d bytes", + slot, offset); + + if (++cfg->counter % 1000 == 0U) { + LOG_INF("[%d] Sent %u packets", slot, cfg->counter); + } + + offset = 0; +#if !defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + } +#endif + } + + *in_use = false; + + (void)websocket_unregister(client); + + cfg->sock = -1; +} + +int ws_setup(int ws_socket, void *user_data) +{ + int slot; + + slot = get_free_slot(config); + if (slot < 0) { + LOG_ERR("Cannot accept more connections"); + /* The caller will close the connection in this case */ + return -ENOENT; + } + + config[slot].sock = ws_socket; + + LOG_INF("[%d] Accepted a Websocket connection", slot); + + k_thread_create(&ws_handler_thread[slot], + ws_handler_stack[slot], + K_THREAD_STACK_SIZEOF(ws_handler_stack[slot]), + ws_handler, + INT_TO_POINTER(slot), &config[slot], &ws_handler_in_use[slot], + THREAD_PRIORITY, + IS_ENABLED(CONFIG_USERSPACE) ? K_USER | + K_INHERIT_PERMS : 0, + K_NO_WAIT); + + if (IS_ENABLED(CONFIG_THREAD_NAME)) { +#define MAX_NAME_LEN sizeof("ws[xx]") + char name[MAX_NAME_LEN]; + + snprintk(name, sizeof(name), "ws[%d]", slot); + k_thread_name_set(&ws_handler_thread[slot], name); + } + + return 0; +} diff --git a/samples/net/sockets/net_mgmt/prj.conf b/samples/net/sockets/net_mgmt/prj.conf index 243cce2173552..a94f5da00948d 100644 --- a/samples/net/sockets/net_mgmt/prj.conf +++ b/samples/net/sockets/net_mgmt/prj.conf @@ -6,7 +6,7 @@ CONFIG_NET_IPV6=y CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y CONFIG_POSIX_API=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_SOCKETS_NET_MGMT=y CONFIG_NET_MGMT_EVENT=y diff --git a/samples/net/sockets/packet/prj.conf b/samples/net/sockets/packet/prj.conf index d01c89254e155..555e824bf5880 100644 --- a/samples/net/sockets/packet/prj.conf +++ b/samples/net/sockets/packet/prj.conf @@ -7,7 +7,7 @@ CONFIG_NET_IPV4=n CONFIG_NET_MAX_CONTEXTS=10 CONFIG_NET_SOCKETS=y CONFIG_POSIX_API=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_NET_CONTEXT_RCVTIMEO=y CONFIG_NET_MGMT=y CONFIG_NET_MGMT_EVENT=y diff --git a/samples/net/sockets/packet/src/packet.c b/samples/net/sockets/packet/src/packet.c index 428a22a907d48..ec6e428c325b4 100644 --- a/samples/net/sockets/packet/src/packet.c +++ b/samples/net/sockets/packet/src/packet.c @@ -86,7 +86,7 @@ static int start_socket(int *sock) *sock = socket(AF_PACKET, IS_ENABLED(CONFIG_NET_SAMPLE_ENABLE_PACKET_DGRAM) ? SOCK_DGRAM : SOCK_RAW, - ETH_P_ALL); + htons(ETH_P_ALL)); if (*sock < 0) { LOG_ERR("Failed to create %s socket : %d", IS_ENABLED(CONFIG_NET_SAMPLE_ENABLE_PACKET_DGRAM) ? diff --git a/samples/net/sockets/txtime/src/main.c b/samples/net/sockets/txtime/src/main.c index 481312d1afe03..2bd41df40ac4e 100644 --- a/samples/net/sockets/txtime/src/main.c +++ b/samples/net/sockets/txtime/src/main.c @@ -273,7 +273,7 @@ static int create_socket(struct net_if *iface, struct sockaddr *peer) if (IS_ENABLED(CONFIG_NET_SAMPLE_PACKET_SOCKET)) { struct sockaddr_ll *addr; - sock = socket(AF_PACKET, SOCK_RAW, ETH_P_ALL); + sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)); if (sock < 0) { LOG_ERR("Cannot create %s socket (%d)", "packet", -errno); diff --git a/samples/net/tftp_client/boards/native_posix.conf b/samples/net/tftp_client/boards/native_posix.conf deleted file mode 100644 index 1e9e27b074ea1..0000000000000 --- a/samples/net/tftp_client/boards/native_posix.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_DNS_RESOLVER=y -CONFIG_DNS_SERVER_IP_ADDRESSES=y -CONFIG_DNS_SERVER1="192.0.2.2" diff --git a/samples/net/tftp_client/boards/qemu_cortex_m3.conf b/samples/net/tftp_client/boards/qemu_cortex_m3.conf index dc256b47832a2..944da5cca684c 100644 --- a/samples/net/tftp_client/boards/qemu_cortex_m3.conf +++ b/samples/net/tftp_client/boards/qemu_cortex_m3.conf @@ -2,3 +2,4 @@ CONFIG_NET_L2_ETHERNET=y CONFIG_ETH_DRIVER=y CONFIG_ETH_STELLARIS=y CONFIG_NET_QEMU_ETHERNET=y +CONFIG_TEST_RANDOM_GENERATOR=y diff --git a/samples/net/tftp_client/sample.yaml b/samples/net/tftp_client/sample.yaml index 6e53b0f188172..fd4b2f2d0c0e9 100644 --- a/samples/net/tftp_client/sample.yaml +++ b/samples/net/tftp_client/sample.yaml @@ -7,6 +7,7 @@ tests: depends_on: netif platform_allow: - native_sim + - qemu_cortex_m3 integration_platforms: - native_sim tags: diff --git a/samples/net/zperf/prj.conf b/samples/net/zperf/prj.conf index e355986210bbd..0bf23e7a7e502 100644 --- a/samples/net/zperf/prj.conf +++ b/samples/net/zperf/prj.conf @@ -20,7 +20,7 @@ CONFIG_NET_MAX_CONTEXTS=5 CONFIG_NET_TC_TX_COUNT=1 CONFIG_NET_SOCKETS=y CONFIG_NET_SOCKETS_POLL_MAX=9 -CONFIG_POSIX_MAX_FDS=8 +CONFIG_ZVFS_OPEN_MAX=8 CONFIG_POSIX_API=y CONFIG_INIT_STACKS=y diff --git a/samples/net/zperf/sample.yaml b/samples/net/zperf/sample.yaml index 12c0cfd1bf2e3..35260fd723aa6 100644 --- a/samples/net/zperf/sample.yaml +++ b/samples/net/zperf/sample.yaml @@ -98,3 +98,10 @@ tests: depends_on: - arduino_spi - arduino_gpio + sample.net.zperf.nxp_enet1g: + extra_args: EXTRA_DTC_OVERLAY_FILE="nxp,enet1g.overlay" + tags: + - net + - zperf + platform_allow: + - mimxrt1170_evk/mimxrt1176/cm7 diff --git a/samples/philosophers/README.rst b/samples/philosophers/README.rst index 77c07cba67001..2392af05165ff 100644 --- a/samples/philosophers/README.rst +++ b/samples/philosophers/README.rst @@ -6,42 +6,42 @@ Dining Philosophers Overview ******** -An implementation of a solution to the Dining Philosophers problem (a classic -multi-thread synchronization problem). This particular implementation -demonstrates the usage of multiple preemptible and cooperative threads of -differing priorities, as well as dynamic mutexes and thread sleeping. +An implementation of a solution to the Dining Philosophers problem (a classic multi-thread +synchronization problem). This particular implementation demonstrates the usage of multiple +preemptible and cooperative threads of differing priorities, as well as dynamic mutexes and thread +sleeping. -The philosopher always tries to get the lowest fork first (f1 then f2). When -done, he will give back the forks in the reverse order (f2 then f1). If he -gets two forks, he is EATING. Otherwise, he is THINKING. Transitional states -are shown as well, such as STARVING when the philosopher is hungry but the -forks are not available, and HOLDING ONE FORK when a philosopher is waiting -for the second fork to be available. +The philosopher always tries to get the lowest fork first (f1 then f2). When done, he will give +back the forks in the reverse order (f2 then f1). If he gets two forks, he is ``EATING``. +Otherwise, he is ``THINKING``. Transitional states are shown as well, such as ``STARVING`` when the +philosopher is hungry but the forks are not available, and ``HOLDING ONE FORK`` when a philosopher +is waiting for the second fork to be available. -Each Philosopher will randomly alternate between the EATING and THINKING state. +Each Philosopher will randomly alternate between the ``EATING`` and ``THINKING`` states. -It is possible to run the demo in coop-only or preempt-only mode. To achieve -this, set these values for CONFIG_NUM_COOP_PRIORITIES and -CONFIG_NUM_PREEMPT_PRIORITIES in prj.conf: +It is possible to run the demo in `coop-only` or `preempt-only` mode. To achieve this, set these +values for ``CONFIG_NUM_COOP_PRIORITIES`` and ``CONFIG_NUM_PREEMPT_PRIORITIES`` in :file:`prj.conf`: -preempt-only: +preempt-only + .. code-block:: cfg - CONFIG_NUM_PREEMPT_PRIORITIES 6 - CONFIG_NUM_COOP_PRIORITIES 0 + CONFIG_NUM_PREEMPT_PRIORITIES=6 + CONFIG_NUM_COOP_PRIORITIES=0 -coop-only: - CONFIG_NUM_PREEMPT_PRIORITIES 0 - CONFIG_NUM_COOP_PRIORITIES 6 +coop-only + .. code-block:: cfg -In these cases, the philosopher threads will run with priorities 0 to 5 -(preempt-only) and -7 to -2 (coop-only). + CONFIG_NUM_PREEMPT_PRIORITIES=0 + CONFIG_NUM_COOP_PRIORITIES=6 + +In these cases, the philosopher threads will run with priorities 0 to 5 (preempt-only) and -7 to -2 +(coop-only). Building and Running ******************** -This project outputs to the console. It can be built and executed -on QEMU as follows: +This project outputs to the console. It can be built and executed on QEMU as follows: .. zephyr-app-commands:: :zephyr-app: samples/philosophers @@ -53,7 +53,7 @@ on QEMU as follows: Sample Output ============= -.. code-block:: console +.. code-block:: Philosopher 0 [P: 3] HOLDING ONE FORK Philosopher 1 [P: 2] HOLDING ONE FORK @@ -67,9 +67,8 @@ Exit QEMU by pressing :kbd:`CTRL+A` :kbd:`x`. Debug Threads ************* -The philosophers sample by default enables :kconfig:option:`CONFIG_DEBUG_THREAD_INFO`. -This allows tools like OpenOCD and J-link to inspect thread data using -``info threads``. +The philosophers sample by default enables :kconfig:option:`CONFIG_DEBUG_THREAD_INFO`. This allows +tools like OpenOCD and J-link to inspect thread data using ``info threads``. .. zephyr-app-commands:: :zephyr-app: samples/philosophers @@ -82,7 +81,7 @@ This allows tools like OpenOCD and J-link to inspect thread data using OpenOCD Sample Output ===================== -.. code-block:: console +.. code-block:: Thread 1 received signal SIGINT, Interrupt. [Switching to Thread 537003160] @@ -104,7 +103,7 @@ OpenOCD Sample Output Info : Getting thread 537002104 reg list 7 Thread 537002104 (Name: Philosopher 0, prio:3,useropts:4) 0x08001404 in arch_irq_unlock (key=0) at zephyr/mainline/zephyr/include/arch/arm/asm_inline_gcc.h:95 -.. code-block:: console +.. code-block:: Philosopher 0 [P: 3] STARVING Philosopher 1 [P: 2] HOLDING ONE FORK @@ -117,7 +116,7 @@ OpenOCD Sample Output J-Link Sample Output ==================== -.. code-block:: console +.. code-block:: Thread 2 received signal SIGTRAP, Trace/breakpoint trap. [Switching to Thread 537920592] @@ -133,7 +132,7 @@ J-Link Sample Output 7 Thread 537920240 (Philosopher 4 PENDING PRIO 255) arch_swap (key=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53 8 Thread 537920416 (Philosopher 5 SUSPENDED PRIO 254) arch_swap (key=key@entry=0) at zephyr/mainline/zephyr/arch/arm/core/swap.c:53 -.. code-block:: console +.. code-block:: Philosopher 0 [P: 3] STARVING Philosopher 1 [P: 2] EATING [ 475 ms ] diff --git a/samples/posix/env/sample.yaml b/samples/posix/env/sample.yaml index c276b6b55f1d3..39ad4f088091d 100644 --- a/samples/posix/env/sample.yaml +++ b/samples/posix/env/sample.yaml @@ -7,7 +7,7 @@ common: - native_posix - native_posix/native/64 integration_platforms: - - qemu_riscv32 + - native_sim harness: console harness_config: type: multi_line diff --git a/samples/posix/env/src/main.c b/samples/posix/env/src/main.c index 9385abce64412..9ae50c36cd1af 100644 --- a/samples/posix/env/src/main.c +++ b/samples/posix/env/src/main.c @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "version.h" - #include #include #include @@ -15,6 +13,7 @@ #include #include +#include #ifdef BUILD_VERSION #define VERSION_BUILD STRINGIFY(BUILD_VERSION) diff --git a/samples/posix/gettimeofday/sample.yaml b/samples/posix/gettimeofday/sample.yaml index a71d29f09c50a..88748aab2a63f 100644 --- a/samples/posix/gettimeofday/sample.yaml +++ b/samples/posix/gettimeofday/sample.yaml @@ -10,6 +10,9 @@ common: tags: - posix - net + platform_exclude: + - native_posix + - native_posix/native/64 tests: sample.posix.gettimeofday: harness: net diff --git a/samples/posix/philosophers/prj.conf b/samples/posix/philosophers/prj.conf index 0934325aea66b..2f8c3da16c300 100644 --- a/samples/posix/philosophers/prj.conf +++ b/samples/posix/philosophers/prj.conf @@ -6,7 +6,7 @@ CONFIG_THREAD_STACK_INFO=y CONFIG_DYNAMIC_THREAD=y CONFIG_DYNAMIC_THREAD_POOL_SIZE=6 -CONFIG_MAX_PTHREAD_COUNT=6 +CONFIG_POSIX_THREAD_THREADS_MAX=6 CONFIG_MAX_PTHREAD_MUTEX_COUNT=6 #Enable thread awareness for debugging tools supporting it diff --git a/samples/posix/philosophers/src/main.c b/samples/posix/philosophers/src/main.c index 29861803aab3e..bfac15861fd6d 100644 --- a/samples/posix/philosophers/src/main.c +++ b/samples/posix/philosophers/src/main.c @@ -21,12 +21,12 @@ #define MAX_NAME_LEN 1 #endif -#define NUM_PHIL CONFIG_MAX_PTHREAD_COUNT +#define NUM_PHIL CONFIG_POSIX_THREAD_THREADS_MAX #define obj_init_type "POSIX" #define fork_type_str "mutexes" -BUILD_ASSERT(CONFIG_MAX_PTHREAD_COUNT == CONFIG_MAX_PTHREAD_MUTEX_COUNT); -BUILD_ASSERT(CONFIG_DYNAMIC_THREAD_POOL_SIZE == CONFIG_MAX_PTHREAD_COUNT); +BUILD_ASSERT(CONFIG_POSIX_THREAD_THREADS_MAX == CONFIG_MAX_PTHREAD_MUTEX_COUNT); +BUILD_ASSERT(CONFIG_DYNAMIC_THREAD_POOL_SIZE == CONFIG_POSIX_THREAD_THREADS_MAX); typedef pthread_mutex_t *fork_t; diff --git a/samples/sensor/accel_polling/src/main.c b/samples/sensor/accel_polling/src/main.c index ef0ecbbb7bc3f..13e8cc3787ced 100644 --- a/samples/sensor/accel_polling/src/main.c +++ b/samples/sensor/accel_polling/src/main.c @@ -62,7 +62,11 @@ int main(void) } } +#ifndef CONFIG_COVERAGE while (1) { +#else + for (int i = 0; i < 5; i++) { +#endif for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) { ret = print_accels(sensors[i]); if (ret < 0) { diff --git a/samples/sensor/bme280/prj.conf b/samples/sensor/bme280/prj.conf index 42fcd3c973bcb..f143196e59a8e 100644 --- a/samples/sensor/bme280/prj.conf +++ b/samples/sensor/bme280/prj.conf @@ -1 +1,2 @@ CONFIG_SENSOR=y +CONFIG_SENSOR_ASYNC_API=y diff --git a/samples/sensor/bme280/src/main.c b/samples/sensor/bme280/src/main.c index 07fa9a60eb64b..433339c88055c 100644 --- a/samples/sensor/bme280/src/main.c +++ b/samples/sensor/bme280/src/main.c @@ -9,15 +9,25 @@ #include #include #include +#include +#include +#include /* * Get a device structure from a devicetree node with compatible * "bosch,bme280". (If there are multiple, just pick one.) */ -static const struct device *get_bme280_device(void) -{ - const struct device *const dev = DEVICE_DT_GET_ANY(bosch_bme280); +const struct device *const dev = DEVICE_DT_GET_ANY(bosch_bme280); + +SENSOR_DT_READ_IODEV(iodev, DT_COMPAT_GET_ANY_STATUS_OKAY(bosch_bme280), + {SENSOR_CHAN_AMBIENT_TEMP, 0}, + {SENSOR_CHAN_HUMIDITY, 0}, + {SENSOR_CHAN_PRESS, 0}); +RTIO_DEFINE(ctx, 1, 1); + +static const struct device *check_bme280_device(void) +{ if (dev == NULL) { /* No such node, or the node does not have status "okay". */ printk("\nError: no device found.\n"); @@ -37,23 +47,56 @@ static const struct device *get_bme280_device(void) int main(void) { - const struct device *dev = get_bme280_device(); + const struct device *dev = check_bme280_device(); if (dev == NULL) { return 0; } while (1) { - struct sensor_value temp, press, humidity; + uint8_t buf[128]; + + int rc = sensor_read(&iodev, &ctx, buf, 128); + + if (rc != 0) { + printk("%s: sensor_read() failed: %d\n", dev->name, rc); + return rc; + } + + const struct sensor_decoder_api *decoder; + + rc = sensor_get_decoder(dev, &decoder); + + if (rc != 0) { + printk("%s: sensor_get_decode() failed: %d\n", dev->name, rc); + return rc; + } + + uint32_t temp_fit = 0; + struct sensor_q31_data temp_data = {0}; + + decoder->decode(buf, + (struct sensor_chan_spec) {SENSOR_CHAN_AMBIENT_TEMP, 0}, + &temp_fit, 1, &temp_data); + + uint32_t press_fit = 0; + struct sensor_q31_data press_data = {0}; + + decoder->decode(buf, + (struct sensor_chan_spec) {SENSOR_CHAN_PRESS, 0}, + &press_fit, 1, &press_data); + + uint32_t hum_fit = 0; + struct sensor_q31_data hum_data = {0}; - sensor_sample_fetch(dev); - sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp); - sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press); - sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &humidity); + decoder->decode(buf, + (struct sensor_chan_spec) {SENSOR_CHAN_HUMIDITY, 0}, + &hum_fit, 1, &hum_data); - printk("temp: %d.%06d; press: %d.%06d; humidity: %d.%06d\n", - temp.val1, temp.val2, press.val1, press.val2, - humidity.val1, humidity.val2); + printk("temp: %s%d.%d; press: %s%d.%d; humidity: %s%d.%d\n", + PRIq_arg(temp_data.readings[0].temperature, 6, temp_data.shift), + PRIq_arg(press_data.readings[0].pressure, 6, press_data.shift), + PRIq_arg(hum_data.readings[0].humidity, 6, hum_data.shift)); k_sleep(K_MSEC(1000)); } diff --git a/samples/sensor/bme680/src/main.c b/samples/sensor/bme680/src/main.c index 93a1c4b82627a..1464504ce436c 100644 --- a/samples/sensor/bme680/src/main.c +++ b/samples/sensor/bme680/src/main.c @@ -21,7 +21,11 @@ int main(void) printf("Device %p name is %s\n", dev, dev->name); +#ifndef CONFIG_COVERAGE while (1) { +#else + for (int i = 0; i < 5; i++) { +#endif k_sleep(K_MSEC(3000)); sensor_sample_fetch(dev); diff --git a/samples/sensor/ccs811/boards/efr32mg_sltb004a.overlay b/samples/sensor/ccs811/boards/sltb004a.overlay similarity index 100% rename from samples/sensor/ccs811/boards/efr32mg_sltb004a.overlay rename to samples/sensor/ccs811/boards/sltb004a.overlay diff --git a/samples/sensor/ccs811/sample.yaml b/samples/sensor/ccs811/sample.yaml index 838eb82b51438..755a9648ddc61 100644 --- a/samples/sensor/ccs811/sample.yaml +++ b/samples/sensor/ccs811/sample.yaml @@ -13,7 +13,7 @@ tests: tags: sensors platform_allow: - thingy52/nrf52832 - - efr32mg_sltb004a + - sltb004a integration_platforms: - - efr32mg_sltb004a + - sltb004a depends_on: i2c diff --git a/samples/sensor/dht_polling/README.rst b/samples/sensor/dht_polling/README.rst index 09550b255d00b..b985c9e0a082e 100644 --- a/samples/sensor/dht_polling/README.rst +++ b/samples/sensor/dht_polling/README.rst @@ -23,7 +23,17 @@ be aliased as ``dhtN`` where ``N`` goes from ``0`` to ``9``. For example: }; }; -Make sure the aliases are in devicetree, then build and run with: + +Make sure the aliases are in devicetree. + +It also requires a correct fixture setup when the sensor is present. +For the correct execution of that sample in twister, add into boards's +map-file next fixture settings:: + + - fixture: fixture_i2c_hs300x + + +Then build and run with: .. zephyr-app-commands:: :zephyr-app: samples/sensor/dht_polling diff --git a/samples/sensor/dht_polling/prj.conf b/samples/sensor/dht_polling/prj.conf index 7d668be1f0b19..8afa5ea2557f3 100644 --- a/samples/sensor/dht_polling/prj.conf +++ b/samples/sensor/dht_polling/prj.conf @@ -1,2 +1,3 @@ CONFIG_STDOUT_CONSOLE=y CONFIG_SENSOR=y +CONFIG_SENSOR_ASYNC_API=y diff --git a/samples/sensor/dht_polling/sample.yaml b/samples/sensor/dht_polling/sample.yaml index 8177e636d2167..50cf2ef6d7ce6 100644 --- a/samples/sensor/dht_polling/sample.yaml +++ b/samples/sensor/dht_polling/sample.yaml @@ -15,6 +15,7 @@ tests: - nucleo_f401re harness: console harness_config: + fixture: fixture_i2c_hs300x type: one_line regex: - "[0-9A-Za-z_,+-.]*@[0-9A-Fa-f]*: temp is (.*) °C humidity is (.*) %RH" diff --git a/samples/sensor/dht_polling/src/main.c b/samples/sensor/dht_polling/src/main.c index 8ff26b5ab9b0a..9055f07cb925c 100644 --- a/samples/sensor/dht_polling/src/main.c +++ b/samples/sensor/dht_polling/src/main.c @@ -8,17 +8,35 @@ #include #include -#include #include #include +#include +#include +#include +#include #define DHT_ALIAS(i) DT_ALIAS(_CONCAT(dht, i)) -#define DHT_DEVICE(i, _) \ +#define DHT_DEVICE(i, _) \ IF_ENABLED(DT_NODE_EXISTS(DHT_ALIAS(i)), (DEVICE_DT_GET(DHT_ALIAS(i)),)) /* Support up to 10 temperature/humidity sensors */ static const struct device *const sensors[] = {LISTIFY(10, DHT_DEVICE, ())}; +#define DHT_IODEV(i, _) \ + IF_ENABLED(DT_NODE_EXISTS(DHT_ALIAS(i)), \ + (SENSOR_DT_READ_IODEV(_CONCAT(dht_iodev, i), DHT_ALIAS(i), \ + {SENSOR_CHAN_AMBIENT_TEMP, 0}, \ + {SENSOR_CHAN_HUMIDITY, 0}))) + +LISTIFY(10, DHT_IODEV, (;)); + +#define DHT_IODEV_REF(i, _) \ + COND_CODE_1(DT_NODE_EXISTS(DHT_ALIAS(i)), (CONCAT(&dht_iodev, i)), (NULL)) + +static struct rtio_iodev *dht_iodev[] = { LISTIFY(10, DHT_IODEV_REF, (,)) }; + +RTIO_DEFINE(dht_ctx, 1, 1); + int main(void) { int rc; @@ -32,29 +50,43 @@ int main(void) while (1) { for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) { - struct device *dev = (struct device *)sensors[i]; + struct device *dev = (struct device *) sensors[i]; + + uint8_t buf[128]; + + rc = sensor_read(dht_iodev[i], &dht_ctx, buf, 128); - rc = sensor_sample_fetch(dev); - if (rc < 0) { - printk("%s: sensor_sample_fetch() failed: %d\n", dev->name, rc); + if (rc != 0) { + printk("%s: sensor_read() failed: %d\n", dev->name, rc); return rc; } - struct sensor_value temp; - struct sensor_value hum; + const struct sensor_decoder_api *decoder; + + rc = sensor_get_decoder(dev, &decoder); - rc = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp); - if (rc == 0) { - rc = sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &hum); - } if (rc != 0) { - printf("get failed: %d\n", rc); - break; + printk("%s: sensor_get_decode() failed: %d\n", dev->name, rc); + return rc; } - printk("%16s: temp is %d.%02d °C humidity is %d.%02d %%RH\n", - dev->name, temp.val1, temp.val2 / 10000, - hum.val1, hum.val2 / 10000); + uint32_t temp_fit = 0; + struct sensor_q31_data temp_data = {0}; + + decoder->decode(buf, + (struct sensor_chan_spec) {SENSOR_CHAN_AMBIENT_TEMP, 0}, + &temp_fit, 1, &temp_data); + + uint32_t hum_fit = 0; + struct sensor_q31_data hum_data = {0}; + + decoder->decode(buf, + (struct sensor_chan_spec) {SENSOR_CHAN_HUMIDITY, 0}, + &hum_fit, 1, &hum_data); + + printk("%16s: temp is %s%d.%d °C humidity is %s%d.%d RH\n", dev->name, + PRIq_arg(temp_data.readings[0].temperature, 2, temp_data.shift), + PRIq_arg(hum_data.readings[0].humidity, 2, hum_data.shift)); } k_msleep(1000); } diff --git a/samples/sensor/die_temp_polling/boards/nucleo_f756zg.overlay b/samples/sensor/die_temp_polling/boards/nucleo_f756zg.overlay new file mode 100644 index 0000000000000..296fa3c6aef0f --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/nucleo_f756zg.overlay @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2024 Noah Pendleton + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + die-temp0 = &die_temp; + }; +}; + +&die_temp { + status = "okay"; +}; + +&adc1 { + pinctrl-0 = <&adc1_in0_pa0>; + pinctrl-names = "default"; + st,adc-prescaler = <4>; + status = "okay"; +}; diff --git a/samples/sensor/die_temp_polling/boards/nucleo_h7a3zi_q.overlay b/samples/sensor/die_temp_polling/boards/nucleo_h7a3zi_q.overlay new file mode 100644 index 0000000000000..f2081833b8cc3 --- /dev/null +++ b/samples/sensor/die_temp_polling/boards/nucleo_h7a3zi_q.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2024, Aurelien Jarno + * + * SPDX-License-Identifier: Apache-2.0 + * + * Application overlay for creating temperature sensor device instance + */ + +/ { + aliases { + die-temp0 = &digi_die_temp; + }; +}; + +&digi_die_temp { + status = "okay"; +}; diff --git a/samples/sensor/die_temp_polling/sample.yaml b/samples/sensor/die_temp_polling/sample.yaml index f64b321c2bdfe..adf8c4c003e58 100644 --- a/samples/sensor/die_temp_polling/sample.yaml +++ b/samples/sensor/die_temp_polling/sample.yaml @@ -8,6 +8,7 @@ tests: filter: dt_alias_exists("die-temp0") integration_platforms: - stm32f3_disco + - nucleo_h7a3zi_q harness: console harness_config: type: one_line diff --git a/samples/sensor/fxos8700-hid/CMakeLists.txt b/samples/sensor/fxos8700-hid/CMakeLists.txt deleted file mode 100644 index e9d8e00fa5907..0000000000000 --- a/samples/sensor/fxos8700-hid/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(fxos8700-hid) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/samples/sensor/fxos8700-hid/prj.conf b/samples/sensor/fxos8700-hid/prj.conf deleted file mode 100644 index 6650650f119af..0000000000000 --- a/samples/sensor/fxos8700-hid/prj.conf +++ /dev/null @@ -1,17 +0,0 @@ -CONFIG_LOG=y -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_HID=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr HID accelerometer mouse sample" -CONFIG_USB_DRIVER_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_LOG_LEVEL_ERR=y -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n - -CONFIG_STDOUT_CONSOLE=y -CONFIG_I2C=y -CONFIG_SENSOR=y -CONFIG_FXOS8700_MODE_ACCEL=y -CONFIG_FXOS8700_TRIGGER_OWN_THREAD=y -CONFIG_SENSOR_LOG_LEVEL_DBG=y - -CONFIG_GPIO=y -CONFIG_CBPRINTF_FP_SUPPORT=y diff --git a/samples/sensor/fxos8700-hid/sample.yaml b/samples/sensor/fxos8700-hid/sample.yaml deleted file mode 100644 index b35bac5f4ef67..0000000000000 --- a/samples/sensor/fxos8700-hid/sample.yaml +++ /dev/null @@ -1,10 +0,0 @@ -sample: - name: USB HID accelerometer mouse sample -tests: - sample.sensor.usb.fxos8700-hid: - depends_on: usb_device - platform_allow: frdm_k64f - harness: usb - tags: - - usb - - sensors diff --git a/samples/sensor/fxos8700-hid/src/main.c b/samples/sensor/fxos8700-hid/src/main.c deleted file mode 100644 index 8932e992d9593..0000000000000 --- a/samples/sensor/fxos8700-hid/src/main.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Copyright (c) 2018 qianfan Zhao - * Copyright (c) 2018 Nordic Semiconductor ASA - * Copyright (c) 2019 Intel Corp - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include - -#include -#include - -#define LOG_LEVEL LOG_LEVEL_DBG -LOG_MODULE_REGISTER(main); - -#define SW0_NODE DT_ALIAS(sw0) -#define SW1_NODE DT_ALIAS(sw1) - -#if DT_NODE_HAS_STATUS(SW0_NODE, okay) -static const struct gpio_dt_spec sw0_gpio = GPIO_DT_SPEC_GET(SW0_NODE, gpios); -#endif - -/* If second button exists, use it as right-click. */ -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) -static const struct gpio_dt_spec sw1_gpio = GPIO_DT_SPEC_GET(SW1_NODE, gpios); -#endif - -static const struct gpio_dt_spec led_gpio = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); - - -static const uint8_t hid_report_desc[] = HID_MOUSE_REPORT_DESC(2); - -static uint32_t def_val[4]; -static volatile uint8_t status[4]; -static K_SEM_DEFINE(sem, 0, 1); /* starts off "not available" */ -static struct gpio_callback gpio_callbacks[4]; - -#define MOUSE_BTN_REPORT_POS 0 -#define MOUSE_X_REPORT_POS 1 -#define MOUSE_Y_REPORT_POS 2 - -#define MOUSE_BTN_LEFT BIT(0) -#define MOUSE_BTN_RIGHT BIT(1) -#define MOUSE_BTN_MIDDLE BIT(2) - - -static void left_button(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - uint32_t cur_val; - uint8_t state = status[MOUSE_BTN_REPORT_POS]; - - cur_val = gpio_pin_get(gpio, pins); - if (def_val[0] != cur_val) { - state |= MOUSE_BTN_LEFT; - } else { - state &= ~MOUSE_BTN_LEFT; - } - - if (status[MOUSE_BTN_REPORT_POS] != state) { - status[MOUSE_BTN_REPORT_POS] = state; - k_sem_give(&sem); - } -} - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) -static void right_button(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) - -{ - uint32_t cur_val; - uint8_t state = status[MOUSE_BTN_REPORT_POS]; - - cur_val = gpio_pin_get(gpio, pins); - if (def_val[0] != cur_val) { - state |= MOUSE_BTN_RIGHT; - } else { - state &= ~MOUSE_BTN_RIGHT; - } - - if (status[MOUSE_BTN_REPORT_POS] != state) { - status[MOUSE_BTN_REPORT_POS] = state; - k_sem_give(&sem); - } -} -#endif - -int callbacks_configure(const struct gpio_dt_spec *gpio, - gpio_callback_handler_t handler, - struct gpio_callback *callback, uint32_t *val) -{ - int ret; - - if (!device_is_ready(gpio->port)) { - LOG_ERR("%s: device not ready.", gpio->port->name); - return -ENODEV; - } - - gpio_pin_configure_dt(gpio, GPIO_INPUT); - - ret = gpio_pin_get_dt(gpio); - if (ret < 0) { - return ret; - } - - *val = (uint32_t)ret; - - gpio_init_callback(callback, handler, BIT(gpio->pin)); - gpio_add_callback(gpio->port, callback); - gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_EDGE_TO_ACTIVE); - - return 0; -} - -static bool read_accel(const struct device *dev) -{ - struct sensor_value val[3]; - int ret; - - ret = sensor_channel_get(dev, SENSOR_CHAN_ACCEL_XYZ, val); - if (ret < 0) { - LOG_ERR("Cannot read sensor channels"); - return false; - } - - /* For printing double we need to use printf with - * printf("%10.6f\n", sensor_value_to_double(x)); - */ - LOG_DBG("int parts: X %d Y %d", val[0].val1, val[1].val1); - - /* TODO: Add proper calculations */ - - if (val[0].val1 != 0) { - status[MOUSE_X_REPORT_POS] = val[0].val1 * 4; - } - - if (val[1].val1 != 0) { - status[MOUSE_Y_REPORT_POS] = val[1].val1 * 4; - } - - if (val[0].val1 != 0 || val[1].val1 != 0) { - return true; - } else { - return false; - } -} - -static void trigger_handler(const struct device *dev, - const struct sensor_trigger *tr) -{ - ARG_UNUSED(tr); - - /* Always fetch the sample to clear the data ready interrupt in the - * sensor. - */ - if (sensor_sample_fetch(dev)) { - LOG_ERR("sensor_sample_fetch failed"); - return; - } - - if (read_accel(dev)) { - k_sem_give(&sem); - } -} - -int main(void) -{ - int ret; - uint8_t report[4] = { 0x00 }; - const struct device *accel_dev, *hid_dev; - - if (!gpio_is_ready_dt(&led_gpio)) { - LOG_ERR("%s: device not ready.", led_gpio.port->name); - return 0; - } - - hid_dev = device_get_binding("HID_0"); - if (hid_dev == NULL) { - LOG_ERR("Cannot get USB HID Device"); - return 0; - } - - gpio_pin_configure_dt(&led_gpio, GPIO_OUTPUT); - - if (callbacks_configure(&sw0_gpio, &left_button, &gpio_callbacks[0], &def_val[0])) { - LOG_ERR("Failed configuring left button callback."); - return 0; - } - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) - if (callbacks_configure(&sw1_gpio, &right_button, &gpio_callbacks[1], &def_val[1])) { - LOG_ERR("Failed configuring right button callback."); - return 0; - } -#endif - - accel_dev = DEVICE_DT_GET_ONE(nxp_fxos8700); - if (!device_is_ready(accel_dev)) { - LOG_ERR("%s: device not ready.", accel_dev->name); - return 0; - } - - struct sensor_value attr = { - .val1 = 6, - .val2 = 250000, - }; - - if (sensor_attr_set(accel_dev, SENSOR_CHAN_ALL, - SENSOR_ATTR_SAMPLING_FREQUENCY, &attr)) { - LOG_ERR("Could not set sampling frequency"); - return 0; - } - - struct sensor_trigger trig = { - .type = SENSOR_TRIG_DATA_READY, - .chan = SENSOR_CHAN_ACCEL_XYZ, - }; - - if (sensor_trigger_set(accel_dev, &trig, trigger_handler)) { - LOG_ERR("Could not set trigger"); - return 0; - } - - usb_hid_register_device(hid_dev, hid_report_desc, - sizeof(hid_report_desc), NULL); - - ret = usb_enable(NULL); - if (ret != 0) { - LOG_ERR("Failed to enable USB"); - return 0; - } - - usb_hid_init(hid_dev); - - while (true) { - k_sem_take(&sem, K_FOREVER); - - report[MOUSE_BTN_REPORT_POS] = status[MOUSE_BTN_REPORT_POS]; - report[MOUSE_X_REPORT_POS] = status[MOUSE_X_REPORT_POS]; - status[MOUSE_X_REPORT_POS] = 0U; - report[MOUSE_Y_REPORT_POS] = status[MOUSE_Y_REPORT_POS]; - status[MOUSE_Y_REPORT_POS] = 0U; - hid_int_ep_write(hid_dev, report, sizeof(report), NULL); - - /* Toggle LED on sent report */ - gpio_pin_toggle_dt(&led_gpio); - } -} diff --git a/samples/sensor/grow_r502a/README.rst b/samples/sensor/grow_r502a/README.rst index 032be38bfff67..06de5aabec575 100644 --- a/samples/sensor/grow_r502a/README.rst +++ b/samples/sensor/grow_r502a/README.rst @@ -8,18 +8,15 @@ Overview This sample has the below functionalities: +#. Sensor LED is controlled using led APIs from zephyr subsystem. #. Shows the number of fingerprints stored in the sensor. +#. Shows the sensor device's configurations like baud rate, library size, address and data packet size in UART frame. #. When SENSOR_ATTR_RECORD_FREE_IDX is set then it search for free index in sensor library. #. When SENSOR_ATTR_RECORD_ADD is set then it adds a new fingerprint to the sensor. #. When SENSOR_ATTR_RECORD_FIND is set then it tries to find a match for the input fingerprint. On finding a match it returns ID and confidence. #. When SENSOR_ATTR_RECORD_DEL is set then it deletes a fingerprint from the sensor. -Note: Fingerprint add & delete functionalities work only when SENSOR_TRIG_TOUCH is set. -Tricolored LED in the sensor hardware will, flash on the below conditions: - -#. On successful addition or deletion of fingerprint it will flash in blue three times. -#. On finding a match for the input fingerprint it will flash in purple. -#. In all other cases it will flash in red. +Note: Fingerprint add functionality work only when SENSOR_TRIG_TOUCH is set. Wiring ******* @@ -42,7 +39,7 @@ build this sample app using: .. zephyr-app-commands:: :zephyr-app: samples/sensor/grow_r502a - :board: nrf52840dk/nrf52840 + :board: esp32_devkitc_wroom/esp32/procpu :goals: build flash Sample Output @@ -50,20 +47,18 @@ Sample Output .. code-block:: console - *** Booting Zephyr OS build zephyr-v3.1.0-2640-g328bb73113d4 *** - template count : 0 + *** Booting Zephyr OS build v3.6.0-3147-g8ae1a2e2718e *** + template count : 4 + baud 57600 + addr 0xffffffff + lib_size 200 + data_pkt_size 128 Fingerprint Deleted at ID #3 - Fingerprint template free idx at ID #0 - Waiting for valid finger to enroll as ID #0 + Fingerprint template free idx at ID #3 + Waiting for valid finger to enroll as ID #3 Place your finger - Fingerprint successfully stored at #0 - template count : 1 - Matched ID : 0 - confidence : 170 - template count : 1 - Matched ID : 0 - confidence : 136 - template count : 1 - Matched ID : 0 - confidence : 318 + Fingerprint successfully stored at #3 + template count : 4 + Matched ID : 2 + confidence : 110 diff --git a/samples/sensor/grow_r502a/boards/esp32_devkitc_wroom_procpu.overlay b/samples/sensor/grow_r502a/boards/esp32_devkitc_wroom_procpu.overlay index 2fa0bb3197f77..7add14e5350cb 100644 --- a/samples/sensor/grow_r502a/boards/esp32_devkitc_wroom_procpu.overlay +++ b/samples/sensor/grow_r502a/boards/esp32_devkitc_wroom_procpu.overlay @@ -25,4 +25,9 @@ int-gpios = <&gpio1 3 GPIO_ACTIVE_LOW>; }; }; + + led { + compatible = "hzgrow,r502a-led"; + status = "okay"; + }; }; diff --git a/samples/sensor/grow_r502a/prj.conf b/samples/sensor/grow_r502a/prj.conf index 0f507ebe69d09..5727d4c0ceb78 100644 --- a/samples/sensor/grow_r502a/prj.conf +++ b/samples/sensor/grow_r502a/prj.conf @@ -2,4 +2,8 @@ CONFIG_SERIAL=y CONFIG_UART_INTERRUPT_DRIVEN=y CONFIG_SENSOR=y +CONFIG_LED=y CONFIG_GROW_R502A_TRIGGER_OWN_THREAD=y + +# Minimum stack size needed +CONFIG_GROW_R502A_THREAD_STACK_SIZE=1536 diff --git a/samples/sensor/grow_r502a/src/main.c b/samples/sensor/grow_r502a/src/main.c index 583d1ed3f6fad..da8923e1fc27b 100644 --- a/samples/sensor/grow_r502a/src/main.c +++ b/samples/sensor/grow_r502a/src/main.c @@ -9,34 +9,57 @@ #include #include #include +#include static bool enroll; -static struct sensor_value fid, val; +static struct sensor_value fid_get, count, find, del, param; -static void finger_match(const struct device *dev) +static void finger_find(const struct device *dev) { - struct sensor_value input; int ret; + ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, + SENSOR_ATTR_R502A_CAPTURE, NULL); + if (ret != 0) { + printk("Capture fingerprint failed %d\n", ret); + return; + } + ret = sensor_attr_get(dev, SENSOR_CHAN_FINGERPRINT, - SENSOR_ATTR_R502A_RECORD_FIND, &input); + SENSOR_ATTR_R502A_RECORD_FIND, &find); if (ret != 0) { - printk("Sensor attr get failed %d\n", ret); + printk("Find fingerprint failed %d\n", ret); return; } - printk("Matched ID : %d\n", input.val1); - printk("confidence : %d\n", input.val2); + printk("Matched ID : %d\n", find.val1); + printk("confidence : %d\n", find.val2); } static void finger_enroll(const struct device *dev) { int ret; - ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, SENSOR_ATTR_R502A_RECORD_ADD, &fid); + ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, + SENSOR_ATTR_R502A_CAPTURE, NULL); + if (ret != 0) { + printk("Capture fingerprint failed %d\n", ret); + return; + } - if (ret == 0) { - printk("Fingerprint successfully stored at #%d\n", fid.val1); + ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, + SENSOR_ATTR_R502A_TEMPLATE_CREATE, NULL); + if (ret != 0) { + printk("Create template failed %d\n", ret); + return; + } + + ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, + SENSOR_ATTR_R502A_RECORD_ADD, &fid_get); + if (!ret) { + printk("Fingerprint successfully stored at #%d\n", fid_get.val1); enroll = false; + } else { + printk("Fingerprint store failed %d\n", ret); } } @@ -49,12 +72,44 @@ static void template_count_get(const struct device *dev) printk("Sample Fetch Error %d\n", ret); return; } - ret = sensor_channel_get(dev, SENSOR_CHAN_FINGERPRINT, &val); + ret = sensor_channel_get(dev, SENSOR_CHAN_FINGERPRINT, &count); if (ret < 0) { printk("Channel Get Error %d\n", ret); return; } - printk("template count : %d\n", val.val1); + printk("template count : %d\n", count.val1); +} + +static int r502a_led(void) +{ + int ret; + const int led_num = 0; + const int led_color_a_inst = 1; + uint8_t led_color = R502A_LED_COLOR_PURPLE; + const struct device *led_dev = DEVICE_DT_GET_ONE(hzgrow_r502a_led); + + if (led_dev == NULL) { + printk("Error: no device found\n"); + return -ENODEV; + } + + if (!device_is_ready(led_dev)) { + printk("Error: Device %s is not ready\n", led_dev->name); + return -EAGAIN; + } + + ret = led_set_color(led_dev, led_num, led_color_a_inst, &led_color); + if (ret != 0) { + printk("led set color failed %d\n", ret); + return -1; + } + + ret = led_on(led_dev, led_num); + if (ret != 0) { + printk("led on failed %d\n", ret); + return -1; + } + return 0; } static void trigger_handler(const struct device *dev, @@ -64,13 +119,29 @@ static void trigger_handler(const struct device *dev, finger_enroll(dev); } else { template_count_get(dev); - finger_match(dev); + finger_find(dev); } } +static void read_fps_param(const struct device *dev) +{ + int ret = 0; + struct r502a_sys_param res; + + ret = r502a_read_sys_param(dev, &res); + if (ret != 0) { + printk("r502a read system parameter failed %d\n", ret); + return; + } + + printk("baud %d\n", res.baud); + printk("addr 0x%x\n", res.addr); + printk("lib_size %d\n", res.lib_size); + printk("data_pkt_size %d\n", res.data_pkt_size); +} + int main(void) { - static struct sensor_value del, fid_get; int ret; const struct device *dev = DEVICE_DT_GET_ONE(hzgrow_r502a); @@ -85,8 +156,16 @@ int main(void) return 0; } + ret = r502a_led(); + if (ret != 0) { + printk("Error: device led failed to set %d", ret); + return 0; + } + template_count_get(dev); + read_fps_param(dev); + del.val1 = 3; ret = sensor_attr_set(dev, SENSOR_CHAN_FINGERPRINT, SENSOR_ATTR_R502A_RECORD_DEL, &del); if (ret != 0) { @@ -103,9 +182,8 @@ int main(void) } printk("Fingerprint template free idx at ID #%d\n", fid_get.val1); - fid.val1 = fid_get.val1; printk("Waiting for valid finger to enroll as ID #%d\n" - "Place your finger\n", fid.val1); + "Place your finger\n", fid_get.val1); enroll = true; if (IS_ENABLED(CONFIG_GROW_R502A_TRIGGER)) { diff --git a/samples/sensor/mcux_lpcmp/CMakeLists.txt b/samples/sensor/mcux_lpcmp/CMakeLists.txt new file mode 100644 index 0000000000000..60cefb742f309 --- /dev/null +++ b/samples/sensor/mcux_lpcmp/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(mcux_lpcmp) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/sensor/mcux_lpcmp/README.rst b/samples/sensor/mcux_lpcmp/README.rst new file mode 100644 index 0000000000000..ed270e4664acd --- /dev/null +++ b/samples/sensor/mcux_lpcmp/README.rst @@ -0,0 +1,36 @@ +.. _mcux_lpcmp: + +NXP MCUX Low-power Analog Comparator (LPCMP) +############################################ + +Overview +******** + +This sample show how to use the NXP MCUX Analog Comparator (LPCMP) driver. + +In this application, the negative input port of the LPCMP is set to 7 which +means the input voltage comes from the LPCMP internal DAC, the reference +voltage of the DAC is set to 0 (for the specific chip, the user needs to +check the reference manual to confirm where this reference voltage comes +from), the output voltage of the DAC is equal to (VREF/256)*(data+1), where +data is set through the attribute ``SENSOR_ATTR_MCUX_LPCMP_DAC_OUTPUT_VOLTAGE``. +The positive input port is set to 0, the user needs to check the reference +manual and board schematic to confirm which specific port is used and can +connect an external voltage to that port and change the input voltage to +see the output change of the LPCMP. + +The output value of the LPCMP is reported on the console. + +Building and Running +******************** + +Building and Running for NXP FRDM-MCXN947 +========================================= +Build the application for the :ref:`frdm_mcxn947` board, and adjust the +LPCMP positive input port voltage by changing the voltage input to J2-17. + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/mcux_lpcmp + :board: frdm_mcxn947//cpu0 + :goals: build flash + :compact: diff --git a/samples/sensor/mcux_lpcmp/boards/frdm_mcxn947_mcxn947_cpu0.overlay b/samples/sensor/mcux_lpcmp/boards/frdm_mcxn947_mcxn947_cpu0.overlay new file mode 100644 index 0000000000000..6a896a5e39177 --- /dev/null +++ b/samples/sensor/mcux_lpcmp/boards/frdm_mcxn947_mcxn947_cpu0.overlay @@ -0,0 +1,9 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&lpcmp0 { + function-clock = "CMP_CLOCK"; +}; diff --git a/samples/sensor/mcux_lpcmp/prj.conf b/samples/sensor/mcux_lpcmp/prj.conf new file mode 100644 index 0000000000000..f8f3fa36322e8 --- /dev/null +++ b/samples/sensor/mcux_lpcmp/prj.conf @@ -0,0 +1,2 @@ +CONFIG_SENSOR=y +CONFIG_MCUX_LPCMP_TRIGGER=y diff --git a/samples/sensor/mcux_lpcmp/sample.yaml b/samples/sensor/mcux_lpcmp/sample.yaml new file mode 100644 index 0000000000000..7ce4b8cbac528 --- /dev/null +++ b/samples/sensor/mcux_lpcmp/sample.yaml @@ -0,0 +1,23 @@ +sample: + description: Demonstration of the NXP MCUX LPCMP driver + name: NXP MCUX LPCMP sample +common: + platform_allow: + - frdm_mcxn947/mcxn947/cpu0 + integration_platforms: + - frdm_mcxn947/mcxn947/cpu0 + tags: + - drivers + - sensor +tests: + sample.sensor.mcux_lpcmp: + harness: console + harness_config: + type: one_line + ordered: true + regex: + - "LPCMP input [a-z]* threshold" + sample.sensor.mcux_lpcmp.no_trigger: + build_only: true + extra_configs: + - CONFIG_MCUX_LPCMP_TRIGGER=n diff --git a/samples/sensor/mcux_lpcmp/src/main.c b/samples/sensor/mcux_lpcmp/src/main.c new file mode 100644 index 0000000000000..2519dcddb55af --- /dev/null +++ b/samples/sensor/mcux_lpcmp/src/main.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020 Vestas Wind Systems A/S + * Copyright NXP 2024 + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +struct lpcmp_attr { + int16_t attr; + int32_t val; +}; + +static const struct lpcmp_attr attrs[] = { + {.attr = SENSOR_ATTR_MCUX_LPCMP_POSITIVE_MUX_INPUT, .val = 0}, + {.attr = SENSOR_ATTR_MCUX_LPCMP_NEGATIVE_MUX_INPUT, .val = 7}, + + {.attr = SENSOR_ATTR_MCUX_LPCMP_DAC_ENABLE, .val = 1}, + {.attr = SENSOR_ATTR_MCUX_LPCMP_DAC_HIGH_POWER_MODE_ENABLE, .val = 0}, + {.attr = SENSOR_ATTR_MCUX_LPCMP_DAC_REFERENCE_VOLTAGE_SOURCE, .val = 0}, + {.attr = SENSOR_ATTR_MCUX_LPCMP_DAC_OUTPUT_VOLTAGE, .val = (0xFF >> 1)}, + + {.attr = SENSOR_ATTR_MCUX_LPCMP_SAMPLE_ENABLE, .val = 0}, + {.attr = SENSOR_ATTR_MCUX_LPCMP_FILTER_COUNT, .val = 7}, + {.attr = SENSOR_ATTR_MCUX_LPCMP_FILTER_PERIOD, .val = (0xFF >> 1)}, + + {.attr = SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_ENABLE, .val = 0}, + {.attr = SENSOR_ATTR_MCUX_LPCMP_COUTA_WINDOW_SIGNAL_INVERT_ENABLE, .val = 0}, + {.attr = SENSOR_ATTR_MCUX_LPCMP_COUTA_SIGNAL, .val = 0}, + {.attr = SENSOR_ATTR_MCUX_LPCMP_COUT_EVENT_TO_CLOSE_WINDOW, .val = 0}, +}; + +#ifdef CONFIG_MCUX_LPCMP_TRIGGER +static const int16_t triggers[] = { + SENSOR_TRIG_MCUX_LPCMP_OUTPUT_RISING, + SENSOR_TRIG_MCUX_LPCMP_OUTPUT_FALLING, +}; +#endif /* CONFIG_MCUX_LPCMP_TRIGGER */ + +static void lpcmp_input_handler(bool above_threshold) +{ + if (above_threshold) { + printf("LPCMP input above threshold\n"); + } else { + printf("LPCMP input below threshold\n"); + } +} + +#ifdef CONFIG_MCUX_LPCMP_TRIGGER +static void lpcmp_trigger_handler(const struct device *dev, const struct sensor_trigger *trigger) +{ + ARG_UNUSED(dev); + + lpcmp_input_handler((int16_t)trigger->type == SENSOR_TRIG_MCUX_LPCMP_OUTPUT_RISING); +} +#endif /* CONFIG_MCUX_LPCMP_TRIGGER */ + +int main(void) +{ +#ifdef CONFIG_MCUX_LPCMP_TRIGGER + struct sensor_trigger trigger[ARRAY_SIZE(triggers)] = { + [0] = { + .chan = SENSOR_CHAN_MCUX_LPCMP_OUTPUT, + .type = triggers[0], + }, + [1] = { + .chan = SENSOR_CHAN_MCUX_LPCMP_OUTPUT, + .type = triggers[1], + } + }; +#endif /* CONFIG_MCUX_LPCMP_TRIGGER */ + const struct device *const lpcmp = DEVICE_DT_GET(DT_NODELABEL(lpcmp0)); + struct sensor_value val; + int err; + + if (!device_is_ready(lpcmp)) { + printf("LPCMP device not ready\n"); + return 0; + } + + /* Set LPCMP attributes */ + val.val2 = 0; + for (uint8_t i = 0; i < ARRAY_SIZE(attrs); i++) { + val.val1 = attrs[i].val; + err = sensor_attr_set(lpcmp, SENSOR_CHAN_MCUX_LPCMP_OUTPUT, attrs[i].attr, &val); + if (err) { + printf("failed to set attribute %d (err %d)\n", i, err); + return 0; + } + } + + /* Delay for analog components (DAC, CMP, ...) to settle */ + k_sleep(K_MSEC(1)); + +#ifdef CONFIG_MCUX_LPCMP_TRIGGER + /* Set LPCMP triggers */ + for (uint8_t i = 0; i < ARRAY_SIZE(triggers); i++) { + err = sensor_trigger_set(lpcmp, &trigger[i], lpcmp_trigger_handler); + if (err) { + printf("failed to set trigger %d (err %d)\n", i, err); + return 0; + } + } + + /* Await trigger */ + while (true) { + k_sleep(K_MSEC(1)); + } +#else /* !CONFIG_MCUX_LPCMP_TRIGGER */ + err = sensor_sample_fetch(lpcmp); + if (err) { + printf("failed to fetch sample (err %d)\n", err); + return 0; + } + + err = sensor_channel_get(lpcmp, SENSOR_CHAN_MCUX_LPCMP_OUTPUT, &val); + if (err) { + printf("failed to get channel (err %d)\n", err); + return 0; + } + + lpcmp_input_handler(val.val1 == 1); +#endif /* CONFIG_MCUX_LPCMP_TRIGGER */ + + return 0; +} diff --git a/samples/sensor/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay b/samples/sensor/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay new file mode 100644 index 0000000000000..748e06aef8358 --- /dev/null +++ b/samples/sensor/qdec/boards/nrf54h20dk_nrf54h20_cpuapp.overlay @@ -0,0 +1,43 @@ +/* + * Copyright 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + aliases { + qdec0 = &qdec130; + qenca = &phase_a; + qencb = &phase_b; + }; + + encoder-emulate { + compatible = "gpio-leds"; + phase_a: phase_a { + gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; + }; + phase_b: phase_b { + gpios = <&gpio1 3 GPIO_ACTIVE_HIGH>; + }; + }; +}; + +&pinctrl { + qdec_pinctrl: qdec_pinctrl { + group1 { + psels = , + ; + }; + }; +}; + +&gpio1 { + status = "okay"; +}; + +&qdec130 { + status = "okay"; + pinctrl-0 = <&qdec_pinctrl>; + pinctrl-names = "default"; + steps = <120>; + led-pre = <500>; +}; diff --git a/samples/sensor/qdec/sample.yaml b/samples/sensor/qdec/sample.yaml index 8982dfccd33db..52e19e8bb1861 100644 --- a/samples/sensor/qdec/sample.yaml +++ b/samples/sensor/qdec/sample.yaml @@ -22,10 +22,12 @@ tests: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - nrf52840dk/nrf52840 - nrf5340dk/nrf5340/cpuapp - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp harness_config: fixture: gpio_loopback type: multi_line diff --git a/samples/sensor/sensor_shell/CMakeLists.txt b/samples/sensor/sensor_shell/CMakeLists.txt index 1f13027d26b90..597957beb61c0 100644 --- a/samples/sensor/sensor_shell/CMakeLists.txt +++ b/samples/sensor/sensor_shell/CMakeLists.txt @@ -7,4 +7,8 @@ project(sensor_shell) target_sources(app PRIVATE src/main.c) +target_sources_ifdef(CONFIG_SAMPLES_SENSOR_SHELL_FAKE_SENSOR app PRIVATE + src/fake_sensor.c +) + target_include_directories(app PRIVATE include) diff --git a/samples/sensor/sensor_shell/Kconfig b/samples/sensor/sensor_shell/Kconfig index 354385ee6cadc..38fcdfa7eb6eb 100644 --- a/samples/sensor/sensor_shell/Kconfig +++ b/samples/sensor/sensor_shell/Kconfig @@ -1,4 +1,10 @@ # Copyright (c) 2023 Google LLC # SPDX-License-Identifier: Apache-2.0 +config SAMPLES_SENSOR_SHELL_FAKE_SENSOR + bool "Enable fake sensor" + help + On boards that do not have a sensor, enabling this will build a fake + sensor that can be interacted with via the sensor shell. + source "Kconfig.zephyr" diff --git a/samples/sensor/sensor_shell/README.rst b/samples/sensor/sensor_shell/README.rst index db9e3e2061f3b..d3146e5201dd3 100644 --- a/samples/sensor/sensor_shell/README.rst +++ b/samples/sensor/sensor_shell/README.rst @@ -18,6 +18,14 @@ enabled, for example: :board: reel_board :goals: build flash +For boards that do not have a sensor, a simple fake sensor driver is provided, for example: + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/sensor_shell + :board: qemu_riscv64 + :goals: run + :gen-args: -DCONFIG_SAMPLES_SENSOR_SHELL_FAKE_SENSOR=y + Shell Module Command Help ========================= diff --git a/samples/sensor/sensor_shell/app.overlay b/samples/sensor/sensor_shell/app.overlay new file mode 100644 index 0000000000000..79d50cb6b2b59 --- /dev/null +++ b/samples/sensor/sensor_shell/app.overlay @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + + / { + app { + #address-cells = <1>; + #size-cells = <0>; + + vsensor0: sensor@0 { + compatible = "vnd,fake-sensor"; + reg = <0>; + friendly-name = "Fake sensor 0"; + status = "okay"; + }; + + vsensor1: sensor@1 { + compatible = "vnd,fake-sensor"; + reg = <1>; + friendly-name = "Fake sensor 1"; + status = "okay"; + }; + }; +}; diff --git a/samples/sensor/sensor_shell/dts/bindings/vnd,sensor.yaml b/samples/sensor/sensor_shell/dts/bindings/vnd,sensor.yaml new file mode 100644 index 0000000000000..50c32f17dbac2 --- /dev/null +++ b/samples/sensor/sensor_shell/dts/bindings/vnd,sensor.yaml @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +description: Fake sensor + +include: sensor-device.yaml + +compatible: "vnd,fake-sensor" diff --git a/samples/sensor/sensor_shell/pytest/test_sensor_shell.py b/samples/sensor/sensor_shell/pytest/test_sensor_shell.py new file mode 100644 index 0000000000000..7a01bec9978c7 --- /dev/null +++ b/samples/sensor/sensor_shell/pytest/test_sensor_shell.py @@ -0,0 +1,75 @@ +# Copyright (c) 2024 Meta Platforms +# SPDX-License-Identifier: Apache-2.0 + +import logging + +from twister_harness import Shell + +logger = logging.getLogger(__name__) + + +def test_sensor_shell_info(shell: Shell): + logger.info('send "sensor info" command') + + lines = shell.exec_command('sensor info') + assert any(['device name: sensor@0' in line for line in lines]), 'expected response not found' + assert any(['device name: sensor@1' in line for line in lines]), 'expected response not found' + + logger.info('response is valid') + + +def test_sensor_shell_get(shell: Shell): + logger.info('send "sensor get" command') + + lines = shell.exec_command('sensor get sensor@0 voltage') + assert any(['channel type=31(voltage)' in line for line in lines]), 'expected response not found' + + lines = shell.exec_command('sensor get sensor@1 53') + assert any(['channel type=53(gauge_state_of_health)' in line for line in lines]), 'expected response not found' + + # Channel should be the last one before 'all' (because 'all' doesn't print anything) so that the + # for-loop in `parse_named_int()` will go through everything + lines = shell.exec_command('sensor get sensor@0 gauge_desired_charging_current') + assert any(['channel type=59(gauge_desired_charging_current)' in line for line in lines]), 'expected response not found' + + logger.info('response is valid') + + +def test_sensor_shell_attr_get(shell: Shell): + logger.info('send "sensor attr_get" command') + + lines = shell.exec_command('sensor attr_get sensor@0 co2 sampling_frequency') + assert any(['sensor@0(channel=co2, attr=sampling_frequency)' in line for line in lines]), 'expected response not found' + + lines = shell.exec_command('sensor attr_get sensor@1 53 3') + assert any(['sensor@1(channel=gauge_state_of_health, attr=slope_th)' in line for line in lines]), 'expected response not found' + + logger.info('response is valid') + + +def test_sensor_shell_attr_set(shell: Shell): + logger.info('send "sensor attr_set" command') + + lines = shell.exec_command('sensor attr_set sensor@0 co2 sampling_frequency 1') + expected_line = 'sensor@0 channel=co2, attr=sampling_frequency set to value=1' + assert any([expected_line in line for line in lines]), 'expected response not found' + + lines = shell.exec_command('sensor attr_set sensor@1 53 3 1') + expected_line = 'sensor@1 channel=gauge_state_of_health, attr=slope_th set to value=1' + assert any([expected_line in line for line in lines]), 'expected response not found' + + logger.info('response is valid') + + +def test_sensor_shell_trig(shell: Shell): + logger.info('send "sensor trig" command') + + lines = shell.exec_command('sensor trig sensor@0 on data_ready') + expected_line = 'Enabled trigger idx=1 data_ready on device sensor@0' + assert any([expected_line in line for line in lines]), 'expected response not found' + + lines = shell.exec_command('sensor trig sensor@0 off data_ready') + expected_line = 'Disabled trigger idx=1 data_ready on device sensor@0' + assert any([expected_line in line for line in lines]), 'expected response not found' + + logger.info('response is valid') diff --git a/samples/sensor/sensor_shell/sample.yaml b/samples/sensor/sensor_shell/sample.yaml index d89dfebc21aae..51f57b10f6c0c 100644 --- a/samples/sensor/sensor_shell/sample.yaml +++ b/samples/sensor/sensor_shell/sample.yaml @@ -1,5 +1,10 @@ sample: name: Shell Sensor Module Sample +common: + tags: + - sensor + - shell + tests: sample.sensor.shell: integration_platforms: @@ -7,7 +12,15 @@ tests: # TODO Remove once #63414 is resolved platform_exclude: gd32l233r_eval filter: ( CONFIG_UART_CONSOLE and CONFIG_SERIAL_SUPPORT_INTERRUPT ) - tags: shell harness: keyboard min_ram: 20 min_flash: 33 + sample.sensor.shell.pytest: + filter: CONFIG_SERIAL and dt_chosen_enabled("zephyr,shell-uart") + min_ram: 40 + harness: pytest + extra_configs: + - arch:posix:CONFIG_NATIVE_UART_0_ON_STDINOUT=y + - CONFIG_SAMPLES_SENSOR_SHELL_FAKE_SENSOR=y + integration_platforms: + - native_sim diff --git a/samples/sensor/sensor_shell/src/fake_sensor.c b/samples/sensor/sensor_shell/src/fake_sensor.c new file mode 100644 index 0000000000000..2d6df21251a83 --- /dev/null +++ b/samples/sensor/sensor_shell/src/fake_sensor.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024 Meta Platforms + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT vnd_fake_sensor + +#include +#include +#include + +LOG_MODULE_REGISTER(fake_sensor); + +static int init(const struct device *dev) +{ + ARG_UNUSED(dev); + + return 0; +} + +static int attr_set(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, + const struct sensor_value *val) +{ + LOG_DBG("[%s] dev: %p, chan: %d, attr: %d, val1: %d, val2: %d", __func__, dev, chan, attr, + val->val1, val->val2); + + return 0; +} + +static int attr_get(const struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, + struct sensor_value *val) +{ + LOG_DBG("[%s] dev: %p, chan: %d, attr: %d", __func__, dev, chan, attr); + + val->val1 = chan; + val->val2 = attr * 100000; + + return 0; +} + +static int sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + LOG_DBG("[%s] dev: %p, chan: %d", __func__, dev, chan); + + return 0; +} + +static int channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) +{ + LOG_DBG("[%s] dev: %p, chan: %d", __func__, dev, chan); + + switch (chan) { + case SENSOR_CHAN_ACCEL_XYZ: + __fallthrough; + case SENSOR_CHAN_GYRO_XYZ: + __fallthrough; + case SENSOR_CHAN_MAGN_XYZ: + __fallthrough; + case SENSOR_CHAN_POS_DXYZ: + for (int i = 0; i < 3; i++, val++) { + val->val1 = chan; + val->val2 = 1; + } + break; + default: + val->val1 = chan; + val->val2 = 1; + break; + } + + return 0; +} + +static int trigger_set(const struct device *dev, const struct sensor_trigger *trig, + sensor_trigger_handler_t handler) +{ + LOG_DBG("[%s - %s] dev: %p, trig->chan: %d, trig->type: %d, handler: %p", __func__, + (handler == NULL) ? "off" : "on", dev, trig->chan, trig->type, handler); + + return 0; +} + +static const struct sensor_driver_api api = { + .attr_get = attr_get, + .attr_set = attr_set, + .sample_fetch = sample_fetch, + .channel_get = channel_get, + .trigger_set = trigger_set, +}; + +#define VND_SENSOR_INIT(n) \ + SENSOR_DEVICE_DT_INST_DEFINE(n, init, NULL, NULL, NULL, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &api); + +DT_INST_FOREACH_STATUS_OKAY(VND_SENSOR_INIT) diff --git a/samples/sensor/sht3xd/boards/efr32mg_sltb004a.overlay b/samples/sensor/sht3xd/boards/sltb004a.overlay similarity index 100% rename from samples/sensor/sht3xd/boards/efr32mg_sltb004a.overlay rename to samples/sensor/sht3xd/boards/sltb004a.overlay diff --git a/samples/sensor/sht3xd/sample.yaml b/samples/sensor/sht3xd/sample.yaml index 0319ba3a7e29c..be30591c2c6a4 100644 --- a/samples/sensor/sht3xd/sample.yaml +++ b/samples/sensor/sht3xd/sample.yaml @@ -8,7 +8,7 @@ sample: name: SHT3XD Sensor Sample common: platform_allow: - - efr32mg_sltb004a + - sltb004a - frdm_k64f - nrf51_ble400 - nrf52840dk/nrf52840 diff --git a/samples/sensor/veaa_x_3/CMakeLists.txt b/samples/sensor/veaa_x_3/CMakeLists.txt new file mode 100644 index 0000000000000..e43b188ab7d9c --- /dev/null +++ b/samples/sensor/veaa_x_3/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(app) + +target_sources(app PRIVATE src/main.c) diff --git a/samples/sensor/veaa_x_3/Kconfig b/samples/sensor/veaa_x_3/Kconfig new file mode 100644 index 0000000000000..7eca02930fd6b --- /dev/null +++ b/samples/sensor/veaa_x_3/Kconfig @@ -0,0 +1,23 @@ +# +# Copyright (c) 2024 Vitrolife A/S +# +# SPDX-License-Identifier: Apache-2.0 +# + +mainmenu "VEAA sample application" + +config SAMPLE_USE_SHELL + bool "Use sensor shell and disable loop" + default n + select SHELL + select SENSOR_SHELL + +config SAMPLE_LOOP_INTERVAL + int "Sample loop delay in milliseconds" + default 200 + +config SAMPLE_LOOP_INCREMENT + int "Sample kPa increment per loop" + default 1 + +source "Kconfig.zephyr" diff --git a/samples/sensor/veaa_x_3/README.rst b/samples/sensor/veaa_x_3/README.rst new file mode 100644 index 0000000000000..09d85eacacfab --- /dev/null +++ b/samples/sensor/veaa_x_3/README.rst @@ -0,0 +1,38 @@ +.. veaa_x_3: + +VEAA-X-3 sample +########################## + +Overview +******** + +A sensor sample that demonstrates how to use a VEAA-X-3 device. + +Building and Running +******************** + +This sample sets the valve setpoint then reads the actual pressure. +This is done continuously. When the maximum supported pressure is reached the setpoint is reset to +the valve's minimum supported pressure value. + +.. zephyr-app-commands:: + :zephyr-app: samples/sensor/veaa_x_3 + :board: + :goals: build flash + :compact: + +Sample Output +============= + +.. code-block:: console + + Testing test_veaa_x_3 + Valve range: 1 to 200 kPa + Setpoint: 1 kPa, actual: 1 kPa + Setpoint: 2 kPa, actual: 2 kPa + Setpoint: 3 kPa, actual: 3 kPa + ... + Setpoint: 199 kPa, actual: 199 kPa + Setpoint: 200 kPa, actual: 200 kPa + Setpoint: 1 kPa, actual: 1 kPa + diff --git a/samples/sensor/veaa_x_3/boards/nucleo_h563zi.overlay b/samples/sensor/veaa_x_3/boards/nucleo_h563zi.overlay new file mode 100644 index 0000000000000..10b9676ac80be --- /dev/null +++ b/samples/sensor/veaa_x_3/boards/nucleo_h563zi.overlay @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * Copyright (c) 2024, Vitrolife A/S + */ + +/* spi1 sck conflicts with dac1 channel 3 */ +/delete-node/ &spi1; + +/ { + test_veaa_x_3: test_veaa_x_3 { + status = "okay"; + compatible = "festo,veaa-x-3"; + io-channels = <&adc1 3>; + dac = <&dac1>; + dac-channel-id = <2>; + dac-resolution = <12>; + pressure-range-type = "D2"; + }; + +}; + +&adc1 { + #address-cells = <1>; + #size-cells = <0>; + + channel@3 { + reg = <3>; + zephyr,gain = "ADC_GAIN_1"; + zephyr,reference = "ADC_REF_INTERNAL"; + zephyr,acquisition-time = ; + zephyr,resolution = <12>; + }; + +}; diff --git a/samples/sensor/veaa_x_3/prj.conf b/samples/sensor/veaa_x_3/prj.conf new file mode 100644 index 0000000000000..e0bc48f5dfef2 --- /dev/null +++ b/samples/sensor/veaa_x_3/prj.conf @@ -0,0 +1,4 @@ +CONFIG_ADC=y +CONFIG_DAC=y +CONFIG_SENSOR=y +CONFIG_LOG=y diff --git a/samples/sensor/veaa_x_3/sample.yaml b/samples/sensor/veaa_x_3/sample.yaml new file mode 100644 index 0000000000000..2039dd9e7ed1a --- /dev/null +++ b/samples/sensor/veaa_x_3/sample.yaml @@ -0,0 +1,8 @@ +sample: + name: VEAA-X-3 sensor sample +tests: + sample.sensor.veaa_x_3: + harness: sensor + tags: sensors + filter: dt_compat_enabled("festo,veaa-x-3") + depends_on: adc dac diff --git a/samples/sensor/veaa_x_3/src/main.c b/samples/sensor/veaa_x_3/src/main.c new file mode 100644 index 0000000000000..db00cda87159b --- /dev/null +++ b/samples/sensor/veaa_x_3/src/main.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2024 Vitrolife A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +static const struct device *const dev = DEVICE_DT_GET_ONE(festo_veaa_x_3); + +int main(void) +{ + int rc; + struct sensor_value range, setpoint, pressure; + + printk("Testing %s\n", dev->name); + + if (!device_is_ready(dev)) { + printk("%s not ready\n", dev->name); + return -ENODEV; + } + + rc = sensor_attr_get(dev, SENSOR_CHAN_PRESS, + (enum sensor_attribute)SENSOR_ATTR_VEAA_X_3_RANGE, &range); + if (rc != 0) { + printk("get range failed: %d\n", rc); + return rc; + } + printk("Valve range: %u to %u kPa\n", range.val1, range.val2); + + if (IS_ENABLED(CONFIG_SAMPLE_USE_SHELL)) { + printk("Loop is disabled. Use the `sensor` command to test %s", dev->name); + return 0; + } + + setpoint.val1 = range.val1; + while (1) { + rc = sensor_attr_set(dev, SENSOR_CHAN_PRESS, + (enum sensor_attribute)SENSOR_ATTR_VEAA_X_3_SETPOINT, + &setpoint); + if (rc != 0) { + printk("Set setpoint to %u failed: %d\n", setpoint.val1, rc); + } + + /* Sleep before get to allow DAC and ADC to stabilize */ + k_msleep(CONFIG_SAMPLE_LOOP_INTERVAL); + + rc = sensor_sample_fetch(dev); + if (rc != 0) { + printk("Fetch sample failed: %d", rc); + } + + rc = sensor_channel_get(dev, SENSOR_CHAN_PRESS, &pressure); + if (rc != 0) { + printk("Get sample failed: %d", rc); + } + + printk("Setpoint: %4u kPa, actual: %4u kPa\n", setpoint.val1, pressure.val1); + + setpoint.val1 += CONFIG_SAMPLE_LOOP_INCREMENT; + if (setpoint.val1 > range.val2) { + setpoint.val1 = range.val1; + } + } + + return 0; +} diff --git a/samples/shields/npm6001_ek/prj.conf b/samples/shields/npm6001_ek/prj.conf index 94da7cfdaef63..b0292200688e7 100644 --- a/samples/shields/npm6001_ek/prj.conf +++ b/samples/shields/npm6001_ek/prj.conf @@ -3,7 +3,7 @@ CONFIG_SHELL=y CONFIG_SHELL_GETOPT=y -CONFIG_GETOPT=y +CONFIG_POSIX_C_LIB_EXT=y CONFIG_GETOPT_LONG=y CONFIG_GPIO=y CONFIG_REGULATOR=y diff --git a/samples/subsys/dap/CMakeLists.txt b/samples/subsys/dap/CMakeLists.txt new file mode 100644 index 0000000000000..72ea1953b3c18 --- /dev/null +++ b/samples/subsys/dap/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(dap) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/dap/README.rst b/samples/subsys/dap/README.rst new file mode 100644 index 0000000000000..dcecb9440b515 --- /dev/null +++ b/samples/subsys/dap/README.rst @@ -0,0 +1,57 @@ +.. _dap-sample: + +DAP Sample Application +###################### + +Overview +******** + +This sample app demonstrates use of a SWDP interface driver and CMSIS DAP +controller through USB Bulk interface. + +Requirements +************ + +This sample supports multiple hardware configurations: + +The simplest configuration would be to connect `SWDIO` to `dio`, `SWDCLK` to `clk` +and optionally `nRESET` to `reset`. The optional `noe` pin is used to enable the port, +e.g. if the SWD connections are multiplexed. + +Building and Running +******************** + +In order for our debug adapter to be recognized by pyOCD we need to change +Zephyr's VID/PID to IDs known to pyOCD, this is up to the user. +The following commands build and flash DAP sample. + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/dap + :board: nrf52840dk_nrf52840 + :goals: flash + :compact: + +Connect HIC to the target and try some pyOCD commands, for example: + +.. code-block:: console + + pyocd commander -t nrf52840 + + 0029527 W Board ID FE5D is not recognized [mbed_board] + Connected to NRF52840 [Sleeping]: FE5D244DFE1F33DB + pyocd> read32 0x20004f18 32 + 20004f18: 20001160 2000244c 00000000 0000e407 | ..` .$L........| + 20004f28: ffffffff ffffffff 00000000 aaaaaaaa |................| + pyocd> halt + Successfully halted device + pyocd> reg + general registers: + lr: 0x00009cdd r7: 0x00000000 (0) + pc: 0x000033ca r8: 0x00000000 (0) + r0: 0x00000000 (0) r9: 0x00000000 (0) + r1: 0x20002854 (536881236) r10: 0x00000000 (0) + r2: 0x20000be4 (536873956) r11: 0x00000000 (0) + r3: 0x00000000 (0) r12: 0x00000000 (0) + r4: 0x200017e8 (536877032) sp: 0x20002898 + r5: 0x20001867 (536877159) xpsr: 0x61000000 (1627389952) + r6: 0x00000000 (0) diff --git a/samples/subsys/dap/app.overlay b/samples/subsys/dap/app.overlay new file mode 100644 index 0000000000000..a0ab85fccd6d8 --- /dev/null +++ b/samples/subsys/dap/app.overlay @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + dp0 { + compatible = "zephyr,swdp-gpio"; + status = "okay"; + + clk-gpios = <&arduino_header 10 GPIO_ACTIVE_HIGH>; /* D4 */ + noe-gpios = <&arduino_header 9 GPIO_ACTIVE_HIGH>; /* D3 */ + dio-gpios = <&arduino_header 8 GPIO_PULL_UP>; /* D2 */ + port-write-cycles = <2>; + }; +}; diff --git a/samples/subsys/dap/boards/nrf52840dk_nrf52840.overlay b/samples/subsys/dap/boards/nrf52840dk_nrf52840.overlay new file mode 100644 index 0000000000000..82438d36d9211 --- /dev/null +++ b/samples/subsys/dap/boards/nrf52840dk_nrf52840.overlay @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + dp0 { + compatible = "zephyr,swdp-gpio"; + status = "okay"; + clk-gpios = <&arduino_header 10 GPIO_ACTIVE_HIGH>; /* D4 */ + dio-gpios = <&arduino_header 8 GPIO_PULL_UP>; /* D2 */ + dout-gpios = <&arduino_header 9 GPIO_ACTIVE_HIGH>; /* D3 */ + dnoe-gpios = <&arduino_header 12 GPIO_ACTIVE_HIGH>; /* D6 */ + noe-gpios = <&arduino_header 11 GPIO_ACTIVE_HIGH>; /* D5 */ + reset-gpios = <&arduino_header 13 GPIO_ACTIVE_HIGH>; /* D7 */ + port-write-cycles = <2>; + }; +}; diff --git a/samples/subsys/dap/prj.conf b/samples/subsys/dap/prj.conf new file mode 100644 index 0000000000000..85e26acafa9fc --- /dev/null +++ b/samples/subsys/dap/prj.conf @@ -0,0 +1,19 @@ +CONFIG_STDOUT_CONSOLE=y +CONFIG_USB_DEVICE_STACK=y +CONFIG_USB_DEVICE_BOS=y +CONFIG_SERIAL=y +CONFIG_USB_DEVICE_PRODUCT="Zephyr CMSIS-DAP" +CONFIG_USB_DEVICE_PID=0x0204 +CONFIG_UART_INTERRUPT_DRIVEN=y +CONFIG_UART_LINE_CTRL=y +CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n + +CONFIG_LOG=y + +CONFIG_USB_DRIVER_LOG_LEVEL_INF=y +CONFIG_USB_DEVICE_LOG_LEVEL_INF=y +CONFIG_DAP_LOG_LEVEL_INF=y +CONFIG_DP_DRIVER_LOG_LEVEL_INF=y +CONFIG_DAP=y +CONFIG_GPIO=y +CONFIG_NET_BUF=y diff --git a/samples/subsys/dap/sample.yaml b/samples/subsys/dap/sample.yaml new file mode 100644 index 0000000000000..65264fa242943 --- /dev/null +++ b/samples/subsys/dap/sample.yaml @@ -0,0 +1,16 @@ +sample: + name: DAP USB +tests: + sample.dap.bulk: + build_only: true + depends_on: arduino_gpio usb_device + platform_allow: + - nrf52840dk/nrf52840 + - frdm_k64f + tags: dap + sample.dap.bulk.nrf: + build_only: true + depends_on: gpio usb_device + platform_allow: + - nrf52840dk/nrf52840 + tags: dap diff --git a/samples/subsys/dap/src/main.c b/samples/subsys/dap/src/main.c new file mode 100644 index 0000000000000..d680f89a23330 --- /dev/null +++ b/samples/subsys/dap/src/main.c @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(dap_sample, LOG_LEVEL_INF); + +NET_BUF_POOL_FIXED_DEFINE(dapusb_rx_pool, CONFIG_CMSIS_DAP_PACKET_COUNT, + CONFIG_CMSIS_DAP_PACKET_SIZE, 0, NULL); + +static uint8_t rx_buf[CONFIG_CMSIS_DAP_PACKET_SIZE]; +static uint8_t tx_buf[CONFIG_CMSIS_DAP_PACKET_SIZE]; + +static K_FIFO_DEFINE(dap_rx_queue); + +#define DAP_IFACE_STR_DESC "CMSIS-DAP v2" + +struct dap_iface_descriptor { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bString[USB_BSTRING_LENGTH(DAP_IFACE_STR_DESC)]; +} __packed; + +USBD_STRING_DESCR_USER_DEFINE(primary) struct dap_iface_descriptor dap_iface_desc = { + .bLength = USB_STRING_DESCRIPTOR_LENGTH(DAP_IFACE_STR_DESC), + .bDescriptorType = USB_DESC_STRING, + .bString = DAP_IFACE_STR_DESC +}; + +#define DAP_USB_EP_IN 0x81 +#define DAP_USB_EP_OUT 0x01 +#define DAP_USB_EP_IN_IDX 0 +#define DAP_USB_EP_OUT_IDX 1 + +#define WEBUSB_VENDOR_CODE 0x21 +#define WINUSB_VENDOR_CODE 0x20 + +/* {CDB3B5AD-293B-4663-AA36-1AAE46463776} */ +#define CMSIS_DAP_V2_DEVICE_INTERFACE_GUID \ + '{', 0x00, 'C', 0x00, 'D', 0x00, 'B', 0x00, '3', 0x00, 'B', 0x00, \ + '5', 0x00, 'A', 0x00, 'D', 0x00, '-', 0x00, '2', 0x00, '9', 0x00, \ + '3', 0x00, 'B', 0x00, '-', 0x00, '4', 0x00, '6', 0x00, '6', 0x00, \ + '3', 0x00, '-', 0x00, 'A', 0x00, 'A', 0x00, '3', 0x00, '6', 0x00, \ + '-', 0x00, '1', 0x00, 'A', 0x00, 'A', 0x00, 'E', 0x00, '4', 0x00, \ + '6', 0x00, '4', 0x00, '6', 0x00, '3', 0x00, '7', 0x00, '7', 0x00, \ + '6', 0x00, '}', 0x00, 0x00, 0x00, 0x00, 0x00 + +#define COMPATIBLE_ID_WINUSB \ + 'W', 'I', 'N', 'U', 'S', 'B', 0x00, 0x00 + +static struct msosv2_descriptor { + struct msosv2_descriptor_set_header header; +#if defined(CONFIG_USB_COMPOSITE_DEVICE) + struct msosv2_function_subset_header subset_header; +#endif + struct msosv2_compatible_id compatible_id; + struct msosv2_guids_property guids_property; +} __packed msosv2_cmsis_dap_desc = { + /* + * Microsoft OS 2.0 descriptor set. This tells Windows what kind + * of device this is and to install the WinUSB driver. + */ + .header = { + .wLength = sizeof(struct msosv2_descriptor_set_header), + .wDescriptorType = MS_OS_20_SET_HEADER_DESCRIPTOR, + .dwWindowsVersion = 0x06030000, + .wTotalLength = sizeof(struct msosv2_descriptor), + }, +#if defined(CONFIG_USB_COMPOSITE_DEVICE) + .subset_header = { + .wLength = sizeof(struct msosv2_function_subset_header), + .wDescriptorType = MS_OS_20_SUBSET_HEADER_FUNCTION, + .wSubsetLength = sizeof(struct msosv2_function_subset_header) + + sizeof(struct msosv2_compatible_id) + + sizeof(struct msosv2_guids_property), + }, +#endif + .compatible_id = { + .wLength = sizeof(struct msosv2_compatible_id), + .wDescriptorType = MS_OS_20_FEATURE_COMPATIBLE_ID, + .CompatibleID = {COMPATIBLE_ID_WINUSB}, + }, + .guids_property = { + .wLength = sizeof(struct msosv2_guids_property), + .wDescriptorType = MS_OS_20_FEATURE_REG_PROPERTY, + .wPropertyDataType = MS_OS_20_PROPERTY_DATA_REG_MULTI_SZ, + .wPropertyNameLength = 42, + .PropertyName = {DEVICE_INTERFACE_GUIDS_PROPERTY_NAME}, + .wPropertyDataLength = 80, + .bPropertyData = {CMSIS_DAP_V2_DEVICE_INTERFACE_GUID}, + }, +}; + +USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_msosv2_desc { + struct usb_bos_platform_descriptor platform; + struct usb_bos_capability_msos cap; +} __packed bos_cap_msosv2 = { + /* Microsoft OS 2.0 Platform Capability Descriptor */ + .platform = { + .bLength = sizeof(struct usb_bos_platform_descriptor) + + sizeof(struct usb_bos_capability_msos), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, + .bReserved = 0, + .PlatformCapabilityUUID = { + /** + * MS OS 2.0 Platform Capability ID + * D8DD60DF-4589-4CC7-9CD2-659D9E648A9F + */ + 0xDF, 0x60, 0xDD, 0xD8, + 0x89, 0x45, + 0xC7, 0x4C, + 0x9C, 0xD2, + 0x65, 0x9D, 0x9E, 0x64, 0x8A, 0x9F, + }, + }, + .cap = { + /* Windows version (8.1) (0x06030000) */ + .dwWindowsVersion = sys_cpu_to_le32(0x06030000), + .wMSOSDescriptorSetTotalLength = + sys_cpu_to_le16(sizeof(msosv2_cmsis_dap_desc)), + .bMS_VendorCode = WINUSB_VENDOR_CODE, + .bAltEnumCode = 0x00 + }, +}; + +USB_DEVICE_BOS_DESC_DEFINE_CAP struct usb_bos_webusb_desc { + struct usb_bos_platform_descriptor platform; + struct usb_bos_capability_webusb cap; +} __packed bos_cap_webusb = { + /* WebUSB Platform Capability Descriptor: + * https://wicg.github.io/webusb/#webusb-platform-capability-descriptor + */ + .platform = { + .bLength = sizeof(struct usb_bos_platform_descriptor) + + sizeof(struct usb_bos_capability_webusb), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_PLATFORM, + .bReserved = 0, + /* WebUSB Platform Capability UUID + * 3408b638-09a9-47a0-8bfd-a0768815b665 + */ + .PlatformCapabilityUUID = { + 0x38, 0xB6, 0x08, 0x34, + 0xA9, 0x09, + 0xA0, 0x47, + 0x8B, 0xFD, + 0xA0, 0x76, 0x88, 0x15, 0xB6, 0x65, + }, + }, + .cap = { + .bcdVersion = sys_cpu_to_le16(0x0100), + .bVendorCode = WEBUSB_VENDOR_CODE, + .iLandingPage = 0x01 + } +}; + +/* URL Descriptor: https://wicg.github.io/webusb/#url-descriptor */ +static const uint8_t webusb_origin_url[] = { + /* Length, DescriptorType, Scheme */ + 24, 0x03, 0x01, + 'w', 'w', 'w', '.', + 'z', 'e', 'p', 'h', 'y', 'r', 'p', 'r', 'o', 'j', 'e', 'c', 't', '.', + 'o', 'r', 'g', '/', +}; + +static int msosv2_vendor_handle_req(struct usb_setup_packet *setup, + int32_t *len, uint8_t **data) +{ + if (usb_reqtype_is_to_device(setup)) { + return -ENOTSUP; + } + + if (setup->bRequest == WEBUSB_VENDOR_CODE && setup->wIndex == 0x02) { + *data = (uint8_t *)(&webusb_origin_url); + *len = sizeof(webusb_origin_url); + + LOG_DBG("Get URL request"); + + return 0; + } + + if (setup->bRequest == WINUSB_VENDOR_CODE && + setup->wIndex == MS_OS_20_DESCRIPTOR_INDEX) { + *data = (uint8_t *)(&msosv2_cmsis_dap_desc); + *len = sizeof(msosv2_cmsis_dap_desc); + + LOG_DBG("Get MS OS Descriptors v2"); + + return 0; + } + + return -ENOTSUP; +} + +USBD_CLASS_DESCR_DEFINE(primary, 0) struct { + struct usb_if_descriptor if0; + struct usb_ep_descriptor if0_out_ep; + struct usb_ep_descriptor if0_in_ep; +} __packed dapusb_desc = { + .if0 = { + .bLength = sizeof(struct usb_if_descriptor), + .bDescriptorType = USB_DESC_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_BCC_VENDOR, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, + }, + .if0_out_ep = { + .bLength = sizeof(struct usb_ep_descriptor), + .bDescriptorType = USB_DESC_ENDPOINT, + .bEndpointAddress = DAP_USB_EP_OUT, + .bmAttributes = USB_DC_EP_BULK, + .wMaxPacketSize = sys_cpu_to_le16(CONFIG_CMSIS_DAP_PACKET_SIZE), + .bInterval = 0, + }, + .if0_in_ep = { + .bLength = sizeof(struct usb_ep_descriptor), + .bDescriptorType = USB_DESC_ENDPOINT, + .bEndpointAddress = DAP_USB_EP_IN, + .bmAttributes = USB_DC_EP_BULK, + .wMaxPacketSize = sys_cpu_to_le16(CONFIG_CMSIS_DAP_PACKET_SIZE), + .bInterval = 0, + }, +}; + +static struct usb_ep_cfg_data dapusb_ep_data[] = { + { + .ep_cb = usb_transfer_ep_callback, + .ep_addr = DAP_USB_EP_OUT + }, + { + .ep_cb = usb_transfer_ep_callback, + .ep_addr = DAP_USB_EP_IN + } +}; + +static void iface_string_desc_init(struct usb_cfg_data *bulk_cfg) +{ + struct usb_if_descriptor *bulk_if = bulk_cfg->interface_descriptor; + + bulk_if->iInterface = usb_get_str_descriptor_idx(&dap_iface_desc); +} + +static void dapusb_read_cb(uint8_t ep, int size, void *priv) +{ + struct usb_cfg_data *cfg = priv; + struct net_buf *buf; + + LOG_DBG("cfg %p ep %x size %u", cfg, ep, size); + + if (size <= 0) { + goto read_cb_done; + } + + buf = net_buf_alloc(&dapusb_rx_pool, K_FOREVER); + net_buf_add_mem(buf, rx_buf, MIN(size, CONFIG_CMSIS_DAP_PACKET_SIZE)); + k_fifo_put(&dap_rx_queue, buf); + +read_cb_done: + usb_transfer(ep, rx_buf, sizeof(rx_buf), USB_TRANS_READ, dapusb_read_cb, cfg); +} + +static void dapusb_dev_status_cb(struct usb_cfg_data *cfg, + enum usb_dc_status_code status, + const uint8_t *param) +{ + ARG_UNUSED(param); + + if (status == USB_DC_CONFIGURED) { + dapusb_read_cb(cfg->endpoint[DAP_USB_EP_IN_IDX].ep_addr, 0, cfg); + } +} + +static void dapusb_interface_config(struct usb_desc_header *head, + uint8_t bInterfaceNumber) +{ + ARG_UNUSED(head); + + dapusb_desc.if0.bInterfaceNumber = bInterfaceNumber; +#if defined(CONFIG_USB_COMPOSITE_DEVICE) + msosv2_cmsis_dap_desc.subset_header.bFirstInterface = bInterfaceNumber; +#endif +} + +USBD_DEFINE_CFG_DATA(dapusb_config) = { + .usb_device_description = NULL, + .interface_config = dapusb_interface_config, + .interface_descriptor = &dapusb_desc.if0, + .cb_usb_status = dapusb_dev_status_cb, + .interface = { + .class_handler = NULL, + .custom_handler = NULL, + .vendor_handler = msosv2_vendor_handle_req, + }, + .num_endpoints = ARRAY_SIZE(dapusb_ep_data), + .endpoint = dapusb_ep_data +}; + +static int dap_usb_process(void) +{ + uint8_t ep = dapusb_config.endpoint[DAP_USB_EP_OUT_IDX].ep_addr; + struct net_buf *buf; + size_t len; + int err; + + buf = k_fifo_get(&dap_rx_queue, K_FOREVER); + + len = dap_execute_cmd(buf->data, tx_buf); + LOG_DBG("response length %u, starting with [0x%02X, 0x%02X]", + len, tx_buf[0], tx_buf[1]); + net_buf_unref(buf); + + err = usb_transfer_sync(ep, tx_buf, len, USB_TRANS_WRITE | USB_TRANS_NO_ZLP); + if (err < 0 || err != len) { + LOG_ERR("usb_transfer_sync failed, %d", err); + return -EIO; + } + + return 0; +} + +int main(void) +{ + const struct device *const swd_dev = DEVICE_DT_GET_ONE(zephyr_swdp_gpio); + int ret; + + if (!device_is_ready(swd_dev)) { + LOG_ERR("SWD device is not ready"); + return -ENODEV; + } + + ret = dap_setup(swd_dev); + if (ret) { + LOG_ERR("Failed to initialize DAP controller, %d", ret); + return ret; + } + + /* Add MS OS 2.0 BOS descriptor to BOS structure */ + usb_bos_register_cap((void *)&bos_cap_msosv2); + /* Point interface index to string descriptor */ + iface_string_desc_init(&dapusb_config); + + ret = usb_enable(NULL); + if (ret != 0) { + LOG_ERR("Failed to enable USB"); + return 0; + } + + while (!dap_usb_process()) { + } + + return usb_disable(); +} diff --git a/samples/subsys/display/lvgl/sample.yaml b/samples/subsys/display/lvgl/sample.yaml index d8bfb5de9b54b..94b26bc108703 100644 --- a/samples/subsys/display/lvgl/sample.yaml +++ b/samples/subsys/display/lvgl/sample.yaml @@ -70,3 +70,25 @@ tests: - shield - lvgl - gui + samples.subsys.display.lvgl.rk043fn66hs_ctg: + platform_allow: + - mimxrt1064_evk + - mimxrt1060_evk + - mimxrt1050_evk + - mimxrt1040_evk + tags: display + harness: console + extra_args: SHIELD=rk043fn66hs_ctg + harness_config: + fixture: fixture_display + samples.subsys.display.lvgl.rk043fn02h_ct: + platform_allow: + - mimxrt1064_evk + - mimxrt1060_evk + - mimxrt1050_evk + - mimxrt1040_evk + tags: display + harness: console + extra_args: SHIELD=rk043fn02h_ct + harness_config: + fixture: fixture_display diff --git a/samples/subsys/fs/format/README.rst b/samples/subsys/fs/format/README.rst index fdcc575ec00be..665c024cbdf38 100644 --- a/samples/subsys/fs/format/README.rst +++ b/samples/subsys/fs/format/README.rst @@ -10,6 +10,7 @@ Overview This sample shows how to format different storage devices for different file systems. There are 2 scenarios prepared for this sample: + * littleFS on flash device * FAT file system on RAM disk diff --git a/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf new file mode 100644 index 0000000000000..949237fd4bafd --- /dev/null +++ b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.conf @@ -0,0 +1,12 @@ +# +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +CONFIG_DISK_DRIVERS=y +CONFIG_DISK_DRIVER_FLASH=y +# There may be no files on internal SoC flash, so this Kconfig +# options has ben enabled to create some if listing does not +# find in the first place. +CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES=y diff --git a/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay new file mode 100644 index 0000000000000..391afea75a404 --- /dev/null +++ b/samples/subsys/fs/fs_sample/boards/nrf54l15pdk_nrf54l15_cpuapp.overlay @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Because FAT FS needs at least 64kiB partition and default + * storage_partition is 36kiB for this board, we need to reorganize + * partitions to get at least 64KiB. + */ +/delete-node/ &slot0_partition; +/delete-node/ &slot1_partition; +/delete-node/ &slot0_ns_partition; +/delete-node/ &slot1_ns_partition; +/delete-node/ &storage_partition; + +&cpuapp_rram { + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + slot0_partition: parition@10000 { + reg = <0x00010000 DT_SIZE_K(300)>; + }; + slot1_partition: partition@5b000 { + reg = <0x0005b000 DT_SIZE_K(300)>; + }; + + storage_partition: partition@a6000 { + label = "storage"; + reg = <0x000a6000 DT_SIZE_K(128)>; + }; + }; +}; + +/ { + msc_disk0 { + status="okay"; + compatible = "zephyr,flash-disk"; + partition = <&storage_partition>; + disk-name = "SD"; + cache-size = <512>; + }; +}; diff --git a/samples/subsys/fs/fs_sample/sample.yaml b/samples/subsys/fs/fs_sample/sample.yaml index 55dc3d8677a08..8041ffb84c45e 100644 --- a/samples/subsys/fs/fs_sample/sample.yaml +++ b/samples/subsys/fs/fs_sample/sample.yaml @@ -43,6 +43,9 @@ tests: extra_args: - OVERLAY_CONFIG=boards/nrf52840dk_nrf52840_ram_disk.conf - DTC_OVERLAY_FILE=boards/nrf52840dk_nrf52840_ram_disk_region.overlay + sample.filesystem.fat_fs.nrf54l15pdk: + build_only: true + platform_allow: nrf54l15pdk/nrf54l15/cpuapp sample.filesystem.fat_fs.nrf52840dk_nrf52840.qspi: build_only: true platform_allow: nrf52840dk/nrf52840 diff --git a/samples/subsys/fs/fs_sample/src/main.c b/samples/subsys/fs/fs_sample/src/main.c index 52c74cc74b1d8..01d935d7e1b50 100644 --- a/samples/subsys/fs/fs_sample/src/main.c +++ b/samples/subsys/fs/fs_sample/src/main.c @@ -48,6 +48,12 @@ static struct fs_mount_t mp = { #endif +#if defined(CONFIG_FAT_FILESYSTEM_ELM) +#define FS_RET_OK FR_OK +#else +#define FS_RET_OK 0 +#endif + LOG_MODULE_REGISTER(main); #define MAX_PATH 128 @@ -107,7 +113,8 @@ int main(void) uint32_t block_count; uint32_t block_size; - if (disk_access_init(disk_pdrv) != 0) { + if (disk_access_ioctl(disk_pdrv, + DISK_IOCTL_CTRL_INIT, NULL) != 0) { LOG_ERR("Storage init ERROR!"); break; } @@ -128,18 +135,32 @@ int main(void) memory_size_mb = (uint64_t)block_count * block_size; printk("Memory Size(MB) %u\n", (uint32_t)(memory_size_mb >> 20)); + + if (disk_access_ioctl(disk_pdrv, + DISK_IOCTL_CTRL_DEINIT, NULL) != 0) { + LOG_ERR("Storage deinit ERROR!"); + break; + } } while (0); mp.mnt_point = disk_mount_pt; int res = fs_mount(&mp); -#if defined(CONFIG_FAT_FILESYSTEM_ELM) - if (res == FR_OK) { -#else - if (res == 0) { -#endif + if (res == FS_RET_OK) { printk("Disk mounted.\n"); + /* Try to unmount and remount the disk */ + res = fs_unmount(&mp); + if (res != FS_RET_OK) { + printk("Error unmounting disk\n"); + return res; + } + res = fs_mount(&mp); + if (res != FS_RET_OK) { + printk("Error remounting disk\n"); + return res; + } + if (lsdir(disk_mount_pt) == 0) { #ifdef CONFIG_FS_SAMPLE_CREATE_SOME_ENTRIES if (create_some_entries(disk_mount_pt)) { diff --git a/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf b/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf deleted file mode 100644 index f2dffe4fe097a..0000000000000 --- a/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57.conf +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2023 EPAM Systems -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_MAIN_STACK_SIZE=4096 -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 -CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 - -CONFIG_DISK_ACCESS=y -CONFIG_DISK_DRIVERS=y -CONFIG_DISK_DRIVER_MMC=y - -CONFIG_FS_LITTLEFS_BLK_DEV=y -CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC=y - -CONFIG_FS_LITTLEFS_FMP_DEV=n diff --git a/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57_blk.conf b/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57_blk.conf new file mode 100644 index 0000000000000..6b4b57ac2a0bb --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/rcar_h3ulcb_r8a77951_a57_blk.conf @@ -0,0 +1,11 @@ +# +# Copyright (c) 2023 EPAM Systems +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 +CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 + +CONFIG_DISK_DRIVER_MMC=y +CONFIG_DISK_DRIVER_SDMMC=n diff --git a/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf b/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf deleted file mode 100644 index f2dffe4fe097a..0000000000000 --- a/samples/subsys/fs/littlefs/boards/rcar_salvator_xs.conf +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2023 EPAM Systems -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_MAIN_STACK_SIZE=4096 -CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 -CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 - -CONFIG_DISK_ACCESS=y -CONFIG_DISK_DRIVERS=y -CONFIG_DISK_DRIVER_MMC=y - -CONFIG_FS_LITTLEFS_BLK_DEV=y -CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC=y - -CONFIG_FS_LITTLEFS_FMP_DEV=n diff --git a/samples/subsys/fs/littlefs/boards/rcar_salvator_xs_blk.conf b/samples/subsys/fs/littlefs/boards/rcar_salvator_xs_blk.conf new file mode 100644 index 0000000000000..6b4b57ac2a0bb --- /dev/null +++ b/samples/subsys/fs/littlefs/boards/rcar_salvator_xs_blk.conf @@ -0,0 +1,11 @@ +# +# Copyright (c) 2023 EPAM Systems +# +# SPDX-License-Identifier: Apache-2.0 +# +CONFIG_MAIN_STACK_SIZE=4096 +CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=8192 +CONFIG_FS_LITTLEFS_FC_HEAP_SIZE=8192 + +CONFIG_DISK_DRIVER_MMC=y +CONFIG_DISK_DRIVER_SDMMC=n diff --git a/samples/subsys/fs/littlefs/prj_blk.conf b/samples/subsys/fs/littlefs/prj_blk.conf index 011f919a56808..b18b8cfe36262 100644 --- a/samples/subsys/fs/littlefs/prj_blk.conf +++ b/samples/subsys/fs/littlefs/prj_blk.conf @@ -16,6 +16,7 @@ CONFIG_FILE_SYSTEM=y CONFIG_FILE_SYSTEM_LITTLEFS=y CONFIG_FS_LITTLEFS_BLK_DEV=y +CONFIG_FS_LITTLEFS_FMP_DEV=n CONFIG_APP_LITTLEFS_STORAGE_BLK_SDMMC=y CONFIG_NOCACHE_MEMORY=y diff --git a/samples/subsys/fs/littlefs/sample.yaml b/samples/subsys/fs/littlefs/sample.yaml index 89ffe9f16ae8d..67231c5cfbdff 100644 --- a/samples/subsys/fs/littlefs/sample.yaml +++ b/samples/subsys/fs/littlefs/sample.yaml @@ -20,14 +20,20 @@ tests: - mimxrt1160_evk/mimxrt1166/cm7 - lpcxpresso55s69/lpc55s69/cpu0 - mr_canhubk3 - - rcar_h3ulcb/r8a77951/a57 - - rcar_salvator_xs - stm32f429i_disc1 - stm32f746g_disco - stm32h747i_disco/stm32h747xx/m7 - stm32h750b_dk + - nrf54l15pdk/nrf54l15/cpuapp integration_platforms: - nrf52840dk/nrf52840 + sample.filesystem.littlefs.blk: + build_only: true + extra_args: + - CONF_FILE=prj_blk.conf + platform_allow: + - rcar_h3ulcb/r8a77951/a57 + - rcar_salvator_xs sample.filesystem.littlefs.nrf52840dk_spi: build_only: true platform_allow: nrf52840dk/nrf52840 diff --git a/samples/subsys/fs/littlefs/src/main.c b/samples/subsys/fs/littlefs/src/main.c index 35fe1d2b3057b..7723023013eb7 100644 --- a/samples/subsys/fs/littlefs/src/main.c +++ b/samples/subsys/fs/littlefs/src/main.c @@ -252,7 +252,7 @@ static int littlefs_flash_erase(unsigned int id) /* Optional wipe flash contents */ if (IS_ENABLED(CONFIG_APP_WIPE_STORAGE)) { - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); LOG_ERR("Erasing flash area ... %d", rc); } diff --git a/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt b/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt index ca0ce8a8cff85..43effdcf6ff5e 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt +++ b/samples/subsys/ipc/ipc_service/icmsg/CMakeLists.txt @@ -8,7 +8,8 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -if(NOT CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP) +if(NOT CONFIG_BOARD_NRF5340DK_NRF5340_CPUAPP AND + NOT CONFIG_BOARD_STM32H747I_DISCO) message(FATAL_ERROR "${BOARD} is not supported for this sample") endif() diff --git a/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild b/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild index d0849e37ddef1..2de1b5072e1c3 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild +++ b/samples/subsys/ipc/ipc_service/icmsg/Kconfig.sysbuild @@ -4,6 +4,7 @@ source "share/sysbuild/Kconfig" -config NET_CORE_BOARD +config REMOTE_BOARD string default "nrf5340dk/nrf5340/cpunet" if $(BOARD) = "nrf5340dk" + default "stm32h747i_disco/stm32h747xx/m4" if $(BOARD) = "stm32h747i_disco" diff --git a/samples/subsys/ipc/ipc_service/icmsg/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/subsys/ipc/ipc_service/icmsg/boards/nrf5340dk_nrf5340_cpuapp.overlay index 22650211611f0..f782bdd85784c 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/samples/subsys/ipc/ipc_service/icmsg/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -31,6 +31,11 @@ mboxes = <&mbox 0>, <&mbox 1>; mbox-names = "tx", "rx"; status = "okay"; + + bt_hci_ipc0: bt_hci_ipc0 { + compatible = "zephyr,bt-hci-ipc"; + status = "okay"; + }; }; }; }; diff --git a/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.conf b/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.conf new file mode 100644 index 0000000000000..acba758575a87 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.conf @@ -0,0 +1 @@ +CONFIG_MBOX_STM32_HSEM=y diff --git a/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.overlay b/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.overlay new file mode 100644 index 0000000000000..52a2facb9bf3a --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/boards/stm32h747i_disco_stm32h747xx_m7.overlay @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /delete-property/ zephyr,ipc_shm; + }; + + /* Define new memory regions for TX and RX */ + /delete-node/ memory@38000000; + + sram_tx: memory@38000000 { + zephyr,memory-region = "SRAM_TX"; + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x38000000 0x08000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + + sram_rx: memory@38008000 { + zephyr,memory-region = "SRAM_RX"; + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x38008000 0x08000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + + ipc0: ipc0 { + compatible = "zephyr,ipc-icmsg"; + tx-region = <&sram_tx>; + rx-region = <&sram_rx>; + mboxes = <&mailbox 11>, <&mailbox 10>; + mbox-names = "tx", "rx"; + status = "okay"; + }; +}; + +&mailbox { + status = "okay"; +}; diff --git a/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf b/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf new file mode 100644 index 0000000000000..110236f8fbde8 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.conf @@ -0,0 +1,5 @@ +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_LOG_BACKEND_UART=y + +CONFIG_MBOX_STM32_HSEM=y diff --git a/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay b/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay new file mode 100644 index 0000000000000..4b8d6f59f4f53 --- /dev/null +++ b/samples/subsys/ipc/ipc_service/icmsg/remote/boards/stm32h747i_disco_stm32h747xx_m4.overlay @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2024 Celina Sophie Kalus + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + chosen { + /delete-property/ zephyr,ipc_shm; + + zephyr,console = &uart8; + zephyr,shell-uart = &uart8; + }; + + /* Define new memory regions for TX and RX */ + /delete-node/ memory@38000000; + + sram_rx: memory@38000000 { + zephyr,memory-region = "SRAM_RX"; + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x38000000 0x08000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + + sram_tx: memory@38008000 { + zephyr,memory-region = "SRAM_TX"; + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x38008000 0x08000>; + zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_RAM_NOCACHE) )>; + }; + + ipc0: ipc0 { + compatible = "zephyr,ipc-icmsg"; + tx-region = <&sram_tx>; + rx-region = <&sram_rx>; + mboxes = <&mailbox 10>, <&mailbox 11>; + mbox-names = "tx", "rx"; + status = "okay"; + }; +}; + +&uart8 { + status = "okay"; +}; + +&mailbox { + status = "okay"; +}; diff --git a/samples/subsys/ipc/ipc_service/icmsg/sample.yaml b/samples/subsys/ipc/ipc_service/icmsg/sample.yaml index af1f172d7097c..ee24fc1aec1b4 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/sample.yaml +++ b/samples/subsys/ipc/ipc_service/icmsg/sample.yaml @@ -7,4 +7,14 @@ tests: - nrf5340dk/nrf5340/cpuapp tags: ipc sysbuild: true - harness: remote + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - "host: IPC-service HOST demo started" + - "host: Ep bounded" + - "host: Perform sends for" + - "host: Sent" + - "host: Received" + - "host: IPC-service HOST demo ended" diff --git a/samples/subsys/ipc/ipc_service/icmsg/src/main.c b/samples/subsys/ipc/ipc_service/icmsg/src/main.c index d10fa6c8bf6bb..d3a7e695b9125 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/src/main.c +++ b/samples/subsys/ipc/ipc_service/icmsg/src/main.c @@ -8,7 +8,9 @@ #include #include +#if CONFIG_NET_CORE_BOARD #include +#endif /* CONFIG_NET_CORE_BOARD */ #include #include "common.h" @@ -21,8 +23,12 @@ K_SEM_DEFINE(bound_sem, 0, 1); static unsigned char expected_message = 'A'; static size_t expected_len = PACKET_SIZE_START; +static size_t received; + static void ep_bound(void *priv) { + received = 0; + k_sem_give(&bound_sem); LOG_INF("Ep bounded"); } @@ -36,6 +42,7 @@ static void ep_recv(const void *data, size_t len, void *priv) __ASSERT(len == expected_len, "Unexpected length. Expected %zu, got %zu", expected_len, len); + received += len; expected_message++; expected_len++; @@ -63,6 +70,7 @@ static int send_for_time(struct ipc_ept *ep, const int64_t sending_time_ms) ret = ipc_service_send(ep, &msg, mlen); if (ret == -ENOMEM) { /* No space in the buffer. Retry. */ + ret = 0; continue; } else if (ret < 0) { LOG_ERR("Failed to send (%c) failed with ret %d", msg.data[0], ret); @@ -129,6 +137,9 @@ int main(void) LOG_INF("Wait 500ms. Let net core finish its sends"); k_msleep(500); + LOG_INF("Received %zu [Bytes] in total", received); + +#if CONFIG_NET_CORE_BOARD LOG_INF("Stop network core"); nrf53_cpunet_enable(false); @@ -167,6 +178,7 @@ int main(void) LOG_ERR("send_for_time() failure"); return ret; } +#endif /* CONFIG_NET_CORE_BOARD */ LOG_INF("IPC-service HOST demo ended"); diff --git a/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake index d0d79b8f24084..b1f0947aff7c4 100644 --- a/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake +++ b/samples/subsys/ipc/ipc_service/icmsg/sysbuild.cmake @@ -1,7 +1,7 @@ # Copyright (c) 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 -if("${SB_CONFIG_NET_CORE_BOARD}" STREQUAL "") +if ("${SB_CONFIG_REMOTE_BOARD}" STREQUAL "") message(FATAL_ERROR "Target ${BOARD} not supported for this sample. " "There is no remote board selected in Kconfig.sysbuild") @@ -10,5 +10,5 @@ endif() ExternalZephyrProject_Add( APPLICATION remote SOURCE_DIR ${APP_DIR}/remote - BOARD ${SB_CONFIG_NET_CORE_BOARD} + BOARD ${SB_CONFIG_REMOTE_BOARD} ) diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp.overlay index 35cffd8ad350b..216561b349be0 100644 --- a/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -39,6 +39,11 @@ mboxes = <&mbox 0>, <&mbox 1>; mbox-names = "tx", "rx"; status = "okay"; + + bt_hci_ipc0: bt_hci_ipc0 { + compatible = "zephyr,bt-hci-ipc"; + status = "okay"; + }; }; ipc1: ipc1 { diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay b/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay index 3db9db032f4c4..2d85fbbf79c1b 100644 --- a/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/boards/nrf5340dk_nrf5340_cpuapp_icbmsg.overlay @@ -41,6 +41,11 @@ mboxes = <&mbox 0>, <&mbox 1>; mbox-names = "tx", "rx"; status = "okay"; + + bt_hci_ipc0: bt_hci_ipc0 { + compatible = "zephyr,bt-hci-ipc"; + status = "okay"; + }; }; ipc1: ipc1 { diff --git a/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml b/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml index 401bbf517357f..b05c8f001f2c9 100644 --- a/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml +++ b/samples/subsys/ipc/ipc_service/multi_endpoint/sample.yaml @@ -1,5 +1,17 @@ sample: name: IPC Service example integration (icmsg multi endpoint backend) +common: + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - "IPC-service HOST \\[INST 0 - ENDP A\\] demo started" + - "IPC-service HOST \\[INST 0 - ENDP B\\] demo started" + - "IPC-service HOST \\[INST 1\\] demo started" + - "IPC-service HOST \\[INST 0 - ENDP A\\] demo ended\\." + - "IPC-service HOST \\[INST 0 - ENDP B\\] demo ended\\." + - "IPC-service HOST \\[INST 1\\] demo ended\\." tests: sample.ipc.multi_endpoint: platform_allow: nrf5340dk/nrf5340/cpuapp @@ -7,7 +19,6 @@ tests: - nrf5340dk/nrf5340/cpuapp tags: ipc sysbuild: true - harness: remote sample.ipc.multi_endpoint.icbmsg: platform_allow: nrf5340dk/nrf5340/cpuapp integration_platforms: diff --git a/samples/subsys/ipc/ipc_service/static_vrings/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/subsys/ipc/ipc_service/static_vrings/boards/nrf5340dk_nrf5340_cpuapp.overlay index 520f007a82179..f07f75fc9a1a7 100644 --- a/samples/subsys/ipc/ipc_service/static_vrings/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/samples/subsys/ipc/ipc_service/static_vrings/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -33,6 +33,11 @@ mbox-names = "tx", "rx"; role = "host"; status = "okay"; + + bt_hci_ipc0: bt_hci_ipc0 { + compatible = "zephyr,bt-hci-ipc"; + status = "okay"; + }; }; ipc1: ipc1 { diff --git a/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml b/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml index 0189185c83998..911b3624e44dc 100644 --- a/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml +++ b/samples/subsys/ipc/ipc_service/static_vrings/sample.yaml @@ -12,4 +12,14 @@ tests: - nrf5340dk/nrf5340/cpuapp tags: ipc sysbuild: true - harness: remote + harness: console + harness_config: + type: multi_line + ordered: false + regex: + - "IPC-service HOST \\[INST 0 - ENDP A\\] demo started" + - "IPC-service HOST \\[INST 0 - ENDP B\\] demo started" + - "IPC-service HOST \\[INST 1\\] demo started" + - "IPC-service HOST \\[INST 0 - ENDP A\\] demo ended\\." + - "IPC-service HOST \\[INST 0 - ENDP B\\] demo ended\\." + - "IPC-service HOST \\[INST 1\\] demo ended\\." diff --git a/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf b/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf deleted file mode 100644 index ae8dba8cc217f..0000000000000 --- a/samples/subsys/ipc/openamp/boards/mimxrt1170_evkb_cm7.conf +++ /dev/null @@ -1,7 +0,0 @@ -# -# Copyright 2023, NXP -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_INCLUDE_REMOTE_DIR=y -CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.conf b/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.conf deleted file mode 100644 index 4dfc4a60b76ac..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1160_evk_cm4.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_BUILD_OUTPUT_INFO_HEADER=y -CONFIG_BUILD_OUTPUT_HEX=y -CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.conf b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.conf deleted file mode 100644 index 4dfc4a60b76ac..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.conf +++ /dev/null @@ -1,3 +0,0 @@ -CONFIG_BUILD_OUTPUT_INFO_HEADER=y -CONFIG_BUILD_OUTPUT_HEX=y -CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay deleted file mode 100644 index 87159192cf249..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evk_cm4.overlay +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2022-2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -#include - -/ { - /* Switch to lpuart2, since primary core uses lpuart1 */ - chosen { - zephyr,flash = &ocram; - zephyr,console = &lpuart2; - zephyr,shell-uart = &lpuart2; - zephyr,ipc_shm = &ocram2_overlay; - }; - - soc { - /delete-node/ gpt@400f0000; - - /* Replace GPT2 with another GPT kernel timer */ - gpt2_hw_timer:gpt@400f0000 { - compatible = "nxp,gpt-hw-timer"; - reg = <0x400f0000 0x4000>; - interrupts = <120 0>; - status = "okay"; - }; - }; - - /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. - * Define a subset of the OCRAM2 region for demo to use - * Note that shared memory must have specific MPU attributes set - */ - ocram2_overlay: memory@202c0000 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x202c0000 DT_SIZE_K(16)>; - zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; - }; -}; - -/* Enable secondary LPUART */ -&lpuart2 { - status = "okay"; - current-speed = <115200>; -}; - -/* Disable primary GPT timer */ -&gpt_hw_timer { - status = "disabled"; -}; diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf deleted file mode 100644 index 7b43b448c72c2..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.conf +++ /dev/null @@ -1,8 +0,0 @@ -# -# Copyright 2023, NXP -# -# SPDX-License-Identifier: Apache-2.0 -# -CONFIG_BUILD_OUTPUT_INFO_HEADER=y -CONFIG_BUILD_OUTPUT_HEX=y -CONFIG_SECOND_CORE_MCUX=y diff --git a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay b/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay deleted file mode 100644 index 72510d261664a..0000000000000 --- a/samples/subsys/ipc/openamp/remote/boards/mimxrt1170_evkb_cm4.overlay +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2023 NXP - * - * SPDX-License-Identifier: Apache-2.0 - */ - -/ { - /* Switch to lpuart2, since primary core uses lpuart1 */ - chosen { - zephyr,flash = &ocram; - zephyr,console = &lpuart2; - zephyr,shell-uart = &lpuart2; - zephyr,ipc_shm = &ocram2_overlay; - }; - - soc { - /delete-node/ gpt@400f0000; - - /* Replace GPT2 with another GPT kernel timer */ - gpt2_hw_timer:gpt@400f0000 { - compatible = "nxp,gpt-hw-timer"; - reg = <0x400f0000 0x4000>; - interrupts = <120 0>; - status = "okay"; - }; - }; - - /* OpenAMP fails with full 512K OCRAM2 memory region as shared memory. - * Define a subset of the OCRAM2 region for demo to use - * Note that shared memory must have specific MPU attributes set - */ - ocram2_overlay: memory@202c0000 { - compatible = "zephyr,memory-region", "mmio-sram"; - reg = <0x202c0000 DT_SIZE_K(16)>; - zephyr,memory-region="OCRAM2_OVERLAY"; - zephyr,memory-attr = <( DT_MEM_ARM(ATTR_MPU_IO) )>; - }; -}; - -/* Enable secondary LPUART */ -&lpuart2 { - status = "okay"; - current-speed = <115200>; -}; - -/* Disable primary GPT timer */ -&gpt_hw_timer { - status = "disabled"; -}; diff --git a/samples/subsys/ipc/openamp_rsc_table/boards/colibri_imx7d_mcimx7d_m4.conf b/samples/subsys/ipc/openamp_rsc_table/boards/colibri_imx7d_mcimx7d_m4.conf new file mode 100644 index 0000000000000..8c960fc2dd342 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table/boards/colibri_imx7d_mcimx7d_m4.conf @@ -0,0 +1,12 @@ +CONFIG_IPM=y +CONFIG_IPM_IMX_MAX_DATA_SIZE_4=y +CONFIG_OPENAMP_WITH_DCACHE=y +CONFIG_PLATFORM_SPECIFIC_INIT=n +CONFIG_OPENAMP=y +CONFIG_OPENAMP_RSC_TABLE_NUM_RPMSG_BUFF=32 +CONFIG_OPENAMP_RSC_TABLE=y +CONFIG_OPENAMP_MASTER=n + + +CONFIG_ROMSTART_RELOCATION_ROM=y +CONFIG_BUILD_OUTPUT_BIN=n diff --git a/samples/subsys/ipc/openamp_rsc_table/boards/colibri_imx7d_mcimx7d_m4.overlay b/samples/subsys/ipc/openamp_rsc_table/boards/colibri_imx7d_mcimx7d_m4.overlay new file mode 100644 index 0000000000000..f55dd790c9503 --- /dev/null +++ b/samples/subsys/ipc/openamp_rsc_table/boards/colibri_imx7d_mcimx7d_m4.overlay @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024 MAKEEN Energy A/S + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* Follow the board's documentation to modify the Linux DT accordingly */ + +/ { + + chosen { + /* Use OCRAM 128kB because TCM 32kB is too small for the sample */ + zephyr,flash = &ocram_code; + zephyr,ipc_shm = &ddr_shm; + zephyr,ipc = &mub; + }; + + ddr_shm: memory1@90000000 { + compatible = "mmio-sram"; + /* use DDR_SYS area as mmio, 0x90000000 0x10000 */ + reg = <0x90000000 0x10000>; + status = "okay"; + }; +}; + +&mub { + status = "okay"; +}; diff --git a/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c b/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c index 8bc1a475d081b..c8d12092ace05 100644 --- a/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c +++ b/samples/subsys/ipc/openamp_rsc_table/src/main_remote.c @@ -53,6 +53,7 @@ static const struct device *const ipm_handle = DEVICE_DT_GET(DT_CHOSEN(zephyr_ipc)); static metal_phys_addr_t shm_physmap = SHM_START_ADDR; +static metal_phys_addr_t rsc_tab_physmap; static struct metal_io_region shm_io_data; /* shared memory */ static struct metal_io_region rsc_io_data; /* rsc_table memory */ @@ -67,7 +68,7 @@ static struct metal_io_region *shm_io = &shm_io_data; static struct metal_io_region *rsc_io = &rsc_io_data; static struct rpmsg_virtio_device rvdev; -static void *rsc_table; +static struct fw_resource_table *rsc_table; static struct rpmsg_device *rpdev; static char rx_sc_msg[20]; /* should receive "Hello world!" */ @@ -139,7 +140,6 @@ int mailbox_notify(void *priv, uint32_t id) int platform_init(void) { - void *rsc_tab_addr; int rsc_size; struct metal_init_params metal_params = METAL_INIT_DEFAULTS; int status; @@ -155,11 +155,11 @@ int platform_init(void) SHM_SIZE, -1, 0, NULL); /* declare resource table region */ - rsc_table_get(&rsc_tab_addr, &rsc_size); - rsc_table = (struct st_resource_table *)rsc_tab_addr; + rsc_table_get(&rsc_table, &rsc_size); + rsc_tab_physmap = (uintptr_t)rsc_table; metal_io_init(rsc_io, rsc_table, - (metal_phys_addr_t *)rsc_table, rsc_size, -1, 0, NULL); + &rsc_tab_physmap, rsc_size, -1, 0, NULL); /* setup IPM */ if (!device_is_ready(ipm_handle)) { diff --git a/samples/subsys/llext/edk/README.rst b/samples/subsys/llext/edk/README.rst new file mode 100644 index 0000000000000..22e678c314d22 --- /dev/null +++ b/samples/subsys/llext/edk/README.rst @@ -0,0 +1,137 @@ +.. zephyr:code-sample:: llext-edk + :name: Linkable loadable extensions EDK + :relevant-api: llext + + Enable linkable loadable extension development outside the Zephyr tree using + LLEXT EDK (Extension Development Kit). + +Overview +******** + +This sample demonstrates how to use the Zephyr LLEXT EDK (Extension Development +Kit). It is composed of one Zephyr application, which provides APIs for the +extensions that it loads. The provided API is a simple publish/subscribe system, +based on :ref:`Zbus `, which extensions use to communicate with each other. + +The application is composed of a subscriber thread, which listens for events +published and republishes them via Zbus to the extensions that are +subscribers. There are four extensions, which are loaded by the application and +run in different contexts. Extensions ``ext1``, ``ext2`` and ``ext3`` run in +userspace, each demonstrating different application and Zephyr API usage, such as +semaphores, spawning threads to listen for events or simply publishing or +subscribing to events. Extension ``kext1`` runs in a kernel thread, albeit similar +to ``ext3``. + +The application also creates different memory domains for each extension, thus +providing some level of isolation - although the kernel one still has access +to all of Zephyr kernel. + +Note that the kernel extension is only available when the EDK is built with +the :kconfig:option:`CONFIG_LLEXT_EDK_USERSPACE_ONLY` option disabled. + + +The application is built using the Zephyr build system. The EDK is built using +the Zephyr build system as well, via ``llext-edk`` target. The EDK is then +extracted and the extensions are built using CMake. + +Finally, the way the application loads the extensions is by including them +during build time, which is not really practical. This sample is about the EDK +providing the ability to build extensions independently from the application. +One could build the extensions in different directories, not related to the +Zephyr application - even on different machines, using only the EDK. At the +limit, one could even imagine a scenario where the extensions are built by +different teams, using the EDK provided by the application developer. + +Building the EDK +**************** + +To build the EDK, use the ``llext-edk`` target. For example: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/edk/app + :board: qemu_cortex_r5 + :goals: build llext-edk + :west-args: -p=always + :compact: + +Copy the EDK to some place and extract it: + +.. code-block:: console + + mkdir /tmp/edk + cp build/zephyr/llext-edk.tar.xz /tmp/edk + cd /tmp/edk + tar -xf llext-edk.tar.xz + +Then set ``LLEXT_EDK_INSTALL_DIR`` to the extracted directory: + +.. code-block:: console + + export LLEXT_EDK_INSTALL_DIR=/tmp/edk/llext-edk + +This variable is used by the extensions to find the EDK. + +Building the extensions +*********************** + +The :envvar:`ZEPHYR_SDK_INSTALL_DIR` environment variable is used by the +extensions to find the Zephyr SDK, so you need to ensure it's properly set: + +.. code-block:: console + + export ZEPHYR_SDK_INSTALL_DIR= + +To build the extensions, in the ``ext1``, ``ext2``, ``ext3`` and ``kext1`` +directories: + +.. code-block:: console + + cmake -B build + make -C build + +Alternatively, you can set the ``LLEXT_EDK_INSTALL_DIR`` directly in the +CMake invocation: + +.. code-block:: console + + cmake -B build -DLLEXT_EDK_INSTALL_DIR=/tmp/edk/llext-edk + make -C build + +Building the application +************************ + +Now, build the application, including the extensions, and run it: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/edk/app + :board: qemu_cortex_r5 + :goals: build run + :west-args: -p=always + :compact: + +You should see something like: + +.. code-block:: console + + [app]Subscriber thread [0x20b28] started. + [app]Loading extension [kext1]. + [app]Thread 0x20840 created to run extension [kext1], at privileged mode. + [k-ext1]Waiting sem + [app]Thread [0x222a0] registered event [0x223c0] + [k-ext1]Waiting event + [app]Loading extension [ext1]. + [app]Thread 0x20a30 created to run extension [ext1], at userspace. + [app]Thread [0x20a30] registered event [0x26060] + [ext1]Waiting event + [app]Loading extension [ext2]. + [app]Thread 0x20938 created to run extension [ext2], at userspace. + [ext2]Publishing tick + [app][subscriber_thread]Got channel tick_chan + [ext1]Got event, reading channel + [ext1]Read val: 0 + [ext1]Waiting event + [k-ext1]Got event, giving sem + [k-ext1]Got sem, reading channel + [k-ext1]Read val: 0 + [k-ext1]Waiting sem + (...) diff --git a/samples/subsys/llext/edk/app/CMakeLists.txt b/samples/subsys/llext/edk/app/CMakeLists.txt new file mode 100644 index 0000000000000..5e553869dc1dd --- /dev/null +++ b/samples/subsys/llext/edk/app/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(app LANGUAGES C) + +target_sources(app PRIVATE src/main.c src/pubsub.c) +zephyr_include_directories(include) diff --git a/samples/subsys/llext/edk/app/include/app_api.h b/samples/subsys/llext/edk/app/include/app_api.h new file mode 100644 index 0000000000000..73d8fe3133d84 --- /dev/null +++ b/samples/subsys/llext/edk/app/include/app_api.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _TEST_EDK_H_ +#define _TEST_EDK_H_ +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + + enum Channels { + CHAN_TICK = 1, + CHAN_LAST + }; + + struct channel_tick_data { + unsigned long l; + }; + + __syscall int publish(enum Channels channel, void *data, + size_t data_len); + __syscall int receive(enum Channels channel, void *data, + size_t data_len); + __syscall int register_subscriber(enum Channels channel, + struct k_event *evt); +#ifdef __cplusplus +} +#endif + +#include +#endif /* _TEST_EDK_H_ */ diff --git a/samples/subsys/llext/edk/app/prj.conf b/samples/subsys/llext/edk/app/prj.conf new file mode 100644 index 0000000000000..c9c758f676736 --- /dev/null +++ b/samples/subsys/llext/edk/app/prj.conf @@ -0,0 +1,19 @@ +CONFIG_APPLICATION_DEFINED_SYSCALL=y +CONFIG_USERSPACE=y +CONFIG_LLEXT=y + +CONFIG_MAIN_STACK_SIZE=4096 + +CONFIG_DYNAMIC_OBJECTS=y +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_ALLOC=y +CONFIG_DYNAMIC_THREAD_PREFER_ALLOC=y +CONFIG_ZBUS=y +CONFIG_ZBUS_CHANNEL_NAME=y + +CONFIG_LLEXT_HEAP_SIZE=32 + +# Uncomment to disable kext1. +#CONFIG_LLEXT_EDK_USERSPACE_ONLY=y + +CONFIG_EVENTS=y diff --git a/samples/subsys/llext/edk/app/sample.yaml b/samples/subsys/llext/edk/app/sample.yaml new file mode 100644 index 0000000000000..1bcfe288e4dd0 --- /dev/null +++ b/samples/subsys/llext/edk/app/sample.yaml @@ -0,0 +1,12 @@ +common: + tags: llext edk + arch_allow: + - arm + filter: CONFIG_ARCH_HAS_USERSPACE +sample: + description: EDK sample application + name: EDK sample application +tests: + sample.edk.app: + build_only: true + tags: edk llext diff --git a/samples/subsys/llext/edk/app/src/main.c b/samples/subsys/llext/edk/app/src/main.c new file mode 100644 index 0000000000000..78f1a664661a0 --- /dev/null +++ b/samples/subsys/llext/edk/app/src/main.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include + +#include + +/** + * Assume that if the extension 1 is not built, we are building the + * EDK. If others are not built, this will just fail. + */ +#if defined __has_include +# if __has_include("../../ext1/build/ext1.inc") +# undef EDK_BUILD +# else +# pragma message "Extension 1 not built, assuming EDK build." +# define EDK_BUILD +# endif +#endif + +#ifndef EDK_BUILD +#include "../../ext1/build/ext1.inc" +#define ext1_inc ext1_llext +#define ext1_len ext1_llext_len +#include "../../ext2/build/ext2.inc" +#define ext2_inc ext2_llext +#define ext2_len ext2_llext_len +#include "../../ext3/build/ext3.inc" +#define ext3_inc ext3_llext +#define ext3_len ext3_llext_len +#ifndef CONFIG_LLEXT_EDK_USERSPACE_ONLY +#include "../../k-ext1/build/kext1.inc" +#define kext1_inc kext1_llext +#define kext1_len kext1_llext_len +#endif +#endif + +#define USER_STACKSIZE 2048 +#define USER_HEAPSIZE 8192 +#define MAX_EXTENSIONS 4 + +extern k_tid_t start_subscriber_thread(void); + +/* Maybe make all this depend on MAX_EXTENSIONS? */ +struct k_thread user_thread1, user_thread2, user_thread3, kernel_thread1; +K_THREAD_STACK_DEFINE(user_stack1, USER_STACKSIZE); +K_THREAD_STACK_DEFINE(user_stack2, USER_STACKSIZE); +K_THREAD_STACK_DEFINE(user_stack3, USER_STACKSIZE); +K_THREAD_STACK_DEFINE(kernel_stack1, USER_STACKSIZE); + +K_HEAP_DEFINE(user_heap1, USER_HEAPSIZE); +K_HEAP_DEFINE(user_heap2, USER_HEAPSIZE); +K_HEAP_DEFINE(user_heap3, USER_HEAPSIZE); +K_HEAP_DEFINE(kernel_heap1, USER_HEAPSIZE); + +struct { + k_tid_t thread; + struct llext *ext; +} extension_threads[MAX_EXTENSIONS]; +int max_extension_thread_idx; + +static const void * const load(const char *name, struct llext **ext, void *buf, + size_t len) +{ +#ifndef EDK_BUILD + struct llext_buf_loader buf_loader = LLEXT_BUF_LOADER(buf, len); + struct llext_loader *loader = &buf_loader.loader; + struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; + + llext_load(loader, name, ext, &ldr_parm); + + return llext_find_sym(&(*ext)->exp_tab, "start"); +#else + return NULL; +#endif +} + +static void unload(struct llext **ext) +{ + llext_unload(ext); +} + +static void user_function(void *p1, void *p2, void *p3) +{ + int (*start_fn)(void) = p1; + + printk("[app]Thread %p created to run extension [%s], at %s\n", + k_current_get(), (char *)p2, + k_is_user_context() ? "userspace." : "privileged mode."); + + start_fn(); + printk("[app]Thread %p done\n", k_current_get()); +} + +void k_sys_fatal_error_handler(unsigned int reason, const struct arch_esf *esf) +{ + int i; + + printk("[app]Fatal handler! Thread: %p\n", k_current_get()); + + for (i = 0; i < max_extension_thread_idx; i++) { + if (extension_threads[i].thread == k_current_get()) { + unload(&extension_threads[i].ext); + } + } +} + +void run_extension_on_thread(void *ext_inc, size_t ext_len, + struct k_mem_domain *domain, + struct k_thread *thread, + k_thread_stack_t *stack, + struct k_heap *heap, + const char *name, + k_tid_t subscriber_thread_id, + int flag) +{ + int (*start_fn)(void); + struct llext **ext = &extension_threads[max_extension_thread_idx].ext; + + printk("[app]Loading extension [%s].\n", name); + start_fn = load(name, ext, ext_inc, ext_len); + + llext_add_domain(*ext, domain); + + k_thread_create(thread, stack, USER_STACKSIZE, + user_function, start_fn, (void *)name, NULL, + -1, flag | K_INHERIT_PERMS, K_FOREVER); + k_mem_domain_add_thread(domain, thread); + k_mem_domain_add_thread(domain, subscriber_thread_id); + + k_thread_heap_assign(thread, heap); + + extension_threads[max_extension_thread_idx].thread = thread; + max_extension_thread_idx++; + + k_thread_start(thread); +} + +int main(void) +{ + struct k_mem_domain domain1, domain2, domain3, kdomain1; + +#ifndef EDK_BUILD + k_tid_t subscriber_thread_id = start_subscriber_thread(); +#endif + /* This and all other similar sleeps are here to provide a chance for + * the newly created thread to run. + */ + k_sleep(K_MSEC(1)); + + k_mem_domain_init(&domain1, 0, NULL); + k_mem_domain_init(&domain2, 0, NULL); + k_mem_domain_init(&domain3, 0, NULL); + k_mem_domain_init(&kdomain1, 0, NULL); + +#ifndef EDK_BUILD +#ifndef CONFIG_LLEXT_EDK_USERSPACE_ONLY + run_extension_on_thread(kext1_inc, kext1_len, &kdomain1, + &kernel_thread1, kernel_stack1, &kernel_heap1, + "kext1", subscriber_thread_id, 0); + k_sleep(K_MSEC(1)); +#endif + run_extension_on_thread(ext1_inc, ext1_len, &domain1, &user_thread1, + user_stack1, &user_heap1, "ext1", + subscriber_thread_id, K_USER); + k_sleep(K_MSEC(1)); + run_extension_on_thread(ext2_inc, ext2_len, &domain2, &user_thread2, + user_stack2, &user_heap2, "ext2", + subscriber_thread_id, K_USER); + k_sleep(K_MSEC(1)); + run_extension_on_thread(ext3_inc, ext3_len, &domain3, &user_thread3, + user_stack3, &user_heap3, "ext3", + subscriber_thread_id, K_USER); +#endif + + k_sleep(K_FOREVER); + + return 0; +} diff --git a/samples/subsys/llext/edk/app/src/pubsub.c b/samples/subsys/llext/edk/app/src/pubsub.c new file mode 100644 index 0000000000000..79719af1b2b91 --- /dev/null +++ b/samples/subsys/llext/edk/app/src/pubsub.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include + +#define MAX_SUBSCRIBERS 64 +#define SUBSCRIBER_THREAD_STACK_SIZE 1024 +#define SUBSCRIBER_THREAD_PRIORITY K_PRIO_PREEMPT(1) + +ZBUS_CHAN_DEFINE(tick_chan, + struct channel_tick_data, + NULL, + NULL, + ZBUS_OBSERVERS(default_sub), + ZBUS_MSG_INIT(.l = 0)); + +ZBUS_SUBSCRIBER_DEFINE(default_sub, 4); + +K_THREAD_STACK_DEFINE(subscriber_thread_stack, SUBSCRIBER_THREAD_STACK_SIZE); +static struct k_thread subscriber_thread; + +static struct subs { + struct { + k_tid_t thread; + struct k_event *evt; + } subscribers[MAX_SUBSCRIBERS]; + struct k_mutex subscribers_mtx; + int subscribers_count; + const struct zbus_channel *chan; +} channel_subscribers[] = { + /* Empty one first, so no channel is zero (first item on enum == 1) */ + {{ }}, + { .chan = &tick_chan }, + {{ }} +}; + +static int remove_subscriber(k_tid_t thread, struct subs *sus) +{ + int i; + + for (i = 0; i < sus->subscribers_count; i++) { + if (sus->subscribers[i].thread == thread) { + sus->subscribers[i].thread = NULL; + sus->subscribers[i].evt = NULL; + break; + } + } + + if (i == sus->subscribers_count) { + return -ENOENT; + } + + /* Move all entries after excluded one, to keep things tidy */ + memmove(&sus->subscribers[i], &sus->subscribers[i + 1], + (sus->subscribers_count - i - 1) * + sizeof(sus->subscribers[0])); + sus->subscribers_count--; + + return 0; +} + +static int add_subscriber(k_tid_t thread, struct subs *sus, + struct k_event *evt) +{ + if (sus->subscribers_count >= MAX_SUBSCRIBERS) { + return -ENOMEM; + } + + sus->subscribers[sus->subscribers_count].thread = thread; + sus->subscribers[sus->subscribers_count].evt = evt; + sus->subscribers_count++; + + printk("[app]Thread [%p] registered event [%p]\n", thread, evt); + return 0; +} + +static void notify_subscribers(enum Channels channel) +{ + int i; + struct subs *subs = &channel_subscribers[channel]; + + for (i = 0; i < subs->subscribers_count; i++) { + k_event_post(subs->subscribers[i].evt, channel); + } +} + +static void subscriber_thread_fn(void *p0, void *p1, void *p2) +{ + const struct zbus_channel *chan; + int i; + + printk("[app]Subscriber thread [%p] started.\n", k_current_get()); + while (zbus_sub_wait(&default_sub, &chan, K_FOREVER) == 0) { + printk("[app][subscriber_thread]Got channel %s\n", + zbus_chan_name(chan)); + + for (i = 0; i < CHAN_LAST; i++) { + if (channel_subscribers[i].chan == chan) { + notify_subscribers((enum Channels)i); + break; + } + } + } +} + +k_tid_t start_subscriber_thread(void) +{ + return k_thread_create(&subscriber_thread, subscriber_thread_stack, + SUBSCRIBER_THREAD_STACK_SIZE, + subscriber_thread_fn, NULL, NULL, NULL, + SUBSCRIBER_THREAD_PRIORITY, 0, K_NO_WAIT); +} + +int z_impl_publish(enum Channels channel, void *data, size_t data_len) +{ + const struct zbus_channel *chan = channel_subscribers[channel].chan; + + if (channel == CHAN_LAST) { + return -EINVAL; + } + + return zbus_chan_pub(chan, data, K_NO_WAIT); +} +EXPORT_SYMBOL(z_impl_publish); + +#ifdef CONFIG_USERSPACE +static inline int z_vrfy_publish(enum Channels channel, void *data, + size_t data_len) +{ + int ret; + void *copy_data; + + copy_data = k_usermode_alloc_from_copy(data, data_len); + if (copy_data == NULL) { + return -EINVAL; + } + + ret = z_impl_publish(channel, copy_data, data_len); + + k_free(copy_data); + + return ret; +} +#include +#endif + +int z_impl_receive(enum Channels channel, void *data, size_t data_len) +{ + size_t msg_size; + + if (channel == CHAN_LAST || data == NULL) { + return -EINVAL; + } + + msg_size = channel_subscribers[channel].chan->message_size; + if (data_len < msg_size) { + return -EINVAL; + } + + return zbus_chan_read(channel_subscribers[channel].chan, data, + K_NO_WAIT); +} +EXPORT_SYMBOL(z_impl_receive); + +#ifdef CONFIG_USERSPACE +static inline int z_vrfy_receive(enum Channels channel, void *data, + size_t data_len) +{ + if (K_SYSCALL_MEMORY_WRITE(data, data_len)) { + return -EINVAL; + } + + return z_impl_receive(channel, data, data_len); +} +#include +#endif + +int z_impl_register_subscriber(enum Channels channel, struct k_event *evt) +{ + struct subs *subs = &channel_subscribers[channel]; + int ret; + + if (channel == CHAN_LAST) { + return -EINVAL; + } + + k_mutex_lock(&subs->subscribers_mtx, K_FOREVER); + + if (evt == NULL) { + ret = remove_subscriber(k_current_get(), subs); + } else { + ret = add_subscriber(k_current_get(), subs, evt); + } + + k_mutex_unlock(&subs->subscribers_mtx); + + return ret; +} +EXPORT_SYMBOL(z_impl_register_subscriber); + +#ifdef CONFIG_USERSPACE +static inline int z_vrfy_register_subscriber(enum Channels channel, + struct k_event *evt) +{ + if (K_SYSCALL_OBJ(evt, K_OBJ_EVENT)) { + return -EINVAL; + } + + return z_impl_register_subscriber(channel, evt); +} +#include +#endif diff --git a/samples/subsys/llext/edk/ext1/CMakeLists.txt b/samples/subsys/llext/edk/ext1/CMakeLists.txt new file mode 100644 index 0000000000000..cfb254797655d --- /dev/null +++ b/samples/subsys/llext/edk/ext1/CMakeLists.txt @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_TOOLCHAIN_FILE toolchain.cmake) +set(CMAKE_C_COMPILER_FORCED TRUE) +set(CMAKE_CXX_COMPILER_FORCED TRUE) + +project(ext1) + +# Include EDK CFLAGS +if(NOT DEFINED LLEXT_EDK_INSTALL_DIR) + set(LLEXT_EDK_INSTALL_DIR $ENV{LLEXT_EDK_INSTALL_DIR}) +endif() +include(${LLEXT_EDK_INSTALL_DIR}/cmake.cflags) + +# Add LLEXT_CFLAGS to our flags +add_compile_options(${LLEXT_CFLAGS}) +add_compile_options("-c") + +# Get flags from COMPILE_OPTIONS +get_property(COMPILE_OPTIONS_PROP DIRECTORY PROPERTY COMPILE_OPTIONS) + +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.inc + COMMAND ${CMAKE_C_COMPILER} ${COMPILE_OPTIONS_PROP} + -o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_SOURCE_DIR}/src/main.c + COMMAND xxd -ip ${PROJECT_NAME}.llext + ${PROJECT_NAME}.inc +) + +add_custom_target(ext1 ALL DEPENDS ${PROJECT_BINARY_DIR}/ext1.llext) diff --git a/samples/subsys/llext/edk/ext1/src/main.c b/samples/subsys/llext/edk/ext1/src/main.c new file mode 100644 index 0000000000000..d7f9c6aa71b3f --- /dev/null +++ b/samples/subsys/llext/edk/ext1/src/main.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +int start(void) +{ + /* Inside extensions, all kobjects need to be dynamically allocated */ + struct k_event *tick_evt = k_object_alloc(K_OBJ_EVENT); + + k_event_init(tick_evt); + + register_subscriber(CHAN_TICK, tick_evt); + + while (true) { + long l; + + printk("[ext1]Waiting event\n"); + k_event_wait(tick_evt, CHAN_TICK, true, K_FOREVER); + + printk("[ext1]Got event, reading channel\n"); + receive(CHAN_TICK, &l, sizeof(l)); + printk("[ext1]Read val: %ld\n", l); + } + + return 0; +} +LL_EXTENSION_SYMBOL(start); diff --git a/samples/subsys/llext/edk/ext1/toolchain.cmake b/samples/subsys/llext/edk/ext1/toolchain.cmake new file mode 100644 index 0000000000000..c511cc4a6a067 --- /dev/null +++ b/samples/subsys/llext/edk/ext1/toolchain.cmake @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CMAKE_C_COMPILER arm-zephyr-eabi-gcc) +set(CMAKE_FIND_ROOT_PATH $ENV{ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi) diff --git a/samples/subsys/llext/edk/ext2/CMakeLists.txt b/samples/subsys/llext/edk/ext2/CMakeLists.txt new file mode 100644 index 0000000000000..70ea00f0b6120 --- /dev/null +++ b/samples/subsys/llext/edk/ext2/CMakeLists.txt @@ -0,0 +1,31 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_TOOLCHAIN_FILE toolchain.cmake) +set(CMAKE_C_COMPILER_FORCED TRUE) +set(CMAKE_CXX_COMPILER_FORCED TRUE) + +project(ext2) + +# Include EDK CFLAGS +if(NOT DEFINED LLEXT_EDK_INSTALL_DIR) + set(LLEXT_EDK_INSTALL_DIR $ENV{LLEXT_EDK_INSTALL_DIR}) +endif() +include(${LLEXT_EDK_INSTALL_DIR}/cmake.cflags) + +# Add LLEXT_CFLAGS to our flags +set(CMAKE_C_FLAGS ${LLEXT_CFLAGS} "-c") + +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.inc + COMMAND ${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} + -o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_SOURCE_DIR}/src/main.c + COMMAND xxd -ip ${PROJECT_NAME}.llext + ${PROJECT_NAME}.inc +) + +add_custom_target(ext2 ALL DEPENDS ${PROJECT_BINARY_DIR}/ext2.llext) diff --git a/samples/subsys/llext/edk/ext2/src/main.c b/samples/subsys/llext/edk/ext2/src/main.c new file mode 100644 index 0000000000000..38a054a5ccb19 --- /dev/null +++ b/samples/subsys/llext/edk/ext2/src/main.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +int start(void) +{ + int i; + + for (i = 0; i < 5; i++) { + struct channel_tick_data ctd = { .l = i }; + + printk("[ext2]Publishing tick\n"); + publish(CHAN_TICK, &ctd, sizeof(ctd)); + k_sleep(K_SECONDS(1)); + } + + return 0; +} +LL_EXTENSION_SYMBOL(start); diff --git a/samples/subsys/llext/edk/ext2/toolchain.cmake b/samples/subsys/llext/edk/ext2/toolchain.cmake new file mode 100644 index 0000000000000..c511cc4a6a067 --- /dev/null +++ b/samples/subsys/llext/edk/ext2/toolchain.cmake @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CMAKE_C_COMPILER arm-zephyr-eabi-gcc) +set(CMAKE_FIND_ROOT_PATH $ENV{ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi) diff --git a/samples/subsys/llext/edk/ext3/CMakeLists.txt b/samples/subsys/llext/edk/ext3/CMakeLists.txt new file mode 100644 index 0000000000000..8f95956a25577 --- /dev/null +++ b/samples/subsys/llext/edk/ext3/CMakeLists.txt @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_TOOLCHAIN_FILE toolchain.cmake) +set(CMAKE_C_COMPILER_FORCED TRUE) +set(CMAKE_CXX_COMPILER_FORCED TRUE) + +project(ext3) + +# Include EDK CFLAGS +if(NOT DEFINED LLEXT_EDK_INSTALL_DIR) + set(LLEXT_EDK_INSTALL_DIR $ENV{LLEXT_EDK_INSTALL_DIR}) +endif() +include(${LLEXT_EDK_INSTALL_DIR}/cmake.cflags) + +# Add LLEXT_CFLAGS to our flags +add_compile_options(${LLEXT_CFLAGS}) +add_compile_options("-c") + +# Get flags from COMPILE_OPTIONS +get_property(COMPILE_OPTIONS_PROP DIRECTORY PROPERTY COMPILE_OPTIONS) + +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.inc + COMMAND ${CMAKE_C_COMPILER} ${COMPILE_OPTIONS_PROP} + -o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_SOURCE_DIR}/src/main.c + COMMAND xxd -ip ${PROJECT_NAME}.llext + ${PROJECT_NAME}.inc +) + +add_custom_target(ext3 ALL DEPENDS ${PROJECT_BINARY_DIR}/ext3.llext) diff --git a/samples/subsys/llext/edk/ext3/src/main.c b/samples/subsys/llext/edk/ext3/src/main.c new file mode 100644 index 0000000000000..19aff8352d967 --- /dev/null +++ b/samples/subsys/llext/edk/ext3/src/main.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#define STACKSIZE 512 +#define PRIORITY 2 + +static struct k_sem *my_sem; + +static void tick_sub(void *p1, void *p2, void *p3) +{ + struct k_event *tick_evt = k_object_alloc(K_OBJ_EVENT); + + k_event_init(tick_evt); + + register_subscriber(CHAN_TICK, tick_evt); + + while (true) { + printk("[ext3]Waiting event\n"); + k_event_wait(tick_evt, CHAN_TICK, true, K_FOREVER); + printk("[ext3]Got event, giving sem\n"); + + k_sem_give(my_sem); + } +} + +int start(void) +{ + k_thread_stack_t *sub_stack; + struct k_thread *sub_thread; + + /* Currently, any kobjects need to be dynamic on extensions, + * so the semaphore, thread stack and thread objects are created + * dynamically. + */ + my_sem = k_object_alloc(K_OBJ_SEM); + k_sem_init(my_sem, 0, 1); + + sub_stack = k_thread_stack_alloc(STACKSIZE, K_USER); + sub_thread = k_object_alloc(K_OBJ_THREAD); + printk("[ext3]%p - %p\n", sub_stack, sub_thread); + k_thread_create(sub_thread, sub_stack, STACKSIZE, tick_sub, NULL, NULL, + NULL, PRIORITY, K_INHERIT_PERMS | K_USER, K_NO_WAIT); + + while (true) { + long l; + + printk("[ext3]Waiting sem\n"); + k_sem_take(my_sem, K_FOREVER); + + printk("[ext3]Got sem, reading channel\n"); + receive(CHAN_TICK, &l, sizeof(l)); + printk("[ext3]Read val: %ld\n", l); + } + + return 0; +} +LL_EXTENSION_SYMBOL(start); diff --git a/samples/subsys/llext/edk/ext3/toolchain.cmake b/samples/subsys/llext/edk/ext3/toolchain.cmake new file mode 100644 index 0000000000000..c511cc4a6a067 --- /dev/null +++ b/samples/subsys/llext/edk/ext3/toolchain.cmake @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CMAKE_C_COMPILER arm-zephyr-eabi-gcc) +set(CMAKE_FIND_ROOT_PATH $ENV{ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi) diff --git a/samples/subsys/llext/edk/k-ext1/CMakeLists.txt b/samples/subsys/llext/edk/k-ext1/CMakeLists.txt new file mode 100644 index 0000000000000..b1f4aae47e84d --- /dev/null +++ b/samples/subsys/llext/edk/k-ext1/CMakeLists.txt @@ -0,0 +1,35 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +set(CMAKE_TOOLCHAIN_FILE toolchain.cmake) +set(CMAKE_C_COMPILER_FORCED TRUE) +set(CMAKE_CXX_COMPILER_FORCED TRUE) + +project(kext1) + +# Include EDK CFLAGS +if(NOT DEFINED LLEXT_EDK_INSTALL_DIR) + set(LLEXT_EDK_INSTALL_DIR $ENV{LLEXT_EDK_INSTALL_DIR}) +endif() +include(${LLEXT_EDK_INSTALL_DIR}/cmake.cflags) + +# Add LLEXT_CFLAGS to our flags +add_compile_options(${LLEXT_CFLAGS}) +add_compile_options("-c") + +# Get flags from COMPILE_OPTIONS +get_property(COMPILE_OPTIONS_PROP DIRECTORY PROPERTY COMPILE_OPTIONS) + +add_custom_command( + OUTPUT + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.inc + COMMAND ${CMAKE_C_COMPILER} ${COMPILE_OPTIONS_PROP} + -o ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.llext + ${PROJECT_SOURCE_DIR}/src/main.c + COMMAND xxd -ip ${PROJECT_NAME}.llext + ${PROJECT_NAME}.inc +) + +add_custom_target(kext1 ALL DEPENDS ${PROJECT_BINARY_DIR}/kext1.llext) diff --git a/samples/subsys/llext/edk/k-ext1/src/main.c b/samples/subsys/llext/edk/k-ext1/src/main.c new file mode 100644 index 0000000000000..34dedc6372820 --- /dev/null +++ b/samples/subsys/llext/edk/k-ext1/src/main.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2024 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include + +#define STACKSIZE 512 +#define PRIORITY 2 + +static struct k_sem *my_sem; + +static void tick_sub(void *p1, void *p2, void *p3) +{ + struct k_event *tick_evt = k_object_alloc(K_OBJ_EVENT); + + k_event_init(tick_evt); + + register_subscriber(CHAN_TICK, tick_evt); + + while (true) { + printk("[k-ext1]Waiting event\n"); + k_event_wait(tick_evt, CHAN_TICK, true, K_FOREVER); + printk("[k-ext1]Got event, giving sem\n"); + + k_sem_give(my_sem); + } +} + +int start(void) +{ + k_thread_stack_t *sub_stack; + struct k_thread *sub_thread; + + /* Currently, any kobjects need to be dynamic on extensions, + * so the semaphore, thread stack and thread objects are created + * dynamically. + */ + my_sem = k_object_alloc(K_OBJ_SEM); + k_sem_init(my_sem, 0, 1); + + sub_stack = k_thread_stack_alloc(STACKSIZE, 0); + sub_thread = k_object_alloc(K_OBJ_THREAD); + k_thread_create(sub_thread, sub_stack, STACKSIZE, tick_sub, NULL, NULL, + NULL, PRIORITY, K_INHERIT_PERMS, K_NO_WAIT); + + while (true) { + long l; + + printk("[k-ext1]Waiting sem\n"); + k_sem_take(my_sem, K_FOREVER); + + printk("[k-ext1]Got sem, reading channel\n"); + receive(CHAN_TICK, &l, sizeof(l)); + printk("[k-ext1]Read val: %ld\n", l); + } + + return 0; +} +LL_EXTENSION_SYMBOL(start); diff --git a/samples/subsys/llext/edk/k-ext1/toolchain.cmake b/samples/subsys/llext/edk/k-ext1/toolchain.cmake new file mode 100644 index 0000000000000..c511cc4a6a067 --- /dev/null +++ b/samples/subsys/llext/edk/k-ext1/toolchain.cmake @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: Apache-2.0 + +set(CMAKE_C_COMPILER arm-zephyr-eabi-gcc) +set(CMAKE_FIND_ROOT_PATH $ENV{ZEPHYR_SDK_INSTALL_DIR}/arm-zephyr-eabi) diff --git a/samples/subsys/llext/modules/CMakeLists.txt b/samples/subsys/llext/modules/CMakeLists.txt new file mode 100644 index 0000000000000..9e5f0e427a511 --- /dev/null +++ b/samples/subsys/llext/modules/CMakeLists.txt @@ -0,0 +1,39 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(fs_shell) + +if(CONFIG_HELLO_WORLD_MODE STREQUAL "m") + + # Build the llext ... + + set(ext_name hello_world) + set(ext_src src/${ext_name}_ext.c) + set(ext_bin ${ZEPHYR_BINARY_DIR}/${ext_name}.llext) + set(ext_inc ${ZEPHYR_BINARY_DIR}/include/generated/${ext_name}_ext.inc) + add_llext_target(${ext_name}_ext + OUTPUT ${ext_bin} + SOURCES ${ext_src} + ) + generate_inc_file_for_target(app ${ext_bin} ${ext_inc}) + + # ...and the code for loading and running it + + target_sources(app PRIVATE + src/main_module.c + ) + +elseif(CONFIG_HELLO_WORLD_MODE STREQUAL "y") + + # Just build the two files together + + target_sources(app PRIVATE + src/main_builtin.c + src/hello_world_ext.c + ) + +else() + message(FATAL_ERROR "Please choose 'y' or 'm' for CONFIG_HELLO_WORLD_MODE") +endif() diff --git a/samples/subsys/llext/modules/Kconfig b/samples/subsys/llext/modules/Kconfig new file mode 100644 index 0000000000000..243d892e1fcad --- /dev/null +++ b/samples/subsys/llext/modules/Kconfig @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Apache-2.0 +# Copyright (c) 2024 Intel Corporation. + +mainmenu "LLEXT functionality test" + +source "Kconfig.zephyr" + +config HELLO_WORLD_MODE + tristate "Include the hello_world function" + default m + help + This enables building the hello_world function, implemented in + hello_world_ext.c, either as an llext module or as a built-in part of + Zephyr. + + If you select 'm', the hello_world function will be built as an llext + "module". If you select 'y', the hello_world function will be directly + linked in the Zephyr image. diff --git a/samples/subsys/llext/modules/README.rst b/samples/subsys/llext/modules/README.rst new file mode 100644 index 0000000000000..a825d1cc65cef --- /dev/null +++ b/samples/subsys/llext/modules/README.rst @@ -0,0 +1,63 @@ +.. zephyr:code-sample:: llext-modules + :name: Linkable loadable extensions "module" sample + :relevant-api: llext + + Call a function in a loadable extension module, + either built-in or loaded at runtime. + +Overview +******** + +This sample demonstrates the use of the :ref:`llext` subsystem in Zephyr. The +llext subsystem allows for the loading of relocatable ELF files at runtime; +their symbols can be accessed and functions called. + +Specifically, this shows how to call a simple "hello world" function, +implemented in :zephyr_file:`samples/subsys/llext/modules/src/hello_world_ext.c`. +This is achieved in two different ways, depending on the value of the Kconfig +symbol ``CONFIG_HELLO_WORLD_MODE``: + +- if it is ``y``, the function is directly compiled and called by the Zephyr + application. The caller code used in this case is in + :zephyr_file:`samples/subsys/llext/modules/src/main_builtin.c`. + +- if it is ``m``, the function is compiled as an llext and it is included in + the application as a binary blob. At runtime, the llext subsystem is used to + load the extension and call the function. The caller code is in + :zephyr_file:`samples/subsys/llext/modules/src/main_module.c`. + +Requirements +************ + +A board with a supported llext architecture and console. This can also be +executed in QEMU emulation on the :ref:`qemu_xtensa ` or +:ref:`qemu_cortex_r5 ` virtual boards. + +Building and running +******************** + +- The following commands build and run the sample so that the files are linked + together in the same binary: + + .. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/modules + :board: qemu_xtensa + :goals: build run + :west-args: -T sample.llext.modules.builtin_build + :compact: + +- The following commands build and run the sample so that the extension code is + compiled separately and included in the Zephyr image as a binary blob: + + .. zephyr-app-commands:: + :zephyr-app: samples/subsys/llext/modules + :board: qemu_xtensa + :goals: build run + :west-args: -T sample.llext.modules.module_build + :compact: + + Take a look at :zephyr_file:`samples/subsys/llext/modules/sample.yaml` for the + additional architecture-specific configurations required in this case. + +To build for a different board, replace ``qemu_xtensa`` in the commands above +with the desired board name. diff --git a/samples/subsys/llext/modules/prj.conf b/samples/subsys/llext/modules/prj.conf new file mode 100644 index 0000000000000..b097e9fdb23ca --- /dev/null +++ b/samples/subsys/llext/modules/prj.conf @@ -0,0 +1,14 @@ +CONFIG_LOG=y +CONFIG_LOG_MODE_IMMEDIATE=y + +CONFIG_MODULES=y + +# LLEXT is only required when loading the extension at runtime. Since in this +# basic example there's only one llext, leaving it in when building the +# extension as a built-in is redundant; in a real application, however, there +# could be other uses of the llext subsystem. + +CONFIG_LLEXT=y +CONFIG_LLEXT_LOG_LEVEL_DBG=y +CONFIG_LLEXT_HEAP_SIZE=64 +CONFIG_LLEXT_TYPE_ELF_RELOCATABLE=y diff --git a/samples/subsys/llext/modules/sample.yaml b/samples/subsys/llext/modules/sample.yaml new file mode 100644 index 0000000000000..cdb8aaff64c18 --- /dev/null +++ b/samples/subsys/llext/modules/sample.yaml @@ -0,0 +1,35 @@ +common: + tags: llext + arch_allow: + - arm + - xtensa + platform_exclude: + - apollo4p_evb # See #73443 + - apollo4p_blue_kxr_evb # See #73443 + - numaker_pfm_m487 # See #63167 + integration_platforms: + - qemu_xtensa + - qemu_cortex_r5 + - mps2/an385 + harness: console +sample: + name: CONFIG_MODULES test + description: Call code directly and from extensions +tests: + sample.llext.modules.module_build: + filter: not CONFIG_MPU and not CONFIG_MMU and not CONFIG_SOC_SERIES_S32ZE + extra_configs: + - CONFIG_HELLO_WORLD_MODE=m + - arch:arm:CONFIG_ARM_MPU=n + - arch:xtensa:CONFIG_LLEXT_STORAGE_WRITABLE=y + harness_config: + type: one_line + regex: + - "Hello, world, from an llext!" + sample.llext.modules.builtin_build: + extra_configs: + - CONFIG_HELLO_WORLD_MODE=y + harness_config: + type: one_line + regex: + - "Hello, world, from the main binary!" diff --git a/samples/subsys/llext/modules/src/hello_world_ext.c b/samples/subsys/llext/modules/src/hello_world_ext.c new file mode 100644 index 0000000000000..41220b027255e --- /dev/null +++ b/samples/subsys/llext/modules/src/hello_world_ext.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2023 Intel Corporation. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * This very simple hello world C code can be used as a test case for building + * probably the simplest loadable extension. It requires a single symbol be + * linked, section relocation support, and the ability to export and call out to + * a function. + */ + +#include +#include + +void hello_world(void) +{ +#if defined(CONFIG_HELLO_WORLD_MODE) + /* HELLO_WORLD_MODE=y: CONFIG_* is defined */ + printk("Hello, world, from the main binary!\n"); +#else + /* HELLO_WORLD_MODE=m: CONFIG_*_MODULE is defined instead */ + printk("Hello, world, from an llext!\n"); +#endif +} +LL_EXTENSION_SYMBOL(hello_world); diff --git a/samples/subsys/llext/modules/src/main_builtin.c b/samples/subsys/llext/modules/src/main_builtin.c new file mode 100644 index 0000000000000..e740c5b80e50c --- /dev/null +++ b/samples/subsys/llext/modules/src/main_builtin.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(app); + +extern void hello_world(void); + +int main(void) +{ + LOG_INF("Calling hello world as a builtin"); + + hello_world(); + + return 0; +} diff --git a/samples/subsys/llext/modules/src/main_module.c b/samples/subsys/llext/modules/src/main_module.c new file mode 100644 index 0000000000000..fd7f3dd5bf7f8 --- /dev/null +++ b/samples/subsys/llext/modules/src/main_module.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2024 Arduino SA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL +#include +LOG_MODULE_REGISTER(app); + +#include +#include + +static uint8_t llext_buf[] = { +#include "hello_world_ext.inc" +}; + +int main(void) +{ + LOG_INF("Calling hello world as a module"); + + size_t llext_buf_len = ARRAY_SIZE(llext_buf); + struct llext_buf_loader buf_loader = LLEXT_BUF_LOADER(llext_buf, llext_buf_len); + struct llext_loader *ldr = &buf_loader.loader; + + struct llext_load_param ldr_parm = LLEXT_LOAD_PARAM_DEFAULT; + struct llext *ext; + int res; + + res = llext_load(ldr, "ext", &ext, &ldr_parm); + if (res != 0) { + LOG_ERR("Failed to load extension, return code %d\n", res); + return res; + } + + void (*hello_world_fn)() = llext_find_sym(&ext->exp_tab, "hello_world"); + + if (hello_world_fn == NULL) { + LOG_ERR("Failed to find symbol\n"); + return -1; + } + + hello_world_fn(); + + return llext_unload(&ext); +} diff --git a/samples/subsys/logging/ble_backend/src/main.c b/samples/subsys/logging/ble_backend/src/main.c index bd11b987634dd..05647be29aad2 100644 --- a/samples/subsys/logging/ble_backend/src/main.c +++ b/samples/subsys/logging/ble_backend/src/main.c @@ -25,7 +25,7 @@ static void start_adv(void) { int err; - err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + err = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (err) { LOG_ERR("Advertising failed to start (err %d)", err); return; diff --git a/samples/subsys/logging/multidomain/boards/nrf5340dk_nrf5340_cpuapp.overlay b/samples/subsys/logging/multidomain/boards/nrf5340dk_nrf5340_cpuapp.overlay index eac4af423aef7..75e9f1b57442f 100644 --- a/samples/subsys/logging/multidomain/boards/nrf5340dk_nrf5340_cpuapp.overlay +++ b/samples/subsys/logging/multidomain/boards/nrf5340dk_nrf5340_cpuapp.overlay @@ -34,6 +34,11 @@ mbox-names = "tx", "rx"; role = "host"; status = "okay"; + + bt_hci_ipc0: bt_hci_ipc0 { + status = "okay"; + compatible = "zephyr,bt-hci-ipc"; + }; }; ipc1: ipc1 { diff --git a/samples/subsys/logging/multidomain/sample.yaml b/samples/subsys/logging/multidomain/sample.yaml index 5fba4c3785364..10f67b9b2f8e6 100644 --- a/samples/subsys/logging/multidomain/sample.yaml +++ b/samples/subsys/logging/multidomain/sample.yaml @@ -4,28 +4,24 @@ common: sysbuild: true tags: ipc tests: - sample.logging.multidomain.ipc_static_vrings.hw: + sample.logging.multidomain.ipc_static_vrings: platform_allow: - nrf5340dk/nrf5340/cpuapp - integration_platforms: - - nrf5340dk/nrf5340/cpuapp - build_only: true - sample.logging.multidomain.ipc_static_vrings.simu: - platform_allow: - nrf5340bsim/nrf5340/cpuapp integration_platforms: + - nrf5340dk/nrf5340/cpuapp - nrf5340bsim/nrf5340/cpuapp harness: console harness_config: type: multi_line ordered: false regex: - - "IPC-service REMOTE \\[INST 1\\] demo started" + - "Hello World!" + - "app: IPC-service HOST \\[INST 1\\] demo started" - "app: loop: 0" - "app: ipc open" - "app: wait for bound" - "app: bounded" - "app: REMOTE \\[1\\]: 0" - "app: HOST \\[1\\]: 1" - - "IPC-service REMOTE \\[INST 1\\] demo ended." - "app: IPC-service HOST \\[INST 1\\] demo ended." diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/README.rst b/samples/subsys/mgmt/mcumgr/smp_svr/README.rst index ce5cd64561dbb..a9ddfcbf4a146 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/README.rst +++ b/samples/subsys/mgmt/mcumgr/smp_svr/README.rst @@ -31,18 +31,14 @@ Caveats properly. More information about the Device Firmware Upgrade subsystem and MCUboot can be found in :ref:`mcuboot`. -* The :file:`mcumgr` command-line tool only works with Bluetooth Low Energy (BLE) - on Linux and macOS. On Windows there is no support for Device Firmware - Upgrade over BLE yet. - Prerequisites ************* -Installing the mcumgr cli -========================= +Use of a tool +============= -To interact remotely with the management subsystem on a device, we need to have the -:file:`mcumgr` installed. Follow the instructions in the :ref:`mcumgr_cli` section +To interact remotely with the management subsystem on a device, a tool is required to interact with +it. There are various tools available which are listed on the :ref:`mcumgr_tools_libraries` page of the Management subsystem documentation. Building a BLE Controller @@ -63,7 +59,7 @@ The below steps describe how to build and run the MCUboot bootloader. Detailed instructions can be found in the :ref:`mcuboot` documentation page. The Zephyr port of MCUboot is essentially a normal Zephyr application, which means that -we can build and flash it like normal using ``west``, like so: +it can be built and flashed like normal using ``west``, like so: .. code-block:: console @@ -156,7 +152,7 @@ Signing the sample image A key feature of MCUboot is that images must be signed before they can be successfully uploaded and run on a target. To sign images, the MCUboot tool :file:`imgtool` can be used. -To sign the sample image we built in a previous step: +To sign the sample image built in the previous step: .. code-block:: console @@ -174,65 +170,22 @@ Flashing the sample image Upload the :file:`zephyr.signed.bin` file from the previous to image slot-0 of your board. See :ref:`flash_map_api` for details on flash partitioning. -To upload the initial image file to an empty slot-0, we simply use ``west flash`` -like normal. ``west flash`` will automatically detect slot-0 address and confirm -the image. +To upload the initial image file to an empty slot-0, use ``west flash`` like normal. +``west flash`` will automatically detect slot-0 address and confirm the image. .. code-block:: console west flash --bin-file build/zephyr/zephyr.signed.bin -We need to explicitly specify the *signed* image file, otherwise the non-signed version +The *signed* image file needs to be used specifically, otherwise the non-signed version will be used and the image won't be runnable. Sample image: hello world! ========================== The ``smp_svr`` app is ready to run. Just reset your board and test the app -with the :file:`mcumgr` command-line tool's ``echo`` functionality, which will -send a string to the remote target device and have it echo it back: - -.. tabs:: - - .. group-tab:: Bluetooth - - .. code-block:: console - - sudo mcumgr --conntype ble --connstring ctlr_name=hci0,peer_name='Zephyr' echo hello - hello - - .. group-tab:: Shell - - .. code-block:: console - - mcumgr --conntype serial --connstring "/dev/ttyACM0,baud=115200" echo hello - hello - - .. group-tab:: UDP - - Using IPv4: - - .. code-block:: console - - mcumgr --conntype udp --connstring=[192.168.1.1]:1337 echo hello - hello - - And using IPv6 - - .. code-block:: console - - mcumgr --conntype udp --connstring=[2001:db8::1]:1337 echo hello - hello - -.. note:: - The :file:`mcumgr` command-line tool requires a connection string in order - to identify the remote target device. In the BT sample we use a BLE-based - connection string, and you might need to modify it depending on the - BLE controller you are using. - -.. note:: - In the following sections, examples will use ```` to represent - the ``--conntype `` and ``--connstring=`` :file:`mcumgr` parameters. +with your choice of tool's ``echo`` functionality, which will +send a string to the remote target device and have it echo it back. J-Link Virtual MSD Interaction Note *********************************** @@ -269,10 +222,6 @@ Direct image upload and Image mapping to MCUboot slot Currently the mcumgr supports, for direct upload, 4 target images, of which first two are mapped into MCUboot primary (slot-0) and secondary (slot-1) respectively. -The mcumgr ``image upload`` command may be provided optional ``-e -n `` parameter that will -select target image for upload; when parameter is no provided, 0 is assumed, which means "default -behaviour", and it performs upload to the "image-1", the MCUboot secondary slot. - For clarity, here is DTS label to slot to ```` translation table: +-----------+--------+------------+ @@ -287,80 +236,47 @@ For clarity, here is DTS label to slot to ```` translation table: | "image-3" | | 3 | +-----------+--------+------------+ -.. note:: - - The ``-e`` option actually means "no erase", and is provided to the mcumgr - to prevent it from sending erase command to target, before updating image. - The options is always needed when ``-n`` is used for image selection, - as the erase command is hardcoded to erase slot-1 ("image-1"), - regardless of which slot is uploaded at the time. - Upload the signed image ======================= -To upload the signed image, use the following command: - -.. code-block:: console - - sudo mcumgr image upload build/zephyr/zephyr.signed.bin +To upload the signed image, refer to the documentation for your chosen tool, select the new +firmware file to upload and begin the upload. .. note:: At the beginning of the upload process, the target might start erasing - the image slot, taking several dozen seconds for some targets. This might - cause an NMP timeout in the management protocol tool. Use the - ``-t image list - -This should print the status and hash values of each of the images present. +A list of images (slot-0 and slot-1) that are present can now be obtained on the remote target device using +the tool of your choice, which should print the status and hash values of each of the images +present. Test the image ============== -In order to instruct MCUboot to swap the images we need to test the image first, -making sure it boots: - -.. code-block:: console - - sudo mcumgr image test - -Now MCUBoot will swap the image on the next reset. +In order to instruct MCUboot to swap the images, the image needs to be tested first, making sure it +boots, see the instructions in the tool of your choice. Upon reboot, MCUBoot will swap to the new +image. .. note:: There is not yet any way of getting the image hash without actually uploading the - image and getting the hash by using the ``image list`` command of :file:`mcumgr`. + image and getting the hash. Reset remotely ============== -We can reset the device remotely to observe (use the console output) how -MCUboot swaps the images: - -.. code-block:: console - - sudo mcumgr reset - -Upon reset MCUboot will swap slot-0 and slot-1. +The device can be reset remotely to observe (use the console output) how MCUboot swaps the images, +check the documentation in the tool of your choice. Upon reset MCUboot will swap slot-0 and +slot-1. Confirm new image ================= -The new image is now loaded into slot-0, but it will be swapped back into slot-1 -on the next reset unless the image is confirmed. To confirm the new image: - -.. code-block:: console - - sudo mcumgr image confirm +The new image is now loaded into slot-0, but it will be swapped back into slot-1 on the next +reset unless the image is confirmed. Confirm the image using the tool of your choice. Note that if you try to send the very same image that is already flashed in slot-0 then the procedure will not complete successfully since the hash values @@ -372,9 +288,4 @@ Download file from File System SMP server supports downloading files from File System on device via :file:`mcumgr`. This is useful with FS log backend, when files are stored in non-volatile memory. Build and flash both MCUboot and smp_svr applications and -then use :file:`mcumgr` with :file:`download` command, e.g.: - -.. code-block:: console - - mcumgr --conntype serial --connstring='dev=/dev/ttyACM0,baud=115200' \ - fs download /lfs/log.0000 ~/log.txt +then use the tool of your choice to download files from the file system. diff --git a/samples/subsys/mgmt/mcumgr/smp_svr/src/bluetooth.c b/samples/subsys/mgmt/mcumgr/smp_svr/src/bluetooth.c index 7503c48a7fb3b..cdaba8540900d 100644 --- a/samples/subsys/mgmt/mcumgr/smp_svr/src/bluetooth.c +++ b/samples/subsys/mgmt/mcumgr/smp_svr/src/bluetooth.c @@ -31,9 +31,7 @@ static void advertise(struct k_work *work) { int rc; - bt_le_adv_stop(); - - rc = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); + rc = bt_le_adv_start(BT_LE_ADV_CONN_ONE_TIME, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd)); if (rc) { LOG_ERR("Advertising failed to start (rc %d)", rc); return; @@ -49,17 +47,24 @@ static void connected(struct bt_conn *conn, uint8_t err) } else { LOG_INF("Connected"); } + + k_work_submit(&advertise_work); } static void disconnected(struct bt_conn *conn, uint8_t reason) { LOG_INF("Disconnected (reason 0x%02x)", reason); +} + +static void on_conn_recycled(void) +{ k_work_submit(&advertise_work); } BT_CONN_CB_DEFINE(conn_callbacks) = { .connected = connected, .disconnected = disconnected, + .recycled = on_conn_recycled, }; static void bt_ready(int err) diff --git a/samples/subsys/mgmt/updatehub/README.rst b/samples/subsys/mgmt/updatehub/README.rst index ab646da39d6e3..71b8c493068c6 100644 --- a/samples/subsys/mgmt/updatehub/README.rst +++ b/samples/subsys/mgmt/updatehub/README.rst @@ -34,7 +34,7 @@ Caveats application should build and run for other platforms with same connectivity. * The sample provides overlay files to enable other technologies like WIFI, - modem, 802.15.4 or OpenThread. These technologies depends on + 802.15.4 or OpenThread. These technologies depends on hardware resources and the correspondent overlay was designed to be generic instead full optimized. @@ -199,23 +199,7 @@ for details. The board disco_l475_iot1 is not supported. The es-WIFI driver currently doesn't support UDP. -Step 4.3: Build for Modem -------------------------- - -Modem needs add ``overlay-modem.conf``. Now, a DTC overlay file is used to -configure the glue between the modem and an arduino headers. The modem config -uses PPP over GSM modem, see :zephyr:code-sample:`gsm-modem` sample application. - -.. zephyr-app-commands:: - :zephyr-app: zephyr/samples/subsys/mgmt/updatehub - :board: [ frdm_k64f | nrf52840dk/nrf52840 | nucleo_f767zi ] - :build-dir: app - :gen-args: -DEXTRA_CONF_FILE="overlay-modem.conf;overlay-prj.conf" \ - -DDTC_OVERLAY_FILE=arduino.overlay - :goals: build - :compact: - -Step 4.4: Build for IEEE 802.15.4 [experimental] +Step 4.3: Build for IEEE 802.15.4 [experimental] ------------------------------------------------ For IEEE 802.15.4 needs add ``overlay-802154.conf``. This requires two nodes: @@ -242,7 +226,7 @@ tested with both native linux driver and ``atusb`` and with ``wpanusb`` sample. :goals: build :compact: -Step 4.6: Build for OpenThread Network [experimental] +Step 4.4: Build for OpenThread Network [experimental] ----------------------------------------------------- The OpenThread requires the ``overlay-ot.conf``. It requires two nodes: diff --git a/samples/subsys/mgmt/updatehub/arduino.overlay b/samples/subsys/mgmt/updatehub/arduino.overlay deleted file mode 100644 index 7a263260ef8bf..0000000000000 --- a/samples/subsys/mgmt/updatehub/arduino.overlay +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright (c) 2020 O.S.Systems - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&arduino_serial { - status = "okay"; - current-speed = <115200>; - gsm: gsm-modem { - compatible = "zephyr,gsm-ppp"; - }; -}; diff --git a/samples/subsys/mgmt/updatehub/overlay-802154.conf b/samples/subsys/mgmt/updatehub/overlay-802154.conf index 0af13d78c26c0..05820f8800f3f 100644 --- a/samples/subsys/mgmt/updatehub/overlay-802154.conf +++ b/samples/subsys/mgmt/updatehub/overlay-802154.conf @@ -1,5 +1,5 @@ # Copyright (c) 2020 O.S.Systems -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Disable default configs CONFIG_BT=n diff --git a/samples/subsys/mgmt/updatehub/overlay-modem.conf b/samples/subsys/mgmt/updatehub/overlay-modem.conf deleted file mode 100644 index 75ecbb3f58c40..0000000000000 --- a/samples/subsys/mgmt/updatehub/overlay-modem.conf +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) 2020 O.S.Systems -# SPDX-License-Identifier: Apache-2.0 - -# Disable default configs -CONFIG_NET_L2_ETHERNET=n - -CONFIG_NET_DHCPV4=n - -CONFIG_NET_CONFIG_SETTINGS=n - -# UART support -CONFIG_SERIAL=y - -# GSM modem support -CONFIG_MODEM=y -CONFIG_MODEM_SHELL=y -CONFIG_MODEM_GSM_PPP=y -CONFIG_MODEM_GSM_APN="" - -# PPP networking support -CONFIG_NET_DRIVERS=y -CONFIG_NET_NATIVE=y -CONFIG_NET_PPP=y -CONFIG_NET_L2_PPP=y -CONFIG_NET_L2_PPP_TIMEOUT=10000 - -CONFIG_DNS_SERVER_IP_ADDRESSES=y -CONFIG_DNS_SERVER1="8.8.8.8" diff --git a/samples/subsys/mgmt/updatehub/overlay-ot.conf b/samples/subsys/mgmt/updatehub/overlay-ot.conf index d425f950a31ef..cfd0742469efc 100644 --- a/samples/subsys/mgmt/updatehub/overlay-ot.conf +++ b/samples/subsys/mgmt/updatehub/overlay-ot.conf @@ -1,5 +1,5 @@ # Copyright (c) 2020 O.S.Systems -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Disable default configs CONFIG_BT=n diff --git a/samples/subsys/mgmt/updatehub/overlay-psa.conf b/samples/subsys/mgmt/updatehub/overlay-psa.conf new file mode 100644 index 0000000000000..4b5dcfd9af67d --- /dev/null +++ b/samples/subsys/mgmt/updatehub/overlay-psa.conf @@ -0,0 +1,3 @@ +CONFIG_FLASH_AREA_CHECK_INTEGRITY_PSA=y +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y diff --git a/samples/subsys/mgmt/updatehub/overlay-wifi.conf b/samples/subsys/mgmt/updatehub/overlay-wifi.conf index de1fc9b8616fd..4d3b3b9cf31f9 100644 --- a/samples/subsys/mgmt/updatehub/overlay-wifi.conf +++ b/samples/subsys/mgmt/updatehub/overlay-wifi.conf @@ -1,5 +1,5 @@ # Copyright (c) 2020 O.S.Systems -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 # Disable default configs CONFIG_NET_L2_ETHERNET=n diff --git a/samples/subsys/mgmt/updatehub/prj.conf b/samples/subsys/mgmt/updatehub/prj.conf index 0ea9be14f7a79..98a20203bdf23 100644 --- a/samples/subsys/mgmt/updatehub/prj.conf +++ b/samples/subsys/mgmt/updatehub/prj.conf @@ -1,5 +1,5 @@ # Copyright (c) 2018-2020 O.S.Systems -# SPDX -License-Identifier: Apache-2.0 +# SPDX-License-Identifier: Apache-2.0 CONFIG_FLASH=y CONFIG_STREAM_FLASH=y CONFIG_FLASH_MAP=y @@ -44,3 +44,5 @@ CONFIG_NET_SHELL=y # Debug helpers CONFIG_LOG=y #CONFIG_UPDATEHUB_LOG_LEVEL_DBG=y + +CONFIG_MAX_THREAD_BYTES=3 diff --git a/samples/subsys/mgmt/updatehub/sample.yaml b/samples/subsys/mgmt/updatehub/sample.yaml index 7f664bb2dfeae..de8192d957e0a 100644 --- a/samples/subsys/mgmt/updatehub/sample.yaml +++ b/samples/subsys/mgmt/updatehub/sample.yaml @@ -19,6 +19,13 @@ tests: - CONFIG_UPDATEHUB_POLL_INTERVAL=1 - CONFIG_UPDATEHUB_CE=y - CONFIG_UPDATEHUB_SERVER="updatehub.io" + sample.net.updatehub.psa: + extra_args: OVERLAY_CONFIG="overlay-psa.conf" + extra_configs: + - CONFIG_UPDATEHUB_PRODUCT_UID="e4d37cfe6ec48a2d069cc0bbb8b078677e9a0d8df3a027c4d8ea131130c4265f" + - CONFIG_UPDATEHUB_POLL_INTERVAL=1 + - CONFIG_UPDATEHUB_CE=y + - CONFIG_UPDATEHUB_SERVER="updatehub.io" sample.net.updatehub.userspace: extra_configs: - CONFIG_UPDATEHUB_PRODUCT_UID="e4d37cfe6ec48a2d069cc0bbb8b078677e9a0d8df3a027c4d8ea131130c4265f" diff --git a/samples/subsys/mgmt/updatehub/src/main.c b/samples/subsys/mgmt/updatehub/src/main.c index 5e23488f10f60..b8b1406ba0c9d 100644 --- a/samples/subsys/mgmt/updatehub/src/main.c +++ b/samples/subsys/mgmt/updatehub/src/main.c @@ -19,11 +19,6 @@ #include "c_certificates.h" #endif -#if defined(CONFIG_MODEM_GSM_PPP) -#define GSM_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_gsm_ppp) -#define UART_NODE DT_BUS(GSM_NODE) -#endif - #include LOG_MODULE_REGISTER(main); @@ -143,12 +138,6 @@ int main(void) LOG_INF("Connect request failed %d. Waiting iface be up...", ret); k_msleep(500); } - -#elif defined(CONFIG_MODEM_GSM_PPP) - const struct device *const uart_dev = DEVICE_DT_GET(UART_NODE); - - LOG_INF("APN '%s' UART '%s' device %p", CONFIG_MODEM_GSM_APN, - uart_dev->name, uart_dev); #endif net_mgmt_init_event_callback(&mgmt_cb, event_handler, EVENT_MASK); diff --git a/samples/subsys/modbus/rtu_server/README.rst b/samples/subsys/modbus/rtu_server/README.rst index aae880b78659f..38604bd1f7a56 100644 --- a/samples/subsys/modbus/rtu_server/README.rst +++ b/samples/subsys/modbus/rtu_server/README.rst @@ -85,7 +85,7 @@ For example, to set LED0 on use FC01 command (write_coil). .. code-block:: console - > client.write_coil address=0 value=1 unit=1 + > client.write_coil address=0 value=1 slave=1 Client should confirm successful communication and LED0 should light. @@ -100,13 +100,13 @@ To set LED0 off but LED1 and LED2 on use FC15 command (write_coils). .. code-block:: console - > client.write_coils address=0 values=0,1,1 unit=1 + > client.write_coils address=0 values=0,1,1 slave=1 To read LED0, LED1, LED2 state FC05 command (read_coils) can be used. .. code-block:: console - > client.read_coils address=0 count=3 unit=1 + > client.read_coils address=0 count=3 slave=1 { "bits": [ false, @@ -128,19 +128,19 @@ To write single holding registers use FC06 command (write_register), .. code-block:: console - > client.write_register address=0 value=42 unit=1 + > client.write_register address=0 value=42 slave=1 or FC16 command (write_registers). .. code-block:: console - > client.write_registers address=0 values=42,42,42 unit=1 + > client.write_registers address=0 values=42,42,42 slave=1 To read holding registers use FC03 command (read_holding_registers). .. code-block:: console - > client.read_holding_registers address=0 count=3 unit=1 + > client.read_holding_registers address=0 count=3 slave=1 { "registers": [ 42, @@ -150,4 +150,4 @@ To read holding registers use FC03 command (read_holding_registers). } .. _`joy-it RS-485 shield for Arduino`: https://joy-it.net/en/products/ARD-RS485 -.. _`PyModbus`: https://github.com/riptideio/pymodbus +.. _`PyModbus`: https://github.com/pymodbus-dev/pymodbus diff --git a/samples/subsys/modbus/tcp_gateway/README.rst b/samples/subsys/modbus/tcp_gateway/README.rst index 5fbc02b41ef2f..483c2311fea5b 100644 --- a/samples/subsys/modbus/tcp_gateway/README.rst +++ b/samples/subsys/modbus/tcp_gateway/README.rst @@ -54,7 +54,7 @@ For example, to set LED0 on use FC01 command (write_coil). .. code-block:: console > client.connect - > client.write_coil address=0 value=1 unit=1 + > client.write_coil address=0 value=1 slave=1 Client should confirm successful communication and LED0 should light. @@ -69,13 +69,13 @@ To set LED0 off but LED1 and LED2 on use FC15 command (write_coils). .. code-block:: console - > client.write_coils address=0 values=0,1,1 unit=1 + > client.write_coils address=0 values=0,1,1 slave=1 To read LED0, LED1, LED2 state FC05 command (read_coils) can be used. .. code-block:: console - > client.read_coils address=0 count=3 unit=1 + > client.read_coils address=0 count=3 slave=1 { "bits": [ false, @@ -97,19 +97,19 @@ To write single holding registers use FC06 command (write_register), .. code-block:: console - > client.write_register address=0 value=42 unit=1 + > client.write_register address=0 value=42 slave=1 or FC16 command (write_registers). .. code-block:: console - > client.write_registers address=0 values=42,42,42 unit=1 + > client.write_registers address=0 values=42,42,42 slave=1 To read holding registers use FC03 command (read_holding_registers). .. code-block:: console - > client.read_holding_registers address=0 count=3 unit=1 + > client.read_holding_registers address=0 count=3 slave=1 { "registers": [ 42, @@ -118,4 +118,4 @@ To read holding registers use FC03 command (read_holding_registers). ] } -.. _`PyModbus`: https://github.com/riptideio/pymodbus +.. _`PyModbus`: https://github.com/pymodbus-dev/pymodbus diff --git a/samples/subsys/modbus/tcp_server/README.rst b/samples/subsys/modbus/tcp_server/README.rst index 1b3f777db45e3..14e1817f175ef 100644 --- a/samples/subsys/modbus/tcp_server/README.rst +++ b/samples/subsys/modbus/tcp_server/README.rst @@ -50,7 +50,7 @@ For example, to set LED0 on use FC01 command (write_coil). .. code-block:: console > client.connect - > client.write_coil address=0 value=1 unit=1 + > client.write_coil address=0 value=1 slave=1 Client should confirm successful communication and LED0 should light. @@ -65,13 +65,13 @@ To set LED0 off but LED1 and LED2 on use FC15 command (write_coils). .. code-block:: console - > client.write_coils address=0 values=0,1,1 unit=1 + > client.write_coils address=0 values=0,1,1 slave=1 To read LED0, LED1, LED2 state FC05 command (read_coils) can be used. .. code-block:: console - > client.read_coils address=0 count=3 unit=1 + > client.read_coils address=0 count=3 slave=1 { "bits": [ false, @@ -93,19 +93,19 @@ To write single holding registers use FC06 command (write_register), .. code-block:: console - > client.write_register address=0 value=42 unit=1 + > client.write_register address=0 value=42 slave=1 or FC16 command (write_registers). .. code-block:: console - > client.write_registers address=0 values=42,42,42 unit=1 + > client.write_registers address=0 values=42,42,42 slave=1 To read holding registers use FC03 command (read_holding_registers). .. code-block:: console - > client.read_holding_registers address=0 count=3 unit=1 + > client.read_holding_registers address=0 count=3 slave=1 { "registers": [ 42, @@ -114,4 +114,4 @@ To read holding registers use FC03 command (read_holding_registers). ] } -.. _`PyModbus`: https://github.com/riptideio/pymodbus +.. _`PyModbus`: https://github.com/pymodbus-dev/pymodbus diff --git a/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c b/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c index a8662c0499870..97fd39f4d1fc8 100644 --- a/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c +++ b/samples/subsys/rtio/sensor_batch_processing/src/vnd_sensor.c @@ -20,6 +20,7 @@ struct vnd_sensor_config { struct vnd_sensor_data { struct rtio_iodev iodev; + struct mpsc io_q; struct k_timer timer; const struct device *dev; uint32_t sample_number; @@ -83,13 +84,13 @@ static void vnd_sensor_iodev_submit(struct rtio_iodev_sqe *iodev_sqe) { struct vnd_sensor_data *data = (struct vnd_sensor_data *) iodev_sqe->sqe.iodev; - rtio_mpsc_push(&data->iodev.iodev_sq, &iodev_sqe->q); + mpsc_push(&data->io_q, &iodev_sqe->q); } static void vnd_sensor_handle_int(const struct device *dev) { struct vnd_sensor_data *data = dev->data; - struct rtio_mpsc_node *node = rtio_mpsc_pop(&data->iodev.iodev_sq); + struct mpsc_node *node = mpsc_pop(&data->io_q); if (node != NULL) { struct rtio_iodev_sqe *iodev_sqe = CONTAINER_OF(node, struct rtio_iodev_sqe, q); @@ -116,7 +117,7 @@ static int vnd_sensor_init(const struct device *dev) data->dev = dev; - rtio_mpsc_init(&data->iodev.iodev_sq); + mpsc_init(&data->io_q); k_timer_init(&data->timer, vnd_sensor_timer_expiry, NULL); diff --git a/samples/subsys/sensing/simple/boards/native_sim.conf b/samples/subsys/sensing/simple/boards/native_sim.conf index b5a8eb94dc8e3..a8d13b8a03580 100644 --- a/samples/subsys/sensing/simple/boards/native_sim.conf +++ b/samples/subsys/sensing/simple/boards/native_sim.conf @@ -3,3 +3,4 @@ CONFIG_BMI160_TRIGGER_NONE=y CONFIG_EMUL_BMI160=y CONFIG_SENSOR=y CONFIG_SENSOR_INFO=y +CONFIG_EMUL=y diff --git a/samples/subsys/settings/boards/nrf54h20dk_nrf54h20_cpuapp.conf b/samples/subsys/settings/boards/nrf54h20dk_nrf54h20_cpuapp.conf new file mode 100644 index 0000000000000..3746c13c741b0 --- /dev/null +++ b/samples/subsys/settings/boards/nrf54h20dk_nrf54h20_cpuapp.conf @@ -0,0 +1,2 @@ +CONFIG_NVS=y +CONFIG_SETTINGS_NVS=y diff --git a/samples/subsys/settings/sample.yaml b/samples/subsys/settings/sample.yaml index 3ab57ee0923c4..e4a9e148c5a1d 100644 --- a/samples/subsys/settings/sample.yaml +++ b/samples/subsys/settings/sample.yaml @@ -13,6 +13,7 @@ tests: - native_sim/native/64 - mr_canhubk3 - nrf54l15pdk/nrf54l15/cpuapp + - nrf54h20dk/nrf54h20/cpuapp integration_platforms: - native_sim harness: console diff --git a/samples/subsys/shell/shell_module/README.rst b/samples/subsys/shell/shell_module/README.rst new file mode 100644 index 0000000000000..6b09a9f19bd72 --- /dev/null +++ b/samples/subsys/shell/shell_module/README.rst @@ -0,0 +1,115 @@ +.. zephyr:code-sample:: shell-module + :name: Custom Shell module + :relevant-api: shell_api + + Register shell commands using the Shell API + +Overview +******** + +This is a simple application demonstrating how to write and register commands +using the :ref:`Shell API `: + +Register Static commands + ``version`` is a static command that prints the kernel version. + +Conditionally Register commands + ``login`` and ``logout`` are conditionally registered commands depending + on :kconfig:option:`CONFIG_SHELL_START_OBSCURED`. + +Register Dynamic commands + See ``dynamic`` command and :zephyr_file:`samples/subsys/shell/shell_module/src/dynamic_cmd.c` + for details on how dynamic commands are implemented. + +Register Dictionary commands + ``dictionary`` implements subsect of dictionary commands. + +Set a Bypass callback + ``bypass`` implements the bypass callback. + +Set a Login command + ``login`` and ``logout`` implement the login and logout mechanism, respectively. + +Obscure user-input with asterisks + ``login`` and ``logout`` implement the feature of enabling and disabling + this functionality, respectively. + +Requirements +************ + +* A target configured with the shell interface, exposed through any of + its :ref:`backends `. + +Building and Running +******************** + +This sample can be found under :zephyr_file:`samples/subsys/shell/shell_module` +in the Zephyr tree. + +The sample can be built for several platforms. + +Emulation Targets +================= + +The sample may run on emulation targets. The following commands build the +application for the qemu_x86. + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/shell/shell_module + :host-os: unix + :board: qemu_x86 + :goals: run + :compact: + +After running the application, the console displays the shell interface, and +shows the shell prompt, at which point the user may start the interaction. + +On-Hardware +=========== + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/shell/shell_module + :host-os: unix + :board: nrf52840dk/nrf52840 + :goals: flash + :compact: + +Sample Output +************* + +.. code-block:: console + + uart:~$ + bypass clear date + demo device devmem + dynamic help history + kernel log log_test + rem resize retval + section_cmd shell shell_uart_release + stats version + uart:~$ demo + demo - Demo commands + Subcommands: + dictionary : Dictionary commands + hexdump : Hexdump params command. + params : Print params command. + ping : Ping command. + board : Show board name command. + uart:~$ dynamic + dynamic - Demonstrate dynamic command usage. + Subcommands: + add : Add a new dynamic command. + Example usage: [ dynamic add test ] will add a dynamic command + 'test'. + In this example, command name length is limited to 32 chars. You can + add up to 20 commands. Commands are automatically sorted to ensure + correct shell completion. + execute : Execute a command. + remove : Remove a command. + show : Show all added dynamic commands. + uart:~$ + +Details on Shell Subsystem +========================== + +For more details on the Shell subsystem, check the general :ref:`Shell documentation `. diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf index b96ff81fe8339..f05bf210213cc 100644 --- a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex5_socdk.conf @@ -5,9 +5,6 @@ CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_SHELL_STACK_SIZE=8192 -# Setting the Shell prompt -CONFIG_SHELL_PROMPT_UART="agilex5$ " - # Setting the max argc CONFIG_SHELL_ARGC_MAX=12 diff --git a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf index 22a3788b1b80a..bc86125f5d585 100644 --- a/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf +++ b/samples/subsys/shell/shell_module/boards/intel_socfpga_agilex_socdk.conf @@ -5,9 +5,6 @@ CONFIG_HEAP_MEM_POOL_SIZE=16384 CONFIG_SHELL_STACK_SIZE=8192 -# Setting the Shell prompt -CONFIG_SHELL_PROMPT_UART="agilex$ " - # Setting the max argc CONFIG_SHELL_ARGC_MAX=12 diff --git a/samples/subsys/shell/shell_module/overlay-usb.conf b/samples/subsys/shell/shell_module/overlay-usb.conf index 692287e23a120..b92529f9cc612 100644 --- a/samples/subsys/shell/shell_module/overlay-usb.conf +++ b/samples/subsys/shell/shell_module/overlay-usb.conf @@ -4,8 +4,9 @@ CONFIG_SHELL_BACKEND_SERIAL_CHECK_DTR=y CONFIG_UART_LINE_CTRL=y CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n -# POSIX_CLOCK requires an embedded C library while the native USB driver is incompatible with it. +# POSIX_TIMERS requires an embedded C library while the native USB driver is incompatible with it. # So let's disable it. Once USB_NATIVE_POSIX supports embedded C libraries this can be removed. -CONFIG_POSIX_CLOCK=n -# DATE_SHELL requires POSIX_CLOCK +CONFIG_POSIX_API=n +CONFIG_POSIX_TIMERS=n +# DATE_SHELL requires POSIX_TIMERS CONFIG_DATE_SHELL=n diff --git a/samples/subsys/shell/shell_module/prj.conf b/samples/subsys/shell/shell_module/prj.conf index 41d51f8e22a7f..ff7c665b38155 100644 --- a/samples/subsys/shell/shell_module/prj.conf +++ b/samples/subsys/shell/shell_module/prj.conf @@ -9,7 +9,8 @@ CONFIG_THREAD_MONITOR=y CONFIG_BOOT_BANNER=n CONFIG_THREAD_NAME=y CONFIG_DEVICE_SHELL=y -CONFIG_POSIX_CLOCK=y +CONFIG_POSIX_API=y +CONFIG_POSIX_TIMERS=y CONFIG_DATE_SHELL=y CONFIG_THREAD_RUNTIME_STATS=y CONFIG_THREAD_RUNTIME_STATS_USE_TIMING_FUNCTIONS=y diff --git a/samples/subsys/shell/shell_module/prj_getopt.conf b/samples/subsys/shell/shell_module/prj_getopt.conf index 6bfeb3dec41e2..8f04ab27d7c62 100644 --- a/samples/subsys/shell/shell_module/prj_getopt.conf +++ b/samples/subsys/shell/shell_module/prj_getopt.conf @@ -9,6 +9,7 @@ CONFIG_THREAD_MONITOR=y CONFIG_BOOT_BANNER=n CONFIG_THREAD_NAME=y CONFIG_DEVICE_SHELL=y -CONFIG_POSIX_CLOCK=y +CONFIG_POSIX_API=y +CONFIG_POSIX_TIMERS=y CONFIG_DATE_SHELL=y CONFIG_THREAD_RUNTIME_STATS=y diff --git a/samples/subsys/shell/shell_module/prj_login.conf b/samples/subsys/shell/shell_module/prj_login.conf index d84acc15622ab..470a41044f82f 100644 --- a/samples/subsys/shell/shell_module/prj_login.conf +++ b/samples/subsys/shell/shell_module/prj_login.conf @@ -8,7 +8,8 @@ CONFIG_THREAD_MONITOR=y CONFIG_BOOT_BANNER=n CONFIG_THREAD_NAME=y CONFIG_DEVICE_SHELL=y -CONFIG_POSIX_CLOCK=y +CONFIG_POSIX_API=y +CONFIG_POSIX_TIMERS=y CONFIG_DATE_SHELL=y CONFIG_THREAD_RUNTIME_STATS=y diff --git a/samples/subsys/shell/shell_module/sample.yaml b/samples/subsys/shell/shell_module/sample.yaml index cfd6adb80de64..482e4a37875fa 100644 --- a/samples/subsys/shell/shell_module/sample.yaml +++ b/samples/subsys/shell/shell_module/sample.yaml @@ -1,5 +1,10 @@ sample: name: Shell Sample +common: + filter: not CONFIG_NATIVE_LIBC + platform_exclude: + - native_posix + - native_posix/native/64 tests: sample.shell.shell_module: filter: CONFIG_SERIAL and dt_chosen_enabled("zephyr,shell-uart") diff --git a/samples/subsys/shell/shell_module/src/main.c b/samples/subsys/shell/shell_module/src/main.c index a3248cc7dc34e..c7519c7485c65 100644 --- a/samples/subsys/shell/shell_module/src/main.c +++ b/samples/subsys/shell/shell_module/src/main.c @@ -6,7 +6,7 @@ #include #include -#include +#include #include #include #include diff --git a/samples/subsys/smf/hsm_psicc2/CMakeLists.txt b/samples/subsys/smf/hsm_psicc2/CMakeLists.txt new file mode 100644 index 0000000000000..86586364114e8 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/CMakeLists.txt @@ -0,0 +1,12 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(smf_hsm_psicc2) + +target_sources(app PRIVATE + src/main.c + src/hsm_psicc2_console_cmds.c + src/hsm_psicc2_thread.c +) diff --git a/samples/subsys/smf/hsm_psicc2/README.rst b/samples/subsys/smf/hsm_psicc2/README.rst new file mode 100644 index 0000000000000..0b79cbb540c2d --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/README.rst @@ -0,0 +1,51 @@ +.. zephyr:code-sample:: smf_hsm_psicc2 + :name: Hierarchical State Machine Demo based on example from PSiCC2 + :relevant-api: smf + + Implement an event-driven hierarchical state machine using State Machine Framework (SMF). + +Overview +******** + +This sample demonstrates the :ref:`State Machine Framework ` subsystem. + +Building and Running +******************** + +It should be possible to build and run this sample on almost any board or emulator. + +Building and Running for ST Disco L475 IOT01 (B-L475E-IOT01A) +============================================================= +The sample can be built and executed for the :ref:`disco_l475_iot1_board` as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/smf/psicc2 + :board: disco_l475_iot1 + :goals: build flash + :compact: + +For other boards just replace the board name. + +Instructions for Use +==================== +This application implements the statechart shown in Figure 2.11 of +Practical UML Statecharts in C/C++, 2nd Edition, by Miro Samek (PSiCC2). Ebook available from +https://www.state-machine.com/psicc2 This demo was chosen as it contains all possible transition +topologies up to four levels of state nesting and is used with permission of the author. + +For each state, the entry, run, and exit actions are logged to the console, as well as logging +when a state handles an event, or explicitly ignores it and passes it up to the parent state. + +There are two shell commands defined for controlling the operation. + +* ``psicc2 event `` sends the event (from A to I) to the state machine. These correspond to + events A through I in PSiCC2 Figure 2.11 +* ``psicc2 terminate`` sends the ``EVENT_TERMINATE`` event to terminate the state machine. There + is no way to restart the state machine once terminated, and future events are ignored. + +Comparison to PSiCC2 Output +=========================== +Not all transitions modelled in UML may be supported by the :ref:`State Machine Framework `. +Unsupported transitions may lead to results different to the example run of the application in +PSiCC2 Section 2.3.15. The differences will not be listed here as it is hoped :ref:`SMF ` +will support these transitions in the future and the list would become outdated. diff --git a/samples/subsys/smf/hsm_psicc2/prj.conf b/samples/subsys/smf/hsm_psicc2/prj.conf new file mode 100644 index 0000000000000..e2104b03a2762 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/prj.conf @@ -0,0 +1,11 @@ +CONFIG_LOG=y +CONFIG_SHELL=y + +# Needed for boards that enable RTT backends for logging +# e.g. nrf52840dk/nrf52840 and any others that enable it +CONFIG_LOG_BACKEND_RTT=n + +# Enable the state machine framework +CONFIG_SMF=y +CONFIG_SMF_ANCESTOR_SUPPORT=y +CONFIG_SMF_INITIAL_TRANSITION=y diff --git a/samples/subsys/smf/hsm_psicc2/sample.yaml b/samples/subsys/smf/hsm_psicc2/sample.yaml new file mode 100644 index 0000000000000..ae32b7594af96 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/sample.yaml @@ -0,0 +1,19 @@ +sample: + name: SMF HSM PSiCC2 Demo +common: + tags: + - smf + integration_platforms: + - native_sim + harness: console + harness_config: + type: multi_line + ordered: true + regex: + - ".* hsm_psicc2_thread: initial_entry.*" + - ".* hsm_psicc2_thread: s_entry.*" + - ".* hsm_psicc2_thread: s2_entry.*" + - ".* hsm_psicc2_thread: s21_entry.*" + - ".* hsm_psicc2_thread: s211_entry.*" +tests: + sample.smf.hsm_psicc2: {} diff --git a/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_console_cmds.c b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_console_cmds.c new file mode 100644 index 0000000000000..9e5e1ab82b7ec --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_console_cmds.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2023 Glenn Andrews + * State Machine example copyright (c) Miro Samek + * + * Implementation of the statechart in Figure 2.11 of + * Practical UML Statecharts in C/C++, 2nd Edition by Miro Samek + * https://www.state-machine.com/psicc2 + * Used with permission of the author. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "hsm_psicc2_thread.h" +#include +#include + +static int cmd_hsm_psicc2_event(const struct shell *sh, size_t argc, char **argv) +{ + struct hsm_psicc2_event event; + int event_id = toupper(argv[1][0]); + + switch (event_id) { + case 'A': + event.event_id = EVENT_A; + break; + case 'B': + event.event_id = EVENT_B; + break; + case 'C': + event.event_id = EVENT_C; + break; + case 'D': + event.event_id = EVENT_D; + break; + case 'E': + event.event_id = EVENT_E; + break; + case 'F': + event.event_id = EVENT_F; + break; + case 'G': + event.event_id = EVENT_G; + break; + case 'H': + event.event_id = EVENT_H; + break; + case 'I': + event.event_id = EVENT_I; + break; + default: + shell_error(sh, "Invalid argument %s", argv[1]); + return -1; + } + + int rc = k_msgq_put(&hsm_psicc2_msgq, &event, K_NO_WAIT); + + if (rc == 0) { + shell_print(sh, "Event %c posted", event_id); + } else { + shell_error(sh, "error posting event: %d", rc); + } + return rc; +} + +static int cmd_hsm_psicc2_terminate(const struct shell *sh, size_t argc, char **argv) +{ + struct hsm_psicc2_event event = {.event_id = EVENT_TERMINATE}; + int rc = k_msgq_put(&hsm_psicc2_msgq, &event, K_NO_WAIT); + + if (rc == 0) { + shell_print(sh, "Terminate event posted"); + } else { + shell_error(sh, "error posting terminate event: %d", rc); + } + return rc; +} + +/* Creating subcommands (level 1 command) array for command "demo". */ +SHELL_STATIC_SUBCMD_SET_CREATE(sub_hsm_psicc2, + SHELL_CMD_ARG(event, NULL, "Send event to State Machine", + cmd_hsm_psicc2_event, 2, 0), + SHELL_CMD_ARG(terminate, NULL, + "Send terminate event to State Machine", + cmd_hsm_psicc2_terminate, 1, 0), + SHELL_SUBCMD_SET_END); + +/* Creating root (level 0) command "demo" */ +SHELL_CMD_REGISTER(hsm_psicc2, &sub_hsm_psicc2, "PSICC2 demo hierarchical state machine commands", + NULL); diff --git a/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c new file mode 100644 index 0000000000000..4a1118754d88b --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.c @@ -0,0 +1,336 @@ +/* + * Copyright (c) 2024 Glenn Andrews + * State Machine example copyright (c) Miro Samek + * + * Implementation of the statechart in Figure 2.11 of + * Practical UML Statecharts in C/C++, 2nd Edition by Miro Samek + * https://www.state-machine.com/psicc2 + * Used with permission of the author. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "hsm_psicc2_thread.h" +#include + +LOG_MODULE_REGISTER(hsm_psicc2_thread); + +/* User defined object */ +struct s_object { + /* This must be first */ + struct smf_ctx ctx; + + /* Other state specific data add here */ + struct hsm_psicc2_event event; + int foo; +} s_obj; + +/* Declaration of possible states */ +enum demo_states { + STATE_INITIAL, + STATE_S, + STATE_S1, + STATE_S2, + STATE_S11, + STATE_S21, + STATE_S211, +}; + +/* Forward declaration of state table */ +static const struct smf_state demo_states[]; + +/********* STATE_INITIAL *********/ +static void initial_entry(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + obj->foo = false; +} + +static void initial_run(void *o) +{ + LOG_INF("%s", __func__); +} + +static void initial_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S *********/ +static void s_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_E: + LOG_INF("%s received EVENT_E", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S11]); + break; + case EVENT_I: + if (obj->foo) { + LOG_INF("%s received EVENT_I and set foo false", __func__); + obj->foo = false; + } else { + LOG_INF("%s received EVENT_I and did nothing", __func__); + } + smf_set_handled(SMF_CTX(obj)); + break; + case EVENT_TERMINATE: + LOG_INF("%s received SMF_EVENT_TERMINATE. Terminating", __func__); + smf_set_terminate(SMF_CTX(obj), -1); + } +} + +static void s_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S1 *********/ +static void s1_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s1_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_A: + LOG_INF("%s received EVENT_A", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S1]); + break; + case EVENT_B: + LOG_INF("%s received EVENT_B", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S11]); + break; + case EVENT_C: + LOG_INF("%s received EVENT_C", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S2]); + break; + case EVENT_D: + if (!obj->foo) { + LOG_INF("%s received EVENT_D and acted on it", __func__); + obj->foo = true; + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S]); + } else { + LOG_INF("%s received EVENT_D and ignored it", __func__); + } + break; + case EVENT_F: + LOG_INF("%s received EVENT_F", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S211]); + break; + case EVENT_I: + LOG_INF("%s received EVENT_I", __func__); + smf_set_handled(SMF_CTX(obj)); + break; + } +} + +static void s1_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S11 *********/ +static void s11_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s11_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_D: + if (obj->foo) { + LOG_INF("%s received EVENT_D and acted upon it", __func__); + obj->foo = false; + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S1]); + } else { + LOG_INF("%s received EVENT_D and ignored it", __func__); + } + break; + case EVENT_G: + LOG_INF("%s received EVENT_G", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S21]); + break; + case EVENT_H: + LOG_INF("%s received EVENT_H", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S]); + break; + } +} + +static void s11_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S2 *********/ +static void s2_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s2_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_C: + LOG_INF("%s received EVENT_C", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S1]); + break; + case EVENT_F: + LOG_INF("%s received EVENT_F", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S11]); + break; + case EVENT_I: + if (!obj->foo) { + LOG_INF("%s received EVENT_I and set foo true", __func__); + obj->foo = true; + smf_set_handled(SMF_CTX(obj)); + } else { + LOG_INF("%s received EVENT_I and did nothing", __func__); + } + break; + } +} + +static void s2_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S21 *********/ +static void s21_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s21_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_A: + LOG_INF("%s received EVENT_A", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S21]); + break; + case EVENT_B: + LOG_INF("%s received EVENT_B", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S211]); + break; + case EVENT_G: + LOG_INF("%s received EVENT_G", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S1]); + break; + } +} + +static void s21_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/********* STATE_S211 *********/ +static void s211_entry(void *o) +{ + LOG_INF("%s", __func__); +} + +static void s211_run(void *o) +{ + LOG_INF("%s", __func__); + struct s_object *obj = (struct s_object *)o; + + switch (obj->event.event_id) { + case EVENT_D: + LOG_INF("%s received EVENT_D", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S21]); + break; + case EVENT_H: + LOG_INF("%s received EVENT_H", __func__); + smf_set_state(SMF_CTX(obj), &demo_states[STATE_S]); + break; + } +} + +static void s211_exit(void *o) +{ + LOG_INF("%s", __func__); +} + +/* State storage: handler functions, parent states and initial transition states */ +static const struct smf_state demo_states[] = { + [STATE_INITIAL] = SMF_CREATE_STATE(initial_entry, initial_run, initial_exit, NULL, + &demo_states[STATE_S2]), + [STATE_S] = SMF_CREATE_STATE(s_entry, s_run, s_exit, &demo_states[STATE_INITIAL], + &demo_states[STATE_S11]), + [STATE_S1] = SMF_CREATE_STATE(s1_entry, s1_run, s1_exit, &demo_states[STATE_S], + &demo_states[STATE_S11]), + [STATE_S2] = SMF_CREATE_STATE(s2_entry, s2_run, s2_exit, &demo_states[STATE_S], + &demo_states[STATE_S211]), + [STATE_S11] = SMF_CREATE_STATE(s11_entry, s11_run, s11_exit, &demo_states[STATE_S1], NULL), + [STATE_S21] = SMF_CREATE_STATE(s21_entry, s21_run, s21_exit, &demo_states[STATE_S2], + &demo_states[STATE_S211]), + [STATE_S211] = + SMF_CREATE_STATE(s211_entry, s211_run, s211_exit, &demo_states[STATE_S21], NULL), +}; + +K_THREAD_STACK_DEFINE(hsm_psicc2_thread_stack, HSM_PSICC2_THREAD_STACK_SIZE); +K_MSGQ_DEFINE(hsm_psicc2_msgq, sizeof(struct hsm_psicc2_event), HSM_PSICC2_THREAD_EVENT_QUEUE_SIZE, + 1); + +static struct k_thread hsm_psicc2_thread_data; +static k_tid_t hsm_psicc2_thread_tid; + +static void hsm_psicc2_thread(void *arg1, void *arg2, void *arg3) +{ + smf_set_initial(SMF_CTX(&s_obj), &demo_states[STATE_INITIAL]); + while (1) { + int rc = k_msgq_get(&hsm_psicc2_msgq, &s_obj.event, K_FOREVER); + + if (rc == 0) { + /* Run state machine with given message */ + rc = smf_run_state(SMF_CTX(&s_obj)); + + if (rc) { + /* State machine terminates if a non-zero value is returned */ + LOG_INF("%s terminating state machine thread", __func__); + break; + } + } else { + LOG_ERR("Waiting for event failed, code %d", rc); + } + } +} + +void hsm_psicc2_thread_run(void) +{ + hsm_psicc2_thread_tid = + k_thread_create(&hsm_psicc2_thread_data, hsm_psicc2_thread_stack, + K_THREAD_STACK_SIZEOF(hsm_psicc2_thread_stack), hsm_psicc2_thread, + NULL, NULL, NULL, HSM_PSICC2_THREAD_PRIORITY, 0, K_NO_WAIT); + + k_thread_name_set(hsm_psicc2_thread_tid, "psicc2_thread"); +} diff --git a/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.h b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.h new file mode 100644 index 0000000000000..e22588dbd67c6 --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/src/hsm_psicc2_thread.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2024 Glenn Andrews + * State Machine example copyright (c) Miro Samek + * + * Implementation of the statechart in Figure 2.11 of + * Practical UML Statecharts in C/C++, 2nd Edition by Miro Samek + * https://www.state-machine.com/psicc2 + * Used with permission of the author. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _HSM_PSICC2_THREAD_H +#define _HSM_PSICC2_THREAD_H + +#define HSM_PSICC2_THREAD_STACK_SIZE 1024 +#define HSM_PSICC2_THREAD_PRIORITY 7 +#define HSM_PSICC2_THREAD_EVENT_QUEUE_SIZE 10 + +/** + * @brief Event to be sent to an event queue + */ +struct hsm_psicc2_event { + uint32_t event_id; +}; + +/** + * @brief List of events that can be sent to the state machine + */ +enum demo_events { + EVENT_A, + EVENT_B, + EVENT_C, + EVENT_D, + EVENT_E, + EVENT_F, + EVENT_G, + EVENT_H, + EVENT_I, + EVENT_TERMINATE, +}; + +/* event queue to post messages to */ +extern struct k_msgq hsm_psicc2_msgq; + +/** + * @brief Initializes and starts the PSICC2 demo thread + * @param None + */ +void hsm_psicc2_thread_run(void); + +#endif /* _HSM_PSICC2_THREAD_H */ diff --git a/samples/subsys/smf/hsm_psicc2/src/main.c b/samples/subsys/smf/hsm_psicc2/src/main.c new file mode 100644 index 0000000000000..0612e1803427c --- /dev/null +++ b/samples/subsys/smf/hsm_psicc2/src/main.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Glenn Andrews + * State Machine example copyright (c) Miro Samek + * + * Implementation of the statechart in Figure 2.11 of + * Practical UML Statecharts in C/C++, 2nd Edition by Miro Samek + * https://www.state-machine.com/psicc2 + * Used with permission of the author. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include "hsm_psicc2_thread.h" + +int main(void) +{ + printk("State Machine Framework Demo\n"); + printk("See PSiCC2 Fig 2.11 for the statechart\n"); + printk("https://www.state-machine.com/psicc2\n\n"); + hsm_psicc2_thread_run(); + return 0; +} diff --git a/samples/subsys/smf/smf.rst b/samples/subsys/smf/smf.rst new file mode 100644 index 0000000000000..bc48258b99f8f --- /dev/null +++ b/samples/subsys/smf/smf.rst @@ -0,0 +1,10 @@ +.. _smf-samples: + +State Machine Framework Samples +############################### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/subsys/task_wdt/boards/nucleo_f401re.overlay b/samples/subsys/task_wdt/boards/nucleo_f401re.overlay new file mode 100644 index 0000000000000..c1f68c375f65a --- /dev/null +++ b/samples/subsys/task_wdt/boards/nucleo_f401re.overlay @@ -0,0 +1,19 @@ +/* + * Copyright 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * stm32F4 has a WWDG clock by APB1 where the APB1 prescaler is 1..16 + * this is too low to configure the WWDG clock for this sample. + * Thus, use the IWDG instead for running this sample. + */ + +&wwdg { + status = "disabled"; +}; + +&iwdg { + status = "okay"; +}; diff --git a/samples/subsys/task_wdt/boards/nucleo_f411re.overlay b/samples/subsys/task_wdt/boards/nucleo_f411re.overlay new file mode 100644 index 0000000000000..c1f68c375f65a --- /dev/null +++ b/samples/subsys/task_wdt/boards/nucleo_f411re.overlay @@ -0,0 +1,19 @@ +/* + * Copyright 2024 STMicroelectronics + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* + * stm32F4 has a WWDG clock by APB1 where the APB1 prescaler is 1..16 + * this is too low to configure the WWDG clock for this sample. + * Thus, use the IWDG instead for running this sample. + */ + +&wwdg { + status = "disabled"; +}; + +&iwdg { + status = "okay"; +}; diff --git a/samples/subsys/tracing/README.rst b/samples/subsys/tracing/README.rst index 89c3ac1eb5f35..c7ee095a90c43 100644 --- a/samples/subsys/tracing/README.rst +++ b/samples/subsys/tracing/README.rst @@ -33,7 +33,9 @@ or: :goals: build :compact: -.. note:: You may need to set "zephyr,tracing-uart" property under the chosen node in your devicetree. See :zephyr_file:`boards/mps2_an521.overlay` for an example. +.. note:: + You may need to set "zephyr,tracing-uart" property under the chosen node in your devicetree. + See :zephyr_file:`samples/subsys/tracing/boards/mps2_an521_cpu0.overlay` for an example. After the application has run for a while, check the trace output file. diff --git a/samples/subsys/usb/cdc_acm/nucleo_f413zh_dwc2.overlay b/samples/subsys/usb/cdc_acm/nucleo_f413zh_dwc2.overlay index 8cd2525699c39..d1e6b29edbd3c 100644 --- a/samples/subsys/usb/cdc_acm/nucleo_f413zh_dwc2.overlay +++ b/samples/subsys/usb/cdc_acm/nucleo_f413zh_dwc2.overlay @@ -15,6 +15,11 @@ interrupt-names = "fsotg"; clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000080>, <&rcc STM32_SRC_PLL_Q NO_SEL>; + num-out-eps = <6>; + num-in-eps = <6>; + ghwcfg1 = <0x00000000>; + ghwcfg2 = <0x229ed520>; + ghwcfg4 = <0x17f08030>; status = "disabled"; }; }; diff --git a/samples/subsys/usb/cdc_acm/sample.yaml b/samples/subsys/usb/cdc_acm/sample.yaml index 85dc6b7af2764..c5d616377ce9f 100644 --- a/samples/subsys/usb/cdc_acm/sample.yaml +++ b/samples/subsys/usb/cdc_acm/sample.yaml @@ -11,13 +11,16 @@ tests: regex: - "Wait for DTR" sample.usb_device_next.cdc-acm: - depends_on: usb_device + depends_on: usbd tags: usb extra_args: CONF_FILE="usbd_next_prj.conf" platform_allow: - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f - 96b_carbon/stm32f401xe + - mimxrt685_evk/mimxrt685s/cm33 + - mimxrt1060_evk harness: console harness_config: type: one_line diff --git a/samples/subsys/usb/cdc_acm/src/main.c b/samples/subsys/usb/cdc_acm/src/main.c index 41cc248aa6b3a..4dffe7cee6dae 100644 --- a/samples/subsys/usb/cdc_acm/src/main.c +++ b/samples/subsys/usb/cdc_acm/src/main.c @@ -49,13 +49,27 @@ static inline void print_baudrate(const struct device *dev) } #if defined(CONFIG_USB_DEVICE_STACK_NEXT) -static struct usbd_contex *sample_usbd; +static struct usbd_context *sample_usbd; K_SEM_DEFINE(dtr_sem, 0, 1); -static void sample_msg_cb(const struct usbd_msg *msg) +static void sample_msg_cb(struct usbd_context *const ctx, const struct usbd_msg *msg) { LOG_INF("USBD message: %s", usbd_msg_type_string(msg->type)); + if (usbd_can_detect_vbus(ctx)) { + if (msg->type == USBD_MSG_VBUS_READY) { + if (usbd_enable(ctx)) { + LOG_ERR("Failed to enable device support"); + } + } + + if (msg->type == USBD_MSG_VBUS_REMOVED) { + if (usbd_disable(ctx)) { + LOG_ERR("Failed to disable device support"); + } + } + } + if (msg->type == USBD_MSG_CDC_ACM_CONTROL_LINE_STATE) { uint32_t dtr = 0U; @@ -80,13 +94,15 @@ static int enable_usb_device_next(void) return -ENODEV; } - err = usbd_enable(sample_usbd); - if (err) { - LOG_ERR("Failed to enable device support"); - return err; + if (!usbd_can_detect_vbus(sample_usbd)) { + err = usbd_enable(sample_usbd); + if (err) { + LOG_ERR("Failed to enable device support"); + return err; + } } - LOG_DBG("USB device support enabled"); + LOG_INF("USB device support enabled"); return 0; } diff --git a/samples/subsys/usb/cdc_acm/usbd_next_prj.conf b/samples/subsys/usb/cdc_acm/usbd_next_prj.conf index c5147519f8704..f08928438b777 100644 --- a/samples/subsys/usb/cdc_acm/usbd_next_prj.conf +++ b/samples/subsys/usb/cdc_acm/usbd_next_prj.conf @@ -8,6 +8,7 @@ CONFIG_USBD_CDC_ACM_CLASS=y CONFIG_LOG=y CONFIG_USBD_LOG_LEVEL_WRN=y CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_USBD_CDC_ACM_LOG_LEVEL_ERR=y CONFIG_SAMPLE_USBD_PID=0x0001 CONFIG_SAMPLE_USBD_PRODUCT="USBD CDC ACM sample" diff --git a/samples/subsys/usb/common/Kconfig.sample_usbd b/samples/subsys/usb/common/Kconfig.sample_usbd index 1d330c2ad0874..765fc69bf2172 100644 --- a/samples/subsys/usb/common/Kconfig.sample_usbd +++ b/samples/subsys/usb/common/Kconfig.sample_usbd @@ -45,4 +45,9 @@ config SAMPLE_USBD_MAX_POWER help bMaxPower value in the sample configuration in 2 mA units. +config SAMPLE_USBD_20_EXTENSION_DESC + bool "Use default USB 2.0 Extension Descriptor" + help + Set bcdUSB value to 0201 and use default USB 2.0 Extension Descriptor. + endmenu diff --git a/samples/subsys/usb/common/sample_usbd.h b/samples/subsys/usb/common/sample_usbd.h index fe7de6be3f29b..11779fef3f5e9 100644 --- a/samples/subsys/usb/common/sample_usbd.h +++ b/samples/subsys/usb/common/sample_usbd.h @@ -27,6 +27,6 @@ * It returns the configured and initialized USB device context on success, * otherwise it returns NULL. */ -struct usbd_contex *sample_usbd_init_device(usbd_msg_cb_t msg_cb); +struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb); #endif /* ZEPHYR_SAMPLES_SUBSYS_USB_COMMON_SAMPLE_USBD_H */ diff --git a/samples/subsys/usb/common/sample_usbd_init.c b/samples/subsys/usb/common/sample_usbd_init.c index 19023e3212fdf..f6b2963b21297 100644 --- a/samples/subsys/usb/common/sample_usbd_init.c +++ b/samples/subsys/usb/common/sample_usbd_init.c @@ -8,97 +8,64 @@ #include #include -#include +#include #include LOG_MODULE_REGISTER(usbd_sample_config); #define ZEPHYR_PROJECT_USB_VID 0x2fe3 +/* doc device instantiation start */ +/* + * Instantiate a context named sample_usbd using the default USB device + * controller, the Zephyr project vendor ID, and the sample product ID. + * Zephyr project vendor ID must not be used outside of Zephyr samples. + */ USBD_DEVICE_DEFINE(sample_usbd, DEVICE_DT_GET(DT_NODELABEL(zephyr_udc0)), ZEPHYR_PROJECT_USB_VID, CONFIG_SAMPLE_USBD_PID); +/* doc device instantiation end */ +/* doc string instantiation start */ USBD_DESC_LANG_DEFINE(sample_lang); USBD_DESC_MANUFACTURER_DEFINE(sample_mfr, CONFIG_SAMPLE_USBD_MANUFACTURER); USBD_DESC_PRODUCT_DEFINE(sample_product, CONFIG_SAMPLE_USBD_PRODUCT); -USBD_DESC_SERIAL_NUMBER_DEFINE(sample_sn, "0123456789ABCDEF"); +USBD_DESC_SERIAL_NUMBER_DEFINE(sample_sn); +/* doc string instantiation end */ +/* doc configuration instantiation start */ static const uint8_t attributes = (IS_ENABLED(CONFIG_SAMPLE_USBD_SELF_POWERED) ? USB_SCD_SELF_POWERED : 0) | (IS_ENABLED(CONFIG_SAMPLE_USBD_REMOTE_WAKEUP) ? USB_SCD_REMOTE_WAKEUP : 0); +/* Full speed configuration */ USBD_CONFIGURATION_DEFINE(sample_fs_config, attributes, CONFIG_SAMPLE_USBD_MAX_POWER); +/* High speed configuration */ USBD_CONFIGURATION_DEFINE(sample_hs_config, attributes, CONFIG_SAMPLE_USBD_MAX_POWER); +/* doc configuration instantiation end */ -static int register_fs_classes(struct usbd_contex *uds_ctx) -{ - int err = 0; - - STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_fs, usbd_class_node, c_nd) { - /* Pull everything that is enabled in our configuration. */ - err = usbd_register_class(uds_ctx, c_nd->c_data->name, - USBD_SPEED_FS, 1); - if (err) { - LOG_ERR("Failed to register FS %s (%d)", - c_nd->c_data->name, err); - return err; - } - - LOG_DBG("Register FS %s", c_nd->c_data->name); - } - - return err; -} - -static int register_hs_classes(struct usbd_contex *uds_ctx) -{ - int err = 0; - - STRUCT_SECTION_FOREACH_ALTERNATE(usbd_class_hs, usbd_class_node, c_nd) { - /* Pull everything that is enabled in our configuration. */ - err = usbd_register_class(uds_ctx, c_nd->c_data->name, - USBD_SPEED_HS, 1); - if (err) { - LOG_ERR("Failed to register HS %s (%d)", - c_nd->c_data->name, err); - return err; - } - - LOG_DBG("Register HS %s", c_nd->c_data->name); - } +/* + * This does not yet provide valuable information, but rather serves as an + * example, and will be improved in the future. + */ +static const struct usb_bos_capability_lpm bos_cap_lpm = { + .bLength = sizeof(struct usb_bos_capability_lpm), + .bDescriptorType = USB_DESC_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_BOS_CAPABILITY_EXTENSION, + .bmAttributes = 0UL, +}; - return err; -} +USBD_DESC_BOS_DEFINE(sample_usbext, sizeof(bos_cap_lpm), &bos_cap_lpm); -static int sample_add_configuration(struct usbd_contex *uds_ctx, - const enum usbd_speed speed, - struct usbd_config_node *config) +static void sample_fix_code_triple(struct usbd_context *uds_ctx, + const enum usbd_speed speed) { - int err; - - err = usbd_add_configuration(uds_ctx, speed, config); - if (err) { - LOG_ERR("Failed to add configuration (%d)", err); - return err; - } - - if (speed == USBD_SPEED_FS) { - err = register_fs_classes(uds_ctx); - } else if (speed == USBD_SPEED_HS) { - err = register_hs_classes(uds_ctx); - } - - if (err) { - return err; - } - /* Always use class code information from Interface Descriptors */ if (IS_ENABLED(CONFIG_USBD_CDC_ACM_CLASS) || IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) || @@ -113,14 +80,13 @@ static int sample_add_configuration(struct usbd_contex *uds_ctx, } else { usbd_device_set_code_triple(uds_ctx, speed, 0, 0, 0); } - - return 0; } -struct usbd_contex *sample_usbd_init_device(usbd_msg_cb_t msg_cb) +struct usbd_context *sample_usbd_init_device(usbd_msg_cb_t msg_cb) { int err; + /* doc add string descriptor start */ err = usbd_add_descriptor(&sample_usbd, &sample_lang); if (err) { LOG_ERR("Failed to initialize language descriptor (%d)", err); @@ -144,23 +110,45 @@ struct usbd_contex *sample_usbd_init_device(usbd_msg_cb_t msg_cb) LOG_ERR("Failed to initialize SN descriptor (%d)", err); return NULL; } + /* doc add string descriptor end */ if (usbd_caps_speed(&sample_usbd) == USBD_SPEED_HS) { - err = sample_add_configuration(&sample_usbd, USBD_SPEED_HS, - &sample_hs_config); + err = usbd_add_configuration(&sample_usbd, USBD_SPEED_HS, + &sample_hs_config); if (err) { LOG_ERR("Failed to add High-Speed configuration"); return NULL; } + + err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_HS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return NULL; + } + + sample_fix_code_triple(&sample_usbd, USBD_SPEED_HS); } - err = sample_add_configuration(&sample_usbd, USBD_SPEED_FS, - &sample_fs_config); + /* doc configuration register start */ + err = usbd_add_configuration(&sample_usbd, USBD_SPEED_FS, + &sample_fs_config); if (err) { LOG_ERR("Failed to add Full-Speed configuration"); return NULL; } + /* doc configuration register end */ + /* doc functions register start */ + err = usbd_register_all_classes(&sample_usbd, USBD_SPEED_FS, 1); + if (err) { + LOG_ERR("Failed to add register classes"); + return NULL; + } + /* doc functions register end */ + + sample_fix_code_triple(&sample_usbd, USBD_SPEED_FS); + + /* doc message callback register start */ if (msg_cb != NULL) { err = usbd_msg_register_cb(&sample_usbd, msg_cb); if (err) { @@ -168,12 +156,26 @@ struct usbd_contex *sample_usbd_init_device(usbd_msg_cb_t msg_cb) return NULL; } } + /* doc message callback register end */ + + if (IS_ENABLED(CONFIG_SAMPLE_USBD_20_EXTENSION_DESC)) { + (void)usbd_device_set_bcd(&sample_usbd, USBD_SPEED_FS, 0x0201); + (void)usbd_device_set_bcd(&sample_usbd, USBD_SPEED_HS, 0x0201); + + err = usbd_add_descriptor(&sample_usbd, &sample_usbext); + if (err) { + LOG_ERR("Failed to add USB 2.0 Extension Descriptor"); + return NULL; + } + } + /* doc device init start */ err = usbd_init(&sample_usbd); if (err) { LOG_ERR("Failed to initialize device support"); return NULL; } + /* doc device init end */ return &sample_usbd; } diff --git a/samples/subsys/usb/console/sample.yaml b/samples/subsys/usb/console/sample.yaml index 0a291d23a678a..4b590862b31fa 100644 --- a/samples/subsys/usb/console/sample.yaml +++ b/samples/subsys/usb/console/sample.yaml @@ -4,7 +4,6 @@ tests: sample.usb.console: depends_on: - usb_device - - usb_cdc tags: usb harness: console harness_config: diff --git a/samples/subsys/usb/console/src/main.c b/samples/subsys/usb/console/src/main.c index a248d74d98ebd..538e768614a23 100644 --- a/samples/subsys/usb/console/src/main.c +++ b/samples/subsys/usb/console/src/main.c @@ -16,7 +16,7 @@ BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart), "Console device is not ACM CDC UART device"); #if defined(CONFIG_USB_DEVICE_STACK_NEXT) -static struct usbd_contex *sample_usbd; +static struct usbd_context *sample_usbd; static int enable_usb_device_next(void) { diff --git a/samples/subsys/usb/hid-cdc/CMakeLists.txt b/samples/subsys/usb/hid-cdc/CMakeLists.txt deleted file mode 100644 index 8bfa12bacb49c..0000000000000 --- a/samples/subsys/usb/hid-cdc/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -cmake_minimum_required(VERSION 3.20.0) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) -project(hid-cdc) - -FILE(GLOB app_sources src/*.c) -target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/hid-cdc/README.rst b/samples/subsys/usb/hid-cdc/README.rst deleted file mode 100644 index e0678d9d17364..0000000000000 --- a/samples/subsys/usb/hid-cdc/README.rst +++ /dev/null @@ -1,107 +0,0 @@ -.. zephyr:code-sample:: usb-hid-cdc - :name: USB HID and CDC ACM - :relevant-api: _usb_device_core_api usb_hid_class input_interface - - Expose multiple USB HID and CDC ACM instances. - -Overview -******** - -This sample app demonstrates use of multiple USB classes with multiple -instances. It combines two HID instances and two CDC ACM instances. -This sample can be found under :zephyr_file:`samples/subsys/usb/hid-cdc` in the -Zephyr project tree. - -Requirements -************ - -This project requires an USB device driver and multiple endpoints. - -The board hardware must have a push button connected via a GPIO pin. These are -called "User buttons" on many of Zephyr's :ref:`boards`. - -The button must be configured using the ``sw0`` :ref:`devicetree ` -alias, usually in the :ref:`BOARD.dts file `. You will -see this error if you try to build this sample for an unsupported board: - -.. code-block:: none - - Unsupported board: sw0 devicetree alias is not defined - -You may see additional build errors if the ``sw0`` alias exists, but is not -properly defined. - -If the devicetree aliases ``sw1``, ``sw2``, and ``sw3`` are defined, they will -also be used as additional buttons as described below. - -Building and Running -******************** - -This sample can be built for multiple boards. To build and flash it -for the :ref:`nrf52840dk_nrf52840` board: - -.. zephyr-app-commands:: - :zephyr-app: samples/subsys/usb/hid-cdc - :board: nrf52840dk/nrf52840 - :goals: build flash - :compact: - -After you have built and flashed the sample app image to your board, plug the -board into a host device, for example, a PC running Linux. -Two CDC ACM interfaces (for example /dev/ttyACM1 and /dev/ttyACM2) -and two HID devices will be detected: - -.. code-block:: console - - usb 2-2: new full-speed USB device number 3 using ohci-pci - usb 2-2: New USB device found, idVendor=2fe3, idProduct=0003, bcdDevice= 2.03 - usb 2-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3 - usb 2-2: Product: Zephyr HID and CDC ACM sample - usb 2-2: Manufacturer: ZEPHYR - usb 2-2: SerialNumber: 86FE679A598AC47A - cdc_acm 2-2:1.0: ttyACM1: USB ACM device - input: ZEPHYR Zephyr HID and CDC ACM sample as /devices/pci0000:00/0000:00:06.0/usb2/2-2/2-2:1.2/0003:2FE3:0100.0002/input/input8 - hid-generic 0003:2FE3:0100.0002: input,hidraw1: USB HID v1.10 Mouse [ZEPHYR Zephyr HID and CDC ACM sample] on usb-0000:00:06.0-2/input2 - cdc_acm 2-2:1.3: ttyACM2: USB ACM device - input: ZEPHYR Zephyr HID and CDC ACM sample as /devices/pci0000:00/0000:00:06.0/usb2/2-2/2-2:1.5/0003:2FE3:0100.0003/input/input9 - hid-generic 0003:2FE3:0100.0003: input,hidraw2: USB HID v1.10 Keyboard [ZEPHYR Zephyr HID and CDC ACM sample] on usb-0000:00:06.0-2/input5 - -You can now connect to both CDC ACM ports: - -.. code-block:: console - - minicom -D /dev/ttyACM1 -b 115200 - -.. code-block:: console - - minicom -D /dev/ttyACM2 -b 115200 - -After both ports have been connected to, messages explaining usage of each port will be displayed: - -.. code-block:: console - - Welcome to CDC_ACM_0 - Supported commands: - up - moves the mouse up - down - moves the mouse down - right - moves the mouse to right - left - moves the mouse to left - -.. code-block:: console - - Welcome to CDC_ACM_1 - Enter a string and terminate it with ENTER. - It will be sent via HID when BUTTON 2 is pressed. - You can modify it by sending a new one here. - -CDC ACM 0 may be used to control the mouse by typing a command and pressing :kbd:`ENTER`. - -CDC ACM 1 is used to control the keyboard - any string typed into it and finished with :kbd:`ENTER` will be saved -on the device and typed back to the host when BUTTON 2 is pressed. - -Buttons have following functions: - -- Button 0 moves HID mouse in random direction -- Button 1 is a left HID mouse button -- Button 2 types the string sent with CDC ACM 1 using HID keyboard -- Button 3 is a CAPS LOCK on HID keyboard diff --git a/samples/subsys/usb/hid-cdc/app.overlay b/samples/subsys/usb/hid-cdc/app.overlay deleted file mode 100644 index dc6bcf2f10575..0000000000000 --- a/samples/subsys/usb/hid-cdc/app.overlay +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2021 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ - -&zephyr_udc0 { - cdc_acm_uart0 { - compatible = "zephyr,cdc-acm-uart"; - }; - - cdc_acm_uart1 { - compatible = "zephyr,cdc-acm-uart"; - }; -}; diff --git a/samples/subsys/usb/hid-cdc/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/subsys/usb/hid-cdc/boards/nrf5340dk_nrf5340_cpuapp.conf deleted file mode 100644 index 48384ea0232a2..0000000000000 --- a/samples/subsys/usb/hid-cdc/boards/nrf5340dk_nrf5340_cpuapp.conf +++ /dev/null @@ -1,2 +0,0 @@ -CONFIG_TEST_RANDOM_GENERATOR=y -CONFIG_TIMER_RANDOM_GENERATOR=y diff --git a/samples/subsys/usb/hid-cdc/prj.conf b/samples/subsys/usb/hid-cdc/prj.conf deleted file mode 100644 index 695f97698a3bd..0000000000000 --- a/samples/subsys/usb/hid-cdc/prj.conf +++ /dev/null @@ -1,18 +0,0 @@ -CONFIG_USB_DEVICE_STACK=y -CONFIG_USB_DEVICE_PRODUCT="Zephyr HID and CDC ACM sample" -CONFIG_USB_DEVICE_PID=0x0003 -CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n -CONFIG_ENTROPY_GENERATOR=y -CONFIG_ENTROPY_DEVICE_RANDOM_GENERATOR=y - -CONFIG_USB_DEVICE_HID=y -CONFIG_USB_HID_DEVICE_COUNT=2 - -CONFIG_LOG=y -CONFIG_USB_DRIVER_LOG_LEVEL_INF=y -CONFIG_USB_DEVICE_LOG_LEVEL_INF=y - -CONFIG_SERIAL=y -CONFIG_UART_LINE_CTRL=y - -CONFIG_GPIO=y diff --git a/samples/subsys/usb/hid-cdc/sample.yaml b/samples/subsys/usb/hid-cdc/sample.yaml deleted file mode 100644 index acc25a0ac1a7b..0000000000000 --- a/samples/subsys/usb/hid-cdc/sample.yaml +++ /dev/null @@ -1,12 +0,0 @@ -sample: - name: USB HID CDC ACM sample -tests: - sample.usb.hid-cdc: - depends_on: usb_device - platform_allow: - - nrf52840dk/nrf52840 - - nrf52840dongle/nrf52840 - integration_platforms: - - nrf52840dk/nrf52840 - harness: button - tags: usb diff --git a/samples/subsys/usb/hid-cdc/src/main.c b/samples/subsys/usb/hid-cdc/src/main.c deleted file mode 100644 index 936afb76f0a66..0000000000000 --- a/samples/subsys/usb/hid-cdc/src/main.c +++ /dev/null @@ -1,841 +0,0 @@ -/* - * Copyright (c) 2019 Nordic Semiconductor ASA - * - * SPDX-License-Identifier: Apache-2.0 - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define LOG_LEVEL LOG_LEVEL_DBG -LOG_MODULE_REGISTER(main); - -#define SW0_NODE DT_ALIAS(sw0) - -#if DT_NODE_HAS_STATUS(SW0_NODE, okay) -static const struct gpio_dt_spec sw0_gpio = GPIO_DT_SPEC_GET(SW0_NODE, gpios); -#endif - -#define SW1_NODE DT_ALIAS(sw1) - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) -static const struct gpio_dt_spec sw1_gpio = GPIO_DT_SPEC_GET(SW1_NODE, gpios); -#endif - -#define SW2_NODE DT_ALIAS(sw2) - -#if DT_NODE_HAS_STATUS(SW2_NODE, okay) -static const struct gpio_dt_spec sw2_gpio = GPIO_DT_SPEC_GET(SW2_NODE, gpios); -#endif - -#define SW3_NODE DT_ALIAS(sw3) - -#if DT_NODE_HAS_STATUS(SW3_NODE, okay) -static const struct gpio_dt_spec sw3_gpio = GPIO_DT_SPEC_GET(SW3_NODE, gpios); -#endif - -/* Event FIFO */ - -K_FIFO_DEFINE(evt_fifo); - -enum evt_t { - GPIO_BUTTON_0 = 0x00, - GPIO_BUTTON_1 = 0x01, - GPIO_BUTTON_2 = 0x02, - GPIO_BUTTON_3 = 0x03, - CDC_UP = 0x04, - CDC_DOWN = 0x05, - CDC_LEFT = 0x06, - CDC_RIGHT = 0x07, - CDC_UNKNOWN = 0x08, - CDC_STRING = 0x09, - HID_MOUSE_CLEAR = 0x0A, - HID_KBD_CLEAR = 0x0B, - HID_KBD_STRING = 0x0C, -}; - -struct app_evt_t { - sys_snode_t node; - enum evt_t event_type; -}; - -#define FIFO_ELEM_MIN_SZ sizeof(struct app_evt_t) -#define FIFO_ELEM_MAX_SZ sizeof(struct app_evt_t) -#define FIFO_ELEM_COUNT 255 -#define FIFO_ELEM_ALIGN sizeof(unsigned int) - -K_HEAP_DEFINE(event_elem_pool, FIFO_ELEM_MAX_SZ * FIFO_ELEM_COUNT + 256); - -static inline void app_evt_free(struct app_evt_t *ev) -{ - k_heap_free(&event_elem_pool, ev); -} - -static inline void app_evt_put(struct app_evt_t *ev) -{ - k_fifo_put(&evt_fifo, ev); -} - -static inline struct app_evt_t *app_evt_get(void) -{ - return k_fifo_get(&evt_fifo, K_NO_WAIT); -} - -static inline void app_evt_flush(void) -{ - struct app_evt_t *ev; - - do { - ev = app_evt_get(); - if (ev) { - app_evt_free(ev); - } - } while (ev != NULL); -} - -static inline struct app_evt_t *app_evt_alloc(void) -{ - struct app_evt_t *ev; - - ev = k_heap_alloc(&event_elem_pool, - sizeof(struct app_evt_t), - K_NO_WAIT); - if (ev == NULL) { - LOG_ERR("APP event allocation failed!"); - app_evt_flush(); - - ev = k_heap_alloc(&event_elem_pool, - sizeof(struct app_evt_t), - K_NO_WAIT); - if (ev == NULL) { - LOG_ERR("APP event memory corrupted."); - __ASSERT_NO_MSG(0); - return NULL; - } - return NULL; - } - - return ev; -} - -/* HID */ - -static const uint8_t hid_mouse_report_desc[] = HID_MOUSE_REPORT_DESC(2); -static const uint8_t hid_kbd_report_desc[] = HID_KEYBOARD_REPORT_DESC(); - -static K_SEM_DEFINE(evt_sem, 0, 1); /* starts off "not available" */ -static K_SEM_DEFINE(usb_sem, 1, 1); /* starts off "available" */ -static struct gpio_callback gpio_callbacks[4]; - -static char data_buf_mouse[64], data_buf_kbd[64]; -static char string[64]; -static uint8_t chr_ptr_mouse, chr_ptr_kbd, str_pointer; - -#define MOUSE_BTN_REPORT_POS 0 -#define MOUSE_X_REPORT_POS 1 -#define MOUSE_Y_REPORT_POS 2 - -#define MOUSE_BTN_LEFT BIT(0) -#define MOUSE_BTN_RIGHT BIT(1) -#define MOUSE_BTN_MIDDLE BIT(2) - -static const char *welcome = "Welcome to "; -static const char *banner0 = "\r\n" - "Supported commands:\r\n" - "up - moves the mouse up\r\n" - "down - moves the mouse down\r\n" - "right - moves the mouse to right\r\n" - "left - moves the mouse to left\r\n"; -static const char *banner1 = "\r\n" - "Enter a string and terminate " - "it with ENTER.\r\n" - "It will be sent via HID " - "when BUTTON 2 is pressed.\r\n" - "You can modify it by sending " - "a new one here.\r\n"; -static const char *gpio0 = "Button 0 pressed\r\n"; -static const char *gpio1 = "Button 1 pressed\r\n"; -static const char *gpio2 = "Button 2 pressed\r\n"; -static const char *gpio3 = "Button 3 pressed\r\n"; -static const char *unknown = "Command not recognized.\r\n"; -static const char *up = "Mouse up\r\n"; -static const char *down = "Mouse down\r\n"; -static const char *left = "Mouse left\r\n"; -static const char *right = "Mouse right\r\n"; -static const char *evt_fail = "Unknown event detected!\r\n"; -static const char *set_str = "String set to: "; -static const char *endl = "\r\n"; - -static void in_ready_cb(const struct device *dev) -{ - ARG_UNUSED(dev); - - k_sem_give(&usb_sem); -} - -static const struct hid_ops ops = { - .int_in_ready = in_ready_cb, -}; - -static void clear_mouse_report(void) -{ - struct app_evt_t *new_evt = app_evt_alloc(); - - new_evt->event_type = HID_MOUSE_CLEAR; - app_evt_put(new_evt); - k_sem_give(&evt_sem); -} - -static void clear_kbd_report(void) -{ - struct app_evt_t *new_evt = app_evt_alloc(); - - new_evt->event_type = HID_KBD_CLEAR; - app_evt_put(new_evt); - k_sem_give(&evt_sem); -} - -static int ascii_to_hid(uint8_t ascii) -{ - if (ascii < 32) { - /* Character not supported */ - return -1; - } else if (ascii < 48) { - /* Special characters */ - switch (ascii) { - case 32: - return HID_KEY_SPACE; - case 33: - return HID_KEY_1; - case 34: - return HID_KEY_APOSTROPHE; - case 35: - return HID_KEY_3; - case 36: - return HID_KEY_4; - case 37: - return HID_KEY_5; - case 38: - return HID_KEY_7; - case 39: - return HID_KEY_APOSTROPHE; - case 40: - return HID_KEY_9; - case 41: - return HID_KEY_0; - case 42: - return HID_KEY_8; - case 43: - return HID_KEY_EQUAL; - case 44: - return HID_KEY_COMMA; - case 45: - return HID_KEY_MINUS; - case 46: - return HID_KEY_DOT; - case 47: - return HID_KEY_SLASH; - default: - return -1; - } - } else if (ascii < 58) { - /* Numbers */ - if (ascii == 48U) { - return HID_KEY_0; - } else { - return ascii - 19; - } - } else if (ascii < 65) { - /* Special characters #2 */ - switch (ascii) { - case 58: - return HID_KEY_SEMICOLON; - case 59: - return HID_KEY_SEMICOLON; - case 60: - return HID_KEY_COMMA; - case 61: - return HID_KEY_EQUAL; - case 62: - return HID_KEY_DOT; - case 63: - return HID_KEY_SLASH; - case 64: - return HID_KEY_2; - default: - return -1; - } - } else if (ascii < 91) { - /* Uppercase characters */ - return ascii - 61U; - } else if (ascii < 97) { - /* Special characters #3 */ - switch (ascii) { - case 91: - return HID_KEY_LEFTBRACE; - case 92: - return HID_KEY_BACKSLASH; - case 93: - return HID_KEY_RIGHTBRACE; - case 94: - return HID_KEY_6; - case 95: - return HID_KEY_MINUS; - case 96: - return HID_KEY_GRAVE; - default: - return -1; - } - } else if (ascii < 123) { - /* Lowercase letters */ - return ascii - 93; - } else if (ascii < 128) { - /* Special characters #4 */ - switch (ascii) { - case 123: - return HID_KEY_LEFTBRACE; - case 124: - return HID_KEY_BACKSLASH; - case 125: - return HID_KEY_RIGHTBRACE; - case 126: - return HID_KEY_GRAVE; - case 127: - return HID_KEY_DELETE; - default: - return -1; - } - } - - return -1; -} - -static bool needs_shift(uint8_t ascii) -{ - if ((ascii < 33) || (ascii == 39U)) { - return false; - } else if ((ascii >= 33U) && (ascii < 44)) { - return true; - } else if ((ascii >= 44U) && (ascii < 58)) { - return false; - } else if ((ascii == 59U) || (ascii == 61U)) { - return false; - } else if ((ascii >= 58U) && (ascii < 91)) { - return true; - } else if ((ascii >= 91U) && (ascii < 94)) { - return false; - } else if ((ascii == 94U) || (ascii == 95U)) { - return true; - } else if ((ascii > 95) && (ascii < 123)) { - return false; - } else if ((ascii > 122) && (ascii < 127)) { - return true; - } else { - return false; - } -} - -/* CDC ACM */ - -static volatile bool data_transmitted; -static volatile bool data_arrived; - -static void flush_buffer_mouse(void) -{ - chr_ptr_mouse = 0U; - memset(data_buf_mouse, 0, sizeof(data_buf_mouse)); -} - -static void flush_buffer_kbd(void) -{ - chr_ptr_kbd = 0U; - memset(data_buf_kbd, 0, sizeof(data_buf_kbd)); -} - -static void write_data(const struct device *dev, const char *buf, int len) -{ - uart_irq_tx_enable(dev); - - while (len) { - int written; - - data_transmitted = false; - written = uart_fifo_fill(dev, (const uint8_t *)buf, len); - while (data_transmitted == false) { - k_yield(); - } - - len -= written; - buf += written; - } - - uart_irq_tx_disable(dev); -} - -static void cdc_mouse_int_handler(const struct device *dev, void *user_data) -{ - ARG_UNUSED(user_data); - - uart_irq_update(dev); - - if (uart_irq_tx_ready(dev)) { - data_transmitted = true; - } - - if (!uart_irq_rx_ready(dev)) { - return; - } - uint32_t bytes_read; - - while ((bytes_read = uart_fifo_read(dev, - (uint8_t *)data_buf_mouse+chr_ptr_mouse, - sizeof(data_buf_mouse)-chr_ptr_mouse))) { - chr_ptr_mouse += bytes_read; - if (data_buf_mouse[chr_ptr_mouse - 1] == '\r') { - /* ENTER */ - struct app_evt_t *ev = app_evt_alloc(); - - data_buf_mouse[chr_ptr_mouse - 1] = '\0'; - - if (!strcmp(data_buf_mouse, "up")) { - ev->event_type = CDC_UP; - } else if (!strcmp(data_buf_mouse, "down")) { - ev->event_type = CDC_DOWN; - } else if (!strcmp(data_buf_mouse, "right")) { - ev->event_type = CDC_RIGHT; - } else if (!strcmp(data_buf_mouse, "left")) { - ev->event_type = CDC_LEFT; - } else { - ev->event_type = CDC_UNKNOWN; - } - flush_buffer_mouse(); - app_evt_put(ev); - k_sem_give(&evt_sem); - } - - if (chr_ptr_mouse >= sizeof(data_buf_mouse)) { - LOG_WRN("Buffer overflow"); - flush_buffer_mouse(); - } - } -} - -static void cdc_kbd_int_handler(const struct device *dev, void *user_data) -{ - ARG_UNUSED(user_data); - - uart_irq_update(dev); - - if (uart_irq_tx_ready(dev)) { - data_transmitted = true; - } - - if (!uart_irq_rx_ready(dev)) { - return; - } - uint32_t bytes_read; - - while ((bytes_read = uart_fifo_read(dev, - (uint8_t *)data_buf_kbd+chr_ptr_kbd, - sizeof(data_buf_kbd)-chr_ptr_kbd))) { - chr_ptr_kbd += bytes_read; - if (data_buf_kbd[chr_ptr_kbd - 1] == '\r') { - /* ENTER */ - struct app_evt_t *ev = app_evt_alloc(); - - data_buf_kbd[chr_ptr_kbd - 1] = '\0'; - strcpy(string, data_buf_kbd); - ev->event_type = CDC_STRING; - flush_buffer_kbd(); - app_evt_put(ev); - k_sem_give(&evt_sem); - } - } -} - -/* Devices */ - -static void btn0(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - struct app_evt_t *ev = app_evt_alloc(); - - ev->event_type = GPIO_BUTTON_0, - app_evt_put(ev); - k_sem_give(&evt_sem); -} - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) -static void btn1(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - struct app_evt_t *ev = app_evt_alloc(); - - ev->event_type = GPIO_BUTTON_1, - app_evt_put(ev); - k_sem_give(&evt_sem); -} -#endif - -#if DT_NODE_HAS_STATUS(SW2_NODE, okay) -static void btn2(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - struct app_evt_t *ev = app_evt_alloc(); - - ev->event_type = GPIO_BUTTON_2, - app_evt_put(ev); - k_sem_give(&evt_sem); -} -#endif - -#if DT_NODE_HAS_STATUS(SW3_NODE, okay) -static void btn3(const struct device *gpio, struct gpio_callback *cb, - uint32_t pins) -{ - struct app_evt_t *ev = app_evt_alloc(); - - ev->event_type = GPIO_BUTTON_3, - app_evt_put(ev); - k_sem_give(&evt_sem); -} -#endif - -int callbacks_configure(const struct gpio_dt_spec *gpio, - void (*handler)(const struct device *, struct gpio_callback*, - uint32_t), - struct gpio_callback *callback) -{ - if (!device_is_ready(gpio->port)) { - LOG_ERR("%s: device not ready.", gpio->port->name); - return -ENODEV; - } - - gpio_pin_configure_dt(gpio, GPIO_INPUT); - - gpio_init_callback(callback, handler, BIT(gpio->pin)); - gpio_add_callback(gpio->port, callback); - gpio_pin_interrupt_configure_dt(gpio, GPIO_INT_EDGE_TO_ACTIVE); - - return 0; -} - -static void status_cb(enum usb_dc_status_code status, const uint8_t *param) -{ - LOG_INF("Status %d", status); -} - -#define DEVICE_AND_COMMA(node_id) DEVICE_DT_GET(node_id), - -int main(void) -{ - const struct device *cdc_dev[] = { - DT_FOREACH_STATUS_OKAY(zephyr_cdc_acm_uart, DEVICE_AND_COMMA) - }; - BUILD_ASSERT(ARRAY_SIZE(cdc_dev) >= 2, "Not enough CDC ACM instances"); - const struct device *hid0_dev, *hid1_dev; - struct app_evt_t *ev; - uint32_t dtr = 0U; - int ret; - - /* Configure devices */ - - hid0_dev = device_get_binding("HID_0"); - if (hid0_dev == NULL) { - LOG_ERR("Cannot get USB HID 0 Device"); - return 0; - } - - hid1_dev = device_get_binding("HID_1"); - if (hid1_dev == NULL) { - LOG_ERR("Cannot get USB HID 1 Device"); - return 0; - } - - for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) { - if (!device_is_ready(cdc_dev[idx])) { - LOG_ERR("CDC ACM device %s is not ready", - cdc_dev[idx]->name); - return 0; - } - } - - if (callbacks_configure(&sw0_gpio, &btn0, &gpio_callbacks[0])) { - LOG_ERR("Failed configuring button 0 callback."); - return 0; - } - -#if DT_NODE_HAS_STATUS(SW1_NODE, okay) - if (callbacks_configure(&sw1_gpio, &btn1, &gpio_callbacks[1])) { - LOG_ERR("Failed configuring button 1 callback."); - return 0; - } -#endif - -#if DT_NODE_HAS_STATUS(SW2_NODE, okay) - if (callbacks_configure(&sw2_gpio, &btn2, &gpio_callbacks[2])) { - LOG_ERR("Failed configuring button 2 callback."); - return 0; - } -#endif - -#if DT_NODE_HAS_STATUS(SW3_NODE, okay) - if (callbacks_configure(&sw3_gpio, &btn3, &gpio_callbacks[3])) { - LOG_ERR("Failed configuring button 3 callback."); - return 0; - } -#endif - - /* Initialize HID */ - - usb_hid_register_device(hid0_dev, hid_mouse_report_desc, - sizeof(hid_mouse_report_desc), &ops); - - usb_hid_register_device(hid1_dev, hid_kbd_report_desc, - sizeof(hid_kbd_report_desc), &ops); - - usb_hid_init(hid0_dev); - usb_hid_init(hid1_dev); - - ret = usb_enable(status_cb); - if (ret != 0) { - LOG_ERR("Failed to enable USB"); - return 0; - } - - /* Initialize CDC ACM */ - for (int idx = 0; idx < ARRAY_SIZE(cdc_dev); idx++) { - LOG_INF("Wait for DTR on %s", cdc_dev[idx]->name); - while (1) { - uart_line_ctrl_get(cdc_dev[idx], - UART_LINE_CTRL_DTR, - &dtr); - if (dtr) { - break; - } else { - /* Give CPU resources to low priority threads. */ - k_sleep(K_MSEC(100)); - } - } - - LOG_INF("DTR on device %s", cdc_dev[idx]->name); - } - - /* Wait 1 sec for the host to do all settings */ - k_busy_wait(USEC_PER_SEC); - - uart_irq_callback_set(cdc_dev[0], cdc_mouse_int_handler); - uart_irq_callback_set(cdc_dev[1], cdc_kbd_int_handler); - - write_data(cdc_dev[0], welcome, strlen(welcome)); - write_data(cdc_dev[0], cdc_dev[0]->name, strlen(cdc_dev[0]->name)); - write_data(cdc_dev[0], banner0, strlen(banner0)); - write_data(cdc_dev[1], welcome, strlen(welcome)); - write_data(cdc_dev[1], cdc_dev[1]->name, strlen(cdc_dev[1]->name)); - write_data(cdc_dev[1], banner1, strlen(banner1)); - - uart_irq_rx_enable(cdc_dev[0]); - uart_irq_rx_enable(cdc_dev[1]); - - while (true) { - k_sem_take(&evt_sem, K_FOREVER); - - while ((ev = app_evt_get()) != NULL) { - switch (ev->event_type) { - case GPIO_BUTTON_0: - { - /* Move the mouse in random direction */ - uint8_t rep[] = {0x00, sys_rand8_get(), - sys_rand8_get(), 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], gpio0, strlen(gpio0)); - clear_mouse_report(); - break; - } - case GPIO_BUTTON_1: - { - /* Press left mouse button */ - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00}; - - rep[MOUSE_BTN_REPORT_POS] |= MOUSE_BTN_LEFT; - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], gpio1, strlen(gpio1)); - clear_mouse_report(); - break; - } - case GPIO_BUTTON_2: - { - /* Send string on HID keyboard */ - write_data(cdc_dev[1], gpio2, strlen(gpio2)); - if (strlen(string) > 0) { - struct app_evt_t *ev2 = app_evt_alloc(); - - ev2->event_type = HID_KBD_STRING, - app_evt_put(ev2); - str_pointer = 0U; - k_sem_give(&evt_sem); - } - break; - } - case GPIO_BUTTON_3: - { - /* Toggle CAPS LOCK */ - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, - HID_KEY_CAPSLOCK}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid1_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[1], gpio3, strlen(gpio3)); - clear_kbd_report(); - break; - } - case CDC_UP: - { - /* Mouse up */ - uint8_t rep[] = {0x00, 0x00, 0xE0, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], up, strlen(up)); - clear_mouse_report(); - break; - } - case CDC_DOWN: - { - /* Mouse down */ - uint8_t rep[] = {0x00, 0x00, 0x20, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], down, strlen(down)); - clear_mouse_report(); - break; - } - case CDC_RIGHT: - { - /* Mouse right */ - uint8_t rep[] = {0x00, 0x20, 0x00, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], right, strlen(right)); - clear_mouse_report(); - break; - } - case CDC_LEFT: - { - /* Mouse left */ - uint8_t rep[] = {0x00, 0xE0, 0x00, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - write_data(cdc_dev[0], left, strlen(left)); - clear_mouse_report(); - break; - } - case CDC_UNKNOWN: - { - write_data(cdc_dev[0], unknown, strlen(unknown)); - write_data(cdc_dev[1], unknown, strlen(unknown)); - break; - } - case CDC_STRING: - { - write_data(cdc_dev[0], set_str, strlen(set_str)); - write_data(cdc_dev[0], string, strlen(string)); - write_data(cdc_dev[0], endl, strlen(endl)); - - write_data(cdc_dev[1], set_str, strlen(set_str)); - write_data(cdc_dev[1], string, strlen(string)); - write_data(cdc_dev[1], endl, strlen(endl)); - break; - } - case HID_MOUSE_CLEAR: - { - /* Clear mouse report */ - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid0_dev, rep, - sizeof(rep), NULL); - break; - } - case HID_KBD_CLEAR: - { - /* Clear kbd report */ - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid1_dev, rep, - sizeof(rep), NULL); - break; - } - case HID_KBD_STRING: - { - int ch = ascii_to_hid(string[str_pointer]); - - if (ch == -1) { - LOG_WRN("Unsupported character: %d", - string[str_pointer]); - } else { - uint8_t rep[] = {0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; - if (needs_shift(string[str_pointer])) { - rep[0] |= - HID_KBD_MODIFIER_RIGHT_SHIFT; - } - rep[7] = ch; - - k_sem_take(&usb_sem, K_FOREVER); - hid_int_ep_write(hid1_dev, rep, - sizeof(rep), NULL); - } - - str_pointer++; - - if (strlen(string) > str_pointer) { - struct app_evt_t *ev2 = app_evt_alloc(); - - ev2->event_type = HID_KBD_STRING, - app_evt_put(ev2); - k_sem_give(&evt_sem); - } else if (strlen(string) == str_pointer) { - clear_kbd_report(); - } - - break; - } - default: - { - LOG_ERR("Unknown event to execute"); - write_data(cdc_dev[0], evt_fail, - strlen(evt_fail)); - write_data(cdc_dev[1], evt_fail, - strlen(evt_fail)); - break; - } - break; - } - app_evt_free(ev); - } - } -} diff --git a/samples/subsys/usb/hid-keyboard/CMakeLists.txt b/samples/subsys/usb/hid-keyboard/CMakeLists.txt new file mode 100644 index 0000000000000..76d18842cff3a --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/CMakeLists.txt @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(hid-keyboard) + +include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/hid-keyboard/Kconfig b/samples/subsys/usb/hid-keyboard/Kconfig new file mode 100644 index 0000000000000..96c5455894806 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/Kconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Source common USB sample options used to initialize new experimental USB +# device stack. The scope of these options is limited to USB samples in project +# tree, you cannot use them in your own application. +source "samples/subsys/usb/common/Kconfig.sample_usbd" + +source "Kconfig.zephyr" diff --git a/samples/subsys/usb/hid-keyboard/README.rst b/samples/subsys/usb/hid-keyboard/README.rst new file mode 100644 index 0000000000000..b1936b5558868 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/README.rst @@ -0,0 +1,36 @@ +.. zephyr:code-sample:: usb-hid-keyboard + :name: USB HID keyboard + :relevant-api: usbd_api usbd_hid_class input_interface + + Implement a basic HID keyboard device. + +Overview +******** + +This sample application demonstrates the HID keyboard implementation using the +new experimental USB device stack. + +Requirements +************ + +This project requires an experimental USB device driver (UDC API) and uses the +:ref:`input` API. There must be a :dtcompatible:`gpio-keys` group of buttons +or keys defined at the board level that can generate input events. +At least one key is required and up to four can be used. The first three keys +are used for Num Lock, Caps Lock and Scroll Lock. The fourth key is used to +report HID keys 1, 2, 3 and the right Alt modifier at once. + +The example can use up to three LEDs, configured via the devicetree alias such +as ``led0``, to indicate the state of the keyboard LEDs. + +Building and Running +******************** + +This sample can be built for multiple boards, in this example we will build it +for the nRF52840DK board: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/usb/hid-keyboard + :board: nrf52840dk/nrf52840 + :goals: build flash + :compact: diff --git a/samples/subsys/usb/hid-keyboard/app.overlay b/samples/subsys/usb/hid-keyboard/app.overlay new file mode 100644 index 0000000000000..0d3d2ee7bd855 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/app.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + interface-name = "HID0"; + protocol-code = "keyboard"; + in-report-size = <64>; + in-polling-period-us = <1000>; + }; +}; diff --git a/samples/subsys/usb/hid-keyboard/large_in_report.overlay b/samples/subsys/usb/hid-keyboard/large_in_report.overlay new file mode 100644 index 0000000000000..93b47691a77f3 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/large_in_report.overlay @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + interface-name = "HID0"; + in-report-size = <256>; + in-polling-period-us = <1000>; + }; +}; diff --git a/samples/subsys/usb/hid-keyboard/large_out_report.overlay b/samples/subsys/usb/hid-keyboard/large_out_report.overlay new file mode 100644 index 0000000000000..e5348743d29a3 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/large_out_report.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "large_in_report.overlay" + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + out-report-size = <128>; + out-polling-period-us = <16000>; + }; +}; diff --git a/samples/subsys/usb/hid-keyboard/out_report.overlay b/samples/subsys/usb/hid-keyboard/out_report.overlay new file mode 100644 index 0000000000000..215cc9300dd0f --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/out_report.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "app.overlay" + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + out-report-size = <64>; + out-polling-period-us = <16000>; + }; +}; diff --git a/samples/subsys/usb/hid-keyboard/prj.conf b/samples/subsys/usb/hid-keyboard/prj.conf new file mode 100644 index 0000000000000..04ce14ad588e1 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/prj.conf @@ -0,0 +1,12 @@ +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_HID_SUPPORT=y + +CONFIG_LOG=y +CONFIG_USBD_LOG_LEVEL_WRN=y +CONFIG_USBD_HID_LOG_LEVEL_WRN=y +CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_SAMPLE_USBD_PID=0x0007 + +CONFIG_GPIO=y +CONFIG_INPUT=y +CONFIG_INPUT_MODE_SYNCHRONOUS=y diff --git a/samples/subsys/usb/hid-keyboard/sample.yaml b/samples/subsys/usb/hid-keyboard/sample.yaml new file mode 100644 index 0000000000000..09efcc0560871 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/sample.yaml @@ -0,0 +1,27 @@ +sample: + name: USB HID keyboard sample +common: + harness: button + filter: dt_alias_exists("sw0") and dt_alias_exists("led0") + depends_on: + - usbd + - gpio + platform_allow: + - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp + - frdm_k64f +tests: + sample.usbd.hid-keyboard: + tags: usb + sample.usbd.hid-keyboard.out-report: + tags: usb + extra_args: + - EXTRA_DTC_OVERLAY_FILE="out_report.overlay" + sample.usbd.hid-keyboard.large-report: + tags: usb + extra_args: + - EXTRA_DTC_OVERLAY_FILE="large_in_report.overlay" + sample.usbd.hid-keyboard.large-out-report: + tags: usb + extra_args: + - EXTRA_DTC_OVERLAY_FILE="large_out_report.overlay" diff --git a/samples/subsys/usb/hid-keyboard/src/main.c b/samples/subsys/usb/hid-keyboard/src/main.c new file mode 100644 index 0000000000000..b56fe26c0c7f9 --- /dev/null +++ b/samples/subsys/usb/hid-keyboard/src/main.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +LOG_MODULE_REGISTER(main, LOG_LEVEL_INF); + +static const uint8_t hid_report_desc[] = HID_KEYBOARD_REPORT_DESC(); + +enum kb_leds_idx { + KB_LED_NUMLOCK = 0, + KB_LED_CAPSLOCK, + KB_LED_SCROLLLOCK, + KB_LED_COUNT, +}; + +static const struct gpio_dt_spec kb_leds[KB_LED_COUNT] = { + GPIO_DT_SPEC_GET_OR(DT_ALIAS(led0), gpios, {0}), + GPIO_DT_SPEC_GET_OR(DT_ALIAS(led1), gpios, {0}), + GPIO_DT_SPEC_GET_OR(DT_ALIAS(led2), gpios, {0}), +}; + +enum kb_report_idx { + KB_MOD_KEY = 0, + KB_RESERVED, + KB_KEY_CODE1, + KB_KEY_CODE2, + KB_KEY_CODE3, + KB_KEY_CODE4, + KB_KEY_CODE5, + KB_KEY_CODE6, + KB_REPORT_COUNT, +}; + +struct kb_event { + uint16_t code; + int32_t value; +}; + +K_MSGQ_DEFINE(kb_msgq, sizeof(struct kb_event), 2, 1); + +static uint8_t __aligned(sizeof(void *)) report[KB_REPORT_COUNT]; +static uint32_t kb_duration; +static bool kb_ready; + +static void input_cb(struct input_event *evt) +{ + struct kb_event kb_evt; + + kb_evt.code = evt->code; + kb_evt.value = evt->value; + if (k_msgq_put(&kb_msgq, &kb_evt, K_NO_WAIT) != 0) { + LOG_ERR("Failed to put new input event"); + } +} + +INPUT_CALLBACK_DEFINE(NULL, input_cb); + +static void kb_iface_ready(const struct device *dev, const bool ready) +{ + LOG_INF("HID device %s interface is %s", + dev->name, ready ? "ready" : "not ready"); + kb_ready = ready; +} + +static int kb_get_report(const struct device *dev, + const uint8_t type, const uint8_t id, const uint16_t len, + uint8_t *const buf) +{ + LOG_WRN("Get Report not implemented, Type %u ID %u", type, id); + + return 0; +} + +static int kb_set_report(const struct device *dev, + const uint8_t type, const uint8_t id, const uint16_t len, + const uint8_t *const buf) +{ + if (type != HID_REPORT_TYPE_OUTPUT) { + LOG_WRN("Unsupported report type"); + return -ENOTSUP; + } + + for (unsigned int i = 0; i < ARRAY_SIZE(kb_leds); i++) { + if (kb_leds[i].port == NULL) { + continue; + } + + (void)gpio_pin_set_dt(&kb_leds[i], buf[0] & BIT(i)); + } + + return 0; +} + +/* Idle duration is stored but not used to calculate idle reports. */ +static void kb_set_idle(const struct device *dev, + const uint8_t id, const uint32_t duration) +{ + LOG_INF("Set Idle %u to %u", id, duration); + kb_duration = duration; +} + +static uint32_t kb_get_idle(const struct device *dev, const uint8_t id) +{ + LOG_INF("Get Idle %u to %u", id, kb_duration); + return kb_duration; +} + +static void kb_set_protocol(const struct device *dev, const uint8_t proto) +{ + LOG_INF("Protocol changed to %s", + proto == 0U ? "Boot Protocol" : "Report Protocol"); +} + +static void kb_output_report(const struct device *dev, const uint16_t len, + const uint8_t *const buf) +{ + LOG_HEXDUMP_DBG(buf, len, "o.r."); + kb_set_report(dev, HID_REPORT_TYPE_OUTPUT, 0U, len, buf); +} + +struct hid_device_ops kb_ops = { + .iface_ready = kb_iface_ready, + .get_report = kb_get_report, + .set_report = kb_set_report, + .set_idle = kb_set_idle, + .get_idle = kb_get_idle, + .set_protocol = kb_set_protocol, + .output_report = kb_output_report, +}; + +int main(void) +{ + struct usbd_context *sample_usbd; + const struct device *hid_dev; + int ret; + + for (unsigned int i = 0; i < ARRAY_SIZE(kb_leds); i++) { + if (kb_leds[i].port == NULL) { + continue; + } + + if (!gpio_is_ready_dt(&kb_leds[i])) { + LOG_ERR("LED device %s is not ready", kb_leds[i].port->name); + return -EIO; + } + + ret = gpio_pin_configure_dt(&kb_leds[i], GPIO_OUTPUT_INACTIVE); + if (ret != 0) { + LOG_ERR("Failed to configure the LED pin, %d", ret); + return -EIO; + } + } + + hid_dev = DEVICE_DT_GET_ONE(zephyr_hid_device); + if (!device_is_ready(hid_dev)) { + LOG_ERR("HID Device is not ready"); + return -EIO; + } + + ret = hid_device_register(hid_dev, + hid_report_desc, sizeof(hid_report_desc), + &kb_ops); + if (ret != 0) { + LOG_ERR("Failed to register HID Device, %d", ret); + return ret; + } + + sample_usbd = sample_usbd_init_device(NULL); + if (sample_usbd == NULL) { + LOG_ERR("Failed to initialize USB device"); + return -ENODEV; + } + + /* doc device enable start */ + ret = usbd_enable(sample_usbd); + if (ret) { + LOG_ERR("Failed to enable device support"); + return ret; + } + /* doc device enable end */ + + LOG_INF("HID keyboard sample is initialized"); + + while (true) { + struct kb_event kb_evt; + + k_msgq_get(&kb_msgq, &kb_evt, K_FOREVER); + + switch (kb_evt.code) { + case INPUT_KEY_0: + if (kb_evt.value) { + report[KB_KEY_CODE1] = HID_KEY_NUMLOCK; + } else { + report[KB_KEY_CODE1] = 0; + } + + break; + case INPUT_KEY_1: + if (kb_evt.value) { + report[KB_KEY_CODE2] = HID_KEY_CAPSLOCK; + } else { + report[KB_KEY_CODE2] = 0; + } + + break; + case INPUT_KEY_2: + if (kb_evt.value) { + report[KB_KEY_CODE3] = HID_KEY_SCROLLLOCK; + } else { + report[KB_KEY_CODE3] = 0; + } + + break; + case INPUT_KEY_3: + if (kb_evt.value) { + report[KB_MOD_KEY] = HID_KBD_MODIFIER_RIGHT_ALT; + report[KB_KEY_CODE4] = HID_KEY_1; + report[KB_KEY_CODE5] = HID_KEY_2; + report[KB_KEY_CODE6] = HID_KEY_3; + } else { + report[KB_MOD_KEY] = HID_KBD_MODIFIER_NONE; + report[KB_KEY_CODE4] = 0; + report[KB_KEY_CODE5] = 0; + report[KB_KEY_CODE6] = 0; + } + + break; + default: + LOG_INF("Unrecognized input code %u value %d", + kb_evt.code, kb_evt.value); + continue; + } + + if (!kb_ready) { + LOG_INF("USB HID device is not ready"); + continue; + } + + ret = hid_device_submit_report(hid_dev, sizeof(report), report); + if (ret) { + LOG_ERR("HID submit report error, %d", ret); + } + } + + return 0; +} diff --git a/samples/subsys/usb/hid-mouse/CMakeLists.txt b/samples/subsys/usb/hid-mouse/CMakeLists.txt index d384859f9fce6..d2217c00a4727 100644 --- a/samples/subsys/usb/hid-mouse/CMakeLists.txt +++ b/samples/subsys/usb/hid-mouse/CMakeLists.txt @@ -4,5 +4,6 @@ cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(hid-mouse) +include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources}) diff --git a/samples/subsys/usb/hid-mouse/Kconfig b/samples/subsys/usb/hid-mouse/Kconfig new file mode 100644 index 0000000000000..96c5455894806 --- /dev/null +++ b/samples/subsys/usb/hid-mouse/Kconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2023 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +# Source common USB sample options used to initialize new experimental USB +# device stack. The scope of these options is limited to USB samples in project +# tree, you cannot use them in your own application. +source "samples/subsys/usb/common/Kconfig.sample_usbd" + +source "Kconfig.zephyr" diff --git a/samples/subsys/usb/hid-mouse/sample.yaml b/samples/subsys/usb/hid-mouse/sample.yaml index f638fefc58c21..aaa6a01dea047 100644 --- a/samples/subsys/usb/hid-mouse/sample.yaml +++ b/samples/subsys/usb/hid-mouse/sample.yaml @@ -1,10 +1,25 @@ sample: name: USB HID mouse sample +common: + harness: button + filter: dt_alias_exists("sw0") and dt_alias_exists("led0") + depends_on: + - gpio tests: sample.usb.hid-mouse: depends_on: - usb_device - - gpio - harness: button - filter: dt_alias_exists("sw0") and dt_alias_exists("led0") + platform_exclude: + - frdm_mcxn947/mcxn947/cpu0 + tags: usb + sample.usb_device_next.hid-mouse: + depends_on: + - usbd + platform_allow: + - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp + - frdm_k64f + extra_args: + - CONF_FILE="usbd_next_prj.conf" + - EXTRA_DTC_OVERLAY_FILE="usbd_next.overlay" tags: usb diff --git a/samples/subsys/usb/hid-mouse/src/main.c b/samples/subsys/usb/hid-mouse/src/main.c index 6a297418b4cbb..28b27877acbaf 100644 --- a/samples/subsys/usb/hid-mouse/src/main.c +++ b/samples/subsys/usb/hid-mouse/src/main.c @@ -5,6 +5,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +#include + #include #include @@ -14,6 +16,7 @@ #include #include +#include #include #include @@ -34,10 +37,10 @@ enum mouse_report_idx { MOUSE_REPORT_COUNT = 4, }; -static uint8_t report[MOUSE_REPORT_COUNT]; +static uint8_t __aligned(sizeof(void *)) report[MOUSE_REPORT_COUNT]; static K_SEM_DEFINE(report_sem, 0, 1); -static void status_cb(enum usb_dc_status_code status, const uint8_t *param) +static inline void status_cb(enum usb_dc_status_code status, const uint8_t *param) { usb_status = status; } @@ -93,6 +96,30 @@ static void input_cb(struct input_event *evt) INPUT_CALLBACK_DEFINE(NULL, input_cb); +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) +static int enable_usb_device_next(void) +{ + struct usbd_context *sample_usbd; + int err; + + sample_usbd = sample_usbd_init_device(NULL); + if (sample_usbd == NULL) { + LOG_ERR("Failed to initialize USB device"); + return -ENODEV; + } + + err = usbd_enable(sample_usbd); + if (err) { + LOG_ERR("Failed to enable device support"); + return err; + } + + LOG_DBG("USB device support enabled"); + + return 0; +} +#endif /* IS_ENABLED(CONFIG_USB_DEVICE_STACK_NEXT) */ + int main(void) { const struct device *hid_dev; @@ -103,7 +130,11 @@ int main(void) return 0; } +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) + hid_dev = DEVICE_DT_GET_ONE(zephyr_hid_device); +#else hid_dev = device_get_binding("HID_0"); +#endif if (hid_dev == NULL) { LOG_ERR("Cannot get USB HID Device"); return 0; @@ -121,7 +152,11 @@ int main(void) usb_hid_init(hid_dev); +#if defined(CONFIG_USB_DEVICE_STACK_NEXT) + ret = enable_usb_device_next(); +#else ret = usb_enable(status_cb); +#endif if (ret != 0) { LOG_ERR("Failed to enable USB"); return 0; diff --git a/samples/subsys/usb/hid-mouse/usbd_next.overlay b/samples/subsys/usb/hid-mouse/usbd_next.overlay new file mode 100644 index 0000000000000..ce74aa5187965 --- /dev/null +++ b/samples/subsys/usb/hid-mouse/usbd_next.overlay @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + hid_dev_0: hid_dev_0 { + compatible = "zephyr,hid-device"; + interface-name = "HID0"; + protocol-code = "none"; + in-polling-period-us = <1000>; + in-report-size = <64>; + }; +}; diff --git a/samples/subsys/usb/hid-mouse/usbd_next_prj.conf b/samples/subsys/usb/hid-mouse/usbd_next_prj.conf new file mode 100644 index 0000000000000..9c8894b2126c6 --- /dev/null +++ b/samples/subsys/usb/hid-mouse/usbd_next_prj.conf @@ -0,0 +1,11 @@ +CONFIG_USB_DEVICE_STACK_NEXT=y +CONFIG_USBD_HID_SUPPORT=y + +CONFIG_LOG=y +CONFIG_USBD_LOG_LEVEL_WRN=y +CONFIG_USBD_HID_LOG_LEVEL_WRN=y +CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y +CONFIG_SAMPLE_USBD_PID=0x0007 + +CONFIG_GPIO=y +CONFIG_INPUT=y diff --git a/samples/subsys/usb/mass/sample.yaml b/samples/subsys/usb/mass/sample.yaml index d7c2c32bc5933..8749a0892a33b 100644 --- a/samples/subsys/usb/mass/sample.yaml +++ b/samples/subsys/usb/mass/sample.yaml @@ -21,10 +21,13 @@ tests: - "The device is put in USB mass storage mode." sample.usb_device_next.mass_ram_none: min_ram: 128 - depends_on: usb_device + depends_on: usbd platform_allow: - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f + - mimxrt685_evk/mimxrt685s/cm33 + - mimxrt1060_evk extra_args: - CONF_FILE="usbd_next_prj.conf" - EXTRA_DTC_OVERLAY_FILE="ramdisk.overlay" @@ -88,7 +91,7 @@ tests: min_ram: 32 modules: - fatfs - depends_on: usb_device + depends_on: usbd filter: dt_compat_enabled("nordic,qspi-nor") platform_allow: - nrf52840dk/nrf52840 diff --git a/samples/subsys/usb/mass/src/main.c b/samples/subsys/usb/mass/src/main.c index 0161db85b1f60..733f6f90ea86f 100644 --- a/samples/subsys/usb/mass/src/main.c +++ b/samples/subsys/usb/mass/src/main.c @@ -36,7 +36,7 @@ FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage); static struct fs_mount_t fs_mnt; #if defined(CONFIG_USB_DEVICE_STACK_NEXT) -static struct usbd_contex *sample_usbd; +static struct usbd_context *sample_usbd; #if CONFIG_DISK_DRIVER_RAM USBD_DEFINE_MSC_LUN(RAM, "Zephyr", "RAMDisk", "0.00"); @@ -89,7 +89,7 @@ static int setup_flash(struct fs_mount_t *mnt) if (rc < 0 && IS_ENABLED(CONFIG_APP_WIPE_STORAGE)) { printk("Erasing flash area ... "); - rc = flash_area_erase(pfa, 0, pfa->fa_size); + rc = flash_area_flatten(pfa, 0, pfa->fa_size); printk("%d\n", rc); } diff --git a/samples/subsys/usb/shell/nucleo_f413zh_dwc2.overlay b/samples/subsys/usb/shell/nucleo_f413zh_dwc2.overlay index ff51b08078efc..2e954626ded21 100644 --- a/samples/subsys/usb/shell/nucleo_f413zh_dwc2.overlay +++ b/samples/subsys/usb/shell/nucleo_f413zh_dwc2.overlay @@ -15,6 +15,11 @@ interrupt-names = "fsotg"; clocks = <&rcc STM32_CLOCK_BUS_AHB2 0x00000080>, <&rcc STM32_SRC_PLL_Q NO_SEL>; + num-out-eps = <6>; + num-in-eps = <6>; + ghwcfg1 = <0x00000000>; + ghwcfg2 = <0x229ed520>; + ghwcfg4 = <0x17f08030>; }; }; }; diff --git a/samples/subsys/usb/shell/sample.yaml b/samples/subsys/usb/shell/sample.yaml index 834044da3df5f..c3c88d002f27c 100644 --- a/samples/subsys/usb/shell/sample.yaml +++ b/samples/subsys/usb/shell/sample.yaml @@ -1,15 +1,19 @@ sample: name: USB support shell sample +common: + depends_on: + - usbd tests: sample.usbd.shell: platform_allow: - nrf52840dk/nrf52840 + - nrf54h20dk/nrf54h20/cpuapp - frdm_k64f - depends_on: usb_device + - mimxrt685_evk/mimxrt685s/cm33 + - mimxrt1060_evk harness: keyboard tags: usb sample.usbh.shell: - depends_on: usb_device tags: - usb - shield diff --git a/samples/subsys/usb/uac2_explicit_feedback/sample.yaml b/samples/subsys/usb/uac2_explicit_feedback/sample.yaml index c9d5457470168..a94996f9f1063 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/sample.yaml +++ b/samples/subsys/usb/uac2_explicit_feedback/sample.yaml @@ -3,7 +3,7 @@ sample: tests: sample.subsys.usb.uac2_explicit_feedback: depends_on: - - usb_device + - usbd - i2s tags: usb i2s platform_allow: nrf5340dk/nrf5340/cpuapp diff --git a/samples/subsys/usb/uac2_explicit_feedback/src/main.c b/samples/subsys/usb/uac2_explicit_feedback/src/main.c index 4770560886b09..a09cb2d5d85c4 100644 --- a/samples/subsys/usb/uac2_explicit_feedback/src/main.c +++ b/samples/subsys/usb/uac2_explicit_feedback/src/main.c @@ -255,7 +255,7 @@ static struct usb_i2s_ctx main_ctx; int main(void) { const struct device *dev = DEVICE_DT_GET(DT_NODELABEL(uac2_headphones)); - struct usbd_contex *sample_usbd; + struct usbd_context *sample_usbd; struct i2s_config config; int ret; diff --git a/samples/subsys/video/capture/README.rst b/samples/subsys/video/capture/README.rst index 29dedf2bdf408..67cbcfdacb355 100644 --- a/samples/subsys/video/capture/README.rst +++ b/samples/subsys/video/capture/README.rst @@ -7,25 +7,33 @@ Description *********** -This sample application uses the :ref:`Video API ` to retrieve video frames from the -video capture device, writes a frame count message to the console, and then -discards the video frame data. +This sample application uses the :ref:`video_api` to capture frames from a video capture +device then uses the :ref:`display_api` to display them onto an LCD screen (if any). Requirements ************ -This sample requires a video capture device (e.g. a camera). +This sample needs a video capture device (e.g. a camera) but it is not mandatory. +Supported camera modules on some i.MX RT boards can be found below. + +- `Camera iMXRT`_ - :ref:`mimxrt1064_evk` - `MT9M114 camera module`_ +- :ref:`mimxrt1170_evk` +- `OV5640 camera module`_ + Wiring ****** -On :ref:`mimxrt1064_evk`, The MT9M114 camera module should be plugged in the +On :ref:`mimxrt1064_evk`, the MT9M114 camera module should be plugged in the J35 camera connector. A USB cable should be connected from a host to the micro -USB debug connector (J41) in order to get console output via the freelink -interface. +USB debug connector (J41) in order to get console output via the freelink interface. + +On :ref:`mimxrt1170_evk`, the OV5640 camera module should be plugged into the +J2 camera connector. A USB cable should be connected from a host to the micro +USB debug connector (J11) in order to get console output via the daplink interface. Building and Running ******************** @@ -35,30 +43,57 @@ For :ref:`mimxrt1064_evk`, build this sample application with the following comm .. zephyr-app-commands:: :zephyr-app: samples/subsys/video/capture :board: mimxrt1064_evk + :shield: "dvp_fpc24_mt9m114 rk043fn66hs_ctg" :goals: build :compact: +For :ref:`mimxrt1170_evk`, build this sample application with the following commands: + +.. zephyr-app-commands:: + :zephyr-app: samples/subsys/video/capture + :board: mimxrt1170_evk/mimxrt1176/cm7 + :shield: "nxp_btb44_ov5640 rk055hdmipi4ma0" + :goals: build + :compact: + +For testing purpose without the need of any real video capture and/or display hardwares, +a video software pattern generator is supported by the above build commands without +specifying the shields. + Sample Output ============= .. code-block:: console - Found video device: CSI - width (640,640), height (480,480) - Supported pixelformats (fourcc): - - RGBP - Use default format (640x480) + Video device: csi@402bc000 + - Capabilities: + RGBP width [480; 480; 0] height [272; 272; 0] + YUYV width [480; 480; 0] height [272; 272; 0] + RGBP width [640; 640; 0] height [480; 480; 0] + YUYV width [640; 640; 0] height [480; 480; 0] + RGBP width [1280; 1280; 0] height [720; 720; 0] + YUYV width [1280; 1280; 0] height [720; 720; 0] + - Default format: RGBP 480x272 + + Display device: display-controller@402b8000 + - Capabilities: + x_resolution = 480, y_resolution = 272, supported_pixel_formats = 40 + current_pixel_format = 32, current_orientation = 0 + Capture started - Got frame 743! size: 614400; timestamp 100740 ms - Got frame 744! size: 614400; timestamp 100875 ms - Got frame 745! size: 614400; timestamp 101010 ms - Got frame 746! size: 614400; timestamp 101146 ms - Got frame 747! size: 614400; timestamp 101281 ms - Got frame 748! size: 614400; timestamp 101416 ms + Got frame 0! size: 261120; timestamp 249 ms + Got frame 1! size: 261120; timestamp 282 ms + Got frame 2! size: 261120; timestamp 316 ms + Got frame 3! size: 261120; timestamp 350 ms + Got frame 4! size: 261120; timestamp 384 ms + Got frame 5! size: 261120; timestamp 418 ms + Got frame 6! size: 261120; timestamp 451 ms References ********** +.. _Camera iMXRT: https://community.nxp.com/t5/i-MX-RT-Knowledge-Base/Connecting-camera-and-LCD-to-i-MX-RT-EVKs/ta-p/1122183 .. _MT9M114 camera module: https://www.onsemi.com/PowerSolutions/product.do?id=MT9M114 +.. _OV5640 camera module: https://cdn.sparkfun.com/datasheets/Sensors/LightImaging/OV5640_datasheet.pdf diff --git a/samples/subsys/video/capture/boards/mimxrt1170_evk_mimxrt1176_cm7.conf b/samples/subsys/video/capture/boards/mimxrt1170_evk_mimxrt1176_cm7.conf new file mode 100644 index 0000000000000..7252f9e67c5cb --- /dev/null +++ b/samples/subsys/video/capture/boards/mimxrt1170_evk_mimxrt1176_cm7.conf @@ -0,0 +1,4 @@ +CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=3686800 +CONFIG_DMA=y +CONFIG_MCUX_ELCDIF_PXP=y +CONFIG_MCUX_ELCDIF_PXP_ROTATE_90=y diff --git a/samples/subsys/video/capture/prj.conf b/samples/subsys/video/capture/prj.conf index f8d9f2b955376..ce6dcc316d67e 100644 --- a/samples/subsys/video/capture/prj.conf +++ b/samples/subsys/video/capture/prj.conf @@ -4,3 +4,4 @@ CONFIG_SHELL=y CONFIG_DEVICE_SHELL=y CONFIG_PRINTK=y CONFIG_LOG=y +CONFIG_DISPLAY=y diff --git a/samples/subsys/video/capture/sample.yaml b/samples/subsys/video/capture/sample.yaml index 88c57fc74928f..34eaffdec69c4 100644 --- a/samples/subsys/video/capture/sample.yaml +++ b/samples/subsys/video/capture/sample.yaml @@ -3,10 +3,18 @@ sample: tests: sample.video.capture: build_only: true - tags: video + tags: + - video + - shield + - samples + extra_args: + - platform:mimxrt1064_evk:SHIELD="dvp_fpc24_mt9m114;rk043fn66hs_ctg" + - platform:mimxrt1170_evk/mimxrt1176/cm7:SHIELD="nxp_btb44_ov5640;rk055hdmipi4ma0" platform_allow: - mimxrt1064_evk + - mimxrt1170_evk/mimxrt1176/cm7 - mm_swiftio depends_on: video integration_platforms: - mimxrt1064_evk + - mimxrt1170_evk/mimxrt1176/cm7 diff --git a/samples/subsys/video/capture/src/main.c b/samples/subsys/video/capture/src/main.c index 5018bdf1ecfd3..862dff287f7aa 100644 --- a/samples/subsys/video/capture/src/main.c +++ b/samples/subsys/video/capture/src/main.c @@ -7,6 +7,7 @@ #include #include +#include #include #define LOG_LEVEL CONFIG_LOG_DEFAULT_LEVEL @@ -15,39 +16,93 @@ LOG_MODULE_REGISTER(main); #define VIDEO_DEV_SW "VIDEO_SW_GENERATOR" +#if DT_HAS_CHOSEN(zephyr_display) +static inline int display_setup(const struct device *const display_dev, const uint32_t pixfmt) +{ + struct display_capabilities capabilities; + int ret = 0; + + if (!device_is_ready(display_dev)) { + LOG_ERR("Device %s not found", display_dev->name); + return -ENODEV; + } + + printk("\nDisplay device: %s\n", display_dev->name); + + display_get_capabilities(display_dev, &capabilities); + + printk("- Capabilities:\n"); + printk(" x_resolution = %u, y_resolution = %u, supported_pixel_formats = %u\n" + " current_pixel_format = %u, current_orientation = %u\n\n", + capabilities.x_resolution, capabilities.y_resolution, + capabilities.supported_pixel_formats, capabilities.current_pixel_format, + capabilities.current_orientation); + + /* Set display pixel format to match the one in use by the camera */ + switch (pixfmt) { + case VIDEO_PIX_FMT_RGB565: + ret = display_set_pixel_format(display_dev, PIXEL_FORMAT_BGR_565); + break; + case VIDEO_PIX_FMT_XRGB32: + ret = display_set_pixel_format(display_dev, PIXEL_FORMAT_ARGB_8888); + break; + default: + return -ENOTSUP; + } + + if (ret) { + LOG_ERR("Unable to set display format"); + return ret; + } + + return display_blanking_off(display_dev); +} + +static inline void video_display_frame(const struct device *const display_dev, + const struct video_buffer *const vbuf, + const struct video_format fmt) +{ + struct display_buffer_descriptor buf_desc; + + buf_desc.buf_size = vbuf->bytesused; + buf_desc.width = fmt.width; + buf_desc.pitch = buf_desc.width; + buf_desc.height = fmt.height; + + display_write(display_dev, 0, 0, &buf_desc, vbuf->buffer); +} +#endif + int main(void) { struct video_buffer *buffers[2], *vbuf; struct video_format fmt; struct video_caps caps; - const struct device *video; unsigned int frame = 0; size_t bsize; int i = 0; + int err; + +#if DT_HAS_CHOSEN(zephyr_camera) + const struct device *const video_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); - /* Default to software video pattern generator */ - video = device_get_binding(VIDEO_DEV_SW); - if (video == NULL) { - LOG_ERR("Video device %s not found", VIDEO_DEV_SW); + if (!device_is_ready(video_dev)) { + LOG_ERR("%s: video device is not ready", video_dev->name); return 0; } +#else + const struct device *const video_dev = device_get_binding(VIDEO_DEV_SW); - /* But would be better to use a real video device if any */ -#if defined(CONFIG_VIDEO_MCUX_CSI) - const struct device *const dev = DEVICE_DT_GET_ONE(nxp_imx_csi); - - if (!device_is_ready(dev)) { - LOG_ERR("%s: device not ready.\n", dev->name); + if (video_dev == NULL) { + LOG_ERR("%s: video device not found or failed to initialized", VIDEO_DEV_SW); return 0; } - - video = dev; #endif - printk("- Device name: %s\n", video->name); + printk("Video device: %s\n", video_dev->name); /* Get capabilities */ - if (video_get_caps(video, VIDEO_EP_OUT, &caps)) { + if (video_get_caps(video_dev, VIDEO_EP_OUT, &caps)) { LOG_ERR("Unable to retrieve video capabilities"); return 0; } @@ -57,43 +112,58 @@ int main(void) const struct video_format_cap *fcap = &caps.format_caps[i]; /* fourcc to string */ printk(" %c%c%c%c width [%u; %u; %u] height [%u; %u; %u]\n", - (char)fcap->pixelformat, - (char)(fcap->pixelformat >> 8), - (char)(fcap->pixelformat >> 16), - (char)(fcap->pixelformat >> 24), - fcap->width_min, fcap->width_max, fcap->width_step, - fcap->height_min, fcap->height_max, fcap->height_step); + (char)fcap->pixelformat, (char)(fcap->pixelformat >> 8), + (char)(fcap->pixelformat >> 16), (char)(fcap->pixelformat >> 24), + fcap->width_min, fcap->width_max, fcap->width_step, fcap->height_min, + fcap->height_max, fcap->height_step); i++; } /* Get default/native format */ - if (video_get_format(video, VIDEO_EP_OUT, &fmt)) { + if (video_get_format(video_dev, VIDEO_EP_OUT, &fmt)) { LOG_ERR("Unable to retrieve video format"); return 0; } printk("- Default format: %c%c%c%c %ux%u\n", (char)fmt.pixelformat, - (char)(fmt.pixelformat >> 8), - (char)(fmt.pixelformat >> 16), - (char)(fmt.pixelformat >> 24), - fmt.width, fmt.height); + (char)(fmt.pixelformat >> 8), (char)(fmt.pixelformat >> 16), + (char)(fmt.pixelformat >> 24), fmt.width, fmt.height); + +#if DT_HAS_CHOSEN(zephyr_display) + const struct device *const display_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display)); + + if (!device_is_ready(display_dev)) { + LOG_ERR("%s: display device not ready.", display_dev->name); + return 0; + } + + err = display_setup(display_dev, fmt.pixelformat); + if (err) { + LOG_ERR("Unable to set up display"); + return err; + } +#endif /* Size to allocate for each buffer */ bsize = fmt.pitch * fmt.height; /* Alloc video buffers and enqueue for capture */ for (i = 0; i < ARRAY_SIZE(buffers); i++) { - buffers[i] = video_buffer_alloc(bsize); + /* + * For some hardwares, such as the PxP used on i.MX RT1170 to do image rotation, + * buffer alignment is needed in order to achieve the best performance + */ + buffers[i] = video_buffer_aligned_alloc(bsize, CONFIG_VIDEO_BUFFER_POOL_ALIGN); if (buffers[i] == NULL) { LOG_ERR("Unable to alloc video buffer"); return 0; } - video_enqueue(video, VIDEO_EP_OUT, buffers[i]); + video_enqueue(video_dev, VIDEO_EP_OUT, buffers[i]); } /* Start video capture */ - if (video_stream_start(video)) { + if (video_stream_start(video_dev)) { LOG_ERR("Unable to start capture (interface)"); return 0; } @@ -102,18 +172,20 @@ int main(void) /* Grab video frames */ while (1) { - int err; - - err = video_dequeue(video, VIDEO_EP_OUT, &vbuf, K_FOREVER); + err = video_dequeue(video_dev, VIDEO_EP_OUT, &vbuf, K_FOREVER); if (err) { LOG_ERR("Unable to dequeue video buf"); return 0; } - printk("\rGot frame %u! size: %u; timestamp %u ms", - frame++, vbuf->bytesused, vbuf->timestamp); + printk("Got frame %u! size: %u; timestamp %u ms\n", frame++, vbuf->bytesused, + vbuf->timestamp); + +#if DT_HAS_CHOSEN(zephyr_display) + video_display_frame(display_dev, vbuf, fmt); +#endif - err = video_enqueue(video, VIDEO_EP_OUT, vbuf); + err = video_enqueue(video_dev, VIDEO_EP_OUT, vbuf); if (err) { LOG_ERR("Unable to requeue video buf"); return 0; diff --git a/samples/subsys/video/tcpserversink/README.rst b/samples/subsys/video/tcpserversink/README.rst index 6c7fc89afde4e..83e9a62d9534d 100644 --- a/samples/subsys/video/tcpserversink/README.rst +++ b/samples/subsys/video/tcpserversink/README.rst @@ -29,11 +29,13 @@ interface. Ethernet cable must be connected to RJ45 connector. Building and Running ******************** -For :ref:`mimxrt1064_evk`, build this sample application with the following commands: +For :ref:`mimxrt1064_evk`, the sample can be built with the following command. +If a mt9m114 camera shield is missing, video software generator will be used instead. .. zephyr-app-commands:: :zephyr-app: samples/subsys/video/tcpserversink :board: mimxrt1064_evk + :shield: [dvp_fpc24_mt9m114] :goals: build :compact: @@ -42,7 +44,7 @@ Sample Output .. code-block:: console - Video device detected, format: RGBP 640x480 + Video device detected, format: RGBP 480x272 TCP: Waiting for client... Then from a peer on the same network you can connect and grab frames. @@ -52,11 +54,12 @@ Example with gstreamer: .. code-block:: console gst-launch-1.0 tcpclientsrc host=192.0.2.1 port=5000 \ - ! videoparse format=rgb16 width=640 height=480 \ + ! videoparse format=rgb16 width=480 height=272 \ ! queue \ ! videoconvert \ ! fpsdisplaysink sync=false +For video software generator, the default resolution should be width=320 and height=160. References ********** diff --git a/samples/subsys/video/tcpserversink/prj.conf b/samples/subsys/video/tcpserversink/prj.conf index 43ddea77f51d2..824c424b2fa8a 100644 --- a/samples/subsys/video/tcpserversink/prj.conf +++ b/samples/subsys/video/tcpserversink/prj.conf @@ -3,7 +3,7 @@ CONFIG_NETWORKING=y CONFIG_NET_TCP=y CONFIG_NET_IPV4=y CONFIG_NET_SOCKETS=y -CONFIG_POSIX_MAX_FDS=6 +CONFIG_ZVFS_OPEN_MAX=6 CONFIG_POSIX_API=y # Kernel options diff --git a/samples/subsys/video/tcpserversink/sample.yaml b/samples/subsys/video/tcpserversink/sample.yaml index 6019ce0341ed7..717923a6fa199 100644 --- a/samples/subsys/video/tcpserversink/sample.yaml +++ b/samples/subsys/video/tcpserversink/sample.yaml @@ -7,9 +7,12 @@ tests: - video - net - socket + - shield platform_allow: mimxrt1064_evk depends_on: - video - netif integration_platforms: - mimxrt1064_evk + extra_args: + - platform:mimxrt1064_evk:SHIELD=dvp_fpc24_mt9m114 diff --git a/samples/subsys/video/tcpserversink/src/main.c b/samples/subsys/video/tcpserversink/src/main.c index 020a8f6d2e1bc..90946be44bd88 100644 --- a/samples/subsys/video/tcpserversink/src/main.c +++ b/samples/subsys/video/tcpserversink/src/main.c @@ -15,7 +15,8 @@ #include LOG_MODULE_REGISTER(main); -#define MY_PORT 5000 +#define VIDEO_DEV_SW "VIDEO_SW_GENERATOR" +#define MY_PORT 5000 #define MAX_CLIENT_QUEUE 1 static ssize_t sendall(int sock, const void *buf, size_t len) @@ -40,8 +41,21 @@ int main(void) struct video_buffer *buffers[2], *vbuf; int i, ret, sock, client; struct video_format fmt; - const struct device *const video = DEVICE_DT_GET_ONE(nxp_imx_csi); +#if DT_HAS_CHOSEN(zephyr_camera) + const struct device *const video = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera)); + if (!device_is_ready(video)) { + LOG_ERR("%s: video device not ready.", video->name); + return 0; + } +#else + const struct device *const video = device_get_binding(VIDEO_DEV_SW); + + if (video == NULL) { + LOG_ERR("%s: video device not found or failed to initialized.", VIDEO_DEV_SW); + return 0; + } +#endif /* Prepare Network */ (void)memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; @@ -67,21 +81,15 @@ int main(void) return 0; } - if (!device_is_ready(video)) { - LOG_ERR("%s: device not ready.\n", video->name); - return 0; - } - /* Get default/native format */ if (video_get_format(video, VIDEO_EP_OUT, &fmt)) { LOG_ERR("Unable to retrieve video format"); return 0; } - printk("Video device detected, format: %c%c%c%c %ux%u\n", - (char)fmt.pixelformat, (char)(fmt.pixelformat >> 8), - (char)(fmt.pixelformat >> 16), (char)(fmt.pixelformat >> 24), - fmt.width, fmt.height); + printk("Video device detected, format: %c%c%c%c %ux%u\n", (char)fmt.pixelformat, + (char)(fmt.pixelformat >> 8), (char)(fmt.pixelformat >> 16), + (char)(fmt.pixelformat >> 24), fmt.width, fmt.height); /* Alloc Buffers */ for (i = 0; i < ARRAY_SIZE(buffers); i++) { @@ -96,8 +104,7 @@ int main(void) do { printk("TCP: Waiting for client...\n"); - client = accept(sock, (struct sockaddr *)&client_addr, - &client_addr_len); + client = accept(sock, (struct sockaddr *)&client_addr, &client_addr_len); if (client < 0) { printk("Failed to accept: %d\n", errno); return 0; @@ -121,14 +128,13 @@ int main(void) /* Capture loop */ i = 0; do { - ret = video_dequeue(video, VIDEO_EP_OUT, &vbuf, - K_FOREVER); + ret = video_dequeue(video, VIDEO_EP_OUT, &vbuf, K_FOREVER); if (ret) { LOG_ERR("Unable to dequeue video buf"); return 0; } - printk("\rSending frame %d", i++); + printk("\rSending frame %d\n", i++); /* Send video buffer to TCP client */ ret = sendall(client, vbuf->buffer, vbuf->bytesused); @@ -149,8 +155,7 @@ int main(void) /* Flush remaining buffers */ do { - ret = video_dequeue(video, VIDEO_EP_OUT, - &vbuf, K_NO_WAIT); + ret = video_dequeue(video, VIDEO_EP_OUT, &vbuf, K_NO_WAIT); } while (!ret); } while (1); diff --git a/samples/sysbuild/hello_world/CMakeLists.txt b/samples/sysbuild/hello_world/CMakeLists.txt new file mode 100644 index 0000000000000..f58082ab8dfd8 --- /dev/null +++ b/samples/sysbuild/hello_world/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(hello_world) +target_sources(app PRIVATE src/main.c) diff --git a/samples/sysbuild/hello_world/Kconfig.sysbuild b/samples/sysbuild/hello_world/Kconfig.sysbuild new file mode 100644 index 0000000000000..edec01b94c98d --- /dev/null +++ b/samples/sysbuild/hello_world/Kconfig.sysbuild @@ -0,0 +1,7 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "${ZEPHYR_BASE}/share/sysbuild/Kconfig" + +config REMOTE_BOARD + string "The board used for remote target" diff --git a/samples/sysbuild/hello_world/README.rst b/samples/sysbuild/hello_world/README.rst new file mode 100644 index 0000000000000..161df95beaeb0 --- /dev/null +++ b/samples/sysbuild/hello_world/README.rst @@ -0,0 +1,69 @@ +.. zephyr:code-sample:: sysbuild_hello_world + :name: Hello World for multiple board targets using Sysbuild + + Run a hello world sample on multiple board targets + +Overview +******** + +The sample demonstrates how to build a Hello World application for two board +targets with :ref:`sysbuild`. This sample can be useful to test, for example, +SoCs with multiple cores as each core is exposed as a board target. Other +scenarios could include boards embedding multiple SoCs. When building with +Zephyr Sysbuild, the build system adds additional images based on the options +selected in the project's additional configuration and build files. + +All images use the same :file:`main.c` that prints the board target on which the +application is programmed. + +Building and Running +******************** + +This sample needs to be built with Sysbuild by using the ``--sysbuild`` option. +The remote board needs to be specified using ``SB_CONFIG_REMOTE_BOARD``. Some +additional settings may be required depending on the platform, for example, +to boot a remote core. + +.. note:: + It is recommended to use sample setups from + :zephyr_file:`samples/sysbuild/hello_world/sample.yaml` using the + ``-T`` option. + +Here's an example to build and flash the sample for the +:ref:`nrf54h20dk_nrf54h20`, using application and radio cores: + +.. zephyr-app-commands:: + :zephyr-app: samples/sysbuild/hello_world + :board: nrf54h20dk/nrf54h20/cpuapp + :west-args: --sysbuild + :gen-args: -DSB_CONFIG_REMOTE_BOARD='"nrf54h20dk/nrf54h20/cpurad"' + :goals: build flash + :compact: + +The same can be achieved by using the +:zephyr_file:`samples/basic/multitarget_hello_world/sample.yaml` setup: + +.. zephyr-app-commands:: + :zephyr-app: samples/sysbuild/hello_world + :board: nrf54h20dk/nrf54h20/cpuapp + :west-args: -T sample.sysbuild.hello_world.nrf54h20dk_cpuapp_cpurad + :goals: build flash + :compact: + +After programming the sample to your board, you should observe a hello world +message in the Zephyr console configured on each target. For example, for the +sample above: + +Application core + + .. code-block:: console + + *** Booting Zephyr OS build v3.6.0-274-g466084bd8c5d *** + Hello world from nrf54h20dk/nrf54h20/cpuapp + +Radio core + + .. code-block:: console + + *** Booting Zephyr OS build v3.6.0-274-g466084bd8c5d *** + Hello world from nrf54h20dk/nrf54h20/cpurad diff --git a/samples/sysbuild/hello_world/boards/nrf5340dk_nrf5340_cpuapp.conf b/samples/sysbuild/hello_world/boards/nrf5340dk_nrf5340_cpuapp.conf new file mode 100644 index 0000000000000..046b18c7559ab --- /dev/null +++ b/samples/sysbuild/hello_world/boards/nrf5340dk_nrf5340_cpuapp.conf @@ -0,0 +1,4 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_BOARD_ENABLE_CPUNET=y diff --git a/samples/sysbuild/hello_world/prj.conf b/samples/sysbuild/hello_world/prj.conf new file mode 100644 index 0000000000000..becd6a5481915 --- /dev/null +++ b/samples/sysbuild/hello_world/prj.conf @@ -0,0 +1 @@ +# no additional configuration is required diff --git a/samples/sysbuild/hello_world/remote/CMakeLists.txt b/samples/sysbuild/hello_world/remote/CMakeLists.txt new file mode 100644 index 0000000000000..62961aff1840b --- /dev/null +++ b/samples/sysbuild/hello_world/remote/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(remote) +target_sources(app PRIVATE ../src/main.c) diff --git a/samples/sysbuild/hello_world/remote/prj.conf b/samples/sysbuild/hello_world/remote/prj.conf new file mode 100644 index 0000000000000..becd6a5481915 --- /dev/null +++ b/samples/sysbuild/hello_world/remote/prj.conf @@ -0,0 +1 @@ +# no additional configuration is required diff --git a/samples/sysbuild/hello_world/sample.yaml b/samples/sysbuild/hello_world/sample.yaml new file mode 100644 index 0000000000000..5add79c52ba82 --- /dev/null +++ b/samples/sysbuild/hello_world/sample.yaml @@ -0,0 +1,44 @@ +sample: + name: Hello World for multiple board targets using Sysbuild + description: | + Hello World application that builds for multiple targets. Both images print + the board target they were run on. + +common: + build_only: true + sysbuild: true + +tests: + sample.sysbuild.hello_world.nrf5340dk_cpuapp_cpunet: + platform_allow: + - nrf5340dk/nrf5340/cpuapp + integration_platforms: + - nrf5340dk/nrf5340/cpuapp + extra_args: + SB_CONF_FILE=sysbuild/nrf5340dk_nrf5340_cpunet.conf + + sample.sysbuild.hello_world.nrf54h20dk_cpuapp_cpurad: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpurad.conf + + sample.sysbuild.hello_world.nrf54h20dk_cpuapp_cpuppr: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf + hello_world_SNIPPET=nordic-ppr + + sample.sysbuild.hello_world.nrf54h20dk_cpuapp_cpuppr_xip: + platform_allow: + - nrf54h20dk/nrf54h20/cpuapp + integration_platforms: + - nrf54h20dk/nrf54h20/cpuapp + extra_args: + SB_CONF_FILE=sysbuild/nrf54h20dk_nrf54h20_cpuppr_xip.conf + hello_world_SNIPPET=nordic-ppr-xip diff --git a/samples/sysbuild/hello_world/src/main.c b/samples/sysbuild/hello_world/src/main.c new file mode 100644 index 0000000000000..af5b6fd3dbe74 --- /dev/null +++ b/samples/sysbuild/hello_world/src/main.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +int main(void) +{ + printk("Hello world from %s\n", CONFIG_BOARD_TARGET); + + return 0; +} diff --git a/samples/sysbuild/hello_world/sysbuild.cmake b/samples/sysbuild/hello_world/sysbuild.cmake new file mode 100644 index 0000000000000..b59062d881f17 --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild.cmake @@ -0,0 +1,15 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if("${SB_CONFIG_REMOTE_BOARD}" STREQUAL "") + message(FATAL_ERROR "REMOTE_BOARD must be set to a valid board name") +endif() + +ExternalZephyrProject_Add( + APPLICATION remote + SOURCE_DIR ${APP_DIR}/remote + BOARD ${SB_CONFIG_REMOTE_BOARD} +) + +add_dependencies(hello_world remote) +sysbuild_add_dependencies(FLASH hello_world remote) diff --git a/samples/sysbuild/hello_world/sysbuild/nrf5340dk_nrf5340_cpunet.conf b/samples/sysbuild/hello_world/sysbuild/nrf5340dk_nrf5340_cpunet.conf new file mode 100644 index 0000000000000..b8ae05d4ef6fa --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild/nrf5340dk_nrf5340_cpunet.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf5340dk/nrf5340/cpunet" diff --git a/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf new file mode 100644 index 0000000000000..f50bc8553a011 --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpuppr" diff --git a/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr_xip.conf b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr_xip.conf new file mode 100644 index 0000000000000..270c92c09a4f3 --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpuppr_xip.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpuppr/xip" diff --git a/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf new file mode 100644 index 0000000000000..dd863e78d9933 --- /dev/null +++ b/samples/sysbuild/hello_world/sysbuild/nrf54h20dk_nrf54h20_cpurad.conf @@ -0,0 +1 @@ +SB_CONFIG_REMOTE_BOARD="nrf54h20dk/nrf54h20/cpurad" diff --git a/samples/sysbuild/sysbuild.rst b/samples/sysbuild/sysbuild.rst new file mode 100644 index 0000000000000..c959e82a3a3ba --- /dev/null +++ b/samples/sysbuild/sysbuild.rst @@ -0,0 +1,10 @@ +.. _sysbuild-samples: + +Sysbuild samples +################ + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/application_development/sysbuild/with_mcuboot/CMakeLists.txt b/samples/sysbuild/with_mcuboot/CMakeLists.txt similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/CMakeLists.txt rename to samples/sysbuild/with_mcuboot/CMakeLists.txt diff --git a/samples/application_development/sysbuild/with_mcuboot/README.rst b/samples/sysbuild/with_mcuboot/README.rst similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/README.rst rename to samples/sysbuild/with_mcuboot/README.rst diff --git a/samples/application_development/sysbuild/with_mcuboot/prj.conf b/samples/sysbuild/with_mcuboot/prj.conf similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/prj.conf rename to samples/sysbuild/with_mcuboot/prj.conf diff --git a/samples/sysbuild/with_mcuboot/sample.yaml b/samples/sysbuild/with_mcuboot/sample.yaml new file mode 100644 index 0000000000000..e1f456405a7cc --- /dev/null +++ b/samples/sysbuild/with_mcuboot/sample.yaml @@ -0,0 +1,20 @@ +sample: + description: Sample with MCUboot built through sysbuild + name: with mcuboot +tests: + sample.sysbuild.with_mcuboot: + sysbuild: true + # Platform allowed is used as twister using sysbuild still lacks proper + # filtering support, see discussion in #49552. + platform_allow: + - reel_board + - nrf52840dk/nrf52840 + integration_platforms: + - nrf52840dk/nrf52840 + tags: mcuboot + harness: console + harness_config: + type: multi_line + regex: + - "Address of sample(.*)" + - "Hello sysbuild with mcuboot!(.*)" diff --git a/samples/application_development/sysbuild/with_mcuboot/src/main.c b/samples/sysbuild/with_mcuboot/src/main.c similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/src/main.c rename to samples/sysbuild/with_mcuboot/src/main.c diff --git a/samples/application_development/sysbuild/with_mcuboot/sysbuild.conf b/samples/sysbuild/with_mcuboot/sysbuild.conf similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/sysbuild.conf rename to samples/sysbuild/with_mcuboot/sysbuild.conf diff --git a/samples/application_development/sysbuild/with_mcuboot/sysbuild/mcuboot.conf b/samples/sysbuild/with_mcuboot/sysbuild/mcuboot.conf similarity index 100% rename from samples/application_development/sysbuild/with_mcuboot/sysbuild/mcuboot.conf rename to samples/sysbuild/with_mcuboot/sysbuild/mcuboot.conf diff --git a/samples/tfm_integration/psa_crypto/CMakeLists.txt b/samples/tfm_integration/psa_crypto/CMakeLists.txt index f8ef1eca23fb7..8a91d138de7b8 100644 --- a/samples/tfm_integration/psa_crypto/CMakeLists.txt +++ b/samples/tfm_integration/psa_crypto/CMakeLists.txt @@ -19,11 +19,9 @@ target_include_directories(app PRIVATE $/api_ns/interface/include ) -# In TF-M, default value of CRYPTO_ENGINE_BUF_SIZE is 0x2080. It causes -# insufficient memory failure while verifying signature. Increase it to 0x2400. set_property(TARGET zephyr_property_target APPEND PROPERTY TFM_CMAKE_OPTIONS - -DCRYPTO_ENGINE_BUF_SIZE=0x2400 + -DPROJECT_CONFIG_HEADER_FILE=${CMAKE_CURRENT_SOURCE_DIR}/src/configs/config_tfm.h ) -zephyr_include_directories(${APPLICATION_SOURCE_DIR}/src/tls_config) +zephyr_include_directories(${APPLICATION_SOURCE_DIR}/src/configs) diff --git a/samples/tfm_integration/psa_crypto/prj.conf b/samples/tfm_integration/psa_crypto/prj.conf index a7ac8db8f2e14..0abda9534232f 100644 --- a/samples/tfm_integration/psa_crypto/prj.conf +++ b/samples/tfm_integration/psa_crypto/prj.conf @@ -26,13 +26,20 @@ CONFIG_MBEDTLS_BUILTIN=y CONFIG_MBEDTLS_ENABLE_HEAP=y CONFIG_MBEDTLS_HEAP_SIZE=32768 CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y -CONFIG_MBEDTLS_USER_CONFIG_FILE="user-tls-conf.h" +CONFIG_MBEDTLS_USER_CONFIG_FILE="config_mbedtls.h" CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_PSA_WANT_KEY_TYPE_ECC_PUBLIC_KEY=y +CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR_BASIC=y +CONFIG_PSA_WANT_ECC_SECP_R1_256=y +CONFIG_PSA_WANT_ALG_ECDSA=y +CONFIG_PSA_WANT_KEY_TYPE_RSA_PUBLIC_KEY=y CONFIG_MBEDTLS_ENTROPY_ENABLED=y CONFIG_MBEDTLS_ECP_C=y CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=y +CONFIG_MBEDTLS_PK_WRITE_C=y # JSON CONFIG_JSON_LIBRARY=y diff --git a/samples/tfm_integration/psa_crypto/src/tls_config/user-tls-conf.h b/samples/tfm_integration/psa_crypto/src/configs/config_mbedtls.h similarity index 100% rename from samples/tfm_integration/psa_crypto/src/tls_config/user-tls-conf.h rename to samples/tfm_integration/psa_crypto/src/configs/config_mbedtls.h diff --git a/samples/tfm_integration/psa_crypto/src/configs/config_tfm.h b/samples/tfm_integration/psa_crypto/src/configs/config_tfm.h new file mode 100644 index 0000000000000..38b24d6e78ce1 --- /dev/null +++ b/samples/tfm_integration/psa_crypto/src/configs/config_tfm.h @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2024 Nordic Semiconductor + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* In TF-M the default value of CRYPTO_ENGINE_BUF_SIZE is 0x2080. + * It causes insufficient memory failure while verifying signature. + */ +#define CRYPTO_ENGINE_BUF_SIZE 0x2400 diff --git a/samples/tfm_integration/psa_crypto/src/main.c b/samples/tfm_integration/psa_crypto/src/main.c index a354cf97f1479..1fd0888d8ce8a 100644 --- a/samples/tfm_integration/psa_crypto/src/main.c +++ b/samples/tfm_integration/psa_crypto/src/main.c @@ -44,5 +44,7 @@ int main(void) /* Dump any queued log messages, and wait for system events. */ al_dump_log(); + LOG_INF("Done."); + return 0; } diff --git a/samples/tfm_integration/psa_crypto/src/psa_crypto.c b/samples/tfm_integration/psa_crypto/src/psa_crypto.c index b94edcd8b2afc..6a934c1c15e3c 100644 --- a/samples/tfm_integration/psa_crypto/src/psa_crypto.c +++ b/samples/tfm_integration/psa_crypto/src/psa_crypto.c @@ -510,7 +510,7 @@ void crp_generate_csr(void) LOG_INF("Certificate Signing Request in JSON:\n"); al_dump_log(); - printf("%s\n", json_encoded_buf); + printf("%s\n\n", json_encoded_buf); /* Close the key to free up the volatile slot. */ status = al_psa_status( diff --git a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt index 0d11c021627fb..03f55dccad136 100644 --- a/samples/tfm_integration/tfm_psa_test/CMakeLists.txt +++ b/samples/tfm_integration/tfm_psa_test/CMakeLists.txt @@ -22,18 +22,7 @@ get_target_property(TFM_TOOLCHAIN_PREFIX tfm TFM_TOOLCHAIN_PREFIX) get_target_property(TFM_TOOLCHAIN_NS_FILE tfm TFM_TOOLCHAIN_NS_FILE) set(TFM_TEST_REPO_PATH ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/../tf-m-tests) -set(TFM_PSA_ARCHTEST_REPO_PATH ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/../psa-arch-tests) - -if (CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION AND CONFIG_TFM_QCBOR_PATH STREQUAL "") -# TODO: Remove this when QCBOR licensing issues w/t_cose have been resolved, -# or only allow it when 'QCBOR_PATH' is set to a local path where QCBOR has -# been manually downloaded by the user before starting the build. -message(FATAL_ERROR "CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION is not available " - "with TF-M 2.0.0 due to licensing issues with a dependent library. This " - "restriction will be removed once licensing issues have been resolved." - ) -endif() - +set(PSA_ARCH_TESTS_PATH ${ZEPHYR_TRUSTED_FIRMWARE_M_MODULE_DIR}/../psa-arch-tests) set(TFM_TEST_DIR "${TFM_TEST_REPO_PATH}/tests_psa_arch/spe/partitions") set(PSA_ARCH_TESTS_CONFIG_FILE "${TFM_TEST_REPO_PATH}/tests_psa_arch/spe/config/config_test_psa_api.cmake") @@ -50,17 +39,13 @@ set(TFM_PSA_TEST_SUITE INITIAL_ATTESTATION) endif() if (NOT DEFINED TFM_PSA_TEST_SUITE) - message(FATAL_ERROR "Please define witch test suite to run: - CONFIG_TFM_PSA_TEST_CRYPTO - CONFIG_TFM_PSA_TEST_PROTECTED_STORAGE - CONFIG_TFM_PSA_TEST_STORAGE - CONFIG_TFM_PSA_TEST_INITIAL_ATTESTATION") + message(FATAL_ERROR "Please define a test suite to run. Refer to the README to see the available test suites.") endif() set(TEST_PSA_API "${TFM_PSA_TEST_SUITE}") set_property(TARGET zephyr_property_target APPEND PROPERTY TFM_CMAKE_OPTIONS - -DPSA_ARCH_TESTS_PATH=${TFM_PSA_ARCHTEST_REPO_PATH} + -DPSA_ARCH_TESTS_PATH=${PSA_ARCH_TESTS_PATH} ) set_property(TARGET zephyr_property_target diff --git a/samples/userspace/prod_consumer/boards/frdm_rw612.overlay b/samples/userspace/prod_consumer/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/samples/userspace/prod_consumer/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/samples/userspace/prod_consumer/boards/rd_rw612_bga.overlay b/samples/userspace/prod_consumer/boards/rd_rw612_bga.overlay new file mode 100644 index 0000000000000..b78c0344f1eb0 --- /dev/null +++ b/samples/userspace/prod_consumer/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/samples/userspace/prod_consumer/src/app_syscall.c b/samples/userspace/prod_consumer/src/app_syscall.c index c1b630ba9f2ad..28090260c5a24 100644 --- a/samples/userspace/prod_consumer/src/app_syscall.c +++ b/samples/userspace/prod_consumer/src/app_syscall.c @@ -54,4 +54,4 @@ static int z_vrfy_magic_syscall(unsigned int *cookie) return ret; } -#include +#include diff --git a/samples/userspace/prod_consumer/src/app_syscall.h b/samples/userspace/prod_consumer/src/app_syscall.h index 7a6d1ff19b6c8..cda913ac6c588 100644 --- a/samples/userspace/prod_consumer/src/app_syscall.h +++ b/samples/userspace/prod_consumer/src/app_syscall.h @@ -8,6 +8,6 @@ __syscall int magic_syscall(unsigned int *cookie); -#include +#include #endif /* MAGIC_SYSCALL_H */ diff --git a/samples/userspace/prod_consumer/src/sample_driver.h b/samples/userspace/prod_consumer/src/sample_driver.h index 0f5eaecee5d40..88329313434aa 100644 --- a/samples/userspace/prod_consumer/src/sample_driver.h +++ b/samples/userspace/prod_consumer/src/sample_driver.h @@ -86,6 +86,6 @@ static inline int sample_driver_set_callback(const struct device *dev, return api->set_callback(dev, cb, context); } -#include +#include #endif diff --git a/samples/userspace/prod_consumer/src/sample_driver_handlers.c b/samples/userspace/prod_consumer/src/sample_driver_handlers.c index 89a4ff1204462..333204eac7966 100644 --- a/samples/userspace/prod_consumer/src/sample_driver_handlers.c +++ b/samples/userspace/prod_consumer/src/sample_driver_handlers.c @@ -17,7 +17,7 @@ int z_vrfy_sample_driver_state_set(const struct device *dev, bool active) return z_impl_sample_driver_state_set(dev, active); } -#include +#include int z_vrfy_sample_driver_write(const struct device *dev, void *buf) { @@ -31,4 +31,4 @@ int z_vrfy_sample_driver_write(const struct device *dev, void *buf) return z_impl_sample_driver_write(dev, buf); } -#include +#include diff --git a/samples/userspace/shared_mem/boards/frdm_rw612.overlay b/samples/userspace/shared_mem/boards/frdm_rw612.overlay new file mode 100644 index 0000000000000..5df8d83c40b87 --- /dev/null +++ b/samples/userspace/shared_mem/boards/frdm_rw612.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2024 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/samples/userspace/shared_mem/boards/rd_rw612_bga.overlay b/samples/userspace/shared_mem/boards/rd_rw612_bga.overlay new file mode 100644 index 0000000000000..b78c0344f1eb0 --- /dev/null +++ b/samples/userspace/shared_mem/boards/rd_rw612_bga.overlay @@ -0,0 +1,17 @@ +/* + * Copyright 2023 NXP + * + * SPDX-License-Identifier: Apache-2.0 + */ + +&smu1 { + smu1_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; + +&smu2 { + smu2_data: memory@0 { + /delete-property/ zephyr,memory-attr; + }; +}; diff --git a/scripts/build/gen_symtab.py b/scripts/build/gen_symtab.py new file mode 100644 index 0000000000000..ac20506a645b5 --- /dev/null +++ b/scripts/build/gen_symtab.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 Meta Platforms +# +# SPDX-License-Identifier: Apache-2.0 + +import argparse +import sys +import os +import re + +from elftools.elf.elffile import ELFFile +from elftools.elf.descriptions import ( + describe_symbol_type, +) + + +class gen_symtab_log: + + def __init__(self, debug=False): + self.__debug = debug + + def debug(self, text): + """Print debug message if debugging is enabled. + + Note - this function requires config global variable to be initialized. + """ + if self.__debug: + sys.stdout.write(os.path.basename( + sys.argv[0]) + ": " + text + "\n") + + @staticmethod + def error(text): + sys.exit(os.path.basename(sys.argv[0]) + ": error: " + text + "\n") + + def set_debug(self, state): + self.__debug = state + + +log = gen_symtab_log() + + +def parse_args(): + parser = argparse.ArgumentParser(description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False) + + parser.add_argument("-k", "--kernel", required=True, + help="Zephyr kernel image") + parser.add_argument("-o", "--output", required=True, + help="Output source file") + parser.add_argument("-d", "--debug", action="store_true", + help="Print additional debugging information") + + return parser.parse_args() + + +class symtab_entry: + def __init__(self, addr, size, offset, name): + self.addr = addr + self.size = size + self.offset = offset + self.name = name + + def __eq__(self, other): + return self.addr == other.addr + + +first_addr = 0 +symtab_list = [] + + +def sanitize_func_name(name): + pattern = r'(^[a-zA-Z_][a-zA-Z0-9_]*)' + match = re.match(pattern, name) + if match: + return match.group(0) + else: + log.error(f"Failed to sanitize function name: {name}") + + return name + + +def main(): + args = parse_args() + log.set_debug(args.debug) + + with open(args.kernel, "rb") as rf: + elf = ELFFile(rf) + + # Find the symbol table. + symtab = elf.get_section_by_name('.symtab') + + i = 1 + for nsym, symbol in enumerate(symtab.iter_symbols()): # pylint: disable=unused-variable + symbol_type = describe_symbol_type(symbol['st_info']['type']) + symbol_addr = symbol['st_value'] + symbol_size = symbol['st_size'] + + if symbol_type == 'FUNC' and symbol_addr != 0: + symbol_name = sanitize_func_name(symbol.name) + dummy_offset = 0 # offsets will be calculated later after we know the first address + entry = symtab_entry( + symbol_addr, symbol_size, dummy_offset, symbol_name) + # Prevent entries with duplicated addresses + if entry not in symtab_list: + symtab_list.append(entry) + + # Sort the address in ascending order + symtab_list.sort(key=lambda x: x.addr, reverse=False) + + # Get the address of the first symbol + first_addr = symtab_list[0].addr + + for i, entry in enumerate(symtab_list): + # Offset is calculated here + entry.offset = entry.addr - first_addr + + # Debug print + log.debug('%6d: %s %s %.25s' % ( + i, + hex(entry.addr), + hex(entry.size), + entry.name)) + + with open(args.output, 'w') as wf: + print("/* AUTO-GENERATED by gen_symtab.py, do not edit! */", file=wf) + print("", file=wf) + print("#include ", file=wf) + print("#include ", file=wf) + print("", file=wf) + print( + f"const struct z_symtab_entry __symtab_entry z_symtab_entries[{len(symtab_list) + 1}] = {{", file=wf) + for i, entry in enumerate(symtab_list): + print( + f"\t/* ADDR: {hex(entry.addr)} SIZE: {hex(entry.size)} */", file=wf) + print( + f"\t[{i}] = {{.offset = {hex(entry.offset)}, .name = \"{entry.name}\"}},", file=wf) + + # Append a dummy entry at the end to facilitate the binary search + if symtab_list[-1].size == 0: + dummy_offset = f"{hex(symtab_list[-1].offset)} + sizeof(uintptr_t)" + else: + dummy_offset = f"{hex(symtab_list[-1].offset + symtab_list[-1].size)}" + print("\t/* dummy entry */", file=wf) + print( + f"\t[{len(symtab_list)}] = {{.offset = {dummy_offset}, .name = \"?\"}},", file=wf) + print(f"}};\n", file=wf) + + print(f"const struct symtab_info __symtab_info z_symtab = {{", file=wf) + print(f"\t.first_addr = {hex(first_addr)},", file=wf) + print(f"\t.length = {len(symtab_list)},", file=wf) + print(f"\t.entries = z_symtab_entries,", file=wf) + print(f"}};\n", file=wf) + + +if __name__ == "__main__": + main() diff --git a/scripts/build/gen_syscalls.py b/scripts/build/gen_syscalls.py index 8755f3c649aac..84f6b546bde58 100755 --- a/scripts/build/gen_syscalls.py +++ b/scripts/build/gen_syscalls.py @@ -91,7 +91,7 @@ #include -#include +#include #include #include @@ -205,21 +205,27 @@ def union_decl(type, split): middle = "struct { uintptr_t lo, hi; } split" if split else "uintptr_t x" return "union { %s; %s val; }" % (middle, type) -def wrapper_defs(func_name, func_type, args, fn): +def wrapper_defs(func_name, func_type, args, fn, userspace_only): ret64 = need_split(func_type) mrsh_args = [] # List of rvalue expressions for the marshalled invocation decl_arglist = ", ".join([" ".join(argrec) for argrec in args]) or "void" syscall_id = "K_SYSCALL_" + func_name.upper() - wrap = "extern %s z_impl_%s(%s);\n" % (func_type, func_name, decl_arglist) - wrap += "\n" + wrap = '' + if not userspace_only: + wrap += "extern %s z_impl_%s(%s);\n" % (func_type, func_name, decl_arglist) + wrap += "\n" + wrap += "__pinned_func\n" wrap += "static inline %s %s(%s)\n" % (func_type, func_name, decl_arglist) wrap += "{\n" - wrap += "#ifdef CONFIG_USERSPACE\n" + if not userspace_only: + wrap += "#ifdef CONFIG_USERSPACE\n" + wrap += ("\t" + "uint64_t ret64;\n") if ret64 else "" - wrap += "\t" + "if (z_syscall_trap()) {\n" + if not userspace_only: + wrap += "\t" + "if (z_syscall_trap()) {\n" valist_args = [] for argnum, (argtype, argname) in enumerate(args): @@ -267,18 +273,19 @@ def wrapper_defs(func_name, func_type, args, fn): for argname in valist_args: wrap += "\t\t" + "va_end(%s);\n" % argname wrap += retcode - wrap += "\t" + "}\n" - wrap += "#endif\n" - - # Otherwise fall through to direct invocation of the impl func. - # Note the compiler barrier: that is required to prevent code from - # the impl call from being hoisted above the check for user - # context. - impl_arglist = ", ".join([argrec[1] for argrec in args]) - impl_call = "z_impl_%s(%s)" % (func_name, impl_arglist) - wrap += "\t" + "compiler_barrier();\n" - wrap += "\t" + "%s%s;\n" % ("return " if func_type != "void" else "", - impl_call) + if not userspace_only: + wrap += "\t" + "}\n" + wrap += "#endif\n" + + # Otherwise fall through to direct invocation of the impl func. + # Note the compiler barrier: that is required to prevent code from + # the impl call from being hoisted above the check for user + # context. + impl_arglist = ", ".join([argrec[1] for argrec in args]) + impl_call = "z_impl_%s(%s)" % (func_name, impl_arglist) + wrap += "\t" + "compiler_barrier();\n" + wrap += "\t" + "%s%s;\n" % ("return " if func_type != "void" else "", + impl_call) wrap += "}\n" @@ -377,7 +384,7 @@ def marshall_defs(func_name, func_type, args): return mrsh, mrsh_name -def analyze_fn(match_group, fn): +def analyze_fn(match_group, fn, userspace_only): func, args = match_group try: @@ -395,7 +402,7 @@ def analyze_fn(match_group, fn): marshaller = None marshaller, handler = marshall_defs(func_name, func_type, args) - invocation = wrapper_defs(func_name, func_type, args, fn) + invocation = wrapper_defs(func_name, func_type, args, fn, userspace_only) # Entry in _k_syscall_table table_entry = "[%s] = %s" % (sys_id, handler) @@ -424,6 +431,8 @@ def parse_args(): help="Generate marshalling files (*_mrsh.c)") parser.add_argument("-e", "--syscall-export-llext", help="output C system call export for extensions") + parser.add_argument("-u", "--userspace-only", action="store_true", + help="Only generate the userpace path of wrappers") args = parser.parse_args() @@ -448,7 +457,7 @@ def main(): exported = [] for match_group, fn, to_emit in syscalls: - handler, inv, mrsh, sys_id, entry = analyze_fn(match_group, fn) + handler, inv, mrsh, sys_id, entry = analyze_fn(match_group, fn, args.userspace_only) if fn not in invocations: invocations[fn] = [] @@ -467,7 +476,7 @@ def main(): if mrsh and to_emit: syscall = typename_split(match_group[0])[1] mrsh_defs[syscall] = mrsh - mrsh_includes[syscall] = "#include " % fn + mrsh_includes[syscall] = "#include " % fn with open(args.syscall_dispatch, "w") as fp: table_entries.append("[K_SYSCALL_BAD] = handler_bad_syscall") diff --git a/scripts/build/llext_inject_slids.py b/scripts/build/llext_inject_slids.py new file mode 100755 index 0000000000000..19e87edba9338 --- /dev/null +++ b/scripts/build/llext_inject_slids.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +"""Injects SLIDs in LLEXT ELFs' symbol tables. + +When Kconfig option CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID is enabled, +all imports from the Zephyr kernel & application are resolved using +SLIDs instead of symbol names. This script stores the SLID of all +imported symbols in their associated entry in the ELF symbol table +to allow the LLEXT subsystem to link it properly at runtime. + +Note that this script is idempotent in theory. However, to prevent +any catastrophic problem, the script will abort if the 'st_value' +field of the `ElfX_Sym` structure is found to be non-zero, which is +the case after one invocation. For this reason, in practice, the script +cannot actually be executed twice on the same ELF file. +""" + +import argparse +import logging +import shutil +import sys + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import SymbolTableSection + +import llext_slidlib + +class LLEXTSymtabPreparator(): + def __init__(self, elf_path, log): + self.log = log + self.elf_path = elf_path + self.elf_fd = open(elf_path, "rb+") + self.elf = ELFFile(self.elf_fd) + + def _find_symtab(self): + supported_symtab_sections = [ + ".symtab", + ".dynsym", + ] + + symtab = None + for section_name in supported_symtab_sections: + symtab = self.elf.get_section_by_name(section_name) + if not isinstance(symtab, SymbolTableSection): + self.log.debug(f"section {section_name} not found.") + else: + self.log.info(f"processing '{section_name}' symbol table...") + self.log.debug(f"(symbol table is at file offset 0x{symtab['sh_offset']:X})") + break + return symtab + + def _find_imports_in_symtab(self, symtab): + i = 0 + imports = [] + for sym in symtab.iter_symbols(): + #Check if symbol is an import + if sym.entry['st_info']['type'] == 'STT_NOTYPE' and \ + sym.entry['st_info']['bind'] == 'STB_GLOBAL' and \ + sym.entry['st_shndx'] == 'SHN_UNDEF': + + self.log.debug(f"found imported symbol '{sym.name}' at index {i}") + imports.append((i, sym)) + + i += 1 + return imports + + def _prepare_inner(self): + #1) Locate the symbol table + symtab = self._find_symtab() + if symtab is None: + self.log.error("no symbol table found in file") + return 1 + + #2) Find imported symbols in symbol table + imports = self._find_imports_in_symtab(symtab) + self.log.info(f"LLEXT has {len(imports)} import(s)") + + #3) Write SLIDs in each symbol's 'st_value' field + def make_stvalue_reader_writer(): + byteorder = "little" if self.elf.little_endian else "big" + if self.elf.elfclass == 32: + sizeof_Elf_Sym = 0x10 #sizeof(Elf32_Sym) + offsetof_st_value = 0x4 #offsetof(Elf32_Sym, st_value) + sizeof_st_value = 0x4 #sizeof(Elf32_Sym.st_value) + else: + sizeof_Elf_Sym = 0x18 + offsetof_st_value = 0x8 + sizeof_st_value = 0x8 + + def seek(symidx): + self.elf_fd.seek( + symtab['sh_offset'] + + symidx * sizeof_Elf_Sym + + offsetof_st_value) + + def reader(symbol_index): + seek(symbol_index) + return int.from_bytes(self.elf_fd.read(sizeof_st_value), byteorder) + + def writer(symbol_index, st_value): + seek(symbol_index) + self.elf_fd.write(int.to_bytes(st_value, sizeof_st_value, byteorder)) + + return reader, writer + + rd_st_val, wr_st_val = make_stvalue_reader_writer() + slid_size = self.elf.elfclass // 8 + + for (index, symbol) in imports: + slid = llext_slidlib.generate_slid(symbol.name, slid_size) + slid_as_str = llext_slidlib.format_slid(slid, slid_size) + msg = f"{symbol.name} -> {slid_as_str}" + + self.log.info(msg) + + # Make sure we're not overwriting something actually important + original_st_value = rd_st_val(index) + if original_st_value != 0: + self.log.error(f"unexpected non-zero st_value for symbol {symbol.name}") + return 1 + + wr_st_val(index, slid) + + return 0 + + def prepare_llext(self): + res = self._prepare_inner() + self.elf_fd.close() + return res + +# Disable duplicate code warning for the code that follows, +# as it is expected for these functions to be similar. +# pylint: disable=duplicate-code +def _parse_args(argv): + """Parse the command line arguments.""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + allow_abbrev=False) + + parser.add_argument("-f", "--elf-file", required=True, + help="LLEXT ELF file to process") + parser.add_argument("-o", "--output-file", + help=("Additional output file where processed ELF " + "will be copied")) + parser.add_argument("-sl", "--slid-listing", + help="write the SLID listing to a file") + parser.add_argument("-v", "--verbose", action="count", + help=("enable verbose output, can be used multiple times " + "to increase verbosity level")) + parser.add_argument("--always-succeed", action="store_true", + help="always exit with a return code of 0, used for testing") + + return parser.parse_args(argv) + +def _init_log(verbose): + """Initialize a logger object.""" + log = logging.getLogger(__file__) + + console = logging.StreamHandler() + console.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) + log.addHandler(console) + + if verbose and verbose > 1: + log.setLevel(logging.DEBUG) + elif verbose and verbose > 0: + log.setLevel(logging.INFO) + else: + log.setLevel(logging.WARNING) + + return log + +def main(argv=None): + args = _parse_args(argv) + + log = _init_log(args.verbose) + + log.info(f"inject_slids_in_llext: {args.elf_file}") + + preparator = LLEXTSymtabPreparator(args.elf_file, log) + + res = preparator.prepare_llext() + + if args.always_succeed: + return 0 + + if res == 0 and args.output_file: + shutil.copy(args.elf_file, args.output_file) + + return res + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/scripts/build/llext_prepare_exptab.py b/scripts/build/llext_prepare_exptab.py new file mode 100755 index 0000000000000..c659709af17e6 --- /dev/null +++ b/scripts/build/llext_prepare_exptab.py @@ -0,0 +1,377 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +""" +Script to prepare the LLEXT exports table of a Zephyr ELF + +This script performs compile-time processing of the LLEXT exports +table for usage at runtime by the LLEXT subsystem code. The table +is a special section filled with 'llext_const_symbol' structures +generated by the EXPORT_SYMBOL macro. + +Currently, the preparatory work consists mostly of sorting the +exports table to allow usage of binary search algorithms at runtime. +If CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID option is enabled, SLIDs +of all exported functions are also injected in the export table by +this script. (In this case, the preparation process is destructive) +""" + +import llext_slidlib + +from elftools.elf.elffile import ELFFile +from elftools.elf.sections import Section + +import argparse +import logging +import pathlib +import struct +import sys + +#!!!!! WARNING !!!!! +# +#These constants MUST be kept in sync with the linker scripts +#and the EXPORT_SYMBOL macro located in 'subsys/llext/llext.h'. +#Otherwise, the LLEXT subsystem will be broken! +# +#!!!!! WARNING !!!!! + +LLEXT_EXPORT_TABLE_SECTION_NAME = "llext_const_symbol_area" +LLEXT_EXPORT_NAMES_SECTION_NAME = "llext_exports_strtab" + +def _llext_const_symbol_struct(ptr_size: int, endianness: str): + """ + ptr_size -- Platform pointer size in bytes + endianness -- Platform endianness ('little'/'big') + """ + endspec = "<" if endianness == 'little' else ">" + if ptr_size == 4: + ptrspec = "I" + elif ptr_size == 8: + ptrspec = "Q" + + # struct llext_const_symbol + # contains just two pointers. + lcs_spec = endspec + 2 * ptrspec + return struct.Struct(lcs_spec) + +#ELF Shdr flag applied to the export table section, to indicate +#the section has already been prepared by this script. This is +#mostly a security measure to prevent the script from running +#twice on the same ELF file, which can result in catastrophic +#failures if SLID-based linking is enabled (in this case, the +#preparation process is destructive). +# +#This flag is part of the SHF_MASKOS mask, of which all bits +#are "reserved for operating system-specific semantics". +#See: https://refspecs.linuxbase.org/elf/gabi4+/ch4.sheader.html +SHF_LLEXT_PREPARATION_DONE = 0x08000000 + +class SectionDescriptor(): + """ELF Section descriptor + + This is a wrapper class around pyelftools' "Section" object. + """ + def __init__(self, elffile, section_name): + self.name = section_name + self.section = elffile.get_section_by_name(section_name) + if not isinstance(self.section, Section): + raise KeyError(f"section {section_name} not found") + + self.shdr_index = elffile.get_section_index(section_name) + self.shdr_offset = elffile['e_shoff'] + \ + self.shdr_index * elffile['e_shentsize'] + self.size = self.section['sh_size'] + self.flags = self.section['sh_flags'] + self.offset = self.section['sh_offset'] + +class LLEXTExptabManipulator(): + """Class used to wrap the LLEXT export table manipulation.""" + def __init__(self, elf_fd, exptab_file_offset, lcs_struct, exports_count): + self.fd = elf_fd + self.exports_count = exports_count + self.base_offset = exptab_file_offset + self.lcs_struct = lcs_struct + + def _seek_to_sym(self, index): + self.fd.seek(self.base_offset + index * self.lcs_struct.size) + + def __getitem__(self, index): + if not isinstance(index, int): + raise TypeError(f"invalid type {type(index)} for index") + + if index >= self.exports_count: + raise IndexError(f"index {index} is out of bounds (max {self.exports_count})") + + self._seek_to_sym(index) + return self.lcs_struct.unpack(self.fd.read(self.lcs_struct.size)) + + def __setitem__(self, index, item): + if not isinstance(index, int): + raise TypeError(f"invalid type {type(index)} for index") + + if index >= self.exports_count: + raise IndexError(f"index {index} is out of bounds (max {self.exports_count})") + + (addr_or_slid, sym_addr) = item + + self._seek_to_sym(index) + self.fd.write(self.lcs_struct.pack(addr_or_slid, sym_addr)) + +class ZephyrElfExptabPreparator(): + """Prepares the LLEXT export table of a Zephyr ELF. + + Attributes: + elf_path: path to the Zephyr ELF to prepare + log: a logging.Logger object + slid_listing_path: path to the file where SLID listing should be saved + """ + def __init__(self, elf_path: str, log: logging.Logger, slid_listing_path: str | None): + self.elf_path = elf_path + self.elf_fd = open(self.elf_path, 'rb+') + self.elf = ELFFile(self.elf_fd) + self.log = log + + # Lazy-open the SLID listing file to ensure it is only created when necessary + self.slid_listing_path = slid_listing_path + self.slid_listing_fd = None + + def _prepare_exptab_for_slid_linking(self): + """ + IMPLEMENTATION NOTES: + In the linker script, we declare the export names table + as starting at address 0. Thanks to this, all "pointers" + to that section are equal to the offset inside the section. + Also note that symbol names are always NUL-terminated. + + The export table is sorted by SLID in ASCENDING order. + """ + def read_symbol_name(name_ptr): + raw_name = b'' + self.elf_fd.seek(self.expstrtab_section.offset + name_ptr) + + c = self.elf_fd.read(1) + while c != b'\0': + raw_name += c + c = self.elf_fd.read(1) + + return raw_name.decode("utf-8") + + #1) Load the export table + exports_list = [] + for (name_ptr, export_address) in self.exptab_manipulator: + export_name = read_symbol_name(name_ptr) + exports_list.append((export_name, export_address)) + + #2) Generate the SLID for all exports + collided = False + sorted_exptab = dict() + for export_name, export_addr in exports_list: + slid = llext_slidlib.generate_slid(export_name, self.ptrsize) + + collision = sorted_exptab.get(slid) + if collision: + #Don't abort immediately on collision: if there are others, we want to log them all. + self.log.error(f"SLID collision: {export_name} and {collision[0]} have the same SLID 0x{slid:X}") + collided = True + else: + sorted_exptab[slid] = (export_name, export_addr) + + if collided: + return 1 + + #3) Sort the export table (order specified above) + sorted_exptab = dict(sorted(sorted_exptab.items())) + + #4) Write the updated export table to ELF, and dump + #to SLID listing if requested by caller + if self.slid_listing_path: + self.slid_listing_fd = open(self.slid_listing_path, "w") + + def slidlist_write(msg): + if self.slid_listing_fd: + self.slid_listing_fd.write(msg + "\n") + + slidlist_write(f"/* SLID listing generated by {__file__} */") + slidlist_write("//") + slidlist_write("// This file contains the 'SLID -> name' mapping for all") + slidlist_write("// symbols exported to LLEXT by this Zephyr executable.") + slidlist_write("") + + self.log.info("SLID -> export name mapping:") + + i = 0 + for (slid, name_and_symaddr) in sorted_exptab.items(): + slid_as_str = llext_slidlib.format_slid(slid, self.ptrsize) + msg = f"{slid_as_str} -> {name_and_symaddr[0]}" + self.log.info(msg) + slidlist_write(msg) + + self.exptab_manipulator[i] = (slid, name_and_symaddr[1]) + i += 1 + + if self.slid_listing_fd: + self.slid_listing_fd.close() + + return 0 + + def _prepare_exptab_for_str_linking(self): + #TODO: sort the export table by symbol + # name to allow binary search too + # + # Plan of action: + # 1) Locate in which section the names are located + # 2) Load the export table and resolve names + # 3) Sort the exports by name + # WARN: THIS MUST USE THE SAME SORTING RULES + # AS LLEXT CODE OR DICHOTOMIC SEARCH WILL BREAK + # Using a custom sorting function might be required. + # 4) Write back the updated export table + # + # N.B.: reusing part of the code in _prepare_elf_for_slid_linking + # might be possible and desireable. + # + # As of writing, this function will never be called as this script + # is only called if CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID is enabled, + # which makes _prepare_exptab_for_slid_linking be called instead. + # + self.log.warn(f"_prepare_exptab_for_str_linking: do nothing") + return 0 + + def _set_prep_done_shdr_flag(self): + #Offset and size of the 'sh_flags' member of + #the Elf_Shdr structure. The offset does not + #change between ELF32 and ELF64. Size in both + #is equal to pointer size (4 bytes for ELF32, + #8 bytes for ELF64). + SHF_OFFSET = 8 + SHF_SIZE = self.ptrsize + + off = self.exptab_section.shdr_offset + SHF_OFFSET + + #Read existing sh_flags, set the PREPARATION_DONE flag + #and write back the new value. + self.elf_fd.seek(off) + sh_flags = int.from_bytes(self.elf_fd.read(SHF_SIZE), self.endianness) + + sh_flags |= SHF_LLEXT_PREPARATION_DONE + + self.elf_fd.seek(off) + self.elf_fd.write(int.to_bytes(sh_flags, self.ptrsize, self.endianness)) + + def _prepare_inner(self): + # Locate the export table section + try: + self.exptab_section = SectionDescriptor( + self.elf, LLEXT_EXPORT_TABLE_SECTION_NAME) + except KeyError as e: + self.log.error(e.args[0]) + return 1 + + # Abort if the ELF has already been processed + if (self.exptab_section.flags & SHF_LLEXT_PREPARATION_DONE) != 0: + self.log.warning("exptab section flagged with LLEXT_PREPARATION_DONE " + "- not preparing again") + return 0 + + # Get the struct.Struct for export table entry + self.ptrsize = self.elf.elfclass // 8 + self.endianness = 'little' if self.elf.little_endian else 'big' + self.lcs_struct = _llext_const_symbol_struct(self.ptrsize, self.endianness) + + # Verify that the export table size is coherent + if (self.exptab_section.size % self.lcs_struct.size) != 0: + self.log.error(f"export table size (0x{self.exptab_section.size:X}) " + f"not aligned to 'llext_const_symbol' size (0x{self.lcs_struct.size:X})") + return 1 + + # Create the export table manipulator + num_exports = self.exptab_section.size // self.lcs_struct.size + self.exptab_manipulator = LLEXTExptabManipulator( + self.elf_fd, self.exptab_section.offset, self.lcs_struct, num_exports) + + # Attempt to locate the export names section + try: + self.expstrtab_section = SectionDescriptor( + self.elf, LLEXT_EXPORT_NAMES_SECTION_NAME) + except KeyError: + self.expstrtab_section = None + + self.log.debug(f"exports table section at file offset 0x{self.exptab_section.offset:X}") + if self.expstrtab_section: + self.log.debug(f"exports strtab section at file offset 0x{self.expstrtab_section.offset:X}") + else: + self.log.debug("no exports strtab section in ELF") + self.log.info(f"{num_exports} symbols are exported to LLEXTs by this ELF") + + # Perform the export table preparation + if self.expstrtab_section: + res = self._prepare_exptab_for_slid_linking() + else: + res = self._prepare_exptab_for_str_linking() + + if res == 0: # Add the "prepared" flag to export table section + self._set_prep_done_shdr_flag() + + def prepare_elf(self): + res = self._prepare_inner() + self.elf_fd.close() + return res + +# pylint: disable=duplicate-code +def _parse_args(argv): + """Parse the command line arguments.""" + parser = argparse.ArgumentParser( + description=__doc__, + formatter_class=argparse.RawDescriptionHelpFormatter, + allow_abbrev=False) + + parser.add_argument("-f", "--elf-file", default=pathlib.Path("build", "zephyr", "zephyr.elf"), + help="ELF file to process") + parser.add_argument("-sl", "--slid-listing", + help=("write the SLID listing to a file (only useful" + "when CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID is enabled) ")) + parser.add_argument("-v", "--verbose", action="count", + help=("enable verbose output, can be used multiple times " + "to increase verbosity level")) + parser.add_argument("--always-succeed", action="store_true", + help="always exit with a return code of 0, used for testing") + + return parser.parse_args(argv) + +def _init_log(verbose): + """Initialize a logger object.""" + log = logging.getLogger(__file__) + + console = logging.StreamHandler() + console.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) + log.addHandler(console) + + if verbose and verbose > 1: + log.setLevel(logging.DEBUG) + elif verbose and verbose > 0: + log.setLevel(logging.INFO) + else: + log.setLevel(logging.WARNING) + + return log + +def main(argv=None): + args = _parse_args(argv) + + log = _init_log(args.verbose) + + log.info(f"prepare_llext_exptab: {args.elf_file}") + + preparator = ZephyrElfExptabPreparator(args.elf_file, log, args.slid_listing) + + res = preparator.prepare_elf() + + if args.always_succeed: + return 0 + + return res + +if __name__ == "__main__": + sys.exit(main(sys.argv[1:])) diff --git a/scripts/build/llext_slidlib.py b/scripts/build/llext_slidlib.py new file mode 100755 index 0000000000000..99157c526dcc3 --- /dev/null +++ b/scripts/build/llext_slidlib.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2024 STMicroelectronics +# SPDX-License-Identifier: Apache-2.0 + +""" +This file implements the Symbol Link Identifer (SLID) +generation code, for use by the LLEXT subsystem. +SLID-based linking is enabled by the Kconfig +option 'CONFIG_LLEXT_EXPORT_BUILTINS_BY_SLID'. + +When executed as a script, this file can be used as +an interactive prompt to calculate the SLID of arbitrary +symbols, which can be useful for debugging purposes. + +IMPLEMENTATION NOTES: + Currently, SLIDs are generated by taking the first + [pointer size] bytes of the symbol name's SHA-256 + hash, taken in big-endian order. + + This ordering provides one advantage: the 32-bit + SLID for an export is present in the top 32 bits of + the 64-bit SLID for the same export. +""" + +from hashlib import sha256 + +def generate_slid(symbol_name: str, slid_size: int) -> int: + """ + Generates the Symbol Link Identifier (SLID) for a symbol. + + symbol_name: Name of the symbol for which to generate a SLID + slid_side: Size of the SLID in bytes (4/8) + """ + if slid_size not in (4, 8): + raise AssertionError(f"Invalid SLID size {slid_size}") + + m = sha256() + m.update(symbol_name.encode("utf-8")) + hash = m.digest() + return int.from_bytes(hash[0:slid_size], byteorder='big', signed=False) + +def format_slid(slid: int, slid_size: int) -> str: + if slid_size == 4: + fmt = f"0x{slid:08X}" + elif slid_size == 8: + fmt = f"0x{slid:016X}" + return fmt + +def repl(): + while True: + sym_name = input("Symbol name? ") + slid32 = generate_slid(sym_name, 4) + slid64 = generate_slid(sym_name, 8) + print(f" 32-bit SLID for '{sym_name}': {format_slid(slid32, 4)}") + print(f" 64-bit SLID for '{sym_name}': {format_slid(slid64, 8)}") + print() + +if __name__ == "__main__": + print("LLEXT SLID calculation REPL") + print("Press ^C to exit.") + try: + repl() + except KeyboardInterrupt: + print() diff --git a/scripts/build/uf2conv.py b/scripts/build/uf2conv.py index 5da08efd5b964..fd70895bc8040 100755 --- a/scripts/build/uf2conv.py +++ b/scripts/build/uf2conv.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # Copyright (c) Microsoft Corporation # SPDX-License-Identifier: MIT -# Copied from 7a9e1f4 of https://github.com/microsoft/uf2/blob/master/utils/uf2conv.py +# Copied from 27e322f of https://github.com/microsoft/uf2/blob/master/utils/uf2conv.py # pylint: skip-file import sys import struct @@ -10,40 +10,14 @@ import os import os.path import argparse +import json +from time import sleep UF2_MAGIC_START0 = 0x0A324655 # "UF2\n" UF2_MAGIC_START1 = 0x9E5D5157 # Randomly selected UF2_MAGIC_END = 0x0AB16F30 # Ditto -families = { - 'SAMD21': 0x68ed2b88, - 'SAML21': 0x1851780a, - 'SAMD51': 0x55114460, - 'NRF52': 0x1b57745f, - 'STM32F0': 0x647824b6, - 'STM32F1': 0x5ee21072, - 'STM32F2': 0x5d1a0a2e, - 'STM32F3': 0x6b846188, - 'STM32F4': 0x57755a57, - 'STM32F7': 0x53b80f00, - 'STM32G0': 0x300f5633, - 'STM32G4': 0x4c71240a, - 'STM32H7': 0x6db66082, - 'STM32L0': 0x202e3a91, - 'STM32L1': 0x1e1f432d, - 'STM32L4': 0x00ff6919, - 'STM32L5': 0x04240bdf, - 'STM32WB': 0x70d16653, - 'STM32WL': 0x21460ff0, - 'ATMEGA32': 0x16573617, - 'MIMXRT10XX': 0x4FB2D5BD, - 'LPC55': 0x2abc77ec, - 'GD32F350': 0x31D228C6, - 'ESP32S2': 0xbfdd4eee, - 'RP2040': 0xe48bff56 -} - INFO_FILE = "/INFO_UF2.TXT" appstartaddr = 0x2000 @@ -59,14 +33,19 @@ def is_hex(buf): w = buf[0:30].decode("utf-8") except UnicodeDecodeError: return False - if w[0] == ':' and re.match(b"^[:0-9a-fA-F\r\n]+$", buf): + if w[0] == ':' and re.match(rb"^[:0-9a-fA-F\r\n]+$", buf): return True return False def convert_from_uf2(buf): global appstartaddr + global familyid numblocks = len(buf) // 512 curraddr = None + currfamilyid = None + families_found = {} + prev_flag = None + all_flags_same = True outp = [] for blockno in range(numblocks): ptr = blockno * 512 @@ -82,9 +61,13 @@ def convert_from_uf2(buf): if datalen > 476: assert False, "Invalid UF2 data size at " + ptr newaddr = hd[3] - if curraddr == None: - appstartaddr = newaddr + if (hd[2] & 0x2000) and (currfamilyid == None): + currfamilyid = hd[7] + if curraddr == None or ((hd[2] & 0x2000) and hd[7] != currfamilyid): + currfamilyid = hd[7] curraddr = newaddr + if familyid == 0x0 or familyid == hd[7]: + appstartaddr = newaddr padding = newaddr - curraddr if padding < 0: assert False, "Block out of order at " + ptr @@ -94,9 +77,38 @@ def convert_from_uf2(buf): assert False, "Non-word padding size at " + ptr while padding > 0: padding -= 4 - outp += b"\x00\x00\x00\x00" - outp.append(block[32 : 32 + datalen]) + outp.append(b"\x00\x00\x00\x00") + if familyid == 0x0 or ((hd[2] & 0x2000) and familyid == hd[7]): + outp.append(block[32 : 32 + datalen]) curraddr = newaddr + datalen + if hd[2] & 0x2000: + if hd[7] in families_found.keys(): + if families_found[hd[7]] > newaddr: + families_found[hd[7]] = newaddr + else: + families_found[hd[7]] = newaddr + if prev_flag == None: + prev_flag = hd[2] + if prev_flag != hd[2]: + all_flags_same = False + if blockno == (numblocks - 1): + print("--- UF2 File Header Info ---") + families = load_families() + for family_hex in families_found.keys(): + family_short_name = "" + for name, value in families.items(): + if value == family_hex: + family_short_name = name + print("Family ID is {:s}, hex value is 0x{:08x}".format(family_short_name,family_hex)) + print("Target Address is 0x{:08x}".format(families_found[family_hex])) + if all_flags_same: + print("All block flag values consistent, 0x{:04x}".format(hd[2])) + else: + print("Flags were not all the same") + print("----------------------------") + if len(families_found) > 1 and familyid == 0x0: + outp = [] + appstartaddr = 0x0 return b"".join(outp) def convert_to_carray(file_content): @@ -170,11 +182,10 @@ def convert_from_hex_to_uf2(buf): upper = ((rec[4] << 8) | rec[5]) << 16 elif tp == 2: upper = ((rec[4] << 8) | rec[5]) << 4 - assert (upper & 0xffff) == 0 elif tp == 1: break elif tp == 0: - addr = upper | (rec[1] << 8) | rec[2] + addr = upper + ((rec[1] << 8) | rec[2]) if appstartaddr == None: appstartaddr = addr i = 4 @@ -201,19 +212,21 @@ def get_drives(): "get", "DeviceID,", "VolumeName,", "FileSystem,", "DriveType"]) for line in to_str(r).split('\n'): - words = re.split('\s+', line) + words = re.split(r'\s+', line) if len(words) >= 3 and words[1] == "2" and words[2] == "FAT": drives.append(words[0]) else: - rootpath = "/media" + searchpaths = ["/media"] if sys.platform == "darwin": - rootpath = "/Volumes" + searchpaths = ["/Volumes"] elif sys.platform == "linux": - tmp = rootpath + "/" + os.environ["USER"] - if os.path.isdir(tmp): - rootpath = tmp - for d in os.listdir(rootpath): - drives.append(os.path.join(rootpath, d)) + searchpaths += ["/media/" + os.environ["USER"], '/run/media/' + os.environ["USER"]] + + for rootpath in searchpaths: + if os.path.isdir(rootpath): + for d in os.listdir(rootpath): + if os.path.isdir(rootpath): + drives.append(os.path.join(rootpath, d)) def has_info(d): @@ -228,7 +241,7 @@ def has_info(d): def board_id(path): with open(path + INFO_FILE, mode='r') as file: file_content = file.read() - return re.search("Board-ID: ([^\r\n]*)", file_content).group(1) + return re.search(r"Board-ID: ([^\r\n]*)", file_content).group(1) def list_drives(): @@ -242,36 +255,57 @@ def write_file(name, buf): print("Wrote %d bytes to %s" % (len(buf), name)) +def load_families(): + # The expectation is that the `uf2families.json` file is in the same + # directory as this script. Make a path that works using `__file__` + # which contains the full path to this script. + filename = "uf2families.json" + pathname = os.path.join(os.path.dirname(os.path.abspath(__file__)), filename) + with open(pathname) as f: + raw_families = json.load(f) + + families = {} + for family in raw_families: + families[family["short_name"]] = int(family["id"], 0) + + return families + + def main(): global appstartaddr, familyid def error(msg): - print(msg) + print(msg, file=sys.stderr) sys.exit(1) - parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.', - allow_abbrev=False) + parser = argparse.ArgumentParser(description='Convert to UF2 or flash directly.') parser.add_argument('input', metavar='INPUT', type=str, nargs='?', help='input file (HEX, BIN or UF2)') - parser.add_argument('-b' , '--base', dest='base', type=str, + parser.add_argument('-b', '--base', dest='base', type=str, default="0x2000", help='set base address of application for BIN format (default: 0x2000)') - parser.add_argument('-o' , '--output', metavar="FILE", dest='output', type=str, + parser.add_argument('-f', '--family', dest='family', type=str, + default="0x0", + help='specify familyID - number or name (default: 0x0)') + parser.add_argument('-o', '--output', metavar="FILE", dest='output', type=str, help='write output to named file; defaults to "flash.uf2" or "flash.bin" where sensible') - parser.add_argument('-d' , '--device', dest="device_path", + parser.add_argument('-d', '--device', dest="device_path", help='select a device path to flash') - parser.add_argument('-l' , '--list', action='store_true', + parser.add_argument('-l', '--list', action='store_true', help='list connected devices') - parser.add_argument('-c' , '--convert', action='store_true', + parser.add_argument('-c', '--convert', action='store_true', help='do not flash, just convert') - parser.add_argument('-D' , '--deploy', action='store_true', + parser.add_argument('-D', '--deploy', action='store_true', help='just flash, do not convert') - parser.add_argument('-f' , '--family', dest='family', type=str, - default="0x0", - help='specify familyID - number or name (default: 0x0)') - parser.add_argument('-C' , '--carray', action='store_true', + parser.add_argument('-w', '--wait', action='store_true', + help='wait for device to flash') + parser.add_argument('-C', '--carray', action='store_true', help='convert binary file to a C array, not UF2') + parser.add_argument('-i', '--info', action='store_true', + help='display header information from UF2, do not convert') args = parser.parse_args() appstartaddr = int(args.base, 0) + families = load_families() + if args.family.upper() in families: familyid = families[args.family.upper()] else: @@ -291,9 +325,12 @@ def error(msg): ext = "uf2" if args.deploy: outbuf = inpbuf - elif from_uf2: + elif from_uf2 and not args.info: outbuf = convert_from_uf2(inpbuf) ext = "bin" + elif from_uf2 and args.info: + outbuf = "" + convert_from_uf2(inpbuf) elif is_hex(inpbuf): outbuf = convert_from_hex_to_uf2(inpbuf.decode("utf-8")) elif args.carray: @@ -301,23 +338,27 @@ def error(msg): ext = "h" else: outbuf = convert_to_uf2(inpbuf) - print("Converting to %s, output size: %d, start address: 0x%x" % - (ext, len(outbuf), appstartaddr)) + if not args.deploy and not args.info: + print("Converted to %s, output size: %d, start address: 0x%x" % + (ext, len(outbuf), appstartaddr)) if args.convert or ext != "uf2": - drives = [] if args.output == None: args.output = "flash." + ext - else: - drives = get_drives() - if args.output: write_file(args.output, outbuf) - else: + if ext == "uf2" and not args.convert and not args.info: + drives = get_drives() if len(drives) == 0: - error("No drive to deploy.") - for d in drives: - print("Flashing %s (%s)" % (d, board_id(d))) - write_file(d + "/NEW.UF2", outbuf) + if args.wait: + print("Waiting for drive to deploy...") + while len(drives) == 0: + sleep(0.1) + drives = get_drives() + elif not args.output: + error("No drive to deploy.") + for d in drives: + print("Flashing %s (%s)" % (d, board_id(d))) + write_file(d + "/NEW.UF2", outbuf) if __name__ == "__main__": diff --git a/scripts/build/uf2families.json b/scripts/build/uf2families.json new file mode 100644 index 0000000000000..14c8e5d043cb6 --- /dev/null +++ b/scripts/build/uf2families.json @@ -0,0 +1,247 @@ +[ + { + "id": "0x16573617", + "short_name": "ATMEGA32", + "description": "Microchip (Atmel) ATmega32" + }, + { + "id": "0x1851780a", + "short_name": "SAML21", + "description": "Microchip (Atmel) SAML21" + }, + { + "id": "0x1b57745f", + "short_name": "NRF52", + "description": "Nordic NRF52" + }, + { + "id": "0x1c5f21b0", + "short_name": "ESP32", + "description": "ESP32" + }, + { + "id": "0x1e1f432d", + "short_name": "STM32L1", + "description": "ST STM32L1xx" + }, + { + "id": "0x202e3a91", + "short_name": "STM32L0", + "description": "ST STM32L0xx" + }, + { + "id": "0x21460ff0", + "short_name": "STM32WL", + "description": "ST STM32WLxx" + }, + { + "id": "0x2abc77ec", + "short_name": "LPC55", + "description": "NXP LPC55xx" + }, + { + "id": "0x300f5633", + "short_name": "STM32G0", + "description": "ST STM32G0xx" + }, + { + "id": "0x31d228c6", + "short_name": "GD32F350", + "description": "GD32F350" + }, + { + "id": "0x04240bdf", + "short_name": "STM32L5", + "description": "ST STM32L5xx" + }, + { + "id": "0x4c71240a", + "short_name": "STM32G4", + "description": "ST STM32G4xx" + }, + { + "id": "0x4fb2d5bd", + "short_name": "MIMXRT10XX", + "description": "NXP i.MX RT10XX" + }, + { + "id": "0x53b80f00", + "short_name": "STM32F7", + "description": "ST STM32F7xx" + }, + { + "id": "0x55114460", + "short_name": "SAMD51", + "description": "Microchip (Atmel) SAMD51" + }, + { + "id": "0x57755a57", + "short_name": "STM32F4", + "description": "ST STM32F4xx" + }, + { + "id": "0x5a18069b", + "short_name": "FX2", + "description": "Cypress FX2" + }, + { + "id": "0x5d1a0a2e", + "short_name": "STM32F2", + "description": "ST STM32F2xx" + }, + { + "id": "0x5ee21072", + "short_name": "STM32F1", + "description": "ST STM32F103" + }, + { + "id": "0x621e937a", + "short_name": "NRF52833", + "description": "Nordic NRF52833" + }, + { + "id": "0x647824b6", + "short_name": "STM32F0", + "description": "ST STM32F0xx" + }, + { + "id": "0x68ed2b88", + "short_name": "SAMD21", + "description": "Microchip (Atmel) SAMD21" + }, + { + "id": "0x6b846188", + "short_name": "STM32F3", + "description": "ST STM32F3xx" + }, + { + "id": "0x6d0922fa", + "short_name": "STM32F407", + "description": "ST STM32F407" + }, + { + "id": "0x6db66082", + "short_name": "STM32H7", + "description": "ST STM32H7xx" + }, + { + "id": "0x70d16653", + "short_name": "STM32WB", + "description": "ST STM32WBxx" + }, + { + "id": "0x7eab61ed", + "short_name": "ESP8266", + "description": "ESP8266" + }, + { + "id": "0x7f83e793", + "short_name": "KL32L2", + "description": "NXP KL32L2x" + }, + { + "id": "0x8fb060fe", + "short_name": "STM32F407VG", + "description": "ST STM32F407VG" + }, + { + "id": "0xada52840", + "short_name": "NRF52840", + "description": "Nordic NRF52840" + }, + { + "id": "0xbfdd4eee", + "short_name": "ESP32S2", + "description": "ESP32-S2" + }, + { + "id": "0xc47e5767", + "short_name": "ESP32S3", + "description": "ESP32-S3" + }, + { + "id": "0xd42ba06c", + "short_name": "ESP32C3", + "description": "ESP32-C3" + }, + { + "id": "0x2b88d29c", + "short_name": "ESP32C2", + "description": "ESP32-C2" + }, + { + "id": "0x332726f6", + "short_name": "ESP32H2", + "description": "ESP32-H2" + }, + { + "id": "0x540ddf62", + "short_name": "ESP32C6", + "description": "ESP32-C6" + }, + { + "id": "0x3d308e94", + "short_name": "ESP32P4", + "description": "ESP32-P4" + }, + { + "id": "0xe48bff56", + "short_name": "RP2040", + "description": "Raspberry Pi RP2040" + }, + { + "id": "0x00ff6919", + "short_name": "STM32L4", + "description": "ST STM32L4xx" + }, + { + "id": "0x9af03e33", + "short_name": "GD32VF103", + "description": "GigaDevice GD32VF103" + }, + { + "id": "0x4f6ace52", + "short_name": "CSK4", + "description": "LISTENAI CSK300x/400x" + }, + { + "id": "0x6e7348a8", + "short_name": "CSK6", + "description": "LISTENAI CSK60xx" + }, + { + "id": "0x11de784a", + "short_name": "M0SENSE", + "description": "M0SENSE BL702" + }, + { + "id": "0x4b684d71", + "short_name": "MaixPlay-U4", + "description": "Sipeed MaixPlay-U4(BL618)" + }, + { + "id": "0x9517422f", + "short_name": "RZA1LU", + "description": "Renesas RZ/A1LU (R7S7210xx)" + }, + { + "id": "0x2dc309c5", + "short_name": "STM32F411xE", + "description": "ST STM32F411xE" + }, + { + "id": "0x06d1097b", + "short_name": "STM32F411xC", + "description": "ST STM32F411xC" + }, + { + "id": "0x72721d4e", + "short_name": "NRF52832xxAA", + "description": "Nordic NRF52832xxAA" + }, + { + "id": "0x6f752678", + "short_name": "NRF52832xxAB", + "description": "Nordic NRF52832xxAB" + } +] diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 27fbd880ef639..c0688e6274182 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4419,11 +4419,13 @@ sub process { # 1. with a type on the left -- int [] a; # 2. at the beginning of a line for slice initialisers -- [0...10] = 5, # 3. inside a curly brace -- = { [0...10] = 5 } +# 4. inside macro arguments, example: #define HCI_ERR(err) [err] = #err while ($line =~ /(.*?\s)\[/g) { my ($where, $prefix) = ($-[1], $1); if ($prefix !~ /$Type\s+$/ && ($where != 0 || $prefix !~ /^.\s+$/) && $prefix !~ /[{,:]\s+$/ && + $prefix !~ /\#define\s+.+\s+$/ && $prefix !~ /:\s+$/) { if (ERROR("BRACKET_SPACE", "space prohibited before open square bracket '['\n" . $herecurr) && diff --git a/scripts/ci/check_compliance.py b/scripts/ci/check_compliance.py index 1bd39950ddefe..5ae142f033239 100755 --- a/scripts/ci/check_compliance.py +++ b/scripts/ci/check_compliance.py @@ -7,6 +7,7 @@ import argparse import collections from email.utils import parseaddr +import json import logging import os from pathlib import Path @@ -178,7 +179,6 @@ def fmtd_failure(self, severity, title, file, line=None, col=None, desc=""): self._result(fail, fail.text) self.fmtd_failures.append(fail) - class EndTest(Exception): """ Raised by ComplianceTest.error()/skip() to end the test. @@ -910,6 +910,7 @@ def check_no_undef_outside_kconfig(self, kconf): "OPT", "OPT_0", "PEDO_THS_MIN", + "PSA_H", # This is used in config-psa.h as guard for the header file "REG1", "REG2", "RIMAGE_SIGNING_SCHEMA", # Optional module @@ -942,6 +943,9 @@ def check_no_undef_outside_kconfig(self, kconf): "ZEPHYR_TRY_MASS_ERASE", # MCUBoot setting described in sysbuild # documentation "ZTEST_FAIL_TEST_", # regex in tests/ztest/fail/CMakeLists.txt + "SUIT_MPI_GENERATE", # Used by nRF runners to program provisioning data, based on build configuration + "SUIT_MPI_APP_AREA_PATH", # Used by nRF runners to program provisioning data, based on build configuration + "SUIT_MPI_RAD_AREA_PATH", # Used by nRF runners to program provisioning data, based on build configuration } @@ -1169,7 +1173,7 @@ def run(self): else: python_environment["PYTHONPATH"] = check_script_dir - pylintcmd = ["pylint", "--rcfile=" + pylintrc, + pylintcmd = ["pylint", "--output-format=json2", "--rcfile=" + pylintrc, "--load-plugins=argparse-checker"] + py_files logger.info(cmd2str(pylintcmd)) try: @@ -1181,21 +1185,19 @@ def run(self): env=python_environment) except subprocess.CalledProcessError as ex: output = ex.output.decode("utf-8") - regex = r'^\s*(\S+):(\d+):(\d+):\s*([A-Z]\d{4}):\s*(.*)$' - - matches = re.findall(regex, output, re.MULTILINE) - for m in matches: - # https://pylint.pycqa.org/en/latest/user_guide/messages/messages_overview.html# + messages = json.loads(output)['messages'] + for m in messages: severity = 'unknown' - if m[3][0] in ('F', 'E'): + if m['messageId'][0] in ('F', 'E'): severity = 'error' - elif m[3][0] in ('W','C', 'R', 'I'): + elif m['messageId'][0] in ('W','C', 'R', 'I'): severity = 'warning' - self.fmtd_failure(severity, m[3], m[0], m[1], col=m[2], - desc=m[4]) + self.fmtd_failure(severity, m['messageId'], m['path'], + m['line'], col=str(m['column']), desc=m['message'] + + f" ({m['symbol']})") - # If the regex has not matched add the whole output as a failure - if len(matches) == 0: + if len(messages) == 0: + # If there are no specific messages add the whole output as a failure self.failure(output) diff --git a/scripts/ci/coverage/coverage_analysis.py b/scripts/ci/coverage/coverage_analysis.py index 34ce99c98549e..8238a5134e2be 100644 --- a/scripts/ci/coverage/coverage_analysis.py +++ b/scripts/ci/coverage/coverage_analysis.py @@ -69,7 +69,8 @@ def parse_testplan(self, testplan_path): break sub_component_name = testcase_name[testcase_name.find('.'):] sub_component_name = sub_component_name[1:] - sub_component_name = sub_component_name[:sub_component_name.find(".")] + if sub_component_name.find(".") > 0: + sub_component_name = sub_component_name[:sub_component_name.find(".")] if known_component_flag is False: sub_component = { @@ -273,7 +274,9 @@ def generate_json_report(self, coverage): "Name":i_fun['name'] } json_file['Uncovered_Functions'].append(json_uncovered_funciton) - json_files.append(json_file) + comp_exists = [x for x in json_files if x['Path'] == json_file['Path']] + if not comp_exists: + json_files.append(json_file) json_component['files']=json_files output_json['components'].append(json_component) else: diff --git a/scripts/ci/test_plan.py b/scripts/ci/test_plan.py index 26787496a7ccc..fba031e574f63 100755 --- a/scripts/ci/test_plan.py +++ b/scripts/ci/test_plan.py @@ -17,6 +17,11 @@ from git import Repo from west.manifest import Manifest +try: + from yaml import CSafeLoader as SafeLoader +except ImportError: + from yaml import SafeLoader + if "ZEPHYR_BASE" not in os.environ: exit("$ZEPHYR_BASE environment variable undefined.") @@ -24,15 +29,15 @@ # however, pylint complains that it doesn't recognized them when used (used-before-assignment). zephyr_base = Path(os.environ['ZEPHYR_BASE']) repository_path = zephyr_base -repo_to_scan = zephyr_base +repo_to_scan = Repo(zephyr_base) args = None - - logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) +logging.getLogger("pykwalify.core").setLevel(50) sys.path.append(os.path.join(zephyr_base, 'scripts')) import list_boards + def _get_match_fn(globs, regexes): # Constructs a single regex that tests for matches against the globs in # 'globs' and the regexes in 'regexes'. Parts are joined with '|' (OR). @@ -95,7 +100,7 @@ def __repr__(self): class Filters: def __init__(self, modified_files, ignore_path, alt_tags, testsuite_root, - pull_request=False, platforms=[], detailed_test_id=True): + pull_request=False, platforms=[], detailed_test_id=True, quarantine_list=None, tc_roots_th=20): self.modified_files = modified_files self.testsuite_root = testsuite_root self.resolved_files = [] @@ -108,6 +113,8 @@ def __init__(self, modified_files, ignore_path, alt_tags, testsuite_root, self.detailed_test_id = detailed_test_id self.ignore_path = ignore_path self.tag_cfg_file = alt_tags + self.quarantine_list = quarantine_list + self.tc_roots_th = tc_roots_th def process(self): self.find_modules() @@ -128,6 +135,9 @@ def get_plan(self, options, integration=False, use_testsuite_root=True): cmd+=["-T", root] if integration: cmd.append("--integration") + if self.quarantine_list: + for q in self.quarantine_list: + cmd += ["--quarantine-list", q] logging.info(" ".join(cmd)) _ = subprocess.call(cmd) @@ -209,45 +219,50 @@ def find_archs(self): self.get_plan(_options, True) def find_boards(self): - boards = set() - all_boards = set() - resolved = [] + changed_boards = set() + matched_boards = {} + resolved_files = [] - for f in self.modified_files: - if f.endswith(".rst") or f.endswith(".png") or f.endswith(".jpg"): + for file in self.modified_files: + if file.endswith(".rst") or file.endswith(".png") or file.endswith(".jpg"): continue - p = re.match(r"^boards\/[^/]+\/([^/]+)\/", f) - if p and p.groups(): - boards.add(p.group(1)) - resolved.append(f) + if file.startswith("boards/"): + changed_boards.add(file) + resolved_files.append(file) roots = [zephyr_base] if repository_path != zephyr_base: roots.append(repository_path) # Look for boards in monitored repositories - lb_args = argparse.Namespace(**{'arch_roots': roots, 'board_roots': roots, 'board': None, + lb_args = argparse.Namespace(**{'arch_roots': roots, 'board_roots': roots, 'board': None, 'soc_roots':roots, 'board_dir': None}) - known_boards = list_boards.find_boards(lb_args) - for b in boards: - name_re = re.compile(b) - for kb in known_boards: - if name_re.search(kb.name): - all_boards.add(kb.name) - - # If modified file is catched by "find_boards" workflow (change in "boards" dir AND board recognized) + known_boards = list_boards.find_v2_boards(lb_args) + + for changed in changed_boards: + for board in known_boards: + c = (zephyr_base / changed).resolve() + if c.is_relative_to(board.dir.resolve()): + for file in glob.glob(os.path.join(board.dir, f"{board.name}*.yaml")): + with open(file, 'r') as f: + b = yaml.load(f.read(), Loader=SafeLoader) + matched_boards[b['identifier']] = board + + + logging.info(f"found boards: {','.join(matched_boards.keys())}") + # If modified file is caught by "find_boards" workflow (change in "boards" dir AND board recognized) # it means a proper testing scope for this file was found and this file can be removed # from further consideration - for board in all_boards: - self.resolved_files.extend(list(filter(lambda f: board in f, resolved))) + for _, board in matched_boards.items(): + self.resolved_files.extend(list(filter(lambda f: str(board.dir.relative_to(zephyr_base)) in f, resolved_files))) _options = [] - if len(all_boards) > 20: - logging.warning(f"{len(boards)} boards changed, this looks like a global change, skipping test handling, revert to default.") + if len(matched_boards) > 20: + logging.warning(f"{len(matched_boards)} boards changed, this looks like a global change, skipping test handling, revert to default.") self.full_twister = True return - for board in all_boards: + for board in matched_boards: _options.extend(["-p", board ]) if _options: @@ -288,7 +303,7 @@ def find_tests(self): for t in tests: _options.extend(["-T", t ]) - if len(tests) > 20: + if len(tests) > self.tc_roots_th: logging.warning(f"{len(tests)} tests changed, this looks like a global change, skipping test handling, revert to default") self.full_twister = True return @@ -298,8 +313,6 @@ def find_tests(self): if self.platforms: for platform in self.platforms: _options.extend(["-p", platform]) - else: - _options.append("--all") self.get_plan(_options, use_testsuite_root=False) def find_tags(self): @@ -392,6 +405,9 @@ def parse_args(): help="Number of tests per builder") parser.add_argument('-n', '--default-matrix', default=10, type=int, help="Number of tests per builder") + parser.add_argument('--testcase-roots-threshold', default=20, type=int, + help="Threshold value for number of modified testcase roots, up to which an optimized scope is still applied." + "When exceeded, full scope will be triggered") parser.add_argument('--detailed-test-id', action='store_true', help="Include paths to tests' locations in tests' names.") parser.add_argument("--no-detailed-test-id", dest='detailed_test_id', action="store_false", @@ -410,6 +426,12 @@ def parse_args(): "testcase.yaml files under here will be processed. May be " "called multiple times. Defaults to the 'samples/' and " "'tests/' directories at the base of the Zephyr tree.") + parser.add_argument( + "--quarantine-list", action="append", metavar="FILENAME", + help="Load list of test scenarios under quarantine. The entries in " + "the file need to correspond to the test scenarios names as in " + "corresponding tests .yaml files. These scenarios " + "will be skipped with quarantine as the reason.") # Include paths in names by default. parser.set_defaults(detailed_test_id=True) @@ -424,8 +446,8 @@ def parse_args(): errors = 0 if args.repo_to_scan: repository_path = Path(args.repo_to_scan) - if args.commits: repo_to_scan = Repo(repository_path) + if args.commits: commit = repo_to_scan.git.diff("--name-only", args.commits) files = commit.split("\n") elif args.modified_files: @@ -438,7 +460,8 @@ def parse_args(): print("=========") f = Filters(files, args.ignore_path, args.alt_tags, args.testsuite_root, - args.pull_request, args.platform, args.detailed_test_id) + args.pull_request, args.platform, args.detailed_test_id, args.quarantine_list, + args.testcase_roots_threshold) f.process() # remove dupes and filtered cases diff --git a/scripts/ci/twister_ignore.txt b/scripts/ci/twister_ignore.txt index 8db6878be3ae8..329a26d4d1e07 100644 --- a/scripts/ci/twister_ignore.txt +++ b/scripts/ci/twister_ignore.txt @@ -31,6 +31,8 @@ doc/* # GH action have no impact on code .github/* *.rst +*.jpg +*.png *.md # if we change this file or associated script, it should not trigger a full # twister. diff --git a/scripts/coccinelle/macros.h b/scripts/coccinelle/macros.h index 2cd5b75cf40c9..b13716689a45b 100644 --- a/scripts/coccinelle/macros.h +++ b/scripts/coccinelle/macros.h @@ -14,6 +14,8 @@ /* Zephyr macros */ +#define ZTEST(suite, fn) static void _##suite##_##fn##_wrapper(void) + /* Attributes */ /* Confirmed problematic */ diff --git a/scripts/coccinelle/ztest_strcmp.cocci b/scripts/coccinelle/ztest_strcmp.cocci new file mode 100644 index 0000000000000..6448bb1ad3ce4 --- /dev/null +++ b/scripts/coccinelle/ztest_strcmp.cocci @@ -0,0 +1,79 @@ +/// Find cases where ztest string comparisons macros can be used +// Copyright: (C) 2024 Nordic Semiconductor ASA +// SPDX-License-Identifier: Apache-2.0 +// Confidence: LOW +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +// Comparing result of strcmp with 0 + +@@ expression E1,E2; @@ +- zassert_equal(strcmp(E1, E2), 0); ++ zassert_str_equal(E1, E2); + +@@ expression E1,E2,E3; @@ +- zassert_equal(strcmp(E1, E2), 0, E3); ++ zassert_str_equal(E1, E2, E3); + +@@ expression E1,E2; @@ +- zassert_equal(0, strcmp(E1, E2)); ++ zassert_str_equal(E1, E2); + +@@ expression E1,E2,E3; @@ +- zassert_equal(0, !strcmp(E1, E2), E3); ++ zassert_str_equal(E1, E2, E3); + + + +// Using assert_true with !strcmp + +@@ expression E1,E2; @@ +- zassert_true(!strcmp(E1, E2)); ++ zassert_str_equal(E1, E2); + +@@ expression E1,E2,E3; @@ +- zassert_true(!strcmp(E1, E2), E3); ++ zassert_str_equal(E1, E2, E3); + + +// using zassert_true with strcmp(E1, E2) == 0 + +@@expression E1,E2; @@ +- zassert_true(strcmp(E1, E2) == 0); ++ zassert_str_equal(E1, E2); + +@@expression E1,E2; @@ +- zassert_true((strcmp(E1, E2) == 0)); ++ zassert_str_equal(E1, E2); + +@@expression E1,E2,E3; @@ +- zassert_true(strcmp(E1, E2) == 0, E3); ++ zassert_str_equal(E1, E2, E3); + +@@expression E1,E2,E3; @@ +- zassert_true((strcmp(E1, E2) == 0), E3); ++ zassert_str_equal(E1, E2, E3); + + + +// using zassert_true with 0 == strcmp(E1, E2) + +@@expression E1,E2; @@ +- zassert_true(0 == strcmp(E1, E2)); ++ zassert_str_equal(E1, E2); + +@@expression E1,E2; @@ +- zassert_true((0 == strcmp(E1, E2))); ++ zassert_str_equal(E1, E2); + +@@expression E1,E2,E3; @@ +- zassert_true(0 == strcmp(E1, E2), E3); ++ zassert_str_equal(E1, E2, E3); + +@@expression E1,E2,E3; @@ +- zassert_true((0 == strcmp(E1, E2)), E3); ++ zassert_str_equal(E1, E2, E3); diff --git a/scripts/coredump/gdbstubs/arch/arm64.py b/scripts/coredump/gdbstubs/arch/arm64.py index 008fb88c1b963..7f4c03eb375ea 100644 --- a/scripts/coredump/gdbstubs/arch/arm64.py +++ b/scripts/coredump/gdbstubs/arch/arm64.py @@ -95,7 +95,7 @@ def parse_arch_data_block(self): self.registers[RegNum.X17] = tu[17] self.registers[RegNum.X18] = tu[18] - # Callee saved registers are not provided in __esf structure + # Callee saved registers are not provided in arch_esf structure # So they will be omitted (set to undefined) when stub generates the # packet in handle_register_group_read_packet. diff --git a/scripts/dts/gen_defines.py b/scripts/dts/gen_defines.py index eb350b0483b70..a9d02dcd4d75d 100755 --- a/scripts/dts/gen_defines.py +++ b/scripts/dts/gen_defines.py @@ -132,6 +132,13 @@ def main(): out_dt_define(f"{node.z_path_id}_CHILD_IDX", node.parent.child_index(node)) + out_comment("Helpers for dealing with node labels:") + out_dt_define(f"{node.z_path_id}_NODELABEL_NUM", len(node.labels)) + out_dt_define(f"{node.z_path_id}_FOREACH_NODELABEL(fn)", + " ".join(f"fn({nodelabel})" for nodelabel in node.labels)) + out_dt_define(f"{node.z_path_id}_FOREACH_NODELABEL_VARGS(fn, ...)", + " ".join(f"fn({nodelabel}, __VA_ARGS__)" for nodelabel in node.labels)) + write_children(node) write_dep_info(node) write_idents_and_existence(node) @@ -416,6 +423,7 @@ def write_regs(node): idx_vals.append((idx_macro, f"{reg.addr} /* {hex(reg.addr)} */")) if reg.name: + name_vals.append((f"{path_id}_REG_NAME_{reg.name}_EXISTS", 1)) name_macro = f"{path_id}_REG_NAME_{reg.name}_VAL_ADDRESS" name_vals.append((name_macro, f"DT_{idx_macro}")) diff --git a/scripts/dts/python-devicetree/src/devicetree/dtlib.py b/scripts/dts/python-devicetree/src/devicetree/dtlib.py index d74fbc67d37d4..cc510ced40356 100644 --- a/scripts/dts/python-devicetree/src/devicetree/dtlib.py +++ b/scripts/dts/python-devicetree/src/devicetree/dtlib.py @@ -166,7 +166,13 @@ def _get_prop(self, name: str) -> 'Property': return prop def _del(self) -> None: - # Removes the node from the tree + # Removes the node from the tree. When called on the root node, + # this method will leave it empty but still part of the tree. + + if self.parent is None: + self.nodes.clear() + self.props.clear() + return self.parent.nodes.pop(self.name) # type: ignore def __str__(self): diff --git a/scripts/dts/python-devicetree/tests/test_dtlib.py b/scripts/dts/python-devicetree/tests/test_dtlib.py index b1b6ce33fd5a2..f7c8a31cc673c 100644 --- a/scripts/dts/python-devicetree/tests/test_dtlib.py +++ b/scripts/dts/python-devicetree/tests/test_dtlib.py @@ -911,6 +911,15 @@ def test_deletion(): verify_parse(""" /dts-v1/; +/ { + x = "foo"; + sub0 { + x = "bar"; + }; +}; + +/delete-node/ &{/}; + / { sub1 { x = < 1 >; @@ -940,6 +949,29 @@ def test_deletion(): x = < 0x1 >; }; }; +""") + + verify_parse(""" +/dts-v1/; + +/ { + x: x = < &sub >, ⊂ + + sub1 { + x = < &sub >, ⊂ + }; + sub2: sub2 { + x = < &sub >, ⊂ + }; +}; + +/delete-node/ &{/}; +""", +""" +/dts-v1/; + +/ { +}; """) verify_error_endswith(""" diff --git a/scripts/footprint/plan.txt b/scripts/footprint/plan.txt index 8e3f5b1b08940..bef204c017b43 100644 --- a/scripts/footprint/plan.txt +++ b/scripts/footprint/plan.txt @@ -19,8 +19,8 @@ bt_peripheral,default,nrf52840dk/nrf52840,samples/bluetooth/peripheral, bt_central_hr,default,nrf52840dk/nrf52840,samples/bluetooth/central_hr, bt_mesh_demo,default,bbc_microbit,samples/bluetooth/mesh_demo, bt_hap_ha,default,nrf5340dk/nrf5340_cpuapp,samples/bluetooth/hap_ha, -bt_unicast_audio_client,default,nrf5340dk/nrf5340/cpuapp,samples/bluetooth/unicast_audio_client, -bt_unicast_audio_server,default,nrf5340dk/nrf5340/cpuapp,samples/bluetooth/unicast_audio_server, +bt_bap_unicast_client,default,nrf5340dk/nrf5340/cpuapp,samples/bluetooth/bap_unicast_client, +bt_bap_unicast_server,default,nrf5340dk/nrf5340/cpuapp,samples/bluetooth/bap_unicast_server, bt_tmap_central,default,nrf5340dk/nrf5340/cpuapp,samples/bluetooth/tmap_central, bt_tmap_peripheral,default,nrf5340dk/nrf5340/cpuapp,samples/bluetooth/tmap_peripheral, bt_tmap_bms,default,nrf5340dk/nrf5340/cpuapp,samples/bluetooth/tmap_bms, diff --git a/scripts/footprint/size_report b/scripts/footprint/size_report index becabeb25a98d..414665c764172 100755 --- a/scripts/footprint/size_report +++ b/scripts/footprint/size_report @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Copyright (c) 2016, 2020 Intel Corporation +# Copyright (c) 2016, 2020-2024 Intel Corporation # # SPDX-License-Identifier: Apache-2.0 @@ -28,7 +28,6 @@ from anytree.exporter import DictExporter import elftools from elftools.elf.elffile import ELFFile -from elftools.elf.relocation import RelocationSection from elftools.elf.sections import SymbolTableSection from elftools.dwarf.descriptions import describe_form_class from elftools.dwarf.descriptions import ( @@ -69,9 +68,9 @@ def is_symbol_in_ranges(sym, ranges): """ for bound in ranges: if bound['start'] <= sym['st_value'] <= bound['end']: - return True + return bound - return False + return None def get_die_mapped_address(die, parser, dwarfinfo): @@ -128,7 +127,7 @@ def match_symbol_address(symlist, die, parser, dwarfinfo): def get_symbols(elf, addr_ranges): """ Fetch the symbols from the symbol table and put them - into ROM, RAM buckets. + into ROM, RAM, unassigned buckets. """ rom_syms = dict() ram_syms = dict() @@ -136,6 +135,7 @@ def get_symbols(elf, addr_ranges): rom_addr_ranges = addr_ranges['rom'] ram_addr_ranges = addr_ranges['ram'] + unassigned_addr_ranges = addr_ranges['unassigned'] for section in elf.iter_sections(): if isinstance(section, SymbolTableSection): @@ -147,24 +147,34 @@ def get_symbols(elf, addr_ranges): found_sec = False entry = {'name': sym.name, 'symbol': sym, - 'mapped_files': set()} + 'mapped_files': set(), + 'section': None} # If symbol is in ROM area? - if is_symbol_in_ranges(sym, rom_addr_ranges): + bound = is_symbol_in_ranges(sym, rom_addr_ranges) + if bound: if sym.name not in rom_syms: rom_syms[sym.name] = list() + entry['section'] = bound['name'] rom_syms[sym.name].append(entry) found_sec = True # If symbol is in RAM area? - if is_symbol_in_ranges(sym, ram_addr_ranges): + bound = is_symbol_in_ranges(sym, ram_addr_ranges) + if bound: if sym.name not in ram_syms: ram_syms[sym.name] = list() + entry['section'] = bound['name'] ram_syms[sym.name].append(entry) found_sec = True if not found_sec: - unassigned_syms['sym_name'] = entry + bound = is_symbol_in_ranges(sym, unassigned_addr_ranges) + if bound: + entry['section'] = bound['name'] + if sym.name not in unassigned_syms: + unassigned_syms[sym.name] = list() + unassigned_syms[sym.name].append(entry) ret = {'rom': rom_syms, 'ram': ram_syms, @@ -172,6 +182,18 @@ def get_symbols(elf, addr_ranges): return ret +def print_section_info(section, descr=""): + if args.verbose: + sec_size = section['sh_size'] + sec_start = section['sh_addr'] + sec_end = sec_start + (sec_size - 1 if sec_size else 0) + print(f"DEBUG: " + f"0x{sec_start:08x}-0x{sec_end:08x} " + f"{descr} '{section.name}': size={sec_size}, " + f"{section['sh_type']}, 0x{section['sh_flags']:08x}") +# + + def get_section_ranges(elf): """ Parse ELF header to find out the address ranges of ROM or RAM sections @@ -179,19 +201,26 @@ def get_section_ranges(elf): """ rom_addr_ranges = list() ram_addr_ranges = list() + unassigned_addr_ranges = list() + rom_size = 0 ram_size = 0 + unassigned_size = 0 for section in elf.iter_sections(): size = section['sh_size'] sec_start = section['sh_addr'] - sec_end = sec_start + size - 1 - bound = {'start': sec_start, 'end': sec_end} + sec_end = sec_start + (size - 1 if size else 0) + bound = {'start': sec_start, 'end': sec_end, 'name': section.name} + is_assigned = False if section['sh_type'] == 'SHT_NOBITS': # BSS and noinit sections ram_addr_ranges.append(bound) ram_size += size + is_assigned = True + print_section_info(section, "RAM bss section") + elif section['sh_type'] == 'SHT_PROGBITS': # Sections to be in flash or memory flags = section['sh_flags'] @@ -199,23 +228,37 @@ def get_section_ranges(elf): # Text section rom_addr_ranges.append(bound) rom_size += size + is_assigned = True + print_section_info(section, "ROM txt section") + elif (flags & SHF_WRITE_ALLOC) == SHF_WRITE_ALLOC: # Data occupies both ROM and RAM # since at boot, content is copied from ROM to RAM rom_addr_ranges.append(bound) rom_size += size - ram_addr_ranges.append(bound) ram_size += size + is_assigned = True + print_section_info(section, "ROM,RAM section") + elif (flags & SHF_ALLOC) == SHF_ALLOC: # Read only data rom_addr_ranges.append(bound) rom_size += size + is_assigned = True + print_section_info(section, "ROM r/o section") + + if not is_assigned: + print_section_info(section, "unassigned section") + unassigned_addr_ranges.append(bound) + unassigned_size += size ret = {'rom': rom_addr_ranges, 'rom_total_size': rom_size, 'ram': ram_addr_ranges, - 'ram_total_size': ram_size} + 'ram_total_size': ram_size, + 'unassigned': unassigned_addr_ranges, + 'unassigned_total_size': unassigned_size} return ret @@ -249,7 +292,7 @@ def get_die_filename(die, lineprog): return path -def do_simple_name_matching(elf, symbol_dict, processed): +def do_simple_name_matching(dwarfinfo, symbol_dict, processed): """ Sequentially process DIEs in compiler units with direct file mappings within the DIEs themselves, and do simply matching between DIE names @@ -260,7 +303,6 @@ def do_simple_name_matching(elf, symbol_dict, processed): unmapped_symbols = processed['unmapped_symbols'] newly_mapped_syms = set() - dwarfinfo = elf.get_dwarf_info() location_lists = dwarfinfo.location_lists() location_parser = LocationParser(location_lists) @@ -370,7 +412,7 @@ def mark_address_aliases(symbol_dict, processed): processed['unmapped_symbols'] = unmapped_symbols -def do_address_range_matching(elf, symbol_dict, processed): +def do_address_range_matching(dwarfinfo, symbol_dict, processed): """ Match symbols indirectly using address ranges. @@ -391,7 +433,6 @@ def do_address_range_matching(elf, symbol_dict, processed): unmapped_symbols = processed['unmapped_symbols'] newly_mapped_syms = set() - dwarfinfo = elf.get_dwarf_info() location_lists = dwarfinfo.location_lists() location_parser = LocationParser(location_lists) @@ -532,13 +573,16 @@ class TreeNode(NodeMixin): A symbol node. """ - def __init__(self, name, identifier, size=0, parent=None, children=None, address=0): + def __init__(self, name, identifier, size=0, parent=None, children=None, address=None, section=None): super().__init__() self._name = name self._size = size self.parent = parent self._identifier = identifier - self.address = address + if address is not None: + self.address = address + if section is not None: + self.section = section if children: self.children = children @@ -584,7 +628,7 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): # A set of helper function for building a simple tree with a path-like # hierarchy. - def _insert_one_elem(root, path, size, addr): + def _insert_one_elem(root, path, size, addr, section): cur = None node = None parent = root @@ -597,12 +641,28 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): results = findall_by_attr(root, cur, name="_identifier") if results: item = results[0] - item._size += size - parent = item + if not hasattr(item, 'address'): + # Passing down through a non-terminal parent node. + parent = item + parent._size += size + else: + # Another symbol node here with the same name; stick to its parent as well. + parent = item.parent + node = TreeNode(name=str(part), identifier=cur, size=size, parent=parent) else: + # There is no such terminal symbol in the tree yet; let's add it. if node: parent = node - node = TreeNode(name=str(part), identifier=cur, size=size, parent=parent, address=addr) + node = TreeNode(name=str(part), identifier=cur, size=size, parent=parent) + if node: + # Set memory block address and section name properties only for terminal symbol nodes. + # Don't do it on file- and directory- level parent nodes. + node.address = addr + node.section = section + else: + # normally this shouldn't happen; just to detect data or logic errors. + print(f"ERROR: no end node created for {root}, {path}, 0x{addr:08x}+{size}@{section}") + # # Mapping paths to tree nodes path_node_map = [ @@ -619,6 +679,7 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): for symbol in sym: size = get_symbol_size(symbol['symbol']) addr = get_symbol_addr(symbol['symbol']) + section = symbol['section'] for file in symbol['mapped_files']: path = Path(file, name) if path.is_absolute(): @@ -636,7 +697,7 @@ def generate_any_tree(symbol_dict, total_size, path_prefix): else: dest_node = node_no_paths - _insert_one_elem(dest_node, path, size, addr) + _insert_one_elem(dest_node, path, size, addr, section) if node_zephyr_base is not root: @@ -683,18 +744,21 @@ def print_any_tree(root, total_size, depth): """ Print the symbol tree. """ - print('{:101s} {:7s} {:8s} {:10s}'.format( - Fore.YELLOW + "Path", "Size", "%", "Address" + Fore.RESET)) - print('=' * 126) + print('{:98s} {:>7s} {:>7s} {:11s} {:16s}'.format( + Fore.YELLOW + "Path", "Size", "%", " Address", "Section" + Fore.RESET)) + print('=' * 138) for row in RenderTree(root, childiter=node_sort, maxlevel=depth): f = len(row.pre) + len(row.node._name) s = str(row.node._size).rjust(100-f) percent = 100 * float(row.node._size) / float(total_size) hex_addr = "-" + section_name = "" cc = cr = "" if not row.node.children: - if row.node._name != "(hidden)": + if hasattr(row.node, 'section'): + section_name = row.node.section + if hasattr(row.node, 'address'): hex_addr = "0x{:08x}".format(row.node.address) cc = Fore.CYAN cr = Fore.RESET @@ -702,8 +766,8 @@ def print_any_tree(root, total_size, depth): cc = Fore.GREEN cr = Fore.RESET - print(f"{row.pre}{cc}{row.node._name} {s} {cr}{Fore.BLUE}{percent:6.2f}%{Fore.RESET} {hex_addr}") - print('=' * 126) + print(f"{row.pre}{cc}{row.node._name} {s} {cr}{Fore.BLUE}{percent:6.2f}%{Fore.RESET} {hex_addr} {section_name}") + print('=' * 138) print(f'{total_size:>101}') @@ -755,22 +819,21 @@ def main(): elif args.target == 'all': targets = ['rom', 'ram'] - for t in targets: - - elf = ELFFile(open(args.kernel, "rb")) - - assert elf.has_dwarf_info(), "ELF file has no DWARF information" + elf = ELFFile(open(args.kernel, "rb")) + assert elf.has_dwarf_info(), "ELF file has no DWARF information" - set_global_machine_arch(elf.get_machine_arch()) + set_global_machine_arch(elf.get_machine_arch()) + addr_ranges = get_section_ranges(elf) + dwarfinfo = elf.get_dwarf_info() - addr_ranges = get_section_ranges(elf) + for t in targets: symbols = get_symbols(elf, addr_ranges) for sym in symbols['unassigned'].values(): - print("WARN: Symbol '{0}' is not in RAM or ROM".format(sym['name'])) - - symbol_dict = None + for sym_entry in sym: + print(f"WARN: Symbol '{sym_entry['name']}' section '{sym_entry['section']}' " + "is not in RAM or ROM.") if args.json: jsonout = args.json @@ -786,9 +849,9 @@ def main(): "mapped_addr": set(), "unmapped_symbols": set(symbol_dict.keys())} - do_simple_name_matching(elf, symbol_dict, processed) + do_simple_name_matching(dwarfinfo, symbol_dict, processed) mark_address_aliases(symbol_dict, processed) - do_address_range_matching(elf, symbol_dict, processed) + do_address_range_matching(dwarfinfo, symbol_dict, processed) mark_address_aliases(symbol_dict, processed) common_path_prefix = find_common_path_prefix(symbol_dict) set_root_path_for_unmapped_symbols(symbol_dict, ranges, processed) diff --git a/scripts/kconfig/hardened.csv b/scripts/kconfig/hardened.csv index f55899569e4f9..84d24dd1000cb 100644 --- a/scripts/kconfig/hardened.csv +++ b/scripts/kconfig/hardened.csv @@ -116,7 +116,6 @@ STM32_LPTIM_TIMER,n,experimental TFTP_LIB,n,experimental THRIFT,n,experimental UART_EMUL,n,experimental -UART_MUX,n,experimental UDC_DRIVER,n,experimental UHC_DRIVER,n,experimental USBD_CDC_ACM_CLASS,n,experimental diff --git a/scripts/kconfig/kconfigfunctions.py b/scripts/kconfig/kconfigfunctions.py index 58fcf9c6a1886..35699e96cb608 100644 --- a/scripts/kconfig/kconfigfunctions.py +++ b/scripts/kconfig/kconfigfunctions.py @@ -29,6 +29,7 @@ edtlib = inspect.getmodule(edt) else: edt = None + edtlib = None def _warn(kconf, msg): @@ -657,6 +658,32 @@ def dt_node_ph_array_prop(kconf, name, path, prop, index, cell, unit=None): if name == "dt_node_ph_array_prop_hex": return hex(_node_ph_array_prop(node, prop, index, cell, unit)) +def dt_node_ph_prop_path(kconf, name, path, prop): + """ + This function takes a 'path' and a property name ('prop') and + looks for an EDT node at that path. If it finds an EDT node, + it will look to see if that node has a property called 'prop' + and if that 'prop' is an phandle type. Then it will return the + path to the pointed-to node, or an empty string if there is + no such node. + """ + if doc_mode or edt is None: + return "" + + try: + node = edt.get_node(path) + except edtlib.EDTError: + return "" + + if prop not in node.props: + return "" + if node.props[prop].type != "phandle": + return "" + + phandle = node.props[prop].val + + return phandle.path if phandle else "" + def dt_node_str_prop_equals(kconf, _, path, prop, val): """ This function takes a 'path' and property name ('prop') looks for an EDT @@ -722,6 +749,21 @@ def dt_compat_on_bus(kconf, _, compat, bus): return "n" +def dt_compat_any_has_prop(kconf, _, compat, prop): + """ + This function takes a 'compat' and a 'prop' and returns "y" if any + node with compatible 'compat' also has a valid property 'prop'. + It returns "n" otherwise. + """ + if doc_mode or edt is None: + return "n" + + if compat in edt.compat2okay: + for node in edt.compat2okay[compat]: + if prop in node.props: + return "y" + + return "n" def dt_nodelabel_has_compat(kconf, _, label, compat): """ @@ -889,6 +931,7 @@ def substring(kconf, _, string, start, stop=None): "dt_has_compat": (dt_has_compat, 1, 1), "dt_compat_enabled": (dt_compat_enabled, 1, 1), "dt_compat_on_bus": (dt_compat_on_bus, 2, 2), + "dt_compat_any_has_prop": (dt_compat_any_has_prop, 2, 2), "dt_chosen_label": (dt_chosen_label, 1, 1), "dt_chosen_enabled": (dt_chosen_enabled, 1, 1), "dt_chosen_path": (dt_chosen_path, 1, 1), @@ -920,6 +963,7 @@ def substring(kconf, _, string, start, stop=None): "dt_node_array_prop_hex": (dt_node_array_prop, 3, 4), "dt_node_ph_array_prop_int": (dt_node_ph_array_prop, 4, 5), "dt_node_ph_array_prop_hex": (dt_node_ph_array_prop, 4, 5), + "dt_node_ph_prop_path": (dt_node_ph_prop_path, 2, 2), "dt_node_str_prop_equals": (dt_node_str_prop_equals, 3, 3), "dt_nodelabel_has_compat": (dt_nodelabel_has_compat, 2, 2), "dt_node_has_compat": (dt_node_has_compat, 2, 2), diff --git a/scripts/kconfig/kconfiglib.py b/scripts/kconfig/kconfiglib.py index bd541d07b42ae..f81979ec2c259 100644 --- a/scripts/kconfig/kconfiglib.py +++ b/scripts/kconfig/kconfiglib.py @@ -1419,7 +1419,7 @@ def load_allconfig(self, filename): def write_autoconf(self, filename=None, header=None): r""" Writes out symbol values as a C header file, matching the format used - by include/generated/autoconf.h in the kernel. + by include/generated/zephyr/autoconf.h in the kernel. The ordering of the #defines matches the one generated by write_config(). The order in the C implementation depends on the hash @@ -1434,7 +1434,7 @@ def write_autoconf(self, filename=None, header=None): Path to write header to. If None (the default), the path in the environment variable - KCONFIG_AUTOHEADER is used if set, and "include/generated/autoconf.h" + KCONFIG_AUTOHEADER is used if set, and "include/generated/zephyr/autoconf.h" otherwise. This is compatible with the C tools. header (default: None): @@ -1453,7 +1453,7 @@ def write_autoconf(self, filename=None, header=None): """ if filename is None: filename = os.getenv("KCONFIG_AUTOHEADER", - "include/generated/autoconf.h") + "include/generated/zephyr/autoconf.h") if self._write_if_changed(filename, self._autoconf_contents(header)): return "Kconfig header saved to '{}'".format(filename) diff --git a/scripts/list_shields.py b/scripts/list_shields.py new file mode 100755 index 0000000000000..dfbf2580eb40c --- /dev/null +++ b/scripts/list_shields.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2024 Vestas Wind Systems A/S +# Copyright (c) 2020 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +import argparse +from dataclasses import dataclass +from pathlib import Path + +# +# This is shared code between the build system's 'shields' target +# and the 'west shields' extension command. If you change it, make +# sure to test both ways it can be used. +# +# (It's done this way to keep west optional, making it possible to run +# 'ninja shields' in a build directory without west installed.) +# + +@dataclass(frozen=True) +class Shield: + name: str + dir: Path + +def shield_key(shield): + return shield.name + +def find_shields(args): + ret = [] + + for root in args.board_roots: + for shields in find_shields_in(root): + ret.append(shields) + + return sorted(ret, key=shield_key) + +def find_shields_in(root): + shields = root / 'boards' / 'shields' + ret = [] + + for maybe_shield in (shields).iterdir(): + if not maybe_shield.is_dir(): + continue + for maybe_kconfig in maybe_shield.iterdir(): + if maybe_kconfig.name == 'Kconfig.shield': + for maybe_overlay in maybe_shield.iterdir(): + file_name = maybe_overlay.name + if file_name.endswith('.overlay'): + shield_name = file_name[:-len('.overlay')] + ret.append(Shield(shield_name, maybe_shield)) + + return sorted(ret, key=shield_key) + +def parse_args(): + parser = argparse.ArgumentParser(allow_abbrev=False) + add_args(parser) + return parser.parse_args() + +def add_args(parser): + # Remember to update west-completion.bash if you add or remove + # flags + parser.add_argument("--board-root", dest='board_roots', default=[], + type=Path, action='append', + help='add a board root, may be given more than once') + +def dump_shields(shields): + for shield in shields: + print(f' {shield.name}') + +if __name__ == '__main__': + dump_shields(find_shields(parse_args())) diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/binary_adapter.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/binary_adapter.py index 228981be0f170..5056f0ccd507a 100755 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/binary_adapter.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/binary_adapter.py @@ -118,7 +118,7 @@ class NativeSimulatorAdapter(BinaryAdapterBase): def generate_command(self) -> None: """Set command to run.""" - self.command = [str(self.device_config.build_dir / 'zephyr' / 'zephyr.exe')] + self.command = [str(self.device_config.app_build_dir / 'zephyr' / 'zephyr.exe')] class UnitSimulatorAdapter(BinaryAdapterBase): @@ -126,10 +126,10 @@ class UnitSimulatorAdapter(BinaryAdapterBase): def generate_command(self) -> None: """Set command to run.""" - self.command = [str(self.device_config.build_dir / 'testbinary')] + self.command = [str(self.device_config.app_build_dir / 'testbinary')] class CustomSimulatorAdapter(BinaryAdapterBase): def generate_command(self) -> None: """Set command to run.""" - self.command = [self.west, 'build', '-d', str(self.device_config.build_dir), '-t', 'run'] + self.command = [self.west, 'build', '-d', str(self.device_config.app_build_dir), '-t', 'run'] diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py index b5560650c1b6c..3f73045f899fe 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/device_adapter.py @@ -14,6 +14,7 @@ import time from datetime import datetime from pathlib import Path +from serial import SerialException from twister_harness.exceptions import ( TwisterHarnessException, @@ -69,14 +70,23 @@ def launch(self) -> None: if self.device_config.type != 'hardware': self._flash_and_run() + self._device_run.set() + self._start_reader_thread() + self.connect() + return self._device_run.set() self._start_reader_thread() - self.connect() - if self.device_config.type == 'hardware': + if self.device_config.flash_before: + # For hardware devices with shared USB or software USB, connect after flashing. + # Retry for up to 10 seconds for USB-CDC based devices to enumerate. + self._flash_and_run() + self.connect(retry_s = 10) + else: # On hardware, flash after connecting to COM port, otherwise some messages # from target can be lost. + self.connect() self._flash_and_run() def close(self) -> None: @@ -89,7 +99,7 @@ def close(self) -> None: self._device_run.clear() self._join_reader_thread() - def connect(self) -> None: + def connect(self, retry_s: int = 0) -> None: """Connect to device - allow for output gathering.""" if self.is_device_connected(): logger.debug('Device already connected') @@ -98,7 +108,20 @@ def connect(self) -> None: msg = 'Cannot connect to not working device' logger.error(msg) raise TwisterHarnessException(msg) - self._connect_device() + + if retry_s > 0: + retry_cycles = retry_s * 10 + for i in range(retry_cycles): + try: + self._connect_device() + break + except SerialException: + if i == retry_cycles - 1: + raise + time.sleep(0.1) + else: + self._connect_device() + self._device_connected.set() def disconnect(self) -> None: diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/qemu_adapter.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/qemu_adapter.py index cae17bc46e9ae..110ce601c2319 100755 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/device/qemu_adapter.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/device/qemu_adapter.py @@ -23,7 +23,7 @@ def __init__(self, device_config: DeviceConfig) -> None: def generate_command(self) -> None: """Set command to run.""" - self.command = [self.west, 'build', '-d', str(self.device_config.build_dir), '-t', 'run'] + self.command = [self.west, 'build', '-d', str(self.device_config.app_build_dir), '-t', 'run'] if 'stdin' in self.process_kwargs: self.process_kwargs.pop('stdin') diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/domains_helper.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/domains_helper.py new file mode 100644 index 0000000000000..c70beec120bb2 --- /dev/null +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/helpers/domains_helper.py @@ -0,0 +1,27 @@ +# Copyright (c) 2024 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations + +import os +import sys +import logging + +from pathlib import Path + +ZEPHYR_BASE = os.environ['ZEPHYR_BASE'] +sys.path.insert(0, os.path.join(ZEPHYR_BASE, 'scripts', 'pylib', 'build_helpers')) + +from domains import Domains + +logger = logging.getLogger(__name__) +logging.getLogger('pykwalify').setLevel(logging.ERROR) + + +def get_default_domain_name(domains_file: Path | str) -> int: + """ + Get the default domain name from the domains.yaml file + """ + domains = Domains.from_file(domains_file) + logger.debug("Loaded sysbuild domain data from %s" % domains_file) + return domains.get_default_domain().name diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py index 34a09aa38f536..e484cb8bb43ca 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/plugin.py @@ -84,6 +84,13 @@ def pytest_addoption(parser: pytest.Parser): '--device-serial-pty', help='Script for controlling pseudoterminal.' ) + twister_harness_group.addoption( + '--flash-before', + type=bool, + help='Flash device before attaching to serial port' + 'This is useful for devices that share the same port for programming' + 'and serial console, or use soft-USB, where flash must come first.' + ) twister_harness_group.addoption( '--west-flash-extra-args', help='Extend parameters for west flash. ' @@ -110,6 +117,10 @@ def pytest_addoption(parser: pytest.Parser): choices=('function', 'class', 'module', 'package', 'session'), help='The scope for which `dut` and `shell` fixtures are shared.' ) + twister_harness_group.addoption( + '--twister-fixture', action='append', dest='fixtures', metavar='FIXTURE', default=[], + help='Twister fixture supported by this platform. May be given multiple times.' + ) def pytest_configure(config: pytest.Config): diff --git a/scripts/pylib/pytest-twister-harness/src/twister_harness/twister_harness_config.py b/scripts/pylib/pytest-twister-harness/src/twister_harness/twister_harness_config.py index ece190c630f88..a4b0b7497775d 100644 --- a/scripts/pylib/pytest-twister-harness/src/twister_harness/twister_harness_config.py +++ b/scripts/pylib/pytest-twister-harness/src/twister_harness/twister_harness_config.py @@ -7,6 +7,7 @@ import logging from dataclasses import dataclass, field from pathlib import Path +from twister_harness.helpers.domains_helper import get_default_domain_name import pytest @@ -26,11 +27,21 @@ class DeviceConfig: id: str = '' product: str = '' serial_pty: str = '' + flash_before: bool = False west_flash_extra_args: list[str] = field(default_factory=list, repr=False) name: str = '' pre_script: Path | None = None post_script: Path | None = None post_flash_script: Path | None = None + fixtures: list[str] = None + app_build_dir: Path | None = None + + def __post_init__(self): + domains = self.build_dir / 'domains.yaml' + if domains.exists(): + self.app_build_dir = self.build_dir / get_default_domain_name(domains) + else: + self.app_build_dir = self.build_dir @dataclass @@ -62,10 +73,12 @@ def create(cls, config: pytest.Config) -> TwisterHarnessConfig: id=config.option.device_id, product=config.option.device_product, serial_pty=config.option.device_serial_pty, + flash_before=bool(config.option.flash_before), west_flash_extra_args=west_flash_extra_args, pre_script=_cast_to_path(config.option.pre_script), post_script=_cast_to_path(config.option.post_script), post_flash_script=_cast_to_path(config.option.post_flash_script), + fixtures=config.option.fixtures, ) devices.append(device_from_cli) diff --git a/scripts/pylib/pytest-twister-harness/tests/device/qemu_adapter_test.py b/scripts/pylib/pytest-twister-harness/tests/device/qemu_adapter_test.py index bcc6a5f472493..42406cb702d14 100755 --- a/scripts/pylib/pytest-twister-harness/tests/device/qemu_adapter_test.py +++ b/scripts/pylib/pytest-twister-harness/tests/device/qemu_adapter_test.py @@ -27,7 +27,7 @@ def fixture_device_adapter(tmp_path) -> Generator[QemuAdapter, None, None]: @patch('shutil.which', return_value='west') def test_if_generate_command_creates_proper_command(patched_which, device: QemuAdapter): - device.device_config.build_dir = Path('build_dir') + device.device_config.app_build_dir = Path('build_dir') device.generate_command() assert device.command == ['west', 'build', '-d', 'build_dir', '-t', 'run'] diff --git a/scripts/pylib/twister/twisterlib/coverage.py b/scripts/pylib/twister/twisterlib/coverage.py index 556f5b359baa4..26ffefec997a8 100644 --- a/scripts/pylib/twister/twisterlib/coverage.py +++ b/scripts/pylib/twister/twisterlib/coverage.py @@ -144,6 +144,7 @@ class Lcov(CoverageTool): def __init__(self, jobs=None): super().__init__() self.ignores = [] + self.ignore_branch_patterns = [] self.output_formats = "lcov,html" self.version = self.get_version() self.jobs = jobs @@ -169,6 +170,9 @@ def add_ignore_file(self, pattern): def add_ignore_directory(self, pattern): self.ignores.append('*/' + pattern + '/*') + def add_ignore_branch_pattern(self, pattern): + self.ignore_branch_patterns.append(pattern) + @property def is_lcov_v2(self): return self.version.startswith("2") @@ -252,6 +256,7 @@ class Gcovr(CoverageTool): def __init__(self): super().__init__() self.ignores = [] + self.ignore_branch_patterns = [] self.output_formats = "html" self.version = self.get_version() @@ -278,6 +283,9 @@ def add_ignore_file(self, pattern): def add_ignore_directory(self, pattern): self.ignores.append(".*/" + pattern + '/.*') + def add_ignore_branch_pattern(self, pattern): + self.ignore_branch_patterns.append(pattern) + @staticmethod def _interleave_list(prefix, list): tuple_list = [(prefix, item) for item in list] @@ -292,6 +300,7 @@ def _generate(self, outdir, coveragelog): ztestfile = os.path.join(outdir, "ztest.json") excludes = Gcovr._interleave_list("-e", self.ignores) + excludes += Gcovr._interleave_list("--exclude-branches-by-pattern", self.ignore_branch_patterns) # Different ifdef-ed implementations of the same function should not be # in conflict treated by GCOVR as separate objects for coverage statistics. @@ -383,5 +392,8 @@ def run_coverage(testplan, options): coverage_tool.add_ignore_file('generated') coverage_tool.add_ignore_directory('tests') coverage_tool.add_ignore_directory('samples') + # Ignore branch coverage on LOG_* and LOG_HEXDUMP_* macros + # Branch misses are due to the implementation of Z_LOG2 and cannot be avoided + coverage_tool.add_ignore_branch_pattern(r"^\s*LOG_(?:HEXDUMP_)?(?:DBG|INF|WRN|ERR)\(.*") coverage_completed = coverage_tool.generate(options.outdir) return coverage_completed diff --git a/scripts/pylib/twister/twisterlib/environment.py b/scripts/pylib/twister/twisterlib/environment.py index 43c05750bf845..01b415ad820f1 100644 --- a/scripts/pylib/twister/twisterlib/environment.py +++ b/scripts/pylib/twister/twisterlib/environment.py @@ -72,7 +72,7 @@ def add_parse_arguments(parser = None): run_group_option = parser.add_mutually_exclusive_group() - device = parser.add_mutually_exclusive_group(required="--device-testing" in sys.argv) + device = parser.add_mutually_exclusive_group() test_or_build = parser.add_mutually_exclusive_group() @@ -178,7 +178,7 @@ def add_parse_arguments(parser = None): parser.add_argument("--flash-before", action="store_true", default=False, help="""Flash device before attaching to serial port. This is useful for devices that share the same port for programming - and serial console, where flash must come first. + and serial console, or use soft-USB, where flash must come first. """) test_or_build.add_argument( @@ -257,7 +257,7 @@ def add_parse_arguments(parser = None): "-A", "--board-root", action="append", default=board_root_list, help="""Directory to search for board configuration files. All .yaml files in the directory will be processed. The directory should have the same -structure in the main Zephyr tree: boards///""") +structure in the main Zephyr tree: boards///""") parser.add_argument( "--allow-installed-plugin", action="store_true", default=None, @@ -385,6 +385,18 @@ def add_parse_arguments(parser = None): help="Generate detailed json reports with ROM/RAM symbol sizes for each test image built " "using additional build option `--target footprint`.") + footprint_group.add_argument( + "--footprint-report", + nargs="?", + default=None, + choices=['all', 'ROM', 'RAM'], + const="all", + help="Select which memory area symbols' data to collect as 'footprint' property " + "of each test suite built, and report in 'twister_footprint.json' together " + "with the relevant execution metadata the same way as in `twister.json`. " + "Implies '--create-rom-ram-report' to generate the footprint data files. " + "No value means '%(const)s'. Default: %(default)s""") + footprint_group.add_argument( "--enable-size-report", action="store_true", @@ -547,6 +559,8 @@ def add_parse_arguments(parser = None): parser.add_argument("--overflow-as-errors", action="store_true", help="Treat RAM/SRAM overflows as errors.") + parser.add_argument("--report-filtered", action="store_true", + help="Include filtered tests in the reports.") parser.add_argument("-P", "--exclude-platform", action="append", default=[], help="""Exclude platforms and do not build or run any tests @@ -602,12 +616,24 @@ def add_parse_arguments(parser = None): help="""Create a report with a custom name. """) + parser.add_argument( + "--report-summary", action="store", nargs='?', type=int, const=0, + help="Show failed/error report from latest run. Default shows all items found. " + "However, you can specify the number of items (e.g. --report-summary 15). " + "It also works well with the --outdir switch.") + parser.add_argument( "--report-suffix", help="""Add a suffix to all generated file names, for example to add a version or a commit ID. """) + parser.add_argument( + "--report-all-options", action="store_true", + help="""Show all command line options applied, including defaults, as + environment.options object in twister.json. Default: show only non-default settings. + """) + parser.add_argument( "--retry-failed", type=int, default=0, help="Retry failing tests again, up to the number of times specified.") @@ -738,7 +764,7 @@ def add_parse_arguments(parser = None): return parser -def parse_arguments(parser, args, options = None): +def parse_arguments(parser, args, options = None, on_init=True): if options is None: options = parser.parse_args(args) @@ -776,13 +802,16 @@ def parse_arguments(parser, args, options = None): if options.last_metrics or options.compare_report: options.enable_size_report = True + if options.footprint_report: + options.create_rom_ram_report = True + if options.aggressive_no_clean: options.no_clean = True if options.coverage: options.enable_coverage = True - if not options.coverage_platform: + if options.enable_coverage and not options.coverage_platform: options.coverage_platform = options.platform if options.coverage_formats: @@ -796,6 +825,10 @@ def parse_arguments(parser, args, options = None): logger.error("valgrind enabled but valgrind executable not found") sys.exit(1) + if (not options.device_testing) and (options.device_serial or options.device_serial_pty or options.hardware_map): + logger.error("Use --device-testing with --device-serial, or --device-serial-pty, or --hardware-map.") + sys.exit(1) + if options.device_testing and (options.device_serial or options.device_serial_pty) and len(options.platform) != 1: logger.error("When --device-testing is used with --device-serial " "or --device-serial-pty, exactly one platform must " @@ -856,13 +889,13 @@ def parse_arguments(parser, args, options = None): # Strip off the initial "--" following validation. options.extra_test_args = options.extra_test_args[1:] - if not options.allow_installed_plugin and PYTEST_PLUGIN_INSTALLED: + if on_init and not options.allow_installed_plugin and PYTEST_PLUGIN_INSTALLED: logger.error("By default Twister should work without pytest-twister-harness " "plugin being installed, so please, uninstall it by " "`pip uninstall pytest-twister-harness` and `git clean " "-dxf scripts/pylib/pytest-twister-harness`.") sys.exit(1) - elif options.allow_installed_plugin and PYTEST_PLUGIN_INSTALLED: + elif on_init and options.allow_installed_plugin and PYTEST_PLUGIN_INSTALLED: logger.warning("You work with installed version of " "pytest-twister-harness plugin.") @@ -874,12 +907,13 @@ def strip_ansi_sequences(s: str) -> str: class TwisterEnv: - def __init__(self, options=None) -> None: + def __init__(self, options=None, default_options=None) -> None: self.version = "Unknown" self.toolchain = None self.commit_date = "Unknown" self.run_date = None self.options = options + self.default_options = default_options if options and options.ninja: self.generator_cmd = "ninja" @@ -914,6 +948,18 @@ def __init__(self, options=None) -> None: self.alt_config_root = options.alt_config_root if options else None + def non_default_options(self) -> dict: + """Returns current command line options which are set to non-default values.""" + diff = {} + if not self.options or not self.default_options: + return diff + dict_options = vars(self.options) + dict_default = vars(self.default_options) + for k in dict_options.keys(): + if k not in dict_default or dict_options[k] != dict_default[k]: + diff[k] = dict_options[k] + return diff + def discover(self): self.check_zephyr_version() self.get_toolchain() diff --git a/scripts/pylib/twister/twisterlib/handlers.py b/scripts/pylib/twister/twisterlib/handlers.py index eaef473af71d7..f832425245002 100755 --- a/scripts/pylib/twister/twisterlib/handlers.py +++ b/scripts/pylib/twister/twisterlib/handlers.py @@ -5,7 +5,6 @@ # Copyright 2022 NXP # SPDX-License-Identifier: Apache-2.0 -import csv import logging import math import os @@ -22,6 +21,7 @@ from queue import Queue, Empty from twisterlib.environment import ZEPHYR_BASE, strip_ansi_sequences from twisterlib.error import TwisterException +from twisterlib.platform import Platform sys.path.insert(0, os.path.join(ZEPHYR_BASE, "scripts/pylib/build_helpers")) from domains import Domains @@ -75,7 +75,6 @@ def __init__(self, instance, type_str="build"): self.run = False self.type_str = type_str - self.binary = None self.pid_fn = None self.call_make_run = True @@ -97,22 +96,6 @@ def get_test_timeout(self): self.instance.platform.timeout_multiplier * self.options.timeout_multiplier) - def record(self, harness): - if harness.recording: - if self.instance.recording is None: - self.instance.recording = harness.recording.copy() - else: - self.instance.recording.extend(harness.recording) - - filename = os.path.join(self.build_dir, "recording.csv") - with open(filename, "at") as csvfile: - cw = csv.DictWriter(csvfile, - fieldnames = harness.recording[0].keys(), - lineterminator = os.linesep, - quoting = csv.QUOTE_NONNUMERIC) - cw.writeheader() - cw.writerows(harness.recording) - def terminate(self, proc): terminate_process(proc) self.terminated = True @@ -131,10 +114,12 @@ def _verify_ztest_suite_name(self, harness_state, detected_suite_names, handler_ return if not detected_suite_names: self._missing_suite_name(expected_suite_names, handler_time) - for detected_suite_name in detected_suite_names: - if detected_suite_name not in expected_suite_names: + return + # compare the expect and detect from end one by one without order + _d_suite = detected_suite_names[-len(expected_suite_names):] + if set(_d_suite) != set(expected_suite_names): + if not set(_d_suite).issubset(set(expected_suite_names)): self._missing_suite_name(expected_suite_names, handler_time) - break def _missing_suite_name(self, expected_suite_names, handler_time): """ @@ -165,7 +150,20 @@ def _final_handle_actions(self, harness, handler_time): for tc in self.instance.testcases: tc.status = "failed" - self.record(harness) + self.instance.record(harness.recording) + + def get_default_domain_build_dir(self): + if self.instance.sysbuild: + # Load domain yaml to get default domain build directory + # Note: for targets using QEMU, we assume that the target will + # have added any additional images to the run target manually + domain_path = os.path.join(self.build_dir, "domains.yaml") + domains = Domains.from_file(domain_path) + logger.debug("Loaded sysbuild domain data from %s" % domain_path) + build_dir = domains.get_default_domain().build_dir + else: + build_dir = self.build_dir + return build_dir class BinaryHandler(Handler): @@ -235,11 +233,28 @@ def _output_handler(self, proc, harness): def _create_command(self, robot_test): if robot_test: - command = [self.generator_cmd, "run_renode_test"] + keywords = os.path.join(self.options.coverage_basedir, 'tests/robot/common.robot') + elf = os.path.join(self.build_dir, "zephyr/zephyr.elf") + command = [self.generator_cmd] + resc = "" + uart = "" + # os.path.join cannot be used on a Mock object, so we are + # explicitly checking the type + if isinstance(self.instance.platform, Platform): + resc = os.path.join(self.options.coverage_basedir, self.instance.platform.resc) + uart = self.instance.platform.uart + command = ["renode-test", + "--variable", "KEYWORDS:" + keywords, + "--variable", "ELF:@" + elf, + "--variable", "RESC:@" + resc, + "--variable", "UART:" + uart] elif self.call_make_run: command = [self.generator_cmd, "run"] - else: + elif self.instance.testsuite.type == "unit": command = [self.binary] + else: + binary = os.path.join(self.get_default_domain_build_dir(), "zephyr", "zephyr.exe") + command = [binary] if self.options.enable_valgrind: command = ["valgrind", "--error-exitcode=2", @@ -307,8 +322,9 @@ def handle(self, harness): harness.run_robot_test(command, self) return - with subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=subprocess.PIPE, cwd=self.build_dir, env=env) as proc: + stderr_log = "{}/handler_stderr.log".format(self.instance.build_dir) + with open(stderr_log, "w+") as stderr_log_fp, subprocess.Popen(command, stdout=subprocess.PIPE, + stderr=stderr_log_fp, cwd=self.build_dir, env=env) as proc: logger.debug("Spawning BinaryHandler Thread for %s" % self.name) t = threading.Thread(target=self._output_handler, args=(proc, harness,), daemon=True) t.start() @@ -318,6 +334,9 @@ def handle(self, harness): t.join() proc.wait() self.returncode = proc.returncode + if proc.returncode != 0: + self.instance.status = "error" + self.instance.reason = "BinaryHandler returned {}".format(proc.returncode) self.try_kill_process_by_pid() handler_time = time.time() - start_time @@ -344,7 +363,6 @@ def __init__(self, instance, type_str): self.pid_fn = os.path.join(instance.build_dir, "renode.pid") elif type_str == 'native': self.call_make_run = False - self.binary = os.path.join(instance.build_dir, "zephyr", "zephyr.exe") self.ready = True @@ -438,7 +456,7 @@ def device_is_available(self, instance): dut_found = False for d in self.duts: - if fixture and fixture not in d.fixtures: + if fixture and fixture not in map(lambda f: f.split(sep=':')[0], d.fixtures): continue if d.platform != device or (d.serial is None and d.serial_pty is None): continue @@ -551,6 +569,16 @@ def _update_instance_info(self, harness_state, handler_time, flash_error): if self.instance.status in ["error", "failed"]: self.instance.add_missing_case_status("blocked", self.instance.reason) + def _terminate_pty(self, ser_pty, ser_pty_process): + logger.debug(f"Terminating serial-pty:'{ser_pty}'") + terminate_process(ser_pty_process) + try: + (stdout, stderr) = ser_pty_process.communicate(timeout=self.get_test_timeout()) + logger.debug(f"Terminated serial-pty:'{ser_pty}', stdout:'{stdout}', stderr:'{stderr}'") + except subprocess.TimeoutExpired: + logger.debug(f"Terminated serial-pty:'{ser_pty}'") + # + def _create_serial_connection(self, serial_device, hardware_baud, flash_timeout, serial_pty, ser_pty_process): try: @@ -570,9 +598,7 @@ def _create_serial_connection(self, serial_device, hardware_baud, self.instance.add_missing_case_status("blocked", "Serial Device Error") if serial_pty and ser_pty_process: - ser_pty_process.terminate() - outs, errs = ser_pty_process.communicate() - logger.debug("Process {} terminated outs: {} errs {}".format(serial_pty, outs, errs)) + self._terminate_pty(serial_pty, ser_pty_process) if serial_pty: self.make_device_available(serial_pty) @@ -736,9 +762,7 @@ def handle(self, harness): ser.close() if serial_pty: - ser_pty_process.terminate() - outs, errs = ser_pty_process.communicate() - logger.debug("Process {} terminated outs: {} errs {}".format(serial_pty, outs, errs)) + self._terminate_pty(serial_pty, ser_pty_process) handler_time = time.time() - start_time @@ -775,6 +799,10 @@ def __init__(self, instance, type_str): self.pid_fn = os.path.join(instance.build_dir, "qemu.pid") + self.stdout_fn = os.path.join(instance.build_dir, "qemu.stdout") + + self.stderr_fn = os.path.join(instance.build_dir, "qemu.stderr") + if instance.testsuite.ignore_qemu_crash: self.ignore_qemu_crash = True self.ignore_unexpected_eof = True @@ -838,19 +866,12 @@ def _thread_close_files(fifo_in, fifo_out, pid, out_fp, in_fp, log_out_fp): os.unlink(fifo_out) @staticmethod - def _thread_update_instance_info(handler, handler_time, out_state): + def _thread_update_instance_info(handler, handler_time, status, reason): handler.instance.execution_time = handler_time - if out_state == "timeout": - handler.instance.status = "failed" - handler.instance.reason = "Timeout" - elif out_state == "failed": - handler.instance.status = "failed" - handler.instance.reason = "Failed" - elif out_state in ['unexpected eof', 'unexpected byte']: - handler.instance.status = "failed" - handler.instance.reason = out_state + handler.instance.status = status + if reason: + handler.instance.reason = reason else: - handler.instance.status = out_state handler.instance.reason = "Unknown" @staticmethod @@ -868,7 +889,8 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, timeout_time = start_time + timeout p = select.poll() p.register(in_fp, select.POLLIN) - out_state = None + _status = None + _reason = None line = "" timeout_extended = False @@ -879,6 +901,9 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, while True: this_timeout = int((timeout_time - time.time()) * 1000) + if timeout_extended: + # Quit early after timeout extension if no more data is being received + this_timeout = min(this_timeout, 1000) if this_timeout < 0 or not p.poll(this_timeout): try: if pid and this_timeout > 0: @@ -886,17 +911,19 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, # of not enough CPU time scheduled by host for # QEMU process during p.poll(this_timeout) cpu_time = QEMUHandler._get_cpu_time(pid) - if cpu_time < timeout and not out_state: + if cpu_time < timeout and not _status: timeout_time = time.time() + (timeout - cpu_time) continue except psutil.NoSuchProcess: pass except ProcessLookupError: - out_state = "failed" + _status = "failed" + _reason = "Execution error" break - if not out_state: - out_state = "timeout" + if not _status: + _status = "failed" + _reason = "timeout" break if pid == 0 and os.path.exists(pid_fn): @@ -906,13 +933,15 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, c = in_fp.read(1).decode("utf-8") except UnicodeDecodeError: # Test is writing something weird, fail - out_state = "unexpected byte" + _status = "failed" + _reason = "unexpected byte" break if c == "": # EOF, this shouldn't happen unless QEMU crashes if not ignore_unexpected_eof: - out_state = "unexpected eof" + _status = "failed" + _reason = "unexpected eof" break line = line + c if c != "\n": @@ -926,13 +955,14 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, harness.handle(line) if harness.state: - # if we have registered a fail make sure the state is not + # if we have registered a fail make sure the status is not # overridden by a false success message coming from the # testsuite - if out_state not in ['failed', 'unexpected eof', 'unexpected byte']: - out_state = harness.state + if _status != 'failed': + _status = harness.state + _reason = harness.reason - # if we get some state, that means test is doing well, we reset + # if we get some status, that means test is doing well, we reset # the timeout and wait for 2 more seconds to catch anything # printed late. We wait much longer if code # coverage is enabled since dumping this information can @@ -946,26 +976,12 @@ def _thread(handler, timeout, outdir, logfile, fifo_fn, pid_fn, line = "" handler_time = time.time() - start_time - logger.debug(f"QEMU ({pid}) complete ({out_state}) after {handler_time} seconds") + logger.debug(f"QEMU ({pid}) complete with {_status} ({_reason}) after {handler_time} seconds") - QEMUHandler._thread_update_instance_info(handler, handler_time, out_state) + QEMUHandler._thread_update_instance_info(handler, handler_time, _status, _reason) QEMUHandler._thread_close_files(fifo_in, fifo_out, pid, out_fp, in_fp, log_out_fp) - def _get_sysbuild_build_dir(self): - if self.instance.testsuite.sysbuild: - # Load domain yaml to get default domain build directory - # Note: for targets using QEMU, we assume that the target will - # have added any additional images to the run target manually - domain_path = os.path.join(self.build_dir, "domains.yaml") - domains = Domains.from_file(domain_path) - logger.debug("Loaded sysbuild domain data from %s" % domain_path) - build_dir = domains.get_default_domain().build_dir - else: - build_dir = self.build_dir - - return build_dir - def _set_qemu_filenames(self, sysbuild_build_dir): # We pass this to QEMU which looks for fifos with .in and .out suffixes. # QEMU fifo will use main build dir @@ -997,11 +1013,11 @@ def _update_instance_info(self, harness_state, is_timeout): def handle(self, harness): self.run = True - sysbuild_build_dir = self._get_sysbuild_build_dir() + domain_build_dir = self.get_default_domain_build_dir() - command = self._create_command(sysbuild_build_dir) + command = self._create_command(domain_build_dir) - self._set_qemu_filenames(sysbuild_build_dir) + self._set_qemu_filenames(domain_build_dir) self.thread = threading.Thread(name=self.name, target=QEMUHandler._thread, args=(self, self.get_test_timeout(), self.build_dir, @@ -1021,7 +1037,7 @@ def handle(self, harness): is_timeout = False qemu_pid = None - with subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=self.build_dir) as proc: + with subprocess.Popen(command, stdout=open(self.stdout_fn, "wt"), stderr=open(self.stderr_fn, "wt"), cwd=self.build_dir) as proc: logger.debug("Spawning QEMUHandler Thread for %s" % self.name) try: @@ -1126,35 +1142,14 @@ def _stop_qemu_process(pid): pass @staticmethod - def _monitor_update_instance_info(handler, handler_time, out_state): + def _monitor_update_instance_info(handler, handler_time, status, reason): handler.instance.execution_time = handler_time - if out_state == "timeout": - handler.instance.status = "failed" - handler.instance.reason = "Timeout" - elif out_state == "failed": - handler.instance.status = "failed" - handler.instance.reason = "Failed" - elif out_state in ['unexpected eof', 'unexpected byte']: - handler.instance.status = "failed" - handler.instance.reason = out_state + handler.instance.status = status + if reason: + handler.instance.reason = reason else: - handler.instance.status = out_state handler.instance.reason = "Unknown" - def _get_sysbuild_build_dir(self): - if self.instance.testsuite.sysbuild: - # Load domain yaml to get default domain build directory - # Note: for targets using QEMU, we assume that the target will - # have added any additional images to the run target manually - domain_path = os.path.join(self.build_dir, "domains.yaml") - domains = Domains.from_file(domain_path) - logger.debug("Loaded sysbuild domain data from %s" % domain_path) - build_dir = domains.get_default_domain().build_dir - else: - build_dir = self.build_dir - - return build_dir - def _set_qemu_filenames(self, sysbuild_build_dir): # PID file will be created in the main sysbuild app's build dir self.pid_fn = os.path.join(sysbuild_build_dir, "qemu.pid") @@ -1200,7 +1195,8 @@ def _enqueue_char(self, queue): def _monitor_output(self, queue, timeout, logfile, pid_fn, harness, ignore_unexpected_eof=False): start_time = time.time() timeout_time = start_time + timeout - out_state = None + _status = None + _reason = None line = "" timeout_extended = False self.pid = 0 @@ -1216,17 +1212,19 @@ def _monitor_output(self, queue, timeout, logfile, pid_fn, harness, ignore_unexp # of not enough CPU time scheduled by host for # QEMU process during p.poll(this_timeout) cpu_time = self._get_cpu_time(self.pid) - if cpu_time < timeout and not out_state: + if cpu_time < timeout and not _status: timeout_time = time.time() + (timeout - cpu_time) continue except psutil.NoSuchProcess: pass except ProcessLookupError: - out_state = "failed" + _status = "failed" + _reason = "Execution error" break - if not out_state: - out_state = "timeout" + if not _status: + _status = "failed" + _reason = "timeout" break if self.pid == 0 and os.path.exists(pid_fn): @@ -1244,13 +1242,15 @@ def _monitor_output(self, queue, timeout, logfile, pid_fn, harness, ignore_unexp c = c.decode("utf-8") except UnicodeDecodeError: # Test is writing something weird, fail - out_state = "unexpected byte" + _status = "failed" + _reason = "unexpected byte" break if c == "": # EOF, this shouldn't happen unless QEMU crashes if not ignore_unexpected_eof: - out_state = "unexpected eof" + _status = "failed" + _reason = "unexpected eof" break line = line + c if c != "\n": @@ -1267,8 +1267,9 @@ def _monitor_output(self, queue, timeout, logfile, pid_fn, harness, ignore_unexp # if we have registered a fail make sure the state is not # overridden by a false success message coming from the # testsuite - if out_state not in ['failed', 'unexpected eof', 'unexpected byte']: - out_state = harness.state + if _status != 'failed': + _status = harness.state + _reason = harness.reason # if we get some state, that means test is doing well, we reset # the timeout and wait for 2 more seconds to catch anything @@ -1286,17 +1287,17 @@ def _monitor_output(self, queue, timeout, logfile, pid_fn, harness, ignore_unexp self.stop_thread = True handler_time = time.time() - start_time - logger.debug(f"QEMU ({self.pid}) complete ({out_state}) after {handler_time} seconds") - self._monitor_update_instance_info(self, handler_time, out_state) + logger.debug(f"QEMU ({self.pid}) complete with {_status} ({_reason}) after {handler_time} seconds") + self._monitor_update_instance_info(self, handler_time, _status, _reason) self._close_log_file(log_out_fp) self._stop_qemu_process(self.pid) def handle(self, harness): self.run = True - sysbuild_build_dir = self._get_sysbuild_build_dir() - command = self._create_command(sysbuild_build_dir) - self._set_qemu_filenames(sysbuild_build_dir) + domain_build_dir = self.get_default_domain_build_dir() + command = self._create_command(domain_build_dir) + self._set_qemu_filenames(domain_build_dir) logger.debug("Running %s (%s)" % (self.name, self.type_str)) is_timeout = False diff --git a/scripts/pylib/twister/twisterlib/hardwaremap.py b/scripts/pylib/twister/twisterlib/hardwaremap.py index e60ba35dd5622..c07e777ca7545 100644 --- a/scripts/pylib/twister/twisterlib/hardwaremap.py +++ b/scripts/pylib/twister/twisterlib/hardwaremap.py @@ -288,8 +288,11 @@ def scan(self, persistent=False): def readlink(link): return str((by_id / link).resolve()) - persistent_map = {readlink(link): str(link) - for link in by_id.iterdir()} + if by_id.exists(): + persistent_map = {readlink(link): str(link) + for link in by_id.iterdir()} + else: + persistent_map = {} else: persistent_map = {} diff --git a/scripts/pylib/twister/twisterlib/harness.py b/scripts/pylib/twister/twisterlib/harness.py index c8aa437930049..7af7867b3e30d 100644 --- a/scripts/pylib/twister/twisterlib/harness.py +++ b/scripts/pylib/twister/twisterlib/harness.py @@ -13,6 +13,7 @@ import threading import time import shutil +import json from twisterlib.error import ConfigurationError from twisterlib.environment import ZEPHYR_BASE, PYTEST_PLUGIN_INSTALLED @@ -45,6 +46,7 @@ class Harness: def __init__(self): self.state = None + self.reason = None self.type = None self.regex = [] self.matches = OrderedDict() @@ -56,6 +58,7 @@ def __init__(self): self.next_pattern = 0 self.record = None self.record_pattern = None + self.record_as_json = None self.recording = [] self.ztest = False self.detected_suite_names = [] @@ -81,6 +84,7 @@ def configure(self, instance): self.record = config.get('record', {}) if self.record: self.record_pattern = re.compile(self.record.get("regex", "")) + self.record_as_json = self.record.get("as_json") def build(self): pass @@ -91,9 +95,34 @@ def get_testcase_name(self): """ return self.id + def translate_record(self, record: dict) -> dict: + if self.record_as_json: + for k in self.record_as_json: + if not k in record: + continue + try: + record[k] = json.loads(record[k]) if record[k] else {} + except json.JSONDecodeError as parse_error: + logger.warning(f"HARNESS:{self.__class__.__name__}: recording JSON failed:" + f" {parse_error} for '{k}':'{record[k]}'") + # Don't set the Harness state to failed for recordings. + record[k] = { 'ERROR': { 'msg': str(parse_error), 'doc': record[k] } } + return record + + def parse_record(self, line) -> re.Match: + match = None + if self.record_pattern: + match = self.record_pattern.search(line) + if match: + rec = self.translate_record({ k:v.strip() for k,v in match.groupdict(default="").items() }) + self.recording.append(rec) + return match + # def process_test(self, line): + self.parse_record(line) + runid_match = re.search(self.run_id_pattern, line) if runid_match: run_id = runid_match.group("run_id") @@ -104,11 +133,13 @@ def process_test(self, line): if self.RUN_PASSED in line: if self.fault: self.state = "failed" + self.reason = "Fault detected while running test" else: self.state = "passed" if self.RUN_FAILED in line: self.state = "failed" + self.reason = "Testsuite failed" if self.fail_on_fault: if self.FAULT == line: @@ -142,18 +173,17 @@ def handle(self, line): tc.status = "passed" def run_robot_test(self, command, handler): - start_time = time.time() env = os.environ.copy() - env["ROBOT_FILES"] = self.path + command.append(os.path.join(handler.sourcedir, self.path)) with subprocess.Popen(command, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, cwd=self.instance.build_dir, env=env) as cmake_proc: - out, _ = cmake_proc.communicate() + stderr=subprocess.STDOUT, cwd=self.instance.build_dir, env=env) as renode_test_proc: + out, _ = renode_test_proc.communicate() self.instance.execution_time = time.time() - start_time - if cmake_proc.returncode == 0: + if renode_test_proc.returncode == 0: self.instance.status = "passed" # all tests in one Robot file are treated as a single test case, # so its status should be set accordingly to the instance status @@ -251,11 +281,6 @@ def handle(self, line): elif self.GCOV_END in line: self.capture_coverage = False - if self.record_pattern: - match = self.record_pattern.search(line) - if match: - self.recording.append({ k:v.strip() for k,v in match.groupdict(default="").items() }) - self.process_test(line) # Reset the resulting test state to 'failed' when not all of the patterns were # found in the output, but just ztest's 'PROJECT EXECUTION SUCCESSFUL'. @@ -269,11 +294,13 @@ def handle(self, line): f" {self.next_pattern} of {self.patterns_expected}" f" expected ordered patterns.") self.state = "failed" + self.reason = "patterns did not match (ordered)" if self.state == "passed" and not self.ordered and len(self.matches) < self.patterns_expected: logger.error(f"HARNESS:{self.__class__.__name__}: failed with" f" {len(self.matches)} of {self.patterns_expected}" f" expected unordered patterns.") self.state = "failed" + self.reason = "patterns did not match (unordered)" tc = self.instance.get_case_or_create(self.get_testcase_name()) if self.state == "passed": @@ -307,6 +334,7 @@ def pytest_run(self, timeout): finally: if self.reserved_serial: self.instance.handler.make_device_available(self.reserved_serial) + self.instance.record(self.recording) self._update_test_status() def generate_command(self): @@ -331,11 +359,11 @@ def generate_command(self): if pytest_dut_scope: command.append(f'--dut-scope={pytest_dut_scope}') - if handler.options.verbose > 1: - command.extend([ - '--log-cli-level=DEBUG', - '--log-cli-format=%(levelname)s: %(message)s' - ]) + # Always pass output from the pytest test and the test image up to Twister log. + command.extend([ + '--log-cli-level=DEBUG', + '--log-cli-format=%(levelname)s: %(message)s' + ]) if handler.type_str == 'device': command.extend( @@ -348,6 +376,10 @@ def generate_command(self): else: raise PytestHarnessException(f'Support for handler {handler.type_str} not implemented yet') + if handler.type_str != 'device': + for fixture in handler.options.fixture: + command.append(f'--twister-fixture={fixture}') + if handler.options.pytest_args: command.extend(handler.options.pytest_args) if pytest_args_yaml: @@ -402,6 +434,12 @@ def _generate_parameters_for_hardware(self, handler: Handler): if hardware.post_script: command.append(f'--post-script={hardware.post_script}') + if hardware.flash_before: + command.append(f'--flash-before={hardware.flash_before}') + + for fixture in hardware.fixtures: + command.append(f'--twister-fixture={fixture}') + return command def run_command(self, cmd, timeout): @@ -413,7 +451,7 @@ def run_command(self, cmd, timeout): env=env ) as proc: try: - reader_t = threading.Thread(target=self._output_reader, args=(proc,), daemon=True) + reader_t = threading.Thread(target=self._output_reader, args=(proc, self), daemon=True) reader_t.start() reader_t.join(timeout) if reader_t.is_alive(): @@ -450,12 +488,13 @@ def _update_command_with_env_dependencies(cmd): return cmd, env @staticmethod - def _output_reader(proc): + def _output_reader(proc, harness): while proc.stdout.readable() and proc.poll() is None: line = proc.stdout.readline().decode().strip() if not line: continue logger.debug('PYTEST: %s', line) + harness.parse_record(line) proc.communicate() def _update_test_status(self): @@ -670,12 +709,13 @@ def handle(self, line): self.process_test(line) if not self.ztest and self.state: - logger.debug(f"not a ztest and no state for {self.id}") + logger.debug(f"not a ztest and no state for {self.id}") tc = self.instance.get_case_or_create(self.id) if self.state == "passed": tc.status = "passed" else: tc.status = "failed" + tc.reason = "Test failure" class Ztest(Test): diff --git a/scripts/pylib/twister/twisterlib/platform.py b/scripts/pylib/twister/twisterlib/platform.py index 769876cf05ae5..6429907928f96 100644 --- a/scripts/pylib/twister/twisterlib/platform.py +++ b/scripts/pylib/twister/twisterlib/platform.py @@ -24,6 +24,8 @@ def __init__(self): self.name = "" self.normalized_name = "" + # if sysbuild to be used by default on a given platform + self.sysbuild = False self.twister = True # if no RAM size is specified by the board, take a default of 128K self.ram = 128 @@ -46,6 +48,8 @@ def __init__(self): self.env = [] self.env_satisfied = True self.filter_data = dict() + self.uart = "" + self.resc = "" def load(self, platform_file): scp = TwisterConfigParser(platform_file, self.platform_schema) @@ -54,6 +58,7 @@ def load(self, platform_file): self.name = data['identifier'] self.normalized_name = self.name.replace("/", "_") + self.sysbuild = data.get("sysbuild", False) self.twister = data.get("twister", True) # if no RAM size is specified by the board, take a default of 128K self.ram = data.get("ram", 128) @@ -63,6 +68,9 @@ def load(self, platform_file): self.only_tags = testing.get("only_tags", []) self.default = testing.get("default", False) self.binaries = testing.get("binaries", []) + renode = testing.get("renode", {}) + self.uart = renode.get("uart", "") + self.resc = renode.get("resc", "") # if no flash size is specified by the board, take a default of 512K self.flash = data.get("flash", 512) self.supported = set() diff --git a/scripts/pylib/twister/twisterlib/reports.py b/scripts/pylib/twister/twisterlib/reports.py index e03d754ee8c29..c688542080364 100644 --- a/scripts/pylib/twister/twisterlib/reports.py +++ b/scripts/pylib/twister/twisterlib/reports.py @@ -11,12 +11,23 @@ import xml.etree.ElementTree as ET import string from datetime import datetime +from pathlib import PosixPath logger = logging.getLogger('twister') logger.setLevel(logging.DEBUG) class Reporting: + json_filters = { + 'twister.json': { + 'deny_suite': ['footprint'] + }, + 'footprint.json': { + 'deny_status': ['filtered'], + 'deny_suite': ['testcases', 'execution_time', 'recording', 'retries', 'runnable'] + } + } + def __init__(self, plan, env) -> None: self.plan = plan #FIXME self.instances = plan.instances @@ -26,6 +37,8 @@ def __init__(self, plan, env) -> None: self.env = env self.timestamp = datetime.now().isoformat() self.outdir = os.path.abspath(env.options.outdir) + self.instance_fail_count = plan.instance_fail_count + self.footprint = None @staticmethod def process_log(log_file): @@ -232,20 +245,41 @@ def xunit_report(self, json_file, filename, selected_platform=None, full_report= with open(filename, 'wb') as report: report.write(result) - def json_report(self, filename, version="NA", platform=None): + def json_report(self, filename, version="NA", platform=None, filters=None): logger.info(f"Writing JSON report {filename}") + + if self.env.options.report_all_options: + report_options = vars(self.env.options) + else: + report_options = self.env.non_default_options() + + # Resolve known JSON serialization problems. + for k,v in report_options.items(): + report_options[k] = str(v) if type(v) in [PosixPath] else v + report = {} report["environment"] = {"os": os.name, "zephyr_version": version, "toolchain": self.env.toolchain, "commit_date": self.env.commit_date, - "run_date": self.env.run_date + "run_date": self.env.run_date, + "options": report_options } suites = [] for instance in self.instances.values(): if platform and platform != instance.platform.name: continue + if instance.status == "filtered" and not self.env.options.report_filtered: + continue + if (filters and 'allow_status' in filters and instance.status not in filters['allow_status']): + logger.debug(f"Skip test suite '{instance.testsuite.name}' status '{instance.status}' " + f"not allowed for {filename}") + continue + if (filters and 'deny_status' in filters and instance.status in filters['deny_status']): + logger.debug(f"Skip test suite '{instance.testsuite.name}' status '{instance.status}' " + f"denied for {filename}") + continue suite = {} handler_log = os.path.join(instance.build_dir, "handler.log") pytest_log = os.path.join(instance.build_dir, "twister_harness.log") @@ -351,6 +385,36 @@ def json_report(self, filename, version="NA", platform=None): if instance.recording is not None: suite['recording'] = instance.recording + if (instance.status + and instance.status not in ["error", "filtered"] + and self.env.options.create_rom_ram_report + and self.env.options.footprint_report is not None): + # Init as empty data preparing for filtering properties. + suite['footprint'] = {} + + # Pass suite properties through the context filters. + if filters and 'allow_suite' in filters: + suite = {k:v for k,v in suite.items() if k in filters['allow_suite']} + + if filters and 'deny_suite' in filters: + suite = {k:v for k,v in suite.items() if k not in filters['deny_suite']} + + # Compose external data only to these properties which pass filtering. + if 'footprint' in suite: + do_all = 'all' in self.env.options.footprint_report + footprint_files = { 'ROM': 'rom.json', 'RAM': 'ram.json' } + for k,v in footprint_files.items(): + if do_all or k in self.env.options.footprint_report: + footprint_fname = os.path.join(instance.build_dir, v) + try: + with open(footprint_fname, "rt") as footprint_json: + logger.debug(f"Collect footprint.{k} for '{instance.name}'") + suite['footprint'][k] = json.load(footprint_json) + except FileNotFoundError: + logger.error(f"Missing footprint.{k} for '{instance.name}'") + # + # + suites.append(suite) report["testsuites"] = suites @@ -432,20 +496,36 @@ def footprint_reports(self, report, show_footprint, all_deltas, (report if not last_metrics else "the last twister run."))) def synopsis(self): + if self.env.options.report_summary == 0: + count = self.instance_fail_count + log_txt = f"The following issues were found (showing the all {count} items):" + elif self.env.options.report_summary: + count = self.env.options.report_summary + log_txt = f"The following issues were found " + if count > self.instance_fail_count: + log_txt += f"(presenting {self.instance_fail_count} out of the {count} items requested):" + else: + log_txt += f"(showing the {count} of {self.instance_fail_count} items):" + else: + count = 10 + log_txt = f"The following issues were found (showing the top {count} items):" cnt = 0 example_instance = None detailed_test_id = self.env.options.detailed_test_id for instance in self.instances.values(): if instance.status not in ["passed", "filtered", "skipped"]: - cnt = cnt + 1 + cnt += 1 if cnt == 1: logger.info("-+" * 40) - logger.info("The following issues were found (showing the top 10 items):") + logger.info(log_txt) logger.info(f"{cnt}) {instance.testsuite.name} on {instance.platform.name} {instance.status} ({instance.reason})") example_instance = instance - if cnt == 10: + if cnt == count: break + if cnt == 0 and self.env.options.report_summary is not None: + logger.info("-+" * 40) + logger.info(f"No errors/fails found") if cnt and example_instance: logger.info("") @@ -539,7 +619,11 @@ def save_reports(self, name, suffix, report_dir, no_update, platform_reports): if not no_update: json_file = filename + ".json" - self.json_report(json_file, version=self.env.version) + self.json_report(json_file, version=self.env.version, + filters=self.json_filters['twister.json']) + if self.env.options.footprint_report is not None: + self.json_report(filename + "_footprint.json", version=self.env.version, + filters=self.json_filters['footprint.json']) self.xunit_report(json_file, filename + ".xml", full_report=False) self.xunit_report(json_file, filename + "_report.xml", full_report=True) self.xunit_report_suites(json_file, filename + "_suite_report.xml") @@ -549,13 +633,19 @@ def save_reports(self, name, suffix, report_dir, no_update, platform_reports): def target_report(self, json_file, outdir, suffix): - platforms = {inst.platform for _, inst in self.instances.items()} - for platform in platforms: + platforms = {repr(inst.platform):inst.platform for _, inst in self.instances.items()} + for platform in platforms.values(): if suffix: filename = os.path.join(outdir,"{}_{}.xml".format(platform.normalized_name, suffix)) - json_platform_file = os.path.join(outdir,"{}_{}.json".format(platform.normalized_name, suffix)) + json_platform_file = os.path.join(outdir,"{}_{}".format(platform.normalized_name, suffix)) else: filename = os.path.join(outdir,"{}.xml".format(platform.normalized_name)) - json_platform_file = os.path.join(outdir,"{}.json".format(platform.normalized_name)) + json_platform_file = os.path.join(outdir, platform.normalized_name) self.xunit_report(json_file, filename, platform.name, full_report=True) - self.json_report(json_platform_file, version=self.env.version, platform=platform.name) + self.json_report(json_platform_file + ".json", + version=self.env.version, platform=platform.name, + filters=self.json_filters['twister.json']) + if self.env.options.footprint_report is not None: + self.json_report(json_platform_file + "_footprint.json", + version=self.env.version, platform=platform.name, + filters=self.json_filters['footprint.json']) diff --git a/scripts/pylib/twister/twisterlib/runner.py b/scripts/pylib/twister/twisterlib/runner.py index 3073a7c4ca6fb..567f125cd8caf 100644 --- a/scripts/pylib/twister/twisterlib/runner.py +++ b/scripts/pylib/twister/twisterlib/runner.py @@ -335,7 +335,7 @@ def run_cmake(self, args="", filter_stages=[]): gen_defines_args = "" warning_command = 'CONFIG_COMPILER_WARNINGS_AS_ERRORS' - if self.testsuite.sysbuild: + if self.instance.sysbuild: warning_command = 'SB_' + warning_command logger.debug("Running cmake on %s for %s" % (self.source_dir, self.platform.name)) @@ -357,7 +357,7 @@ def run_cmake(self, args="", filter_stages=[]): f'-P{canonical_zephyr_base}/cmake/package_helper.cmake', ] - if self.testsuite.sysbuild and not filter_stages: + if self.instance.sysbuild and not filter_stages: logger.debug("Building %s using sysbuild" % (self.source_dir)) source_args = [ f'-S{canonical_zephyr_base}/share/sysbuild', @@ -445,7 +445,7 @@ def parse_generated(self, filter_stages=[]): if self.platform.name == "unit_testing": return {} - if self.testsuite.sysbuild and not filter_stages: + if self.instance.sysbuild and not filter_stages: # Load domain yaml to get default domain build directory domain_path = os.path.join(self.build_dir, "domains.yaml") domains = Domains.from_file(domain_path) @@ -498,20 +498,14 @@ def parse_generated(self, filter_stages=[]): filter_data.update(self.defconfig) filter_data.update(self.cmake_cache) - if self.testsuite.sysbuild and self.env.options.device_testing: + if self.instance.sysbuild and self.env.options.device_testing: # Verify that twister's arguments support sysbuild. # Twister sysbuild flashing currently only works with west, so - # --west-flash must be passed. Additionally, erasing the DUT - # before each test with --west-flash=--erase will inherently not - # work with sysbuild. + # --west-flash must be passed. if self.env.options.west_flash is None: logger.warning("Sysbuild test will be skipped. " + "West must be used for flashing.") return {os.path.join(self.platform.name, self.testsuite.name): True} - elif "--erase" in self.env.options.west_flash: - logger.warning("Sysbuild test will be skipped, " + - "--erase is not supported with --west-flash") - return {os.path.join(self.platform.name, self.testsuite.name): True} if self.testsuite and self.testsuite.filter: try: @@ -559,6 +553,13 @@ def log_info(self, filename, inline_logs, log_testcases=False): except Exception as e: data = "Unable to read log data (%s)\n" % (str(e)) + # Remove any coverage data from the dumped logs + data = re.sub( + r"GCOV_COVERAGE_DUMP_START.*GCOV_COVERAGE_DUMP_END", + "GCOV_COVERAGE_DUMP_START\n...\nGCOV_COVERAGE_DUMP_END", + data, + flags=re.DOTALL, + ) logger.error(data) logger.info("{:-^100}".format(filename)) @@ -579,6 +580,7 @@ def log_info(self, filename, inline_logs, log_testcases=False): def log_info_file(self, inline_logs): build_dir = self.instance.build_dir h_log = "{}/handler.log".format(build_dir) + he_log = "{}/handler_stderr.log".format(build_dir) b_log = "{}/build.log".format(build_dir) v_log = "{}/valgrind.log".format(build_dir) d_log = "{}/device.log".format(build_dir) @@ -590,6 +592,8 @@ def log_info_file(self, inline_logs): self.log_info("{}".format(pytest_log), inline_logs, log_testcases=True) elif os.path.exists(h_log) and os.path.getsize(h_log) > 0: self.log_info("{}".format(h_log), inline_logs) + elif os.path.exists(he_log) and os.path.getsize(he_log) > 0: + self.log_info("{}".format(he_log), inline_logs) elif os.path.exists(d_log) and os.path.getsize(d_log) > 0: self.log_info("{}".format(d_log), inline_logs) else: @@ -763,9 +767,12 @@ def cleanup_artifacts(self, additional_keep: List[str] = []): allow = [ os.path.join('zephyr', '.config'), 'handler.log', + 'handler_stderr.log', 'build.log', 'device.log', 'recording.csv', + 'rom.json', + 'ram.json', # below ones are needed to make --test-only work as well 'Makefile', 'CMakeCache.txt', @@ -799,7 +806,7 @@ def cleanup_device_testing_artifacts(self): files_to_keep = self._get_binaries() files_to_keep.append(os.path.join('zephyr', 'runners.yaml')) - if self.testsuite.sysbuild: + if self.instance.sysbuild: files_to_keep.append('domains.yaml') for domain in self.instance.domains.get_domains(): files_to_keep += self._get_artifact_allow_list_for_domain(domain.name) @@ -839,7 +846,7 @@ def _get_binaries(self) -> List[str]: # Get binaries for a single-domain build binaries += self._get_binaries_from_runners() # Get binaries in the case of a multiple-domain build - if self.testsuite.sysbuild: + if self.instance.sysbuild: for domain in self.instance.domains.get_domains(): binaries += self._get_binaries_from_runners(domain.name) @@ -1317,8 +1324,22 @@ def add_tasks_to_queue(self, pipeline, build_only=False, test_only=False, retry_ def pipeline_mgr(self, pipeline, done_queue, lock, results): - if sys.platform == 'linux': - with self.jobserver.get_job(): + try: + if sys.platform == 'linux': + with self.jobserver.get_job(): + while True: + try: + task = pipeline.get_nowait() + except queue.Empty: + break + else: + instance = task['test'] + pb = ProjectBuilder(instance, self.env, self.jobserver) + pb.duts = self.duts + pb.process(pipeline, done_queue, task, lock, results) + + return True + else: while True: try: task = pipeline.get_nowait() @@ -1329,20 +1350,10 @@ def pipeline_mgr(self, pipeline, done_queue, lock, results): pb = ProjectBuilder(instance, self.env, self.jobserver) pb.duts = self.duts pb.process(pipeline, done_queue, task, lock, results) - return True - else: - while True: - try: - task = pipeline.get_nowait() - except queue.Empty: - break - else: - instance = task['test'] - pb = ProjectBuilder(instance, self.env, self.jobserver) - pb.duts = self.duts - pb.process(pipeline, done_queue, task, lock, results) - return True + except Exception as e: + logger.error(f"General exception: {e}") + sys.exit(1) def execute(self, pipeline, done): lock = Lock() @@ -1362,6 +1373,11 @@ def execute(self, pipeline, done): try: for p in processes: p.join() + if p.exitcode != 0: + logger.error(f"Process {p.pid} failed, aborting execution") + for proc in processes: + proc.terminate() + sys.exit(1) except KeyboardInterrupt: logger.info("Execution interrupted") for p in processes: diff --git a/scripts/pylib/twister/twisterlib/size_calc.py b/scripts/pylib/twister/twisterlib/size_calc.py index f449d26ac991a..0c6634c874213 100644 --- a/scripts/pylib/twister/twisterlib/size_calc.py +++ b/scripts/pylib/twister/twisterlib/size_calc.py @@ -56,7 +56,6 @@ class SizeCalculator: "ccm_data", "usb_descriptor", "usb_data", "usb_bos_desc", - "uart_mux", 'log_backends_sections', 'log_dynamic_sections', 'log_const_sections', diff --git a/scripts/pylib/twister/twisterlib/testinstance.py b/scripts/pylib/twister/twisterlib/testinstance.py index 5be57e1deb69f..3540b3e58f201 100644 --- a/scripts/pylib/twister/twisterlib/testinstance.py +++ b/scripts/pylib/twister/twisterlib/testinstance.py @@ -10,6 +10,7 @@ import logging import shutil import glob +import csv from twisterlib.testsuite import TestCase, TestSuite from twisterlib.platform import Platform @@ -66,6 +67,8 @@ def __init__(self, testsuite, platform, outdir): self.build_dir = os.path.join(outdir, platform.normalized_name, source_dir_rel, testsuite.name) self.run_id = self._get_run_id() self.domains = None + # Instance need to use sysbuild if a given suite or a platform requires it + self.sysbuild = testsuite.sysbuild or platform.sysbuild self.run = False self.testcases: list[TestCase] = [] @@ -73,6 +76,22 @@ def __init__(self, testsuite, platform, outdir): self.filters = [] self.filter_type = None + def record(self, recording, fname_csv="recording.csv"): + if recording: + if self.recording is None: + self.recording = recording.copy() + else: + self.recording.extend(recording) + + filename = os.path.join(self.build_dir, fname_csv) + with open(filename, "wt") as csvfile: + cw = csv.DictWriter(csvfile, + fieldnames = self.recording[0].keys(), + lineterminator = os.linesep, + quoting = csv.QUOTE_NONNUMERIC) + cw.writeheader() + cw.writerows(self.recording) + def add_filter(self, reason, filter_type): self.filters.append({'type': filter_type, 'reason': reason }) self.status = "filtered" @@ -163,7 +182,7 @@ def testsuite_runnable(testsuite, fixtures): # command-line, then we need to run the test, not just build it. fixture = testsuite.harness_config.get('fixture') if fixture: - can_run = fixture in fixtures + can_run = fixture in map(lambda f: f.split(sep=':')[0], fixtures) return can_run @@ -318,7 +337,7 @@ def calculate_sizes(self, from_buildlog: bool = False, generate_warning: bool = def get_elf_file(self) -> str: - if self.testsuite.sysbuild: + if self.sysbuild: build_dir = self.domains.get_default_domain().build_dir else: build_dir = self.build_dir diff --git a/scripts/pylib/twister/twisterlib/testplan.py b/scripts/pylib/twister/twisterlib/testplan.py index 85335491af693..83c5d6b06fdad 100755 --- a/scripts/pylib/twister/twisterlib/testplan.py +++ b/scripts/pylib/twister/twisterlib/testplan.py @@ -17,6 +17,7 @@ import shutil import random import snippets +from colorama import Fore from pathlib import Path from argparse import Namespace @@ -107,6 +108,7 @@ def __init__(self, env=None): self.default_platforms = [] self.load_errors = 0 self.instances = dict() + self.instance_fail_count = 0 self.warnings = 0 self.scenarios = [] @@ -217,7 +219,7 @@ def load(self): else: last_run = os.path.join(self.options.outdir, "twister.json") - if self.options.only_failed: + if self.options.only_failed or self.options.report_summary is not None: self.load_from_file(last_run) self.selected_platforms = set(p.platform.name for p in self.instances.values()) elif self.options.load_tests: @@ -387,8 +389,6 @@ def report_test_list(self): print(" - {}".format(test)) print("{} total.".format(cnt)) - def config(self): - logger.info("coverage platform: {}".format(self.coverage_platform)) # Debug Functions @staticmethod @@ -571,71 +571,95 @@ def get_platform(self, name): break return selected_platform - def load_from_file(self, file, filter_platform=[]): - with open(file, "r") as json_test_plan: - jtp = json.load(json_test_plan) - instance_list = [] - for ts in jtp.get("testsuites", []): - logger.debug(f"loading {ts['name']}...") - testsuite = ts["name"] + def handle_quarantined_tests(self, instance: TestInstance, plat: Platform): + if self.quarantine: + matched_quarantine = self.quarantine.get_matched_quarantine( + instance.testsuite.id, plat.name, plat.arch, plat.simulation + ) + if matched_quarantine and not self.options.quarantine_verify: + instance.add_filter("Quarantine: " + matched_quarantine, Filters.QUARANTINE) + return + if not matched_quarantine and self.options.quarantine_verify: + instance.add_filter("Not under quarantine", Filters.QUARANTINE) - platform = self.get_platform(ts["platform"]) - if filter_platform and platform.name not in filter_platform: - continue - instance = TestInstance(self.testsuites[testsuite], platform, self.env.outdir) - if ts.get("run_id"): - instance.run_id = ts.get("run_id") + def load_from_file(self, file, filter_platform=[]): + try: + with open(file, "r") as json_test_plan: + jtp = json.load(json_test_plan) + instance_list = [] + for ts in jtp.get("testsuites", []): + logger.debug(f"loading {ts['name']}...") + testsuite = ts["name"] + + platform = self.get_platform(ts["platform"]) + if filter_platform and platform.name not in filter_platform: + continue + instance = TestInstance(self.testsuites[testsuite], platform, self.env.outdir) + if ts.get("run_id"): + instance.run_id = ts.get("run_id") - if self.options.device_testing: - tfilter = 'runnable' - else: - tfilter = 'buildable' - instance.run = instance.check_runnable( - self.options.enable_slow, - tfilter, - self.options.fixture, - self.hwm - ) + if self.options.device_testing: + tfilter = 'runnable' + else: + tfilter = 'buildable' + instance.run = instance.check_runnable( + self.options.enable_slow, + tfilter, + self.options.fixture, + self.hwm + ) - instance.metrics['handler_time'] = ts.get('execution_time', 0) - instance.metrics['used_ram'] = ts.get("used_ram", 0) - instance.metrics['used_rom'] = ts.get("used_rom",0) - instance.metrics['available_ram'] = ts.get('available_ram', 0) - instance.metrics['available_rom'] = ts.get('available_rom', 0) - - status = ts.get('status', None) - reason = ts.get("reason", "Unknown") - if status in ["error", "failed"]: - instance.status = None - instance.reason = None - instance.retries += 1 - # test marked as passed (built only) but can run when - # --test-only is used. Reset status to capture new results. - elif status == 'passed' and instance.run and self.options.test_only: - instance.status = None - instance.reason = None - else: - instance.status = status - instance.reason = reason - - for tc in ts.get('testcases', []): - identifier = tc['identifier'] - tc_status = tc.get('status', None) - tc_reason = None - # we set reason only if status is valid, it might have been - # reset above... - if instance.status: - tc_reason = tc.get('reason') - if tc_status: - case = instance.set_case_status_by_name(identifier, tc_status, tc_reason) - case.duration = tc.get('execution_time', 0) - if tc.get('log'): - case.output = tc.get('log') - - - instance.create_overlay(platform, self.options.enable_asan, self.options.enable_ubsan, self.options.enable_coverage, self.options.coverage_platform) - instance_list.append(instance) - self.add_instances(instance_list) + instance.metrics['handler_time'] = ts.get('execution_time', 0) + instance.metrics['used_ram'] = ts.get("used_ram", 0) + instance.metrics['used_rom'] = ts.get("used_rom",0) + instance.metrics['available_ram'] = ts.get('available_ram', 0) + instance.metrics['available_rom'] = ts.get('available_rom', 0) + + status = ts.get('status', None) + reason = ts.get("reason", "Unknown") + if status in ["error", "failed"]: + if self.options.report_summary is not None: + if status == "error": status = "ERROR" + elif status == "failed": status = "FAILED" + instance.status = Fore.RED + status + Fore.RESET + instance.reason = reason + self.instance_fail_count += 1 + else: + instance.status = None + instance.reason = None + instance.retries += 1 + # test marked as passed (built only) but can run when + # --test-only is used. Reset status to capture new results. + elif status == 'passed' and instance.run and self.options.test_only: + instance.status = None + instance.reason = None + else: + instance.status = status + instance.reason = reason + + self.handle_quarantined_tests(instance, platform) + + for tc in ts.get('testcases', []): + identifier = tc['identifier'] + tc_status = tc.get('status', None) + tc_reason = None + # we set reason only if status is valid, it might have been + # reset above... + if instance.status: + tc_reason = tc.get('reason') + if tc_status: + case = instance.set_case_status_by_name(identifier, tc_status, tc_reason) + case.duration = tc.get('execution_time', 0) + if tc.get('log'): + case.output = tc.get('log') + + + instance.create_overlay(platform, self.options.enable_asan, self.options.enable_ubsan, self.options.enable_coverage, self.options.coverage_platform) + instance_list.append(instance) + self.add_instances(instance_list) + except FileNotFoundError as e: + logger.error(f"{e}") + return 1 def apply_filters(self, **kwargs): @@ -903,15 +927,7 @@ def apply_filters(self, **kwargs): break # handle quarantined tests - if self.quarantine: - matched_quarantine = self.quarantine.get_matched_quarantine( - instance.testsuite.id, plat.name, plat.arch, plat.simulation - ) - if matched_quarantine and not self.options.quarantine_verify: - instance.add_filter("Quarantine: " + matched_quarantine, Filters.QUARANTINE) - if not matched_quarantine and self.options.quarantine_verify: - instance.add_filter("Not under quarantine", Filters.QUARANTINE) - + self.handle_quarantined_tests(instance, plat) # platform_key is a list of unique platform attributes that form a unique key a test # will match against to determine if it should be scheduled to run. A key containing a diff --git a/scripts/pylib/twister/twisterlib/twister_main.py b/scripts/pylib/twister/twisterlib/twister_main.py index 30656544b94fa..33b0569f330bc 100644 --- a/scripts/pylib/twister/twisterlib/twister_main.py +++ b/scripts/pylib/twister/twisterlib/twister_main.py @@ -62,7 +62,7 @@ def init_color(colorama_strip): colorama.init(strip=colorama_strip) -def main(options): +def main(options, default_options): start_time = time.time() # Configure color output @@ -73,7 +73,7 @@ def main(options): previous_results = None # Cleanup - if options.no_clean or options.only_failed or options.test_only: + if options.no_clean or options.only_failed or options.test_only or options.report_summary is not None: if os.path.exists(options.outdir): print("Keeping artifacts untouched") elif options.last_metrics: @@ -105,7 +105,7 @@ def main(options): VERBOSE = options.verbose setup_logging(options.outdir, options.log_file, VERBOSE, options.timestamps) - env = TwisterEnv(options) + env = TwisterEnv(options, default_options) env.discover() hwm = HardwareMap(env) @@ -160,6 +160,13 @@ def main(options): report.json_report(options.save_tests) return 0 + if options.report_summary is not None: + if options.report_summary < 0: + logger.error("The report summary value cannot be less than 0") + return 1 + report.synopsis() + return 0 + if options.device_testing and not options.build_only: print("\nDevice testing on:") hwm.dump(filtered=tplan.selected_platforms) diff --git a/scripts/requirements-compliance.txt b/scripts/requirements-compliance.txt index 31c395ac4f050..68469fc80ea07 100644 --- a/scripts/requirements-compliance.txt +++ b/scripts/requirements-compliance.txt @@ -5,5 +5,5 @@ python-magic python-magic-bin; sys_platform == "win32" lxml junitparser>=2 -pylint +pylint>=3 yamllint diff --git a/scripts/requirements-run-test.txt b/scripts/requirements-run-test.txt index a710eb962a5f3..8b1d01afb093e 100644 --- a/scripts/requirements-run-test.txt +++ b/scripts/requirements-run-test.txt @@ -17,3 +17,6 @@ psutil # Artifacts package creation bz + +# used for CAN <=> host testing +python-can>=4.3.0 diff --git a/scripts/schemas/twister/platform-schema.yaml b/scripts/schemas/twister/platform-schema.yaml index b5c3339fc03ab..c651f83c3e364 100644 --- a/scripts/schemas/twister/platform-schema.yaml +++ b/scripts/schemas/twister/platform-schema.yaml @@ -66,6 +66,8 @@ mapping: type: seq seq: - type: str + "sysbuild": + type: bool "env": type: seq seq: @@ -100,3 +102,10 @@ mapping: type: seq seq: - type: str + "renode": + type: map + mapping: + "uart": + type: str + "resc": + type: str diff --git a/scripts/schemas/twister/testsuite-schema.yaml b/scripts/schemas/twister/testsuite-schema.yaml index 1eae7dcef1b1f..28b7e730edbe5 100644 --- a/scripts/schemas/twister/testsuite-schema.yaml +++ b/scripts/schemas/twister/testsuite-schema.yaml @@ -130,6 +130,11 @@ schema;scenario-schema: "regex": type: str required: true + "as_json": + type: seq + required: false + sequence: + - type: str "bsim_exe_name": type: str required: false diff --git a/scripts/set_assignees.py b/scripts/set_assignees.py index d209193158592..679735414c3ed 100755 --- a/scripts/set_assignees.py +++ b/scripts/set_assignees.py @@ -70,15 +70,12 @@ def process_pr(gh, maintainer_file, number): all_areas = set() fn = list(pr.get_files()) - manifest_change = False for changed_file in fn: if changed_file.filename in ['west.yml','submanifests/optional.yaml']: - manifest_change = True break - # one liner PRs should be trivial - if pr.commits == 1 and (pr.additions <= 1 and pr.deletions <= 1) and not manifest_change: - labels = {'Trivial'} + if pr.commits == 1 and (pr.additions <= 1 and pr.deletions <= 1): + labels = {'size: XS'} if len(fn) > 500: log(f"Too many files changed ({len(fn)}), skipping....") diff --git a/scripts/tests/twister/pytest_integration/test_harness_pytest.py b/scripts/tests/twister/pytest_integration/test_harness_pytest.py index befd384be37b1..86628d40ce80c 100644 --- a/scripts/tests/twister/pytest_integration/test_harness_pytest.py +++ b/scripts/tests/twister/pytest_integration/test_harness_pytest.py @@ -19,12 +19,14 @@ def testinstance() -> TestInstance: testsuite = TestSuite('.', 'samples/hello', 'unit.test') testsuite.harness_config = {} testsuite.ignore_faults = False + testsuite.sysbuild = False platform = Platform() testinstance = TestInstance(testsuite, platform, 'outdir') testinstance.handler = mock.Mock() testinstance.handler.options = mock.Mock() testinstance.handler.options.verbose = 1 + testinstance.handler.options.fixture = ['fixture1:option1', 'fixture2'] testinstance.handler.options.pytest_args = None testinstance.handler.type_str = 'native' return testinstance @@ -41,7 +43,9 @@ def test_pytest_command(testinstance: TestInstance, device_type): 'samples/hello/pytest', f'--build-dir={testinstance.build_dir}', f'--junit-xml={testinstance.build_dir}/report.xml', - f'--device-type={device_type}' + f'--device-type={device_type}', + '--twister-fixture=fixture1:option1', + '--twister-fixture=fixture2' ] command = pytest_harness.generate_command() diff --git a/scripts/tests/twister/test_handlers.py b/scripts/tests/twister/test_handlers.py index 7eddd016ca9af..9ae333389fa06 100644 --- a/scripts/tests/twister/test_handlers.py +++ b/scripts/tests/twister/test_handlers.py @@ -18,10 +18,12 @@ from importlib import reload from serial import SerialException from subprocess import CalledProcessError, TimeoutExpired +from types import SimpleNamespace import twisterlib.harness -from conftest import ZEPHYR_BASE +ZEPHYR_BASE = os.getenv("ZEPHYR_BASE") + from twisterlib.error import TwisterException from twisterlib.handlers import ( Handler, @@ -129,6 +131,7 @@ def test_handler_final_handle_actions(mocked_instance): harness.detected_suite_names = mock.Mock() harness.matched_run_id = False harness.run_id_exists = True + harness.recording = mock.Mock() handler_time = mock.Mock() @@ -143,6 +146,8 @@ def test_handler_final_handle_actions(mocked_instance): handler.instance.reason = 'This reason shan\'t be changed.' handler._final_handle_actions(harness, handler_time) + instance.assert_has_calls([mock.call.record(harness.recording)]) + assert handler.instance.reason == 'This reason shan\'t be changed.' @@ -204,42 +209,6 @@ def test_handler_missing_suite_name(mocked_instance): ) -def test_handler_record(mocked_instance): - instance = mocked_instance - instance.testcases = [mock.Mock()] - - handler = Handler(instance) - - harness = twisterlib.harness.Harness() - harness.recording = [ {'field_1': 'recording_1_1', 'field_2': 'recording_1_2'}, - {'field_1': 'recording_2_1', 'field_2': 'recording_2_2'} - ] - - with mock.patch( - 'builtins.open', - mock.mock_open(read_data='') - ) as mock_file, \ - mock.patch( - 'csv.DictWriter.writerow', - mock.Mock() - ) as mock_writeheader, \ - mock.patch( - 'csv.DictWriter.writerows', - mock.Mock() - ) as mock_writerows: - handler.record(harness) - - print(mock_file.mock_calls) - - mock_file.assert_called_with( - os.path.join(instance.build_dir, 'recording.csv'), - 'at' - ) - - mock_writeheader.assert_has_calls([mock.call({ k:k for k in harness.recording[0].keys()})]) - mock_writerows.assert_has_calls([mock.call(harness.recording)]) - - def test_handler_terminate(mocked_instance): def mock_kill_function(pid, sig): if pid < 0: @@ -446,9 +415,9 @@ def wait(self, *args, **kwargs): ['valgrind', '--error-exitcode=2', '--leak-check=full', f'--suppressions={ZEPHYR_BASE}/scripts/valgrind.supp', '--log-file=build_dir/valgrind.log', '--track-origins=yes', - 'generator', 'run_renode_test']), + 'generator']), (False, True, False, 123, None, ['generator', 'run', '--seed=123']), - (False, False, False, None, ['ex1', 'ex2'], ['bin', 'ex1', 'ex2']), + (False, False, False, None, ['ex1', 'ex2'], ['build_dir/zephyr/zephyr.exe', 'ex1', 'ex2']), ] @pytest.mark.parametrize( @@ -470,10 +439,16 @@ def test_binaryhandler_create_command( handler.generator_cmd = 'generator' handler.binary = 'bin' handler.call_make_run = call_make_run - handler.options = mock.Mock(enable_valgrind=enable_valgrind) + handler.options = SimpleNamespace() + handler.options.enable_valgrind = enable_valgrind + handler.options.coverage_basedir = "coverage_basedir" handler.seed = seed handler.extra_test_args = extra_args handler.build_dir = 'build_dir' + handler.instance.sysbuild = False + handler.platform = SimpleNamespace() + handler.platform.resc = "file.resc" + handler.platform.uart = "uart" command = handler._create_command(robot_test) @@ -1194,6 +1169,7 @@ def mock_serial(*args, **kwargs): available_mock = mock.Mock() handler.make_device_available = available_mock handler.options = mock.Mock(timeout_multiplier=1) + twisterlib.handlers.terminate_process = mock.Mock() hardware_baud = 14400 flash_timeout = 60 @@ -1216,7 +1192,7 @@ def mock_serial(*args, **kwargs): missing_mock.assert_called_once_with('blocked', 'Serial Device Error') if terminate_ser_pty_process: - ser_pty_process.terminate.assert_called_once() + twisterlib.handlers.terminate_process.assert_called_once() ser_pty_process.communicate.assert_called_once() if make_available: @@ -1277,7 +1253,8 @@ def mock_popen(command, *args, **kwargs): (True, False, False, False, 0, True, False, None, None, ['Timed out while monitoring serial output on IPName']), (True, False, False, False, 0, False, True, - None, None, ['Process Serial PTY terminated outs: errs ']), + None, None, ["Terminating serial-pty:'Serial PTY'", + "Terminated serial-pty:'Serial PTY', stdout:'', stderr:''"]), ] @pytest.mark.parametrize( @@ -1376,6 +1353,7 @@ def mock_popen(command, *args, **kwargs): handler._update_instance_info = mock.Mock() handler._final_handle_actions = mock.Mock() handler.make_device_available = mock.Mock() + twisterlib.handlers.terminate_process = mock.Mock() handler.instance.platform.name = 'IPName' harness = mock.Mock() @@ -1478,7 +1456,7 @@ def mock_process(pid): TESTDATA_19, ids=['domains build dir', 'self build dir'] ) -def test_qemuhandler_get_sysbuild_build_dir( +def test_qemuhandler_get_default_domain_build_dir( mocked_instance, self_sysbuild, self_build_dir, @@ -1491,11 +1469,11 @@ def test_qemuhandler_get_sysbuild_build_dir( from_file_mock = mock.Mock(return_value=domains_mock) handler = QEMUHandler(mocked_instance, 'build') - handler.instance.testsuite.sysbuild = self_sysbuild + handler.instance.sysbuild = self_sysbuild handler.build_dir = self_build_dir with mock.patch('domains.Domains.from_file', from_file_mock): - result = handler._get_sysbuild_build_dir() + result = handler.get_default_domain_build_dir() assert result == expected @@ -1753,28 +1731,29 @@ def mock_kill(pid, sig): TESTDATA_24 = [ - ('timeout', 'failed', 'Timeout'), - ('failed', 'failed', 'Failed'), - ('unexpected eof', 'failed', 'unexpected eof'), - ('unexpected byte', 'failed', 'unexpected byte'), - (None, None, 'Unknown'), + ('failed', 'timeout', 'failed', 'timeout'), + ('failed', 'Execution error', 'failed', 'Execution error'), + ('failed', 'unexpected eof', 'failed', 'unexpected eof'), + ('failed', 'unexpected byte', 'failed', 'unexpected byte'), + (None, None, None, 'Unknown'), ] @pytest.mark.parametrize( - 'out_state, expected_status, expected_reason', + '_status, _reason, expected_status, expected_reason', TESTDATA_24, ids=['timeout', 'failed', 'unexpected eof', 'unexpected byte', 'unknown'] ) def test_qemuhandler_thread_update_instance_info( mocked_instance, - out_state, + _status, + _reason, expected_status, expected_reason ): handler = QEMUHandler(mocked_instance, 'build') handler_time = 59 - QEMUHandler._thread_update_instance_info(handler, handler_time, out_state) + QEMUHandler._thread_update_instance_info(handler, handler_time, _status, _reason) assert handler.instance.execution_time == handler_time @@ -1790,6 +1769,7 @@ def test_qemuhandler_thread_update_instance_info( [None] * 60 + ['success'] * 6, 1000, False, + 'failed', 'timeout', [mock.call('1\n'), mock.call('1\n')] ), @@ -1801,6 +1781,7 @@ def test_qemuhandler_thread_update_instance_info( 100, False, 'failed', + None, [mock.call('1\n'), mock.call('1\n')] ), ( @@ -1810,6 +1791,7 @@ def test_qemuhandler_thread_update_instance_info( ['success'] * 3, 100, False, + 'failed', 'unexpected eof', [] ), @@ -1820,6 +1802,7 @@ def test_qemuhandler_thread_update_instance_info( ['success'] * 3, 100, False, + 'failed', 'unexpected byte', [] ), @@ -1831,6 +1814,7 @@ def test_qemuhandler_thread_update_instance_info( 100, False, 'success', + None, [mock.call('1\n'), mock.call('2\n'), mock.call('3\n'), mock.call('4\n')] ), ( @@ -1840,6 +1824,7 @@ def test_qemuhandler_thread_update_instance_info( [None] * 3 + ['success'] * 7, 100, False, + 'failed', 'timeout', [mock.call('1\n'), mock.call('2\n')] ), @@ -1851,13 +1836,14 @@ def test_qemuhandler_thread_update_instance_info( (n for n in [100, 100, 10000]), True, 'success', + None, [mock.call('1\n'), mock.call('2\n'), mock.call('3\n'), mock.call('4\n')] ), ] @pytest.mark.parametrize( 'content, timeout, pid, harness_states, cputime, capture_coverage,' \ - ' expected_out_state, expected_log_calls', + ' expected_status, expected_reason, expected_log_calls', TESTDATA_25, ids=[ 'timeout', @@ -1878,7 +1864,8 @@ def test_qemuhandler_thread( harness_states, cputime, capture_coverage, - expected_out_state, + expected_status, + expected_reason, expected_log_calls ): def mock_cputime(pid): @@ -1955,7 +1942,8 @@ def mocked_open(filename, *args, **kwargs): mock_thread_update_instance_info.assert_called_once_with( handler, mock.ANY, - expected_out_state + expected_status, + mock.ANY ) log_fp_mock.write.assert_has_calls(expected_log_calls) @@ -2017,7 +2005,7 @@ def mock_filenames(sysbuild_build_dir): harness = mock.Mock(state=harness_state) handler_options_west_flash = [] - sysbuild_build_dir = os.path.join('sysbuild', 'dummydir') + domain_build_dir = os.path.join('sysbuild', 'dummydir') command = ['generator_cmd', '-C', os.path.join('cmd', 'path'), 'run'] handler.options = mock.Mock( @@ -2030,7 +2018,7 @@ def mock_filenames(sysbuild_build_dir): handler._final_handle_actions = mock.Mock(return_value=None) handler._create_command = mock.Mock(return_value=command) handler._set_qemu_filenames = mock.Mock(side_effect=mock_filenames) - handler._get_sysbuild_build_dir = mock.Mock(return_value=sysbuild_build_dir) + handler.get_default_domain_build_dir = mock.Mock(return_value=domain_build_dir) handler.terminate = mock.Mock() unlink_mock = mock.Mock() diff --git a/scripts/tests/twister/test_hardwaremap.py b/scripts/tests/twister/test_hardwaremap.py index 57c028bfea69a..65440362f6971 100644 --- a/scripts/tests/twister/test_hardwaremap.py +++ b/scripts/tests/twister/test_hardwaremap.py @@ -383,6 +383,9 @@ def mock_iterdir(path): Path(path / 'basic-file2-link') ] + def mock_exists(path): + return True + mocked_hm.manufacturer = ['dummy manufacturer', 'Texas Instruments'] mocked_hm.runner_mapping = { 'dummy runner': ['product[0-9]+',], @@ -433,7 +436,9 @@ def mock_iterdir(path): mock.patch('twisterlib.hardwaremap.Path.resolve', autospec=True, side_effect=mock_resolve), \ mock.patch('twisterlib.hardwaremap.Path.iterdir', - autospec=True, side_effect=mock_iterdir): + autospec=True, side_effect=mock_iterdir), \ + mock.patch('twisterlib.hardwaremap.Path.exists', + autospec=True, side_effect=mock_exists): mocked_hm.scan(persistent) assert sorted([d.__repr__() for d in mocked_hm.detected]) == \ diff --git a/scripts/tests/twister/test_harness.py b/scripts/tests/twister/test_harness.py index 3657163a7ba45..2e0028b234a9c 100644 --- a/scripts/tests/twister/test_harness.py +++ b/scripts/tests/twister/test_harness.py @@ -44,6 +44,49 @@ def process_logs(harness, logs): harness.handle(line) +TEST_DATA_RECORDING = [ + ([''], "^START:(?P.*):END", [], None), + (['START:bar:STOP'], "^START:(?P.*):END", [], None), + (['START:bar:END'], "^START:(?P.*):END", [{'foo':'bar'}], None), + (['START:bar:baz:END'], "^START:(?P.*):(?P.*):END", [{'foo':'bar', 'boo':'baz'}], None), + (['START:bar:baz:END','START:may:jun:END'], "^START:(?P.*):(?P.*):END", + [{'foo':'bar', 'boo':'baz'}, {'foo':'may', 'boo':'jun'}], None), + (['START:bar:END'], "^START:(?P.*):END", [{'foo':'bar'}], []), + (['START:bar:END'], "^START:(?P.*):END", [{'foo':'bar'}], ['boo']), + (['START:bad_json:END'], "^START:(?P.*):END", + [{'foo':{'ERROR':{'msg':'Expecting value: line 1 column 1 (char 0)', 'doc':'bad_json'}}}], ['foo']), + (['START::END'], "^START:(?P.*):END", [{'foo':{}}], ['foo']), + (['START: {"one":1, "two":2} :END'], "^START:(?P.*):END", [{'foo':{'one':1, 'two':2}}], ['foo']), + (['START: {"one":1, "two":2} :STOP:oops:END'], "^START:(?P.*):STOP:(?P.*):END", + [{'foo':{'one':1, 'two':2},'boo':'oops'}], ['foo']), + (['START: {"one":1, "two":2} :STOP:{"oops":0}:END'], "^START:(?P.*):STOP:(?P.*):END", + [{'foo':{'one':1, 'two':2},'boo':{'oops':0}}], ['foo','boo']), + ] +@pytest.mark.parametrize( + "lines, pattern, expected_records, as_json", + TEST_DATA_RECORDING, + ids=["empty", "no match", "match 1 field", "match 2 fields", "match 2 records", + "as_json empty", "as_json no such field", "error parsing json", "empty json value", "simple json", + "plain field and json field", "two json fields" + ] +) +def test_harness_parse_record(lines, pattern, expected_records, as_json): + harness = Harness() + harness.record = { 'regex': pattern } + harness.record_pattern = re.compile(pattern) + + harness.record_as_json = as_json + if as_json is not None: + harness.record['as_json'] = as_json + + assert not harness.recording + + for line in lines: + harness.parse_record(line) + + assert harness.recording == expected_records + + TEST_DATA_1 = [('RunID: 12345', False, False, False, None, True), ('PROJECT EXECUTION SUCCESSFUL', False, False, False, 'passed', False), ('PROJECT EXECUTION SUCCESSFUL', True, False, False, 'failed', False), @@ -63,6 +106,7 @@ def test_harness_process_test(line, fault, fail_on_fault, cap_cov, exp_stat, exp harness.state = None harness.fault = fault harness.fail_on_fault = fail_on_fault + mock.patch.object(Harness, 'parse_record', return_value=None) #Act harness.process_test(line) @@ -71,6 +115,7 @@ def test_harness_process_test(line, fault, fail_on_fault, cap_cov, exp_stat, exp assert harness.matched_run_id == exp_id assert harness.state == exp_stat assert harness.capture_coverage == cap_cov + assert harness.recording == [] def test_robot_configure(tmp_path): @@ -138,7 +183,7 @@ def test_robot_handle(tmp_path): ) def test_robot_run_robot_test(tmp_path, caplog, exp_out, returncode, expected_status): # Arrange - command = "command" + command = ["command"] handler = mock.Mock() handler.sourcedir = "sourcedir" @@ -317,6 +362,7 @@ def test_pytest__generate_parameters_for_hardware(tmp_path, pty_value, hardware_ hardware.baud = 115200 hardware.runner = "runner" hardware.runner_params = ["--runner-param1", "runner-param2"] + hardware.fixtures = ['fixture1:option1', 'fixture2'] options = handler.options options.west_flash = "args" @@ -358,6 +404,8 @@ def test_pytest__generate_parameters_for_hardware(tmp_path, pty_value, hardware_ assert '--pre-script=pre_script' in command assert '--post-flash-script=post_flash_script' in command assert '--post-script=post_script' in command + assert '--twister-fixture=fixture1:option1' in command + assert '--twister-fixture=fixture2' in command def test__update_command_with_env_dependencies(): @@ -436,8 +484,8 @@ def test_get_harness(name): ("", "PASS - test_example in 0 seconds", [], "passed", True, None), ("", "SKIP - test_example in 0 seconds", [], "skipped", True, None), ("", "FAIL - test_example in 0 seconds", [], "failed", True, None), - ("not a ztest and no state for test_id", "START - test_testcase", [], "passed", False, "passed"), - ("not a ztest and no state for test_id", "START - test_testcase", [], "failed", False, "failed")] + ("not a ztest and no state for test_id", "START - test_testcase", [], "passed", False, "passed"), + ("not a ztest and no state for test_id", "START - test_testcase", [], "failed", False, "failed")] @pytest.mark.parametrize( "exp_out, line, exp_suite_name, exp_status, ztest, state", TEST_DATA_7, diff --git a/scripts/tests/twister/test_jobserver.py b/scripts/tests/twister/test_jobserver.py index c97e93204479b..554df8545fb2e 100644 --- a/scripts/tests/twister/test_jobserver.py +++ b/scripts/tests/twister/test_jobserver.py @@ -14,15 +14,13 @@ from contextlib import nullcontext from errno import ENOENT -from fcntl import F_GETFL from selectors import EVENT_READ -from twisterlib.jobserver import ( - JobHandle, - JobClient, - GNUMakeJobClient, - GNUMakeJobServer -) +# Job server only works on Linux for now. +pytestmark = pytest.mark.skipif(sys.platform != 'linux', reason='JobServer only works on Linux.') +if sys.platform == 'linux': + from twisterlib.jobserver import GNUMakeJobClient, GNUMakeJobServer, JobClient, JobHandle + from fcntl import F_GETFL def test_jobhandle(capfd): @@ -96,7 +94,6 @@ def test_jobclient_popen(kwargs, expected_kwargs): (True, 16), ] - @pytest.mark.parametrize( 'inheritable, internal_jobs', TESTDATA_2, @@ -283,6 +280,7 @@ def mock_fcntl(fd, flag): **expected_kwargs) + def test_gnumakejobclient_get_job(): inherit_read_fd = mock.Mock() inherit_write_fd = mock.Mock() diff --git a/scripts/tests/twister/test_runner.py b/scripts/tests/twister/test_runner.py index e2a51fc2a09d1..e1e12242108ef 100644 --- a/scripts/tests/twister/test_runner.py +++ b/scripts/tests/twister/test_runner.py @@ -42,6 +42,7 @@ def mocked_instance(tmp_path): testsuite.source_dir: str = '' instance.testsuite = testsuite platform = mock.Mock() + platform.sysbuild = False platform.binaries: List[str] = [] instance.platform = platform build_dir = tmp_path / 'build_dir' @@ -131,7 +132,7 @@ def test_if_default_binaries_are_taken_properly(project_builder: ProjectBuilder) os.path.join('zephyr', 'zephyr.elf'), os.path.join('zephyr', 'zephyr.exe'), ] - project_builder.testsuite.sysbuild = False + project_builder.instance.sysbuild = False binaries = project_builder._get_binaries() assert sorted(binaries) == sorted(default_binaries) @@ -139,7 +140,7 @@ def test_if_default_binaries_are_taken_properly(project_builder: ProjectBuilder) def test_if_binaries_from_platform_are_taken_properly(project_builder: ProjectBuilder): platform_binaries = ['spi_image.bin'] project_builder.platform.binaries = platform_binaries - project_builder.testsuite.sysbuild = False + project_builder.instance.sysbuild = False platform_binaries_expected = [os.path.join('zephyr', bin) for bin in platform_binaries] binaries = project_builder._get_binaries() assert sorted(binaries) == sorted(platform_binaries_expected) @@ -554,20 +555,6 @@ def mock_popen(*args, **kwargs): ['Sysbuild test will be skipped. West must be used for flashing.'], {os.path.join('other', 'dummy.testsuite.name'): True} ), - ( - 'other', ['other'], True, - False, ['--erase'], True, - 'Dummy parse results', True, - None, - None, - {}, - {}, - None, - b'dummy edt pickle contents', - ['Sysbuild test will be skipped,' \ - ' --erase is not supported with --west-flash'], - {os.path.join('other', 'dummy.testsuite.name'): True} - ), ( 'other', ['other'], False, True, None, False, @@ -651,7 +638,7 @@ def mock_popen(*args, **kwargs): ' expected_logs, expected_return', TESTDATA_3, ids=['unit testing', 'domain', 'kconfig', 'no cache', - 'no west options', 'erase west flash option', 'no edt', + 'no west options', 'no edt', 'parse result', 'no parse result', 'no testsuite filter', 'parse err'] ) def test_filterbuilder_parse_generated( @@ -712,7 +699,6 @@ def mock_pickle(datafile): return mock.Mock() testsuite_mock = mock.Mock() - testsuite_mock.sysbuild = 'sysbuild' if sysbuild else None testsuite_mock.name = 'dummy.testsuite.name' testsuite_mock.filter = testsuite_filter platform_mock = mock.Mock() @@ -724,6 +710,7 @@ def mock_pickle(datafile): fb = FilterBuilder(testsuite_mock, platform_mock, source_dir, build_dir, mocked_jobserver) instance_mock = mock.Mock() + instance_mock.sysbuild = 'sysbuild' if sysbuild else None fb.instance = instance_mock fb.env = mock.Mock() fb.env.options = mock.Mock() @@ -1689,7 +1676,7 @@ def test_projectbuilder_cleanup_device_testing_artifacts( bins = [os.path.join('zephyr', 'file.bin')] instance_mock = mock.Mock() - instance_mock.testsuite.sysbuild = False + instance_mock.sysbuild = False build_dir = os.path.join('build', 'dir') instance_mock.build_dir = build_dir env_mock = mock.Mock() @@ -2705,6 +2692,7 @@ def mock_join(): process_mock = mock.Mock() process_mock().join = mock.Mock(side_effect=mock_join) + process_mock().exitcode = 0 pipeline_mock = mock.Mock() done_mock = mock.Mock() diff --git a/scripts/tests/twister/test_testinstance.py b/scripts/tests/twister/test_testinstance.py index 1b1c99a214358..560923173b094 100644 --- a/scripts/tests/twister/test_testinstance.py +++ b/scripts/tests/twister/test_testinstance.py @@ -226,6 +226,37 @@ def test_testinstance_init(all_testsuites_dict, class_testplan, platforms_list, assert testinstance.build_dir == os.path.join(class_testplan.env.outdir, platform.name, testsuite.source_dir_rel, testsuite.name) +@pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'sample'}], indirect=True) +def test_testinstance_record(testinstance): + testinstance.testcases = [mock.Mock()] + recording = [ {'field_1': 'recording_1_1', 'field_2': 'recording_1_2'}, + {'field_1': 'recording_2_1', 'field_2': 'recording_2_2'} + ] + with mock.patch( + 'builtins.open', + mock.mock_open(read_data='') + ) as mock_file, \ + mock.patch( + 'csv.DictWriter.writerow', + mock.Mock() + ) as mock_writeheader, \ + mock.patch( + 'csv.DictWriter.writerows', + mock.Mock() + ) as mock_writerows: + testinstance.record(recording) + + print(mock_file.mock_calls) + + mock_file.assert_called_with( + os.path.join(testinstance.build_dir, 'recording.csv'), + 'wt' + ) + + mock_writeheader.assert_has_calls([mock.call({ k:k for k in recording[0]})]) + mock_writerows.assert_has_calls([mock.call(recording)]) + + @pytest.mark.parametrize('testinstance', [{'testsuite_kind': 'sample'}], indirect=True) def test_testinstance_add_filter(testinstance): reason = 'dummy reason' @@ -566,7 +597,7 @@ def test_testinstance_get_elf_file(caplog, tmp_path, testinstance, sysbuild, exp sysbuild_elf2 = zephyr_dir / 'dummy2.elf' sysbuild_elf2.write_bytes(b'0') - testinstance.testsuite.sysbuild = sysbuild + testinstance.sysbuild = sysbuild testinstance.domains = mock.Mock( get_default_domain=mock.Mock( return_value=mock.Mock( diff --git a/scripts/tests/twister/test_testplan.py b/scripts/tests/twister/test_testplan.py index 600cde4c1a6db..60f6c3a4d42de 100644 --- a/scripts/tests/twister/test_testplan.py +++ b/scripts/tests/twister/test_testplan.py @@ -110,7 +110,7 @@ def test_get_platforms_short(class_testplan, platforms_list): ("None", "None", "env", ['BSIM_OUT_PATH', 'demo_env'], "Environment (BSIM_OUT_PATH, demo_env) not satisfied"), ("build_on_all", True, None, None, "Platform is excluded on command line."), ("build_on_all", True, "level", "foobar", "Unknown test level 'foobar'"), - (None, None, "supported_toolchains", ['gcc'], "Not supported by the toolchain"), + (None, None, "supported_toolchains", ['gcc', 'xcc', 'xt-clang'], "Not supported by the toolchain"), ] @@ -709,6 +709,7 @@ def test_testplan_load( testplan.testsuites['ts1'].name = 'ts1' testplan.testsuites['ts2'].name = 'ts2' testplan.options = mock.Mock( + report_summary=None, outdir=tmp_path, report_suffix=report_suffix, only_failed=only_failed, @@ -1058,15 +1059,6 @@ def test_testplan_report_test_list(capfd): '10 total.' in out -def test_testplan_config(caplog): - testplan = TestPlan(env=mock.Mock()) - testplan.coverage_platform = 'dummy cov' - - testplan.config() - - assert 'coverage platform: dummy cov' in caplog.text - - def test_testplan_info(capfd): TestPlan.info('dummy text') @@ -1460,7 +1452,7 @@ def get_platform(name): ts5.name = 'TestSuite 5' testplan = TestPlan(env=mock.Mock(outdir=os.path.join('out', 'dir'))) - testplan.options = mock.Mock(device_testing=device_testing, test_only=True) + testplan.options = mock.Mock(device_testing=device_testing, test_only=True, report_summary=None) testplan.testsuites = { 'TestSuite 1': ts1, 'TestSuite 2': ts2, diff --git a/scripts/tests/twister/test_testsuite.py b/scripts/tests/twister/test_testsuite.py index 74402561fc190..565fa9dadd848 100644 --- a/scripts/tests/twister/test_testsuite.py +++ b/scripts/tests/twister/test_testsuite.py @@ -213,26 +213,41 @@ def test_scan_file(test_data, test_file, class_env, expected: ScanPathResult): assert result == expected -TESTDATA_3 = [ - ( - 'nt', - {'access': mmap.ACCESS_READ} - ), - ( - 'posix', - { - 'flags': mmap.MAP_PRIVATE, - 'prot': mmap.PROT_READ, - 'offset': 0 - } +# Generate testcases depending on available mmap attributes +TESTIDS_3 = [] +TESTDATA_3 = [] + +try: + TESTDATA_3.append( + ( + 'nt', + {'access': mmap.ACCESS_READ} + ) ) -] + TESTIDS_3.append('windows') +except AttributeError: + pass + +try: + TESTDATA_3.append( + ( + 'posix', + { + 'flags': mmap.MAP_PRIVATE, + 'prot': mmap.PROT_READ, + 'offset': 0 + } + ) + ) + TESTIDS_3.append('linux') +except AttributeError: + pass @pytest.mark.parametrize( 'os_name, expected', TESTDATA_3, - ids=['windows', 'linux'] + ids=TESTIDS_3 ) def test_scan_file_mmap(os_name, expected): class TestException(Exception): diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/CMakeLists.txt b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/CMakeLists.txt new file mode 100644 index 0000000000000..635c696edf9d5 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/prj.conf new file mode 100644 index 0000000000000..9467c2926896d --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/src/main.c b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/src/main.c new file mode 100644 index 0000000000000..3c250486af659 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/src/main.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +ZTEST_SUITE(a1_1_tests, NULL, NULL, NULL, NULL, NULL); + +/** + * @brief Test Asserts + * + * This test verifies various assert macros provided by ztest. + * + */ +ZTEST(a1_1_tests, test_assert) +{ + zassert_true(1, "1 was false"); + zassert_false(0, "0 was true"); + zassert_is_null(NULL, "NULL was not NULL"); + zassert_not_null("foo", "\"foo\" was NULL"); + zassert_equal(1, 1, "1 was not equal to 1"); + zassert_equal_ptr(NULL, NULL, "NULL was not equal to NULL"); +} diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/test_data.yaml b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/test_data.yaml new file mode 100644 index 0000000000000..e42250e6b248c --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup1/test_data.yaml @@ -0,0 +1,11 @@ +tests: + one_fail_two_error_one_pass.agnostic.group1.subgroup1: + platform_allow: + - native_posix + - qemu_x86 + - qemu_x86_64 + integration_platforms: + - native_posix + tags: + - agnostic + - subgrouped diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/CMakeLists.txt b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/CMakeLists.txt new file mode 100644 index 0000000000000..635c696edf9d5 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/prj.conf new file mode 100644 index 0000000000000..9467c2926896d --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/src/main.c b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/src/main.c new file mode 100644 index 0000000000000..d896f500c9e45 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/src/main.c @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +ZTEST_SUITE(a1_2_tests, NULL, NULL, NULL, NULL, NULL); + +/** + * @brief Test Asserts + * + * This test verifies various assert macros provided by ztest. + * + */ +ZTEST(a1_2_tests, test_assert) +{ + zassert_true(0, "1 was false"); + zassert_false(1, "0 was true"); +} diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/test_data.yaml b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/test_data.yaml new file mode 100644 index 0000000000000..b2813ad46e12c --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup2/test_data.yaml @@ -0,0 +1,11 @@ +tests: + one_fail_two_error_one_pass.agnostic.group1.subgroup2: + platform_allow: + - native_posix + - qemu_x86 + - qemu_x86_64 + integration_platforms: + - native_posix + tags: + - agnostic + - subgrouped diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/CMakeLists.txt b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/CMakeLists.txt new file mode 100644 index 0000000000000..635c696edf9d5 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/prj.conf new file mode 100644 index 0000000000000..9467c2926896d --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/src/main.c b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/src/main.c new file mode 100644 index 0000000000000..04b4de0e0867e --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/src/main.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +ZTEST_SUITE(a1_2_tests, NULL, NULL, NULL, NULL, NULL); + +/** + * @brief Test Asserts + * + * This test verifies various assert macros provided by ztest. + * + */ +ZTEST(a1_2_tests, test_assert) +{ + dummy + zassert_true(0, "1 was false"); + zassert_false(1, "0 was true"); +} diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/test_data.yaml b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/test_data.yaml new file mode 100644 index 0000000000000..c5c9486c735cb --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup3/test_data.yaml @@ -0,0 +1,11 @@ +tests: + one_fail_two_error_one_pass.agnostic.group1.subgroup3: + platform_allow: + - native_posix + - qemu_x86 + - qemu_x86_64 + integration_platforms: + - native_posix + tags: + - agnostic + - subgrouped diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/CMakeLists.txt b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/CMakeLists.txt new file mode 100644 index 0000000000000..635c696edf9d5 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/CMakeLists.txt @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(integration) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${app_sources}) diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/prj.conf b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/prj.conf new file mode 100644 index 0000000000000..9467c2926896d --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/prj.conf @@ -0,0 +1 @@ +CONFIG_ZTEST=y diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/src/main.c b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/src/main.c new file mode 100644 index 0000000000000..04b4de0e0867e --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/src/main.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 Intel Corporation + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + + +ZTEST_SUITE(a1_2_tests, NULL, NULL, NULL, NULL, NULL); + +/** + * @brief Test Asserts + * + * This test verifies various assert macros provided by ztest. + * + */ +ZTEST(a1_2_tests, test_assert) +{ + dummy + zassert_true(0, "1 was false"); + zassert_false(1, "0 was true"); +} diff --git a/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/test_data.yaml b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/test_data.yaml new file mode 100644 index 0000000000000..a4957e6f5ebb3 --- /dev/null +++ b/scripts/tests/twister_blackbox/test_data/tests/one_fail_two_error_one_pass/agnostic/group1/subgroup4/test_data.yaml @@ -0,0 +1,11 @@ +tests: + one_fail_two_error_one_pass.agnostic.group1.subgroup4: + platform_allow: + - native_posix + - qemu_x86 + - qemu_x86_64 + integration_platforms: + - native_posix + tags: + - agnostic + - subgrouped diff --git a/scripts/tests/twister_blackbox/test_report.py b/scripts/tests/twister_blackbox/test_report.py index 80f8f722a3eb2..d7aa016212777 100644 --- a/scripts/tests/twister_blackbox/test_report.py +++ b/scripts/tests/twister_blackbox/test_report.py @@ -13,10 +13,12 @@ import pytest import shutil import sys +import re from lxml import etree -from conftest import TEST_DATA, ZEPHYR_BASE, testsuite_filename_mock +# pylint: disable=no-name-in-module +from conftest import TEST_DATA, ZEPHYR_BASE, testsuite_filename_mock, clear_log_in_test from twisterlib.testplan import TestPlan @@ -106,6 +108,15 @@ class TestReport: "TEST_LOG_FILE.log" ), ] + TESTDATA_7 = [ + ( + os.path.join(TEST_DATA, 'tests', 'one_fail_two_error_one_pass'), + ['qemu_x86'], + [r'one_fail_two_error_one_pass.agnostic.group1.subgroup2 on qemu_x86 FAILED \(.*\)', + r'one_fail_two_error_one_pass.agnostic.group1.subgroup3 on qemu_x86 ERROR \(Build failure\)', + r'one_fail_two_error_one_pass.agnostic.group1.subgroup4 on qemu_x86 ERROR \(Build failure\)'], + ) + ] @classmethod def setup_class(cls): @@ -333,14 +344,25 @@ def test_log_file(self, capfd, test_path, test_platforms, out_path, file_name): assert str(sys_exit.value) == '0' @pytest.mark.parametrize( - 'test_path, expected_testcase_count', - [(os.path.join(TEST_DATA, 'tests', 'dummy'), 6),], - ids=['dummy tests'] + 'test_path, flags, expected_testcase_counts', + [ + ( + os.path.join(TEST_DATA, 'tests', 'dummy'), + ['--detailed-skipped-report'], + {'qemu_x86': 5, 'frdm_k64f': 1} + ), + ( + os.path.join(TEST_DATA, 'tests', 'dummy'), + ['--detailed-skipped-report', '--report-filtered'], + {'qemu_x86': 6, 'frdm_k64f': 6} + ), + ], + ids=['dummy tests', 'dummy tests with filtered'] ) - def test_detailed_skipped_report(self, out_path, test_path, expected_testcase_count): + def test_detailed_skipped_report(self, out_path, test_path, flags, expected_testcase_counts): test_platforms = ['qemu_x86', 'frdm_k64f'] args = ['-i', '--outdir', out_path, '-T', test_path] + \ - ['--detailed-skipped-report'] + \ + flags + \ [val for pair in zip( ['-p'] * len(test_platforms), test_platforms ) for val in pair] @@ -356,12 +378,47 @@ def test_detailed_skipped_report(self, out_path, test_path, expected_testcase_co for ts in xml_data.iter('testsuite'): testsuite_counter += 1 # Without the tested flag, filtered testcases would be missing from the report - assert len(list(ts.iter('testcase'))) == expected_testcase_count, \ - 'Not all expected testcases appear in the report.' + testcase_count = len(list(ts.iter('testcase'))) + expected_tc_count = expected_testcase_counts[ts.get('name')] + assert testcase_count == expected_tc_count, \ + f'Not all expected testcases appear in the report.' \ + f' (In {ts.get("name")}, expected {expected_tc_count}, got {testcase_count}.)' assert testsuite_counter == len(test_platforms), \ 'Some platforms are missing from the XML report.' + @pytest.mark.parametrize( + 'test_path, report_filtered, expected_filtered_count', + [ + (os.path.join(TEST_DATA, 'tests', 'dummy'), False, 0), + (os.path.join(TEST_DATA, 'tests', 'dummy'), True, 4), + ], + ids=['no filtered', 'with filtered'] + ) + def test_report_filtered(self, out_path, test_path, report_filtered, expected_filtered_count): + test_platforms = ['qemu_x86', 'frdm_k64f'] + args = ['-i', '--outdir', out_path, '-T', test_path] + \ + (['--report-filtered'] if report_filtered else []) + \ + [val for pair in zip( + ['-p'] * len(test_platforms), test_platforms + ) for val in pair] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + assert str(sys_exit.value) == '0' + + with open(os.path.join(out_path, 'twister.json')) as f: + j = json.load(f) + + testsuites = j.get('testsuites') + assert testsuites, 'No testsuites found.' + statuses = [testsuite.get('status') for testsuite in testsuites] + filtered_status_count = statuses.count("filtered") + assert filtered_status_count == expected_filtered_count, \ + f'Expected {expected_filtered_count} filtered statuses, got {filtered_status_count}.' + def test_enable_size_report(self, out_path): test_platforms = ['qemu_x86', 'frdm_k64f'] path = os.path.join(TEST_DATA, 'tests', 'dummy', 'device', 'group') @@ -397,3 +454,65 @@ def test_enable_size_report(self, out_path): if ts['name'] == expected_rel_path and not 'reason' in ts ] ) + + @pytest.mark.parametrize( + 'test_path, test_platforms, expected_content', + TESTDATA_7, + ids=[ + 'Report summary test' + ] + ) + + def test_report_summary(self, out_path, capfd, test_path, test_platforms, expected_content): + args = ['-i', '--outdir', out_path, '-T', test_path] + \ + [val for pair in zip( + ['-p'] * len(test_platforms), test_platforms + ) for val in pair] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + assert str(sys_exit.value) == '1' + + capfd.readouterr() + + clear_log_in_test() + + args += ['--report-summary'] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + for line in expected_content: + result = re.search(line, err) + assert result, f'missing information in log: {line}' + + capfd.readouterr() + + clear_log_in_test() + + args = ['-i', '--outdir', out_path, '-T', test_path] + \ + ['--report-summary', '2'] + \ + [val for pair in zip( + ['-p'] * len(test_platforms), test_platforms + ) for val in pair] + + with mock.patch.object(sys, 'argv', [sys.argv[0]] + args), \ + pytest.raises(SystemExit) as sys_exit: + self.loader.exec_module(self.twister_module) + + out, err = capfd.readouterr() + sys.stdout.write(out) + sys.stderr.write(err) + + lines=0 + for line in expected_content: + result = re.search(line, err) + if result: lines += 1 + assert lines == 2, f'too many or too few lines' diff --git a/scripts/tests/twister_blackbox/test_runner.py b/scripts/tests/twister_blackbox/test_runner.py index 97e36d8b8a633..1e5f10683153d 100644 --- a/scripts/tests/twister_blackbox/test_runner.py +++ b/scripts/tests/twister_blackbox/test_runner.py @@ -45,15 +45,15 @@ class TestRunner: ['qemu_x86', 'qemu_x86_64', 'frdm_k64f'], { 'selected_test_scenarios': 3, - 'selected_test_instances': 9, - 'skipped_configurations': 3, - 'skipped_by_static_filter': 3, + 'selected_test_instances': 6, + 'skipped_configurations': 0, + 'skipped_by_static_filter': 0, 'skipped_at_runtime': 0, 'passed_configurations': 4, 'failed_configurations': 0, 'errored_configurations': 0, 'executed_test_cases': 8, - 'skipped_test_cases': 5, + 'skipped_test_cases': 0, 'platform_count': 0, 'executed_on_platform': 4, 'only_built': 2 @@ -622,7 +622,7 @@ def test_only_failed(self, capfd, out_path, test_path, test_platforms, expected) assert re.search( - r'one_fail_one_pass.agnostic.group1.subgroup2 on qemu_x86 failed \(Failed\)', err) + r'one_fail_one_pass.agnostic.group1.subgroup2 on qemu_x86 failed \(.*\)', err) pass_search = re.search(pass_regex, err, re.MULTILINE) diff --git a/scripts/twister b/scripts/twister index aa075beb7a1fb..c6382f9a9e337 100755 --- a/scripts/twister +++ b/scripts/twister @@ -211,7 +211,8 @@ if __name__ == "__main__": try: parser = add_parse_arguments() options = parse_arguments(parser, sys.argv[1:]) - ret = main(options) + default_options = parse_arguments(parser, [], on_init=False) + ret = main(options, default_options) finally: if (os.name != "nt") and os.isatty(1): # (OS is not Windows) and (stdout is interactive) diff --git a/scripts/utils/migrate_posix_kconfigs.py b/scripts/utils/migrate_posix_kconfigs.py new file mode 100644 index 0000000000000..ea8eed2d2f8e5 --- /dev/null +++ b/scripts/utils/migrate_posix_kconfigs.py @@ -0,0 +1,137 @@ +""" +Utility script to migrate Zephyr-based projects to normative POSIX Kconfig options. + +This script should be used for migrating from versions of Zephyr older than v3.7.0 to Zephyr +version v3.7.0 or later. + +Usage:: + + python $ZEPHYR_BASE/scripts/utils/migrate_posix_kconfigs.py -r root_path + +The utility will process c, cpp, h, hpp, rst, conf, CMakeLists.txt, +yml, yaml and Kconfig files. + + +Copyright (c) 2022 Nordic Semiconductor ASA +Copyright (c) 2024 Tenstorrent AI ULC +SPDX-License-Identifier: Apache-2.0 +""" + +import argparse +from pathlib import Path +import re +import sys + + +ZEPHYR_BASE = Path(__file__).parents[2] + +FILE_PATTERNS = ( + r".+\.c", r".+\.cpp", r".+\.hpp", r".+\.h", r".+\.rst", r".+\.conf", + r".+\.yml", r".+\.yaml", r"CMakeLists.txt", r"Kconfig(\..+)?" +) + +REPLACEMENTS = { + "EVENTFD_MAX": "ZVFS_EVENTFD_MAX", + "FNMATCH": "POSIX_C_LIB_EXT", + "GETENTROPY": "POSIX_C_LIB_EXT", + "GETOPT": "POSIX_C_LIB_EXT", + "MAX_PTHREAD_COUNT": "POSIX_THREAD_THREADS_MAX", + "MAX_PTHREAD_KEY_COUNT": "POSIX_THREAD_KEYS_MAX", + "MAX_TIMER_COUNT": "POSIX_TIMER_MAX", + "MSG_COUNT_MAX": "POSIX_MQ_OPEN_MAX", + "POSIX_CLOCK": "POSIX_TIMERS", + "POSIX_CONFSTR": "POSIX_SINGLE_PROCESS", + "POSIX_ENV": "POSIX_SINGLE_PROCESS", + "POSIX_FS": "POSIX_FILE_SYSTEM", + "POSIX_LIMITS_RTSIG_MAX": "POSIX_RTSIG_MAX", + "POSIX_MAX_FDS": "ZVFS_OPEN_MAX", + "POSIX_MAX_OPEN_FILES": "ZVFS_OPEN_MAX", + "POSIX_MQUEUE": "POSIX_MESSAGE_PASSING", + "POSIX_PUTMSG": "XOPEN_STREAMS", + "POSIX_SIGNAL": "POSIX_SIGNALS", + "POSIX_SYSCONF": "POSIX_SINGLE_PROCESS", + "POSIX_SYSLOG": "XSI_SYSTEM_LOGGING", + "POSIX_UNAME": "POSIX_SINGLE_PROCESS", + "PTHREAD": "POSIX_THREADS", + "PTHREAD_BARRIER": "POSIX_BARRIERS", + "PTHREAD_COND": "POSIX_THREADS", + "PTHREAD_IPC": "POSIX_THREADS", + "PTHREAD_KEY": "POSIX_THREADS", + "PTHREAD_MUTEX": "POSIX_THREADS", + "PTHREAD_RWLOCK": "POSIX_READER_WRITER_LOCKS", + "PTHREAD_SPINLOCK": "POSIX_SPIN_LOCKS", + "TIMER": "POSIX_TIMERS", + "TIMER_DELAYTIMER_MAX": "POSIX_DELAYTIMER_MAX", + "SEM_NAMELEN_MAX": "POSIX_SEM_NAME_MAX", + "SEM_VALUE_MAX": "POSIX_SEM_VALUE_MAX", +} + +MESSAGES = { + "POSIX_CLOCK": + "POSIX_CLOCK is a one-to-many replacement. If this simple substitution is not " + "sufficient, it's best to try a combination of POSIX_CLOCK_SELECTION, POSIX_CPUTIME, " + "POSIX_MONOTONIC_CLOCK, POSIX_TIMERS, and POSIX_TIMEOUTS.", + "POSIX_MAX_FDS": + "A read-only version of this symbol is POSIX_OPEN_MAX, which is of course, the standard " + "symbol. ZVFS_OPEN_MAX may be set by the user. Consider using POSIX_MAX_FDS if the " + "use-case is read-only.", +} + + +def process_file(path): + modified = False + output = [] + + try: + with open(path) as f: + lines = f.readlines() + + for line in lines: + longest = "" + length = 0 + for m in REPLACEMENTS: + if re.match(".*" + m + ".*", line) and len(m) > length: + length = len(m) + longest = m + + if length != 0: + modified = True + line = line.replace(longest, REPLACEMENTS[longest]) + msg = MESSAGES.get(longest) + if msg: + print( + f"Notice: {longest} -> {REPLACEMENTS[longest]}: {msg}") + + output.append(line) + + if modified is False: + return + + with open(path, "w") as f: + f.writelines(output) + + except UnicodeDecodeError: + print(f"Unable to read lines from {path}", file=sys.stderr) + except Exception as e: + print(f"Failed with exception {e}", e) + + +def process_tree(project): + for p in project.glob("**/*"): + for fp in FILE_PATTERNS: + cfp = re.compile(".+/" + fp + "$") + if re.match(cfp, str(p)) is not None: + process_file(p) + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(allow_abbrev=False) + parser.add_argument( + "-r", + "--root", + type=Path, + required=True, + help="Zephyr-based project path") + args = parser.parse_args() + + process_tree(args.root) diff --git a/scripts/west-commands.yml b/scripts/west-commands.yml index 803d2b7b2d1a9..24bbddb984535 100644 --- a/scripts/west-commands.yml +++ b/scripts/west-commands.yml @@ -10,6 +10,11 @@ west-commands: - name: boards class: Boards help: display information about supported boards + - file: scripts/west_commands/shields.py + commands: + - name: shields + class: Shields + help: display list of supported shields - file: scripts/west_commands/build.py commands: - name: build @@ -61,3 +66,13 @@ west-commands: - name: bindesc class: Bindesc help: work with Binary Descriptors + - file: scripts/west_commands/robot.py + commands: + - name: robot + class: Robot + help: run RobotFramework test suites + - file: scripts/west_commands/simulate.py + commands: + - name: simulate + class: Simulate + help: simulate board diff --git a/scripts/west_commands/blobs.py b/scripts/west_commands/blobs.py index d501416f54014..d23729c9d90fc 100644 --- a/scripts/west_commands/blobs.py +++ b/scripts/west_commands/blobs.py @@ -81,7 +81,15 @@ def do_add_parser(self, parser_adder): def get_blobs(self, args): blobs = [] modules = args.modules - for module in zephyr_module.parse_modules(ZEPHYR_BASE, self.manifest): + all_modules = zephyr_module.parse_modules(ZEPHYR_BASE, self.manifest) + all_names = [m.meta.get('name', None) for m in all_modules] + + unknown = set(modules) - set(all_names) + + if len(unknown): + log.die(f'Unknown module(s): {unknown}') + + for module in all_modules: # Filter by module module_name = module.meta.get('name', None) if len(modules) and module_name not in modules: diff --git a/scripts/west_commands/build.py b/scripts/west_commands/build.py index f7a605f4d7fc8..c137d1a95d2bf 100644 --- a/scripts/west_commands/build.py +++ b/scripts/west_commands/build.py @@ -24,6 +24,7 @@ BUILD_USAGE = '''\ west build [-h] [-b BOARD[@REV]]] [-d BUILD_DIR] + [-S SNIPPET] [--shield SHIELD] [-t TARGET] [-p {auto, always, never}] [-c] [--cmake-only] [-n] [-o BUILD_OPT] [-f] [--sysbuild | --no-sysbuild] [--domain DOMAIN] @@ -135,13 +136,20 @@ def do_add_parser(self, parser_adder): group.add_argument('-n', '--just-print', '--dry-run', '--recon', dest='dry_run', action='store_true', help="just print build commands; don't run them") - group.add_argument('-S', '--snippet', dest='snippets', + group.add_argument('-S', '--snippet', dest='snippets', metavar='SNIPPET', action='append', default=[], help='''add the argument to SNIPPET; may be given multiple times. Forces CMake to run again if given. Do not use this option with manually specified -DSNIPPET... cmake arguments: the results are undefined''') + group.add_argument('--shield', dest='shields', metavar='SHIELD', + action='append', default=[], + help='''add the argument to SHIELD; may be given + multiple times. Forces CMake to run again if given. + Do not use this option with manually specified + -DSHIELD... cmake arguments: the results are + undefined''') group = parser.add_mutually_exclusive_group() group.add_argument('--sysbuild', action='store_true', @@ -214,7 +222,8 @@ def do_run(self, args, remainder): else: self._update_cache() if (self.args.cmake or self.args.cmake_opts or - self.args.cmake_only or self.args.snippets): + self.args.cmake_only or self.args.snippets or + self.args.shields): self.run_cmake = True else: self.run_cmake = True @@ -267,7 +276,7 @@ def _parse_remainder(self, remainder): if remainder: self.args.cmake_opts = remainder except IndexError: - return + pass def _parse_test_item(self, test_item): found_test_metadata = False @@ -552,6 +561,8 @@ def _run_cmake(self, board, origin, cmake_opts): cmake_opts.extend(self.args.cmake_opts) if self.args.snippets: cmake_opts.append(f'-DSNIPPET={";".join(self.args.snippets)}') + if self.args.shields: + cmake_opts.append(f'-DSHIELD={";".join(self.args.shields)}') user_args = config_get('cmake-args', None) if user_args: diff --git a/scripts/west_commands/completion/west-completion.bash b/scripts/west_commands/completion/west-completion.bash index d812e8933b1b7..3a528cded68a7 100644 --- a/scripts/west_commands/completion/west-completion.bash +++ b/scripts/west_commands/completion/west-completion.bash @@ -401,6 +401,11 @@ __set_comp_west_boards() __set_comp ${boards[@]} } +__set_comp_west_shields() +{ + __set_comp "$(__west_x shields "$@")" +} + __comp_west_west() { case "$prev" in @@ -689,6 +694,37 @@ __comp_west_boards() esac } +__comp_west_shields() +{ + local other_opts=" + --format -f + --name -n + " + + local dir_opts=" + --board-root + " + + all_opts="$dir_opts $other_opts" + + case "$prev" in + $(__west_to_extglob "$other_opts") ) + # We don't know how to autocomplete these. + return + ;; + $(__west_to_extglob "$dir_opts") ) + __set_comp_dirs + return + ;; + esac + + case "$cur" in + -*) + __set_comp $all_opts + ;; + esac +} + __comp_west_build() { local bool_opts=" @@ -702,6 +738,8 @@ __comp_west_build() local special_opts=" --board -b + --snippet -S + --shield --pristine -p " @@ -722,6 +760,10 @@ __comp_west_build() __set_comp_west_boards return ;; + --shield) + __set_comp_west_shields + return + ;; --pristine|-p) __set_comp "auto always never" return @@ -930,6 +972,175 @@ __comp_west_blobs() esac } +__comp_west_twister() +{ + local bool_opts=" + --aggressive-no-clean + --all -l + --all-deltas -D + --allow-installed-plugin + --build-only -b + --clobber-output -c + --cmake-only + --coverage -C + --create-rom-ram-report + --detailed-skipped-report + --detailed-test-id + --device-flash-with-test + --device-testing + --disable-suite-name-check + --disable-unrecognized-section-test + --disable-warnings-as-errors -W + --dry-run -y + --emulation-only + --enable-asan + --enable-coverage + --enable-lsan + --enable-size-report + --enable-slow -S + --enable-slow-only + --enable-ubsan + --enable-valgrind + --flash-before + --footprint-from-buildlog + --force-color + --force-platform -K + --force-toolchain + --ignore-platform-key + --inline-logs -i + --integration -G + --last-metrics -m + --list-tags + --list-tests + --make -k + --ninja -N + --no-clean -n + --no-detailed-test-id + --no-update -u + --only-failed -f + --overflow-as-errors + --persistent-hardware-map + --platform-reports + --prep-artifacts-for-testing + --quarantine-verify + --retry-build-errors + --short-build-path + --show-footprint + --shuffle-tests + --test-only + --test-tree + --timestamps + --verbose -v + " + + local dir_opts=" + --alt-config-root + --board-root -A + --coverage-basedir + --outdir -O + --report-dir -o + --testsuite-root -T + " + + local file_opts=" + --compare-report + --device-serial + --device-serial-pty + --gcov-tool + --generate-hardware-map + --hardware-map + --load-tests -F + --log-file + --package-artifacts + --pre-script + --quarantine-list + --save-tests -E + --size -z + --test-config + " + + local special_opts=" + --coverage-platform + --coverage-tool + --exclude-platform -P + --filter + --platform -p + --runtime-artifact-cleanup -M + " + + local other_opts=" + --arch -a + --coverage-formats + --device-flash-timeout + --device-serial-baud + --exclude-tag -e + --extra-args -x + --fixture -X + --footprint-threshold -H + --jobs -j + --level + --pytest-args + --report-name + --report-suffix + --retry-failed + --retry-interval + --scenario --test -s + --seed + --shuffle-tests-seed + --sub-test + --subset -B + --tag -t + --timeout-multiplier + --vendor + --west-flash + --west-runner + " + + all_opts="$bool_opts $dir_opts $file_opts $special_opts $other_opts" + + case "$prev" in + --platform|-p|--exclude-platform|-P|--coverage-platform) + __set_comp_west_boards + return + ;; + + --coverage-tool) + __set_comp "gcovr lcov" + return + ;; + + --filter) + __set_comp "buildable runnable" + return + ;; + + --runtime-artifact-cleanup|-M) + __set_comp "all pass" + return + ;; + + $(__west_to_extglob "$dir_opts") ) + __set_comp_dirs + return + ;; + + $(__west_to_extglob "$file_opts") ) + __set_comp_files + return + ;; + + # We don't know how to autocomplete those + $(__west_to_extglob "$other_opts") ) + return + ;; + esac + + case "$cur" in + -*) + __set_comp $all_opts + ;; + esac +} __comp_west() { @@ -954,6 +1165,7 @@ __comp_west() local zephyr_ext_cmds=( completion boards + shields build sign flash @@ -963,6 +1175,7 @@ __comp_west() zephyr-export spdx blobs + twister ) local cmds=(${builtin_cmds[*]} ${zephyr_ext_cmds[*]}) diff --git a/scripts/west_commands/flash.py b/scripts/west_commands/flash.py index 4f173535be886..484c5b3c65fb5 100644 --- a/scripts/west_commands/flash.py +++ b/scripts/west_commands/flash.py @@ -9,7 +9,8 @@ from west.commands import WestCommand from run_common import add_parser_common, do_run_common, get_build_dir -from build_helpers import load_domains + +from pathlib import Path class Flash(WestCommand): @@ -28,6 +29,5 @@ def do_add_parser(self, parser_adder): def do_run(self, my_args, runner_args): build_dir = get_build_dir(my_args) - domains = load_domains(build_dir).get_domains(my_args.domain, - default_flash_order=True) - do_run_common(self, my_args, runner_args, domains=domains) + domains_file = Path(build_dir) / 'domains.yaml' + do_run_common(self, my_args, runner_args, domain_file=domains_file) diff --git a/scripts/west_commands/robot.py b/scripts/west_commands/robot.py new file mode 100644 index 0000000000000..fb5325afe9423 --- /dev/null +++ b/scripts/west_commands/robot.py @@ -0,0 +1,29 @@ +# Copyright (c) 2024 Antmicro +# +# SPDX-License-Identifier: Apache-2.0 + +from west.commands import WestCommand +from run_common import add_parser_common, do_run_common + +EXPORT_DESCRIPTION = '''\ +Run RobotFramework test suites with a runner of choice. +''' + + +class Robot(WestCommand): + + def __init__(self): + super(Robot, self).__init__( + 'robot', + # Keep this in sync with the string in west-commands.yml. + 'run RobotFramework test suites', + EXPORT_DESCRIPTION, + accepts_unknown_args=True) + + self.runner_key = 'robot-runner' # in runners.yaml + + def do_add_parser(self, parser_adder): + return add_parser_common(self, parser_adder) + + def do_run(self, my_args, runner_args): + do_run_common(self, my_args, runner_args) diff --git a/scripts/west_commands/run_common.py b/scripts/west_commands/run_common.py index 8656d0907679b..fd8a85749ea37 100644 --- a/scripts/west_commands/run_common.py +++ b/scripts/west_commands/run_common.py @@ -161,7 +161,7 @@ def add_parser_common(command, parser_adder=None, parser=None): return parser -def do_run_common(command, user_args, user_runner_args, domains=None): +def do_run_common(command, user_args, user_runner_args, domain_file=None): # This is the main routine for all the "west flash", "west debug", # etc. commands. @@ -186,7 +186,7 @@ def do_run_common(command, user_args, user_runner_args, domains=None): if not user_args.skip_rebuild: rebuild(command, build_dir, user_args) - if domains is None: + if domain_file is None: if user_args.domain is None: # No domains are passed down and no domains specified by the user. # So default domain will be used. @@ -195,6 +195,9 @@ def do_run_common(command, user_args, user_runner_args, domains=None): # No domains are passed down, but user has specified domains to use. # Get the user specified domains. domains = load_domains(build_dir).get_domains(user_args.domain) + else: + domains = load_domains(build_dir).get_domains(user_args.domain, + default_flash_order=True) if len(domains) > 1: if len(user_runner_args) > 0: @@ -512,7 +515,7 @@ def runners_yaml_path(build_dir, board): ret = Path(build_dir) / 'zephyr' / 'runners.yaml' if not ret.is_file(): log.die(f'either a pristine build is needed, or board {board} ' - "doesn't support west flash/debug " + "doesn't support west flash/debug/simulate " '(no ZEPHYR_RUNNERS_YAML in CMake cache)') return ret diff --git a/scripts/west_commands/runners/__init__.py b/scripts/west_commands/runners/__init__.py index aa5686f73b067..0f08aa366599b 100644 --- a/scripts/west_commands/runners/__init__.py +++ b/scripts/west_commands/runners/__init__.py @@ -48,6 +48,8 @@ def _import_runner_module(runner_name): 'nxp_s32dbg', 'openocd', 'pyocd', + 'renode', + 'renode-robot', 'qemu', 'silabs_commander', 'spi_burn', diff --git a/scripts/west_commands/runners/core.py b/scripts/west_commands/runners/core.py index 21a60edc1a06f..10e740a4230f8 100644 --- a/scripts/west_commands/runners/core.py +++ b/scripts/west_commands/runners/core.py @@ -130,6 +130,8 @@ class BuildConfiguration: Kconfig configuration values are available (parsed from .config).''' + config_prefix = 'CONFIG' + def __init__(self, build_dir: str): self.build_dir = build_dir self.options: Dict[str, Union[str, int]] = {} @@ -153,8 +155,9 @@ def getboolean(self, option): def _parse(self): filename = self.path - opt_value = re.compile('^(?P