This is an automated email from the ASF dual-hosted git repository.

mgorecki pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit fd2a8966fb660338af62c2ef8ca60bce53fd1477
Author: Michal Gorecki <[email protected]>
AuthorDate: Mon Jul 14 14:28:29 2025 +0200

    apps: Add Simple SPI Nanopb example
    
    Application based on example from Nanopb repository.
    Communicates over SPI and shows the basic Nanopb API usage.
---
 apps/nanopb_simple_spi/README.md       |  38 +++++
 apps/nanopb_simple_spi/pkg.yml         |  33 ++++
 apps/nanopb_simple_spi/src/main.c      | 274 +++++++++++++++++++++++++++++++++
 apps/nanopb_simple_spi/src/simple.pb.c |  33 ++++
 apps/nanopb_simple_spi/src/simple.pb.h |  69 +++++++++
 apps/nanopb_simple_spi/syscfg.yml      |  40 +++++
 6 files changed, 487 insertions(+)

diff --git a/apps/nanopb_simple_spi/README.md b/apps/nanopb_simple_spi/README.md
new file mode 100644
index 000000000..0340db823
--- /dev/null
+++ b/apps/nanopb_simple_spi/README.md
@@ -0,0 +1,38 @@
+<!--
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+-->
+
+### Nanopb SPI Simple Example
+
+##### Overview
+********
+
+This application is based on Nanopb example called Simple.
+It contains source and header file generated with Nanopb.
+The header file defines one structure (message) with one int field
+called lucky_number. The application shows how to use basic Nanopb API and
+configures the SPI to send the message and receive it on the other device.
+Two devices are required for this to work:
+1. MASTER - encodes and sends one message per second over the SPI.
+   After sending one message the lucky_number is incremented, encoded
+   and sent again. Toggles the LED after each sent message.
+2. SLAVE - after receiving the message it decodes it and prints
+   the lucky_number value. Toggles the LED after each received
+   message.
diff --git a/apps/nanopb_simple_spi/pkg.yml b/apps/nanopb_simple_spi/pkg.yml
new file mode 100644
index 000000000..7b69743fc
--- /dev/null
+++ b/apps/nanopb_simple_spi/pkg.yml
@@ -0,0 +1,33 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+pkg.name: apps/nanopb_simple_spi
+pkg.type: app
+pkg.description: Nanopb SPI example
+pkg.author: "Apache Mynewt <[email protected]>"
+pkg.homepage: "http://mynewt.apache.org/";
+pkg.keywords:
+
+pkg.deps:
+    - "@apache-mynewt-core/sys/console"
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/sys/config"
+    - "@apache-mynewt-core/sys/log"
+    - "@apache-mynewt-core/sys/stats"
+    - "@apache-mynewt-core/encoding/nanopb"
diff --git a/apps/nanopb_simple_spi/src/main.c 
b/apps/nanopb_simple_spi/src/main.c
new file mode 100644
index 000000000..b5ea52266
--- /dev/null
+++ b/apps/nanopb_simple_spi/src/main.c
@@ -0,0 +1,274 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <console/console.h>
+#include <assert.h>
+#include <pb_decode.h>
+#include <pb_encode.h>
+#include "simple.pb.h"
+#include "os/mynewt.h"
+#include "bsp/bsp.h"
+#include "hal/hal_gpio.h"
+#include "hal/hal_spi.h"
+#include "stats/stats.h"
+#include "config/config.h"
+#ifdef ARCH_sim
+#include <mcu/mcu_sim.h>
+#endif
+
+/* Task 1 */
+#define TASK1_PRIO       (1)
+#define TASK1_STACK_SIZE OS_STACK_ALIGN(1024)
+struct os_task task1;
+
+/* For LED toggling */
+int g_led_pin;
+
+#define SPI_BAUDRATE      500
+#define MESSAGE_BUFF_SIZE 5
+
+#if MYNEWT_VAL(SPI_0_MASTER) || MYNEWT_VAL(SPI_1_MASTER) || 
MYNEWT_VAL(SPI_2_MASTER)
+#define SPI_MASTER 1
+#define SPI_SS_PIN (MYNEWT_VAL(PB_SPI_SS_PIN))
+#if SPI_SS_PIN < 0
+#error "PB_SPI_SS_PIN must be set in the target config."
+#endif
+#define SPI_M_NUM (MYNEWT_VAL(PB_SPI_M_NUM))
+#endif
+
+#if MYNEWT_VAL(SPI_0_SLAVE) || MYNEWT_VAL(SPI_1_SLAVE) || 
MYNEWT_VAL(SPI_2_SLAVE)
+#define SPI_SLAVE 1
+#define SPI_S_NUM (MYNEWT_VAL(PB_SPI_S_NUM))
+#endif
+
+#if defined(SPI_MASTER) && defined(SPI_SLAVE)
+#if SPI_M_NUM == SPI_S_NUM
+#error "SPI_M_NUM and SPI_S_NUM cannot be the same."
+#endif
+#endif
+
+#ifdef SPI_MASTER
+void
+spi_irqm_handler(void *arg, int len)
+{
+    hal_gpio_write(SPI_SS_PIN, 1);
+}
+
+void
+spim_cfg(int spi_num)
+{
+    struct hal_spi_settings my_spi;
+
+    my_spi.data_order = HAL_SPI_MSB_FIRST;
+    my_spi.data_mode = HAL_SPI_MODE0;
+    my_spi.baudrate = SPI_BAUDRATE;
+    my_spi.word_size = HAL_SPI_WORD_SIZE_8BIT;
+    assert(hal_spi_config(spi_num, &my_spi) == 0);
+}
+#endif
+
+#ifdef SPI_SLAVE
+struct os_sem g_spi_sem;
+int32_t g_lucky_number;
+uint8_t g_spi_rx_buf[MESSAGE_BUFF_SIZE];
+
+void
+spi_irqs_handler(void *arg, int len)
+{
+    /* Allocate space for the decoded message. */
+    SimpleMessage message = SimpleMessage_init_zero;
+    pb_istream_t stream;
+    bool status;
+
+    /* Create a stream that reads from the buffer. */
+    stream = pb_istream_from_buffer(g_spi_rx_buf, (size_t)len);
+    /* Now we are ready to decode the message. */
+    status = pb_decode(&stream, SimpleMessage_fields, &message);
+    /* Check for errors... */
+    assert(status);
+
+    /* Save the data contained in the message. */
+    g_lucky_number = message.lucky_number;
+
+    os_sem_release(&g_spi_sem);
+}
+
+void
+spis_cfg(int spi_num)
+{
+    struct hal_spi_settings my_spi;
+
+    my_spi.data_order = HAL_SPI_MSB_FIRST;
+    my_spi.data_mode = HAL_SPI_MODE0;
+    my_spi.baudrate = SPI_BAUDRATE;
+    my_spi.word_size = HAL_SPI_WORD_SIZE_8BIT;
+    assert(hal_spi_config(spi_num, &my_spi) == 0);
+
+    hal_spi_set_txrx_cb(spi_num, spi_irqs_handler, NULL);
+}
+#endif
+
+#ifdef SPI_MASTER
+void
+spim_task_handler(void *arg)
+{
+    /* 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;
+    /* This is the buffer where we will store our message. */
+    uint8_t buffer[MESSAGE_BUFF_SIZE];
+    pb_ostream_t stream;
+    bool status;
+    int rc;
+
+    /* Initialize the lucky number */
+    message.lucky_number = 0;
+
+    /* Set the led pin */
+    g_led_pin = LED_BLINK_PIN;
+    hal_gpio_init_out(g_led_pin, 1);
+
+    /* Configure SS pin */
+    hal_gpio_init_out(SPI_SS_PIN, 1);
+    spim_cfg(SPI_M_NUM);
+
+    /* Set up the callback to use when non-blocking API used */
+    hal_spi_set_txrx_cb(SPI_M_NUM, spi_irqm_handler, NULL);
+    hal_spi_enable(SPI_M_NUM);
+
+    while (1) {
+        /* Send non-blocking */
+        hal_gpio_write(SPI_SS_PIN, 0);
+        /* Create a stream that will write to our buffer. */
+        stream = pb_ostream_from_buffer(buffer, sizeof(buffer));
+        /* Increment the lucky number */
+        message.lucky_number++;
+        /* Now we are ready to encode the message! */
+        status = pb_encode(&stream, SimpleMessage_fields, &message);
+        /* Then just check for any errors... */
+        assert(status);
+
+        rc = hal_spi_txrx_noblock(SPI_M_NUM, buffer, NULL, 
(int)stream.bytes_written);
+        assert(!rc);
+
+        /* Wait one second */
+        os_time_delay(OS_TICKS_PER_SEC);
+
+        /* Toggle the LED */
+        hal_gpio_toggle(g_led_pin);
+    }
+}
+#endif
+
+#ifdef SPI_SLAVE
+
+void
+spis_task_handler(void *arg)
+{
+    /* This is the buffer where we will store our message. */
+    int rc;
+
+    g_led_pin = LED_BLINK_PIN;
+    hal_gpio_init_out(g_led_pin, 1);
+
+    spis_cfg(SPI_S_NUM);
+    hal_spi_enable(SPI_S_NUM);
+
+    /* Make the default character 0x77 */
+    hal_spi_slave_set_def_tx_val(SPI_S_NUM, 0x77);
+
+    while (1) {
+        rc = hal_spi_txrx_noblock(SPI_S_NUM, NULL, g_spi_rx_buf, 
MESSAGE_BUFF_SIZE);
+        assert(rc == 0);
+
+        os_sem_pend(&g_spi_sem, OS_TIMEOUT_NEVER);
+
+        console_printf("Lucky number: %ld\n", g_lucky_number);
+
+        /* Toggle the LED */
+        hal_gpio_toggle(g_led_pin);
+    }
+}
+#endif
+
+/**
+ * init_tasks
+ *
+ * Called by main.c after sysinit(). This function performs initializations
+ * that are required before tasks are running.
+ *
+ * @return int 0 success; error otherwise.
+ */
+static void
+init_tasks(void)
+{
+    os_stack_t *pstack;
+
+    (void)pstack;
+
+#if defined(SPI_MASTER)
+    pstack = malloc(sizeof(os_stack_t) * TASK1_STACK_SIZE);
+    assert(pstack);
+
+    os_task_init(&task1, "spim", spim_task_handler, NULL, TASK1_PRIO,
+                 OS_WAIT_FOREVER, pstack, TASK1_STACK_SIZE);
+#endif
+
+#if defined(SPI_SLAVE)
+    /* Initialize semaphore */
+    os_sem_init(&g_spi_sem, 0);
+
+    pstack = malloc(sizeof(os_stack_t) * TASK1_STACK_SIZE);
+    assert(pstack);
+
+    os_task_init(&task1, "spis", spis_task_handler, NULL, TASK1_PRIO,
+                 OS_WAIT_FOREVER, pstack, TASK1_STACK_SIZE);
+#endif
+}
+
+/**
+ * main
+ *
+ * The main task for the project. This function initializes the packages, calls
+ * init_tasks to initialize additional tasks (and possibly other objects),
+ * then starts serving events from default event queue.
+ *
+ * @return int NOTE: this function should never return!
+ */
+int
+mynewt_main(int argc, char **argv)
+{
+    int rc;
+
+    sysinit();
+    init_tasks();
+
+    while (1) {
+        os_eventq_run(os_eventq_dflt_get());
+    }
+    /* Never returns */
+    assert(0);
+
+    return rc;
+}
diff --git a/apps/nanopb_simple_spi/src/simple.pb.c 
b/apps/nanopb_simple_spi/src/simple.pb.c
new file mode 100644
index 000000000..b1fb24b7f
--- /dev/null
+++ b/apps/nanopb_simple_spi/src/simple.pb.c
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* This file is automatically generated so we disable clang-format */
+/* clang-format off */
+/* Automatically generated nanopb constant definitions */
+/* Generated by nanopb-1.0.0-dev */
+
+#include "simple.pb.h"
+#if PB_PROTO_HEADER_VERSION != 40
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+PB_BIND(SimpleMessage, SimpleMessage, AUTO)
+
+
+
diff --git a/apps/nanopb_simple_spi/src/simple.pb.h 
b/apps/nanopb_simple_spi/src/simple.pb.h
new file mode 100644
index 000000000..22fecacff
--- /dev/null
+++ b/apps/nanopb_simple_spi/src/simple.pb.h
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* This file is automatically generated so we disable clang-format */
+/* clang-format off */
+/* Automatically generated nanopb header */
+/* Generated by nanopb-1.0.0-dev */
+
+#ifndef PB_SIMPLE_PB_H_INCLUDED
+#define PB_SIMPLE_PB_H_INCLUDED
+#include <pb.h>
+
+#if PB_PROTO_HEADER_VERSION != 40
+#error Regenerate this file with the current version of nanopb generator.
+#endif
+
+/* Struct definitions */
+typedef struct _SimpleMessage {
+    int32_t lucky_number;
+} SimpleMessage;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Initializer values for message structs */
+#define SimpleMessage_init_default               {0}
+#define SimpleMessage_init_zero                  {0}
+
+/* Field tags (for use in manual encoding/decoding) */
+#define SimpleMessage_lucky_number_tag           1
+
+/* Struct field encoding specification for nanopb */
+#define SimpleMessage_FIELDLIST(X, a) \
+X(a, STATIC,   REQUIRED, INT32,    lucky_number,      1)
+#define SimpleMessage_CALLBACK NULL
+#define SimpleMessage_DEFAULT NULL
+
+extern const pb_msgdesc_t SimpleMessage_msg;
+
+/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
+#define SimpleMessage_fields &SimpleMessage_msg
+
+/* Maximum encoded size of messages (where known) */
+#define SIMPLE_PB_H_MAX_SIZE                     SimpleMessage_size
+#define SimpleMessage_size                       11
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif
diff --git a/apps/nanopb_simple_spi/syscfg.yml 
b/apps/nanopb_simple_spi/syscfg.yml
new file mode 100644
index 000000000..25967e2d4
--- /dev/null
+++ b/apps/nanopb_simple_spi/syscfg.yml
@@ -0,0 +1,40 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#  http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+syscfg.defs:
+    PB_SPI_SS_PIN:
+        description: 'SPI slave select pin number'
+        value:  -1
+
+    PB_SPI_M_NUM:
+        description: 'SPI peripheral number to use for master'
+        value: 0
+
+    PB_SPI_S_NUM:
+        description: 'SPI peripheral number to use for slave'
+        value: 0
+
+syscfg.vals:
+    CONSOLE_IMPLEMENTATION: full
+    LOG_IMPLEMENTATION: full
+    STATS_IMPLEMENTATION: full
+
+    SHELL_TASK: 0
+
+    # Default task settings
+    OS_MAIN_STACK_SIZE: 512

Reply via email to