diff --git a/modules/Kconfig b/modules/Kconfig index a1c1ef4bdea..32821908aec 100644 --- a/modules/Kconfig +++ b/modules/Kconfig @@ -54,6 +54,9 @@ comment "hal_nordic module not available." comment "Trusted-firmware-m module not available." depends on !ZEPHYR_TRUSTED_FIRMWARE_M_MODULE +comment "Nanopb module not available." + depends on !ZEPHYR_NANOPB_MODULE + # This ensures that symbols are available in Kconfig for dependency checking # and referencing, while keeping the settings themselves unavailable when the # modules are not present in the workspace diff --git a/modules/nanopb/CMakeLists.txt b/modules/nanopb/CMakeLists.txt new file mode 100644 index 00000000000..7696ae9e118 --- /dev/null +++ b/modules/nanopb/CMakeLists.txt @@ -0,0 +1,61 @@ +# Copyright (c) 2021, Basalte bv +# +# SPDX-License-Identifier: Apache-2.0 + +if(CONFIG_NANOPB) + + set(NANOPB_DIR ${ZEPHYR_CURRENT_MODULE_DIR}) + + find_program(PROTOC protoc) + if(NOT PROTOC) + message(FATAL_ERROR "'protoc' not found, please ensure protoc is installed\ + and in path. See https://docs.zephyrproject.org/latest/samples/modules/nanopb/README.html") + endif() + + set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${NANOPB_DIR}/extra) + find_package(Nanopb REQUIRED) + + zephyr_library() + + zephyr_include_directories(${NANOPB_DIR}) + + zephyr_library_sources( + ${NANOPB_DIR}/pb_common.c + ${NANOPB_DIR}/pb_encode.c + ${NANOPB_DIR}/pb_decode.c + ) + + zephyr_compile_definitions( + PB_MAX_REQUIRED_FIELDS=${CONFIG_NANOPB_MAX_REQUIRED_FIELDS}) + + zephyr_compile_definitions_ifdef( + CONFIG_NANOPB_ENABLE_MALLOC + PB_ENABLE_MALLOC + ) + + zephyr_compile_definitions_ifdef( + CONFIG_NANOPB_NO_ERRMSG + PB_NO_ERRMSG + ) + + zephyr_compile_definitions_ifdef( + CONFIG_NANOPB_BUFFER_ONLY + PB_BUFFER_ONLY + ) + + zephyr_compile_definitions_ifdef( + CONFIG_NANOPB_WITHOUT_64BIT + PB_WITHOUT_64BIT + ) + + zephyr_compile_definitions_ifdef( + CONFIG_NANOPB_ENCODE_ARRAYS_UNPACKED + PB_ENCODE_ARRAYS_UNPACKED + ) + + zephyr_compile_definitions_ifdef( + CONFIG_NANOPB_VALIDATE_UTF8 + PB_VALIDATE_UTF8 + ) + +endif() diff --git a/modules/nanopb/Kconfig b/modules/nanopb/Kconfig new file mode 100644 index 00000000000..f798b1f3be5 --- /dev/null +++ b/modules/nanopb/Kconfig @@ -0,0 +1,59 @@ +# Copyright (c) 2021 Basalte bv +# SPDX-License-Identifier: Apache-2.0 + +config ZEPHYR_NANOPB_MODULE + bool + +menuconfig NANOPB + bool "Nanopb Support" + help + This option enables the Nanopb library and generator. + +if NANOPB + +config NANOPB_ENABLE_MALLOC + bool "Enable malloc usage" + help + This option enables dynamic allocation support in the decoder. + +config NANOPB_MAX_REQUIRED_FIELDS + int "Max number of required fields" + default 64 + help + Maximum number of proto2 required fields to check for presence. + Default and minimum value is 64. + +config NANOPB_NO_ERRMSG + bool "Disable error messages" + help + Disable error message support to save code size. Only error + information is the true/false return value. + +config NANOPB_BUFFER_ONLY + bool "Buffers only" + help + Disable support for custom streams. Only supports encoding and + decoding with memory buffers. Speeds up execution and slightly + decreases code size. + +config NANOPB_WITHOUT_64BIT + bool "Disable 64-bit integer fields" + help + Disable support of 64-bit integer fields, for old compilers or + for a slight speedup on 8-bit platforms. + +config NANOPB_ENCODE_ARRAYS_UNPACKED + bool "Encode arrays unpacked" + help + Encode scalar arrays in the unpacked format, which takes up more + space. + Only to be used when the decoder on the receiving side cannot + process packed arrays, such as protobuf.js versions before 2020. + +config NANOPB_VALIDATE_UTF8 + bool "Validate UTF-8" + help + Check whether incoming strings are valid UTF-8 sequences. + Adds a small performance and code size penalty. + +endif # NANOPB diff --git a/samples/index.rst b/samples/index.rst index 057367e6ee1..c8240fcec2d 100644 --- a/samples/index.rst +++ b/samples/index.rst @@ -24,6 +24,7 @@ Samples and Demos posix/* kernel/* tfm_integration/tfm_integration.rst + modules/* .. comment To add a new sample document, please use the template available under diff --git a/samples/modules/index.rst b/samples/modules/index.rst new file mode 100644 index 00000000000..af42259cb79 --- /dev/null +++ b/samples/modules/index.rst @@ -0,0 +1,10 @@ +.. _module-samples: + +External Module Samples +####################### + +.. toctree:: + :maxdepth: 1 + :glob: + + **/* diff --git a/samples/modules/nanopb/CMakeLists.txt b/samples/modules/nanopb/CMakeLists.txt new file mode 100644 index 00000000000..1f5361af5bb --- /dev/null +++ b/samples/modules/nanopb/CMakeLists.txt @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.13.1) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(nanopb_sample) + +nanopb_generate_cpp(proto_sources proto_headers RELPATH . + src/simple.proto +) +# we need to be able to include generated header files +zephyr_library_include_directories(${CMAKE_CURRENT_BINARY_DIR}) + +FILE(GLOB app_sources src/*.c) +target_sources(app PRIVATE ${proto_sources} ${app_sources}) diff --git a/samples/modules/nanopb/README.rst b/samples/modules/nanopb/README.rst new file mode 100644 index 00000000000..be591738098 --- /dev/null +++ b/samples/modules/nanopb/README.rst @@ -0,0 +1,55 @@ +.. _nanopb_sample: + +Nanopb sample +############# + +Overview +******** + +A simple protocol buffer sample using Nanopb for serializing structured data +to platform independent raw buffers or streams. + + +Requirements +************ + +Nanopb uses the protocol buffer compiler to generate source and header files, +make sure the ``protoc`` executable is intalled and available. + +.. tabs:: + + .. group-tab:: Ubuntu + + Use ``apt`` to install dependency: + + .. code-block:: bash + + sudo apt install protobuf-compiler + + .. group-tab:: macOS + + Use ``brew`` to install dependency: + + .. code-block:: bash + + brew install protobuf + + .. group-tab:: Windows + + Use ``choco`` to install dependency: + + .. code-block:: console + + choco install protoc + +Building and Running +******************** + +This application can be built as follows: + +.. zephyr-app-commands:: + :zephyr-app: samples/modules/nanopb + :host-os: unix + :board: qemu_x86 + :goals: run + :compact: diff --git a/samples/modules/nanopb/prj.conf b/samples/modules/nanopb/prj.conf new file mode 100644 index 00000000000..e7b4094f4c7 --- /dev/null +++ b/samples/modules/nanopb/prj.conf @@ -0,0 +1 @@ +CONFIG_NANOPB=y diff --git a/samples/modules/nanopb/sample.yaml b/samples/modules/nanopb/sample.yaml new file mode 100644 index 00000000000..553cdafb178 --- /dev/null +++ b/samples/modules/nanopb/sample.yaml @@ -0,0 +1,13 @@ +sample: + description: Nanopb sample, with a simple proto + buffer + name: Simple nanopb +common: + harness: console + harness_config: + type: one_line + regex: + - "Your lucky number was 13!" +tests: + sample.modules.nanopb: + tags: samples nanopb diff --git a/samples/modules/nanopb/src/main.c b/samples/modules/nanopb/src/main.c new file mode 100644 index 00000000000..057bd4daff3 --- /dev/null +++ b/samples/modules/nanopb/src/main.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2011 Petteri Aimonen + * Copyright (c) 2021 Basalte bv + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +#include "src/simple.pb.h" + +bool encode_message(uint8_t *buffer, size_t *message_length) +{ + bool status; + + /* Allocate space on the stack to store the message data. + * + * Nanopb generates simple struct definitions for all the messages. + * - check out the contents of simple.pb.h! + * It is a good idea to always initialize your structures + * so that you do not have garbage data from RAM in there. + */ + SimpleMessage message = SimpleMessage_init_zero; + + /* Create a stream that will write to our buffer. */ + pb_ostream_t stream = pb_ostream_from_buffer(buffer, sizeof(buffer)); + + /* Fill in the lucky number */ + message.lucky_number = 13; + + /* Now we are ready to encode the message! */ + status = pb_encode(&stream, SimpleMessage_fields, &message); + *message_length = stream.bytes_written; + + if (!status) { + printk("Encoding failed: %s\n", PB_GET_ERROR(&stream)); + } + + return status; +} + +bool decode_message(uint8_t *buffer, size_t message_length) +{ + bool status; + + /* Allocate space for the decoded message. */ + SimpleMessage message = SimpleMessage_init_zero; + + /* Create a stream that reads from the buffer. */ + pb_istream_t stream = pb_istream_from_buffer(buffer, message_length); + + /* Now we are ready to decode the message. */ + status = pb_decode(&stream, SimpleMessage_fields, &message); + + /* Check for errors... */ + if (status) { + /* Print the data contained in the message. */ + printk("Your lucky number was %d!\n", (int)message.lucky_number); + } else { + printk("Decoding failed: %s\n", PB_GET_ERROR(&stream)); + } + + return status; +} + +void main(void) +{ + /* This is the buffer where we will store our message. */ + uint8_t buffer[SimpleMessage_size]; + size_t message_length; + + /* Encode our message */ + if (!encode_message(buffer, &message_length)) { + return; + } + + /* Now we could transmit the message over network, store it in a file or + * wrap it to a pigeon's leg. + */ + + /* But because we are lazy, we will just decode it immediately. */ + decode_message(buffer, message_length); +} diff --git a/samples/modules/nanopb/src/simple.proto b/samples/modules/nanopb/src/simple.proto new file mode 100644 index 00000000000..f6bc03d9766 --- /dev/null +++ b/samples/modules/nanopb/src/simple.proto @@ -0,0 +1,8 @@ +// A very simple protocol definition, consisting of only +// one message. + +syntax = "proto2"; + +message SimpleMessage { + required int32 lucky_number = 1; +} diff --git a/scripts/requirements-extras.txt b/scripts/requirements-extras.txt index a447190aa61..ee6fa553ea4 100644 --- a/scripts/requirements-extras.txt +++ b/scripts/requirements-extras.txt @@ -17,3 +17,6 @@ Pillow # can be used to sign a Zephyr application binary for consumption by a bootloader imgtool>=1.7.1 + +# used by nanopb module to generate sources from .proto files +protobuf diff --git a/west.yml b/west.yml index 4510b7cf695..ab64a9e5b19 100644 --- a/west.yml +++ b/west.yml @@ -145,6 +145,9 @@ manifest: repo-path: mcuboot path: modules/tee/tfm-mcuboot revision: v1.7.2 + - name: nanopb + path: modules/lib/nanopb + revision: d148bd26718e4c10414f07a7eb1bd24c62e56c5d self: path: zephyr