diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e65e6e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +# editors +.vscode +*.swp +*~ + +# python +.venv + +# build +/build* diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d2c2e87 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,7 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# +# This CMake file is picked by the Zephyr build system because it is defined +# as the module CMake entry point (see zephyr/module.yml). + +add_subdirectory(drivers) diff --git a/Kconfig b/Kconfig new file mode 100644 index 0000000..1e908a1 --- /dev/null +++ b/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# +# This Kconfig file is picked by the Zephyr build system because it is defined +# as the module Kconfig entry point (see zephyr/module.yml). You can browse +# module options by going to Zephyr -> Modules in Kconfig. + +rsource "drivers/Kconfig" diff --git a/README.md b/README.md index ccad12e..992e44a 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,58 @@ -# example-application -Example out-of-tree application that is also a module +# Zephyr Example Application + +This repository contains a Zephyr example application. The main purpose of this +repository is to serve as a reference on how to structure Zephyr based +applications. Some of the features demonstrated in this example are: + +- Basic application skeleton +- [Custom boards][board_porting] +- Custom [devicetree bindings][bindings] +- Out-of-tree [drivers][drivers] +- Documentation using Doxygen and Sphinx +- Example CI configuration (using Github Actions) + +[board_porting]: https://docs.zephyrproject.org/latest/guides/porting/board_porting.html +[bindings]: https://docs.zephyrproject.org/latest/guides/dts/bindings.html +[drivers]: https://docs.zephyrproject.org/latest/reference/drivers/index.html + +## Getting Started + +Before getting started, make sure you have a proper Zephyr development +environment. You can follow the official +[Zephyr Getting Started Guide](https://docs.zephyrproject.org/latest/getting_started/index.html). + +### Initialization + +The first step is to initialize the workspace folder (``my-workspace``) where +the ``example-application`` and all Zephyr modules will be cloned. You can do +that by running: + +```shell +# initialize my-workspace for the example-application (main branch) +west init -m https://github.com/zephyrproject-rtos/example-application --mr main my-workspace +# update Zephyr modules +cd my-workspace +west update +``` + +### Build & Run + +The application can be built by running: + +```shell +west build -b $BOARD -s app +``` + +where `$BOARD` is the target board. A sample debug configuration is also +provided. You can apply it by running: + +```shell +west build -b $BOARD -s app -- -DOVERLAY_CONFIG=debug.conf +``` + +Note that you may also use it together with `rtt.conf` if using Segger RTT. Once +you have built the application you can flash it by running: + +```shell +west flash +``` diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt new file mode 100644 index 0000000..8b768ad --- /dev/null +++ b/app/CMakeLists.txt @@ -0,0 +1,15 @@ +#------------------------------------------------------------------------------- +# Zephyr Example Application +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13.1) +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(app LANGUAGES C VERSION 1.0.0) + +configure_file(app_version.h.in ${CMAKE_BINARY_DIR}/app/include/app_version.h) +target_include_directories(app PRIVATE ${CMAKE_BINARY_DIR}/app/include src) + +target_sources(app PRIVATE src/main.c src/foo.c) diff --git a/app/Kconfig b/app/Kconfig new file mode 100644 index 0000000..140eaaf --- /dev/null +++ b/app/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# +# This file is the application Kconfig entry point. All application Kconfig +# options can be defined here or included via other application Kconfig files. +# You can browse these options using the west targets menuconfig (terminal) or +# guiconfig (GUI). + +menu "Zephyr" +source "Kconfig.zephyr" +endmenu + +module = APP +module-str = APP +source "subsys/logging/Kconfig.template.log_config" diff --git a/app/app_version.h.in b/app/app_version.h.in new file mode 100644 index 0000000..cfa55f4 --- /dev/null +++ b/app/app_version.h.in @@ -0,0 +1,29 @@ +/** + * @file app_version.h + * + * Application version information. + * + * Copyright (c) 2021 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef APP_VERSION_H_ +#define APP_VERSION_H_ + +/** Application major version. */ +#define APP_VERSION_MAJOR ${PROJECT_VERSION_MAJOR} +/** Application minor version. */ +#define APP_VERSION_MINOR ${PROJECT_VERSION_MINOR} +/** Application patch version. */ +#define APP_VERSION_PATCH ${PROJECT_VERSION_PATCH} + +/** Application version. */ +#define APP_VERSION \ + ((APP_VERSION_MAJOR << 16) + \ + (APP_VERSION_MINOR << 8) + \ + APP_VERSION_PATCH) + +/** Application version (string). */ +#define APP_VERSION_STR "${PROJECT_VERSION}" + +#endif /* APP_VERSION_H_ */ diff --git a/app/debug.conf b/app/debug.conf new file mode 100644 index 0000000..885971f --- /dev/null +++ b/app/debug.conf @@ -0,0 +1,19 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# +# This is a Kconfig fragment which can be used to enable debug-related options +# in the application. See the README for more details. + +# compiler +CONFIG_DEBUG_OPTIMIZATIONS=y + +# console +CONFIG_CONSOLE=y + +# UART console +CONFIG_SERIAL=y +CONFIG_UART_CONSOLE=y + +# logging +CONFIG_LOG=y +CONFIG_APP_LOG_LEVEL_DBG=y diff --git a/app/prj.conf b/app/prj.conf new file mode 100644 index 0000000..36abcea --- /dev/null +++ b/app/prj.conf @@ -0,0 +1,7 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# +# This file contains selected Kconfig options for the application. + +CONFIG_SENSOR=y +CONFIG_EXAMPLESENSOR=y diff --git a/app/rtt.conf b/app/rtt.conf new file mode 100644 index 0000000..9ccea96 --- /dev/null +++ b/app/rtt.conf @@ -0,0 +1,9 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# +# This is a Kconfig fragment which can be used to enable Segger RTT options. +# It should be used in conjunction with debug.conf. + +# segger RTT console +CONFIG_USE_SEGGER_RTT=y +CONFIG_RTT_CONSOLE=y diff --git a/app/src/foo.c b/app/src/foo.c new file mode 100644 index 0000000..63e2d71 --- /dev/null +++ b/app/src/foo.c @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "foo.h" + +int app_foo_bar(void) +{ + return 0; +} diff --git a/app/src/foo.h b/app/src/foo.h new file mode 100644 index 0000000..34d8e1e --- /dev/null +++ b/app/src/foo.h @@ -0,0 +1,30 @@ +/** + * @file foo.h + * + * Foo API. + * + * Copyright (c) 2021 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef _FOO_H_ +#define _FOO_H_ + +/** + * @defgroup app_foo Foo API + * + * A detailed description of the foo API. + * + * @{ + */ + +/** + * @brief An example foo API call. + * + * @return 0 on success, negative errno otherwise. + */ +int app_foo_bar(void); + +/** @} */ + +#endif /* _FOO_H_ */ diff --git a/app/src/main.c b/app/src/main.c new file mode 100644 index 0000000..158dbee --- /dev/null +++ b/app/src/main.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include "app_version.h" +#include "foo.h" + +#include +LOG_MODULE_REGISTER(main, CONFIG_APP_LOG_LEVEL); + +void main(void) +{ + int ret; + const struct device *sensor; + + printk("Zephyr Example Application %s\n", APP_VERSION_STR); + + ret = app_foo_bar(); + if (ret < 0) { + LOG_ERR("app_foo_bar failed (%d)", ret); + return; + } + + sensor = DEVICE_DT_GET(DT_NODELABEL(examplesensor0)); + if (!device_is_ready(sensor)) { + LOG_ERR("Sensor not ready"); + return; + } + + while (1) { + struct sensor_value val; + + ret = sensor_sample_fetch(sensor); + if (ret < 0) { + LOG_ERR("Could not fetch sample (%d)", ret); + return; + } + + ret = sensor_channel_get(sensor, SENSOR_CHAN_PROX, &val); + if (ret < 0) { + LOG_ERR("Could not get sample (%d)", ret); + return; + } + + printk("Sensor value: %d\n", val.val1); + + k_sleep(K_MSEC(1000)); + } +} + diff --git a/boards/arm/custom_plank/Kconfig b/boards/arm/custom_plank/Kconfig new file mode 100644 index 0000000..8cd0b55 --- /dev/null +++ b/boards/arm/custom_plank/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_ENABLE_DCDC + bool "Enable DCDC mode" + select SOC_DCDC_NRF52X + default y + depends on BOARD_CUSTOM_PLANK diff --git a/boards/arm/custom_plank/Kconfig.board b/boards/arm/custom_plank/Kconfig.board new file mode 100644 index 0000000..51cdc50 --- /dev/null +++ b/boards/arm/custom_plank/Kconfig.board @@ -0,0 +1,6 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config BOARD_CUSTOM_PLANK + bool "Custom Plank Board" + depends on SOC_NRF52840_QIAA diff --git a/boards/arm/custom_plank/Kconfig.defconfig b/boards/arm/custom_plank/Kconfig.defconfig new file mode 100644 index 0000000..114f0ee --- /dev/null +++ b/boards/arm/custom_plank/Kconfig.defconfig @@ -0,0 +1,9 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if BOARD_CUSTOM_PLANK + +config BOARD + default "custom_plank" + +endif # BOARD_CUSTOM_PLANK diff --git a/boards/arm/custom_plank/README.md b/boards/arm/custom_plank/README.md new file mode 100644 index 0000000..f4b868b --- /dev/null +++ b/boards/arm/custom_plank/README.md @@ -0,0 +1,6 @@ +# Custom Plank Board + +`custom_plank` board is used to demonstrate how to create custom boards. It is +in fact a simplified version of the nRF52840-DK board, so the +`example-application` can be run on that development kit when using +`custom_plank`. diff --git a/boards/arm/custom_plank/board.cmake b/boards/arm/custom_plank/board.cmake new file mode 100644 index 0000000..5c6b531 --- /dev/null +++ b/boards/arm/custom_plank/board.cmake @@ -0,0 +1,12 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +board_runner_args(jlink "--device=nrf52" "--speed=4000") +board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000") + +set(OPENOCD_NRF5_SUBFAMILY "nrf52") + +include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake) +include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake) +include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake) +include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake) diff --git a/boards/arm/custom_plank/custom_plank.dts b/boards/arm/custom_plank/custom_plank.dts new file mode 100644 index 0000000..e188102 --- /dev/null +++ b/boards/arm/custom_plank/custom_plank.dts @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +/dts-v1/; +#include + +/ { + model = "Custom Plank Board"; + compatible = "vendor,custom-plank"; + + chosen { + zephyr,console = &uart0; + zephyr,sram = &sram0; + zephyr,flash = &flash0; + }; + + examplesensor0: examplesensor_0 { + compatible = "zephyr,examplesensor"; + label = "EXAMPLESENSOR_0"; + input-gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + }; +}; + +&gpio0 { + status = "okay"; +}; + +&uart0 { + compatible = "nordic,nrf-uarte"; + status = "okay"; + + current-speed = <115200>; + tx-pin = <6>; + rx-pin = <8>; + rts-pin = <5>; + cts-pin = <7>; +}; diff --git a/boards/arm/custom_plank/custom_plank.yaml b/boards/arm/custom_plank/custom_plank.yaml new file mode 100644 index 0000000..071ba3d --- /dev/null +++ b/boards/arm/custom_plank/custom_plank.yaml @@ -0,0 +1,15 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +identifier: custom_plank +name: Custom-Plank +type: mcu +arch: arm +ram: 256 +flash: 1024 +toolchain: + - zephyr + - gnuarmemb + - xtools +supported: + - gpio diff --git a/boards/arm/custom_plank/custom_plank_defconfig b/boards/arm/custom_plank/custom_plank_defconfig new file mode 100644 index 0000000..cff0d09 --- /dev/null +++ b/boards/arm/custom_plank/custom_plank_defconfig @@ -0,0 +1,12 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_SOC_SERIES_NRF52X=y +CONFIG_SOC_NRF52840_QIAA=y +CONFIG_BOARD_CUSTOM_PLANK=y + +CONFIG_ARM_MPU=y +CONFIG_HW_STACK_PROTECTION=y + +CONFIG_GPIO=y +CONFIG_GPIO_AS_PINRESET=y diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt new file mode 100644 index 0000000..183462e --- /dev/null +++ b/drivers/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory_ifdef(CONFIG_SENSOR sensor) diff --git a/drivers/Kconfig b/drivers/Kconfig new file mode 100644 index 0000000..550329c --- /dev/null +++ b/drivers/Kconfig @@ -0,0 +1,6 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +menu "Drivers" +rsource "sensor/Kconfig" +endmenu diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt new file mode 100644 index 0000000..fbb6b45 --- /dev/null +++ b/drivers/sensor/CMakeLists.txt @@ -0,0 +1,4 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +add_subdirectory_ifdef(CONFIG_EXAMPLESENSOR examplesensor) diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig new file mode 100644 index 0000000..23c1966 --- /dev/null +++ b/drivers/sensor/Kconfig @@ -0,0 +1,6 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +if SENSOR +rsource "examplesensor/Kconfig" +endif # SENSOR diff --git a/drivers/sensor/examplesensor/CMakeLists.txt b/drivers/sensor/examplesensor/CMakeLists.txt new file mode 100644 index 0000000..ff3266e --- /dev/null +++ b/drivers/sensor/examplesensor/CMakeLists.txt @@ -0,0 +1,5 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +zephyr_library() +zephyr_library_sources(examplesensor.c) diff --git a/drivers/sensor/examplesensor/Kconfig b/drivers/sensor/examplesensor/Kconfig new file mode 100644 index 0000000..1cb49b2 --- /dev/null +++ b/drivers/sensor/examplesensor/Kconfig @@ -0,0 +1,8 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +config EXAMPLESENSOR + bool "Example sensor" + depends on GPIO + help + Enable example sensor diff --git a/drivers/sensor/examplesensor/examplesensor.c b/drivers/sensor/examplesensor/examplesensor.c new file mode 100644 index 0000000..b2087da --- /dev/null +++ b/drivers/sensor/examplesensor/examplesensor.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021 Nordic Semiconductor ASA + * SPDX-License-Identifier: Apache-2.0 + */ + +#define DT_DRV_COMPAT zephyr_examplesensor + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(examplesensor, CONFIG_SENSOR_LOG_LEVEL); + +struct examplesensor_data { + int state; +}; + +struct examplesensor_config { + struct gpio_dt_spec input; +}; + +static int examplesensor_sample_fetch(const struct device *dev, + enum sensor_channel chan) +{ + const struct examplesensor_config *config = dev->config; + struct examplesensor_data *data = dev->data; + + data->state = gpio_pin_get(config->input.port, config->input.pin); + + return 0; +} + +static int examplesensor_channel_get(const struct device *dev, + enum sensor_channel chan, + struct sensor_value *val) +{ + struct examplesensor_data *data = dev->data; + + if (chan != SENSOR_CHAN_PROX) { + return -ENOTSUP; + } + + val->val1 = data->state; + + return 0; +} + +static const struct sensor_driver_api examplesensor_api = { + .sample_fetch = &examplesensor_sample_fetch, + .channel_get = &examplesensor_channel_get, +}; + +static int examplesensor_init(const struct device *dev) +{ + const struct examplesensor_config *config = dev->config; + + int ret; + + if (!device_is_ready(config->input.port)) { + LOG_ERR("Input GPIO not ready"); + return -ENODEV; + } + + ret = gpio_pin_configure_dt(&config->input, GPIO_INPUT); + if (ret < 0) { + LOG_ERR("Could not configure input GPIO (%d)", ret); + return ret; + } + + return 0; +} + +#define EXAMPLESENSOR_INIT(i) \ + static struct examplesensor_data examplesensor_data_##i; \ + \ + static const struct examplesensor_config examplesensor_config_##i = { \ + .input = GPIO_DT_SPEC_GET(DT_DRV_INST(i), input_gpios), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(i, examplesensor_init, NULL, \ + &examplesensor_data_##i, \ + &examplesensor_config_##i, POST_KERNEL, \ + CONFIG_SENSOR_INIT_PRIORITY, &examplesensor_api); + +DT_INST_FOREACH_STATUS_OKAY(EXAMPLESENSOR_INIT) diff --git a/dts/bindings/sensor/zephyr,examplesensor.yaml b/dts/bindings/sensor/zephyr,examplesensor.yaml new file mode 100644 index 0000000..8b73087 --- /dev/null +++ b/dts/bindings/sensor/zephyr,examplesensor.yaml @@ -0,0 +1,24 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +description: | + An example sensor that reads the GPIO level defined in input-gpios. The + purpose of this sensor is to demonstrate how to create out-of-tree drivers. + + Example definition in devicetree: + + examplesensor { + compatible = "zephyr,examplesensor"; + label = "EXAMPLESENSOR"; + input-gpios = <&gpio0 0 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>; + }; + +compatible: "zephyr,examplesensor" + +include: base.yaml + +properties: + input-gpios: + type: phandle-array + required: true + description: Input GPIO to be sensed. diff --git a/west.yml b/west.yml new file mode 100644 index 0000000..e575f0a --- /dev/null +++ b/west.yml @@ -0,0 +1,16 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +manifest: + self: + path: example-application + + remotes: + - name: zephyrproject-rtos + url-base: https://github.com/zephyrproject-rtos + + projects: + - name: zephyr + remote: zephyrproject-rtos + revision: master + import: true diff --git a/zephyr/module.yml b/zephyr/module.yml new file mode 100644 index 0000000..047032a --- /dev/null +++ b/zephyr/module.yml @@ -0,0 +1,20 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +build: + # Path to the Kconfig file that will be sourced into Zephyr Kconfig tree under + # Zephyr > Modules > example-application. Path is relative from root of this + # repository. + kconfig: Kconfig + # Path to the folder that contains the CMakeLists.txt file to be included by + # Zephyr build system. The `.` is the root of this repository. + cmake: . + settings: + # Additional roots for boards and DTS files. Zephyr will use the + # `/boards` for additional boards. The `.` is the root of this + # repository. + board_root: . + # Zephyr will use the `/dts` for additional dts files and + # `/dts/bindings` for additional dts binding files. The `.` is + # the root of this repository. + dts_root: .