app: initial application skeleton

initial application skeleton demonstrating:

- custom boards
- custom DT bindings
- Out-of-tree drivers

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
This commit is contained in:
Gerard Marull-Paretas 2021-04-18 20:47:28 +02:00 committed by Anas Nashif
parent 36602d0c70
commit d1c935e55c
31 changed files with 558 additions and 2 deletions

10
.gitignore vendored Normal file
View file

@ -0,0 +1,10 @@
# editors
.vscode
*.swp
*~
# python
.venv
# build
/build*

7
CMakeLists.txt Normal file
View file

@ -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)

8
Kconfig Normal file
View file

@ -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"

View file

@ -1,2 +1,58 @@
# example-application # Zephyr Example Application
Example out-of-tree application that is also a module
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
```

15
app/CMakeLists.txt Normal file
View file

@ -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)

15
app/Kconfig Normal file
View file

@ -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"

29
app/app_version.h.in Normal file
View file

@ -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_ */

19
app/debug.conf Normal file
View file

@ -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

7
app/prj.conf Normal file
View file

@ -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

9
app/rtt.conf Normal file
View file

@ -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

11
app/src/foo.c Normal file
View file

@ -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;
}

30
app/src/foo.h Normal file
View file

@ -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_ */

54
app/src/main.c Normal file
View file

@ -0,0 +1,54 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr.h>
#include <drivers/sensor.h>
#include "app_version.h"
#include "foo.h"
#include <logging/log.h>
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));
}
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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`.

View file

@ -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)

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
/dts-v1/;
#include <nordic/nrf52840_qiaa.dtsi>
/ {
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>;
};

View file

@ -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

View file

@ -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

4
drivers/CMakeLists.txt Normal file
View file

@ -0,0 +1,4 @@
# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
add_subdirectory_ifdef(CONFIG_SENSOR sensor)

6
drivers/Kconfig Normal file
View file

@ -0,0 +1,6 @@
# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
menu "Drivers"
rsource "sensor/Kconfig"
endmenu

View file

@ -0,0 +1,4 @@
# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
add_subdirectory_ifdef(CONFIG_EXAMPLESENSOR examplesensor)

6
drivers/sensor/Kconfig Normal file
View file

@ -0,0 +1,6 @@
# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
if SENSOR
rsource "examplesensor/Kconfig"
endif # SENSOR

View file

@ -0,0 +1,5 @@
# Copyright (c) 2021 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
zephyr_library()
zephyr_library_sources(examplesensor.c)

View file

@ -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

View file

@ -0,0 +1,86 @@
/*
* Copyright (c) 2021 Nordic Semiconductor ASA
* SPDX-License-Identifier: Apache-2.0
*/
#define DT_DRV_COMPAT zephyr_examplesensor
#include <device.h>
#include <drivers/gpio.h>
#include <drivers/sensor.h>
#include <logging/log.h>
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)

View file

@ -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.

16
west.yml Normal file
View file

@ -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

20
zephyr/module.yml Normal file
View file

@ -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
# `<board_root>/boards` for additional boards. The `.` is the root of this
# repository.
board_root: .
# Zephyr will use the `<dts_root>/dts` for additional dts files and
# `<dts_root>/dts/bindings` for additional dts binding files. The `.` is
# the root of this repository.
dts_root: .