mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
examples: add Lely CANopen master example
add Lely CANopen master example Signed-off-by: raiden00pl <raiden00@railab.me>
This commit is contained in:
parent
caa7d7faa5
commit
962d90bb6e
10 changed files with 1702 additions and 0 deletions
53
examples/lely_master/CMakeLists.txt
Normal file
53
examples/lely_master/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# ##############################################################################
|
||||
# apps/examples/lely_master/CMakeLists.txt
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
if(CONFIG_EXAMPLES_LELYMASTER)
|
||||
|
||||
set(LELY_INCDIR ${NUTTX_APPS_DIR}/canutils/lely-canopen/lely-core/include)
|
||||
|
||||
set(SRCS master_main.c sdev_master.c)
|
||||
|
||||
if(CONFIG_EXAMPLES_LELYMASTER_CHARDEV)
|
||||
list(APPEND SRCS candev_char.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_EXAMPLES_LELYMASTER_SOCKET)
|
||||
list(APPEND SRCS candev_sock.c)
|
||||
endif()
|
||||
|
||||
nuttx_add_application(
|
||||
NAME
|
||||
comaster
|
||||
PRIORITY
|
||||
${CONFIG_EXAMPLES_LELYMASTER_PRIORITY}
|
||||
STACKSIZE
|
||||
${CONFIG_EXAMPLES_LELYMASTER_STACKSIZE}
|
||||
MODULE
|
||||
${CONFIG_EXAMPLES_LELYMASTER}
|
||||
COMPILE_FLAGS
|
||||
-Wno-undef
|
||||
INCLUDE_DIRECTORIES
|
||||
${LELY_INCDIR}
|
||||
SRCS
|
||||
${SRCS})
|
||||
|
||||
endif()
|
||||
50
examples/lely_master/Kconfig
Normal file
50
examples/lely_master/Kconfig
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
config EXAMPLES_LELYMASTER
|
||||
tristate "Lely CANopen master example"
|
||||
default n
|
||||
depends on CANUTILS_LELYCANOPEN && CANUTILS_LELYCANOPEN_SDEV
|
||||
depends on CANUTILS_LELYCANOPEN_TIME && CANUTILS_LELYCANOPEN_OBJUPLOAD
|
||||
depends on CANUTILS_LELYCANOPEN_MASTER
|
||||
---help---
|
||||
Enable the Lely CANopen master (comaster) example application.
|
||||
|
||||
if EXAMPLES_LELYMASTER
|
||||
|
||||
choice
|
||||
prompt "CAN backend"
|
||||
default EXAMPLES_LELYMASTER_CHARDEV
|
||||
|
||||
config EXAMPLES_LELYMASTER_CHARDEV
|
||||
bool "CAN character driver"
|
||||
depends on CAN
|
||||
|
||||
config EXAMPLES_LELYMASTER_SOCKET
|
||||
bool "SocketCAN"
|
||||
depends on NET_CAN
|
||||
select NETUTILS_NETLIB
|
||||
|
||||
endchoice
|
||||
|
||||
config EXAMPLES_LELYMASTER_DEVPATH
|
||||
string "CAN character device path"
|
||||
default "/dev/can0"
|
||||
depends on EXAMPLES_LELYMASTER_CHARDEV
|
||||
|
||||
config EXAMPLES_LELYMASTER_INTF
|
||||
string "SocketCAN interface"
|
||||
default "can0"
|
||||
depends on EXAMPLES_LELYMASTER_SOCKET
|
||||
|
||||
config EXAMPLES_LELYMASTER_PRIORITY
|
||||
int "Task priority"
|
||||
default 100
|
||||
|
||||
config EXAMPLES_LELYMASTER_STACKSIZE
|
||||
int "Stack size"
|
||||
default DEFAULT_TASK_STACKSIZE
|
||||
|
||||
endif
|
||||
25
examples/lely_master/Make.defs
Normal file
25
examples/lely_master/Make.defs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
############################################################################
|
||||
# apps/examples/lely_master/Make.defs
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_EXAMPLES_LELYMASTER),)
|
||||
CONFIGURED_APPS += $(APPDIR)/examples/lely_master
|
||||
endif
|
||||
47
examples/lely_master/Makefile
Normal file
47
examples/lely_master/Makefile
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
############################################################################
|
||||
# apps/examples/lely_master/Makefile
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# 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
|
||||
|
||||
PROGNAME = comaster
|
||||
PRIORITY = $(CONFIG_EXAMPLES_LELYMASTER_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_EXAMPLES_LELYMASTER_STACKSIZE)
|
||||
MODULE = $(CONFIG_EXAMPLES_LELYMASTER)
|
||||
|
||||
CFLAGS += -DHAVE_CONFIG_H=1
|
||||
|
||||
# Lely headers use bare "#if __cplusplus"; silence -Wundef like the library
|
||||
|
||||
CFLAGS += -Wno-undef
|
||||
|
||||
CSRCS = sdev_master.c
|
||||
|
||||
ifeq ($(CONFIG_EXAMPLES_LELYMASTER_CHARDEV),y)
|
||||
CSRCS += candev_char.c
|
||||
endif
|
||||
ifeq ($(CONFIG_EXAMPLES_LELYMASTER_SOCKET),y)
|
||||
CSRCS += candev_sock.c
|
||||
endif
|
||||
|
||||
MAINSRC = master_main.c
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
44
examples/lely_master/candev.h
Normal file
44
examples/lely_master/candev.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* apps/examples/lely_master/candev.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 __APPS_EXAMPLES_LELY_MASTER_CANDEV_H
|
||||
#define __APPS_EXAMPLES_LELY_MASTER_CANDEV_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <canutils/lely/config.h>
|
||||
|
||||
#include <lely/can/msg.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
int comaster_candev_init(void);
|
||||
int comaster_candev_send(FAR const struct can_msg *msg);
|
||||
int comaster_candev_recv(FAR struct can_msg *msg);
|
||||
|
||||
#endif /* __APPS_EXAMPLES_LELY_MASTER_CANDEV_H */
|
||||
173
examples/lely_master/candev_char.c
Normal file
173
examples/lely_master/candev_char.c
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
/****************************************************************************
|
||||
* apps/examples/lely_master/candev_char.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <nuttx/can/can.h>
|
||||
|
||||
#include "candev.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static int g_candev_fd;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: comaster_candev_init
|
||||
****************************************************************************/
|
||||
|
||||
int comaster_candev_init(void)
|
||||
{
|
||||
struct canioc_bittiming_s bt;
|
||||
int ret;
|
||||
|
||||
/* Non-blocking so the main loop keeps servicing the CANopen timers */
|
||||
|
||||
g_candev_fd = open(CONFIG_EXAMPLES_LELYMASTER_DEVPATH,
|
||||
O_RDWR | O_NONBLOCK);
|
||||
if (g_candev_fd < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
printf("ERROR: open %s failed %d\n",
|
||||
CONFIG_EXAMPLES_LELYMASTER_DEVPATH, errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ioctl(g_candev_fd, CANIOC_GET_BITTIMING, &bt);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("Bit timing not available: %d\n", errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Bit timing:\n");
|
||||
printf(" Baud: %lu\n", (unsigned long)bt.bt_baud);
|
||||
printf(" TSEG1: %u\n", bt.bt_tseg1);
|
||||
printf(" TSEG2: %u\n", bt.bt_tseg2);
|
||||
printf(" SJW: %u\n", bt.bt_sjw);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: comaster_candev_send
|
||||
****************************************************************************/
|
||||
|
||||
int comaster_candev_send(FAR const struct can_msg *msg)
|
||||
{
|
||||
struct can_msg_s txmsg;
|
||||
ssize_t nwritten;
|
||||
int i;
|
||||
|
||||
txmsg.cm_hdr.ch_id = msg->id;
|
||||
txmsg.cm_hdr.ch_rtr = (msg->flags & CAN_FLAG_RTR) != 0;
|
||||
txmsg.cm_hdr.ch_dlc = msg->len;
|
||||
#ifdef CONFIG_CAN_EXTID
|
||||
txmsg.cm_hdr.ch_extid = (msg->flags & CAN_FLAG_IDE) != 0;
|
||||
#endif
|
||||
#ifdef CONFIG_CAN_ERRORS
|
||||
txmsg.cm_hdr.ch_error = 0;
|
||||
#endif
|
||||
txmsg.cm_hdr.ch_tcf = 0;
|
||||
|
||||
for (i = 0; i < msg->len; i++)
|
||||
{
|
||||
txmsg.cm_data[i] = msg->data[i];
|
||||
}
|
||||
|
||||
nwritten = write(g_candev_fd, &txmsg, CAN_MSGLEN(txmsg.cm_hdr.ch_dlc));
|
||||
if (nwritten != CAN_MSGLEN(txmsg.cm_hdr.ch_dlc))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: comaster_candev_recv
|
||||
****************************************************************************/
|
||||
|
||||
int comaster_candev_recv(FAR struct can_msg *msg)
|
||||
{
|
||||
struct can_msg_s rxmsg;
|
||||
ssize_t nread;
|
||||
int i;
|
||||
|
||||
nread = read(g_candev_fd, &rxmsg, sizeof(struct can_msg_s));
|
||||
if (nread < 0)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nread < CAN_MSGLEN(0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg->id = rxmsg.cm_hdr.ch_id;
|
||||
msg->flags = 0;
|
||||
|
||||
#ifdef CONFIG_CAN_EXTID
|
||||
if (rxmsg.cm_hdr.ch_extid)
|
||||
{
|
||||
msg->flags |= CAN_FLAG_IDE;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rxmsg.cm_hdr.ch_rtr)
|
||||
{
|
||||
msg->flags |= CAN_FLAG_RTR;
|
||||
}
|
||||
|
||||
msg->len = rxmsg.cm_hdr.ch_dlc;
|
||||
|
||||
for (i = 0; i < rxmsg.cm_hdr.ch_dlc; i++)
|
||||
{
|
||||
msg->data[i] = rxmsg.cm_data[i];
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
197
examples/lely_master/candev_sock.c
Normal file
197
examples/lely_master/candev_sock.c
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/****************************************************************************
|
||||
* apps/examples/lely_master/candev_sock.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <nuttx/can.h>
|
||||
|
||||
#include "netutils/netlib.h"
|
||||
#include "candev.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static int g_candev_sock;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: comaster_candev_init
|
||||
****************************************************************************/
|
||||
|
||||
int comaster_candev_init(void)
|
||||
{
|
||||
struct sockaddr_can addr;
|
||||
struct ifreq ifr;
|
||||
int on = 1;
|
||||
int ret;
|
||||
|
||||
g_candev_sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
if (g_candev_sock < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
printf("ERROR: socket failed %d\n", errno);
|
||||
return ret;
|
||||
}
|
||||
|
||||
strlcpy(ifr.ifr_name, CONFIG_EXAMPLES_LELYMASTER_INTF, IFNAMSIZ);
|
||||
|
||||
/* SocketCAN silently drops traffic while the interface is down, so bring
|
||||
* it up here. This lets the example run without a separate "ifup" step.
|
||||
*/
|
||||
|
||||
if (netlib_ifup(ifr.ifr_name) < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
printf("ERROR: netlib_ifup %s failed %d\n", ifr.ifr_name, errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ifr.ifr_ifindex = if_nametoindex(ifr.ifr_name);
|
||||
if (ifr.ifr_ifindex == 0)
|
||||
{
|
||||
ret = -errno;
|
||||
printf("ERROR: if_nametoindex %s failed %d\n", ifr.ifr_name, errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
setsockopt(g_candev_sock, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
|
||||
&on, sizeof(on));
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
if (bind(g_candev_sock, (FAR struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
printf("ERROR: bind failed %d\n", errno);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
ret = fcntl(g_candev_sock, F_SETFL, O_NONBLOCK);
|
||||
if (ret < 0)
|
||||
{
|
||||
ret = -errno;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
errout:
|
||||
close(g_candev_sock);
|
||||
g_candev_sock = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: comaster_candev_send
|
||||
****************************************************************************/
|
||||
|
||||
int comaster_candev_send(FAR const struct can_msg *msg)
|
||||
{
|
||||
struct can_frame frame;
|
||||
ssize_t nwritten;
|
||||
|
||||
memset(&frame, 0, sizeof(frame));
|
||||
|
||||
frame.can_id = msg->id;
|
||||
if (msg->flags & CAN_FLAG_IDE)
|
||||
{
|
||||
frame.can_id |= CAN_EFF_FLAG;
|
||||
}
|
||||
|
||||
if (msg->flags & CAN_FLAG_RTR)
|
||||
{
|
||||
frame.can_id |= CAN_RTR_FLAG;
|
||||
}
|
||||
|
||||
frame.can_dlc = msg->len;
|
||||
memcpy(frame.data, msg->data, msg->len);
|
||||
|
||||
nwritten = write(g_candev_sock, &frame, sizeof(frame));
|
||||
if (nwritten != sizeof(frame))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: comaster_candev_recv
|
||||
****************************************************************************/
|
||||
|
||||
int comaster_candev_recv(FAR struct can_msg *msg)
|
||||
{
|
||||
struct can_frame frame;
|
||||
ssize_t nread;
|
||||
|
||||
nread = read(g_candev_sock, &frame, sizeof(frame));
|
||||
if (nread < 0)
|
||||
{
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (nread < sizeof(frame))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg->id = frame.can_id & CAN_EFF_MASK;
|
||||
msg->flags = 0;
|
||||
if (frame.can_id & CAN_EFF_FLAG)
|
||||
{
|
||||
msg->flags |= CAN_FLAG_IDE;
|
||||
}
|
||||
|
||||
if (frame.can_id & CAN_RTR_FLAG)
|
||||
{
|
||||
msg->flags |= CAN_FLAG_RTR;
|
||||
}
|
||||
|
||||
msg->len = frame.can_dlc;
|
||||
memcpy(msg->data, frame.data, frame.can_dlc);
|
||||
|
||||
return 1;
|
||||
}
|
||||
358
examples/lely_master/master_main.c
Normal file
358
examples/lely_master/master_main.c
Normal file
|
|
@ -0,0 +1,358 @@
|
|||
/****************************************************************************
|
||||
* apps/examples/lely_master/master_main.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <canutils/lely/config.h>
|
||||
|
||||
#include <lely/co/csdo.h>
|
||||
#include <lely/co/dev.h>
|
||||
#include <lely/co/nmt.h>
|
||||
#include <lely/co/sdev.h>
|
||||
#include <lely/co/sdo.h>
|
||||
#include <lely/co/time.h>
|
||||
|
||||
#include "sdev.h"
|
||||
#include "candev.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define SLAVE_ID 0x02
|
||||
#define OBJ_COUNTER 0x2100
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
enum master_phase_e
|
||||
{
|
||||
PHASE_WAIT, /* wait for the slave, then read its info via SDO */
|
||||
PHASE_SDO, /* SDO request in flight */
|
||||
PHASE_RUN /* network operational, streaming PDO data */
|
||||
};
|
||||
|
||||
struct co_net_s
|
||||
{
|
||||
can_net_t *net;
|
||||
co_dev_t *dev;
|
||||
co_nmt_t *nmt;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct co_net_s g_net;
|
||||
static bool g_sdo_done;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: elapsed_ms
|
||||
****************************************************************************/
|
||||
|
||||
static long elapsed_ms(const struct timespec *a, const struct timespec *b)
|
||||
{
|
||||
return (a->tv_sec - b->tv_sec) * 1000 +
|
||||
(a->tv_nsec - b->tv_nsec) / 1000000;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: on_can_send
|
||||
****************************************************************************/
|
||||
|
||||
static int on_can_send(const struct can_msg *msg, void *data)
|
||||
{
|
||||
UNUSED(data);
|
||||
|
||||
return comaster_candev_send(msg);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nmt_start_remote
|
||||
****************************************************************************/
|
||||
|
||||
static void nmt_start_remote(co_unsigned8_t id)
|
||||
{
|
||||
struct can_msg msg;
|
||||
|
||||
/* NMT command frame: COB-ID 0x000, {command specifier, node-ID} */
|
||||
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
msg.len = 2;
|
||||
msg.data[0] = CO_NMT_CS_START;
|
||||
msg.data[1] = id;
|
||||
|
||||
comaster_candev_send(&msg);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: on_sdo_up
|
||||
****************************************************************************/
|
||||
|
||||
static void on_sdo_up(co_csdo_t *sdo, co_unsigned16_t idx,
|
||||
co_unsigned8_t subidx, co_unsigned32_t ac,
|
||||
const void *ptr, size_t n, void *data)
|
||||
{
|
||||
co_unsigned32_t val;
|
||||
|
||||
UNUSED(sdo);
|
||||
UNUSED(idx);
|
||||
UNUSED(subidx);
|
||||
UNUSED(data);
|
||||
|
||||
if (ac == 0 && n >= sizeof(co_unsigned32_t))
|
||||
{
|
||||
memcpy(&val, ptr, sizeof(val));
|
||||
printf("SDO: slave device type (0x1000) = 0x%08x\n", (unsigned)val);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("SDO: read failed, abort code 0x%08x\n", (unsigned)ac);
|
||||
}
|
||||
|
||||
g_sdo_done = true;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: on_time
|
||||
****************************************************************************/
|
||||
|
||||
static void on_time(co_time_t *time, const struct timespec *tp, void *data)
|
||||
{
|
||||
UNUSED(time);
|
||||
UNUSED(data);
|
||||
|
||||
/* Update the wall clock */
|
||||
|
||||
clock_settime(CLOCK_REALTIME, tp);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: on_nmt_cs
|
||||
****************************************************************************/
|
||||
|
||||
static void on_nmt_cs(co_nmt_t *nmt, co_unsigned8_t cs, void *data)
|
||||
{
|
||||
UNUSED(data);
|
||||
|
||||
switch (cs)
|
||||
{
|
||||
case CO_NMT_CS_START:
|
||||
case CO_NMT_CS_ENTER_PREOP:
|
||||
{
|
||||
co_time_set_ind(co_nmt_get_time(nmt), &on_time, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
case CO_NMT_CS_RESET_NODE:
|
||||
{
|
||||
exit(0);
|
||||
break;
|
||||
}
|
||||
|
||||
case CO_NMT_CS_STOP:
|
||||
case CO_NMT_CS_RESET_COMM:
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: main
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, FAR char *argv[])
|
||||
{
|
||||
struct timespec now;
|
||||
struct can_msg msg;
|
||||
struct timespec t0;
|
||||
co_unsigned32_t last = 0xffffffff;
|
||||
int phase = PHASE_WAIT;
|
||||
int ret;
|
||||
co_csdo_t *csdo;
|
||||
co_unsigned32_t v;
|
||||
|
||||
memset(&g_net, 0, sizeof(g_net));
|
||||
g_sdo_done = false;
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
ret = comaster_candev_init();
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("ERROR: comaster_candev_init failed %d\n", ret);
|
||||
goto errout;
|
||||
}
|
||||
|
||||
g_net.net = can_net_create();
|
||||
if (!g_net.net)
|
||||
{
|
||||
printf("ERROR: can_net_create failed\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
can_net_set_send_func(g_net.net, &on_can_send, NULL);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
can_net_set_time(g_net.net, &now);
|
||||
|
||||
/* Create dev from struct */
|
||||
|
||||
g_net.dev = co_dev_create_from_sdev(&g_sdev_master);
|
||||
if (!g_net.dev)
|
||||
{
|
||||
printf("ERROR: co_dev_create_from_sdev failed\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
g_net.nmt = co_nmt_create(g_net.net, g_net.dev);
|
||||
if (!g_net.nmt)
|
||||
{
|
||||
printf("ERROR: co_nmt_create failed\n");
|
||||
goto errout;
|
||||
}
|
||||
|
||||
/* Start the NMT service by resetting the node */
|
||||
|
||||
co_nmt_cs_ind(g_net.nmt, CO_NMT_CS_RESET_NODE);
|
||||
|
||||
/* Set the NMT indication function after the initial reset */
|
||||
|
||||
co_nmt_set_cs_ind(g_net.nmt, &on_nmt_cs, NULL);
|
||||
|
||||
printf("lely CANopen master running (node 0x%02x)\n", g_sdev_master.id);
|
||||
|
||||
clock_gettime(CLOCK_MONOTONIC, &t0);
|
||||
|
||||
while (1)
|
||||
{
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
can_net_set_time(g_net.net, &now);
|
||||
|
||||
while (comaster_candev_recv(&msg) > 0)
|
||||
{
|
||||
can_net_recv(g_net.net, &msg);
|
||||
}
|
||||
|
||||
switch (phase)
|
||||
{
|
||||
/* Give the slave time to boot, then read its device type with
|
||||
* a Client-SDO transfer (works while both nodes are pre-op).
|
||||
*/
|
||||
|
||||
case PHASE_WAIT:
|
||||
{
|
||||
if (elapsed_ms(&now, &t0) >= 500)
|
||||
{
|
||||
csdo = co_nmt_get_csdo(g_net.nmt, 1);
|
||||
if (csdo != NULL && co_csdo_up_req(
|
||||
csdo, 0x1000, 0x00, &on_sdo_up, NULL) == 0)
|
||||
{
|
||||
phase = PHASE_SDO;
|
||||
}
|
||||
else
|
||||
{
|
||||
t0 = now;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Once the SDO completes, bring the network to OPERATIONAL:
|
||||
* the master itself and the slave (NMT start). PDO/SYNC then
|
||||
* flow.
|
||||
*/
|
||||
|
||||
case PHASE_SDO:
|
||||
{
|
||||
if (g_sdo_done)
|
||||
{
|
||||
co_nmt_cs_ind(g_net.nmt, CO_NMT_CS_START);
|
||||
nmt_start_remote(SLAVE_ID);
|
||||
printf("NMT: master + slave 0x%02x OPERATIONAL\n",
|
||||
SLAVE_ID);
|
||||
phase = PHASE_RUN;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* The slave's synchronous TPDO lands in object 0x2100 via the
|
||||
* RPDO mapping; print it whenever it changes.
|
||||
*/
|
||||
|
||||
case PHASE_RUN:
|
||||
{
|
||||
v = co_dev_get_val_u32(g_net.dev, OBJ_COUNTER, 0x00);
|
||||
if (v != last)
|
||||
{
|
||||
printf("PDO rx: counter = %u\n", (unsigned)v);
|
||||
last = v;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
usleep(1000);
|
||||
}
|
||||
|
||||
errout:
|
||||
if (g_net.nmt)
|
||||
{
|
||||
co_nmt_destroy(g_net.nmt);
|
||||
}
|
||||
|
||||
if (g_net.dev)
|
||||
{
|
||||
co_dev_destroy(g_net.dev);
|
||||
}
|
||||
|
||||
if (g_net.net)
|
||||
{
|
||||
can_net_destroy(g_net.net);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
41
examples/lely_master/sdev.h
Normal file
41
examples/lely_master/sdev.h
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/****************************************************************************
|
||||
* apps/examples/lely_master/sdev.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 __APPS_EXAMPLES_LELY_SDEV_H
|
||||
#define __APPS_EXAMPLES_LELY_SDEV_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <canutils/lely/config.h>
|
||||
#include <lely/co/sdev.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public data
|
||||
****************************************************************************/
|
||||
|
||||
extern const struct co_sdev g_sdev_master;
|
||||
|
||||
#endif /* __APPS_EXAMPLES_LELY_SDEV_H */
|
||||
714
examples/lely_master/sdev_master.c
Normal file
714
examples/lely_master/sdev_master.c
Normal file
|
|
@ -0,0 +1,714 @@
|
|||
/****************************************************************************
|
||||
* apps/examples/lely_master/sdev_master.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 <nuttx/config.h>
|
||||
|
||||
#include "sdev.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define CO_SDEV_STRING(s) s
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/* Object 0x1000 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1000_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Device type"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = CO_UNSIGNED32_MIN,
|
||||
#endif
|
||||
.val.u32 = CO_UNSIGNED32_MIN,
|
||||
.access = CO_ACCESS_RO,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1001 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1001_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Error register"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED8,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u8 = CO_UNSIGNED8_MIN,
|
||||
.max.u8 = CO_UNSIGNED8_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u8 = CO_UNSIGNED8_MIN,
|
||||
#endif
|
||||
.val.u8 = CO_UNSIGNED8_MIN,
|
||||
.access = CO_ACCESS_RO,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1005 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1005_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("COB-ID SYNC message"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = 0x40000080lu,
|
||||
#endif
|
||||
.val.u32 = 0x40000080lu,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1006 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1006_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Communication cycle period"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = 0x000186a0lu,
|
||||
#endif
|
||||
.val.u32 = 0x000186a0lu,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1012 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1012_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("COB-ID time stamp object"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = 0x80000100lu,
|
||||
#endif
|
||||
.val.u32 = 0x80000100lu,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1017 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1017_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Producer heartbeat time"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED16,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u16 = CO_UNSIGNED16_MIN,
|
||||
.max.u16 = CO_UNSIGNED16_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u16 = 0x0032,
|
||||
#endif
|
||||
.val.u16 = 0x0032,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1018 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1018_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Highest sub-index supported"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED8,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u8 = CO_UNSIGNED8_MIN,
|
||||
.max.u8 = CO_UNSIGNED8_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u8 = 0x04,
|
||||
#endif
|
||||
.val.u8 = 0x04,
|
||||
.access = CO_ACCESS_CONST,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Vendor-ID"),
|
||||
#endif
|
||||
.subidx = 0x01,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = 0x00000360lu,
|
||||
#endif
|
||||
.val.u32 = 0x00000360lu,
|
||||
.access = CO_ACCESS_RO,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Product code"),
|
||||
#endif
|
||||
.subidx = 0x02,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = CO_UNSIGNED32_MIN,
|
||||
#endif
|
||||
.val.u32 = CO_UNSIGNED32_MIN,
|
||||
.access = CO_ACCESS_RO,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Revision number"),
|
||||
#endif
|
||||
.subidx = 0x03,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = CO_UNSIGNED32_MIN,
|
||||
#endif
|
||||
.val.u32 = CO_UNSIGNED32_MIN,
|
||||
.access = CO_ACCESS_RO,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Serial number"),
|
||||
#endif
|
||||
.subidx = 0x04,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = CO_UNSIGNED32_MIN,
|
||||
#endif
|
||||
.val.u32 = CO_UNSIGNED32_MIN,
|
||||
.access = CO_ACCESS_RO,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1280 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1280_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Highest sub-index supported"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED8,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u8 = CO_UNSIGNED8_MIN,
|
||||
.max.u8 = CO_UNSIGNED8_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u8 = 0x03,
|
||||
#endif
|
||||
.val.u8 = 0x03,
|
||||
.access = CO_ACCESS_CONST,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("COB-ID client to server"),
|
||||
#endif
|
||||
.subidx = 0x01,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = 0x00000602lu,
|
||||
#endif
|
||||
.val.u32 = 0x00000602lu,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("COB-ID server to client"),
|
||||
#endif
|
||||
.subidx = 0x02,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = 0x00000582lu,
|
||||
#endif
|
||||
.val.u32 = 0x00000582lu,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Node-ID of the SDO server"),
|
||||
#endif
|
||||
.subidx = 0x03,
|
||||
.type = CO_DEFTYPE_UNSIGNED8,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u8 = CO_UNSIGNED8_MIN,
|
||||
.max.u8 = CO_UNSIGNED8_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u8 = 0x02,
|
||||
#endif
|
||||
.val.u8 = 0x02,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1400 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1400_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Highest sub-index supported"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED8,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u8 = CO_UNSIGNED8_MIN,
|
||||
.max.u8 = CO_UNSIGNED8_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u8 = 0x02,
|
||||
#endif
|
||||
.val.u8 = 0x02,
|
||||
.access = CO_ACCESS_CONST,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("COB-ID"),
|
||||
#endif
|
||||
.subidx = 0x01,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = 0x00000182lu,
|
||||
#endif
|
||||
.val.u32 = 0x00000182lu,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Transmission type"),
|
||||
#endif
|
||||
.subidx = 0x02,
|
||||
.type = CO_DEFTYPE_UNSIGNED8,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u8 = CO_UNSIGNED8_MIN,
|
||||
.max.u8 = CO_UNSIGNED8_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u8 = 0x01,
|
||||
#endif
|
||||
.val.u8 = 0x01,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1600 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1600_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Number of mapped objects"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED8,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u8 = CO_UNSIGNED8_MIN,
|
||||
.max.u8 = CO_UNSIGNED8_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u8 = 0x01,
|
||||
#endif
|
||||
.val.u8 = 0x01,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Mapping 1"),
|
||||
#endif
|
||||
.subidx = 0x01,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = 0x21000020lu,
|
||||
#endif
|
||||
.val.u32 = 0x21000020lu,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x1f80 sub-objects */
|
||||
|
||||
static const struct co_ssub g_1f80_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("NMT startup"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = CO_UNSIGNED32_MIN,
|
||||
#endif
|
||||
.val.u32 = 0x00000000lu,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
| CO_OBJ_FLAGS_PARAMETER_VALUE
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x2000 sub-objects */
|
||||
|
||||
static const struct co_ssub g_2000_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Object with custom SDO download callback"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = CO_UNSIGNED32_MIN,
|
||||
#endif
|
||||
.val.u32 = CO_UNSIGNED32_MIN,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x2001 sub-objects */
|
||||
|
||||
static const struct co_ssub g_2001_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Object with custom SDO upload callback"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = CO_UNSIGNED32_MIN,
|
||||
#endif
|
||||
.val.u32 = CO_UNSIGNED32_MIN,
|
||||
.access = CO_ACCESS_RO,
|
||||
.pdo_mapping = 0,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object 0x2100 sub-objects */
|
||||
|
||||
static const struct co_ssub g_2100_sub[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Counter"),
|
||||
#endif
|
||||
.subidx = 0x00,
|
||||
.type = CO_DEFTYPE_UNSIGNED32,
|
||||
#if !LELY_NO_CO_OBJ_LIMITS
|
||||
.min.u32 = CO_UNSIGNED32_MIN,
|
||||
.max.u32 = CO_UNSIGNED32_MAX,
|
||||
#endif
|
||||
#if !LELY_NO_CO_OBJ_DEFAULT
|
||||
.def.u32 = CO_UNSIGNED32_MIN,
|
||||
#endif
|
||||
.val.u32 = CO_UNSIGNED32_MIN,
|
||||
.access = CO_ACCESS_RW,
|
||||
.pdo_mapping = 1,
|
||||
.flags = 0
|
||||
}
|
||||
};
|
||||
|
||||
/* Object dictionary */
|
||||
|
||||
static const struct co_sobj g_g_sdev_master_objs[] =
|
||||
{
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Device type"),
|
||||
#endif
|
||||
.idx = 0x1000,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_1000_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Error register"),
|
||||
#endif
|
||||
.idx = 0x1001,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_1001_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("COB-ID SYNC message"),
|
||||
#endif
|
||||
.idx = 0x1005,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_1005_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Communication cycle period"),
|
||||
#endif
|
||||
.idx = 0x1006,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_1006_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("COB-ID time stamp object"),
|
||||
#endif
|
||||
.idx = 0x1012,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_1012_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Producer heartbeat time"),
|
||||
#endif
|
||||
.idx = 0x1017,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_1017_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Identity object"),
|
||||
#endif
|
||||
.idx = 0x1018,
|
||||
.code = CO_OBJECT_RECORD,
|
||||
.nsub = 5,
|
||||
.subs = g_1018_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("SDO client parameter"),
|
||||
#endif
|
||||
.idx = 0x1280,
|
||||
.code = CO_OBJECT_RECORD,
|
||||
.nsub = 4,
|
||||
.subs = g_1280_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("RPDO communication parameter"),
|
||||
#endif
|
||||
.idx = 0x1400,
|
||||
.code = CO_OBJECT_RECORD,
|
||||
.nsub = 3,
|
||||
.subs = g_1400_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("RPDO mapping parameter"),
|
||||
#endif
|
||||
.idx = 0x1600,
|
||||
.code = CO_OBJECT_RECORD,
|
||||
.nsub = 2,
|
||||
.subs = g_1600_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("NMT startup"),
|
||||
#endif
|
||||
.idx = 0x1f80,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_1f80_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Object with custom SDO download callback"),
|
||||
#endif
|
||||
.idx = 0x2000,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_2000_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Object with custom SDO upload callback"),
|
||||
#endif
|
||||
.idx = 0x2001,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_2001_sub
|
||||
},
|
||||
{
|
||||
#if !LELY_NO_CO_OBJ_NAME
|
||||
.name = CO_SDEV_STRING("Counter"),
|
||||
#endif
|
||||
.idx = 0x2100,
|
||||
.code = CO_OBJECT_VAR,
|
||||
.nsub = 1,
|
||||
.subs = g_2100_sub
|
||||
}
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
const struct co_sdev g_sdev_master =
|
||||
{
|
||||
.id = 0x01,
|
||||
.name = NULL,
|
||||
.vendor_name = CO_SDEV_STRING("Apache NuttX RTOS"),
|
||||
.vendor_id = 0x00000000,
|
||||
.product_name = NULL,
|
||||
.product_code = 0x00000000,
|
||||
.revision = 0x00000000,
|
||||
.order_code = NULL,
|
||||
.baud = CO_BAUD_125,
|
||||
.rate = 0,
|
||||
.lss = 0,
|
||||
.dummy = 0x000000fe,
|
||||
.nobj = 14,
|
||||
.objs = g_g_sdev_master_objs
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
Loading…
Add table
Add a link
Reference in a new issue