parent
1e5701228f
commit
c99284043e
@ -0,0 +1,30 @@
|
||||
#
|
||||
# Copyright (c) 2018 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
#
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
|
||||
list(APPEND BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(NONE)
|
||||
|
||||
# NORDIC SDK APP START
|
||||
target_sources(app PRIVATE
|
||||
src/main.c
|
||||
src/connection.c
|
||||
src/advertising.c
|
||||
src/uart.c
|
||||
src/spi.c
|
||||
src/int_comm.c
|
||||
src/pb_comm.c
|
||||
src/trz_nus.c
|
||||
src/protob/messages.pb.c
|
||||
src/protob/protob_helpers.c
|
||||
)
|
||||
|
||||
|
||||
# NORDIC SDK APP END
|
||||
|
||||
zephyr_library_include_directories(.)
|
@ -0,0 +1,43 @@
|
||||
#
|
||||
# Copyright (c) 2018 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
#
|
||||
|
||||
source "Kconfig.zephyr"
|
||||
|
||||
menu "Nordic UART BLE GATT service sample"
|
||||
|
||||
config BT_NUS_THREAD_STACK_SIZE
|
||||
int "Thread stack size"
|
||||
default 1024
|
||||
help
|
||||
Stack size used in each of the two threads
|
||||
|
||||
config BT_NUS_UART_BUFFER_SIZE
|
||||
int "UART payload buffer element size"
|
||||
default 40
|
||||
help
|
||||
Size of the payload buffer in each RX and TX FIFO element
|
||||
|
||||
config BT_NUS_SECURITY_ENABLED
|
||||
bool "Enable security"
|
||||
default y
|
||||
select BT_SMP
|
||||
help
|
||||
"Enable BLE security for the UART service"
|
||||
|
||||
config BT_NUS_UART_RX_WAIT_TIME
|
||||
int "Timeout for UART RX complete event"
|
||||
default 50000
|
||||
help
|
||||
Wait for RX complete event time in microseconds
|
||||
|
||||
config BT_NUS_UART_ASYNC_ADAPTER
|
||||
bool "Enable UART async adapter"
|
||||
select SERIAL_SUPPORT_ASYNC
|
||||
help
|
||||
Enables asynchronous adapter for UART drives that supports only
|
||||
IRQ interface.
|
||||
|
||||
endmenu
|
@ -0,0 +1,10 @@
|
||||
#
|
||||
# Copyright (c) 2023 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
#
|
||||
|
||||
source "${ZEPHYR_BASE}/share/sysbuild/Kconfig"
|
||||
|
||||
config NRF_DEFAULT_BLUETOOTH
|
||||
default y
|
@ -0,0 +1,244 @@
|
||||
.. _peripheral_uart:
|
||||
|
||||
Bluetooth: Peripheral UART
|
||||
##########################
|
||||
|
||||
.. contents::
|
||||
:local:
|
||||
:depth: 2
|
||||
|
||||
The Peripheral UART sample demonstrates how to use the :ref:`nus_service_readme`.
|
||||
It uses the NUS service to send data back and forth between a UART connection and a Bluetooth® LE connection, emulating a serial port over Bluetooth LE.
|
||||
|
||||
Requirements
|
||||
************
|
||||
|
||||
The sample supports the following development kits:
|
||||
|
||||
.. table-from-sample-yaml::
|
||||
|
||||
.. include:: /includes/tfm.txt
|
||||
|
||||
.. note::
|
||||
* The boards ``nrf52dk_nrf52810``, ``nrf52840dk_nrf52811``, and ``nrf52833dk_nrf52820`` only support the `Minimal sample variant`_.
|
||||
* When used with :ref:`zephyr:thingy53_nrf5340`, the sample supports the MCUboot bootloader with serial recovery and SMP DFU over Bluetooth.
|
||||
Thingy:53 has no built-in SEGGER chip, so the UART 0 peripheral is not gated to a USB CDC virtual serial port.
|
||||
* When used with :ref:`zephyr:nrf5340dk_nrf5340`, the sample might support the MCUboot bootloader with serial recovery of the networking core image.
|
||||
|
||||
The sample also requires a smartphone or tablet running a compatible application.
|
||||
The `Testing`_ instructions refer to `nRF Connect for Mobile`_, but you can also use other similar applications (for example, `nRF Blinky`_ or `nRF Toolbox`_).
|
||||
|
||||
You can also test the application with the :ref:`central_uart` sample.
|
||||
See the documentation for that sample for detailed instructions.
|
||||
|
||||
.. note::
|
||||
|thingy53_sample_note|
|
||||
|
||||
The sample also enables an additional USB CDC ACM port that is used instead of UART 0.
|
||||
Because of that, it uses a separate USB Vendor and Product ID.
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
When connected, the sample forwards any data received on the RX pin of the UART 0 peripheral to the Bluetooth LE unit.
|
||||
On Nordic Semiconductor's development kits, the UART 0 peripheral is typically gated through the SEGGER chip to a USB CDC virtual serial port.
|
||||
|
||||
Any data sent from the Bluetooth LE unit is sent out of the UART 0 peripheral's TX pin.
|
||||
|
||||
.. note::
|
||||
Thingy:53 uses the second instance of USB CDC ACM class instead of UART 0, because it has no built-in SEGGER chip that could be used to gate UART 0.
|
||||
|
||||
.. _peripheral_uart_debug:
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
In this sample, the UART console is used to send and read data over the NUS service.
|
||||
Debug messages are not displayed in this UART console.
|
||||
Instead, they are printed by the RTT logger.
|
||||
|
||||
If you want to view the debug messages, follow the procedure in :ref:`testing_rtt_connect`.
|
||||
|
||||
.. note::
|
||||
On the Thingy:53, debug logs are provided over the USB CDC ACM class serial port, instead of using RTT.
|
||||
|
||||
For more information about debugging in the |NCS|, see :ref:`debugging`.
|
||||
|
||||
FEM support
|
||||
***********
|
||||
|
||||
.. include:: /includes/sample_fem_support.txt
|
||||
|
||||
.. _peripheral_uart_minimal_ext:
|
||||
|
||||
Minimal sample variant
|
||||
======================
|
||||
|
||||
You can build the sample with a minimum configuration as a demonstration of how to reduce code size and RAM usage.
|
||||
This variant is available for resource-constrained boards.
|
||||
|
||||
See :ref:`peripheral_uart_sample_activating_variants` for details.
|
||||
|
||||
.. _peripheral_uart_cdc_acm_ext:
|
||||
|
||||
USB CDC ACM extension
|
||||
=====================
|
||||
|
||||
For the boards with the USB device peripheral, you can build the sample with support for the USB CDC ACM class serial port instead of the physical UART.
|
||||
This build uses the sample-specific UART async adapter module that acts as a bridge between USB CDC ACM and Zephyr's UART asynchronous API used by the sample.
|
||||
See :ref:`peripheral_uart_sample_activating_variants` for details about how to build the sample with this extension using the :file:`prj_cdc.conf`.
|
||||
|
||||
Async adapter experimental module
|
||||
---------------------------------
|
||||
|
||||
The default sample configuration uses the UART async API, which is an :ref:`experimental <software_maturity>` module.
|
||||
The UART async adapter creates and initializes an instance of the async module.
|
||||
This is needed because the USB CDC ACM implementation provides only the interrupt interface.
|
||||
The adapter uses data provided in the :c:struct:`uart_async_adapter_data` to connect to the UART device that does not use the asynchronous interface.
|
||||
|
||||
The module requires the :ref:`CONFIG_BT_NUS_UART_ASYNC_ADAPTER <CONFIG_BT_NUS_UART_ASYNC_ADAPTER>` to be set to ``y``.
|
||||
For more information about the adapter, see the :file:`uart_async_adapter` source files available in the :file:`peripheral_uart/src` directory.
|
||||
|
||||
MCUboot with serial recovery of the networking core image
|
||||
=========================================================
|
||||
|
||||
For the ``nrf5340dk_nrf5340_cpuapp``, it is possible to enable serial recovery of the network core while multi-image update is not enabled in the MCUboot.
|
||||
See :ref:`peripheral_uart_sample_activating_variants` for details on how to build the sample with this feature using the :file:`nrf5340dk_app_sr_net.conf` and :file:`nrf5340dk_mcuboot_sr_net.conf` files.
|
||||
|
||||
User interface
|
||||
**************
|
||||
|
||||
The user interface of the sample depends on the hardware platform you are using.
|
||||
|
||||
Development kits
|
||||
================
|
||||
|
||||
LED 1:
|
||||
Blinks, toggling on/off every second, when the main loop is running and the device is advertising.
|
||||
|
||||
LED 2:
|
||||
Lit when connected.
|
||||
|
||||
Button 1:
|
||||
Confirm the passkey value that is printed in the debug logs to pair/bond with the other device.
|
||||
|
||||
Button 2:
|
||||
Reject the passkey value that is printed in the debug logs to prevent pairing/bonding with the other device.
|
||||
|
||||
Thingy:53
|
||||
=========
|
||||
|
||||
RGB LED:
|
||||
The RGB LED channels are used independently to display the following information:
|
||||
|
||||
* Red channel blinks with a period of two seconds, duty cycle 50%, when the main loop is running (device is advertising).
|
||||
* Green channel displays if device is connected.
|
||||
|
||||
Button:
|
||||
Confirm the passkey value that is printed in the debug logs to pair/bond with the other device.
|
||||
Thingy:53 has only one button, therefore the passkey value cannot be rejected by pressing a button.
|
||||
|
||||
Configuration
|
||||
*************
|
||||
|
||||
|config|
|
||||
|
||||
Configuration options
|
||||
=====================
|
||||
|
||||
Check and configure the following configuration options for the sample:
|
||||
|
||||
.. _CONFIG_BT_NUS_UART_ASYNC_ADAPTER:
|
||||
|
||||
CONFIG_BT_NUS_UART_ASYNC_ADAPTER - Enable UART async adapter
|
||||
Enables asynchronous adapter for UART drives that supports only IRQ interface.
|
||||
|
||||
Building and running
|
||||
********************
|
||||
|
||||
.. |sample path| replace:: :file:`samples/bluetooth/peripheral_uart`
|
||||
|
||||
.. include:: /includes/build_and_run_ns.txt
|
||||
|
||||
.. _peripheral_uart_sample_activating_variants:
|
||||
|
||||
Activating sample extensions
|
||||
============================
|
||||
|
||||
To activate the optional extensions supported by this sample, modify :makevar:`OVERLAY_CONFIG` in the following manner:
|
||||
|
||||
* For the minimal build variant, set :file:`prj_minimal.conf`.
|
||||
* For the USB CDC ACM extension, set :file:`prj_cdc.conf`.
|
||||
Additionally, you need to set :makevar:`DTC_OVERLAY_FILE` to the :file:`usb.overlay` file.
|
||||
* For the MCUboot with serial recovery of the networking core image feature, set the :file:`nrf5340dk_app_sr_net.conf` file.
|
||||
You also need to set the :makevar:`mcuboot_OVERLAY_CONFIG` variant to the :file:`nrf5340dk_mcuboot_sr_net.conf` file.
|
||||
|
||||
See :ref:`cmake_options` for instructions on how to add this option.
|
||||
For more information about using configuration overlay files, see :ref:`zephyr:important-build-vars` in the Zephyr documentation.
|
||||
|
||||
.. _peripheral_uart_testing:
|
||||
|
||||
Testing
|
||||
=======
|
||||
|
||||
After programming the sample to your development kit, complete the following steps to test it:
|
||||
|
||||
1. Connect the device to the computer to access UART 0.
|
||||
If you use a development kit, UART 0 is forwarded as a COM port (Windows) or ttyACM device (Linux) after you connect the development kit over USB.
|
||||
If you use Thingy:53, you must attach the debug board and connect an external USB to UART converter to it.
|
||||
#. |connect_terminal|
|
||||
#. Optionally, you can display debug messages. See :ref:`peripheral_uart_debug` for details.
|
||||
#. Reset the kit.
|
||||
#. Observe that **LED 1** is blinking and that the device is advertising with the device name that is configured in :kconfig:option:`CONFIG_BT_DEVICE_NAME`.
|
||||
#. Observe that the text "Starting Nordic UART service example" is printed on the COM listener running on the computer.
|
||||
#. Connect to the device using nRF Connect for Mobile.
|
||||
Observe that **LED 2** is lit.
|
||||
#. Optionally, pair or bond with the device with MITM protection.
|
||||
This requires using the passkey value displayed in debug messages.
|
||||
See :ref:`peripheral_uart_debug` for details on how to access debug messages.
|
||||
To confirm pairing or bonding, press **Button 1** on the device and accept the passkey value on the smartphone.
|
||||
#. In the application, observe that the services are shown in the connected device.
|
||||
#. Select the UART RX characteristic value in nRF Connect for Mobile.
|
||||
You can write to the UART RX and get the text displayed on the COM listener.
|
||||
#. Type "0123456789" and tap :guilabel:`SEND`.
|
||||
Verify that the text "0123456789" is displayed on the COM listener.
|
||||
#. To send data from the device to your phone or tablet, enter any text, for example, "Hello", and press Enter to see it on the COM listener.
|
||||
Observe that a notification is sent to the peer.
|
||||
#. Disconnect the device in nRF Connect for Mobile.
|
||||
Observe that **LED 2** turns off.
|
||||
|
||||
Dependencies
|
||||
************
|
||||
|
||||
This sample uses the following sample-specific library:
|
||||
|
||||
* :file:`uart_async_adapter` at :file:`peripheral_uart/src`
|
||||
|
||||
This sample uses the following |NCS| libraries:
|
||||
|
||||
* :ref:`nus_service_readme`
|
||||
* :ref:`dk_buttons_and_leds_readme`
|
||||
|
||||
In addition, it uses the following Zephyr libraries:
|
||||
|
||||
* :file:`include/zephyr/types.h`
|
||||
* :file:`boards/arm/nrf*/board.h`
|
||||
* :ref:`zephyr:kernel_api`:
|
||||
|
||||
* :file:`include/kernel.h`
|
||||
|
||||
* :ref:`zephyr:api_peripherals`:
|
||||
|
||||
* :file:`include/gpio.h`
|
||||
* :file:`include/uart.h`
|
||||
|
||||
* :ref:`zephyr:bluetooth_api`:
|
||||
|
||||
* :file:`include/bluetooth/bluetooth.h`
|
||||
* :file:`include/bluetooth/gatt.h`
|
||||
* :file:`include/bluetooth/hci.h`
|
||||
* :file:`include/bluetooth/uuid.h`
|
||||
|
||||
The sample also uses the following secure firmware component:
|
||||
|
||||
* :ref:`Trusted Firmware-M <ug_tfm>`
|
@ -0,0 +1,5 @@
|
||||
VERSION_MAJOR = 2
|
||||
VERSION_MINOR = 5
|
||||
PATCHLEVEL = 0
|
||||
VERSION_TWEAK = 0
|
||||
EXTRAVERSION =
|
@ -0,0 +1,11 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
*/
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
nordic,nus-uart = &uart0;
|
||||
};
|
||||
};
|
@ -0,0 +1,10 @@
|
||||
# nRF52833 DK NRF52833 board configuration
|
||||
|
||||
# Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config BOARD_ENABLE_DCDC
|
||||
bool "DCDC mode"
|
||||
select SOC_DCDC_NRF52X
|
||||
default y
|
||||
depends on BOARD_T3W1_NRF52833
|
@ -0,0 +1,8 @@
|
||||
# nRF52833 DK NRF52833 board configuration
|
||||
|
||||
# Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config BOARD_T3W1_NRF52833
|
||||
bool "T3W1 NRF52833"
|
||||
depends on SOC_NRF52833_QIAA
|
@ -0,0 +1,14 @@
|
||||
# nRF52833 DK NRF52833 board configuration
|
||||
|
||||
# Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if BOARD_T3W1_NRF52833
|
||||
|
||||
config BOARD
|
||||
default "t3w1_nrf52833"
|
||||
|
||||
config BT_CTLR
|
||||
default BT
|
||||
|
||||
endif # BOARD_T3W1_NRF52833
|
@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(jlink "--device=nRF52833_xxAA" "--speed=4000")
|
||||
board_runner_args(pyocd "--target=nrf52833" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
|
||||
include(${ZEPHYR_BASE}/boards/common/nrfutil.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)
|
@ -0,0 +1,217 @@
|
||||
.. _nrf52833dk_nrf52833:
|
||||
|
||||
nRF52833 DK
|
||||
###########
|
||||
|
||||
Overview
|
||||
********
|
||||
|
||||
The nRF52833 Development Kit (PCA10100) hardware provides
|
||||
support for the Nordic Semiconductor nRF52833 ARM Cortex-M4F CPU and
|
||||
the following devices:
|
||||
|
||||
* :abbr:`ADC (Analog to Digital Converter)`
|
||||
* CLOCK
|
||||
* FLASH
|
||||
* :abbr:`GPIO (General Purpose Input Output)`
|
||||
* :abbr:`I2C (Inter-Integrated Circuit)`
|
||||
* :abbr:`MPU (Memory Protection Unit)`
|
||||
* :abbr:`NVIC (Nested Vectored Interrupt Controller)`
|
||||
* :abbr:`PWM (Pulse Width Modulation)`
|
||||
* RADIO (Bluetooth Low Energy and 802.15.4)
|
||||
* :abbr:`RTC (nRF RTC System Clock)`
|
||||
* Segger RTT (RTT Console)
|
||||
* :abbr:`SPI (Serial Peripheral Interface)`
|
||||
* :abbr:`UART (Universal asynchronous receiver-transmitter)`
|
||||
* :abbr:`USB (Universal Serial Bus)`
|
||||
* :abbr:`WDT (Watchdog Timer)`
|
||||
|
||||
More information about the board can be found at the
|
||||
`nRF52833 DK website`_. The `Nordic Semiconductor Infocenter`_
|
||||
contains the processor's information and the datasheet.
|
||||
|
||||
|
||||
Hardware
|
||||
********
|
||||
|
||||
nRF52833 DK has two external oscillators. The frequency of
|
||||
the slow clock is 32.768 kHz. The frequency of the main clock
|
||||
is 32 MHz.
|
||||
|
||||
Supported Features
|
||||
==================
|
||||
|
||||
The nrf52833dk_nrf52833 board configuration supports the following
|
||||
hardware features:
|
||||
|
||||
+-----------+------------+----------------------+
|
||||
| Interface | Controller | Driver/Component |
|
||||
+===========+============+======================+
|
||||
| ADC | on-chip | adc |
|
||||
+-----------+------------+----------------------+
|
||||
| CLOCK | on-chip | clock_control |
|
||||
+-----------+------------+----------------------+
|
||||
| FLASH | on-chip | flash |
|
||||
+-----------+------------+----------------------+
|
||||
| GPIO | on-chip | gpio |
|
||||
+-----------+------------+----------------------+
|
||||
| I2C(M) | on-chip | i2c |
|
||||
+-----------+------------+----------------------+
|
||||
| MPU | on-chip | arch/arm |
|
||||
+-----------+------------+----------------------+
|
||||
| NVIC | on-chip | arch/arm |
|
||||
+-----------+------------+----------------------+
|
||||
| PWM | on-chip | pwm |
|
||||
+-----------+------------+----------------------+
|
||||
| RADIO | on-chip | Bluetooth, |
|
||||
| | | ieee802154 |
|
||||
+-----------+------------+----------------------+
|
||||
| RTC | on-chip | system clock |
|
||||
+-----------+------------+----------------------+
|
||||
| RTT | Segger | console |
|
||||
+-----------+------------+----------------------+
|
||||
| SPI(M/S) | on-chip | spi |
|
||||
+-----------+------------+----------------------+
|
||||
| UART | on-chip | serial |
|
||||
+-----------+------------+----------------------+
|
||||
| USB | on-chip | usb |
|
||||
+-----------+------------+----------------------+
|
||||
| WDT | on-chip | watchdog |
|
||||
+-----------+------------+----------------------+
|
||||
|
||||
Other hardware features have not been enabled yet for this board.
|
||||
See `nRF52833 DK website`_ and `Nordic Semiconductor Infocenter`_
|
||||
for a complete list of nRF52833 Development Kit board hardware features.
|
||||
|
||||
Connections and IOs
|
||||
===================
|
||||
|
||||
LED
|
||||
---
|
||||
|
||||
* LED1 (green) = P0.13
|
||||
* LED2 (green) = P0.14
|
||||
* LED3 (green) = P0.15
|
||||
* LED4 (green) = P0.16
|
||||
|
||||
Push buttons
|
||||
------------
|
||||
|
||||
* BUTTON1 = SW1 = P0.11
|
||||
* BUTTON2 = SW2 = P0.12
|
||||
* BUTTON3 = SW3 = P0.24
|
||||
* BUTTON4 = SW4 = P0.25
|
||||
* BOOT = SW5 = boot/reset
|
||||
|
||||
Programming and Debugging
|
||||
*************************
|
||||
|
||||
Applications for the ``nrf52833dk_nrf52833`` board configuration can be built,
|
||||
flashed, and debugged in the usual way. See :ref:`build_an_application` and
|
||||
:ref:`application_run` for more details on building and running.
|
||||
|
||||
Flashing
|
||||
========
|
||||
|
||||
Follow the instructions in the :ref:`nordic_segger` page to install
|
||||
and configure all the necessary software. Further information can be
|
||||
found in :ref:`nordic_segger_flashing`. Then build and flash
|
||||
applications as usual (see :ref:`build_an_application` and
|
||||
:ref:`application_run` for more details).
|
||||
|
||||
Here is an example for the :ref:`hello_world` application.
|
||||
|
||||
First, run your favorite terminal program to listen for output.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ minicom -D <tty_device> -b 115200
|
||||
|
||||
Replace :code:`<tty_device>` with the port where the board nRF52 DK
|
||||
can be found. For example, under Linux, :code:`/dev/ttyACM0`.
|
||||
|
||||
Then build and flash the application in the usual way.
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/hello_world
|
||||
:board: nrf52833dk_nrf52833
|
||||
:goals: build flash
|
||||
|
||||
Debugging
|
||||
=========
|
||||
|
||||
Refer to the :ref:`nordic_segger` page to learn about debugging Nordic boards with a
|
||||
Segger IC.
|
||||
|
||||
|
||||
Testing the LEDs and buttons in the nRF52833 DK
|
||||
***********************************************
|
||||
|
||||
There are 2 samples that allow you to test that the buttons (switches) and LEDs on
|
||||
the board are working properly with Zephyr:
|
||||
|
||||
* :ref:`blinky-sample`
|
||||
* :ref:`button-sample`
|
||||
|
||||
You can build and flash the examples to make sure Zephyr is running correctly on
|
||||
your board. The button and LED definitions can be found in
|
||||
:zephyr_file:`boards/arm/nrf52833dk_nrf52833/nrf52833dk_nrf52833.dts`.
|
||||
|
||||
Changing UART1 pins
|
||||
*******************
|
||||
|
||||
The following approach can be used when an application needs to use another set
|
||||
of pins for UART1:
|
||||
|
||||
1. Add devicetree overlay file to the main directory of your application:
|
||||
|
||||
.. code-block:: devicetree
|
||||
|
||||
&pinctrl {
|
||||
uart1_default_alt: uart1_default_alt {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 14)>,
|
||||
<NRF_PSEL(UART_RX, 0, 16)>;
|
||||
};
|
||||
};
|
||||
/* required if CONFIG_PM_DEVICE=y */
|
||||
uart1_sleep_alt: uart1_sleep_alt {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 14)>,
|
||||
<NRF_PSEL(UART_RX, 0, 16)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
pinctrl-0 = <&uart1_default_alt>;
|
||||
/* if sleep state is not used, use /delete-property/ pinctrl-1; and
|
||||
* skip the "sleep" entry.
|
||||
*/
|
||||
pinctrl-1 = <&uart1_sleep_alt>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
In the overlay file above, pin P0.16 is used for RX and P0.14 is used for TX
|
||||
|
||||
See :ref:`set-devicetree-overlays` for further details.
|
||||
|
||||
Selecting the pins
|
||||
==================
|
||||
|
||||
Pins can be configured in the board pinctrl file. To see the available mappings,
|
||||
open the `nRF52833 Product Specification`_, chapter 7 'Hardware and Layout'.
|
||||
In the table 7.1.1 'aQFN73 ball assignments' select the pins marked
|
||||
'General purpose I/O'. Note that pins marked as 'low frequency I/O only' can only be used
|
||||
in under-10KHz applications. They are not suitable for 115200 speed of UART.
|
||||
|
||||
References
|
||||
**********
|
||||
|
||||
.. target-notes::
|
||||
|
||||
.. _nRF52833 DK website: https://www.nordicsemi.com/Software-and-Tools/Development-Kits/nRF52833-DK
|
||||
.. _Nordic Semiconductor Infocenter: https://infocenter.nordicsemi.com
|
||||
.. _J-Link Software and documentation pack: https://www.segger.com/jlink-software.html
|
||||
.. _nRF52833 Product Specification: https://infocenter.nordicsemi.com/pdf/nRF52833_OPS_v0.7.pdf
|
@ -0,0 +1,7 @@
|
||||
# Copyright (c) 2022 Nordic Semiconductor
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Suppress "unique_unit_address_if_enabled" to handle the following overlaps:
|
||||
# - power@40000000 & clock@40000000 & bprot@40000000
|
||||
# - acl@4001e000 & flash-controller@4001e000
|
||||
list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled")
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&pinctrl {
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 27)>,
|
||||
<NRF_PSEL(UART_RTS, 0, 8)>;
|
||||
};
|
||||
group2 {
|
||||
psels = <NRF_PSEL(UART_RX, 0, 26)>,
|
||||
<NRF_PSEL(UART_CTS, 0, 6)>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_sleep: uart0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 27)>,
|
||||
<NRF_PSEL(UART_RX, 0, 26)>,
|
||||
<NRF_PSEL(UART_RTS, 0, 8)>,
|
||||
<NRF_PSEL(UART_CTS, 0, 6)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
spi0_default: spi0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 0, 14)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 0, 16)>,
|
||||
<NRF_PSEL(SPIM_MISO, 0, 15)>;
|
||||
};
|
||||
};
|
||||
|
||||
spi0_sleep: spi0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 0, 14)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 0, 16)>,
|
||||
<NRF_PSEL(SPIM_MISO, 0, 15)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
};
|
@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <nordic/nrf52833_qiaa.dtsi>
|
||||
#include "t3w1_nrf52833-pinctrl.dtsi"
|
||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||
|
||||
/ {
|
||||
model = "T3W1 NRF52833";
|
||||
compatible = "nordic,t3w1_nrf52833";
|
||||
|
||||
chosen {
|
||||
zephyr,console = &uart0;
|
||||
zephyr,shell-uart = &uart0;
|
||||
zephyr,uart-mcumgr = &uart0;
|
||||
zephyr,bt-mon-uart = &uart0;
|
||||
zephyr,bt-c2h-uart = &uart0;
|
||||
zephyr,sram = &sram0;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,code-partition = &slot0_partition;
|
||||
zephyr,ieee802154 = &ieee802154;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led0: led_0 {
|
||||
gpios = <&gpio0 22 GPIO_ACTIVE_LOW>;
|
||||
label = "Green LED 0";
|
||||
};
|
||||
led1: led_1 {
|
||||
gpios = <&gpio0 24 GPIO_ACTIVE_LOW>;
|
||||
label = "Green LED 1";
|
||||
};
|
||||
out0: out_0 {
|
||||
gpios = <&gpio0 29 GPIO_ACTIVE_HIGH>;
|
||||
label = "FW Running";
|
||||
};
|
||||
};
|
||||
|
||||
buttons {
|
||||
compatible = "gpio-keys";
|
||||
button0: button_0 {
|
||||
gpios = <&gpio1 8 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "Push button switch 0";
|
||||
zephyr,code = <INPUT_KEY_0>;
|
||||
};
|
||||
trezor_ready: trezor_ready {
|
||||
gpios = <&gpio0 30 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
|
||||
label = "Trezor ready";
|
||||
zephyr,code = <INPUT_KEY_1>;
|
||||
};
|
||||
};
|
||||
|
||||
/* These aliases are provided for compatibility with samples */
|
||||
aliases {
|
||||
led0 = &led0;
|
||||
led1 = &led1;
|
||||
sw0 = &button0;
|
||||
bootloader-led0 = &led0;
|
||||
mcuboot-button0 = &button0;
|
||||
mcuboot-led0 = &led0;
|
||||
watchdog0 = &wdt0;
|
||||
};
|
||||
};
|
||||
|
||||
&adc {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uicr {
|
||||
gpio-as-nreset;
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
status = "okay";
|
||||
current-speed = <115200>;
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-1 = <&uart0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
&spi0 {
|
||||
compatible = "nordic,nrf-spim";
|
||||
status = "okay";
|
||||
pinctrl-0 = <&spi0_default>;
|
||||
pinctrl-1 = <&spi0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
cs-gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
|
||||
reg_my_spi_master: spi-dev-a@0 {
|
||||
reg = <0>;
|
||||
};
|
||||
};
|
||||
|
||||
&ieee802154 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&flash0 {
|
||||
|
||||
partitions {
|
||||
compatible = "fixed-partitions";
|
||||
#address-cells = <1>;
|
||||
#size-cells = <1>;
|
||||
|
||||
boot_partition: partition@0 {
|
||||
label = "mcuboot";
|
||||
reg = <0x00000000 0xC000>;
|
||||
};
|
||||
slot0_partition: partition@c000 {
|
||||
label = "image-0";
|
||||
reg = <0x0000C000 0x37000>;
|
||||
};
|
||||
slot1_partition: partition@43000 {
|
||||
label = "image-1";
|
||||
reg = <0x00043000 0x37000>;
|
||||
};
|
||||
storage_partition: partition@7a000 {
|
||||
label = "storage";
|
||||
reg = <0x0007A000 0x00006000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
zephyr_udc0: &usbd {
|
||||
compatible = "nordic,nrf-usbd";
|
||||
status = "okay";
|
||||
};
|
@ -0,0 +1,16 @@
|
||||
identifier: t3w1_nrf52833
|
||||
name: tw31-NRF52833
|
||||
type: mcu
|
||||
arch: arm
|
||||
ram: 128
|
||||
flash: 512
|
||||
toolchain:
|
||||
- zephyr
|
||||
- gnuarmemb
|
||||
- xtools
|
||||
supported:
|
||||
- usb_device
|
||||
- ble
|
||||
- gpio
|
||||
- watchdog
|
||||
- counter
|
@ -0,0 +1,26 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_SOC_SERIES_NRF52X=y
|
||||
CONFIG_SOC_NRF52833_QIAA=y
|
||||
CONFIG_BOARD_T3W1_NRF52833=y
|
||||
|
||||
# Enable MPU
|
||||
CONFIG_ARM_MPU=y
|
||||
|
||||
# Enable hardware stack protection
|
||||
CONFIG_HW_STACK_PROTECTION=y
|
||||
|
||||
# Enable RTT
|
||||
CONFIG_USE_SEGGER_RTT=y
|
||||
|
||||
# enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
# enable uart driver
|
||||
CONFIG_SERIAL=y
|
||||
|
||||
# enable console
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
|
||||
CONFIG_PINCTRL=y
|
@ -0,0 +1,69 @@
|
||||
#
|
||||
# Copyright (c) 2018 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
#
|
||||
|
||||
# Enable the UART driver
|
||||
CONFIG_UART_ASYNC_API=y
|
||||
CONFIG_NRFX_UARTE0=y
|
||||
CONFIG_SERIAL=y
|
||||
|
||||
CONFIG_NANOPB=y
|
||||
|
||||
# Enable the SPI driver
|
||||
CONFIG_SPI=y
|
||||
CONFIG_NRFX_SPIM0=y
|
||||
|
||||
CONFIG_GPIO=y
|
||||
|
||||
|
||||
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=2048
|
||||
|
||||
CONFIG_BT=y
|
||||
CONFIG_BT_PERIPHERAL=y
|
||||
CONFIG_BT_DEVICE_NAME="TrezorZephyr"
|
||||
CONFIG_BT_DEVICE_APPEARANCE=833
|
||||
CONFIG_BT_MAX_CONN=1
|
||||
CONFIG_BT_MAX_PAIRED=8
|
||||
CONFIG_BT_SMP=y
|
||||
CONFIG_BT_SMP_SC_ONLY=y
|
||||
CONFIG_BT_FILTER_ACCEPT_LIST=y
|
||||
CONFIG_BT_PRIVACY=y
|
||||
# CONFIG_BT_LL_SW_SPLIT=y
|
||||
|
||||
#PHY update needed for updating PHY request
|
||||
CONFIG_BT_USER_PHY_UPDATE=y
|
||||
|
||||
# HCI ACL buffers size
|
||||
# BT_L2CAP_RX_MTU = CONFIG_BT_BUF_ACL_RX_SIZE - BT_L2CAP_HDR_SIZE
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=251
|
||||
|
||||
# L2CAP SDU/PDU TX MTU
|
||||
CONFIG_BT_L2CAP_TX_MTU=247
|
||||
|
||||
|
||||
# Enable bonding
|
||||
CONFIG_BT_SETTINGS=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_NVS=y
|
||||
CONFIG_SETTINGS=y
|
||||
|
||||
# Enable DK LED and Buttons library
|
||||
CONFIG_DK_LIBRARY=y
|
||||
|
||||
# This example requires more stack
|
||||
CONFIG_MAIN_STACK_SIZE=1152
|
||||
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
|
||||
|
||||
# Config logger
|
||||
CONFIG_LOG=y
|
||||
CONFIG_USE_SEGGER_RTT=y
|
||||
CONFIG_LOG_BACKEND_RTT=y
|
||||
CONFIG_LOG_BACKEND_UART=n
|
||||
CONFIG_LOG_PRINTK=n
|
||||
|
||||
CONFIG_ASSERT=y
|
@ -0,0 +1,18 @@
|
||||
#
|
||||
# Copyright (c) 2021 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
#
|
||||
|
||||
# Enable the UART driver
|
||||
CONFIG_UART_LINE_CTRL=y
|
||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
CONFIG_BT_NUS_UART_ASYNC_ADAPTER=y
|
||||
CONFIG_USB_DEVICE_STACK=y
|
||||
CONFIG_USB_DEVICE_REMOTE_WAKEUP=n
|
||||
CONFIG_USB_CDC_ACM=y
|
||||
CONFIG_USB_CDC_ACM_LOG_LEVEL_OFF=y
|
||||
|
||||
# Disable the UARTE0 enabled in default project configuration
|
||||
CONFIG_NRFX_UARTE0=n
|
||||
CONFIG_UART_NRFX=n
|
@ -0,0 +1,131 @@
|
||||
#
|
||||
# Copyright (c) 2021 Nordic Semiconductor
|
||||
#
|
||||
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
#
|
||||
|
||||
# Enable the UART driver
|
||||
CONFIG_UART_ASYNC_API=y
|
||||
CONFIG_NRFX_UARTE0=y
|
||||
CONFIG_SERIAL=y
|
||||
|
||||
CONFIG_HEAP_MEM_POOL_SIZE=2048
|
||||
|
||||
CONFIG_BT=y
|
||||
CONFIG_BT_PERIPHERAL=y
|
||||
CONFIG_BT_DEVICE_NAME="Nordic_UART_Service"
|
||||
CONFIG_BT_DEVICE_APPEARANCE=833
|
||||
CONFIG_BT_MAX_CONN=1
|
||||
CONFIG_BT_MAX_PAIRED=1
|
||||
|
||||
# Enable the NUS service
|
||||
CONFIG_BT_NUS=y
|
||||
|
||||
# Enable bonding
|
||||
CONFIG_BT_SETTINGS=y
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_NVS=y
|
||||
CONFIG_SETTINGS=y
|
||||
|
||||
# Enable DK LED and Buttons library
|
||||
CONFIG_DK_LIBRARY=y
|
||||
|
||||
# Drivers and peripherals
|
||||
CONFIG_I2C=n
|
||||
CONFIG_WATCHDOG=n
|
||||
CONFIG_SPI=n
|
||||
CONFIG_GPIO=n
|
||||
|
||||
# Power management
|
||||
|
||||
# Interrupts
|
||||
CONFIG_DYNAMIC_INTERRUPTS=n
|
||||
CONFIG_IRQ_OFFLOAD=n
|
||||
|
||||
# Memory protection
|
||||
CONFIG_THREAD_STACK_INFO=n
|
||||
CONFIG_THREAD_CUSTOM_DATA=n
|
||||
CONFIG_FPU=n
|
||||
|
||||
# Boot
|
||||
CONFIG_BOOT_BANNER=n
|
||||
CONFIG_BOOT_DELAY=0
|
||||
|
||||
# Console
|
||||
CONFIG_CONSOLE=n
|
||||
CONFIG_UART_CONSOLE=n
|
||||
CONFIG_STDOUT_CONSOLE=n
|
||||
CONFIG_PRINTK=n
|
||||
CONFIG_EARLY_CONSOLE=n
|
||||
|
||||
# Build
|
||||
CONFIG_SIZE_OPTIMIZATIONS=y
|
||||
|
||||
# ARM
|
||||
CONFIG_ARM_MPU=n
|
||||
|
||||
# In order to correctly tune the stack sizes for the threads the following
|
||||
# Configurations can enabled to print the current use:
|
||||
#CONFIG_THREAD_NAME=y
|
||||
#CONFIG_THREAD_ANALYZER=y
|
||||
#CONFIG_THREAD_ANALYZER_AUTO=y
|
||||
#CONFIG_THREAD_ANALYZER_RUN_UNLOCKED=y
|
||||
#CONFIG_THREAD_ANALYZER_USE_PRINTK=y
|
||||
#CONFIG_CONSOLE=y
|
||||
#CONFIG_UART_CONSOLE=y
|
||||
#CONFIG_SERIAL=y
|
||||
#CONFIG_PRINTK=y
|
||||
|
||||
# Example output of thread analyzer
|
||||
#SDC RX : unused 800 usage 224 / 1024 (21 %)
|
||||
#BT ECC : unused 216 usage 888 / 1104 (80 %)
|
||||
#BT RX : unused 1736 usage 464 / 2200 (21 %)
|
||||
#BT TX : unused 1008 usage 528 / 1536 (34 %)
|
||||
#ble_write_thread_id : unused 688 usage 336 / 1024 (32 %)
|
||||
#sysworkq : unused 1912 usage 136 / 2048 (6 %)
|
||||
#MPSL signal : unused 928 usage 96 / 1024 (9 %)
|
||||
#idle 00 : unused 224 usage 96 / 320 (30 %)
|
||||
#main : unused 568 usage 456 / 1024 (44 %)
|
||||
CONFIG_BT_RX_STACK_SIZE=1024
|
||||
CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y
|
||||
CONFIG_BT_HCI_TX_STACK_SIZE=640
|
||||
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512
|
||||
CONFIG_MPSL_WORK_STACK_SIZE=256
|
||||
CONFIG_MAIN_STACK_SIZE=864
|
||||
CONFIG_IDLE_STACK_SIZE=128
|
||||
CONFIG_ISR_STACK_SIZE=1024
|
||||
CONFIG_BT_NUS_THREAD_STACK_SIZE=512
|
||||
|
||||
# Disable features not needed
|
||||
CONFIG_TIMESLICING=n
|
||||
CONFIG_MINIMAL_LIBC_MALLOC=n
|
||||
CONFIG_LOG=n
|
||||
CONFIG_ASSERT=n
|
||||
|
||||
# Disable Bluetooth features not needed
|
||||
CONFIG_BT_DEBUG_NONE=y
|
||||
CONFIG_BT_ASSERT=n
|
||||
CONFIG_BT_DATA_LEN_UPDATE=n
|
||||
CONFIG_BT_PHY_UPDATE=n
|
||||
CONFIG_BT_GATT_CACHING=n
|
||||
CONFIG_BT_GATT_SERVICE_CHANGED=n
|
||||
CONFIG_BT_GAP_PERIPHERAL_PREF_PARAMS=n
|
||||
CONFIG_BT_SETTINGS_CCC_LAZY_LOADING=y
|
||||
CONFIG_BT_HCI_VS_EXT=n
|
||||
|
||||
# Disable Bluetooth controller features not needed
|
||||
CONFIG_BT_CTLR_PRIVACY=n
|
||||
CONFIG_BT_CTLR_PHY_2M=n
|
||||
|
||||
# Reduce Bluetooth buffers
|
||||
CONFIG_BT_BUF_EVT_DISCARDABLE_COUNT=1
|
||||
CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=43
|
||||
CONFIG_BT_BUF_EVT_RX_COUNT=2
|
||||
|
||||
CONFIG_BT_CONN_TX_MAX=2
|
||||
CONFIG_BT_L2CAP_TX_BUF_COUNT=2
|
||||
CONFIG_BT_CTLR_RX_BUFFERS=1
|
||||
CONFIG_BT_BUF_ACL_TX_COUNT=3
|
||||
CONFIG_BT_BUF_ACL_TX_SIZE=27
|
@ -0,0 +1,65 @@
|
||||
sample:
|
||||
description: Bluetooth Low Energy UART service sample
|
||||
name: BLE UART service
|
||||
tests:
|
||||
sample.bluetooth.peripheral_uart:
|
||||
build_only: true
|
||||
platform_allow: nrf52dk_nrf52832 nrf52833dk_nrf52833 t3w1_nrf52833 nrf52840dk_nrf52840
|
||||
nrf5340dk_nrf5340_cpuapp nrf5340dk_nrf5340_cpuapp_ns thingy53_nrf5340_cpuapp
|
||||
thingy53_nrf5340_cpuapp_ns nrf21540dk_nrf52840
|
||||
integration_platforms:
|
||||
- nrf52dk_nrf52832
|
||||
- nrf52833dk_nrf52833
|
||||
- t3w1_nrf52833
|
||||
- nrf52840dk_nrf52840
|
||||
- nrf5340dk_nrf5340_cpuapp
|
||||
- nrf5340dk_nrf5340_cpuapp_ns
|
||||
- thingy53_nrf5340_cpuapp
|
||||
- thingy53_nrf5340_cpuapp_ns
|
||||
- nrf21540dk_nrf52840
|
||||
tags: bluetooth ci_build
|
||||
sample.bluetooth.peripheral_uart.sysbuild:
|
||||
build_only: true
|
||||
sysbuild: true
|
||||
platform_allow: nrf52840dk_nrf52840 nrf5340dk_nrf5340_cpuapp
|
||||
nrf5340dk_nrf5340_cpuapp_ns
|
||||
integration_platforms:
|
||||
- nrf52840dk_nrf52840
|
||||
- nrf5340dk_nrf5340_cpuapp
|
||||
- nrf5340dk_nrf5340_cpuapp_ns
|
||||
tags: bluetooth ci_build sysbuild
|
||||
sample.bluetooth.peripheral_uart_cdc:
|
||||
build_only: true
|
||||
extra_args: OVERLAY_CONFIG=prj_cdc.conf DTC_OVERLAY_FILE="usb.overlay"
|
||||
integration_platforms:
|
||||
- nrf52840dk_nrf52840
|
||||
- nrf52833dk_nrf52833
|
||||
platform_allow: nrf52840dk_nrf52840 nrf52833dk_nrf52833
|
||||
tags: bluetooth ci_build
|
||||
sample.bluetooth.peripheral_uart_minimal:
|
||||
build_only: true
|
||||
extra_args: OVERLAY_CONFIG=prj_minimal.conf
|
||||
integration_platforms:
|
||||
- nrf52dk_nrf52810
|
||||
- nrf52840dk_nrf52811
|
||||
- nrf52833dk_nrf52820
|
||||
platform_allow: nrf52dk_nrf52810 nrf52840dk_nrf52811 nrf52833dk_nrf52820
|
||||
tags: bluetooth ci_build
|
||||
sample.bluetooth.peripheral_uart_ble_rpc:
|
||||
build_only: true
|
||||
extra_configs:
|
||||
- CONFIG_BT_RPC_STACK=y
|
||||
integration_platforms:
|
||||
- nrf5340dk_nrf5340_cpuapp
|
||||
platform_allow: nrf5340dk_nrf5340_cpuapp
|
||||
tags: bluetooth ci_build
|
||||
sample.bluetooth.peripheral_uart.security_disabled:
|
||||
build_only: true
|
||||
platform_allow: nrf52dk_nrf52832 nrf52833dk_nrf52833 nrf52840dk_nrf52840
|
||||
nrf5340dk_nrf5340_cpuapp nrf5340dk_nrf5340_cpuapp_ns thingy53_nrf5340_cpuapp
|
||||
thingy53_nrf5340_cpuapp_ns nrf21540dk_nrf52840
|
||||
integration_platforms:
|
||||
- nrf52840dk_nrf52840
|
||||
tags: bluetooth ci_build
|
||||
extra_configs:
|
||||
- CONFIG_BT_NUS_SECURITY_ENABLED=n
|
@ -0,0 +1,138 @@
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <bluetooth/services/nus.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "int_comm.h"
|
||||
#include "connection.h"
|
||||
|
||||
|
||||
#define LOG_MODULE_NAME fw_int_advertising
|
||||
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||
|
||||
|
||||
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
|
||||
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
|
||||
|
||||
bool advertising = false;
|
||||
bool advertising_wl = false;
|
||||
int bond_cnt = 0;
|
||||
|
||||
static const struct bt_data ad[] = {
|
||||
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
|
||||
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
|
||||
};
|
||||
|
||||
static const struct bt_data sd[] = {
|
||||
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_NUS_VAL),
|
||||
};
|
||||
|
||||
|
||||
static void add_to_whitelist(const struct bt_bond_info *info, void *user_data){
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
bt_addr_le_to_str(&info->addr, addr, sizeof(addr));
|
||||
|
||||
int err = bt_le_filter_accept_list_add(&info->addr);
|
||||
if (err){
|
||||
LOG_WRN("whitelist add: %s FAILED!\n", addr);
|
||||
}else{
|
||||
LOG_INF("whitelist add: %s\n", addr);
|
||||
}
|
||||
|
||||
bond_cnt++;
|
||||
}
|
||||
|
||||
|
||||
void advertising_setup_wl(void) {
|
||||
bt_le_filter_accept_list_clear();
|
||||
bt_foreach_bond(BT_ID_DEFAULT, add_to_whitelist, NULL);
|
||||
}
|
||||
|
||||
void advertising_start(bool wl){
|
||||
|
||||
if (advertising) {
|
||||
if (wl != advertising_wl) {
|
||||
LOG_WRN("Restarting advertising");
|
||||
bt_le_adv_stop();
|
||||
}else {
|
||||
LOG_WRN("Already advertising");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int err;
|
||||
|
||||
if (wl) {
|
||||
advertising_setup_wl();
|
||||
LOG_INF("Advertising with whitelist");
|
||||
err = bt_le_adv_start(
|
||||
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_FILTER_CONN | BT_LE_ADV_OPT_FILTER_SCAN_REQ,
|
||||
160, 1600, NULL),
|
||||
ad, ARRAY_SIZE(ad),
|
||||
sd, ARRAY_SIZE(sd));
|
||||
}
|
||||
else {
|
||||
LOG_INF("Advertising no whitelist");
|
||||
err = bt_le_adv_start(
|
||||
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE,
|
||||
160, 1600, NULL),
|
||||
ad, ARRAY_SIZE(ad),
|
||||
sd, ARRAY_SIZE(sd));
|
||||
}
|
||||
if (err) {
|
||||
LOG_ERR("Advertising failed to start (err %d)", err);
|
||||
return;
|
||||
}
|
||||
advertising = true;
|
||||
advertising_wl = wl;
|
||||
send_status_event();
|
||||
}
|
||||
|
||||
void advertising_stop(void){
|
||||
|
||||
if (!advertising) {
|
||||
LOG_WRN("Not advertising");
|
||||
return;
|
||||
}
|
||||
|
||||
int err = bt_le_adv_stop();
|
||||
if (err) {
|
||||
LOG_ERR("Advertising failed to stop (err %d)", err);
|
||||
return;
|
||||
}
|
||||
advertising = false;
|
||||
advertising_wl = false;
|
||||
send_status_event();
|
||||
}
|
||||
|
||||
bool is_advertising(void){
|
||||
return advertising;
|
||||
}
|
||||
|
||||
bool is_advertising_whitelist(void){
|
||||
return advertising_wl;
|
||||
}
|
||||
|
||||
|
||||
void advertising_init(void){
|
||||
LOG_INF("Advertising init");
|
||||
advertising_setup_wl();
|
||||
}
|
||||
|
||||
void erase_bonds(void){
|
||||
int err = bt_unpair(BT_ID_DEFAULT, BT_ADDR_LE_ANY);
|
||||
if (err) {
|
||||
LOG_INF("Cannot delete bond (err: %d)\n", err);
|
||||
} else {
|
||||
LOG_INF("Bond deleted successfully \n");
|
||||
}
|
||||
}
|
||||
|
||||
int advertising_get_bond_count(void){
|
||||
advertising_setup_wl();
|
||||
return bond_cnt;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
|
||||
void advertising_start(bool wl);
|
||||
void advertising_stop(void);
|
||||
bool is_advertising(void);
|
||||
bool is_advertising_whitelist(void);
|
||||
void advertising_init(void);
|
||||
void advertising_setup_wl(void);
|
||||
int advertising_get_bond_count(void);
|
||||
void erase_bonds(void);
|
@ -0,0 +1,170 @@
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
#include <zephyr/bluetooth/hci.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <dk_buttons_and_leds.h>
|
||||
|
||||
#include "connection.h"
|
||||
#include "advertising.h"
|
||||
#include "int_comm.h"
|
||||
#include "pb_comm.h"
|
||||
|
||||
#define CON_STATUS_LED DK_LED2
|
||||
|
||||
#define LOG_MODULE_NAME fw_int_connection
|
||||
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||
|
||||
static struct bt_conn *current_conn;
|
||||
static struct bt_conn *auth_conn;
|
||||
|
||||
void connected(struct bt_conn *conn, uint8_t err)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
if (err) {
|
||||
LOG_ERR("Connection failed (err %u)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
LOG_INF("Connected %s", addr);
|
||||
|
||||
current_conn = bt_conn_ref(conn);
|
||||
|
||||
// struct bt_le_conn_param params = BT_LE_CONN_PARAM_INIT(6,6,0,400);
|
||||
//
|
||||
// bt_conn_le_param_update(conn, ¶ms);
|
||||
|
||||
err = bt_conn_le_phy_update(current_conn, BT_CONN_LE_PHY_PARAM_2M);
|
||||
if (err) {
|
||||
LOG_ERR("Phy update request failed: %d", err);
|
||||
}
|
||||
|
||||
dk_set_led_on(CON_STATUS_LED);
|
||||
|
||||
send_status_event();
|
||||
}
|
||||
|
||||
void disconnected(struct bt_conn *conn, uint8_t reason)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
LOG_INF("Disconnected: %s (reason %u)", addr, reason);
|
||||
|
||||
if (auth_conn) {
|
||||
bt_conn_unref(auth_conn);
|
||||
auth_conn = NULL;
|
||||
}
|
||||
|
||||
if (current_conn) {
|
||||
bt_conn_unref(current_conn);
|
||||
current_conn = NULL;
|
||||
dk_set_led_off(CON_STATUS_LED);
|
||||
}
|
||||
|
||||
send_status_event();
|
||||
}
|
||||
|
||||
bool is_connected(void) {
|
||||
return current_conn != NULL;
|
||||
}
|
||||
|
||||
|
||||
void disconnect(void){
|
||||
if (current_conn) {
|
||||
bt_conn_disconnect(current_conn, BT_HCI_ERR_REMOTE_USER_TERM_CONN);
|
||||
}
|
||||
}
|
||||
|
||||
void num_comp_reply(bool accept)
|
||||
{
|
||||
if (accept) {
|
||||
bt_conn_auth_passkey_confirm(auth_conn);
|
||||
LOG_INF("Numeric Match, conn %p", (void *)auth_conn);
|
||||
} else {
|
||||
bt_conn_auth_cancel(auth_conn);
|
||||
LOG_INF("Numeric Reject, conn %p", (void *)auth_conn);
|
||||
}
|
||||
|
||||
bt_conn_unref(auth_conn);
|
||||
auth_conn = NULL;
|
||||
}
|
||||
|
||||
void passkey_to_str(uint8_t buf[6], unsigned int passkey) {
|
||||
buf[5] = (passkey % 10) + '0';
|
||||
buf[4] = ((passkey / 10) % 10) + '0';
|
||||
buf[3] = ((passkey / 100) % 10) + '0';
|
||||
buf[2] = ((passkey / 1000) % 10) + '0';
|
||||
buf[1] = ((passkey / 10000) % 10) + '0';
|
||||
buf[0] = ((passkey / 100000) % 10) + '0';
|
||||
}
|
||||
|
||||
void auth_passkey_display(struct bt_conn *conn, unsigned int passkey)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
uint8_t passkey_str[6];
|
||||
passkey_to_str(passkey_str, passkey);
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
pb_comm_enqueue(PASSKEY_DISPLAY, passkey_str, 6);
|
||||
}
|
||||
|
||||
void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
auth_conn = bt_conn_ref(conn);
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
uint8_t passkey_str[6];
|
||||
passkey_to_str(passkey_str, passkey);
|
||||
pb_comm_enqueue(COMPARISON_REQUEST, passkey_str, 6);
|
||||
|
||||
send_status_event();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void auth_cancel(struct bt_conn *conn)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
LOG_INF("Pairing cancelled: %s", addr);
|
||||
}
|
||||
|
||||
|
||||
void pairing_complete(struct bt_conn *conn, bool bonded)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
if (bonded) {
|
||||
advertising_setup_wl();
|
||||
}
|
||||
|
||||
LOG_INF("Pairing completed: %s, bonded: %d", addr, bonded);
|
||||
}
|
||||
|
||||
|
||||
void pairing_failed(struct bt_conn *conn, enum bt_security_err reason)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
LOG_INF("Pairing failed conn: %s, reason %d", addr, reason);
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
#include <zephyr/bluetooth/hci.h>
|
||||
|
||||
void connected(struct bt_conn *conn, uint8_t err);
|
||||
|
||||
void disconnect(void);
|
||||
|
||||
void disconnected(struct bt_conn *conn, uint8_t reason);
|
||||
|
||||
bool is_connected(void);
|
||||
|
||||
void num_comp_reply(bool accept);
|
||||
void auth_passkey_display(struct bt_conn *conn, unsigned int passkey);
|
||||
void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey);
|
||||
void auth_cancel(struct bt_conn *conn);
|
||||
void pairing_complete(struct bt_conn *conn, bool bonded);
|
||||
void pairing_failed(struct bt_conn *conn, enum bt_security_err reason);
|
||||
|
||||
void num_comp_reply(bool accept);
|
@ -0,0 +1,127 @@
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "uart.h"
|
||||
#include "int_comm_defs.h"
|
||||
#include "connection.h"
|
||||
#include "advertising.h"
|
||||
#include "pb_comm.h"
|
||||
|
||||
#define LOG_MODULE_NAME fw_int_comm
|
||||
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||
|
||||
static K_SEM_DEFINE(int_comm_ok, 0, 1);
|
||||
|
||||
|
||||
|
||||
void send_packet(uint8_t message_type, const uint8_t *tx_data, uint16_t len) {
|
||||
uart_data_t *tx = k_malloc(sizeof(*tx));
|
||||
|
||||
if (!tx) {
|
||||
LOG_WRN("Not able to allocate UART send data buffer");
|
||||
return;
|
||||
}
|
||||
|
||||
tx->len = len + OVERHEAD_SIZE;
|
||||
|
||||
tx->data[0] = message_type;
|
||||
tx->data[1] = (tx->len >> 8) & 0xFF;
|
||||
tx->data[2] = tx->len & 0xFF;
|
||||
memcpy(&tx->data[3], tx_data, len);
|
||||
tx->data[tx->len-1] = EOM;
|
||||
|
||||
uart_send(tx);
|
||||
|
||||
}
|
||||
|
||||
void send_status_event(void) {
|
||||
// ble_version_t version = {0};
|
||||
//
|
||||
// sd_ble_version_get(&version);
|
||||
|
||||
event_status_msg_t msg = {0};
|
||||
msg.msg_id = INTERNAL_EVENT_STATUS;
|
||||
msg.connected = is_connected();
|
||||
msg.advertising = is_advertising();
|
||||
msg.advertising_whitelist = is_advertising_whitelist();
|
||||
msg.peer_count = advertising_get_bond_count();
|
||||
msg.sd_version_number = 0;
|
||||
msg.sd_company_id = 0;
|
||||
msg.sd_subversion_number = 0;
|
||||
msg.app_version = 0;
|
||||
msg.bld_version = 0;
|
||||
|
||||
send_packet(INTERNAL_EVENT, (uint8_t *)&msg, sizeof(msg));
|
||||
}
|
||||
|
||||
|
||||
void send_success_event(void) {
|
||||
uint8_t tx_data[] = {
|
||||
INTERNAL_EVENT_SUCCESS,
|
||||
};
|
||||
send_packet(INTERNAL_EVENT, tx_data, sizeof(tx_data));
|
||||
}
|
||||
|
||||
uint16_t get_message_type(const uint8_t *rx_data) {
|
||||
return (rx_data[3] << 8) | rx_data[4];
|
||||
}
|
||||
|
||||
|
||||
void process_command(uint8_t *data, uint16_t len) {
|
||||
uint8_t cmd = data[0];
|
||||
switch (cmd) {
|
||||
case INTERNAL_CMD_SEND_STATE:
|
||||
send_status_event();
|
||||
break;
|
||||
case INTERNAL_CMD_ADVERTISING_ON:
|
||||
advertising_start(data[1] != 0);
|
||||
break;
|
||||
case INTERNAL_CMD_ADVERTISING_OFF:
|
||||
advertising_stop();
|
||||
break;
|
||||
case INTERNAL_CMD_ERASE_BONDS:
|
||||
erase_bonds();
|
||||
send_success_event();
|
||||
break;
|
||||
case INTERNAL_CMD_DISCONNECT:
|
||||
disconnect();
|
||||
send_success_event();
|
||||
case INTERNAL_CMD_ACK:
|
||||
pb_msg_ack();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void int_comm_start(void)
|
||||
{
|
||||
k_sem_give(&int_comm_ok);
|
||||
}
|
||||
|
||||
|
||||
void int_comm_thread(void)
|
||||
{
|
||||
/* Don't go any further until BLE is initialized */
|
||||
k_sem_take(&int_comm_ok, K_FOREVER);
|
||||
|
||||
for (;;) {
|
||||
/* Wait indefinitely for data to process */
|
||||
uart_data_t *buf = uart_get_data_int();
|
||||
|
||||
process_command(buf->data, buf->len);
|
||||
|
||||
k_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
//K_THREAD_DEFINE(int_comm_thread_id, CONFIG_BT_NUS_THREAD_STACK_SIZE, int_comm_thread, NULL, NULL,
|
||||
// NULL, 7, 0, 0);
|
@ -0,0 +1,18 @@
|
||||
#ifndef INT_COMM__
|
||||
#define INT_COMM__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void process_command(uint8_t *data, uint16_t len);
|
||||
|
||||
void send_status_event(void);
|
||||
|
||||
void int_comm_start(void);
|
||||
|
||||
void int_comm_thread(void);
|
||||
|
||||
void send_packet(uint8_t message_type, const uint8_t *tx_data, uint16_t len);
|
||||
|
||||
void pb_msg_ack(void);
|
||||
|
||||
#endif
|
@ -0,0 +1,50 @@
|
||||
|
||||
#ifndef __INT_COMM_DEFS__
|
||||
#define __INT_COMM_DEFS__
|
||||
|
||||
#define BLE_PACKET_SIZE (244)
|
||||
#define USB_DATA_SIZE (64)
|
||||
|
||||
#define COMM_HEADER_SIZE (3)
|
||||
#define COMM_FOOTER_SIZE (1)
|
||||
#define OVERHEAD_SIZE (COMM_HEADER_SIZE + COMM_FOOTER_SIZE)
|
||||
#define UART_PACKET_SIZE (USB_DATA_SIZE + OVERHEAD_SIZE)
|
||||
|
||||
#define EOM (0x55)
|
||||
#define INTERNAL_EVENT (0xA2)
|
||||
#define EXTERNAL_MESSAGE (0xA1)
|
||||
#define INTERNAL_MESSAGE (0xA0)
|
||||
|
||||
typedef struct {
|
||||
uint8_t msg_id;
|
||||
uint8_t connected;
|
||||
uint8_t advertising;
|
||||
uint8_t advertising_whitelist;
|
||||
|
||||
uint8_t peer_count;
|
||||
uint8_t reserved[2];
|
||||
uint8_t sd_version_number;
|
||||
|
||||
uint16_t sd_company_id;
|
||||
uint16_t sd_subversion_number;
|
||||
|
||||
uint32_t app_version;
|
||||
uint32_t bld_version;
|
||||
|
||||
} event_status_msg_t;
|
||||
|
||||
typedef enum {
|
||||
INTERNAL_EVENT_STATUS = 0x01,
|
||||
INTERNAL_EVENT_SUCCESS = 0x02,
|
||||
INTERNAL_EVENT_FAILURE = 0x03,
|
||||
} InternalEvent_t;
|
||||
|
||||
typedef enum {
|
||||
INTERNAL_CMD_SEND_STATE = 0x00,
|
||||
INTERNAL_CMD_ADVERTISING_ON = 0x01,
|
||||
INTERNAL_CMD_ADVERTISING_OFF = 0x02,
|
||||
INTERNAL_CMD_ERASE_BONDS = 0x03,
|
||||
INTERNAL_CMD_DISCONNECT = 0x04,
|
||||
INTERNAL_CMD_ACK = 0x05,
|
||||
} InternalCmd_t;
|
||||
#endif
|
@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Nordic UART Bridge Service (NUS) sample
|
||||
*/
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
#include <soc.h>
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
#include <zephyr/bluetooth/hci.h>
|
||||
|
||||
|
||||
#include <dk_buttons_and_leds.h>
|
||||
|
||||
#include <zephyr/settings/settings.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "uart.h"
|
||||
#include "spi.h"
|
||||
#include "connection.h"
|
||||
#include "int_comm.h"
|
||||
#include "pb_comm.h"
|
||||
#include "advertising.h"
|
||||
#include "trz_nus.h"
|
||||
|
||||
#define LOG_MODULE_NAME fw
|
||||
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||
|
||||
#define STACKSIZE CONFIG_BT_NUS_THREAD_STACK_SIZE
|
||||
#define PRIORITY 7
|
||||
|
||||
#define RUN_STATUS_LED DK_LED1
|
||||
#define RUN_LED_BLINK_INTERVAL 1000
|
||||
|
||||
#define FW_RUNNING_SIG DK_LED3
|
||||
|
||||
|
||||
#define KEY_PASSKEY_ACCEPT DK_BTN1_MSK
|
||||
#define KEY_PASSKEY_REJECT DK_BTN2_MSK
|
||||
|
||||
static K_SEM_DEFINE(ble_init_ok, 0, 1);
|
||||
static K_SEM_DEFINE(led_init_ok, 0, 1);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void security_changed(struct bt_conn *conn, bt_security_t level,
|
||||
enum bt_security_err err)
|
||||
{
|
||||
char addr[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
|
||||
|
||||
if (!err) {
|
||||
LOG_INF("Security changed: %s level %u", addr, level);
|
||||
} else {
|
||||
LOG_WRN("Security failed: %s level %u err %d", addr,
|
||||
level, err);
|
||||
}
|
||||
}
|
||||
|
||||
BT_CONN_CB_DEFINE(conn_callbacks) = {
|
||||
.connected = connected,
|
||||
.disconnected = disconnected,
|
||||
.security_changed = security_changed,
|
||||
};
|
||||
|
||||
|
||||
static struct bt_conn_auth_cb conn_auth_callbacks = {
|
||||
.passkey_display = auth_passkey_display,
|
||||
.passkey_confirm = auth_passkey_confirm,
|
||||
.cancel = auth_cancel,
|
||||
};
|
||||
|
||||
static struct bt_conn_auth_info_cb conn_auth_info_callbacks = {
|
||||
.pairing_complete = pairing_complete,
|
||||
.pairing_failed = pairing_failed
|
||||
};
|
||||
|
||||
|
||||
static void bt_receive_cb(struct bt_conn *conn, const uint8_t *const data,
|
||||
uint16_t len)
|
||||
{
|
||||
if ((dk_get_buttons() & DK_BTN2_MSK) == 0){
|
||||
LOG_INF("Trezor not ready, rejecting data");
|
||||
send_error_response();
|
||||
return;
|
||||
}
|
||||
|
||||
char addr[BT_ADDR_LE_STR_LEN] = {0};
|
||||
|
||||
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, ARRAY_SIZE(addr));
|
||||
|
||||
LOG_INF("Received data from: %s, %d", addr, len);
|
||||
|
||||
spi_send(data, len);
|
||||
}
|
||||
|
||||
static struct bt_nus_cb nus_cb = {
|
||||
.received = bt_receive_cb,
|
||||
};
|
||||
|
||||
void error(void)
|
||||
{
|
||||
dk_set_leds_state(DK_ALL_LEDS_MSK, DK_NO_LEDS_MSK);
|
||||
|
||||
while (true) {
|
||||
/* Spin for ever */
|
||||
k_sleep(K_MSEC(1000));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void button_changed(uint32_t button_state, uint32_t has_changed)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void configure_gpio(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = dk_buttons_init(button_changed);
|
||||
if (err) {
|
||||
LOG_ERR("Cannot init buttons (err: %d)", err);
|
||||
}
|
||||
|
||||
err = dk_leds_init();
|
||||
if (err) {
|
||||
LOG_ERR("Cannot init LEDs (err: %d)", err);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
LOG_INF("Initializing");
|
||||
|
||||
|
||||
configure_gpio();
|
||||
|
||||
err = uart_init();
|
||||
if (err) {
|
||||
error();
|
||||
}
|
||||
|
||||
spi_init();
|
||||
|
||||
err = bt_conn_auth_cb_register(&conn_auth_callbacks);
|
||||
if (err) {
|
||||
printk("Failed to register authorization callbacks.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = bt_conn_auth_info_cb_register(&conn_auth_info_callbacks);
|
||||
if (err) {
|
||||
printk("Failed to register authorization info callbacks.\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
err = bt_enable(NULL);
|
||||
if (err) {
|
||||
error();
|
||||
}
|
||||
|
||||
LOG_INF("Bluetooth initialized");
|
||||
|
||||
k_sem_give(&ble_init_ok);
|
||||
|
||||
if (IS_ENABLED(CONFIG_SETTINGS)) {
|
||||
settings_load();
|
||||
}
|
||||
|
||||
err = bt_nus_init(&nus_cb);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to initialize UART service (err: %d)", err);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bt_set_name("TrezorGAP");
|
||||
|
||||
advertising_init();
|
||||
int_comm_start();
|
||||
pb_comm_start();
|
||||
dk_set_led(FW_RUNNING_SIG, 1);
|
||||
send_status_event();
|
||||
|
||||
k_sem_give(&led_init_ok);
|
||||
|
||||
for (;;) {
|
||||
int_comm_thread();
|
||||
}
|
||||
}
|
||||
|
||||
void ble_write_thread(void)
|
||||
{
|
||||
/* Don't go any further until BLE is initialized */
|
||||
k_sem_take(&ble_init_ok, K_FOREVER);
|
||||
|
||||
for (;;) {
|
||||
/* Wait indefinitely for data to be sent over bluetooth */
|
||||
uart_data_t *buf = uart_get_data_ext();
|
||||
|
||||
if (bt_nus_send(NULL, buf->data, buf->len)) {
|
||||
LOG_WRN("Failed to send data over BLE connection");
|
||||
}
|
||||
|
||||
k_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void led_thread(void)
|
||||
{
|
||||
int blink_status = 0;
|
||||
/* Don't go any further until BLE is initialized */
|
||||
k_sem_take(&led_init_ok, K_FOREVER);
|
||||
|
||||
for (;;) {
|
||||
dk_set_led(RUN_STATUS_LED, (++blink_status) % 2);
|
||||
k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
K_THREAD_DEFINE(ble_write_thread_id, STACKSIZE, ble_write_thread, NULL, NULL,
|
||||
NULL, PRIORITY, 0, 0);
|
||||
|
||||
|
||||
K_THREAD_DEFINE(led_thread_id, STACKSIZE, led_thread, NULL, NULL,
|
||||
NULL, PRIORITY, 0, 0);
|
@ -0,0 +1,390 @@
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <dk_buttons_and_leds.h>
|
||||
|
||||
#include "protob/protob_helpers.h"
|
||||
#include "protob/messages.pb.h"
|
||||
|
||||
#include "int_comm.h"
|
||||
#include "int_comm_defs.h"
|
||||
#include "uart.h"
|
||||
#include "pb_comm.h"
|
||||
#include "connection.h"
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
void *fifo_reserved;
|
||||
uint8_t cmd;
|
||||
uint8_t data[PB_BUF_SIZE];
|
||||
uint16_t len;
|
||||
}pb_comm_data_t;
|
||||
|
||||
|
||||
#define PASSKEY_LEN 6
|
||||
|
||||
static K_SEM_DEFINE(pb_comm_ok, 0, 1);
|
||||
static K_SEM_DEFINE(pb_wait_for_ack, 0, 1);
|
||||
|
||||
|
||||
static K_FIFO_DEFINE(fifo_pb_tx_in); // data to send to trezor
|
||||
static K_FIFO_DEFINE(fifo_pb_tx_out); // data to send to host
|
||||
|
||||
|
||||
void prepare_response_wait() {
|
||||
k_sem_reset(&pb_wait_for_ack);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool write_resp(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) {
|
||||
write_state *state = (write_state *)(stream->state);
|
||||
|
||||
size_t written = 0;
|
||||
// while we have data left
|
||||
while (written < count) {
|
||||
size_t remaining = count - written;
|
||||
// if all remaining data fit into our packet
|
||||
if (state->packet_pos + remaining <= USB_PACKET_SIZE) {
|
||||
// append data from buf to state->buf
|
||||
memcpy(state->buf + state->packet_pos, buf + written, remaining);
|
||||
// advance position
|
||||
state->packet_pos += remaining;
|
||||
// and return
|
||||
return true;
|
||||
} else {
|
||||
// append data that fits
|
||||
memcpy(state->buf + state->packet_pos, buf + written,
|
||||
USB_PACKET_SIZE - state->packet_pos);
|
||||
written += USB_PACKET_SIZE - state->packet_pos;
|
||||
|
||||
// send packet
|
||||
uart_data_t * buf = k_malloc(sizeof(uart_data_t));
|
||||
buf->len = USB_DATA_SIZE;
|
||||
memcpy(buf->data, state->buf, USB_DATA_SIZE);
|
||||
uart_send_ext(buf);
|
||||
|
||||
// prepare new packet
|
||||
state->packet_index++;
|
||||
memset(state->buf, 0, USB_PACKET_SIZE);
|
||||
state->buf[0] = '?';
|
||||
state->packet_pos = MSG_HEADER2_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
void write_resp_flush(write_state *state) {
|
||||
// if packet is not filled up completely
|
||||
if (state->packet_pos < USB_PACKET_SIZE) {
|
||||
// pad it with zeroes
|
||||
memset(state->buf + state->packet_pos, 0,
|
||||
USB_PACKET_SIZE - state->packet_pos);
|
||||
}
|
||||
// send packet
|
||||
uart_data_t * buf = k_malloc(sizeof(uart_data_t));
|
||||
buf->len = USB_DATA_SIZE;
|
||||
memcpy(buf->data, state->buf, USB_DATA_SIZE);
|
||||
uart_send_ext(buf);
|
||||
}
|
||||
|
||||
bool write(pb_ostream_t *stream, const pb_byte_t *buf, size_t count) {
|
||||
write_state *state = (write_state *)(stream->state);
|
||||
|
||||
size_t written = 0;
|
||||
// while we have data left
|
||||
while (written < count) {
|
||||
size_t remaining = count - written;
|
||||
// if all remaining data fit into our packet
|
||||
if (state->packet_pos + remaining <= USB_PACKET_SIZE) {
|
||||
// append data from buf to state->buf
|
||||
memcpy(state->buf + state->packet_pos, buf + written, remaining);
|
||||
// advance position
|
||||
state->packet_pos += remaining;
|
||||
// and return
|
||||
return true;
|
||||
} else {
|
||||
// append data that fits
|
||||
memcpy(state->buf + state->packet_pos, buf + written,
|
||||
USB_PACKET_SIZE - state->packet_pos);
|
||||
written += USB_PACKET_SIZE - state->packet_pos;
|
||||
|
||||
// send packet
|
||||
send_packet(state->iface_num, state->buf, USB_PACKET_SIZE);
|
||||
|
||||
// prepare new packet
|
||||
state->packet_index++;
|
||||
memset(state->buf, 0, USB_PACKET_SIZE);
|
||||
state->buf[0] = '?';
|
||||
state->packet_pos = MSG_HEADER2_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
void write_flush(write_state *state) {
|
||||
// if packet is not filled up completely
|
||||
if (state->packet_pos < USB_PACKET_SIZE) {
|
||||
// pad it with zeroes
|
||||
memset(state->buf + state->packet_pos, 0,
|
||||
USB_PACKET_SIZE - state->packet_pos);
|
||||
}
|
||||
// send packet
|
||||
send_packet(state->iface_num, state->buf, USB_PACKET_SIZE);
|
||||
}
|
||||
|
||||
/* we don't use secbool/sectrue/secfalse here as it is a nanopb api */
|
||||
static bool read(pb_istream_t *stream, uint8_t *buf, size_t count) {
|
||||
read_state *state = (read_state *)(stream->state);
|
||||
|
||||
size_t read = 0;
|
||||
// while we have data left
|
||||
while (read < count) {
|
||||
size_t remaining = count - read;
|
||||
// if all remaining data fit into our packet
|
||||
if (state->packet_pos + remaining <= state->packet_size) {
|
||||
// append data from buf to state->buf
|
||||
memcpy(buf + read, state->buf + state->packet_pos, remaining);
|
||||
// advance position
|
||||
state->packet_pos += remaining;
|
||||
// and return
|
||||
return true;
|
||||
} else {
|
||||
// append data that fits
|
||||
memcpy(buf + read, state->buf + state->packet_pos,
|
||||
state->packet_size - state->packet_pos);
|
||||
read += state->packet_size - state->packet_pos;
|
||||
|
||||
// read next packet
|
||||
uart_data_t * data = uart_get_data_pb();
|
||||
if (data == NULL) {
|
||||
return false;
|
||||
}
|
||||
memcpy(state->buf, data->data, USB_PACKET_SIZE > data->len ? data->len : USB_PACKET_SIZE);
|
||||
k_free(data);
|
||||
|
||||
// prepare next packet
|
||||
state->packet_index++;
|
||||
state->packet_pos = MSG_HEADER2_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void read_flush(read_state *state) { (void)state; }
|
||||
|
||||
#define MSG_SEND_NRF(msg) (MSG_SEND(msg, write, write_flush))
|
||||
#define MSG_SEND_NRF_RESPONSE(msg) (MSG_SEND(msg, write_resp, write_resp_flush))
|
||||
|
||||
|
||||
|
||||
secbool process_auth_key(uint8_t *data, uint32_t len, void *msg) {
|
||||
recv_protob_msg(INTERNAL_MESSAGE, len, data, AuthKey_fields, msg, read,
|
||||
read_flush, USB_PACKET_SIZE);
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool process_success(uint8_t *data, uint32_t len, void *msg) {
|
||||
recv_protob_msg(INTERNAL_MESSAGE, len, data, Success_fields, msg, read,
|
||||
read_flush, USB_PACKET_SIZE);
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
void process_unexpected(uint8_t *data, uint32_t len) {}
|
||||
|
||||
|
||||
|
||||
secbool await_response(uint16_t expected,
|
||||
secbool (*process)(uint8_t *data, uint32_t len,
|
||||
void *msg),
|
||||
void *msg_recv) {
|
||||
|
||||
if (k_sem_take(&pb_wait_for_ack, K_MSEC(100)) != 0) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
if ((dk_get_buttons() & DK_BTN2_MSK) == 0) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
uint16_t id = 0;
|
||||
uint32_t msg_size = 0;
|
||||
|
||||
uart_data_t * data = uart_get_data_pb();
|
||||
while (data == NULL) {
|
||||
|
||||
if ((dk_get_buttons() & DK_BTN2_MSK) == 0) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
data = uart_get_data_pb();
|
||||
}
|
||||
|
||||
msg_parse_header(data->data, &id, &msg_size);
|
||||
|
||||
if (id == expected) {
|
||||
if (process != NULL) {
|
||||
return process(data->data, msg_size, msg_recv);
|
||||
}
|
||||
return sectrue;
|
||||
} else {
|
||||
process_unexpected(data->data, msg_size);
|
||||
}
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool read_authkey(pb_istream_t *stream, const pb_field_t *field,
|
||||
void **arg) {
|
||||
uint8_t *key_buffer = (uint8_t *)(*arg);
|
||||
|
||||
if (stream->bytes_left > PASSKEY_LEN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memset(key_buffer, 0, PASSKEY_LEN);
|
||||
|
||||
while (stream->bytes_left) {
|
||||
// read data
|
||||
if (!pb_read(stream, (pb_byte_t *)(key_buffer),
|
||||
(stream->bytes_left > PASSKEY_LEN)
|
||||
? PASSKEY_LEN
|
||||
: stream->bytes_left)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool write_authkey(pb_ostream_t *stream, const pb_field_t *field,
|
||||
void *const *arg) {
|
||||
uint8_t *key = (uint8_t *)(*arg);
|
||||
if (!pb_encode_tag_for_field(stream, field)) return false;
|
||||
|
||||
return pb_encode_string(stream, (uint8_t *)key, PASSKEY_LEN);
|
||||
}
|
||||
|
||||
bool send_comparison_request(uint8_t *p_key, int8_t p_key_len) {
|
||||
prepare_response_wait();
|
||||
uint8_t iface_num = INTERNAL_MESSAGE;
|
||||
MSG_SEND_INIT(ComparisonRequest);
|
||||
MSG_SEND_CALLBACK(key, write_authkey, p_key);
|
||||
MSG_SEND_NRF(ComparisonRequest);
|
||||
|
||||
MSG_RECV_INIT(Success);
|
||||
secbool result = await_response(MessageType_MessageType_Success,
|
||||
process_success, &msg_recv);
|
||||
|
||||
if (result != sectrue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_auth_key_request(uint8_t *p_key, uint8_t p_key_len) {
|
||||
prepare_response_wait();
|
||||
uint8_t iface_num = INTERNAL_MESSAGE;
|
||||
MSG_SEND_INIT(PairingRequest);
|
||||
MSG_SEND_NRF(PairingRequest);
|
||||
|
||||
uint8_t buffer[PASSKEY_LEN];
|
||||
MSG_RECV_INIT(AuthKey);
|
||||
MSG_RECV_CALLBACK(key, read_authkey, buffer);
|
||||
secbool result = await_response(MessageType_MessageType_AuthKey,
|
||||
process_auth_key, &msg_recv);
|
||||
|
||||
if (result != sectrue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(p_key, buffer,
|
||||
PASSKEY_LEN > p_key_len ? p_key_len : PASSKEY_LEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool send_repair_request(void) {
|
||||
prepare_response_wait();
|
||||
uint8_t iface_num = INTERNAL_MESSAGE;
|
||||
MSG_SEND_INIT(RepairRequest);
|
||||
MSG_SEND_NRF(RepairRequest);
|
||||
|
||||
MSG_RECV_INIT(Success);
|
||||
|
||||
secbool result = await_response(MessageType_MessageType_Success,
|
||||
process_success, &msg_recv);
|
||||
|
||||
return result == sectrue;
|
||||
}
|
||||
|
||||
|
||||
void send_error_response(void) {
|
||||
// communication with trezor is disabled
|
||||
uint8_t iface_num = 0;
|
||||
|
||||
MSG_SEND_INIT(Failure);
|
||||
MSG_SEND_ASSIGN_VALUE(code, FailureType_Failure_ProcessError);
|
||||
|
||||
msg_send.has_message = true;
|
||||
memset(msg_send.message, 0, sizeof(msg_send.message));
|
||||
const char msg[] = "Device Locked or Busy";
|
||||
strncpy(msg_send.message, msg, sizeof(msg_send.message) - 1);
|
||||
MSG_SEND_NRF_RESPONSE(Failure);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void pb_comm_start(void)
|
||||
{
|
||||
k_sem_give(&pb_comm_ok);
|
||||
}
|
||||
|
||||
void pb_comm_enqueue(uint8_t cmd, uint8_t * data, uint16_t len)
|
||||
{
|
||||
pb_comm_data_t * buf = k_malloc(sizeof(pb_comm_data_t));
|
||||
buf->cmd = cmd;
|
||||
memcpy(buf->data, data, len);
|
||||
buf->len = len;
|
||||
k_fifo_put(&fifo_pb_tx_in, buf);
|
||||
}
|
||||
|
||||
|
||||
void pb_comm_thread(void)
|
||||
{
|
||||
/* Don't go any further until BLE is initialized */
|
||||
k_sem_take(&pb_comm_ok, K_FOREVER);
|
||||
|
||||
for (;;) {
|
||||
/* Wait indefinitely for data to process */
|
||||
pb_comm_data_t * buf = k_fifo_get(&fifo_pb_tx_in, K_FOREVER);
|
||||
|
||||
switch(buf->cmd) {
|
||||
case COMPARISON_REQUEST:
|
||||
if (send_comparison_request(buf->data, buf->len)) {
|
||||
num_comp_reply(true);
|
||||
} else {
|
||||
num_comp_reply(false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
k_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
void pb_msg_ack(void) {
|
||||
k_sem_give(&pb_wait_for_ack);
|
||||
}
|
||||
|
||||
|
||||
K_THREAD_DEFINE(p_comm_thread_id, CONFIG_BT_NUS_THREAD_STACK_SIZE, pb_comm_thread, NULL, NULL,
|
||||
NULL, 7, 0, 0);
|
@ -0,0 +1,15 @@
|
||||
|
||||
#define PB_BUF_SIZE 64
|
||||
|
||||
typedef enum {
|
||||
COMPARISON_REQUEST = 0,
|
||||
AUTH_KEY_REQUEST = 1,
|
||||
REPAIR_REQUEST = 2,
|
||||
PASSKEY_DISPLAY = 3,
|
||||
}pb_comm_cmd_t;
|
||||
|
||||
void pb_comm_start(void);
|
||||
|
||||
void pb_comm_enqueue(pb_comm_cmd_t cmd, uint8_t *data, uint16_t len);
|
||||
|
||||
void send_error_response(void);
|
@ -0,0 +1,60 @@
|
||||
/* Automatically generated nanopb constant definitions */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#include "messages.pb.h"
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
PB_BIND(Initialize, Initialize, AUTO)
|
||||
|
||||
|
||||
PB_BIND(GetFeatures, GetFeatures, AUTO)
|
||||
|
||||
|
||||
PB_BIND(Features, Features, 2)
|
||||
|
||||
|
||||
PB_BIND(Ping, Ping, 2)
|
||||
|
||||
|
||||
PB_BIND(Success, Success, 2)
|
||||
|
||||
|
||||
PB_BIND(Failure, Failure, 2)
|
||||
|
||||
|
||||
PB_BIND(ButtonRequest, ButtonRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ButtonAck, ButtonAck, AUTO)
|
||||
|
||||
|
||||
PB_BIND(FirmwareErase, FirmwareErase, AUTO)
|
||||
|
||||
|
||||
PB_BIND(FirmwareRequest, FirmwareRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(FirmwareUpload, FirmwareUpload, AUTO)
|
||||
|
||||
|
||||
PB_BIND(UnlockBootloader, UnlockBootloader, AUTO)
|
||||
|
||||
|
||||
PB_BIND(PairingRequest, PairingRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(AuthKey, AuthKey, AUTO)
|
||||
|
||||
|
||||
PB_BIND(RepairRequest, RepairRequest, AUTO)
|
||||
|
||||
|
||||
PB_BIND(ComparisonRequest, ComparisonRequest, AUTO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,404 @@
|
||||
/* Automatically generated nanopb header */
|
||||
/* Generated by nanopb-0.4.5 */
|
||||
|
||||
#ifndef PB_MESSAGES_PB_H_INCLUDED
|
||||
#define PB_MESSAGES_PB_H_INCLUDED
|
||||
#include <pb.h>
|
||||
|
||||
#if PB_PROTO_HEADER_VERSION != 40
|
||||
#error Regenerate this file with the current version of nanopb generator.
|
||||
#endif
|
||||
|
||||
/* Enum definitions */
|
||||
typedef enum _MessageType {
|
||||
MessageType_MessageType_Initialize = 0,
|
||||
MessageType_MessageType_Ping = 1,
|
||||
MessageType_MessageType_Success = 2,
|
||||
MessageType_MessageType_Failure = 3,
|
||||
MessageType_MessageType_WipeDevice = 5,
|
||||
MessageType_MessageType_FirmwareErase = 6,
|
||||
MessageType_MessageType_FirmwareUpload = 7,
|
||||
MessageType_MessageType_FirmwareRequest = 8,
|
||||
MessageType_MessageType_Features = 17,
|
||||
MessageType_MessageType_ButtonRequest = 26,
|
||||
MessageType_MessageType_ButtonAck = 27,
|
||||
MessageType_MessageType_GetFeatures = 55,
|
||||
MessageType_MessageType_UnlockBootloader = 96,
|
||||
MessageType_MessageType_PairingRequest = 8003,
|
||||
MessageType_MessageType_AuthKey = 8004,
|
||||
MessageType_MessageType_RepairRequest = 8005,
|
||||
MessageType_MessageType_ComparisonRequest = 8008
|
||||
} MessageType;
|
||||
|
||||
typedef enum _FailureType {
|
||||
FailureType_Failure_UnexpectedMessage = 1,
|
||||
FailureType_Failure_DataError = 3,
|
||||
FailureType_Failure_ActionCancelled = 4,
|
||||
FailureType_Failure_ProcessError = 9
|
||||
} FailureType;
|
||||
|
||||
typedef enum _ButtonRequestType {
|
||||
ButtonRequestType_ButtonRequest_Other = 1
|
||||
} ButtonRequestType;
|
||||
|
||||
/* Struct definitions */
|
||||
typedef struct _AuthKey {
|
||||
pb_callback_t key;
|
||||
} AuthKey;
|
||||
|
||||
typedef struct _ButtonAck {
|
||||
char dummy_field;
|
||||
} ButtonAck;
|
||||
|
||||
typedef struct _ComparisonRequest {
|
||||
pb_callback_t key;
|
||||
} ComparisonRequest;
|
||||
|
||||
typedef struct _GetFeatures {
|
||||
char dummy_field;
|
||||
} GetFeatures;
|
||||
|
||||
typedef struct _Initialize {
|
||||
char dummy_field;
|
||||
} Initialize;
|
||||
|
||||
typedef struct _PairingRequest {
|
||||
char dummy_field;
|
||||
} PairingRequest;
|
||||
|
||||
typedef struct _RepairRequest {
|
||||
char dummy_field;
|
||||
} RepairRequest;
|
||||
|
||||
typedef struct _UnlockBootloader {
|
||||
char dummy_field;
|
||||
} UnlockBootloader;
|
||||
|
||||
typedef struct _ButtonRequest {
|
||||
bool has_code;
|
||||
ButtonRequestType code;
|
||||
} ButtonRequest;
|
||||
|
||||
typedef struct _Failure {
|
||||
bool has_code;
|
||||
FailureType code;
|
||||
bool has_message;
|
||||
char message[256];
|
||||
} Failure;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(20) Features_revision_t;
|
||||
typedef struct _Features {
|
||||
bool has_vendor;
|
||||
char vendor[33];
|
||||
uint32_t major_version;
|
||||
uint32_t minor_version;
|
||||
uint32_t patch_version;
|
||||
bool has_bootloader_mode;
|
||||
bool bootloader_mode;
|
||||
bool has_device_id;
|
||||
char device_id[25];
|
||||
bool has_language;
|
||||
char language[17];
|
||||
bool has_label;
|
||||
char label[33];
|
||||
bool has_initialized;
|
||||
bool initialized;
|
||||
bool has_revision;
|
||||
Features_revision_t revision;
|
||||
bool has_firmware_present;
|
||||
bool firmware_present;
|
||||
bool has_model;
|
||||
char model[17];
|
||||
bool has_fw_major;
|
||||
uint32_t fw_major;
|
||||
bool has_fw_minor;
|
||||
uint32_t fw_minor;
|
||||
bool has_fw_patch;
|
||||
uint32_t fw_patch;
|
||||
bool has_fw_vendor;
|
||||
char fw_vendor[256];
|
||||
bool has_internal_model;
|
||||
char internal_model[17];
|
||||
bool has_unit_color;
|
||||
uint32_t unit_color;
|
||||
bool has_unit_btconly;
|
||||
bool unit_btconly;
|
||||
bool has_bootloader_locked;
|
||||
bool bootloader_locked;
|
||||
} Features;
|
||||
|
||||
typedef struct _FirmwareErase {
|
||||
bool has_length;
|
||||
uint32_t length;
|
||||
} FirmwareErase;
|
||||
|
||||
typedef struct _FirmwareRequest {
|
||||
uint32_t offset;
|
||||
uint32_t length;
|
||||
} FirmwareRequest;
|
||||
|
||||
typedef PB_BYTES_ARRAY_T(32) FirmwareUpload_hash_t;
|
||||
typedef struct _FirmwareUpload {
|
||||
pb_callback_t payload;
|
||||
bool has_hash;
|
||||
FirmwareUpload_hash_t hash;
|
||||
} FirmwareUpload;
|
||||
|
||||
typedef struct _Ping {
|
||||
bool has_message;
|
||||
char message[256];
|
||||
} Ping;
|
||||
|
||||
typedef struct _Success {
|
||||
bool has_message;
|
||||
char message[256];
|
||||
} Success;
|
||||
|
||||
|
||||
/* Helper constants for enums */
|
||||
#define _MessageType_MIN MessageType_MessageType_Initialize
|
||||
#define _MessageType_MAX MessageType_MessageType_ComparisonRequest
|
||||
#define _MessageType_ARRAYSIZE ((MessageType)(MessageType_MessageType_ComparisonRequest+1))
|
||||
|
||||
#define _FailureType_MIN FailureType_Failure_UnexpectedMessage
|
||||
#define _FailureType_MAX FailureType_Failure_ProcessError
|
||||
#define _FailureType_ARRAYSIZE ((FailureType)(FailureType_Failure_ProcessError+1))
|
||||
|
||||
#define _ButtonRequestType_MIN ButtonRequestType_ButtonRequest_Other
|
||||
#define _ButtonRequestType_MAX ButtonRequestType_ButtonRequest_Other
|
||||
#define _ButtonRequestType_ARRAYSIZE ((ButtonRequestType)(ButtonRequestType_ButtonRequest_Other+1))
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Initializer values for message structs */
|
||||
#define Initialize_init_default {0}
|
||||
#define GetFeatures_init_default {0}
|
||||
#define Features_init_default {false, "", 0, 0, 0, false, 0, false, "", false, "", false, "", false, 0, false, {0, {0}}, false, 0, false, "", false, 0, false, 0, false, 0, false, "", false, "", false, 0, false, 0, false, 0}
|
||||
#define Ping_init_default {false, ""}
|
||||
#define Success_init_default {false, ""}
|
||||
#define Failure_init_default {false, _FailureType_MIN, false, ""}
|
||||
#define ButtonRequest_init_default {false, _ButtonRequestType_MIN}
|
||||
#define ButtonAck_init_default {0}
|
||||
#define FirmwareErase_init_default {false, 0}
|
||||
#define FirmwareRequest_init_default {0, 0}
|
||||
#define FirmwareUpload_init_default {{{NULL}, NULL}, false, {0, {0}}}
|
||||
#define UnlockBootloader_init_default {0}
|
||||
#define PairingRequest_init_default {0}
|
||||
#define AuthKey_init_default {{{NULL}, NULL}}
|
||||
#define RepairRequest_init_default {0}
|
||||
#define ComparisonRequest_init_default {{{NULL}, NULL}}
|
||||
#define Initialize_init_zero {0}
|
||||
#define GetFeatures_init_zero {0}
|
||||
#define Features_init_zero {false, "", 0, 0, 0, false, 0, false, "", false, "", false, "", false, 0, false, {0, {0}}, false, 0, false, "", false, 0, false, 0, false, 0, false, "", false, "", false, 0, false, 0, false, 0}
|
||||
#define Ping_init_zero {false, ""}
|
||||
#define Success_init_zero {false, ""}
|
||||
#define Failure_init_zero {false, _FailureType_MIN, false, ""}
|
||||
#define ButtonRequest_init_zero {false, _ButtonRequestType_MIN}
|
||||
#define ButtonAck_init_zero {0}
|
||||
#define FirmwareErase_init_zero {false, 0}
|
||||
#define FirmwareRequest_init_zero {0, 0}
|
||||
#define FirmwareUpload_init_zero {{{NULL}, NULL}, false, {0, {0}}}
|
||||
#define UnlockBootloader_init_zero {0}
|
||||
#define PairingRequest_init_zero {0}
|
||||
#define AuthKey_init_zero {{{NULL}, NULL}}
|
||||
#define RepairRequest_init_zero {0}
|
||||
#define ComparisonRequest_init_zero {{{NULL}, NULL}}
|
||||
|
||||
/* Field tags (for use in manual encoding/decoding) */
|
||||
#define AuthKey_key_tag 1
|
||||
#define ComparisonRequest_key_tag 1
|
||||
#define ButtonRequest_code_tag 1
|
||||
#define Failure_code_tag 1
|
||||
#define Failure_message_tag 2
|
||||
#define Features_vendor_tag 1
|
||||
#define Features_major_version_tag 2
|
||||
#define Features_minor_version_tag 3
|
||||
#define Features_patch_version_tag 4
|
||||
#define Features_bootloader_mode_tag 5
|
||||
#define Features_device_id_tag 6
|
||||
#define Features_language_tag 9
|
||||
#define Features_label_tag 10
|
||||
#define Features_initialized_tag 12
|
||||
#define Features_revision_tag 13
|
||||
#define Features_firmware_present_tag 18
|
||||
#define Features_model_tag 21
|
||||
#define Features_fw_major_tag 22
|
||||
#define Features_fw_minor_tag 23
|
||||
#define Features_fw_patch_tag 24
|
||||
#define Features_fw_vendor_tag 25
|
||||
#define Features_internal_model_tag 44
|
||||
#define Features_unit_color_tag 45
|
||||
#define Features_unit_btconly_tag 46
|
||||
#define Features_bootloader_locked_tag 49
|
||||
#define FirmwareErase_length_tag 1
|
||||
#define FirmwareRequest_offset_tag 1
|
||||
#define FirmwareRequest_length_tag 2
|
||||
#define FirmwareUpload_payload_tag 1
|
||||
#define FirmwareUpload_hash_tag 2
|
||||
#define Ping_message_tag 1
|
||||
#define Success_message_tag 1
|
||||
|
||||
/* Struct field encoding specification for nanopb */
|
||||
#define Initialize_FIELDLIST(X, a) \
|
||||
|
||||
#define Initialize_CALLBACK NULL
|
||||
#define Initialize_DEFAULT NULL
|
||||
|
||||
#define GetFeatures_FIELDLIST(X, a) \
|
||||
|
||||
#define GetFeatures_CALLBACK NULL
|
||||
#define GetFeatures_DEFAULT NULL
|
||||
|
||||
#define Features_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, STRING, vendor, 1) \
|
||||
X(a, STATIC, REQUIRED, UINT32, major_version, 2) \
|
||||
X(a, STATIC, REQUIRED, UINT32, minor_version, 3) \
|
||||
X(a, STATIC, REQUIRED, UINT32, patch_version, 4) \
|
||||
X(a, STATIC, OPTIONAL, BOOL, bootloader_mode, 5) \
|
||||
X(a, STATIC, OPTIONAL, STRING, device_id, 6) \
|
||||
X(a, STATIC, OPTIONAL, STRING, language, 9) \
|
||||
X(a, STATIC, OPTIONAL, STRING, label, 10) \
|
||||
X(a, STATIC, OPTIONAL, BOOL, initialized, 12) \
|
||||
X(a, STATIC, OPTIONAL, BYTES, revision, 13) \
|
||||
X(a, STATIC, OPTIONAL, BOOL, firmware_present, 18) \
|
||||
X(a, STATIC, OPTIONAL, STRING, model, 21) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, fw_major, 22) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, fw_minor, 23) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, fw_patch, 24) \
|
||||
X(a, STATIC, OPTIONAL, STRING, fw_vendor, 25) \
|
||||
X(a, STATIC, OPTIONAL, STRING, internal_model, 44) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, unit_color, 45) \
|
||||
X(a, STATIC, OPTIONAL, BOOL, unit_btconly, 46) \
|
||||
X(a, STATIC, OPTIONAL, BOOL, bootloader_locked, 49)
|
||||
#define Features_CALLBACK NULL
|
||||
#define Features_DEFAULT NULL
|
||||
|
||||
#define Ping_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, STRING, message, 1)
|
||||
#define Ping_CALLBACK NULL
|
||||
#define Ping_DEFAULT (const pb_byte_t*)"\x0a\x00\x00"
|
||||
|
||||
#define Success_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, STRING, message, 1)
|
||||
#define Success_CALLBACK NULL
|
||||
#define Success_DEFAULT (const pb_byte_t*)"\x0a\x00\x00"
|
||||
|
||||
#define Failure_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, UENUM, code, 1) \
|
||||
X(a, STATIC, OPTIONAL, STRING, message, 2)
|
||||
#define Failure_CALLBACK NULL
|
||||
#define Failure_DEFAULT (const pb_byte_t*)"\x08\x01\x00"
|
||||
|
||||
#define ButtonRequest_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, UENUM, code, 1)
|
||||
#define ButtonRequest_CALLBACK NULL
|
||||
#define ButtonRequest_DEFAULT (const pb_byte_t*)"\x08\x01\x00"
|
||||
|
||||
#define ButtonAck_FIELDLIST(X, a) \
|
||||
|
||||
#define ButtonAck_CALLBACK NULL
|
||||
#define ButtonAck_DEFAULT NULL
|
||||
|
||||
#define FirmwareErase_FIELDLIST(X, a) \
|
||||
X(a, STATIC, OPTIONAL, UINT32, length, 1)
|
||||
#define FirmwareErase_CALLBACK NULL
|
||||
#define FirmwareErase_DEFAULT NULL
|
||||
|
||||
#define FirmwareRequest_FIELDLIST(X, a) \
|
||||
X(a, STATIC, REQUIRED, UINT32, offset, 1) \
|
||||
X(a, STATIC, REQUIRED, UINT32, length, 2)
|
||||
#define FirmwareRequest_CALLBACK NULL
|
||||
#define FirmwareRequest_DEFAULT NULL
|
||||
|
||||
#define FirmwareUpload_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, REQUIRED, BYTES, payload, 1) \
|
||||
X(a, STATIC, OPTIONAL, BYTES, hash, 2)
|
||||
#define FirmwareUpload_CALLBACK pb_default_field_callback
|
||||
#define FirmwareUpload_DEFAULT NULL
|
||||
|
||||
#define UnlockBootloader_FIELDLIST(X, a) \
|
||||
|
||||
#define UnlockBootloader_CALLBACK NULL
|
||||
#define UnlockBootloader_DEFAULT NULL
|
||||
|
||||
#define PairingRequest_FIELDLIST(X, a) \
|
||||
|
||||
#define PairingRequest_CALLBACK NULL
|
||||
#define PairingRequest_DEFAULT NULL
|
||||
|
||||
#define AuthKey_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, REQUIRED, BYTES, key, 1)
|
||||
#define AuthKey_CALLBACK pb_default_field_callback
|
||||
#define AuthKey_DEFAULT NULL
|
||||
|
||||
#define RepairRequest_FIELDLIST(X, a) \
|
||||
|
||||
#define RepairRequest_CALLBACK NULL
|
||||
#define RepairRequest_DEFAULT NULL
|
||||
|
||||
#define ComparisonRequest_FIELDLIST(X, a) \
|
||||
X(a, CALLBACK, REQUIRED, BYTES, key, 1)
|
||||
#define ComparisonRequest_CALLBACK pb_default_field_callback
|
||||
#define ComparisonRequest_DEFAULT NULL
|
||||
|
||||
extern const pb_msgdesc_t Initialize_msg;
|
||||
extern const pb_msgdesc_t GetFeatures_msg;
|
||||
extern const pb_msgdesc_t Features_msg;
|
||||
extern const pb_msgdesc_t Ping_msg;
|
||||
extern const pb_msgdesc_t Success_msg;
|
||||
extern const pb_msgdesc_t Failure_msg;
|
||||
extern const pb_msgdesc_t ButtonRequest_msg;
|
||||
extern const pb_msgdesc_t ButtonAck_msg;
|
||||
extern const pb_msgdesc_t FirmwareErase_msg;
|
||||
extern const pb_msgdesc_t FirmwareRequest_msg;
|
||||
extern const pb_msgdesc_t FirmwareUpload_msg;
|
||||
extern const pb_msgdesc_t UnlockBootloader_msg;
|
||||
extern const pb_msgdesc_t PairingRequest_msg;
|
||||
extern const pb_msgdesc_t AuthKey_msg;
|
||||
extern const pb_msgdesc_t RepairRequest_msg;
|
||||
extern const pb_msgdesc_t ComparisonRequest_msg;
|
||||
|
||||
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
|
||||
#define Initialize_fields &Initialize_msg
|
||||
#define GetFeatures_fields &GetFeatures_msg
|
||||
#define Features_fields &Features_msg
|
||||
#define Ping_fields &Ping_msg
|
||||
#define Success_fields &Success_msg
|
||||
#define Failure_fields &Failure_msg
|
||||
#define ButtonRequest_fields &ButtonRequest_msg
|
||||
#define ButtonAck_fields &ButtonAck_msg
|
||||
#define FirmwareErase_fields &FirmwareErase_msg
|
||||
#define FirmwareRequest_fields &FirmwareRequest_msg
|
||||
#define FirmwareUpload_fields &FirmwareUpload_msg
|
||||
#define UnlockBootloader_fields &UnlockBootloader_msg
|
||||
#define PairingRequest_fields &PairingRequest_msg
|
||||
#define AuthKey_fields &AuthKey_msg
|
||||
#define RepairRequest_fields &RepairRequest_msg
|
||||
#define ComparisonRequest_fields &ComparisonRequest_msg
|
||||
|
||||
/* Maximum encoded size of messages (where known) */
|
||||
/* FirmwareUpload_size depends on runtime parameters */
|
||||
/* AuthKey_size depends on runtime parameters */
|
||||
/* ComparisonRequest_size depends on runtime parameters */
|
||||
#define ButtonAck_size 0
|
||||
#define ButtonRequest_size 2
|
||||
#define Failure_size 260
|
||||
#define Features_size 490
|
||||
#define FirmwareErase_size 6
|
||||
#define FirmwareRequest_size 12
|
||||
#define GetFeatures_size 0
|
||||
#define Initialize_size 0
|
||||
#define PairingRequest_size 0
|
||||
#define Ping_size 258
|
||||
#define RepairRequest_size 0
|
||||
#define Success_size 258
|
||||
#define UnlockBootloader_size 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,87 @@
|
||||
|
||||
|
||||
#include "protob_helpers.h"
|
||||
|
||||
secbool send_protob_msg(uint8_t iface_num, uint16_t msg_id,
|
||||
const pb_msgdesc_t *fields, const void *msg,
|
||||
bool (*write)(pb_ostream_t *stream,
|
||||
const pb_byte_t *buf, size_t count),
|
||||
void (*write_flush)(write_state *state)) {
|
||||
// determine message size by serializing it into a dummy stream
|
||||
pb_ostream_t sizestream = {.callback = NULL,
|
||||
.state = NULL,
|
||||
.max_size = SIZE_MAX,
|
||||
.bytes_written = 0,
|
||||
.errmsg = NULL};
|
||||
if (false == pb_encode(&sizestream, fields, msg)) {
|
||||
return secfalse;
|
||||
}
|
||||
const uint32_t msg_size = sizestream.bytes_written;
|
||||
|
||||
write_state state = {
|
||||
.iface_num = iface_num,
|
||||
.packet_index = 0,
|
||||
.packet_pos = MSG_HEADER1_LEN,
|
||||
.buf =
|
||||
{
|
||||
'?',
|
||||
'#',
|
||||
'#',
|
||||
(msg_id >> 8) & 0xFF,
|
||||
msg_id & 0xFF,
|
||||
(msg_size >> 24) & 0xFF,
|
||||
(msg_size >> 16) & 0xFF,
|
||||
(msg_size >> 8) & 0xFF,
|
||||
msg_size & 0xFF,
|
||||
},
|
||||
};
|
||||
|
||||
pb_ostream_t stream = {.callback = write,
|
||||
.state = &state,
|
||||
.max_size = SIZE_MAX,
|
||||
.bytes_written = 0,
|
||||
.errmsg = NULL};
|
||||
|
||||
if (false == pb_encode(&stream, fields, msg)) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
write_flush(&state);
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
secbool recv_protob_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
|
||||
const pb_msgdesc_t *fields, void *msg,
|
||||
bool (*read)(pb_istream_t *stream, pb_byte_t *buf,
|
||||
size_t count),
|
||||
void (*read_flush)(read_state *state),
|
||||
uint16_t packet_size) {
|
||||
read_state state = {.iface_num = iface_num,
|
||||
.packet_index = 0,
|
||||
.packet_pos = MSG_HEADER1_LEN,
|
||||
.packet_size = packet_size,
|
||||
.buf = buf};
|
||||
|
||||
pb_istream_t stream = {.callback = read,
|
||||
.state = &state,
|
||||
.bytes_left = msg_size,
|
||||
.errmsg = NULL};
|
||||
|
||||
if (false == pb_decode_noinit(&stream, fields, msg)) {
|
||||
return secfalse;
|
||||
}
|
||||
|
||||
read_flush(&state);
|
||||
|
||||
return sectrue;
|
||||
}
|
||||
|
||||
secbool msg_parse_header(const uint8_t *buf, uint16_t *msg_id,
|
||||
uint32_t *msg_size) {
|
||||
if (buf[0] != '?' || buf[1] != '#' || buf[2] != '#') {
|
||||
return secfalse;
|
||||
}
|
||||
*msg_id = (buf[3] << 8) + buf[4];
|
||||
*msg_size = (buf[5] << 24) + (buf[6] << 16) + (buf[7] << 8) + buf[8];
|
||||
return sectrue;
|
||||
}
|
@ -0,0 +1,87 @@
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "secbool.h"
|
||||
|
||||
#define USB_PACKET_SIZE 64
|
||||
#define MSG_HEADER1_LEN 9
|
||||
#define MSG_HEADER2_LEN 1
|
||||
|
||||
#define MSG_SEND_INIT(TYPE) TYPE msg_send = TYPE##_init_default
|
||||
#define MSG_SEND_ASSIGN_REQUIRED_VALUE(FIELD, VALUE) \
|
||||
{ msg_send.FIELD = VALUE; }
|
||||
#define MSG_SEND_ASSIGN_VALUE(FIELD, VALUE) \
|
||||
{ \
|
||||
msg_send.has_##FIELD = true; \
|
||||
msg_send.FIELD = VALUE; \
|
||||
}
|
||||
#define MSG_SEND_ASSIGN_STRING(FIELD, VALUE) \
|
||||
{ \
|
||||
msg_send.has_##FIELD = true; \
|
||||
memzero(msg_send.FIELD, sizeof(msg_send.FIELD)); \
|
||||
strncpy(msg_send.FIELD, VALUE, sizeof(msg_send.FIELD) - 1); \
|
||||
}
|
||||
#define MSG_SEND_ASSIGN_STRING_LEN(FIELD, VALUE, LEN) \
|
||||
{ \
|
||||
msg_send.has_##FIELD = true; \
|
||||
memzero(msg_send.FIELD, sizeof(msg_send.FIELD)); \
|
||||
strncpy(msg_send.FIELD, VALUE, MIN(LEN, sizeof(msg_send.FIELD) - 1)); \
|
||||
}
|
||||
#define MSG_SEND_ASSIGN_BYTES(FIELD, VALUE, LEN) \
|
||||
{ \
|
||||
msg_send.has_##FIELD = true; \
|
||||
memzero(msg_send.FIELD.bytes, sizeof(msg_send.FIELD.bytes)); \
|
||||
memcpy(msg_send.FIELD.bytes, VALUE, \
|
||||
MIN(LEN, sizeof(msg_send.FIELD.bytes))); \
|
||||
msg_send.FIELD.size = MIN(LEN, sizeof(msg_send.FIELD.bytes)); \
|
||||
}
|
||||
#define MSG_SEND_CALLBACK(FIELD, CALLBACK, ARGUMENT) \
|
||||
{ \
|
||||
msg_send.FIELD.funcs.encode = &CALLBACK; \
|
||||
msg_send.FIELD.arg = (void *)ARGUMENT; \
|
||||
}
|
||||
#define MSG_SEND(TYPE, WRITE, WRITE_FLUSH) \
|
||||
send_protob_msg(iface_num, MessageType_MessageType_##TYPE, TYPE##_fields, \
|
||||
&msg_send, WRITE, WRITE_FLUSH)
|
||||
|
||||
#define MSG_RECV_INIT(TYPE) TYPE msg_recv = TYPE##_init_default
|
||||
#define MSG_RECV_CALLBACK(FIELD, CALLBACK, ARGUMENT) \
|
||||
{ \
|
||||
msg_recv.FIELD.funcs.decode = &CALLBACK; \
|
||||
msg_recv.FIELD.arg = (void *)ARGUMENT; \
|
||||
}
|
||||
#define MSG_RECV(TYPE, READ, READ_FLUSH, PACKET_SIZE) \
|
||||
recv_protob_msg(iface_num, msg_size, buf, TYPE##_fields, &msg_recv, READ, \
|
||||
READ_FLUSH, PACKET_SIZE)
|
||||
|
||||
typedef struct {
|
||||
uint8_t iface_num;
|
||||
uint8_t packet_index;
|
||||
uint8_t packet_pos;
|
||||
uint8_t buf[USB_PACKET_SIZE];
|
||||
} write_state;
|
||||
|
||||
typedef struct {
|
||||
uint8_t iface_num;
|
||||
uint8_t packet_index;
|
||||
uint8_t packet_pos;
|
||||
uint16_t packet_size;
|
||||
uint8_t *buf;
|
||||
} read_state;
|
||||
|
||||
secbool send_protob_msg(uint8_t iface_num, uint16_t msg_id,
|
||||
const pb_msgdesc_t *fields, const void *msg,
|
||||
bool (*write_fnc)(pb_ostream_t *stream,
|
||||
const pb_byte_t *buf, size_t count),
|
||||
void (*write_flush)(write_state *state));
|
||||
|
||||
secbool recv_protob_msg(uint8_t iface_num, uint32_t msg_size, uint8_t *buf,
|
||||
const pb_msgdesc_t *fields, void *msg,
|
||||
bool (*read)(pb_istream_t *stream, pb_byte_t *buf,
|
||||
size_t count),
|
||||
void (*read_flush)(read_state *state),
|
||||
uint16_t packet_size);
|
||||
|
||||
secbool msg_parse_header(const uint8_t *buf, uint16_t *msg_id,
|
||||
uint32_t *msg_size);
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This file is part of the Trezor project, https://trezor.io/
|
||||
*
|
||||
* Copyright (c) SatoshiLabs
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_SECBOOL_H
|
||||
#define TREZORHAL_SECBOOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint32_t secbool;
|
||||
#define sectrue 0xAAAAAAAAU
|
||||
#define secfalse 0x00000000U
|
||||
|
||||
#ifndef __wur
|
||||
#define __wur __attribute__((warn_unused_result))
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,108 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/drivers/spi.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
|
||||
#include "spi.h"
|
||||
|
||||
#define MY_SPI_MASTER DT_NODELABEL(spi0)
|
||||
|
||||
static K_SEM_DEFINE(spi_comm_ok, 0, 1);
|
||||
static K_FIFO_DEFINE(fifo_spi_tx_data);
|
||||
|
||||
typedef struct {
|
||||
void *fifo_reserved;
|
||||
uint8_t data[244];
|
||||
uint16_t len;
|
||||
}spi_data_t;
|
||||
|
||||
|
||||
const struct device *spi_dev;
|
||||
static struct k_poll_signal spi_done_sig = K_POLL_SIGNAL_INITIALIZER(spi_done_sig);
|
||||
|
||||
struct spi_cs_control spim_cs = {
|
||||
.gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(reg_my_spi_master)),
|
||||
.delay = 0,
|
||||
};
|
||||
|
||||
static const struct spi_config spi_cfg = {
|
||||
.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB,
|
||||
.frequency = 8000000,
|
||||
.slave = 0,
|
||||
.cs = {
|
||||
.gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(reg_my_spi_master)),
|
||||
.delay = 0,
|
||||
},
|
||||
};
|
||||
|
||||
void spi_init(void)
|
||||
{
|
||||
spi_dev = DEVICE_DT_GET(MY_SPI_MASTER);
|
||||
if(!device_is_ready(spi_dev)) {
|
||||
printk("SPI master device not ready!\n");
|
||||
}
|
||||
if(!device_is_ready(spim_cs.gpio.port)){
|
||||
printk("SPI master chip select device not ready!\n");
|
||||
}
|
||||
|
||||
k_sem_give(&spi_comm_ok);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void spi_send(const uint8_t * data, uint32_t len)
|
||||
{
|
||||
if (len != 244) {
|
||||
// unexpected length
|
||||
return;
|
||||
}
|
||||
|
||||
spi_data_t * tx = k_malloc(sizeof(*tx));
|
||||
|
||||
if (!tx) {
|
||||
printk("Not able to allocate SPI send data buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
tx->len = len;
|
||||
memcpy(tx->data, data, len);
|
||||
|
||||
k_fifo_put(&fifo_spi_tx_data, tx);
|
||||
}
|
||||
|
||||
void spi_thread(void)
|
||||
{
|
||||
/* Don't go any further until BLE is initialized */
|
||||
k_sem_take(&spi_comm_ok, K_FOREVER);
|
||||
|
||||
for (;;) {
|
||||
/* Wait indefinitely for data to process */
|
||||
spi_data_t *buf = k_fifo_get(&fifo_spi_tx_data, K_FOREVER);
|
||||
|
||||
const struct spi_buf tx_buf = {
|
||||
.buf = buf->data,
|
||||
.len = buf->len,
|
||||
};
|
||||
|
||||
const struct spi_buf_set tx = {
|
||||
.buffers = &tx_buf,
|
||||
.count = 1
|
||||
};
|
||||
|
||||
spi_transceive(spi_dev, &spi_cfg, &tx,NULL);
|
||||
|
||||
k_free(buf);
|
||||
}
|
||||
}
|
||||
|
||||
K_THREAD_DEFINE(spi_thread_id, CONFIG_BT_NUS_THREAD_STACK_SIZE, spi_thread, NULL, NULL,
|
||||
NULL, 7, 0, 0);
|
@ -0,0 +1,6 @@
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void spi_init(void);
|
||||
void spi_send(const uint8_t * data, uint32_t len);
|
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
*/
|
||||
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "trz_nus.h"
|
||||
|
||||
LOG_MODULE_REGISTER(trznus);
|
||||
|
||||
static struct bt_nus_cb nus_cb;
|
||||
|
||||
|
||||
static void nus_ccc_cfg_changed(const struct bt_gatt_attr *attr,
|
||||
uint16_t value)
|
||||
{
|
||||
if (nus_cb.send_enabled) {
|
||||
LOG_DBG("Notification has been turned %s",
|
||||
value == BT_GATT_CCC_NOTIFY ? "on" : "off");
|
||||
nus_cb.send_enabled(value == BT_GATT_CCC_NOTIFY ?
|
||||
BT_NUS_SEND_STATUS_ENABLED : BT_NUS_SEND_STATUS_DISABLED);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static ssize_t on_receive(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr,
|
||||
const void *buf,
|
||||
uint16_t len,
|
||||
uint16_t offset,
|
||||
uint8_t flags)
|
||||
{
|
||||
LOG_DBG("Received data, handle %d, conn %p",
|
||||
attr->handle, (void *)conn);
|
||||
|
||||
if (nus_cb.received) {
|
||||
nus_cb.received(conn, buf, len);
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
static void on_sent(struct bt_conn *conn, void *user_data)
|
||||
{
|
||||
ARG_UNUSED(user_data);
|
||||
|
||||
LOG_DBG("Data send, conn %p", (void *)conn);
|
||||
|
||||
if (nus_cb.sent) {
|
||||
nus_cb.sent(conn);
|
||||
}
|
||||
}
|
||||
|
||||
/* UART Service Declaration */
|
||||
BT_GATT_SERVICE_DEFINE(nus_svc,
|
||||
BT_GATT_PRIMARY_SERVICE(BT_UUID_NUS_SERVICE),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_NUS_TX, BT_GATT_CHRC_NOTIFY, BT_GATT_PERM_READ_ENCRYPT, NULL, NULL, NULL),
|
||||
BT_GATT_CCC(nus_ccc_cfg_changed, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT),
|
||||
BT_GATT_CHARACTERISTIC(BT_UUID_NUS_RX, BT_GATT_CHRC_WRITE | BT_GATT_CHRC_WRITE_WITHOUT_RESP, BT_GATT_PERM_READ_ENCRYPT | BT_GATT_PERM_WRITE_ENCRYPT, NULL, on_receive, NULL),
|
||||
);
|
||||
|
||||
int bt_nus_init(struct bt_nus_cb *callbacks)
|
||||
{
|
||||
if (callbacks) {
|
||||
nus_cb.received = callbacks->received;
|
||||
nus_cb.sent = callbacks->sent;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bt_nus_send(struct bt_conn *conn, const uint8_t *data, uint16_t len)
|
||||
{
|
||||
struct bt_gatt_notify_params params = {0};
|
||||
const struct bt_gatt_attr *attr = &nus_svc.attrs[2];
|
||||
|
||||
params.attr = attr;
|
||||
params.data = data;
|
||||
params.len = len;
|
||||
params.func = on_sent;
|
||||
|
||||
if (conn && bt_gatt_is_subscribed(conn, attr, BT_GATT_CCC_NOTIFY)) {
|
||||
return bt_gatt_notify_cb(conn, ¶ms);
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
|
||||
*/
|
||||
|
||||
#ifndef BT_NUS_H_
|
||||
#define BT_NUS_H_
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @defgroup bt_nus Nordic UART (NUS) GATT Service
|
||||
* @{
|
||||
* @brief Nordic UART (NUS) GATT Service API.
|
||||
*/
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/uuid.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @brief UUID of the NUS Service. **/
|
||||
#define BT_UUID_NUS_VAL \
|
||||
BT_UUID_128_ENCODE(0x6e400001, 0xb5a3, 0xf393, 0xe0a9, 0xe50e24dcca9e)
|
||||
|
||||
/** @brief UUID of the TX Characteristic. **/
|
||||
#define BT_UUID_NUS_TX_VAL \
|
||||
BT_UUID_128_ENCODE(0x6e400003, 0xb5a3, 0xf393, 0xe0a9, 0xe50e24dcca9e)
|
||||
|
||||
/** @brief UUID of the RX Characteristic. **/
|
||||
#define BT_UUID_NUS_RX_VAL \
|
||||
BT_UUID_128_ENCODE(0x6e400002, 0xb5a3, 0xf393, 0xe0a9, 0xe50e24dcca9e)
|
||||
|
||||
#define BT_UUID_NUS_SERVICE BT_UUID_DECLARE_128(BT_UUID_NUS_VAL)
|
||||
#define BT_UUID_NUS_RX BT_UUID_DECLARE_128(BT_UUID_NUS_RX_VAL)
|
||||
#define BT_UUID_NUS_TX BT_UUID_DECLARE_128(BT_UUID_NUS_TX_VAL)
|
||||
|
||||
/** @brief NUS send status. */
|
||||
enum bt_nus_send_status {
|
||||
/** Send notification enabled. */
|
||||
BT_NUS_SEND_STATUS_ENABLED,
|
||||
/** Send notification disabled. */
|
||||
BT_NUS_SEND_STATUS_DISABLED,
|
||||
};
|
||||
|
||||
/** @brief Pointers to the callback functions for service events. */
|
||||
struct bt_nus_cb {
|
||||
/** @brief Data received callback.
|
||||
*
|
||||
* The data has been received as a write request on the NUS RX
|
||||
* Characteristic.
|
||||
*
|
||||
* @param[in] conn Pointer to connection object that has received data.
|
||||
* @param[in] data Received data.
|
||||
* @param[in] len Length of received data.
|
||||
*/
|
||||
void (*received)(struct bt_conn *conn,
|
||||
const uint8_t *const data, uint16_t len);
|
||||
|
||||
/** @brief Data sent callback.
|
||||
*
|
||||
* The data has been sent as a notification and written on the NUS TX
|
||||
* Characteristic.
|
||||
*
|
||||
* @param[in] conn Pointer to connection object, or NULL if sent to all
|
||||
* connected peers.
|
||||
*/
|
||||
void (*sent)(struct bt_conn *conn);
|
||||
|
||||
/** @brief Send state callback.
|
||||
*
|
||||
* Indicate the
|
||||
* CCCD descriptor status of the NUS TX characteristic.
|
||||
*
|
||||
* @param[in] status Send notification status.
|
||||
*/
|
||||
void (*send_enabled)(enum bt_nus_send_status status);
|
||||
|
||||
};
|
||||
|
||||
/**@brief Initialize the service.
|
||||
*
|
||||
* @details This function registers a GATT service with two characteristics,
|
||||
* TX and RX. A remote device that is connected to this service
|
||||
* can send data to the RX Characteristic. When the remote enables
|
||||
* notifications, it is notified when data is sent to the TX
|
||||
* Characteristic.
|
||||
*
|
||||
* @param[in] callbacks Struct with function pointers to callbacks for service
|
||||
* events. If no callbacks are needed, this parameter can
|
||||
* be NULL.
|
||||
*
|
||||
* @retval 0 If initialization is successful.
|
||||
* Otherwise, a negative value is returned.
|
||||
*/
|
||||
int bt_nus_init(struct bt_nus_cb *callbacks);
|
||||
|
||||
/**@brief Send data.
|
||||
*
|
||||
* @details This function sends data to a connected peer, or all connected
|
||||
* peers.
|
||||
*
|
||||
* @param[in] conn Pointer to connection object, or NULL to send to all
|
||||
* connected peers.
|
||||
* @param[in] data Pointer to a data buffer.
|
||||
* @param[in] len Length of the data in the buffer.
|
||||
*
|
||||
* @retval 0 If the data is sent.
|
||||
* Otherwise, a negative value is returned.
|
||||
*/
|
||||
int bt_nus_send(struct bt_conn *conn, const uint8_t *data, uint16_t len);
|
||||
|
||||
/**@brief Get maximum data length that can be used for @ref bt_nus_send.
|
||||
*
|
||||
* @param[in] conn Pointer to connection Object.
|
||||
*
|
||||
* @return Maximum data length.
|
||||
*/
|
||||
static inline uint32_t bt_nus_get_mtu(struct bt_conn *conn)
|
||||
{
|
||||
/* According to 3.4.7.1 Handle Value Notification off the ATT protocol.
|
||||
* Maximum supported notification is ATT_MTU - 3 */
|
||||
return bt_gatt_get_mtu(conn) - 3;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
*@}
|
||||
*/
|
||||
|
||||
#endif /* BT_NUS_H_ */
|
@ -0,0 +1,309 @@
|
||||
#include <zephyr/types.h>
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/devicetree.h>
|
||||
|
||||
#include <dk_buttons_and_leds.h>
|
||||
|
||||
#include <zephyr/settings/settings.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include "uart.h"
|
||||
#include "int_comm.h"
|
||||
#include "int_comm_defs.h"
|
||||
|
||||
#define LOG_MODULE_NAME fw_uart
|
||||
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||
|
||||
#define UART_WAIT_FOR_BUF_DELAY K_MSEC(50)
|
||||
#define UART_WAIT_FOR_RX CONFIG_BT_NUS_UART_RX_WAIT_TIME
|
||||
|
||||
static const struct device *uart = DEVICE_DT_GET(DT_CHOSEN(nordic_nus_uart));
|
||||
|
||||
static K_FIFO_DEFINE(fifo_uart_tx_data);
|
||||
static K_FIFO_DEFINE(fifo_uart_rx_data);
|
||||
static K_FIFO_DEFINE(fifo_uart_rx_data_int);
|
||||
static K_FIFO_DEFINE(fifo_uart_rx_data_pb);
|
||||
|
||||
|
||||
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
|
||||
{
|
||||
ARG_UNUSED(dev);
|
||||
|
||||
static size_t aborted_len;
|
||||
uart_data_t *buf;
|
||||
static uint8_t *aborted_buf;
|
||||
static bool disable_req;
|
||||
static uint8_t rx_phase = 0;
|
||||
static uint8_t rx_msg_type = 0;
|
||||
static uint8_t rx_data_len = 0;
|
||||
static uint8_t rx_len = 0;
|
||||
|
||||
switch (evt->type) {
|
||||
case UART_TX_DONE:
|
||||
LOG_DBG("UART_TX_DONE");
|
||||
if ((evt->data.tx.len == 0) ||
|
||||
(!evt->data.tx.buf)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (aborted_buf) {
|
||||
buf = CONTAINER_OF(aborted_buf, uart_data_t,
|
||||
data);
|
||||
aborted_buf = NULL;
|
||||
aborted_len = 0;
|
||||
} else {
|
||||
buf = CONTAINER_OF(evt->data.tx.buf, uart_data_t,
|
||||
data);
|
||||
}
|
||||
|
||||
k_free(buf);
|
||||
|
||||
buf = k_fifo_get(&fifo_uart_tx_data, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (uart_tx(uart, buf->data, buf->len, SYS_FOREVER_MS)) {
|
||||
LOG_WRN("Failed to send data over UART");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case UART_RX_RDY:
|
||||
LOG_DBG("UART_RX_RDY");
|
||||
buf = CONTAINER_OF(evt->data.rx.buf, uart_data_t, data);
|
||||
buf->len += evt->data.rx.len;
|
||||
|
||||
switch(rx_phase) {
|
||||
case 0:
|
||||
if (buf->len == 1 && (buf->data[0] == INTERNAL_EVENT || buf->data[0] == INTERNAL_MESSAGE || buf->data[0] == EXTERNAL_MESSAGE) ) {
|
||||
rx_phase = 1;
|
||||
rx_msg_type = buf->data[0];
|
||||
} else {
|
||||
rx_phase = 0;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (buf->len == 2) {
|
||||
rx_data_len = buf->data[0] << 8 | buf->data[1];
|
||||
rx_phase = 2;
|
||||
} else{
|
||||
rx_phase = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
if (buf->len == rx_data_len - 3) {
|
||||
rx_phase = 3;
|
||||
} else {
|
||||
rx_phase = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// if (disable_req) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if ((evt->data.rx.buf[buf->len - 1] == '\n') ||
|
||||
// (evt->data.rx.buf[buf->len - 1] == '\r')) {
|
||||
// disable_req = true;
|
||||
// uart_rx_disable(uart);
|
||||
// }
|
||||
|
||||
break;
|
||||
|
||||
case UART_RX_DISABLED:
|
||||
LOG_DBG("UART_RX_DISABLED");
|
||||
disable_req = false;
|
||||
|
||||
buf = k_malloc(sizeof(*buf));
|
||||
|
||||
if (buf) {
|
||||
|
||||
switch (rx_phase) {
|
||||
case 0:
|
||||
rx_len = 1;
|
||||
break;
|
||||
case 1:
|
||||
rx_len = 2;
|
||||
break;
|
||||
case 2:
|
||||
rx_len = rx_data_len - 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
rx_len = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
buf->len = 0;
|
||||
uart_rx_enable(uart, buf->data, rx_len, SYS_FOREVER_US);
|
||||
} else {
|
||||
LOG_WRN("Not able to allocate UART receive buffer");
|
||||
}
|
||||
|
||||
// buf = k_malloc(sizeof(*buf));
|
||||
// if (buf) {
|
||||
// buf->len = 0;
|
||||
// } else {
|
||||
// LOG_WRN("Not able to allocate UART receive buffer");
|
||||
// k_work_reschedule(&uart_work, UART_WAIT_FOR_BUF_DELAY);
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// uart_rx_enable(uart, buf->data, sizeof(buf->data),
|
||||
// UART_WAIT_FOR_RX);
|
||||
|
||||
break;
|
||||
|
||||
// case UART_RX_BUF_REQUEST:
|
||||
// LOG_INF("UART_RX_BUF_REQUEST");
|
||||
// buf = k_malloc(sizeof(*buf));
|
||||
//
|
||||
//
|
||||
// if (buf) {
|
||||
//
|
||||
// switch (rx_phase) {
|
||||
// case 0:
|
||||
// rx_len = 1;
|
||||
// break;
|
||||
// case 1:
|
||||
// rx_len = 2;
|
||||
// break;
|
||||
// default:
|
||||
// rx_len = 1;
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// buf->len = 0;
|
||||
// LOG_INF("Providing buf %d", rx_len);
|
||||
// uart_rx_buf_rsp(uart, buf->data, rx_len);
|
||||
// } else {
|
||||
// LOG_WRN("Not able to allocate UART receive buffer");
|
||||
// }
|
||||
//
|
||||
// break;
|
||||
|
||||
case UART_RX_BUF_RELEASED:
|
||||
LOG_DBG("UART_RX_BUF_RELEASED");
|
||||
buf = CONTAINER_OF(evt->data.rx_buf.buf, uart_data_t,
|
||||
data);
|
||||
|
||||
if (rx_phase == 3 && buf->len > 0) {
|
||||
buf->len -= 1;
|
||||
if (rx_msg_type == EXTERNAL_MESSAGE) {
|
||||
k_fifo_put(&fifo_uart_rx_data, buf);
|
||||
}
|
||||
else if (rx_msg_type == INTERNAL_EVENT) {
|
||||
k_fifo_put(&fifo_uart_rx_data_int, buf);
|
||||
}
|
||||
else {
|
||||
k_fifo_put(&fifo_uart_rx_data_pb, buf);
|
||||
}
|
||||
rx_data_len= 0;
|
||||
rx_len = 0;
|
||||
rx_msg_type = 0;
|
||||
rx_phase = 0;
|
||||
} else {
|
||||
k_free(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case UART_TX_ABORTED:
|
||||
LOG_DBG("UART_TX_ABORTED");
|
||||
if (!aborted_buf) {
|
||||
aborted_buf = (uint8_t *)evt->data.tx.buf;
|
||||
}
|
||||
|
||||
aborted_len += evt->data.tx.len;
|
||||
buf = CONTAINER_OF(aborted_buf, uart_data_t,
|
||||
data);
|
||||
|
||||
uart_tx(uart, &buf->data[aborted_len],
|
||||
buf->len - aborted_len, SYS_FOREVER_MS);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uart_init(void)
|
||||
{
|
||||
int err;
|
||||
uart_data_t *rx;
|
||||
|
||||
if (!device_is_ready(uart)) {
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
struct uart_config cfg = {
|
||||
.baudrate = 1000000,
|
||||
.parity = UART_CFG_PARITY_NONE,
|
||||
.stop_bits = UART_CFG_STOP_BITS_1,
|
||||
.data_bits = UART_CFG_DATA_BITS_8,
|
||||
.flow_ctrl = UART_CFG_FLOW_CTRL_RTS_CTS,
|
||||
|
||||
};
|
||||
|
||||
uart_configure(uart, &cfg);
|
||||
|
||||
rx = k_malloc(sizeof(*rx));
|
||||
if (rx) {
|
||||
rx->len = 0;
|
||||
} else {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err = uart_callback_set(uart, uart_cb, NULL);
|
||||
if (err) {
|
||||
k_free(rx);
|
||||
LOG_ERR("Cannot initialize UART callback");
|
||||
return err;
|
||||
}
|
||||
|
||||
// receive message type
|
||||
err = uart_rx_enable(uart, rx->data, 1, SYS_FOREVER_US);
|
||||
if (err) {
|
||||
LOG_ERR("Cannot enable uart reception (err: %d)", err);
|
||||
/* Free the rx buffer only because the tx buffer will be handled in the callback */
|
||||
k_free(rx);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
void uart_send_ext(uart_data_t *tx)
|
||||
{
|
||||
k_fifo_put(&fifo_uart_rx_data, tx);
|
||||
}
|
||||
|
||||
uart_data_t *uart_get_data_ext(void)
|
||||
{
|
||||
return k_fifo_get(&fifo_uart_rx_data, K_FOREVER);
|
||||
}
|
||||
|
||||
uart_data_t *uart_get_data_int(void)
|
||||
{
|
||||
return k_fifo_get(&fifo_uart_rx_data_int, K_FOREVER);
|
||||
}
|
||||
|
||||
uart_data_t *uart_get_data_pb(void)
|
||||
{
|
||||
return k_fifo_get(&fifo_uart_rx_data_pb, K_MSEC(100));
|
||||
}
|
||||
|
||||
void uart_send(uart_data_t *tx)
|
||||
{
|
||||
int err = uart_tx(uart, tx->data, tx->len, SYS_FOREVER_MS);
|
||||
if (err) {
|
||||
k_fifo_put(&fifo_uart_tx_data, tx);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,21 @@
|
||||
#ifndef UART_H
|
||||
#define UART_H
|
||||
|
||||
#define UART_BUF_SIZE 247
|
||||
|
||||
typedef struct {
|
||||
void *fifo_reserved;
|
||||
uint8_t data[UART_BUF_SIZE];
|
||||
uint16_t len;
|
||||
}uart_data_t;
|
||||
|
||||
int uart_init(void);
|
||||
|
||||
uart_data_t * uart_get_data_ext(void);
|
||||
uart_data_t * uart_get_data_int(void);
|
||||
uart_data_t * uart_get_data_pb(void);
|
||||
|
||||
void uart_send(uart_data_t *data);
|
||||
void uart_send_ext(uart_data_t *tx);
|
||||
|
||||
#endif
|
Loading…
Reference in new issue