Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support compilation for x86 as a static library using CMake. #201

Merged
merged 56 commits into from
Jan 17, 2023
Merged
Show file tree
Hide file tree
Changes from 54 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
c2144fe
Adding a minimal CMakeLists.txt to build this library as a static C++…
aentinger Jan 11, 2023
faf0749
C++11 dropped designated initializers (what a shame). They only come …
aentinger Jan 11, 2023
9c54345
Parameter req not used, dropping it.
aentinger Jan 11, 2023
f2062bf
Adding CI build smoke test.
aentinger Jan 11, 2023
e0e5e97
Eliminating unused parameters.
aentinger Jan 11, 2023
3ffcb9c
Fix deprecated-copy warning.
aentinger Jan 11, 2023
bda6916
Improve conditional code flow.
aentinger Jan 11, 2023
b1d09cb
Enable -Werror.
aentinger Jan 11, 2023
362e894
Breaking out the base class (and make one, where non exists) into a s…
aentinger Jan 11, 2023
10a660c
Add libsocketcan to CMake build not to Arduino build.
aentinger Jan 12, 2023
711282c
Adding C++ wraper around C socketcan driver.
aentinger Jan 12, 2023
c8aeb83
Minimal documentation of how to build this library as a static C++ li…
aentinger Jan 12, 2023
f636142
Adding minimum executable and move host source code into extras folde…
aentinger Jan 12, 2023
54c3f34
Create proper library structure.
aentinger Jan 12, 2023
3a9feef
Fix compilation (Note: do not ever prefix a library target name with …
aentinger Jan 12, 2023
92c021c
Fixing typo to o1heap.
aentinger Jan 12, 2023
290260a
Pass unique id by reference, saves one copy.
aentinger Jan 12, 2023
926351b
Implementing a very basic OpenCyphal node.
aentinger Jan 12, 2023
870f446
Renaming to be consistent with Ardunio examples.
aentinger Jan 12, 2023
9508028
A simple millis() function simplifies the code somewhat.
aentinger Jan 12, 2023
f08b9b6
Implementing code for receiving.
aentinger Jan 12, 2023
145f056
Prevent race conditions via locking.
aentinger Jan 12, 2023
17c601b
Enable usage of a single library include only.
aentinger Jan 12, 2023
050d30b
A better solution for the header file situation.
aentinger Jan 12, 2023
da71a31
Rename to libcyphal++.
aentinger Jan 12, 2023
4a9b5d0
Adding script for setting up virtual can.
aentinger Jan 16, 2023
7867bdf
Fix: Erroneous handling of deadline lead to no CAN frame being sent.
aentinger Jan 16, 2023
425d073
Fix: we need a clock that does not progress when we halt the program …
aentinger Jan 16, 2023
8297a08
Adding some very basic documentation.
aentinger Jan 16, 2023
a5a3396
Remove trailing whitespaces.
aentinger Jan 16, 2023
7a9e035
Fix spelling.
aentinger Jan 16, 2023
02899d8
Add candump to documentation.
aentinger Jan 16, 2023
d57204a
Fix: uptime is in seconds, not milliseconds.
aentinger Jan 16, 2023
319d78f
Improve documentation on how to invoke the setup scripts.
aentinger Jan 16, 2023
ee06f9b
Consting for file descriptor.
aentinger Jan 16, 2023
6131cf4
Drop virtual prefix from method that overrides.
aentinger Jan 16, 2023
cd78218
Rule-of-5 (and all that).
aentinger Jan 16, 2023
569942c
Prevent further inheritance from Publisher.
aentinger Jan 16, 2023
b9a15bb
Use final to prevent further inheritance.
aentinger Jan 16, 2023
98ad67b
Drop virtual prefix for override member functions.
aentinger Jan 16, 2023
db5d502
Mark setup_yakut.sh as executable.
aentinger Jan 17, 2023
abaa99e
Using std::find saves iterating over the same std::map twice.
aentinger Jan 17, 2023
1dd3629
Improve documentation.
aentinger Jan 17, 2023
0efaabc
Turn CAN transmit function into a member variable (again).
aentinger Jan 17, 2023
f489043
No need for defining the empty response, automatically done in ctor.
aentinger Jan 17, 2023
b7653e4
Move SocketCAN.h/.cpp out of cyphal++ library and into 'libsocketcan'…
aentinger Jan 17, 2023
c77a2d5
A dedicated CanRxItem eliminates the need for std::tuple and automati…
aentinger Jan 17, 2023
43e54cf
Using peek/pop eliminates unnecessary copy-ing.
aentinger Jan 17, 2023
f1ffd2b
Rename registers to from uavcan to cyphal.
aentinger Jan 17, 2023
e858604
Adding missing newline.
aentinger Jan 17, 2023
b0d31bb
Fix: Usage of unassigned variable.
aentinger Jan 17, 2023
5237c5e
Fix: add missing include for unique_ptr.
aentinger Jan 17, 2023
7cbb949
Add required include for strlen.
aentinger Jan 17, 2023
6ee8649
canard_transfer_kind can be protected.
aentinger Jan 17, 2023
779617e
Fix how to initialize virtual can.
aentinger Jan 17, 2023
e3f095a
Update extras/cyphal++/examples/example-01-opencyphal-basic-node/READ…
aentinger Jan 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/smoke-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Build

# See: https://docs.github.com/en/actions/reference/events-that-trigger-workflows
on:
push:
pull_request:
schedule:
# Run every Tuesday at 8 AM UTC
- cron: "0 8 * * TUE"
workflow_dispatch:
repository_dispatch:

permissions:
contents: read

jobs:
smoke-test:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Install CMake
run: sudo apt-get install cmake

- name: Create build directory, run CMake and Make
run: mkdir build && cd build && cmake -DBUILD_EXAMPLES=ON .. && make
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
.vscode/
.idea/
build/
cmake-build-debug/
33 changes: 33 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
##########################################################################
cmake_minimum_required(VERSION 3.15)
##########################################################################
project("cyphal++")
##########################################################################
set(CMAKE_VERBOSE_MAKEFILE OFF)
##########################################################################
option(BUILD_EXAMPLES "Build all examples provided with this library" OFF)
##########################################################################
add_subdirectory(src/libcanard)
add_subdirectory(src/libo1heap)
add_subdirectory(extras/cyphal++/libsocketcan)
##########################################################################
add_library(${PROJECT_NAME} STATIC
src/nodeinfo/NodeInfo.cpp
src/register/util/ListResponse.cpp
src/register/RegisterBase.cpp
src/register/RegisterList.cpp
src/Node.cpp
)
##########################################################################
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra -Wpedantic -Werror)
endif()
##########################################################################
target_include_directories(${PROJECT_NAME} PUBLIC src extras/cyphal++/include)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_11)
target_link_libraries(${PROJECT_NAME} canard o1heap socketcan)
##########################################################################
if(BUILD_EXAMPLES)
add_subdirectory(extras/cyphal++/examples/example-01-opencyphal-basic-node)
endif()
##########################################################################
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
====================
[![Arduino Library Badge](https://www.ardu-badge.com/badge/107-Arduino-Cyphal.svg?)](https://www.ardu-badge.com/107-Arduino-Cyphal)
[![Compile Examples](https://github.com/107-systems/107-Arduino-Cyphal/workflows/Compile%20Examples/badge.svg)](https://github.com/107-systems/107-Arduino-Cyphal/actions?workflow=Compile+Examples)
[![Smoke test status](https://github.com/107-systems/107-Arduino-Cyphal/actions/workflows/smoke-test.yml/badge.svg)](https://github.com/107-systems/107-Arduino-Cyphal/actions/workflows/smoke-test.yml)
[![Arduino Lint](https://github.com/107-systems/107-Arduino-Cyphal/workflows/Arduino%20Lint/badge.svg)](https://github.com/107-systems/107-Arduino-Cyphal/actions?workflow=Arduino+Lint)
[![keywords.txt Checks](https://github.com/107-systems/107-Arduino-Cyphal/workflows/Extra%20Library%20Checks/badge.svg)](https://github.com/107-systems/107-Arduino-Cyphal/actions?workflow=Extra+Library+Checks)
[![General Formatting Checks](https://github.com/107-systems/107-Arduino-Cyphal/workflows/General%20Formatting%20Checks/badge.svg)](https://github.com/107-systems/107-Arduino-Cyphal/actions?workflow=General+Formatting+Checks)
Expand All @@ -20,6 +21,16 @@ This library works for
* [arduino-esp32](https://github.com/espressif/arduino-esp32): `ESP32 Dev Module`, `ESP32 Wrover Module`, ... :heavy_check_mark:
* [arduino-pico](https://github.com/earlephilhower/arduino-pico): [`Raspberry Pi Pico`](https://www.raspberrypi.org/products/raspberry-pi-pico), `Adafruit Feather RP2040`, ... :heavy_check_mark:
* [adafruit/ArduinoCore-samd](https://github.com/adafruit/ArduinoCore-samd): [`Adafruit Feather M4 CAN Express`](https://www.adafruit.com/product/4759), ... :heavy_check_mark:
* **Host** (x86/x64/...): Using the CMake build system this library can be cross-compiled to a static C++ library and linked against any C++ executable. This is possible because the code itself is pure C/C++ without and dependencies to the Arduino framework.
```bash
* git clone https://github.com/107-systems/libdynamixelplusplus && cd libdynamixelplusplus
mkdir build && cd build
cmake .. && make
```
or
```bash
cmake -DBUILD_EXAMPLES=ON .. && make
```

### Reference-Implementation OpenCyphal on Arduino
* [OpenCyphal-GNSS-Node](examples/OpenCyphal-GNSS-Node): A OpenCyphal node with a GNSS sensor providing location data.
Expand Down
4 changes: 2 additions & 2 deletions examples/OpenCyphal-Blink/OpenCyphal-Blink.ino
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ ArduinoMCP2515 mcp2515([]() { digitalWrite(MKRCAN_MCP2515_CS_PIN, LOW); },
nullptr);

Node::Heap<Node::DEFAULT_O1HEAP_SIZE> node_heap;
Node node_hdl(node_heap.data(), node_heap.size(), micros);
Node node_hdl(node_heap.data(), node_heap.size(), micros, [] (CanardFrame const & frame) { return mcp2515.transmit(frame); });

Publisher<Heartbeat_1_0<>> heartbeat_pub = node_hdl.create_publisher<Heartbeat_1_0<>>(
Heartbeat_1_0<>::PORT_ID, 1*1000*1000UL /* = 1 sec in usecs. */);
Expand Down Expand Up @@ -124,7 +124,7 @@ void loop()
*/
{
CriticalSection crit_sec;
node_hdl.spinSome([] (CanardFrame const & frame) { return mcp2515.transmit(frame); });
node_hdl.spinSome();
}

/* Update the heartbeat object */
Expand Down
4 changes: 2 additions & 2 deletions examples/OpenCyphal-GNSS-Node/OpenCyphal-GNSS-Node.ino
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ ArduinoMCP2515 mcp2515([]() { digitalWrite(MKRCAN_MCP2515_CS_PIN, LOW); },
nullptr);

Node::Heap<Node::DEFAULT_O1HEAP_SIZE> node_heap;
Node node_hdl(node_heap.data(), node_heap.size(), micros);
Node node_hdl(node_heap.data(), node_heap.size(), micros, [] (CanardFrame const & frame) { return mcp2515.transmit(frame); });

Publisher<uavcan::node::Heartbeat_1_0<>> heartbeat_pub = node_hdl.create_publisher<uavcan::node::Heartbeat_1_0<>>(uavcan::node::Heartbeat_1_0<>::PORT_ID, 1*1000*1000UL /* = 1 sec in usecs. */);

Expand Down Expand Up @@ -151,7 +151,7 @@ void loop()
*/
{
CriticalSection crit_sec;
node_hdl.spinSome([] (CanardFrame const & frame) { return mcp2515.transmit(frame); });
node_hdl.spinSome();
}

/* Handle actions common to all states.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include <107-Arduino-Cyphal.h>
#include <107-Arduino-MCP2515.h>
#include <107-Arduino-CriticalSection.h>

/**************************************************************************************
* NAMESPACE
Expand All @@ -40,7 +41,7 @@ ArduinoMCP2515 mcp2515([]() { digitalWrite(MKRCAN_MCP2515_CS_PIN, LOW); },
nullptr);

Node::Heap<Node::DEFAULT_O1HEAP_SIZE> node_heap;
Node node_hdl(node_heap.data(), node_heap.size(), micros);
Node node_hdl(node_heap.data(), node_heap.size(), micros, [] (CanardFrame const & frame) { return mcp2515.transmit(frame); });

Publisher<Heartbeat_1_0<>> heartbeat_pub = node_hdl.create_publisher<Heartbeat_1_0<>>(Heartbeat_1_0<>::PORT_ID, 1*1000*1000UL /* = 1 sec in usecs. */);

Expand Down Expand Up @@ -80,7 +81,10 @@ void loop()
{
/* Process all pending OpenCyphal actions.
*/
node_hdl.spinSome([] (CanardFrame const & frame) { return mcp2515.transmit(frame); });
{
CriticalSection crit_sec;
node_hdl.spinSome();
}

/* Update the heartbeat object */
hb_msg.data.uptime = millis() / 1000;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ ArduinoMCP2515 mcp2515([]() { digitalWrite(MKRCAN_MCP2515_CS_PIN, LOW); },
nullptr);

Node::Heap<Node::DEFAULT_O1HEAP_SIZE> node_heap;
Node node_hdl(node_heap.data(), node_heap.size(), micros);
Node node_hdl(node_heap.data(), node_heap.size(), micros, [] (CanardFrame const & frame) { return mcp2515.transmit(frame); });

Subscription heartbeat_subscription =
node_hdl.create_subscription<Heartbeat_1_0<>>(Heartbeat_1_0<>::PORT_ID, CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC, onHeartbeat_1_0_Received);
Expand Down Expand Up @@ -83,7 +83,7 @@ void loop()
*/
{
CriticalSection crit_sec;
node_hdl.spinSome([] (CanardFrame const & frame) { return mcp2515.transmit(frame); });
node_hdl.spinSome();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ ArduinoMCP2515 mcp2515([]() { digitalWrite(MKRCAN_MCP2515_CS_PIN, LOW); },
nullptr);

Node::Heap<Node::DEFAULT_O1HEAP_SIZE> node_heap;
Node node_hdl(node_heap.data(), node_heap.size(), micros);
Node node_hdl(node_heap.data(), node_heap.size(), micros, [] (CanardFrame const & frame) { return mcp2515.transmit(frame); });

ServiceClient<ExecuteCommand_1_1::Request<>> srv_client = node_hdl.create_service_client<ExecuteCommand_1_1::Request<>, ExecuteCommand_1_1::Response<>>(
ExecuteCommand_1_1::Request<>::PORT_ID,
Expand Down Expand Up @@ -98,7 +98,7 @@ void loop()
*/
{
CriticalSection crit_sec;
node_hdl.spinSome([] (CanardFrame const & frame) { return mcp2515.transmit(frame); });
node_hdl.spinSome();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ ArduinoMCP2515 mcp2515([]() { digitalWrite(MKRCAN_MCP2515_CS_PIN, LOW); },
nullptr);

Node::Heap<Node::DEFAULT_O1HEAP_SIZE> node_heap;
Node node_hdl(node_heap.data(), node_heap.size(), micros);
Node node_hdl(node_heap.data(), node_heap.size(), micros, [] (CanardFrame const & frame) { return mcp2515.transmit(frame); });

ServiceServer execute_command_srv = node_hdl.create_service_server<ExecuteCommand_1_1::Request<>, ExecuteCommand_1_1::Response<>>(
ExecuteCommand_1_1::Request<>::PORT_ID,
Expand Down Expand Up @@ -86,7 +86,7 @@ void loop()
*/
{
CriticalSection crit_sec;
node_hdl.spinSome([] (CanardFrame const & frame) { return mcp2515.transmit(frame); });
node_hdl.spinSome();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ ArduinoMCP2515 mcp2515([]()
nullptr);

Node::Heap<Node::DEFAULT_O1HEAP_SIZE> node_heap;
Node node_hdl(node_heap.data(), node_heap.size(), micros, OPEN_CYPHAL_NODE_ID);
Node node_hdl(node_heap.data(), node_heap.size(), micros, [] (CanardFrame const & frame) { return mcp2515.transmit(frame); }, OPEN_CYPHAL_NODE_ID);

Publisher<Heartbeat_1_0<>> heartbeat_pub = node_hdl.create_publisher<Heartbeat_1_0<>>(Heartbeat_1_0<>::PORT_ID, 1*1000*1000UL /* = 1 sec in usecs. */);
Publisher<DistanceMessageType> tof_pub = node_hdl.create_publisher<DistanceMessageType>(OPEN_CYPHAL_ID_DISTANCE_DATA, 1*1000*1000UL /* = 1 sec in usecs. */);
Expand Down Expand Up @@ -161,10 +161,10 @@ DEBUG_INSTANCE(120, Serial);

/* REGISTER ***************************************************************************/

static RegisterNatural8 reg_rw_uavcan_node_id ("uavcan.node.id", Register::Access::ReadWrite, Register::Persistent::No, OPEN_CYPHAL_NODE_ID, [&node_hdl](uint8_t const & val) { node_hdl.setNodeId(val); });
static RegisterString reg_ro_uavcan_node_description ("uavcan.node.description", Register::Access::ReadWrite, Register::Persistent::No, "OpenCyphal-ToF-Distance-Sensor-Node");
static RegisterNatural16 reg_ro_uavcan_pub_distance_id ("uavcan.pub.distance.id", Register::Access::ReadOnly, Register::Persistent::No, OPEN_CYPHAL_ID_DISTANCE_DATA);
static RegisterString reg_ro_uavcan_pub_distance_type("uavcan.pub.distance.type", Register::Access::ReadOnly, Register::Persistent::No, "uavcan.primitive.scalar.Real32.1.0");
static RegisterNatural8 reg_rw_cyphal_node_id ("cyphal.node.id", Register::Access::ReadWrite, Register::Persistent::No, OPEN_CYPHAL_NODE_ID, [&node_hdl](uint8_t const & val) { node_hdl.setNodeId(val); });
static RegisterString reg_ro_cyphal_node_description ("cyphal.node.description", Register::Access::ReadWrite, Register::Persistent::No, "OpenCyphal-ToF-Distance-Sensor-Node");
static RegisterNatural16 reg_ro_cyphal_pub_distance_id ("cyphal.pub.distance.id", Register::Access::ReadOnly, Register::Persistent::No, OPEN_CYPHAL_ID_DISTANCE_DATA);
static RegisterString reg_ro_cyphal_pub_distance_type("cyphal.pub.distance.type", Register::Access::ReadOnly, Register::Persistent::No, "cyphal.primitive.scalar.Real32.1.0");
static RegisterList reg_list(node_hdl);

/* NODE INFO **************************************************************************/
Expand Down Expand Up @@ -234,10 +234,10 @@ void setup()

/* Register callbacks for node info and register api.
*/
reg_list.add(reg_rw_uavcan_node_id);
reg_list.add(reg_ro_uavcan_node_description);
reg_list.add(reg_ro_uavcan_pub_distance_id);
reg_list.add(reg_ro_uavcan_pub_distance_type);
reg_list.add(reg_rw_cyphal_node_id);
reg_list.add(reg_ro_cyphal_node_description);
reg_list.add(reg_ro_cyphal_pub_distance_id);
reg_list.add(reg_ro_cyphal_pub_distance_type);
}

void loop()
Expand All @@ -246,7 +246,7 @@ void loop()
*/
{
CriticalSection crit_sec;
node_hdl.spinSome([] (CanardFrame const & frame) { return mcp2515.transmit(frame); });
node_hdl.spinSome();
}

/* Handle actions common to all states.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
##########################################################################
cmake_minimum_required(VERSION 3.15)
##########################################################################
set(EXAMPLE_01_TARGET example-01-basic-cyphal-node)
##########################################################################
add_executable(${EXAMPLE_01_TARGET} example-01-opencyphal-basic-node.cpp)
target_link_libraries(${EXAMPLE_01_TARGET} cyphal++ pthread)
##########################################################################
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<a href="https://opencyphal.org/"><img align="right" src="https://raw.githubusercontent.com/107-systems/.github/main/logo/opencyphal.svg" width="25%"></a>
:floppy_disk: `example-01-opencyphal-basic-node`
================================================
* Setup a virtual CAN interface (`vcan0`)
```bash
sudo . setup_vcan.sh
aentinger marked this conversation as resolved.
Show resolved Hide resolved
```
You can observe the frames on the virtual CAN bus using `candump`
```bash
candump vcan0
```
* Install `yakut`
```bash
python3 -m pip install yakut
```
* Compile OpenCyphal DSDL
```bash
yakut compile https://github.com/OpenCyphal/public_regulated_data_types/archive/refs/heads/master.zip
```
* Setup `yakut`
```bash
. setup_yakut.sh
```
* Start `yakut`
```bash
yakut monitor
```
* Use `yakut`

Read the register list of the node.
```bash
yakut rl 42
[cyphal.node.description, cyphal.node.id, cyphal.pub.temperature.id, cyphal.pub.temperature.type]
```
Loading