diff --git a/CODEOWNERS b/CODEOWNERS index 9225e294f1951..8e4054f5e3d9f 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -45,6 +45,7 @@ /soc/arm/nuvoton_npcx/ @MulinChao @WealianLiao @ChiHuaL /soc/arm/nuvoton_numicro/ @ssekar15 /soc/arm/quicklogic_eos_s3/ @kowalewskijan @kgugala +/soc/arm/rpi_pico/ @yonsch /soc/arm/silabs_exx32/efm32pg1b/ @rdmeneze /soc/arm/silabs_exx32/efr32mg21/ @l-alfred /soc/arm/st_stm32/ @erwango @@ -127,6 +128,7 @@ /boards/arm/quick_feather/ @kowalewskijan @kgugala /boards/arm/rak4631_nrf52840/ @gpaquet85 /boards/arm/rak5010_nrf52840/ @gpaquet85 +/boards/arm/rpi_pico/ @yonsch /boards/arm/ronoth_lodev/ @NorthernDean /boards/arm/xmc45_relax_kit/ @parthitce /boards/arm/sam4e_xpro/ @nandojve @@ -262,6 +264,7 @@ /drivers/gpio/*eos_s3* @wtatarski @kowalewskijan @kgugala /drivers/gpio/*rcar* @julien-massot /drivers/gpio/*esp32* @glaubermaroto +/drivers/gpio/*rpi_pico* @yonsch /drivers/hwinfo/ @alexanderwachter /drivers/i2c/i2c_common.c @sjg20 /drivers/i2c/i2c_emul.c @sjg20 @@ -349,6 +352,7 @@ /drivers/serial/uart_mcux_iuart.c @Mani-Sadhasivam /drivers/serial/Kconfig.rtt @carlescufi @pkral78 /drivers/serial/uart_rtt.c @carlescufi @pkral78 +/drivers/serial/*rpi_pico* @yonsch /drivers/serial/Kconfig.xlnx @wjliang /drivers/serial/uart_xlnx_ps.c @wjliang /drivers/serial/uart_xlnx_uartlite.c @henrikbrixandersen @@ -443,6 +447,7 @@ /dts/arm/nuvoton/ @ssekar15 @MulinChao @WealianLiao @ChiHuaL /dts/arm/nxp/ @mmahadevan108 @dleach02 /dts/arm/microchip/ @franciscomunoz @albertofloyd @sjvasanth1 +/dts/arm/rpi_pico/ @yonsch /dts/arm/silabs/efm32_pg_1b.dtsi @rdmeneze /dts/arm/silabs/efm32gg11b* @oanerer /dts/arm/silabs/efm32_jg_pg* @chrta @@ -484,6 +489,7 @@ /dts/bindings/*/nordic* @anangl /dts/bindings/*/nxp* @mmahadevan108 @dleach02 /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 diff --git a/boards/arm/rpi_pico/Kconfig.board b/boards/arm/rpi_pico/Kconfig.board new file mode 100644 index 0000000000000..ac9d9661bbfe4 --- /dev/null +++ b/boards/arm/rpi_pico/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_RPI_PICO + bool "Raspberry Pi Pico Board" + depends on SOC_RP2040 diff --git a/boards/arm/rpi_pico/Kconfig.defconfig b/boards/arm/rpi_pico/Kconfig.defconfig new file mode 100644 index 0000000000000..859efc0fdd30c --- /dev/null +++ b/boards/arm/rpi_pico/Kconfig.defconfig @@ -0,0 +1,12 @@ +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_RPI_PICO + +config BOARD + default "rpi_pico" + +config RP2_FLASH_W25Q080 + default y + +endif # BOARD_RPI_PICO diff --git a/boards/arm/rpi_pico/board.cmake b/boards/arm/rpi_pico/board.cmake new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/boards/arm/rpi_pico/doc/img/rpi_pico.png b/boards/arm/rpi_pico/doc/img/rpi_pico.png new file mode 100644 index 0000000000000..0b223bb334bd9 Binary files /dev/null and b/boards/arm/rpi_pico/doc/img/rpi_pico.png differ diff --git a/boards/arm/rpi_pico/doc/index.rst b/boards/arm/rpi_pico/doc/index.rst new file mode 100644 index 0000000000000..ef0d7cfd8b89d --- /dev/null +++ b/boards/arm/rpi_pico/doc/index.rst @@ -0,0 +1,59 @@ +.. _rpi_pico: + +Raspberry Pi Pico +################# + +Overview +******** + +The Raspberry Pi Pico is a small, low-cost, versatile board from +Raspberry Pi. It is equipped with an RP2040 SoC, an on-board LED, +a USB connector, and an SWD interface. The USB bootloader allows it +to be flashed without any adapter, in a drag-and-drop manner. +It is also possible to flash and debug the Pico with its SWD interface, +using an external adapter. + +Hardware +******** +- Dual core Arm Cortex-M0+ processor running up to 133MHz +- 264KB on-chip SRAM +- 2MB on-board QSPI flash with XIP capabilities +- 26 GPIO pins +- 3 Analog inputs +- 2 UART peripherals +- 2 SPI controllers +- 2 I2C controllers +- 16 PWM channels +- USB 1.1 controller (host/device) +- 8 Programmable I/O (PIO) for custom peripherals +- On-board LED + + +.. figure:: img/rpi_pico.png + :width: 150px + :align: center + :alt: Raspberry Pi Pico + + Raspberry Pi Pico (Image courtesy of Raspberry Pi) + +Supported Features +================== + +The rpi_pico board configuration supports the following +hardware features: + +.. list-table:: + :header-rows: 1 + + * - Peripheral + - Kconfig option + - Devicetree compatible + * - NVIC + - N/A + - :dtcompatible:`arm,v6m-nvic` + * - UART + - :kconfig:`CONFIG_SERIAL` + - :dtcompatible:`rpi,pico-uart` + * - GPIO + - :kconfig:`CONFIG_GPIO` + - :dtcompatible:`rpi,pico-gpio` diff --git a/boards/arm/rpi_pico/rpi_pico-pinctrl.dtsi b/boards/arm/rpi_pico/rpi_pico-pinctrl.dtsi new file mode 100644 index 0000000000000..f20558729c4bd --- /dev/null +++ b/boards/arm/rpi_pico/rpi_pico-pinctrl.dtsi @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, Yonatan Schachter + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +&pinctrl { + uart0_default: uart0_default { + group1 { + pinmux = ; + }; + group2 { + pinmux = ; + input-enable; + }; + }; +}; diff --git a/boards/arm/rpi_pico/rpi_pico.dts b/boards/arm/rpi_pico/rpi_pico.dts new file mode 100644 index 0000000000000..050df862a1209 --- /dev/null +++ b/boards/arm/rpi_pico/rpi_pico.dts @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; + +#include +#include "rpi_pico-pinctrl.dtsi" + +/ { + chosen { + zephyr,sram = &sram0; + zephyr,flash = &flash0; + zephyr,console = &uart0; + zephyr,code-partition = &code_partition; + }; + + leds { + compatible = "gpio-leds"; + led0: led_0 { + gpios = <&gpio0 25 GPIO_ACTIVE_LOW>; + label = "LED"; + }; + }; + + aliases { + led0 = &led0; + }; +}; + +&flash0 { + reg = <0x10000000 DT_SIZE_M(2)>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + /* Reserved memory for the second stage bootloader */ + settings: partition@0 { + label = "settings"; + reg = <0x00000000 0x100>; + read-only; + }; + + /* + * Usable flash. Starts at 0x100, after the bootloader. The partition + * size is 2MB minus the 0x100 bytes taken by the bootloader. + */ + code_partition: partition@100 { + label = "code-partition"; + reg = <0x100 (DT_SIZE_M(2) - 0x100)>; + read-only; + }; + }; +}; + +&uart0 { + current-speed = <115200>; + status = "okay"; + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; +}; + +&gpio0 { + status = "okay"; +}; diff --git a/boards/arm/rpi_pico/rpi_pico.yaml b/boards/arm/rpi_pico/rpi_pico.yaml new file mode 100644 index 0000000000000..0541db609e984 --- /dev/null +++ b/boards/arm/rpi_pico/rpi_pico.yaml @@ -0,0 +1,10 @@ +identifier: rpi_pico +name: RaspberryPi-Pico +type: mcu +arch: arm +flash: 2048 +ram: 264 +toolchain: + - zephyr + - gnuarmemb + - xtools diff --git a/boards/arm/rpi_pico/rpi_pico_defconfig b/boards/arm/rpi_pico/rpi_pico_defconfig new file mode 100644 index 0000000000000..f6f18d9821418 --- /dev/null +++ b/boards/arm/rpi_pico/rpi_pico_defconfig @@ -0,0 +1,8 @@ +CONFIG_SOC_SERIES_RP2XXX=y +CONFIG_SOC_RP2040=y +CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC=125000000 +CONFIG_SERIAL=y +CONFIG_CONSOLE=y +CONFIG_UART_CONSOLE=y +CONFIG_GPIO=y +CONFIG_USE_DT_CODE_PARTITION=y diff --git a/cmake/app/boilerplate.cmake b/cmake/app/boilerplate.cmake index 6102d739c9f51..72aba79600a4b 100644 --- a/cmake/app/boilerplate.cmake +++ b/cmake/app/boilerplate.cmake @@ -1,12 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 -# This file must be included into the toplevel CMakeLists.txt file of -# Zephyr applications. -# Zephyr CMake package automatically includes this file when CMake function -# find_package() is used. -# -# To ensure this file is loaded in a Zephyr application it must start with -# one of those lines: +###################################### +# The use of this file is deprecated # +###################################### + +# To build a Zephyr application it must start with one of those lines: # # find_package(Zephyr) # find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) @@ -14,693 +12,9 @@ # The `REQUIRED HINTS $ENV{ZEPHYR_BASE}` variant is required for any application # inside the Zephyr repository. # -# It exists to reduce boilerplate code that Zephyr expects to be in -# application CMakeLists.txt code. - -# CMake version 3.20 is the real minimum supported version. -# -# Unfortunately CMake requires the toplevel CMakeLists.txt file to -# define the required version, not even invoking it from an included -# file, like boilerplate.cmake, is sufficient. It is however permitted -# to have multiple invocations of cmake_minimum_required. -# -# Under these restraints we use a second 'cmake_minimum_required' -# invocation in every toplevel CMakeLists.txt. -cmake_minimum_required(VERSION 3.20.0) - -define_property(GLOBAL PROPERTY ZEPHYR_LIBS - BRIEF_DOCS "Global list of all Zephyr CMake libs that should be linked in" - FULL_DOCS "Global list of all Zephyr CMake libs that should be linked in. -zephyr_library() appends libs to this list.") -set_property(GLOBAL PROPERTY ZEPHYR_LIBS "") - -define_property(GLOBAL PROPERTY ZEPHYR_INTERFACE_LIBS - BRIEF_DOCS "Global list of all Zephyr interface libs that should be linked in." - FULL_DOCS "Global list of all Zephyr interface libs that should be linked in. -zephyr_interface_library_named() appends libs to this list.") -set_property(GLOBAL PROPERTY ZEPHYR_INTERFACE_LIBS "") - -define_property(GLOBAL PROPERTY GENERATED_APP_SOURCE_FILES - BRIEF_DOCS "Source files that are generated after Zephyr has been linked once." - FULL_DOCS "\ -Source files that are generated after Zephyr has been linked once.\ -May include dev_handles.c etc." - ) -set_property(GLOBAL PROPERTY GENERATED_APP_SOURCE_FILES "") - -define_property(GLOBAL PROPERTY GENERATED_KERNEL_OBJECT_FILES - BRIEF_DOCS "Object files that are generated after symbol addresses are fixed." - FULL_DOCS "\ -Object files that are generated after symbol addresses are fixed.\ -May include mmu tables, etc." - ) -set_property(GLOBAL PROPERTY GENERATED_KERNEL_OBJECT_FILES "") - -define_property(GLOBAL PROPERTY GENERATED_KERNEL_SOURCE_FILES - BRIEF_DOCS "Source files that are generated after symbol addresses are fixed." - FULL_DOCS "\ -Source files that are generated after symbol addresses are fixed.\ -May include isr_tables.c etc." - ) -set_property(GLOBAL PROPERTY GENERATED_KERNEL_SOURCE_FILES "") - -set(APPLICATION_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "Application Source Directory") -set(APPLICATION_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH "Application Binary Directory") - -set(__build_dir ${CMAKE_CURRENT_BINARY_DIR}/zephyr) - -set(PROJECT_BINARY_DIR ${__build_dir}) - -message(STATUS "Application: ${APPLICATION_SOURCE_DIR}") - -add_custom_target(code_data_relocation_target) - -# The zephyr/runners.yaml file in the build directory is used to -# configure the scripts/west_commands/runners Python package used -# by 'west flash', 'west debug', etc. -# -# This is a helper target for setting property:value pairs related to -# this file: -# -# Property Description -# -------------- -------------------------------------------------- -# bin_file "zephyr.bin" file for flashing -# hex_file "zephyr.hex" file for flashing -# elf_file "zephyr.elf" file for flashing or debugging -# yaml_contents generated contents of runners.yaml -# -# Note: there are quotes around "zephyr.bin" etc. because the actual -# paths can be changed, e.g. to flash signed versions of these files -# for consumption by bootloaders such as MCUboot. -# -# See cmake/flash/CMakeLists.txt for more details. -add_custom_target(runners_yaml_props_target) - -# CMake's 'project' concept has proven to not be very useful for Zephyr -# due in part to how Zephyr is organized and in part to it not fitting well -# with cross compilation. -# Zephyr therefore tries to rely as little as possible on project() -# and its associated variables, e.g. PROJECT_SOURCE_DIR. -# It is recommended to always use ZEPHYR_BASE instead of PROJECT_SOURCE_DIR -# when trying to reference ENV${ZEPHYR_BASE}. - -set(ENV_ZEPHYR_BASE $ENV{ZEPHYR_BASE}) -# This add support for old style boilerplate include. -if((NOT DEFINED ZEPHYR_BASE) AND (DEFINED ENV_ZEPHYR_BASE)) - set(ZEPHYR_BASE ${ENV_ZEPHYR_BASE} CACHE PATH "Zephyr base") -endif() - -find_package(ZephyrBuildConfiguration - QUIET NO_POLICY_SCOPE - NAMES ZephyrBuild - PATHS ${ZEPHYR_BASE}/../* - NO_CMAKE_PATH - NO_CMAKE_ENVIRONMENT_PATH - NO_SYSTEM_ENVIRONMENT_PATH - NO_CMAKE_PACKAGE_REGISTRY - NO_CMAKE_SYSTEM_PATH - NO_CMAKE_SYSTEM_PACKAGE_REGISTRY +# Loading of this file directly is deprecated and only kept for backward compatibility. +message(WARNING "Loading of Zephyr boilerplate.cmake directly is deprecated, " + "please use 'find_package(Zephyr)'" ) -# Note any later project() resets PROJECT_SOURCE_DIR -file(TO_CMAKE_PATH "${ZEPHYR_BASE}" PROJECT_SOURCE_DIR) - -set(ZEPHYR_BINARY_DIR ${PROJECT_BINARY_DIR}) - -set(AUTOCONF_H ${__build_dir}/include/generated/autoconf.h) -# Re-configure (Re-execute all CMakeLists.txt code) when autoconf.h changes -set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${AUTOCONF_H}) - - -# -# Import more CMake functions and macros -# - -include(CheckCCompilerFlag) -include(CheckCXXCompilerFlag) -include(${ZEPHYR_BASE}/cmake/extensions.cmake) -include(${ZEPHYR_BASE}/cmake/git.cmake) -include(${ZEPHYR_BASE}/cmake/version.cmake) # depends on hex.cmake - -# -# Find tools -# - -include(${ZEPHYR_BASE}/cmake/python.cmake) -include(${ZEPHYR_BASE}/cmake/west.cmake) -include(${ZEPHYR_BASE}/cmake/ccache.cmake) - -if(ZEPHYR_EXTRA_MODULES) - # ZEPHYR_EXTRA_MODULES has either been specified on the cmake CLI or is - # already in the CMakeCache.txt. This has precedence over the environment - # variable ZEPHYR_EXTRA_MODULES -elseif(DEFINED ENV{ZEPHYR_EXTRA_MODULES}) - set(ZEPHYR_EXTRA_MODULES $ENV{ZEPHYR_EXTRA_MODULES}) -endif() - -# 'MODULE_EXT_ROOT' is a prioritized list of directories where module glue code -# may be found. It always includes ${ZEPHYR_BASE} at the lowest priority. -# For module roots, later entries may overrule module settings already defined -# by processed module roots, hence first in list means lowest priority. -zephyr_file(APPLICATION_ROOT MODULE_EXT_ROOT) -list(INSERT MODULE_EXT_ROOT 0 ${ZEPHYR_BASE}) - -# -# Find Zephyr modules. -# Those may contain additional DTS, BOARD, SOC, ARCH ROOTs. -# Also create the Kconfig binary dir for generated Kconf files. -# -set(KCONFIG_BINARY_DIR ${CMAKE_BINARY_DIR}/Kconfig) -file(MAKE_DIRECTORY ${KCONFIG_BINARY_DIR}) -include(${ZEPHYR_BASE}/cmake/zephyr_module.cmake) - -if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) - message(FATAL_ERROR "Source directory equals build directory.\ - In-source builds are not supported.\ - Please specify a build directory, e.g. cmake -Bbuild -H.") -endif() - -add_custom_target( - pristine - COMMAND ${CMAKE_COMMAND} -DBINARY_DIR=${APPLICATION_BINARY_DIR} - -DSOURCE_DIR=${APPLICATION_SOURCE_DIR} - -P ${ZEPHYR_BASE}/cmake/pristine.cmake - # Equivalent to rm -rf build/* - ) - -# Dummy add to generate files. -zephyr_linker_sources(SECTIONS) - -# 'BOARD_ROOT' is a prioritized list of directories where boards may -# be found. It always includes ${ZEPHYR_BASE} at the lowest priority. -zephyr_file(APPLICATION_ROOT BOARD_ROOT) -list(APPEND BOARD_ROOT ${ZEPHYR_BASE}) - -# 'SOC_ROOT' is a prioritized list of directories where socs may be -# found. It always includes ${ZEPHYR_BASE}/soc at the lowest priority. -zephyr_file(APPLICATION_ROOT SOC_ROOT) -list(APPEND SOC_ROOT ${ZEPHYR_BASE}) - -# 'ARCH_ROOT' is a prioritized list of directories where archs may be -# found. It always includes ${ZEPHYR_BASE} at the lowest priority. -zephyr_file(APPLICATION_ROOT ARCH_ROOT) -list(APPEND ARCH_ROOT ${ZEPHYR_BASE}) - -# Check that BOARD has been provided, and that it has not changed. -zephyr_check_cache(BOARD REQUIRED) - -string(FIND "${BOARD}" "@" REVISION_SEPARATOR_INDEX) -if(NOT (REVISION_SEPARATOR_INDEX EQUAL -1)) - math(EXPR BOARD_REVISION_INDEX "${REVISION_SEPARATOR_INDEX} + 1") - string(SUBSTRING ${BOARD} ${BOARD_REVISION_INDEX} -1 BOARD_REVISION) - string(SUBSTRING ${BOARD} 0 ${REVISION_SEPARATOR_INDEX} BOARD) -endif() - -set(BOARD_MESSAGE "Board: ${BOARD}") - -if(DEFINED ENV{ZEPHYR_BOARD_ALIASES}) - include($ENV{ZEPHYR_BOARD_ALIASES}) - if(${BOARD}_BOARD_ALIAS) - set(BOARD_ALIAS ${BOARD} CACHE STRING "Board alias, provided by user") - set(BOARD ${${BOARD}_BOARD_ALIAS}) - message(STATUS "Aliased BOARD=${BOARD_ALIAS} changed to ${BOARD}") - endif() -endif() -include(${ZEPHYR_BASE}/boards/deprecated.cmake) -if(${BOARD}_DEPRECATED) - set(BOARD_DEPRECATED ${BOARD} CACHE STRING "Deprecated board name, provided by user") - set(BOARD ${${BOARD}_DEPRECATED}) - message(WARNING "Deprecated BOARD=${BOARD_DEPRECATED} name specified, board automatically changed to: ${BOARD}.") -endif() - -zephyr_boilerplate_watch(BOARD) - -foreach(root ${BOARD_ROOT}) - # Check that the board root looks reasonable. - if(NOT IS_DIRECTORY "${root}/boards") - 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 in doubt, use absolute paths") - endif() - - # NB: find_path will return immediately if the output variable is - # already set - if (BOARD_ALIAS) - find_path(BOARD_HIDDEN_DIR - NAMES ${BOARD_ALIAS}_defconfig - PATHS ${root}/boards/*/* - NO_DEFAULT_PATH - ) - if(BOARD_HIDDEN_DIR) - message("Board alias ${BOARD_ALIAS} is hiding the real board of same name") - endif() - endif() - find_path(BOARD_DIR - NAMES ${BOARD}_defconfig - PATHS ${root}/boards/*/* - NO_DEFAULT_PATH - ) - if(BOARD_DIR AND NOT (${root} STREQUAL ${ZEPHYR_BASE})) - set(USING_OUT_OF_TREE_BOARD 1) - endif() -endforeach() - -if(EXISTS ${BOARD_DIR}/revision.cmake) - # Board provides revision handling. - include(${BOARD_DIR}/revision.cmake) -elseif(BOARD_REVISION) - message(WARNING "Board revision ${BOARD_REVISION} specified for ${BOARD}, \ - but board has no revision so revision will be ignored.") -endif() - -if(DEFINED BOARD_REVISION) - set(BOARD_MESSAGE "${BOARD_MESSAGE}, Revision: ${BOARD_REVISION}") - if(DEFINED ACTIVE_BOARD_REVISION) - set(BOARD_MESSAGE "${BOARD_MESSAGE} (Active: ${ACTIVE_BOARD_REVISION})") - set(BOARD_REVISION ${ACTIVE_BOARD_REVISION}) - endif() - - string(REPLACE "." "_" BOARD_REVISION_STRING ${BOARD_REVISION}) -endif() - -# Check that SHIELD has not changed. -zephyr_check_cache(SHIELD WATCH) - -if(SHIELD) - set(BOARD_MESSAGE "${BOARD_MESSAGE}, Shield(s): ${SHIELD}") -endif() - -message(STATUS "${BOARD_MESSAGE}") - -if(DEFINED SHIELD) - string(REPLACE " " ";" SHIELD_AS_LIST "${SHIELD}") -endif() -# SHIELD-NOTFOUND is a real CMake list, from which valid shields can be popped. -# After processing all shields, only invalid shields will be left in this list. -set(SHIELD-NOTFOUND ${SHIELD_AS_LIST}) - -# Use BOARD to search for a '_defconfig' file. -# e.g. zephyr/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51_defconfig. -# When found, use that path to infer the ARCH we are building for. -foreach(root ${BOARD_ROOT}) - set(shield_dir ${root}/boards/shields) - # Match the Kconfig.shield files in the shield directories to make sure we are - # finding shields, e.g. x_nucleo_iks01a1/Kconfig.shield - file(GLOB_RECURSE shields_refs_list ${shield_dir}/*/Kconfig.shield) - - # The above gives a list like - # x_nucleo_iks01a1/Kconfig.shield;x_nucleo_iks01a2/Kconfig.shield - # we construct a list of shield names by extracting the folder and find - # and overlay files in there. Each overlay corresponds to a shield. - # We obtain the shield name by removing the overlay extension. - unset(SHIELD_LIST) - foreach(shields_refs ${shields_refs_list}) - get_filename_component(shield_path ${shields_refs} DIRECTORY) - file(GLOB shield_overlays RELATIVE ${shield_path} ${shield_path}/*.overlay) - foreach(overlay ${shield_overlays}) - get_filename_component(shield ${overlay} NAME_WE) - list(APPEND SHIELD_LIST ${shield}) - set(SHIELD_DIR_${shield} ${shield_path}) - endforeach() - endforeach() - - if(DEFINED SHIELD) - foreach(s ${SHIELD_AS_LIST}) - if(NOT ${s} IN_LIST SHIELD_LIST) - continue() - endif() - - list(REMOVE_ITEM SHIELD-NOTFOUND ${s}) - - # if shield config flag is on, add shield overlay to the shield overlays - # list and dts_fixup file to the shield fixup file - list(APPEND - shield_dts_files - ${SHIELD_DIR_${s}}/${s}.overlay - ) - - list(APPEND - shield_dts_fixups - ${SHIELD_DIR_${s}}/dts_fixup.h - ) - - list(APPEND - SHIELD_DIRS - ${SHIELD_DIR_${s}} - ) - - # search for shield/shield.conf file - if(EXISTS ${SHIELD_DIR_${s}}/${s}.conf) - # add shield.conf to the shield config list - list(APPEND - shield_conf_files - ${SHIELD_DIR_${s}}/${s}.conf - ) - endif() - - zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards - DTS shield_dts_files - KCONF shield_conf_files - ) - zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards/${s} - DTS shield_dts_files - KCONF shield_conf_files - ) - endforeach() - endif() -endforeach() - -if(NOT BOARD_DIR) - message("No board named '${BOARD}' found. - -Please choose one of the following boards: -") - execute_process( - COMMAND - ${CMAKE_COMMAND} - -DZEPHYR_BASE=${ZEPHYR_BASE} - -DBOARD_ROOT=${BOARD_ROOT} - -DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM} - -P ${ZEPHYR_BASE}/cmake/boards.cmake - ) - unset(CACHED_BOARD CACHE) - message(FATAL_ERROR "Invalid BOARD; see above.") -endif() - -if(DEFINED SHIELD AND NOT (SHIELD-NOTFOUND STREQUAL "")) - foreach (s ${SHIELD-NOTFOUND}) - message("No shield named '${s}' found") - endforeach() - message("Please choose from among the following shields:") - string(REPLACE ";" "\\;" SHIELD_LIST_ESCAPED "${SHIELD_LIST}") - execute_process( - COMMAND - ${CMAKE_COMMAND} - -DZEPHYR_BASE=${ZEPHYR_BASE} - -DSHIELD_LIST=${SHIELD_LIST_ESCAPED} - -P ${ZEPHYR_BASE}/cmake/shields.cmake - ) - unset(CACHED_SHIELD CACHE) - message(FATAL_ERROR "Invalid SHIELD; see above.") -endif() - -get_filename_component(BOARD_ARCH_DIR ${BOARD_DIR} DIRECTORY) -get_filename_component(ARCH ${BOARD_ARCH_DIR} NAME) - -foreach(root ${ARCH_ROOT}) - if(EXISTS ${root}/arch/${ARCH}/CMakeLists.txt) - set(ARCH_DIR ${root}/arch) - break() - endif() -endforeach() - -if(NOT ARCH_DIR) - message(FATAL_ERROR "Could not find ARCH=${ARCH} for BOARD=${BOARD}, \ -please check your installation. ARCH roots searched: \n\ -${ARCH_ROOT}") -endif() - -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() - -if(DEFINED CONF_FILE) - # This ensures that CACHE{CONF_FILE} will be set correctly to current scope - # variable CONF_FILE. An already current scope variable will stay the same. - set(CONF_FILE ${CONF_FILE}) - - # CONF_FILE has either been specified on the cmake CLI or is already - # in the CMakeCache.txt. This has precedence over the environment - # variable CONF_FILE and the default prj.conf - - # In order to support a `prj_.conf pattern for auto inclusion of board - # overlays, then we must first ensure only a single conf file is provided. - string(REPLACE " " ";" CONF_FILE_AS_LIST "${CONF_FILE}") - list(LENGTH CONF_FILE_AS_LIST CONF_FILE_LENGTH) - if(${CONF_FILE_LENGTH} EQUAL 1) - # Need the file name to look for match. - # Need path in order to check if it is absolute. - get_filename_component(CONF_FILE_NAME ${CONF_FILE} NAME) - if(${CONF_FILE_NAME} MATCHES "prj_(.*).conf") - set(CONF_FILE_BUILD_TYPE ${CMAKE_MATCH_1}) - set(CONF_FILE_INCLUDE_FRAGMENTS true) - endif() - endif() -elseif(CACHED_CONF_FILE) - # Cached conf file is present. - # That value has precedence over anything else than a new - # `cmake -DCONF_FILE=` invocation. - set(CONF_FILE ${CACHED_CONF_FILE}) -elseif(DEFINED ENV{CONF_FILE}) - set(CONF_FILE $ENV{CONF_FILE}) - -elseif(EXISTS ${APPLICATION_CONFIG_DIR}/prj_${BOARD}.conf) - set(CONF_FILE ${APPLICATION_CONFIG_DIR}/prj_${BOARD}.conf) - -elseif(EXISTS ${APPLICATION_CONFIG_DIR}/prj.conf) - set(CONF_FILE ${APPLICATION_CONFIG_DIR}/prj.conf) - set(CONF_FILE_INCLUDE_FRAGMENTS true) -endif() - -if(CONF_FILE_INCLUDE_FRAGMENTS) - zephyr_file(CONF_FILES ${APPLICATION_CONFIG_DIR}/boards KCONF CONF_FILE BUILD ${CONF_FILE_BUILD_TYPE}) -endif() - -set(APPLICATION_CONFIG_DIR ${APPLICATION_CONFIG_DIR} CACHE INTERNAL "The application configuration folder") -set(CACHED_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.\ -Multiple files may be listed, e.g. CONF_FILE=\"prj1.confi;prj2.conf\" \ -The CACHED_CONF_FILE is internal Zephyr variable used between CMake runs. \ -To change CONF_FILE, use the CONF_FILE variable.") -unset(CONF_FILE CACHE) - -zephyr_file(CONF_FILES ${APPLICATION_CONFIG_DIR}/boards DTS APP_BOARD_DTS) - -# The CONF_FILE variable is now set to its final value. -zephyr_boilerplate_watch(CONF_FILE) - -if(DTC_OVERLAY_FILE) - # DTC_OVERLAY_FILE has either been specified on the cmake CLI or is already - # in the CMakeCache.txt. -elseif(APP_BOARD_DTS) - set(DTC_OVERLAY_FILE ${APP_BOARD_DTS}) -elseif(EXISTS ${APPLICATION_CONFIG_DIR}/${BOARD}.overlay) - set(DTC_OVERLAY_FILE ${APPLICATION_CONFIG_DIR}/${BOARD}.overlay) -elseif(EXISTS ${APPLICATION_CONFIG_DIR}/app.overlay) - set(DTC_OVERLAY_FILE ${APPLICATION_CONFIG_DIR}/app.overlay) -endif() - -set(DTC_OVERLAY_FILE ${DTC_OVERLAY_FILE} CACHE STRING "If desired, you can \ -build the application using the DT configuration settings specified in an \ -alternate .overlay file using this parameter. These settings will override the \ -settings in the board's .dts file. Multiple files may be listed, e.g. \ -DTC_OVERLAY_FILE=\"dts1.overlay dts2.overlay\"") - -# Populate USER_CACHE_DIR with a directory that user applications may -# write cache files to. -if(NOT DEFINED USER_CACHE_DIR) - find_appropriate_cache_directory(USER_CACHE_DIR) -endif() -message(STATUS "Cache files will be written to: ${USER_CACHE_DIR}") - -# Prevent CMake from testing the toolchain -set(CMAKE_C_COMPILER_FORCED 1) -set(CMAKE_CXX_COMPILER_FORCED 1) - -include(${ZEPHYR_BASE}/cmake/verify-toolchain.cmake) -include(${ZEPHYR_BASE}/cmake/host-tools.cmake) - -# Include board specific device-tree flags before parsing. -include(${BOARD_DIR}/pre_dt_board.cmake OPTIONAL) - -# The DTC_OVERLAY_FILE variable is now set to its final value. -zephyr_boilerplate_watch(DTC_OVERLAY_FILE) - -# DTS should be close to kconfig because CONFIG_ variables from -# kconfig and dts should be available at the same time. -# -# The DT system uses a C preprocessor for it's code generation needs. -# This creates an awkward chicken-and-egg problem, because we don't -# always know exactly which toolchain the user needs until we know -# more about the target, e.g. after DT and Kconfig. -# -# To resolve this we find "some" C toolchain, configure it generically -# with the minimal amount of configuration needed to have it -# preprocess DT sources, and then, after we have finished processing -# both DT and Kconfig we complete the target-specific configuration, -# and possibly change the toolchain. -include(${ZEPHYR_BASE}/cmake/generic_toolchain.cmake) -include(${ZEPHYR_BASE}/cmake/dts.cmake) -include(${ZEPHYR_BASE}/cmake/kconfig.cmake) - -set(SOC_NAME ${CONFIG_SOC}) -set(SOC_SERIES ${CONFIG_SOC_SERIES}) -set(SOC_TOOLCHAIN_NAME ${CONFIG_SOC_TOOLCHAIN_NAME}) -set(SOC_FAMILY ${CONFIG_SOC_FAMILY}) - -# For the gen_app_partitions.py to work correctly, we must ensure that -# all targets exports their compile commands to fetch object files. -# We enable it unconditionally, as this is also useful for several IDEs -set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE CACHE BOOL - "Export CMake compile commands. Used by gen_app_partitions.py script" - FORCE -) - -if("${SOC_SERIES}" STREQUAL "") - set(SOC_PATH ${SOC_NAME}) -else() - set(SOC_PATH ${SOC_FAMILY}/${SOC_SERIES}) -endif() - -# Use SOC to search for a 'CMakeLists.txt' file. -# e.g. zephyr/soc/xtense/intel_apl_adsp/CMakeLists.txt. -foreach(root ${SOC_ROOT}) - # Check that the root looks reasonable. - if(NOT IS_DIRECTORY "${root}/soc") - message(WARNING "SOC_ROOT element without a 'soc' subdirectory: -${root} -Hints: - - if your SoC family directory is '/foo/bar/soc//my_soc_family', then add '/foo/bar' to SOC_ROOT, not the entire SoC family path - - if in doubt, use absolute paths") - endif() - - if(EXISTS ${root}/soc/${ARCH}/${SOC_PATH}) - set(SOC_DIR ${root}/soc) - break() - endif() -endforeach() - -if(NOT SOC_DIR) - message(FATAL_ERROR "Could not find SOC=${SOC_NAME} for BOARD=${BOARD}, \ -please check your installation. SOC roots searched: \n\ -${SOC_ROOT}") -endif() - -include(${ZEPHYR_BASE}/cmake/target_toolchain.cmake) - -project(Zephyr-Kernel VERSION ${PROJECT_VERSION}) - -# Add .S file extension suffix into CMAKE_ASM_SOURCE_FILE_EXTENSIONS, -# because clang from OneApi can't recongnize them as asm files on -# windows now. -list(APPEND CMAKE_ASM_SOURCE_FILE_EXTENSIONS "S") -enable_language(C CXX ASM) - -# The setup / configuration of the toolchain itself and the configuration of -# supported compilation flags are now split, as this allows to use the toolchain -# for generic purposes, for example DTS, and then test the toolchain for -# supported flags at stage two. -# Testing the toolchain flags requires the enable_language() to have been called in CMake. - -# Verify that the toolchain can compile a dummy file, if it is not we -# won't be able to test for compatibility with certain C flags. -zephyr_check_compiler_flag(C "" toolchain_is_ok) -assert(toolchain_is_ok "The toolchain is unable to build a dummy C file. See CMakeError.log.") - -include(${ZEPHYR_BASE}/cmake/target_toolchain_flags.cmake) - -# 'project' sets PROJECT_BINARY_DIR to ${CMAKE_CURRENT_BINARY_DIR}, -# but for legacy reasons we need it to be set to -# ${CMAKE_CURRENT_BINARY_DIR}/zephyr -set(PROJECT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/zephyr) -set(PROJECT_SOURCE_DIR ${ZEPHYR_BASE}) - -set(KERNEL_NAME ${CONFIG_KERNEL_BIN_NAME}) - -set(KERNEL_ELF_NAME ${KERNEL_NAME}.elf) -set(KERNEL_BIN_NAME ${KERNEL_NAME}.bin) -set(KERNEL_HEX_NAME ${KERNEL_NAME}.hex) -set(KERNEL_UF2_NAME ${KERNEL_NAME}.uf2) -set(KERNEL_MAP_NAME ${KERNEL_NAME}.map) -set(KERNEL_LST_NAME ${KERNEL_NAME}.lst) -set(KERNEL_S19_NAME ${KERNEL_NAME}.s19) -set(KERNEL_EXE_NAME ${KERNEL_NAME}.exe) -set(KERNEL_STAT_NAME ${KERNEL_NAME}.stat) -set(KERNEL_STRIP_NAME ${KERNEL_NAME}.strip) -set(KERNEL_META_NAME ${KERNEL_NAME}.meta) - -include(${BOARD_DIR}/board.cmake OPTIONAL) - -# If we are using a suitable ethernet driver inside qemu, then these options -# must be set, otherwise a zephyr instance cannot receive any network packets. -# The Qemu supported ethernet driver should define CONFIG_ETH_NIC_MODEL -# string that tells what nic model Qemu should use. -if(CONFIG_QEMU_TARGET) - if ((CONFIG_NET_QEMU_ETHERNET OR CONFIG_NET_QEMU_USER) AND NOT CONFIG_ETH_NIC_MODEL) - message(FATAL_ERROR " - No Qemu ethernet driver configured! - Enable Qemu supported ethernet driver like e1000 at drivers/ethernet" - ) - elseif(CONFIG_NET_QEMU_ETHERNET) - if(CONFIG_ETH_QEMU_EXTRA_ARGS) - set(NET_QEMU_ETH_EXTRA_ARGS ",${CONFIG_ETH_QEMU_EXTRA_ARGS}") - endif() - list(APPEND QEMU_FLAGS_${ARCH} - -nic tap,model=${CONFIG_ETH_NIC_MODEL},script=no,downscript=no,ifname=${CONFIG_ETH_QEMU_IFACE_NAME}${NET_QEMU_ETH_EXTRA_ARGS} - ) - elseif(CONFIG_NET_QEMU_USER) - list(APPEND QEMU_FLAGS_${ARCH} - -nic user,model=${CONFIG_ETH_NIC_MODEL},${CONFIG_NET_QEMU_USER_EXTRA_ARGS} - ) - else() - list(APPEND QEMU_FLAGS_${ARCH} - -net none - ) - endif() -endif() - -# General purpose Zephyr target. -# This target can be used for custom zephyr settings that needs to be used elsewhere in the build system -# -# Currently used properties: -# - COMPILES_OPTIONS: Used by application memory partition feature -add_custom_target(zephyr_property_target) - -# "app" is a CMake library containing all the application code and is -# modified by the entry point ${APPLICATION_SOURCE_DIR}/CMakeLists.txt -# that was specified when cmake was called. -zephyr_library_named(app) -set_property(TARGET app PROPERTY ARCHIVE_OUTPUT_DIRECTORY app) - -add_subdirectory(${ZEPHYR_BASE} ${__build_dir}) - -# Link 'app' with the Zephyr interface libraries. -# -# NB: This must be done in boilerplate.cmake because 'app' can only be -# modified in the CMakeLists.txt file that created it. And it must be -# done after 'add_subdirectory(${ZEPHYR_BASE} ${__build_dir})' -# because interface libraries are defined while processing that -# subdirectory. -get_property(ZEPHYR_INTERFACE_LIBS_PROPERTY GLOBAL PROPERTY ZEPHYR_INTERFACE_LIBS) -foreach(boilerplate_lib ${ZEPHYR_INTERFACE_LIBS_PROPERTY}) - # Linking 'app' with 'boilerplate_lib' causes 'app' to inherit the INTERFACE - # properties of 'boilerplate_lib'. The most common property is 'include - # directories', but it is also possible to have defines and compiler - # flags in the interface of a library. - # - string(TOUPPER ${boilerplate_lib} boilerplate_lib_upper_case) # Support lowercase lib names - target_link_libraries_ifdef( - CONFIG_APP_LINK_WITH_${boilerplate_lib_upper_case} - app - PUBLIC - ${boilerplate_lib} - ) -endforeach() - -if("${CMAKE_EXTRA_GENERATOR}" STREQUAL "Eclipse CDT4") - # Call the amendment function before .project and .cproject generation - # C and CXX includes, defines in .cproject without __cplusplus - # with project includes and defines - include(${ZEPHYR_BASE}/cmake/ide/eclipse_cdt4_generator_amendment.cmake) - eclipse_cdt4_generator_amendment(1) -endif() +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) diff --git a/cmake/boards.cmake b/cmake/boards.cmake deleted file mode 100644 index 16216c4f2a50a..0000000000000 --- a/cmake/boards.cmake +++ /dev/null @@ -1,40 +0,0 @@ -# SPDX-License-Identifier: Apache-2.0 - -set(arch_root_args) -foreach(root ${ARCH_ROOT}) - list(APPEND arch_root_args "--arch-root=${root}") -endforeach() - -set(board_root_args) -foreach(root ${BOARD_ROOT}) - list(APPEND board_root_args "--board-root=${root}") -endforeach() - -set(list_boards_commands - COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/list_boards.py - ${arch_root_args} ${board_root_args} -) - -if(CMAKE_SCRIPT_MODE_FILE AND NOT CMAKE_PARENT_LIST_FILE) -# If this file is invoked as a script directly with -P: -# cmake [options] -P board.cmake -# Note that CMAKE_PARENT_LIST_FILE not being set ensures that this present -# file is being invoked directly with -P, and not via an include directive from -# some other script - -# The options available are: -# ARCH_ROOT: Semi-colon separated arch roots -# BOARD_ROOT: Semi-colon separated board roots -# FILE_OUT: Set to a file path to save the boards to a file. If not defined the -# the contents will be printed to stdout -cmake_minimum_required(VERSION 3.20.0) - -set(NO_BOILERPLATE TRUE) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) - -if (FILE_OUT) - list(APPEND list_boards_commands OUTPUT_FILE "${FILE_OUT}") -endif() - -execute_process(${list_boards_commands}) -endif() diff --git a/cmake/modules/arch.cmake b/cmake/modules/arch.cmake new file mode 100644 index 0000000000000..2f949287e8056 --- /dev/null +++ b/cmake/modules/arch.cmake @@ -0,0 +1,40 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2022, Nordic Semiconductor ASA + +# Configure ARCH settings based on board directory and arch root. +# +# This CMake module will set the following variables in the build system based +# on board directory and arch root. +# +# If no implementation is available for the current arch an error will be raised. +# +# Outcome: +# The following variables will be defined when this CMake module completes: +# +# - ARCH: Name of the arch in use. +# - ARCH_DIR: Directory containing the arch implementation. +# +# Variable dependencies: +# - ARCH_ROOT: CMake list of arch roots containing arch implementations +# - BOARD_DIR: CMake variable specifying the directory of the selected BOARD + +# 'ARCH_ROOT' is a prioritized list of directories where archs may be +# found. It always includes ${ZEPHYR_BASE} at the lowest priority. +list(APPEND ARCH_ROOT ${ZEPHYR_BASE}) + +cmake_path(GET BOARD_DIR PARENT_PATH board_arch_dir) +cmake_path(GET board_arch_dir FILENAME ARCH) + +foreach(root ${ARCH_ROOT}) + if(EXISTS ${root}/arch/${ARCH}/CMakeLists.txt) + set(ARCH_DIR ${root}/arch) + break() + endif() +endforeach() + +if(NOT ARCH_DIR) + message(FATAL_ERROR "Could not find ARCH=${ARCH} for BOARD=${BOARD}, \ +please check your installation. ARCH roots searched: \n\ +${ARCH_ROOT}") +endif() diff --git a/cmake/modules/boards.cmake b/cmake/modules/boards.cmake new file mode 100644 index 0000000000000..dfcc3c83ef693 --- /dev/null +++ b/cmake/modules/boards.cmake @@ -0,0 +1,147 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2021, Nordic Semiconductor ASA + +# Validate board and setup boards target. +# +# This CMake module will validate the BOARD argument as well as splitting the +# BOARD argument into and . +# +# If a board implementation is not found for the specified board an error will +# be raised and list of valid boards will be printed. +# +# If user provided board is a board alias, the board will be adjusted to real +# board name. +# +# If board name is deprecated, then board will be adjusted to new board name and +# a deprecation warning will be printed to the user. +# +# Outcome: +# The following variables will be defined when this CMake module completes: +# +# - BOARD: Board, without revision field. +# - BOARD_REVISION: Board revision +# - BOARD_DIR: Board directory with the implementation for selected board +# - ARCH_DIR: Arch dir for extracted from selected board +# +# The following targets will be defined when this CMake module completes: +# - board : when invoked a list of valid boards will be printed +# +# Variable dependencies: +# - BOARD_ROOT: CMake list of board roots containing board implementations +# - ARCH_ROOT: CMake list of arch roots containing arch implementations +# +# CMake module dependencies: +# - extensions CMake module. + +include_guard(GLOBAL) + +# Dependencies of this module. +include(extensions) + +# Check that BOARD has been provided, and that it has not changed. +# If user tries to change the BOARD, the BOARD value is reset to the BOARD_CACHED value. +zephyr_check_cache(BOARD REQUIRED) + +# 'BOARD_ROOT' is a prioritized list of directories where boards may +# be found. It always includes ${ZEPHYR_BASE} at the lowest priority. +list(APPEND BOARD_ROOT ${ZEPHYR_BASE}) + +string(FIND "${BOARD}" "@" REVISION_SEPARATOR_INDEX) +if(NOT (REVISION_SEPARATOR_INDEX EQUAL -1)) + math(EXPR BOARD_REVISION_INDEX "${REVISION_SEPARATOR_INDEX} + 1") + string(SUBSTRING ${BOARD} ${BOARD_REVISION_INDEX} -1 BOARD_REVISION) + string(SUBSTRING ${BOARD} 0 ${REVISION_SEPARATOR_INDEX} BOARD) +endif() + +message(STATUS "Board: ${BOARD}") + +if(DEFINED ENV{ZEPHYR_BOARD_ALIASES}) + include($ENV{ZEPHYR_BOARD_ALIASES}) + if(${BOARD}_BOARD_ALIAS) + set(BOARD_ALIAS ${BOARD} CACHE STRING "Board alias, provided by user") + set(BOARD ${${BOARD}_BOARD_ALIAS}) + message(STATUS "Aliased BOARD=${BOARD_ALIAS} changed to ${BOARD}") + endif() +endif() +include(${ZEPHYR_BASE}/boards/deprecated.cmake) +if(${BOARD}_DEPRECATED) + set(BOARD_DEPRECATED ${BOARD} CACHE STRING "Deprecated board name, provided by user") + set(BOARD ${${BOARD}_DEPRECATED}) + message(WARNING "Deprecated BOARD=${BOARD_DEPRECATED} name specified, board automatically changed to: ${BOARD}.") +endif() + +zephyr_boilerplate_watch(BOARD) + +foreach(root ${BOARD_ROOT}) + # Check that the board root looks reasonable. + if(NOT IS_DIRECTORY "${root}/boards") + 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 in doubt, use absolute paths") + endif() + + # NB: find_path will return immediately if the output variable is + # already set + if (BOARD_ALIAS) + find_path(BOARD_HIDDEN_DIR + NAMES ${BOARD_ALIAS}_defconfig + PATHS ${root}/boards/*/* + NO_DEFAULT_PATH + ) + if(BOARD_HIDDEN_DIR) + message("Board alias ${BOARD_ALIAS} is hiding the real board of same name") + endif() + endif() + find_path(BOARD_DIR + NAMES ${BOARD}_defconfig + PATHS ${root}/boards/*/* + NO_DEFAULT_PATH + ) + if(BOARD_DIR AND NOT (${root} STREQUAL ${ZEPHYR_BASE})) + set(USING_OUT_OF_TREE_BOARD 1) + endif() +endforeach() + +if(EXISTS ${BOARD_DIR}/revision.cmake) + # Board provides revision handling. + include(${BOARD_DIR}/revision.cmake) +elseif(BOARD_REVISION) + message(WARNING "Board revision ${BOARD_REVISION} specified for ${BOARD}, \ + but board has no revision so revision will be ignored.") +endif() + +if(DEFINED BOARD_REVISION) + set(BOARD_MESSAGE "${BOARD_MESSAGE}, Revision: ${BOARD_REVISION}") + if(DEFINED ACTIVE_BOARD_REVISION) + set(BOARD_MESSAGE "${BOARD_MESSAGE} (Active: ${ACTIVE_BOARD_REVISION})") + set(BOARD_REVISION ${ACTIVE_BOARD_REVISION}) + endif() + + string(REPLACE "." "_" BOARD_REVISION_STRING ${BOARD_REVISION}) +endif() + +# Prepare boards usage command printing. +# This command prints all boards in the system in the following cases: +# - User specifies an invalid BOARD +# - User invokes ' boards' target +list(TRANSFORM ARCH_ROOT PREPEND "--arch-root=" OUTPUT_VARIABLE arch_root_args) +list(TRANSFORM BOARD_ROOT PREPEND "--board-root=" OUTPUT_VARIABLE board_root_args) + +set(list_boards_commands + COMMAND ${PYTHON_EXECUTABLE} ${ZEPHYR_BASE}/scripts/list_boards.py + ${arch_root_args} ${board_root_args} +) + +if(NOT BOARD_DIR) + message("No board named '${BOARD}' found.\n\n" + "Please choose one of the following boards:\n" + ) + execute_process(${list_boards_commands}) + unset(CACHED_BOARD CACHE) + message(FATAL_ERROR "Invalid BOARD; see above.") +endif() + +add_custom_target(boards ${list_boards_commands} USES_TERMINAL) diff --git a/cmake/modules/build_configuration.cmake b/cmake/modules/build_configuration.cmake new file mode 100644 index 0000000000000..7e19babb9ea2c --- /dev/null +++ b/cmake/modules/build_configuration.cmake @@ -0,0 +1,112 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2021, Nordic Semiconductor ASA + +# Configure Zephyr build system. +# +# This CMake module will setup various configuration settings based on user input. +# +# Outcome: +# The following variables will be defined when this CMake module completes: +# +# - CONF_FILE: List of Kconfig fragments +# - DTC_OVERLAY_FILE: List of devicetree overlay files +# - APPLICATIUON_CONFIG_DIR: Root folder for application configuration +# +# If any of the above variables are already set when this CMake module is +# loaded, then no changes to the variable will happen. +# +# CMake module dependencies: +# - extensions CMake module. + +include_guard(GLOBAL) + +# Dependencies of this module. +include(extensions) + +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() + +if(DEFINED CONF_FILE) + # This ensures that CACHE{CONF_FILE} will be set correctly to current scope + # variable CONF_FILE. An already current scope variable will stay the same. + set(CONF_FILE ${CONF_FILE}) + + # CONF_FILE has either been specified on the cmake CLI or is already + # in the CMakeCache.txt. This has precedence over the environment + # variable CONF_FILE and the default prj.conf + + # In order to support a `prj_.conf pattern for auto inclusion of board + # overlays, then we must first ensure only a single conf file is provided. + string(REPLACE " " ";" CONF_FILE_AS_LIST "${CONF_FILE}") + list(LENGTH CONF_FILE_AS_LIST CONF_FILE_LENGTH) + if(${CONF_FILE_LENGTH} EQUAL 1) + # Need the file name to look for match. + # Need path in order to check if it is absolute. + get_filename_component(CONF_FILE_NAME ${CONF_FILE} NAME) + if(${CONF_FILE_NAME} MATCHES "prj_(.*).conf") + set(CONF_FILE_BUILD_TYPE ${CMAKE_MATCH_1}) + set(CONF_FILE_INCLUDE_FRAGMENTS true) + endif() + endif() +elseif(CACHED_CONF_FILE) + # Cached conf file is present. + # That value has precedence over anything else than a new + # `cmake -DCONF_FILE=` invocation. + set(CONF_FILE ${CACHED_CONF_FILE}) +elseif(DEFINED ENV{CONF_FILE}) + set(CONF_FILE $ENV{CONF_FILE}) + +elseif(EXISTS ${APPLICATION_CONFIG_DIR}/prj_${BOARD}.conf) + set(CONF_FILE ${APPLICATION_CONFIG_DIR}/prj_${BOARD}.conf) + +elseif(EXISTS ${APPLICATION_CONFIG_DIR}/prj.conf) + set(CONF_FILE ${APPLICATION_CONFIG_DIR}/prj.conf) + set(CONF_FILE_INCLUDE_FRAGMENTS true) +endif() + +if(CONF_FILE_INCLUDE_FRAGMENTS) + zephyr_file(CONF_FILES ${APPLICATION_CONFIG_DIR}/boards KCONF CONF_FILE BUILD ${CONF_FILE_BUILD_TYPE}) +endif() + +set(APPLICATION_CONFIG_DIR ${APPLICATION_CONFIG_DIR} CACHE INTERNAL "The application configuration folder") +set(CACHED_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.\ +Multiple files may be listed, e.g. CONF_FILE=\"prj1.confi;prj2.conf\" \ +The CACHED_CONF_FILE is internal Zephyr variable used between CMake runs. \ +To change CONF_FILE, use the CONF_FILE variable.") +unset(CONF_FILE CACHE) + +zephyr_file(CONF_FILES ${APPLICATION_CONFIG_DIR}/boards DTS APP_BOARD_DTS) + +# The CONF_FILE variable is now set to its final value. +zephyr_boilerplate_watch(CONF_FILE) + +if(DTC_OVERLAY_FILE) + # DTC_OVERLAY_FILE has either been specified on the cmake CLI or is already + # in the CMakeCache.txt. +elseif(APP_BOARD_DTS) + set(DTC_OVERLAY_FILE ${APP_BOARD_DTS}) +elseif(EXISTS ${APPLICATION_CONFIG_DIR}/${BOARD}.overlay) + set(DTC_OVERLAY_FILE ${APPLICATION_CONFIG_DIR}/${BOARD}.overlay) +elseif(EXISTS ${APPLICATION_CONFIG_DIR}/app.overlay) + set(DTC_OVERLAY_FILE ${APPLICATION_CONFIG_DIR}/app.overlay) +endif() + +set(DTC_OVERLAY_FILE ${DTC_OVERLAY_FILE} CACHE STRING "If desired, you can \ +build the application using the DT configuration settings specified in an \ +alternate .overlay file using this parameter. These settings will override the \ +settings in the board's .dts file. Multiple files may be listed, e.g. \ +DTC_OVERLAY_FILE=\"dts1.overlay dts2.overlay\"") + +# The DTC_OVERLAY_FILE variable is now set to its final value. +zephyr_boilerplate_watch(DTC_OVERLAY_FILE) diff --git a/cmake/ccache.cmake b/cmake/modules/ccache.cmake similarity index 94% rename from cmake/ccache.cmake rename to cmake/modules/ccache.cmake index cfe7f91aed74e..c1d41d6b9e44a 100644 --- a/cmake/ccache.cmake +++ b/cmake/modules/ccache.cmake @@ -3,6 +3,8 @@ # Use ccache if it is installed, unless the user explicitly disables # it by setting USE_CCACHE=0. +include_guard(GLOBAL) + if(USE_CCACHE STREQUAL "0") else() find_program(CCACHE_FOUND ccache) diff --git a/cmake/modules/doc.cmake b/cmake/modules/doc.cmake new file mode 100644 index 0000000000000..daf16336405c7 --- /dev/null +++ b/cmake/modules/doc.cmake @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2021, Nordic Semiconductor ASA + +# This CMake module will load all Zephyr CMake modules required for a +# documentation build. +# +# The following CMake modules will be loaded: +# - extensions +# - python +# - west +# - root +# - zephyr_module +# +# Outcome: +# The Zephyr package required for documentation build setup. + +include_guard(GLOBAL) + +include(extensions) +include(python) +include(west) +include(root) +include(zephyr_module) diff --git a/cmake/dts.cmake b/cmake/modules/dts.cmake similarity index 98% rename from cmake/dts.cmake rename to cmake/modules/dts.cmake index 039853a69255f..f9646e5e8648f 100644 --- a/cmake/dts.cmake +++ b/cmake/modules/dts.cmake @@ -1,5 +1,13 @@ # SPDX-License-Identifier: Apache-2.0 +include_guard(GLOBAL) + +# Dependencies of this module. +include(extensions) +include(python) +include(boards) +include(generic_toolchain) + file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/include/generated) # Zephyr code can configure itself based on a KConfig'uration with the diff --git a/cmake/extensions.cmake b/cmake/modules/extensions.cmake similarity index 98% rename from cmake/extensions.cmake rename to cmake/modules/extensions.cmake index cf2db3c098a48..99307cd5f5092 100644 --- a/cmake/extensions.cmake +++ b/cmake/modules/extensions.cmake @@ -1,5 +1,14 @@ # SPDX-License-Identifier: Apache-2.0 +include_guard(GLOBAL) + +# Extensions depends on two CMake modules, so load them here +include(CheckCCompilerFlag) +include(CheckCXXCompilerFlag) + +# Dependencies of this module. +include(user_cache) + ######################################################## # Table of contents ######################################################## @@ -2054,81 +2063,6 @@ macro(assert_exists var) endmacro() # 3.5. File system management -function(check_if_directory_is_writeable dir ok) - execute_process( - COMMAND - ${PYTHON_EXECUTABLE} - ${ZEPHYR_BASE}/scripts/dir_is_writeable.py - ${dir} - RESULT_VARIABLE ret - ) - - if("${ret}" STREQUAL "0") - # The directory is write-able - set(${ok} 1 PARENT_SCOPE) - else() - set(${ok} 0 PARENT_SCOPE) - endif() -endfunction() - -function(find_appropriate_cache_directory dir) - set(env_suffix_LOCALAPPDATA .cache) - - if(CMAKE_HOST_APPLE) - # On macOS, ~/Library/Caches is the preferred cache directory. - set(env_suffix_HOME Library/Caches) - else() - set(env_suffix_HOME .cache) - endif() - - # Determine which env vars should be checked - if(CMAKE_HOST_APPLE) - set(dirs HOME) - elseif(CMAKE_HOST_WIN32) - set(dirs LOCALAPPDATA) - else() - # Assume Linux when we did not detect 'mac' or 'win' - # - # On Linux, freedesktop.org recommends using $XDG_CACHE_HOME if - # that is defined and defaulting to $HOME/.cache otherwise. - set(dirs - XDG_CACHE_HOME - HOME - ) - endif() - - foreach(env_var ${dirs}) - if(DEFINED ENV{${env_var}}) - set(env_dir $ENV{${env_var}}) - - set(test_user_dir ${env_dir}/${env_suffix_${env_var}}) - - check_if_directory_is_writeable(${test_user_dir} ok) - if(${ok}) - # The directory is write-able - set(user_dir ${test_user_dir}) - break() - else() - # The directory was not writeable, keep looking for a suitable - # directory - endif() - endif() - endforeach() - - # Populate local_dir with a suitable directory for caching - # files. Prefer a directory outside of the git repository because it - # is good practice to have clean git repositories. - if(DEFINED user_dir) - # Zephyr's cache files go in the "zephyr" subdirectory of the - # user's cache directory. - set(local_dir ${user_dir}/zephyr) - else() - set(local_dir ${ZEPHYR_BASE}/.cache) - endif() - - set(${dir} ${local_dir} PARENT_SCOPE) -endfunction() - function(generate_unique_target_name_from_filename filename target_name) get_filename_component(basename ${filename} NAME) string(REPLACE "." "_" x ${basename}) diff --git a/cmake/generic_toolchain.cmake b/cmake/modules/generic_toolchain.cmake similarity index 89% rename from cmake/generic_toolchain.cmake rename to cmake/modules/generic_toolchain.cmake index cea472c5a87f0..c1f930c2349ab 100644 --- a/cmake/generic_toolchain.cmake +++ b/cmake/modules/generic_toolchain.cmake @@ -1,5 +1,15 @@ # SPDX-License-Identifier: Apache-2.0 +include_guard(GLOBAL) + +# Dependencies of this module. +include(extensions) +include(verify-toolchain) + +# Prevent CMake from testing the toolchain +set(CMAKE_C_COMPILER_FORCED 1) +set(CMAKE_CXX_COMPILER_FORCED 1) + if(NOT TOOLCHAIN_ROOT) if(DEFINED ENV{TOOLCHAIN_ROOT}) # Support for out-of-tree toolchain diff --git a/cmake/git.cmake b/cmake/modules/git.cmake similarity index 97% rename from cmake/git.cmake rename to cmake/modules/git.cmake index fa79e30a54a4f..814fb47c41324 100644 --- a/cmake/git.cmake +++ b/cmake/modules/git.cmake @@ -10,6 +10,7 @@ # See also: independent and more static ``KERNEL_VERSION_*`` in # ``version.cmake`` and ``kernel_version.h`` +include_guard(GLOBAL) # https://cmake.org/cmake/help/latest/module/FindGit.html find_package(Git QUIET) diff --git a/cmake/host-tools.cmake b/cmake/modules/host-tools.cmake similarity index 98% rename from cmake/host-tools.cmake rename to cmake/modules/host-tools.cmake index c44251d3b93fb..abe153837cf7d 100644 --- a/cmake/host-tools.cmake +++ b/cmake/modules/host-tools.cmake @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +include_guard(GLOBAL) + if(ZEPHYR_SDK_HOST_TOOLS) include(${ZEPHYR_BASE}/cmake/toolchain/zephyr/host-tools.cmake) endif() diff --git a/cmake/kconfig.cmake b/cmake/modules/kconfig.cmake similarity index 93% rename from cmake/kconfig.cmake rename to cmake/modules/kconfig.cmake index cd7ba45b70659..66aca9256ac7a 100644 --- a/cmake/kconfig.cmake +++ b/cmake/modules/kconfig.cmake @@ -1,5 +1,18 @@ # SPDX-License-Identifier: Apache-2.0 +include_guard(GLOBAL) + +# Dependencies of this module. +include(extensions) +include(python) + +# 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) +# Re-configure (Re-execute all CMakeLists.txt code) when autoconf.h changes +set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${AUTOCONF_H}) + # Folders needed for conf/mconf files (kconfig has no method of redirecting all output files). # conf/mconf needs to be run from a different directory because of: GH-3408 file(MAKE_DIRECTORY ${PROJECT_BINARY_DIR}/kconfig/include/generated) @@ -250,6 +263,11 @@ else() set(input_configs ${DOTCONFIG}) endif() +cmake_path(GET AUTOCONF_H PARENT_PATH autoconf_h_path) +if(NOT EXISTS ${autoconf_h_path}) + file(MAKE_DIRECTORY ${autoconf_h_path}) +endif() + execute_process( COMMAND ${CMAKE_COMMAND} -E env ${COMMON_KCONFIG_ENV_SETTINGS} diff --git a/cmake/modules/kernel.cmake b/cmake/modules/kernel.cmake new file mode 100644 index 0000000000000..b0c32410f18a0 --- /dev/null +++ b/cmake/modules/kernel.cmake @@ -0,0 +1,243 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2021, Nordic Semiconductor ASA + +# Zephyr Kernel CMake module. +# +# This is the main Zephyr Kernel CMake module which is resposible for creation +# of Zephyr libraries and the Zephyr executeable. +# +# This CMake module creates 'project(Zephyr-Kernel)' +# +# It defines properties to use while configuring libraries to be build as well +# as using add_subdirectory() to add the main /CMakeLists.txt file. +# +# Outcome: +# - Zephyr build system. +# - Zephyr project +# +# Important libraries: +# - app: This is the main application library where the application can add +# source files that must be included when building Zephyr +# +# CMake module dependencies: +# - All Zephyr CMake modules are required for this CMake module to work correctly + +include_guard(GLOBAL) + +# As this module is not intended for direct loading, but should be loaded through +# find_package(Zephyr) then it won't be loading any Zephyr CMake modules by itself. + +define_property(GLOBAL PROPERTY ZEPHYR_LIBS + BRIEF_DOCS "Global list of all Zephyr CMake libs that should be linked in" + FULL_DOCS "Global list of all Zephyr CMake libs that should be linked in. +zephyr_library() appends libs to this list.") +set_property(GLOBAL PROPERTY ZEPHYR_LIBS "") + +define_property(GLOBAL PROPERTY ZEPHYR_INTERFACE_LIBS + BRIEF_DOCS "Global list of all Zephyr interface libs that should be linked in." + FULL_DOCS "Global list of all Zephyr interface libs that should be linked in. +zephyr_interface_library_named() appends libs to this list.") +set_property(GLOBAL PROPERTY ZEPHYR_INTERFACE_LIBS "") + +define_property(GLOBAL PROPERTY GENERATED_APP_SOURCE_FILES + BRIEF_DOCS "Source files that are generated after Zephyr has been linked once." + FULL_DOCS "\ +Source files that are generated after Zephyr has been linked once.\ +May include dev_handles.c etc." + ) +set_property(GLOBAL PROPERTY GENERATED_APP_SOURCE_FILES "") + +define_property(GLOBAL PROPERTY GENERATED_KERNEL_OBJECT_FILES + BRIEF_DOCS "Object files that are generated after symbol addresses are fixed." + FULL_DOCS "\ +Object files that are generated after symbol addresses are fixed.\ +May include mmu tables, etc." + ) +set_property(GLOBAL PROPERTY GENERATED_KERNEL_OBJECT_FILES "") + +define_property(GLOBAL PROPERTY GENERATED_KERNEL_SOURCE_FILES + BRIEF_DOCS "Source files that are generated after symbol addresses are fixed." + FULL_DOCS "\ +Source files that are generated after symbol addresses are fixed.\ +May include isr_tables.c etc." + ) +set_property(GLOBAL PROPERTY GENERATED_KERNEL_SOURCE_FILES "") + +add_custom_target(code_data_relocation_target) + +# The zephyr/runners.yaml file in the build directory is used to +# configure the scripts/west_commands/runners Python package used +# by 'west flash', 'west debug', etc. +# +# This is a helper target for setting property:value pairs related to +# this file: +# +# Property Description +# -------------- -------------------------------------------------- +# bin_file "zephyr.bin" file for flashing +# hex_file "zephyr.hex" file for flashing +# elf_file "zephyr.elf" file for flashing or debugging +# yaml_contents generated contents of runners.yaml +# +# Note: there are quotes around "zephyr.bin" etc. because the actual +# paths can be changed, e.g. to flash signed versions of these files +# for consumption by bootloaders such as MCUboot. +# +# See cmake/flash/CMakeLists.txt for more details. +add_custom_target(runners_yaml_props_target) + +# CMake's 'project' concept has proven to not be very useful for Zephyr +# due in part to how Zephyr is organized and in part to it not fitting well +# with cross compilation. +# Zephyr therefore tries to rely as little as possible on project() +# and its associated variables, e.g. PROJECT_SOURCE_DIR. +# It is recommended to always use ZEPHYR_BASE instead of PROJECT_SOURCE_DIR +# when trying to reference ENV${ZEPHYR_BASE}. + +# Note any later project() resets PROJECT_SOURCE_DIR +file(TO_CMAKE_PATH "${ZEPHYR_BASE}" PROJECT_SOURCE_DIR) + +set(ZEPHYR_BINARY_DIR ${PROJECT_BINARY_DIR}) + +if(${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_BINARY_DIR}) + message(FATAL_ERROR "Source directory equals build directory.\ + In-source builds are not supported.\ + Please specify a build directory, e.g. cmake -Bbuild -H.") +endif() + +add_custom_target( + pristine + COMMAND ${CMAKE_COMMAND} -DBINARY_DIR=${APPLICATION_BINARY_DIR} + -DSOURCE_DIR=${APPLICATION_SOURCE_DIR} + -P ${ZEPHYR_BASE}/cmake/pristine.cmake + # Equivalent to rm -rf build/* + ) + +# Dummy add to generate files. +zephyr_linker_sources(SECTIONS) + +# For the gen_app_partitions.py to work correctly, we must ensure that +# all targets exports their compile commands to fetch object files. +# We enable it unconditionally, as this is also useful for several IDEs +set(CMAKE_EXPORT_COMPILE_COMMANDS TRUE CACHE BOOL + "Export CMake compile commands. Used by gen_app_partitions.py script" + FORCE +) + +project(Zephyr-Kernel VERSION ${PROJECT_VERSION}) + +# Add .S file extension suffix into CMAKE_ASM_SOURCE_FILE_EXTENSIONS, +# because clang from OneApi can't recongnize them as asm files on +# windows now. +list(APPEND CMAKE_ASM_SOURCE_FILE_EXTENSIONS "S") +enable_language(C CXX ASM) + +# The setup / configuration of the toolchain itself and the configuration of +# supported compilation flags are now split, as this allows to use the toolchain +# for generic purposes, for example DTS, and then test the toolchain for +# supported flags at stage two. +# Testing the toolchain flags requires the enable_language() to have been called in CMake. + +# Verify that the toolchain can compile a dummy file, if it is not we +# won't be able to test for compatibility with certain C flags. +zephyr_check_compiler_flag(C "" toolchain_is_ok) +assert(toolchain_is_ok "The toolchain is unable to build a dummy C file. See CMakeError.log.") + +include(${ZEPHYR_BASE}/cmake/target_toolchain_flags.cmake) + +# 'project' sets PROJECT_BINARY_DIR to ${CMAKE_CURRENT_BINARY_DIR}, +# but for legacy reasons we need it to be set to +# ${CMAKE_CURRENT_BINARY_DIR}/zephyr +set(PROJECT_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/zephyr) +set(PROJECT_SOURCE_DIR ${ZEPHYR_BASE}) + +set(KERNEL_NAME ${CONFIG_KERNEL_BIN_NAME}) + +set(KERNEL_ELF_NAME ${KERNEL_NAME}.elf) +set(KERNEL_BIN_NAME ${KERNEL_NAME}.bin) +set(KERNEL_HEX_NAME ${KERNEL_NAME}.hex) +set(KERNEL_UF2_NAME ${KERNEL_NAME}.uf2) +set(KERNEL_MAP_NAME ${KERNEL_NAME}.map) +set(KERNEL_LST_NAME ${KERNEL_NAME}.lst) +set(KERNEL_S19_NAME ${KERNEL_NAME}.s19) +set(KERNEL_EXE_NAME ${KERNEL_NAME}.exe) +set(KERNEL_STAT_NAME ${KERNEL_NAME}.stat) +set(KERNEL_STRIP_NAME ${KERNEL_NAME}.strip) +set(KERNEL_META_NAME ${KERNEL_NAME}.meta) + +include(${BOARD_DIR}/board.cmake OPTIONAL) + +# If we are using a suitable ethernet driver inside qemu, then these options +# must be set, otherwise a zephyr instance cannot receive any network packets. +# The Qemu supported ethernet driver should define CONFIG_ETH_NIC_MODEL +# string that tells what nic model Qemu should use. +if(CONFIG_QEMU_TARGET) + if ((CONFIG_NET_QEMU_ETHERNET OR CONFIG_NET_QEMU_USER) AND NOT CONFIG_ETH_NIC_MODEL) + message(FATAL_ERROR " + No Qemu ethernet driver configured! + Enable Qemu supported ethernet driver like e1000 at drivers/ethernet" + ) + elseif(CONFIG_NET_QEMU_ETHERNET) + if(CONFIG_ETH_QEMU_EXTRA_ARGS) + set(NET_QEMU_ETH_EXTRA_ARGS ",${CONFIG_ETH_QEMU_EXTRA_ARGS}") + endif() + list(APPEND QEMU_FLAGS_${ARCH} + -nic tap,model=${CONFIG_ETH_NIC_MODEL},script=no,downscript=no,ifname=${CONFIG_ETH_QEMU_IFACE_NAME}${NET_QEMU_ETH_EXTRA_ARGS} + ) + elseif(CONFIG_NET_QEMU_USER) + list(APPEND QEMU_FLAGS_${ARCH} + -nic user,model=${CONFIG_ETH_NIC_MODEL},${CONFIG_NET_QEMU_USER_EXTRA_ARGS} + ) + else() + list(APPEND QEMU_FLAGS_${ARCH} + -net none + ) + endif() +endif() + +# General purpose Zephyr target. +# This target can be used for custom zephyr settings that needs to be used elsewhere in the build system +# +# Currently used properties: +# - COMPILES_OPTIONS: Used by application memory partition feature +add_custom_target(zephyr_property_target) + +# "app" is a CMake library containing all the application code and is +# modified by the entry point ${APPLICATION_SOURCE_DIR}/CMakeLists.txt +# that was specified when cmake was called. +zephyr_library_named(app) +set_property(TARGET app PROPERTY ARCHIVE_OUTPUT_DIRECTORY app) + +add_subdirectory(${ZEPHYR_BASE} ${__build_dir}) + +# Link 'app' with the Zephyr interface libraries. +# +# NB: This must be done in boilerplate.cmake because 'app' can only be +# modified in the CMakeLists.txt file that created it. And it must be +# done after 'add_subdirectory(${ZEPHYR_BASE} ${__build_dir})' +# because interface libraries are defined while processing that +# subdirectory. +get_property(ZEPHYR_INTERFACE_LIBS_PROPERTY GLOBAL PROPERTY ZEPHYR_INTERFACE_LIBS) +foreach(boilerplate_lib ${ZEPHYR_INTERFACE_LIBS_PROPERTY}) + # Linking 'app' with 'boilerplate_lib' causes 'app' to inherit the INTERFACE + # properties of 'boilerplate_lib'. The most common property is 'include + # directories', but it is also possible to have defines and compiler + # flags in the interface of a library. + # + string(TOUPPER ${boilerplate_lib} boilerplate_lib_upper_case) # Support lowercase lib names + target_link_libraries_ifdef( + CONFIG_APP_LINK_WITH_${boilerplate_lib_upper_case} + app + PUBLIC + ${boilerplate_lib} + ) +endforeach() + +if("${CMAKE_EXTRA_GENERATOR}" STREQUAL "Eclipse CDT4") + # Call the amendment function before .project and .cproject generation + # C and CXX includes, defines in .cproject without __cplusplus + # with project includes and defines + include(${ZEPHYR_BASE}/cmake/ide/eclipse_cdt4_generator_amendment.cmake) + eclipse_cdt4_generator_amendment(1) +endif() diff --git a/cmake/python.cmake b/cmake/modules/python.cmake similarity index 98% rename from cmake/python.cmake rename to cmake/modules/python.cmake index 0ac40f9dc1102..fdc981f7a7ba0 100644 --- a/cmake/python.cmake +++ b/cmake/modules/python.cmake @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 +include_guard(GLOBAL) + # On Windows, instruct Python to output UTF-8 even when not # interacting with a terminal. This is required since Python scripts # are invoked by CMake code and, on Windows, standard I/O encoding defaults diff --git a/cmake/modules/root.cmake b/cmake/modules/root.cmake new file mode 100644 index 0000000000000..d5f29c8c0dde4 --- /dev/null +++ b/cmake/modules/root.cmake @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2021, Nordic Semiconductor ASA + +# Convert Zephyr roots to absolute paths. +# +# This CMake module will convert all relative paths in existing ROOT lists to +# absolute path relative from APPLICATION_SOURCE_DIR. +# +# Optional variables: +# - ARCH_ROOT: CMake list of arch roots containing arch implementations +# - 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 +# +# 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. +# If a root is undefined it will still be undefined when this module has loaded. +# +# CMake module dependencies: +# - extensions CMake module. + +include_guard(GLOBAL) + +# Dependencies of this module. +include(extensions) + +# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR +zephyr_file(APPLICATION_ROOT MODULE_EXT_ROOT) + +# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR +zephyr_file(APPLICATION_ROOT BOARD_ROOT) + +# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR +zephyr_file(APPLICATION_ROOT SOC_ROOT) + +# Convert paths to absolute, relative from APPLICATION_SOURCE_DIR +zephyr_file(APPLICATION_ROOT ARCH_ROOT) diff --git a/cmake/modules/shields.cmake b/cmake/modules/shields.cmake new file mode 100644 index 0000000000000..86e668baefbe3 --- /dev/null +++ b/cmake/modules/shields.cmake @@ -0,0 +1,143 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2021, Nordic Semiconductor ASA + +# Validate shields and setup shields target. +# +# This module will validate the SHIELD argument. +# +# If a shield implementation is not found for one of the specified shields an +# error will be raised and list of valid shields will be printed. +# +# Outcome: +# The following variables will be defined when this module completes: +# - shield_conf_files: List of shield specific Kconfig fragments +# - shield_dts_files : List of shield specific devicetree files +# - shield_dts_fixups: List of shield specific devicetree fixups +# +# The following targets will be defined when this module completes: +# - shields: when invoked a list of valid shields will be printed +# +# Variable dependencies: +# - BOARD_ROOT: CMake list of board roots containing board implementations +# +# Module dependencies: +# - extension module. + +include_guard(GLOBAL) + +# Dependencies of this module. +include(extensions) + +# Check that SHIELD has not changed. +zephyr_check_cache(SHIELD WATCH) + +if(SHIELD) + set(BOARD_MESSAGE "${BOARD_MESSAGE}, Shield(s): ${SHIELD}") +endif() + +if(DEFINED SHIELD) + string(REPLACE " " ";" SHIELD_AS_LIST "${SHIELD}") +endif() +# SHIELD-NOTFOUND is a real CMake list, from which valid shields can be popped. +# After processing all shields, only invalid shields will be left in this list. +set(SHIELD-NOTFOUND ${SHIELD_AS_LIST}) + +# Use BOARD to search for a '_defconfig' file. +# e.g. zephyr/boards/arm/96b_carbon_nrf51/96b_carbon_nrf51_defconfig. +# When found, use that path to infer the ARCH we are building for. +foreach(root ${BOARD_ROOT}) + set(shield_dir ${root}/boards/shields) + # Match the Kconfig.shield files in the shield directories to make sure we are + # finding shields, e.g. x_nucleo_iks01a1/Kconfig.shield + file(GLOB_RECURSE shields_refs_list ${shield_dir}/*/Kconfig.shield) + + # The above gives a list like + # x_nucleo_iks01a1/Kconfig.shield;x_nucleo_iks01a2/Kconfig.shield + # we construct a list of shield names by extracting the folder and find + # and overlay files in there. Each overlay corresponds to a shield. + # We obtain the shield name by removing the overlay extension. + unset(SHIELD_LIST) + foreach(shields_refs ${shields_refs_list}) + get_filename_component(shield_path ${shields_refs} DIRECTORY) + file(GLOB shield_overlays RELATIVE ${shield_path} ${shield_path}/*.overlay) + foreach(overlay ${shield_overlays}) + get_filename_component(shield ${overlay} NAME_WE) + list(APPEND SHIELD_LIST ${shield}) + set(SHIELD_DIR_${shield} ${shield_path}) + endforeach() + endforeach() + + if(DEFINED SHIELD) + foreach(s ${SHIELD_AS_LIST}) + if(NOT ${s} IN_LIST SHIELD_LIST) + continue() + endif() + + list(REMOVE_ITEM SHIELD-NOTFOUND ${s}) + + # if shield config flag is on, add shield overlay to the shield overlays + # list and dts_fixup file to the shield fixup file + list(APPEND + shield_dts_files + ${SHIELD_DIR_${s}}/${s}.overlay + ) + + list(APPEND + shield_dts_fixups + ${SHIELD_DIR_${s}}/dts_fixup.h + ) + + list(APPEND + SHIELD_DIRS + ${SHIELD_DIR_${s}} + ) + + # search for shield/shield.conf file + if(EXISTS ${SHIELD_DIR_${s}}/${s}.conf) + # add shield.conf to the shield config list + list(APPEND + shield_conf_files + ${SHIELD_DIR_${s}}/${s}.conf + ) + endif() + + zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards + DTS shield_dts_files + KCONF shield_conf_files + ) + zephyr_file(CONF_FILES ${SHIELD_DIR_${s}}/boards/${s} + DTS shield_dts_files + KCONF shield_conf_files + ) + endforeach() + endif() +endforeach() + +# Prepare shield usage command printing. +# This command prints all ishield in the system in the following cases: +# - User specifies an invalid SHIELD +# - User invokes ' shields' target +list(SORT SHIELD_LIST) + +if(DEFINED SHIELD AND NOT (SHIELD-NOTFOUND STREQUAL "")) + # Convert the list to pure string with newlines for printing. + string(REPLACE ";" "\n" shield_string "${SHIELD_LIST}") + + foreach (s ${SHIELD-NOTFOUND}) + message("No shield named '${s}' found") + endforeach() + message("Please choose from among the following shields:\n" + "${shield_string}" + ) + unset(CACHED_SHIELD CACHE) + message(FATAL_ERROR "Invalid SHIELD; see above.") +endif() + +# Prepend each shield with COMMAND -E echo " for printing. +# Each shield is printed as new command because build files are not fond of newlines. +list(TRANSFORM SHIELD_LIST PREPEND "COMMAND;${CMAKE_COMMAND};-E;echo;" + OUTPUT_VARIABLE shields_target_cmd +) + +add_custom_target(shields ${shields_target_cmd} USES_TERMINAL) diff --git a/cmake/modules/soc.cmake b/cmake/modules/soc.cmake new file mode 100644 index 0000000000000..48ea3736e7160 --- /dev/null +++ b/cmake/modules/soc.cmake @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2021, Nordic Semiconductor ASA + +# Configure SoC settings based on Kconfig settings and SoC root. +# +# This CMake module will set the following variables in the build system based +# on Kconfig settings and selected SoC. +# +# If no implementation is available for the selected SoC an error will be raised. +# +# Outcome: +# The following variables will be defined when this CMake module completes: +# +# - SOC_NAME: Name of the SoC in use, identical to CONFIG_SOC +# - SOC_SERIES: Name of the SoC series in use, identical to CONFIG_SOC_SERIES +# - SOC_FAMILY: Name of the SoC family, identical to CONFIG_SOC_FAMILY +# - SOC_PATH: Path fragment defined by either SOC_NAME or SOC_FAMILY/SOC_SERIES. +# - SOC_DIR: Directory containing the SoC implementation +# +# Variable dependencies: +# - SOC_ROOT: CMake list of SoC roots containing SoC implementations +# +# Cmake module dependencies: +# - kconfig CMake module. + +include_guard(GLOBAL) + +# 'SOC_ROOT' is a prioritized list of directories where socs may be +# found. It always includes ${ZEPHYR_BASE}/soc at the lowest priority. +list(APPEND SOC_ROOT ${ZEPHYR_BASE}) + +set(SOC_NAME ${CONFIG_SOC}) +set(SOC_SERIES ${CONFIG_SOC_SERIES}) +set(SOC_TOOLCHAIN_NAME ${CONFIG_SOC_TOOLCHAIN_NAME}) +set(SOC_FAMILY ${CONFIG_SOC_FAMILY}) + +if("${SOC_SERIES}" STREQUAL "") + set(SOC_PATH ${SOC_NAME}) +else() + set(SOC_PATH ${SOC_FAMILY}/${SOC_SERIES}) +endif() + +# Use SOC to search for a 'CMakeLists.txt' file. +# e.g. zephyr/soc/xtense/intel_apl_adsp/CMakeLists.txt. +foreach(root ${SOC_ROOT}) + # Check that the root looks reasonable. + if(NOT IS_DIRECTORY "${root}/soc") + message(WARNING "\nSOC_ROOT element(s) without a 'soc' subdirectory: +${root} +Hints: + - if your SoC family directory is '/foo/bar/soc//my_soc_family', then add '/foo/bar' to SOC_ROOT, not the entire SoC family path + - if in doubt, use absolute paths\n") + endif() + + if(EXISTS ${root}/soc/${ARCH}/${SOC_PATH}) + set(SOC_DIR ${root}/soc) + break() + endif() +endforeach() + +if(NOT SOC_DIR) + message(FATAL_ERROR "Could not find SOC=${SOC_NAME} for BOARD=${BOARD},\n" + "please check your installation.\n" + "SOC roots searched:\n" + "${SOC_ROOT}\n" + ) +endif() diff --git a/cmake/target_toolchain.cmake b/cmake/modules/target_toolchain.cmake similarity index 92% rename from cmake/target_toolchain.cmake rename to cmake/modules/target_toolchain.cmake index 0d8bbc2d32d0c..9c9d4d8d74387 100644 --- a/cmake/target_toolchain.cmake +++ b/cmake/modules/target_toolchain.cmake @@ -1,5 +1,11 @@ # SPDX-License-Identifier: Apache-2.0 +include_guard(GLOBAL) + +# Prevent CMake from testing the toolchain +set(CMAKE_C_COMPILER_FORCED 1) +set(CMAKE_CXX_COMPILER_FORCED 1) + # No official documentation exists for the "Generic" value, except their wiki. # # https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/CrossCompiling: @@ -56,5 +62,5 @@ add_custom_target(bintools) include(${TOOLCHAIN_ROOT}/cmake/compiler/${COMPILER}/target.cmake OPTIONAL) include(${TOOLCHAIN_ROOT}/cmake/linker/${LINKER}/target.cmake OPTIONAL) -include(${CMAKE_CURRENT_LIST_DIR}/bintools/bintools_template.cmake) +include(${ZEPHYR_BASE}/cmake/bintools/bintools_template.cmake) include(${TOOLCHAIN_ROOT}/cmake/bintools/${BINTOOLS}/target.cmake OPTIONAL) diff --git a/subsys/testsuite/unittest.cmake b/cmake/modules/unittest.cmake similarity index 100% rename from subsys/testsuite/unittest.cmake rename to cmake/modules/unittest.cmake diff --git a/cmake/modules/user_cache.cmake b/cmake/modules/user_cache.cmake new file mode 100644 index 0000000000000..d3f401e33948d --- /dev/null +++ b/cmake/modules/user_cache.cmake @@ -0,0 +1,96 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2021, Nordic Semiconductor ASA + +# Configure user cache directory. +# +# The user cache can be used for caching of data that should be persistent +# across builds to speed up CMake configure / build system generation and/or +# compilation. +# +# Only data that can be safely re-generated should be placed in this cache. +# +# Zephyr build system uses this user cache to store Zephyr compiler check +# results which significantly improve toolchain testing performance. +# See https://github.com/zephyrproject-rtos/zephyr/pull/7102 for details. +# +# Outcome: +# The following variables will be defined when this CMake module completes: +# +# - USER_CACHE_DIR: User cache directory in use. +# +# CMake module dependencies: +# - python CMake module. + +include_guard(GLOBAL) + +# Dependencies of this module. +include(python) + +function(find_appropriate_cache_directory dir) + set(env_suffix_LOCALAPPDATA .cache) + + if(CMAKE_HOST_APPLE) + # On macOS, ~/Library/Caches is the preferred cache directory. + set(env_suffix_HOME Library/Caches) + else() + set(env_suffix_HOME .cache) + endif() + + # Determine which env vars should be checked + if(CMAKE_HOST_APPLE) + set(dirs HOME) + elseif(CMAKE_HOST_WIN32) + set(dirs LOCALAPPDATA) + else() + # Assume Linux when we did not detect 'mac' or 'win' + # + # On Linux, freedesktop.org recommends using $XDG_CACHE_HOME if + # that is defined and defaulting to $HOME/.cache otherwise. + set(dirs + XDG_CACHE_HOME + HOME + ) + endif() + + foreach(env_var ${dirs}) + if(DEFINED ENV{${env_var}}) + set(env_dir $ENV{${env_var}}) + + set(test_user_dir ${env_dir}/${env_suffix_${env_var}}) + + execute_process(COMMAND ${PYTHON_EXECUTABLE} + ${ZEPHYR_BASE}/scripts/dir_is_writeable.py ${test_user_dir} + RESULT_VARIABLE writable_result + ) + if("${writable_result}" STREQUAL "0") + # The directory is write-able + set(user_dir ${test_user_dir}) + break() + else() + # The directory was not writeable, keep looking for a suitable + # directory + endif() + endif() + endforeach() + + # Populate local_dir with a suitable directory for caching + # files. Prefer a directory outside of the git repository because it + # is good practice to have clean git repositories. + if(DEFINED user_dir) + # Zephyr's cache files go in the "zephyr" subdirectory of the + # user's cache directory. + set(local_dir ${user_dir}/zephyr) + else() + set(local_dir ${ZEPHYR_BASE}/.cache) + endif() + + set(${dir} ${local_dir} PARENT_SCOPE) +endfunction() + +# Populate USER_CACHE_DIR with a directory that user applications may +# write cache files to. +if(NOT DEFINED USER_CACHE_DIR) + find_appropriate_cache_directory(USER_CACHE_DIR) +endif() +message(STATUS "Cache files will be written to: ${USER_CACHE_DIR}") diff --git a/cmake/verify-toolchain.cmake b/cmake/modules/verify-toolchain.cmake similarity index 99% rename from cmake/verify-toolchain.cmake rename to cmake/modules/verify-toolchain.cmake index 7dce062d5046d..06a01b7abb261 100644 --- a/cmake/verify-toolchain.cmake +++ b/cmake/modules/verify-toolchain.cmake @@ -15,6 +15,8 @@ # it takes the following arguments: # FORMAT=json: Print the output as a json formatted string, useful for Python +include_guard(GLOBAL) + # This is the minimum required Zephyr-SDK version which supports CMake package set(TOOLCHAIN_ZEPHYR_MINIMUM_REQUIRED_VERSION 0.13.1) diff --git a/cmake/version.cmake b/cmake/modules/version.cmake similarity index 90% rename from cmake/version.cmake rename to cmake/modules/version.cmake index 326a33ca2a271..666adc3e4bd53 100644 --- a/cmake/version.cmake +++ b/cmake/modules/version.cmake @@ -26,6 +26,11 @@ # See also: independent and more dynamic ``BUILD_VERSION`` in # ``git.cmake``. +# Note: version.cmake is loaded multiple times by ZephyrConfigVersion.cmake to +# determine this Zephyr package version and thus the correct Zephyr CMake +# package to load. +# Therefore `version.cmake` should not use include_guard(GLOBAL). +# The final load of `version.cmake` will setup correct build version values. include(${ZEPHYR_BASE}/cmake/hex.cmake) file(READ ${ZEPHYR_BASE}/VERSION ver) diff --git a/cmake/west.cmake b/cmake/modules/west.cmake similarity index 98% rename from cmake/west.cmake rename to cmake/modules/west.cmake index 79479ae1316b9..cffeb35b18d23 100644 --- a/cmake/west.cmake +++ b/cmake/modules/west.cmake @@ -1,5 +1,10 @@ # SPDX-License-Identifier: Apache-2.0 +include_guard(GLOBAL) + +# Dependencies of this module. +include(python) + # west is an optional dependency. We need to run west using the same # Python interpreter as everything else, though, so we play some extra # tricks. diff --git a/cmake/modules/zephyr_default.cmake b/cmake/modules/zephyr_default.cmake new file mode 100644 index 0000000000000..b42f0f31c71b9 --- /dev/null +++ b/cmake/modules/zephyr_default.cmake @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: Apache-2.0 +# +# Copyright (c) 2021, Nordic Semiconductor ASA + +# This CMake module will load all Zephyr CMake modules in correct order for +# default Zephyr build system. +# +# Outcome: +# See individual CMake module descriptions + +include_guard(GLOBAL) + +# The code line below defines the real minimum supported CMake version. +# +# Unfortunately CMake requires the toplevel CMakeLists.txt file to define the +# required version, not even invoking it from a CMake module is sufficient. +# It is however permitted to have multiple invocations of cmake_minimum_required. +cmake_minimum_required(VERSION 3.20.0) + +message(STATUS "Application: ${APPLICATION_SOURCE_DIR}") + +find_package(ZephyrBuildConfiguration + QUIET NO_POLICY_SCOPE + NAMES ZephyrBuild + PATHS ${ZEPHYR_BASE}/../* + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_PACKAGE_REGISTRY + NO_CMAKE_SYSTEM_PATH + NO_CMAKE_SYSTEM_PACKAGE_REGISTRY +) + +# Load Zephyr extensions +include(extensions) +include(git) +include(version) # depends on hex.cmake + +# +# Find tools +# + +include(python) +include(west) +include(ccache) + +# Load default root settings +include(root) + +# +# Find Zephyr modules. +# Those may contain additional DTS, BOARD, SOC, ARCH ROOTs. +# Also create the Kconfig binary dir for generated Kconf files. +# +include(zephyr_module) + +include(boards) +include(shields) +include(arch) +include(build_configuration) + +include(user_cache) +include(verify-toolchain) +include(host-tools) + +# Include board specific device-tree flags before parsing. +include(${BOARD_DIR}/pre_dt_board OPTIONAL) + +# DTS should be close to kconfig because CONFIG_ variables from +# kconfig and dts should be available at the same time. +# +# The DT system uses a C preprocessor for it's code generation needs. +# This creates an awkward chicken-and-egg problem, because we don't +# always know exactly which toolchain the user needs until we know +# more about the target, e.g. after DT and Kconfig. +# +# To resolve this we find "some" C toolchain, configure it generically +# with the minimal amount of configuration needed to have it +# preprocess DT sources, and then, after we have finished processing +# both DT and Kconfig we complete the target-specific configuration, +# and possibly change the toolchain. +include(generic_toolchain) +include(dts) +include(kconfig) +include(soc) +include(target_toolchain) +include(kernel) diff --git a/cmake/zephyr_module.cmake b/cmake/modules/zephyr_module.cmake similarity index 77% rename from cmake/zephyr_module.cmake rename to cmake/modules/zephyr_module.cmake index 21850f908fa12..31c40af5e606d 100644 --- a/cmake/zephyr_module.cmake +++ b/cmake/modules/zephyr_module.cmake @@ -1,19 +1,25 @@ # SPDX-License-Identifier: Apache-2.0 +include_guard(GLOBAL) + +# Dependencies of this module. +include(extensions) +include(python) + # This cmake file provides functionality to import CMakeLists.txt and Kconfig # files for Zephyr modules into Zephyr build system. # -# CMakeLists.txt and Kconfig files can reside directly in the module or in a -# MODULE_EXT_ROOT. +# CMakeLists.txt and Kconfig files can reside directly in the Zephyr module or +# in a MODULE_EXT_ROOT. # The `/zephyr/module.yml` file specifies whether the build files are -# located in the module or in a MODULE_EXT_ROOT. +# located in the Zephyr module or in a MODULE_EXT_ROOT. # # A list of Zephyr modules can be provided to the build system using: # -DZEPHYR_MODULES=[;] # # It looks for: /zephyr/module.yml or # /zephyr/CMakeLists.txt -# to load the module into Zephyr build system. +# to load the Zephyr module into Zephyr build system. # If west is available, it uses `west list` to obtain a list of projects to # search for zephyr/module.yml # @@ -23,6 +29,17 @@ # - `ZEPHYR__KCONFIG` is used for inclusion of the Kconfig # files into the build system. +# Settings used by Zephyr module but where systems may define an alternative value. +set_ifndef(KCONFIG_BINARY_DIR ${CMAKE_BINARY_DIR}/Kconfig) + +if(ZEPHYR_EXTRA_MODULES) + # ZEPHYR_EXTRA_MODULES has either been specified on the cmake CLI or is + # already in the CMakeCache.txt. This has precedence over the environment + # variable ZEPHYR_EXTRA_MODULES +elseif(DEFINED ENV{ZEPHYR_EXTRA_MODULES}) + set(ZEPHYR_EXTRA_MODULES $ENV{ZEPHYR_EXTRA_MODULES}) +endif() + if(ZEPHYR_MODULES) set(ZEPHYR_MODULES_ARG "--modules" ${ZEPHYR_MODULES}) endif() @@ -31,6 +48,7 @@ if(ZEPHYR_EXTRA_MODULES) set(ZEPHYR_EXTRA_MODULES_ARG "--extra-modules" ${ZEPHYR_EXTRA_MODULES}) endif() +file(MAKE_DIRECTORY ${KCONFIG_BINARY_DIR}) set(KCONFIG_MODULES_FILE ${KCONFIG_BINARY_DIR}/Kconfig.modules) set(ZEPHYR_SETTINGS_FILE ${CMAKE_BINARY_DIR}/zephyr_settings.txt) @@ -69,17 +87,13 @@ if(WEST OR ZEPHYR_MODULES) # lazy regexes (it supports greedy only). string(REGEX REPLACE "\"(.*)\":\".*\"" "\\1" key ${setting}) string(REGEX REPLACE "\".*\":\"(.*)\"" "\\1" value ${setting}) - # MODULE_EXT_ROOT is process order which means module roots processed - # later wins. To ensure ZEPHYR_BASE stays first, and command line settings - # are processed last, we insert at position 1. - if ("${key}" STREQUAL "MODULE_EXT_ROOT") - list(INSERT ${key} 1 ${value}) - else() - list(APPEND ${key} ${value}) - endif() + list(APPEND ${key} ${value}) endforeach() endif() + # Append ZEPHYR_BASE as a default ext root at lowest priority + list(APPEND MODULE_EXT_ROOT ${ZEPHYR_BASE}) + if(EXISTS ${CMAKE_BINARY_DIR}/zephyr_modules.txt) file(STRINGS ${CMAKE_BINARY_DIR}/zephyr_modules.txt ZEPHYR_MODULES_TXT ENCODING UTF-8) @@ -94,6 +108,9 @@ if(WEST OR ZEPHYR_MODULES) endforeach() endif() + # MODULE_EXT_ROOT is process order which means Zephyr module roots processed + # later wins. therefore we reverse the list before processing. + list(REVERSE MODULE_EXT_ROOT) foreach(root ${MODULE_EXT_ROOT}) if(NOT EXISTS ${root}) message(FATAL_ERROR "No `modules.cmake` found in module root `${root}`.") @@ -105,8 +122,8 @@ if(WEST OR ZEPHYR_MODULES) if(DEFINED ZEPHYR_MODULES_TXT) foreach(module ${ZEPHYR_MODULES_TXT}) # Match "":"" for each line of file, each corresponding to - # one module. The use of quotes is required due to CMake not supporting - # lazy regexes (it supports greedy only). + # one Zephyr module. The use of quotes is required due to CMake not + # supporting lazy regexes (it supports greedy only). string(CONFIGURE ${module} module) string(REGEX REPLACE "\"(.*)\":\".*\":\".*\"" "\\1" module_name ${module}) string(REGEX REPLACE "\".*\":\"(.*)\":\".*\"" "\\1" module_path ${module}) @@ -126,7 +143,7 @@ ${MODULE_NAME_UPPER} is a restricted name for Zephyr modules as it is used for \ else() file(WRITE ${KCONFIG_MODULES_FILE} - "# No west and no modules\n" + "# No west and no Zephyr modules\n" ) endif() diff --git a/cmake/shields.cmake b/cmake/shields.cmake deleted file mode 100644 index 2ea062bdc6038..0000000000000 --- a/cmake/shields.cmake +++ /dev/null @@ -1,18 +0,0 @@ -if(CMAKE_SCRIPT_MODE_FILE AND NOT CMAKE_PARENT_LIST_FILE) - # This file was invoked as a script directly with -P: - # cmake -P shields.cmake - # - # Unlike boards.cmake, this takes no OUTPUT_FILE option, but - # SHIELD_LIST_SPACE_SEPARATED is required. - list(SORT SHIELD_LIST) - foreach(shield ${SHIELD_LIST}) - message("${shield}") - endforeach() -else() - # This file was included into usage.cmake. - set(sorted_shield_list ${SHIELD_LIST}) - list(SORT sorted_shield_list) - foreach(shield ${sorted_shield_list}) - list(APPEND sorted_shield_cmds COMMAND ${CMAKE_COMMAND} -E echo "${shield}") - endforeach() -endif() diff --git a/cmake/usage/CMakeLists.txt b/cmake/usage/CMakeLists.txt index 88ccbd7984371..5205b71353bc1 100644 --- a/cmake/usage/CMakeLists.txt +++ b/cmake/usage/CMakeLists.txt @@ -1,15 +1,5 @@ # SPDX-License-Identifier: Apache-2.0 -include (${ZEPHYR_BASE}/cmake/shields.cmake) -include (${ZEPHYR_BASE}/cmake/boards.cmake) - -# shields.cmake and boards.cmake can be run with cmake -P for printing -# help output on user error when settings BOARD or SHIELD, and -# add_custom_target() is not available in script mode, so we place -# them in here. -add_custom_target(shields ${sorted_shield_cmds} USES_TERMINAL) -add_custom_target(boards ${list_boards_commands} USES_TERMINAL) - add_custom_target( usage ${CMAKE_COMMAND} diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index fd20f6dce5c49..1a8fffb5529f9 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -3,8 +3,7 @@ cmake_minimum_required(VERSION 3.20.0) project(Zephyr-Kernel-Doc LANGUAGES) -set(NO_BOILERPLATE TRUE) -find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} ..) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} .. COMPONENTS doc) file(TO_CMAKE_PATH "${ZEPHYR_BASE}" ZEPHYR_BASE) message(STATUS "Zephyr base: ${ZEPHYR_BASE}") @@ -36,11 +35,6 @@ if(NOT LATEX_PDFLATEX_FOUND OR NOT LATEXMK) message(WARNING "LaTeX components not found. PDF build will not be available.") endif() -include(${ZEPHYR_BASE}/cmake/python.cmake) - -# Find west to (optionally) process modules for Kconfig -find_program(WEST west) - #------------------------------------------------------------------------------- # Environment & Paths @@ -103,11 +97,6 @@ set_target_properties( # kconfig set(KCONFIG_BINARY_DIR ${CMAKE_BINARY_DIR}/Kconfig) -list(INSERT MODULE_EXT_ROOT 0 ${ZEPHYR_BASE}) -file(MAKE_DIRECTORY ${KCONFIG_BINARY_DIR}) - -include(${ZEPHYR_BASE}/cmake/extensions.cmake) -include(${ZEPHYR_BASE}/cmake/zephyr_module.cmake) foreach(module_name ${ZEPHYR_MODULE_NAMES}) zephyr_string(SANITIZE TOUPPER MODULE_NAME_UPPER ${module_name}) diff --git a/drivers/gpio/CMakeLists.txt b/drivers/gpio/CMakeLists.txt index 32412257a2fd7..af23733f36831 100644 --- a/drivers/gpio/CMakeLists.txt +++ b/drivers/gpio/CMakeLists.txt @@ -30,6 +30,7 @@ zephyr_library_sources_ifdef(CONFIG_GPIO_SAM4L gpio_sam4l.c) zephyr_library_sources_ifdef(CONFIG_GPIO_SX1509B gpio_sx1509b.c) zephyr_library_sources_ifdef(CONFIG_GPIO_INTEL gpio_intel.c) zephyr_library_sources_ifdef(CONFIG_GPIO_STELLARIS gpio_stellaris.c) +zephyr_library_sources_ifdef(CONFIG_GPIO_RPI_PICO gpio_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_GPIO_RV32M1 gpio_rv32m1.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LMP90XXX gpio_lmp90xxx.c) zephyr_library_sources_ifdef(CONFIG_GPIO_LITEX gpio_litex.c) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index ccec99316a9d6..7ff6931a3717b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -77,6 +77,8 @@ source "drivers/gpio/Kconfig.xec" source "drivers/gpio/Kconfig.stellaris" +source "drivers/gpio/Kconfig.rpi_pico" + source "drivers/gpio/Kconfig.rv32m1" source "drivers/gpio/Kconfig.lmp90xxx" diff --git a/drivers/gpio/Kconfig.rpi_pico b/drivers/gpio/Kconfig.rpi_pico new file mode 100644 index 0000000000000..8bd1488d74f6c --- /dev/null +++ b/drivers/gpio/Kconfig.rpi_pico @@ -0,0 +1,10 @@ +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +# Workaround for not being able to have commas in macro arguments +DT_COMPAT_RPI_PICO_GPIO := raspberrypi,pico-gpio + +config GPIO_RPI_PICO + default $(dt_compat_enabled,$(DT_COMPAT_RPI_PICO_GPIO)) + select PICOSDK_USE_GPIO + bool "Raspberry Pi Pico GPIO driver" diff --git a/drivers/gpio/gpio_rpi_pico.c b/drivers/gpio/gpio_rpi_pico.c new file mode 100644 index 0000000000000..e66673c6cb337 --- /dev/null +++ b/drivers/gpio/gpio_rpi_pico.c @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2021, Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* pico-sdk includes */ +#include +#include +#include + +#include "gpio_utils.h" + +#define DT_DRV_COMPAT raspberrypi_pico_gpio + +#define ALL_EVENTS (GPIO_IRQ_EDGE_FALL | GPIO_IRQ_EDGE_RISE \ + | GPIO_IRQ_LEVEL_LOW | GPIO_IRQ_LEVEL_HIGH) + +struct gpio_rpi_config { + struct gpio_driver_config common; + void (*bank_config_func)(void); +}; + +struct gpio_rpi_data { + struct gpio_driver_data common; + sys_slist_t callbacks; + uint32_t int_enabled_mask; +}; + +static int gpio_rpi_configure(const struct device *dev, + gpio_pin_t pin, + gpio_flags_t flags) +{ + if (flags & GPIO_SINGLE_ENDED) { + return -ENOTSUP; + } + + gpio_init(pin); + + if (flags & GPIO_OUTPUT) { + gpio_set_dir(pin, GPIO_OUT); + + if (flags & GPIO_OUTPUT_INIT_HIGH) { + gpio_put(pin, 1); + } else if (flags & GPIO_OUTPUT_INIT_LOW) { + gpio_put(pin, 0); + } + } else if (flags & GPIO_INPUT) { + gpio_set_dir(pin, GPIO_IN); + if (flags & GPIO_PULL_UP) { + gpio_pull_up(pin); + } else if (flags & GPIO_PULL_DOWN) { + gpio_pull_down(pin); + } + } + + return 0; +} + +static int gpio_rpi_port_get_raw(const struct device *dev, uint32_t *value) +{ + *value = gpio_get_all(); + return 0; +} + +static int gpio_rpi_port_set_masked_raw(const struct device *port, + uint32_t mask, uint32_t value) +{ + gpio_put_masked(mask, value); + return 0; +} + +static int gpio_rpi_port_set_bits_raw(const struct device *port, + uint32_t pins) +{ + gpio_set_mask(pins); + return 0; +} + +static int gpio_rpi_port_clear_bits_raw(const struct device *port, + uint32_t pins) +{ + gpio_clr_mask(pins); + return 0; +} + +static int gpio_rpi_port_toggle_bits(const struct device *port, + uint32_t pins) +{ + gpio_xor_mask(pins); + return 0; +} + +static int gpio_rpi_pin_interrupt_configure(const struct device *dev, + gpio_pin_t pin, + enum gpio_int_mode mode, + enum gpio_int_trig trig) +{ + struct gpio_rpi_data *data = dev->data; + uint32_t events = 0; + + if (mode != GPIO_INT_DISABLE) { + if (mode & GPIO_INT_EDGE) { + if (trig & GPIO_INT_LOW_0) { + events |= GPIO_IRQ_EDGE_FALL; + } + if (trig & GPIO_INT_HIGH_1) { + events |= GPIO_IRQ_EDGE_RISE; + } + } else { + if (trig & GPIO_INT_LOW_0) { + events |= GPIO_IRQ_LEVEL_LOW; + } + if (trig & GPIO_INT_HIGH_1) { + events |= GPIO_IRQ_LEVEL_HIGH; + } + } + gpio_set_irq_enabled(pin, events, true); + } + WRITE_BIT(data->int_enabled_mask, pin, mode != GPIO_INT_DISABLE); + return 0; +} + +static int gpio_rpi_manage_callback(const struct device *dev, + struct gpio_callback *callback, bool set) +{ + struct gpio_rpi_data *data = dev->data; + + return gpio_manage_callback(&data->callbacks, callback, set); +} + +static const struct gpio_driver_api gpio_rpi_driver_api = { + .pin_configure = gpio_rpi_configure, + .port_get_raw = gpio_rpi_port_get_raw, + .port_set_masked_raw = gpio_rpi_port_set_masked_raw, + .port_set_bits_raw = gpio_rpi_port_set_bits_raw, + .port_clear_bits_raw = gpio_rpi_port_clear_bits_raw, + .port_toggle_bits = gpio_rpi_port_toggle_bits, + .pin_interrupt_configure = gpio_rpi_pin_interrupt_configure, + .manage_callback = gpio_rpi_manage_callback, +}; + +static void gpio_rpi_isr(const struct device *dev) +{ + struct gpio_rpi_data *data = dev->data; + io_irq_ctrl_hw_t *irq_ctrl_base; + const io_rw_32 *status_reg; + uint32_t events; + uint32_t pin; + + irq_ctrl_base = &iobank0_hw->proc0_irq_ctrl; + for (pin = 0; pin < NUM_BANK0_GPIOS; pin++) { + status_reg = &irq_ctrl_base->ints[pin / 8]; + events = (*status_reg >> 4 * (pin % 8)) & ALL_EVENTS; + if (events) { + gpio_acknowledge_irq(pin, ALL_EVENTS); + gpio_fire_callbacks(&data->callbacks, dev, BIT(pin)); + } + } +} + +static int gpio_rpi_bank_init(const struct device *dev) +{ + const struct gpio_rpi_config *config = dev->config; + + config->bank_config_func(); + return 0; +} + +#define GPIO_RPI_INIT(idx) \ +static void bank_##idx##_config_func(void) \ +{ \ + IRQ_CONNECT(DT_INST_IRQN(idx), DT_INST_IRQ(idx, priority), \ + gpio_rpi_isr, DEVICE_DT_INST_GET(idx), 0); \ + irq_enable(DT_INST_IRQN(idx)); \ +} \ +static const struct gpio_rpi_config gpio_rpi_##idx##_config = { \ + .bank_config_func = bank_##idx##_config_func, \ +}; \ + \ +static struct gpio_rpi_data gpio_rpi_##idx##_data; \ + \ +DEVICE_DT_INST_DEFINE(idx, gpio_rpi_bank_init, NULL, \ + &gpio_rpi_##idx##_data, \ + &gpio_rpi_##idx##_config, \ + POST_KERNEL, CONFIG_GPIO_INIT_PRIORITY, \ + &gpio_rpi_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(GPIO_RPI_INIT) diff --git a/drivers/pinctrl/CMakeLists.txt b/drivers/pinctrl/CMakeLists.txt index a14936b479dd8..79d0eaa6b372a 100644 --- a/drivers/pinctrl/CMakeLists.txt +++ b/drivers/pinctrl/CMakeLists.txt @@ -7,4 +7,5 @@ zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AF pinctrl_gd32_af.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_GD32_AFIO pinctrl_gd32_afio.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_NRF pinctrl_nrf.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_RCAR_PFC pfc_rcar.c) +zephyr_library_sources_ifdef(CONFIG_PINCTRL_RPI_PICO pinctrl_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_PINCTRL_STM32 pinctrl_stm32.c) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 8162329175028..8680acc3234ec 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -32,6 +32,7 @@ config PINCTRL_DYNAMIC source "drivers/pinctrl/Kconfig.gd32" source "drivers/pinctrl/Kconfig.nrf" source "drivers/pinctrl/Kconfig.rcar" +source "drivers/pinctrl/Kconfig.rpi_pico" source "drivers/pinctrl/Kconfig.stm32" endif # PINCTRL diff --git a/drivers/pinctrl/Kconfig.rpi_pico b/drivers/pinctrl/Kconfig.rpi_pico new file mode 100644 index 0000000000000..066e05eb0f516 --- /dev/null +++ b/drivers/pinctrl/Kconfig.rpi_pico @@ -0,0 +1,12 @@ +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +DT_COMPAT_RPI_PICO_PINCTRL := raspberrypi,pico-pinctrl + +config PINCTRL_RPI_PICO + bool "RaspberryPi Pico pin controller driver" + depends on SOC_FAMILY_RPI_PICO + default $(dt_compat_enabled,$(DT_COMPAT_RPI_PICO_PINCTRL)) + select PICOSDK_USE_GPIO + help + RaspberryPi Pico pinctrl driver diff --git a/drivers/pinctrl/pinctrl_rpi_pico.c b/drivers/pinctrl/pinctrl_rpi_pico.c new file mode 100644 index 0000000000000..8a51cd4e6b8b9 --- /dev/null +++ b/drivers/pinctrl/pinctrl_rpi_pico.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +/* pico-sdk includes */ +#include + +static void pinctrl_configure_pin(const pinctrl_soc_pin_t *pin) +{ + gpio_init(pin->pin_num); + gpio_set_function(pin->pin_num, pin->alt_func); + gpio_set_pulls(pin->pin_num, pin->pullup, pin->pulldown); + gpio_set_drive_strength(pin->pin_num, pin->drive_strength); + gpio_set_slew_rate(pin->pin_num, (pin->slew_rate ? + GPIO_SLEW_RATE_FAST : GPIO_SLEW_RATE_SLOW)); + gpio_set_input_hysteresis_enabled(pin->pin_num, pin->schmitt_enable); + gpio_set_input_enabled(pin->pin_num, pin->input_enable); +} + +int pinctrl_configure_pins(const pinctrl_soc_pin_t *pins, uint8_t pin_cnt, + uintptr_t reg) +{ + ARG_UNUSED(reg); + + for (uint8_t i = 0U; i < pin_cnt; i++) { + pinctrl_configure_pin(pins++); + } + + return 0; +} diff --git a/drivers/serial/CMakeLists.txt b/drivers/serial/CMakeLists.txt index acb5195d73a4a..5eef4eab5ff77 100644 --- a/drivers/serial/CMakeLists.txt +++ b/drivers/serial/CMakeLists.txt @@ -32,6 +32,7 @@ zephyr_library_sources_ifdef(CONFIG_UART_SAM0 uart_sam0.c) zephyr_library_sources_ifdef(CONFIG_UART_PSOC6 uart_psoc6.c) zephyr_library_sources_ifdef(CONFIG_UART_PL011 uart_pl011.c) zephyr_library_sources_ifdef(CONFIG_UART_RV32M1_LPUART uart_rv32m1_lpuart.c) +zephyr_library_sources_ifdef(CONFIG_UART_RPI_PICO uart_rpi_pico.c) zephyr_library_sources_ifdef(CONFIG_UART_LITEUART uart_liteuart.c) zephyr_library_sources_ifdef(CONFIG_UART_RTT_DRIVER uart_rtt.c) zephyr_library_sources_ifdef(CONFIG_UART_XLNX_PS uart_xlnx_ps.c) diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 2455174ae4280..3d110543d92f1 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -159,6 +159,8 @@ source "drivers/serial/Kconfig.pl011" source "drivers/serial/Kconfig.rv32m1_lpuart" +source "drivers/serial/Kconfig.rpi_pico" + source "drivers/serial/Kconfig.litex" source "drivers/serial/Kconfig.rtt" diff --git a/drivers/serial/Kconfig.rpi_pico b/drivers/serial/Kconfig.rpi_pico new file mode 100644 index 0000000000000..bab871be581b0 --- /dev/null +++ b/drivers/serial/Kconfig.rpi_pico @@ -0,0 +1,11 @@ +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +# Workaround for not being able to have commas in macro arguments +DT_COMPAT_RPI_PICO_UART := raspberrypi,pico-uart + +config UART_RPI_PICO + bool "Raspberry Pi UART driver" + default $(dt_compat_enabled,$(DT_COMPAT_RPI_PICO_UART)) + select SERIAL_HAS_DRIVER + select PICOSDK_USE_UART diff --git a/drivers/serial/uart_rpi_pico.c b/drivers/serial/uart_rpi_pico.c new file mode 100644 index 0000000000000..b0f4e28034545 --- /dev/null +++ b/drivers/serial/uart_rpi_pico.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021, Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +/* pico-sdk includes */ +#include + +#define DT_DRV_COMPAT raspberrypi_pico_uart + +struct uart_rpi_config { + uart_inst_t *const uart_dev; + uint32_t baudrate; + const struct pinctrl_dev_config *pcfg; +}; + +static int uart_rpi_poll_in(const struct device *dev, unsigned char *c) +{ + const struct uart_rpi_config *config = dev->config; + + if (!uart_is_readable(config->uart_dev)) { + return -1; + } + + *c = (unsigned char)uart_get_hw(config->uart_dev)->dr; + return 0; +} + +static void uart_rpi_poll_out(const struct device *dev, unsigned char c) +{ + const struct uart_rpi_config *config = dev->config; + + uart_putc_raw(config->uart_dev, c); +} + +static int uart_rpi_init(const struct device *dev) +{ + const struct uart_rpi_config *config = dev->config; + int ret; + + ret = pinctrl_apply_state(config->pcfg, PINCTRL_STATE_DEFAULT); + if (ret < 0) { + return ret; + } + + uart_init(config->uart_dev, config->baudrate); + + return 0; +} + +static const struct uart_driver_api uart_rpi_driver_api = { + .poll_in = uart_rpi_poll_in, + .poll_out = uart_rpi_poll_out, +}; + +#define RPI_UART_INIT(idx) \ + PINCTRL_DT_INST_DEFINE(idx); \ + static const struct uart_rpi_config uart_rpi_cfg_##idx = { \ + .uart_dev = (uart_inst_t *)DT_INST_REG_ADDR(idx), \ + .baudrate = DT_INST_PROP(idx, current_speed), \ + .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(idx), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(idx, &uart_rpi_init, \ + NULL, \ + NULL, \ + &uart_rpi_cfg_##idx, PRE_KERNEL_1, \ + CONFIG_SERIAL_INIT_PRIORITY, \ + &uart_rpi_driver_api); + +DT_INST_FOREACH_STATUS_OKAY(RPI_UART_INIT) diff --git a/dts/arm/rpi_pico/rp2040.dtsi b/dts/arm/rpi_pico/rp2040.dtsi new file mode 100644 index 0000000000000..72d6efeb712c5 --- /dev/null +++ b/dts/arm/rpi_pico/rp2040.dtsi @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include "rpi_pico_common.dtsi" + +/ { + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-m0+"; + reg = <0>; + }; + + cpu1: cpu@1 { + compatible = "arm,cortex-m0+"; + reg = <1>; + }; + }; + + soc { + sram0: memory@20000000 { + compatible = "mmio-sram"; + reg = <0x20000000 DT_SIZE_K(264)>; + }; + + flash0: flash@10000000 { + compatible = "soc-nv-flash"; + label = "FLASH_RP2"; + + write-block-size = <1>; + }; + + peripheral_clk: peripheral-clk { + compatible = "fixed-clock"; + clock-frequency = <125000000>; + #clock-cells = <0>; + }; + + pinctrl: pin-controller@40014000 { + compatible = "raspberrypi,pico-pinctrl"; + reg = <0x40014000 DT_SIZE_K(4)>; + status = "okay"; + label = "PINCTRL"; + }; + + gpio0: gpio@40014000 { + compatible = "raspberrypi,pico-gpio"; + reg = <0x40014000 DT_SIZE_K(4)>; + interrupts = <13 RPI_PICO_DEFAULT_IRQ_PRIORITY>; + gpio-controller; + #gpio-cells = <2>; + label = "GPIO_0"; + status = "disabled"; + }; + + uart0: uart@40034000 { + compatible = "raspberrypi,pico-uart"; + reg = <0x40034000 DT_SIZE_K(4)>; + clocks = <&peripheral_clk>; + interrupts = <20 RPI_PICO_DEFAULT_IRQ_PRIORITY>; + interrupt-names = "uart0"; + label = "UART_0"; + status = "disabled"; + }; + + uart1: uart@40038000 { + compatible = "raspberrypi,pico-uart"; + reg = <0x40038000 DT_SIZE_K(4)>; + clocks = <&peripheral_clk>; + interrupts = <21 RPI_PICO_DEFAULT_IRQ_PRIORITY>; + interrupt-names = "uart1"; + label = "UART_1"; + status = "disabled"; + }; + }; +}; + +&nvic { + arm,num-irq-priority-bits = <3>; +}; diff --git a/dts/arm/rpi_pico/rpi_pico_common.dtsi b/dts/arm/rpi_pico/rpi_pico_common.dtsi new file mode 100644 index 0000000000000..738cae8e7ae45 --- /dev/null +++ b/dts/arm/rpi_pico/rpi_pico_common.dtsi @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef RPI_PICO_DEFAULT_IRQ_PRIORITY +#define RPI_PICO_DEFAULT_IRQ_PRIORITY 3 +#endif diff --git a/dts/bindings/gpio/raspberrypi,pico-gpio.yaml b/dts/bindings/gpio/raspberrypi,pico-gpio.yaml new file mode 100644 index 0000000000000..ab987ecb75889 --- /dev/null +++ b/dts/bindings/gpio/raspberrypi,pico-gpio.yaml @@ -0,0 +1,22 @@ +# Copyright (c) 2021, Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +description: Raspberry Pi Pico GPIO + +compatible: "raspberrypi,pico-gpio" + +include: [gpio-controller.yaml, base.yaml] + +properties: + reg: + required: true + + label: + required: true + + "#gpio-cells": + const: 2 + +gpio-cells: + - pin + - flags diff --git a/dts/bindings/pinctrl/raspberrypi,pico-pinctrl.yaml b/dts/bindings/pinctrl/raspberrypi,pico-pinctrl.yaml new file mode 100644 index 0000000000000..dbd43713dea2c --- /dev/null +++ b/dts/bindings/pinctrl/raspberrypi,pico-pinctrl.yaml @@ -0,0 +1,123 @@ +# Copyright (c) 2021 Teslabs Engineering S.L. +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +description: | + The RPi Pico pin controller is a node responsible for controlling + pin function selection and pin properties, such as routing a UART0 Rx + to pin 1 and enabling the pullup resistor on that pin. + + The node has the 'pinctrl' node label set in your SoC's devicetree, + so you can modify it like this: + + &pinctrl { + /* your modifications go here */ + }; + + All device pin configurations should be placed in child nodes of the + 'pinctrl' node, as shown in this example: + + /* You can put this in places like a board-pinctrl.dtsi file in + * your board directory, or a devicetree overlay in your application. + */ + + /* include pre-defined combinations for the SoC variant used by the board */ + #include + + &pinctrl { + /* configuration for the usart0 "default" state */ + uart0_default: uart0_default { + /* group 1 */ + group1 { + /* configure P0 as UART0 TX */ + pinmux = ; + }; + /* group 2 */ + group2 { + /* configure P1 as UART0 RX */ + pinmux = ; + /* enable input on pin 1 */ + input-enable; + }; + }; + }; + + The 'uart0_default' child node encodes the pin configurations for a + particular state of a device; in this case, the default (that is, active) + state. + + As shown, pin configurations are organized in groups within each child node. + Each group can specify a list of pin function selections in the 'pinmux' + property. + + A group can also specify shared pin properties common to all the specified + pins, such as the 'input-enable' property in group 2. Here is a list of + supported standard pin properties: + + - bias-disable: Disable pull-up/down (default, not required). + - bias-pull-up: Enable pull-up resistor. + - bias-pull-down: Enable pull-down resistor. + - input-enable: Enable input from the pin. + - input-schmitt-enable: Enable input hysteresys. + - drive-strength: Set the drive strength of the pin, in milliamps. Possible + values are: 2, 4, 8, 12 (default: 4mA) + - slew-rate: If set to 0, slew rate is set to slow. If set to 1, it is set + to fast. + + To link pin configurations with a device, use a pinctrl-N property for some + number N, like this example you could place in your board's DTS file: + + #include "board-pinctrl.dtsi" + + &uart0 { + pinctrl-0 = <&uart0_default>; + pinctrl-1 = <&uart0_sleep>; + pinctrl-names = "default", "sleep"; + }; + +compatible: "raspberrypi,pico-pinctrl" + +include: + - name: base.yaml + - name: pincfg-node-group.yaml + child-binding: + child-binding: + property-allowlist: + - bias-disable + - bias-pull-down + - bias-pull-up + - input-enable + - input-schmitt-enable + - drive-strength + - slew-rate + +child-binding: + description: | + Definitions for a pinctrl state. + child-binding: + properties: + pinmux: + required: true + type: array + description: | + An array of pins sharing the same group properties. Each + element of the array is an integer constructed from the + pin number and the alternative function of the pin. + drive-strength: + enum: + - 2 + - 4 + - 8 + - 12 + default: 4 + description: | + The drive strength of a pin, in mA. The default value is 4mA, as this + is the power on reset value. + slew-rate: + enum: + - 0 + - 1 + default: 0 + description: | + The slew rate of a pin. 0 corresponds to slow, and 1 corresponds to fast. + The default value is 0 (slow), as this is the power on reset value. diff --git a/dts/bindings/serial/raspberrypi,pico-uart.yaml b/dts/bindings/serial/raspberrypi,pico-uart.yaml new file mode 100644 index 0000000000000..50c3bd44d741e --- /dev/null +++ b/dts/bindings/serial/raspberrypi,pico-uart.yaml @@ -0,0 +1,12 @@ +description: Raspberry Pi Pico UART + +compatible: "raspberrypi,pico-uart" + +include: [uart-controller.yaml, pinctrl-device.yaml] + +properties: + reg: + required: true + + interrupts: + required: true diff --git a/include/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h b/include/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h new file mode 100644 index 0000000000000..b01637c34f83f --- /dev/null +++ b/include/dt-bindings/pinctrl/rpi-pico-rp2040-pinctrl.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __RP2040_PINCTRL_H__ +#define __RP2040_PINCTRL_H__ + +#define PINCTRL_GPIO_FUNC_XIP 0 +#define PINCTRL_GPIO_FUNC_SPI 1 +#define PINCTRL_GPIO_FUNC_UART 2 +#define PINCTRL_GPIO_FUNC_I2C 3 +#define PINCTRL_GPIO_FUNC_PWM 4 +#define PINCTRL_GPIO_FUNC_SIO 5 +#define PINCTRL_GPIO_FUNC_PIO0 6 +#define PINCTRL_GPIO_FUNC_PIO1 7 +#define PINCTRL_GPIO_FUNC_GPCK 8 +#define PINCTRL_GPIO_FUNC_USB 9 +#define PINCTRL_GPIO_FUNC_NULL 0xf + +#define ALT_FUNC_POS 0 +#define ALT_FUNC_MASK 0xf + +#define PIN_NUM_POS 4 +#define PIN_NUM_MASK 0x1f + +#define RP2040_PINMUX(pin_num, alt_func) (pin_num << PIN_NUM_POS | \ + alt_func << ALT_FUNC_POS) + +#define UART0_TX_P0 RP2040_PINMUX(0, PINCTRL_GPIO_FUNC_UART) +#define UART0_RX_P1 RP2040_PINMUX(1, PINCTRL_GPIO_FUNC_UART) +#define UART0_CTS_P2 RP2040_PINMUX(2, PINCTRL_GPIO_FUNC_UART) +#define UART0_RTS_P3 RP2040_PINMUX(3, PINCTRL_GPIO_FUNC_UART) +#define UART1_TX_P4 RP2040_PINMUX(4, PINCTRL_GPIO_FUNC_UART) +#define UART1_RX_P5 RP2040_PINMUX(5, PINCTRL_GPIO_FUNC_UART) +#define UART1_CTS_P6 RP2040_PINMUX(6, PINCTRL_GPIO_FUNC_UART) +#define UART1_RTS_P7 RP2040_PINMUX(7, PINCTRL_GPIO_FUNC_UART) +#define UART1_TX_P8 RP2040_PINMUX(8, PINCTRL_GPIO_FUNC_UART) +#define UART1_RX_P9 RP2040_PINMUX(9, PINCTRL_GPIO_FUNC_UART) +#define UART1_CTS_P10 RP2040_PINMUX(10, PINCTRL_GPIO_FUNC_UART) +#define UART1_RTS_P11 RP2040_PINMUX(11, PINCTRL_GPIO_FUNC_UART) +#define UART0_TX_P12 RP2040_PINMUX(12, PINCTRL_GPIO_FUNC_UART) +#define UART0_RX_P13 RP2040_PINMUX(13, PINCTRL_GPIO_FUNC_UART) +#define UART0_CTS_P14 RP2040_PINMUX(14, PINCTRL_GPIO_FUNC_UART) +#define UART0_RTS_P15 RP2040_PINMUX(15, PINCTRL_GPIO_FUNC_UART) +#define UART0_TX_P16 RP2040_PINMUX(16, PINCTRL_GPIO_FUNC_UART) +#define UART0_RX_P17 RP2040_PINMUX(17, PINCTRL_GPIO_FUNC_UART) +#define UART0_CTS_P18 RP2040_PINMUX(18, PINCTRL_GPIO_FUNC_UART) +#define UART0_RTS_P19 RP2040_PINMUX(19, PINCTRL_GPIO_FUNC_UART) +#define UART1_TX_P20 RP2040_PINMUX(20, PINCTRL_GPIO_FUNC_UART) +#define UART1_RX_P21 RP2040_PINMUX(21, PINCTRL_GPIO_FUNC_UART) +#define UART1_CTS_P22 RP2040_PINMUX(22, PINCTRL_GPIO_FUNC_UART) +#define UART1_RTS_P23 RP2040_PINMUX(23, PINCTRL_GPIO_FUNC_UART) +#define UART1_TX_P24 RP2040_PINMUX(24, PINCTRL_GPIO_FUNC_UART) +#define UART1_RX_P25 RP2040_PINMUX(25, PINCTRL_GPIO_FUNC_UART) +#define UART1_CTS_P26 RP2040_PINMUX(26, PINCTRL_GPIO_FUNC_UART) +#define UART1_RTS_P27 RP2040_PINMUX(27, PINCTRL_GPIO_FUNC_UART) +#define UART0_TX_P28 RP2040_PINMUX(28, PINCTRL_GPIO_FUNC_UART) +#define UART0_RX_P29 RP2040_PINMUX(29, PINCTRL_GPIO_FUNC_UART) + +#endif /* __RP2040_PINCTRL_H__ */ diff --git a/modules/hal_rpi_pico/CMakeLists.txt b/modules/hal_rpi_pico/CMakeLists.txt new file mode 100644 index 0000000000000..28269f033a054 --- /dev/null +++ b/modules/hal_rpi_pico/CMakeLists.txt @@ -0,0 +1,49 @@ +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_HAS_RPI_PICO) + zephyr_library() + + set(rp2_common_dir ${ZEPHYR_HAL_RPI_PICO_MODULE_DIR}/src/rp2_common) + set(rp2040_dir ${ZEPHYR_HAL_RPI_PICO_MODULE_DIR}/src/rp2040) + set(common_dir ${ZEPHYR_HAL_RPI_PICO_MODULE_DIR}/src/common) + set(boot_stage_dir ${rp2_common_dir}/boot_stage2) + + # Pico sources and headers necessary for every build. + # These contain definitions and implementation used mostly for + # initializing the SoC, and therefore are always required. + + zephyr_library_sources( + ${rp2_common_dir}/hardware_clocks/clocks.c + ${rp2_common_dir}/hardware_pll/pll.c + ${rp2_common_dir}/hardware_xosc/xosc.c + ${rp2_common_dir}/hardware_watchdog/watchdog.c + ${rp2_common_dir}/pico_platform/platform.c + ) + + zephyr_include_directories( + ${rp2_common_dir}/hardware_base/include + ${rp2_common_dir}/hardware_clocks/include + ${rp2_common_dir}/hardware_watchdog/include + ${rp2_common_dir}/hardware_xosc/include + ${rp2_common_dir}/hardware_pll/include + ${rp2_common_dir}/hardware_irq/include + ${rp2_common_dir}/hardware_sync/include + ${rp2_common_dir}/hardware_timer/include + ${rp2_common_dir}/hardware_resets/include + ${rp2040_dir}/hardware_regs/include + ${rp2040_dir}/hardware_structs/include + ${common_dir}/pico_base/include + ${rp2_common_dir}/pico_platform/include + ${CMAKE_CURRENT_LIST_DIR} + ) + + zephyr_library_sources_ifdef(CONFIG_PICOSDK_USE_GPIO + ${rp2_common_dir}/hardware_gpio/gpio.c) + zephyr_include_directories_ifdef(CONFIG_PICOSDK_USE_GPIO + ${rp2_common_dir}/hardware_gpio/include) + + zephyr_library_sources_ifdef(CONFIG_PICOSDK_USE_UART + ${rp2_common_dir}/hardware_uart/uart.c) + zephyr_include_directories_ifdef(CONFIG_PICOSDK_USE_UART + ${rp2_common_dir}/hardware_uart/include) +endif() diff --git a/modules/hal_rpi_pico/Kconfig b/modules/hal_rpi_pico/Kconfig new file mode 100644 index 0000000000000..ebbe5b831977b --- /dev/null +++ b/modules/hal_rpi_pico/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +config HAS_RPI_PICO + bool + +config PICOSDK_USE_UART + bool + help + Use the UART driver from pico-sdk + +config PICOSDK_USE_GPIO + bool + help + Use the GPIO driver from pico-sdk diff --git a/modules/hal_rpi_pico/pico/config_autogen.h b/modules/hal_rpi_pico/pico/config_autogen.h new file mode 100644 index 0000000000000..95f4f52fff0cd --- /dev/null +++ b/modules/hal_rpi_pico/pico/config_autogen.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _CONFIG_AUTOGEN_H_ +#define _CONFIG_AUTOGEN_H_ + +/* WORKAROUNDS */ + +/* Use Zephyr's __asm macro instead of pico-sdk's asm */ +#define asm __asm + +/* pico-sdk uses static assertions, which fail the compilation */ +#define static_assert(...) + +/** + * pico-sdk expects __CONCAT to be defined, but we can't use + * Zephyr's sys/cdefs.h because this file is also included in + * assembly files. Therefore, we have to manually define __CONCAT + * only when it isn't defined, to avoid a conflict. + */ +#ifndef __CONCAT +#define __CAT(a, b) a ## b +#define __CONCAT(a, b) __CAT(a, b) +#endif /* __CONCAT */ + +/* Disable binary info */ +#define PICO_NO_BINARY_INFO 1 + +/* Zephyr compatible way of forcing inline */ +#ifndef __always_inline +#define __always_inline inline __attribute__((__always_inline__)) +#endif /* __always_inline */ + +/** + * Undefine the MHZ and KHZ defined by Zephyr, as they conflict + * with pico-sdk's definitions in clocks.h. + */ +#undef KHZ +#undef MHZ + +#endif diff --git a/modules/hal_rpi_pico/pico/version.h b/modules/hal_rpi_pico/pico/version.h new file mode 100644 index 0000000000000..00ea81156cb43 --- /dev/null +++ b/modules/hal_rpi_pico/pico/version.h @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2021, Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/* File intentionally left blank. It's expected by pico-sdk, but isn't used. */ diff --git a/samples/boards/rpi_pico/boot_stage2/CMakeLists.txt b/samples/boards/rpi_pico/boot_stage2/CMakeLists.txt new file mode 100644 index 0000000000000..76e074c68a080 --- /dev/null +++ b/samples/boards/rpi_pico/boot_stage2/CMakeLists.txt @@ -0,0 +1,75 @@ +# +# Copyright (c) 2022 Nordic Semiconductor ASA +# +# SPDX-License-Identifier: Apache-2.0 +# + +cmake_minimum_required(VERSION 3.20.0) + +# This is not a Zephyr sample, but a minimal stage2 bootloader. +# However, we reuse the Zephyr build infrastructure for Zephyr modules, +# board processing, toolchain and other related tools +# List of Zephyr CMake modules required. +set(zephyr_cmake_modules extensions west root zephyr_module boards shields arch + build_configuration host-tools generic_toolchain kconfig soc target_toolchain +) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE} COMPONENTS ${zephyr_cmake_modules}) +project(rpi_boot2) + +enable_language(C CXX ASM) + +# Test the toolchain. +zephyr_check_compiler_flag(C "" toolchain_is_ok) +assert(toolchain_is_ok "The toolchain is unable to build a dummy C file. See CMakeError.log.") + +# Load flash and friends. +add_subdirectory(${ZEPHYR_BASE}/cmake/flash flash) + +set(rp2_common_dir ${ZEPHYR_HAL_RPI_PICO_MODULE_DIR}/src/rp2_common) +set(rp2040_dir ${ZEPHYR_HAL_RPI_PICO_MODULE_DIR}/src/rp2040) +set(common_dir ${ZEPHYR_HAL_RPI_PICO_MODULE_DIR}/src/common) +set(boot_stage_dir ${rp2_common_dir}/boot_stage2) + +# Compile the second stage bootloader + +add_executable(boot_stage2) + +target_sources_ifdef(CONFIG_RP2_FLASH_W25Q080 boot_stage2 PRIVATE + ${boot_stage_dir}/boot2_w25q080.S) +target_sources_ifdef(CONFIG_RP2_FLASH_GENERIC_03H boot_stage2 PRIVATE + ${boot_stage_dir}/boot2_generic_03h.S) +target_sources_ifdef(CONFIG_RP2_FLASH_IS25LP080 boot_stage2 PRIVATE + ${boot_stage_dir}/boot2_is25lp080.S) +target_sources_ifdef(CONFIG_RP2_FLASH_W25X10CL boot_stage2 PRIVATE + ${boot_stage_dir}/boot2_w25x10cl.S) + +target_include_directories(boot_stage2 PUBLIC + ${ZEPHYR_BASE}/modules/hal_rpi_pico + ${boot_stage_dir}/asminclude + ${rp2_common_dir}/pico_platform/include + ${rp2040_dir}/hardware_regs/include + ${common_dir}/pico_base/include + ) + +target_link_options(boot_stage2 PRIVATE + "-nostartfiles" + "--specs=nosys.specs" + "LINKER:--script=${boot_stage_dir}/boot_stage2.ld" + ) + +# Generates a binary file from the compiled bootloader +add_custom_target(bootloader_bin ALL DEPENDS boot_stage2.bin) +add_custom_command(OUTPUT boot_stage2.bin + DEPENDS boot_stage2 + COMMAND ${CMAKE_OBJCOPY} -Obinary $ boot_stage2.bin + ) + +# @yonsh I assume you still will need to pad checksum, and then convert the +# final result to a hex or bin file before flashing, correct ? +# Checksums the binary, pads it, and generates an assembly file +#add_custom_target(boot_stage2_asm ALL DEPENDS boot_stage2.S) +#add_custom_command(OUTPUT boot_stage2.S +# DEPENDS boot_stage2.bin +# COMMAND ${Python3_EXECUTABLE} ${boot_stage_dir}/pad_checksum +# -s 0xffffffff boot_stage2.bin boot_stage2.S) diff --git a/samples/boards/rpi_pico/boot_stage2/prj.conf b/samples/boards/rpi_pico/boot_stage2/prj.conf new file mode 100644 index 0000000000000..b95f805a06e27 --- /dev/null +++ b/samples/boards/rpi_pico/boot_stage2/prj.conf @@ -0,0 +1 @@ +CONFIG_UART_CONSOLE=n diff --git a/scripts/checkpatch/typedefsfile b/scripts/checkpatch/typedefsfile index 7e030b5b97b00..ef5109b14747f 100644 --- a/scripts/checkpatch/typedefsfile +++ b/scripts/checkpatch/typedefsfile @@ -3,3 +3,4 @@ k_mem_partition_attr_t mbedtls_pk_context z_arch_esf_t pinctrl_soc_pin_t +io_rw_32 diff --git a/scripts/pylib/twister/twisterlib.py b/scripts/pylib/twister/twisterlib.py index 512b6f51ad692..980e7cf181967 100755 --- a/scripts/pylib/twister/twisterlib.py +++ b/scripts/pylib/twister/twisterlib.py @@ -3025,7 +3025,7 @@ def get_all_tests(self): @staticmethod def get_toolchain(): - toolchain_script = Path(ZEPHYR_BASE) / Path('cmake/verify-toolchain.cmake') + toolchain_script = Path(ZEPHYR_BASE) / Path('cmake/modules/verify-toolchain.cmake') result = CMake.run_cmake_script([toolchain_script, "FORMAT=json"]) try: diff --git a/share/zephyr-package/cmake/ZephyrConfig.cmake b/share/zephyr-package/cmake/ZephyrConfig.cmake index 7c1e6212ba7bc..22e5089d56ad8 100644 --- a/share/zephyr-package/cmake/ZephyrConfig.cmake +++ b/share/zephyr-package/cmake/ZephyrConfig.cmake @@ -11,17 +11,48 @@ # It will be empty if not set in environment. macro(include_boilerplate location) + list(PREPEND CMAKE_MODULE_PATH ${ZEPHYR_BASE}/cmake/modules) if(ZEPHYR_UNITTEST) + message(WARNING "The ZephyrUnittest CMake package has been deprecated.\n" + "ZephyrUnittest has been replaced with Zephyr CMake module 'unittest' \n" + "and can be loaded as: 'find_package(Zephyr COMPONENTS unittest)'" + ) set(ZephyrUnittest_FOUND True) - set(BOILERPLATE_FILE ${ZEPHYR_BASE}/subsys/testsuite/unittest.cmake) + set(Zephyr_FIND_COMPONENTS unittest) else() set(Zephyr_FOUND True) - set(BOILERPLATE_FILE ${ZEPHYR_BASE}/cmake/app/boilerplate.cmake) endif() + if(NOT DEFINED APPLICATION_SOURCE_DIR) + set(APPLICATION_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH + "Application Source Directory" + ) + endif() + + if(NOT DEFINED APPLICATION_BINARY_DIR) + set(APPLICATION_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE PATH + "Application Binary Directory" + ) + endif() + + set(__build_dir ${APPLICATION_BINARY_DIR}/zephyr) + set(PROJECT_BINARY_DIR ${__build_dir}) + if(NOT NO_BOILERPLATE) - message("Including boilerplate (${location}): ${BOILERPLATE_FILE}") - include(${BOILERPLATE_FILE} NO_POLICY_SCOPE) + list(LENGTH Zephyr_FIND_COMPONENTS components_length) + if(components_length EQUAL 0) + message("Loading Zephyr default modules (${location}).") + include(zephyr_default NO_POLICY_SCOPE) + else() + message("Loading Zephyr module(s) (${location}): ${Zephyr_FIND_COMPONENTS}") + foreach(component ${Zephyr_FIND_COMPONENTS}) + include(${component}) + endforeach() + endif() + else() + message(WARNING "The NO_BOILERPLATE setting has been deprecated.\n" + "Please use: 'find_package(Zephyr COMPONENTS )'" + ) endif() endmacro() diff --git a/share/zephyr-package/cmake/ZephyrConfigVersion.cmake b/share/zephyr-package/cmake/ZephyrConfigVersion.cmake index 9292f0a58ea4e..5b9472b1ebb9e 100644 --- a/share/zephyr-package/cmake/ZephyrConfigVersion.cmake +++ b/share/zephyr-package/cmake/ZephyrConfigVersion.cmake @@ -56,7 +56,7 @@ if((DEFINED ZEPHYR_BASE) OR (DEFINED ENV_ZEPHYR_BASE)) # We are the Zephyr to be used set(NO_PRINT_VERSION True) - include(${ZEPHYR_BASE}/cmake/version.cmake) + include(${ZEPHYR_BASE}/cmake/modules/version.cmake) # Zephyr uses project version, but CMake package uses PACKAGE_VERSION set(PACKAGE_VERSION ${PROJECT_VERSION}) check_zephyr_version() @@ -93,7 +93,7 @@ set(ZEPHYR_BASE ${CURRENT_ZEPHYR_DIR}) # Tell version.cmake to not print as printing version for all Zephyr installations being tested # will lead to confusion on which is being used. set(NO_PRINT_VERSION True) -include(${ZEPHYR_BASE}/cmake/version.cmake) +include(${ZEPHYR_BASE}/cmake/modules/version.cmake) # Zephyr uses project version, but CMake package uses PACKAGE_VERSION set(PACKAGE_VERSION ${PROJECT_VERSION}) set(ZEPHYR_BASE) diff --git a/soc/arm/rpi_pico/CMakeLists.txt b/soc/arm/rpi_pico/CMakeLists.txt new file mode 100644 index 0000000000000..226f3bd626f61 --- /dev/null +++ b/soc/arm/rpi_pico/CMakeLists.txt @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory(${SOC_SERIES}) diff --git a/soc/arm/rpi_pico/Kconfig b/soc/arm/rpi_pico/Kconfig new file mode 100644 index 0000000000000..7d0f4215aad3f --- /dev/null +++ b/soc/arm/rpi_pico/Kconfig @@ -0,0 +1,18 @@ +# Raspberry Pi (RP) MCU line + +# Copyright (c) 2021 Nordic Semiconductor ASA +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +config SOC_FAMILY_RPI_PICO + bool + +if SOC_FAMILY_RPI_PICO + +config SOC_FAMILY + string + default "rpi_pico" + +source "soc/arm/rpi_pico/*/Kconfig.soc" + +endif # SOC_FAMILY_RPI_PICO diff --git a/soc/arm/rpi_pico/Kconfig.defconfig b/soc/arm/rpi_pico/Kconfig.defconfig new file mode 100644 index 0000000000000..468d4545c5b23 --- /dev/null +++ b/soc/arm/rpi_pico/Kconfig.defconfig @@ -0,0 +1,13 @@ +# Raspberry Pi (RP) MCU line + +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if SOC_FAMILY_RPI_PICO + +source "soc/arm/rpi_pico/*/Kconfig.defconfig.series" + +config PINCTRL + default y + +endif # SOC_FAMILY_RPI_PICO diff --git a/soc/arm/rpi_pico/Kconfig.soc b/soc/arm/rpi_pico/Kconfig.soc new file mode 100644 index 0000000000000..d53c18307e0d3 --- /dev/null +++ b/soc/arm/rpi_pico/Kconfig.soc @@ -0,0 +1,6 @@ +# Raspberry Pi (RP) MCU line + +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +source "soc/arm/rpi_pico/*/Kconfig.series" diff --git a/soc/arm/rpi_pico/rp2/CMakeLists.txt b/soc/arm/rpi_pico/rp2/CMakeLists.txt new file mode 100644 index 0000000000000..4f93d41e2068c --- /dev/null +++ b/soc/arm/rpi_pico/rp2/CMakeLists.txt @@ -0,0 +1,9 @@ +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() + +zephyr_library_sources( + soc.c + rp2_init.c + ) diff --git a/soc/arm/rpi_pico/rp2/Kconfig.defconfig.rp2040 b/soc/arm/rpi_pico/rp2/Kconfig.defconfig.rp2040 new file mode 100644 index 0000000000000..a410181900c62 --- /dev/null +++ b/soc/arm/rpi_pico/rp2/Kconfig.defconfig.rp2040 @@ -0,0 +1,8 @@ +# # Raspberry Pi RP2040 MCU + +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config SOC + default "rp2040" + depends on SOC_RP2040 diff --git a/soc/arm/rpi_pico/rp2/Kconfig.defconfig.series b/soc/arm/rpi_pico/rp2/Kconfig.defconfig.series new file mode 100644 index 0000000000000..7df057ae441b1 --- /dev/null +++ b/soc/arm/rpi_pico/rp2/Kconfig.defconfig.series @@ -0,0 +1,17 @@ +# Raspberry Pi RP2XXX MCU line + +# Copyright (c) 2021 Nordic Semiconductor ASA +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +if SOC_SERIES_RP2XXX + +source "soc/arm/rpi_pico/rp2/Kconfig.defconfig.rp2*" + +config SOC_SERIES + default "rp2" + +config NUM_IRQS + default 26 + +endif # SOC_SERIES_RP2XXX diff --git a/soc/arm/rpi_pico/rp2/Kconfig.series b/soc/arm/rpi_pico/rp2/Kconfig.series new file mode 100644 index 0000000000000..0c8c925f347f8 --- /dev/null +++ b/soc/arm/rpi_pico/rp2/Kconfig.series @@ -0,0 +1,18 @@ +# Raspberry Pi RP2XXX MCU line + +# Copyright (c) 2021 Nordic Semiconductor ASA +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +config SOC_SERIES_RP2XXX + bool "Raspberry Pi RP2 series MCU" + select ARM + select CPU_CORTEX_M0PLUS + select CPU_CORTEX_M_HAS_SYSTICK + select CPU_CORTEX_M_HAS_VTOR + select CPU_HAS_ARM_MPU + select SOC_FAMILY_RPI_PICO + select HAS_RPI_PICO + select XIP + help + Enable support for Raspberry Pi RP2 MCU series diff --git a/soc/arm/rpi_pico/rp2/Kconfig.soc b/soc/arm/rpi_pico/rp2/Kconfig.soc new file mode 100644 index 0000000000000..c52478c504c3f --- /dev/null +++ b/soc/arm/rpi_pico/rp2/Kconfig.soc @@ -0,0 +1,28 @@ +# Raspberry Pi RP2XXX MCU line + +# Copyright (c) 2021 Nordic Semiconductor ASA +# Copyright (c) 2021 Yonatan Schachter +# SPDX-License-Identifier: Apache-2.0 + +choice + prompt "RP2xxx MCU Selection" + depends on SOC_SERIES_RP2XXX + +config SOC_RP2040 + bool "Raspberry Pi RP2040" + +endchoice + +# Flash type used by the SoC. The board should select the one used. + +config RP2_FLASH_W25Q080 + bool + +config RP2_FLASH_GENERIC_03H + bool + +config RP2_FLASH_IS25LP080 + bool + +config RP2_FLASH_W25X10CL + bool diff --git a/soc/arm/rpi_pico/rp2/linker.ld b/soc/arm/rpi_pico/rp2/linker.ld new file mode 100644 index 0000000000000..c811fd921e210 --- /dev/null +++ b/soc/arm/rpi_pico/rp2/linker.ld @@ -0,0 +1,22 @@ +/* linker.ld - Linker command/script file */ + +/* + * Copyright (c) 2014 Wind River Systems, Inc. + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +MEMORY +{ + BOOT_FLASH (r) : ORIGIN = 0x10000000, LENGTH = 256 +} + +SECTIONS +{ + .boot2 : { + KEEP(*(.boot2)) + } > BOOT_FLASH +} + +#include diff --git a/soc/arm/rpi_pico/rp2/pinctrl_soc.h b/soc/arm/rpi_pico/rp2/pinctrl_soc.h new file mode 100644 index 0000000000000..bff3cbda11d21 --- /dev/null +++ b/soc/arm/rpi_pico/rp2/pinctrl_soc.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYR_SOC_ARM_RPI_PICO_RP2_PINCTRL_SOC_H_ +#define ZEPHYR_SOC_ARM_RPI_PICO_RP2_PINCTRL_SOC_H_ + +#include + +/** + * @brief Type to hold a pin's pinctrl configuration. + */ +struct rpi_pinctrl_soc_pin { + /** Pin number 0..29 */ + uint32_t pin_num : 5; + /** Alternative function (UART, SPI, etc.) */ + uint32_t alt_func : 4; + /** Maximum current used by a pin, in mA */ + uint32_t drive_strength : 4; + /** Slew rate, may be either false (slow) or true (fast) */ + uint32_t slew_rate : 1; + /** Enable the internal pull up resistor */ + uint32_t pullup : 1; + /** Enable the internal pull down resistor */ + uint32_t pulldown : 1; + /** Enable the pin as an input */ + uint32_t input_enable : 1; + /** Enable the internal schmitt trigger */ + uint32_t schmitt_enable : 1; +}; + +typedef struct rpi_pinctrl_soc_pin pinctrl_soc_pin_t; + +/** + * @brief Utility macro to initialize each pin. + * + * @param node_id Node identifier. + * @param prop Property name. + * @param idx Property entry index. + */ +#define Z_PINCTRL_STATE_PIN_INIT(node_id, prop, idx) \ + { \ + RP2_GET_PIN_NUM(DT_PROP_BY_IDX(node_id, prop, idx)), \ + RP2_GET_PIN_ALT_FUNC(DT_PROP_BY_IDX(node_id, prop, idx)), \ + DT_ENUM_IDX(node_id, drive_strength), \ + DT_ENUM_IDX(node_id, slew_rate), \ + DT_PROP(node_id, bias_pull_up), \ + DT_PROP(node_id, bias_pull_down), \ + DT_PROP(node_id, input_enable), \ + DT_PROP(node_id, input_schmitt_enable), \ + }, + +/** + * @brief Utility macro to initialize state pins contained in a given property. + * + * @param node_id Node identifier. + * @param prop Property name describing state pins. + */ +#define Z_PINCTRL_STATE_PINS_INIT(node_id, prop) \ + {DT_FOREACH_CHILD_VARGS(DT_PHANDLE(node_id, prop), \ + DT_FOREACH_PROP_ELEM, pinmux, \ + Z_PINCTRL_STATE_PIN_INIT)} + +#define RP2_GET_PIN_NUM(pinctrl) \ + (((pinctrl) >> PIN_NUM_POS) & PIN_NUM_MASK) +#define RP2_GET_PIN_ALT_FUNC(pinctrl) \ + (((pinctrl) >> ALT_FUNC_POS) & ALT_FUNC_MASK) + +#endif /* ZEPHYR_SOC_ARM_RPI_PICO_RP2_PINCTRL_SOC_H_ */ diff --git a/soc/arm/rpi_pico/rp2/rp2_init.c b/soc/arm/rpi_pico/rp2/rp2_init.c new file mode 100644 index 0000000000000..0b2db9291af11 --- /dev/null +++ b/soc/arm/rpi_pico/rp2/rp2_init.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void rp2_init(void) +{ + reset_block(~(RESETS_RESET_IO_QSPI_BITS | + RESETS_RESET_PADS_QSPI_BITS | + RESETS_RESET_PLL_USB_BITS | + RESETS_RESET_PLL_SYS_BITS)); + + unreset_block_wait(RESETS_RESET_BITS & ~( + RESETS_RESET_ADC_BITS | + RESETS_RESET_RTC_BITS | + RESETS_RESET_SPI0_BITS | + RESETS_RESET_SPI1_BITS | + RESETS_RESET_UART0_BITS | + RESETS_RESET_UART1_BITS | + RESETS_RESET_USBCTRL_BITS)); + + clocks_init(); + + unreset_block_wait(RESETS_RESET_BITS); +} diff --git a/soc/arm/rpi_pico/rp2/soc.c b/soc/arm/rpi_pico/rp2/soc.c new file mode 100644 index 0000000000000..84f7a9bbd6799 --- /dev/null +++ b/soc/arm/rpi_pico/rp2/soc.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file + * @brief System/hardware module for Raspberry Pi RP2040 family processor + * + * This module provides routines to initialize and support board-level hardware + * for the Raspberry Pi RP2040 family processor. + */ + +#include +#include +#include + + +#ifdef CONFIG_RUNTIME_NMI +extern void z_arm_nmi_init(void); +#define NMI_INIT() z_arm_nmi_init() +#else +#define NMI_INIT() +#endif + +LOG_MODULE_REGISTER(soc, CONFIG_SOC_LOG_LEVEL); + +void rp2_init(void); + +static int rpi_rp2040_init(const struct device *arg) +{ + uint32_t key; + + rp2_init(); + + ARG_UNUSED(arg); + + key = irq_lock(); + + /* Install default handler that simply resets the CPU + * if configured in the kernel, NOP otherwise + */ + NMI_INIT(); + + irq_unlock(key); + + return 0; +} + +SYS_INIT(rpi_rp2040_init, PRE_KERNEL_1, 0); diff --git a/soc/arm/rpi_pico/rp2/soc.h b/soc/arm/rpi_pico/rp2/soc.h new file mode 100644 index 0000000000000..100145df438d8 --- /dev/null +++ b/soc/arm/rpi_pico/rp2/soc.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2016 Linaro Limited + * Copyright (c) 2021 Yonatan Schachter + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @file SoC configuration macros for the Raspberry Pi RP2040 family processors + */ + +#ifndef _RPI_PICO_RP2040_SOC_H_ +#define _RPI_PICO_RP2040_SOC_H_ + +#define __VTOR_PRESENT 1 +#define __MPU_PRESENT 1 + +#endif /* _RPI_PICO_RP2040_SOC_H_ */ diff --git a/west.yml b/west.yml index 1ad354b3dab6e..23d105a602083 100644 --- a/west.yml +++ b/west.yml @@ -113,6 +113,11 @@ manifest: repo-path: hal_quicklogic groups: - hal + - name: hal_rpi_pico + path: modules/hal/rpi_pico + revision: pull/1/head + groups: + - hal - name: hal_silabs revision: be39d4eebeddac6e18e9c0c3ba1b31ad1e82eaed path: modules/hal/silabs