diff --git a/apps/nanopb_simple_spi/README.md b/apps/nanopb_simple_spi/README.md new file mode 100644 index 0000000000..0340db8231 --- /dev/null +++ b/apps/nanopb_simple_spi/README.md @@ -0,0 +1,38 @@ + + +### 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 0000000000..7b69743fce --- /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 " +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 0000000000..b5ea522660 --- /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 +#include +#include +#include +#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 +#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 0000000000..b1fb24b7f1 --- /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 0000000000..22fecacffb --- /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 + +#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 0000000000..25967e2d4a --- /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 diff --git a/encoding/nanopb/pkg.yml b/encoding/nanopb/pkg.yml new file mode 100644 index 0000000000..e0bc4ca618 --- /dev/null +++ b/encoding/nanopb/pkg.yml @@ -0,0 +1,46 @@ +# +# 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: encoding/nanopb +pkg.description: Nanopb for Mynewt +pkg.keywords: + - display + +pkg.type: sdk + +pkg.include_dirs: + - "@nanopb/." + +pkg.src_dirs: + - "@nanopb/." + +pkg.ignore_dirs: + - "build-tests" + - "examples" + - "extra" + - "spm-test" + - "spm_headers" + - "tests" + +repository.nanopb: + type: github + branch: master + vers: nanopb-0.4.9.1-commit + user: nanopb + repo: nanopb