You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2022/08/02 09:01:34 UTC
[incubator-nuttx-apps] 01/02: Add libcanardv1 for Cyphal, rename libcanard to libcanardv0
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx-apps.git
commit 819c34e975839658727ce2df43dd9a62f88c1c46
Author: Peter van der Perk <pe...@nxp.com>
AuthorDate: Mon Aug 1 15:44:33 2022 +0200
Add libcanardv1 for Cyphal, rename libcanard to libcanardv0
---
canutils/{libcanard => libcanardv0}/.gitignore | 0
canutils/{libcanard => libcanardv0}/Kconfig | 12 +-
canutils/{libcanard => libcanardv0}/Make.defs | 6 +-
canutils/{libcanard => libcanardv0}/Makefile | 34 +-
canutils/{libcanard => libcanardv1}/.gitignore | 1 +
canutils/libcanardv1/Kconfig | 39 +++
canutils/{libcanard => libcanardv1}/Make.defs | 6 +-
canutils/libcanardv1/Makefile | 100 ++++++
examples/{canard => canardv0}/Kconfig | 22 +-
examples/{canard => canardv0}/Make.defs | 6 +-
examples/{canard => canardv0}/Makefile | 8 +-
examples/{canard => canardv0}/canard_main.c | 18 +-
examples/{canard => canardv1}/Kconfig | 30 +-
examples/{canard => canardv1}/Make.defs | 6 +-
examples/{canard => canardv1}/Makefile | 11 +-
examples/canardv1/canard_main.c | 412 +++++++++++++++++++++++++
examples/canardv1/socketcan.c | 227 ++++++++++++++
examples/canardv1/socketcan.h | 114 +++++++
include/canutils/.gitignore | 2 +
19 files changed, 975 insertions(+), 79 deletions(-)
diff --git a/canutils/libcanard/.gitignore b/canutils/libcanardv0/.gitignore
similarity index 100%
copy from canutils/libcanard/.gitignore
copy to canutils/libcanardv0/.gitignore
diff --git a/canutils/libcanard/Kconfig b/canutils/libcanardv0/Kconfig
similarity index 69%
rename from canutils/libcanard/Kconfig
rename to canutils/libcanardv0/Kconfig
index dfb760752..db32d813b 100644
--- a/canutils/libcanard/Kconfig
+++ b/canutils/libcanardv0/Kconfig
@@ -3,22 +3,22 @@
# see the file kconfig-language.txt in the NuttX tools repository.
#
-config CANUTILS_LIBCANARD
- bool "libcanard UAVCAN Library"
+config CANUTILS_LIBCANARDV0
+ bool "libcanard UAVCAN v0 Library"
default n
depends on CAN && CAN_EXTID
---help---
- Enable the libcanard UAVCAN library.
+ Enable the libcanard UAVCAN v0 library.
-if CANUTILS_LIBCANARD
+if CANUTILS_LIBCANARDV0
-config LIBCANARD_URL
+config LIBCANARDV0_URL
string "libcanard URL"
default "https://github.com/UAVCAN/libcanard/archive"
---help---
libcanard URL.
-config LIBCANARD_VERSION
+config LIBCANARDV0_VERSION
string "libcanard Version"
default "5ad65c6a4efda60cda7a8f0512da0f465822bbb8"
---help---
diff --git a/canutils/libcanard/Make.defs b/canutils/libcanardv0/Make.defs
similarity index 88%
copy from canutils/libcanard/Make.defs
copy to canutils/libcanardv0/Make.defs
index 433b07b58..4dc7280ce 100644
--- a/canutils/libcanard/Make.defs
+++ b/canutils/libcanardv0/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# apps/canutils/libcanard/Make.defs
+# apps/canutils/libcanardv0/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -18,6 +18,6 @@
#
############################################################################
-ifeq ($(CONFIG_CANUTILS_LIBCANARD),y)
-CONFIGURED_APPS += $(APPDIR)/canutils/libcanard
+ifeq ($(CONFIG_CANUTILS_LIBCANARDV0),y)
+CONFIGURED_APPS += $(APPDIR)/canutils/libcanardv0
endif
diff --git a/canutils/libcanard/Makefile b/canutils/libcanardv0/Makefile
similarity index 60%
rename from canutils/libcanard/Makefile
rename to canutils/libcanardv0/Makefile
index a89ed738a..a337fd3a7 100644
--- a/canutils/libcanard/Makefile
+++ b/canutils/libcanardv0/Makefile
@@ -1,5 +1,5 @@
############################################################################
-# apps/canutils/libcanard/Makefile
+# apps/canutils/libcanardv0/Makefile
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -23,38 +23,38 @@ include $(APPDIR)/Make.defs
UNPACK = unzip
PACKEXT = .zip
-LIBCANARD_URL = $(patsubst "%",%,$(strip $(CONFIG_LIBCANARD_URL)))
-LIBCANARD_VERSION = $(patsubst "%",%,$(strip $(CONFIG_LIBCANARD_VERSION)))
-LIBCANARD_UNPACKNAME = libcanard-$(LIBCANARD_VERSION)
-LIBCANARD_PACKNAME = $(LIBCANARD_UNPACKNAME)$(PACKEXT)
-LIBCANARD_SRCDIR = $(LIBCANARD_UNPACKNAME)
-LIBCANARD_DRVDIR = $(LIBCANARD_SRCDIR)$(DELIM)drivers$(DELIM)nuttx
+LIBCANARDV0_URL = $(patsubst "%",%,$(strip $(CONFIG_LIBCANARDV0_URL)))
+LIBCANARDV0_VERSION = $(patsubst "%",%,$(strip $(CONFIG_LIBCANARDV0_VERSION)))
+LIBCANARDV0_UNPACKNAME = libcanard-$(LIBCANARDV0_VERSION)
+LIBCANARDV0_PACKNAME = $(LIBCANARDV0_UNPACKNAME)$(PACKEXT)
+LIBCANARDV0_SRCDIR = $(LIBCANARDV0_UNPACKNAME)
+LIBCANARDV0_DRVDIR = $(LIBCANARDV0_SRCDIR)$(DELIM)drivers$(DELIM)nuttx
APPS_INCDIR = $(APPDIR)$(DELIM)include$(DELIM)canutils
CFLAGS += -std=c99 -DCANARD_ASSERT=DEBUGASSERT
CFLAGS += ${shell $(INCDIR) "$(CC)" $(APPS_INCDIR)}
-CSRCS = $(LIBCANARD_SRCDIR)$(DELIM)canard.c $(LIBCANARD_DRVDIR)$(DELIM)canard_nuttx.c
+CSRCS = $(LIBCANARDV0_SRCDIR)$(DELIM)canard.c $(LIBCANARDV0_DRVDIR)$(DELIM)canard_nuttx.c
-$(LIBCANARD_PACKNAME):
+$(LIBCANARDV0_PACKNAME):
@echo "Downloading: $@"
- $(Q) curl -o $@ -L $(LIBCANARD_URL)$(DELIM)$(LIBCANARD_VERSION)$(PACKEXT)
+ $(Q) curl -o $@ -L $(LIBCANARDV0_URL)$(DELIM)$(LIBCANARDV0_VERSION)$(PACKEXT)
-$(LIBCANARD_UNPACKNAME): $(LIBCANARD_PACKNAME)
+$(LIBCANARDV0_UNPACKNAME): $(LIBCANARDV0_PACKNAME)
@echo "Unpacking: $< -> $@"
$(call DELDIR, $@)
$(Q) $(UNPACK) $<
$(Q) touch $@
-$(LIBCANARD_SRCDIR)$(DELIM)canard.h: $(LIBCANARD_UNPACKNAME)
+$(LIBCANARDV0_SRCDIR)$(DELIM)canard.h: $(LIBCANARDV0_UNPACKNAME)
-$(LIBCANARD_DRVDIR)$(DELIM)canard_nuttx.h: $(LIBCANARD_UNPACKNAME)
+$(LIBCANARDV0_DRVDIR)$(DELIM)canard_nuttx.h: $(LIBCANARDV0_UNPACKNAME)
-$(APPS_INCDIR)$(DELIM)canard.h: $(LIBCANARD_SRCDIR)$(DELIM)canard.h
+$(APPS_INCDIR)$(DELIM)canard.h: $(LIBCANARDV0_SRCDIR)$(DELIM)canard.h
$(Q) cp $< $@
-$(APPS_INCDIR)$(DELIM)canard_nuttx.h: $(LIBCANARD_DRVDIR)$(DELIM)canard_nuttx.h
+$(APPS_INCDIR)$(DELIM)canard_nuttx.h: $(LIBCANARDV0_DRVDIR)$(DELIM)canard_nuttx.h
$(Q) cp $< $@
context:: $(APPS_INCDIR)$(DELIM)canard.h $(APPS_INCDIR)$(DELIM)canard_nuttx.h
@@ -65,7 +65,7 @@ clean::
distclean::
$(call DELFILE, $(APPS_INCDIR)$(DELIM)canard.h)
$(call DELFILE, $(APPS_INCDIR)$(DELIM)canard_nuttx.h)
- $(call DELDIR, $(LIBCANARD_UNPACKNAME))
- $(call DELFILE, $(LIBCANARD_PACKNAME))
+ $(call DELDIR, $(LIBCANARDV0_UNPACKNAME))
+ $(call DELFILE, $(LIBCANARDV0_PACKNAME))
include $(APPDIR)/Application.mk
diff --git a/canutils/libcanard/.gitignore b/canutils/libcanardv1/.gitignore
similarity index 56%
rename from canutils/libcanard/.gitignore
rename to canutils/libcanardv1/.gitignore
index ab82ca37f..19287278b 100644
--- a/canutils/libcanard/.gitignore
+++ b/canutils/libcanardv1/.gitignore
@@ -1 +1,2 @@
/libcanard-*
+/o1heap-*
diff --git a/canutils/libcanardv1/Kconfig b/canutils/libcanardv1/Kconfig
new file mode 100644
index 000000000..70d58c648
--- /dev/null
+++ b/canutils/libcanardv1/Kconfig
@@ -0,0 +1,39 @@
+#
+# For a description of the syntax of this configuration file,
+# see the file kconfig-language.txt in the NuttX tools repository.
+#
+
+config CANUTILS_LIBCANARDV1
+ bool "libcanard UAVCAN v1 Library"
+ default n
+ depends on NET_CAN && ALLOW_MIT_COMPONENTS
+ ---help---
+ Enable the libcanard UAVCAN v1 library.
+
+if CANUTILS_LIBCANARDV1
+
+config LIBCANARDV1_URL
+ string "libcanard URL"
+ default "https://github.com/UAVCAN/libcanard/archive"
+ ---help---
+ libcanard URL.
+
+config LIBCANARDV1_VERSION
+ string "libcanard Version"
+ default "cde670347425023480a1417fcd603b27c8eb06c1"
+ ---help---
+ libcanard version.
+
+config O1HEAP_URL
+ string "O(1) heap URL"
+ default "https://github.com/pavel-kirienko/o1heap/archive"
+ ---help---
+ libcanard URL.
+
+config O1HEAP_VERSION
+ string "O(1) heap Version"
+ default "b21b069e4b971d3016dd232784faca6f7d9fd724"
+ ---help---
+ libcanard version.
+
+endif
diff --git a/canutils/libcanard/Make.defs b/canutils/libcanardv1/Make.defs
similarity index 88%
rename from canutils/libcanard/Make.defs
rename to canutils/libcanardv1/Make.defs
index 433b07b58..382381897 100644
--- a/canutils/libcanard/Make.defs
+++ b/canutils/libcanardv1/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# apps/canutils/libcanard/Make.defs
+# apps/canutils/libcanardv1/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -18,6 +18,6 @@
#
############################################################################
-ifeq ($(CONFIG_CANUTILS_LIBCANARD),y)
-CONFIGURED_APPS += $(APPDIR)/canutils/libcanard
+ifeq ($(CONFIG_CANUTILS_LIBCANARDV1),y)
+CONFIGURED_APPS += $(APPDIR)/canutils/libcanardv1
endif
diff --git a/canutils/libcanardv1/Makefile b/canutils/libcanardv1/Makefile
new file mode 100644
index 000000000..947d8426a
--- /dev/null
+++ b/canutils/libcanardv1/Makefile
@@ -0,0 +1,100 @@
+############################################################################
+# apps/canutils/libcanardv1/Makefile
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership. The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+include $(APPDIR)/Make.defs
+
+UNPACK = unzip
+PACKEXT = .zip
+
+LIBCANARDV1_URL = $(patsubst "%",%,$(strip $(CONFIG_LIBCANARDV1_URL)))
+LIBCANARDV1_VERSION = $(patsubst "%",%,$(strip $(CONFIG_LIBCANARDV1_VERSION)))
+LIBCANARDV1_UNPACKNAME = libcanard-$(LIBCANARDV1_VERSION)
+LIBCANARDV1_PACKNAME = $(LIBCANARDV1_UNPACKNAME)$(PACKEXT)
+LIBCANARDV1_SRCDIR = $(LIBCANARDV1_UNPACKNAME)
+LIBCANARDV1_DRVDIR = $(LIBCANARDV1_SRCDIR)$(DELIM)libcanard
+
+O1HEAP_URL = $(patsubst "%",%,$(strip $(CONFIG_O1HEAP_URL)))
+O1HEAP_VERSION = $(patsubst "%",%,$(strip $(CONFIG_O1HEAP_VERSION)))
+O1HEAP_UNPACKNAME = o1heap-$(O1HEAP_VERSION)
+O1HEAP_PACKNAME = $(O1HEAP_UNPACKNAME)$(PACKEXT)
+O1HEAP_SRCDIR = $(O1HEAP_UNPACKNAME)
+O1HEAP_DRVDIR = $(O1HEAP_SRCDIR)$(DELIM)o1heap
+
+APPS_INCDIR = $(APPDIR)$(DELIM)include$(DELIM)canutils
+
+CFLAGS += -std=c11 -DCANARD_ASSERT=DEBUGASSERT -DCANARD_DSDL_CONFIG_LITTLE_ENDIAN=1
+CFLAGS += ${shell $(INCDIR) "$(CC)" $(APPS_INCDIR)}
+
+CSRCS = $(LIBCANARDV1_DRVDIR)$(DELIM)canard.c $(LIBCANARDV1_DRVDIR)$(DELIM)canard_dsdl.c
+CSRCS += $(O1HEAP_DRVDIR)$(DELIM)o1heap.c
+
+
+$(LIBCANARDV1_PACKNAME):
+ @echo "Downloading: $@"
+ $(Q) curl -o $@ -L $(LIBCANARDV1_URL)$(DELIM)$(LIBCANARDV1_VERSION)$(PACKEXT)
+
+$(LIBCANARDV1_UNPACKNAME): $(LIBCANARDV1_PACKNAME)
+ @echo "Unpacking: $< -> $@"
+ $(call DELDIR, $@)
+ $(Q) $(UNPACK) $<
+ $(Q) touch $@
+
+$(O1HEAP_PACKNAME):
+ @echo "Downloading: $@"
+ $(Q) curl -o $@ -L $(O1HEAP_URL)$(DELIM)$(O1HEAP_VERSION)$(PACKEXT)
+
+$(O1HEAP_UNPACKNAME): $(O1HEAP_PACKNAME)
+ @echo "Unpacking: $< -> $@"
+ $(call DELDIR, $@)
+ $(Q) $(UNPACK) $<
+ $(Q) touch $@
+
+$(LIBCANARDV1_DRVDIR)$(DELIM)canard.h: $(LIBCANARDV1_UNPACKNAME)
+
+$(LIBCANARDV1_DRVDIR)$(DELIM)canard_dsdl.h: $(LIBCANARDV1_UNPACKNAME)
+
+$(O1HEAP_DRVDIR)$(DELIM)o1heap.h: $(O1HEAP_UNPACKNAME)
+
+$(APPS_INCDIR)$(DELIM)canard.h: $(LIBCANARDV1_DRVDIR)$(DELIM)canard.h
+ $(Q) cp $< $@
+
+$(APPS_INCDIR)$(DELIM)canard_dsdl.h: $(LIBCANARDV1_DRVDIR)$(DELIM)canard_dsdl.h
+ $(Q) cp $< $@
+
+$(APPS_INCDIR)$(DELIM)o1heap.h: $(O1HEAP_DRVDIR)$(DELIM)o1heap.h
+ $(Q) cp $< $@
+
+context:: $(APPS_INCDIR)$(DELIM)canard.h $(APPS_INCDIR)$(DELIM)canard_dsdl.h $(APPS_INCDIR)$(DELIM)o1heap.h
+
+clean::
+ $(foreach OBJ, $(OBJS), $(call DELFILE, $(OBJ)))
+
+distclean::
+ $(call DELFILE, $(APPS_INCDIR)$(DELIM)canard.h)
+ $(call DELFILE, $(APPS_INCDIR)$(DELIM)canard_dsdl.h)
+ $(call DELDIR, $(LIBCANARDV1_UNPACKNAME))
+ $(call DELFILE, $(LIBCANARDV1_PACKNAME))
+ $(call DELDIR, $(O1HEAP_UNPACKNAME))
+ $(call DELFILE, $(O1HEAP_PACKNAME))
+ $(call DELFILE, $(APPS_INCDIR)$(DELIM)o1heap.h)
+ $(call DELDIR, $(O1HEAP_UNPACKNAME))
+ $(call DELFILE, $(O1HEAP_PACKNAME))
+
+include $(APPDIR)/Application.mk
diff --git a/examples/canard/Kconfig b/examples/canardv0/Kconfig
similarity index 59%
copy from examples/canard/Kconfig
copy to examples/canardv0/Kconfig
index 888a756de..3aea891e1 100644
--- a/examples/canard/Kconfig
+++ b/examples/canardv0/Kconfig
@@ -3,45 +3,45 @@
# see the file kconfig-language.txt in the NuttX tools repository.
#
-config EXAMPLES_LIBCANARD
- tristate "libcandard example"
+config EXAMPLES_LIBCANARDV0
+ tristate "libcandard v0 example"
default n
- depends on CANUTILS_LIBCANARD && SYSTEM_TIME64
+ depends on CANUTILS_LIBCANARDV0 && SYSTEM_TIME64
---help---
- Enable the LIBCANARD example
+ Enable the LIBCANARDV0 example
-if EXAMPLES_LIBCANARD
+if EXAMPLES_LIBCANARDV0
-config EXAMPLES_LIBCANARD_DEVPATH
+config EXAMPLES_LIBCANARDV0_DEVPATH
string "Device Path"
default "/dev/can0"
---help---
The device path
-config EXAMPLES_LIBCANARD_NODE_ID
+config EXAMPLES_LIBCANARDV0_NODE_ID
int "Node ID"
default 1
range 1 127
---help---
Specifies the node's ID
-config EXAMPLES_LIBCANARD_APP_NODE_NAME
+config EXAMPLES_LIBCANARDV0_APP_NODE_NAME
string "Node name"
default "org.uavcan.libcanard.nuttx.demo"
---help---
app node name
-config EXAMPLES_LIBCANARD_NODE_MEM_POOL_SIZE
+config EXAMPLES_LIBCANARDV0_NODE_MEM_POOL_SIZE
int "Node Memory Pool Size"
default 1024
---help---
Specifies the node's memory pool size
-config EXAMPLES_LIBCANARD_DAEMON_PRIORITY
+config EXAMPLES_LIBCANARDV0_DAEMON_PRIORITY
int "daemon task priority"
default 100
-config EXAMPLES_LIBCANARD_STACKSIZE
+config EXAMPLES_LIBCANARDV0_STACKSIZE
int "canard stack size"
default DEFAULT_TASK_STACKSIZE
diff --git a/examples/canard/Make.defs b/examples/canardv0/Make.defs
similarity index 88%
copy from examples/canard/Make.defs
copy to examples/canardv0/Make.defs
index b8b7b51ae..84f5e3aad 100644
--- a/examples/canard/Make.defs
+++ b/examples/canardv0/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# apps/examples/canard/Make.defs
+# apps/examples/canardv0/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -18,6 +18,6 @@
#
############################################################################
-ifneq ($(CONFIG_EXAMPLES_LIBCANARD),)
-CONFIGURED_APPS += $(APPDIR)/examples/canard
+ifneq ($(CONFIG_EXAMPLES_LIBCANARDV0),)
+CONFIGURED_APPS += $(APPDIR)/examples/canardv0
endif
diff --git a/examples/canard/Makefile b/examples/canardv0/Makefile
similarity index 88%
copy from examples/canard/Makefile
copy to examples/canardv0/Makefile
index cfc9c8044..00f5f21ae 100644
--- a/examples/canard/Makefile
+++ b/examples/canardv0/Makefile
@@ -1,5 +1,5 @@
############################################################################
-# apps/examples/canard/Makefile
+# apps/examples/canardv0/Makefile
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -20,10 +20,10 @@
include $(APPDIR)/Make.defs
-PROGNAME = canard
+PROGNAME = canardv0
PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = $(CONFIG_EXAMPLES_LIBCANARD_STACKSIZE)
-MODULE = $(CONFIG_EXAMPLES_LIBCANARD)
+STACKSIZE = $(CONFIG_EXAMPLES_LIBCANARDV0_STACKSIZE)
+MODULE = $(CONFIG_EXAMPLES_LIBCANARDV0)
CFLAGS += ${shell $(INCDIR) "$(CC)" $(APPDIR)/include/canutils}
MAINSRC = canard_main.c
diff --git a/examples/canard/canard_main.c b/examples/canardv0/canard_main.c
similarity index 97%
rename from examples/canard/canard_main.c
rename to examples/canardv0/canard_main.c
index 87ba6020a..b99fb09f8 100644
--- a/examples/canard/canard_main.c
+++ b/examples/canardv0/canard_main.c
@@ -1,5 +1,5 @@
/****************************************************************************
- * apps/examples/canard/canard_main.c
+ * apps/examples/canardv0/canard_main.c
*
* Copyright (C) 2016 ETH Zuerich. All rights reserved.
* Author: Matthias Renner <re...@ethz.ch>
@@ -60,7 +60,7 @@
#define APP_VERSION_MAJOR 1
#define APP_VERSION_MINOR 0
-#define APP_NODE_NAME CONFIG_EXAMPLES_LIBCANARD_APP_NODE_NAME
+#define APP_NODE_NAME CONFIG_EXAMPLES_LIBCANARDV0_APP_NODE_NAME
#define GIT_HASH 0xb28bf6ac
/* Some useful constants defined by the UAVCAN specification.
@@ -99,7 +99,7 @@ static CanardInstance canard;
/* Arena for memory allocation, used by the library */
-static uint8_t canard_memory_pool[CONFIG_EXAMPLES_LIBCANARD_NODE_MEM_POOL_SIZE];
+static uint8_t canard_memory_pool[CONFIG_EXAMPLES_LIBCANARDV0_NODE_MEM_POOL_SIZE];
static uint8_t unique_id[UNIQUE_ID_LENGTH_BYTES] =
{ 0x00, 0x00, 0x00, 0x00,
@@ -436,11 +436,11 @@ static int canard_daemon(int argc, char *argv[])
/* Open the CAN device for reading */
ret = canardNuttXInit(&canardnuttx_instance,
- CONFIG_EXAMPLES_LIBCANARD_DEVPATH);
+ CONFIG_EXAMPLES_LIBCANARDV0_DEVPATH);
if (ret < 0)
{
printf("canard_daemon: ERROR: open %s failed: %d\n",
- CONFIG_EXAMPLES_LIBCANARD_DEVPATH, errno);
+ CONFIG_EXAMPLES_LIBCANARDV0_DEVPATH, errno);
errval = 2;
goto errout_with_dev;
}
@@ -469,9 +469,9 @@ static int canard_daemon(int argc, char *argv[])
canardInit(&canard, canard_memory_pool, sizeof(canard_memory_pool),
onTransferReceived, shouldAcceptTransfer, (void *)(12345));
- canardSetLocalNodeID(&canard, CONFIG_EXAMPLES_LIBCANARD_NODE_ID);
+ canardSetLocalNodeID(&canard, CONFIG_EXAMPLES_LIBCANARDV0_NODE_ID);
printf("canard_daemon: canard initialized\n");
- printf("start node (ID: %d Name: %s)\n", CONFIG_EXAMPLES_LIBCANARD_NODE_ID,
+ printf("start node (ID: %d Name: %s)\n", CONFIG_EXAMPLES_LIBCANARDV0_NODE_ID,
APP_NODE_NAME);
g_canard_daemon_started = true;
@@ -517,8 +517,8 @@ int main(int argc, FAR char *argv[])
return EXIT_SUCCESS;
}
- ret = task_create("canard_daemon", CONFIG_EXAMPLES_LIBCANARD_DAEMON_PRIORITY,
- CONFIG_EXAMPLES_LIBCANARD_STACKSIZE, canard_daemon,
+ ret = task_create("canard_daemon", CONFIG_EXAMPLES_LIBCANARDV0_DAEMON_PRIORITY,
+ CONFIG_EXAMPLES_LIBCANARDV0_STACKSIZE, canard_daemon,
NULL);
if (ret < 0)
{
diff --git a/examples/canard/Kconfig b/examples/canardv1/Kconfig
similarity index 50%
rename from examples/canard/Kconfig
rename to examples/canardv1/Kconfig
index 888a756de..9ce2e6698 100644
--- a/examples/canard/Kconfig
+++ b/examples/canardv1/Kconfig
@@ -3,45 +3,45 @@
# see the file kconfig-language.txt in the NuttX tools repository.
#
-config EXAMPLES_LIBCANARD
- tristate "libcandard example"
+config EXAMPLES_LIBCANARDV1
+ tristate "libcandard v1 example"
default n
- depends on CANUTILS_LIBCANARD && SYSTEM_TIME64
+ depends on CANUTILS_LIBCANARDV1
---help---
- Enable the LIBCANARD example
+ Enable the LIBCANARDV1 example
-if EXAMPLES_LIBCANARD
+if EXAMPLES_LIBCANARDV1
-config EXAMPLES_LIBCANARD_DEVPATH
- string "Device Path"
- default "/dev/can0"
+config EXAMPLES_LIBCANARDV1_DEV
+ string "Device"
+ default "can0"
---help---
- The device path
+ The device
-config EXAMPLES_LIBCANARD_NODE_ID
+config EXAMPLES_LIBCANARDV1_NODE_ID
int "Node ID"
default 1
range 1 127
---help---
Specifies the node's ID
-config EXAMPLES_LIBCANARD_APP_NODE_NAME
+config EXAMPLES_LIBCANARDV1_APP_NODE_NAME
string "Node name"
- default "org.uavcan.libcanard.nuttx.demo"
+ default "org.uavcan.libcanardv1.nuttx.demo"
---help---
app node name
-config EXAMPLES_LIBCANARD_NODE_MEM_POOL_SIZE
+config EXAMPLES_LIBCANARDV1_NODE_MEM_POOL_SIZE
int "Node Memory Pool Size"
default 1024
---help---
Specifies the node's memory pool size
-config EXAMPLES_LIBCANARD_DAEMON_PRIORITY
+config EXAMPLES_LIBCANARDV1_DAEMON_PRIORITY
int "daemon task priority"
default 100
-config EXAMPLES_LIBCANARD_STACKSIZE
+config EXAMPLES_LIBCANARDV1_DAEMON_STACK_SIZE
int "canard stack size"
default DEFAULT_TASK_STACKSIZE
diff --git a/examples/canard/Make.defs b/examples/canardv1/Make.defs
similarity index 88%
rename from examples/canard/Make.defs
rename to examples/canardv1/Make.defs
index b8b7b51ae..dc9399209 100644
--- a/examples/canard/Make.defs
+++ b/examples/canardv1/Make.defs
@@ -1,5 +1,5 @@
############################################################################
-# apps/examples/canard/Make.defs
+# apps/examples/canardv1/Make.defs
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -18,6 +18,6 @@
#
############################################################################
-ifneq ($(CONFIG_EXAMPLES_LIBCANARD),)
-CONFIGURED_APPS += $(APPDIR)/examples/canard
+ifneq ($(CONFIG_EXAMPLES_LIBCANARDV1),)
+CONFIGURED_APPS += $(APPDIR)/examples/canardv1
endif
diff --git a/examples/canard/Makefile b/examples/canardv1/Makefile
similarity index 79%
rename from examples/canard/Makefile
rename to examples/canardv1/Makefile
index cfc9c8044..646d91792 100644
--- a/examples/canard/Makefile
+++ b/examples/canardv1/Makefile
@@ -1,5 +1,5 @@
############################################################################
-# apps/examples/canard/Makefile
+# apps/examples/canardv1/Makefile
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
@@ -20,12 +20,13 @@
include $(APPDIR)/Make.defs
-PROGNAME = canard
+PROGNAME = canardv1
PRIORITY = SCHED_PRIORITY_DEFAULT
-STACKSIZE = $(CONFIG_EXAMPLES_LIBCANARD_STACKSIZE)
-MODULE = $(CONFIG_EXAMPLES_LIBCANARD)
+STACKSIZE = $(CONFIG_EXAMPLES_LIBCANARDV1_DAEMON_STACK_SIZE)
+MODULE = $(CONFIG_EXAMPLES_LIBCANARDV1)
-CFLAGS += ${shell $(INCDIR) "$(CC)" $(APPDIR)/include/canutils}
+CFLAGS += -std=c11 ${shell $(INCDIR) "$(CC)" $(APPDIR)/include/canutils $(APPDIR)/include/o1heap}
+CSRCS = socketcan.c
MAINSRC = canard_main.c
include $(APPDIR)/Application.mk
diff --git a/examples/canardv1/canard_main.c b/examples/canardv1/canard_main.c
new file mode 100644
index 000000000..ebf8f0119
--- /dev/null
+++ b/examples/canardv1/canard_main.c
@@ -0,0 +1,412 @@
+/****************************************************************************
+ * apps/examples/canardv1/canard_main.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <canard.h>
+#include <canard_dsdl.h>
+#include <o1heap.h>
+
+#include <sched.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <net/if.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <poll.h>
+
+#include <nuttx/can.h>
+#include <netpacket/can.h>
+
+#include "socketcan.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Application constants */
+
+#define APP_VERSION_MAJOR 1
+#define APP_VERSION_MINOR 0
+#define APP_NODE_NAME CONFIG_EXAMPLES_LIBCANARDV1_APP_NODE_NAME
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Arena for memory allocation, used by the library */
+
+#define O1_HEAP_SIZE CONFIG_EXAMPLES_LIBCANARDV1_NODE_MEM_POOL_SIZE
+
+/* Temporary development UAVCAN topic service ID to publish/subscribe from */
+#define PORT_ID 4421
+#define TOPIC_SIZE 512
+
+O1HeapInstance *my_allocator;
+static uint8_t uavcan_heap[O1_HEAP_SIZE]
+__attribute__((aligned(O1HEAP_ALIGNMENT)));
+
+/* Node status variables */
+
+static bool g_canard_daemon_started;
+
+static uint8_t my_message_transfer_id;
+
+struct pollfd fd;
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: memallocate
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+static void *memallocate(CanardInstance *const ins, const size_t amount)
+{
+ (void) ins;
+ return o1heapAllocate(my_allocator, amount);
+}
+
+/****************************************************************************
+ * Name: memfree
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+static void memfree(CanardInstance *const ins, void *const pointer)
+{
+ (void) ins;
+ o1heapFree(my_allocator, pointer);
+}
+
+/****************************************************************************
+ * Name: getmonotonictimestampusec
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+uint64_t getmonotonictimestampusec(void)
+{
+ struct timespec ts;
+
+ memset(&ts, 0, sizeof(ts));
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
+ {
+ abort();
+ }
+
+ return ts.tv_sec * 1000000ULL + ts.tv_nsec / 1000ULL;
+}
+
+/****************************************************************************
+ * Name: process1hztasks
+ *
+ * Description:
+ * This function is called at 1 Hz rate from the main loop.
+ *
+ ****************************************************************************/
+
+void process1hztasks(CanardInstance *ins, uint64_t timestamp_usec)
+{
+ CanardMicrosecond transmission_deadline =
+ getmonotonictimestampusec() + 1000 * 10;
+
+ const CanardTransfer transfer =
+ {
+ .timestamp_usec = transmission_deadline, /* Zero if transmission deadline is not limited. */
+ .priority = CanardPriorityNominal,
+ .transfer_kind = CanardTransferKindMessage,
+ .port_id = 1234, /* This is the subject-ID. */
+ .remote_node_id = CANARD_NODE_ID_UNSET, /* Messages cannot be unicast, so use UNSET. */
+ .transfer_id = my_message_transfer_id,
+ .payload_size = 47,
+ .payload = "\x2D\x00"
+ "Sancho, it strikes me thou art in great fear.",
+ };
+
+ ++my_message_transfer_id; /* The transfer-ID shall be incremented after every transmission on this subject. */
+ int32_t result = canardTxPush(ins, &transfer);
+
+ if (result < 0)
+ {
+ /* An error has occurred: either an argument is invalid or we've
+ * ran out of memory. It is possible to statically prove that an
+ * out-of-memory will never occur for a given application if the
+ * heap is sized correctly; for background, refer to the Robson's
+ * Proof and the documentation for O1Heap.
+ */
+
+ fprintf(stderr, "Transmit error %ld\n", result);
+ }
+}
+
+/****************************************************************************
+ * Name: processTxRxOnce
+ *
+ * Description:
+ * Transmits all frames from the TX queue, receives up to one frame.
+ *
+ ****************************************************************************/
+
+void processtxrxonce(CanardInstance *ins, canardsocketinstance *sock_ins,
+ int timeout_msec)
+{
+ int32_t result;
+
+ /* Transmitting, Look at the top of the TX queue. */
+
+ for (const CanardFrame *txf = NULL; (txf = canardTxPeek(ins)) != NULL; )
+ {
+ if (txf->timestamp_usec > getmonotonictimestampusec()) /* Check if the frame has timed out. */
+ {
+ if (socketcantransmit(sock_ins, txf) == 0) /* Send the frame. Redundant interfaces may be used here. */
+ {
+ /* If the driver is busy, break and retry later. */
+
+ break;
+ }
+ }
+
+ canardTxPop(ins); /* Remove the frame from the queue after it's transmitted. */
+ ins->memory_free(ins, (CanardFrame *)txf);
+ }
+
+ /* Poll receive */
+
+ if (poll(&fd, 1, timeout_msec) <= 0)
+ {
+ return;
+ }
+
+ /* Receiving */
+
+ CanardFrame received_frame;
+
+ socketcanreceive(sock_ins, &received_frame);
+
+ CanardTransfer receive;
+ result = canardRxAccept(ins,
+ &received_frame, /* The CAN frame received from the bus. */
+ 0, /* If the transport is not redundant, use 0. */
+ &receive);
+
+ if (result < 0)
+ {
+ /* An error has occurred: either an argument is invalid or we've ran
+ * out of memory. It is possible to statically prove that an
+ * out-of-memory will never occur for a given application
+ * if the heap is sized correctly; for background, refer to the
+ * Robson's Proof and the documentation for O1Heap.
+ * Reception of an invalid frame is NOT an error.
+ */
+
+ fprintf(stderr, "Receive error %ld\n", result);
+ }
+ else if (result == 1)
+ {
+ /* A transfer has been received, process it */
+
+ printf("Receive UAVCAN port id%d TODO process me\n",
+ receive.port_id);
+
+ ins->memory_free(ins, (void *)receive.payload);
+ }
+ else
+ {
+ /* Nothing to do.
+ * The received frame is either invalid or it's a non-last frame
+ * of a multi-frame transfer.
+ * Reception of an invalid frame is NOT reported as an error
+ * because it is not an error.
+ */
+ }
+}
+
+/****************************************************************************
+ * Name: canard_daemon
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+static int canard_daemon(int argc, char *argv[])
+{
+ int errval = 0;
+ int can_fd = 0;
+ int pub = 1;
+
+ if (argc > 2)
+ {
+ for (int args = 2; args < argc; args++)
+ {
+ if (!strcmp(argv[args], "canfd"))
+ {
+ can_fd = 1;
+ }
+
+ if (!strcmp(argv[args], "pub"))
+ {
+ pub = 1;
+ }
+
+ if (!strcmp(argv[args], "sub"))
+ {
+ pub = 0;
+ }
+ }
+ }
+
+ my_allocator = o1heapInit(&uavcan_heap, O1_HEAP_SIZE);
+
+ if (my_allocator == NULL)
+ {
+ printf("o1heapInit failed with size %d\n", O1_HEAP_SIZE);
+ errval = 2;
+ goto errout_with_dev;
+ }
+
+ CanardInstance ins = canardInit(&memallocate, &memfree);
+
+ if (can_fd)
+ {
+ ins.mtu_bytes = CANARD_MTU_CAN_FD;
+ }
+ else
+ {
+ ins.mtu_bytes = CANARD_MTU_CAN_CLASSIC;
+ }
+
+ ins.node_id = (pub ? CONFIG_EXAMPLES_LIBCANARDV1_NODE_ID :
+ CONFIG_EXAMPLES_LIBCANARDV1_NODE_ID + 1);
+
+ /* Open the CAN device for reading */
+
+ canardsocketinstance sock_ins;
+ socketcanopen(&sock_ins, CONFIG_EXAMPLES_LIBCANARDV1_DEV, can_fd);
+
+ /* setup poll fd */
+
+ fd.fd = sock_ins.s;
+ fd.events = POLLIN;
+
+ if (sock_ins.s < 0)
+ {
+ printf("canard_daemon: ERROR: open %s failed: %d\n",
+ CONFIG_EXAMPLES_LIBCANARDV1_DEV, errno);
+ errval = 2;
+ goto errout_with_dev;
+ }
+
+ printf("canard_daemon: canard initialized\n");
+ printf("start node (ID: %d Name: %s MTU: %d PUB: %d TOPIC_SIZE: %d)\n",
+ ins.node_id, APP_NODE_NAME, ins.mtu_bytes, pub, TOPIC_SIZE);
+
+ CanardRxSubscription heartbeat_subscription;
+ (void) canardRxSubscribe(&ins, /* Subscribe to messages uavcan.node.Heartbeat. */
+ CanardTransferKindMessage,
+ 32085, /* The fixed Subject-ID of the Heartbeat message type (see DSDL definition). */
+ 7, /* The maximum payload size (max DSDL object size) from the DSDL definition. */
+ CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC,
+ &heartbeat_subscription);
+
+ CanardRxSubscription my_subscription;
+ (void) canardRxSubscribe(&ins,
+ CanardTransferKindMessage,
+ PORT_ID, /* The Service-ID to subscribe to. */
+ TOPIC_SIZE, /* The maximum payload size (max DSDL object size). */
+ CANARD_DEFAULT_TRANSFER_ID_TIMEOUT_USEC,
+ &my_subscription);
+
+ g_canard_daemon_started = true;
+ uint64_t next_1hz_service_at = getmonotonictimestampusec();
+
+ for (; ; )
+ {
+ processtxrxonce(&ins, &sock_ins, 10);
+
+ const uint64_t ts = getmonotonictimestampusec();
+
+ if (ts >= next_1hz_service_at)
+ {
+ next_1hz_service_at += 1000000;
+ process1hztasks(&ins, ts);
+ }
+ }
+
+errout_with_dev:
+
+ g_canard_daemon_started = false;
+ printf("canard_daemon: Terminating!\n");
+ fflush(stdout);
+ return errval;
+}
+
+/****************************************************************************
+ * Name: canard_main
+ *
+ * Description:
+ *
+ ****************************************************************************/
+
+int canardv1_main(int argc, FAR char *argv[])
+{
+ int ret;
+
+ printf("canard_main: Starting canard_daemon\n");
+
+ if (g_canard_daemon_started)
+ {
+ printf("canard_main: receive and send task already running\n");
+ return EXIT_SUCCESS;
+ }
+
+ ret = task_create("canard_daemon",
+ CONFIG_EXAMPLES_LIBCANARDV1_DAEMON_PRIORITY,
+ CONFIG_EXAMPLES_LIBCANARDV1_DAEMON_STACK_SIZE,
+ canard_daemon, argv);
+
+ if (ret < 0)
+ {
+ int errcode = errno;
+ printf("canard_main: ERROR: Failed to start canard_daemon: %d\n",
+ errcode);
+ return EXIT_FAILURE;
+ }
+
+ printf("canard_main: canard_daemon started\n");
+ return EXIT_SUCCESS;
+}
diff --git a/examples/canardv1/socketcan.c b/examples/canardv1/socketcan.c
new file mode 100644
index 000000000..678724c46
--- /dev/null
+++ b/examples/canardv1/socketcan.c
@@ -0,0 +1,227 @@
+/****************************************************************************
+ * apps/examples/canardv1/socketcan.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include "socketcan.h"
+
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <stdio.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+int16_t socketcanopen(canardsocketinstance *ins,
+ const char *const can_iface_name, const bool can_fd)
+{
+ struct sockaddr_can addr;
+ struct ifreq ifr;
+
+ ins->can_fd = can_fd;
+
+ /* open socket */
+
+ if ((ins->s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
+ {
+ perror("socket");
+ return -1;
+ }
+
+ strncpy(ifr.ifr_name, can_iface_name, IFNAMSIZ - 1);
+ ifr.ifr_name[IFNAMSIZ - 1] = '\0';
+ ifr.ifr_ifindex = if_nametoindex(ifr.ifr_name);
+
+ if (!ifr.ifr_ifindex)
+ {
+ perror("if_nametoindex");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.can_family = AF_CAN;
+ addr.can_ifindex = ifr.ifr_ifindex;
+
+ const int on = 1;
+
+ /* RX Timestamping */
+
+ if (setsockopt(ins->s, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) < 0)
+ {
+ perror("SO_TIMESTAMP is disabled");
+ return -1;
+ }
+
+ /* NuttX Feature: Enable TX deadline when sending CAN frames
+ * When a deadline occurs the driver will remove the CAN frame
+ */
+
+ if (setsockopt(ins->s, SOL_CAN_RAW, CAN_RAW_TX_DEADLINE,
+ &on, sizeof(on)) < 0)
+ {
+ perror("CAN_RAW_TX_DEADLINE is disabled");
+ return -1;
+ }
+
+ if (can_fd)
+ {
+ if (setsockopt(ins->s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
+ &on, sizeof(on)) < 0)
+ {
+ perror("no CAN FD support");
+ return -1;
+ }
+ }
+
+ if (bind(ins->s, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ {
+ perror("bind");
+ return -1;
+ }
+
+ /* Setup TX msg */
+
+ ins->send_iov.iov_base = &ins->send_frame;
+
+ if (ins->can_fd)
+ {
+ ins->send_iov.iov_len = sizeof(struct canfd_frame);
+ }
+ else
+ {
+ ins->send_iov.iov_len = sizeof(struct can_frame);
+ }
+
+ memset(&ins->send_control, 0x00, sizeof(ins->send_control));
+
+ ins->send_msg.msg_iov = &ins->send_iov;
+ ins->send_msg.msg_iovlen = 1;
+ ins->send_msg.msg_control = &ins->send_control;
+ ins->send_msg.msg_controllen = sizeof(ins->send_control);
+
+ ins->send_cmsg = CMSG_FIRSTHDR(&ins->send_msg);
+ ins->send_cmsg->cmsg_level = SOL_CAN_RAW;
+ ins->send_cmsg->cmsg_type = CAN_RAW_TX_DEADLINE;
+ ins->send_cmsg->cmsg_len = sizeof(struct timeval);
+ ins->send_tv = (struct timeval *)CMSG_DATA(&ins->send_cmsg);
+
+ /* Setup RX msg */
+
+ ins->recv_iov.iov_base = &ins->recv_frame;
+
+ if (can_fd)
+ {
+ ins->recv_iov.iov_len = sizeof(struct canfd_frame);
+ }
+ else
+ {
+ ins->recv_iov.iov_len = sizeof(struct can_frame);
+ }
+
+ memset(&ins->recv_control, 0x00, sizeof(ins->recv_control));
+
+ ins->recv_msg.msg_iov = &ins->recv_iov;
+ ins->recv_msg.msg_iovlen = 1;
+ ins->recv_msg.msg_control = &ins->recv_control;
+ ins->recv_msg.msg_controllen = sizeof(ins->recv_control);
+ ins->recv_cmsg = CMSG_FIRSTHDR(&ins->recv_msg);
+
+ return 0;
+}
+
+int16_t socketcantransmit(canardsocketinstance *ins, const CanardFrame *txf)
+{
+ /* Copy CanardFrame to can_frame/canfd_frame */
+
+ if (ins->can_fd)
+ {
+ ins->send_frame.can_id = txf->extended_can_id;
+ ins->send_frame.can_id |= CAN_EFF_FLAG;
+ ins->send_frame.len = txf->payload_size;
+ memcpy(&ins->send_frame.data, txf->payload, txf->payload_size);
+ }
+ else
+ {
+ struct can_frame *frame = (struct can_frame *)&ins->send_frame;
+ frame->can_id = txf->extended_can_id;
+ frame->can_id |= CAN_EFF_FLAG;
+ frame->can_dlc = txf->payload_size;
+ memcpy(&frame->data, txf->payload, txf->payload_size);
+ }
+
+ /* Set CAN_RAW_TX_DEADLINE timestamp */
+
+ ins->send_tv->tv_usec = txf->timestamp_usec % 1000000ULL;
+ ins->send_tv->tv_sec = (txf->timestamp_usec - ins->send_tv->tv_usec)
+ / 1000000ULL;
+
+ return sendmsg(ins->s, &ins->send_msg, 0);
+}
+
+int16_t socketcanreceive(canardsocketinstance *ins, CanardFrame *rxf)
+{
+ int32_t result = recvmsg(ins->s, &ins->recv_msg, 0);
+
+ if (result < 0)
+ {
+ return result;
+ }
+
+ /* Copy CAN frame to CanardFrame */
+
+ if (ins->can_fd)
+ {
+ struct canfd_frame *recv_frame =
+ (struct canfd_frame *)&ins->recv_frame;
+ rxf->extended_can_id = recv_frame->can_id & CAN_EFF_MASK;
+ rxf->payload_size = recv_frame->len;
+ rxf->payload = &recv_frame->data;
+ }
+ else
+ {
+ struct can_frame *recv_frame = (struct can_frame *)&ins->recv_frame;
+ rxf->extended_can_id = recv_frame->can_id & CAN_EFF_MASK;
+ rxf->payload_size = recv_frame->can_dlc;
+ rxf->payload = &recv_frame->data;
+ }
+
+ /* Read SO_TIMESTAMP value */
+
+ if (ins->recv_cmsg->cmsg_level == SOL_SOCKET
+ && ins->recv_cmsg->cmsg_type == SO_TIMESTAMP)
+ {
+ struct timeval *tv = (struct timeval *)CMSG_DATA(ins->recv_cmsg);
+ rxf->timestamp_usec = tv->tv_sec * 1000000ULL + tv->tv_usec;
+ }
+
+ return result;
+}
+
+/* TODO implement corresponding IOCTL */
+
+int16_t socketcanconfigurefilter(const fd_t fd, const size_t num_filters,
+ const struct can_filter *filters)
+{
+ return -1;
+}
diff --git a/examples/canardv1/socketcan.h b/examples/canardv1/socketcan.h
new file mode 100644
index 000000000..da5de9298
--- /dev/null
+++ b/examples/canardv1/socketcan.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+ * apps/examples/canardv1/socketcan.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef SOCKETCAN_H_INCLUDED
+#define SOCKETCAN_H_INCLUDED
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include <sys/time.h>
+#include <sys/socket.h>
+
+#include <nuttx/can.h>
+#include <netpacket/can.h>
+
+#include <canard.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+typedef struct canardsocketinstance canardsocketinstance;
+typedef int fd_t;
+
+struct canardsocketinstance
+{
+ fd_t s;
+ bool can_fd;
+
+ /* Send msg structure */
+
+ struct iovec send_iov;
+ struct canfd_frame send_frame;
+ struct msghdr send_msg;
+ struct cmsghdr *send_cmsg;
+ struct timeval *send_tv; /* TX deadline timestamp */
+ uint8_t send_control[sizeof(struct cmsghdr)
+ + sizeof(struct timeval)];
+
+ /* Receive msg structure */
+
+ struct iovec recv_iov;
+ struct canfd_frame recv_frame;
+ struct msghdr recv_msg;
+ struct cmsghdr *recv_cmsg;
+ uint8_t recv_control[sizeof(struct cmsghdr)
+ + sizeof(struct timeval)];
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/* Creates a SocketCAN socket for corresponding iface can_iface_name
+ * Also sets up the message structures required for transmit and receive
+ * can_fd determines to use CAN FD frame when is 1, and classical CAN
+ * frame when is 0. The return value is 0 on succes and -1 on error
+ */
+
+int16_t socketcanopen(canardsocketinstance *ins,
+ const char *const can_iface_name,
+ const bool can_fd);
+
+/* Send a CanardFrame to the canardsocketinstance socket
+ * This function is blocking
+ * The return value is number of bytes transferred, negative value on error.
+ */
+
+int16_t socketcantransmit(canardsocketinstance *ins, const CanardFrame *txf);
+
+/* Receive a CanardFrame from the canardsocketinstance socket
+ * This function is blocking
+ * The return value is number of bytes received, negative value on error.
+ */
+
+int16_t socketcanreceive(canardsocketinstance *ins, CanardFrame *rxf);
+
+/* TODO implement ioctl for CAN filter */
+
+int16_t socketcanconfigurefilter(const fd_t fd, const size_t num_filters,
+ const struct can_filter *filters);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //SOCKETCAN_H_INCLUDED
diff --git a/include/canutils/.gitignore b/include/canutils/.gitignore
index 4396c63a2..cd3875f43 100644
--- a/include/canutils/.gitignore
+++ b/include/canutils/.gitignore
@@ -1,2 +1,4 @@
/canard.h
/canard_nuttx.h
+/canard_dsdl.h
+/o1heap.h